local EC = require("design.Encounter")
local LD = require("design.LevelDesignLibrary")
local timers = require("level.timer")
local monitors = require("level.MonitorLibrary")
local checkpoint = require("level.checkpoint")
local collisionCheck = require("camera.collisioncheck")
local thisLevel, player, son, Area_1_Encounter_1, Area_2_Encounter_1, Area_3_Encounter_1, Area_4_Encounter_1, Area_4_Encounter_2, PDB_Encounter_1, A2_E1_Wave2, A3_E1_Wave2, A3_E1_Wave3, Repop_A4E1, Traveler_HealthMonitor, Witch_HealthMonitor, ZM_PDB_Start, ZM_A1E1
local HudToggle = false
local penDepth = 0.2
local verticalP = 0.5
local horizontalP = 0
local travelerStatueBroken = false
local A1E1Complete = false
local dragonShrinesBroken = 0
local attackZoneMortar, attackZoneBreath, TakeOffWhoosh, Beam_Attack_Zones, TravelerDespawnMonitor
function OnScriptLoaded(level)
  thisLevel = level
  player = game.Player.FindPlayer()
  son = game.AI.FindSon()
  if game.Level.GetVariable("CompletedCineNumber") >= 340 then
    Fanatic_Pray_1()
    Fanatic_Pray_2()
    Fanatic_Pray_3()
    Main_Square2()
    Repop_Main_Square()
    Prologue_Dragon_Breath()
  end
  attackZoneBreath = level:GetGameObject("Beam_Attack_Zones")
  attackZoneMortar = level:GetGameObject("Mortar_Attack_Zones")
  TakeOffWhoosh = level:GetGameObject("TakeOffWhoosh_Xpl650_MasonTrailCave")
  Beam_Attack_Zones = level:GetGameObject("Beam_Attack_Zones")
  game.Audio.StartMusicMaster("SND_MX_XPL650_start_master")
end
function OnStart(level, obj)
  if game.Level.GetVariable("CompletedCineNumber") >= 340 then
    if PDB_Encounter_1:WasRunning() then
      PDB_Encounter_1:Start()
    end
    if Area_1_Encounter_1:WasRunning() then
      Area_1_Encounter_1:Start()
    end
    if Area_2_Encounter_1:WasRunning() then
      Area_2_Encounter_1:Start()
    end
    if Area_3_Encounter_1:WasRunning() then
      Area_3_Encounter_1:Start()
    end
  end
  LD.HideFX(TakeOffWhoosh)
  GameObjects.LiftGate_Xpl400.LuaObjectScript.ExcludeSon()
  GameObjects.LiftGate_Xpl401.LuaObjectScript.ExcludeSon()
end
function LuaHook_PlayTakeOffWhoosh()
  if TakeOffWhoosh ~= nil then
    LD.ShowFX(TakeOffWhoosh)
  end
end
function DragonStatue_CheckpointComplete()
  print("removed the checkpoint because it can break the game")
end
function DisableDragonZones()
  attackZoneMortar:HideEntityVolume()
  attackZoneBreath:HideEntityVolume()
end
function Pillar_L_Damaged()
end
function Pillar_L_Broken()
  game.World.StoreCheckpoint({
    OverrideObject = GameObjects.PrayOverride01.Child
  })
end
function Pillar_C_Broken()
  game.World.StoreCheckpoint({
    OverrideObject = GameObjects.PrayOverride01.Child
  })
end
function Pillar_R_Broken()
  if A1E1Complete == true then
    game.World.StoreCheckpoint({
      OverrideObject = GameObjects.PrayOverride03.Child
    })
  end
end
function Pillar_Traveler_Fight()
  if A1E1Complete == true and travelerStatueBroken == true then
    game.Audio.PlayBanter("Xpl650_Shrine" .. tostring(dragonShrinesBroken))
  end
end
function StartFinalCaveFight()
  local questState = game.QuestManager.GetQuestState("Quest_WorldDragon_Fafnir_Objective_01")
  if questState == "Complete" then
    Area_4_Encounter_2:Start()
  end
end
function A3E1Finished()
end
function DragonDispelStarted()
  local dragon = LD.FindSingleAIByMarker("DragonMarker")
  if dragon ~= nil then
    GameObjects.dragon_AttackZone.LuaObjectScript.SetDispelInProgress()
  end
