local class = require("core.class")
local state = require("ai.state")
local AggroSystem = class.Class("AggroSystem", state.State)
local DL = require("design.DesignerLibrary")
local gUIVFSDebug
function AggroSystem:init()
  gUIVFSDebug = engine.VFSBool.New("Show UI")
  gUIVFSDebug.value = 0
  self.aggroAttributes = {}
  self.aggroAttributes.dTree = "DTR_BRAWLER00_OFFENSIVE"
  self.aggroAttributes.subClass = "humanoid"
  self.sonAggroSystemEnabled = true
  self.previousRuneStage = 0
  self.forceAttackNow = false
  self.forcedTempAggroTime = 5
  self.forcedTempAggroNow = false
  self.forceAggroDuration = 3
  self.forcedProximityAggroTime = 0
  self.aggroAttributes.forceAggroThreshold = 1
  self.aggroAttributes.forceAggroCurrent = 0
  self.aggroAttributes.aggroCooldownTimer = 0
  self.aggroAttributes.aggroCooldownTimerMax = 10
  self.runicLightStickyBomb = {}
  _G.global.hadSonRune = false
  function _G.OnForceTempAggro(ai, duration)
    self.forcedTempAggroTime = duration
    self.forcedTempAggroNow = true
  end
  function _G.LuaHookDecision_ResetAggro(ai, data)
    _G.global.targetParams = "FIND_TARGET_PARAMETERS_COMBAT_KRATOS_ONLY"
  end
  function _G.LuaHook_ForceResetAggro(ai, data)
    _G.global.targetParams = "FIND_TARGET_PARAMETERS_COMBAT_KRATOS_ONLY"
    if self.forcedTempAggroNow then
      game.Level.SetVariable("CBT_SonAggro", game.Level.GetVariable("CBT_SonAggro") + 1)
    end
    self.forcedTempAggroTime = 0
    self.forcedTempAggroNow = false
    self.forcedProximityAggroTime = 0
  end
  function _G.LuaHook_SoftResetAggro(ai, data)
    if self.forcedTempAggroNow then
      game.Level.SetVariable("CBT_SonAggro", game.Level.GetVariable("CBT_SonAggro") + 1)
    end
    self.forcedTempAggroTime = 0
    self.forcedTempAggroNow = false
    self.forcedProximityAggroTime = 0
  end
  function _G.LuaHook_TempToggleAggro(ai, data)
    if _G.global.targetParams == "FIND_TARGET_PARAMETERS_COMBAT_KRATOS_ONLY" then
      _G.global.targetParams = "FIND_TARGET_PARAMETERS_COMBAT_SON_ONLY"
      self.forcedProximityAggroTime = 1
    elseif _G.global.targetParams == "FIND_TARGET_PARAMETERS_COMBAT_SON_ONLY" then
      _G.global.targetParams = "FIND_TARGET_PARAMETERS_COMBAT_KRATOS_ONLY"
      if self.forcedTempAggroNow then
        game.Level.SetVariable("CBT_SonAggro", game.Level.GetVariable("CBT_SonAggro") + 1)
      end
      self.forcedTempAggroTime = 0
      self.forcedTempAggroNow = false
      self.forcedProximityAggroTime = 0
    end
  end
  function _G.LuaHookDecision_NewIsTargetSon(ai, data)
    local currentTarget = ai:GetTargetCreature()
    if currentTarget == game.AI.FindSon() and _G.global.targetParams == "FIND_TARGET_PARAMETERS_COMBAT_SON_ONLY" then
      return true
    end
    return false
  end
  function _G.LuaHookDecision_NewIsTargetHero(ai, data)
    local currentTarget = ai:GetTargetCreature()
    if currentTarget == game.Player.FindPlayer() and _G.global.targetParams == "FIND_TARGET_PARAMETERS_COMBAT_KRATOS_ONLY" then
      return true
    end
    return false
  end
  function _G.LuaHook_NewJasonTargetSon(ai)
    if not self.forcedTempAggroNow then
      game.Level.SetVariable("CBT_SonAggro", game.Level.GetVariable("CBT_SonAggro") - 1)
    end
    ai:CallScript("OnForceTempAggro", 6)
  end
  function _G.LuaHook_NewProximityTargetSon(ai)
    self.forcedProximityAggroTime = 1
  end
  function _G.LuaHookDecision_NewIsTargetAccurate(ai, data)
    local currentTarget = ai:GetTargetCreature()
    if currentTarget == game.AI.FindSon() and _G.global.targetParams == "FIND_TARGET_PARAMETERS_COMBAT_SON_ONLY" or currentTarget == game.Player.FindPlayer() and _G.global.targetParams == "FIND_TARGET_PARAMETERS_COMBAT_KRATOS_ONLY" then
      return true
    end
    return false
  end
  function _G.LuaHookDecision_NewIsSonKnockedOut(ai)
    local son = game.AI.FindSon()
    if son == nil then
      return false
    end
    return son:HasMarker("Son_KnockedDown") or not son:IsAvailableForCombat() or son.OwnedPOI ~= nil and son.OwnedPOI:FindLuaTableAttribute("AvailableDuringCombat")
  end
  function _G.LuaHookDecision_IsSonAggroFull(ai)
    local son = game.AI.FindSon()
    if game.Level.GetVariable("CBT_SonAggro") < 1 or son ~= nil and son:HasMarker("FirstTrollBehavior") == true then
      return true
    end
    return false
  end
  function _G.LuaHookDecision_IsSonAtFirstTroll(ai)
    local son = game.AI.FindSon()
    if son ~= nil and son:HasMarker("FirstTrollBehavior") == true then
      return true
    end
    return false
  end
  function _G.LuaHookDecision_IsSonInBeginnerMode(ai)
    local son = game.AI.FindSon()
    if son ~= nil and son:HasMarker("FullOnRampage") then
      return true
    end
    return false
  end
  function _G.LuaHookDecision_HeroHasPickup(ai, data)
    local hasDetonate = game.Wallets.GetResourceValue("HERO", "SonPerk_ShockArrow_DetonationConduit") > 0
    if hasDetonate then
      return data:FindOutcomeBranchesEntry("True")
    end
    return data:FindOutcomeBranchesEntry("False")
  end
  function _G.LuaHookDecision_CanOccupySon(ai, data)
    local son = game.AI.FindSon()
    return son:PickupIsAcquired("Son_AllowOccupy") and son:PickupGetStage("Son_AllowOccupy") == 1 and son:IsDoingSyncMove() == false
  end
  function _G.LuaHookDecision_CanIncapacitateSon(ai, data)
    local son = game.AI.FindSon()
    return son:PickupIsAcquired("Son_AllowIncapacitate") and son:PickupGetStage("Son_AllowIncapacitate") == 1 and son:IsDoingSyncMove() == false
  end
  function _G.LuaHookDecision_CanKillSon(ai, data)
    local player = game.Player.FindPlayer()
    if player:IsPlayingMove("MOV_DeathSaveEnter") or player:IsPlayingMove("MOV_DeathSave") then
      return false
    end
    local son = game.AI.FindSon()
    return son:IsDoingSyncMove() == false and ai:PickupIsAcquired("SonKiller") and son:HasMarker("Dead") == false and son:PickupIsAcquired("Son_AllowDeath") and son:PickupGetStage("Son_AllowDeath") == 1
  end
  function _G.LuaHook_CanPerformDismount(ai, data)
    local canPerformDismount = game.Wallets.HasResource("HERO", "SonPerk_LockDownTarget")
    if canPerformDismount then
      return data:FindOutcomeBranchesEntry("CanPerform")
    end
    return data:FindOutcomeBranchesEntry("CannotPerform")
  end
  function _G.LuaHookDecision_SonNotInSurvivalMode(ai, data)
    local son = game.AI.FindSon()
    local sonBB = son:GetBlackboard()
    if sonBB:Exists("IsInSurvival") then
      return not sonBB:GetBoolean("IsInSurvival")
    end
    return true
  end
  function _G.LuaHookDecision_SonEnraged(ai, data)
    local son = game.AI.FindSon()
    if son == nil then
      return false
    end
    if (son:PickupIsAcquired("SonArmorOffense03") or son:PickupIsAcquired("SonArmorBonus01") or son:PickupIsAcquired("SonArmorBonus03") or son:PickupIsAcquired("SonArmorBonus04")) and ai:MeterGetValue("Health") < 40 then
      return true
    end
    local sonBB = son:GetBlackboard()
    if sonBB:Exists("Enraged") then
      return sonBB:GetBoolean("Enraged")
    end
    return false
  end
  function _G.LuaHook_AcquireProperHoldTimer_Stage0(ai, data)
    local son = game.AI.FindSon()
    if ai:PickupIsAcquired("Son_HoldTimer") == false then
      ai:PickupAcquire("Son_HoldTimer")
    end
    if son:PickupIsAcquired("SonArmorOffense03") or son:PickupIsAcquired("SonArmorBonus01") or son:PickupIsAcquired("SonArmorBonus03") or son:PickupIsAcquired("SonArmorBonus04") then
      ai:PickupSetStage("Son_HoldTimer", 2)
    else
      ai:PickupSetStage("Son_HoldTimer", 0)
    end
  end
  function _G.LuaHook_AcquireProperHoldTimer_Stage1(ai, data)
    local son = game.AI.FindSon()
    if ai:PickupIsAcquired("Son_HoldTimer") == false then
      ai:PickupAcquire("Son_HoldTimer")
    end
    if son:PickupIsAcquired("SonArmorOffense03") or son:PickupIsAcquired("SonArmorBonus01") or son:PickupIsAcquired("SonArmorBonus03") or son:PickupIsAcquired("SonArmorBonus04") then
      ai:PickupSetStage("Son_HoldTimer", 3)
    else
      ai:PickupSetStage("Son_HoldTimer", 1)
    end
  end
  function _G.LuaHook_AcquireProperHoldTimer_Stage2(ai, data)
    local son = game.AI.FindSon()
    if ai:PickupIsAcquired("Son_HoldTimer") == false then
      ai:PickupAcquire("Son_HoldTimer")
    end
    if son:PickupIsAcquired("SonArmorOffense03") or son:PickupIsAcquired("SonArmorBonus01") or son:PickupIsAcquired("SonArmorBonus03") or son:PickupIsAcquired("SonArmorBonus04") then
      ai:PickupSetStage("Son_HoldTimer", 4)
    else
      ai:PickupSetStage("Son_HoldTimer", 2)
    end
  end
  function _G.LuaHook_DetonateAllRunes(ai, data)
    if ai:PickupIsAcquired("SonRune") then
      local stage = ai:PickupGetStage("SonRune")
      if stage <= 3 then
        local concussionParams = {}
        concussionParams.WorldLocation = DL.GetWorldJointPositionByName(ai, "JOPelvis1")
        concussionParams.GameObject = ai
        concussionParams.EnemyId = DL.HashCreatureID(game.Player.FindPlayer(), "SON00")
        if stage == 0 then
          stage = 1
        end
        concussionParams.Tweak = "CNC_SON_LIGHTNING_EXPLOSION_LARGER_LV" .. stage
        if concussionParams ~= {} then
          game.Combat.PlayConcussion(concussionParams)
        end
        ai:PickupRelinquish("SonRune")
      end
    end
  end
  function _G.LuaHookDecision_SonHasFerocity_lv1(ai, data)
    local son = game.AI.FindSon()
    if son == nil then
      return false
    end
    if son:PickupIsAcquired("SonArmorOffense01") or son:PickupIsAcquired("SonArmorOffense02") or son:PickupIsAcquired("SonArmorOffense03") or son:PickupIsAcquired("SonArmorBonus01") or son:PickupIsAcquired("SonArmorBonus03") or son:PickupIsAcquired("SonArmorBonus04") then
      return true
    end
    return false
  end
  function _G.LuaHookDecision_SonHasFerocity_lv2(ai, data)
    local son = game.AI.FindSon()
    if son == nil then
      return false
    end
    if son:PickupIsAcquired("SonArmorOffense02") or son:PickupIsAcquired("SonArmorOffense03") or son:PickupIsAcquired("SonArmorBonus01") or son:PickupIsAcquired("SonArmorBonus03") or son:PickupIsAcquired("SonArmorBonus04") then
      return true
    end
    return false
  end
  function _G.LuaHook_DamageWithoutKill(ai, data)
    local damageVal = 15
    local currentHealth = ai:MeterGetValue("Health")
    if damageVal >= currentHealth then
      ai:MeterSetValue("Health", 1)
    else
      ai:MeterSetValue("Health", currentHealth - damageVal)
    end
  end
  function _G.AggroChangeAttribute(ai, sonAttributeChange)
    for k, v in pairs(sonAttributeChange) do
      self.aggroAttributes[k] = v
    end
  end
