local LD = require("design.LevelDesignLibrary")
local timer = require("level.timer")
local monitors = require("level.MonitorLibrary")
local CCOS = require("camera.camera_oneshot")
local CSL = require("camera.shakelibrary")
local player, son, playerPuppeteer, sonPuppeteer, thisObj
local state = 0
local animDriver_Cine, animDriver_Stuck, animDriver_Free, gears, rock, pulley_counterweight, pulley_claw, liftCart, crankMechanism, lockCollision, rollerCrank, breakableRope, rollerAnimMonitor, liftClawMonitor
local pushCartPath_Anim = "envPeak080CounterWeight_RollerCart"
local crankIntro_Anim = "poiPeakRopeStuckA"
local stuckShake_Anim = "envPeak080CounterWeight_StuckShake"
local liftCartAttached_Anim = "envPeak080CounterWeight_LiftCart"
local camZoneRollerOutsideHint
local rocksCrumbled = false
local clawReleasedCount = 0
local clawDownCount = 0
local reached_RollerRoom = false
local reached_MonolithStone = false
local interacted_MonolithStone = false
local playerInPeak210 = false
local playerArrivedSecondFloor = false
local ropeBroken = false
local finalCheckpointTriggered = false
local firstAttach = false
local firstFree = false
local doorCartOpen = false
local camOneShot_LookAtWheel, camOneShot_SpecialAxeRecall
local kRecenterDuration_FrozenCrank = 0.5
local fx_CartImpact, fx_DoorImpact, fx_RockImpact, axePinFreezeFx, axeIceRecallFx, pad
STATE_PRE_COLLAPSE = 0
STATE_COLLAPSE = 1
STATE_POST_COLLAPSE_IDLE = 2
STATE_ROCK_PUSH = 3
STATE_CRANK_FREE = 4
STATE_CART_ATTACHED = 5
debugFired = false
function OnScriptLoaded(level, obj)
  thisObj = obj
  player = game.Player.FindPlayer()
  son = game.AI.FindSon()
  pad = player.Pad
  animDriver_Cine = GameObjects.animDriver_Cine
  animDriver_Stuck = GameObjects.animDriver_Stuck
  animDriver_Free = GameObjects.animDriver_Free
  gears = GameObjects.liftMechanics00_P.Child
  rock = GameObjects.monolithStone00_P.Child
  pulley_claw = GameObjects.liftClaw00_P.Child
  pulley_counterweight = GameObjects.liftCounterweight00_P.Child
  liftCart = GameObjects.pushCart00_P.Child
  crankMechanism = gears:FindSingleGOByName("WheelCrank_PeaksPass").Child
  rollerCrank = GameObjects.lineCrankHandle.Child
  breakableRope = GameObjects.pushCartRope00_P.Child
  lockCollision = gears:FindSingleGOByName("LockCollision")
  lockCollision.LuaObjectScript.SetSaveAxeState(true)
  lockCollision.LuaObjectScript.RegisterOnWeaponEmbed(FreezeGears)
  lockCollision.LuaObjectScript.RegisterOnWeaponUnembed(UnfreezeGears)
  lockCollision.LuaObjectScript.RegisterOnWeaponUnembedStart(UnfreezeGearsStart)
  axePinFreezeFx = gears:FindSingleGOByName("FrozenRoot_freezeFX")
  axeIceRecallFx = gears:FindSingleGOByName("FrozenRoot_recallFX")
  fx_CartImpact = GameObjects.Large_Cart_Impact
  fx_DoorImpact = GameObjects.Large_Door_Impact
  fx_RockImpact = GameObjects.Large_Rock_Impact
  SoundInit()
  game.SubObject.Sleep(obj)
end
function OnFirstStart(level, obj)
  SetState(0)
  SetCrankFrameRange_Start()
  liftCart:FindSingleGOByName("Rings2"):Hide()
  liftCart:FindSingleGOByName("TraverseLink_CartJump"):HideTraverseLink()
  liftCart:FindSingleGOByName("TraversePath_BuddyBoost"):HideTraversePath()
  liftCart:FindSingleGOByName("TraversePath_BuddyDrop"):HideTraversePath()
  liftCart:FindSingleGOByName("TraverseLink_Mantle263"):HideTraverseLink()
  liftCart:FindSingleGOByName("TraverseLink_Mantle300"):HideTraverseLink()
  liftCart:FindSingleGOByName("Col_ExitWall"):HideCollision()
  liftCart:FindSingleGOByName("Col_StaticWalls"):HideCollision()
  GameObjects.SpeedControl_Up:HideEntityVolume()
  LD.HideFX(fx_CartImpact)
  LD.HideFX(fx_DoorImpact)
  LD.HideFX(fx_RockImpact)
  LD.HideFX(axePinFreezeFx)
  axePinFreezeFx:HideModel()
  LD.HideFX(axeIceRecallFx)
  axeIceRecallFx:HideModel()
  GameObjects.Collision_CollapseWall_Broken1:HideCollision()
  GameObjects.Collision_CollapseWall_Broken2:HideCollision()
  GameObjects.Collision_MonolithStone_Down:HideCollision()
  GameObjects.s_hook_breakable_Cart.Child:HideBehaviors()
  breakableRope:StartAnim("envPeak080RollerCartRope_Stuck")
  breakableRope:JumpAnimToPercent(0)
  breakableRope:PauseAnim()
  game.GameObject.AnimSync(breakableRope, liftCart, 20)
  game.GameObject.AnimSync(liftCart:FindSingleGOByName("Rings"), liftCart, 16)
  GameObjects.Col_CartSClipBlock:HideCollision()
end
function OnStart(level, obj)
  if state < STATE_CART_ATTACHED then
    crankMechanism.LuaObjectScript.SetEaseEnabled(false)
    local counterWeightSlave = {Slave = pulley_counterweight}
    rock.LuaObjectScript.AddSlavesToSynch({counterWeightSlave})
    local counterWeightInteract = rock.LuaObjectScript.GetInteractZone()
    counterWeightInteract:SetHintXZRange(15)
    counterWeightInteract:SetXZRange(3)
    GameObjects.monolithStone00_P.LuaObjectScript.ExcludeSon()
    SetupRollerCartMonitors()
  else
    game.GameObject.AnimSync(liftCart, animDriver_Free, 1)
  end
  GameObjects.InteractZone_SonReleaseCrank.LuaObjectScript.GetInteractZone():SetRequiresSonUnoccupied(true)
  liftClawMonitor = monitors.CreateAnimFrameMonitor(gears)
  liftClawMonitor:OnFrame(300, function()
    IfNotAttachedToClaw(LiftClawReachedFinalState)
  end)
  liftClawMonitor:OnFrameForward(151, SwitchToClawCamera)
  liftClawMonitor:OnFrameBackward(149, SwitchToWeightCamera)
  liftClawMonitor:OnFrameBackward(290, SwitchToClawCamera)
  liftClawMonitor:OnFrameForward(295, SwitchToClawSolveSetupCamera)
end
function OnUpdate(level, obj)
  if camOneShot_LookAtWheel ~= nil then
    camOneShot_LookAtWheel:Update()
  end
  if camOneShot_SpecialAxeRecall ~= nil then
    camOneShot_SpecialAxeRecall:Update()
  end
end
function Debug_PuzzleSolved_CartAttached()
  crankMechanism.LuaObjectScript.SetDrivenObject(GameObjects.liftMechanics00)
  SetState(STATE_CART_ATTACHED)
  crankMechanism.LuaObjectScript.AssignCamera("PLYR_Crank_Wheel_L_CrankFree_Claw_Solve_Cart")
  gears:StartAnim(liftCartAttached_Anim)
  gears:JumpAnimToFrame(0)
  gears:PlayAnimToEnd(-1)
  pulley_counterweight:StartAnim(liftCartAttached_Anim)
  pulley_counterweight:JumpAnimToFrame(0)
  pulley_counterweight:PlayAnimToEnd(-1)
  rock:JumpAnimToFrame(0)
  rock:PauseAnim()
  game.GameObject.AnimSync(rock, rock, 1)
  liftCart:StartAnim(liftCartAttached_Anim)
  liftCart:JumpAnimToFrame(0)
  liftCart:PauseAnim()
  pulley_claw:StartAnim(liftCartAttached_Anim)
  pulley_claw:JumpAnimToFrame(0)
  pulley_claw:PauseAnim()
  rollerCrank.LuaObjectScript.SetDetachedBehavior_FastForward()
  rollerCrank.LuaObjectScript.SetMinStopCycle(1)
  rollerCrank.LuaObjectScript.SetMaxStopCycle(20)
  rollerCrank.LuaObjectScript.SetCurrentCycle(20)
  crankMechanism.LuaObjectScript.SetDrivenObject(GameObjects.animDriver_Free)
  crankMechanism.LuaObjectScript.SetCurrentCycle(0)
  crankMechanism.LuaObjectScript.RecalculateStopFrames()
  crankMechanism.LuaObjectScript.Unlock()
  crankMechanism.LuaObjectScript.Enable()
