local statemachine = require("ai.statemachine")
local tablex = require("core.tablex")
local picklelib = require("core.pickle")
local DL = require("design.DesignerLibrary")
local navbranchlogic = require("creature.navBranchLogic_SmallNonStrafe")
local globalLuaHooks = require("design.GlobalLuaHooks")
globalLuaHooks.InstallHooks()
local traverselink = require("creature.traverselink")
traverselink.InstallHooks()
Brain_Core = require("behavior.corebrain")
constants = {}
global = {}
local powerLevel = "1"
local pLevelInt = 1
local bodyType
function OnAIPostSpawn(ai)
  setupCharacter(ai)
end
function Brain_Core:OnSetPowerlevelOverrideCustom(ai, global, constants, level, isElite, forced)
  powerLevel = level
  ToggleCharacterConfig(ai, forced)
end
function setupCharacter(ai)
  local moveName = ""
  local aggroState = ""
  local spawnContext = ai:GetContext()
  if StartConfig ~= nil then
    if StartConfig.EliteDifficulty ~= nil and StartConfig.EliteDifficulty and not ai:PickupIsAcquired("Wolf00_Elite") then
      ai:PickupAcquire("Wolf00_Elite")
    end
    if StartConfig.AggroState ~= nil then
      DL.switch(StartConfig.AggroState):caseof({
        Unaware = function()
          aggroState = "UNAWARE"
        end,
        Passive = function()
          aggroState = "PASSIVE"
        end,
        NonHostile = function()
          aggroState = "NONHOSTILE"
        end,
        InCombat = function()
          aggroState = "INCOMBAT"
        end
      })
    end
    if StartConfig.Variant ~= nil then
      bodyType = StartConfig.Variant
    end
    if StartConfig.SpawnMove ~= nil then
      moveName = StartConfig.SpawnMove
    end
  end
  ToggleCharacterConfig(ai, not game.CHECK_FEATURE("PREEMPT_SPAWN_CONFIG"))
  if aggroState == "" then
    if DL.CheckCreatureContext(spawnContext, "UNAWARE") then
      aggroState = "UNAWARE"
    elseif DL.CheckCreatureContext(spawnContext, "NONHOSTILE") then
      aggroState = "NONHOSTILE"
    else
      aggroState = "INCOMBAT"
    end
  end
  global.aggroState = aggroState
  if moveName ~= "" then
    ai:ForceMove(moveName)
  end
  DL.NewGamePlusLevelBoost(ai, "Wolf00_PowerLevel")
  DL.NewGamePlusLevelBoost(ai, "Wolf10_PowerLevel")
end
function ToggleCharacterConfig(ai, override)
  if powerLevel == "1" then
    pLevelInt = 1
  elseif powerLevel == "2" then
    pLevelInt = 2
  elseif powerLevel == "3" then
    pLevelInt = 3
  elseif powerLevel == "4" then
    pLevelInt = 4
  elseif powerLevel == "5" then
    pLevelInt = 5
  elseif powerLevel == "6" then
    pLevelInt = 6
  elseif powerLevel == "7" then
    pLevelInt = 7
  elseif powerLevel == "8" then
    pLevelInt = 8
  else
    pLevelInt = powerLevel
  end
  if bodyType ~= nil then
    if bodyType == "Poison" then
      if not ai:PickupIsAcquired("Wolf_Poison") then
        ai:PickupAcquire("Wolf_Poison")
      end
      if override ~= nil and override == true then
        if pLevelInt <= 2 then
          ai:SetCharacterConfig("wolf01_easy")
        elseif 3 <= pLevelInt and pLevelInt <= 4 then
          ai:SetCharacterConfig("wolf01_moderate")
        elseif 5 <= pLevelInt then
          ai:SetCharacterConfig("wolf01_veryhard")
        end
      end
    elseif override ~= nil and override == true then
      if pLevelInt <= 2 then
        ai:SetCharacterConfig("wolf00_easy")
      elseif 3 <= pLevelInt and pLevelInt <= 4 then
        ai:SetCharacterConfig("wolf00_moderate")
      elseif 5 <= pLevelInt then
        ai:SetCharacterConfig("wolf00_veryhard")
      end
    end
  end
