local LD = require("design.LevelDesignLibrary")
local EC = require("design.Encounter")
local PupLib = require("design.PuppeteerLibrary")
local timer = require("level.timer")
local uiCalls = require("ui.uicalls")
local monitors = require("level.MonitorLibrary")
local checkpoint = require("level.checkpoint")
local CCOS = require("camera.camera_oneshot")
local TUT = require("game.GlobalTutorials")
local CSL = require("camera.shakelibrary")
local thisLevel, player, son
local TemLtDoorUnlocked = false
local TemRtDoorUnlocked = false
local BridgeJumpUnlocked = false
local zonereportentered = false
local thorpiecesbroken = 0
local dragonshrinesbroken
local SonLeverPulled = false
local SecretGateBoost, SecretGateMantle
local ToggleForkIdle = false
local Shortcut_02_Unlocked = false
local shortcut_03_Unlocked = false
local gapJumpBouldersGone = false
local chainDrop_unlocked = false
local chainDrop_beach_unlocked = false
local camOneShot_LookAtSolvedLeftRunes, camOneShot_LookAtSolvedRightRunes, camOneShot_PushInLeft, camOneShot_PushInRight
local DragonRune01Unlocked = false
local DragonRune02Unlocked = false
local DragonRune03Unlocked = false
local DragonMarkersDestroyed = false
local dragonShrinesBroken = 0
local BridgeBombs
local dragonShrineEnabled = false
local TakeOffWhoosh, attackZoneMortar, attackZoneBreath, PuzzleR_Bars, PuzzleL_Bars
local StatuePuzzleSolved = false
local runeTable, FlipperTable
local rightbeamsunlocked = false
local leftbeamsunlocked = false
local templedoorsunlocked = false
local runedoorcounter = 0
local RightSpear, LeftSpear, TempleEntDoor, SecretGate01, BridgeGapJump
local FireBreathStarted = false
local bombsActive = false
local TriggerRuneSideZone, WaitExploreZone
local RightRuneHinted = false
local LeftFlipperHit = false
local RightFlipperHit = false
local leftSpinnerSolved = false
local rightSpinnerSolved = false
local GateStimTriggered = false
local xpl200DragonFree = false
local musicStage = 0
function OnScriptLoaded(level)
  thisLevel = level
  player = game.Player.FindPlayer()
  son = game.AI.FindSon()
  SoundInit()
  RightSpear = level:GetGameObject("RightSpear")
  LeftSpear = level:GetGameObject("LeftSpear")
  TempleEntDoor = level:GetGameObject("TempleEntDoor")
  runeTable = {}
  runeTable[1] = 13
  runeTable[2] = 1
  runeTable[3] = 29
  runeTable[4] = 21
  FlipperTable = {}
  for i = 1, 4 do
    table.insert(FlipperTable, level:GetGameObject("SpearFlipper0" .. tostring(i)))
  end
  PuzzleR_Bars = level:GetGameObject("PuzzleR_Bars")
  PuzzleL_Bars = level:GetGameObject("PuzzleL_Bars")
  SecretGate01 = level:GetGameObject("SecretGate01")
  SecretGateMantle = level:GetGameObject("SecretGateMantle")
  BridgeGapJump = level:GetGameObject("BridgeGapJump")
  BridgeBombs = level:GetGameObject("BridgeBombs")
  SecretGateBoost = level:GetGameObject("SecretGateBoost")
  TakeOffWhoosh = level:GetGameObject("BaldurDragon_TakeOffWhoosh_01")
  attackZoneBreath = level:GetGameObject("attackZoneBreath")
  attackZoneMortar = level:GetGameObject("attackZoneMortar")
  TriggerRuneSideZone = level:GetGameObject("TriggerRuneSideZone")
  WaitExploreZone = level:GetGameObject("WaitExploreZone")
end
function OnPreStart(level, obj)
  if SonLeverPulled == true then
    GameObjects.SecretGateChain.LuaObjectScript.ClearDrivenObject()
  end
end
function OnStart(level, obj)
  SoundOnStart()
  SetGatewayMarker()
end
function OnFirstStart(level, obj)
  LD.HideFX(TakeOffWhoosh)
  SetGatewayMarker()
  TriggerRuneSideZone:HideEntityVolume()
  WaitExploreZone:HideEntityVolume()
  HideBridgeGapJump()
  SecretGateMantle:HideTraverseLink()
end
function OnUpdate(level)
  if SonLeverPulled == false and SecretGate01.AnimFrame < 20 then
    SecretGateBoost:HideTraversePath()
  elseif SonLeverPulled == false and SecretGate01.AnimFrame > 20 then
    SecretGateBoost:ShowTraversePath()
  end
  if camOneShot_LookAtSolvedLeftRunes ~= nil then
    camOneShot_LookAtSolvedLeftRunes:Update()
  end
  if camOneShot_LookAtSolvedRightRunes ~= nil then
    camOneShot_LookAtSolvedRightRunes:Update()
  end
  if camOneShot_PushInLeft ~= nil then
    camOneShot_PushInLeft:Update()
  end
  if camOneShot_PushInRight ~= nil then
    camOneShot_PushInRight:Update()
  end
  if game.World.IsInsideCameraZone(player.WorldPosition, "CamZone_Stonehenge_Chaindrop") then
    game.Camera.SubmitCameraByName("PLYR_CrackClimb_Reduced_Chain_Xpl200")
  end
  if game.World.IsInsideCameraZone(player.WorldPosition, "CamZone_Limited_WHYDOESTHISCLIMBEXIST") then
    game.Camera.SubmitCameraByName("PLYR_CrackClimb_Limited_65_LimitDown")
  end
