1------------------- ABOUT ---------------------- 2-- 3-- Hero has to pass as fast as possible inside the 4-- rings as in the racer mode 5 6HedgewarsScriptLoad("/Scripts/Locale.lua") 7HedgewarsScriptLoad("/Scripts/Animate.lua") 8HedgewarsScriptLoad("/Scripts/Utils.lua") 9HedgewarsScriptLoad("/Missions/Campaign/A_Space_Adventure/global_functions.lua") 10 11----------------- VARIABLES -------------------- 12-- globals 13local missionName = loc("Hard flying") 14local challengeStarted = false 15local challengeStartRequested = false 16local currentWaypoint = 1 17local radius = 75 -- Ring radius. Will become smaller and smaller 18local totalTime = 15000 -- Total available time. Initial value is start time; is added to later when player wins extra time 19local totalSaucers = 3 20local gameEnded = false 21local heroTurn = false 22local RED = 0xff0000ff 23local GREEN = 0x00ff00ff 24local challengeObjectives = loc("To win the game you have to pass into the rings in time.").. 25 "|"..loc("You'll get extra time in case you need it when you pass a ring.").."|".. 26 loc("Green double rings also give you a new flying saucer.").."|".. 27 loc("Use the attack key twice to change the flying saucer while floating in mid-air.") 28local timeRecord 29-- dialogs 30local dialog01 = {} 31-- hogs 32local hero = {} 33local ally = {} 34-- teams 35local teamA = {} 36local teamB = {} 37-- hedgehogs values 38hero.name = loc("Hog Solo") 39hero.x = 750 40hero.y = 130 41hero.dead = false 42ally.name = loc("Paul McHoggy") 43ally.x = 860 44ally.y = 130 45teamA.name = loc("Hog Solo") 46teamA.color = -6 47teamB.name = loc("Allies") 48teamB.color = -6 49-- way points 50local waypoints = { 51 [1] = {x=1450, y=140}, 52 [2] = {x=990, y=580}, 53 [3] = {x=1650, y=950}, 54 [4] = {x=620, y=630}, 55 [5] = {x=1470, y=540}, 56 [6] = {x=1960, y=60}, 57 [7] = {x=1600, y=400}, 58 [8] = {x=240, y=940}, 59 [9] = {x=200, y=530}, 60 [10] = {x=1180, y=120}, 61 [11] = {x=1950, y=660}, 62 [12] = {x=1280, y=980}, 63 [13] = {x=590, y=1100}, 64 [14] = {x=20, y=620}, 65 [15] = {x=hero.x, y=hero.y} 66} 67 68-------------- LuaAPI EVENT HANDLERS ------------------ 69 70function onGameInit() 71 GameFlags = gfInvulnerable + gfOneClanMode 72 Seed = 1 73 TurnTime = totalTime 74 Ready = 25000 75 CaseFreq = 0 76 MinesNum = 0 77 MinesTime = 1 78 Explosives = 0 79 Map = "ice02_map" 80 Theme = "Snow" 81 -- Disable Sudden Death 82 WaterRise = 0 83 HealthDecrease = 0 84 85 -- Hero 86 teamA.name = AddMissionTeam(teamA.color) 87 hero.gear = AddMissionHog(100) 88 hero.name = GetHogName(hero.gear) 89 AnimSetGearPosition(hero.gear, hero.x, hero.y) 90 -- Ally 91 teamB.name = AddTeam(teamB.name, teamB.color, "heart", "Island", "Default_qau", "cm_face") 92 SetTeamPassive(teamB.name, true) 93 ally.gear = AddHog(ally.name, 0, 100, "war_airwarden02") 94 AnimSetGearPosition(ally.gear, ally.x, ally.y) 95 HogTurnLeft(ally.gear, true) 96 97 timeRecord = tonumber(GetCampaignVar("IceStadiumBestTime")) 98 99 initCheckpoint("ice02") 100 101 AnimInit(true) 102 AnimationSetup() 103end 104 105function ShowGoals() 106 -- mission objectives 107 local goalStr = challengeObjectives 108 if timeRecord ~= nil then 109 local personalBestStr = string.format(loc("Personal best: %.3f seconds"), timeRecord/1000) 110 goalStr = goalStr .. "|" .. personalBestStr 111 end 112 ShowMission(missionName, loc("Getting ready"), goalStr, 1, 25000) 113end 114 115function onGameStart() 116 AnimWait(hero.gear, 3000) 117 FollowGear(hero.gear) 118 ShowGoals() 119 HideMission() 120 121 AddEvent(onHeroDeath, {hero.gear}, heroDeath, {hero.gear}, 0) 122 123 AddAmmo(hero.gear, amJetpack, 3) 124 125 -- place a waypoint 126 placeNextWaypoint() 127 128 SendHealthStatsOff() 129 AddAnim(dialog01) 130end 131 132function onEndTurn() 133 if not hero.dead and CurrentHedgehog == hero.gear and challengeStarted then 134 heroLost() 135 end 136end 137 138function onNewTurn() 139 if challengeStartRequested then 140 challengeStarted = true 141 end 142 if not hero.dead and CurrentHedgehog == hero.gear and challengeStarted then 143 SetWeapon(amJetpack) 144 end 145 heroTurn = CurrentHedgehog == hero.gear 146end 147 148function onGameTick() 149 AnimUnWait() 150 if ShowAnimation() == false then 151 return 152 end 153 ExecuteAfterAnimations() 154 CheckEvents() 155end 156 157function onGameTick20() 158 if checkIfHeroInWaypoint() then 159 if not gameEnded and not placeNextWaypoint() then 160 gameEnded = true 161 -- GAME OVER, WIN! 162 totalTime = totalTime - TurnTimeLeft 163 local totalTimePrinted = totalTime / 1000 164 local saucersLeft = GetAmmoCount(hero.gear, amJetpack) 165 local saucersUsed = totalSaucers - saucersLeft 166 SetTeamLabel(teamA.name, string.format(loc("%.3fs"), totalTimePrinted)) 167 SendStat(siGameResult, loc("Hooray! You are a champion!")) 168 SendStat(siCustomAchievement, string.format(loc("You completed the mission in %.3f seconds."), totalTimePrinted)) 169 if timeRecord ~= nil and totalTime >= timeRecord then 170 SendStat(siCustomAchievement, string.format(loc("Your personal best time so far: %.3f seconds"), timeRecord/1000)) 171 end 172 if timeRecord == nil or totalTime < timeRecord then 173 SaveCampaignVar("IceStadiumBestTime", tostring(totalTime)) 174 if timeRecord ~= nil then 175 SendStat(siCustomAchievement, loc("This is a new personal best time, congratulations!")) 176 end 177 end 178 SendStat(siCustomAchievement, string.format(loc("You have used %d flying saucers."), saucersUsed)) 179 180 local leastSaucersRecord = tonumber(GetCampaignVar("IceStadiumLeastSaucersUsed")) 181 if leastSaucersRecord == nil or saucersUsed < leastSaucersRecord then 182 SaveCampaignVar("IceStadiumLeastSaucersUsed", tostring(saucersUsed)) 183 end 184 185 SendStat(siPointType, "!TIME") 186 SendStat(siPlayerKills, totalTime, GetHogTeamName(hero.gear)) 187 SaveCampaignVar("Mission6Won", "true") 188 checkAllMissionsCompleted() 189 SetTurnTimeLeft(MAX_TURN_TIME) 190 EndGame() 191 end 192 end 193 if heroTurn and challengeStarted and not gameEnded and not hero.dead and ReadyTimeLeft == 0 then 194 local time = totalTime - TurnTimeLeft 195 local timePrinted = time / 1000 196 SetTeamLabel(teamA.name, string.format(loc("%.1fs"), timePrinted)) 197 if TurnTimeLeft <= 0 then 198 local wp = waypoints[currentWaypoint-1] 199 if wp ~= nil then 200 DeleteVisualGear(wp.gear) 201 DeleteVisualGear(wp.gear2) 202 end 203 end 204 end 205end 206 207function onGearDelete(gear) 208 if gear == hero.gear then 209 hero.dead = true 210 end 211end 212 213function onGearAdd(gear) 214 if GetGearType(gear) == gtJetpack then 215 HideMission() 216 end 217end 218 219function onPrecise() 220 if GameTime > 3000 then 221 SetAnimSkip(true) 222 end 223end 224 225-------------- EVENTS ------------------ 226 227function onHeroDeath(gear) 228 if hero.dead then 229 return true 230 end 231 return false 232end 233 234-------------- ACTIONS ------------------ 235 236function heroDeath(gear) 237 heroLost() 238end 239 240-------------- ANIMATIONS ------------------ 241 242function Skipanim(anim) 243 ShowGoals() 244 startFlying() 245end 246 247function AnimationSetup() 248 -- DIALOG 01 - Start, some story telling 249 AddSkipFunction(dialog01, Skipanim, {dialog01}) 250 table.insert(dialog01, {func = AnimWait, args = {hero.gear, 3000}}) 251 table.insert(dialog01, {func = AnimCaption, args = {hero.gear, loc("In the stadium, where the best pilots compete ..."), 5000}}) 252 table.insert(dialog01, {func = AnimSay, args = {ally.gear, loc("This is the Olympic Stadium of Saucer Flying."), SAY_SAY, 4000}}) 253 table.insert(dialog01, {func = AnimSay, args = {ally.gear, loc("All the saucer pilots dream to come here one day in order to compete with the best!"), SAY_SAY, 5000}}) 254 table.insert(dialog01, {func = AnimSay, args = {ally.gear, loc("Now you have the chance to try and claim the place that you deserve among the best."), SAY_SAY, 6000}}) 255 table.insert(dialog01, {func = AnimSay, args = {ally.gear, loc("Can you do it?"), SAY_SAY, 2000}}) 256 table.insert(dialog01, {func = AnimWait, args = {hero.gear, 500}}) 257 table.insert(dialog01, {func = ShowGoals, args = {}}) 258 table.insert(dialog01, {func = startFlying, args = {hero.gear}}) 259end 260 261------------------ Other Functions ------------------- 262 263function startFlying() 264 challengeStartRequested = true 265 EndTurn(true) 266end 267 268function placeNextWaypoint() 269 if gameEnded then 270 return 271 end 272 if currentWaypoint > 1 then 273 local wp = waypoints[currentWaypoint-1] 274 DeleteVisualGear(wp.gear) 275 DeleteVisualGear(wp.gear2) 276 end 277 if currentWaypoint < 16 then 278 local wp = waypoints[currentWaypoint] 279 wp.gear = AddVisualGear(1,1,vgtCircle,1,true) 280 -- 1st, 3rd, 5th, 7th, 9th, ... ring 281 if currentWaypoint % 2 == 0 then 282 -- Render single red ring 283 SetVisualGearValues(wp.gear, wp.x,wp.y, 20, 200, 0, 0, 100, radius, 3, RED) 284 -- Give 1 flying saucer and, if needed, extra time 285 AddAmmo(hero.gear, amJetpack, GetAmmoCount(hero.gear, amJetpack)+1) 286 PlaySound(sndShotgunReload) 287 totalSaucers = totalSaucers + 1 288 local vgear = AddVisualGear(GetX(hero.gear), GetY(hero.gear), vgtAmmo, 0, true) 289 if vgear ~= nil then 290 SetVisualGearValues(vgear,nil,nil,nil,nil,nil,amJetpack) 291 end 292 local message 293 if TurnTimeLeft <= 22000 then 294 SetTurnTimeLeft(TurnTimeLeft + 8000) 295 totalTime = totalTime + 8000 296 PlaySound(sndExtraTime) 297 message = loc("Got 1 more saucer and 8 more seconds added to the clock") 298 else 299 message = loc("Got 1 more saucer") 300 end 301 AnimCaption(hero.gear, message, 4000) 302 -- 2nd, 4th, 6th, 8th, 10th, ... ring 303 else 304 -- Render double green ring 305 SetVisualGearValues(wp.gear, wp.x,wp.y, 20, 200, 0, 0, 100, radius, 3, GREEN) 306 wp.gear2 = AddVisualGear(1,1,vgtCircle,1,true) 307 SetVisualGearValues(wp.gear2, wp.x,wp.y, 20, 200, 0, 0, 100, radius - 6, 2, GREEN) 308 -- Give extra time, if needed 309 if TurnTimeLeft <= 16000 then 310 if currentWaypoint ~= 1 then 311 SetTurnTimeLeft(TurnTimeLeft + 6000) 312 totalTime = totalTime + 6000 313 PlaySound(sndExtraTime) 314 AnimCaption(hero.gear, loc("6 more seconds added to the clock"), 4000) 315 end 316 end 317 end 318 radius = radius - 4 319 currentWaypoint = currentWaypoint + 1 320 return true 321 else 322 AnimCaption(hero.gear, loc("Congratulations, you won!"), 4000) 323 PlaySound(sndVictory, hero.gear) 324 end 325 return false 326end 327 328function checkIfHeroInWaypoint() 329 if (not hero.dead) and (TurnTimeLeft > 0) then 330 local wp = waypoints[currentWaypoint-1] 331 if gearIsInCircle(hero.gear, wp.x, wp.y, radius+4, false) then 332 SetWind(GetRandom(201)-100) 333 return true 334 end 335 end 336 return false 337end 338 339function heroLost() 340 SendStat(siGameResult, loc("Oh man! Learn how to fly!")) 341 SendStat(siCustomAchievement, loc("To win the game you have to pass into the rings in time.")) 342 SendStat(siCustomAchievement, loc("You'll get extra time in case you need it when you pass a ring.")) 343 SendStat(siCustomAchievement, loc("Green double rings also give you a new flying saucer.")) 344 SendStat(siCustomAchievement, loc("Use the attack key twice to change the flying saucer while being in air.")) 345 sendSimpleTeamRankings({teamA.name}) 346 gameEnded = true 347 EndGame() 348end 349