local LD = require("design.LevelDesignLibrary")
local timers = require("level.timer")
local CCOS = require("camera.camera_oneshot")
local monitors = require("level.MonitorLibrary")
local uiCalls = require("ui.uicalls")
local actor = require("narrative.actor")
local LM = require("level.loadmonitor")
local player, thisLevel, playerPosition, son
local origin = engine.Vector.New(0, 0, 0)
local kratosActor, tLinks_GapRear, tLinks_GapRear2, tLinks_GapFront, board01, board02
local playerBurnedBramble = false
local playerUsedCrankAfterLatchTNF = false
local playerUsedCrankAfterBurnables = false
local haveWarnedFires = false
local concussionKillDelay = 0.75
local docksFightDone = false
local parentRefnode, lastShipPos, lastShipDir, shipRef, sailsRef, HelR_200, crank, shipEncounterScript, crankHalfStateReached, breakableMoment01Anim, breakableMoment02Anim, breakableMoment03Anim
local totalHarpoons = 0
local harpoonsRemoved = 0
local fireL, fireR, rFireState, lFireState
local fireL_FirstTime = true
local fireR_FirstTime = true
local burnablesLatch, burnablesCrank, debug_docksComplete, debug_skipDocks, debug_startHarpoonOne, debug_startHarpoonTwo, debug_startHarpoonThree, cameraOneShotSailsRaised, camTargetAnimGroupHarp01, camera_Harpoon01_Follow_010, camera_Harpoon01_Follow_020
local camHarpoon01Follow010Type = "PLYR_Harpoon01_Track_010"
local camHarpoon01Follow020Type = "PLYR_Harpoon01_Track_020"
local camTargetAnimGroupHarp02, camera_Harpoon02_Follow_010, camera_Harpoon02_Follow_020, camera_Harpoon02_Follow_030
local camHarpoon02Follow010Type = "PLYR_Harpoon02_Track_010"
local camHarpoon02Follow020Type = "PLYR_Harpoon02_Track_020"
local camHarpoon02Follow030Type = "PLYR_Harpoon02_Track_030"
local camera_Harpoon03_Follow_010, camera_Harpoon03_Follow_012, camera_Harpoon03_Follow_020, camera_IcebergHit_01, camera_IcebergHit_02
local bPlayerIdleCamera = false
local STATE_DOCKS_IDLE = 0
local STATE_HALF_CRANK_COMPLETE = 1
local STATE_SAILS_TNF_COMPLETE = 3
local STATE_CRASH_INTO_LOWER_DECK = 4
local STATE_FINAL_LIFTOFF = 5
local STATE_TELEPORT_ORIGIN = 5.5
local STATE_START_FIGHT_ONE = 6
local STATE_START_BIG_MOMENT_ONE = 7
local STATE_START_HARPOON_ONE = 8
local STATE_START_FIGHT_TWO = 9
local STATE_START_HARPOON_TWO = 10
local STATE_START_FIGHT_THREE = 11
local STATE_START_HARPOON_THREE = 12
local STATE_FINAL_TNF_WIN = 13
local state = STATE_DOCKS_IDLE
function OnScriptLoaded(level, obj)
  haveWarnedFires = false
  player = game.Player.FindPlayer()
  thisLevel = level
  son = game.AI.FindSon()
  shipEncounterScript = GameObjects.HelheimShipCombat.LuaObjectScript
  crank = GameObjects.WheelCrank_HelheimShip
  camTargetAnimGroupHarp01 = GameObjects.CameraTarget_Harpoon01
  camTargetAnimGroupHarp02 = GameObjects.CameraTarget_Harpoon02
  fireR = GameObjects.HeatStone_Helship_FrontR.Child
  fireL = GameObjects.HeatStone_Helship_BackL.Child
  GameObjects.FXFog:Hide()
  burnablesLatch = {
    fireR,
    GameObjects.Latch_Burn1,
    GameObjects.Latch_Burn2,
    GameObjects.Latch_Burn3,
    GameObjects.Latch_Burn4,
    GameObjects.Latch_Burn5
  }
  burnablesCrank = {
    fireL,
    GameObjects.Crank_Burn_1,
    GameObjects.Crank_Burn_2,
    GameObjects.Crank_Burn_3,
    GameObjects.Crank_Burn_4,
    GameObjects.Crank_Burn_5,
    GameObjects.Crank_Burn_6,
    GameObjects.Crank_Burn_7,
    GameObjects.Crank_Burn_8
  }
  breakableMoment01Anim = GameObjects.breakMoment01_Anim
  breakableMoment02Anim = GameObjects.breakMoment02_Anim
  breakableMoment03Anim = GameObjects.breakMoment03_Anim
  tLinks_GapFront = GameObjects.helShip_TraverseLinks_Break_Front
  tLinks_GapRear = GameObjects.helShip_TraverseLinks_Break_Rear
  tLinks_GapRear2 = GameObjects.helShip_TraverseLinks_Break_Rear2
end
function OnFirstStart(level, obj)
  state = STATE_DOCKS_IDLE
  SetState(state)
  VisOffRearFires()
  VisOffFrontFires()
  GameObjects.helShip_Collision_Guide01:HideCollision()
  GameObjects.helShip_Collision_Guide02:HideCollision()
  GameObjects.helShip_Collision_NavObstacle01:HideNavObstacle()
  GameObjects.helShip_Collision_NavObstacle02:HideNavObstacle()
  GameObjects.helShip_Collision_NavObstacleNoSon01:HideNavObstacle()
  GameObjects.helShip_Collision_NavObstacleNoSon02:HideNavObstacle()
  GameObjects.NoVaultBack:Hide()
  VisOffFX()
  GameObjects.BowEdges:Hide()
  GameObjects.SternEdges:Hide()
  GameObjects.Btr_110_RaiseSail_Start:HideEntityVolume()
  GameObjects.ent_110_RaiseSail_Reminder:HideEntityVolume()
  GameObjects.CollisionTumbleRail:HideCollision()
  GameObjects.SonNoJumpOffWalls:HideCollision()
  GameObjects.BoatCAON:HideEntityVolume()
  for _, child in pairs(breakableMoment02Anim.Children) do
    if child:GetName() == "floor_wall_01" or child:GetName() == "floor_wall_02" then
      child:Hide()
      child:HideBehaviors()
    end
  end
end
function SendEvent_ShipLoaded(wad, obj)
  local target = wad
  if type(wad) == "string" then
    wad = game.FindLevel(wad)
  end
  if wad then
    if obj ~= nil then
      target = target:FindSingleGameObject(obj)
    end
    if shipRef ~= nil then
      target:CallScript("ShipPassiveSpawned", shipRef)
    end
  end
end
function OnWadLoaded(level, newLevel)
  if newLevel.Name == "WAD_HelR200_BoatRide" then
    SetupZoneHandlers()
  end
end
function OnPassiveSpawned(level, passive)
  local passiveName = passive:GetName()
  if passiveName == "helheimship00" then
    shipRef = passive
  elseif passiveName == "helheimshipsail00" then
    sailsRef = passive
  end
  if sailsRef ~= nil and shipRef ~= nil then
    GameObjects.SNDhelheimShipDistGrp.LuaObjectScript.ShipPassiveSpawned(nil, nil, shipRef)
    GameObjects.SNDhelheimShip00Grp.LuaObjectScript.ShipPassiveSpawned(nil, nil, shipRef)
    local loadMonitor_HelR300_AI_CineJump = LM.CreateLoadMonitor()
    loadMonitor_HelR300_AI_CineJump:AddCallback({
      Wads = {
        "HelR300_AI_CineJump"
      },
      Functions = {
        function(wads)
          SendEvent_ShipLoaded(wads.HelR300_AI_CineJump, "Cine_FlyingBoatJump")
        end
      }
    })
    local loadMonitor_HelR100_Docks = LM.CreateLoadMonitor()
    loadMonitor_HelR100_Docks:AddCallback({
      Wads = {
        "HelR100_Docks"
      },
      Functions = {
        function(wads)
          SendEvent_ShipLoaded(wads.HelR100_Docks)
        end
      }
    })
    GameObjects.TNF_UpperDeckPush.LuaObjectScript.SetSynchObject(shipRef)
    GameObjects.TNF_HarpMoment01_HarpL1.LuaObjectScript.SetSynchObject(shipRef)
    GameObjects.TNF_HarpMoment02_HarpL1.LuaObjectScript.SetSynchObject(shipRef)
    GameObjects.TNF_HarpMoment02_HarpL2.LuaObjectScript.SetSynchObject(shipRef)
    GameObjects.TNF_HarpMoment02_HarpR2.LuaObjectScript.SetSynchObject(shipRef)
    GameObjects.TNF_HarpMoment02_HarpR1.LuaObjectScript.SetSynchObject(shipRef)
    GameObjects.TNF_HarpMoment03_HarpFront.LuaObjectScript.SetSynchObject(shipRef)
    GameObjects.TNF_UpperDeckPush.LuaObjectScript.AddSlavesToSynch({
      Slave = shipRef,
      Branch = "BRA_TNF_UpperDeckPush_Enter"
    })
    GameObjects.TNF_UpperDeckPush.LuaObjectScript.SetUseLinkJointForPrompt(true)
    GameObjects.TNF_HarpMoment01_HarpL1.LuaObjectScript.AddSlavesToSynch({
      Slave = shipRef,
      Branch = "BRA_TNF_ShipHarpMoment01_Enter"
    })
    GameObjects.TNF_HarpMoment02_HarpL1.LuaObjectScript.AddSlavesToSynch({
      Slave = shipRef,
      Branch = "BRA_TNF_ShipHarpMoment02_LFirst_Enter"
    })
    GameObjects.TNF_HarpMoment02_HarpL2.LuaObjectScript.AddSlavesToSynch({
      Slave = shipRef,
      Branch = "BRA_TNF_ShipHarpMoment02_LSecond_Enter"
    })
    GameObjects.TNF_HarpMoment02_HarpR2.LuaObjectScript.AddSlavesToSynch({
      Slave = shipRef,
      Branch = "BRA_TNF_ShipHarpMoment02_RSecond_Enter"
    })
    GameObjects.TNF_HarpMoment02_HarpR1.LuaObjectScript.AddSlavesToSynch({
      Slave = shipRef,
      Branch = "BRA_TNF_ShipHarpMoment02_RFirst_Enter"
    })
    GameObjects.TNF_HarpMoment03_HarpFront.LuaObjectScript.AddSlavesToSynch({
      Slave = shipRef,
      Branch = "BRA_TNF_ShipHarpMoment03_Front_Enter"
    })
    GameObjects.TNF_HarpMoment03_HarpFront.LuaObjectScript.RegisterCustomEvent(OnTNFWin_Harp03_Start)
    SoundOnStart()
    if lastShipPos ~= nil and lastShipDir ~= nil then
      shipRef:Warp(lastShipPos, lastShipDir)
    end
    shipRef:AddChild(sailsRef, shipRef:GetJointIndex("JOPelvis1"), 1)
    if state == STATE_DOCKS_IDLE then
      HideHarpoonMesh()
      sailsRef:HideJoint(sailsRef:GetJointIndex("sailGame"))
    end
    shipRef:AddMarkerPointTest("HelheimShip_Mrkr", shipRef:GetJointIndex("JOPelvis1"))
    if state >= STATE_FINAL_LIFTOFF and state < STATE_FINAL_TNF_WIN then
      fireR.LuaObjectScript.IncrementHeatLevel(100)
      fireL.LuaObjectScript.IncrementHeatLevel(100)
    end
  end
end
function OnStart(level, obj)
  parentRefnode = GameObjects.helheimShipRefnode
  local sailsParentRefnode = GameObjects.helheimShipSailRefnode
  if parentRefnode:GetPassive() ~= nil then
    OnPassiveSpawned(level, parentRefnode:GetPassive())
  end
  if sailsParentRefnode:GetPassive() ~= nil then
    OnPassiveSpawned(level, sailsParentRefnode:GetPassive())
  end
  if lastShipPos and lastShipDir then
    parentRefnode:SetWorldPosition(lastShipPos)
    parentRefnode:SetWorldFacing(lastShipDir)
  end
  if state == STATE_CRASH_INTO_LOWER_DECK then
    son:AddMarker("DisableSummon")
  end
  if state >= STATE_FINAL_LIFTOFF and state < STATE_FINAL_TNF_WIN then
    player:CallScript("LuaHook_DisableRevive", true)
  end
  debug_docksComplete = engine.VFSBool.New("DEBUG: Docks Complete")
  debug_skipDocks = engine.VFSBool.New("DEBUG: Skip Docks")
  debug_startHarpoonOne = engine.VFSBool.New("DEBUG: Start Harpoon One Moment")
  debug_startHarpoonTwo = engine.VFSBool.New("DEBUG: Start Harpoon Two Moment")
  debug_startHarpoonThree = engine.VFSBool.New("DEBUG: Start Harpoon Three Moment")
  playerPosition = player:GetWorldPosition()
  local deckTNFInteract = GameObjects.TNF_UpperDeckPush.LuaObjectScript.GetInteractZone()
  deckTNFInteract:SetHintXZRange(12)
  deckTNFInteract:SetXZRange(4)
  if FindHelR200() ~= nil then
    SetupZoneHandlers()
  end
  crank.LuaObjectScript.SetEaseEnabled(false)
  crank.LuaObjectScript.SetRewindTime(8)
  for i = 1, #burnablesLatch do
    burnablesLatch[i].LuaObjectScript.OnIgnite(function()
      Latch_Burn_Spread(i)
    end)
  end
  for i = 1, #burnablesCrank do
    burnablesCrank[i].LuaObjectScript.OnIgnite(function()
      Crank_Burn_Spread(i)
    end)
  end