end
function OnUseWorld(level)
end
function Funeral_ZnReportEnter()
  if zonereportentered == false then
    uiCalls.UI_Event_DiscoverLocation("VikingFuneral")
    zonereportentered = true
  end
end
function Funeral_ZnReportExit()
  if zonereportentered == true then
    zonereportentered = false
  end
end
function UnlockWayOutBanter()
  if game.Level.GetVariable("FUNERAL_TrollKilled") == true then
    return true
  else
    return false
  end
end
function triggerLoadCheck_Xpl250()
  game.UI.LoadCheck("Xpl250_FuneralInterior")
end
function triggerLoadCheck_Xpl225()
  game.UI.LoadCheck("Xpl225_FuneralLH")
end
function WarpPlayerSon_INT_89673()
  player:Warp(GameObjects.CheckpointOverride_INT_89673.Child:GetWorldJointPosition(GameObjects.CheckpointOverride_INT_89673.Child:GetJointIndex("kratos")), GameObjects.CheckpointOverride_INT_89673.Child:GetWorldJointForward(GameObjects.CheckpointOverride_INT_89673.Child:GetJointIndex("kratos")))
  son:Warp(GameObjects.CheckpointOverride_INT_89673.Child:GetWorldJointPosition(GameObjects.CheckpointOverride_INT_89673.Child:GetJointIndex("son")), GameObjects.CheckpointOverride_INT_89673.Child:GetWorldJointForward(GameObjects.CheckpointOverride_INT_89673.Child:GetJointIndex("son")))
  game.UI.LoadCheck("Xpl250_FuneralInterior")
end
function SetGatewayMarker()
  game.Compass.OnWarp()
  if chainDrop_unlocked then
    game.Compass.SetGatewayMarkerIsOpen("VF_200_ChainDrop", true)
  else
    game.Compass.SetGatewayMarkerIsOpen("VF_200_ChainDrop", false)
  end
  if Shortcut_02_Unlocked then
    game.Compass.SetGatewayMarkerIsOpen("VF_200_Helper9", true)
  else
    game.Compass.SetGatewayMarkerIsOpen("VF_200_Helper9", false)
  end
  if gapJumpBouldersGone then
    game.Compass.SetGatewayMarkerIsOpen("VF_200_Helper5B", true)
  else
    game.Compass.SetGatewayMarkerIsOpen("VF_200_Helper5B", false)
  end
  if shortcut_03_Unlocked then
    game.Compass.SetGatewayMarkerIsOpen("VF_200_Helper16", true)
  else
    game.Compass.SetGatewayMarkerIsOpen("VF_200_Helper16", false)
  end
  local waterLevel = LD.GetCurrentWaterLevel()
  if waterLevel == 1 then
    game.Compass.SetGatewayMarkerIsOpen("VF_220_Helper_WaterLevelOne", true)
  else
    game.Compass.SetGatewayMarkerIsOpen("VF_220_Helper_WaterLevelOne", false)
  end
  if chainDrop_beach_unlocked then
    game.Compass.SetGatewayMarkerIsOpen("VF_200_Helper13", true)
  else
    game.Compass.SetGatewayMarkerIsOpen("VF_200_Helper13", false)
  end
end
function UnlockShortcut_02()
  SetGatewayMarker()
  if Shortcut_02_Unlocked == false then
    GameObjects.CA_ExitGateIdle.LuaObjectScript.Enable()
    Shortcut_02_Unlocked = true
  end
end
function UnlockShortcut_03()
  SetGatewayMarker()
  shortcut_03_Unlocked = true
end
function ExitRopeDropTriggered()
  chainDrop_unlocked = true
  SetGatewayMarker()
end
function ShortcutRopeDropTriggered()
  chainDrop_unlocked = true
  SetGatewayMarker()
end
function GapJumpBouldersRemoved()
  SetGatewayMarker()
  gapJumpBouldersGone = true
end
function DragonDispelStarted()
  local dragon = LD.FindSingleAIByMarker("DragonMarker")
  if dragon ~= nil then
    GameObjects.dragon_AttackZone.LuaObjectScript.SetDispelInProgress()
    GameObjects.FastTravel.LuaObjectScript.Disable()
  end
end
function ReenableFastTravel()
  local completedCineNumber = game.Level.GetVariable("completedCineNumber")
  local cineNumber_FastTravelAcquired = 183
  if completedCineNumber >= cineNumber_FastTravelAcquired then
    GameObjects.FastTravel.LuaObjectScript.Enable()
  end
end
function DragonRelease()
  local dragon = LD.FindSingleAIByMarker("DragonMarker")
  if dragon ~= nil then
    LD.HideFX(GameObjects.dragon_fx_chain)
    son:CallScript("ClearBehaviorContext")
    GameObjects.CA_SonCover01.LuaObjectScript.Disable()
    GameObjects.CA_SonCover02.LuaObjectScript.Disable()
    GameObjects.CA_SonCover03.LuaObjectScript.Disable()
    GameObjects.dragon_AttackZone.LuaObjectScript.SetDragonFree()
    game.Audio.PlayBanter("VFuneral_DragonTurnIn")
    StopSoundDragonChain()
    game.Audio.StartMusic("SND_MX_XPL200_free_dragon")
    xpl200DragonFree = true
  end
end
function DisableDragonZones()
  attackZoneMortar:HideEntityVolume()
  attackZoneBreath:HideEntityVolume()
