share/hedgewars/Data/Missions/Campaign/A_Classic_Fairytale/shadow.lua
author unC0Rr
Sat, 28 Sep 2024 22:27:13 +0200
changeset 16066 2b4f361e3891
parent 15188 9d4a6ab60dec
permissions -rw-r--r--
Wrap chat lines into div

--[[
A Classic Fairytale: The Shadow Falls

= SUMMARY =
Dense Cloud and Leaks a Lot fight against waves of cannibals. Then a
cyborg shows up and offers one of the natives goodies in exchange for
betraying his tribe.

The decision affects the rest of the story. The survival of Dense
Cloud is important for the gameplay of the next mission.

= GOALS =
Kill Weaklings and Stronglings.

= FLOW CHART =
== Linear events ==

- Initial hog spawns: Dense Cloud, Leaks a Lot and Brainiac (Weaklings)
- Cut scene: startDialogue
- TBS
- Brainiac dead
- Cut scene: weaklingsAnim
- The remaining Weaklings spawn
- TBS
- All Weaklings dead
- Cut scene: stronglingsAnim: Stronglings spawn, Dense Cloud walks to forest, meets cyborg, cyborg makes offer
- The cyborg offer is an IMPORTANT decision, it completely changes the next mission, and the rest of the story
| Accept: Player walks to cyborg
    - Cut scene: acceptAnim
    - Dense Cloud needs to walk all the way back (infinite turn time)
    | Dense Cloud reached tree
        - Turn time starts
        - TBS
        - Stronglings defeated
        | Stronglings defeated with both hogs survived
            - Cut scene: acceptedSurvivedFinalAnim
        | Stronglings defeated with Dense Cloud dead
            - Cut scene: acceptedDiedFinalAnim
        > Victory
    | Dense Cloud dies before reaching the tree
        > Game over
| Reject: Player walks away
    - Cut scene: refusedAnim
    - Leaks a Lot teleports back to tree at the start (automatically)
    - Spiky Cheese and Ramon appear together with crates
    - Spiky Cheese gains control
    - TBS
    - Stronglings defeated
    - Cut scene: refusedFinalAnim
    > Victory
| Attack: Player attacks cyborg
    - Cut scene: attackAnim
    - Cyborg kills Dense Cloud
    - Other native's turn to defeat Stronglings
    - TBS
    - Stronglings defeated
    - Cut scene: attackedFinalAnim
    > Victory

== Non-linear events ==
| Dense Cloud or Leaks A Lot dead (exceptions: killed by cyborg; or Leaks A Lot died in the battle against the Stronglings):
    > Game over

]]

HedgewarsScriptLoad("/Scripts/Locale.lua")
HedgewarsScriptLoad("/Scripts/Animate.lua")

-----------------------------Constants---------------------------------
startStage = 0
spyStage = 1
wave1Stage = 2
wave2Stage = 3
cyborgStage = 4
ramonStage = 5
aloneStage = 6
duoStage = 7
interSpyStage = 8
interWeakStage = 9
acceptedReturnStage = 10
refusedReturnStage = 11
attackedReturnStage = 12
loseStage = 13

wave1EnemyTurn = false

ourTeam = 0
weakTeam = 1
strongTeam = 2
cyborgTeam = 3

leaksNr = 0
denseNr = 1

choiceAccept = 1
choiceRefuse = 2
choiceAttack = 3

HogNames = {loc("Brainiac"), loc("Corpsemonger"), loc("Femur Lover"), loc("Glark"), loc("Bonely"), loc("Rot Molester"), loc("Bloodrocutor"), loc("Muscle Dissolver"), loc("Bloodsucker")}

nativesTeamName = nil
weaklingsTeamName = nil

---POSITIONS---

cannibalPos = {{3108, 1127}, 
               {2559, 1080}, {3598, 1270}, {3293, 1177}, {2623, 1336}, 
               {3418, 1336}, {3447, 1335}, {3481, 1340}, {3507, 1324}} 
densePos = {2776, 1177}
leaksPos = {2941, 1172}
cyborgPos = {1113, 1818}

---Animations

startDialogue = {}
weaklingsAnim = {}
stronglingsAnim = {}
acceptedAnim = {}
acceptedSurvivedFinalAnim = {}
acceptedDiedFinalAnim = {}
refusedAnim = {}
refusedFinalAnim = {}
attackedAnim = {}
attackedFinalAnim = {}

-----------------------------Variables---------------------------------
lastHogTeam = ourTeam
lastOurHog = leaksNr
lastEnemyHog = 0
stage = 0
choice = 0
checkAcceptTimer = 0

brainiacDead = false
cyborgHidden = false
leaksHidden = false
denseHidden = false
cyborgAttacked = false
shotgunTaken = false
grenadeTaken = false
spikyDead = false
ramonDead = false
denseDead = false
leaksDead = false
ramonHidden = false
spikyHidden = false
grenadeUsed = false
shotgunUsed = false


hogNr = {}
cannibalDead = {}
isHidden = {}

--------------------------Anim skip functions--------------------------
function AfterRefusedAnim()
  if stage == loseStage then
    return
  end
  SpawnSupplyCrate(2045, 1575, amSwitch)
  SpawnSupplyCrate(2365, 1495, amShotgun)
  SpawnSupplyCrate(2495, 1519, amGrenade)
  SpawnSupplyCrate(2620, 1524, amRope)
  ShowMission(loc("The Shadow Falls"), loc("The Showdown"), loc("Save Leaks A Lot!|Hint: The switch hedgehog utility might be of help to you."), 1, 6000)
  RemoveEventFunc(CheckDenseDead)
  AddEvent(CheckStronglingsDead, {}, DoStronglingsDeadRefused, {}, 0)
  AddAmmo(cannibals[6], amGrenade, 1)
  AddAmmo(cannibals[7], amGrenade, 1)
  AddAmmo(cannibals[8], amGrenade, 1)
  AddAmmo(cannibals[9], amGrenade, 1)
  AddAmmo(dense, amSkip, 100)
  AddAmmo(leaks, amSkip, 100)
  stage = ramonStage
  SwitchHog(cannibals[9])
  FollowGear(ramon)
  EndTurn(true)
  SetGearMessage(ramon, 0)
  SetGearMessage(leaks, 0)
  AnimWait(ramon, 1)
  AddFunction({func = HideHog, args = {cyborg}})
end

function SkipRefusedAnim()
  if stage == loseStage then
    return
  end
  RefusedStart()
  AnimSetGearPosition(dense, 2645, 1146)
  AnimSetGearPosition(ramon, 2218, 1675)
  AnimSetGearPosition(spiky, 2400, 1675)
end

function AfterStartDialogue()
  if stage == loseStage then
    return
  end
  stage = spyStage
  ShowMission(loc("The Shadow Falls"), loc("Play with me!"), loc("Kill the cannibal!").."|"..loc("Both your hedgehogs must survive."), 1, 6000)
  SetTurnTimeLeft(TurnTime)