end
function Latch_Burn_Spread(fireNumber)
  RightFireFullyLit()
  local delay = 0.1
  for i = fireNumber + 1, #burnablesLatch do
    burnablesLatch[i].LuaObjectScript.ClearOnIgniteCallbacks()
    LD.CallFunctionAfterDelay(function()
      burnablesLatch[i].LuaObjectScript.IgniteObject()
    end, delay)
    delay = delay + 0.2
  end
  local delayDown = 0.1
  for i = fireNumber - 1, 1, -1 do
    burnablesLatch[i].LuaObjectScript.ClearOnIgniteCallbacks()
    LD.CallFunctionAfterDelay(function()
      burnablesLatch[i].LuaObjectScript.IgniteObject()
    end, delayDown)
    delayDown = delayDown + 0.2
  end
end
function Crank_Burn_Spread(fireNumber)
  LeftFireFullyLit()
  local delay = 0.1
  for i = fireNumber + 1, #burnablesCrank do
    burnablesCrank[i].LuaObjectScript.ClearOnIgniteCallbacks()
    LD.CallFunctionAfterDelay(function()
      burnablesCrank[i].LuaObjectScript.IgniteObject()
    end, delay)
    delay = delay + 0.2
  end
  local delayDown = 0.1
  for i = fireNumber - 1, 1, -1 do
    burnablesCrank[i].LuaObjectScript.ClearOnIgniteCallbacks()
    LD.CallFunctionAfterDelay(function()
      burnablesCrank[i].LuaObjectScript.IgniteObject()
    end, delayDown)
    delayDown = delayDown + 0.2
  end
end
local respawnAttempt_Current = 0
local respawnAttempt_Total = 2
function ValidateRespawn(level)
  if respawnAttempt_Current < respawnAttempt_Total then
    respawnAttempt_Current = respawnAttempt_Current + level:GetUnitTime()
    if player:InsideZone(GameObjects.DeckZone) == false then
      player:Warp(GameObjects.CheckpointOverride_Fights:GetWorldPosition(), GameObjects.CheckpointOverride_Fights:GetWorldForward())
    end
  end
end
function OnUpdate(level, obj)
  if state >= STATE_FINAL_LIFTOFF and state < STATE_FINAL_TNF_WIN then
    ValidateRespawn(level)
  end
  CameraUpdates()
  if engine.IsDebug() then
    if debug_docksComplete.value then
      debug_docksComplete.value = false
      Debug_DocksComplete()
    elseif debug_skipDocks.value then
      debug_skipDocks.value = false
      Debug_SkipDocks()
    elseif debug_startHarpoonOne.value then
      debug_startHarpoonOne.value = false
      Debug_StartHarpoonOne()
    elseif debug_startHarpoonTwo.value then
      debug_startHarpoonTwo.value = false
      Debug_StartHarpoonTwo()
    elseif debug_startHarpoonThree.value then
      debug_startHarpoonThree.value = false
      Debug_StartHarpoonThree()
    end
  end
  UpdateTraverseLinkJumpHack()
end
local plyrIsJumping = false
function UpdateTraverseLinkJumpHack()
  if state >= STATE_FINAL_LIFTOFF and state < STATE_FINAL_TNF_WIN then
    if PlayerIsJumping() then
      plyrIsJumping = true
      TraversalActive_SlowShipAnims()
    elseif plyrIsJumping then
      plyrIsJumping = false
      TraversalComplete_ResumeShipAnims()
    end
  end
end
function TraversalActive_SlowShipAnims()
  shipRef:SetTimeScaleMultiplier(0.2)
  sailsRef:SetTimeScaleMultiplier(0.2)
end
function TraversalComplete_ResumeShipAnims()
  shipRef:SetTimeScaleMultiplier(1)
  sailsRef:SetTimeScaleMultiplier(1)
end
function PlayerIsJumping()
  if player:IsPlayingMove("MOV_GapJumpRun") then
    return true
  end
  if player:IsPlayingMove("MOV_GapJumpIdle") then
    return true
  end
  if player:IsPlayingMove("MOV_GapJumpSprint") then
    return true
  end
  return false
end
function CameraUpdates()
  playerPosition = player.WorldPosition
  if cameraOneShotSailsRaised ~= nil then
    cameraOneShotSailsRaised:Update()
  end
  if camera_Harpoon01_Follow_010 ~= nil then
    camera_Harpoon01_Follow_010:Update()
  end
  if camera_Harpoon01_Follow_020 ~= nil then
    camera_Harpoon01_Follow_020:Update()
  end
  if camera_Harpoon02_Follow_010 ~= nil then
    camera_Harpoon02_Follow_010:Update()
  end
  if camera_Harpoon02_Follow_020 ~= nil then
    camera_Harpoon02_Follow_020:Update()
  end
  if camera_Harpoon02_Follow_030 ~= nil then
    camera_Harpoon02_Follow_030:Update()
  end
  if camera_Harpoon03_Follow_010 ~= nil then
    camera_Harpoon03_Follow_010:Update()
  end
  if camera_Harpoon03_Follow_012 ~= nil then
    camera_Harpoon03_Follow_012:Update()
  end
  if camera_Harpoon03_Follow_020 ~= nil then
    camera_Harpoon03_Follow_020:Update()
  end
  if camera_IcebergHit_01 ~= nil then
    camera_IcebergHit_01:Update()
  end
  if camera_IcebergHit_02 ~= nil then
    camera_IcebergHit_02:Update()
  end
  if bPlayerIdleCamera == true then
    game.Camera.SubmitCameraByName("ENV_HelheimSpindleCrank_Flyaway")
  end
end
function SetState(newState)
  state = newState
  if state == STATE_DOCKS_IDLE then
    crankHalfStateReached = false
    game.Level.SetVariable("Hel_MapState", 1)
    GameObjects.BoatLatch_Helheim_TEMP.LuaObjectScript.DisableInteract()
    GameObjects.BoatLatch_Helheim_TEMP.Child:StartAnim("envHelShipLatchClosedtoIdle01")
    GameObjects.BoatLatch_Helheim_TEMP.Child:PauseAnim()
    game.GameObject.AnimSync(GameObjects.BoatLatch_Helheim_TEMP.Child, GameObjects.SailsAnimDriver, 4.5)
    crank.LuaObjectScript.SetLockWhenFullyCranked(false)
    crank.LuaObjectScript.SetMaxStopCycle(0)
    crank.LuaObjectScript.Lock()
    HideAllGapTraverseLinks()
    GameObjects.helShip_Collision_Guide01:HideCollision()
    GameObjects.helShip_Collision_Guide02:HideCollision()
    GameObjects.helShip_Collision_NavObstacle01:HideNavObstacle()
    GameObjects.helShip_Collision_NavObstacle02:HideNavObstacle()
    GameObjects.helShip_Collision_NavObstacleNoSon01:HideNavObstacle()
    GameObjects.helShip_Collision_NavObstacleNoSon02:HideNavObstacle()
  elseif state == STATE_HALF_CRANK_COMPLETE then
    game.Level.SetVariable("Hel_MapState", 2)
    GameObjects.SailFolded_Static:Hide()
    GameObjects.CollidableBox_Sails:HideCollision()
    bPlayerIdleCamera = true
    TriggerMoveEvent_ShipAndSails("kLEShipForwardIceberg")
    Btr_ShipStartsMoving()
    game.GameObject.AnimSync(GameObjects.BoatLatch_Helheim_TEMP.Child)
    PlaySoundIcebergGrind()
    LD.CallFunctionAfterDelay(function()
      local hitIcebergMonitor = monitors.CreateAnimFrameMonitor(shipRef)
      hitIcebergMonitor:OnFrameForward(shipRef.AnimLengthFrames - 20, function()
        Btr_ShipStuckIceberg(hitIcebergMonitor)
        StaggerAndSyncIcebergHit()
        timers.StartLevelTimer(0, StartDynamicCamIcebergHit_010)
        timers.StartLevelTimer(2, StartDynamicCamIcebergHit_020)
        GameObjects.BoatLatch_Helheim_TEMP.LuaObjectScript.EnableInteract()
        bPlayerIdleCamera = false
        local hel100 = game.FindLevel("HelR100_Docks")
        if hel100 ~= nil then
          hel100:CallScript("BreakIceBerg_HelR100")
        end
        GameObjects.Reaction_Jotunn.LuaObjectScript.Trigger()
        ShipStoppedRTPC(true)
      end)
    end, 1)
    HideAllGapTraverseLinks()
    local hel100 = game.FindLevel("HelR100_Docks")
    if hel100 ~= nil then
      hel100:CallScript("HideAllDocksCA")
    end
  elseif state == STATE_SAILS_TNF_COMPLETE then
    LD.CallFunctionAfterDelay(function()
      GameObjects.BoatLatch_Helheim_TEMP:Hide()
      GameObjects.BoatLatch_Helheim_TEMP:HideCollision()
    end, 7)
    Btr_BreakLatch_Success()
    crank.LuaObjectScript.SetMinStopCycle(6)
    crank.LuaObjectScript.SetMaxStopCycle(9)
    crank.LuaObjectScript.SetDetachedBehavior_Rewind()
    crank.LuaObjectScript.SetLockWhenFullyCranked(true)
    crank.LuaObjectScript.Enable()
  elseif state == STATE_CRASH_INTO_LOWER_DECK then
    game.Level.SetVariable("Hel_MapState", 3)
    GameObjects.ContextAction_Son_ObserveForward_Latch.LuaObjectScript.Disable()
    LD.CallFunctionAfterDelay(function()
      GameObjects.ContextAction_Son_WarmHands.LuaObjectScript:Enable()
    end, 20)
    local helR100 = game.FindLevel("HelR100_Docks")
    if helR100 ~= nil then
      helR100:CallScript("AnimateUpperBridgeOnShipCrankComplete")
    end
    TriggerMoveEvent_ShipAndSails("kLEShipHitLowerDeck")
    LD.CallFunctionAfterDelay(function()
      GameObjects.Reaction_StartFlying.LuaObjectScript.Trigger()
    end, 3)
    LD.CallFunctionAfterDelay(function()
      GameObjects.Reaction_StartFlying1.LuaObjectScript.Trigger()
    end, 10)
    Btr_SailsFull()
    GameObjects.FX_HelShip_Hull_Water:Show()
    GameObjects.FX_HelShip_Hull_Water:PlayAnimToEnd()
    LD.CallFunctionAfterDelay(function()
      LD.BreakObject(GameObjects.HelSmallWeaponRack40)
    end, 18)
    LD.CallFunctionAfterDelay(function()
      GameObjects.FX_HelShip_Hull_Water:HideParticleEmitter()
    end, 30)
    LD.CallFunctionAfterDelay(function()
      GameObjects.FX_HelShip_Hull_Water:Hide()
    end, 32)
    ShipStoppedRTPC(false)
    SoundBoatLiftOff()
    LD.CallFunctionAfterDelay(function()
      local hitPlatform01Monitor = monitors.CreateAnimFrameMonitor(shipRef)
      hitPlatform01Monitor:OnFrameForward(shipRef.AnimLengthFrames * 0.832, function()
        hitPlatform01Monitor:Stop()
        ShipStoppedRTPC(true)
        local hel100 = game.FindLevel("HelR100_Docks")
        if hel100 ~= nil then
          hel100:CallScript("PlaySound_ShipHitPlatform01")
        end
        hitPlatform01Monitor = nil
      end)
    end, 1)
    HideAllGapTraverseLinks()
  elseif state == STATE_FINAL_LIFTOFF then
    game.Level.SetVariable("Hel_MapState", 4)
    PlayMusicShipLiftoff()
    VisOnFX()
    GameObjects.FX_HelShip_Hull_Water:Hide()
    ShipStoppedRTPC(false)
    JustSonShipCombat()
    HideAllInitialTraverseLinks()
    HideAllGapTraverseLinks()
  elseif state == STATE_START_FIGHT_ONE then
    PlayMusicFight1()
    shipEncounterScript.StartFightOne()
  elseif state == STATE_START_BIG_MOMENT_ONE then
    LD.CallFunctionAfterDelay(AddScreenShake, 4)
  elseif state == STATE_START_HARPOON_ONE then
    PlayMusicHarpoon1()
    LD.CallFunctionAfterDelay(function()
      game.Audio.PlayBanter("170_HarpoonNetwork_Portside")
    end, 7)
    LD.CallFunctionAfterDelay(function()
      game.Audio.PlayBanter("170_HarpoonNetwork_Warning")
    end, 9.5)
    shipRef:ShowJoint(shipRef:GetJointIndex("JOHarpoon00"))
    shipRef:ShowJoint(shipRef:GetJointIndex("JOHarpoon01"))
    LD.CallFunctionAfterDelay(function()
      shipRef:HideJoint(shipRef:GetJointIndex("JOHarpoon00"))
    end, 10)
    haveWarnedFires = false
    GameObjects.helShip_Collision_NavObstacleNoSon01:ShowNavObstacle()
    GameObjects.helShip_Collision_NavObstacle01:ShowNavObstacle()
    LD.CallFunctionAfterDelay(function()
      GameObjects.helShip_Collision_NavObstacleNoSon01:HideNavObstacle()
    end, 8)
    camTargetAnimGroupHarp01:JumpAnimToFrame(0)
    camTargetAnimGroupHarp01:PauseAnim()
    SetDriversForWarp01AndPlayKratos_010()
    timers.StartLevelTimer(1, StartDynamicCamHarpoon01_010)
    timers.StartLevelTimer(3, CamPlayHarpoonTarget01)
    LD.CallFunctionAfterDelay(function()
      shipEncounterScript.Temp_StaggerNearbyEnemies()
      TriggerMoveEvent_ShipAndSails("kLEHarpoonBreak01")
      DisableFireInteraction()
      ResetHarpoons(1)
      ShipStoppedRTPC(true)
      for _, child in pairs(breakableMoment01Anim.Children) do
        child:JumpAnimToFrame(0)
        child:PlayAnimToEnd()
      end
      FindHelR200():CallScript("AnimateWorld_Pause")
      VisOffFX()
      LD.CallFunctionAfterDelay(AddScreenShake, 4)
    end, 0.3)
    LD.CallFunctionAfterDelay(function()
      local harpoonAnimMonitor = monitors.CreateAnimFrameMonitor(shipRef)
      harpoonAnimMonitor:OnFrame(56, function()
        HarpoonConcussion_ClearEnemies("concussionJ_01")
        LD.CallFunctionAfterDelay(function()
          shipEncounterScript.StartHarpoonFightOne()
        end, concussionKillDelay)
      end)
      harpoonAnimMonitor:OnFrame(35, function()
        GameObjects.helShip_Collision_Break01:HideCollision()
        GameObjects.helShip_Collision_Guide01:ShowCollision()
        tLinks_GapFront:ShowTraverseLink()
        tLinks_GapRear:HideTraverseLink()
        HideAllInitialTraverseLinks()
      end)
      harpoonAnimMonitor:OnFrame(shipRef.AnimLengthFrames, function()
        GameObjects.helShip_Collision_NavObstacleNoSon01:HideNavObstacle()
        GameObjects.TNF_HarpMoment01_HarpL1.LuaObjectScript.Enable()
        GameObjects.TNF_HarpMoment01_HarpL1.LuaObjectScript.OverrideHintXZRange(50)
        harpoonAnimMonitor:Stop()
        harpoonAnimMonitor:Terminate()
        harpoonAnimMonitor = nil
      end)
    end, 0.4)
  elseif state == STATE_START_FIGHT_TWO then
    PlayMusicFight2()
    shipEncounterScript.StartFightTwo()
  elseif state == STATE_START_HARPOON_TWO then
    PlayMusicHarpoon2()
    haveWarnedFires = false
    shipEncounterScript.Temp_StaggerNearbyEnemies()
    shipRef:ShowJoint(shipRef:GetJointIndex("JOHarpoon00"))
    shipRef:ShowJoint(shipRef:GetJointIndex("JOHarpoon01"))
    shipRef:ShowJoint(shipRef:GetJointIndex("JOHarpoon02"))
    LD.CallFunctionAfterDelay(function()
      shipRef:HideJoint(shipRef:GetJointIndex("JOHarpoon00"))
    end, 10)
    camTargetAnimGroupHarp02:JumpAnimToFrame(0)
    camTargetAnimGroupHarp02:PauseAnim()
    SetDriversForWarp02AndPlayKratos_020()
    timers.StartLevelTimer(0.5, StartDynamicCamHarpoon02_010)
    timers.StartLevelTimer(2.1, StartDynamicCamHarpoon02_020)
    timers.StartLevelTimer(2, CamPlayHarpoonTarget02)
    TriggerMoveEvent_ShipAndSails("kLEHarpoonBreak02")
    GameObjects.helShip_Collision_NavObstacle02:ShowNavObstacle()
    GameObjects.helShip_Collision_NavObstacleNoSon02:ShowNavObstacle()
    LD.CallFunctionAfterDelay(function()
      GameObjects.helShip_Collision_NavObstacleNoSon02:HideNavObstacle()
    end, 8)
    LD.CallFunctionAfterDelay(function()
      local harpoonAnimMonitor = monitors.CreateAnimFrameMonitor(shipRef)
      harpoonAnimMonitor:OnFrame(15, function()
        HarpoonConcussion_ClearEnemies("concussionJ_02")
        LD.CallFunctionAfterDelay(function()
          shipEncounterScript.StartHarpoonFightTwo()
          PlaySoundWitchSinging()
          LD.CallFunctionAfterDelay(function()
            for _, child in pairs(breakableMoment02Anim.Children) do
              child:ShowBehaviors()
            end
          end, 3)
        end, concussionKillDelay)
      end)
      harpoonAnimMonitor:OnFrame(35, function()
        GameObjects.helShip_Collision_Break02:HideCollision()
        GameObjects.helShip_Collision_Guide02:ShowCollision()
        tLinks_GapRear:ShowTraverseLink()
        tLinks_GapFront:ShowTraverseLink()
        HideAllInitialTraverseLinks()
      end)
      harpoonAnimMonitor:OnFrame(shipRef.AnimLengthFrames, function()
        GameObjects.helShip_Collision_NavObstacleNoSon02:HideNavObstacle()
        GameObjects.TNF_HarpMoment02_HarpL1.LuaObjectScript.Enable()
        GameObjects.TNF_HarpMoment02_HarpR1.LuaObjectScript.Enable()
        GameObjects.TNF_HarpMoment02_HarpL1.LuaObjectScript.OverrideHintXZRange(50)
        GameObjects.TNF_HarpMoment02_HarpR1.LuaObjectScript.OverrideHintXZRange(50)
        harpoonAnimMonitor:Stop()
        harpoonAnimMonitor:Terminate()
        harpoonAnimMonitor = nil
      end)
    end, 0.1)
    DisableFireInteraction()
    ResetHarpoons(2)
    ShipStoppedRTPC(true)
    for _, child in pairs(breakableMoment02Anim.Children) do
      child:JumpAnimToFrame(0)
      child:PlayAnimToEnd()
      if child:GetName() == "floor_wall_01" or child:GetName() == "floor_wall_02" then
        LD.CallFunctionAfterDelay(function()
          child:Show()
          child:ShowCollision()
        end, 1)
      end
    end
    FindHelR200():CallScript("AnimateWorld_Pause")
    VisOffFX()
    LD.SetCurrentRealm("Helheim")
    LD.SetSelectedRealm("Helheim")
  elseif state == STATE_START_FIGHT_THREE then
    PlayMusicFight3()
    shipEncounterScript.StartFightThree()
    FindHelR200():CallScript("ShowFinalMonolith")
    TurnFogOn()
    GameObjects.FX_HelR100:PlayAnimToFrame(1, 0.05)
    LD.CallFunctionAfterDelay(function()
      game.World.StoreCheckpoint({
        OverrideObject = GameObjects.CheckpointOverride_Reload.Child
      })
    end, 1)
    FindHelR200():CallScript("HideShips")
  elseif state == STATE_START_HARPOON_THREE then
    shipEncounterScript.Temp_StaggerNearbyEnemies()
    HarpoonConcussion_ClearEnemies("concussionJ_03")
    shipEncounterScript.StartHarpoonFightThree()
    game.Audio.PlayBanter("190_MoreHarpoons")
    LD.CallFunctionAfterDelay(function()
      PlayBowRipIdleSound()
    end, 7)
    LD.CallFunctionAfterDelay(function()
      GameObjects.Reaction_Jotunn.LuaObjectScript.Trigger()
    end, 10)
    DisablePlayerInput()
    LD.CallFunctionAfterDelay(function()
      EnablePlayerInput()
    end, 6.5)
    SetDriversForWarp03AndPlayKratos_030()
    timers.StartLevelTimer(0.5, StartDynamicCamHarpoon03_010)
    timers.StartLevelTimer(3, StartDynamicCamHarpoon03_012)
    timers.StartLevelTimer(6, StartDynamicCamHarpoon03_020)
    shipRef:ShowJoint(shipRef:GetJointIndex("JOHarpoon00"))
    shipRef:ShowJoint(shipRef:GetJointIndex("JOHarpoon01"))
    shipRef:ShowJoint(shipRef:GetJointIndex("JOHarpoon02"))
    DisableFireInteraction()
    ResetHarpoons(1)
    ShipStoppedRTPC(true)
    FindHelR200():CallScript("AnimateWorld_Pause")
    GameObjects.State_2_TumbleObjs:PlayAnimToEnd()
    for _, child in pairs(breakableMoment03Anim.Children) do
      child:JumpAnimToFrame(0)
      child:PlayAnimToEnd()
    end
    GameObjects.BowBreak_Collision:ShowCollision()
    VisOffFX()
    AddScreenShake()
    LD.CallFunctionAfterDelay(function()
      AddScreenShake()
    end, 2)
  end