end
function AggroSystem:OnBrainInit(ai, global, constants)
  global.ai = ai
  local bb = ai:GetBlackboard()
  if bb == nil then
    ai:SetBlackboardSize(32)
  end
  if self.aggroAttributes.myself == nil then
    self.aggroAttributes.myself = ai
  end
  self.stringID = DL.ReturnStringID(ai)
end
function AggroSystem:SetVariables(ai, attributes)
  local bb = ai:GetPrivateBlackboard()
  if bb ~= nil then
    if attributes.classType ~= nil then
      bb:Set("ClassType", DL.ReturnClassValue(attributes.classType))
    end
    if attributes.creatureRadius ~= nil then
      bb:Set("CreatureRadius", attributes.creatureRadius)
    end
    if attributes.creatureCone ~= nil then
      bb:Set("ConeAngle", attributes.creatureCone)
    end
    if attributes.creatureLength ~= nil then
      bb:Set("ConeLength", attributes.creatureLength)
    end
  end
end
function AggroSystem:UpdateData(ai, global, constants)
  if self.updatedBlackboard == nil then
    self.updatedBlackboard = true
    self:SetVariables(ai, self.aggroAttributes)
  end
  if ai:PickupIsActive("TurretMode") then
    self.sonAggroSystemEnabled = false
  end
  local timer = ai:GetFrameTime()
  local bombCount = #self.runicLightStickyBomb
  if 0 < bombCount then
    for i = bombCount, 1, -1 do
      self.runicLightStickyBomb[i] = self.runicLightStickyBomb[i] - timer
      if ai:IsDoingSyncMove() then
        self.runicLightStickyBomb[i] = 0.75
      end
      if self.runicLightStickyBomb[i] <= 0 then
        table.remove(self.runicLightStickyBomb, i)
        self:CreateLightStickyExplosion(ai, global)
      end
    end
  end
  if ai:PickupIsAcquired("SonKnifeAttackSetup") and ai:CheckDecision("tweak_Decision_OnCamera") == false then
    ai:PickupRelinquish("SonKnifeAttackSetup")
  end
  if ai:PickupIsAcquired("SonRune") then
    if self.aggroAttributes.classType == "eFodder" or self.aggroAttributes.classType == "dGrunts" or self.aggroAttributes.classType == "cMajorGrunts" then
      if ai:HasMarker("Attacking") then
        local pickupstage = ai:PickupGetStage("SonRune")
        if 2 <= pickupstage then
          ai:TriggerMoveEvent("kLEShockResume")
        end
      elseif ai:IsInNavigationMove() or ai:HasMarker("CanEvadeSpecialAttack") then
        local pickupstage = ai:PickupGetStage("SonRune")
        if 2 <= pickupstage then
          ai:TriggerMoveEvent("kLEShockResume")
        end
      end
    end
    _G.global.hadSonRune = true
  elseif global.hadSonRune == true then
    global.hadSonRune = false
    game.Combat.RemoveArrows(ai)
  end
  self.forcedProximityAggroTime = self.forcedProximityAggroTime - timer
  self.aggroAttributes.aggroCooldownTimer = self.aggroAttributes.aggroCooldownTimer - timer
  self.forcedTempAggroTime = self.forcedTempAggroTime - timer
  if 0 >= self.forcedTempAggroTime and self.forcedTempAggroNow then
    self.forcedTempAggroNow = false
    game.Level.SetVariable("CBT_SonAggro", game.Level.GetVariable("CBT_SonAggro") + 1)
  end
  if self.stringID ~= "TROLL10" and self.stringID ~= "TROLL20" and self.stringID ~= "JOTUNN00" and self.stringID ~= "JOTUNN10" and self.stringID ~= "JOTUNN20" and ai:PickupIsAcquired("SonForcedAggro") and ai:PickupGetStage("SonForcedAggro") == 0 then
    if self.stringID == "DARKONE00" then
      ai:PickupAcquire("Enraged_At_Son")
    else
      ai:PickupAcquire("Enraged_At_Son")
      ai:PickupSetStage("Enraged_At_Son", 1)
    end
    if ai:IsInNavigationMove() then
      ai:PickupSetStage("SonForcedAggro", 1)
      self.forcedProximityAggroTime = self.forceAggroDuration
      self.aggroAttributes.forceAggroCurrent = 0
      self.aggroAttributes.aggroCooldownTimer = self.aggroAttributes.aggroCooldownTimerMax
    end
  end
  AggroSystem:SurvivalInfluenceCheck(ai, global, constants)
  if not ai:IsInNavigationMove() then
    return
  end
  self:EvaluateAggroTarget(ai, global, constants)
