1------------------- ABOUT ----------------------
2--
3-- Hero has been surrounded my some space villains
4-- He has to defeat them in order to escape
5
6HedgewarsScriptLoad("/Scripts/Locale.lua")
7HedgewarsScriptLoad("/Scripts/Animate.lua")
8HedgewarsScriptLoad("/Missions/Campaign/A_Space_Adventure/global_functions.lua")
9
10----------------- VARIABLES --------------------
11-- globals
12local missionName = loc("Killing the specialists")
13local challengeObjectives = loc("Use your available weapons in order to eliminate the enemies.").."|"..
14	loc("The enemy hogs play in a random order.").."|"..
15	loc("At the start of the game each enemy hog has only the weapon that he is named after.").."|"..
16	loc("A random hedgehog will inherit the weapons of his deceased team-mates.").."|"..
17	loc("After you killed an enemy, you'll lose the weapon that he is named after.").."|"..
18	loc("If only one enemy is left, you'll get bonus ammo.").."|"..
19	loc("If you hurt an enemy, you'll get one third of the damage dealt.").."|"..
20	loc("If you kill an enemy, your health will be set to 100.")
21-- mission objectives
22local goals = {
23	["init"] = {missionName, loc("Challenge objectives"), challengeObjectives, 1, 35000},
24}
25-- hogs
26local hero = {
27	name = loc("Hog Solo"),
28	x = 850,
29	y = 469,
30	mortarAmmo = 2,
31	firepunchAmmo = 1,
32	deagleAmmo = 4,
33	bazookaAmmo = 2,
34	grenadeAmmo = 4,
35}
36local heroTurns = 0
37local enemies = {
38	{ name = GetAmmoName(amMortar), x = 1890, y = 535, weapon = amMortar, additionalWeapons = {}},
39	{ name = GetAmmoName(amDEagle), x = 1390, y = 815, weapon = amDEagle, additionalWeapons = {}},
40	{ name = GetAmmoName(amGrenade), x = 186, y = 62, weapon = amGrenade, additionalWeapons = {}},
41	{ name = GetAmmoName(amFirePunch), x = 330, y = 285, weapon = amFirePunch, additionalWeapons = {}},
42	{ name = GetAmmoName(amBazooka), x = 1950, y = 152, weapon = amBazooka, additionalWeapons = {}},
43}
44-- teams
45local teamA = {
46	name = loc("Hog Solo"),
47	color = -6
48}
49local teamB = {
50	name = loc("5 Deadly Hogs"),
51	color = -1
52}
53-- After hero killed an enemy, his weapons will be reset in the next round
54local heroWeaponResetPending = false
55local battleStarted = false
56local firstTurn = true
57
58-------------- LuaAPI EVENT HANDLERS ------------------
59
60function onGameInit()
61	Seed = 1
62	TurnTime = 25000
63	CaseFreq = 0
64	MinesNum = 0
65	MinesTime = 1
66	Explosives = 0
67	Map = "death02_map"
68	Theme = "Hell"
69	-- Disable Sudden Death
70	WaterRise = 0
71	HealthDecrease = 0
72
73	-- Hero
74	teamA.name = AddMissionTeam(teamA.color)
75	hero.gear = AddMissionHog(100)
76	hero.name = GetHogName(hero.gear)
77	SetGearPosition(hero.gear, hero.x, hero.y)
78	-- enemies
79	shuffleHogs(enemies)
80	teamB.name = AddTeam(teamB.name, teamB.color, "skull", "Island", "Default_qau", "cm_skull")
81	for i=1,table.getn(enemies) do
82		enemies[i].gear = AddHog(enemies[i].name, 1, 100, "war_desertgrenadier1")
83		SetGearPosition(enemies[i].gear, enemies[i].x, enemies[i].y)
84		if enemies[i].x > hero.x then
85			HogTurnLeft(enemies[i].gear, true)
86		end
87	end
88
89	initCheckpoint("death02")
90
91	AnimInit()
92end
93
94function onGameStart()
95	AnimWait(hero.gear, 3000)
96	FollowGear(hero.gear)
97	ShowMission(unpack(goals["init"]))
98
99	AddEvent(onHeroDeath, {hero.gear}, heroDeath, {hero.gear}, 0)
100	AddEvent(onHeroWin, {hero.gear}, heroWin, {hero.gear}, 0)
101
102	--hero ammo
103	AddAmmo(hero.gear, amSkip, 100)
104	AddAmmo(hero.gear, amRope, 2)
105	refreshHeroAmmo()
106
107	SendHealthStatsOff()
108end
109
110function onNewTurn()
111	battleStarted = true
112	if firstTurn then
113		-- Generous ready time in first turn to more time to read the mission panel
114		SetReadyTimeLeft(35000)
115		firstTurn = false
116	end
117	if CurrentHedgehog ~= hero.gear then
118		enemyWeapons()
119	else
120		heroTurns = heroTurns + 1
121	end
122end
123
124function onGearDelete(gear)
125	if isHog(gear) then
126		-- Set health to 100 (with heal effect, if health was smaller)
127		local healthDiff = 100 - GetHealth(hero.gear)
128		if healthDiff > 1 then
129			HealHog(hero.gear, healthDiff, true, 0x00FF00FF)
130		else
131			SetHealth(hero.gear, 100)
132		end
133		local deadHog = getHog(gear)
134		if deadHog.weapon == amMortar then
135			hero.mortarAmmo = 0
136		elseif deadHog.weapon == amFirePunch then
137			hero.firepunchAmmo = 0
138		elseif deadHog.weapon == amDEagle then
139			hero.deagleAmmo = 0
140		elseif deadHog.weapon == amBazooka then
141			hero.bazookaAmmo = 0
142		elseif deadHog.weapon == amGrenade then
143			hero.grenadeAmmo = 0
144		end
145		local randomHog = GetRandom(table.getn(enemies))+1
146		while not GetHealth(enemies[randomHog].gear) do
147			randomHog = GetRandom(table.getn(enemies))+1
148		end
149		table.insert(enemies[randomHog].additionalWeapons, deadHog.weapon)
150		for i=1,table.getn(deadHog.additionalWeapons) do
151			table.insert(enemies[randomHog].additionalWeapons, deadHog.additionalWeapons[i])
152		end
153		heroWeaponResetPending = true
154	end
155end
156
157function onGearDamage(gear, damage)
158	if isHog(gear) and GetHealth(hero.gear) then
159		local bonusHealth = div(damage, 3)
160		HealHog(hero.gear, bonusHealth, true, 0xFF0000FF)
161	end
162end
163
164function onGameTick()
165	AnimUnWait()
166	if ShowAnimation() == false then
167		return
168	end
169	ExecuteAfterAnimations()
170	CheckEvents()
171end
172
173function onGameTick20()
174	-- Refresh hero ammo immediately after its not his turn anymore
175	if CurrentHedgehog ~= hero.gear and heroWeaponResetPending then
176		refreshHeroAmmo()
177	end
178end
179
180-- Hide mission panel when player does anything
181function hideMissionOnAction()
182	if battleStarted then
183		HideMission()
184	end
185end
186
187onHogAttack = hideMissionOnAction
188onAttack = hideMissionOnAction
189onSlot = hideMissionOnAction
190onSetWeapon = hideMissionOnAction
191
192-------------- EVENTS ------------------
193
194function onHeroDeath(gear)
195	if not GetHealth(hero.gear) then
196		return true
197	end
198	return false
199end
200
201function onHeroWin(gear)
202	if not IsHogAlive(gear) then
203		return false
204	end
205	local allDead = true
206	for i=1,table.getn(enemies) do
207		if GetHealth(enemies[i].gear) then
208			allDead = false
209			break
210		end
211	end
212	return allDead
213end
214
215-------------- ACTIONS ------------------
216
217function heroDeath(gear)
218	SendStat(siGameResult, string.format(loc("%s lost, try again!"), hero.name))
219	SendStat(siCustomAchievement, loc("You have to eliminate all the enemies."))
220	SendStat(siCustomAchievement, loc("Read the challenge objectives from within the mission for more details."))
221	sendSimpleTeamRankings({teamB.name, teamA.name})
222	EndGame()
223end
224
225function heroWin(gear)
226	saveBonus(3, 4)
227	SendStat(siGameResult, loc("Congratulations, you won!"))
228	SendStat(siCustomAchievement, string.format(loc("You completed the mission in %d rounds."), heroTurns))
229	local record = tonumber(GetCampaignVar("FastestSpecialistsWin"))
230	if record ~= nil and heroTurns >= record then
231		SendStat(siCustomAchievement, string.format(loc("Your fastest victory so far: %d rounds"), record))
232	end
233	if record == nil or heroTurns < record then
234		SaveCampaignVar("FastestSpecialistsWin", tostring(heroTurns))
235		if record ~= nil then
236			SendStat(siCustomAchievement, loc("This is a new personal best, congratulations!"))
237		end
238	end
239	-- An old version of this mission was buggy and stored a turn record WAY too low.
240	-- Let's clear the broken variable (FastestSpecialistsKill) here.
241	SaveCampaignVar("FastestSpecialistsKill", "")
242	SendStat(siCustomAchievement, loc("The next 4 times you play the \"The last encounter\" mission you'll get 20 more hit points and a laser sight."))
243	sendSimpleTeamRankings({teamA.name, teamB.name})
244	SaveCampaignVar("Mission11Won", "true")
245	checkAllMissionsCompleted()
246	EndGame()
247end
248
249------------ Other Functions -------------------
250
251function shuffleHogs(hogs)
252    local hogsNumber = table.getn(hogs)
253    for i=1,hogsNumber do
254		local randomHog = GetRandom(hogsNumber) + 1
255		hogs[i], hogs[randomHog] = hogs[randomHog], hogs[i]
256    end
257end
258
259function refreshHeroAmmo()
260	local extraAmmo = 0
261	if getAliveEnemiesCount() == 1 then
262		extraAmmo = 2
263		PlaySound(sndShotgunReload)
264		AddCaption(loc("Reinforcements! +2 of each weapon!"), GetClanColor(GetHogClan(hero.gear)), capgrpAmmoinfo)
265	end
266	AddAmmo(hero.gear, amMortar, hero.mortarAmmo + extraAmmo)
267	AddAmmo(hero.gear, amFirePunch, hero.firepunchAmmo + extraAmmo)
268	AddAmmo(hero.gear, amDEagle, hero.deagleAmmo + extraAmmo)
269	AddAmmo(hero.gear, amBazooka, hero.bazookaAmmo + extraAmmo)
270	AddAmmo(hero.gear, amGrenade, hero.grenadeAmmo + extraAmmo)
271	heroWeaponResetPending = false
272end
273
274function enemyWeapons()
275	for i=1,table.getn(enemies) do
276		if GetHealth(enemies[i].gear) and enemies[i].gear == CurrentHedgehog then
277			AddAmmo(enemies[i].gear, amMortar, 0)
278			AddAmmo(enemies[i].gear, amFirePunch, 0)
279			AddAmmo(enemies[i].gear, amDEagle, 0)
280			AddAmmo(enemies[i].gear, amBazooka, 0)
281			AddAmmo(enemies[i].gear, amGrenade, 0)
282			AddAmmo(enemies[i].gear, enemies[i].weapon, 1)
283			for w=1,table.getn(enemies[i].additionalWeapons) do
284				AddAmmo(enemies[i].gear, enemies[i].additionalWeapons[w], 1)
285			end
286		end
287	end
288end
289
290function isHog(gear)
291	local hog = false
292	for i=1,table.getn(enemies) do
293		if gear == enemies[i].gear then
294			hog = true
295			break
296		end
297	end
298	return hog
299end
300
301function getHog(gear)
302	for i=1,table.getn(enemies) do
303		if gear == enemies[i].gear then
304			return enemies[i]
305		end
306	end
307end
308
309function getAliveEnemiesCount()
310	local count = 0
311	for i=1,table.getn(enemies) do
312		if GetHealth(enemies[i].gear) then
313			count = count + 1
314		end
315	end
316	return count
317end
318