end
function HarpoonConcussion_ClearEnemies(locJointIndex)
  local concussionParams = {
    Tweak = "CNC_HELHEIM_SHIP_EXPLOSION_KNOCKBACK",
    WorldLocation = shipRef:GetWorldJointPosition(shipRef:GetJointIndex(locJointIndex)),
    Creature = player,
    EnemyId = player:GetID()
  }
  game.Combat.PlayConcussion(concussionParams)
  LD.CallFunctionAfterDelay(function()
    local concussionParams2 = {
      Tweak = "CNC_HELHEIM_SHIP_EXPLOSION_DAMAGE",
      WorldLocation = shipRef:GetWorldJointPosition(shipRef:GetJointIndex(locJointIndex)),
      Creature = player,
      EnemyId = player:GetID()
    }
    game.Combat.PlayConcussion(concussionParams2)
  end, concussionKillDelay)
end
function MakeBowTNFAvailable()
  game.Audio.PlayBanter("190_MoreHarpoons01")
  GameObjects.TNF_HarpMoment03_HarpFront.LuaObjectScript.Enable()
  GameObjects.TNF_HarpMoment03_HarpFront.LuaObjectScript.OverrideHintXZRange(50)
end
function Checkpoint()
  game.World.StoreCheckpoint()
end
function LatchInteract_Stage01()
  TriggerMoveEvent_ShipAndSails("kLEAxeHit")
  Btr_BreakLatch_Attempt()
end
function LatchInteract_Stage02()
  TriggerMoveEvent_ShipAndSails("kLEAxeHit")
end
function LatchInteract_Stage03()
  TriggerMoveEvent_ShipAndSails("kLEAxeHit")
end
function LatchInteract_Stage04()
  TriggerMoveEvent_ShipAndSails("kLEFinalHit")
  player:TriggerMoveEvent("kLEFinalHit")
  SetState(STATE_SAILS_TNF_COMPLETE)
  uiCalls.UI_Event_TurnOffDesignerMessage()
end
function SetState_LatchRelease()
end
function TriggerUpwardDeckMovement()
  TriggerMoveEvent_ShipAndSails("kLEShipHitUpperDeck")
  GameObjects.ContextAction_Son_WarmHands.LuaObjectScript.Disable()
  GameObjects.CollisionTurretGuide:ShowCollision()
  LD.CallFunctionAfterDelay(function()
    GameObjects.ContextAction_Son_ShootFromPoint.LuaObjectScript.Enable()
    GameObjects.ContextAction_Son_StandAtPoint.LuaObjectScript.Enable()
    GameObjects.CollisionTurretRail:HideCollision()
    GameObjects.CollisionTumbleRail:HideCollision()
  end, 1)
  GameObjects.FX_HelShip_Hull_Water:Show()
  GameObjects.FX_HelShip_Hull_Water:PlayAnimToEnd()
  LD.CallFunctionAfterDelay(function()
    GameObjects.FX_HelShip_Hull_Water:HideParticleEmitter()
  end, 8)
  LD.CallFunctionAfterDelay(function()
    GameObjects.FX_HelShip_Hull_Water:Hide()
  end, 10)
  PlaySoundShipFreedPlatform01()
  ShipStoppedRTPC(false)
  LD.CallFunctionAfterDelay(function()
    local hitPlatform02Monitor = monitors.CreateAnimFrameMonitor(shipRef)
    hitPlatform02Monitor:OnFrameForward(shipRef.AnimLengthFrames * 0.832, function()
      hitPlatform02Monitor:Stop()
      ShipStoppedRTPC(true)
      local hel100 = game.FindLevel("HelR100_Docks")
      if hel100 ~= nil then
        hel100:CallScript("PlaySound_ShipHitPlatform02")
      end
      hitPlatform02Monitor = nil
    end)
  end, 1)
end
function EnableUpperDeckTNF()
  GameObjects.TNF_UpperDeckPush.LuaObjectScript.Enable()
end
function SetState_FinalLift()
  SetState(STATE_FINAL_LIFTOFF)
  LD.CallFunctionAfterDelay(function()
    local helr300 = game.FindLevel("HelR300_HelShip")
    helr300:CallScript("ZeusVoiceFX")
  end, 4)
  LD.CallFunctionAfterDelay(function()
  end, 6)
  game.Audio.PlayBanter("134_KratosHauntsForeshadow02")
end
function UpperDeckTNFEnter()
  player:CallScript("DisableColdIdle")
  son:CallScript("ClearThisBehaviorContextIfActive", "COLD_BEHAVIOR_CONTEXT_CONFIG")
  game.Compass.SetDesignerForcedHide(true)
  local helr300 = game.FindLevel("HelR300_HelShip")
  helr300:CallScript("FirstFog")
end
function UpperDeckTNFWin()
  LD.CallFunctionAfterDelay(function()
    TurnFogOn()
    GameObjects.FX_HelR100:PlayAnimToFrame(15, 0.03)
  end, 2)
  print("fog down")
  GameObjects.FXFog:Show()
  LD.CallFunctionAfterDelay(function()
    GameObjects.FXFog:PlayAnimCycle()
  end, 2)
  LD.CallFunctionAfterDelay(function()
    GameObjects.FXFog:JumpAnimToFrame(1)
    GameObjects.FXFog:PlayAnimCycle()
  end, 5)
  LD.CallFunctionAfterDelay(function()
    TurnFogOn()
    GameObjects.FX_HelR100:PlayAnimToFrame(1, -0.01)
  end, 10)
  LD.CallFunctionAfterDelay(function()
    LD.HideFX(GameObjects.FXFog)
  end, 3)
  GameObjects.CollisionTurretRail:ShowCollision()
  GameObjects.CollisionTumbleRail:ShowCollision()
  GameObjects.SonNoJumpOffWalls:ShowCollision()
  GameObjects.LowWalls:HideCollision()
  son:RemoveMarker("DisableSummon")
  LD.CallFunctionAfterDelay(function()
    local finalAnimMonitor = monitors.CreateAnimFrameMonitor(shipRef)
    finalAnimMonitor:OnFrame(300, FlashFunction)
    finalAnimMonitor:OnFrame(310, TeleportShip_Origin)
    finalAnimMonitor:OnFrame(shipRef.AnimLengthFrames - 30, CompleteObjective300)
    finalAnimMonitor:OnFrame(shipRef.AnimLengthFrames, function()
      StartSequence(finalAnimMonitor)
    end)
    game.UI.LoadCheck("HelR200_BoatRide")
  end, 1)