end
function Debug_Crank_Lock()
  crankMechanism.LuaObjectScript.Lock()
end
function SetupRollerCartMonitors()
  if rollerAnimMonitor == nil then
    rollerAnimMonitor = monitors.CreateAnimFrameMonitor(liftCart)
    rollerAnimMonitor:OnFrameBackward(55, function()
      IfNotAttachedToClaw(EnableSecretCollision)
    end)
    rollerAnimMonitor:OnFrameForward(55, function()
      IfNotAttachedToClaw(DisableSecretCollision)
    end)
    rollerAnimMonitor:OnFrameForward(5, function()
      IfNotAttachedToClaw(CartMovesBanter)
      GameObjects.Col_CartSClipBlock:ShowCollision()
    end)
    rollerAnimMonitor:OnFrameBackward(260, function()
      IfNotAttachedToClaw(function()
        EnableCartNavObstacle()
        DisableTraverseLink263()
        _G.LeadTheWay_210CartUpDownA_Disable()
      end)
    end)
    rollerAnimMonitor:OnFrameForward(262, function()
      IfNotAttachedToClaw(function()
        DisableCartNavObstacle()
        EnableTraverseLink263()
        _G.LeadTheWay_210CartUpDownA_Enable()
        GameObjects.Peak080_Banter.LuaObjectScript.OnTheRightTrack01_Banter()
      end)
    end)
    rollerAnimMonitor:OnFrameBackward(275, function()
      IfNotAttachedToClaw(function()
        EnableTraverseLink263()
        DisableTraverseLink300()
        _G.LeadTheWay_210CartUpDownA_Enable()
        _G.LeadTheWay_210CartUpDownB_Disable()
      end)
    end)
    rollerAnimMonitor:OnFrameForward(277, function()
      IfNotAttachedToClaw(function()
        DisableTraverseLink263()
        EnableTraverseLink300()
        _G.LeadTheWay_210CartUpDownA_Disable()
        _G.LeadTheWay_210CartUpDownB_Enable()
      end)
    end)
    rollerAnimMonitor:OnFrameBackward(308, function()
      IfNotAttachedToClaw(function()
        DisableCartNavObstacle()
        EnableTraverseLink300()
        _G.LeadTheWay_210CartUpDownB_Enable()
      end)
    end)
    rollerAnimMonitor:OnFrameForward(315, function()
      IfNotAttachedToClaw(function()
        EnableCartNavObstacle()
        DisableTraverseLink300()
        _G.LeadTheWay_210CartUpDownB_Disable()
      end)
    end)
    rollerAnimMonitor:OnFrameBackward(480, function()
      IfNotAttachedToClaw(function()
        DisableCartJump()
        _G.LeadTheWay_200CartJumpA_Disable()
      end)
    end)
    rollerAnimMonitor:OnFrameForward(480, function()
      IfNotAttachedToClaw(function()
        EnableCartJump()
        _G.LeadTheWay_200CartJumpA_Enable()
      end)
    end)
    rollerAnimMonitor:OnFrameBackward(515, function()
      IfNotAttachedToClaw(function()
        _G.LeadTheWay_200CartJumpA_Enable()
        _G.LeadTheWay_200CartJumpB_Disable()
      end)
    end)
    rollerAnimMonitor:OnFrameForward(515, function()
      IfNotAttachedToClaw(function()
        _G.LeadTheWay_200CartJumpA_Disable()
        _G.LeadTheWay_200CartJumpB_Enable()
      end)
    end)
    rollerAnimMonitor:OnFrameBackward(530, function()
      IfNotAttachedToClaw(function()
        EnableCartJump()
        _G.LeadTheWay_200CartJumpB_Enable()
      end)
    end)
    rollerAnimMonitor:OnFrameForward(530, function()
      IfNotAttachedToClaw(function()
        DisableCartJump()
        _G.LeadTheWay_200CartJumpB_Disable()
      end)
    end)
    rollerAnimMonitor:OnFrameBackward(560, function()
      IfNotAttachedToClaw(function()
        if not interacted_MonolithStone then
          local banterObj = game.FindLevel("peak200_ChimneyLow"):GetGameObject("Peak200_Banter")
          banterObj:CallScript("Btr_RopeRoomReturn01_Enable")
        end
      end)
    end)
    rollerAnimMonitor:OnFrameForward(630, function()
      IfNotAttachedToClaw(SetForwardMotion)
    end)
    rollerAnimMonitor:OnFrameForward(630, function()
      IfNotAttachedToClaw(function()
        SetForwardMotion()
      end)
    end)
    rollerAnimMonitor:OnFrameBackward(630, function()
      IfNotAttachedToClaw(function()
        SetStationaryMotion()
      end)
    end)
    rollerAnimMonitor:OnFrameBackward(749, function()
      IfNotAttachedToClaw(EnableCartNavObstacle)
    end)
    rollerAnimMonitor:OnFrame(750, function()
      IfNotAttachedToClaw(RollerCartReachedFinalState)
    end)
  end
end
function ClearRollerCartMonitors()
  if rollerAnimMonitor ~= nil then
    rollerAnimMonitor:Stop()
    rollerAnimMonitor:Terminate()
    rollerAnimMonitor = nil
  end
end
function IfNotAttachedToClaw(fn)
  if state < STATE_CART_ATTACHED then
    fn()
  end