end
function DragonRelease()
  local dragon = LD.FindSingleAIByMarker("DragonMarker")
  if dragon ~= nil then
    LD.HideFX(GameObjects.dragon_fx_chain)
    GameObjects.dragon_AttackZone.LuaObjectScript.SetDragonFree()
    game.Audio.StartMusic("SND_MX_XPL650_free_dragon")
    game.Audio.SetCheckpointedMusic("SND_MX_XPL650_explore2_in")
    LD.CallFunctionAfterDelay(function()
      game.Audio.PlayBanter("Xpl650_FafnirBeFree")
    end, 6)
  end
end
function CheckZoneLocalDragonQuest()
  if dragonShrinesBroken == 0 then
    LD.ActivateQuest("Quest_WorldDragon_Fafnir_Parent")
    game.Audio.SetBanterFact("Seen1Dragon", "True")
  end
end
function CheckBreakableLocalDragonQuest()
  dragonShrinesBroken = dragonShrinesBroken + 1
  game.QuestManager.IncrementQuestProgress("Quest_WorldDragon_Fafnir_Objective_01", 1)
  game.Audio.PlayBanter("Xpl650_Shrine" .. tostring(dragonShrinesBroken))
end
function CheckBreakableDragonQuestTraveler()
  travelerStatueBroken = true
  dragonShrinesBroken = dragonShrinesBroken + 1
  game.QuestManager.IncrementQuestProgress("Quest_WorldDragon_Fafnir_Objective_01", 1)
  if A1E1Complete == true then
    game.Audio.PlayBanter("Xpl650_Shrine" .. tostring(dragonShrinesBroken))
  end
end
function DisableBeamZone()
  Beam_Attack_Zones:HideEntityVolume()
end
function WarpSonBehind()
  local OneMeterBehindKratos = player.WorldPosition - player:GetWorldForward()
  if not collisionCheck.isTargetInFrustumUnobstructed(son:GetWorldPosition(), horizontalP, verticalP, penDepth, HudToggle) then
    son:Warp(OneMeterBehindKratos, player:GetWorldForward())
  end
end
function Prologue_Dragon_Breath()
  PDB_Encounter_1 = EC.NewEncounter(thisLevel, "Prologue Dragon Breath", {
    CheckpointOnComplete = false,
    LeashZone = "NavLeash_Main"
  })
  PDB_Encounter_1:AddWave({
    {
      spawners = "Fanatic_DragonPatrol",
      spawnLocators = "A4_P_LOC_1",
      useSpawnLocatorsOnly = true,
      maxActive = 1,
      totalSpawns = 1,
      spawnCooldown = 0
    },
    {
      spawners = "Fanatic_DragonPatrol",
      spawnLocators = "A4_P_LOC_3",
      useSpawnLocatorsOnly = true,
      maxActive = 1,
      totalSpawns = 1,
      spawnCooldown = 0.7
    }
  })
  PDB_Encounter_1:SetStartZone(GameObjects.EntZn_P_DragonBreath)