end


function StartSkipFunc()
  if stage == loseStage then
    return
  end
  SetState(cannibals[1], 0)
  AnimTurn(leaks, "Right")
  AnimSwitchHog(leaks)
end

function AfterWeaklingsAnim()
  if stage == loseStage then
    return
  end
  AddAmmo(cannibals[2], amShotgun, 1)
  AddAmmo(cannibals[2], amGrenade, 1)
  AddAmmo(cannibals[3], amShotgun, 1)
  AddAmmo(cannibals[3], amGrenade, 1)
  AddAmmo(cannibals[4], amShotgun, 1)
  AddAmmo(cannibals[4], amGrenade, 1)
  AddAmmo(cannibals[5], amShotgun, 1)
  AddAmmo(cannibals[5], amGrenade, 1)
  AddAmmo(leaks, amSkip, 100)
  AddAmmo(dense, amSkip, 100)
  AddEvent(CheckWeaklingsKilled, {}, DoWeaklingsKilled, {}, 0)
  SetHealth(SpawnHealthCrate(2757, 1030), 50)
  SetHealth(SpawnHealthCrate(2899, 1009), 50)
  stage = wave1Stage
  SetGearMessage(dense, 0)
  SetGearMessage(leaks, 0)
  EndTurn(true)
  ShowMission(loc("The Shadow Falls"), loc("Why do you not like me?"), loc("Obliterate them!|Hint: You might want to take cover...").."|"..loc("Both your hedgehogs must survive."), 1, 6000)
end

function SkipWeaklingsAnim()
  if stage == loseStage then
    return
  end
  for i = 2, 5 do
    if isHidden[cannibals[i]] == true then
      RestoreHog(cannibals[i])
      isHidden[cannibals[i]] = false
    end
    AnimSetGearPosition(cannibals[i], unpack(cannibalPos[i]))
    SetState(cannibals[i], 0)
  end
  AnimSwitchHog(cannibals[2])
end

function AfterStronglingsAnim()
  if stage == loseStage then
    return
  end
  stage = cyborgStage
  ShowMission(loc("The Shadow Falls"), loc("The Dilemma"), loc("Choose your side! If you want to join the strange man, walk up to him.|Otherwise, walk away from him. If you decide to att...nevermind..."), 3, 8000)
  AddEvent(CheckChoice, {}, DoChoice, {}, 0)
  AddEvent(CheckRefuse, {}, DoRefuse, {}, 0)
  AddEvent(CheckAccept, {}, DoAccept, {}, 0)
  AddEvent(CheckConfront, {}, DoConfront, {}, 0)
  AddAmmo(dense, amSwitch, 0)
  AddAmmo(dense, amSkip, 0)
  AddAmmo(leaks, amSwitch, 0)
  AddAmmo(leaks, amSkip, 0)
  SetHealth(SpawnHealthCrate(2557, 1030), 50)
  SetHealth(SpawnHealthCrate(3599, 1009), 50)
  EndTurn(true)
end

function SkipStronglingsAnim()
  if stage == loseStage then
    return
  end
  for i = 6, 9 do
    if isHidden[cannibals[i]] == true then
      RestoreHog(cannibals[i])
      isHidden[cannibals[i]] = false
    end
    AnimSetGearPosition(cannibals[i], unpack(cannibalPos[i]))
    SetState(cannibals[i], 0)
  end
  if cyborgHidden == true then
    RestoreHog(cyborg)
    cyborgHidden = false
  end
  SetState(cyborg, 0)
  SetState(dense, 0)
  AnimSetGearPosition(dense, 1350, 1315)
  FollowGear(dense)
  HogTurnLeft(dense, true)
  AnimSetGearPosition(cyborg, 1250, 1315)
  SwitchHog(dense)
end

function AfterAcceptedAnim()
  if stage == loseStage then
    return
  end
  stage = acceptedReturnStage
  SpawnSupplyCrate(1370, 810, amGirder)
  SpawnSupplyCrate(1300, 810, amParachute)
  ShowMission(loc("The Shadow Falls"), loc("The walk of Fame"), loc("Return to Leaks A Lot!"), 1, 6000)
  AddEvent(CheckReadyForStronglings, {}, DoReadyForStronglings, {}, 0)
  AddEvent(CheckNeedGirder, {}, DoNeedGirder, {}, 0)
  AddEvent(CheckNeedWeapons, {}, DoNeedWeapons, {}, 0)
  SwitchHog(dense)
  AnimWait(dense, 1)
  AddFunction({func = HideHog, args = {cyborg}})
end

function SkipAcceptedAnim()
  if stage == loseStage then
    return
  end
  AnimSetGearPosition(cyborg, unpack(cyborgPos))
  SetState(cyborg, gstInvisible)
  AnimSwitchHog(dense)
end

function AfterAttackedAnim()
  if stage == loseStage then
    return
  end
  stage = aloneStage
  ShowMission(loc("The Shadow Falls"), loc("The Individualist"), loc("Defeat the cannibals!"), 1, 12000)
  AddAmmo(cannibals[6], amGrenade, 1)
  AddAmmo(cannibals[6], amFirePunch, 0)
  AddAmmo(cannibals[6], amBaseballBat, 0)
  AddAmmo(cannibals[7], amGrenade, 1)
  AddAmmo(cannibals[7], amFirePunch, 0)
  AddAmmo(cannibals[7], amBaseballBat, 0)
  AddAmmo(cannibals[8], amGrenade, 1)
  AddAmmo(cannibals[8], amFirePunch, 0)
  AddAmmo(cannibals[8], amBaseballBat, 0)
  AddAmmo(cannibals[9], amGrenade, 1)
  AddAmmo(cannibals[9], amFirePunch, 0)
  AddAmmo(cannibals[9], amBaseballBat, 0)
  SetGearMessage(leaks, 0)
  SetTurnTimeLeft(TurnTime)
  AddEvent(CheckStronglingsDead, {}, DoStronglingsDeadAttacked, {}, 0)
  SwitchHog(leaks)
  AnimWait(dense, 1)
  AddFunction({func = HideHog, args = {cyborg}})
end

function SkipAttackedAnim()
  if stage == loseStage then
    return
  end
  if denseDead == false then
    DeleteGear(dense)
  end
  SpawnSupplyCrate(2551, 994, amGrenade)
  SpawnSupplyCrate(3551, 994, amGrenade)
  SpawnSupplyCrate(3392, 1101, amShotgun)
  SpawnSupplyCrate(3192, 1101, amShotgun)
  AnimSetGearPosition(cyborg, unpack(cyborgPos))
  SetState(cyborg, gstInvisible)
end

  
-----------------------------Animations--------------------------------