end
function SetState(newState)
  state = newState
  if state == STATE_PRE_COLLAPSE then
    gears:StartAnim(crankIntro_Anim)
    gears:JumpAnimToFrame(0)
    gears:PauseAnim()
    rock:StartAnim(crankIntro_Anim)
    rock:JumpAnimToFrame(0)
    rock:PauseAnim()
    pulley_claw:StartAnim(crankIntro_Anim)
    pulley_claw:JumpAnimToFrame(0)
    pulley_claw:PauseAnim()
    pulley_counterweight:StartAnim(crankIntro_Anim .. "1")
    pulley_counterweight:JumpAnimToFrame(0)
    pulley_counterweight:PauseAnim()
    crankMechanism:StartAnim(crankIntro_Anim)
    crankMechanism:JumpAnimToFrame(0)
    crankMechanism:PauseAnim()
    game.GameObject.AnimSync(pulley_counterweight, animDriver_Cine, 1)
    game.GameObject.AnimSync(pulley_claw, animDriver_Cine, 1)
    game.GameObject.AnimSync(rock, animDriver_Cine, 1)
    game.GameObject.AnimSync(gears, animDriver_Cine, 1)
    liftCart:StartAnim(pushCartPath_Anim)
    liftCart:JumpAnimToFrame(0)
    liftCart:PauseAnim()
    rollerCrank.LuaObjectScript.RecalculateStopFrames()
    crankMechanism.LuaObjectScript.SetTotalCycles(12)
    local collapseCamera = "PLYR_Crank_Wheel_L_Post_Collapse"
    crankMechanism.LuaObjectScript.AssignCamera(collapseCamera)
  elseif state == STATE_POST_COLLAPSE_IDLE then
    local peak200CombatScript = game.FindLevel("peak200_ChimneyLow"):FindSingleGameObject("CombatScripts")
    peak200CombatScript:CallScript("StartEncounter02")
    crankMechanism.LuaObjectScript.SetDrivenObject(GameObjects.animDriver_Stuck)
    crankMechanism.LuaObjectScript.Enable()
    gears:ClearAllAnimCallbacks()
    game.GameObject.AnimSync(pulley_claw)
    game.GameObject.AnimSync(pulley_counterweight)
    game.GameObject.AnimSync(rock)
    game.GameObject.AnimSync(gears)
    LD.CallFunctionAfterDelay(function()
      gears:StartAnim(stuckShake_Anim)
      gears:JumpAnimToFrame(0)
      gears:PauseAnim()
      rock:StartAnim(stuckShake_Anim)
      rock:JumpAnimToFrame(0)
      rock:PauseAnim()
      pulley_counterweight:StartAnim(stuckShake_Anim)
      pulley_counterweight:JumpAnimToFrame(0)
      pulley_counterweight:PauseAnim()
    end, 0.25)
    LD.CallFunctionAfterDelay(function()
      game.GameObject.AnimSync(pulley_counterweight, animDriver_Stuck, 0.5)
      game.GameObject.AnimSync(rock, animDriver_Stuck, 0.5)
      game.GameObject.AnimSync(gears, animDriver_Stuck, 1)
    end, 0.5)
    crankMechanism.LuaObjectScript.SetTotalCycles(1)
    crankMechanism.LuaObjectScript.SetRewindTime(1)
    StoreCheckpoint()
    SetUpSound_PostCollapse()
    PlaySound_PostCollapse()
  elseif state == STATE_ROCK_PUSH then
    interacted_MonolithStone = true
    pulley_counterweight:OnAnimDone(thisObj, "SetState_CrankReleased")
  elseif state == STATE_CRANK_FREE then
    if firstFree == false then
      firstFree = true
      rock:ClearAllAnimCallbacks()
      rock.LuaObjectScript.Disable()
      game.GameObject.AnimSync(rock)
      crankMechanism.LuaObjectScript.SetEaseEnabled(true)
      crankMechanism.LuaObjectScript.SetDrivenObject(GameObjects.animDriver_Free)
      gears:StartAnim(liftCartAttached_Anim)
      gears:PauseAnim()
      pulley_counterweight:StartAnim(liftCartAttached_Anim)
      pulley_claw:StartAnim(liftCartAttached_Anim)
      game.GameObject.AnimSync(pulley_counterweight, animDriver_Free, 1)
      game.GameObject.AnimSync(pulley_claw, animDriver_Free, 1)
      game.GameObject.AnimSync(gears, animDriver_Free, 1)
      crankMechanism.LuaObjectScript.SetTotalCycles(12)
      GameObjects.Collision_MonolithStone_Down:ShowCollision()
      StoreCheckpoint()
    end
    if liftCart.AnimFrame == liftCart.AnimLengthFrames then
      EnableMode_PushBlock()
    end
    crankMechanism.LuaObjectScript.SetRewindTime(10)
    SwitchToWeightCamera()
    SetUpSound_CrankFree()
  elseif state == STATE_CART_ATTACHED then
    if firstAttach == false then
      firstAttach = true
      clawReleasedCount = 0
      timer.StartLevelTimer(0.5, function()
        GameObjects.Peak080_Banter.LuaObjectScript.ChainFreezeCartPuzzle06_Banter()
      end)
    end
    if not rollerCrank.LuaObjectScript.PlayerIsAttached() then
      LD.CallFunctionAfterDelay(function()
        EnableMode_LiftCart()
        StoreFinalCheckpoint()
      end, 0.25)
    end
    crankMechanism.LuaObjectScript.SetRewindTime(35)
    PlaySoundClawGrabsCart()
    SetUpSound_CartAttached()
  end
end
function GetState()
  return state
end
function SetState_SonCollapseCrank(level, obj)
  SetState(STATE_COLLAPSE)
end
function SetState_PostCollapse(level, obj)
  SetState(STATE_POST_COLLAPSE_IDLE)
end
function SetState_MoveMonolithStone(level, obj)
  SetState(STATE_ROCK_PUSH)
end
function SetState_CrankReleased(level, obj)
  pulley_counterweight:ClearAllAnimCallbacks()
  SetState(STATE_CRANK_FREE)
end
function SetState_CartAttached(level, obj)
  SetState(STATE_CART_ATTACHED)
end
function SetCrankFrameRange_Start()
  rollerCrank.LuaObjectScript.SetMaxStopCycle(1)
  rollerCrank.LuaObjectScript.SetMinStopCycle(1)
end
function SetForwardMotion()
  SetSoundPushCartCrankMotion_Override()
  rollerCrank.LuaObjectScript.SetDetachedBehavior_FastForward()
  SetSoundPushCartCrankMotion_Forward()
  rollerCrank.LuaObjectScript.PlaySoundOnCrank("SND_MECH_Wooden_Cart_Large_PushPull_Turn")
end
function SetStationaryMotion()
  SetSoundPushCartCrankMotion_Override()
  rollerCrank.LuaObjectScript.SetDetachedBehavior_Stationary()
  SetSoundPushCartCrankMotion_Backward()
end
function RopeBroken()
  ropeBroken = true
  game.GameObject.AnimSync(breakableRope)
  breakableRope:StartAnim("envPeak080RollerCartRope_Break")
  game.Level.SetVariable("PEAK_RopeBroken", true)
  liftCart:FindSingleGOByName("Rings"):Hide()
  liftCart:FindSingleGOByName("Rings2"):Show()
  liftCart:FindSingleGOByName("Rings2"):PlayAnimToEnd()
  GameObjects.Col_CartSClipBlock:HideCollision()
  rollerCrank.LuaObjectScript.SetMaxStopCycle(9)
  GameObjects.Peak080_Banter.LuaObjectScript.FoundCart04_Banter()
  timer.StartLevelTimer(2, function()
    GameObjects.Peak080_Banter.LuaObjectScript.FoundCart04b_Banter()
  end)
  LD.CallFunctionAfterDelay(function()
    if playerInPeak210 and playerArrivedSecondFloor == false then
      GameObjects.Peak080_Banter.LuaObjectScript.GateControl_Banter()
    end
  end, 30)
end
function EnableCartJump()
  liftCart:FindSingleGOByName("TraverseLink_CartJump"):ShowTraverseLink()
  liftCart:FindSingleGOByName("NavObstacle_Cart"):HideNavObstacle()
end
function DisableCartJump()
  liftCart:FindSingleGOByName("TraverseLink_CartJump"):HideTraverseLink()
  liftCart:FindSingleGOByName("NavObstacle_Cart"):ShowNavObstacle()
end
function EnableCartNavObstacle()
  liftCart:FindSingleGOByName("NavObstacle_Cart"):ShowNavObstacle()
  print("ENABLE NAV OBSTACLE ON CART")
end
function DisableCartNavObstacle()
  liftCart:FindSingleGOByName("NavObstacle_Cart"):HideNavObstacle()
  print("DISABLE NAV OBSTACLE ON CART")
end
function DisableTraverseLink263()
  liftCart:FindSingleGOByName("TraverseLink_Mantle263"):HideTraverseLink()
end
function EnableTraverseLink263()
  liftCart:FindSingleGOByName("TraverseLink_Mantle263"):ShowTraverseLink()
end
function DisableTraverseLink300()
  liftCart:FindSingleGOByName("TraverseLink_Mantle300"):HideTraverseLink()
end
function EnableTraverseLink300()
  liftCart:FindSingleGOByName("TraverseLink_Mantle300"):ShowTraverseLink()
end
function EnableSecretCollision()
  GameObjects.Secret_Collision:ShowCollision()
end
function DisableSecretCollision()
  GameObjects.Secret_Collision:HideCollision()
end
function OpenDoorCart()
  rollerCrank.LuaObjectScript.SetMaxStopCycle(20)
  _G.LeadTheWay_200CartGateOpen_Enable()
  doorCartOpen = true
  local LevelPeak210 = game.FindLevel("Peak210_RollerRoomLH")
  LevelPeak210:CallScript("HideRolleZoneExitHint")
  local peak200 = game.FindLevel("Peak200_ChimneyLow")
  peak200:CallScript("Zone_Btr_CartPeak_Disable")
  game.FindLevel("Peak200_ChimneyLow"):GetGameObject("Peak200_Banter"):CallScript("EnableRopeRoomReturn")
  StoreCheckpoint()
  SetUpCartSound_DoorOpen()
  PlaySoundChainCrankFinished()
end
function CloseDoorCart()
  LD.ShowFX(fx_DoorImpact)
end
function InputMask_Elevator()
  pad:DisableGameButton(tweaks.ePad.kPadSquare)
  pad:DisableGameButton(tweaks.ePad.kPadTriangle)
  pad:DisableGameButton(tweaks.ePad.kPadCross)
  pad:DisableGameButton(tweaks.ePad.kPadUp)
  pad:DisableGameButton(tweaks.ePad.kPadLeft)
  pad:DisableGameButton(tweaks.ePad.kPadDown)
  pad:DisableGameButton(tweaks.ePad.kPadRight)
  pad:DisableGameButton(tweaks.ePad.kPadL1)
  pad:DisableGameButton(tweaks.ePad.kPadL2)
  pad:DisableGameButton(tweaks.ePad.kPadL3)
  pad:DisableGameButton(tweaks.ePad.kPadR1)
  pad:DisableGameButton(tweaks.ePad.kPadR2)