end
function Fanatic_Pray_1()
  local powerLevel
  local cineNumber = game.Level.GetVariable("CompletedCineNumber")
  if 600 <= cineNumber then
    powerLevel = 6
  end
  Area_1_Encounter_1 = EC.NewEncounter(thisLevel, "[Area 1]Fanatic Pray 1", {
    CheckpointOnComplete = true,
    LeashZone = "NavLeash_Traveler",
    StartMusic = "SND_MX_XPL650_guard_fight_in",
    StopMusic = "SND_MX_XPL650_explore1_in"
  })
  Area_1_Encounter_1:AddWave({
    powerLevel = powerLevel,
    {
      spawners = "Fanatic_Pray_1_T2",
      markerID = "Fanatic_Pray_1",
      maxActive = 1,
      totalSpawns = 1,
      spawnCooldown = 0
    },
    {
      spawners = "Traveler00_Spawn_T2",
      markerID = "Traveler_Pray_1",
      spawnLocators = "A1_A_LOC_1",
      spawnWad = "Xpl650_AI_01",
      useSpawnLocatorsOnly = true,
      maxActive = 1,
      totalSpawns = 1,
      spawnCooldown = 0
    }
  })
  Area_1_Encounter_1:AddWave({
    prioritizeOnScreenSpawners = true,
    requireSpawnersInRange = {3, 20},
    triggerWaveFromScript = true,
    {
      spawners = "Bandit00_DSW_SP_SFG_T2",
      spawnLocators = "A1_B_LOC_*",
      spawnWad = "Xpl650_AI_02",
      useSpawnLocatorsOnly = true,
      maxActive = 1,
      totalSpawns = 1,
      spawnCooldown = 0,
      powerLevel = powerLevel
    }
  })
  Area_1_Encounter_1:AddWave({
    prioritizeOnScreenSpawners = true,
    requireSpawnersInRange = {3, 20},
    triggerWaveFromScript = true,
    {
      spawners = "Bandit00_DSW_SP_SFG_T2",
      spawnLocators = "A1_B_LOC_*",
      spawnWad = "Xpl650_AI_02",
      useSpawnLocatorsOnly = true,
      maxActive = 1,
      totalSpawns = 1,
      spawnCooldown = 0,
      powerLevel = powerLevel
    }
  })
  Area_1_Encounter_1:SetStartZone(GameObjects.EntZn_Area_4_Encounter_2)
  Area_1_Encounter_1:OnEnemySpawn(Traveler_Health_Encounter, {
    markerID = "Traveler_Pray_1"
  })
  ZM_A1E1 = monitors.CreateEntityZoneMonitor(player, GameObjects.EntZn_AlertA1E1)
  ZM_A1E1:OnEnter(function()
    Area_1_Encounter_1:AlertEnemies(1)
  end)
  TravelerDespawnMonitor = monitors.CreateEntityZoneMonitor(player, GameObjects.TravelerFightDespawn)
  TravelerDespawnMonitor:OnEnter(function()
    if Area_1_Encounter_1 ~= nil and not Area_1_Encounter_1:IsComplete() then
      Area_1_Encounter_1:DespawnEnemies()
      Area_1_Encounter_1:Reset()
      Area_1_Encounter_1:Stop()
    end
  end)
  Area_1_Encounter_1:OnComplete(function()
    LD.UnlockBestiaryEntry_EndOfEncounter("Bestiary_Unlock_Seidr_Traveler")
  end)
  Area_1_Encounter_1:OnComplete(function()
    A1E1Complete = true
  end)
  Area_1_Encounter_1:OnComplete(Pillar_Traveler_Fight)
end
local Traveler_Next = function()
  Area_1_Encounter_1:StartWave()
end
function Traveler_Health_Encounter(Enemy)
  if Enemy ~= nil then
    local Traveler_Health = Enemy:GetHitPoints()
    Traveler_HealthMonitor = monitors.CreateHealthMonitor(Enemy)
    local Health_Phase_1 = Traveler_Health * 0.9
    local Health_Phase_2 = Traveler_Health * 0.5
    Traveler_HealthMonitor:OnHealthLessThan(Health_Phase_1, Traveler_Next)
    Traveler_HealthMonitor:OnHealthLessThan(Health_Phase_2, Traveler_Next)
  end
end
function Fanatic_Pray_2()
  local powerLevel
  local cineNumber = game.Level.GetVariable("CompletedCineNumber")
  if 600 <= cineNumber then
    powerLevel = 6
  end
  Area_2_Encounter_1 = EC.NewEncounter(thisLevel, "[Area 1]Fanatic Pray 2", {
    CheckpointOnComplete = false,
    LeashZone = "NavLeash_Main"
  })
  Area_2_Encounter_1:AddWave({
    {
      spawners = "Fanatic_Pray_2_T2",
      markerID = "Fanatic_Pray_2",
      maxActive = 1,
      totalSpawns = 1,
      spawnCooldown = 0,
      powerLevel = powerLevel
    }
  })
  Area_2_Encounter_1:SetStartZone(GameObjects.EntZn_Area_4_Encounter_1)
  Area_2_Encounter_1:SetAlertZone(GameObjects.Alert02PrayZone)
end
function Fanatic_Pray_3()
  local powerLevel
  local cineNumber = game.Level.GetVariable("CompletedCineNumber")
  if 600 <= cineNumber then
    powerLevel = 6
  end
  Area_3_Encounter_1 = EC.NewEncounter(thisLevel, "[Area 1]Fanatic Pray 3", {
    CheckpointOnComplete = false,
    LeashZone = "NavLeash_Main"
  })
  Area_3_Encounter_1:AddWave({
    timeBeforeNextWave = 0.1,
    {
      spawners = "Fanatic_Pray_3_T2",
      markerID = "Fanatic_Pray_3",
      maxActive = 1,
      totalSpawns = 1,
      spawnCooldown = 0,
      powerLevel = powerLevel
    }
  })
  Area_3_Encounter_1:AddWave({
    {
      spawners = "Bandit00_GSHBC_SP_ES_T3",
      spawnLocators = "A3_B_LOC_1",
      spawnWad = "Xpl650_AI_02",
      useSpawnLocatorsOnly = true,
      maxActive = 1,
      totalSpawns = 1,
      spawnCooldown = 0,
      powerLevel = powerLevel
    },
    {
      spawners = "Bandit00_GSHBC_SP_ES_T3",
      spawnLocators = "A3_B_LOC_2",
      spawnWad = "Xpl650_AI_02",
      useSpawnLocatorsOnly = true,
      maxActive = 1,
      totalSpawns = 1,
      spawnCooldown = 0.1,
      powerLevel = powerLevel
    }
  })
  Area_3_Encounter_1:SetStartZone(GameObjects.EntZn_Area_4_Encounter_1)
  Area_3_Encounter_1:SetAlertZone(GameObjects.Alert01PrayZone)