end
function CompleteObjective300()
  LD.CompleteQuest("Quest_Helheim_Objective300")
end
function FindHelR200()
  if HelR_200 == nil then
    HelR_200 = game.FindLevel("HelR200_BoatRide")
  end
  return HelR_200
end
function ShipHitUpperDeck(monitor)
  if monitor ~= nil then
    monitor:Stop()
    monitor = nil
  end
  local hel100 = game.FindLevel("HelR100_Docks")
  if hel100 ~= nil then
    hel100:CallScript("ShipHitUpperDeck")
  end
end
function TeleportShip_Origin()
  SetState(STATE_TELEPORT_ORIGIN)
  player:CallScript("LuaHook_DisableRevive", true)
  local sonPosRelativeToShip
  if son ~= nil then
    sonPosRelativeToShip = LD.GetPosInLocalSpaceOfObject(son.WorldPosition, GameObjects.WarpReferenceObj)
  end
  local playerPosRelativeToShip = LD.GetPosInLocalSpaceOfObject(player.WorldPosition, GameObjects.WarpReferenceObj)
  parentRefnode:SetWorldPosition(GameObjects.WarpToOrigin.WorldPosition)
  shipRef:Warp(origin, GameObjects.WarpToOrigin:GetWorldForward())
  local playerProjectedPosition = LD.ProjectPositionOntoObject(playerPosRelativeToShip, GameObjects.WarpToOrigin)
  player:Warp(playerProjectedPosition, player:GetWorldForward())
  local sonProjectedPosition
  if son ~= nil then
    sonProjectedPosition = LD.ProjectPositionOntoObject(sonPosRelativeToShip, GameObjects.WarpToOrigin)
    son:Warp(sonProjectedPosition, son:GetWorldForward())
  end
  SetupZoneHandlers()
end
function FlashFunction()
  GameObjects.FX_Flash:PlayAnimToFrame(40)
end
function FlashFinal()
  GameObjects.FX_Flash:JumpAnimToFrame(1)
  GameObjects.FX_Flash:PlayAnimToFrame(60)
end
function StartSequence(monitor)
  if monitor ~= nil then
    monitor:Stop()
    monitor:Terminate()
    monitor = nil
  end
  FindHelR200()
  HelR_200:CallScript("AnimateWorld_JumpToFrame", 0)
  HelR_200:CallScript("AnimateWorld_SlowdownLong")
  LD.CallFunctionAfterDelay(function()
    local bookmarks = require("design.Bookmarks")
    local tableEntry = bookmarks["BOOKMARK_" .. "28_HelheimR_040_StartFlight"]
    tableEntry.OverrideObject = GameObjects.CheckpointOverride_Reload
    game.World.StoreCheckpointAndBookmark(tableEntry)
  end, 0.25)
end
function SetupZoneHandlers()
  FindHelR200()
  local zones = {
    HelR_200:FindSingleGameObject("NoFailZones"),
    HelR_200:FindSingleGameObject("FightOneZone"),
    HelR_200:FindSingleGameObject("BigMomentOneZone"),
    HelR_200:FindSingleGameObject("HarpoonOneZone"),
    HelR_200:FindSingleGameObject("FightTwoZone"),
    HelR_200:FindSingleGameObject("BigMomentTwoZone"),
    HelR_200:FindSingleGameObject("HarpoonTwoZone"),
    HelR_200:FindSingleGameObject("FightThreeZone"),
    HelR_200:FindSingleGameObject("HarpoonThreeZone")
  }
  for _, zone in pairs(zones) do
    game.SubObject.SetEntityZoneHandler(GameObjects.HelheimShipScript, zone)
  end
end
function TeleportShip_FinalPhase()
  player:CallScript("LuaHook_DisableRevive", false)
  FindHelR200()
  HelR_200:CallScript("AnimateWorld_Pause")
  HelR_200:CallScript("Teleport_Monolith")
  game.Compass.SetDesignerForcedHide(false)
  local sonPosRelativeToShip = LD.GetPosInLocalSpaceOfObject(son.WorldPosition, GameObjects.WarpReferenceObj)
  local playerPosRelativeToShip = LD.GetPosInLocalSpaceOfObject(player.WorldPosition, GameObjects.WarpReferenceObj)
  parentRefnode:SetWorldPosition(GameObjects.FlyingBoatJump_Warp.WorldPosition)
  shipRef:Warp(GameObjects.FlyingBoatJump_Warp.WorldPosition, GameObjects.FlyingBoatJump_Warp:GetWorldForward())
  local heroPosCine = engine.Vector.New(396.25, 35.17, 50.57)
  player:Warp(heroPosCine, player:GetWorldForward())
  local sonProjectedPosition = LD.ProjectPositionOntoObject(sonPosRelativeToShip, GameObjects.WarpLocation_FinalBattle)
  if son ~= nil then
    son:Warp(sonProjectedPosition, son:GetWorldForward())
  end
  AddScreenShake()
  LD.CallFunctionAfterDelay(function()
    AddScreenShake()
  end, 2)
  VisONRearFires()
  VisONFrontFires()
  game.UI.LoadCheck("Cal170_Library1")
  game.UI.LoadCheck("HelR300_AI_CineJump")
  game.FindLevel("HelR300_AI_CineJump"):GetGameObject("Cine_FlyingBoatJump"):CallScript("SetupCineSequence")
end
function OnMarkerExitZone(level, obj, zoneObject, markerObject, markerId)
  if ShipExitedZone("NoFailZones", markerId, zoneObject) then
    EnableFireInteraction()
  end
end
function OnMarkerEnterZone(level, obj, zoneObject, markerObject, markerId)
  FindHelR200()
  if ShipEnteredZone("NoFailZones", markerId, zoneObject) then
    DisableFireInteraction()
  end
  if ShipEnteredZone("FightOneZone", markerId, zoneObject) then
    if state >= STATE_START_FIGHT_ONE then
      return
    end
    SetState(STATE_START_FIGHT_ONE)
    TriggerMoveEvent_ShipAndSails("kLESwellR")
    print("fog down")
    TurnFogOn()
    LD.CallFunctionAfterDelay(function()
      GameObjects.FX_HelR100:PlayAnimToFrame(2, -0.01)
    end, 2)
    game.World.StoreCheckpoint({
      OverrideObject = GameObjects.CheckpointOverride_Reload.Child
    })
  elseif ShipEnteredZone("BigMomentOneZone", markerId, zoneObject) then
    if state >= STATE_START_BIG_MOMENT_ONE then
      return
    end
    print("enter big moment zone 1")
    SetState(STATE_START_BIG_MOMENT_ONE)
    LD.CallFunctionAfterDelay(function()
      TriggerMoveEvent_ShipAndSails("kLESwellL")
    end, 5)
    if HelR_200 ~= nil then
      HelR_200:CallScript("ShowGhosts")
    end
    print("fog off")
    TurnFogOn()
    GameObjects.FX_HelR100:PlayAnimToFrame(1, -0.05)
    LD.BreakObject(GameObjects.HelSmallWeaponRack38)
    game.World.StoreCheckpoint({
      OverrideObject = GameObjects.CheckpointOverride_Reload.Child
    })
  elseif ShipEnteredZone("HarpoonOneZone", markerId, zoneObject) then
    print("enter harpoon zone 1")
    if state >= STATE_START_HARPOON_ONE then
      return
    end
    SetState(STATE_START_HARPOON_ONE)
    if HelR_200 ~= nil then
      HelR_200:CallScript("GoGhosts")
    end
    print("fog up")
    TurnFogOn()
    GameObjects.FX_HelR100:PlayAnimToFrame(1, 0.25)
    GameObjects.BowEdges:Show()
    LD.CallFunctionAfterDelay(function()
      LD.BreakObject(GameObjects.HelSmallWeaponRack36)
    end, 3.9)
    LD.CallFunctionAfterDelay(function()
      LD.BreakObject(GameObjects.HelSmallWeaponRack37)
      LD.BreakObject(GameObjects.xpl300_barrel_02_break20)
    end, 5.5)
  elseif ShipEnteredZone("FightTwoZone", markerId, zoneObject) then
    print("enter fight zone 2")
    if state >= STATE_START_FIGHT_TWO then
      return
    end
    SetState(STATE_START_FIGHT_TWO)
    if HelR_200 ~= nil then
      HelR_200:CallScript("HideGhosts")
    end
    game.World.StoreCheckpoint({
      OverrideObject = GameObjects.CheckpointOverride_Fights.Child
    })
  elseif ShipEnteredZone("HarpoonTwoZone", markerId, zoneObject) then
    print("enter harpoon zone 2")
    if state >= STATE_START_HARPOON_TWO then
      return
    end
    SetState(STATE_START_HARPOON_TWO)
    LD.CallFunctionAfterDelay(function()
      LD.BreakObject(GameObjects.HelSmallWeaponRack19)
      LD.BreakObject(GameObjects.crate_1_5m3)
      LD.BreakObject(GameObjects.crate_1_5m5)
      LD.BreakObject(GameObjects.crate_1_5m6)
      LD.BreakObject(GameObjects.crate_1_5m7)
      LD.BreakObject(GameObjects.crate_1_5m8)
    end, 2)
    LD.CallFunctionAfterDelay(function()
      LD.BreakObject(GameObjects.HelSmallWeaponRack38)
      LD.BreakObject(GameObjects.xpl300_barrel_02_break18)
    end, 2.5)
    LD.CallFunctionAfterDelay(function()
      LD.BreakObject(GameObjects.HelSmallWeaponRack40)
      LD.BreakObject(GameObjects.xpl300_barrel_02_break25)
    end, 4.75)
    print("fog off")
    TurnFogOn()
    GameObjects.FX_HelR100:PlayAnimToFrame(1, 0.05)
    GameObjects.SternEdges:Show()
  elseif ShipEnteredZone("FightThreeZone", markerId, zoneObject) then
    print("enter fight zone 2")
    if state >= STATE_START_FIGHT_THREE then
      return
    end
    SetState(STATE_START_FIGHT_THREE)
  elseif ShipEnteredZone("HarpoonThreeZone", markerId, zoneObject) then
    print("enter harpoon zone 3")
    if state >= STATE_START_HARPOON_THREE then
      return
    end
    SetState(STATE_START_HARPOON_THREE)
    print("fog up")
    TurnFogOn()
    HelR_200:CallScript("MonolithProxyAnim")
    GameObjects.FX_HelR100:PlayAnimToFrame(3, 0.05)
    LD.CallFunctionAfterDelay(function()
      LD.BreakObject(GameObjects.HelSmallWeaponRack30)
      LD.BreakObject(GameObjects.HelSmallWeaponRack31)
      LD.BreakObject(GameObjects.HelSmallWeaponRack32)
    end, 1)
  end
end
function TurnFogOn()
  GameObjects.FX_HelR100:ShowTriggerVolume()
  GameObjects.FX_HelR100:ShowEntityVolume()
  GameObjects.FX_HelR100:ShowParticles()
  GameObjects.FX_HelR100:ShowParticleEmitter()
end
function DocksFightDone()
  docksFightDone = true
  GameObjects.Btr_110_RaiseSail_Start:ShowEntityVolume()
  GameObjects.ent_110_RaiseSail_Reminder:ShowEntityVolume()
end
function BreakBoards_01()
  board01 = true
  if board01 == true and board02 == true then
    tLinks_GapRear2:ShowTraverseLink()
    GameObjects.BoardBarrier:HideCollision()
    GameObjects.BoardBarrier1:HideCollision()
  end
end
function BreakBoards_02()
  board02 = true
  if board01 == true and board02 == true then
    tLinks_GapRear2:ShowTraverseLink()
  end
end
function SetupDebug()
  fireR.LuaObjectScript.IncrementHeatLevel(100)
  fireL.LuaObjectScript.IncrementHeatLevel(100)
  crank.LuaObjectScript.Lock()
  GameObjects.CollidableBox_Sails:Hide()
end
function Debug_DocksComplete()
  local helr100 = game.FindLevel("HelR100_Docks")
  if helr100 then
    helr100:CallScript("ShipFreedLowerDeck")
  end
  GameObjects.TNF_UpperDeckPush.LuaObjectScript.Enable()
  shipRef:TriggerMoveEvent("kLEDebugEvent_DocksComplete")
  TriggerMoveEvent_ShipAndSails("kLEStartFinalFlight")
  SetupDebug()
  LD.CallFunctionAfterDelay(function()
    local warpPos = shipRef:GetWorldJointPosition(shipRef:GetJointIndex("debugWarpLoc"))
    local warpDir = shipRef:GetWorldJointForward(shipRef:GetJointIndex("debugWarpLoc"))
    player:Warp(warpPos, warpDir)
    son:Warp(warpPos, warpDir)
  end, 0.2)
  VisOnFX()
  HideAllInitialTraverseLinks()
  HideAllGapTraverseLinks()
end
function WaitForHel200Load(functionCallback)
  _G.WatchForHel200Load(functionCallback)
end
function HideLatch()
  GameObjects.BoatLatch_Helheim_TEMP:Hide()
  GameObjects.BoatLatch_Helheim_TEMP:HideCollision()