end
function ClearInputMask()
  pad:ClearAllDisabledGameButtons()
end
function RollerCartReachedFinalState()
  if GameObjects.liftClaw00_P.Child.AnimFrame == GameObjects.liftClaw00_P.Child.AnimLengthFrames and state == STATE_CRANK_FREE then
    if not rollerCrank.LuaObjectScript.PlayerIsAttached() then
      SetState_CartAttached()
      DisableCartNavObstacle()
    end
  else
    liftCart:FindSingleGOByName("TraverseLinks_CartOnto"):ShowTraverseLink()
    if 1 < clawDownCount then
      timer.StartLevelTimer(0.75, function()
        GameObjects.Peak080_Banter.LuaObjectScript.ChainFreezeCartPuzzle05_Banter()
      end)
    end
  end
end
function LiftClawReachedFinalState()
  if liftCart.AnimFrame == liftCart.AnimLengthFrames and state == STATE_CRANK_FREE then
    SetState_CartAttached()
  end
end
function StoreFinalCheckpoint()
  if finalCheckpointTriggered == false then
    finalCheckpointTriggered = true
    BOOKMARK_09_PeaksPass_028_ElevatorReady()
  end
end
function BOOKMARK_09_PeaksPass_028_ElevatorReady()
  local bookmarks = require("design.Bookmarks")
  local tableEntry = bookmarks["BOOKMARK_" .. "09_PeaksPass_028_ElevatorReady"]
  game.World.StoreCheckpointAndBookmark(tableEntry)
end
function PushCartAtEndEvent()
  if state == STATE_POST_COLLAPSE_IDLE and rollerCrank.LuaObjectScript.GetMaxStopCycle() == 9 then
    PlaySoundPushCartHitDoor()
  end
end
function PushCartOnForwardEvent()
  if rollerCrank.LuaObjectScript.GetCurrentCycle() == 1 then
    LD.BreakObject(GameObjects.Roller_Cart_rope_rocks_P)
    GameObjects.s_hook_breakable_Cart.Child:ShowBehaviors()
  end
end
function PushCartOnAttachedEvent()
  if state == STATE_CART_ATTACHED and liftCart.AnimFrame == liftCart.AnimLengthFrames then
    SetState_CrankReleased()
  end
end
function PushCartOnDetachedEvent()
  if state == STATE_CRANK_FREE then
    local currentCartCycle = rollerCrank.LuaObjectScript.GetCurrentCycle()
    if liftCart.AnimFrame == liftCart.AnimLengthFrames then
      RollerCartReachedFinalState()
    elseif 16 < currentCartCycle and currentCartCycle < 20 then
      liftCart:FindSingleGOByName("TraverseLinks_CartOnto"):HideTraverseLink()
    end
  end
  if state == STATE_POST_COLLAPSE_IDLE and GameObjects.Peak080_Banter.LuaObjectScript.banterPlayed.OnTheRightTrack02 == false and (liftCart.AnimFrame > 100 and liftCart.AnimFrame < 260 or liftCart.AnimFrame > 315 and liftCart.AnimFrame <= 338) then
    timer.StartLevelTimer(1, function()
      GameObjects.Peak080_Banter.LuaObjectScript.OnTheRightTrack02_Banter()
    end)
  end
end
function PushCartOnFastForwardEvent()
  PlaySoundPushCartFastForward()
end
function EnableMode_PushBlock()
  liftCart:FindSingleGOByName("TraverseLinks_CartOnto"):ShowTraverseLink()
  liftCart:FindSingleGOByName("TraversePath_BuddyBoost"):HideTraversePath()
  game.GameObject.AnimSync(liftCart)
  liftCart:FindSingleGOByName("Col_StaticWalls"):HideCollision()
  liftCart:FindSingleGOByName("Col_ExitWall"):HideCollision()
  liftCart:StartAnim(pushCartPath_Anim)
  liftCart:JumpAnimToFrame(liftCart.AnimLengthFrames)
  liftCart:PauseAnim()
  rollerCrank.LuaObjectScript.RecalculateStopFrames()
  SetupRollerCartMonitors()
  _G.SCA_CartRideUpElevator_Ready_Disable()
  GameObjects.NavObstacle_Cart_IsUp:HideNavObstacle()
end
function EnableMode_LiftCart()
  ClearRollerCartMonitors()
  liftCart:FindSingleGOByName("TraverseLinks_CartOnto"):HideTraverseLink()
  liftCart:FindSingleGOByName("TraversePath_BuddyBoost"):ShowTraversePath()
  liftCart:FindSingleGOByName("Col_StaticWalls"):ShowCollision()
  liftCart:StartAnim(liftCartAttached_Anim)
  liftCart:JumpAnimToFrame(liftCart.AnimLengthFrames)
  liftCart:PauseAnim()
  rollerCrank.LuaObjectScript.RecalculateStopFrames()
  game.GameObject.AnimSync(liftCart, animDriver_Free, 1)
  _G.SCA_CartRideUpElevator_Ready_Enable()
  GameObjects.NavObstacle_Cart_IsUp:ShowNavObstacle()
end
function ForceRemoveAxeFromGears()
  LD.ForceAxeUnembed(GameObjects.LockCollision)
end
function ForceRemoveAxeFromGears_IfRopeStuck()
  if state == STATE_POST_COLLAPSE_IDLE then
    ForceRemoveAxeFromGears()
  end
end
function FreezeGears()
  LD.ShowFX(axePinFreezeFx)
  LD.HideFX(axeIceRecallFx)
  axeIceRecallFx:HideModel()
  if state > STATE_PRE_COLLAPSE then
    crankMechanism.LuaObjectScript.Lock()
  end
  if state == STATE_CART_ATTACHED and crankMechanism.LuaObjectScript.GetCurrentCycle() == crankMechanism.LuaObjectScript.GetMaxStopCycle() then
    crankMechanism.LuaObjectScript.RemovePlayerImmediate()
    GameObjects.SCA_CartRideUpElevator_Ready.LuaObjectScript.Enable()
    GameObjects.SCA_CrankStandby.LuaObjectScript.Disable()
    GameObjects.Zone_CrankStandBy_Toggle:HideEntityVolume()
    print("TEST TEST FREEZE")
    liftCart:FindSingleGOByName("TraversePath_BuddyBoost"):ShowTraversePath()
    rollerCrank.LuaObjectScript.Enable()
    timer.StartLevelTimer(1.5, function()
      GameObjects.Peak080_Banter.LuaObjectScript.ChainFreezeCartPuzzle09_Banter()
      StoreFinalCheckpoint()
    end)
  end
  StopSoundOnGears()
  StopSoundOnClaw()
  PlaySound_MachineryFrozen()
end
function UnfreezeGearsStart()
  LD.HideFX(axePinFreezeFx)
  axePinFreezeFx:HideModel()
  LD.ShowFX(axeIceRecallFx)
  axeIceRecallFx:OnAnimDone(thisObj, "HideRecallFX")
  if state == STATE_CART_ATTACHED then
    if player:InsideZone(liftCart) then
      game.SubObject.Wake(thisObj)
      Recenter_FrozenCrank()
      CamOneShot_SpecialAxeRecall()
      timer.StartLevelTimer(kRecenterDuration_FrozenCrank, function()
        CamOneShot_LookAtWheel()
      end)
      GameObjects.NavObstacle_Cart_IsUp:ShowNavObstacle()
      timer.StartLevelTimer(30, Recenter_CloseToTop)
      crankMechanism.LuaObjectScript.Disable()
      game.AI.FindSon():CallScript("ClearBehaviorContext")
      game.Audio.StartMusic("SND_MX_PEAK_chimneylow_puzzle_out")
      timer.StartLevelTimer(26.5, function()
        local peak300 = game.FindLevel("peak300_ChimneyMid")
        if peak300 ~= nil then
          peak300:CallScript("ElevatorSpoolAnimate")
        end
      end)
    end
    liftCart:FindSingleGOByName("TraversePath_BuddyBoost"):HideTraversePath()
    liftCart:FindSingleGOByName("TraversePath_BuddyDrop"):HideTraversePath()
    GameObjects.SCA_CartRideUpElevator_Ready.LuaObjectScript.Disable()
    GameObjects.SCA_CrankStandby.LuaObjectScript.Enable()
    GameObjects.Zone_CrankStandBy_Toggle:ShowEntityVolume()
    print("TEST TEST UNFREEZE")
    rollerCrank.LuaObjectScript.Disable()
  end
  if state > STATE_COLLAPSE then
    crankMechanism.LuaObjectScript.Unlock()
  end
  StopSound_MachineryUnfrozen()
