local P=require("\105\110\118\111\107\097\116\105\111\110\046\099\111\110\115\116\046\115\101\116\116\105\110\103\115")local E="\065\116\116\101\109\112\116\101\100 \116\111 \115\101\116 \099\117\115\116\111\109 \112\108\097\121\101\114 \099\111\108\111\114 \102\111\114 \112\108\097\121\101\114 \037\100 \097\110\100 \116\101\097\109 \037\100\044 \098\117\116 \116\104\101 \116\101\097\109 \099\111\108\111\114 \105\115 \110\111\116 \099\111\110\102\105\103\117\114\101\100\046"function GameMode._OnGameRulesStateChange(u,C)if GameMode._reentrantCheck then return end local F=GameRules:State_Get()GameMode._reentrantCheck=true u:OnGameRulesStateChange(F,C)GameMode._reentrantCheck=false if F==DOTA_GAMERULES_STATE_HERO_SELECTION then u:PostLoadPrecache()u:OnAllPlayersLoaded()if P.USE_CUSTOM_TEAM_COLORS_FOR_PLAYERS then for C=0,DOTA_DEFAULT_MAX_TEAM_PLAYERS,1 do if PlayerResource:IsValidPlayer(C)then local F=PlayerResource:GetTeam(C)local Z=P.TEAM_COLORS[F]if Z~=nil then PlayerResource:SetCustomPlayerColor(C,Z[1],Z[2],Z[3])else u:warnf(E,C,F)end end end end elseif F==DOTA_GAMERULES_STATE_GAME_IN_PROGRESS then u:OnGameInProgress()end end function GameMode._OnConnectFull(E,P)E:d("\095\079\110\067\111\110\110\101\099\116\070\117\108\108",{payload=P})if GameMode._reentrantCheck then return end local C=PlayerResource:GetPlayer(P.PlayerID)GameMode._reentrantCheck=true E:OnConnectFull(C,P.userid)GameMode._reentrantCheck=false if not E.firstPlayerLoaded then E.firstPlayerLoaded=true E:OnFirstPlayerLoaded()end end function GameMode._OnNPCSpawned(E,P)E:d("\095\079\110\078\080\067\083\112\097\119\110\101\100",{payload=P})if GameMode._reentrantCheck then return end local C=EntIndexToHScript(P.entindex)if C and(C:IsRealHero()and not E.firstSpawned)then E.firstSpawned=true E:OnHeroInGame(C)end end function GameMode._OnEntityKilled(E,P)E:d("\095\079\110\069\110\116\105\116\121\075\105\108\108\101\100",{payload=P})if GameMode._reentrantCheck then return end local C=EntIndexToHScript(P.entindex_killed)local u=nil local F=nil if P.entindex_attacker~=nil then u=EntIndexToHScript(P.entindex_attacker)end if P.entindex_inflictor~=nil then F=EntIndexToHScript(P.entindex_inflictor)end GameMode._reentrantCheck=true E:OnEntityKilled(C,u,F)GameMode._reentrantCheck=false end
--- Internal Game Events Listeners
-- @submodule invokation.GameMode
local S = require("invokation.const.settings")

local WARNF_MISSING_TEAM_COLOR =
  "Attempted to set custom player color for player %d and team %d, but the team color is not configured."

--- Internal Game Events Listeners
-- @section internal_game_events

--- Called when the overall game state has changed.
-- @tparam table payload
function GameMode:_OnGameRulesStateChange(payload)
  if GameMode._reentrantCheck then
    return
  end

  local state = GameRules:State_Get()

  GameMode._reentrantCheck = true
  self:OnGameRulesStateChange(state, payload)
  GameMode._reentrantCheck = false

  if state == DOTA_GAMERULES_STATE_HERO_SELECTION then
    self:PostLoadPrecache()
    self:OnAllPlayersLoaded()

    if S.USE_CUSTOM_TEAM_COLORS_FOR_PLAYERS then
      for i = 0, DOTA_DEFAULT_MAX_TEAM_PLAYERS do
        if PlayerResource:IsValidPlayer(i) then
          local team = PlayerResource:GetTeam(i)
          local color = S.TEAM_COLORS[team]

          if color ~= nil then
            PlayerResource:SetCustomPlayerColor(i, color[1], color[2], color[3])
          else
            self:warnf(WARNF_MISSING_TEAM_COLOR, i, team)
          end
        end
      end
    end
  elseif state == DOTA_GAMERULES_STATE_GAME_IN_PROGRESS then
    self:OnGameInProgress()
  end
end

--- Called once when the player fully connects and becomes "Ready" during loading.
-- @tparam table payload
-- @tparam int payload.PlayerID Player id
-- @tparam int payload.userid User id
function GameMode:_OnConnectFull(payload)
  self:d("_OnConnectFull", { payload = payload })

  if GameMode._reentrantCheck then
    return
  end

  local player = PlayerResource:GetPlayer(payload.PlayerID)

  GameMode._reentrantCheck = true
  self:OnConnectFull(player, payload.userid)
  GameMode._reentrantCheck = false

  if not self.firstPlayerLoaded then
    self.firstPlayerLoaded = true
    self:OnFirstPlayerLoaded()
  end
end

--- Called when an NPC has spawned somewhere in game, including heroes.
-- @tparam table payload
-- @tparam int payload.entindex Unit entity index
function GameMode:_OnNPCSpawned(payload)
  self:d("_OnNPCSpawned", { payload = payload })

  if GameMode._reentrantCheck then
    return
  end

  local npc = EntIndexToHScript(payload.entindex) --[[@as CDOTA_BaseNPC]]

  if npc and npc:IsRealHero() and not self.firstSpawned then
    self.firstSpawned = true
    self:OnHeroInGame(npc)
  end
end

--- Called when an entity was killed.
-- @tparam table payload
-- @tparam int payload.entindex_killed Victim (unit) entity index
-- @tparam[opt] int payload.entindex_attacker Attacker (unit) entity index
-- @tparam[opt] int payload.entindex_inflictor Inflictor (item, ability, etc) entity index
function GameMode:_OnEntityKilled(payload)
  self:d("_OnEntityKilled", { payload = payload })

  if GameMode._reentrantCheck then
    return
  end

  local killed = EntIndexToHScript(payload.entindex_killed)
  local attacker = nil
  local inflictor = nil

  if payload.entindex_attacker ~= nil then
    attacker = EntIndexToHScript(payload.entindex_attacker)
  end

  if payload.entindex_inflictor ~= nil then
    inflictor = EntIndexToHScript(payload.entindex_inflictor)
  end

  GameMode._reentrantCheck = true
  self:OnEntityKilled(killed, attacker, inflictor)
  GameMode._reentrantCheck = false
end