end
function LuaHook_AddBlood_Cleave_Impact(ai, data)
  local player = game.Player.FindPlayer()
  player:AddBlood(game.GameObject.eRegionId.kHead, 0.2)
  player:AddBlood(game.GameObject.eRegionId.kLeftChest, 0.4)
  player:AddBlood(game.GameObject.eRegionId.kRightChest, 0.4)
  player:AddBlood(game.GameObject.eRegionId.kFrontAbdomen, 0.4)
  player:AddBlood(game.GameObject.eRegionId.kLeftFrontUpperArm, 0.4)
  player:AddBlood(game.GameObject.eRegionId.kLeftFrontLowerArm, 0.6)
  player:AddBlood(game.GameObject.eRegionId.kRightFrontUpperArm, 0.4)
  player:AddBlood(game.GameObject.eRegionId.kRightFrontLowerArm, 0.6)
  player:AddBlood(game.GameObject.eRegionId.kLeftFrontLeg, 0.2)
  player:AddBlood(game.GameObject.eRegionId.kRightFrontLeg, 0.2)
  player:AddBlood(game.GameObject.eRegionId.kLeftBack, 0.2)
  player:AddBlood(game.GameObject.eRegionId.kRightBack, 0.2)
  player:AddBlood(game.GameObject.eRegionId.kBackAbdomen, 0.2)
  player:AddBlood(game.GameObject.eRegionId.kLeftBackUpperArm, 0.2)
  player:AddBlood(game.GameObject.eRegionId.kLeftBackLowerArm, 0.4)
  player:AddBlood(game.GameObject.eRegionId.kRightBackUpperArm, 0.2)
  player:AddBlood(game.GameObject.eRegionId.kRightBackLowerArm, 0.4)
  player:AddBlood(game.GameObject.eRegionId.kLeftBackLeg, 0.1)
  player:AddBlood(game.GameObject.eRegionId.kRightBackLeg, 0.1)
end
function LuaHook_AddBlood_Wolf_RageEnter(ai, data)
  local player = game.Player.FindPlayer()
  player:AddBlood(game.GameObject.eRegionId.kHead, 0.2)
  player:AddBlood(game.GameObject.eRegionId.kLeftChest, 0.4)
  player:AddBlood(game.GameObject.eRegionId.kFrontAbdomen, 0.4)
  player:AddBlood(game.GameObject.eRegionId.kLeftFrontUpperArm, 0.6)
  player:AddBlood(game.GameObject.eRegionId.kLeftFrontLowerArm, 0.8)
  player:AddBlood(game.GameObject.eRegionId.kLeftBack, 0.2)
  player:AddBlood(game.GameObject.eRegionId.kBackAbdomen, 0.2)
  player:AddBlood(game.GameObject.eRegionId.kLeftBackUpperArm, 0.4)
  player:AddBlood(game.GameObject.eRegionId.kLeftBackLowerArm, 0.6)
end
function LuaHook_AddBlood_Wolf_RageSlams(ai, data)
  local player = game.Player.FindPlayer()
  player:AddBlood(game.GameObject.eRegionId.kHead, 0.2)
  player:AddBlood(game.GameObject.eRegionId.kLeftChest, 0.6)
  player:AddBlood(game.GameObject.eRegionId.kRightChest, 0.6)
  player:AddBlood(game.GameObject.eRegionId.kFrontAbdomen, 0.6)
  player:AddBlood(game.GameObject.eRegionId.kLeftFrontUpperArm, 0.4)
  player:AddBlood(game.GameObject.eRegionId.kLeftFrontLowerArm, 0.4)
  player:AddBlood(game.GameObject.eRegionId.kRightFrontUpperArm, 0.4)
  player:AddBlood(game.GameObject.eRegionId.kRightFrontLowerArm, 0.4)
  player:AddBlood(game.GameObject.eRegionId.kLeftFrontLeg, 0.2)
  player:AddBlood(game.GameObject.eRegionId.kRightFrontLeg, 0.2)
  player:AddBlood(game.GameObject.eRegionId.kLeftBack, 0.2)
  player:AddBlood(game.GameObject.eRegionId.kRightBack, 0.2)
  player:AddBlood(game.GameObject.eRegionId.kBackAbdomen, 0.2)
  player:AddBlood(game.GameObject.eRegionId.kLeftBackUpperArm, 0.2)
  player:AddBlood(game.GameObject.eRegionId.kLeftBackLowerArm, 0.2)
  player:AddBlood(game.GameObject.eRegionId.kRightBackUpperArm, 0.2)
  player:AddBlood(game.GameObject.eRegionId.kRightBackLowerArm, 0.2)
  player:AddBlood(game.GameObject.eRegionId.kLeftBackLeg, 0.2)
  player:AddBlood(game.GameObject.eRegionId.kRightBackLeg, 0.2)
