local LD = require("design.LevelDesignLibrary")
local timers = require("level.timer")
local actor = require("narrative.actor")
local ND = require("design.NarrativeDesignLibrary")
local collisionCheck = require("camera.collisioncheck")
local thisObj, thisLevel, player, son
local kratosActor = actor.Actor.New("Kratos", game.Player.FindPlayer)
local sonActor = actor.Actor.New("Son", game.AI.FindSon)
local playedFirstHumanKillAftermath1 = false
local playedFirstHumanKillAftermath2 = false
local boostStarted = false
local fHKAftermathZones_Shown = false
local chainHintSpoken = false
local encouragementPrompt01_Pressed = false
local encouragementPrompt02_Pressed = false
local encouragementPrompt03_Pressed = false
local encouragementBanter01_Over = false
local encouragementBanter02_Over = false
local bUseFirstCamera, bUseSecondCamera, bUseThirdCamera, fStartFrustumCheckValue, fHoldingFrustumCheckValue, fCurrentFrustumCheckValue, bEmoCamCompleted, bEmoCamStarted
function OnScriptLoaded(level, obj)
  thisObj = obj
  thisLevel = level
  player = game.Player.FindPlayer()
  son = game.AI.FindSon()
  game.SubObject.Sleep(thisObj)
end
function OnStart()
  local cineNum = game.Level.GetVariable("CompletedCineNumber")
  if 130 <= cineNum or not fHKAftermathZones_Shown then
    GameObjects.BtrZone_FirstHumanKillAftermath01_B:Hide()
    GameObjects.BtrZone_FirstHumanKillAftermath03:Hide()
  else
    timers.StartLevelTimer(30, FirstHumanKillAftermath02_IfNeeded)
  end
  GameObjects.Encouragement_InteractZone01:Hide()
  GameObjects.Encouragement_InteractZone02:Hide()
  GameObjects.Encouragement_InteractZone03:Hide()
end
function OnUpdate(level, obj)
  if bEmoCamStarted == true then
    PlayEmotionalCam()
  end
end
function OnSaveCheckpoint(level, obj)
  local savedInfo = {}
  savedInfo.playedFirstHumanKillAftermath2 = playedFirstHumanKillAftermath2
  savedInfo.fHKAftermathZones_Shown = fHKAftermathZones_Shown
  savedInfo.boostStarted = boostStarted
  savedInfo.chainHintSpoken = chainHintSpoken
  return savedInfo
end
function OnRestoreCheckpoint(level, obj, savedInfo)
  playedFirstHumanKillAftermath2 = savedInfo.playedFirstHumanKillAftermath2
  fHKAftermathZones_Shown = savedInfo.fHKAftermathZones_Shown
  boostStarted = savedInfo.boostStarted
  chainHintSpoken = savedInfo.chainHintSpoken
end
function FirstHumanKillAftermath1_Banter()
  local aftermath1Seq = ND.CreateCineSequence(thisLevel, thisObj, "firstHumanKillAftermath")
  aftermath1Seq:WaitSeconds(2)
  aftermath1Seq:Do(function()
    game.AI.FindSon():CallScript("ClearBehaviorContext")
  end)
  aftermath1Seq:WaitSeconds(3)
  aftermath1Seq:Do(function()
    game.Audio.PlayBanter("RIV_FirstHumanKillAftermath01_A", EnableFHKAftermathZones)
  end)
  aftermath1Seq:WaitSeconds(4)
  aftermath1Seq:Do(function()
    son:CallScript("EnterBehaviorContext", "SAD_BEHAVIOR_CONTEXT_CONFIG")
  end)
  aftermath1Seq:Do(FirstHumanKillAftermath02_IfNeeded)
  aftermath1Seq:StartSequence()
end
function EnableFHKAftermathZones()
  LD.CompleteQuest("Quest_RiverPass_Objective201")
  _G.EnableBoost()
  LD.CallFunctionAfterDelay(_G.HellwalkerFightComplete, 12)
  if not boostStarted then
    GameObjects.BtrZone_FirstHumanKillAftermath01_B:Show()
    GameObjects.BtrZone_FirstHumanKillAftermath03:Show()
    fHKAftermathZones_Shown = true
  end
  game.World.StoreCheckpoint({
    OverrideObject = GameObjects.CheckpointOverride_BoostPuzzle.Child
  })
end
function FirstHumanKillAftermath02_IfNeeded()
  timers.StartLevelTimer(35, FirstHumanKillAftermath2_Banter)
end
function SonBoostStarted()
  boostStarted = true
  timers.StartLevelTimer(1.5, FirstHumanKillAftermath4_Banter)
  GameObjects.BtrZone_FirstHumanKillAftermath01_B:Hide()
  GameObjects.BtrZone_FirstHumanKillAftermath03:Hide()