end
function Debug_SkipDocks()
  TriggerMoveEvent_ShipAndSails("kLEDebugEvent_Origin")
  if FindHelR200() then
    FindHelR200():CallScript("HideMonolithProxy")
  end
  SetupDebug()
  WarpPlayerIntoLoadZone()
  DebugWarp_Delayed()
  WarpShipToOrigin()
  HideAllGapTraverseLinks()
  HideAllInitialTraverseLinks()
  HideLatch()
  GameObjects.SailFolded_Static:Hide()
  GameObjects.FX_HelR100:Show()
  GameObjects.FX_HelR100:PlayAnimToEnd()
  sailsRef:ShowJoint(sailsRef:GetJointIndex("sailGame"))
  if FindHelR200() ~= nil then
    LD.CallFunctionAfterDelay(function()
      FindHelR200():CallScript("AnimateWorld_JumpToFrame", 0)
      SetupZoneHandlers()
      game.World.StoreCheckpoint()
    end, 1)
  else
    WaitForHel200Load(function()
      Debug_SkipDocks()
    end)
  end
end
function Debug_StartHarpoonOne()
  TriggerMoveEvent_ShipAndSails("kLEDebugEvent_Origin")
  SetupDebug()
  DebugWarp_Delayed()
  WarpShipToOrigin()
  WarpPlayerIntoLoadZone()
  HideLatch()
  GameObjects.SailFolded_Static:Hide()
  sailsRef:ShowJoint(sailsRef:GetJointIndex("sailGame"))
  for _, child in pairs(breakableMoment01Anim.Children) do
    child:JumpAnimToFrame(0)
    child:PauseAnim()
  end
  for _, child in pairs(breakableMoment02Anim.Children) do
    child:JumpAnimToFrame(0)
    child:PauseAnim()
  end
  if FindHelR200() ~= nil then
    LD.CallFunctionAfterDelay(function()
      FindHelR200():CallScript("AnimateWorld_JumpToFrame", 700)
      SetupZoneHandlers()
    end, 1)
  else
    WaitForHel200Load(function()
      Debug_StartHarpoonOne()
    end)
  end
end
function Debug_StartHarpoonTwo()
  TriggerMoveEvent_ShipAndSails("kLEDebugEvent_Origin")
  SetupDebug()
  DebugWarp_Delayed()
  WarpShipToOrigin()
  WarpPlayerIntoLoadZone()
  HideLatch()
  if FindHelR200() ~= nil then
    HelR_200:CallScript("SnapEagleToSecondPosition")
  end
  GameObjects.SailFolded_Static:Hide()
  sailsRef:ShowJoint(sailsRef:GetJointIndex("sailGame"))
  for _, child in pairs(breakableMoment01Anim.Children) do
    child:JumpAnimToFrame(child.AnimLengthFrames)
  end
  for _, child in pairs(breakableMoment02Anim.Children) do
    child:JumpAnimToFrame(0)
    child:PauseAnim()
  end
  if FindHelR200() ~= nil then
    LD.CallFunctionAfterDelay(function()
      FindHelR200():CallScript("AnimateWorld_JumpToFrame", 2000)
      SetupZoneHandlers()
    end, 1)
  else
    WaitForHel200Load(function()
      Debug_StartHarpoonTwo()
    end)
  end
end
function Debug_StartHarpoonThree()
  TriggerMoveEvent_ShipAndSails("kLEDebugEvent_Origin")
  SetupDebug()
  DebugWarp_Delayed()
  WarpShipToOrigin()
  WarpPlayerIntoLoadZone()
  HideLatch()
  sailsRef:ShowJoint(sailsRef:GetJointIndex("sailGame"))
  GameObjects.SailFolded_Static:Hide()
  for _, child in pairs(breakableMoment01Anim.Children) do
    child:JumpAnimToFrame(child.AnimLengthFrames)
  end
  for _, child in pairs(breakableMoment02Anim.Children) do
    child:JumpAnimToFrame(child.AnimLengthFrames)
  end
  ShowAllGapTraverseLinks()
  HideAllInitialTraverseLinks()
  if FindHelR200() ~= nil then
    LD.CallFunctionAfterDelay(function()
      FindHelR200():CallScript("AnimateWorld_JumpToFrame", 2540)
      SetupZoneHandlers()
    end, 1)
  else
    WaitForHel200Load(function()
      Debug_StartHarpoonThree()
    end)
  end
end
function WarpShipToOrigin()
  parentRefnode:SetWorldPosition(GameObjects.WarpToOrigin.WorldPosition)
  shipRef:Warp(origin, GameObjects.WarpToOrigin:GetWorldForward())
end
function WarpPlayerIntoLoadZone()
  local warpObj = game.FindLevel("HelR100_Docks")
  if warpObj ~= nil then
    warpObj = warpObj:FindSingleGameObject("HelR100_Docks_Zone")
    if warpObj ~= nil then
      player:Warp(warpObj.WorldPosition, player:GetWorldForward())
    end
  end
end
function DebugWarp_Delayed()
  if DetermineBestHarpoon01Position() == nil then
    LD.CallFunctionAfterDelay(function()
      local warpPos = shipRef:GetWorldJointPosition(shipRef:GetJointIndex("debugWarpLoc"))
      local warpDir = shipRef:GetWorldJointForward(shipRef:GetJointIndex("debugWarpLoc"))
      player:Warp(warpPos, warpDir)
      if son ~= nil then
        son:Warp(warpPos, warpDir)
      end
    end, 0.2)
  else
    local sonPosRelativeToShip
    if son ~= nil then
      sonPosRelativeToShip = LD.GetPosInLocalSpaceOfObject(son.WorldPosition, GameObjects.WarpReferenceObj)
    end
    local playerPosRelativeToShip = LD.GetPosInLocalSpaceOfObject(player.WorldPosition, GameObjects.WarpReferenceObj)
    LD.CallFunctionAfterDelay(function()
      local playerProjectedPosition = LD.ProjectPositionOntoObject(playerPosRelativeToShip, GameObjects.WarpToOrigin)
      player:Warp(playerProjectedPosition, player:GetWorldForward())
      if son ~= nil then
        local sonProjectedPosition = LD.ProjectPositionOntoObject(sonPosRelativeToShip, GameObjects.WarpToOrigin)
        son:Warp(sonProjectedPosition, son:GetWorldForward())
      end
    end, 0.2)
  end
end
function HelShipTiltFail_KratosSync(movePosition)
  local branchTable = {
    right = "BRA_ShipTiltRightFail",
    left = "BRA_ShipTiltLeftFail"
  }
  local playerPositionX = player.WorldPosition.x
  local closestReferencePoint = "TiltFail_Front_Mid"
  if 14 <= playerPositionX then
    closestReferencePoint = "TiltFail_Back_Mid"
  elseif 5 < playerPositionX and playerPositionX < 14 then
    closestReferencePoint = "TiltFail_Back_Mid"
  elseif playerPositionX <= 5 and -5 < playerPositionX then
    closestReferencePoint = "TiltFail_Front_Mid"
  elseif playerPositionX <= -5 and -28 < playerPositionX then
    closestReferencePoint = "TiltFail_Front_Bow"
  end
  kratosActor = actor.Actor.New("Kratos", game.Player.FindPlayer)
  local seq = LD.CreateCineSequence(thisLevel, GameObjects.SyncScript_HelShip_TiltFail, "TiltFailWarp")
  seq:ActorSync(kratosActor, {
    Branch = branchTable[movePosition],
    ReferenceJoint = closestReferencePoint,
    ReferenceJointOn = 0.01,
    ReferenceJointTweenTime = 0.5
  })
  seq:StartSequence()
end
function TriggerMoveEvent_ShipAndSails(moveEvent)
  if shipRef then
    shipRef:TriggerMoveEvent(moveEvent)
  end
  if sailsRef then
    sailsRef:TriggerMoveEvent(moveEvent)
  end
end
function ResetHarpoons(newHarpoons)
  totalHarpoons = newHarpoons
  harpoonsRemoved = 0
end
function OnTNFWin_Harp01()
  CheckTotalHarpoons()
  LD.CallFunctionAfterDelay(function()
    LD.ShowFX(GameObjects.Breakable_Burst_Dust_Splinters01)
  end, 1.6)
  LD.CallFunctionAfterDelay(function()
    game.Audio.PlayBanter("135_KratosHaunts2")
  end, 13)
  LD.CallFunctionAfterDelay(function()
    game.Audio.PlayBanter("170_HarpoonNetwork_Free")
  end, 2)
  LD.CallFunctionAfterDelay(function()
    shipRef:HideJoint(shipRef:GetJointIndex("JOHarpoon01"))
  end, 5)
end
function OnTNFWin_Harp02_LFirst()
  GameObjects.TNF_HarpMoment02_HarpR1.LuaObjectScript.Disable()
  GameObjects.TNF_HarpMoment02_HarpR2.LuaObjectScript.Enable()
  GameObjects.TNF_HarpMoment02_HarpR2.LuaObjectScript.OverrideHintXZRange(50)
  CheckTotalHarpoons()
  LD.CallFunctionAfterDelay(function()
    shipRef:HideJoint(shipRef:GetJointIndex("JOHarpoon01"))
  end, 5)
  shipEncounterScript.StartHarpoonFightTwo_NextWave()
  StopSoundWitchSinging()
end
function OnTNFWin_Harp02_RFirst()
  GameObjects.TNF_HarpMoment02_HarpL1.LuaObjectScript.Disable()
  GameObjects.TNF_HarpMoment02_HarpL2.LuaObjectScript.Enable()
  GameObjects.TNF_HarpMoment02_HarpL2.LuaObjectScript.OverrideHintXZRange(50)
  CheckTotalHarpoons()
  LD.CallFunctionAfterDelay(function()
    shipRef:HideJoint(shipRef:GetJointIndex("JOHarpoon02"))
  end, 5)
  shipEncounterScript.StartHarpoonFightTwo_NextWave()
  StopSoundWitchSinging()
end
function OnTNFWin_Harp02_RSecond()
  CheckTotalHarpoons()
  LD.CallFunctionAfterDelay(function()
    shipRef:HideJoint(shipRef:GetJointIndex("JOHarpoon02"))
  end, 5)
  LD.CallFunctionAfterDelay(function()
    game.Audio.PlayBanter("170_HarpoonNetwork_Free")
  end, 2)
  LD.CallFunctionAfterDelay(function()
    game.Audio.PlayBanter("110_RaiseSail_AfterHarpoon1")
  end, 16)
end
function OnTNFWin_Harp02_LSecond()
  CheckTotalHarpoons()
  LD.CallFunctionAfterDelay(function()
    shipRef:HideJoint(shipRef:GetJointIndex("JOHarpoon01"))
  end, 5)
  LD.CallFunctionAfterDelay(function()
    game.Audio.PlayBanter("170_HarpoonNetwork_Free")
  end, 2)
  LD.CallFunctionAfterDelay(function()
    game.Audio.PlayBanter("110_RaiseSail_AfterHarpoon1")
  end, 16)
end
function OnTNFFail_Harp03()
  GameObjects.FXFog:Hide()
end
function OnTNFStruggle_Harp03()
  print("|||| Struggle Start!")
  LD.ShowFX(GameObjects.FX_impact_dust_synchJoint5)
  GameObjects.FXFog:Show()
  GameObjects.FXFog:JumpAnimToFrame(1)
  GameObjects.FXFog:PlayAnimCycle()
end
function OnTNFWin_Harp03_Start()
  print("|||| win start!")
  GameObjects.FXFog:Hide()
  local helr300 = game.FindLevel("HelR300_HelShip")
  helr300:CallScript("ShipToHideWarp")
  LD.CallFunctionAfterDelay(function()
    LD.ShowFX(GameObjects.FX_impact_dust_synchJoint5)
  end, 1.5)
end
function OnTNFWin_Harp03()
  TeleportShip_FinalPhase()
  SetState(STATE_FINAL_TNF_WIN)
  FindHelR200():CallScript("MonolithProxyAnimStop")
  GameObjects.FX_HelR100:PlayAnimToFrame(30, 0.5)
  _G.RemoteBowBreak()
  LD.CallFunctionAfterDelay(function()
    FindHelR200():CallScript("ShowFirstLoadZone")
  end, 0.2)
  LD.CallFunctionAfterDelay(function()
    GameObjects.FX_HelR100:PlayAnimToFrame(2, -0.13)
  end, 3)
  CheckTotalHarpoons()
end
function OnTNF_Interrupted()
  TriggerMoveEvent_ShipAndSails("kLETNF_Failed")
end
function CheckTotalHarpoons()
  harpoonsRemoved = harpoonsRemoved + 1
  if harpoonsRemoved == totalHarpoons then
    FindHelR200():CallScript("AnimateWorld_Slowdown")
    LD.CallFunctionAfterDelay(CheckFireStatesAfterHarpoonRemoval, 3)
    EnableFireInteraction()
    VisOnFX()
    ShipStoppedRTPC(false)
    LD.CallFunctionAfterDelay(function()
      VisOffFX()
    end, 60)
  end
end
function CheckFireStatesAfterHarpoonRemoval()
  if lFireState == 0 and rFireState == 1 then
    TriggerMoveEvent_ShipAndSails("kLELeftFireExtinguished")
  elseif lFireState == 1 and rFireState == 0 then
    TriggerMoveEvent_ShipAndSails("kLERightFireExtinguished")
  elseif lFireState == 0 and rFireState == 0 then
    TriggerMoveEvent_ShipAndSails("kLEBothFiresExtinguished")
  end
end
function VisOffFX()
  GameObjects.FX_INFLIGHT:Hide()
  GameObjects.TrailsAndSnow:Hide()
end
function VisOnFX()
  GameObjects.FX_INFLIGHT:Show()
  GameObjects.TrailsAndSnow:Show()