end
function LuaHook_AddBlood_Wolf_BitePoison(ai, data)
  local player = game.Player.FindPlayer()
  player:AddBlood(game.GameObject.eRegionId.kHead, 0.4)
  player:AddBlood(game.GameObject.eRegionId.kLeftChest, 0.8)
  player:AddBlood(game.GameObject.eRegionId.kRightChest, 0.6)
  player:AddBlood(game.GameObject.eRegionId.kFrontAbdomen, 0.6)
  player:AddBlood(game.GameObject.eRegionId.kLeftFrontUpperArm, 0.6)
  player:AddBlood(game.GameObject.eRegionId.kLeftFrontLowerArm, 0.4)
  player:AddBlood(game.GameObject.eRegionId.kLeftBack, 0.2)
  player:AddBlood(game.GameObject.eRegionId.kRightBack, 0.2)
  player:AddBlood(game.GameObject.eRegionId.kBackAbdomen, 0.4)
  player:AddBlood(game.GameObject.eRegionId.kLeftBackUpperArm, 0.4)
  player:AddBlood(game.GameObject.eRegionId.kLeftBackLowerArm, 0.2)
end
function LuaHook_AddBlood_Wolf_BiteEnter(ai, data)
  local player = game.Player.FindPlayer()
  player:AddBlood(game.GameObject.eRegionId.kHead, 0.2)
  player:AddBlood(game.GameObject.eRegionId.kLeftChest, 0.4)
  player:AddBlood(game.GameObject.eRegionId.kFrontAbdomen, 0.4)
  player:AddBlood(game.GameObject.eRegionId.kLeftFrontUpperArm, 0.6)
  player:AddBlood(game.GameObject.eRegionId.kLeftFrontLowerArm, 0.8)
  player:AddBlood(game.GameObject.eRegionId.kLeftBack, 0.2)
  player:AddBlood(game.GameObject.eRegionId.kBackAbdomen, 0.2)
  player:AddBlood(game.GameObject.eRegionId.kLeftBackUpperArm, 0.4)
  player:AddBlood(game.GameObject.eRegionId.kLeftBackLowerArm, 0.6)
end
function LuaHook_AddBlood_Wolf_BiteLoop(ai, data)
  local player = game.Player.FindPlayer()
  player:AddBlood(game.GameObject.eRegionId.kLeftChest, 0.1)
  player:AddBlood(game.GameObject.eRegionId.kRightChest, 0.05)
  player:AddBlood(game.GameObject.eRegionId.kFrontAbdomen, 0.075)
  player:AddBlood(game.GameObject.eRegionId.kLeftFrontUpperArm, 0.1)
  player:AddBlood(game.GameObject.eRegionId.kLeftFrontLowerArm, 0.075)
  player:AddBlood(game.GameObject.eRegionId.kLeftBack, 0.1)
  player:AddBlood(game.GameObject.eRegionId.kRightBack, 0.05)
  player:AddBlood(game.GameObject.eRegionId.kLeftBackUpperArm, 0.1)
  player:AddBlood(game.GameObject.eRegionId.kLeftBackLowerArm, 0.075)
end
function LuaHook_AddBlood_Wolf_BiteEscape(ai, data)
  local player = game.Player.FindPlayer()
  player:AddBlood(game.GameObject.eRegionId.kHead, 0.2)
  player:AddBlood(game.GameObject.eRegionId.kRightChest, 0.4)
  player:AddBlood(game.GameObject.eRegionId.kFrontAbdomen, 0.4)
  player:AddBlood(game.GameObject.eRegionId.kRightFrontUpperArm, 0.8)
  player:AddBlood(game.GameObject.eRegionId.kRightFrontLowerArm, 1)
  player:AddBlood(game.GameObject.eRegionId.kRightFrontLeg, 0.4)
  player:AddBlood(game.GameObject.eRegionId.kRightBack, 0.2)
  player:AddBlood(game.GameObject.eRegionId.kBackAbdomen, 0.2)
  player:AddBlood(game.GameObject.eRegionId.kRightBackUpperArm, 0.6)
  player:AddBlood(game.GameObject.eRegionId.kRightBackLowerArm, 0.8)
  player:AddBlood(game.GameObject.eRegionId.kRightBackLeg, 0.2)