function SpawnCrates()
  SpawnSupplyCrate(2551, 994, amGrenade)
  SpawnSupplyCrate(3551, 994, amGrenade)
  SpawnSupplyCrate(3392, 1101, amShotgun)
  SpawnSupplyCrate(3192, 1101, amShotgun)
  return true
end

function EmitDenseClouds(anim, dir)
  if stage == loseStage then
    return
  end
  local dif
  if dir == "Left" then 
    dif = 10
  else
    dif = -10
  end
  AnimInsertStepNext({func = AnimVisualGear, args = {dense, GetX(dense) + dif, GetY(dense) + dif, vgtSteam, 0, true}, swh = false})
  AnimInsertStepNext({func = AnimVisualGear, args = {dense, GetX(dense) + dif, GetY(dense) + dif, vgtSteam, 0, true}, swh = false})
  AnimInsertStepNext({func = AnimVisualGear, args = {dense, GetX(dense) + dif, GetY(dense) + dif, vgtSteam, 0, true}, swh = false})
  AnimInsertStepNext({func = AnimWait, args = {dense, 800}})
  AnimInsertStepNext({func = AnimVisualGear, args = {dense, GetX(dense) + dif, GetY(dense) + dif, vgtSteam, 0, true}, swh = false})
  AnimInsertStepNext({func = AnimVisualGear, args = {dense, GetX(dense) + dif, GetY(dense) + dif, vgtSteam, 0, true}, swh = false})
  AnimInsertStepNext({func = AnimWait, args = {dense, 800}})
  AnimInsertStepNext({func = AnimVisualGear, args = {dense, GetX(dense) + dif, GetY(dense) + dif, vgtSteam, 0, true}, swh = false})
end

function BlowDenseCloud()
  if stage == loseStage then
    return
  end
  AnimInsertStepNext({func = DeleteGear, args = {dense}, swh = false}) 
  AnimInsertStepNext({func = AnimVisualGear, args = {dense, GetX(dense), GetY(dense), vgtBigExplosion, 0, true}, swh = false})
  AnimInsertStepNext({func = AnimWait, args = {dense, 1200}})
  AnimInsertStepNext({func = AnimVisualGear, args = {dense, GetX(dense) + 20, GetY(dense), vgtExplosion, 0, true}, swh = false})
  AnimInsertStepNext({func = AnimWait, args = {dense, 100}})
  AnimInsertStepNext({func = AnimVisualGear, args = {dense, GetX(dense) + 10, GetY(dense), vgtExplosion, 0, true}, swh = false})
  AnimInsertStepNext({func = AnimWait, args = {dense, 100}})
  AnimInsertStepNext({func = AnimVisualGear, args = {dense, GetX(dense) - 10, GetY(dense), vgtExplosion, 0, true}, swh = false})
  AnimInsertStepNext({func = AnimWait, args = {dense, 100}})
  AnimInsertStepNext({func = AnimVisualGear, args = {dense, GetX(dense) - 20, GetY(dense), vgtExplosion, 0, true}, swh = false})
end

function SetupAcceptedSurvivedFinalAnim()
  table.insert(acceptedSurvivedFinalAnim, {func = AnimCustomFunction, args = {dense, CondNeedToTurn, {leaks, dense}}})
  table.insert(acceptedSurvivedFinalAnim, {func = AnimSay, args = {leaks, loc("Pfew! That was close!"), SAY_SAY, 3000}})
  if grenadeUsed and shotgunUsed then
    table.insert(acceptedSurvivedFinalAnim, {func = AnimSay, args = {leaks, loc("Where did you get the exploding apples and the magic bow that shoots many arrows?"), SAY_SAY, 9000}})
  elseif grenadeUsed then
    table.insert(acceptedSurvivedFinalAnim, {func = AnimSay, args = {leaks, loc("Where did you get the exploding apples?"), SAY_SAY, 6000}})
  elseif shotgunUsed then
    table.insert(acceptedSurvivedFinalAnim, {func = AnimSay, args = {leaks, loc("Where did you get the magic bow that shoots many arrows?"), SAY_SAY, 8000}})
  else
    table.insert(acceptedSurvivedFinalAnim, {func = AnimSay, args = {leaks, loc("Did you warn the village?"), SAY_SAY, 4000}})
    table.insert(acceptedSurvivedFinalAnim, {func = AnimSay, args = {dense, loc("No, I came back to help you out..."), SAY_SAY, 5000}})
  end
  if grenadeUsed or shotgunUsed then
    table.insert(acceptedSurvivedFinalAnim, {func = AnimSay, args = {dense, loc("Uhm...I met one of them and took his weapons."), SAY_SAY, 5000}})
  end
  table.insert(acceptedSurvivedFinalAnim, {func = AnimSay, args = {dense, loc("We should head back to the village now."), SAY_SAY, 5000}})
end