end
local warmAvailable
function WarmAvailable()
  warmAvailable = true
end
function AllSonBoatOff()
  GameObjects.ContextAction_Son_WarmHands.LuaObjectScript.Disable()
  GameObjects.ContextAction_Son_ShootFromPoint.LuaObjectScript.Disable()
  GameObjects.ContextAction_Son_StandAtPoint.LuaObjectScript.Disable()
  GameObjects.ContextAction_Son_ObserveForward_Fire1.LuaObjectScript.Disable()
  GameObjects.ContextAction_Son_ObserveForward_Fire2.LuaObjectScript.Disable()
  GameObjects.ContextAction_Son_ObserveForward_Crank.LuaObjectScript.Disable()
  GameObjects.ContextAction_Son_ObserveForward_Latch.LuaObjectScript.Disable()
  GameObjects.LeadTheWay_ShipRing.LuaObjectScript.Disable()
end
function JustSonLTWShipRing()
  GameObjects.ContextAction_Son_WarmHands.LuaObjectScript.Disable()
  GameObjects.ContextAction_Son_ShootFromPoint.LuaObjectScript.Disable()
  GameObjects.ContextAction_Son_StandAtPoint.LuaObjectScript.Disable()
  GameObjects.ContextAction_Son_ObserveForward_Fire1.LuaObjectScript.Disable()
  GameObjects.ContextAction_Son_ObserveForward_Fire2.LuaObjectScript.Disable()
  GameObjects.ContextAction_Son_ObserveForward_Crank.LuaObjectScript.Disable()
  GameObjects.ContextAction_Son_ObserveForward_Latch.LuaObjectScript.Disable()
  GameObjects.LeadTheWay_ShipRing.LuaObjectScript.Enable()
end
function JustSonShipCombat()
  GameObjects.ContextAction_Son_WarmHands.LuaObjectScript.Disable()
  GameObjects.ContextAction_Son_ShootFromPoint.LuaObjectScript.Disable()
  GameObjects.ContextAction_Son_StandAtPoint.LuaObjectScript.Disable()
  GameObjects.ContextAction_Son_ObserveForward_Fire1.LuaObjectScript.Disable()
  GameObjects.ContextAction_Son_ObserveForward_Fire2.LuaObjectScript.Disable()
  GameObjects.ContextAction_Son_ObserveForward_Crank.LuaObjectScript.Disable()
  GameObjects.ContextAction_Son_ObserveForward_Latch.LuaObjectScript.Disable()
  GameObjects.LeadTheWay_ShipRing.LuaObjectScript.Disable()
end
function AllSonBoatOn()
  if warmAvailable == true then
    GameObjects.ContextAction_Son_WarmHands.LuaObjectScript.Enable()
    GameObjects.LeadTheWay_ShipRing.LuaObjectScript.Enable()
  else
    GameObjects.ContextAction_Son_ObserveForward_Latch.LuaObjectScript.Enable()
  end
end
function MoveSonForTNF()
  GameObjects.ContextAction_Son_ShootFromPoint.LuaObjectScript.Disable()
  GameObjects.ContextAction_Son_StandAtPoint.LuaObjectScript.Disable()
  GameObjects.ContextAction_Son_ObserveForward_Crank.LuaObjectScript.Enable()
end
function BreakTopCrate()
  LD.BreakObject(GameObjects.crate_1_5m8)
end
function BridgeSmashRemote()
  TriggerMoveEvent_ShipAndSails("kLEBridgeSmash")
  PlaySoundShipImpact(nil, nil, "BIG")
end
function GateSmashRemote()
  LD.ShowFX(GameObjects.FX_impact_dust_synchJoint)
  LD.CallFunctionAfterDelay(function()
    LD.ShowFX(GameObjects.FX_impact_dust_synchJoint2)
    LD.ShowFX(GameObjects.FX_impact_dust_synchJoint3)
  end, 0.5)
  LD.CallFunctionAfterDelay(function()
    LD.ShowFX(GameObjects.FX_impact_dust_synchJoint4)
  end, 0.8)
end
function PlayBridgeFogRemote()
  shipEncounterScript.Temp_StaggerNearbyEnemies()
  print("fog up")
  LD.CallFunctionAfterDelay(function()
    TurnFogOn()
    GameObjects.FX_HelR100:PlayAnimToFrame(15, 0.03)
  end, 1)
  LD.CallFunctionAfterDelay(function()
    TurnFogOn()
    GameObjects.FX_HelR100:PlayAnimToFrame(1, -0.05)
  end, 11)
end
function FogToBringEagleBackRemote()
  LD.CallFunctionAfterDelay(function()
    GameObjects.FX_HelR100:PlayAnimToFrame(15, 0.05)
  end, 1)
  LD.CallFunctionAfterDelay(function()
    GameObjects.FX_HelR100:PlayAnimToFrame(1, -0.05)
  end, 15)
end
function StaggerEnemies()
  shipEncounterScript.Temp_StaggerNearbyEnemies()
end
function VisOffRearFires()
  GameObjects.DeckFires_Rear:Hide()
end
function VisONRearFires()
  GameObjects.DeckFires_Rear:Show()
  LD.CallFunctionAfterDelay(VisOffRearFires, 4)
end
function VisOffFrontFires()
  GameObjects.DeckFires_Front:Hide()
end
function VisONFrontFires()
  GameObjects.DeckFires_Front:Show()
  LD.CallFunctionAfterDelay(VisOffFrontFires, 4)
end
function AddScreenShake()
  local shakeParams = {
    EffectName = "FSE_shake_temp_Generic_Large",
    Duration = 0.5
  }
  game.FX.SubmitEffect(shakeParams)
end
function ShipEnteredZone(ZoneObjectName, markerId, zoneObject)
  if LD.MarkerIDsMatch(markerId, "HelheimShip_Mrkr") and zoneObject == HelR_200:FindSingleGameObject(ZoneObjectName) then
    return true
  end
  return false
end
function ShipExitedZone(ZoneObjectName, markerId, zoneObject)
  if LD.MarkerIDsMatch(markerId, "HelheimShip_Mrkr") and zoneObject == HelR_200:FindSingleGameObject(ZoneObjectName) then
    return true
  end
  return false
end
function ShipFailState()
  LD.CallFunctionAfterDelay(function()
    game.Combat.KillPlayer(1)
  end, 3.2)
  LD.CallFunctionAfterDelay(function()
    uiCalls.UI_Event_Fade_To_Black(0.1)
  end, 2.8)
  GameObjects.HelheimShipFailDeathHints.LuaObjectScript.EventFailed_BothFiresExtinguished()
  LD.CallFunctionAfterDelay(function()
    LD.BreakObject(GameObjects.HelSmallWeaponRack19)
    LD.BreakObject(GameObjects.HelSmallWeaponRack24)
    LD.BreakObject(GameObjects.HelSmallWeaponRack26)
    LD.BreakObject(GameObjects.HelSmallWeaponRack30)
    LD.BreakObject(GameObjects.HelSmallWeaponRack32)
    LD.BreakObject(GameObjects.HelSmallWeaponRack36)
    LD.BreakObject(GameObjects.HelSmallWeaponRack38)
    LD.BreakObject(GameObjects.crate_1_5m3)
    LD.BreakObject(GameObjects.crate_1_5m8)
    LD.BreakObject(GameObjects.xpl300_barrel_02_break8)
    LD.BreakObject(GameObjects.xpl300_barrel_02_break12)
    LD.BreakObject(GameObjects.xpl300_barrel_02_break18)
    LD.BreakObject(GameObjects.xpl300_barrel_02_break35)
    LD.BreakObject(GameObjects.xpl300_barrel_02_break38)
    for _, child in pairs(breakableMoment01Anim.Children) do
      child:JumpAnimToFrame(0)
      child:PlayAnimToEnd(2)
    end
    for _, child in pairs(breakableMoment02Anim.Children) do
      child:JumpAnimToFrame(0)
      child:PlayAnimToEnd(2)
    end
  end, 0.1)
end
function HideAllInitialTraverseLinks()
  GameObjects.NoVaultBack:Show()
end
function HideAllGapTraverseLinks()
  tLinks_GapRear:HideTraverseLink()
  tLinks_GapRear2:HideTraverseLink()
  tLinks_GapFront:HideTraverseLink()
end
function ShowAllGapTraverseLinks()
  tLinks_GapRear:ShowTraverseLink()
  tLinks_GapRear2:ShowTraverseLink()
  tLinks_GapFront:ShowTraverseLink()
end
function HideHarpoonMesh()
  shipRef:HideJoint(shipRef:GetJointIndex("JOHarpoon00"))
  shipRef:HideJoint(shipRef:GetJointIndex("JOHarpoon01"))
  shipRef:HideJoint(shipRef:GetJointIndex("JOHarpoon02"))
  shipRef:HideJoint(shipRef:GetJointIndex("JOHarpoon03"))
end
function CrankPulledDown()
  if crankHalfStateReached == false and crank.LuaObjectScript.GetCurrentCycle() == 3 then
    StartCameraSailsRaised()
    crank.LuaObjectScript.RemovePlayer()
    crank.LuaObjectScript.SetDetachedBehavior_FastForward()
    crank.LuaObjectScript.Disable()
    PlaySoundSailHalfRaised()
    PlaySoundSailLoop()
  end
  PlayerStartTurnCrank()
  TriggerMoveEvent_ShipAndSails("kLECrankPulled")
  sailsRef:ShowJoint(sailsRef:GetJointIndex("sailGame"))
  PlaySoundHalyardAxleCranked()
end
function CrankPushedUp()
  TriggerMoveEvent_ShipAndSails("kLECrankPushed")
  PlaySoundHalyardAxleCranked()
end
function CrankRewindStart()
  TriggerMoveEvent_ShipAndSails("kLECrankReleased")
end
function CrankReachedStartState()
  if crank.LuaObjectScript.GetCurrentCycle() == 0 then
    sailsRef:HideJoint(sailsRef:GetJointIndex("sailGame"))
  elseif crankHalfStateReached == false and crank.LuaObjectScript.GetCurrentCycle() > 0 then
    crankHalfStateReached = true
    SetState(STATE_HALF_CRANK_COMPLETE)
  end
end
function CrankReachedEndState()
  if crankHalfStateReached then
    PlaySoundSailFullyRaised()
    SetState(STATE_CRASH_INTO_LOWER_DECK)
  end
end
function DisableFireInteraction()
  fireL.LuaObjectScript.PausePOI()
  fireR.LuaObjectScript.PausePOI()
end
function EnableFireInteraction()
  if lFireState == 1 then
    fireL.LuaObjectScript.UnpausePOI()
  end
  if rFireState == 1 then
    fireR.LuaObjectScript.UnpausePOI()
  end
end
function LeftFireFullyLit()
  if state >= STATE_FINAL_TNF_WIN then
    return
  end
  lFireState = 1
  if fireL_FirstTime == true then
    fireL_FirstTime = false
    GameObjects.TarAndCollision_Back:Hide()
    VisONRearFires()
    GameObjects.HelR_Boat_Fire_01:ShowLights()
    GameObjects.ContextAction_Son_ObserveForward_Fire2.LuaObjectScript.Disable()
    crank.LuaObjectScript.Unlock()
    if fireR_FirstTime then
      Btr_PlayerBurnedBramble_LFirst()
    else
      Btr_PlayerBurnedBramble_LSecond()
      crank.LuaObjectScript.SetMaxStopCycle(6)
    end
  end
  TriggerMoveEvent_ShipAndSails("kLELeftFireLit")
  shipEncounterScript.Enable_Left_Spawners()
end
function LeftFireFullyUnlit()
  if state >= STATE_FINAL_TNF_WIN then
    return
  end
  lFireState = 0
  if state > STATE_TELEPORT_ORIGIN then
    GameObjects.HelR_Boat_Fire_01:HideLights()
    game.Audio.PlayBanter("140_BoatFight_Act1_PortsideOut")
    LD.AddControllerRumble({EffectName = "FFB_GIANT", Duration = 0.4})
    if rFireState == 1 then
      TriggerMoveEvent_ShipAndSails("kLELeftFireExtinguished")
    elseif rFireState == 0 then
      HelShipTiltFail_KratosSync("right")
      TriggerMoveEvent_ShipAndSails("kLEBothFiresExtinguished")
      ShipFailState()
      if shipEncounterScript.EncountersRunning() then
        shipEncounterScript.Stop_Ship_Encounters()
      end
    end
  end
  shipEncounterScript.Disable_Left_Spawners()
end
function RightFireFullyLit()
  if state >= STATE_FINAL_TNF_WIN then
    return
  end
  rFireState = 1
  if fireR_FirstTime == true then
    fireR_FirstTime = false
    GameObjects.TarAndCollision_Front:Hide()
    VisONFrontFires()
    GameObjects.HelR_Boat_Fire_02:ShowLights()
    GameObjects.ContextAction_Son_ObserveForward_Latch.LuaObjectScript.Disable()
    GameObjects.ContextAction_Son_WarmHands.LuaObjectScript.Enable()
    if fireL_FirstTime then
      Btr_PlayerBurnedBramble_RFirst()
    else
      crank.LuaObjectScript.SetMaxStopCycle(6)
      Btr_PlayerBurnedBramble_RSecond()
    end
  end
  TriggerMoveEvent_ShipAndSails("kLERightFireLit")
  shipEncounterScript.Enable_Right_Spawners()