end
function LuaHook_AddBlood_Wolf_BiteDeath(ai, data)
  local player = game.Player.FindPlayer()
  player:AddBlood(game.GameObject.eRegionId.kHead, 1)
  player:AddBlood(game.GameObject.eRegionId.kLeftChest, 1)
  player:AddBlood(game.GameObject.eRegionId.kRightChest, 0.8)
  player:AddBlood(game.GameObject.eRegionId.kFrontAbdomen, 1)
  player:AddBlood(game.GameObject.eRegionId.kLeftFrontUpperArm, 1)
  player:AddBlood(game.GameObject.eRegionId.kLeftFrontLowerArm, 0.8)
  player:AddBlood(game.GameObject.eRegionId.kRightFrontUpperArm, 0.8)
  player:AddBlood(game.GameObject.eRegionId.kRightFrontLowerArm, 0.6)
  player:AddBlood(game.GameObject.eRegionId.kLeftBack, 0.6)
  player:AddBlood(game.GameObject.eRegionId.kRightBack, 0.6)
  player:AddBlood(game.GameObject.eRegionId.kBackAbdomen, 0.6)
  player:AddBlood(game.GameObject.eRegionId.kLeftBackUpperArm, 0.6)
  player:AddBlood(game.GameObject.eRegionId.kLeftBackLowerArm, 0.4)
  player:AddBlood(game.GameObject.eRegionId.kRightBackUpperArm, 0.6)
  player:AddBlood(game.GameObject.eRegionId.kRightBackLowerArm, 0.4)
end
function OnAIUpdate(ai)
  traverselink.OnUpdate(ai)
end
function _G.OnAICreateLuaState(ai)
  _G.OnAICreateLuaState = nil
end
function Brain_Core:OnUpdateCombat(ai, global, constants, dTreeParams)
end
picklelib.Install()
function Pickle(GO)
  return {
    global = global
  }
end
function Unpickle(GO, t)
  global = t.global
end
function LuaHook_Evade_CollisionCheck(ai, data)
  local distanceAmount = 5
  local jointIndex = ai:GetJointIndex("zeroJoint")
  local zeroJointFacingFwd = ai:GetWorldJointForward(jointIndex)
  local zeroJointFacingLeft = ai:GetWorldJointLeft(jointIndex)
  local offset = engine.Vector.New(0, 1.5, 0)
  local offsetZeroJoint = ai.WorldPosition + offset
  local toBack = zeroJointFacingFwd * -distanceAmount
  local offsetBack = offsetZeroJoint + toBack
  offsetBack.y = offsetZeroJoint.y
  local hitBack = game.World.RaycastCollision(offsetZeroJoint, offsetBack, {SourceGameObject = ai, FindAnything = true})
  local toLeft = zeroJointFacingLeft * distanceAmount
  local offsetLeft = offsetZeroJoint + toLeft
  offsetLeft.y = offsetZeroJoint.y
  local hitLeft = game.World.RaycastCollision(offsetZeroJoint, offsetLeft, {SourceGameObject = ai, FindAnything = true})
  local toRight = zeroJointFacingLeft * -distanceAmount
  local offsetRight = offsetZeroJoint + toRight
  offsetRight.y = offsetZeroJoint.y
  local hitRight = game.World.RaycastCollision(offsetZeroJoint, offsetRight, {SourceGameObject = ai, FindAnything = true})
  if ai:DebugIsSelectedCreature() then
    engine.DrawLine(offsetZeroJoint, offsetBack, 8388736)
    engine.DrawLine(offsetZeroJoint, offsetLeft, 8388736)
    engine.DrawLine(offsetZeroJoint, offsetRight, 8388736)
  end
  if not hitBack and not hitRight and not hitLeft then
    return data:FindOutcomeBranchesEntry("EvadeAny")
  elseif not hitBack then
    return data:FindOutcomeBranchesEntry("EvadeBack")
  elseif not hitRight then
    return data:FindOutcomeBranchesEntry("EvadeRight")
  elseif not hitLeft then
    return data:FindOutcomeBranchesEntry("EvadeLeft")
  else
    return data:FindOutcomeBranchesEntry("EvadeFailed")
  end
end
function LuaHook_FindNearbyWolves(ai, data)
  local nearbyCreatures = ai:FindFriendlies(50)
  local nearbyWolves = 0
  for _, creature in ipairs(nearbyCreatures) do
    if creature ~= ai and 0 < creature:GetHitPoints() and creature:GetName() == "wolf00" then
      nearbyWolves = nearbyWolves + 1
    end
  end
  if 0 < nearbyWolves then
    return data:FindOutcomeBranchesEntry("WolvesAvailable")
  else
    return data:FindOutcomeBranchesEntry("WolvesUnavailable")
  end
end