end
function FirstHumanKillAftermath2_Banter()
  if not boostStarted and not playedFirstHumanKillAftermath2 then
    game.Audio.PlayBanterNonCritical("RIV_FirstHumanKillAftermath02")
    playedFirstHumanKillAftermath2 = true
    FirstHumanKillAftermath02_IfNeeded()
  end
end
function Set_ChainHintSpoken()
  chainHintSpoken = true
end
function FirstHumanKillAftermath4_Banter()
  if chainHintSpoken then
    game.Audio.PlayBanter("RIV_FirstHumanKillAftermath04_A")
  else
    game.Audio.PlayBanter("RIV_FirstHumanKillAftermath04_B")
  end
end
function SonBoostFinished()
  local seq = ND.CreateCineSequence(thisLevel, GameObjects.POI_EncouragementMoment, "EncouragementMoment")
  seq:WaitForFunctionTrue(function()
    return son:IsPlayingMove("MOV_SonBoostSad4MeterCrawlStandSad")
  end)
  seq:WaitUntilActorAnimPastPercentage(sonActor, 0.996)
  seq:RequestCineModeAndWait(sonActor, GameObjects.POI_EncouragementMoment)
  seq:ActorSync(sonActor, {
    Branch = "BRA_EncouragementMomentEnter",
    ReferenceJoint = "POI_EncouragementMoment_SyncJoint"
  })
  seq:WaitForAndCompleteCineMode(sonActor, GameObjects.POI_EncouragementMoment)
  seq:WaitSeconds(0.2)
  seq:Do(ShowCamZones)
  seq:Do(function()
    GameObjects.Encouragement_InteractZone01:Show()
  end)
  seq:Do(function()
    GameObjects.Encouragement_InteractZone01.LuaObjectScript.Enable()
  end)
  seq:WaitForFunctionTrue(function()
    return encouragementPrompt01_Pressed
  end)
  seq:Do(StartDesignerCamera)
  seq:RequestCineModeAndWait(sonActor, GameObjects.POI_EncouragementMoment)
  seq:Do(EnableSlowZones)
  seq:Do(function()
    bUseFirstCamera = true
  end)
  seq:Do(function()
    game.Audio.PlayBanter("RIV_EncouragementMoment_01", function()
      encouragementBanter01_Over = true
    end)
  end)
  seq:Do(function()
    son:TriggerMoveEvent("LE_BRA_EncouragmentMoment02")
  end)
  seq:WaitForAndCompleteCineMode(sonActor, GameObjects.POI_EncouragementMoment)
  seq:WaitForFunctionTrue(function()
    return encouragementBanter01_Over
  end)
  seq:WaitSeconds(0.1)
  seq:Do(function()
    GameObjects.Encouragement_InteractZone02:Show()
  end)
  seq:Do(function()
    GameObjects.Encouragement_InteractZone02.LuaObjectScript.Enable()
  end)
  seq:WaitForFunctionTrue(function()
    return encouragementPrompt02_Pressed
  end)
  seq:Do(RecenterToSonsElevation)
  seq:Do(function()
    bUseSecondCamera = true
  end)
  seq:RequestCineModeAndWait(sonActor, GameObjects.POI_EncouragementMoment)
  seq:Do(function()
    game.Audio.PlayBanter("RIV_EncouragementMoment_02", function()
      encouragementBanter02_Over = true
    end)
  end)
  seq:Do(function()
    son:TriggerMoveEvent("LE_BRA_EncouragmentMoment03")
  end)
  seq:WaitForAndCompleteCineMode(sonActor, GameObjects.POI_EncouragementMoment)
  seq:WaitForFunctionTrue(function()
    return encouragementBanter02_Over
  end)
  seq:WaitSeconds(1)
  seq:Do(function()
    GameObjects.Encouragement_InteractZone03:Show()
  end)
  seq:Do(function()
    GameObjects.Encouragement_InteractZone03.LuaObjectScript.Enable()
  end)
  seq:WaitForFunctionTrue(function()
    return encouragementPrompt03_Pressed
  end)
  seq:Do(RecenterToSonsElevation)
  seq:Do(function()
    bUseThirdCamera = true
  end)
  seq:RequestCineModeAndWait(sonActor, GameObjects.POI_EncouragementMoment)
  seq:Do(function()
    game.Audio.PlayBanter("RIV_EncouragementMoment_03")
  end)
  seq:Do(function()
    son:TriggerMoveEvent("LE_BRA_EncouragmentMomentExit")
  end)
  seq:WaitUntilActorAnimPastFrame(sonActor, 580)
  seq:Do(function()
    GameObjects.EncouragementMoment_RopeDrop.LuaObjectScript.Enable()
  end)
  seq:Do(DisableSlowZones)
  seq:Do(HideCamZones)
  seq:WaitForAndCompleteCineMode(sonActor)
  seq:StopPuppetingActor(sonActor)
  seq:Do(_G.SonReachedRope)
  seq:StartSequence()
