local LD = require("design.LevelDesignLibrary")
local ND = require("design.NarrativeDesignLibrary")
local collisionCheck = require("camera.collisioncheck")
local timer = require("level.timer")
local monitors = require("level.MonitorLibrary")
local actor = require("narrative.actor")
local CCEC = require("camera.camera_cineentercamera")
local TUT = require("game.GlobalTutorials")
local thisObj, thisLevel, player, son, cineB_lights, kratosActor, sonActor, banditActor, brawlerActor, helwalkerActor, firstHumanKill_PartA_ActorTable, firstHumanKill_PartB_ActorTable, kra_Start, kra_Start_Fwd, zombie1, zombie2, zombie3
local zombiesKilledCounter = 0
local zombie1_DeathMonitor, zombie2_DeathMonitor, zombie3_DeathMonitor, impactFX, cameraCineEnter, hel1sound, hel2sound, hel3sound
function OnScriptLoaded(level, obj)
  thisObj = obj
  thisLevel = level
  player = game.Player.FindPlayer()
  son = game.AI.FindSon()
  cameraCineEnter = CCEC.CineEnterCamera.New("ENV_CineEnter_narRivFirstHumanKill030CineScene", 4, nil)
  cameraCineEnter:SetObjectToSleep(obj)
  game.SubObject.Sleep(obj)
end
function OnStart(level, obj)
  if game.CHECK_FEATURE("PRESTREAM_ENEMIES") then
    local pos = thisObj:GetWorldJointPosition(thisObj:GetJointIndex("bandit_start"))
    game.Encounters.RequestGlobalCharacterPrestream(thisLevel, pos, "CRT_BanditHuman00", "Bandit00")
    pos = thisObj:GetWorldJointPosition(thisObj:GetJointIndex("helwalker_start"))
    game.Encounters.RequestGlobalCharacterPrestream(thisLevel, pos, "CRT_Bandit00", "Helwalker02")
    pos = thisObj:GetWorldJointPosition(thisObj:GetJointIndex("brawler_start"))
    game.Encounters.RequestGlobalCharacterPrestream(thisLevel, pos, "CRT_BrawlerCine00", "Brawler00")
  end
  InitializeVariables()
  HideCineLightsAndFX()
  if game.Level.GetVariable("CompletedCineNumber") <= 120 then
    CreateActorsAndPositions()
    SetSpawnFunctions()
  end
end
function OnUpdate(level, obj)
  if cameraCineEnter ~= nil then
    cameraCineEnter:Update()
  end
end
function OnSaveCheckpoint(level, obj)
  local savedInfo = {}
  return savedInfo
end
function OnRestoreCheckpoint(level, obj, savedInfo)
end
function InitializeVariables()
  cineB_lights = GameObjects.Cine_Start_120
  impactFX = GameObjects.Riv250_AI01_Impact_FX.Child
end
function CreateActorsAndPositions()
  kratosActor = actor.Actor.New("Kratos", game.Player.FindPlayer)
  sonActor = actor.Actor.New("Son", game.AI.FindSon)
  banditActor = actor.Actor.New("BanditHuman")
  helwalkerActor = actor.Actor.New("HelWalker")
  brawlerActor = actor.Actor.New("Brawler")
  kra_Start_Fwd = thisObj:GetWorldJointForward(thisObj:GetJointIndex("kratos_start"))
  kra_Start = thisObj:GetWorldJointPosition(thisObj:GetJointIndex("kratos_start"))
  firstHumanKill_PartA_ActorTable = {
    {Actor = sonActor},
    {Actor = banditActor},
    {Actor = brawlerActor}
  }
  firstHumanKill_PartB_ActorTable = {
    {Actor = sonActor},
    {Actor = banditActor},
    {Actor = helwalkerActor}
  }