end
function AggroSystem:EvaluateAggroTarget(ai, global, constants)
  if not self.sonAggroSystemEnabled then
    return
  end
  self:ForceSonAggroLogic(ai, global, constants)
  local son = game.AI.FindSon()
  if son ~= nil and not son:HasMarker("RemoveAggro") and (self.forceAttackNow or self.forcedTempAggroNow or self.forcedProximityAggroTime > 0) then
    local player = game.Player.FindPlayer()
    if game.AIUtil.IntersectPointCone(ai.WorldPosition, player.WorldPosition, player:GetWorldForward(), 65, 3) == false then
      global.targetParams = "FIND_TARGET_PARAMETERS_COMBAT_SON_ONLY"
      if constants.theaterInfluenceSettings ~= nil then
        ai:SetInfluenceConeIsEnabled(false)
        ai:SetInfluenceCircleIsEnabled(true)
      end
    elseif ai:HasMarker("Attacking") == false then
      global.targetParams = "FIND_TARGET_PARAMETERS_COMBAT_KRATOS_ONLY"
    end
  else
    if self.forcedTempAggroNow then
      game.Level.SetVariable("CBT_SonAggro", game.Level.GetVariable("CBT_SonAggro") + 1)
    end
    self.forcedTempAggroNow = false
    global.targetParams = "FIND_TARGET_PARAMETERS_COMBAT_KRATOS_ONLY"
    if constants.theaterInfluenceSettings ~= nil then
      ai:SetInfluenceConeIsEnabled(true)
      ai:SetInfluenceCircleIsEnabled(true)
    end
  end
