share/hedgewars/Data/Missions/Campaign/A_Classic_Fairytale/shadow.lua
author Wuzzy <Wuzzy2@mail.ru>
Wed, 19 Dec 2018 20:34:07 +0100
changeset 14484 4e5280a9e782
parent 14406 6c21bd8547dd
child 14490 f37910a73c19
permissions -rw-r--r--
Lua: AddTeam / AddMissionTeam now return team index

--[[
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, hero 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
    - Hero needs to walk all the way back (infinite turn time)
    - Hero reached tree
    - Turn time starts
    - TBS
    - Stronglings defeated
    | Stronglings defeated with both hogs survived
        - Cut scene: acceptedSurvivedFinalAnim
    | Stronglings deafeated with Dense Cloud dead
        - Cut scene: acceptedDiedFinalAnim
    > Victory
| 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 hero
    - 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

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")}

---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

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 = {}

local grenadeHint = loc("Grenade hint: Set timer with the [Timer] controls, aim with [Up]/[Down].") .. "|" ..
                    loc("Hold [Attack] pressed to throw with more power.")
if INTERFACE == "touch" then
  grenadeHint = grenadeHint .. "|" ..
                loc("Change detonation timer: Tap the [Clock]") .. "|" ..
                loc("Attack: Tap the [Bomb]")
else
  grenadeHint = grenadeHint .. "|" ..
                loc("Set detonation timer: [1]-[5]") .. "|" ..
                loc("Attack: [Space]")
end

--------------------------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
  SwitchHog(dense)
  SetGearMessage(dense, 0)
  SetGearMessage(leaks, 0)
  SetTurnTimeLeft(TurnTime)
  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
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..."), 1, 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)
  RemoveEventFunc(CheckDenseDead)
  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!") .. "|" .. grenadeHint, 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)
  AnimSwitchHog(leaks)
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 = {leaks}})
  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()
	AddTeam(loc("Natives"), -2, "Bone", "Island", "HillBilly", "cm_birdy")
  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")

  AddTeam(loc("Weaklings"), -1, "skull", "Island", "Pirate","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","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", "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
  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 denseDead or GetHealth(dense) == 0 or leaksDead or GetHealth(leaks) == 0 then
    return
  end
  SetGearMessage(CurrentHedgehog, 0)
  AddAnim(stronglingsAnim)
  AddFunction({func = AfterStronglingsAnim, args = {}})
  stage = interWeakStage
  DismissTeam(loc("Weaklings"))
end

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

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

function CheckAccept()
  return GetX(dense) < 1300 and StoppedGear(dense)
end

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

function CheckConfront()
  return cyborgAttacked 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 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 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
  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!") .. "|" .. grenadeHint, 1, 12000)
  AddAmmo(dense, amSkip, 100)
  AddAmmo(dense, amSwitch, 100)
  AddAmmo(leaks, amSkip, 100)
  AddAmmo(leaks, amSwitch, 100)
  stage = duoStage
  RemoveEventFunc(CheckNeedGirder)
  RemoveEventFunc(CheckNeedWeapons)
  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 leaksDead or GetHealth(leaks) == 0 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(loc("Natives"))
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, 1, 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) == loc("Natives") then
    grenadeUsed = true
  elseif GetGearType(gear) == gtShotgunShot and GetHogTeamName(CurrentHedgehog) == loc("Natives") 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 == 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