local LD = require("design.LevelDesignLibrary")
local player, thisObj, thisLevel, parent, flameHazard, breakEvents, latchBreakable, chainJointIndex
local destroyed = false
local includeConcussion, includeScreenShake, includeControllerVibration, flameDuration
local offsetVector = engine.Vector.New(0, -0.2, 0)
local isFalling = false
local bComCollEnabled = false
local tCollisionDefinition
function OnScriptLoaded(level, obj)
  player = game.Player.FindPlayer()
  thisObj = obj
  thisLevel = level
  parent = obj.Parent
  includeConcussion = obj:GetLuaTableAttribute("includeConcussion")
  includeScreenShake = obj:GetLuaTableAttribute("includeScreenShake")
  includeControllerVibration = obj:GetLuaTableAttribute("includeControllerVibration")
  breakEvents = obj:GetLuaTableAttribute("Event_OnBroken")
  flameDuration = obj:FindLuaTableAttribute("flameDuration")
  tCollisionDefinition = obj:FindLuaTableAttribute("tCollisionDefinition")
  if tCollisionDefinition ~= nil and tCollisionDefinition ~= "" then
    bComCollEnabled = true
  end
  if breakEvents then
    breakEvents = LD.ExtractCallbacksForEvent(level, obj, breakEvents)
  end
  latchBreakable = parent:FindSingleGOByName("s_hook_breakable")
  if latchBreakable then
    if latchBreakable.IsRefNode then
      latchBreakable = latchBreakable.Child
    end
    chainJointIndex = parent:FindJointIndex("animGroup_Chain_VisOff")
    latchBreakable.LuaObjectScript.OnBroken(LatchBroken)
  end
  game.SubObject.Sleep(thisObj)
  SoundInit()
end
function OnStart(level, obj)
  if destroyed == false and thisObj:GetBreakable().Broken == false and parent.AnimFrame == 0 then
    LD.CallFunctionAfterDelay(PlaySoundOnIdle, 0.1)
  else
    LD.CallFunctionAfterDelay(StopSoundOnIdle, 0.1)
  end
end
function OnSaveCheckpoint(level, obj)
  return {
    destroyed = destroyed,
    bComCollEnabled = bComCollEnabled,
    tCollisionDefinition = tCollisionDefinition
  }
end
function OnRestoreCheckpoint(level, obj, savedInfo)
  destroyed = savedInfo.destroyed
  bComCollEnabled = savedInfo.bComCollEnabled
  tCollisionDefinition = savedInfo.tCollisionDefinition
end
function OnUpdate(level, obj)
  if isFalling == true then
    local startCheckPos = obj:GetWorldJointPosition(obj:GetJointIndex("Pristine"))
    local hitCheck = game.World.RaycastCollision(startCheckPos, startCheckPos + offsetVector, {SourceGameObject = obj})
    if hitCheck then
      isFalling = false
      HitGround()
    end
  end
end
function HitGround()
  isFalling = false
  BreakBreakable()
  game.SubObject.Sleep(thisObj)
end
function BreakBreakable()
  local brk = thisObj:GetBreakable()
  if brk.Broken == false then
    brk:Break()
  end
end
function OnBreakableBroken(level, obj)
  if destroyed then
    return
  end
  if latchBreakable ~= nil then
    if latchBreakable.Broken then
      StopSoundOnLatchBreak()
    else
      latchBreakable:Break()
      PlaySoundOnBreakHanging()
    end
  else
    PlaySoundOnBreakHanging()
  end
  parent:PlayAnimToEnd()
  destroyed = true
  StopSoundOnIdle()
  local myPos = thisObj:GetWorldJointPosition(thisObj:GetJointIndex("Broken1"))
  if not latchBreakable or latchBreakable.Broken then
    ShowFlameHazard(myPos)
  end
  if chainJointIndex ~= nil then
    parent:HideJoint(chainJointIndex)
  end
  TriggerEffect(myPos)
  if breakEvents ~= nil and breakEvents ~= "" then
    LD.ExecuteCallbacksForEvent(thisLevel, thisObj, breakEvents, "Event_OnBroken")
  end
end
function LuaHook_OnFlameHazardCreated(level, spawner, spawned)
  flameHazard = spawned
  LD.CallFunctionAfterDelay(CleanUpFlameHazard, flameDuration)
  PlaySoundOnHazard()
end
function ShowFlameHazard(pos)
  if 0 < flameDuration then
    thisObj:SpawnGameObject({
      SpawnObject = "goFlame_Hazard_Root",
      HookName = "LuaHook_OnFlameHazardCreated",
      OffsetPosition = pos
    })
  end