end
function Main_Square2()
  local powerLevel
  local cineNumber = game.Level.GetVariable("CompletedCineNumber")
  if 600 <= cineNumber then
    powerLevel = 6
  end
  Area_4_Encounter_2 = EC.NewEncounter(thisLevel, "[Area 4]Main Square 2", {
    CheckpointOnComplete = true,
    LeashZone = "NavLeash_Main"
  })
  Area_4_Encounter_2:AddWave({
    {
      spawners = "Brawler00_A_SP_RC_T2",
      spawnLocators = "A4_C_LOC_1",
      spawnWad = "Xpl650_AI_02",
      useSpawnLocatorsOnly = true,
      markerID = "PocketRiftSpawn1Enemy",
      maxActive = 1,
      totalSpawns = 1,
      spawnCooldown = 1.2,
      powerLevel = powerLevel
    },
    {
      spawners = "Brawler00_A_SP_RC_T2",
      spawnLocators = "A4_C_LOC_2",
      spawnWad = "Xpl650_AI_02",
      useSpawnLocatorsOnly = true,
      markerID = "PocketRiftSpawn2Enemy",
      maxActive = 1,
      totalSpawns = 1,
      spawnCooldown = 0.5,
      powerLevel = powerLevel
    },
    {
      spawners = "Witch10_Spawn",
      markerID = "Witch_Main",
      spawnLocators = "A4_A_LOC_1",
      spawnWad = "Xpl650_AI_01",
      useSpawnLocatorsOnly = true,
      maxActive = 1,
      totalSpawns = 1,
      spawnCooldown = 6,
      powerLevel = powerLevel
    }
  })
  Area_4_Encounter_2:OnEnemySpawn(function()
    GameObjects.PocketRiftSpawn1.LuaObjectScript.PlaySoundCombatPortalEnemySpawn()
  end, {
    markerID = "PocketRiftSpawn1Enemy"
  })
  Area_4_Encounter_2:OnEnemySpawn(function()
    GameObjects.PocketRiftSpawn2.LuaObjectScript.PlaySoundCombatPortalEnemySpawn()
  end, {
    markerID = "PocketRiftSpawn2Enemy"
  })
  Area_4_Encounter_2:OnStart(function()
    LD.CallFunctionAfterDelay(function()
      GameObjects.PocketRiftSpawn1.LuaObjectScript.StartCombatState()
    end, 0.4)
    GameObjects.PocketRiftSpawn2.LuaObjectScript.StartCombatState()
    LD.CallFunctionAfterDelay(function()
      GameObjects.PocketRiftSpawn1.LuaObjectScript.SpawningDone()
    end, 5)
    LD.CallFunctionAfterDelay(function()
      GameObjects.PocketRiftSpawn2.LuaObjectScript.SpawningDone()
    end, 4)
  end)
  Area_4_Encounter_2:OnComplete(DisableBeamZone)