end
function CheckZoneLocalDragonQuest()
  if dragonShrinesBroken == 0 then
    LD.ActivateQuest("Quest_WorldDragon_Otr_Parent")
    game.Audio.SetBanterFact("Seen1Dragon", "True")
  elseif dragonShrinesBroken == 3 then
    local questState = game.QuestManager.GetQuestState("Quest_WorldDragon_Otr_Parent")
    if questState == "Inactive" then
      FixUpDragonQuest()
    elseif questState == "Active" then
      local spotAQuest = game.QuestManager.GetQuestState("Quest_WorldDragon_VF_Otr_Obj1")
      local spotBQuest = game.QuestManager.GetQuestState("Quest_WorldDragon_VF_Otr_Obj2")
      local spotCQuest = game.QuestManager.GetQuestState("Quest_WorldDragon_VF_Otr_Obj3")
      if spotAQuest == "Active" or spotBQuest == "Active" or spotCQuest == "Active" then
        FixUpDragonQuest()
      end
    end
  end
end
function FixUpDragonQuest()
  LD.ActivateQuest("Quest_WorldDragon_Otr_Parent")
  LD.CallFunctionAfterDelay(function()
    LD.CompleteQuest("Quest_WorldDragon_VF_Otr_Obj1")
  end, 0.11)
  LD.CallFunctionAfterDelay(function()
    LD.CompleteQuest("Quest_WorldDragon_VF_Otr_Obj2")
  end, 0.12)
  LD.CallFunctionAfterDelay(function()
    LD.CompleteQuest("Quest_WorldDragon_VF_Otr_Obj3")
  end, 0.13)
  LD.CallFunctionAfterDelay(function()
    game.QuestManager.IncrementQuestProgress("Quest_WorldDragon_Otr_Objective_01", 3)
  end, 0.15)
  game.Audio.SetBanterFact("Seen1Dragon", "True")
end
function CheckBreakableLocalDragonQuest()
  local questState = game.QuestManager.GetQuestState("Quest_WorldDragon_Otr_Parent")
  if questState == "Inactive" then
    LD.ActivateQuest("Quest_WorldDragon_Otr_Parent")
    IncrementDragonShrineObjective()
  else
    IncrementDragonShrineObjective()
  end
end
function IncrementDragonShrineObjective()
  dragonShrinesBroken = dragonShrinesBroken + 1
  game.QuestManager.IncrementQuestProgress("Quest_WorldDragon_Otr_Objective_01", 1)
  game.Audio.PlayBanter("VFuneral_DragonShrine" .. tostring(dragonShrinesBroken))
  LD.CallFunctionAfterDelay(function()
    game.World.StoreCheckpoint()
  end, 2)
end
function DisablePanicZone()
  if dragonShrinesBroken == 3 then
    GameObjects.PanicContextZone.LuaObjectScript.Disable()
  end
end
function SetVisitedFuneralTrue()
  game.Level.SetVariable("QST_FuneralVisited", true)
end
function EnableBridgeGapJump()
  BridgeGapJump:ShowTraverseLink()
  LD.CallFunctionAfterDelay(function()
    LD.BreakObject(GameObjects.Boulder_Breakable_01)
    LD.BreakObject(GameObjects.Boulder_Breakable_02)
    LD.BreakObject(GameObjects.Boulder_Breakable_03)
  end, 0.1)
  BridgeJumpUnlocked = true
end
function HideBridgeGapJump()
  BridgeGapJump:HideTraverseLink()
end
function EnableBridgeBombs()
  if bombsActive == false then
    BridgeBombs:JumpAnimToFrame(2)
    bombsActive = true
  end
end
function DisableBridgeBombs()
  if bombsActive == true then
    BridgeBombs:JumpAnimToFrame(0)
    bombsActive = false
  end
end
function LoadCheckInterior()
  game.UI.LoadCheck("Xpl250_FuneralInterior")
end
function DisableCombatBanter()
  LD.DisableCombatBanter()
end
function EnableCombatBanter()
  LD.EnableCombatBanter()
end
function TemMainDoorUnlocked()
  if rightbeamsunlocked == true and leftbeamsunlocked == true then
    GameObjects.CA_RightSpinObserve.LuaObjectScript.Disable()
    GameObjects.CA_LeftSpinObserve.LuaObjectScript.Disable()
    TempleEntDoor:PlayAnimToEnd()
    PlaySoundDoorOpen()
    PlayShake("FSE_SHAKE_SLIDING_HORIZONTAL_HEAVY", 1.3, 0, 0.8)
    GameObjects.CA_TempleEntLead.LuaObjectScript.Enable()
    game.World.StoreCheckpoint()
    templedoorsunlocked = true
  end
end
function PuzzleSolved()
  if rightbeamsunlocked == true and leftbeamsunlocked == true then
    GameObjects.CA_RightSpinObserve.LuaObjectScript.Disable()
    GameObjects.CA_RightSpinExplore.LuaObjectScript.Disable()
    GameObjects.CA_LeftSpinObserve.LuaObjectScript.Disable()
    GameObjects.CA_DoorRuneRead.LuaObjectScript.Enable()
    LD.CallFunctionAfterDelay(function()
      TemMainDoorUnlocked()
    end, 2.5)
  end
