--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/hedgewars/Data/Scripts/TargetPractice.lua Thu Dec 11 21:00:42 2014 +0900
@@ -0,0 +1,260 @@
+--[=[
+Target Practice Mission Framework for Hedgewars
+
+This is a simple library intended to make setting up simple training missions a trivial
+task requiring just. The library has been created to reduce redundancy in Lua scripts.
+
+The training framework generates complete and fully usable training missions by just
+one function call.
+
+The missions generated by this script are all the same:
+- The player will get a team with a single hedgehog.
+- The team gets a single predefined weapon infinitely times.
+- A fixed sequence of targets will spawn at predefined positions.
+- When a target has been destroyed, the next target of the target sequence appears
+- The mission ends successfully when all targets have been destroyed
+- The mission ends unsuccessfully when the time runs out or the hedgehog dies
+- When the mission ends, a score is awarded, based on the performance (hit targets,
+ accuracy and remaining time) of the hedgehog. When not all targets are hit, there
+ will be no accuracy and time bonuses.
+
+To use this library, you first have to load it and to call TrainingMission once with
+the appropriate parameters. Really, that’s all!
+See the comment of TrainingMission for a specification of all parameters.
+
+Below is a template for your convenience, you just have to fill in the fields and delete
+optional arguments you don’t want.
+----- snip -----
+HedgewarsScriptLoad("/Scripts/Training.lua")
+params = {
+ missionTitle = ,
+ map = ,
+ theme = ,
+ time = ,
+ ammoType = ,
+ gearType = ,
+ targets = {
+ { x = , y = },
+ { x = , y = },
+ -- etc.
+ },
+
+ wind = ,
+ solidLand = ,
+ artillery = ,
+ hogHat = ,
+ hogName = ,
+ teamName = ,
+ teamGrave = ,
+ clanColor = ,
+ goalText = ,
+ shootText =
+}
+TargetPracticeMission(params)
+----- snip -----
+]=]
+
+HedgewarsScriptLoad("/Scripts/Locale.lua")
+
+local player = nil
+local scored = 0
+local shots = 0
+local end_timer = 1000
+local game_lost = false
+local time_goal = 0
+local total_targets
+local targets
+
+--[[
+TrainingMission(params)
+
+This function sets up the *entire* training mission and needs one argument: params.
+The argument “params” is a table containing fields which describe the training mission.
+ mandatory fields:
+ - missionTitle: the name of the mission
+ - map: the name map to be used
+ - theme: the name of the theme (does not need to be a standalone theme)
+ - time: the time limit in milliseconds
+ - ammoType: the ammo type of the weapon to be used
+ - gearType: the gear type of the gear which is fired (used to count shots)
+ - targets: The coordinates of where the targets will be spawned.
+ It is a table containing tables containing coordinates of format
+ { x=value, y=value }. The targets will be spawned in the same
+ order as specified the coordinate tables appear. Example:
+ targets = {
+ { x = 324, y = 43 },
+ { x = 123, y = 56 },
+ { x = 6, y = 0 },
+ }
+ There must be at least 1 target.
+
+ optional fields:
+ - wind: the initial wind (-100 to 100) (default: 0 (no wind))
+ - solidLand: weather the terrain is indestructible (default: false)
+ - artillery: if true, the hog can’t move (default: false)
+ - hogHat: hat of the hedgehog (default: "NoHat")
+ - hogName: name of the hedgehog (default: "Trainee")
+ - teamName: name of the hedgehog’s team (default: "Training Team")
+ - teamGrave: name of the hedgehog’s grave
+ - clanColor: color of the (only) clan (default: 0xFF0204, which is a red tone)
+ - goalText: A short string explaining the goal of the mission
+ (default: "Destroy all targets within the time!")
+ - shootText: A string which says how many times the player shot, “%d” is replaced
+ by the number of shots. (default: "You have shot %d times.")
+]]
+function TargetPracticeMission(params)
+ if params.hogHat == nil then params.hogHat = "NoHat" end
+ if params.hogName == nil then params.hogName = loc("Trainee") end
+ if params.teamName == nil then params.teamName = loc("Training Team") end
+ if params.goalText == nil then params.goalText = loc("Eliminate all targets before your time runs out.|You have unlimited ammo for this mission.") end
+ if params.shootText == nil then params.shootText = loc("You have shot %d times.") end
+ if params.clanColor == nil then params.clanColor = 0xFF0204 end
+ if params.teamGrave == nil then params.teamGrave= "Statue" end
+ if params.wind == nil then params.wind = 0 end
+
+ local solid, artillery
+ if params.solidLand == true then solid = gfSolidLand else solid = 0 end
+ if params.artillery == true then artillery = gfArtillery else artillery = 0 end
+
+ targets = params.targets
+
+ total_targets = #targets
+
+ _G.onAmmoStoreInit = function()
+ SetAmmo(params.ammoType, 9, 0, 0, 0)
+ end
+
+ _G.onGameInit = function()
+ Seed = 1
+ GameFlags = gfDisableWind + gfInfAttack + gfOneClanMode + solid + artillery
+ TurnTime = params.time
+ Map = params.map
+ Theme = params.theme
+ Goals = params.goalText
+ CaseFreq = 0
+ MinesNum = 0
+ Explosives = 0
+
+ SetWind(params.wind)
+
+ AddTeam(loc(params.teamName), params.clanColor, params.teamGrave, "Island", "Default", "Flowerhog")
+
+ player = AddHog(loc(params.hogName), 0, 1, params.hogHat)
+ SetGearPosition(player, params.hog_x, params.hog_y)
+ end
+
+ _G.onGameStart = function()
+ SendHealthStatsOff()
+ ShowMission(params.missionTitle, loc("Aiming practice"), params.goalText, -params.ammoType, 5000)
+ spawnTarget()
+ end
+
+ _G.onNewTurn = function()
+ -- TODO: Remove the else branch when 0.9.21 has been released
+ if SetWeapon ~= nil then
+ SetWeapon(params.ammoType)
+ else
+ ParseCommand("/setweap "..string.char(params.ammoType))
+ end
+ end
+
+ _G.spawnTarget = function()
+ gear = AddGear(0, 0, gtTarget, 0, 0, 0, 0)
+
+ x = targets[scored+1].x
+ y = targets[scored+1].y
+
+ SetGearPosition(gear, x, y)
+ end
+
+ _G.onGameTick20 = function()
+ if TurnTimeLeft < 40 and TurnTimeLeft > 0 and scored < total_targets and game_lost == false then
+ game_lost = true
+ AddCaption(loc("Time’s up!"), 0xFFFFFFFF, capgrpGameState)
+ ShowMission(params.missionTitle, loc("Aiming practice"), loc("Oh no! Time's up! Just try again."), -amSkip, 0)
+ SetHealth(player, 0)
+ time_goal = 1
+ end
+
+ if band(GetState(player), gstDrowning) == gstDrowning and game_lost == false and scored < total_targets then
+ game_lost = true
+ time_goal = 1
+ AddCaption(loc("You lose!"), 0xFFFFFFFF, capgrpGameState)
+ ShowMission(params.missionTitle, loc("Aiming practice"), loc("Oh no! You failed! Just try again."), -amSkip, 0)
+ end
+
+ if scored == total_targets or game_lost then
+ if end_timer == 0 then
+ generateStats()
+ EndGame()
+ else
+ TurnTimeLeft = time_goal
+ end
+ end_timer = end_timer - 20
+ end
+ end
+
+ _G.onGearAdd = function(gear)
+ if GetGearType(gear) == params.gearType then
+ shots = shots + 1
+ end
+ end
+
+ _G.onGearDamage = function(gear, damage)
+ if GetGearType(gear) == gtTarget then
+ scored = scored + 1
+ if scored < total_targets then
+ AddCaption(string.format(loc("Targets left: %d"), (total_targets-scored)), 0xFFFFFFFF, capgrpMessage)
+ spawnTarget()
+ else
+ if not game_lost then
+ AddCaption(loc("You have destroyed all targets!"), 0xFFFFFFFF, capgrpGameState)
+ ShowMission(params.missionTitle, loc("Aiming practice"), loc("Congratulations! You have destroyed all targets within the time."), 0, 0)
+ PlaySound(sndVictory, player)
+ SetState(player, bor(GetState(player), gstWinner))
+ time_goal = TurnTimeLeft
+ end
+ end
+ end
+
+ if GetGearType(gear) == gtHedgehog then
+ if not game_lost then
+ game_lost = true
+ AddCaption(loc("You lose!", 0xFFFFFFFF, capgrpGameState))
+ ShowMission(params.missionTitle, loc("Aiming practice"), loc("Oh no! You failed! Just try again."), -amSkip, 0)
+
+ SetHealth(player, 0)
+ time_goal = 1
+ end
+ end
+ end
+
+ _G.generateStats = function()
+ local accuracy = (scored/shots)*100
+ local end_score_targets = scored * math.ceil(6000/#targets)
+ local end_score_overall
+ if not game_lost then
+ local end_score_time = math.ceil(time_goal/(params.time/6000))
+ local end_score_accuracy = math.ceil(accuracy * 60)
+ end_score_overall = end_score_time + end_score_targets + end_score_accuracy
+
+ SendStat(siGameResult, loc("You have finished the target practice!"))
+
+ SendStat(siCustomAchievement, string.format(loc("You have destroyed %d of %d targets (+%d points)."), scored, total_targets, end_score_targets))
+ SendStat(siCustomAchievement, string.format(params.shootText, shots))
+ SendStat(siCustomAchievement, string.format(loc("Your accuracy was %.1f%% (+%d points)."), accuracy, end_score_accuracy))
+ SendStat(siCustomAchievement, string.format(loc("You had %.1fs 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)."), scored, total_targets, end_score_targets))
+ SendStat(siCustomAchievement, string.format(params.shootText, shots))
+ if(shots > 0) then
+ SendStat(siCustomAchievement, string.format(loc("Your accuracy was %.1f%%."), accuracy))
+ end
+ end_score_overall = end_score_targets
+ end
+ SendStat(siPlayerKills, tostring(end_score_overall), loc(params.teamName))
+ SendStat(siPointType, loc("points"))
+ end
+end