end
function HideRecallFX()
  LD.HideFX(axeIceRecallFx)
  axeIceRecallFx:HideModel()
end
function UnfreezeGears()
  if state == STATE_CART_ATTACHED and player:InsideZone(liftCart) then
    PlaySoundClawLiftStart()
    GameObjects.LockCollision:HideCollision()
    timer.StartLevelTimer(0.2, function()
      GameObjects.SpeedControl_Up:ShowEntityVolume()
      InputMask_Elevator()
      game.AI.FindSon():CallScript("EnterBehaviorContext", "ALERT_BEHAVIOR_CONTEXT_CONFIG")
      game.Player.FindPlayer().Pad:DisableGameButton(tweaks.ePad.kPadSquare)
    end)
    timer.StartLevelTimer(0.375, function()
      GameObjects.Peak080_Banter.LuaObjectScript.ChainFreezeCartPuzzle10_Banter()
    end)
    timer.StartLevelTimer(5, function()
      GameObjects.Peak080_Banter.LuaObjectScript.CartElevatorRide_Banter()
    end)
    timer.StartLevelTimer(35, function()
      GameObjects.SpeedControl_Up:HideEntityVolume()
      game.AI.FindSon():CallScript("ClearBehaviorContext")
      ClearInputMask()
    end)
    local endSyncMonitor = monitors.CreateAnimFrameMonitor(liftCart)
    endSyncMonitor:OnFrame(0, function()
      ElevatorArrivedAtTop()
      game.Player.FindPlayer().Pad:EnableGameButton(tweaks.ePad.kPadSquare)
      crankMechanism.LuaObjectScript.ClearDrivenObject()
      crankMechanism.LuaObjectScript.Disable()
      game.GameObject.AnimSync(liftCart)
      game.GameObject.AnimSync(pulley_counterweight)
      game.GameObject.AnimSync(pulley_claw)
      liftCart:PauseAnim()
      pulley_counterweight:PauseAnim()
      pulley_claw:PauseAnim()
      endSyncMonitor:Stop()
      endSyncMonitor:Terminate()
      endSyncMonitor = nil
    end)
  end
end
function ElevatorArrivedAtTop()
  liftCart:FindSingleGOByName("Col_ExitWall"):HideCollision()
end
function RopeIsBroken()
  return ropeBroken
end
function PreRollerRoom()
  if reached_RollerRoom == false then
    return true
  end
  return false
end
function ExitedRollerRoom()
  playerInPeak210 = false
end
function ArrivedSecondFloor()
  playerArrivedSecondFloor = true
end
function PlayerReachedRollerRoom()
  playerInPeak210 = true
  if reached_RollerRoom == false then
    reached_RollerRoom = true
  end
end
function PlayerReachedMonolithStone()
  reached_MonolithStone = true
end
function PlayerLeftMonolithStone_NoInteract()
  if reached_MonolithStone == true and interacted_MonolithStone == false then
    GameObjects.Peak080_Banter.LuaObjectScript.LooksHeavy04_Banter()
  end
end
function CartMovesBanter()
  GameObjects.Peak080_Banter.LuaObjectScript.FoundCart03_Banter()
end
function WheelCrankAtBeginningEvent()
  PlaySoundCounterweightDown()
  StopSoundOnClaw()
  StopSoundOnGears()
end
function WheelCrankAtEndEvent()
  if state == STATE_CRANK_FREE then
    clawDownCount = clawDownCount + 1
  elseif state == STATE_CART_ATTACHED then
    crankMechanism.LuaObjectScript.Enable()
    LD.ShowFX(fx_CartImpact)
  end
  if rocksCrumbled == false and state == STATE_POST_COLLAPSE_IDLE then
    rocksCrumbled = true
    GameObjects.peak200_rock_slide_break.Child:JumpAnimToFrame(285)
    GameObjects.peak200_rock_slide_break.Child:PlayAnimToEnd(0.75)
    LD.PlaySound(GameObjects.peak200_rock_slide_break.Child.SoundEmitters[1], "SND_MECH_Counterweight_Rocks_Collapse_Peak200")
    GameObjects.Collision_CollapseWall_Broken1:HideCollision()
    GameObjects.Collision_CollapseWall_Broken2:ShowCollision()
    local peak200CombatScript = game.FindLevel("peak200_ChimneyLow"):FindSingleGameObject("CombatScripts")
    peak200CombatScript:CallScript("StartFight_PostRocksCrumbled")
    _G.LeadTheWay_200PathTo260_Enable()
    GameObjects.SCA_PostUp_AfterCrash.LuaObjectScript.Enable()
  end
  if state > STATE_POST_COLLAPSE_IDLE then
    StartBounceAnim()
  end
  StopSwayAnim()
  if state == STATE_POST_COLLAPSE_IDLE then
    PlaySoundGearsStuck()
  end
  StopSoundOnClaw()
  StopSoundOnGears()
end
function WheelCrankOnAttachedEvent()
  if state == STATE_POST_COLLAPSE_IDLE then
    if rock:GetAnimationName() ~= stuckShake_Anim then
      rock:StartAnim(stuckShake_Anim)
      rock:PauseAnim()
      game.GameObject.AnimSync(rock, animDriver_Stuck, 0.5)
    end
    if pulley_counterweight:GetAnimationName() ~= stuckShake_Anim then
      pulley_counterweight:StartAnim(stuckShake_Anim)
      pulley_counterweight:PauseAnim()
      game.GameObject.AnimSync(pulley_counterweight, animDriver_Stuck, 0.5)
    end
  end
  StopSoundOnClaw()
  StopSoundOnGears()
end
function WheelCrankOnDetachedEvent()
  if state == STATE_CRANK_FREE or state == STATE_CART_ATTACHED then
    StopSwayAnim()
  end
end
function WheelCrankOnForwardEvent()
  if state == STATE_POST_COLLAPSE_IDLE and rocksCrumbled == false then
    game.UI.Idle(true)
    LD.CallFunctionAfterDelay(function()
      crankMechanism.LuaObjectScript.RemovePlayerImmediate()
      game.UI.Idle(false)
    end, 4)
  end
  if state == STATE_CRANK_FREE then
    if crankMechanism.LuaObjectScript.GetCurrentCycle() == 2 then
      GameObjects.Peak080_Banter.LuaObjectScript.ChainFreezeCartPuzzle01_Banter()
    elseif crankMechanism.LuaObjectScript.GetCurrentCycle() == crankMechanism.LuaObjectScript.GetMaxStopCycle() then
      GameObjects.Peak080_Banter.LuaObjectScript.ChainFreezeCartPuzzle02_Banter()
    end
  end
  if crankMechanism.LuaObjectScript.GetCurrentCycle() == crankMechanism.LuaObjectScript.GetMaxStopCycle() then
    StopSwayAnim()
  end
  if state == STATE_PRE_COLLAPSE or state == STATE_POST_COLLAPSE_IDLE then
    game.FindLevel("Peak200_ChimneyLow"):GetGameObject("Peak200_Banter"):CallScript("PullCrank")
  end
  if state > STATE_POST_COLLAPSE_IDLE then
    PlaySoundClawForward()
    PlaySoundGearsDown()
  end
end
function WheelCrankOnBackwardEvent()
  if state > STATE_POST_COLLAPSE_IDLE then
    PlaySoundClawBackward()
    PlaySoundGearsUp()
  end
end
function WheelCrankOnRewindEvent()
  if state > STATE_POST_COLLAPSE_IDLE then
    PlaySoundClawRewind()
    PlaySoundGearsUp()
  end
  if state == STATE_CRANK_FREE then
    clawReleasedCount = clawReleasedCount + 1
    if clawReleasedCount == 1 then
      LD.CallFunctionAfterDelay(function()
        GameObjects.Peak080_Banter.LuaObjectScript.ChainFreezeCartPuzzle03_Banter()
      end, 0.75)
    elseif 2 <= clawReleasedCount then
      LD.CallFunctionAfterDelay(function()
        GameObjects.Peak080_Banter.LuaObjectScript.ChainFreezeCartPuzzle04_Banter()
      end, 1)
    end
  elseif state == STATE_CART_ATTACHED and player:InsideZone(liftCart) == false then
    clawReleasedCount = clawReleasedCount + 1
    if clawReleasedCount == 1 then
      LD.CallFunctionAfterDelay(function()
        GameObjects.Peak080_Banter.LuaObjectScript.ChainFreezeCartPuzzle07_Banter()
      end, 0.5)
    elseif clawReleasedCount == 2 then
      LD.CallFunctionAfterDelay(function()
        GameObjects.Peak080_Banter.LuaObjectScript.ChainFreezeCartPuzzle08_Banter()
      end, 0.5)
    elseif 3 <= clawReleasedCount then
      LD.CallFunctionAfterDelay(function()
        GameObjects.Peak080_Banter.LuaObjectScript.ChainFreezeCartPuzzle08_B_Banter()
      end, 0.5)
    end
  end
