local LD = require("design.LevelDesignLibrary")
local EC = require("design.Encounter")
local monitors = require("level.MonitorLibrary")
local checkpoint = require("level.checkpoint")
local timer = require("level.timer")
local timers = require("level.timer")
local uiCalls = require("ui.uicalls")
local delayTimers = require("level.timer")
local ExploreEncounterL, Player, Son, RiftWarpMarker
local camShakeLarge = {
  EffectName = "FSE_shake_temp_Generic_Large",
  Duration = 1
}
local thisLevel
local varGateUnblocked = false
local LowerTendrilOpen = false
local varGateIsMoving = false
local varPlayerPastGatePuzzle = false
local varTendrilDropDownBroken = false
local Area_1_Encounter_1, Area_1_Encounter_2, Area_1_Encounter_3, Area_2_Encounter_1, Area_2_Encounter_2, AlfDgn110_DespawnMonitor
local Rift_Challenge_Duration = 10
local Challenge_Started = false
local ecTimer, ec_TimeRequirement, hudTimeRemaining
local delayDestruction = false
local delayDestruction_T = {}
function OnScriptLoaded(level)
  Player = game.Player.FindPlayer()
  Son = game.AI.FindSon()
  thisLevel = level
  RiftWarpMarker = GameObjects.SonWarpPoint1
  BeachFight_Area_1_Fight_1()
  BeachFight_Area_1_Fight_2()
  BeachFight_Area_1_Repop()
  BeachFight_Area_2_Fight_1()
  if game.GetNewGamePlus() then
    New_Game_Plus_BeachFight_Area_2_Fight_2()
  else
    BeachFight_Area_2_Fight_2()
  end
  local tendrilGate = level:FindGameObject("SwitchFloor1")
  tendrilGate.LuaObjectScript.OverrideCameraInteractApproach("ENV_Interact_WallSwitch_AlfDgn110")
  tendrilGate.LuaObjectScript.OverideInteractApproachYaw(true)
  tendrilGate.LuaObjectScript.OverrideCameraSubmissionTime(4)
  tendrilGate.LuaObjectScript.OverrideCancelCameraIfAiming(true)
  local gapjumpGate = level:FindGameObject("SwitchFloor_0")
  gapjumpGate.LuaObjectScript.OverrideCameraInteractApproach("ENV_Interact_WallSwitch_GapJump_AlfDgn110")
  gapjumpGate.LuaObjectScript.OverideInteractApproachYaw(true)
  gapjumpGate.LuaObjectScript.OverrideCameraSubmissionTime(1.8)
  SoundInit()
end
function OnStart(level, obj)
  SoundOnStart()
  if Area_1_Encounter_1:WasRunning() then
    Area_1_Encounter_1:Start()
  end
  if Area_1_Encounter_2:WasRunning() then
    Area_1_Encounter_2:Start()
  end
  GameObjects.SwitchFloor1.LuaObjectScript.Enable()
  GameObjects.SwitchFloor_0_Alt.LuaObjectScript.Enable()
  GameObjects.SwitchFloor_0.LuaObjectScript.Enable()
  if GameObjects.SwitchFloor1.LuaObjectScript.SwitchIsBeingTurnedOn() then
    GameObjects.SwitchFloor1.LuaObjectScript.ToggleState()
  end
  if GameObjects.SwitchFloor_0_Alt.LuaObjectScript.SwitchIsBeingTurnedOn() then
    GameObjects.SwitchFloor_0_Alt.LuaObjectScript.ToggleState()
  end
  if GameObjects.SwitchFloor_0.LuaObjectScript.SwitchIsBeingTurnedOn() then
    GameObjects.SwitchFloor_0.LuaObjectScript.ToggleState()
  end
  if varGateUnblocked == true then
    GameObjects.TendrilAxeTarget_01:Hide()
    GameObjects.TendrilAxeTarget_02:Hide()
  end
  if GameObjects.TendrilControllerGate.LuaObjectScript.GetTendrilCutCount() < 0 then
    GameObjects.TendrilControllerGate.LuaObjectScript.Reset()
  end
end
function OnFirstStart(level)
  GameObjects.TraversePath_Drop5m:HideTraversePath()
end
function OnUpdate(level)
  UpdateCreatureDestruction()
  if Challenge_Started then
    Encounter_Timer()
  end
end
function EnableCA_SpinRoom()
  GameObjects.CA_Idle_SpinningRoom.LuaObjectScript.Enable()
end
function DisableCA_SpinRoom()
  GameObjects.CA_Idle_SpinningRoom.LuaObjectScript.Disable()
end
function Enable_LTW_SpinRoom()
  GameObjects.LeadTheWay3.LuaObjectScript.Enable()
  GameObjects.LeadTheWay.LuaObjectScript.Disable()
end
function Disable_LTW_SpinRoom()
  GameObjects.LeadTheWay3.LuaObjectScript.Disable()
end
function EnableCA_BellPuzzle()
  GameObjects.CA_Idle_BellPuzzle.LuaObjectScript.Enable()
end
function DisableCA_BellPuzzle()
  GameObjects.CA_Idle_BellPuzzle.LuaObjectScript.Disable()
