HedgewarsScriptLoad("/Scripts/Locale.lua") HedgewarsScriptLoad("/Scripts/Utils.lua") local hhs = {} local deadHogs = {} local missionWon = nil local endTimer = 1000 local hogsKilled = 0 local totalEnemies = 0 local finishTime local playerFail = false local ropeGear = nil local endGameCalled = false local missionEndHandled = false local valkyriesTimer = -1 local valkyriesDuration = 20000 local timeBonus = 6000 local killBonus = 6000 local playValkyries = false local extraTime local playerTeamName local missionName = loc("Rope-knocking Challenge") -- Mission type: -- 0 = none (no special handling) -- 1 = challenge (saves mission vars) local missionType = 1 local function getKillScore() return div(hogsKilled * killBonus, totalEnemies) end local function protectEnemies() -- Protect enemy hogs for i=1, totalEnemies do if hhs[i] and GetHealth(hhs[i]) then SetEffect(hhs[i], heInvulnerable, 1) SetEffect(hhs[i], heResurrectable, 1) end end end local function killStr(killed, total, score) if total == 16 then return string.format(loc("You have killed %d of 16 hedgehogs (+%d points)."), killed, score) else return string.format(loc("You have killed %d of %d hedgehogs (+%d points)."), killed, total, score) end end local function gameOver() StopMusicSound(sndRideOfTheValkyries) valkyriesTimer = -1 missionWon = false SendStat(siGameResult, loc("Challenge over!")) local score = getKillScore() SendStat(siCustomAchievement, killStr(hogsKilled, totalEnemies, score)) SendStat(siPointType, "!POINTS") SendStat(siPlayerKills, tostring(score), playerTeamName) protectEnemies() if not endGameCalled then EndGame() endGameCalled = true end if missionType == 1 then -- Update highscore updateChallengeRecord("Highscore", score) end end local function victory(onVictory) missionWon = true local e = 0 if extraTime then e = extraTime end local totalTime = TurnTime + e * totalEnemies local completeTime = (totalTime - finishTime) / 1000 ShowMission(missionName, loc("Challenge completed!"), loc("Congratulations!") .. "|" .. string.format(loc("Completion time: %.2fs"), completeTime), 0, 0) PlaySound(sndHomerun) -- Protect player hog if hhs[0] and GetHealth(hhs[0]) then SetEffect(hhs[0], heInvulnerable, 1) SetEffect(hhs[0], heResurrectable, 1) end SendStat(siGameResult, loc("Challenge completed!")) local hogScore = getKillScore() local timeScore = div(finishTime * timeBonus, totalTime) local score = hogScore + timeScore SendStat(siCustomAchievement, killStr(hogsKilled, totalEnemies, hogScore)) SendStat(siCustomAchievement, string.format(loc("You have completed this challenge in %.2f s (+%d points)."), completeTime, timeScore)) SendStat(siPointType, "!POINTS") SendStat(siPlayerKills, tostring(score), playerTeamName) SetTeamLabel(playerTeamName, tostring(score)) SetTurnTimeLeft(MAX_TURN_TIME) if missionType == 1 then -- Update highscore updateChallengeRecord("Highscore", score) end if onVictory then onVictory() end end local function knockTaunt() local r = math.random(0,23) local taunt if r == 0 then taunt = loc("%s has been knocked out.") elseif r == 1 then taunt = loc("%s hit the ground.") elseif r == 2 then taunt = loc("%s splatted.") elseif r == 3 then taunt = loc("%s was smashed.") elseif r == 4 then taunt = loc("%s felt unstable.") elseif r == 5 then taunt = loc("%s exploded.") elseif r == 6 then taunt = loc("%s fell from a high cliff.") elseif r == 7 then taunt = loc("%s goes the way of the lemming.") elseif r == 8 then taunt = loc("%s was knocked away.") elseif r == 9 then taunt = loc("%s was really unlucky.") elseif r == 10 then taunt = loc("%s felt victim to rope-knocking.") elseif r == 11 then taunt = loc("%s had no chance.") elseif r == 12 then taunt = loc("%s was a good target.") elseif r == 13 then taunt = loc("%s spawned at a really bad position.") elseif r == 14 then taunt = loc("%s was doomed from the beginning.") elseif r == 15 then taunt = loc("%s has fallen victim to gravity.") elseif r == 16 then taunt = loc("%s hates Newton.") -- Isaac Newton elseif r == 17 then taunt = loc("%s had it coming.") elseif r == 18 then taunt = loc("%s is eliminated!") elseif r == 19 then taunt = loc("%s fell too fast.") elseif r == 20 then taunt = loc("%s flew like a rock.") elseif r == 21 then taunt = loc("%s stumbled.") elseif r == 22 then taunt = loc("%s was shoved away.") elseif r == 23 then taunt = loc("%s didn't expect that.") end return taunt end local function declareEnemyKilled(gear, onVictory) if deadHogs[gear] or playerFail then return end deadHogs[gear] = true hogsKilled = hogsKilled + 1 -- Award extra time, if available if extraTime and extraTime ~= 0 then SetTurnTimeLeft(TurnTimeLeft + extraTime) AddCaption(string.format(loc("+%d seconds!"), div(extraTime, 1000)), 0xFFFFFFFF, capgrpMessage2) end SetTeamLabel(playerTeamName, tostring(getKillScore())) if hogsKilled == totalEnemies - 1 then if playValkyries then PlayMusicSound(sndRideOfTheValkyries) valkyriesTimer = valkyriesDuration end elseif hogsKilled == totalEnemies then finishTime = TurnTimeLeft victory(onVictory) end end --[[ RopeKnocking function! This creates a rope-knocking challenge. The player spawns with one hog and a rope and must kill all other hogs by rope-knocking before the time runs out. The player wins points for each kill and gets a time bonus for killing all enemies. params is a table with all the required parameters. Fields of the params table: MANDATORY: - map: Map name - theme: Theme name - turnTime: Turn time - playerTeam: Player team info: { x, y: Start position faceLeft: If true, hog faces left } - enemyTeams: Table of enemy team tables. each enemy team table has this format: { name: Team name flag: Flag hogs: Hogs table: { x, y: Position faceLeft: If true, hog faces left hat: Hat name name: Hog name } } OPTIONAL: - missionName: Mission name - missionType: 0: None/other: No special handling 1: Challenge: Will save mission variables at end (default) - killBonus: Score for killing all hogs (one hog scores ca. (killBonus/ 0) then valkyriesTimer = valkyriesTimer - 20 if valkyriesTimer <= 0 then StopMusicSound(sndRideOfTheValkyries) end end local drown = (hhs[0]) and (band(GetState(hhs[0]), gstDrowning) ~= 0) if drown and missionWon == nil then -- Player hog drowns playerFail = true return end for i=1, totalEnemies do local hog = hhs[i] drown = (hog) and (not deadHogs[hog]) and (band(GetState(hhs[i]), gstDrowning) ~= 0) if drown then declareEnemyKilled(hog, params.onVictory) end end if ropeGear and not missionWon and band(GetState(ropeGear), gstCollision) ~= 0 then -- Hide mission on first rope attach HideMission() end end _G.onGearDamage = function(gear, damage) if gear == hhs[0] then -- Player hog hurts itself playerFail = true StopMusicSound(sndRideOfTheValkyries) valkyriesTimer = -1 protectEnemies() end if gear ~= hhs[0] and GetGearType(gear) == gtHedgehog and not deadHogs[gear] and missionWon == nil and playerFail == false then -- Enemy hog took damage AddVisualGear(GetX(gear), GetY(gear), vgtBigExplosion, 0, false) DeleteGear(gear) PlaySound(sndExplosion) AddCaption(string.format(knockTaunt(), GetHogName(gear)), 0xFFFFFFFF, capgrpMessage) declareEnemyKilled(gear, params.onVictory) end end _G.onGearAdd = function(gear) if GetGearType(gear) == gtRope then ropeGear = gear end end _G.onGearDelete = function(gear) if (gear == hhs[0]) and (missionWon == nil) then playerFail = true gameOver() end if GetGearType(gear) == gtHedgehog and gear ~= hhs[0] and not deadHogs[gear] then declareEnemyKilled(gear, params.onVictory) end if GetGearType(gear) == gtRope then ropeGear = nil end end if params.onAmmoStoreInit then _G.onAmmoStoreInit = params.onAmmoStoreInit else _G.onAmmoStoreInit = function() SetAmmo(amRope, 9, 0, 0, 0) end _G.onNewTurn = function() SetWeapon(amRope) end end end