local k=require("\105\110\118\111\107\097\116\105\111\110\046\100\111\116\097\050\046\107\118\046\065\098\105\108\105\116\121\075\101\121\086\097\108\117\101\115")local V=require("\105\110\118\111\107\097\116\105\111\110\046\100\111\116\097\050\046\107\118\046\072\101\114\111\075\101\121\086\097\108\117\101\115")local E=require("\105\110\118\111\107\097\116\105\111\110\046\100\111\116\097\050\046\116\097\108\101\110\116\115")local D=require("\109\111\115\101\115")local l=require("\105\110\118\111\107\097\116\105\111\110\046\099\111\110\115\116\046\097\098\105\108\105\116\105\101\115")local x=require("\105\110\118\111\107\097\116\105\111\110\046\099\111\110\115\116\046\104\101\114\111\101\115")local h=require("\105\110\118\111\107\097\116\105\111\110\046\099\111\110\115\116\046\117\110\105\116\115")local O="\065\066\073\076\073\084\089\095\084\065\076\069\078\084\095\076\037\100\095\037\115"local A={_serialized=nil}function A.Serialize(k)if k._serialized==nil then local V=D.clone(k)V._serialized=nil V.KEY_VALUES=nil V.HERO_KEY_VALUES=nil V.ABILITIES_KEY_VALUES=nil k._serialized=V end return k._serialized end A.HERO_ID=74 A.UNIT_NAME=h.INVOKER A.SPAWNED_UNITS=h.INVOKER_SPAWNED A.KEY_VALUES=x.KEY_VALUES[A.UNIT_NAME]A.HERO_KEY_VALUES=V(A.UNIT_NAME,A.KEY_VALUES)A.ABILITY_QUAS="\105\110\118\111\107\101\114\095\113\117\097\115"A.ABILITY_WEX="\105\110\118\111\107\101\114\095\119\101\120"A.ABILITY_EXORT="\105\110\118\111\107\101\114\095\101\120\111\114\116"A.ABILITY_EMPTY1="\105\110\118\111\107\101\114\095\101\109\112\116\121\049"A.ABILITY_EMPTY2="\105\110\118\111\107\101\114\095\101\109\112\116\121\050"A.ABILITY_INVOKE="\105\110\118\111\107\101\114\095\105\110\118\111\107\101"A.ABILITY_COLD_SNAP="\105\110\118\111\107\101\114\095\099\111\108\100\095\115\110\097\112"A.ABILITY_GHOST_WALK="\105\110\118\111\107\101\114\095\103\104\111\115\116\095\119\097\108\107"A.ABILITY_ICE_WALL="\105\110\118\111\107\101\114\095\105\099\101\095\119\097\108\108"A.ABILITY_EMP="\105\110\118\111\107\101\114\095\101\109\112"A.ABILITY_TORNADO="\105\110\118\111\107\101\114\095\116\111\114\110\097\100\111"A.ABILITY_ALACRITY="\105\110\118\111\107\101\114\095\097\108\097\099\114\105\116\121"A.ABILITY_SUN_STRIKE="\105\110\118\111\107\101\114\095\115\117\110\095\115\116\114\105\107\101"A.ABILITY_FORGE_SPIRIT="\105\110\118\111\107\101\114\095\102\111\114\103\101\095\115\112\105\114\105\116"A.ABILITY_CHAOS_METEOR="\105\110\118\111\107\101\114\095\099\104\097\111\115\095\109\101\116\101\111\114"A.ABILITY_DEAFENING_BLAST="\105\110\118\111\107\101\114\095\100\101\097\102\101\110\105\110\103\095\098\108\097\115\116"for k,V in pairs(A.HERO_KEY_VALUES:Talents())do local D=O:format(E.LevelAndSide(k))A[D]=V end A.ORB_ABILITIES={A.ABILITY_QUAS;A.ABILITY_WEX;A.ABILITY_EXORT}A.SPELL_ABILITIES={A.ABILITY_COLD_SNAP,A.ABILITY_GHOST_WALK,A.ABILITY_ICE_WALL,A.ABILITY_EMP;A.ABILITY_TORNADO,A.ABILITY_ALACRITY;A.ABILITY_SUN_STRIKE,A.ABILITY_FORGE_SPIRIT;A.ABILITY_CHAOS_METEOR;A.ABILITY_DEAFENING_BLAST}A.TALENT_ABILITIES=D.values(A.HERO_KEY_VALUES:Talents())A.ABILITIES_KEY_VALUES={}for V,E in ipairs(A.ORB_ABILITIES)do A.ABILITIES_KEY_VALUES[E]=k(E,l.KEY_VALUES[E])end for V,E in ipairs(A.SPELL_ABILITIES)do A.ABILITIES_KEY_VALUES[E]=k(E,l.KEY_VALUES[E])end for V,E in ipairs(A.TALENT_ABILITIES)do A.ABILITIES_KEY_VALUES[E]=k(E,l.KEY_VALUES[E])end A.SPELL_COMPOSITION={[A.ABILITY_COLD_SNAP]={A.ABILITY_QUAS;A.ABILITY_QUAS;A.ABILITY_QUAS};[A.ABILITY_GHOST_WALK]={A.ABILITY_QUAS,A.ABILITY_QUAS;A.ABILITY_WEX};[A.ABILITY_ICE_WALL]={A.ABILITY_QUAS;A.ABILITY_QUAS,A.ABILITY_EXORT},[A.ABILITY_EMP]={A.ABILITY_WEX,A.ABILITY_WEX,A.ABILITY_WEX};[A.ABILITY_TORNADO]={A.ABILITY_WEX;A.ABILITY_WEX;A.ABILITY_QUAS};[A.ABILITY_ALACRITY]={A.ABILITY_WEX;A.ABILITY_WEX;A.ABILITY_EXORT};[A.ABILITY_SUN_STRIKE]={A.ABILITY_EXORT,A.ABILITY_EXORT,A.ABILITY_EXORT},[A.ABILITY_FORGE_SPIRIT]={A.ABILITY_EXORT,A.ABILITY_EXORT,A.ABILITY_QUAS};[A.ABILITY_CHAOS_METEOR]={A.ABILITY_EXORT,A.ABILITY_EXORT,A.ABILITY_WEX};[A.ABILITY_DEAFENING_BLAST]={A.ABILITY_QUAS,A.ABILITY_WEX;A.ABILITY_EXORT}}A.INDEX_ABILITY_QUAS=0 A.INDEX_ABILITY_WEX=1 A.INDEX_ABILITY_EXORT=2 A.INDEX_ABILITY_EMPTY1=3 A.INDEX_ABILITY_EMPTY2=4 A.INDEX_ABILITY_INVOKE=5 A.ABILITY_INDICES={[A.ABILITY_QUAS]=A.INDEX_ABILITY_QUAS;[A.ABILITY_WEX]=A.INDEX_ABILITY_WEX;[A.ABILITY_EXORT]=A.INDEX_ABILITY_EXORT,[A.ABILITY_EMPTY1]=A.INDEX_ABILITY_EMPTY1,[A.ABILITY_EMPTY2]=A.INDEX_ABILITY_EMPTY2;[A.ABILITY_INVOKE]=A.INDEX_ABILITY_INVOKE}A.MAX_VISIBLE_ABILITY_INDEX=5 A.FACETS=A.KEY_VALUES.Facets return A
--- Invoker constants.
-- @module invokation.const.invoker
local AbilityKeyValues = require("invokation.dota2.kv.AbilityKeyValues")
local HeroKeyValues = require("invokation.dota2.kv.HeroKeyValues")
local Talents = require("invokation.dota2.talents")
local m = require("moses")