end
function DestroyHiveBlocker()
  GameObjects.AnimatedHiveBlocker:HideCollision()
  for _, x in pairs(GameObjects.StaticHive.Children) do
    x.Child.LuaObjectScript.StartDecay()
  end
  for _, x in pairs(GameObjects.MovingHive.Children) do
    x.Child.LuaObjectScript.StartDecay()
  end
  GameObjects.chest_legendary_tier1_alfdgn110_1.LuaObjectScript.Enable()
  GameObjects.IdleContext_Puzzled_02.LuaObjectScript.Disable()
  if game.Level.GetVariable("CompletedCineNumber") ~= 245 then
    LD.CallFunctionAfterDelay(function()
      GameObjects.Reaction_SpinRoomWin.LuaObjectScript.Trigger()
    end, 0.5)
  end
end
function UnblockExit()
  GameObjects.Hive_ExitBlocker_IC:HideCollision()
  GameObjects.NavObstacle_PuzzleGateHive:HideNavObstacle()
  timer.StartLevelTimer(1, function()
    GameObjects.TendrilAxeTarget_01:Hide()
  end)
  timer.StartLevelTimer(1, function()
    GameObjects.TendrilAxeTarget_02:Hide()
  end)
  if game.Level.GetVariable("CompletedCineNumber") ~= 247 then
    timer.StartLevelTimer(1.5, function()
      GameObjects.Reaction_GateWin.LuaObjectScript.Trigger()
    end)
  end
  GameObjects.IdleContext_Puzzled_01.LuaObjectScript.Disable()
  for _, x in pairs(GameObjects.Hive_ExitBlocker.Children) do
    x.Child.LuaObjectScript.StartDecay()
  end
  timer.StartLevelTimer(0.5, function()
    game.World.StoreCheckpoint()
  end)
  varGateUnblocked = true
end
function EnableCA_Gate0()
  GameObjects.CA_WaitBeforeGate0.LuaObjectScript.Enable()
  GameObjects.LeadTheWay.LuaObjectScript.Enable()
end
function DisableCA_Gate0()
  GameObjects.CA_WaitBeforeGate0.LuaObjectScript.Interrupt()
  GameObjects.CA_WaitBeforeGate0.LuaObjectScript.Disable()
end
function StopLTW()
  GameObjects.LeadTheWay.LuaObjectScript.Disable()
end
function EnableCA_GatePuzzle()
  GameObjects.CA_WaitBeforeGatePuzzle.LuaObjectScript.Enable()
  GameObjects.CA_WaitBeforeGate0.LuaObjectScript.Interrupt()
  GameObjects.CA_WaitBeforeGate0.LuaObjectScript.Disable()
  varPlayerPastGatePuzzle = false
end
function PastGatePuzzle()
  varPlayerPastGatePuzzle = true
  GameObjects.LeadTheWay.LuaObjectScript.Enable()
end
function EnterBellPuzzle()
  varPlayerPastGatePuzzle = true
end
function DisableCA_GatePuzzle()
  GameObjects.CA_WaitBeforeGatePuzzle.LuaObjectScript.Disable()
end
function TriggerGateAnim_0()
  timer.StartLevelTimer(1, function()
    GameObjects.SwitchFloor_0.LuaObjectScript.Disable()
    GameObjects.Gate_0:JumpAnimToFrame(0)
    GameObjects.Timer_0:JumpAnimToFrame(0)
  end)
  timer.StartLevelTimer(5, function()
    GameObjects.Gate_0:PlayAnimToFrame(0, -3)
  end)
  timer.StartLevelTimer(5, ResetGate_0)
  timer.StartLevelTimer(5.7, ShakeRumble)
  PlayGate_0AnimSound()
end
function ShakeRumble()
  game.FX.SubmitEffect(camShakeLarge)
end
function ResetGate_0()
  GameObjects.SwitchFloor_0.LuaObjectScript.ToggleState()
  timer.StartLevelTimer(1, function()
    GameObjects.SwitchFloor_0.LuaObjectScript.Enable()
  end)
end
function TriggerGateAnim_0_Alt()
  GameObjects.Gate_0:JumpAnimToFrame(0)
  GameObjects.Timer_0:JumpAnimToFrame(0)
  timer.StartLevelTimer(1, function()
    GameObjects.SwitchFloor_0_Alt.LuaObjectScript.Disable()
  end)
  timer.StartLevelTimer(4, ResetGate_0_Alt)
  timer.StartLevelTimer(4, function()
    GameObjects.Gate_0:PlayAnimToFrame(0, -3)
  end)
  timer.StartLevelTimer(4.7, ShakeRumble)
  PlayGate_0AnimSound()
end
function ResetGate_0_Alt()
  GameObjects.SwitchFloor_0_Alt.LuaObjectScript.ToggleState()
  timer.StartLevelTimer(1, function()
    GameObjects.SwitchFloor_0_Alt.LuaObjectScript.Enable()
  end)
end
function PlayJammedShakeEffect()
  local effect = {
    EffectName = "FSE_SHAKE_JAMMED",
    Duration = 1.8,
    TweenInTime = 0.08,
    TweenOutTime = 0.07
  }
  game.FX.SubmitEffect(effect)
