author | sheepluva |
Tue, 22 Jun 2021 22:13:55 +0200 | |
changeset 15824 | d5c37e78ab83 |
parent 15524 | ad9fe7dc2ff7 |
permissions | -rw-r--r-- |
HedgewarsScriptLoad("/Scripts/Locale.lua") HedgewarsScriptLoad("/Scripts/Utils.lua") HedgewarsScriptLoad("/Scripts/Params.lua") local hTag = nil local hTagHeight = 33000 local tTag = nil local rTag = nil local startTime = 0 local MaxHeight = 32640 local RecordHeight = 33000 local RecordHeightHogName = nil local Fire = {} local HH = {} local totalHedgehogs = 0 local deadHedgehogs = 0 local currTeam = '' local teams = {} local teamScoreStats = {} local teamBests = {} local teamTimes = {} local MrMine -- in honour of sparkle's first arrival in the cabin local YouWon = false local YouLost = false local HogsAreInvulnerable = false local WaterRise = nil local Cake = nil local CakeWarning = false local CakeFireWarning = false local CakeTries = 0 local addCake = true local takeASeat = false local Stars = {} local jokeAwardNavy = nil local jokeAwardSpeed = nil local jokeAwardDamage = nil local recordBroken = false local dummyHog = nil local dummySkip = 0 local baseWaterSpeed = 2 local waterSpeed = 0 local waterAccel = 0 local delayHeight = 32000 local delayTime = 0 local airMineX = {} local airMineY = {} local airMine = {} local init = true local multiplayerVictoryDelay = -1 local multiplayerWinningHogs = {} local multiplayerWins = 0 local racing = false -- Placement positions of winning hogs local victoryPosses = { } do local m = 0 for y=108, 39, -32 do for x=1820+m, 1972-m, 22 do table.insert(victoryPosses, {x=x, y=y}) end m = m + 32 end end function onParameters() parseParams() if params["speed"] ~= nil then baseWaterSpeed = params["speed"] end if params["accel"] ~= nil then waterAccel = params["accel"] if waterAccel ~= 0 then waterAccel = div(32640000,waterAccel) end end if params["delaytime"] ~= nil then delayTime = params["delaytime"] end if params["delayheight"] ~= nil then delayHeight = 32768-params["delayheight"] end if params["nocake"] ~= nil then addCake = false end end function onGameInit() -- Ensure people get same map for same theme TurnTime = MAX_TURN_TIME CaseFreq = 0 Explosives = 0 MineDudPercent = 0 EnableGameFlags(gfOneClanMode) DisableGameFlags(gfBottomBorder+gfBorder) -- gfDisableLandObjects is not used. This reduced startup time by only about 15% and looked ugly -- Force seed so the land objects are the same. Some themes will still be easier, but at least you won't luck out on the same theme Seed = "" -- Disable Sudden Death WaterRise = 0 HealthDecrease = 0 end function onGearAdd(gear) if GetGearType(gear) == gtHedgehog then HH[gear] = 1 totalHedgehogs = totalHedgehogs + 1 teams[GetHogTeamName(gear)] = 1 elseif init and GetGearType(gear) == gtAirMine then airMine[gear] = 1 end end function onGearDelete(gear) if gear == MrMine then AddCaption(loc("Once you set off the proximity trigger, Mr. Mine is not your friend"), capcolDefault, capgrpMessage2) MrMine = nil elseif GetGearType(gear) == gtCake then Cake = nil CakeWarning = false elseif GetGearType(gear) == gtHedgehog then onGameTick20() onGearDamage(gear, 0) HH[gear] = nil end end function onGameStart() SendHealthStatsOff() local recordInfo = "" if isSinglePlayer then recordInfo = getReadableChallengeRecord("Highscore") end ShowMission(loc("Climb Home"), loc("Challenge"), loc("You are far from home, and the water is rising, climb up as high as you can!|Your score will be based on your height.") .. "|" .. recordInfo, -amRope, 0) local x = 1818 for h,i in pairs(HH) do if h ~= nil then SetGearPosition(h,x,108) SetHealth(h,1) if x < 1978 then x = x+32 else x = 1818 end if GetEffect(h,heInvulnerable) == 0 then SetEffect(h,heInvulnerable,1) else HogsAreInvulnerable = true end SetState(h,bor(GetState(h),gstInvisible)) end end -- 1925,263 - Mr. Mine position MrMine = AddGear(1925,263,gtMine,0,0,0,0) for i=0, TeamsCount-1 do SetTeamLabel(GetTeamName(i), "0") end end function onAmmoStoreInit() SetAmmo(amRope, 9, 0, 0, 0) end function onNewTurn() if init then init = false for a,i in pairs(airMine) do x,y = GetGearPosition(a) airMineX[a] = x airMineY[a] = y end else for a,i in pairs(airMine) do local x,y = GetGearPosition(a) if not x or airMineX[a] ~= x or airMineY[a] ~= y then DeleteGear(a) AddGear(airMineX[a],airMineY[a], gtAirMine, gsttmpFlag, 0, 0, 0) end end end startTime = GameTime --disable to preserve highest over multiple turns --will need to change water check too ofc MaxHeight = 32640 hTagHeight = 33000 SetWaterLine(32768) YouWon = false YouLost = false takeASeat = false recordBroken = false currTeam = GetHogTeamName(CurrentHedgehog) if CurrentHedgehog ~= nil then if CurrentHedgehog ~= dummyHog or multiplayerWinningHogs[CurrentHedgehog] == true then SetGearPosition(CurrentHedgehog, 1951,32640) HogTurnLeft(CurrentHedgehog, true) if not HogsAreInvulnerable then SetEffect(CurrentHedgehog,heInvulnerable,0) end AddVisualGear(1951,32640,vgtExplosion,0,false) SetState(CurrentHedgehog,band(GetState(CurrentHedgehog),bnot(gstInvisible))) SetWeapon(amRope) else dummySkip = GameTime+1 end end for hog, _ in pairs(multiplayerWinningHogs) do SetEffect(hog, heInvulnerable, 1) end for f,i in pairs(Fire) do DeleteGear(f) end for s,i in pairs(Stars) do DeleteVisualGear(s) Stars[s] = nil end if CurrentHedgehog ~= dummyHog then for i = 0,12 do flame = AddGear(2000+i*2,308, gtFlame, gsttmpFlag, 0, 0, 0) SetTag(flame, 999999+i) Fire[flame]=1 end end if Cake ~= nil then DeleteGear(Cake) end CakeTries = 0 end function FireBoom(x,y,d) -- going to add for rockets too PlaySound(sndExplosion) AddVisualGear(x,y,vgtExplosion,0,false) -- should approximate circle by removing corners for i = 0,50 do fx = GetRandom(d)-div(d,2) fy = GetRandom(d)-div(d,2) if fx<0 then fdx = -5000-GetRandom(3000) else fdx = 5000+GetRandom(3000) end if fy<0 then fdy = -5000-GetRandom(3000) else fdy = 5000+GetRandom(3000) end flame = AddGear(x+fx, y+fy, gtFlame, gsttmpFlag, fdx, fdy, 0) SetTag(flame, 999999+i) SetFlightTime(flame, 0) Fire[flame]=1 end end function onGameTick20() local x,y if math.random(20) == 1 then AddVisualGear(2012,56,vgtSmoke,0,false) end if CurrentHedgehog == dummyHog and dummySkip ~= 0 and dummySkip < GameTime then SkipTurn() dummySkip = 0 end for s,i in pairs(Stars) do local _, Y = GetVisualGearValues(s) if Y ~= nil and Y > WaterLine + 500 then DeleteVisualGear(s) Stars[s] = nil elseif Y == nil then Stars[s] = nil end end -- This will be executed if a player reached home in multiplayer if multiplayerVictoryDelay > 0 then multiplayerVictoryDelay = multiplayerVictoryDelay - 20 if multiplayerVictoryDelay <= 0 then -- If delay's over, the game will continue with the next hog if CurrentHedgehog then multiplayerWinningHogs[CurrentHedgehog] = true multiplayerWins = multiplayerWins + 1 local victoryX, victoryY if multiplayerWins <= #victoryPosses then victoryX, victoryY = victoryPosses[multiplayerWins].x, victoryPosses[multiplayerWins].y else victoryX, victoryY = victoryPosses[#victoryPosses].x, victoryPosses[#victoryPosses].y end SetGearPosition(CurrentHedgehog, victoryX, victoryY) SetEffect(CurrentHedgehog, heInvulnerable, 1) SetHealth(CurrentHedgehog, 1) if (deadHedgehogs + multiplayerWins) >= totalHedgehogs then makeFinalMultiPlayerStats() EndGame() onAchievementsDeclaration() else EndTurn(true) SetInputMask(0xFFFFFFFF) end return end end end if CurrentHedgehog ~= nil then x,y = GetGearPosition(CurrentHedgehog) if Cake ~= nil then local cx,cy = GetGearPosition(Cake) if y < cy-1500 then DeleteGear(Cake) end if Cake ~= nil and GetHealth(Cake) < 999980 then if not CakeWarning and gearIsInCircle(CurrentHedgehog,cx,cy,1350) then AddCaption(loc("Warning: Fire cake detected")) CakeWarning = true end if gearIsInCircle(CurrentHedgehog,cx,cy,450) then if not CakeFireWarning then AddCaption(loc("Don't touch the flames!")) CakeFireWarning = true end FireBoom(cx,cy,200) -- TODO: animate DeleteGear(Cake) end end end if band(GetState(CurrentHedgehog),gstHHDriven) == 0 then for f,i in pairs(Fire) do -- takes too long to fall otherwise DeleteGear(f) end if Cake ~= nil then DeleteGear(Cake) end end end if CurrentHedgehog ~= nil and TurnTimeLeft > 0 and band(GetState(CurrentHedgehog),gstHHDriven) ~= 0 then if MaxHeight < delayHeight and TurnTimeLeft<(MAX_TURN_TIME-delayTime) and MaxHeight > 286 and WaterLine > 286 then if waterAccel ~= 0 then SetWaterLine(WaterLine-(baseWaterSpeed+div(getActualHeight(MaxHeight)*100,waterAccel))) else SetWaterLine(WaterLine-baseWaterSpeed) end end if y > 0 and y < 30000 and MaxHeight > 286 and math.random(y) < 500 then local s = AddVisualGear(0, 0, vgtStraightShot, 0, false) if s then local c = div(250000,y) if c > 255 then c = 255 end c = c * 0x10000 + 0xFF0000FF SetVisualGearValues(s, math.random(2048), -5000, 0, -1-(1/y*1000), math.random(360), 0, 999999999, -- frameticks sprStar, -- star 0, c) Stars[s] = 1 end end local vx, vy = GetGearVelocity(CurrentHedgehog) local distanceFromWater = WaterLine - y --[[ check joke awards ]] -- navy award: when distance from main map is over 1000 local navyDistance = 1250 if x < -navyDistance or x > LAND_WIDTH+navyDistance then local awarded = false local dist = 0 if jokeAwardNavy == nil then awarded = true else if x < 0 then dist = math.abs(x) else dist = x - LAND_WIDTH end if dist > jokeAwardNavy.distance then awarded = true end end if awarded == true then jokeAwardNavy = { hogName = GetHogName(CurrentHedgehog), teamName = GetHogTeamName(CurrentHedgehog), distance = dist } end end -- Speed award for largest distance from water if distanceFromWater > 3000 and WaterLine < 32000 then local awarded = false if jokeAwardSpeed == nil or distanceFromWater > jokeAwardSpeed.distance then awarded = true end if awarded == true then jokeAwardSpeed = { hogName = GetHogName(CurrentHedgehog), teamName = GetHogTeamName(CurrentHedgehog), distance = distanceFromWater } end end local rawFinishTime = GameTime-startTime local finishTime = rawFinishTime/1000 local roundedFinishTime = math.ceil(math.floor(finishTime+0.5)) if isSinglePlayer then if distanceFromWater < 0 and not YouLost and not YouWon then makeSinglePlayerLoserStats() YouLost = true end -- FIXME: Hog is also in winning box if it just walks into the chair from the left, touching it. Intentional? if not YouWon and not YouLost and gearIsInBox(CurrentHedgehog, 1920, 252, 50, 50) then SaveMissionVar("Won", "true") AddCaption(loc("Victory!"), capcolDefault, capgrpGameState) ShowMission(loc("Climb Home"), loc("Made it!"), string.format(loc("Ahhh, home, sweet home. Made it in %d seconds."), roundedFinishTime), -amRope, 0) PlaySound(sndVictory,CurrentHedgehog) SendStat(siGameResult, loc("You have beaten the challenge!")) SendStat(siGraphTitle, loc("Your height over time")) SendStat(siCustomAchievement, string.format(loc("%s reached home in %.3f seconds. Congratulations!"), GetHogName(CurrentHedgehog), finishTime)) updateChallengeRecord("TimeRecord", rawFinishTime, false) SendStat(siCustomAchievement, string.format(loc("%s bravely climbed up to a dizzy height of %d to reach home."), GetHogName(CurrentHedgehog), getActualHeight(RecordHeight))) updateChallengeRecord("Highscore", getActualHeight(RecordHeight)) SendStat(siPointType, "!TIME") SendStat(siPlayerKills, tostring(rawFinishTime), GetHogTeamName(CurrentHedgehog)) EndGame() SetState(CurrentHedgehog, gstWinner) onAchievementsDeclaration() YouWon = true end else if distanceFromWater < 0 and not YouLost and not YouWon then makeMultiPlayerLoserStat(CurrentHedgehog) deadHedgehogs = deadHedgehogs + 1 YouLost = true if deadHedgehogs >= totalHedgehogs then makeFinalMultiPlayerStats() EndGame() onAchievementsDeclaration() end end -- Check victory if not YouWon and not YouLost and gearIsInBox(CurrentHedgehog, 1920, 252, 50, 50) and -- Delay victory if MrMine is triggered (not MrMine or (MrMine and band(GetState(MrMine), gstAttacking) == 0)) then -- Player managed to reach home in multiplayer. -- Stop hog, disable controls, celebrate victory and continue the game after 4 seconds. AddCaption(string.format(loc("%s climbed home in %d seconds!"), GetHogName(CurrentHedgehog), roundedFinishTime), capcolDefault, capgrpGameState) SendStat(siCustomAchievement, string.format(loc("%s (%s) reached home in %.3f seconds."), GetHogName(CurrentHedgehog), GetHogTeamName(CurrentHedgehog), finishTime)) makeMultiPlayerWinnerStat(CurrentHedgehog) PlaySound(sndVictory, CurrentHedgehog) SetWeapon(amNothing) SetGearMessage(CurrentHedgehog, band(GetGearMessage(CurrentHedgehog), bnot(gmLeft+gmRight+gmUp+gmDown+gmHJump+gmLJump+gmPrecise))) SetInputMask(0x00) -- TODO: Add stupid winner grin. multiplayerVictoryDelay = 4000 YouWon = true end end if GameTime % 500 == 0 then if not isSinglePlayer then for t,i in pairs(teams) do if currTeam == t then SendStat(siClanHealth, tostring(getActualHeight(y)), t) else SendStat(siClanHealth, '0', t) end end else SendStat(siClanHealth, tostring(getActualHeight(y)), GetHogTeamName(CurrentHedgehog)) end -- If player is inside home, tell player to take a seat. if not takeASeat and gearIsInBox(CurrentHedgehog, 1765, 131, 244, 189) then AddCaption(loc("Welcome home! Please take a seat")) takeASeat = true end if addCake and CakeTries < 10 and y < 32600 and y > 3000 and Cake == nil then -- doing this just after the start the first time to take advantage of randomness sources -- Pick a clear y to start with if y > 31000 then cy = 24585 elseif y > 28000 then cy = 21500 elseif y > 24000 then cy = 19000 elseif y > 21500 then cy = 16000 elseif y > 19000 then cy = 12265 elseif y > 16000 then cy = 8800 elseif y > 12000 then cy = 5700 else cy = 400 end Cake = AddGear(GetRandom(2048), cy, gtCake, 0, 0, 0, 0) SetHealth(Cake,999999) CakeTries = CakeTries + 1 end if (y > 286) or (y < 286 and MaxHeight > 286) then if MaxHeight > 286 and y <= 286 then -- wow, reached top local teamName = GetHogTeamName(CurrentHedgehog) if teamTimes[teamName] == nil or teamTimes[teamName] > GameTime - startTime then teamTimes[teamName] = GameTime - startTime end MaxHeight = 286 end if y < MaxHeight and y > 286 then MaxHeight = y end -- New maximum height of this turn? if MaxHeight < hTagHeight then hTagHeight = MaxHeight if hTag ~= nil then DeleteVisualGear(hTag) end hTag = AddVisualGear(0, 0, vgtHealthTag, 0, true) local score = 32640-hTagHeight -- snagged from space invasion SetVisualGearValues ( hTag, --id -(ScreenWidth/2) + 40, --xoffset ScreenHeight - 60, --yoffset 0, --dx 0, --dy 1.1, --zoom 1, --~= 0 means align to screen nil, --frameticks -- 116px off bottom for lowest rock, 286 or so off top for position of chair -- 32650 is "0" score, --value 99999999999,--timer GetClanColor(GetHogClan(CurrentHedgehog)) ) local team = GetHogTeamName(CurrentHedgehog) SetTeamLabel(team, math.max(score, teamBests[team] or 0)) end -- New record height? if MaxHeight < RecordHeight then RecordHeight = MaxHeight local oldName = RecordHeightHogName RecordHeightHogName = GetHogName(CurrentHedgehog) if oldName == nil then recordBroken = true end if not isSinglePlayer and RecordHeight > 1500 and not recordBroken then recordBroken = true AddCaption(string.format(loc("%s has passed the best height of %s!"), RecordHeightHogName, oldName)) end if not isSinglePlayer then if rTag ~= nil then DeleteVisualGear(rTag) end rTag = AddVisualGear(0, 0, vgtHealthTag, 0, true) -- snagged from space invasion SetVisualGearValues ( rTag, --id -(ScreenWidth/2) + 100, --xoffset ScreenHeight - 60, --yoffset 0, --dx 0, --dy 1.1, --zoom 1, --~= 0 means align to screen nil, --frameticks -- 116px off bottom for lowest rock, 286 or so off top for position of chair -- 32650 is "0" getActualHeight(RecordHeight), --value 99999999999,--timer GetClanColor(GetHogClan(CurrentHedgehog)) ) end end end if MaxHeight > 286 then if tTag ~= nil then DeleteVisualGear(tTag) end tTag = AddVisualGear(0, 0, vgtHealthTag, 0, true) -- snagged from space invasion SetVisualGearValues ( tTag, --id -(ScreenWidth/2) + 40, --xoffset ScreenHeight - 100, --yoffset 0, --dx 0, --dy 1.1, --zoom 1, --~= 0 means align to screen nil, --frameticks (GameTime-startTime)/1000, --value 99999999999,--timer 0xffffffff ) end end end end function onGearDamage(gear, damage) if GetGearType(gear) == gtHedgehog and not YouLost and not YouWon then -- Joke award for largest damage to hog local qualifyDamage = 50 if (damage >= qualifyDamage) then local awarded = false if jokeAwardDamage == nil or damage > jokeAwardDamage.damage then awarded = true end if awarded == true then jokeAwardDamage = { hogName = GetHogName(CurrentHedgehog), teamName = GetHogTeamName(CurrentHedgehog), damage = damage } end end if isSinglePlayer then makeSinglePlayerLoserStats() else deadHedgehogs = deadHedgehogs + 1 makeMultiPlayerLoserStat(gear) if (deadHedgehogs + multiplayerWins) >= totalHedgehogs then makeFinalMultiPlayerStats() EndGame() onAchievementsDeclaration() end end YouLost = true end end function makeLoserComment() local m if isSinglePlayer then m = 10 else m = 6 end local r = math.random(1,m) if r == 1 then text = loc("%s never got the ninja diploma.") elseif r == 2 then text = loc("You have to move upwards, not downwards, %s!") elseif r == 3 then text = loc("%s never wanted to reach for the sky in the first place.") elseif r == 4 then text = loc("%s should try the rope training mission first.") elseif r == 5 then text = loc("%s skipped ninja classes.") elseif r == 6 then text = loc("%s doesn’t really know how to handle a rope properly.") elseif r == 7 then text = loc("Better luck next time!") elseif r == 8 then text = loc("It was all just bad luck!") elseif r == 9 then text = loc("Well, that escalated quickly!") elseif r == 10 then text = loc("What? Is it over already?") end return text end function makeSinglePlayerLoserStats() local actualHeight = getActualHeight(RecordHeight) SendStat(siGameResult, loc("Challenge over!")) SendStat(siGraphTitle, loc("Your height over time")) local text if actualHeight > 30000 then text = loc("%s was damn close to home.") elseif actualHeight > 28000 then text = loc("%s was close to home.") elseif actualHeight > 24265 then text = loc("%s was good, but not good enough.") elseif actualHeight > 16177 then text = loc("%s managed to pass half of the distance towards home.") elseif actualHeight > 8088 then text = loc("%s went over a quarter of the way towards home.") elseif actualHeight > 5100 then text = loc("%s still had a long way to go.") elseif actualHeight > 2000 then text = loc("%s made it past the hogosphere.") elseif actualHeight > 1500 then text = loc("%s barely made it past the hogosphere.") else text = makeLoserComment() end if actualHeight > 1500 then SendStat(siCustomAchievement, string.format(text, RecordHeightHogName, actualHeight)) else SendStat(siCustomAchievement, string.format(text, RecordHeightHogName)) end updateChallengeRecord("Highscore", actualHeight) SendStat(siPointType, "!POINTS") SendStat(siPlayerKills, actualHeight, GetHogTeamName(CurrentHedgehog)) EndGame() onAchievementsDeclaration() end function makeMultiPlayerLoserStat(gear) local teamName = GetHogTeamName(gear) local actualHeight = getActualHeight(MaxHeight) if teamBests[teamName] == nil then teamBests[teamName] = actualHeight end if teamBests[teamName] < actualHeight then teamBests[teamName] = actualHeight end if teamScoreStats[teamName] == nil then teamScoreStats[teamName] = {} end table.insert(teamScoreStats[teamName], actualHeight) end function makeMultiPlayerWinnerStat(gear) return makeMultiPlayerLoserStat(gear) end function makeFinalMultiPlayerStats() local ranking = {} for k,v in pairs(teamBests) do table.insert(ranking, {name=k, score=v}) end local comp = function(table1, table2) if table1.score < table2.score then return true else return false end end table.sort(ranking, comp) local winner = ranking[#ranking] local loser = ranking[1] SendStat(siGameResult, string.format(loc("%s wins!"), winner.name)) SendStat(siGraphTitle, string.format(loc("Height over time"))) if winner.score < 1500 then SendStat(siCustomAchievement, string.format(loc("This round’s award for ultimate disappointment goes to: Everyone!"))) else if winner.score > 30000 then text = loc("%s (%s) reached for the sky and beyond with a height of %d!") elseif winner.score > 24750 then text = loc("%s (%s) was certainly not afraid of heights: Peak height of %d!") elseif winner.score > 16500 then text = loc("%s (%s) does not have to feel ashamed for their best height of %d.") elseif winner.score > 8250 then text = loc("%s (%s) reached a decent peak height of %d.") else text = loc("%s (%s) reached a peak height of %d.") end SendStat(siCustomAchievement, string.format(text, RecordHeightHogName, winner.name, winner.score)) if loser.score < 1500 then text = makeLoserComment() SendStat(siCustomAchievement, string.format(text, loser.name)) end end checkAwards() for i = #ranking, 1, -1 do SendStat(siPointType, "!POINTS") SendStat(siPlayerKills, tostring(ranking[i].score), ranking[i].name) end end function checkAwards() if jokeAwardNavy ~= nil then if isSinglePlayer then SendStat(siCustomAchievement, string.format(loc("The Navy greets %s for managing to get in a distance of %d away from the mainland!"), jokeAwardNavy.hogName, jokeAwardNavy.distance)) else SendStat(siCustomAchievement, string.format(loc("Greetings from the Navy, %s (%s), for being a distance of %d away from the mainland!"), jokeAwardNavy.hogName, jokeAwardNavy.teamName, jokeAwardNavy.distance)) end end if jokeAwardSpeed ~= nil then if isSinglePlayer then SendStat(siCustomAchievement, string.format(loc("Your hedgehog was panicly afraid of the water and decided to go in a safe distance of %d from it."), jokeAwardSpeed.distance)) else SendStat(siCustomAchievement, string.format(loc("%s (%s) was panicly afraid of the water and decided to get in a safe distance of %d from it."), jokeAwardSpeed.hogName, jokeAwardSpeed.teamName, jokeAwardSpeed.distance)) end end if jokeAwardDamage ~= nil then if isSinglePlayer then SendStat(siCustomAchievement, string.format(loc("Ouch! That must have hurt. You mutilated your poor hedgehog hog with %d damage."), jokeAwardDamage.damage)) else SendStat(siCustomAchievement, string.format(loc("Ouch! That must have hurt. %s (%s) hit the ground with %d damage points."), jokeAwardDamage.hogName, jokeAwardDamage.teamName, jokeAwardDamage.damage)) end end end function getActualHeight(height) return 32640-height end function onAchievementsDeclaration() for teamname, score in pairs(teamBests) do DeclareAchievement("height reached", teamname, "ClimbHome", -score) end for teamname, score in pairs(teamTimes) do DeclareAchievement("rope race", teamname, "ClimbHome", score) end end