end
function UnlockLeftBeams()
  leftSpinnerSolved = true
  TriggerFlipperStim()
  EnableDoorBanterCA()
  GameObjects.SpearFlipper03:FindSingleGOByName("FlipperModule").LuaObjectScript.DisableRotation()
  GameObjects.SpearFlipper04:FindSingleGOByName("FlipperModule").LuaObjectScript.DisableRotation()
  LD.CallFunctionAfterDelay(function()
    GameObjects.SpearFlipper03.LuaObjectScript.EnableRunes()
  end, 3.25)
  LD.CallFunctionAfterDelay(function()
    GameObjects.SpearFlipper04.LuaObjectScript.EnableRunes()
  end, 3.25)
  GameObjects.CA_LeftSpinObserve.LuaObjectScript.Interrupt()
  if rightbeamsunlocked == false then
    GameObjects.CA_DoorObserve02.LuaObjectScript.Enable()
  end
  LD.CallFunctionAfterDelay(function()
    if not (LeftSpear.AnimFrame > 1) then
      PlaySoundRuneSuccessLeft()
    end
    LeftSpear:PlayAnimToEnd()
    LeftSpear:OnAnimDone(thisLevel, "StopSoundRuneSuccessLeft")
  end, 1.25)
  LD.CallFunctionAfterDelay(function()
    PlayShake("FSE_SHAKE_JAMMED", 1, 0, 0.2)
  end, 1.25)
  LD.CallFunctionAfterDelay(function()
    if not (PuzzleL_Bars.AnimFrame > 1) then
      PlaySoundUnblockLeft()
    end
    PuzzleL_Bars:PlayAnimToEnd(0.7)
  end, 3.5)
  LD.CallFunctionAfterDelay(function()
    PlayShake("FSE_SHAKE_SLIDING_HORIZONTAL_LIGHT", 3.8, 0, 0.8)
  end, 3.5)
  LD.CallFunctionAfterDelay(PushInLeft, 0)
  LD.CallFunctionAfterDelay(SolvedLeftRunes, 3.8)
  TriggerRuneSideZone:ShowEntityVolume()
  PuzzleL_Bars:OnAnimDone(thisLevel, "LeftBarricadeUnlocked")
end
function UnlockRightBeams()
  rightSpinnerSolved = true
  TriggerFlipperStim()
  EnableDoorBanterCA()
  GameObjects.SpearFlipper01:FindSingleGOByName("FlipperModule").LuaObjectScript.DisableRotation()
  GameObjects.SpearFlipper02:FindSingleGOByName("FlipperModule").LuaObjectScript.DisableRotation()
  LD.CallFunctionAfterDelay(function()
    GameObjects.SpearFlipper01.LuaObjectScript.EnableRunes()
  end, 3.25)
  LD.CallFunctionAfterDelay(function()
    GameObjects.SpearFlipper02.LuaObjectScript.EnableRunes()
  end, 3.25)
  GameObjects.CA_RightSpinObserve.LuaObjectScript.Disable()
  if leftbeamsunlocked == false then
    GameObjects.CA_DoorObserve02.LuaObjectScript.Enable()
  end
  LD.CallFunctionAfterDelay(function()
    if not (RightSpear.AnimFrame > 1) then
      PlaySoundRuneSuccessRight()
    end
    RightSpear:PlayAnimToEnd()
    RightSpear:OnAnimDone(thisLevel, "StopSoundRuneSuccessRight")
  end, 1.25)
  LD.CallFunctionAfterDelay(function()
    PlayShake("FSE_SHAKE_JAMMED", 1, 0, 0.2)
  end, 1.25)
  LD.CallFunctionAfterDelay(function()
    if not (PuzzleR_Bars.AnimFrame > 1) then
      PlaySoundUnblockRight()
    end
    PuzzleR_Bars:PlayAnimToEnd(0.7)
  end, 3.5)
  LD.CallFunctionAfterDelay(function()
    PlayShake("FSE_SHAKE_SLIDING_HORIZONTAL_LIGHT", 3.8, 0, 0.8)
  end, 3.5)
  LD.CallFunctionAfterDelay(PushInRight, 0)
  LD.CallFunctionAfterDelay(SolvedRightRunes, 3.8)
  TriggerRuneSideZone:ShowEntityVolume()
  PuzzleR_Bars:OnAnimDone(thisLevel, "RightBarricadeUnlocked")
end
function LeftBarricadeUnlocked()
  StopSoundUnblockLeft()
  leftbeamsunlocked = true
  EnableRightSpinObserve()
  PuzzleSolved()
end
function RightBarricadeUnlocked()
  StopSoundUnblockRight()
  rightbeamsunlocked = true
  EnableLeftSpinObserve()
  PuzzleSolved()
end
function OnRotateCallback()
  local DoRunesMatch = {}
  DoRunesMatch[1] = false
  DoRunesMatch[2] = false
  DoRunesMatch[3] = false
  DoRunesMatch[4] = false
  for i = 1, 4 do
    DoRunesMatch[i] = runeTable[i] == FlipperTable[i].LuaObjectScript.GetCurrentRune()
  end
  if templedoorsunlocked == false then
    if rightbeamsunlocked == false and DoRunesMatch[1] and DoRunesMatch[2] then
      UnlockRightBeams()
    end
    if leftbeamsunlocked == false and DoRunesMatch[3] and DoRunesMatch[4] then
      UnlockLeftBeams()
    end
  end