local ABILITIES = require("invokation.const.abilities")
local HEROES = require("invokation.const.heroes")
local UNITS = require("invokation.const.units")

local FMT_ABILITY_TALENT_CONST_NAME = "ABILITY_TALENT_L%d_%s"

---@class invokation.const.Invoker
local M = {
  _serialized = nil,
}

---@return invokation.const.Invoker
function M:Serialize()
  if self._serialized == nil then
    local serialized = m.clone(self)

    serialized._serialized = nil
    serialized.KEY_VALUES = nil
    serialized.HERO_KEY_VALUES = nil
    serialized.ABILITIES_KEY_VALUES = nil

    self._serialized = serialized
  end

  return self._serialized
end

--- Hero id
-- @tfield int HERO_ID
M.HERO_ID = 74

--- Unit name
-- @tfield string UNIT_NAME
M.UNIT_NAME = UNITS.INVOKER

--- Units spawned by Invoker
-- Copy of @{INVOKER_SPAWNED}
M.SPAWNED_UNITS = UNITS.INVOKER_SPAWNED

--- Raw KeyValues table
-- @table KEY_VALUES
M.KEY_VALUES = HEROES.KEY_VALUES[M.UNIT_NAME]

--- `dota2.kv.HeroKeyValues` instance
M.HERO_KEY_VALUES = HeroKeyValues(M.UNIT_NAME, M.KEY_VALUES)