function AnimationSetup()
  table.insert(startDialogue, {func = AnimWait, args = {dense, 4000}})
  table.insert(startDialogue, {func = AnimCaption, args = {leaks, loc("After the shock caused by the enemy spy, Leaks A Lot and Dense Cloud went hunting to relax."), 6000}})
  table.insert(startDialogue, {func = AnimCaption, args = {leaks, loc("Little did they know that this hunt will mark them forever..."), 4000}})
  table.insert(startDialogue, {func = AnimSay, args = {leaks, loc("I have no idea where that mole disappeared...Can you see it?"), SAY_SAY, 9000}})
  table.insert(startDialogue, {func = AnimSay, args = {dense, loc("Nope. It was one fast mole, that's for sure."), SAY_SAY, 5000}}) 
  table.insert(startDialogue, {func = AnimCustomFunction, args = {dense, EmitDenseClouds, {startDialogue, "Right"}}})
  table.insert(startDialogue, {func = AnimWait, args = {dense, 2000}})
  table.insert(startDialogue, {func = AnimSay, args = {leaks, loc("Please, stop releasing your \"smoke signals\"!"), SAY_SAY, 5000}})
  table.insert(startDialogue, {func = AnimSay, args = {leaks, loc("You're terrorizing the forest...We won't catch anything like this!"), SAY_SAY, 6000}})
  table.insert(startDialogue, {func = AnimSay, args = {leaks, loc("..."), SAY_THINK, 1000}})
  table.insert(startDialogue, {func = AnimGiveState, args = {cannibals[1], 0}, swh = false})
  table.insert(startDialogue, {func = AnimOutOfNowhere, args = {cannibals[1], unpack(cannibalPos[1])}, swh = false})
  table.insert(startDialogue, {func = AnimTurn, args = {leaks, "Right"}})
  table.insert(startDialogue, {func = AnimTurn, args = {cannibals[1], "Right"}})
  table.insert(startDialogue, {func = AnimWait, args = {cannibals[1], 1000}})
  table.insert(startDialogue, {func = AnimTurn, args = {cannibals[1], "Left"}})
  table.insert(startDialogue, {func = AnimWait, args = {cannibals[1], 1000}})
  table.insert(startDialogue, {func = AnimTurn, args = {cannibals[1], "Right"}})
  table.insert(startDialogue, {func = AnimSay, args = {cannibals[1], loc("I can't believe it worked!"), SAY_THINK, 3500}})
  table.insert(startDialogue, {func = AnimSay, args = {cannibals[1], loc("That shaman sure knows what he's doing!"), SAY_THINK, 6000}})
  table.insert(startDialogue, {func = AnimSay, args = {cannibals[1], loc("Yeah...I think it's a 'he', lol."), SAY_THINK, 5000}})
  table.insert(startDialogue, {func = AnimSay, args = {leaks, loc("It wants our brains!"), SAY_SHOUT, 3000}})
  table.insert(startDialogue, {func = AnimTurn, args = {cannibals[1], "Left"}})
  table.insert(startDialogue, {func = AnimSay, args = {cannibals[1], loc("Not you again! My head still hurts from last time!"), SAY_SHOUT, 6000}})
  table.insert(startDialogue, {func = AnimSwitchHog, args = {leaks}})
  AddSkipFunction(startDialogue, StartSkipFunc, {})

  table.insert(weaklingsAnim, {func = AnimGearWait, args = {leaks, 1000}})
  table.insert(weaklingsAnim, {func = AnimCustomFunction, args = {leaks, CondNeedToTurn, {leaks, dense}}})
  table.insert(weaklingsAnim, {func = AnimSay, args = {leaks, loc("Did you see him coming?"), SAY_SAY, 3500}})
  table.insert(weaklingsAnim, {func = AnimSay, args = {dense, loc("No. Where did he come from?"), SAY_SAY, 3500}})
  table.insert(weaklingsAnim, {func = AnimCustomFunction, args = {leaks, UnHideWeaklings, {}}})
  table.insert(weaklingsAnim, {func = AnimOutOfNowhere, args = {cannibals[2], unpack(cannibalPos[2])}})
  table.insert(weaklingsAnim, {func = AnimGiveState, args = {cannibals[2], 0}})
  table.insert(weaklingsAnim, {func = AnimWait, args = {leaks, 400}})
  table.insert(weaklingsAnim, {func = AnimGiveState, args = {cannibals[3], 0}})
  table.insert(weaklingsAnim, {func = AnimOutOfNowhere, args = {cannibals[3], unpack(cannibalPos[3])}})
  table.insert(weaklingsAnim, {func = AnimWait, args = {leaks, 400}})
  table.insert(weaklingsAnim, {func = AnimGiveState, args = {cannibals[4], 0}})
  table.insert(weaklingsAnim, {func = AnimOutOfNowhere, args = {cannibals[4], unpack(cannibalPos[4])}})
  table.insert(weaklingsAnim, {func = AnimWait, args = {leaks, 400}})
  table.insert(weaklingsAnim, {func = AnimGiveState, args = {cannibals[5], 0}})
  table.insert(weaklingsAnim, {func = AnimOutOfNowhere, args = {cannibals[5], unpack(cannibalPos[5])}})
  table.insert(weaklingsAnim, {func = AnimWait, args = {leaks, 400}})
  table.insert(weaklingsAnim, {func = AnimSay, args = {cannibals[3], loc("Are we there yet?"), SAY_SAY, 4000}}) 
  table.insert(weaklingsAnim, {func = AnimSay, args = {dense, loc("This must be some kind of sorcery!"), SAY_SHOUT, 3500}})
  table.insert(weaklingsAnim, {func = AnimSwitchHog, args = {cannibals[2]}})
  AddSkipFunction(weaklingsAnim, SkipWeaklingsAnim, {})

  table.insert(stronglingsAnim, {func = AnimGearWait, args = {leaks, 1000}})
  table.insert(stronglingsAnim, {func = AnimCustomFunction, args = {leaks, UnHideStronglings, {}}})
  table.insert(stronglingsAnim, {func = AnimCustomFunction, args = {leaks, CondNeedToTurn, {leaks, dense}}})
  table.insert(stronglingsAnim, {func = AnimGiveState, args = {leaks, 0}})
  table.insert(stronglingsAnim, {func = AnimGiveState, args = {dense, 0}})
  table.insert(stronglingsAnim, {func = AnimSay, args = {leaks, loc("I thought their shaman died when he tried our medicine!"), SAY_SAY, 7000}})
  table.insert(stronglingsAnim, {func = AnimSay, args = {dense, loc("I saw it with my own eyes!"), SAY_SAY, 4000}})
  table.insert(stronglingsAnim, {func = AnimSay, args = {leaks, loc("Then how do they keep appearing?"), SAY_SAY, 4000}})
  table.insert(stronglingsAnim, {func = AnimSay, args = {leaks, loc("It's impossible to communicate with the spirits without a shaman."), SAY_SAY, 7000}})
  table.insert(stronglingsAnim, {func = AnimSay, args = {dense, loc("We need to warn the village."), SAY_SAY, 3500}})
  table.insert(stronglingsAnim, {func = AnimGiveState, args = {cannibals[6], 0}})
  table.insert(stronglingsAnim, {func = AnimOutOfNowhere, args = {cannibals[6], unpack(cannibalPos[6])}})
  table.insert(stronglingsAnim, {func = AnimWait, args = {leaks, 400}})
  table.insert(stronglingsAnim, {func = AnimGiveState, args = {cannibals[7], 0}})
  table.insert(stronglingsAnim, {func = AnimOutOfNowhere, args = {cannibals[7], unpack(cannibalPos[7])}})
  table.insert(stronglingsAnim, {func = AnimWait, args = {leaks, 400}})
  table.insert(stronglingsAnim, {func = AnimGiveState, args = {cannibals[8], 0}})
  table.insert(stronglingsAnim, {func = AnimOutOfNowhere, args = {cannibals[8], unpack(cannibalPos[8])}})
  table.insert(stronglingsAnim, {func = AnimWait, args = {leaks, 400}})
  table.insert(stronglingsAnim, {func = AnimGiveState, args = {cannibals[9], 0}})
  table.insert(stronglingsAnim, {func = AnimOutOfNowhere, args = {cannibals[9], unpack(cannibalPos[9])}})
  table.insert(stronglingsAnim, {func = AnimWait, args = {leaks, 400}})
  table.insert(stronglingsAnim, {func = AnimSay, args = {cannibals[7], loc("What a ride!"), SAY_SHOUT, 2000}})
  table.insert(stronglingsAnim, {func = AnimTurn, args = {leaks, "Right"}})
  table.insert(stronglingsAnim, {func = AnimWait, args = {leaks, 700}})
  table.insert(stronglingsAnim, {func = AnimTurn, args = {leaks, "Left"}})
  table.insert(stronglingsAnim, {func = AnimSay, args = {leaks, loc("We can't defeat them!"), SAY_THINK, 3000}})
  table.insert(stronglingsAnim, {func = AnimSay, args = {leaks, loc("I'll hold them off while you return to the village!"), SAY_SAY, 6000}})
  table.insert(stronglingsAnim, {func = AnimFollowGear, args = {cyborg}, swh = false})
  table.insert(stronglingsAnim, {func = AnimCaption, args = {cyborg, loc("30 minutes later...")}, swh = false})
  table.insert(stronglingsAnim, {func = AnimWait, args = {cyborg, 2000}})
  table.insert(stronglingsAnim, {func = AnimSetGearPosition, args = {dense, 1420, 1315}})
  table.insert(stronglingsAnim, {func = AnimMove, args = {dense, "Left", 1400, 0}})
  table.insert(stronglingsAnim, {func = AnimCustomFunction, args = {dense, EmitDenseClouds, {stronglingsAnim, "Left"}}})
  table.insert(stronglingsAnim, {func = AnimMove, args = {dense, "Left", 1350, 0}})
  table.insert(stronglingsAnim, {func = AnimOutOfNowhere, args = {cyborg, 1250, 1320}})
  table.insert(stronglingsAnim, {func = AnimRemoveState, args = {cyborg, gstInvisible}})
  table.insert(stronglingsAnim, {func = AnimGearWait, args = {cyborg, 2000}})
  table.insert(stronglingsAnim, {func = AnimSay, args = {cyborg, loc("Greetings, cloudy one!"), SAY_SAY, 3000}})
  table.insert(stronglingsAnim, {func = AnimSay, args = {cyborg, loc("I have come to make you an offering..."), SAY_SAY, 6000}})
  table.insert(stronglingsAnim, {func = AnimSay, args = {cyborg, loc("You are given the chance to turn your life around..."), SAY_SAY, 6000}})
  table.insert(stronglingsAnim, {func = AnimSay, args = {cyborg, loc("If you agree to provide the information we need, you will be spared!"), SAY_SAY, 7000}})
  table.insert(stronglingsAnim, {func = AnimSay, args = {cyborg, loc("Have no illusions, your tribe is dead, indifferent of your choice."), SAY_SAY, 7000}})
  table.insert(stronglingsAnim, {func = AnimSay, args = {cyborg, loc("If you decide to help us, though, we will no longer need to find a new governor for the island."), SAY_SAY, 8000}})
  table.insert(stronglingsAnim, {func = AnimSay, args = {cyborg, loc("If you know what I mean..."), SAY_SAY, 3000}})
  table.insert(stronglingsAnim, {func = AnimSay, args = {cyborg, loc("So? What will it be?"), SAY_SAY, 3000}})
  table.insert(stronglingsAnim, {func = AnimSwitchHog, args = {dense}})
  AddSkipFunction(stronglingsAnim, SkipStronglingsAnim, {})

  table.insert(acceptedAnim, {func = AnimSay, args = {cyborg, loc("Great choice, Steve! Mind if I call you that?"), SAY_SAY, 7000}})
  table.insert(acceptedAnim, {func = AnimSay, args = {dense, loc("Whatever floats your boat..."), SAY_SAY, 4500}})
  table.insert(acceptedAnim, {func = AnimSay, args = {cyborg, loc("Great! You will be contacted soon for assistance."), SAY_SAY, 6000}})
  table.insert(acceptedAnim, {func = AnimSay, args = {cyborg, loc("In the meantime, take these and return to your \"friend\"!"), SAY_SAY, 6000}})
  table.insert(acceptedAnim, {func = AnimGiveState, args = {cyborg, gstInvisible}})
  table.insert(acceptedAnim, {func = AnimDisappear, args = {cyborg, unpack(cyborgPos)}})
  table.insert(acceptedAnim, {func = AnimSwitchHog, args = {dense}})
  AddSkipFunction(acceptedAnim, SkipAcceptedAnim, {}) 

  table.insert(acceptedDiedFinalAnim, {func = AnimSay, args = {leaks, loc("Pfew! That was close!"), SAY_THINK, 3000}})
  table.insert(acceptedDiedFinalAnim, {func = AnimSay, args = {leaks, loc("Your death will not be in vain, Dense Cloud!"), SAY_THINK, 5000}})
  table.insert(acceptedDiedFinalAnim, {func = AnimSay, args = {dense, loc("You will be avenged!"), SAY_SAY, 3000}})

  table.insert(refusedAnim, {func = AnimSay, args = {cyborg, loc("I see..."), SAY_SAY, 2000}})
  table.insert(refusedAnim, {func = AnimSay, args = {cyborg, loc("Remember this, pathetic animal: When the day comes, you will regret your blind loyalty!"), SAY_SAY, 8000}})
  table.insert(refusedAnim, {func = AnimSay, args = {cyborg, loc("You just committed suicide..."), SAY_SAY, 5000}})
  table.insert(refusedAnim, {func = AnimDisappear, args = {cyborg, unpack(cyborgPos)}})
  table.insert(refusedAnim, {func = AnimGiveState, args = {cyborg, gstInvisible}})
  table.insert(refusedAnim, {func = AnimSay, args = {dense, loc("If you say so..."), SAY_THINK, 3000}})
  table.insert(refusedAnim, {func = AnimFollowGear, args = {cyborg}, swh = false})
  table.insert(refusedAnim, {func = AnimWait, args = {cyborg, 700}})
  table.insert(refusedAnim, {func = AnimCustomFunction, args = {dense, RefusedStart, {}}})
  table.insert(refusedAnim, {func = AnimOutOfNowhere, args = {dense, 2645, 1146}})
  table.insert(refusedAnim, {func = AnimOutOfNowhere, args = {ramon, 2218, 1675}})
  table.insert(refusedAnim, {func = AnimOutOfNowhere, args = {spiky, 2400, 1675}})
  table.insert(refusedAnim, {func = AnimTurn, args = {spiky, "Left"}})
  table.insert(refusedAnim, {func = AnimWait, args = {cyborg, 1700}})
  table.insert(refusedAnim, {func = AnimTurn, args = {spiky, "Right"}})
  table.insert(refusedAnim, {func = AnimWait, args = {cyborg, 1700}})
  table.insert(refusedAnim, {func = AnimTurn, args = {spiky, "Left"}})
  table.insert(refusedAnim, {func = AnimSay, args = {spiky, loc("Dude, we really need a new shaman..."), SAY_SAY, 4000}})
  AddSkipFunction(refusedAnim, SkipRefusedAnim, {})

  table.insert(refusedFinalAnim, {func = AnimSay, args = {leaks, loc("It's over..."), SAY_SAY, 2000}})
  table.insert(refusedFinalAnim, {func = AnimSay, args = {leaks, loc("Let's head back to the village!"), SAY_SAY, 4000}})

  table.insert(attackedAnim, {func = AnimCustomFunction, args = {dense, CondNeedToTurn, {cyborg, dense}}})
  table.insert(attackedAnim, {func = AnimCustomFunction, args = {cyborg, SetHealth, {cyborg, 200}}})
  table.insert(attackedAnim, {func = AnimWait, args = {cyborg, 2000}})
  table.insert(attackedAnim, {func = AnimSay, args = {cyborg, loc("Really?! You thought you could harm me with your little toys?"), SAY_SAY, 7000}})
  table.insert(attackedAnim, {func = AnimSay, args = {cyborg, loc("You're pathetic! You are not worthy of my attention..."), SAY_SAY, 6000}})
  table.insert(attackedAnim, {func = AnimSay, args = {cyborg, loc("Actually, you aren't worthy of life! Take this..."), SAY_SAY, 5000}})
  table.insert(attackedAnim, {func = AnimCustomFunction, args = {dense, BlowDenseCloud, {}}, swh = false})
  table.insert(attackedAnim, {func = AnimWait, args = {cyborg, 2000}})
  table.insert(attackedAnim, {func = AnimSay, args = {cyborg, loc("Incredible..."), SAY_SAY, 3000}})
  table.insert(attackedAnim, {func = AnimDisappear, args = {cyborg, unpack(cyborgPos)}})
  table.insert(attackedAnim, {func = AnimGiveState, args = {cyborg, gstInvisible}})
  table.insert(attackedAnim, {func = AnimSwitchHog, args = {leaks}})
  table.insert(attackedAnim, {func = AnimSay, args = {leaks, loc("I wonder where Dense Cloud is..."), SAY_THINK, 4000}})
  table.insert(attackedAnim, {func = AnimSay, args = {leaks, loc("I can't wait any more, I have to save myself!"), SAY_THINK, 5000}})
  table.insert(attackedAnim, {func = AnimCustomFunction, args = {leaks, SpawnCrates, {}}})
  table.insert(attackedAnim, {func = AnimWait, args = {leaks, 1500}})
  table.insert(attackedAnim, {func = AnimSay, args = {leaks, loc("Where are all these crates coming from?!"), SAY_THINK, 5500}})
  AddSkipFunction(attackedAnim, SkipAttackedAnim, {})
  
  table.insert(attackedFinalAnim, {func = AnimWait, args = {leaks, 2000}})
  table.insert(attackedFinalAnim, {func = AnimSay, args = {leaks, loc("I have to get back to the village!"), SAY_THINK, 5000}})
  table.insert(attackedFinalAnim, {func = AnimSay, args = {leaks, loc("Dense Cloud must have already told them everything..."), SAY_THINK, 7000}})