end
function RightFireFullyUnlit()
  if state >= STATE_FINAL_TNF_WIN then
    return
  end
  rFireState = 0
  if state > STATE_TELEPORT_ORIGIN then
    GameObjects.HelR_Boat_Fire_02:HideLights()
    game.Audio.PlayBanter("140_BoatFight_Act1_StarboardOut")
    LD.AddControllerRumble({EffectName = "FFB_GIANT", Duration = 0.4})
    if lFireState == 1 then
      TriggerMoveEvent_ShipAndSails("kLERightFireExtinguished")
    elseif lFireState == 0 then
      HelShipTiltFail_KratosSync("left")
      TriggerMoveEvent_ShipAndSails("kLEBothFiresExtinguished")
      ShipFailState()
      if shipEncounterScript.EncountersRunning() then
        shipEncounterScript.Stop_Ship_Encounters()
      end
    end
  end
  shipEncounterScript.Disable_Right_Spawners()
end
function OnIceBlastRight(data, test)
  AddScreenShake()
  if haveWarnedFires == false then
    LD.CallFunctionAfterDelay(function()
      game.Audio.PlayBanter("140_BoatFight_Act1_StarboardWarning")
    end, 0.1)
    haveWarnedFires = true
  end
end
function OnIceBlastLeft(data, test)
  AddScreenShake()
  if haveWarnedFires == false then
    LD.CallFunctionAfterDelay(function()
      game.Audio.PlayBanter("140_BoatFight_Act1_PortsideWarning")
    end, 0.1)
    haveWarnedFires = true
  end
end
function StartCameraSailsRaised()
  cameraOneShotSailsRaised = CCOS.OneShotCamera.New("PLYR_Nar_HelSails_Raised", 3.6)
  cameraOneShotSailsRaised:SetCallback(DestroyCameraSailsRaised)
  cameraOneShotSailsRaised:Start()
end
function DestroyCameraSailsRaised()
  cameraOneShotSailsRaised = nil
end
function SetDriversForWarp01AndPlayKratos_010()
  local helr300 = game.FindLevel("HelR300_HelShip")
  helr300:CallScript("Harpoon01_KratosSync")
end
function DetermineBestHarpoon01Position()
  if playerPosition == nil then
    playerPosition = player.WorldPosition
  end
  if game.World.IsInsideCameraZone(playerPosition, "CamZone_Harpoon01_010") then
    return "markerHarpoon01_goTo_010"
  elseif game.World.IsInsideCameraZone(playerPosition, "CamZone_Harpoon01_020") then
    return "markerHarpoon01_goTo_020"
  elseif game.World.IsInsideCameraZone(playerPosition, "CamZone_Harpoon01_030") then
    return "markerHarpoon01_goTo_030"
  elseif game.World.IsInsideCameraZone(playerPosition, "CamZone_Harpoon01_040") then
    return "markerHarpoon01_goTo_040"
  elseif game.World.IsInsideCameraZone(playerPosition, "CamZone_Harpoon01_050") then
    return "markerHarpoon01_goTo_050"
  elseif game.World.IsInsideCameraZone(playerPosition, "CamZone_Harpoon01_060") then
    return "markerHarpoon01_goTo_060"
  end
  return nil
end
function CamPlayHarpoonTarget01()
  camTargetAnimGroupHarp01:PlayAnimToEnd()
  timers.StartLevelTimer(1.5, StartDynamicCamHarpoon01_020)
end
function StartDynamicCamHarpoon01_010()
  camera_Harpoon01_Follow_010 = CCOS.OneShotCamera.New(camHarpoon01Follow010Type, 4.5)
  camera_Harpoon01_Follow_010:Reinitialize()
  camera_Harpoon01_Follow_010:Start()
end
function StartDynamicCamHarpoon01_020()
  camera_Harpoon01_Follow_020 = CCOS.OneShotCamera.New(camHarpoon01Follow020Type, 0.4)
  camera_Harpoon01_Follow_020:Reinitialize()
  camera_Harpoon01_Follow_020:Start()
  game.SetSlowdown(0.2, 1)
end
function SetDriversForWarp02AndPlayKratos_020()
  local helr300 = game.FindLevel("HelR300_HelShip")
  helr300:CallScript("Harpoon02_KratosSync")
end
function CamPlayHarpoonTarget02()
  camTargetAnimGroupHarp02:PlayAnimToEnd()
end
function StartDynamicCamHarpoon02_010()
  camera_Harpoon02_Follow_010 = CCOS.OneShotCamera.New(camHarpoon02Follow010Type, 3)
  camera_Harpoon02_Follow_010:Reinitialize()
  camera_Harpoon02_Follow_010:Start()
end
function StartDynamicCamHarpoon02_020()
  camera_Harpoon02_Follow_020 = CCOS.OneShotCamera.New(camHarpoon02Follow020Type, 3)
  camera_Harpoon02_Follow_020:Reinitialize()
  camera_Harpoon02_Follow_020:Start()
end
function StartDynamicCamHarpoon02_030()
  camera_Harpoon02_Follow_030 = CCOS.OneShotCamera.New(camHarpoon02Follow030Type, 1.8)
  camera_Harpoon02_Follow_030:SetCallBack(DestroyHarpoonCameras02)
  camera_Harpoon02_Follow_030:Start()
end
function DestroyHarpoonCameras02()
  camera_Harpoon02_Follow_010 = nil
  camera_Harpoon02_Follow_020 = nil
  camera_Harpoon02_Follow_030 = nil
end
function SetDriversForWarp03AndPlayKratos_030()
  local helr300 = game.FindLevel("HelR300_HelShip")
  helr300:CallScript("Harpoon03_KratosSync")
end
function StartDynamicCamHarpoon03_010()
  camera_Harpoon03_Follow_010 = CCOS.OneShotCamera.New("PLYR_Harpoon03_Track_010", 7.5)
  camera_Harpoon03_Follow_010:Start()
end
function StartDynamicCamHarpoon03_012()
  camera_Harpoon03_Follow_012 = CCOS.OneShotCamera.New("PLYR_Harpoon03_Track_012", 3)
  camera_Harpoon03_Follow_012:Start()
end
function StartDynamicCamHarpoon03_020()
  camera_Harpoon03_Follow_020 = CCOS.OneShotCamera.New("PLYR_Nar2s_HelR_JotunnIntro", 1.5)
  camera_Harpoon03_Follow_020:SetCallback(DestroyHarpoon03Cameras)
  camera_Harpoon03_Follow_020:Start()
end
function DestroyHarpoon03Cameras()
  camera_Harpoon03_Follow_010 = nil
  camera_Harpoon03_Follow_012 = nil
  camera_Harpoon03_Follow_020 = nil
end
function StartDynamicCamIcebergHit_010()
  camera_IcebergHit_01 = CCOS.OneShotCamera.New("PLYR_Nar_Iceberg_010", 4)
  camera_IcebergHit_01:Reinitialize()
  camera_IcebergHit_01:Start()
end
function StartDynamicCamIcebergHit_020()
  camera_IcebergHit_02 = CCOS.OneShotCamera.New("PLYR_Nar_Iceberg_020", 2.8)
  camera_IcebergHit_02:Reinitialize()
  camera_IcebergHit_02:Start()
end
function StaggerAndSyncIcebergHit()
  local helr300 = game.FindLevel("HelR300_HelShip")
  helr300:CallScript("Iceberg_KratosSync")
end
function EnablePlayerInput()
  player.Pad:ClearAllDisabledGameButtons()
end
function DisablePlayerInput()
  player.Pad:DisableAllGameButtons()
  player.Pad:DisableGameButton(tweaks.ePad.kPadLeftStickX)
  player.Pad:DisableGameButton(tweaks.ePad.kPadLeftStickY)
  player.Pad:DisableGameButton(tweaks.ePad.kPadRightStickX)
  player.Pad:DisableGameButton(tweaks.ePad.kPadRightStickY)
end
function PlayerEnteredShip()
  GameObjects.ContextAction_Son_ObserveForward_Latch.LuaObjectScript.Enable()
  GameObjects.BoatCAON:ShowEntityVolume()
  GameObjects.BoatCAOFF:ShowEntityVolume()
  if docksFightDone == true then
    LD.CallFunctionAfterDelay(Btr_PlayerEnteredShip_BrambleHint, 20)
  end
end
function Btr_PlayerEnteredShip_BrambleHint()
  if playerBurnedBramble == false and docksFightDone == true then
    playerBurnedBramble = true
    game.Audio.PlayBanter("110_RaiseSail_Reminder")
  end
end
function Btr_PlayerBurnedBramble_LFirst()
  if docksFightDone == true then
    playerBurnedBramble = true
    game.Audio.PlayBanter("110_RaiseSail_CrankCleared")
  end
end
function Btr_PlayerBurnedBramble_LSecond()
  if docksFightDone == true then
    game.Audio.PlayBanter("110_RaiseSail_MainstayCleared")
  end
end
function Btr_PlayerBurnedBramble_LFirst_FollowUp()
end
function Btr_PlayerBurnedBramble_RFirst()
  if docksFightDone == true then
    playerBurnedBramble = true
    game.Audio.PlayBanter("110_RaiseSail_CrankCleared")
  end
end
function Btr_PlayerBurnedBramble_RFirst_FollowUp()
end
function Btr_PlayerBurnedBramble_RSecond()
  if docksFightDone == true then
    game.Audio.PlayBanter("110_RaiseSail_MainstayCleared")
  end
end
function Btr_ShipStartsMoving()
  GameObjects.ContextAction_Son_WarmHands.LuaObjectScript.Disable()
  GameObjects.ContextAction_Son_ObserveForward_Fire2.LuaObjectScript.Disable()
  GameObjects.LeadTheWay_ShipRing.LuaObjectScript.Enable()
  game.Audio.PlayBanter("110_RaiseSail_TurnCrank_02")
end
function Btr_SkidvalanirStory()
end
function Btr_ShipStuckIceberg(monitor)
  if monitor ~= nil then
    monitor:Stop()
    monitor:Terminate()
    monitor = nil
  end
  game.Audio.PlayBanter("120_Stuck_Collision", Btr_ReturnToMainstay)
  GameObjects.ContextAction_Son_ObserveForward_Crank.LuaObjectScript.Disable()
  LD.CallFunctionAfterDelay(function()
    GameObjects.ContextAction_Son_ObserveForward_Latch.LuaObjectScript.Enable()
  end, 5)
end
function Btr_ReturnToMainstay()
  LD.CallFunctionAfterDelay(Btr_ReturnToMainstay_Hint, 30)
end
local breakingLatch = false
function Btr_ReturnToMainstay_Hint()
  if not breakingLatch then
    game.Audio.PlayBanter("120_Stuck_MainstayHint")
  end
end
function Btr_BreakLatch_Attempt()
  breakingLatch = true
  game.Audio.PlayBanter("120_Stuck_SnapsRope")
end
function Btr_BreakLatch_Success()
  game.Audio.PlayBanter("120_Stuck_SnapsRopeSuccess")
  GameObjects.ContextAction_Son_ObserveForward_Latch.LuaObjectScript.Disable()
  LD.CallFunctionAfterDelay(Btr_ReturnToCrank, 30)
end
function Btr_ReturnToCrank()
  if playerUsedCrankAfterLatchTNF == false then
    game.Audio.PlayBanter("120_Stuck_TurnCrankReminder")
  end
end
function Btr_SailsFull()
  LD.CallFunctionAfterDelay(function()
    game.Audio.PlayBanter("130_StuckAgain")
  end, 10)
  local seq = LD.CreateCineSequence(thisLevel, shipRef, "BridgeCollision")
  seq:WaitForFunctionTrue(function()
    return shipRef:IsPlayingMove("MOV_ShipLowerDeckIdle")
  end)
  seq:Do(HitLowerDeck)
  seq:StartSequence()
end
function HitLowerDeck()
  game.Audio.PlayBanter("130_StuckAgain_Collision", Btr_SailsFull_Stuck_FollowUp)
  GameObjects.CollisionTurretRail:HideCollision()
  GameObjects.CollisionTumbleRail:HideCollision()
  GameObjects.CollisionTurretGuide:HideCollision()
end
function Btr_SailsFull_Stuck_FollowUp()
  game.Audio.PlayBanter("130_StuckAgain_SkyLantern")
end
local playedLockedBanter = false
function PlayerStartTurnCrank()
  if state >= STATE_HALF_CRANK_COMPLETE then
    if playerUsedCrankAfterLatchTNF == false then
      playerUsedCrankAfterLatchTNF = true
      game.Audio.PlayBanter("120_Stuck_SailsDown")
    end
  elseif state < STATE_SAILS_TNF_COMPLETE and fireR_FirstTime == false and fireL_FirstTime == false then
    if playerUsedCrankAfterBurnables == false then
      playerUsedCrankAfterBurnables = true
      game.Audio.PlayBanter("110_RaiseSail_TurnCrank_01")
    end
  elseif state < STATE_SAILS_TNF_COMPLETE and not playedLockedBanter then
    game.Audio.PlayBanter("110_RaiseSail_CrankLockedByMainstay")
    playedLockedBanter = true
  end
end
function CameraRecenterToGameplay(fTime, fLockPercentage)
  game.Camera.Recenter({
    TimeStart = 0,
    LockRecenter = fLockPercentage,
    TimeDuration = fTime,
    PitchRange = -1,
    YawRange = 360,
    TriggerDown = 0,
    ReturnDown = -12,
    TriggerUp = 0,
    ReturnUp = -11,
    EaseIn = -1,
    EaseOut = 1
  })
end
function CameraRecenterAfterLatchBreak()
  game.Camera.Recenter({
    TimeStart = 0,
    LockRecenter = 0.8,
    TimeDuration = 3,
    PitchRange = -1,
    YawRange = 360,
    TriggerDown = 0,
    ReturnDown = -12,
    TriggerUp = 0,
    ReturnUp = -11,
    EaseIn = -1,
    EaseOut = 1
  })
