# HG changeset patch # User mikade # Date 1418297883 -32400 # Node ID 1c85a442bd563271eba18e6f59862fb50de52445 # Parent cdce07f5a0117a68863dd37f7658b5dbf45382db Wuzzy's changes to stats for some of the training missions. diff -r cdce07f5a011 -r 1c85a442bd56 share/hedgewars/Data/Missions/Training/Basic_Training_-_Bazooka.lua --- a/share/hedgewars/Data/Missions/Training/Basic_Training_-_Bazooka.lua Thu Dec 11 10:33:49 2014 +0100 +++ b/share/hedgewars/Data/Missions/Training/Basic_Training_-_Bazooka.lua Thu Dec 11 20:38:03 2014 +0900 @@ -1,186 +1,242 @@ --- Hedgewars Bazooka Training --- Scripting Example - --- Lines such as this one are comments - they are ignored --- by the game, no matter what kind of text is in there. --- It's also possible to place a comment after some real --- instruction as you see below. In short, everything --- following "--" is ignored. - ---------------------------------------------------------------- --- At first we implement the localization library using loadfile. --- This allows us to localize strings without needing to think --- about translations. --- We can use the function loc(text) to localize a string. - -HedgewarsScriptLoad("/Scripts/Locale.lua") - --- This variable will hold the number of destroyed targets. -local score = 0 --- This variable represents the number of targets to destroy. -local score_goal = 5 --- This variable controls how many milliseconds/ticks we'd --- like to wait before we end the round once all targets --- have been destroyed. -local end_timer = 1000 -- 1000 ms = 1 s --- This variable is set to true if the game is lost (i.e. --- time runs out). -local game_lost = false --- This variable will point to the hog's gear -local player = nil --- This variable will grab the time left at the end of the round -local time_goal = 0 - --- This is a custom function to make it easier to --- spawn more targets with just one line of code --- You may define as many custom functions as you --- like. -function spawnTarget() - -- add a new target gear - gear = AddGear(0, 0, gtTarget, 0, 0, 0, 0) - - -- move it to a random position within 0 and - -- LAND_WIDTH - the width of the map - FindPlace(gear, true, 0, LAND_WIDTH) - - -- move the target to a higher vertical position - -- to ensure it's not somewhere down below - x, y = GetGearPosition(gear) - SetGearPosition(gear, x, 0) -end - --- This function is called before the game loads its --- resources. --- It's one of the predefined function names that will --- be called by the game. They give you entry points --- where you're able to call your own code using either --- provided instructions or custom functions. -function onGameInit() - -- At first we have to overwrite/set some global variables - -- that define the map, the game has to load, as well as - -- other things such as the game rules to use, etc. - -- Things we don't modify here will use their default values. - - -- The base number for the random number generator - Seed = 1 - -- Game settings and rules - EnableGameFlags(gfMultiWeapon, gfOneClanMode, gfSolidLand) - -- Uncommenting this wouldn't do anything - --EnableGameFlags(gfMultiWeapon, gfOneClanMode, gfSolidLand) - -- Neither this - --DisableGameFlags(gfArtillery) - -- Uncommenting this would make the terrain damageable - --DisableGameFlags(gfSolidLand) - -- Uncommenting this would remove all flags set previously - --ClearGameFlags() - -- The time the player has to move each round (in ms) - TurnTime = 60000 - -- The frequency of crate drops - CaseFreq = 0 - -- The number of mines being placed - MinesNum = 0 - -- The number of explosives being placed - Explosives = 0 - -- The delay between each round - Delay = 0 - -- The map to be played - Map = "Bamboo" - -- The theme to be used - Theme = "Bamboo" - - -- Create the player team - AddTeam(loc("'Zooka Team"), 14483456, "Simple", "Island", "Default") - -- And add a hog to it - player = AddHog(loc("Hunter"), 0, 1, "NoHat") - SetGearPosition(player, 936, 136) -end - --- This function is called when the round starts --- it spawns the first target that has to be destroyed. --- In addition it shows the scenario goal(s). -function onGameStart() - -- Spawn the first target. - spawnTarget() - - -- Show some nice mission goals. - -- Parameters are: caption, sub caption, description, - -- extra text, icon and time to show. - -- A negative icon parameter (-n) represents the n-th weapon icon - -- A positive icon paramter (n) represents the (n+1)-th mission icon - -- A timeframe of 0 is replaced with the default time to show. - ShowMission(loc("Bazooka Training"), loc("Aiming Practice"), loc("Eliminate all targets before your time runs out.|You have unlimited ammo for this mission."), -amBazooka, 0) -end - -function onNewTurn() - SetWeapon(amBazooka) -end - --- This function is called every game tick. --- Note that there are 1000 ticks within one second. --- You shouldn't try to calculate too complicated --- code here as this might slow down your game. -function onGameTick20() - -- If time's up, set the game to be lost. - -- We actually check the time to be "1 ms" as it - -- will be at "0 ms" right at the start of the game. - if TurnTimeLeft < 40 and TurnTimeLeft > 0 and score < score_goal then - game_lost = true - -- ... and show a short message. - ShowMission(loc("Bazooka Training"), loc("Aiming Practice"), loc("Oh no! Time's up! Just try again."), -amSkip, 0) - -- How about killing our poor hog due to his poor performance? - SetHealth(player, 0) - -- Just to be sure set the goal time to 1 ms - time_goal = 1 - end - -- If the goal is reached or we've lost ... - if score == score_goal or game_lost then - -- ... check to see if the time we'd like to - -- wait has passed and then ... - if end_timer == 0 then - -- ... end the game ... - EndGame() - else - -- ... or just lower the timer by 20ms. - -- Reset the time left to stop the timer - TurnTimeLeft = time_goal - end - end_timer = end_timer - 20 - end -end - --- This function is called when the game is initialized --- to request the available ammo and probabilities -function onAmmoStoreInit() - -- add an unlimited supply of bazooka ammo - SetAmmo(amBazooka, 9, 0, 0, 0) -end - --- This function is called when a new gear is added. --- We don't need it for this training, so we can --- keep it empty. --- function onGearAdd(gear) --- end - --- This function is called before a gear is destroyed. --- We use it to count the number of targets destroyed. -function onGearDelete(gear) - -- We're only interested in target gears. - if GetGearType(gear) == gtTarget then - -- Add one point to our score/counter - score = score + 1 - -- If we haven't reached the goal ... - if score < score_goal then - -- ... spawn another target. - spawnTarget() - else - if not game_lost then - -- Otherwise show that the goal was accomplished - ShowMission(loc("Bazooka Training"), loc("Aiming Practice"), loc("Congratulations! You've eliminated all targets|within the allowed time frame."), 0, 0) - -- Also let the hogs shout "victory!" - PlaySound(sndVictory) - -- Save the time left so we may keep it. - time_goal = TurnTimeLeft - end - end - end -end +-- Hedgewars Bazooka Training +-- Scripting Example + +-- Lines such as this one are comments - they are ignored +-- by the game, no matter what kind of text is in there. +-- It's also possible to place a comment after some real +-- instruction as you see below. In short, everything +-- following "--" is ignored. + +--------------------------------------------------------------- +-- At first we implement the localization library using loadfile. +-- This allows us to localize strings without needing to think +-- about translations. +-- We can use the function loc(text) to localize a string. + +HedgewarsScriptLoad("/Scripts/Locale.lua") + +-- This variable will hold the number of destroyed targets. +local score = 0 +-- This variable represents the number of targets to destroy. +local score_goal = 5 +-- This variable controls how many milliseconds/ticks we'd +-- like to wait before we end the round once all targets +-- have been destroyed. +local end_timer = 1000 -- 1000 ms = 1 s +-- This variable is set to true if the game is lost (i.e. +-- time runs out). +local game_lost = false +-- This variable will point to the hog's gear +local player = nil +-- This variable will grab the time left at the end of the round +local time_goal = 0 +-- This variable stores the number of bazooka shots +local shots = 0 + +-- This is a custom function to make it easier to +-- spawn more targets with just one line of code +-- You may define as many custom functions as you +-- like. +function spawnTarget() + -- add a new target gear + gear = AddGear(0, 0, gtTarget, 0, 0, 0, 0) + + -- move it to a random position within 0 and + -- LAND_WIDTH - the width of the map + FindPlace(gear, true, 0, LAND_WIDTH) + + -- move the target to a higher vertical position + -- to ensure it's not somewhere down below + x, y = GetGearPosition(gear) + SetGearPosition(gear, x, 0) +end + +-- This function is called before the game loads its +-- resources. +-- It's one of the predefined function names that will +-- be called by the game. They give you entry points +-- where you're able to call your own code using either +-- provided instructions or custom functions. +function onGameInit() + -- At first we have to overwrite/set some global variables + -- that define the map, the game has to load, as well as + -- other things such as the game rules to use, etc. + -- Things we don't modify here will use their default values. + + -- The base number for the random number generator + Seed = 1 + -- Game settings and rules + EnableGameFlags(gfMultiWeapon, gfOneClanMode, gfSolidLand) + -- Uncommenting this wouldn't do anything + --EnableGameFlags(gfMultiWeapon, gfOneClanMode, gfSolidLand) + -- Neither this + --DisableGameFlags(gfArtillery) + -- Uncommenting this would make the terrain damageable + --DisableGameFlags(gfSolidLand) + -- Uncommenting this would remove all flags set previously + --ClearGameFlags() + -- The time the player has to move each round (in ms) + TurnTime = 60000 + -- The frequency of crate drops + CaseFreq = 0 + -- The number of mines being placed + MinesNum = 0 + -- The number of explosives being placed + Explosives = 0 + -- The delay between each round + Delay = 0 + -- The map to be played + Map = "Bamboo" + -- The theme to be used + Theme = "Bamboo" + + -- Create the player team + AddTeam(loc("'Zooka Team"), 14483456, "Simple", "Island", "Default") + -- And add a hog to it + player = AddHog(loc("Hunter"), 0, 1, "NoHat") + SetGearPosition(player, 936, 136) +end + +-- This function is called when the round starts +-- it spawns the first target that has to be destroyed. +-- In addition it shows the scenario goal(s). +function onGameStart() + -- Disable the graph in the stats screen, we don't need it + SendHealthStatsOff() + -- Spawn the first target. + spawnTarget() + + -- Show some nice mission goals. + -- Parameters are: caption, sub caption, description, + -- extra text, icon and time to show. + -- A negative icon parameter (-n) represents the n-th weapon icon + -- A positive icon paramter (n) represents the (n+1)-th mission icon + -- A timeframe of 0 is replaced with the default time to show. + ShowMission(loc("Bazooka Training"), loc("Aiming Practice"), loc("Eliminate all targets before your time runs out.|You have unlimited ammo for this mission."), -amBazooka, 0) +end + +function onNewTurn() + SetWeapon(amBazooka) +end + +-- This function is called every game tick. +-- Note that there are 1000 ticks within one second. +-- You shouldn't try to calculate too complicated +-- code here as this might slow down your game. +function onGameTick20() + -- If time's up, set the game to be lost. + -- We actually check the time to be "1 ms" as it + -- will be at "0 ms" right at the start of the game. + if TurnTimeLeft < 40 and TurnTimeLeft > 0 and score < score_goal and not game_lost then + game_lost = true + -- ... and show a short message. + ShowMission(loc("Bazooka Training"), loc("Aiming Practice"), loc("Oh no! Time's up! Just try again."), -amSkip, 0) + -- How about killing our poor hog due to his poor performance? + SetHealth(player, 0) + -- Just to be sure set the goal time to 1 ms + time_goal = 1 + end + + if band(GetState(player), gstDrowning) == gstDrowning and game_lost == false and score < score_goal then + game_lost = true + time_goal = 1 + AddCaption(loc("You lose!"), 0xFFFFFFFF, capgrpGameState) + ShowMission(loc("Bazooka Training"), loc("Aiming practice"), loc("Oh no! You failed! Just try again."), -amSkip, 0) + end + + -- If the goal is reached or we've lost ... + if score == score_goal or game_lost then + -- ... check to see if the time we'd like to + -- wait has passed and then ... + if end_timer == 0 then + -- Let’s create some stats for the stats screen! + -- We will expose the number of hit targets hit, launched bazooka and the accuracy + + SendStat(siPointType, loc("hits")) + SendStat(siPlayerKills, tostring(score), loc("'Zooka Team")) + SendStat(siCustomAchievement, string.format(loc("You have destroyed %d of %d targets."), score, score_goal)) + SendStat(siCustomAchievement, string.format(loc("You have launched %d bazookas."), shots)) + + -- We must avoid a division by zero + if(shots > 0) then + SendStat(siCustomAchievement, string.format(loc("Your accuracy was %.1f%%."), (score/shots)*100)) + end + if score == score_goal then + SendStat(siGameResult, "You have finished the bazooka training!") + SendStat(siCustomAchievement, string.format(loc("%.1f seconds were remaining."), (time_goal/1000), math.ceil(time_goal/12))) + end + if game_lost then + SendStat(siGameResult, "You lose!") + end + + -- Finally we end the game ... + EndGame() + else + -- ... or just lower the timer by 20ms. + -- Reset the time left to stop the timer + TurnTimeLeft = time_goal + end + end_timer = end_timer - 20 + end +end + +-- This function is called when the game is initialized +-- to request the available ammo and probabilities +function onAmmoStoreInit() + -- add an unlimited supply of bazooka ammo + SetAmmo(amBazooka, 9, 0, 0, 0) +end + +-- This function is called when a new gear is added. +-- We don't need it for this training, so we can +-- keep it empty. +-- function onGearAdd(gear) +-- end + +-- This function is called before a gear is destroyed. +-- We use it to count the number of targets destroyed. +function onGearDelete(gear) + -- We're only interested in target gears. + if GetGearType(gear) == gtTarget then + -- Add one point to our score/counter + score = score + 1 + -- If we haven't reached the goal ... + if score < score_goal then + -- ... spawn another target. + spawnTarget() + else + if not game_lost then + -- Otherwise show that the goal was accomplished + ShowMission(loc("Bazooka Training"), loc("Aiming Practice"), loc("Congratulations! You've eliminated all targets|within the allowed time frame."), 0, 0) + -- Also let the hogs shout "victory!" + PlaySound(sndVictory) + -- Save the time left so we may keep it. + time_goal = TurnTimeLeft + end + end + end +end + +-- This function is called when a gear has been damaged. +-- We only use it to determine wheather our hog took damage in order to abort the mission. +function onGearDamage(gear, damage) + if GetGearType(gear) == gtHedgehog then + if not game_lost then + game_lost = true + AddCaption(loc("You lose!", 0xFFFFFFFF, capgrpGameState)) + ShowMission(loc("Bazooka Training") , loc("Aiming practice"), loc("Oh no! You failed! Just try again."), -amSkip, 0) + + time_goal = 1 + end + end +end + + +-- This function is called after a gear is added. +-- We use it to count the number of bazooka shots. +function onGearAdd(gear) + -- Count the number of bazooka shots for our stats + if GetGearType(gear) == gtShell then + shots = shots + 1 + end +end diff -r cdce07f5a011 -r 1c85a442bd56 share/hedgewars/Data/Missions/Training/Basic_Training_-_Sniper_Rifle.lua --- a/share/hedgewars/Data/Missions/Training/Basic_Training_-_Sniper_Rifle.lua Thu Dec 11 10:33:49 2014 +0100 +++ b/share/hedgewars/Data/Missions/Training/Basic_Training_-_Sniper_Rifle.lua Thu Dec 11 20:38:03 2014 +0900 @@ -1,312 +1,349 @@ --- Hedgewars SniperRifle Training --- Scripting Example - --- Lines such as this one are comments - they are ignored --- by the game, no matter what kind of text is in there. --- It's also possible to place a comment after some real --- instruction as you see below. In short, everything --- following "--" is ignored. - ---------------------------------------------------------------- --- At first we implement the localization library using loadfile. --- This allows us to localize strings without needing to think --- about translations. --- We can use the function loc(text) to localize a string. - -HedgewarsScriptLoad("/Scripts/Locale.lua") - --- This variable will hold the number of destroyed targets. -local score = 0 --- This variable represents the number of targets to destroy. -local score_goal = 31 --- This variable controls how many milliseconds/ticks we'd --- like to wait before we end the round once all targets --- have been destroyed. -local end_timer = 1000 -- 1000 ms = 1 s --- This variable is set to true if the game is lost (i.e. --- time runs out). -local game_lost = false --- This variable will point to the hog's gear -local player = nil --- This variable will grab the time left at the end of the round -local time_goal = 0 - -local target = nil - -local last_hit_time = 0 --- This is a custom function to make it easier to --- spawn more targets with just one line of code --- You may define as many custom functions as you --- like. -function spawnTarget(x, y) - -- add a new target gear - target = AddGear(x, y, gtTarget, 0, 0, 0, 0) - -- have the camera move to the target so the player knows where it is - FollowGear(target) -end - -function blowUp(x, y) - -- adds some TNT - gear = AddGear(x, y, gtDynamite, 0, 0, 0, 0) -end - -function onNewTurn() - SetWeapon(amSniperRifle) -end - --- This function is called before the game loads its --- resources. --- It's one of the predefined function names that will --- be called by the game. They give you entry points --- where you're able to call your own code using either --- provided instructions or custom functions. -function onGameInit() - -- At first we have to overwrite/set some global variables - -- that define the map, the game has to load, as well as - -- other things such as the game rules to use, etc. - -- Things we don't modify here will use their default values. - - -- The base number for the random number generator - Seed = 0 - -- Game settings and rules - GameFlags = gfMultiWeapon + gfOneClanMode + gfArtillery - -- The time the player has to move each round (in ms) - TurnTime = 150000 - -- The frequency of crate drops - CaseFreq = 0 - -- The number of mines being placed - MinesNum = 0 - -- The number of explosives being placed - Explosives = 0 - -- The delay between each round - Delay = 0 - -- The map to be played - Map = "Ropes" - -- The theme to be used - Theme = "City" - - -- Create the player team - AddTeam(loc("Sniperz"), 14483456, "Simple", "Island", "Default") - -- And add a hog to it - player = AddHog(loc("Hunter"), 0, 1, "Sniper") - SetGearPosition(player, 602, 1465) -end - --- This function is called when the round starts --- it spawns the first target that has to be destroyed. --- In addition it shows the scenario goal(s). -function onGameStart() - -- Spawn the first target. - spawnTarget(860,1020) - - -- Show some nice mission goals. - -- Parameters are: caption, sub caption, description, - -- extra text, icon and time to show. - -- A negative icon parameter (-n) represents the n-th weapon icon - -- A positive icon paramter (n) represents the (n+1)-th mission icon - -- A timeframe of 0 is replaced with the default time to show. - ShowMission(loc("Sniper Training"), loc("Aiming Practice"), loc("Eliminate all targets before your time runs out.|You have unlimited ammo for this mission."), -amSniperRifle, 0) -end - --- This function is called every game tick. --- Note that there are 1000 ticks within one second. --- You shouldn't try to calculate too complicated --- code here as this might slow down your game. -function onGameTick20() - if game_lost then - return - end - -- after a target is destroyed, show hog, then target - if (target ~= nil) and (TurnTimeLeft + 1300 < last_hit_time) then - -- move camera to the target - FollowGear(target) - elseif TurnTimeLeft + 300 < last_hit_time then - -- move camera to the hog - FollowGear(player) - end - -- If time's up, set the game to be lost. - -- We actually check the time to be "1 ms" as it - -- will be at "0 ms" right at the start of the game. - if TurnTimeLeft < 40 and TurnTimeLeft > 0 and score < score_goal then - game_lost = true - -- ... and show a short message. - ShowMission(loc("Sniper Training"), loc("Aiming Practice"), loc("Oh no! Time's up! Just try again."), -amSkip, 0) - -- How about killing our poor hog due to his poor performance? - SetHealth(player, 0) - -- Just to be sure set the goal time to 1 ms - time_goal = 1 - end - -- If the goal is reached or we've lost ... - if score == score_goal or game_lost then - -- ... check to see if the time we'd like to - -- wait has passed and then ... - if end_timer == 0 then - -- ... end the game ... - EndGame() - else - -- ... or just lower the timer by 1. - -- Reset the time left to stop the timer - TurnTimeLeft = time_goal - end - end_timer = end_timer - 20 - end -end - --- This function is called when the game is initialized --- to request the available ammo and probabilities -function onAmmoStoreInit() - -- add an unlimited supply of shotgun ammo - SetAmmo(amSniperRifle, 9, 0, 0, 0) -end - --- This function is called when a new gear is added. --- We don't need it for this training, so we can --- keep it empty. --- function onGearAdd(gear) --- end - --- This function is called before a gear is destroyed. --- We use it to count the number of targets destroyed. -function onGearDelete(gear) - - if GetGearType(gear) == gtCase then - game_lost = true - return - end - - if (GetGearType(gear) == gtTarget) then - -- remember when the target was hit for adjusting the camera - last_hit_time = TurnTimeLeft - -- Add one point to our score/counter - score = score + 1 - -- If we haven't reached the goal ... - if score < score_goal then - -- ... spawn another target. - if score == 1 then - spawnTarget(1520,1350) - elseif score == 2 then - spawnTarget(1730,1040) - elseif score == 3 then - spawnTarget(2080,780) - elseif score == 4 then - AddCaption(loc("Good so far!") .. " " .. loc("Keep it up!")); - blowUp(1730,1226) - blowUp(1440,1595) - blowUp(1527,1575) - blowUp(1614,1595) - blowUp(1420,1675) - blowUp(1527,1675) - blowUp(1634,1675) - blowUp(1440,1755) - blowUp(1527,1775) - blowUp(1614,1755) - spawnTarget(1527,1667) - elseif score == 5 then - spawnTarget(1527,1667) - elseif score == 6 then - spawnTarget(2175,1300) - elseif score == 7 then - spawnTarget(2250,940) - elseif score == 8 then - spawnTarget(2665,1540) - elseif score == 9 then - spawnTarget(3040,1160) - elseif score == 10 then - spawnTarget(2930,1500) - elseif score == 11 then - AddCaption(loc("This one's tricky.")); - spawnTarget(700,720) - elseif score == 12 then - AddCaption(loc("Well done.")); - blowUp(914,1222) - blowUp(1050,1222) - blowUp(1160,1008) - blowUp(1160,1093) - blowUp(1160,1188) - blowUp(375,911) - blowUp(510,911) - blowUp(640,911) - blowUp(780,911) - blowUp(920,911) - blowUp(1060,913) - blowUp(1198,913) - spawnTarget(1200,730) - elseif score == 13 then - spawnTarget(1200,830) - elseif score == 14 then - spawnTarget(1430,450) - elseif score == 15 then - spawnTarget(796,240) - elseif score == 16 then - spawnTarget(300,10) - elseif score == 17 then - spawnTarget(2080,820) - elseif score == 18 then - AddCaption(loc("Demolition is fun!")); - blowUp(2110,920) - blowUp(2210,920) - blowUp(2200,305) - blowUp(2300,305) - blowUp(2300,400) - blowUp(2300,500) - blowUp(2300,600) - blowUp(2300,700) - blowUp(2300,800) - blowUp(2300,900) - blowUp(2401,305) - blowUp(2532,305) - blowUp(2663,305) - spawnTarget(2300,760) - elseif score == 19 then - spawnTarget(2300,760) - elseif score == 20 then - spawnTarget(2738,190) - elseif score == 21 then - spawnTarget(2590,-100) - elseif score == 22 then - AddCaption(loc("Will this ever end?")); - blowUp(2790,305) - blowUp(2930,305) - blowUp(3060,305) - blowUp(3190,305) - blowUp(3310,305) - blowUp(3393,613) - blowUp(2805,370) - blowUp(2805,500) - blowUp(2805,630) - blowUp(2805,760) - blowUp(2805,890) - blowUp(3258,370) - blowUp(3258,475) - blowUp(3264,575) - spawnTarget(3230,240) - elseif score == 23 then - spawnTarget(3230,290) - elseif score == 24 then - spawnTarget(3670,250) - elseif score == 25 then - spawnTarget(2620,-100) - elseif score == 26 then - spawnTarget(2870,300) - elseif score == 27 then - spawnTarget(3850,900) - elseif score == 28 then - spawnTarget(3780,300) - elseif score == 29 then - spawnTarget(3670,0) - elseif score == 30 then - AddCaption(loc("Last Target!")); - spawnTarget(3480,1200) - end - else - if not game_lost then - -- Otherwise show that the goal was accomplished - ShowMission(loc("Sniper Training"), loc("Aiming Practice"), loc("Congratulations! You've eliminated all targets|within the allowed time frame."), 0, 0) - -- Also let the hogs shout "victory!" - PlaySound(sndVictory) - -- Save the time left so we may keep it. - time_goal = TurnTimeLeft - end - end - end -end +-- Hedgewars SniperRifle Training +-- Scripting Example + +-- Lines such as this one are comments - they are ignored +-- by the game, no matter what kind of text is in there. +-- It's also possible to place a comment after some real +-- instruction as you see below. In short, everything +-- following "--" is ignored. + +--------------------------------------------------------------- +-- At first we implement the localization library using loadfile. +-- This allows us to localize strings without needing to think +-- about translations. +-- We can use the function loc(text) to localize a string. + +HedgewarsScriptLoad("/Scripts/Locale.lua") + +-- This variable will hold the number of destroyed targets. +local score = 0 +-- This variable will hold the number of shots from the sniper rifle +local shots = 0 +-- This variable represents the number of targets to destroy. +local score_goal = 31 +-- This variable controls how many milliseconds/ticks we'd +-- like to wait before we end the round once all targets +-- have been destroyed. +local end_timer = 1000 -- 1000 ms = 1 s +-- This variable is set to true if the game is lost (i.e. +-- time runs out). +local game_lost = false +-- This variable will point to the hog's gear +local player = nil +-- This variable will grab the time left at the end of the round +local time_goal = 0 + +local target = nil + +local last_hit_time = 0 +-- This is a custom function to make it easier to +-- spawn more targets with just one line of code +-- You may define as many custom functions as you +-- like. +function spawnTarget(x, y) + -- add a new target gear + target = AddGear(x, y, gtTarget, 0, 0, 0, 0) + -- have the camera move to the target so the player knows where it is + FollowGear(target) +end + +function blowUp(x, y) + -- adds some TNT + gear = AddGear(x, y, gtDynamite, 0, 0, 0, 0) +end + +function onNewTurn() + SetWeapon(amSniperRifle) +end + +-- This function is called before the game loads its +-- resources. +-- It's one of the predefined function names that will +-- be called by the game. They give you entry points +-- where you're able to call your own code using either +-- provided instructions or custom functions. +function onGameInit() + -- At first we have to overwrite/set some global variables + -- that define the map, the game has to load, as well as + -- other things such as the game rules to use, etc. + -- Things we don't modify here will use their default values. + + -- The base number for the random number generator + Seed = 0 + -- Game settings and rules + GameFlags = gfMultiWeapon + gfOneClanMode + gfArtillery + -- The time the player has to move each round (in ms) + TurnTime = 150000 + -- The frequency of crate drops + CaseFreq = 0 + -- The number of mines being placed + MinesNum = 0 + -- The number of explosives being placed + Explosives = 0 + -- The delay between each round + Delay = 0 + -- The map to be played + Map = "Ropes" + -- The theme to be used + Theme = "City" + + -- Create the player team + AddTeam(loc("Sniperz"), 14483456, "Simple", "Island", "Default") + -- And add a hog to it + player = AddHog(loc("Hunter"), 0, 1, "Sniper") + SetGearPosition(player, 602, 1465) +end + +-- This function is called when the round starts +-- it spawns the first target that has to be destroyed. +-- In addition it shows the scenario goal(s). +function onGameStart() + -- Disable graph in stats screen + SendHealthStatsOff() + -- Spawn the first target. + spawnTarget(860,1020) + + -- Show some nice mission goals. + -- Parameters are: caption, sub caption, description, + -- extra text, icon and time to show. + -- A negative icon parameter (-n) represents the n-th weapon icon + -- A positive icon paramter (n) represents the (n+1)-th mission icon + -- A timeframe of 0 is replaced with the default time to show. + ShowMission(loc("Sniper Training"), loc("Aiming Practice"), loc("Eliminate all targets before your time runs out.|You have unlimited ammo for this mission."), -amSniperRifle, 0) +end + +-- This function is called every game tick. +-- Note that there are 1000 ticks within one second. +-- You shouldn't try to calculate too complicated +-- code here as this might slow down your game. +function onGameTick20() + if game_lost then + return + end + -- after a target is destroyed, show hog, then target + if (target ~= nil) and (TurnTimeLeft + 1300 < last_hit_time) then + -- move camera to the target + FollowGear(target) + elseif TurnTimeLeft + 300 < last_hit_time then + -- move camera to the hog + FollowGear(player) + end + -- If time's up, set the game to be lost. + -- We actually check the time to be "1 ms" as it + -- will be at "0 ms" right at the start of the game. + if TurnTimeLeft < 40 and TurnTimeLeft > 0 and score < score_goal and game_lost == false then + game_lost = true + -- ... and show a short message. + AddCaption(loc("Time's up!")) + ShowMission(loc("Sniper Training"), loc("Aiming Practice"), loc("Oh no! Time's up! Just try again."), -amSkip, 0) + -- and generate the stats and go to the stats screen + generateStats() + EndGame() + -- Just to be sure set the goal time to 1 ms + time_goal = 1 + end + -- If the goal is reached or we've lost ... + if score == score_goal or game_lost then + -- ... check to see if the time we'd like to + -- wait has passed and then ... + if end_timer == 0 then + -- ... end the game ... + generateStats() + EndGame() + else + -- ... or just lower the timer by 1. + -- Reset the time left to stop the timer + TurnTimeLeft = time_goal + end + end_timer = end_timer - 20 + end +end + +-- This function is called when the game is initialized +-- to request the available ammo and probabilities +function onAmmoStoreInit() + -- add an unlimited supply of shotgun ammo + SetAmmo(amSniperRifle, 9, 0, 0, 0) +end + +-- This function is called when a new gear is added. +-- We use it to count the number of shots, which we +-- in turn use to calculate the final score and stats +function onGearAdd(gear) + if GetGearType(gear) == gtSniperRifleShot then + shots = shots + 1 + end +end + +-- This function is called before a gear is destroyed. +-- We use it to count the number of targets destroyed. +function onGearDelete(gear) + + if GetGearType(gear) == gtCase then + game_lost = true + return + end + + if (GetGearType(gear) == gtTarget) then + -- remember when the target was hit for adjusting the camera + last_hit_time = TurnTimeLeft + -- Add one point to our score/counter + score = score + 1 + -- If we haven't reached the goal ... + if score < score_goal then + -- ... spawn another target. + if score == 1 then + spawnTarget(1520,1350) + elseif score == 2 then + spawnTarget(1730,1040) + elseif score == 3 then + spawnTarget(2080,780) + elseif score == 4 then + AddCaption(loc("Good so far!") .. " " .. loc("Keep it up!")); + blowUp(1730,1226) + blowUp(1440,1595) + blowUp(1527,1575) + blowUp(1614,1595) + blowUp(1420,1675) + blowUp(1527,1675) + blowUp(1634,1675) + blowUp(1440,1755) + blowUp(1527,1775) + blowUp(1614,1755) + spawnTarget(1527,1667) + elseif score == 5 then + spawnTarget(1527,1667) + elseif score == 6 then + spawnTarget(2175,1300) + elseif score == 7 then + spawnTarget(2250,940) + elseif score == 8 then + spawnTarget(2665,1540) + elseif score == 9 then + spawnTarget(3040,1160) + elseif score == 10 then + spawnTarget(2930,1500) + elseif score == 11 then + AddCaption(loc("This one's tricky.")); + spawnTarget(700,720) + elseif score == 12 then + AddCaption(loc("Well done.")); + blowUp(914,1222) + blowUp(1050,1222) + blowUp(1160,1008) + blowUp(1160,1093) + blowUp(1160,1188) + blowUp(375,911) + blowUp(510,911) + blowUp(640,911) + blowUp(780,911) + blowUp(920,911) + blowUp(1060,913) + blowUp(1198,913) + spawnTarget(1200,730) + elseif score == 13 then + spawnTarget(1200,830) + elseif score == 14 then + spawnTarget(1430,450) + elseif score == 15 then + spawnTarget(796,240) + elseif score == 16 then + spawnTarget(300,10) + elseif score == 17 then + spawnTarget(2080,820) + elseif score == 18 then + AddCaption(loc("Demolition is fun!")); + blowUp(2110,920) + blowUp(2210,920) + blowUp(2200,305) + blowUp(2300,305) + blowUp(2300,400) + blowUp(2300,500) + blowUp(2300,600) + blowUp(2300,700) + blowUp(2300,800) + blowUp(2300,900) + blowUp(2401,305) + blowUp(2532,305) + blowUp(2663,305) + spawnTarget(2300,760) + elseif score == 19 then + spawnTarget(2300,760) + elseif score == 20 then + spawnTarget(2738,190) + elseif score == 21 then + spawnTarget(2590,-100) + elseif score == 22 then + AddCaption(loc("Will this ever end?")); + blowUp(2790,305) + blowUp(2930,305) + blowUp(3060,305) + blowUp(3190,305) + blowUp(3310,305) + blowUp(3393,613) + blowUp(2805,370) + blowUp(2805,500) + blowUp(2805,630) + blowUp(2805,760) + blowUp(2805,890) + blowUp(3258,370) + blowUp(3258,475) + blowUp(3264,575) + spawnTarget(3230,240) + elseif score == 23 then + spawnTarget(3230,290) + elseif score == 24 then + spawnTarget(3670,250) + elseif score == 25 then + spawnTarget(2620,-100) + elseif score == 26 then + spawnTarget(2870,300) + elseif score == 27 then + spawnTarget(3850,900) + elseif score == 28 then + spawnTarget(3780,300) + elseif score == 29 then + spawnTarget(3670,0) + elseif score == 30 then + AddCaption(loc("Last Target!")); + spawnTarget(3480,1200) + end + else + if not game_lost then + -- Otherwise show that the goal was accomplished + ShowMission(loc("Sniper Training"), loc("Aiming Practice"), loc("Congratulations! You've eliminated all targets|within the allowed time frame."), 0, 0) + -- Also let the hogs shout "victory!" + PlaySound(sndVictory) + -- Save the time left so we may keep it. + time_goal = TurnTimeLeft + end + end + end +end + +-- This function calculates the final score of the player and provides some texts and +-- data for the final stats screen +function generateStats() + local accuracy = (score/shots)*100 + local end_score_targets = (score * 200) + local end_score_overall + if not game_lost then + local end_score_time = math.ceil(time_goal/5) + local end_score_accuracy = math.ceil(accuracy * 100) + end_score_overall = end_score_time + end_score_targets + end_score_accuracy + + SendStat(siGameResult, loc("You have successfully finished the sniper rifle training!")) + SendStat(siCustomAchievement, string.format(loc("You have destroyed %d of %d targets (+%d points)."), score, score_goal, end_score_targets)) + SendStat(siCustomAchievement, string.format(loc("You have made %d shots."), shots)) + SendStat(siCustomAchievement, string.format(loc("Accuracy bonus: +%d points"), end_score_accuracy)) + SendStat(siCustomAchievement, string.format(loc("You had %.2fs remaining on the clock (+%d points)."), (time_goal/1000), end_score_time)) + else + SendStat(siGameResult, loc("You lose!")) + + SendStat(siCustomAchievement, string.format(loc("You have destroyed %d of %d targets (+%d points)."), score, score_goal, end_score_targets)) + SendStat(siCustomAchievement, string.format(loc("You have made %d shots."), shots)) + end_score_overall = end_score_targets + end + SendStat(siPlayerKills, tostring(end_score_overall), loc("Sniperz")) + SendStat(siPointType, loc("points")) +end diff -r cdce07f5a011 -r 1c85a442bd56 share/hedgewars/Data/Missions/Training/User_Mission_-_RCPlane_Challenge.lua --- a/share/hedgewars/Data/Missions/Training/User_Mission_-_RCPlane_Challenge.lua Thu Dec 11 10:33:49 2014 +0100 +++ b/share/hedgewars/Data/Missions/Training/User_Mission_-_RCPlane_Challenge.lua Thu Dec 11 20:38:03 2014 +0900 @@ -1,343 +1,490 @@ -HedgewarsScriptLoad("/Scripts/Locale.lua") - -local player = nil -local RCGear = nil -local planesUsed = 0 -local cratesLeft = 0 - -function onGameInit() - - Seed = 1 - GameFlags = gfInfAttack + gfInvulnerable + gfOneClanMode + gfSolidLand - - TurnTime = 90 * 1000 - - Map = "Ropes" - Theme = "Eyes" - - CaseFreq = 0 - MinesNum = 0 - Explosives = 0 - - AddTeam(loc("Wannabe Flyboys"), 14483456, "Simple", "Island", "Default", "Hedgewars") - player = AddHog(loc("Ace"), 0, 80, "Gasmask") - SetGearPosition(player, 1380, 1500) - -end - - - -function onGameStart() - - ShowMission ( - loc("RC PLANE TRAINING"), - loc("a Hedgewars challenge"), - - loc("Collect or destroy all the health crates.") .. "|" .. - loc("Compete to use as few planes as possible!") .. "|" .. - "", -amRCPlane, 4000 - ) - - PlaceGirder(2192, 508, 6) - PlaceGirder(2192, 670, 6) - PlaceGirder(2193, 792, 2) - PlaceGirder(2100, 825, 4) - PlaceGirder(2009, 899, 6) - PlaceGirder(2084, 992, 4) - PlaceGirder(2145, 1087, 6) - PlaceGirder(2199, 1235, 5) - PlaceGirder(2308, 1296, 0) - PlaceGirder(2424, 1234, 7) - PlaceGirder(2473, 1129, 2) - PlaceGirder(2437, 1046, 1) - PlaceGirder(2409, 927, 6) - PlaceGirder(2408, 763, 6) - PlaceGirder(2404, 540, 6) - PlaceGirder(2426, 423, 3) - PlaceGirder(2550, 400, 4) - PlaceGirder(2668, 425, 1) - PlaceGirder(2707, 541, 6) - PlaceGirder(2706, 703, 6) - PlaceGirder(2705, 867, 6) - PlaceGirder(2779, 962, 4) - PlaceGirder(2894, 924, 3) - PlaceGirder(2908, 802, 6) - PlaceGirder(2907, 639, 6) - PlaceGirder(3052, 566, 4) - PlaceGirder(2971, 394, 4) - PlaceGirder(3103, 448, 7) - PlaceGirder(3047, 654, 0) - PlaceGirder(3043, 746, 6) - PlaceGirder(3265, 1583, 6) - PlaceGirder(3256, 1491, 4) - PlaceGirder(3187, 1401, 6) - PlaceGirder(3326, 1400, 6) - PlaceGirder(774, 530, 5) - PlaceGirder(922, 595, 4) - PlaceGirder(1079, 533, 7) - PlaceGirder(1139, 386, 6) - PlaceGirder(1074, 237, 5) - PlaceGirder(723, 381, 6) - PlaceGirder(781, 229, 7) - PlaceGirder(927, 746, 6) - PlaceGirder(874, 736, 0) - PlaceGirder(982, 737, 0) - PlaceGirder(2430, 1730, 4) - - PlaceGirder(1613, 1104, 7) - PlaceGirder(1564, 1256, 6) - PlaceGirder(1643, 1341, 5) - PlaceGirder(1780, 1372, 4) - PlaceGirder(1869, 1296, 7) - PlaceGirder(1858, 1163, 5) - PlaceGirder(1739, 1044, 5) - PlaceGirder(1621, 926, 5) - PlaceGirder(1597, 985, 5) - PlaceGirder(1449, 939, 4) - PlaceGirder(1473, 874, 4) - PlaceGirder(2092, 1352, 7) - PlaceGirder(2145, 1444, 7) - PlaceGirder(2004, 1443, 3) - PlaceGirder(1978, 1523, 2) - PlaceGirder(2021, 1596, 1) - PlaceGirder(2103, 1625, 0) - PlaceGirder(2208, 1551, 7) - PlaceGirder(2327, 1431, 7) - PlaceGirder(2395, 1478, 6) - PlaceGirder(2396, 1600, 2) - PlaceGirder(2495, 1285, 6) - PlaceGirder(2494, 1408, 2) - PlaceGirder(2547, 530, 0) - - PlaceGirder(2451, 1551, 0) - PlaceGirder(2551, 706, 6) - PlaceGirder(2551, 869, 6) - PlaceGirder(2623, 1016, 5) - PlaceGirder(2773, 1083, 4) - PlaceGirder(2924, 1019, 7) - PlaceGirder(2568, 1491, 7) - PlaceGirder(2618, 1346, 6) - PlaceGirder(2674, 1195, 7) - PlaceGirder(2822, 1142, 4) - PlaceGirder(2963, 1069, 7) - PlaceGirder(3067, 938, 5) - PlaceGirder(2803, 1373, 2) - PlaceGirder(2811, 1559, 2) - - tempG = SpawnHealthCrate(930, 557) - SetHealth(tempG, 25) - tempG = SpawnHealthCrate(979, 692) - SetHealth(tempG, 25) - tempG = SpawnHealthCrate(876, 703) - SetHealth(tempG, 25) - tempG = SpawnHealthCrate(2309, 1260) - SetHealth(tempG, 25) - tempG = SpawnHealthCrate(1733, 1127) - SetHealth(tempG, 25) - tempG = SpawnHealthCrate(1738, 1320) - SetHealth(tempG, 25) - tempG = SpawnHealthCrate(3249, 1460) - SetHealth(tempG, 25) - tempG = SpawnHealthCrate(3051, 617) - SetHealth(tempG, 25) - tempG = SpawnHealthCrate(2972, 353) - SetHealth(tempG, 25) - tempG = SpawnHealthCrate(2548, 358) - - SetHealth(tempG, 25) - tempG = SpawnHealthCrate(2090, 1580) - SetHealth(tempG, 25) - tempG = SpawnHealthCrate(1752, 1753) - SetHealth(tempG, 25) - tempG = SpawnHealthCrate(1865, 1758) - SetHealth(tempG, 25) - tempG = SpawnHealthCrate(1985, 1760) - SetHealth(tempG, 25) - tempG = SpawnHealthCrate(2429, 1760) - SetHealth(tempG, 25) - tempG = SpawnHealthCrate(2810, 1480) - SetHealth(tempG, 25) - tempG = SpawnHealthCrate(2800, 1277) - SetHealth(tempG, 25) - tempG = SpawnHealthCrate(2806, 1107) - SetHealth(tempG, 25) - - PlaceGirder(1897, 903, 6) - PlaceGirder(1916, 784, 3) - PlaceGirder(2010, 732, 4) - PlaceGirder(2082, 639, 6) - PlaceGirder(2081, 516, 2) - PlaceGirder(1985, 487, 4) - PlaceGirder(1862, 407, 5) - PlaceGirder(1855, 224, 7) - PlaceGirder(2006, 163, 4) - PlaceGirder(2128, 187, 1) - PlaceGirder(2251, 213, 4) - PlaceGirder(2413, 213, 4) - PlaceGirder(1952, 618, 0) - PlaceGirder(957, 1068, 4) - PlaceGirder(794, 1069, 4) - PlaceGirder(728, 1163, 6) - PlaceGirder(728, 1287, 2) - PlaceGirder(802, 1342, 4) - PlaceGirder(966, 1342, 4) - PlaceGirder(674, 1032, 1) - PlaceGirder(554, 1011, 4) - PlaceGirder(445, 1056, 3) - PlaceGirder(422, 1174, 6) - PlaceGirder(369, 1341, 5) - PlaceGirder(495, 1313, 5) - PlaceGirder(568, 1379, 3) - PlaceGirder(577, 1202, 2) - PlaceGirder(744, 1490, 5) - PlaceGirder(760, 1617, 7) - PlaceGirder(622, 1693, 4) - PlaceGirder(476, 1623, 5) - PlaceGirder(376, 1697, 1) - PlaceGirder(955, 1746, 2) - PlaceGirder(1025, 1746, 2) - PlaceGirder(1090, 1745, 2) - PlaceGirder(1156, 1746, 2) - PlaceGirder(3806, 1530, 2) - PlaceGirder(3880, 1464, 2) - PlaceGirder(3738, 1458, 2) - PlaceGirder(3806, 1390, 2) - PlaceGirder(3805, 1588, 0) - PlaceGirder(3676, 1609, 3) - PlaceGirder(3930, 1615, 1) - PlaceGirder(3719, 1295, 0) - PlaceGirder(3888, 1294, 0) - PlaceGirder(3661, 1385, 2) - PlaceGirder(3955, 1377, 2) - PlaceGirder(3982, 1518, 0) - PlaceGirder(3378, 440, 2) - PlaceGirder(3447, 492, 4) - PlaceGirder(3564, 529, 1) - PlaceGirder(3596, 647, 6) - PlaceGirder(3521, 740, 4) - PlaceGirder(3524, 838, 4) - PlaceGirder(3644, 819, 3) - PlaceGirder(3691, 708, 6) - PlaceGirder(3690, 545, 6) - PlaceGirder(3612, 433, 5) - PlaceGirder(3463, 383, 4) - PlaceGirder(2815, 122, 7) - PlaceGirder(2960, 72, 4) - PlaceGirder(3032, 123, 2) - PlaceGirder(3063, 174, 0) - PlaceGirder(3095, 124, 2) - PlaceGirder(3169, 71, 4) - PlaceGirder(3320, 124, 5) - PlaceGirder(3210, 179, 2) - PlaceGirder(2932, 181, 2) - - tempG = SpawnHealthCrate(3804, 1461) - SetHealth(tempG, 25) - tempG = SpawnHealthCrate(3269, 1742) - SetHealth(tempG, 25) - tempG = SpawnHealthCrate(3066, 121) - SetHealth(tempG, 25) - tempG = SpawnHealthCrate(3207, 104) - SetHealth(tempG, 25) - tempG = SpawnHealthCrate(2928, 103) - SetHealth(tempG, 25) - tempG = SpawnHealthCrate(1997, 202) - SetHealth(tempG, 25) - tempG = SpawnHealthCrate(2253, 159) - SetHealth(tempG, 25) - tempG = SpawnHealthCrate(2132, 774) - SetHealth(tempG, 25) - tempG = SpawnHealthCrate(2549, 490) - SetHealth(tempG, 25) - tempG = SpawnHealthCrate(3527, 694) - SetHealth(tempG, 25) - tempG = SpawnHealthCrate(3777, 78) - SetHealth(tempG, 25) - tempG = SpawnHealthCrate(1124, 1746) - SetHealth(tempG, 25) - tempG = SpawnHealthCrate(1056, 1740) - SetHealth(tempG, 25) - tempG = SpawnHealthCrate(993, 1742) - SetHealth(tempG, 25) - tempG = SpawnHealthCrate(799, 1298) - SetHealth(tempG, 25) - tempG = SpawnHealthCrate(577, 1126) - SetHealth(tempG, 25) - tempG = SpawnHealthCrate(596, 1463) - SetHealth(tempG, 25) - tempG = SpawnHealthCrate(3854, 1043) - SetHealth(tempG, 25) - tempG = SpawnHealthCrate(1944, 567) - SetHealth(tempG, 25) - tempG = SpawnHealthCrate(338, 1748) - SetHealth(tempG, 25) - - -end - ---function onGameTick() - - --if RCGear ~= nil then - -- AddCaption(GetTimer(RCGear)) - --end - ---end - -function onNewTurn() - TurnTimeLeft = -1 -end - -function onGearAdd(gear) - - if GetGearType(gear) == gtRCPlane then - RCGear = gear - planesUsed = planesUsed + 1 - end - - if GetGearType(gear) == gtCase then - cratesLeft = cratesLeft + 1 - end - -end - -function onGearDelete(gear) - - if GetGearType(gear) == gtRCPlane then - - RCGear = nil - AddCaption(loc("Planes Used:") .. " " .. planesUsed) - - elseif GetGearType(gear) == gtCase then - - AddCaption(loc("Crates Left:") .. " " .. cratesLeft) - cratesLeft = cratesLeft - 1 - - if cratesLeft == 0 then - - if planesUsed == 1 then - AddCaption(loc("Achievement Unlocked") .. ": " .. loc("Prestigious Pilot"),0xffba00ff,capgrpMessage2) - end - - ShowMission ( - loc("CHALLENGE COMPLETE"), - loc("Congratulations!"), - loc("Planes Used") .. ": " .. planesUsed .. "|" .. - "", 0, 0 - ) - - - - DismissTeam(loc("Wannabe Flyboys")) - end - - if RCGear ~= nil then - SetTimer(RCGear, GetTimer(RCGear) + 10000) - end - - end - -end - -function onAmmoStoreInit() - SetAmmo(amRCPlane, 9, 0, 0, 0) -end +HedgewarsScriptLoad("/Scripts/Locale.lua") + +local player = nil +local RCGear = nil +local planesUsed = 0 +local planeTimer = 0 +local planeUhOh = false +local cratesLeft = 0 +local crateStreak = 0 +local longestCrateStreak = 0 +local commentTimer = 0 +local missiles = 0 +local totalMissiles = 0 +local missileScanTimer = 0 +local nextComment = sndNone + +function onGameInit() + + Seed = 1 + GameFlags = gfInfAttack + gfInvulnerable + gfOneClanMode + gfSolidLand + + TurnTime = 90 * 1000 + + Map = "Ropes" + Theme = "Eyes" + + CaseFreq = 0 + MinesNum = 0 + Explosives = 0 + + AddTeam(loc("Wannabe Flyboys"), 14483456, "Simple", "Island", "Default", "Hedgewars") + player = AddHog(loc("Ace"), 0, 80, "Gasmask") + SetGearPosition(player, 1380, 1500) + +end + + + +function onGameStart() + + SendHealthStatsOff() + + ShowMission ( + loc("RC PLANE TRAINING"), + loc("a Hedgewars challenge"), + + loc("Collect or destroy all the health crates.") .. "|" .. + loc("Compete to use as few planes as possible!") .. "|" .. + "", -amRCPlane, 4000 + ) + + PlaceGirder(2192, 508, 6) + PlaceGirder(2192, 670, 6) + PlaceGirder(2193, 792, 2) + PlaceGirder(2100, 825, 4) + PlaceGirder(2009, 899, 6) + PlaceGirder(2084, 992, 4) + PlaceGirder(2145, 1087, 6) + PlaceGirder(2199, 1235, 5) + PlaceGirder(2308, 1296, 0) + PlaceGirder(2424, 1234, 7) + PlaceGirder(2473, 1129, 2) + PlaceGirder(2437, 1046, 1) + PlaceGirder(2409, 927, 6) + PlaceGirder(2408, 763, 6) + PlaceGirder(2404, 540, 6) + PlaceGirder(2426, 423, 3) + PlaceGirder(2550, 400, 4) + PlaceGirder(2668, 425, 1) + PlaceGirder(2707, 541, 6) + PlaceGirder(2706, 703, 6) + PlaceGirder(2705, 867, 6) + PlaceGirder(2779, 962, 4) + PlaceGirder(2894, 924, 3) + PlaceGirder(2908, 802, 6) + PlaceGirder(2907, 639, 6) + PlaceGirder(3052, 566, 4) + PlaceGirder(2971, 394, 4) + PlaceGirder(3103, 448, 7) + PlaceGirder(3047, 654, 0) + PlaceGirder(3043, 746, 6) + PlaceGirder(3265, 1583, 6) + PlaceGirder(3256, 1491, 4) + PlaceGirder(3187, 1401, 6) + PlaceGirder(3326, 1400, 6) + PlaceGirder(774, 530, 5) + PlaceGirder(922, 595, 4) + PlaceGirder(1079, 533, 7) + PlaceGirder(1139, 386, 6) + PlaceGirder(1074, 237, 5) + PlaceGirder(723, 381, 6) + PlaceGirder(781, 229, 7) + PlaceGirder(927, 746, 6) + PlaceGirder(874, 736, 0) + PlaceGirder(982, 737, 0) + PlaceGirder(2430, 1730, 4) + + PlaceGirder(1613, 1104, 7) + PlaceGirder(1564, 1256, 6) + PlaceGirder(1643, 1341, 5) + PlaceGirder(1780, 1372, 4) + PlaceGirder(1869, 1296, 7) + PlaceGirder(1858, 1163, 5) + PlaceGirder(1739, 1044, 5) + PlaceGirder(1621, 926, 5) + PlaceGirder(1597, 985, 5) + PlaceGirder(1449, 939, 4) + PlaceGirder(1473, 874, 4) + PlaceGirder(2092, 1352, 7) + PlaceGirder(2145, 1444, 7) + PlaceGirder(2004, 1443, 3) + PlaceGirder(1978, 1523, 2) + PlaceGirder(2021, 1596, 1) + PlaceGirder(2103, 1625, 0) + PlaceGirder(2208, 1551, 7) + PlaceGirder(2327, 1431, 7) + PlaceGirder(2395, 1478, 6) + PlaceGirder(2396, 1600, 2) + PlaceGirder(2495, 1285, 6) + PlaceGirder(2494, 1408, 2) + PlaceGirder(2547, 530, 0) + + PlaceGirder(2451, 1551, 0) + PlaceGirder(2551, 706, 6) + PlaceGirder(2551, 869, 6) + PlaceGirder(2623, 1016, 5) + PlaceGirder(2773, 1083, 4) + PlaceGirder(2924, 1019, 7) + PlaceGirder(2568, 1491, 7) + PlaceGirder(2618, 1346, 6) + PlaceGirder(2674, 1195, 7) + PlaceGirder(2822, 1142, 4) + PlaceGirder(2963, 1069, 7) + PlaceGirder(3067, 938, 5) + PlaceGirder(2803, 1373, 2) + PlaceGirder(2811, 1559, 2) + + tempG = SpawnHealthCrate(930, 557) + SetHealth(tempG, 25) + tempG = SpawnHealthCrate(979, 692) + SetHealth(tempG, 25) + tempG = SpawnHealthCrate(876, 703) + SetHealth(tempG, 25) + tempG = SpawnHealthCrate(2309, 1260) + SetHealth(tempG, 25) + tempG = SpawnHealthCrate(1733, 1127) + SetHealth(tempG, 25) + tempG = SpawnHealthCrate(1738, 1320) + SetHealth(tempG, 25) + tempG = SpawnHealthCrate(3249, 1460) + SetHealth(tempG, 25) + tempG = SpawnHealthCrate(3051, 617) + SetHealth(tempG, 25) + tempG = SpawnHealthCrate(2972, 353) + SetHealth(tempG, 25) + tempG = SpawnHealthCrate(2548, 358) + + SetHealth(tempG, 25) + tempG = SpawnHealthCrate(2090, 1580) + SetHealth(tempG, 25) + tempG = SpawnHealthCrate(1752, 1753) + SetHealth(tempG, 25) + tempG = SpawnHealthCrate(1865, 1758) + SetHealth(tempG, 25) + tempG = SpawnHealthCrate(1985, 1760) + SetHealth(tempG, 25) + tempG = SpawnHealthCrate(2429, 1760) + SetHealth(tempG, 25) + tempG = SpawnHealthCrate(2810, 1480) + SetHealth(tempG, 25) + tempG = SpawnHealthCrate(2800, 1277) + SetHealth(tempG, 25) + tempG = SpawnHealthCrate(2806, 1107) + SetHealth(tempG, 25) + + PlaceGirder(1897, 903, 6) + PlaceGirder(1916, 784, 3) + PlaceGirder(2010, 732, 4) + PlaceGirder(2082, 639, 6) + PlaceGirder(2081, 516, 2) + PlaceGirder(1985, 487, 4) + PlaceGirder(1862, 407, 5) + PlaceGirder(1855, 224, 7) + PlaceGirder(2006, 163, 4) + PlaceGirder(2128, 187, 1) + PlaceGirder(2251, 213, 4) + PlaceGirder(2413, 213, 4) + PlaceGirder(1952, 618, 0) + PlaceGirder(957, 1068, 4) + PlaceGirder(794, 1069, 4) + PlaceGirder(728, 1163, 6) + PlaceGirder(728, 1287, 2) + PlaceGirder(802, 1342, 4) + PlaceGirder(966, 1342, 4) + PlaceGirder(674, 1032, 1) + PlaceGirder(554, 1011, 4) + PlaceGirder(445, 1056, 3) + PlaceGirder(422, 1174, 6) + PlaceGirder(369, 1341, 5) + PlaceGirder(495, 1313, 5) + PlaceGirder(568, 1379, 3) + PlaceGirder(577, 1202, 2) + PlaceGirder(744, 1490, 5) + PlaceGirder(760, 1617, 7) + PlaceGirder(622, 1693, 4) + PlaceGirder(476, 1623, 5) + PlaceGirder(376, 1697, 1) + PlaceGirder(955, 1746, 2) + PlaceGirder(1025, 1746, 2) + PlaceGirder(1090, 1745, 2) + PlaceGirder(1156, 1746, 2) + PlaceGirder(3806, 1530, 2) + PlaceGirder(3880, 1464, 2) + PlaceGirder(3738, 1458, 2) + PlaceGirder(3806, 1390, 2) + PlaceGirder(3805, 1588, 0) + PlaceGirder(3676, 1609, 3) + PlaceGirder(3930, 1615, 1) + PlaceGirder(3719, 1295, 0) + PlaceGirder(3888, 1294, 0) + PlaceGirder(3661, 1385, 2) + PlaceGirder(3955, 1377, 2) + PlaceGirder(3982, 1518, 0) + PlaceGirder(3378, 440, 2) + PlaceGirder(3447, 492, 4) + PlaceGirder(3564, 529, 1) + PlaceGirder(3596, 647, 6) + PlaceGirder(3521, 740, 4) + PlaceGirder(3524, 838, 4) + PlaceGirder(3644, 819, 3) + PlaceGirder(3691, 708, 6) + PlaceGirder(3690, 545, 6) + PlaceGirder(3612, 433, 5) + PlaceGirder(3463, 383, 4) + PlaceGirder(2815, 122, 7) + PlaceGirder(2960, 72, 4) + PlaceGirder(3032, 123, 2) + PlaceGirder(3063, 174, 0) + PlaceGirder(3095, 124, 2) + PlaceGirder(3169, 71, 4) + PlaceGirder(3320, 124, 5) + PlaceGirder(3210, 179, 2) + PlaceGirder(2932, 181, 2) + + tempG = SpawnHealthCrate(3804, 1461) + SetHealth(tempG, 25) + tempG = SpawnHealthCrate(3269, 1742) + SetHealth(tempG, 25) + tempG = SpawnHealthCrate(3066, 121) + SetHealth(tempG, 25) + tempG = SpawnHealthCrate(3207, 104) + SetHealth(tempG, 25) + tempG = SpawnHealthCrate(2928, 103) + SetHealth(tempG, 25) + tempG = SpawnHealthCrate(1997, 202) + SetHealth(tempG, 25) + tempG = SpawnHealthCrate(2253, 159) + SetHealth(tempG, 25) + tempG = SpawnHealthCrate(2132, 774) + SetHealth(tempG, 25) + tempG = SpawnHealthCrate(2549, 490) + SetHealth(tempG, 25) + tempG = SpawnHealthCrate(3527, 694) + SetHealth(tempG, 25) + tempG = SpawnHealthCrate(3777, 78) + SetHealth(tempG, 25) + tempG = SpawnHealthCrate(1124, 1746) + SetHealth(tempG, 25) + tempG = SpawnHealthCrate(1056, 1740) + SetHealth(tempG, 25) + tempG = SpawnHealthCrate(993, 1742) + SetHealth(tempG, 25) + tempG = SpawnHealthCrate(799, 1298) + SetHealth(tempG, 25) + tempG = SpawnHealthCrate(577, 1126) + SetHealth(tempG, 25) + tempG = SpawnHealthCrate(596, 1463) + SetHealth(tempG, 25) + tempG = SpawnHealthCrate(3854, 1043) + SetHealth(tempG, 25) + tempG = SpawnHealthCrate(1944, 567) + SetHealth(tempG, 25) + tempG = SpawnHealthCrate(338, 1748) + SetHealth(tempG, 25) + + +end + +--function onGameTick() + + --if RCGear ~= nil then + -- AddCaption(GetTimer(RCGear)) + --end + +--end + +function onGameTick20() + if RCGear ~= nil then + if(GetTimer(RCGear) < 3000 and planeUhOh == false) then + PlaySound(sndUhOh, player) + planeUhOh = true + end + planeTimer = planeTimer + 20 + end + if commentTimer > 0 then + commentTimer = commentTimer - 20 + elseif(nextComment ~= sndNone) then + PlaySound(nextComment, player) + nextComment = sndNone + end + if missileScanTimer > 0 then + missileScanTimer = missileScanTimer - 20 + else + if crateStreak == 0 and missiles == 3 then + PlaySound(sndMissed, player) + missiles = 4 + end + end +end + +function onNewTurn() + TurnTimeLeft = -1 +end + +function onGearAdd(gear) + + if GetGearType(gear) == gtRCPlane then + RCGear = gear + planesUsed = planesUsed + 1 + planeTimer = 0 + missiles = 0 + end + + if GetGearType(gear) == gtCase then + cratesLeft = cratesLeft + 1 + end + + if GetGearType(gear) == gtAirBomb then + totalMissiles = totalMissiles + 1 + end +end + +function onGearDelete(gear) + + if GetGearType(gear) == gtRCPlane then + + RCGear = nil + planeUhOh = false + missiles = 0 + AddCaption(string.format(loc("Planes used: %d"), planesUsed)) + + if(planeTimer < 2000 and crateStreak == 0) then + nextComment = sndStupid + commentTimer = math.min(2000-planeTimer, 800) + elseif(planeTimer < 5000 and crateStreak == 0) then + PlaySound(sndOops, player) + elseif(planesUsed == 72) then + PlaySound(sndStupid, player) + elseif(planesUsed == 50) then + PlaySound(sndNutter, player) + elseif(planesUsed == 30) then + PlaySound(sndOops, player) + end + + crateStreak = 0 + + elseif GetGearType(gear) == gtAirBomb then + missiles = missiles + 1 + missileScanTimer = 500 + + elseif GetGearType(gear) == gtCase then + + cratesLeft = cratesLeft - 1 + crateStreak = crateStreak + 1 + if(crateStreak > longestCrateStreak) then + longestCrateStreak = crateStreak + end + + AddCaption(string.format(loc("Crates left: %d"), cratesLeft)) + + if cratesLeft == 0 then + + local rank = "unknown" + local color = 0xFFFFFFFF + local sound = sndVictory + if planesUsed >= 156 then + rank = loc("Destroyer of planes") + color = 0xD06700FF + sound = sndLaugh + elseif planesUsed >= 98 then + rank = loc("Hopeless case") + color = 0xFF0000FF + elseif planesUsed >= 72 then + rank = loc("Drunk greenhorn") + color = 0xFF0040FF + elseif planesUsed >= 50 then + rank = loc("Greenhorn") -- a.k.a. "absolute beginner" + color = 0xFF0080FF + elseif planesUsed >= 39 then + rank = loc("Beginner") + color = 0xFF00BFFF + elseif planesUsed >= 30 then + rank = loc("Experienced beginner") + color = 0xFF00CCFF + elseif planesUsed >= 21 then + rank = loc("Below-average pilot") + color = 0xFF00FFFF + elseif planesUsed >= 17 then + rank = loc("Average pilot") + color = 0xBF00FFFF + elseif planesUsed >= 13 then + rank = loc("Above-average pilot") + color = 0x8000FFFF + elseif planesUsed >= 8 then + rank = loc("Professional pilot") + color = 0x4000FFFF + elseif planesUsed >= 5 then + rank = loc("Professional stunt pilot") + color = 0x0000FFFF + elseif planesUsed >= 3 then + rank = loc("Elite pilot") + color = 0x0040FFFF + elseif planesUsed == 2 then + rank = loc("Upper-class elite pilot") + color = 0x0080FFFF + elseif planesUsed == 1 then + rank = loc("Top-class elite pilot") + color = 0x00FFFFFF + sound = sndFlawless + else + rank = loc("Cheater") + color = 0xFF0000FF + sound = sndCoward + end + AddCaption(string.format(loc("Rank: %s"), rank), color, capgrpMessage2) + SendStat(siCustomAchievement, string.format(loc("Your rank: %s"), rank)) + if planesUsed == 1 then + AddCaption(loc("Flawless victory!")) + SendStat(siGameResult, loc("You have perfectly beaten the challenge!")) + SendStat(siCustomAchievement, loc("You have used only 1 RC plane. Outstanding!")) + else + AddCaption(loc("Victory!")) + SendStat(siGameResult, loc("You have finished the challenge!")) + SendStat(siCustomAchievement, string.format(loc("You have used %d RC planes."), planesUsed)) + end + + if(totalMissiles > 1) then + SendStat(siCustomAchievement, string.format(loc("You have dropped %d missiles."), totalMissiles)) + end + + if(longestCrateStreak > 5) then + if(planesUsed == 1) then + SendStat(siCustomAchievement, string.format(loc("In your best (and only) flight you took out %d crates with one RC plane!"), longestCrateStreak)) + else + SendStat(siCustomAchievement, string.format(loc("In your best flight you took out %d crates with one RC plane."), longestCrateStreak)) + end + end + + if(planesUsed == 2) then + SendStat(siCustomAchievement, loc("This was an awesome performance! But this challenge can be finished with even just one RC plane. Can you figure out how?")) + end + if(planesUsed == 1) then + SendStat(siCustomAchievement, loc("Congratulations! You have truly mastered this challenge! Don't forget to save the demo.")) + SendStat(siCustomAchievement, string.format(loc("You have gained an achievement: %s"), loc("Prestigious Pilot"))) + end + + ShowMission ( + loc("CHALLENGE COMPLETE"), + loc("Congratulations!"), + string.format(loc("Planes used: %d"), planesUsed) .. "|" .. + "", 0, 0 + ) + SetState(player, gstWinner) + PlaySound(sound, player) + + + DismissTeam(loc("Wannabe Flyboys")) + EndGame() + end + + if RCGear ~= nil then + SetTimer(RCGear, GetTimer(RCGear) + 10000) + end + end + +end + +function onAmmoStoreInit() + SetAmmo(amRCPlane, 9, 0, 0, 0) +end \ No newline at end of file