end
function TriggerGateAnim()
  GameObjects.SwitchFloor1.LuaObjectScript.Disable()
  timer.StartLevelTimer(4, ResetFloorSwitch)
  if varGateUnblocked == false then
    timer.StartLevelTimer(2.1, PlayJammedShakeEffect)
    timer.StartLevelTimer(2, CheckTendrilStatus)
    timer.StartLevelTimer(2.333, CheckTendrilStatus)
    timer.StartLevelTimer(2.666, CheckTendrilStatus)
    GameObjects.Gate:JumpAnimToFrame(0)
    GameObjects.Timer:JumpAnimToFrame(0)
    timer.StartLevelTimer(5, function()
      GameObjects.Gate:PlayAnimToFrame(80, -3)
    end)
  else
    GameObjects.Gate:JumpAnimToFrame(80)
    GameObjects.Timer:JumpAnimToFrame(0)
    timer.StartLevelTimer(5, function()
      GameObjects.Gate:PlayAnimToFrame(80, -3)
    end)
  end
  PlayGateAnimSound()
  timer.StartLevelTimer(6, function()
    if varPlayerPastGatePuzzle == false then
      GameObjects.CA_WaitBeforeGatePuzzle.LuaObjectScript.Enable()
    end
  end)
end
function CheckTendrilStatus()
  if varGateIsMoving == false then
    if LowerTendrilOpen then
      GameObjects.Gate:JumpAnimToFrame(80)
      varGateIsMoving = true
      timer.StartLevelTimer(3, CutLowerTendril)
      timer.StartLevelTimer(5, RestoreLowerTendril)
    else
      GameObjects.Gate:PlayAnimToFrame(80, 0.45)
    end
  end
end
function ResetFloorSwitch()
  GameObjects.SwitchFloor1.LuaObjectScript.ToggleState()
  timer.StartLevelTimer(1, function()
    GameObjects.SwitchFloor1.LuaObjectScript.Enable()
  end)
end
function CutLowerTendril()
  if varGateUnblocked == false then
    GameObjects.TendrilAxeTarget_02.LuaObjectScript.HitTendril_NoCooldown()
    LowerTendrilOpen = true
  end
end
function RestoreLowerTendril()
  varGateIsMoving = false
  if varGateUnblocked == false then
    GameObjects.TendrilAxeTarget_02.LuaObjectScript.ForceRegrow()
    LowerTendrilOpen = false
  end
end
function LowerTendrilCut()
  LowerTendrilOpen = true
end
function LowerTendrilRestored()
  LowerTendrilOpen = false
end
function HigherTendrilCut()
  GameObjects.Gate:PlayAnimToFrame(80, -3)
  varGateIsMoving = true
  timer.StartLevelTimer(0.6, CutLowerTendril)
  timer.StartLevelTimer(2, RestoreLowerTendril)
end
function EnableSonBoostDrop()
  if varTendrilDropDownBroken then
    GameObjects.TraversePath_Drop5m:ShowTraversePath()
  end
end
function DisableSonBoostDrop()
end
function PlayerCompletesLoop()
  GameObjects.LeadTheWay.LuaObjectScript.Disable()
  GameObjects.EZ_BeforeGate0:HideEntityVolume()
  GameObjects.EntZone_PuzzleArea:HideEntityVolume()
  GameObjects.EntZone_BellChest:HideEntityVolume()
  GameObjects.EZ_LakeOverlook:HideEntityVolume()
end
function Tendril_Loot_Setup()
  GameObjects.TendrilDrop_Jail:HideCollision()
  timer.StartLevelTimer(1, function()
    GameObjects.TendrilAxeTargetT1:Hide()
  end)
  timer.StartLevelTimer(1, function()
    GameObjects.TendrilAxeTargetT2:Hide()
  end)
  timer.StartLevelTimer(1, function()
    GameObjects.TendrilAxeTargetT3:Hide()
  end)
  timer.StartLevelTimer(2, function()
    GameObjects.ArtifactAlfheim02_RN.Child.LuaObjectScript.Enable()
    EnableSonBoostDrop()
  end)
  for _, x in pairs(GameObjects.SimpleSetupHiveGeo.Children) do
    x.Child.LuaObjectScript.StartDecay()
  end
  varTendrilDropDownBroken = true
end
function Tendril_DropDown_Setup()
  for _, x in pairs(GameObjects.HiveOverDropDown.Children) do
    x.Child.LuaObjectScript.StartDecay()
  end
  GameObjects.TendrilDrop_Sheet:HideCollision()
  GameObjects.LeadTheWay_Roots.LuaObjectScript.Enable()
  GameObjects.CA_Observe_TendrilDrop.LuaObjectScript.Disable()
  GameObjects.CA_LakeVista.LuaObjectScript.Disable()
  GameObjects.CA_BeforeRift.LuaObjectScript.Disable()
end
function ExploreLEnd(level, obj)
  ExploreEncounterL:Stop()
end
function SwitchBeachDeactivate()
  GameObjects.SwitchFloor_0.LuaObjectScript.Disable()
end
function SwitchBeachActivate()
  GameObjects.SwitchFloor_0.LuaObjectScript.Enable()