end
local shipCloseEmitter, shipDistEmitter, bowEmitter, sailEmitter
local soundOverrides_MastRemoval = {
  synchObjSoundEmitter = "SNDMast",
  loopSound = "SND_CINE_HelShip_Mast_TNF_Push_LP",
  inactiveLoopSound = "SND_CINE_HelShip_Mast_Scrape_Dist_LP",
  winSound = "SND_CINE_HelShip_Mast_TNF_Win",
  failSound = "SND_CINE_HelShip_Mast_TNF_Abort"
}
local soundOverrides_HarpoonTNFs = {
  synchObjSoundEmitter = "SNDHarpoon01",
  explicit_InteractStart = "SND_TNF_HelR_Harpoon_Minigame_Start",
  explicit_LoopSound = "SND_TNF_HelR_Harpoon_Minigame_LP",
  explicit_WinSound = "SND_TNF_HelR_Harpoon_Minigame_Win",
  explicit_FailSound = "SND_TNF_HelR_Harpoon_Minigame_Fail"
}
local soundSailFlapEvents = {
  activeLoop = "SND_AMB_Emit_HelShip_Sail_Mvmt_LP",
  halfRaised = "SND_AMB_EMIT_HelShip_Sail_Flap_01",
  fullyRaised = "SND_AMB_EMIT_HelShip_Sail_Flap_02"
}
local soundHalyardWinchEvents = {
  SoundEmitter = nil,
  UseExplicitSoundMotion = true,
  OnForward = "SND_MECH_HelShip_Crank_Move_LP",
  OnBackward = "SND_MECH_HelShip_Crank_Move_LP",
  OnFastForward = "SND_MECH_HelShip_Crank_Move_LP",
  OnRewind = "SND_MECH_HelShip_Crank_Move_LP"
}
local soundHalyardAxleEmitter
local soundHalyardAxleEvent = "SND_MECH_HelShip_Crank_Mast_Pulley"
local witchSingEmitter
local witchSingEvent = "SND_vo_glb_cbt_bntr_lure_wit_LP"
local witchSingComplete, bowLeftImpactPointEmitter
function SoundOnStart()
  GameObjects.TNF_HarpMoment01_HarpL1.LuaObjectScript.SoundSetup(soundOverrides_HarpoonTNFs)
  GameObjects.TNF_HarpMoment02_HarpL1.LuaObjectScript.SoundSetup(soundOverrides_HarpoonTNFs)
  GameObjects.TNF_HarpMoment02_HarpL2.LuaObjectScript.SoundSetup(soundOverrides_HarpoonTNFs)
  soundOverrides_HarpoonTNFs.synchObjSoundEmitter = "SNDHarpoon02"
  GameObjects.TNF_HarpMoment02_HarpR1.LuaObjectScript.SoundSetup(soundOverrides_HarpoonTNFs)
  GameObjects.TNF_HarpMoment02_HarpR2.LuaObjectScript.SoundSetup(soundOverrides_HarpoonTNFs)
  shipCloseEmitter = shipRef:FindSingleGOByName("SNDhelheimShip00Grp"):FindSingleSoundEmitterByName("SNDhelheimShip00")
  shipDistEmitter = shipRef:FindSingleGOByName("SNDhelheimShipDistGrp"):FindSingleSoundEmitterByName("SNDhelheimShipDist")
  bowEmitter = shipRef:FindSingleSoundEmitterByName("SNDBowRipIdle")
  sailEmitter = sailsRef.SoundEmitters[1]
  witchSingEmitter = shipRef:FindSingleSoundEmitterByName("SNDShipWitchSing")
  bowLeftImpactPointEmitter = shipRef:FindSingleSoundEmitterByName("SNDBowLeftImpactPoint")
  soundHalyardWinchEvents.SoundEmitter = crank.Child:FindSingleSoundEmitterByName("SNDHalyardWinch")
  crank.LuaObjectScript.DrivenObjectSoundSetup(soundHalyardWinchEvents)
  soundHalyardAxleEmitter = shipRef:FindSingleSoundEmitterByName("SNDHalyardAxle")
  SetupSoundBasedOnShipState()
  PlayMusicOnCheckpoint()
end
function SetupSoundBasedOnShipState()
  if game.Level.GetVariable("CompletedCineNumber") < 498 then
    if state > STATE_DOCKS_IDLE then
      PlayCreakLoops()
      PlaySoundSailLoop()
    end
    if state == STATE_START_HARPOON_ONE or state == STATE_START_HARPOON_TWO or state == STATE_START_HARPOON_THREE or state == STATE_CRASH_INTO_LOWER_DECK then
      ShipStoppedRTPC(true)
    else
      ShipStoppedRTPC(false)
    end
    if state == STATE_START_HARPOON_TWO and witchSingComplete ~= nil and not witchSingComplete then
      PlaySoundWitchSinging()
    end
  else
    StopAllBoatLoops()
  end
end
function EnableShipMovingAmbience()
  thisLevel:CallScript("EnableBoatMovingAmbience", thisLevel)
end
function PlaySoundHalyardAxleCranked()
  LD.PlaySound(soundHalyardAxleEmitter, soundHalyardAxleEvent)
end
function SoundBoatLiftOff()
  LD.PlaySound(shipCloseEmitter, "SND_CINE_HelShip_Flight_Start")
end
function PlaySoundIcebergGrind()
  LD.CallFunctionAfterDelay(function()
    LD.PlaySoundOnFrame(bowLeftImpactPointEmitter, shipRef, "SND_CINE_HeShip_Iceberg_Hit", shipRef.AnimLengthFrames * 0.715, "forward")
  end, 2.5)
end
function PlaySoundSailHalfRaised()
  LD.PlaySound(sailEmitter, soundSailFlapEvents.halfRaised)
end
function PlaySoundSailLoop()
  LD.PlaySound(sailEmitter, soundSailFlapEvents.activeLoop)
end
function PlaySoundSailFullyRaised()
  LD.PlaySound(sailEmitter, soundSailFlapEvents.fullyRaised)
end
function PlaySoundShipFreedPlatform01()
  LD.PlaySound(shipCloseEmitter, "SND_CINE_HelShip_Platform_01_Freed")
end
function PlaySoundWitchSinging()
  if witchSingEmitter then
    LD.PlaySound(witchSingEmitter, witchSingEvent)
  end
  witchSingComplete = false
end
function StopSoundWitchSinging()
  if witchSingEmitter then
    LD.CallFunctionAfterDelay(function()
      LD.StopSound(witchSingEmitter, witchSingEvent)
    end, 2.5)
  end
  witchSingComplete = true
end
function PlayCreakLoops()
  print("Playing creak sounds")
  LD.PlaySoundAfterDelay(shipCloseEmitter, "SND_WOOD_HelShip_Creak_LP", 0.5)
  LD.PlaySoundAfterDelay(shipDistEmitter, "SND_WOOD_HelShip_Creak_Dist_LP", 0.5)
end
function StopCreakLoops()
  print("Stopping creak sounds")
  LD.StopSound(shipCloseEmitter, "SND_WOOD_HelShip_Creak_LP")
  LD.StopSound(shipDistEmitter, "SND_WOOD_HelShip_Creak_Dist_LP")
end
function ShipStoppedRTPC(stopped)
  local maxRTPCValue = 100
  local minRTPCValue = 0
  local val = maxRTPCValue
  if stopped then
    val = minRTPCValue
  end
  game.Audio.SetWwiseRTPCValue(shipRef, "HelShip_Creak_Frequency", val)
end
function PlayBowRipIdleSound()
  LD.PlaySound(bowEmitter, "SND_TNF_HelShip_BowRip_Idle_LP")
end
function PlaySoundShipImpact(level, go, intensity)
  local formattedIntensity = string.upper(tostring(intensity))
  if formattedIntensity == "BIG" then
    LD.PlaySound(shipCloseEmitter, "SND_CINE_HeShip_Impact_Big")
  elseif formattedIntensity == "DEEP" then
    LD.PlaySound(shipCloseEmitter, "SND_CINE_HeShip_Impact_Deep")
  elseif formattedIntensity == "MAST" then
    LD.PlaySound(shipCloseEmitter, "SND_CINE_HeShip_Impact_Mast")
  elseif formattedIntensity == "MIXED" then
    LD.PlaySound(shipCloseEmitter, "SND_CINE_HeShip_Impact_Mixed")
  else
    LD.PlaySound(shipCloseEmitter, "SND_CINE_HeShip_Impact_Med")
  end
end
function PlayMusicHarpoon1()
  game.Audio.StartCheckpointedMusic("SND_MX_HEL_ship_combat_p2_trans")
end
function PlayMusicHarpoon2()
  game.Audio.StartCheckpointedMusic("SND_MX_HEL_ship_combat_p3_trans")
end
function PlayMusicFight1()
  game.Audio.StartCheckpointedMusic("SND_MX_HEL_ship_combat_p1_in")
end
function PlayMusicFight2()
  game.Audio.StartCheckpointedMusic("SND_MX_HEL_ship_combat_p2_in")
end
function PlayMusicFight3()
  game.Audio.StartCheckpointedMusic("SND_MX_HEL_ship_combat_p3_in")
end
function PlayMusicShipLiftoff()
  game.Audio.StartCheckpointedMusic("SND_MX_HEL_ship_combat_intro")
end
function StopAllBoatLoops()
  print("StopAllBoatLoops")
  fireR.LuaObjectScript.StopBonfireLoop()
  fireL.LuaObjectScript.StopBonfireLoop()
  StopCreakLoops()
  LD.StopSound(sailEmitter, soundSailFlapEvents.activeLoop)
  LD.StopSound(sailEmitter, soundSailFlapEvents.halfRaised)
  LD.StopSound(sailEmitter, soundSailFlapEvents.fullyRaised)
end
function PlayMusicOnCheckpoint()
  if state == STATE_START_FIGHT_ONE then
    PlayMusicFight1()
  elseif state == STATE_START_HARPOON_ONE then
    PlayMusicHarpoon1()
  elseif state == STATE_START_FIGHT_TWO then
    PlayMusicFight2()
  elseif state == STATE_START_HARPOON_TWO then
    PlayMusicHarpoon2()
  elseif state == STATE_START_FIGHT_THREE then
    PlayMusicFight3()
  end
end
function GetFixedUpShipPosAndDir()
  if state == STATE_DOCKS_IDLE then
    return engine.Vector.New(2229, -344, 598), engine.Vector.New(-1, 0, 0)
  elseif state == STATE_HALF_CRANK_COMPLETE then
    return engine.Vector.New(2229, -344, 598), engine.Vector.New(-1, 0, 0)
  elseif state == STATE_SAILS_TNF_COMPLETE then
    return engine.Vector.New(2229, -344, 598), engine.Vector.New(-1, 0, 0)
  elseif state == STATE_CRASH_INTO_LOWER_DECK then
    return engine.Vector.New(2229, -344, 598), engine.Vector.New(-1, 0, 0)
  elseif state == STATE_FINAL_LIFTOFF then
    return engine.Vector.New(0, 0, 0), engine.Vector.New(-1, 0, 0)
  elseif state == STATE_TELEPORT_ORIGIN then
    return engine.Vector.New(0, 0, 0), engine.Vector.New(-1, 0, 0)
  elseif state == STATE_START_FIGHT_ONE then
    return engine.Vector.New(0, 0, 0), engine.Vector.New(-1, 0, 0)
  elseif state == STATE_START_BIG_MOMENT_ONE then
    return engine.Vector.New(0, 0, 0), engine.Vector.New(-1, 0, 0)
  elseif state == STATE_START_HARPOON_ONE then
    return engine.Vector.New(0, 0, 0), engine.Vector.New(-1, 0, 0)
  elseif state == STATE_START_FIGHT_TWO then
    return engine.Vector.New(0, 0, 0), engine.Vector.New(-1, 0, 0)
  elseif state == STATE_START_HARPOON_TWO then
    return engine.Vector.New(0, 0, 0), engine.Vector.New(-1, 0, 0)
  elseif state == STATE_START_FIGHT_THREE then
    return engine.Vector.New(0, 0, 0), engine.Vector.New(-1, 0, 0)
  elseif state == STATE_START_HARPOON_THREE then
    return engine.Vector.New(0, 0, 0), engine.Vector.New(-1, 0, 0)
  elseif state == STATE_FINAL_TNF_WIN then
    return engine.Vector.New(155.971, 18.519, 64.57), engine.Vector.New(0, 0, -1)
  end
  return engine.Vector.New(0, 0, 0), engine.Vector.New(-1, 0, 0)
end
function OnSaveCheckpoint(level, obj)
  local shipPosToSave, shipDirToSave
  if shipRef ~= nil then
    shipPosToSave = shipRef:GetWorldPosition()
    shipDirToSave = shipRef:GetWorldForward()
  else
    shipPosToSave, shipDirToSave = GetFixedUpShipPosAndDir()
  end
  return {
    state = state,
    lastShipPos = shipPosToSave,
    lastShipDir = shipDirToSave,
    crankHalfStateReached = crankHalfStateReached,
    fireL_FirstTime = fireL_FirstTime,
    fireR_FirstTime = fireR_FirstTime,
    docksFightDone = docksFightDone,
    totalHarpoons = totalHarpoons,
    harpoonsRemoved = harpoonsRemoved,
    witchSingComplete = witchSingComplete
  }
end
function OnRestoreCheckpoint(level, obj, savedInfo)
  state = savedInfo.state
  lastShipPos = savedInfo.lastShipPos
  lastShipDir = savedInfo.lastShipDir
  crankHalfStateReached = savedInfo.crankHalfStateReached
  fireL_FirstTime = savedInfo.fireL_FirstTime
  fireR_FirstTime = savedInfo.fireR_FirstTime
  docksFightDone = savedInfo.docksFightDone
  totalHarpoons = savedInfo.totalHarpoons
  harpoonsRemoved = savedInfo.harpoonsRemoved
  witchSingComplete = savedInfo.witchSingComplete
end