end
function EnableDoorBanterCA()
  if rightSpinnerSolved == true and leftSpinnerSolved == true then
    GameObjects.CA_DoorRuneRead.LuaObjectScript.Enable()
    GameObjects.CA_RightSpinObserve.LuaObjectScript.Disable()
    GameObjects.CA_LeftSpinObserve.LuaObjectScript.Disable()
    GameObjects.CA_TempleEntLead.LuaObjectScript.Enable()
    GameObjects.CA_RightSpinObserve.LuaObjectScript.Disable()
    GameObjects.CA_RightSpinExplore.LuaObjectScript.Disable()
    GameObjects.CA_LeftSpinObserve.LuaObjectScript.Disable()
    game.Audio.StartCheckpointedMusic("SND_MX_XPL200_temple_puzzle_solve")
  end
end
function TriggerFlipperStim()
  if rightSpinnerSolved == true and leftSpinnerSolved == false then
    GameObjects.Stim_Flipper_Celebrate.LuaObjectScript.Trigger()
  elseif leftSpinnerSolved == true and rightSpinnerSolved == false then
    GameObjects.Stim_Flipper_Celebrate.LuaObjectScript.Trigger()
  end
end
function SetLeftFlipperHit()
  if LeftFlipperHit == false then
    EnableLeftSpinObserve()
  end
end
function SetRightFlipperHit()
  if RightFlipperHit == false then
    EnableRightSpinObserve()
  end
end
function EnableLeftSpinObserve()
  if LeftFlipperHit == false then
    GameObjects.CA_DoorObserve01.LuaObjectScript.Interrupt()
    GameObjects.CA_RightSpinExplore.LuaObjectScript.Interrupt()
    GameObjects.CA_RightSpinObserve.LuaObjectScript.Interrupt()
    GameObjects.CA_LeftSpinObserve.LuaObjectScript.Enable()
    LeftFlipperHit = true
  end
end
function EnableRightSpinObserve()
  if RightRuneHinted == false and RightFlipperHit == false then
    GameObjects.CA_DoorObserve01.LuaObjectScript.Interrupt()
    GameObjects.CA_LeftSpinObserve.LuaObjectScript.Interrupt()
    WaitExploreZone:ShowEntityVolume()
    GameObjects.CA_RightSpinObserve.LuaObjectScript.Enable()
    RightFlipperHit = true
  end
end
function EnableRightExplore()
  if RightRuneHinted == false then
    LD.CallFunctionAfterDelay(function()
      GameObjects.CA_RightSpinObserve.LuaObjectScript.Interrupt()
    end, 6)
    GameObjects.CA_RightSpinExplore.LuaObjectScript.Enable()
    RightRuneHinted = true
  end
end
function PlayCastleEntrance()
  if runedoorcounter == 0 then
    game.Audio.PlayBanter("VFuneral_CastleEntrance")
  end
end
function ToggleSpinObserve()
  if leftbeamsunlocked == true and rightbeamsunlocked == false then
    LD.CallFunctionAfterDelay(function()
      GameObjects.CA_DoorObserve02.LuaObjectScript.Interrupt()
    end, 4)
    LD.CallFunctionAfterDelay(function()
      GameObjects.CA_RightSpinObserve.LuaObjectScript.Enable()
    end, 6)
    WaitExploreZone:ShowEntityVolume()
  elseif leftbeamsunlocked == false and rightbeamsunlocked == true then
    LD.CallFunctionAfterDelay(function()
      GameObjects.CA_DoorObserve02.LuaObjectScript.Interrupt()
    end, 4)
    LD.CallFunctionAfterDelay(function()
      GameObjects.CA_LeftSpinObserve.LuaObjectScript.Enable()
    end, 6)
  end
end
function HiddenRunesFound()
  runedoorcounter = runedoorcounter + 1
  if runedoorcounter == 1 and rightbeamsunlocked == false then
    game.Audio.PlayBanter("VFuneral_FirstRuneFound")
  elseif 2 <= runedoorcounter and rightbeamsunlocked == false then
    game.Audio.PlayBanter("VFuneral_SecondRuneFound")
  end
end
function Btr_PuzzleSolved()
  game.Audio.PlayBanter("VFuneral_CastlePuzzleSolved", Disable_DoorRuneRead)
end
function Disable_DoorRuneRead()
  GameObjects.CA_DoorRuneRead.LuaObjectScript.Disable()
end
function RuneDebugTable(x, y)
  if engine.IsDebug() then
    local debugTable = {}
    debugTable.Y = y or 5
    debugTable.X = x or 50
    debugTable.Title = "Rune Info"
    debugTable.TitleColor = engine.Vector.New(255, 0, 128)
    for i = 1, 4 do
      local tableToAdd = {
        "Rune" .. i .. ": "
      }
      table.insert(tableToAdd, "runeTable: ")
      table.insert(tableToAdd, runeTable[i])
      table.insert(tableToAdd, "Flipper Value: ")
      table.insert(tableToAdd, FlipperTable[i].LuaObjectScript.GetCurrentRune())
      table.insert(debugTable, tableToAdd)
    end
    engine.DrawDebugTable(debugTable)
  end
end
function ToggleBeachPostUp()
  local BeachPatrol = GameObjects.Cbt_Xpl200.LuaObjectScript.GetBeachPatrol_Encounter()
  if BeachPatrol:IsRunning() then
    GameObjects.CA_BeachOnAlert.LuaObjectScript.Enable()
  elseif BeachPatrol:IsComplete() then
    GameObjects.CA_BeachIdle.LuaObjectScript.Enable()
  end