end
function AggroSystem:SurvivalInfluenceCheck(ai, global, constants)
  local son = game.AI.FindSon()
  if son == nil then
    return
  end
  local sonBB = son:GetBlackboard()
  if sonBB ~= nil then
    local validTarget = self.stringID ~= "TROLL00" and self.stringID ~= "TROLL10" and self.stringID ~= "TROLL20" and self.stringID ~= "TROLL30" and self.stringID ~= "GOLEM00" and self.stringID ~= "GOLEM10" and self.stringID ~= "GOLEM20" and self.stringID ~= "GOLEM30" and self.stringID ~= "JOTUNN00" and self.stringID ~= "JOTUNN10" and self.stringID ~= "JOTUNN20"
    local inMode = false
    if sonBB:Exists("IsInSurvival") and sonBB:GetBoolean("IsInSurvival") then
      inMode = true
    end
    if sonBB:Exists("IsInGoToTarget") and sonBB:GetBoolean("IsInGoToTarget") then
      inMode = true
    end
    if inMode and validTarget then
      ai:SetInfluenceConeIsEnabled(false)
      ai:SetInfluenceCircleIsEnabled(false)
    end
  end
end
function AggroSystem:ForceSonAggroLogic(ai, global, constants)
  if ai:PickupIsAcquired("SonKiller") then
    local player = game.Player.FindPlayer()
    if (ai.WorldPosition - player.WorldPosition):Length() < 3 then
      self.forceAttackNow = false
    else
      self.forceAttackNow = true
    end
  end