end
function SetSpawnFunctions()
  banditActor:SetSpawnFunction(function()
    local pos = thisObj:GetWorldJointPosition(thisObj:GetJointIndex("bandit_start"))
    local dir = thisObj:GetWorldJointForward(thisObj:GetJointIndex("bandit_start"))
    return game.AI.Spawn(thisLevel, pos, dir, "CRT_BanditHuman00", "BRA_FirstHumanKillA", {PowerLevel = 1}, "Bandit00")
  end)
  helwalkerActor:SetSpawnFunction(function()
    local pos = thisObj:GetWorldJointPosition(thisObj:GetJointIndex("helwalker_start"))
    local dir = thisObj:GetWorldJointForward(thisObj:GetJointIndex("helwalker_start"))
    return game.AI.Spawn(thisLevel, pos, dir, "CRT_Bandit00", "BRA_FirstHumanKillB_Spawn", {PowerLevel = 1}, "Helwalker02")
  end)
  brawlerActor:SetSpawnFunction(function()
    local pos = thisObj:GetWorldJointPosition(thisObj:GetJointIndex("brawler_start"))
    local dir = thisObj:GetWorldJointForward(thisObj:GetJointIndex("brawler_start"))
    return game.AI.Spawn(thisLevel, pos, dir, "CRT_BrawlerCine00", "BRA_FirstHumanKillA", {PowerLevel = 1}, "Brawler00")
  end)
end
function StartCineSequence()
  local firstHumanKillASeq = ND.CreateCineSequence(thisLevel, thisObj, "firstHumanKillA")
  DisableSelectInputs()
  firstHumanKillASeq:SetPostSkipMusic("SND_MX_RIV_start_master", "SND_MX_SonSick_master")
  firstHumanKillASeq:MarkAbleToSkip()
  firstHumanKillASeq:WaitForFunctionTrue(function()
    return not kratosActor:GetCreature():IsPlayingMove("MOV_GlobalRecall") and not kratosActor:GetCreature():IsPlayingMove("MOV_GlobalRecallExitNoAim")
  end)
  firstHumanKillASeq:RequestCineModeAndWait(kratosActor, thisObj)
  firstHumanKillASeq:Do(DisableFaceSwapping)
  firstHumanKillASeq:SpawnActorAndWait(banditActor)
  firstHumanKillASeq:SpawnActorAndWait(brawlerActor)
  firstHumanKillASeq:Do(DropAxeIfReturning)
  firstHumanKillASeq:ActorSync(kratosActor, {
    Slaves = firstHumanKill_PartA_ActorTable,
    Branch = "BRA_FirstHumanKillA",
    ReferenceJoint = "FirstHumanKill_SyncJoint",
    ReferenceJointOn = 0.135,
    ReferenceJointTweenTime = 0.45
  })
  firstHumanKillASeq:WaitForFunctionTrue(function()
    return brawlerActor:GetCreature():IsPlayingMove("MOV_FirstHumanKillA")
  end)
  firstHumanKillASeq:WaitUntilActorAnimPastFrame(brawlerActor, 66)
  firstHumanKillASeq:Do(function()
    game.FindLevel("Riv250_DangersSide"):CallScript("ShowCameraVolume_GoToFallenSon")
  end)
  firstHumanKillASeq:Do(function()
    game.FindLevel("Riv250_DangersSide"):CallScript("DisableAvoidSplineSmall")
  end)
  firstHumanKillASeq:Do(PlayEffects)
  firstHumanKillASeq:WaitForAndCompleteCineMode(kratosActor, thisObj)
  firstHumanKillASeq:Do(function()
    GameObjects.SonInteractZone.Child.LuaObjectScript:Enable()
  end)
  firstHumanKillASeq:Do(EnableSelectInputs)
  firstHumanKillASeq:WaitSeconds(2)
  firstHumanKillASeq:Do(function()
    game.Audio.PlayBanterNonCritical("RIV_FirstHumanSpill")
  end)
  firstHumanKillASeq:StartSequence()
end
function DropAxeIfReturning()
  if player ~= nil and player.Axe ~= nil and player.Axe.ThrowOutStatus == tweaks.tThrowOutStatus.eThrownWeaponStatus.kTOSInFlightReturn then
    player:DropThrowable("ATT_Axe")
  end
end
function PlayEffects()
  impactFX:Show()
  impactFX:JumpAnimToFrame(0)
  impactFX:PlayAnimToEnd()
end
function DisableSelectInputs()
  player.Pad:DisableGameButton(tweaks.ePad.kPadTriangle)
  player.Pad:DisableGameButton(tweaks.ePad.kPadR1)
  player.Pad:DisableGameButton(tweaks.ePad.kPadR2)