end
function WheelCrankOnFastForward()
end
function WheelCrankOnPauseEvent()
  local maxCycle = crankMechanism.LuaObjectScript.GetMaxStopCycle
  local minCycle = crankMechanism.LuaObjectScript.GetMinStopCycle()
  local currCycle = crankMechanism.LuaObjectScript.GetCurrentCycle()
  if currCycle ~= maxCycle and currCycle ~= minCycle and state > STATE_POST_COLLAPSE_IDLE then
    StartBounceAnim()
    StartSwayAnim()
  end
  StopSoundOnClaw()
  StopSoundOnGears()
end
function StartBounceAnim()
  GameObjects.settleAnimGroup:JumpAnimToPercent(0)
  GameObjects.settleAnimGroup:PlayAnimToEnd()
end
function StartSwayAnim()
end
function StopSwayAnim()
  if state == STATE_CRANK_FREE or state == STATE_CART_ATTACHED then
    local targetFrame
    local playRate = 1
    local staticFrames = {
      0,
      160,
      320
    }
    local currentFrame = GameObjects.SwayAnimGroup.AnimFrame
    local maxDif = GameObjects.SwayAnimGroup.AnimLengthFrames
    for _, f in pairs(staticFrames) do
      if currentFrame == f then
        GameObjects.SwayAnimGroup:PauseAnim()
        return
      end
      if maxDif > math.abs(currentFrame - f) then
        targetFrame = f
        maxDif = math.abs(currentFrame - f)
      end
    end
    if currentFrame > targetFrame then
      playRate = playRate * -1
    end
    GameObjects.SwayAnimGroup:PlayAnimToFrame(targetFrame, playRate)
  end
end
function StartMonolithAttempt()
  game.GameObject.AnimSync(rock)
  game.GameObject.AnimSync(pulley_counterweight)
  LD.CallFunctionAfterDelay(function()
    local warpObj = GameObjects.SonWarp_MonolithStone
    local warpJointIndex = warpObj:GetJointIndex("warpLoc")
    local warpPos = warpObj:GetWorldJointPosition(warpJointIndex)
    local warpDir = warpObj:GetWorldJointForward(warpJointIndex)
    son:Warp(warpPos, warpDir)
  end, 2)
  timer.StartLevelTimer(2.75, function()
    GameObjects.Peak080_Banter.LuaObjectScript.LooksHeavy02_Banter()
  end)
end
function Event_OnRockHitGround()
  PlaySound_LiftRelease()
  LD.ShowFX(fx_RockImpact)
end
function ChainPulleyOnForwardEvent()
  if GameObjects.ChainPull_DoorCart.LuaObjectScript.GetCurrentCycle() > 1 then
    GameObjects.Peak080_Banter.LuaObjectScript.OpenCartGate_Banter()
  end
end
local counterweightEmitter, liftClawEmitter, liftGearsEmitter, rockEmitter, chainCrankEmitter, liftMechanicsFrozenEmitter
local wheelCrankDrivenObjectSound_Override_PostCollapse = {
  OnStuckAtEnd = "",
  OnStuckAtStart = "",
  OnEnd = "",
  OnReturnToStart = "",
  OnForward = "",
  OnBackward = "",
  OnFastForward = "",
  OnRewind = ""
}
local wheelCrankDrivenObjectSound_Override_CrankFree = {
  OnStuckAtEnd = "",
  OnStuckAtStart = "",
  OnEnd = "",
  OnReturnToStart = "",
  OnForward = "",
  OnBackward = "",
  OnFastForward = "",
  OnRewind = ""
}
local wheelCrankDrivenObjectSound_Override_CartAttached = {
  OnStuckAtEnd = "",
  OnStuckAtStart = "",
  OnEnd = "",
  OnReturnToStart = "",
  OnForward = "",
  OnBackward = "",
  OnFastForward = "",
  OnRewind = ""
}
local liftClawSounds = {
  OnForward = "",
  OnBackward = "",
  OnFastForward = "",
  OnRewind = ""
}
local liftClawSounds_Override_CrankFree = {
  OnForward = "SND_MECH_Claw_Lift_Moving_Down_Platform_LP",
  OnBackward = "SND_MECH_Claw_Lift_Moving_Up_Empty_Platform_LP",
  OnFastForward = "SND_MECH_Claw_Lift_Moving_Down_Platform_LP",
  OnRewind = "SND_MECH_Claw_Lift_Moving_Up_Empty_Platform_LP"
}
local liftClawSounds_Override_CartAttached = {
  OnForward = "SND_MECH_Claw_Lift_Moving_Kratos_Onboard_Platform_LP",
  OnBackward = "SND_MECH_Claw_Lift_Moving_Kratos_Onboard_Platform_LP",
  OnFastForward = "SND_MECH_Claw_Lift_Moving_Kratos_Onboard_Platform_LP",
  OnRewind = "SND_MECH_Claw_Lift_Moving_Kratos_Onboard_Platform_LP"
}
local counterweightSounds = {
  OnUp = "SND_MECH_Counterweight_Up_Peak200",
  OnDown = "SND_MECH_Counterweight_Drop_Peak200"
}
local liftGearsSounds = {
  OnStuck = "",
  OnUp = "",
  OnDown = ""
}
local liftGearsSounds_Override_PostCollapse = {
  OnStuck = "SND_MECH_Claw_Lift_Stuck",
  OnUp = "",
  OnDown = ""
}
local liftGearsSounds_Override_CrankFree = {
  OnStuck = "",
  OnUp = "SND_MECH_Claw_Lift_Moving_Up_Empty_Gears_LP",
  OnDown = "SND_MECH_Claw_Lift_Moving_Down_Gears_LP"
}
local liftGearsSounds_Override_CartAttached = {
  OnStuck = "",
  OnUp = "SND_MECH_Claw_Lift_Moving_Kratos_Onboard_Gears_LP",
  OnDown = "SND_MECH_Claw_Lift_Moving_Kratos_Onboard_Gears_LP"
}
local cartLineCrankSoundOverridesDoorClosed = {
  OnStart = "",
  OnReturnToStart = "SND_MECH_Wooden_Cart_Large_PushPull_Stuck",
  OnForward = "SND_MECH_Wooden_Cart_Large_PushPull_Moving_LP",
  OnForwardLoop = "",
  OnFirstForward = "",
  OnBackward = "SND_MECH_Wooden_Cart_Large_PushPull_Moving_LP",
  OnBackwardLoop = "",
  OnFirstBackward = "",
  OnFastForward = "SND_MECH_Wooden_Cart_Large_PushPull_Moving_LP",
  OnRewind = "SND_MECH_Wooden_Cart_Large_PushPull_Moving_LP",
  OnEnd = "SND_MECH_Wooden_Cart_Large_PushPull_Hit_Gate",
  OnStuckAtEnd = "SND_MECH_Wooden_Cart_Large_PushPull_In_Place",
  OnStuckAtStart = "SND_MECH_Wooden_Cart_Large_PushPull_In_Place"
}
local cartLineCrankSoundOverridesDoorOpen = {
  OnStart = "",
  OnReturnToStart = "SND_MECH_Wooden_Cart_Large_PushPull_Stuck",
  OnForward = "SND_MECH_Wooden_Cart_Large_PushPull_Moving_LP",
  OnForwardLoop = "",
  OnFirstForward = "",
  OnBackward = "SND_MECH_Wooden_Cart_Large_PushPull_Moving_LP",
  OnBackwardLoop = "",
  OnFirstBackward = "",
  OnFastForward = "SND_MECH_Wooden_Cart_Large_PushPull_Moving_LP",
  OnRewind = "SND_MECH_Wooden_Cart_Large_PushPull_Moving_LP",
  OnEnd = "SND_MECH_Wooden_Cart_Large_PushPull_CantMove",
  OnStuckAtEnd = "SND_MECH_Wooden_Cart_Large_PushPull_CantMove",
  OnStuckAtStart = "SND_MECH_Wooden_Cart_Large_PushPull_In_Place"
}
function SoundInit()
  crankMechanism.LuaObjectScript.DrivenObjectSoundSetup({
    SoundEmitter = gears:FindSingleSoundEmitterByName("SNDLiftMechanics00")
  })
  liftClawEmitter = pulley_claw:FindSingleSoundEmitterByName("SNDLiftClaw00")
  liftGearsEmitter = GameObjects.SNDChain:FindSingleSoundEmitterByName("SNDChain200to300")
  counterweightEmitter = pulley_counterweight:FindSingleSoundEmitterByName("SNDCounterweight")
  rollerCrank.LuaObjectScript.CrankSoundSetup(cartLineCrankSoundOverridesDoorClosed)
  rockEmitter = rock:FindSingleSoundEmitterByName("SNDMonolithStone00")
  chainCrankEmitter = GameObjects.ChainPull_DoorCart.Child:FindSingleSoundEmitterByName("SNDBasicCrankObject")
  liftMechanicsFrozenEmitter = gears:FindSingleSoundEmitterByName("SNDFrozenMachinery")