end
function AggroSystem.Events:OnBlockedReaction(event, ai, global, constants)
  AggroSystem.ProcessBlockAndHitEvents(self, event, ai, global, constants)
end
function AggroSystem.Events:OnHitReaction(event, ai, global, constants)
  AggroSystem.ProcessBlockAndHitEvents(self, event, ai, global, constants)
end
function AggroSystem:ProcessBlockAndHitEvents(event, ai, global, constants)
  if event.enemyId == DL.HashCreatureID(ai, "HERO") then
    if self.forcedTempAggroNow then
      game.Level.SetVariable("CBT_SonAggro", game.Level.GetVariable("CBT_SonAggro") + 1)
    end
    if global.targetParams == "FIND_TARGET_PARAMETERS_COMBAT_SON_ONLY" and (ai:HasMarker("Attacking") == false or ai:HasMarker("For800Troll")) then
      global.targetParams = "FIND_TARGET_PARAMETERS_COMBAT_KRATOS_ONLY"
    end
    self.forcedTempAggroNow = false
    self.forcedTempAggroTime = 0
  end
  if DL.CheckCreatureContext(event.collisionContext, "ARROW_LIGHT") and event.enemyId == DL.HashCreatureID(ai, "SON00") then
    table.insert(self.runicLightStickyBomb, 1)
  end
  if DL.CheckCreatureContext(event.collisionContext, "ARROW_SHOCK") and event.enemyId == DL.HashCreatureID(ai, "SON00") then
    AggroSystem:GenerateLightningArrow(ai)
  end
  if DL.CheckCreatureContext(event.collisionContext, "ARROW_LIGHT") or DL.CheckCreatureContext(event.collisionContext, "ARROW_SHOCK") or DL.CheckCreatureContext(event.collisionContext, "ARROW_NORMAL_COMMAND") then
    local forceaggro = false
    self.aggroAttributes.forceAggroCurrent = self.aggroAttributes.forceAggroCurrent + 1
    if self.aggroAttributes.forceAggroCurrent >= self.aggroAttributes.forceAggroThreshold and 0 >= self.aggroAttributes.aggroCooldownTimer then
      forceaggro = true
    end
    if ai:PickupIsAcquired("SonForcedAggro") == false and forceaggro then
      ai:PickupAcquire("SonForcedAggro")
    end
  end
  if ai:PickupIsAcquired("SonRune") and event.enemyId == DL.HashCreatureID(ai, "SON00") then
    AggroSystem.CreateConcussion_Son(self, ai, event.collisionContext, global)
  end