--- Quas ability name
-- @tfield string ABILITY_QUAS
M.ABILITY_QUAS = "invoker_quas"
--- Wex ability name
-- @tfield string ABILITY_WEX
M.ABILITY_WEX = "invoker_wex"
--- Exort ability name
-- @tfield string ABILITY_EXORT
M.ABILITY_EXORT = "invoker_exort"
--- Empty1 ability name
-- @tfield string ABILITY_EMPTY1
M.ABILITY_EMPTY1 = "invoker_empty1"
--- Empty2 ability name
-- @tfield string ABILITY_EMPTY2
M.ABILITY_EMPTY2 = "invoker_empty2"
--- Invoke ability name
-- @tfield string ABILITY_INVOKE
M.ABILITY_INVOKE = "invoker_invoke"
--- Cold Snap ability name
-- @tfield string ABILITY_COLD_SNAP
M.ABILITY_COLD_SNAP = "invoker_cold_snap"
--- Ghost Walk ability name
-- @tfield string ABILITY_GHOST_WALK
M.ABILITY_GHOST_WALK = "invoker_ghost_walk"
--- Ice Wall ability name
-- @tfield string ABILITY_ICE_WALL
M.ABILITY_ICE_WALL = "invoker_ice_wall"
--- EMP ability name
-- @tfield string ABILITY_EMP
M.ABILITY_EMP = "invoker_emp"
--- Tornado ability name
-- @tfield string ABILITY_TORNADO
M.ABILITY_TORNADO = "invoker_tornado"
--- Alacrity ability name
-- @tfield string ABILITY_ALACRITY
M.ABILITY_ALACRITY = "invoker_alacrity"
--- Sun Strike ability name
-- @tfield string ABILITY_SUN_STRIKE
M.ABILITY_SUN_STRIKE = "invoker_sun_strike"
--- Forge Spirit ability name
-- @tfield string ABILITY_FORGE_SPIRIT
M.ABILITY_FORGE_SPIRIT = "invoker_forge_spirit"
--- Chaos Meteor ability name
-- @tfield string ABILITY_CHAOS_METEOR
M.ABILITY_CHAOS_METEOR = "invoker_chaos_meteor"
--- Deafening Blast ability name
-- @tfield string ABILITY_DEAFENING_BLAST
M.ABILITY_DEAFENING_BLAST = "invoker_deafening_blast"

--- Level 10 right talent ability name
-- @tfield string ABILITY_TALENT_L10_RIGHT

--- Level 10 left talent ability name
-- @tfield string ABILITY_TALENT_L10_LEFT

--- Level 15 right talent ability name
-- @tfield string ABILITY_TALENT_L15_RIGHT

--- Level 15 left talent ability name
-- @tfield string ABILITY_TALENT_L15_LEFT

--- Level 20 right talent ability name
-- @tfield string ABILITY_TALENT_L20_RIGHT

--- Level 20 left talent ability name
-- @tfield string ABILITY_TALENT_L20_LEFT

--- Level 25 right talent ability name
-- @tfield string ABILITY_TALENT_L25_RIGHT

--- Level 25 left talent ability name
-- @tfield string ABILITY_TALENT_L25_LEFT

for enumValue, abilityName in pairs(M.HERO_KEY_VALUES:Talents()) do
  local constName = FMT_ABILITY_TALENT_CONST_NAME:format(Talents.LevelAndSide(enumValue))

  M[constName] = abilityName
end

--- Array of orb abilities names.
-- @table ORB_ABILITIES
-- @tfield string 1 Quas
-- @tfield string 2 Wex
-- @tfield string 3 Exort
M.ORB_ABILITIES = { M.ABILITY_QUAS, M.ABILITY_WEX, M.ABILITY_EXORT }