end
function CleanUpFlameHazard()
  flameHazard:FindSingleGOByName("CombatCollisionManager").LuaObjectScript.Disable()
  for _, desc in pairs(flameHazard.Descendants) do
    desc:HideLights()
    desc:HideEntityVolume()
    desc:HideParticleEmitter()
  end
  LD.CallFunctionAfterDelay(function()
    if flameHazard then
      flameHazard:Destroy()
    end
  end, 2)
  StopSoundOnHazard()
end
function LatchBroken()
  if destroyed == false then
    game.SubObject.Wake(thisObj)
    isFalling = true
    StartSafetyCheckTimer()
    parent:PlayAnimToEnd()
    thisObj:ShowPhysics()
    if latchBreakable and chainJointIndex ~= nil then
      parent:HideJoint(chainJointIndex)
    end
    if bComCollEnabled then
      game.Combat.AddSubObjectCombatCollision(thisObj, tCollisionDefinition)
    end
    PlaySoundOnLatchBreak()
  end
end
function StartSafetyCheckTimer()
  LD.CallFunctionAfterDelay(HitGround, 3)
end
function TriggerEffect(pos)
  if includeConcussion then
    local concussionParams = {
      Tweak = "CNC_ExplosiveBarrel",
      WorldLocation = pos,
      GameObject = player,
      EnemyId = player:GetID()
    }
    game.Combat.PlayConcussion(concussionParams)
    concussionParams = {
      Tweak = "CNC_ExplosiveBarrel_KratosOnly",
      WorldLocation = pos,
      GameObject = player,
      EnemyId = player:GetID()
    }
    game.Combat.PlayConcussion(concussionParams)
  end
  if includeScreenShake then
    game.Blender.Trigger({
      Name = "FSE_SHAKE_GENERIC_MEDIUM",
      Duration = 1.5,
      TweenIn = {Time = 0},
      TweenOut = {Time = 0.2}
    })
  end
  if includeControllerVibration then
    local rumbleParams = {EffectName = "FFB_MEDIUM", Duration = 0.1}
    game.FX.SubmitEffect(rumbleParams)
  end
end
local soundEmitter, flameHazardEmitter
local soundEvents = {
  OnIdle = "SND_BRK_Fire_Pot_Idle_LP",
  OnBreakHanging = "SND_BRK_Fire_Pot_Explo",
  OnLatchBreak = "SND_BRK_Fire_Pot_Fall_LP",
  OnHazard = "SND_BRK_Fire_Pot_Hazard_LP"
}
function SoundInit()
  soundEmitter = thisObj:FindSingleSoundEmitterByName("SNDBombBag")
end
function SoundSetup(sounds)
  if sounds ~= nil then
    if sounds.SoundEmitter ~= nil then
      soundEmitter = thisObj:FindSingleSoundEmitterByName(sounds.SoundEmitter)
    end
    if sounds.FlameHazardEmitter ~= nil then
      flameHazardEmitter = flameHazard:FindSingleSoundEmitterByName(sounds.FlameHazardEmitter)
    end
    for key in pairs(soundEvents) do
      for newKey, newValue in pairs(sounds) do
        if newKey == key and newValue ~= nil and newValue ~= "" then
          soundEvents[key] = newValue
        end
      end
      LD.SoundDebug(tostring(key) .. ": " .. tostring(soundEvents[key]))
    end
  end
end
function PlaySoundOnIdle()
  LD.PlayRestartableSoundLoop(soundEmitter, soundEvents.OnIdle)
end
function StopSoundOnIdle()
  LD.StopRestartableSoundLoop(soundEmitter, soundEvents.OnIdle)
end
function PlaySoundOnHazard()
  flameHazardEmitter = flameHazard:FindSingleSoundEmitterByName("SNDFlameHazard")
  LD.PlaySound(flameHazardEmitter, soundEvents.OnHazard)
end
function StopSoundOnHazard()
  LD.StopSound(flameHazardEmitter, soundEvents.OnHazard)
end
function PlaySoundOnBreakHanging()
  StopSoundOnIdle()
  LD.PlaySound(soundEmitter, soundEvents.OnBreakHanging)
end
function PlaySoundOnLatchBreak()
  StopSoundOnIdle()
  LD.PlaySound(soundEmitter, soundEvents.OnLatchBreak)
end
function StopSoundOnLatchBreak()
  LD.StopSound(soundEmitter, soundEvents.OnLatchBreak)
end