end


-----------------------------Misc--------------------------------------


function RefusedStart()
  if stage == loseStage then
    return
  end
  if ramonHidden == true then
    RestoreHog(ramon)
    ramonHidden = false
  end
  if spikyHidden == true then
    RestoreHog(spiky)
    spikyHidden = false
  end
  SetState(ramon, 0)
  SetState(spiky, 0)
  SetGearMessage(dense, 0)
  SetGearMessage(ramon, 0)
  SetGearMessage(spiky, 0)
end

function AddHogs()
  nativesTeamName = AddMissionTeam(-2)
  ramon = AddHog(loc("Ramon"), 0, 100, "rasta")
	leaks = AddHog(loc("Leaks A Lot"), 0, 100, "Rambo")
  dense = AddHog(loc("Dense Cloud"), 0, 100, "RobinHood")
  spiky = AddHog(loc("Spiky Cheese"), 0, 100, "hair_yellow")

  weaklingsTeamName = AddTeam(loc("Weaklings"), -1, "skull", "Island", "Pirate_qau", "cm_vampire")
  cannibals = {}
  cannibals[1] = AddHog(loc("Brainiac"), 5, 20, "Zombi")

  for i = 2, 5 do
    cannibals[i] = AddHog(HogNames[i], 5, 20, "Zombi")
    hogNr[cannibals[i]] = i - 2
  end

  AddTeam(loc("Stronglings"), -1, "skull", "Island", "Pirate_qau", "cm_vampire")

  for i = 6, 9 do
    cannibals[i] = AddHog(HogNames[i], 4, 30, "vampirichog")
    hogNr[cannibals[i]] = i - 2
  end

  AddTeam(loc("011101001"), -1, "ring", "UFO", "Robot_qau", "cm_binary")
  cyborg = AddHog(loc("Y3K1337"), 0, 200, "cyborg1")