end
function RestoreSoundOverrides()
  if state == STATE_POST_COLLAPSE_IDLE then
    SetUpSound_PostCollapse()
  elseif state == STATE_CRANK_FREE then
    SetUpSound_CrankFree()
  elseif state == STATE_CART_ATTACHED then
    SetUpSound_CartAttached()
  end
  if doorCartOpen then
    SetUpCartSound_DoorOpen()
  end
end
function PlaySound_PostCollapse()
  crankMechanism.LuaObjectScript.PlaySoundOnDrivenObject("SND_MECH_Chimney_Lift_Platform_B_Stuck_Impact")
end
function PlaySound_LiftRelease()
  LD.PlaySound(liftGearsEmitter, "SND_MECH_Claw_Lift_Release")
end
function PlaySound_MachineryFrozen()
  LD.PlaySound(liftMechanicsFrozenEmitter, "SND_WPN_Axe_Hit_Freeze_Object_LP")
end
function StopSound_MachineryUnfrozen()
  LD.StopSound(liftMechanicsFrozenEmitter, "SND_WPN_Axe_Hit_Freeze_Object_LP")
end
function SetUpSound_PostCollapse()
  SoundInitCounterweightStuckSoundMonitor()
  SetUpCrankSound_PostCollapse()
  SetUpGearsSound_PostCollapse()
end
function SetUpSound_CrankFree()
  SoundClearCounterwightStuckSoundMonitor()
  SetUpCrankSound_CrankFree()
  SetUpClawSound_CrankFree()
  SetUpGearsSound_CrankFree()
end
function SetUpSound_CartAttached()
  SetUpCrankSound_CartAttached()
  SetUpClawSound_CartAttached()
  SetUpGearsSound_CartAttached()
end
function SetUpCrankSound_PostCollapse()
  crankMechanism.LuaObjectScript.DrivenObjectSoundSetup(wheelCrankDrivenObjectSound_Override_PostCollapse)
end
function SetUpCrankSound_CrankFree()
  crankMechanism.LuaObjectScript.DrivenObjectSoundSetup(wheelCrankDrivenObjectSound_Override_CrankFree)
end
function SetUpCrankSound_CartAttached()
  crankMechanism.LuaObjectScript.DrivenObjectSoundSetup(wheelCrankDrivenObjectSound_Override_CartAttached)
end
local sound_clawMotion
function PlaySoundClawGrabsCart()
  StopSoundOnGears()
  StopSoundOnClaw()
  LD.PlaySound(liftClawEmitter, "SND_MECH_Claw_Lift_Claw_Grabs_Crate")
end
function sound_SetClawMotion(clawMotion)
  sound_clawMotion = clawMotion
end
function PlaySoundClawForward()
  if sound_clawMotion ~= "forward" then
    sound_SetClawMotion("forward")
    LD.PlaySound(liftClawEmitter, liftClawSounds.OnForward)
  end
end
function StopSoundClawForward()
  LD.StopSound(liftClawEmitter, liftClawSounds.OnForward)
  if state == STATE_CART_ATTACHED and pulley_claw.AnimFrame > 290 then
    LD.PlaySound(liftClawEmitter, "SND_MECH_Claw_Lift_Moving_Hits_Ground")
  end
end
function PlaySoundClawBackward()
  if sound_clawMotion ~= "backward" then
    sound_SetClawMotion("backward")
    LD.PlaySound(liftClawEmitter, liftClawSounds.OnBackward)
  end
end
function StopSoundClawBackward()
  LD.StopSound(liftClawEmitter, liftClawSounds.OnBackward)
end
function StopSoundClawFastForward()
  LD.StopSound(liftClawEmitter, liftClawSounds.OnFastForward)
end
function PlaySoundClawRewind()
  if sound_clawMotion ~= "rewind" then
    sound_SetClawMotion("rewind")
    LD.PlaySound(liftClawEmitter, liftClawSounds.OnRewind)
  end
end
function StopSoundClawRewind()
  LD.StopSound(liftClawEmitter, liftClawSounds.OnRewind)
end
function StopSoundOnClaw()
  if sound_clawMotion == "forward" then
    StopSoundClawForward()
  elseif sound_clawMotion == "backward" then
    StopSoundClawBackward()
  elseif sound_clawMotion == "rewind" then
    StopSoundClawRewind()
  end
  sound_clawMotion = "stopped"
end
function SetUpClawSound_CrankFree()
  liftClawSounds = liftClawSounds_Override_CrankFree
end
function SetUpClawSound_CartAttached()
  liftClawSounds = liftClawSounds_Override_CartAttached
end
function PlaySoundGearsStuck()
  LD.PlaySound(liftGearsEmitter, liftGearsSounds.OnStuck)
end
function PlaySoundGearsUp()
  LD.PlaySound(liftGearsEmitter, liftGearsSounds.OnUp)
end
function PlaySoundGearsDown()
  LD.PlaySound(liftGearsEmitter, liftGearsSounds.OnDown)
end
function StopSoundOnGears()
  LD.StopSound(liftGearsEmitter, liftGearsSounds.OnUp)
  LD.StopSound(liftGearsEmitter, liftGearsSounds.OnDown)
end
function SetUpGearsSound_PostCollapse()
  liftGearsSounds = liftGearsSounds_Override_PostCollapse
end
function SetUpGearsSound_CrankFree()
  liftGearsSounds = liftGearsSounds_Override_CrankFree
end
function SetUpGearsSound_CartAttached()
  liftGearsSounds = liftGearsSounds_Override_CartAttached
end
local counterweightStuckSoundMonitor
function SoundInitCounterweightStuckSoundMonitor()
  SoundClearCounterwightStuckSoundMonitor()
  counterweightStuckSoundMonitor = monitors.CreateAnimFrameMonitor(pulley_counterweight)
  counterweightStuckSoundMonitor:OnFrameForward(16, PlaySoundCounterweightUp)
end
function SoundClearCounterwightStuckSoundMonitor()
  if counterweightStuckSoundMonitor ~= nil then
    counterweightStuckSoundMonitor:Stop()
    counterweightStuckSoundMonitor:Terminate()
    counterweightStuckSoundMonitor = nil
  end
end
function PlaySoundCounterweightUp()
  LD.PlaySound(counterweightEmitter, counterweightSounds.OnUp)
end
function PlaySoundCounterweightDown()
  LD.PlaySound(counterweightEmitter, counterweightSounds.OnDown)
end
function SetUpCartSound_DoorOpen()
  rollerCrank.LuaObjectScript.CrankSoundSetup(cartLineCrankSoundOverridesDoorOpen)
end
function SetSoundPushCartCrankMotion_Override()
  SetSoundPushCartCrankMotion("override")
end
function SetSoundPushCartCrankMotion_Forward()
  SetSoundPushCartCrankMotion("forward")
end
function SetSoundPushCartCrankMotion_Backward()
  SetSoundPushCartCrankMotion("backward")
end
function SetSoundPushCartCrankMotion(newMotion)
  if newMotion ~= nil then
    rollerCrank.LuaObjectScript.SetCrankMotion(newMotion)
  end