end
function EnableSelectInputs()
  player.Pad:EnableGameButton(tweaks.ePad.kPadTriangle)
  player.Pad:EnableGameButton(tweaks.ePad.kPadR1)
  player.Pad:EnableGameButton(tweaks.ePad.kPadR2)
end
function SetDriversAndTriggerMoveEvent()
  local rotationDriver = player:GetAnimDriver("firstHumanKillRotDriv")
  local translationDriver = player:GetAnimDriver("firstHumanKillTransDriv")
  rotationDriver.ValueVec = kra_Start_Fwd
  translationDriver.ValueVec = kra_Start
  player:TriggerMoveEvent("LE_StartFirstHumanKillA")
end
function PlayFirstHumanKillB()
  local firstHumanKillBSeq = ND.CreateCineSequence(thisLevel, thisObj, "firstHumanKillB")
  firstHumanKillBSeq:SetPostSkipMusic("SND_MX_RIV_start_master", "SND_MX_SonSick_master")
  firstHumanKillBSeq:MarkAbleToSkip()
  firstHumanKillBSeq:Do(StartPreCineCamera)
  firstHumanKillBSeq:SpawnActorAndWait(helwalkerActor)
  firstHumanKillBSeq:RequestCineModeAndWait(kratosActor, thisObj)
  firstHumanKillBSeq:ActorForceApproachAndWait(kratosActor, {
    Branch = "BRA_FirstHumanKillB",
    ReferenceJoint = "FirstHumanKill_SyncJoint",
    speed = ND.KraWalkSpeed,
    stop = false,
    radius = 0.3,
    weapon_state = "bare"
  })
  firstHumanKillBSeq:Do(PlayCineBLights)
  firstHumanKillBSeq:ActorSync(kratosActor, {
    Slaves = firstHumanKill_PartB_ActorTable,
    Branch = "BRA_FirstHumanKillB",
    ReferenceJoint = "FirstHumanKill_SyncJoint"
  })
  firstHumanKillBSeq:WaitForActorMoveComplete(banditActor)
  firstHumanKillBSeq:DespawnActor(banditActor)
  firstHumanKillBSeq:WaitUntilActorAnimPastFrame(kratosActor, 321)
  firstHumanKillBSeq:DespawnActor(brawlerActor)
  firstHumanKillBSeq:Do(SpawnZombies)
  firstHumanKillBSeq:Do(_G.DestroyBanditCorpses)
  firstHumanKillBSeq:Do(function()
    game.FindLevel("Riv250_DangersSide"):CallScript("HideCameraVolume_GoToFallenSon")
  end)
  firstHumanKillBSeq:Do(function()
    game.FindLevel("Riv250_DangersSide"):CallScript("DisableAvoidSplineSmall")
  end)
  firstHumanKillBSeq:WaitUntilActorAnimPastFrame(kratosActor, 1400)
  firstHumanKillBSeq:Do(function()
    zombie1:TriggerMoveEvent("kLEAlert")
    LD.PlaySound(hel1sound, "SND_CHR_Helwalker_Slow_Rise_Up")
  end)
  firstHumanKillBSeq:WaitUntilActorAnimPastFrame(kratosActor, 1560)
  firstHumanKillBSeq:Do(function()
    zombie2:TriggerMoveEvent("kLEAlert")
    LD.PlaySound(hel2sound, "SND_CHR_Helwalker_Slow_Rise_Up")
  end)
  firstHumanKillBSeq:WaitUntilActorAnimPastFrame(kratosActor, 1630)
  firstHumanKillBSeq:Do(function()
    zombie3:TriggerMoveEvent("kLEAlert")
    LD.PlaySound(hel3sound, "SND_CHR_Helwalker_Slow_Rise_Up")
  end)
  firstHumanKillBSeq:WaitUntilActorAnimPastFrame(kratosActor, 1655)
  firstHumanKillBSeq:WaitUntilActorAnimPastFrame(kratosActor, 1700)
  firstHumanKillBSeq:WaitUntilActorAnimPastFrame(kratosActor, 1752)
  firstHumanKillBSeq:WaitForAndCompleteCineMode(kratosActor, thisObj)
  firstHumanKillBSeq:DespawnActor(helwalkerActor)
  firstHumanKillBSeq:SetCompletedCineNumber(120)
  firstHumanKillBSeq:WaitForAndCompleteCineMode(kratosActor, thisObj)
  firstHumanKillBSeq:Do(function()
    firstHumanKillBSeq:EndSkipIfActive()
  end)
  firstHumanKillBSeq:Do(HostileZombies)
  firstHumanKillBSeq:Do(ClearPrestreamData)
  firstHumanKillBSeq:StopPuppetingActor(kratosActor)
  firstHumanKillBSeq:Do(EnableFaceSwapping)
  firstHumanKillBSeq:Do(HideCineLightsAndFX)
  firstHumanKillBSeq:Do(SetIdleContext)
  firstHumanKillBSeq:Do(_G.HellWalkerEncounterStart)
  firstHumanKillBSeq:StartSequence()