end
function AggroSystem:CreateLightStickyExplosion(ai, global)
  local owner = game.AI.FindSon()
  if owner == nil then
    owner = game.Player.FindPlayer()
  end
  local concussionParams = {}
  concussionParams.WorldLocation = DL.GetWorldJointPositionByName(ai, "JOPelvis1")
  concussionParams.Creature = owner
  concussionParams.EnemyId = DL.HashCreatureID(owner, "SON00")
  concussionParams.Tweak = "CNC_SON_LIGHT_EXPLOSION_LV2"
  if game.Wallets.HasResource("HERO", "SonPerk_LightArrow_ExplosionSpread") then
    concussionParams.Tweak = "CNC_SON_LIGHT_EXPLOSION_LV6"
  elseif game.Wallets.HasResource("HERO", "SonPerk_LightArrow_ExplosionRadius") then
    concussionParams.Tweak = "CNC_SON_LIGHT_EXPLOSION_LV4"
  end
  game.Combat.PlayConcussion(concussionParams)
end
function AggroSystem:CreateLightArrowConcussion(ai, global)
  local lightstage = ai:HasMeter("Weaken") and ai:MeterGetValue("Weaken") >= 100
  if not lightstage then
    return
  end
  local concussionParams = {}
  concussionParams.WorldLocation = DL.GetWorldJointPositionByName(ai, "JOPelvis1")
  concussionParams.Creature = game.AI.FindSon()
  concussionParams.EnemyId = DL.HashCreatureID(game.Player.FindPlayer(), "SON00")
  concussionParams.Tweak = "CNC_SON_LIGHT_EXPLOSION_LV1"
  if game.Wallets.HasResource("HERO", "SonPerk_LightArrow_ExplosionSpread") then
    if lightstage then
      concussionParams.Tweak = "CNC_SON_LIGHT_EXPLOSION_LV6"
    end
  elseif game.Wallets.HasResource("HERO", "SonPerk_LightArrow_ExplosionRadius") then
    if lightstage then
      concussionParams.Tweak = "CNC_SON_LIGHT_EXPLOSION_LV4"
    end
  elseif lightstage then
    concussionParams.Tweak = "CNC_SON_LIGHT_EXPLOSION_LV2"
  end
  game.Combat.PlayConcussion(concussionParams)