end

function PlaceHogs()
  HogTurnLeft(leaks, true)

  for i = 2, 9 do
    AnimSetGearPosition(cannibals[i], unpack(cyborgPos))
    AnimTurn(cannibals[i], "Left")
    cannibalDead[i] = false
  end

  AnimSetGearPosition(cannibals[1], cannibalPos[1][1], cannibalPos[1][2])
  AnimTurn(cannibals[1], "Left")

  AnimSetGearPosition(cyborg, cyborgPos[1], cyborgPos[2])
  AnimSetGearPosition(ramon, 2218, 1675)
  AnimSetGearPosition(skiky, 2400, 1675)
  AnimSetGearPosition(dense, densePos[1], densePos[2])
  AnimSetGearPosition(leaks, leaksPos[1], leaksPos[2]) 
end

function VisiblizeHogs()
  for i = 1, 9 do
    SetState(cannibals[i], gstInvisible)
  end
  SetState(cyborg, gstInvisible)
  SetState(ramon, gstInvisible)
  SetState(spiky, gstInvisible)
end

function CondNeedToTurn(hog1, hog2)
  if stage == loseStage then
    return
  end
  xl, xd = GetX(hog1), GetX(hog2)
  if xl and xd then
    if xl > xd then
      AnimInsertStepNext({func = AnimTurn, args = {hog1, "Left"}})
      AnimInsertStepNext({func = AnimTurn, args = {hog2, "Right"}})
    elseif xl < xd then
      AnimInsertStepNext({func = AnimTurn, args = {hog2, "Left"}})
      AnimInsertStepNext({func = AnimTurn, args = {hog1, "Right"}})
    end
  end
end

function HideHogs()
  for i = 2, 9 do
    HideHog(cannibals[i])
    isHidden[cannibals[i]] = true
  end
  HideHog(cyborg)
  cyborgHidden = true
  HideHog(ramon)
  HideHog(spiky)
  ramonHidden = true
  spikyHidden = true
end

function HideStronglings()
  if stage == loseStage then
    return
  end
  for i = 6, 9 do
    HideHog(cannibals[i])
    isHidden[cannibals[i]] = true
  end
end

function UnHideWeaklings()
  if stage == loseStage then
    return
  end
  for i = 2, 5 do
    RestoreHog(cannibals[i])
    isHidden[cannibals[i]] = false
    SetState(cannibals[i], gstInvisible)
  end
end