--- Array of orb abilities names.
-- @table SPELL_ABILITIES
-- @tfield string 1 Cold Snap
-- @tfield string 2 Ghost Walk
-- @tfield string 3 Ice Wall
-- @tfield string 4 EMP
-- @tfield string 5 Tornado
-- @tfield string 6 Alacrity
-- @tfield string 7 Sun Strike
-- @tfield string 8 Forge Spirit
-- @tfield string 9 Chaos Meteor
-- @tfield string 10 Deafening Blast
M.SPELL_ABILITIES = {
  M.ABILITY_COLD_SNAP,
  M.ABILITY_GHOST_WALK,
  M.ABILITY_ICE_WALL,
  M.ABILITY_EMP,
  M.ABILITY_TORNADO,
  M.ABILITY_ALACRITY,
  M.ABILITY_SUN_STRIKE,
  M.ABILITY_FORGE_SPIRIT,
  M.ABILITY_CHAOS_METEOR,
  M.ABILITY_DEAFENING_BLAST,
}

--- Array of talent abilities names.
-- @table TALENT_ABILITIES
-- @tfield string 1 Level 10 right
-- @tfield string 2 Level 10 left
-- @tfield string 3 Level 15 right
-- @tfield string 4 Level 15 left
-- @tfield string 5 Level 20 right
-- @tfield string 6 Level 20 left
-- @tfield string 7 Level 25 right
-- @tfield string 8 Level 25 left
M.TALENT_ABILITIES = m.values(M.HERO_KEY_VALUES:Talents())

--- Abilities KeyValues
-- @table ABILITIES_KEY_VALUES
-- @tfield AbilityKeyValues ABILITY_QUAS
-- @tfield AbilityKeyValues ABILITY_WEX
-- @tfield AbilityKeyValues ABILITY_EXORT
-- @tfield AbilityKeyValues ABILITY_COLD_SNAP
-- @tfield AbilityKeyValues ABILITY_GHOST_WALK
-- @tfield AbilityKeyValues ABILITY_ICE_WALL
-- @tfield AbilityKeyValues ABILITY_EMP
-- @tfield AbilityKeyValues ABILITY_TORNADO
-- @tfield AbilityKeyValues ABILITY_ALACRITY
-- @tfield AbilityKeyValues ABILITY_SUN_STRIKE
-- @tfield AbilityKeyValues ABILITY_FORGE_SPIRIT
-- @tfield AbilityKeyValues ABILITY_CHAOS_METEOR
-- @tfield AbilityKeyValues ABILITY_DEAFENING_BLAST
-- @tfield AbilityKeyValues ABILITY_TALENT_1
-- @tfield AbilityKeyValues ABILITY_TALENT_2
-- @tfield AbilityKeyValues ABILITY_TALENT_3
-- @tfield AbilityKeyValues ABILITY_TALENT_4
-- @tfield AbilityKeyValues ABILITY_TALENT_5
-- @tfield AbilityKeyValues ABILITY_TALENT_6
-- @tfield AbilityKeyValues ABILITY_TALENT_7
-- @tfield AbilityKeyValues ABILITY_TALENT_8
M.ABILITIES_KEY_VALUES = {}

for _, abilityName in ipairs(M.ORB_ABILITIES) do
  M.ABILITIES_KEY_VALUES[abilityName] =
    AbilityKeyValues(abilityName, ABILITIES.KEY_VALUES[abilityName])
end

for _, abilityName in ipairs(M.SPELL_ABILITIES) do
  M.ABILITIES_KEY_VALUES[abilityName] =
    AbilityKeyValues(abilityName, ABILITIES.KEY_VALUES[abilityName])
end

for _, abilityName in ipairs(M.TALENT_ABILITIES) do
  M.ABILITIES_KEY_VALUES[abilityName] =
    AbilityKeyValues(abilityName, ABILITIES.KEY_VALUES[abilityName])
end