end
function SwitchPuzzleDeactivate()
  GameObjects.SwitchFloor_0_Alt.LuaObjectScript.Disable()
  GameObjects.SwitchFloor1.LuaObjectScript.Disable()
end
function SwitchPuzzleActivate()
  GameObjects.SwitchFloor_0_Alt.LuaObjectScript.Enable()
  GameObjects.SwitchFloor1.LuaObjectScript.Enable()
end
function BeachFight_Area_1_Fight_1()
  local powerLevel01, powerLevel02
  local cineNumber = game.Level.GetVariable("CompletedCineNumber")
  if 375 <= cineNumber and cineNumber <= 599 then
    powerLevel01 = 3
    powerLevel02 = 4
  elseif 600 <= cineNumber then
    powerLevel01 = 4
    powerLevel02 = 5
  end
  Area_1_Encounter_1 = EC.NewEncounter(thisLevel, "[Area 1]EC:1 Beach Fight AlfDgn110", {
    CheckpointOnComplete = true,
    LeashZone = "LeashZoneDgn110_2",
    StartMusic = "SND_MX_ALF_secret_beach_explore_in",
    StopMusic = "SND_MX_ALF_secret_beach_explore_out"
  })
  Area_1_Encounter_1:AddWave({
    {
      spawners = "Crawler_L_S",
      spawnLocators = "A1_Loc_1",
      useSpawnLocatorsOnly = true,
      maxActive = 1,
      totalSpawns = 1,
      spawnCooldown = 0.5,
      powerLevel = powerLevel01
    },
    {
      spawners = "Crawler_L_S",
      spawnLocators = "A1_Loc_2",
      useSpawnLocatorsOnly = true,
      maxActive = 1,
      totalSpawns = 1,
      spawnCooldown = 3,
      powerLevel = powerLevel02
    },
    {
      spawners = "Draugr_P_SFG_TURR",
      spawnLocators = "A1_Loc_3",
      useSpawnLocatorsOnly = true,
      maxActive = 1,
      totalSpawns = 1,
      spawnCooldown = 7,
      powerLevel = powerLevel01
    }
  })
  Area_1_Encounter_1:AddWave({
    requireCompletionOfAllPriorWaves = true,
    {
      spawners = "Draugr_P_SFG_TURR",
      spawnLocators = "A1_Loc_4",
      useSpawnLocatorsOnly = true,
      maxActive = 1,
      totalSpawns = 1,
      spawnCooldown = 1,
      powerLevel = powerLevel02
    }
  })
  Area_1_Encounter_1:SetStartZone(thisLevel:GetGameObject("EntZn_Area_1_Spawn"))
  Area_1_Encounter_1:OnEnemyDeath(function()
    Area_1_Encounter_1:StartWave(2)
  end, {count = 2})
  Area_1_Encounter_1:OnStart(SwitchBeachDeactivate)
  Area_1_Encounter_1:OnComplete(SwitchBeachActivate)
  AlfDgn110_DespawnMonitor = monitors.CreateEntityZoneMonitor(Player, thisLevel:GetGameObject("EntZn_Area_DespawnAll"))
  AlfDgn110_DespawnMonitor:OnEnter(function()
  end)
end
function StartCellFight()
  Area_1_Encounter_2:Start()
end
function BeachFight_Area_1_Fight_2()
  local powerLevel01
  local cineNumber = game.Level.GetVariable("CompletedCineNumber")
  if 375 <= cineNumber and cineNumber <= 599 then
    powerLevel01 = 3
  elseif 600 <= cineNumber then
    powerLevel01 = 4
  end
  Area_1_Encounter_2 = EC.NewEncounter(thisLevel, "[Area 1]EC:1 Prison Cell Fight AlfDgn110", {
    CheckpointOnComplete = false,
    LeashZone = "LeashZoneDgn110_2"
  })
  Area_1_Encounter_2:AddWave({
    {
      spawners = "Draugr_L2_H_SFG",
      spawnLocators = "A1_Loc_9",
      useSpawnLocatorsOnly = true,
      maxActive = 1,
      totalSpawns = 1,
      spawnCooldown = 0.5,
      powerLevel = powerLevel01
    }
  })
end
function BeachFight_Area_1_Repop()
  Area_1_Encounter_3 = EC.NewEncounter(thisLevel, "[Area 1]EC:1 Beach Fight AlfDgn110 Repop", {
    CheckpointOnComplete = false,
    LeashZone = "LeashZoneDgn110_2",
    RepopulationEncounter = true,
    MustHaveCompletedList = {
      "[Area 1]EC:1 Beach Fight AlfDgn110"
    }
  })
  Area_1_Encounter_3:AddWave({
    {
      spawners = "Draugr_L6_H_SFG",
      spawnLocators = "A1_LocR_1",
      useSpawnLocatorsOnly = true,
      maxActive = 1,
      totalSpawns = 1,
      spawnCooldown = 0
    },
    {
      spawners = "Crawler_L5_S",
      spawnLocators = "A1_LocR_2",
      useSpawnLocatorsOnly = true,
      maxActive = 1,
      totalSpawns = 1,
      spawnCooldown = 0.5
    }
  })
  Area_1_Encounter_3:SetStartZone(thisLevel:GetGameObject("EntZn_Area_1_Repop"), {
    cineRequirement = {375, 900}
  })