end
function AggroSystem:CreateConcussion_Son(ai, context, global)
  local pickupstage = ai:PickupGetStage("SonRune")
  if pickupstage == 2 and DL.CheckCreatureContext(context, "ARROW_SHOCK") then
    local chain2 = game.FX.Spawn("LightningChainLogic", ai.Level)
    chain2:SetWorldPosition(ai.WorldPosition)
  end
  self.previousRuneStage = pickupstage
end
function AggroSystem:CreateConcussion(ai, context)
  local concussionParams = {}
  concussionParams.WorldLocation = DL.GetWorldJointPositionByName(ai, "JOPelvis1")
  concussionParams.GameObject = ai
  concussionParams.EnemyId = DL.HashCreatureID(game.Player.FindPlayer(), "SON00")
  concussionParams.Tweak = "CNC_SON_LIGHTNING_EXPLOSION_LARGER_LV3"
  game.Combat.PlayConcussion(concussionParams)
  if ai:PickupIsAcquired("SonRune_Activate") then
    ai:PickupRelinquish("SonRune_Activate")
  end
end
function AggroSystem:GenerateLightningArrow(ai)
  local friendlyai = ai:FindFriendlies(15)
  local randomAISelectionIndex = 0
  if 1 < #friendlyai then
    for i = #friendlyai, 1, -1 do
      if friendlyai[i] == ai then
        table.remove(friendlyai, i)
      end
    end
    if 0 < #friendlyai then
      randomAISelectionIndex = math.random(1, #friendlyai)
    end
  else
    return
  end
  local arrowData = {}
  arrowData.Creator = ai
  arrowData.CreatorEmitJoint = "JOPelvis1"
  arrowData.EmitLocation = ai.WorldPosition + engine.Vector.New(0, 0.5, 0)
  arrowData.Target = friendlyai[randomAISelectionIndex]
  arrowData.Tweak = "ARR_SPARK_SPAWN_ONHIT"
  game.Combat.EmitArrow(arrowData)
  local player = game.Player.FindPlayer()
  arrowData.EmitLocation = player.Axe.WorldPosition
end
return {AggroSystem = AggroSystem}