end
function SecretLeverPulled()
  if SonLeverPulled == false then
    SonLeverPulled = true
    GameObjects.SecretGateChain.LuaObjectScript.ClearDrivenObject()
    GameObjects.SecretGateChain.LuaObjectScript.Disable()
    GameObjects.SecretGateGear.LuaObjectScript.Disable()
    GameObjects.CA_SecretIdle.LuaObjectScript.Enable()
    SecretGate01:PlayAnimToEnd()
    LD.CallFunctionAfterDelay(function()
      SecretGate01:PauseAnim()
    end, 3.5)
    SecretGateBoost:HideTraversePath()
    SecretGateMantle:ShowTraverseLink()
  end
end
function TriggerGateStim()
  if GateStimTriggered == false then
    GameObjects.Stim_Gate_Celebrate.LuaObjectScript.Trigger()
    GateStimTriggered = true
  end
end
function EnableForkIdle_01()
  if ToggleForkIdle == false then
    GameObjects.CA_ForkIdle.LuaObjectScript.Enable()
    ToggleForkIdle = true
  end
end
function EnableForkIdle_02()
  if ToggleForkIdle == false then
    GameObjects.CA_ForkIdle_02.LuaObjectScript.Enable()
    ToggleForkIdle = true
  end
end
function DisableForkIdles()
  if ToggleForkIdle == true then
    ToggleForkIdle = false
    GameObjects.CA_ForkIdle.LuaObjectScript.Interrupt()
    GameObjects.CA_ForkIdle_02.LuaObjectScript.Interrupt()
    GameObjects.CA_ForkIdle.LuaObjectScript.Disable()
    GameObjects.CA_ForkIdle_02.LuaObjectScript.Disable()
  end
end
function EnableGraveyardLead()
  GameObjects.CA_GraveyardRightLead.LuaObjectScript.Enable()
  GameObjects.CA_GraveyardLeftLead.LuaObjectScript.Enable()
  GameObjects.CA_GraveyardCenterLead.LuaObjectScript.Enable()
  GameObjects.CA_GraveyardBridgeLead.LuaObjectScript.Enable()
end
function DisableGraveyardLead()
  GameObjects.CA_GraveyardRightLead.LuaObjectScript.Disable()
  GameObjects.CA_GraveyardLeftLead.LuaObjectScript.Disable()
  GameObjects.CA_GraveyardCenterLead.LuaObjectScript.Disable()
  GameObjects.CA_GraveyardBridgeLead.LuaObjectScript.Disable()
end
function ObserveMainStatue()
  if BridgeJumpUnlocked == false then
    GameObjects.CA_ObserveStatue.LuaObjectScript.Enable()
  end
end
function ToggleDoorPostUp()
  local PuzzleEncounter = GameObjects.Cbt_Xpl200.LuaObjectScript.GetPuzzleAreaEncounter()
  if PuzzleEncounter:IsRunning() then
    LD.CallFunctionAfterDelay(function()
      GameObjects.CA_BrawlerPostUp.LuaObjectScript.Enable()
    end, 0.5)
  elseif PuzzleEncounter:IsComplete() then
    GameObjects.CA_BridgeIdle.LuaObjectScript.Enable()
  end
end
function LuaHook_PlayTakeOffWhoosh()
  if TakeOffWhoosh ~= nil then
    LD.ShowFX(TakeOffWhoosh)
  end
end
function ThorPieceBroken()
  thorpiecesbroken = thorpiecesbroken + 1
  CSL.PlayShake("FSE_SHAKE_SWITCH_CLUNK_VERYLIGHT", 1.2, 0, 0.3)
  local questState = game.QuestManager.GetQuestState("Quest_UnfinishedBusiness03_Parent")
  if thorpiecesbroken == 1 and questState == "Active" then
    game.Audio.PlayBanter("UB_TR_OnePieceBroken")
  end
  if thorpiecesbroken == 3 then
    game.Audio.PlayBanter("UB_TR_ThreePiecesBroken")
  end
  if thorpiecesbroken == 5 then
    local mainbreakable = GameObjects.main_body_breakable:GetBreakable()
    if mainbreakable.Broken == false then
      CSL.PlayShake("FSE_SHAKE_GROUND_IMPACT", 2.6, 1.2, 0.3)
      timer.StartLevelTimer(3.5, function()
        PlayShake("FSE_SHAKE_CRASH_MEDIUM", 1.2)
      end)
      timer.StartLevelTimer(4.2, function()
        PlayShake("FSE_SHAKE_ROLLING_OBJECT_MEDIUM", 2.4, 0, 0.3)
      end)
      mainbreakable:Break()
      game.Audio.PlayBanter("UB_TR_FivePiecesBroken")
      local questStateObjective = game.QuestManager.GetQuestState("Quest_UnfinishedBusiness03_Objective_01")
      if questStateObjective == "Active" then
        LD.CallFunctionAfterDelay(ThorQuestComplete, 3)
      else
        game.Level.SetVariable("ThorStatueBroken", true)
        Checkpoint()
      end
    end
  else
    Checkpoint()
  end
end
function ThorQuestComplete()
  LD.CompleteQuest("Quest_UnfinishedBusiness03_Objective_01")
  LD.SetRecentlyActivatedQuest("Quest_UnfinishedBusiness03_Return")
  Checkpoint()
end
function ThorBeachBanter()
  local questState = game.QuestManager.GetQuestState("Quest_UnfinishedBusiness03_Objective_01")
  if questState == "Active" then
    return true
  else
    return false
  end
end
function ThorStatueLookAtBanter()
  local questState = game.QuestManager.GetQuestState("Quest_UnfinishedBusiness03_Objective_01")
  if questState == "Inactive" then
    game.Audio.SetBanterFact("TRquestIsActive", "false")
    return true
  elseif questState == "Active" then
    game.Audio.SetBanterFact("TRquestIsActive", "true")
    return true
  elseif questState == "Complete" then
    return false
  end