end
function BeachFight_Area_2_Fight_1()
  local powerLevel01
  local cineNumber = game.Level.GetVariable("CompletedCineNumber")
  if 375 <= cineNumber and cineNumber <= 599 then
    powerLevel01 = 3
  elseif 600 <= cineNumber then
    powerLevel01 = 4
  end
  Area_2_Encounter_1 = EC.NewEncounter(thisLevel, "[Area 1]EC:1 Gate Puzzle Fight AlfDgn110", {
    CheckpointOnComplete = false,
    LeashZone = "LeashZoneDgn110_1"
  })
  Area_2_Encounter_1:AddWave({
    {
      spawners = "Crawler_L_S",
      spawnLocators = "A2_Loc_1",
      useSpawnLocatorsOnly = true,
      maxActive = 1,
      totalSpawns = 1,
      spawnCooldown = 0.5,
      powerLevel = powerLevel01
    },
    {
      spawners = "Crawler_L_S",
      spawnLocators = "A2_Loc_2",
      useSpawnLocatorsOnly = true,
      maxActive = 1,
      totalSpawns = 1,
      spawnCooldown = 5,
      powerLevel = powerLevel01
    }
  })
  Area_2_Encounter_1:SetStartZone(thisLevel:GetGameObject("EntZn_Area_1_GatePuzzle"))
  Area_2_Encounter_1:OnStart(SwitchPuzzleDeactivate)
  Area_2_Encounter_1:OnComplete(SwitchPuzzleActivate)
  AlfDgn110_DespawnMonitor = monitors.CreateEntityZoneMonitor(Player, thisLevel:GetGameObject("EntZn_Area_DespawnAll"))
  AlfDgn110_DespawnMonitor:OnEnter(function()
  end)
end
function StartRiftFight()
  if Son:IsInsideEntityZone(GameObjects.EntZone_Past_GateCrawl) == false then
    Son:Warp(RiftWarpMarker:GetWorldPosition(), RiftWarpMarker:GetWorldForward())
  end
  timer.StartLevelTimer(3, function()
    Area_2_Encounter_2:Start()
  end)
end
function RespawnRiftObject()
  if Area_2_Encounter_2 ~= nil and not Area_2_Encounter_2:IsComplete() and not Area_2_Encounter_2:IsRunning() then
    local alf300 = game.FindLevel("Alf300_LakeDark")
    if alf300 ~= nil then
      alf300:CallScript("ResetRiftState")
    end
  end
end
function StopFightRift110()
  GameObjects.CA_LakeVista.LuaObjectScript.Enable()
  local alf300 = game.FindLevel("Alf300_LakeDark")
  if alf300 ~= nil then
    alf300:CallScript("StopRiftFight")
  end
  local alf050 = game.FindLevel("Alf050_Sound")
  if alf050 ~= nil and game.Level.GetVariable("CompletedCineNumber") >= 610 then
    LD.CallFunctionAfterDelay(function()
      alf050:CallScript("revisitMusic")
    end, 13.5)
  end
end
function PlaySoundEnemySpawnFightRift110()
  local alf300 = game.FindLevel("Alf300_LakeDark")
  if alf300 ~= nil then
    alf300:CallScript("PlayRiftSound")
  end
end
function TurnOnAlfRiftMarker()
  LD.SetMarkerState("ALF_300_LeftBeachFight", 1)
end
function BeachFight_Area_2_Fight_2()
  Area_2_Encounter_2 = EC.NewEncounter(thisLevel, "[Area 1]EC:1 Balcony Rift Fight AlfDgn110", {
    CheckpointOnComplete = true,
    LeashZone = "LeashZoneDgn110_3",
    StartMusic = "SND_MX_ALF_pocket_rift_combat_in",
    StopMusic = "SND_MX_ALF_pocket_rift_combat_out"
  })
  Area_2_Encounter_2:AddWave({
    {
      spawners = "Draugr_L3_H_RIFT1",
      maxActive = 1,
      totalSpawns = 1,
      spawnCooldown = 0
    },
    {
      spawners = "Draugr_L3_H_RIFT2",
      maxActive = 1,
      totalSpawns = 1,
      spawnCooldown = 4
    }
  })
  Area_2_Encounter_2:OnEnemySpawn(PlaySoundEnemySpawnFightRift110)
  Area_2_Encounter_2:OnStart(function()
    GameObjects.Reaction_Threat_High.LuaObjectScript.Trigger()
  end)
  Area_2_Encounter_2:OnComplete(StopFightRift110)
  Area_2_Encounter_2:OnComplete(function()
    LD.SetMarkerState("ALF_300_LeftBeachFight", 0)
  end)