end
function Set_EncouragementPrompt01_Pressed()
  encouragementPrompt01_Pressed = true
end
function Set_EncouragementPrompt02_Pressed()
  encouragementPrompt02_Pressed = true
end
function Set_EncouragementPrompt03_Pressed()
  encouragementPrompt03_Pressed = true
end
function InitCamera()
  bUseFirstCamera = false
  fStartFrustumCheckValue = 0.5
  fHoldingFrustumCheckValue = 0.2
  fCurrentFrustumCheckValue = fStartFrustumCheckValue
  bEmoCamStarted = false
  bEmoCamCompleted = false
end
function StartDesignerCamera()
  InitCamera()
  game.SubObject.Wake(thisObj)
  bEmoCamStarted = true
  RecenterToSonsElevation()
end
function PlayEmotionalCam()
  if bEmoCamCompleted == true then
    game.SubObject.Sleep(thisObj)
    return
  end
  if collisionCheck.isTargetInFrustum(son:GetWorldPosition(), 0, 0, fCurrentFrustumCheckValue, false) == false then
    fCurrentFrustumCheckValue = fStartFrustumCheckValue
    return
  else
    fCurrentFrustumCheckValue = fHoldingFrustumCheckValue
  end
  if game.World.IsInsideCameraZone(player:GetWorldPosition(), "CamZone_WhereKratosShouldTalk") then
    if bUseFirstCamera == true then
      game.Camera.SubmitCameraByName("PLYR_NAR_Riv250_EmoCamera_Set")
    end
    if bUseSecondCamera == true then
      fCurrentFrustumCheckValue = 0.03
      game.Camera.SubmitCameraByName("PLYR_NAR_Riv250_EmoCamera_Set")
      game.Camera.SubmitCameraByName("PLYR_NAR_Riv250_EmoCamera2_Set")
    end
    if bUseThirdCamera == true then
      if son:GetActiveMovePercent() > 0.83 then
        bEmoCamCompleted = true
      end
      fCurrentFrustumCheckValue = 0.01
      game.Camera.SubmitCameraByName("PLYR_NAR_Riv250_EmoCamera2_Set")
      game.Camera.SubmitCameraByName("PLYR_NAR_Riv250_EmoCamera3_Set")
    end
  end
end
function RecenterToSonsElevation()
  local adjustedAngle = GetElevationEaseValue()
  local orbitValue = game.Camera.GetOrbitElevation()
  if adjustedAngle > orbitValue then
    game.Camera.Recenter({
      TimeStart = 0,
      RotationSpace = 1,
      TimeDuration = 1.6,
      LockRecenter = 0.29,
      PitchRange = -1,
      ReturnUp = adjustedAngle,
      ReturnDown = adjustedAngle,
      YawRange = 360
    })
  end
end
function GetLinearEaseValue(et, b, c, d)
  if d < et then
    return c
  end
  local delta = c - b
  local t = et / d
  local result = delta * t + b
  if 0 < delta then
    if c < result then
      return c
    end
  elseif c > result then
    return c
  end
  return result
end
function GetDistanceToSon()
  if son ~= nil and player ~= nil then
    local distance = son:GetWorldPosition():Distance(player:GetWorldPosition())
    return distance
  end
  return 0
end
function GetElevationEaseValue()
  local distance = GetDistanceToSon()
  local maxrange = 7.58
  local closestDistance = 5.42
  if distance < 5.42 then
    distance = 5.42
  end
  local traveledDistance = distance - closestDistance
  local newvalue = GetLinearEaseValue(traveledDistance, 22, 8.5, maxrange)
  return newvalue
end
function DisableSlowZones()
  GameObjects.SlowZone_EmoSon:Hide()
end
function DelayedSlowZoneDisable()
  timers.StartLevelTimer(3.5, DisableSlowZones)
end
function EnableSlowZones()
  GameObjects.SlowZone_EmoSon:Show()
end
function ShowCamZones()
  GameObjects.CamZone_WhereKratosShouldTalk:ShowCameraVolume()
  GameObjects.CamZone_WhereKidWalks:ShowCameraVolume()
end
function HideCamZones()
  GameObjects.CamZone_WhereKratosShouldTalk:HideCameraVolume()
  GameObjects.CamZone_WhereKidWalks:HideCameraVolume()
end