end
function PlayBanterGraveRobber()
  local questState = game.QuestManager.GetQuestState("Quest_UnfinishedBusiness03_Objective_01")
  if questState == "Active" then
    game.Audio.SetBanterFact("GraveLooted_QuestIncomplete", "True")
  else
    game.Audio.SetBanterFact("GraveLooted_QuestIncomplete", "False")
  end
  game.Audio.PlayBanter("UB_TR_GraveLooted")
  game.Level.SetVariable("ThorGraveLooted", true)
  LD.CallFunctionAfterDelay(Checkpoint, 1)
end
function PlayBanterLootAndLeave()
  local questState = game.QuestManager.GetQuestState("Quest_UnfinishedBusiness03_Objective_01")
  local graveLooted = game.Level.GetVariable("ThorGraveLooted")
  if graveLooted and thorpiecesbroken == 0 and questState == "Active" then
    return true
  else
    return false
  end
end
function OnSaveCheckpoint(level)
  return {
    levelstate = checkpoint.Save(),
    DragonMarkersDestroyed = DragonMarkersDestroyed,
    BridgeJumpUnlocked = BridgeJumpUnlocked,
    templedoorsunlocked = templedoorsunlocked,
    rightbeamsunlocked = rightbeamsunlocked,
    leftbeamsunlocked = leftbeamsunlocked,
    dragonShrinesBroken = dragonShrinesBroken,
    thorpiecesbroken = thorpiecesbroken,
    bombsActive = bombsActive,
    dragonShrineEnabled = dragonShrineEnabled,
    SonLeverPulled = SonLeverPulled,
    ToggleForkIdle = ToggleForkIdle,
    Shortcut_02_Unlocked = Shortcut_02_Unlocked,
    shortcut_03_Unlocked = shortcut_03_Unlocked,
    chainDrop_unlocked = chainDrop_unlocked,
    gapJumpBouldersGone = shortcut_03_Unlocked,
    RightRuneHinted = RightRuneHinted,
    GateStimTriggered = GateStimTriggered,
    rightSpinnerSolved = rightSpinnerSolved,
    leftSpinnerSolved = leftSpinnerSolved,
    xpl200DragonFree = xpl200DragonFree,
    musicStage = musicStage
  }
end
function OnRestoreCheckpoint(level, savedInfo)
  checkpoint.Restore(savedInfo.levelstate)
  BridgeJumpUnlocked = savedInfo.BridgeJumpUnlocked
  DragonMarkersDestroyed = savedInfo.DragonMarkersDestroyed
  templedoorsunlocked = savedInfo.templedoorsunlocked
  rightbeamsunlocked = savedInfo.rightbeamsunlocked
  leftbeamsunlocked = savedInfo.leftbeamsunlocked
  dragonShrinesBroken = savedInfo.dragonShrinesBroken
  thorpiecesbroken = savedInfo.thorpiecesbroken
  bombsActive = savedInfo.bombsActive
  dragonShrineEnabled = savedInfo.dragonShrineEnabled
  SonLeverPulled = savedInfo.SonLeverPulled
  ToggleForkIdle = savedInfo.ToggleForkIdle
  Shortcut_02_Unlocked = savedInfo.Shortcut_02_Unlocked
  shortcut_03_Unlocked = savedInfo.shortcut_03_Unlocked
  chainDrop_unlocked = savedInfo.chainDrop_unlocked
  gapJumpBouldersGone = savedInfo.gapJumpBouldersGone
  RightRuneHinted = savedInfo.RightRuneHinted
  GateStimTriggered = savedInfo.GateStimTriggered
  rightSpinnerSolved = savedInfo.rightSpinnerSolved
  leftSpinnerSolved = savedInfo.leftSpinnerSolved
  xpl200DragonFree = savedInfo.xpl200DragonFree
  musicStage = savedInfo.musicStage
end
local SNDBlocker1, SNDBlocker2, SNDDoor, SNDRune1, SNDRune2, SNDDragonChain
function SoundInit()
  SNDBlocker1 = GameObjects.SNDBlocker_1.SoundEmitters[1]
  SNDBlocker2 = GameObjects.SNDBlocker_2.SoundEmitters[1]
  SNDDoor = GameObjects.SNDDoor.SoundEmitters[1]
  SNDRune1 = GameObjects.SNDRuneSuccess_1.SoundEmitters[1]
  SNDRune2 = GameObjects.SNDRuneSuccess_2.SoundEmitters[1]
  SNDDragonChain = GameObjects.SNDDragonChainGrp.SoundEmitters[1]
  print(SNDRune1)
  print(SNDRune2)
  print(SNDDoor)
  print(SNDBlocker1)
  print(SNDBlocker1)
end
function PlaySoundUnblockLeft()
  LD.PlaySound(SNDBlocker1, "SND_MECH_Temple_Entrance_Door_Slats_Slide_Open")
end
function StopSoundUnblockLeft()
  LD.StopSound(SNDBlocker1, "SND_MECH_Temple_Entrance_Door_Slats_Slide_Open")
end
function PlaySoundUnblockRight()
  LD.PlaySound(SNDBlocker2, "SND_MECH_Temple_Entrance_Door_Slats_Slide_Open")
end
function StopSoundUnblockRight()
  LD.StopSound(SNDBlocker2, "SND_MECH_Temple_Entrance_Door_Slats_Slide_Open")