end
function New_Game_Plus_BeachFight_Area_2_Fight_2()
  Area_2_Encounter_2 = EC.NewEncounter(thisLevel, "[Area 1]EC:1 NPlus Balcony Rift Fight AlfDgn110", {
    CheckpointOnComplete = true,
    LeashZone = "LeashZoneDgn110_3",
    StartMusic = "SND_MX_ALF_pocket_rift_combat_in",
    StopMusic = "SND_MX_ALF_pocket_rift_combat_out"
  })
  Area_2_Encounter_2:AddWave({
    {
      spawners = "Draugr_L3_H_RIFT1",
      maxActive = 1,
      totalSpawns = 1,
      spawnCooldown = 0
    },
    {
      spawners = "Draugr_L3_H_RIFT2",
      maxActive = 1,
      totalSpawns = 1,
      spawnCooldown = 4
    }
  })
  Area_2_Encounter_2:OnStart(function()
    Set_Encounter_Timer(120, Area_2_Encounter_2)
    Start_Timer()
  end)
  Area_2_Encounter_2:OnEnemySpawn(PlaySoundEnemySpawnFightRift110)
  Area_2_Encounter_2:OnStart(function()
    GameObjects.Reaction_Threat_High.LuaObjectScript.Trigger()
  end)
  Area_2_Encounter_2:OnComplete(StopFightRift110)
  Area_2_Encounter_2:OnComplete(Event_Complete)
  Area_2_Encounter_2:OnComplete(function()
    LD.SetMarkerState("ALF_300_LeftBeachFight", 0)
  end)
end
function OnSaveCheckpoint(level)
  return {
    levelstate = checkpoint.Save(),
    varGateUnblocked = varGateUnblocked,
    varTendrilDropDownBroken = varTendrilDropDownBroken
  }
end
function OnRestoreCheckpoint(level, savedInfo)
  checkpoint.Restore(savedInfo.levelstate)
  varGateUnblocked = savedInfo.varGateUnblocked
  varTendrilDropDownBroken = savedInfo.varTendrilDropDownBroken or false
end
function OnEvaluateLoadGroup_Lighting()
  if game.Level.GetVariable("ALF_LightAcquired") == false then
    return "LightingPre"
  elseif game.Level.GetVariable("ALF_LightAcquired") == true then
    return "LightingPost"
  end
end
function RecenterFloorPuzzle()
  game.Camera.Recenter({
    TimeStart = 0,
    TimeDuration = 2.4,
    LockRecenter = 0.67,
    YawRange = -1,
    TriggerLeft = 0,
    ReturnLeft = 1,
    ReturnRight = 1,
    TriggerRight = 0,
    PitchRange = -1,
    TriggerUp = 0,
    ReturnUp = 18,
    ReturnDown = 18,
    TriggerDown = 0
  })
end
local spinningRingsDrivenObjectSoundTable = {
  UseExplicitSoundMotion = true,
  SoundEmitter = nil,
  OnForward = "SND_MECH_Puzl_TendrilSpin_Rings_LP",
  OnForwardFrame = -1,
  OnBackward = "SND_MECH_Puzl_TendrilSpin_Rings_LP",
  OnBackwardFrame = -1,
  OnRewind = "SND_MECH_Puzl_TendrilSpin_Rings_LP",
  OnRewindFrame = -1
}
local gateEmitters = {
  top = {},
  center = {},
  bottom = {},
  gate = nil
}
local gate_0Emitters = {
  top = {},
  center = {},
  bottom = {},
  gate = nil
}
local gateTable = {gateEmitters, gate_0Emitters}
local gateEvents = {
  gateTimer = "SND_MECH_Alfheim_Door_Puzzle_Door_Gem_Countdown",
  gateOpen = "SND_MECH_Puzzle_Gate_Alf110_LP",
  gateStuck = "SND_MECH_Puzzle_Gate_Stuck_Alf110",
  gateTimerTickingLoop = "SND_MECH_Puzzle_Timer_01_LP",
  gateTimerTickingSpeedUp = "SND_MECH_Puzzle_Timer_Speed_x2"
}
local gateMonitor, gate0Monitor
function SoundInit()
  local spinningRingsSoundEmitterTarget = GameObjects.Tendrils_Group:FindSingleSoundEmitterByName("SNDSpinningRingsMechanism")
  if spinningRingsSoundEmitterTarget then
    spinningRingsDrivenObjectSoundTable.SoundEmitter = spinningRingsSoundEmitterTarget
  end
  gateEmitters[1] = gateEmitters.top
  gateEmitters[2] = gateEmitters.center
  gateEmitters[3] = gateEmitters.bottom
  gate_0Emitters[1] = gate_0Emitters.top
  gate_0Emitters[2] = gate_0Emitters.center
  gate_0Emitters[3] = gate_0Emitters.bottom
  table.insert(gateEmitters[1], GameObjects.SNDGrpGateTimer:FindSingleSoundEmitterByName("SNDGate_Top_1"))
  table.insert(gateEmitters[1], GameObjects.SNDGrpGateTimer:FindSingleSoundEmitterByName("SNDGate_Top_2"))
  table.insert(gateEmitters[2], GameObjects.SNDGrpGateTimer:FindSingleSoundEmitterByName("SNDGate_Center_1"))
  table.insert(gateEmitters[2], GameObjects.SNDGrpGateTimer:FindSingleSoundEmitterByName("SNDGate_Center_2"))
  table.insert(gateEmitters[3], GameObjects.SNDGrpGateTimer:FindSingleSoundEmitterByName("SNDGate_Bottom_1"))
  table.insert(gateEmitters[3], GameObjects.SNDGrpGateTimer:FindSingleSoundEmitterByName("SNDGate_Bottom_2"))
  table.insert(gate_0Emitters[1], GameObjects.SNDGrpGate_0Timer:FindSingleSoundEmitterByName("SNDGate_0_Top_1"))
  table.insert(gate_0Emitters[1], GameObjects.SNDGrpGate_0Timer:FindSingleSoundEmitterByName("SNDGate_0_Top_2"))
  table.insert(gate_0Emitters[1], GameObjects.SNDGrpGate_0Timer:FindSingleSoundEmitterByName("SNDGate_0_Top_3"))
  table.insert(gate_0Emitters[1], GameObjects.SNDGrpGate_0Timer:FindSingleSoundEmitterByName("SNDGate_0_Top_4"))
  table.insert(gate_0Emitters[2], GameObjects.SNDGrpGate_0Timer:FindSingleSoundEmitterByName("SNDGate_0_Center_1"))
  table.insert(gate_0Emitters[2], GameObjects.SNDGrpGate_0Timer:FindSingleSoundEmitterByName("SNDGate_0_Center_2"))
  table.insert(gate_0Emitters[2], GameObjects.SNDGrpGate_0Timer:FindSingleSoundEmitterByName("SNDGate_0_Center_3"))
  table.insert(gate_0Emitters[2], GameObjects.SNDGrpGate_0Timer:FindSingleSoundEmitterByName("SNDGate_0_Center_4"))
  table.insert(gate_0Emitters[3], GameObjects.SNDGrpGate_0Timer:FindSingleSoundEmitterByName("SNDGate_0_Bottom_1"))
  table.insert(gate_0Emitters[3], GameObjects.SNDGrpGate_0Timer:FindSingleSoundEmitterByName("SNDGate_0_Bottom_2"))
  table.insert(gate_0Emitters[3], GameObjects.SNDGrpGate_0Timer:FindSingleSoundEmitterByName("SNDGate_0_Bottom_3"))
  table.insert(gate_0Emitters[3], GameObjects.SNDGrpGate_0Timer:FindSingleSoundEmitterByName("SNDGate_0_Bottom_4"))
  gateEmitters.gate = GameObjects.Gate:FindSingleSoundEmitterByName("SNDGate_AlfDgn110")
  gate_0Emitters.gate = GameObjects.Gate_0:FindSingleSoundEmitterByName("SNDGate_0_AlfDgn110")