function UnHideStronglings()
  if stage == loseStage then
    return
  end
  for i = 6, 9 do
    RestoreHog(cannibals[i])
    isHidden[cannibals[i]] = false
    SetState(cannibals[i], gstInvisible)
  end
  RestoreHog(cyborg)
  cyborgHidden = false
  SetState(cyborg, gstInvisible)
end

function ChoiceTaken()
  if stage == loseStage then
    return
  end
  SetGearMessage(CurrentHedgehog, 0)
  if choice == choiceAccept then
    AddAnim(acceptedAnim)
    AddFunction({func = AfterAcceptedAnim, args = {}})
  elseif choice == choiceRefuse then
    AddAnim(refusedAnim)
    AddFunction({func = AfterRefusedAnim, args = {}})
  else
    AddAnim(attackedAnim)
    AddFunction({func = AfterAttackedAnim, args = {}})
  end
end

function KillCyborg()
  if stage == loseStage then
    return
  end
  RestoreHog(cyborg)
  DeleteGear(cyborg)
  EndTurn(true)
end
-----------------------------Events------------------------------------

function CheckBrainiacDead()
  return brainiacDead
end

function DoBrainiacDead()
  if stage == loseStage then
    return
  end
  if (not IsHogAlive(dense)) or (not IsHogAlive(leaks)) then
    return
  end

  EndTurn(true)
  SetGearMessage(CurrentHedgehog, 0)
  AddAnim(weaklingsAnim)
  AddFunction({func = AfterWeaklingsAnim, args = {}})
  stage = interSpyStage
end
  
function CheckWeaklingsKilled()
  for i = 2, 5 do
    if cannibalDead[i] == false then
      return false
    end
  end
  return true
end

function DoWeaklingsKilled()
  if stage == loseStage then
    return
  end
  if (not IsHogAlive(dense)) or (not IsHogAlive(leaks)) then
    return
  end
  SetGearMessage(CurrentHedgehog, 0)
  AddAnim(stronglingsAnim)
  AddFunction({func = AfterStronglingsAnim, args = {}})
  stage = interWeakStage
  DismissTeam(weaklingsTeamName)
end

function CheckRefuse()
  return IsHogAlive(dense) and GetX(dense) > 1400 and StoppedGear(dense)
end

function DoRefuse()
  if stage == loseStage then
    return
  end
  choice = choiceRefuse
end

function CheckAccept()
  if not IsHogAlive(dense) then
    return false
  end
  if GetX(dense) < 1300 then
    -- When close to cyborg, wait for a short time before accepting,
    -- to allow player to attack with melee weapons.
    checkAcceptTimer = checkAcceptTimer + 1
    if checkAcceptTimer > 2000 and denseDead == false and StoppedGear(dense) then
      return true
    end
  else
    checkAcceptTimer = 0
  end
  return false
end

function DoAccept()
  if stage == loseStage then
    return
  end
  choice = choiceAccept
end

function CheckConfront()
  return cyborgAttacked and IsHogAlive(dense) and StoppedGear(dense)
end

function DoConfront()
  if stage == loseStage then
    return
  end
  choice = choiceAttack
end

function CheckChoice()
  return choice ~= 0
end

function DoChoice()
  if stage == loseStage then
    return
  end
  RemoveEventFunc(CheckConfront)
  RemoveEventFunc(CheckAccept)
  RemoveEventFunc(CheckRefuse)
  ChoiceTaken()
end

function CheckNeedGirder()
  if stage == loseStage then
    return false
  end
  return denseDead == false and GetX(dense) > 1640 and StoppedGear(dense)
end

function DoNeedGirder()
  if stage == loseStage then
    return
  end
  local ctrl = loc("Hint: To place a girder, select it,|then use [Left] and [Right] to select angle and length,|then choose a location for the girder.")
  if INTERFACE == "touch" then
    ctrl = ctrl .. "|" .. loc("Choose location: Tap the [Target] button, then tap on the spot you want to choose")
  else
    ctrl = ctrl .. "|" .. loc("Choose location: Left click")
  end
  ShowMission(loc("The Shadow Falls"), loc("Under Construction"), loc("Return to Leaks A Lot!") .. "|" .. ctrl, 1, 6000)
end

function CheckNeedWeapons()
  if stage == loseStage then
    return false
  end
  return denseDead == false and GetX(dense) > 2522 and StoppedGear(dense)
end

function DoNeedWeapons()
  if stage == loseStage then
    return
  end
  grenadeCrate = SpawnSupplyCrate(2550, 800, amGrenade)
  shotgunCrate = SpawnSupplyCrate(2610, 850, amShotgun)
  AddCaption(loc("A little gift from the cyborgs"))
end

function CheckReadyForStronglings()
  if stage == loseStage then
    return false
  end
  if not IsHogAlive(dense) then
    return false
  end
  return (shotgunTaken and grenadeTaken) or GetX(dense) > 2700
end

function DoReadyForStronglings()
  if stage == loseStage then
    return
  end

  ShowMission(loc("The Shadow Falls"), loc("The guardian"), loc("Defeat the cannibals!") .."|".. loc("Leaks A Lot must survive!"), 1, 12000)
  AddAmmo(dense, amSkip, 100)
  AddAmmo(dense, amSwitch, 100)
  AddAmmo(leaks, amSkip, 100)
  AddAmmo(leaks, amSwitch, 100)
  stage = duoStage
  RemoveEventFunc(CheckNeedGirder)
  RemoveEventFunc(CheckNeedWeapons)
  RemoveEventFunc(CheckDenseDead)
  AddEvent(CheckStronglingsDead, {}, DoStronglingsDead, {}, 0)
  AddAmmo(cannibals[6], amGrenade, 2)
  AddAmmo(cannibals[6], amShotgun, 2)
  AddAmmo(cannibals[7], amGrenade, 2)
  AddAmmo(cannibals[7], amShotgun, 2)
  AddAmmo(cannibals[8], amGrenade, 2)
  AddAmmo(cannibals[8], amShotgun, 2)
  AddAmmo(cannibals[9], amGrenade, 2)
  AddAmmo(cannibals[9], amShotgun, 2)
  SetGearMessage(leaks, 0)
  SetGearMessage(dense, 0)
  SetTurnTimeLeft(TurnTime)
end

function DoStronglingsDead()
  if stage == loseStage then
    return
  end
  if not IsHogAlive(leaks) then
    return
  end
  SetGearMessage(CurrentHedgehog, 0)
  if denseDead == true then
    AddAnim(acceptedDiedFinalAnim)
    SaveCampaignVar("M2DenseDead", "1")
  else
    SetupAcceptedSurvivedFinalAnim()
    AddAnim(acceptedSurvivedFinalAnim)
    SaveCampaignVar("M2DenseDead", "0")
  end
  SaveCampaignVar("M2RamonDead", "0")
  SaveCampaignVar("M2SpikyDead", "0")
  AddFunction({func = KillCyborg, args = {}})
  if progress and progress<2 then
    SaveCampaignVar("Progress", "2")
  end
  SaveCampaignVar("M2Choice", "" .. choice)