end
function PlayCineBLights()
  cineB_lights:Show()
  cineB_lights:JumpAnimToFrame(0)
  cineB_lights:PlayAnimToEnd()
end
function HideCineLightsAndFX()
  cineB_lights:Hide()
  impactFX:Hide()
end
function DisableFaceSwapping()
  if game.PhotoMode.SetFaceChangeEnabled then
    game.PhotoMode.SetFaceChangeEnabled(false)
  end
end
function EnableFaceSwapping()
  if game.PhotoMode.SetFaceChangeEnabled then
    game.PhotoMode.SetFaceChangeEnabled(true)
  end
end
function EnableCineMaterials()
  son:CallScript("LuaHook_FirstHumanKill")
end
function DisableCineMaterials()
  son:CallScript("LuaHook_originalMaterial")
end
function StartPreCineCamera()
  cameraCineEnter:Start()
end
function SetIdleContext()
  if sonActor.puppeteer ~= nil then
    sonActor.puppeteer:Clear()
    sonActor.puppeteer:ReturnToNav()
    sonActor.puppeteer:DetachPuppet()
    sonActor.puppeteer = nil
  end
  game.FindLevel("Riv250_DangersSide"):CallScript("LTW_AvoidEnemiesEnable")
end
function ClearPrestreamData()
  if game.CHECK_FEATURE("PRESTREAM_ENEMIES") then
    game.Encounters.ClearGlobalCharacterPrestreamRequest()
  end
end
function SpawnZombies()
  zombie1 = GameObjects.Helwalker_S_1.LuaObjectScript.SpawnEnemy()
  zombie2 = GameObjects.Helwalker_S_2.LuaObjectScript.SpawnEnemy()
  zombie3 = GameObjects.Helwalker_S_3.LuaObjectScript.SpawnEnemy()
  hel1sound = zombie1:FindSingleSoundEmitterByName("SNDSpawn")
  hel2sound = zombie2:FindSingleSoundEmitterByName("SNDSpawn")
  hel3sound = zombie3:FindSingleSoundEmitterByName("SNDSpawn")
end
function HostileZombies()
  zombie1:CallScript("LuaHook_SetInCombatState")
  zombie2:CallScript("LuaHook_SetInCombatState")
  zombie3:CallScript("LuaHook_SetInCombatState")
  LD.CallFunctionAfterDelay(function()
  end, 0.1)
  LD.CallFunctionAfterDelay(function()
  end, 0.1)
  LD.CallFunctionAfterDelay(function()
  end, 0.1)
  CreateZombieHealthMonitors()
  game.Audio.StartCheckpointedMusic("SND_MX_RIV_fight_undead_in")
  timer.StartLevelTimer(0.1, function()
    game.AI.FindSon():CallScript("EnterBehaviorContext", "WILL_NOT_FIGHT_BEHAVIOR_CONTEXT_CONFIG")
  end)
end
function CreateZombieHealthMonitors()
  zombie1_DeathMonitor = monitors.CreateDeathMonitor(zombie1)
  zombie2_DeathMonitor = monitors.CreateDeathMonitor(zombie2)
  zombie3_DeathMonitor = monitors.CreateDeathMonitor(zombie3)
  zombie1_DeathMonitor:OnDeath(ZombiesKilled)
  zombie2_DeathMonitor:OnDeath(ZombiesKilled)
  zombie3_DeathMonitor:OnDeath(ZombiesKilled)
end
function ZombiesKilled()
  zombiesKilledCounter = zombiesKilledCounter + 1
  if 2 < zombiesKilledCounter then
    _G.HellWalkerEncounterComplete()
  end
end