end
function Repop_Main_Square()
  Repop_A4E1 = EC.NewEncounter(thisLevel, "[Repop Area 4]Main Square", {
    CheckpointOnComplete = false,
    LeashZone = "NavLeash_Main",
    RepopulationEncounter = true,
    MustHaveCompletedList = {
      "[Area 4]Main Square",
      "[Area 1]Fanatic Pray 1",
      "[Area 1]Fanatic Pray 2",
      "[Area 1]Fanatic Pray 3",
      "[Area 4]Main Square 2"
    }
  })
  Repop_A4E1:AddWave({
    {
      spawners = "T6_Brawler00_A_SP_RC",
      spawnLocators = "A4_R_LOC_1",
      spawnWad = "Xpl650_AI_02",
      useSpawnLocatorsOnly = true,
      maxActive = 1,
      totalSpawns = 1,
      spawnCooldown = 0
    },
    {
      spawners = "T6_Brawler00_A_SP_RC",
      spawnLocators = "A4_R_LOC_2",
      spawnWad = "Xpl650_AI_02",
      useSpawnLocatorsOnly = true,
      maxActive = 1,
      totalSpawns = 1,
      spawnCooldown = 1
    },
    {
      spawners = "E_T6_Brawler00_A_SP_RC",
      spawnLocators = "A4_R_LOC_3",
      spawnWad = "Xpl650_AI_02",
      useSpawnLocatorsOnly = true,
      maxActive = 1,
      totalSpawns = 1,
      spawnCooldown = 3.4
    }
  })
  Repop_A4E1:AddWave({
    prioritizeOnScreenSpawners = true,
    requireSpawnersInRange = {3, 25},
    {
      spawners = "T6_Bandit00_DSW_SP_SFG",
      spawnLocators = "A4_R_LOC_*",
      spawnWad = "Xpl650_AI_02",
      useSpawnLocatorsOnly = true,
      maxActive = 1,
      totalSpawns = 1,
      spawnCooldown = 0
    },
    {
      spawners = "T7_Bandit00_DSW_SP_SFG",
      spawnLocators = "A4_R_LOC_*",
      spawnWad = "Xpl650_AI_02",
      useSpawnLocatorsOnly = true,
      maxActive = 1,
      totalSpawns = 1,
      spawnCooldown = 3
    },
    {
      spawners = "E_T6_Bandit00_DSW_SP_SFG",
      spawnLocators = "A4_R_LOC_*",
      spawnWad = "Xpl650_AI_02",
      useSpawnLocatorsOnly = true,
      maxActive = 1,
      totalSpawns = 1,
      spawnCooldown = 7
    },
    {
      spawners = "T7_Bandit00_DSW_SP_SFG",
      spawnLocators = "A4_R_LOC_*",
      spawnWad = "Xpl650_AI_02",
      useSpawnLocatorsOnly = true,
      maxActive = 1,
      totalSpawns = 1,
      spawnCooldown = 15
    }
  })
  Repop_A4E1:SetStartZone(GameObjects.EntZn_Repop)
  Repop_A4E1:OnStart(function()
    GameObjects.PocketRiftSpawn3.LuaObjectScript.StartCombatState()
    LD.CallFunctionAfterDelay(function()
      GameObjects.PocketRiftSpawn4.LuaObjectScript.StartCombatState()
    end, 1)
    LD.CallFunctionAfterDelay(function()
      GameObjects.PocketRiftSpawn5.LuaObjectScript.StartCombatState()
    end, 2)
    LD.CallFunctionAfterDelay(function()
      GameObjects.PocketRiftSpawn3.LuaObjectScript.SpawningDone()
    end, 4)
    LD.CallFunctionAfterDelay(function()
      GameObjects.PocketRiftSpawn4.LuaObjectScript.SpawningDone()
    end, 5)
    LD.CallFunctionAfterDelay(function()
      GameObjects.PocketRiftSpawn5.LuaObjectScript.SpawningDone()
    end, 6)
  end)
  Repop_A4E1:OnEnemyDeath(function()
    Repop_A4E1:StartWave(2)
  end, {count = 2})
end
local xpl650BanterMus = false
local xpl650Music = false
function xpl650GateBanterMus()
  game.Audio.StartMusic("SND_MX_XPL650_enter_cave")
  game.Audio.SetCheckpointedMusic("SND_MX_XPL650_explore1_in")
  xpl650BanterMus = true
  xpl650Music = true
end
function xpl650GateEnter()
  if xpl650Music == false and xpl650BanterMus == true then
    game.Audio.StartCheckpointedMusic("SND_MX_XPL650_explore1_in")
    xpl650Music = true
  end
end
function xpl650MusIdle()
  if xpl650Music == true then
    game.Audio.StartMusic("SND_MX_XPL650_idle")
    xpl650Music = false
  end
end
function OnSaveCheckpoint(level)
  return {
    levelstate = checkpoint.Save(),
    dragonShrinesBroken = dragonShrinesBroken,
    xpl650Music = xpl650Music,
    xpl650BanterMus = xpl650BanterMus
  }
end
function OnRestoreCheckpoint(level, savedInfo)
  checkpoint.Restore(savedInfo.levelstate)
  dragonShrinesBroken = savedInfo.dragonShrinesBroken
  xpl650Music = savedInfo.xpl650Music
  xpl650BanterMus = false
  if savedInfo.xpl650BanterMus ~= nil then
    xpl650BanterMus = savedInfo.xpl650BanterMus
  end
end