end
function SoundOnStart()
  GameObjects.WheelCrank_Alfheim.LuaObjectScript.DrivenObjectSoundSetup(spinningRingsDrivenObjectSoundTable)
end
function GateTimerSound(gateNumber, gatePosition)
  local emitters = gateTable[gateNumber][gatePosition]
  for i = 1, #emitters do
    LD.PlaySound(emitters[i], gateEvents.gateTimer)
  end
end
function GateSound(gateNumber, event)
  LD.PlaySound(gateTable[gateNumber].gate, event)
end
function StopGateSound(gateNumber, event)
  LD.StopSound(gateTable[gateNumber].gate, event)
end
function PlayGateAnimSound()
  if gateMonitor == nil then
    gateMonitor = monitors.CreateAnimFrameMonitor(GameObjects.Gate)
    if varGateUnblocked == false then
      gateMonitor:OnFrameForward(1, function()
        GateTimerSound(1, 1)
        GateSound(1, gateEvents.gateTimerTickingLoop)
      end)
      gateMonitor:OnFrameForward(16, function()
        GateTimerSound(1, 2)
      end)
      gateMonitor:OnFrameForward(31, function()
        GateTimerSound(1, 3)
      end)
      gateMonitor:OnFrameForward(60, function()
        GateSound(1, gateEvents.gateStuck)
      end)
      gateMonitor:OnFrameForward(79, function()
        if not varGateIsMoving then
          StopGateSound(1, gateEvents.gateTimerTickingLoop)
        end
      end)
      gateMonitor:OnFrameForward(81, function()
        GateSound(1, gateEvents.gateOpen)
        GateSound(1, gateEvents.gateTimerTickingSpeedUp)
      end)
    else
      gateMonitor:OnFrameForward(82, function()
        GateTimerSound(1, 1)
        GateSound(1, gateEvents.gateOpen)
        GateSound(1, gateEvents.gateTimerTickingLoop)
      end)
      gateMonitor:OnFrameForward(97, function()
        GateTimerSound(1, 2)
      end)
      gateMonitor:OnFrameForward(111, function()
        GateTimerSound(1, 3)
      end)
      gateMonitor:OnFrameForward(120, function()
        GateSound(1, gateEvents.gateTimerTickingSpeedUp)
      end)
    end
    gateMonitor:OnFrameBackward(80, function()
      StopGateSound(1, gateEvents.gateTimerTickingLoop)
      StopGateSound(1, gateEvents.gateOpen)
      StopGateAnimSound()
    end)
  end