end
function PlaySoundDoorOpen()
  LD.PlaySound(SNDDoor, "SND_MECH_Temple_Entrance_Door_Open")
end
function PlaySoundRuneSuccessLeft()
  LD.PlaySound(SNDRune1, "SND_MECH_Temple_Entrance_Door_Spindle_Light")
end
function StopSoundRuneSuccessLeft()
  LD.StopSound(SNDRune1, "SND_MECH_Temple_Entrance_Door_Spindle_Light")
end
function PlaySoundRuneSuccessRight()
  LD.PlaySound(SNDRune2, "SND_MECH_Temple_Entrance_Door_Spindle_Light")
end
function StopSoundRuneSuccessRight()
  LD.StopSound(SNDRune2, "SND_MECH_Temple_Entrance_Door_Spindle_Light")
end
function PlaySoundDragonChain()
  LD.PlaySound(SNDDragonChain, "SND_MECH_Dragon_XPL_Leash_LP")
end
function StopSoundDragonChain()
  LD.StopSound(SNDDragonChain, "SND_MECH_Dragon_XPL_Leash_LP")
end
function Checkpoint()
  game.World.StoreCheckpoint()
end
function SoundOnStart()
  PlaySoundDragonChain()
  GameObjects.BeachLoreMarker:FindSingleGOByName("pSonReadRune").LuaObjectScript.LoreMarkerRuneReadSoundSetup()
  GameObjects.CastleLoreMarker:FindSingleGOByName("pSonReadRune").LuaObjectScript.LoreMarkerRuneReadSoundSetup()
end
function xpl200StairsEnter()
  game.Audio.StartMusic("SND_MX_XPL200_staircase")
end
function xpl200StairsTop()
  if musicStage == 0 and not xpl200DragonFree then
    musicStage = 1
    game.Audio.StartCheckpointedMusic("SND_MX_XPL200_explore1_in")
  end
end
function Xpl200TempleEnter()
  if not game.Level.GetVariable("FUNERAL_TrollKilled") then
    musicStage = 2
    game.Audio.StartCheckpointedMusic("SND_MX_XPL200_explore2_in")
  end
end
function Xpl200TempleExit()
  if musicStage == 2 and not game.Level.GetVariable("FUNERAL_TrollKilled") and not xpl200DragonFree then
    musicStage = 1
    game.Audio.StartCheckpointedMusic("SND_MX_XPL200_explore1_in")
  elseif musicStage == 2 then
    xpl200Exit()
  end
end
function xpl200Exit()
  game.Audio.StartMusic("SND_MX_XPL200_idle")
  if musicStage == 1 then
    musicStage = 0
  end
end
function xpl200FastTravelMusic()
  if not xpl200DragonFree then
    musicStage = 0
  end
end
function Emitters200WaterFallsOn()
  GameObjects.SNDGrpWaterFalls:Show()
end
function Emitters200WaterFallsOff()
  GameObjects.SNDGrpWaterFalls:Hide()
end
function DestroyOneShot_LookAtSolvedLeftRunes()
  camOneShot_LookAtSolvedLeftRunes = nil
  ClearSlowWalk()
end
function DestroyOneShot_LookAtSolvedRightRunes()
  camOneShot_LookAtSolvedRightRunes = nil
  ClearSlowWalk()
end
function DestroyOneShot_PushInLeft()
  camOneShot_PushInLeft = nil
end
function DestroyOneShot_PushInRight()
  camOneShot_PushInRight = nil
end
function SetSlowWalk()
  local player = game.Player.FindPlayer()
  player:SetMaxSpeedOverride(1.5)
end
function ClearSlowWalk()
  local player = game.Player.FindPlayer()
  player:ClearMaxSpeedOverride()
end
function SolvedLeftRunes()
  SetSlowWalk()
  camOneShot_LookAtSolvedLeftRunes = CCOS.OneShotCamera.New("PLYR_NAR_XPL200_Solved_FrameLeft", 3)
  camOneShot_LookAtSolvedLeftRunes:SetCallback(DestroyOneShot_LookAtSolvedLeftRunes)
  camOneShot_LookAtSolvedLeftRunes:Start()
end
function SolvedRightRunes()
  SetSlowWalk()
  camOneShot_LookAtSolvedRightRunes = CCOS.OneShotCamera.New("PLYR_NAR_XPL200_Solved_FrameRight", 3)
  camOneShot_LookAtSolvedRightRunes:SetCallback(DestroyOneShot_LookAtSolvedRightRunes)
  camOneShot_LookAtSolvedRightRunes:Start()
end
function PushInLeft()
  camOneShot_PushInLeft = CCOS.OneShotCamera.New("PLYR_NAR_Solved_PushInLeft", 5.5)
  camOneShot_PushInLeft:SetCallback(DestroyOneShot_PushInLeft)
  camOneShot_PushInLeft:Start()
end
function PushInRight()
  camOneShot_PushInRight = CCOS.OneShotCamera.New("PLYR_NAR_Solved_PushInRight", 5.5)
  camOneShot_PushInRight:SetCallback(DestroyOneShot_PushInRight)
  camOneShot_PushInRight:Start()
end
function PlayShake(nameofeffect, duration, tweenin, tweenout)
  local effect = {
    EffectName = nameofeffect,
    Duration = duration,
    TweenInTime = tweenin,
    TweenOutTime = tweenout
  }
  game.FX.SubmitEffect(effect)
end
function EnemyPowerLevelTut200()
end