end

function DoStronglingsDeadRefused()
  if stage == loseStage then
    return
  end
  if denseDead == true then
    SaveCampaignVar("M2DenseDead", "1")
  else
    SaveCampaignVar("M2DenseDead", "0")
  end
  if ramonDead == true then
    SaveCampaignVar("M2RamonDead", "1")
  else
    SaveCampaignVar("M2RamonDead", "0")
  end
  if spikyDead == true then
    SaveCampaignVar("M2SpikyDead", "1")
  else
    SaveCampaignVar("M2SpikyDead", "0")
  end
  AddAnim(refusedFinalAnim)
  AddFunction({func = KillCyborg, args = {}})
  if progress and progress<2 then
    SaveCampaignVar("Progress", "2")
  end
  SaveCampaignVar("M2Choice", "" .. choice)
end

function DoStronglingsDeadAttacked()
  if stage == loseStage then
    return
  end
  SaveCampaignVar("M2DenseDead", "1")
  SaveCampaignVar("M2RamonDead", "0")
  SaveCampaignVar("M2SpikyDead", "0")
  if progress and progress<2 then
    SaveCampaignVar("Progress", "2")
  end
  SaveCampaignVar("M2Choice", "" .. choice)
  AddAnim(attackedFinalAnim)
  AddFunction({func = KillCyborg, args = {}})
end

function CheckStronglingsDead()
  if leaksDead == true then
    return false
  end
  for i = 6, 9 do
    if cannibalDead[i] == false then
      return false
    end
  end
  return true
end

function CheckLeaksDead()
  return leaksDead
end

function DoDead()
  if stage == loseStage then
    return
  end
  AddCaption(loc("...and so the cyborgs took over the world..."))
  stage = loseStage
  DismissTeam(nativesTeamName)
end

function CheckDenseDead()
  return denseDead and choice ~= choiceAttack 
end

-----------------------------Main Functions----------------------------

function onGameInit()
	Seed = 334 
	GameFlags = gfSolidLand + gfDisableWind + gfPerHogAmmo
	TurnTime = 50000 
	CaseFreq = 0
	MinesNum = 0
	MinesTime = 3000
	Explosives = 0
	Map = "A_Classic_Fairytale_shadow"
	Theme = "Nature"
	-- Disable Sudden Death
	HealthDecrease = 0
	WaterRise = 0

  AddHogs()
  PlaceHogs()
  VisiblizeHogs()
  
  AnimInit()
  AnimationSetup()
end

function onGameStart()
  progress = tonumber(GetCampaignVar("Progress"))
  HideHogs()
  AddAmmo(leaks, amSwitch, 100)
  AddAmmo(dense, amSwitch, 100)
  AddEvent(CheckLeaksDead, {}, DoDead, {}, 0)
  AddEvent(CheckDenseDead, {}, DoDead, {}, 0)
  AddAnim(startDialogue)
  AddFunction({func = AfterStartDialogue, args = {}})
  AddEvent(CheckBrainiacDead, {}, DoBrainiacDead, {}, 0)
  local hint
  if INTERFACE == "touch" then
     -- FIXME: No precise key available in Touch yet.
     hint = ""
  else
     hint = "|" .. loc("Hint: Cinematics can be skipped with the [Precise] key.")
  end
  ShowMission(loc("The Shadow Falls"), loc("The First Encounter"), loc("Survive!") .. hint, 10, 0)
end

function onGameTick()
  AnimUnWait()
  if ShowAnimation() == false then
    return
  end
  ExecuteAfterAnimations()
  CheckEvents()
end

function onGearDelete(gear)
  if gear == cannibals[1] then
    brainiacDead = true
  elseif gear == grenadeCrate then
    grenadeTaken = true
  elseif gear == shotgunCrate then
    shotgunTaken = true
  elseif gear == dense then
    denseDead = true
  elseif gear == leaks then
    leaksDead = true
  elseif gear == ramon then
    ramonDead = true
  elseif gear == spiky then
    spikyDead = true
  else
    for i = 2, 9 do
      if gear == cannibals[i] then
        cannibalDead[i] = true
      end
    end
  end
end

function onGearAdd(gear)
  if GetGearType(gear) == gtGrenade and GetHogTeamName(CurrentHedgehog) == nativesTeamName then
    grenadeUsed = true
  elseif GetGearType(gear) == gtShotgunShot and GetHogTeamName(CurrentHedgehog) == nativesTeamName then
    shotgunUsed = true
  end
end

function onAmmoStoreInit()
  SetAmmo(amDEagle, 9, 0, 0, 0)
  SetAmmo(amSniperRifle, 6, 0, 0, 0)
  SetAmmo(amFirePunch, 3, 0, 0, 0)
  SetAmmo(amWhip, 4, 0, 0, 0)
  SetAmmo(amBaseballBat, 4, 0, 0, 0)
  SetAmmo(amHammer, 2, 0, 0, 0)
  SetAmmo(amLandGun, 1, 0, 0, 0)
  SetAmmo(amSnowball, 7, 0, 0, 0)
  SetAmmo(amGirder, 0, 0, 0, 2)
  SetAmmo(amParachute, 0, 0, 0, 2)
  SetAmmo(amGrenade, 0, 0, 0, 3)
  SetAmmo(amShotgun, 0, 0, 0, 3)
  SetAmmo(amSwitch, 0, 0, 0, 8)
  SetAmmo(amRope, 0, 0, 0, 6)
  SetAmmo(amSkip, 9, 0, 0, 0)
end

function onNewTurn()
  if AnimInProgress() then
    SetTurnTimeLeft(MAX_TURN_TIME)
  elseif stage == wave1Stage then
    if GetHogClan(CurrentHedgehog) == GetTeamClan(weaklingsTeamName) and (not wave1EnemyTurn) then
      EndTurn(true)
      wave1EnemyTurn = true
    end
  elseif stage == cyborgStage then
    if CurrentHedgehog ~= dense then
      EndTurn(true)
    else
      SetTurnTimeLeft(MAX_TURN_TIME)
    end
  elseif stage == acceptedReturnStage then
    SwitchHog(dense)
    FollowGear(dense)
    SetTurnTimeLeft(MAX_TURN_TIME)
  end
end

function onGearDamage(gear, damage)
  if gear == cyborg and stage == cyborgStage then
    cyborgAttacked = true
  end
end

function onPrecise()
  if GameTime > 2500 and AnimInProgress() then
    SetAnimSkip(true)
    return
  end
end

function onGameResult(winner)
  if winner == GetTeamClan(nativesTeamName) then
    SendStat(siGameResult, loc("Mission succeeded!"))
  else
    SendStat(siGameResult, loc("Mission failed!"))
  end
end