end
function PlayGate_0AnimSound()
  if gate0Monitor == nil then
    gate0Monitor = monitors.CreateAnimFrameMonitor(GameObjects.Gate_0)
    gate0Monitor:OnFrameForward(1, function()
      GateTimerSound(2, 1)
      GateSound(2, gateEvents.gateTimerTickingLoop)
    end)
    gate0Monitor:OnFrameForward(16, function()
      GateTimerSound(2, 2)
    end)
    gate0Monitor:OnFrameForward(31, function()
      GateTimerSound(2, 3)
    end)
    gate0Monitor:OnFrameForward(60, function()
      GateSound(2, gateEvents.gateOpen)
      GateSound(2, gateEvents.gateTimerTickingSpeedUp)
    end)
    gate0Monitor:OnFrameBackward(57, function()
      StopGateSound(2, gateEvents.gateTimerTickingLoop)
      StopGateSound(2, gateEvents.gateOpen)
      StopGate0AnimSound()
    end)
  end
end
function StopGateAnimSound()
  if gateMonitor ~= nil then
    gateMonitor:Stop()
    gateMonitor:Terminate()
    gateMonitor = nil
  end
end
function StopGate0AnimSound()
  if gate0Monitor ~= nil then
    gate0Monitor:Stop()
    gate0Monitor:Terminate()
    gate0Monitor = nil
  end
end
function KillPlane()
  local uiCalls = require("ui.uicalls")
  uiCalls.UI_Event_Fade_To_Black(0.25)
end
function Set_Encounter_Timer(timeRequirement, encounter)
  ec_TimeRequirement = timeRequirement
  ecTimer = StartLevelTimer(timeRequirement, function()
    EventFailed_TimeElapsed(encounter)
  end)
  ecTimer:Stop()
end
function Start_Timer()
  local startDelay = 1
  Challenge_Started = true
  LD.CallFunctionAfterDelay(function()
    ecTimer:Start()
  end, startDelay)
  hudTimeRemaining = math.floor(ec_TimeRequirement - ecTimer.time)
  local seconds = ec_TimeRequirement % 60
  local minutes = (hudTimeRemaining - seconds) / 60
  local Time_Text = string.format("%02d : %02d", minutes, seconds)
end
function Encounter_Timer()
  hudTimeRemaining = math.floor(ec_TimeRequirement - ecTimer.time)
  local seconds = hudTimeRemaining % 60
  local minutes = (hudTimeRemaining - seconds) / 60
  local Time_Text = string.format("%02d : %02d", minutes, seconds)
  uiCalls.EnableMechanicText(37906, {minutes, seconds})
end
function EventFailed_TimeElapsed(encounter)
  local seconds = Rift_Challenge_Duration % 60
  local minutes = Rift_Challenge_Duration / 60
  local Time_Text = string.format("%02d : %02d", minutes, seconds)
  uiCalls.DisableMechanicText()
  Despawn_Enemy_VFX(encounter)
  encounter:Reset()
  encounter:Stop()
  ResetRift_Callback(encounter)
  ecTimer:Stop()
  ecTimer:Reset()
  Challenge_Started = false
end
function Event_Complete()
  uiCalls.DisableMechanicText()
  ecTimer:Stop()
  ecTimer:Reset()
  Challenge_Started = false
end
function Despawn_Enemy_VFX(encounter)
  local minTime = 0.01
  local maxTime = 0.3
  local randomFn = function()
    return math.random(minTime * 1000, maxTime * 1000) / 1000
  end
  local enemies = encounter:GetActiveEnemies()
  for _, enemy in pairs(enemies) do
    if enemy ~= nil and enemy:IsDoingSyncMove() == false then
      timers.StartLevelTimer(randomFn(), function()
        if enemy ~= nil then
          SpawnFXAtCreatureLocation(enemy)
          enemy:Destroy()
        end
      end)
      CreatureInSyncMove_DelayDestruction(enemy)
    end
  end
  encounter:ResetLivingEnemiesCount()
  encounter:ReportWaveDespawned(nil)
end
function SpawnFXAtCreatureLocation(creature)
  local fx = game.FX.Spawn("Body_Fire_Explode", nil, {
    AutoDelete = true,
    EffectCreator = creature,
    Scale = 1.5
  })
  local lastEnemyPos = creature:GetWorldJointPosition(creature:GetJointIndex("JOPelvis1"))
  fx:SetWorldPosition(lastEnemyPos)
end
function CreatureInSyncMove_DelayDestruction(creature)
  delayDestruction = true
  delayDestruction_T[creature] = true
end
function UpdateCreatureDestruction()
  if delayDestruction == true then
    local remaining = 0
    for creature, _ in pairs(delayDestruction_T) do
      if creature ~= nil and delayDestruction_T[creature] == true then
        if creature:IsDoingSyncMove() == false then
          SpawnFXAtCreatureLocation(creature)
          creature:Destroy()
          delayDestruction_T[creature] = nil
        else
          remaining = remaining + 1
        end
      end
    end
    if remaining == 0 then
      delayDestruction = false
      delayDestruction_T = {}
    end
  end
end
function ResetRift_Callback(encounter)
  local alf300 = game.FindLevel("Alf300_LakeDark")
  if alf300 ~= nil then
    alf300:CallScript("ResetRiftFight_NGP")
  end
end
