require("PGBase") require("GameManager/PlayerClass") require("GameManager/UnitClass") ---@class GalacticGameClass ---@field StartTime integer The start time. ---@field Players PlayerClass[] The combatant players in this game. ---@field BuildStatsTable table The engine-owned GalacticBuildStatsTable reference, set from GameScoring.lua. ---@field KillStatsTable table The engine-owned GalacticKillStatsTable reference, set from GameScoring.lua. ---@field NeutralizedStatsTable table The engine-owned GalacticNeutralizedTable reference, set from GameScoring.lua. ---@field GalacticConquestTable table The engine-owned GalacticConquestTable reference, set from GameScoring.lua. GalacticGameClass = {} GalacticGameClass.__index = GalacticGameClass ---Creates a new Galactic Game context. ---@return GalacticGameClass function GalacticGameClass:New() ScriptMessage("Initializing Galactic game...") local self = setmetatable({}, GalacticGameClass) self.StartTime = GetCurrentTime() self.Players = self:_FindPlayers() ScriptMessage("Galactic Game initialized!") return self end ---Services the Galactic Game. function GalacticGameClass:Service() ScriptMessage("Servicing Galactic game...") -- Service Players for _, player in pairs(self.Players) do player:Service() end end -- ================================================== -- Player event handlers -- ================================================== ---Gets the Player by ID. ---@param id integer Player ID ---@return PlayerClass|nil function GalacticGameClass:GetPlayer(id) for playerId, player in pairs(self.Players) do if playerId == id then return player end end end ---Records the Player ID as having quit at the current time. ---@param id integer Player ID. function GalacticGameClass:PlayerQuit(id) for playerId, player in pairs(self.Players) do if playerId == id then player:Quit() end end end -- ================================================== -- Unit event handlers -- ================================================== ---Adds a built unit to the Unit table. ---@param objectType GameObjectType The game object type that was built. ---@param player PlayerObject The player that owns the new game object. ---@param planet PlanetObject The planet the game object type was built at. function GalacticGameClass:UnitBuilt(objectType, player, planet) local playerId = player.Get_ID() local playerEntry = self.Players[playerId] if playerEntry then local unit = playerEntry:AddUnit(objectType) self:UpdateGalacticBuildStatsTable(unit, planet) end end ---Sets a unit as killed. ---@param gameObject GameObject The game object that was killed. ---@param killer PlayerObject The player that killed the game object. function GalacticGameClass:UnitKilled(gameObject, killer) local ownerId = gameObject.Get_Owner().Get_ID() local owner = self.Players[ownerId] if not owner then return end ---@type UnitClass|nil local killedUnit = nil for _, unit in pairs(owner.Units) do if unit.GameObject == gameObject then killedUnit = unit break end end if killedUnit then killedUnit:SetDead(killer.Get_ID()) self:UpdateGalacticKillStatsTable(killedUnit, killer) end end function GalacticGameClass:UnitNeutralized(objectType, killer) self:UpdateGalacticNeutralizedTable(objectType, killer) end -- ================================================== -- Planet event handlers -- ================================================== ---Sets a planet as changed faction. ---@param planet PlanetObject ---@param newOwner PlayerObject ---@param oldOwner PlayerObject function GalacticGameClass:PlanetFactionChange(planet, newOwner, oldOwner) end -- ================================================== -- Stat tables -- ================================================== ---Updates the Galactic Build Stats Table with the build object type. ---@param unit UnitClass The game object type that was built. ---@param planet PlanetObject|nil The planet where the game object was built. function GalacticGameClass:UpdateGalacticBuildStatsTable(unit, planet) ---@type GameObjectType|integer local planetType = 1 if planet then planetType = planet.Get_Type() end local playerEntry = self.BuildStatsTable[unit.OwnerId] if not playerEntry then playerEntry = {} self.BuildStatsTable[unit.OwnerId] = playerEntry end local planetEntry = playerEntry[planetType] if not planetEntry then planetEntry = {} playerEntry[planetType] = planetEntry end local typeEntry = planetEntry[unit.Name] if not typeEntry then typeEntry = { build_count = 1, combat_power = unit.CombatRating, build_cost = unit.BuildCost, score_value = unit.ScoreValue } planetEntry[unit.Name] = typeEntry else typeEntry.build_count = typeEntry.build_count + 1 typeEntry.combat_power = typeEntry.combat_power + unit.CombatRating typeEntry.build_cost = typeEntry.build_cost + unit.BuildCost typeEntry.score_value = typeEntry.score_value + unit.ScoreValue end end ---Updates the Galactic Kill Stats Table with the killed object. ---@param unit UnitClass The unit that was killed. ---@param killer PlayerObject The player that killed the unit. function GalacticGameClass:UpdateGalacticKillStatsTable(unit, killer) if not TestValid(killer) then return end -- Update Frags local fragEntry = self.KillStatsTable[FragIndex] if not fragEntry then fragEntry = {} self.KillStatsTable[FragIndex] = fragEntry end local killerId = killer.Get_ID() local killerEntry = fragEntry[killerId] if not killerEntry then killerEntry = {} fragEntry[killerId] = killerEntry end local killerObjEntry = killerEntry[unit.GameObjectType] if not killerObjEntry then killerObjEntry = { kills = 1, combat_power = unit.CombatRating, build_cost = unit.BuildCost, score_value = unit.ScoreValue } killerEntry[unit.GameObjectType] = killerObjEntry else killerObjEntry.kills = killerObjEntry.kills + 1 killerObjEntry.combat_power = killerObjEntry.combat_power + unit.CombatRating killerObjEntry.build_cost = killerObjEntry.build_cost + unit.BuildCost killerObjEntry.score_value = killerObjEntry.score_value + unit.ScoreValue end -- Update Deaths local deathEntry = self.KillStatsTable[DeathIndex] if not deathEntry then deathEntry = {} self.KillStatsTable[DeathIndex] = deathEntry end local ownerEntry = deathEntry[unit.OwnerId] if not ownerEntry then ownerEntry = {} deathEntry[unit.OwnerId] = ownerEntry end local ownerObjEntry = ownerEntry[unit.GameObjectType] if not ownerObjEntry then ownerObjEntry = { kills = 1, combat_power = unit.CombatRating, build_cost = unit.BuildCost, score_value = unit.ScoreValue } ownerEntry[unit.GameObjectType] = ownerObjEntry else ownerObjEntry.kills = ownerObjEntry.kills + 1 ownerObjEntry.combat_power = ownerObjEntry.combat_power + unit.CombatRating ownerObjEntry.build_cost = ownerObjEntry.build_cost + unit.BuildCost ownerObjEntry.score_value = ownerObjEntry.score_value + unit.ScoreValue end end ---Updates the Galactic Neutralized Table with the neutralized hero. ---@param objectType GameObjectType The hero type that was neutralized. ---@param killer GameObject The hero that killed this hero. function GalacticGameClass:UpdateGalacticNeutralizedTable(objectType, killer) local killerId = killer.Get_Owner().Get_ID() local killerEntry = self.NeutralizedStatsTable[killerId] if not killerEntry then killerEntry = {} self.NeutralizedStatsTable[killerId] = killerEntry end local neutralizedEntry = killerEntry[objectType] if not neutralizedEntry then neutralizedEntry = { neutralized = 1 } killerEntry[objectType] = neutralizedEntry else neutralizedEntry.neutralized = neutralizedEntry.neutralized + 1 end end -- ================================================== -- Private functions -- ================================================== ---@private ---Finds all players of defined Factions via FoCAPI. ---@return PlayerClass[] function GalacticGameClass:_FindPlayers() local isSuccess, result = pcall(Get_All_Players) if isSuccess then local players = {} for _, playerWrapper in pairs(result) do local factionName = playerWrapper.Get_Faction_Name() for _, faction in pairs(Factions) do if faction.Name == factionName then local player = PlayerClass:New(playerWrapper) players[player.Id] = player end end end return players end return self:_FindPlayersFallback() end ---@private ---Finds all players of defined Factions via planets. ---@return PlayerClass[] function GalacticGameClass:_FindPlayersFallback() ---@type PlayerClass[] local players = {} for _, planet in pairs(FindPlanet.Get_All_Planets()) do local owner = planet.Get_Owner() local factionName = owner.Get_Faction_Name() for _, faction in pairs(Factions) do if faction.Name == factionName then local player = PlayerClass:New(owner) players[player.Id] = player end end end return players end