end
function PlaySoundPushCartFastForward()
  rollerCrank.LuaObjectScript.PlaySoundOnCrank(cartLineCrankSoundOverridesDoorClosed.OnFastForward)
end
function PlaySoundPushCartHitDoor()
  rollerCrank.LuaObjectScript.PlaySoundOnCrank(cartLineCrankSoundOverridesDoorClosed.OnEnd)
end
function PlaySoundClawLiftStart()
  LD.PlaySound(liftClawEmitter, "SND_MECH_Claw_Lift_Moving_Released_Start")
end
function LuaHook_RockLiftStart(ai, data)
  LD.PlaySound(rockEmitter, "SND_TNF_Stone_Lift_Peak200_Lift_Up")
end
function LuaHook_RockLiftUp(ai, data)
  LD.PlaySound(rockEmitter, "SND_TNF_Stone_Lift_Peak200_Lift_Up_High")
  LD.StopSound(rockEmitter, "SND_TNF_Stone_Lift_Peak200_Stress_LP")
end
function LuaHook_RockLiftWin(ai, data)
  LD.PlaySound(rockEmitter, "SND_TNF_Stone_Lift_Peak200_Push_Out")
  LD.StopSound(rockEmitter, "SND_TNF_Stone_Lift_Peak200_Stress_LP")
  timer.StartLevelTimer(4.1, function()
    GameObjects.Peak080_Banter.LuaObjectScript.LooksHeavy03_Banter()
  end)
end
function LuaHook_RockLiftStruggle(ai, data)
  LD.PlaySound(rockEmitter, "SND_TNF_Stone_Lift_Peak200_Stress_LP")
end
function LuaHook_RockLiftFail(ai, data)
  LD.PlaySound(rockEmitter, "SND_TNF_Stone_Lift_Peak200_Drop_Down_s1")
  LD.StopSound(rockEmitter, "SND_TNF_Stone_Lift_Peak200_Stress_LP")
end
function LuaHook_RockLiftFail2(ai, data)
  LD.PlaySound(rockEmitter, "SND_TNF_Stone_Lift_Peak200_Drop_Down_s2")
  LD.StopSound(rockEmitter, "SND_TNF_Stone_Lift_Peak200_Stress_LP")
end
function PlaySoundRockPushSuccess()
  LD.PlaySoundOnFrame(rockEmitter, rock, "SND_MECH_Stone_Lift_Peak200_Push_Out", 0, "Forward")
  LD.PlaySoundOnFrame(liftGearsEmitter, pulley_counterweight, "SND_MECH_Claw_Lift_Release", 0, "Forward")
end
function PlaySoundChainCrankFinished()
  LD.PlaySound(chainCrankEmitter, "SND_EVNT_Peaks_Pass_ChainPull_1_Close")
end
function StoreCheckpoint()
  game.World.StoreCheckpoint()
end
function OnSaveCheckpoint(level, obj)
  return {
    state = state,
    rocksCrumbled = rocksCrumbled,
    clawDownCount = clawDownCount,
    clawReleasedCount = clawReleasedCount,
    reached_RollerRoom = reached_RollerRoom,
    reached_MonolithStone = reached_MonolithStone,
    interacted_MonolithStone = interacted_MonolithStone,
    ropeBroken = ropeBroken,
    finalCheckpointTriggered = finalCheckpointTriggered,
    playerInPeak210 = playerInPeak210,
    firstAttach = firstAttach,
    firstFree = firstFree,
    doorCartOpen = doorCartOpen
  }
end
function OnRestoreCheckpoint(level, obj, savedInfo)
  state = savedInfo.state
  rocksCrumbled = savedInfo.rocksCrumbled
  clawDownCount = savedInfo.clawDownCount
  clawReleasedCount = savedInfo.clawReleasedCount
  reached_RollerRoom = savedInfo.reached_RollerRoom
  reached_MonolithStone = savedInfo.reached_MonolithStone
  interacted_MonolithStone = savedInfo.interacted_MonolithStone
  ropeBroken = savedInfo.ropeBroken
  finalCheckpointTriggered = savedInfo.finalCheckpointTriggered
  playerInPeak210 = savedInfo.playerInPeak210
  firstAttach = savedInfo.firstAttach
  firstFree = savedInfo.firstFree
  doorCartOpen = savedInfo.doorCartOpen
  RestoreSoundOverrides()
end
function SetCamera(onStartState)
  local state = onStartState
  local camera
  if state < STATE_ROCK_PUSH then
    camera = "PLYR_Crank_Wheel_L_Post_Collapse"
  elseif state == STATE_CRANK_FREE then
    if gears.AnimFrame < 151 then
      camera = "PLYR_Crank_Wheel_L_CrankFree_Weight"
    elseif gears.AnimFrame >= 295 then
      camera = "PLYR_Crank_Wheel_L_CrankFree_Claw_Solve"
    else
      camera = "PLYR_Crank_Wheel_L_CrankFree_Claw"
    end
  elseif state == STATE_CART_ATTACHED then
    camera = "PLYR_Crank_Wheel_L_CrankFree_Claw_Solve_Cart"
  end
  crankMechanism.LuaObjectScript.AssignCamera(camera)
end
function SwitchToClawCamera()
  if state > STATE_ROCK_PUSH then
    local crankFreeCamera = "PLYR_Crank_Wheel_L_CrankFree_Claw"
    crankMechanism.LuaObjectScript.AssignCamera(crankFreeCamera)
  end
end
function SwitchToWeightCamera()
  if state > STATE_ROCK_PUSH then
    local crankFreeCamera = "PLYR_Crank_Wheel_L_CrankFree_Weight"
    crankMechanism.LuaObjectScript.AssignCamera(crankFreeCamera)
  end
end
function SwitchToClawSolveSetupCamera()
  local crankFreeCamera
  if state > STATE_ROCK_PUSH and state < STATE_CART_ATTACHED then
    crankFreeCamera = "PLYR_Crank_Wheel_L_CrankFree_Claw_Solve"
  elseif state == STATE_CART_ATTACHED then
    crankFreeCamera = "PLYR_Crank_Wheel_L_CrankFree_Claw_Solve_Cart"
  end
  if crankFreeCamera ~= nil then
    crankMechanism.LuaObjectScript.AssignCamera(crankFreeCamera)
  end
end
function DestroyOneShot_SpecialAxeRecall()
  camOneShot_SpecialAxeRecall = nil
end
function CamOneShot_SpecialAxeRecall()
  camOneShot_SpecialAxeRecall = CCOS.OneShotCamera.New("PLYR_RTT_FrozenCrank", 3)
  camOneShot_SpecialAxeRecall:SetCallback(DestroyOneShot_SpecialAxeRecall)
  camOneShot_SpecialAxeRecall:Start()
  timer.StartLevelTimer(0, function()
    CSL.PlayShake("FSE_SWAY_BOUYANT_ZIPLINE_NORMAL", 8, 0.8, 4.2)
  end)
end
function DestroyOneShot_LookAtWheel()
  camOneShot_LookAtWheel = nil
  game.SubObject.Sleep(thisObj)
end
function CamOneShot_LookAtWheel()
  camOneShot_LookAtWheel = CCOS.OneShotCamera.New("ENV_PeaksCartElevatorUp", 4.2)
  camOneShot_LookAtWheel:SetCallback(DestroyOneShot_LookAtWheel)
  camOneShot_LookAtWheel:Start()
end
function Recenter_CloseToTop()
  local recenterTable = {
    RotationSpace = 1,
    TimeStart = 0,
    TimeDuration = 4.2,
    LockRecenter = 0,
    YawRange = -1,
    TriggerLeft = -145,
    ReturnLeft = -178,
    ReturnRight = 168,
    TriggerRight = 160,
    PitchRange = -1,
    TriggerUp = 7,
    ReturnUp = 5,
    ReturnDown = 3,
    TriggerDown = 1
  }
  game.Camera.Recenter(recenterTable)
end
function Recenter_FrozenCrank()
  local recenterTable = {
    RotationSpace = 1,
    TimeStart = 0,
    TimeDuration = kRecenterDuration_FrozenCrank,
    LockRecenter = 0.2,
    PitchRange = -1,
    TriggerUp = 90,
    ReturnUp = -4,
    ReturnDown = -4,
    TriggerDown = -5,
    YawRange = -1,
    TriggerLeft = 0,
    ReturnLeft = 88,
    ReturnRight = 88,
    TriggerRight = 0
  }
  timer.StartLevelTimer(0, function()
    game.Camera.Recenter(recenterTable)
  end)
end