--- Table of orb abilities composition ("recipes") of spell abilities.
-- @table SPELL_COMPOSITION
-- @tfield {string,...} ABILITY_COLD_SNAP Cold Snap
-- @tfield {string,...} ABILITY_GHOST_WALK Ghost Walk
-- @tfield {string,...} ABILITY_ICE_WALL Ice Wall
-- @tfield {string,...} ABILITY_EMP EMP
-- @tfield {string,...} ABILITY_TORNADO Tornado
-- @tfield {string,...} ABILITY_ALACRITY Alacrity
-- @tfield {string,...} ABILITY_SUN_STRIKE Sun Strike
-- @tfield {string,...} ABILITY_FORGE_SPIRIT Forge Spirit
-- @tfield {string,...} ABILITY_CHAOS_METEOR Chaos Meteor
-- @tfield {string,...} ABILITY_DEAFENING_BLAST Deafening Blast
M.SPELL_COMPOSITION = {
  [M.ABILITY_COLD_SNAP] = { M.ABILITY_QUAS, M.ABILITY_QUAS, M.ABILITY_QUAS },
  [M.ABILITY_GHOST_WALK] = { M.ABILITY_QUAS, M.ABILITY_QUAS, M.ABILITY_WEX },
  [M.ABILITY_ICE_WALL] = { M.ABILITY_QUAS, M.ABILITY_QUAS, M.ABILITY_EXORT },
  [M.ABILITY_EMP] = { M.ABILITY_WEX, M.ABILITY_WEX, M.ABILITY_WEX },
  [M.ABILITY_TORNADO] = { M.ABILITY_WEX, M.ABILITY_WEX, M.ABILITY_QUAS },
  [M.ABILITY_ALACRITY] = { M.ABILITY_WEX, M.ABILITY_WEX, M.ABILITY_EXORT },
  [M.ABILITY_SUN_STRIKE] = { M.ABILITY_EXORT, M.ABILITY_EXORT, M.ABILITY_EXORT },
  [M.ABILITY_FORGE_SPIRIT] = { M.ABILITY_EXORT, M.ABILITY_EXORT, M.ABILITY_QUAS },
  [M.ABILITY_CHAOS_METEOR] = { M.ABILITY_EXORT, M.ABILITY_EXORT, M.ABILITY_WEX },
  [M.ABILITY_DEAFENING_BLAST] = { M.ABILITY_QUAS, M.ABILITY_WEX, M.ABILITY_EXORT },
}

-- empty1 and empty2 can change indices, we're using them only to reference spell slots

--- Quas ability index.
-- @tfield int INDEX_ABILITY_QUAS
M.INDEX_ABILITY_QUAS = 0
--- Wex ability index.
-- @tfield int INDEX_ABILITY_WEX
M.INDEX_ABILITY_WEX = 1
--- Exort ability index.
-- @tfield int INDEX_ABILITY_EXORT
M.INDEX_ABILITY_EXORT = 2
--- Spell slot 1 ability index.
-- @tfield int INDEX_ABILITY_EMPTY1
M.INDEX_ABILITY_EMPTY1 = 3
--- Spell slot 2 ability index.
-- @tfield int INDEX_ABILITY_EMPTY2
M.INDEX_ABILITY_EMPTY2 = 4
--- Invoke ability index.
-- @tfield int INDEX_ABILITY_INVOKE
M.INDEX_ABILITY_INVOKE = 5

--- Table of ability indices by ability name.
-- @table ABILITY_INDICES
-- @tfield int ABILITY_QUAS Quas
-- @tfield int ABILITY_WEX Wex
-- @tfield int ABILITY_EXORT Exort
-- @tfield int ABILITY_EMPTY1 Spell slot 1
-- @tfield int ABILITY_EMPTY2 Spell slot 2
-- @tfield int ABILITY_INVOKE Invoke
M.ABILITY_INDICES = {
  [M.ABILITY_QUAS] = M.INDEX_ABILITY_QUAS,
  [M.ABILITY_WEX] = M.INDEX_ABILITY_WEX,
  [M.ABILITY_EXORT] = M.INDEX_ABILITY_EXORT,
  [M.ABILITY_EMPTY1] = M.INDEX_ABILITY_EMPTY1,
  [M.ABILITY_EMPTY2] = M.INDEX_ABILITY_EMPTY2,
  [M.ABILITY_INVOKE] = M.INDEX_ABILITY_INVOKE,
}

--- Maximum index of the last visible ability.
--
-- Abilities with index higher than this are hidden.
--- @tfield int MAX_VISIBLE_ABILITY_INDEX
M.MAX_VISIBLE_ABILITY_INDEX = 5

M.FACETS = M.KEY_VALUES["Facets"]

return M
