require("GameManager/TacticalGameClass") require("GameManager/SpectatorStruct") require("GameManager/TeamStruct") ---@class SkirmishGameClass : TacticalGameClass ---@field Spectators SpectatorStruct[] The spectator players in this game. ---@field IsLocalSpectator boolean Whether the local player is a spectator. ---@field Teams TeamStruct[] The teams in this game. SkirmishGameClass = {} SkirmishGameClass.__index = SkirmishGameClass setmetatable(SkirmishGameClass, { __index = TacticalGameClass }) ---Creates a new Skirmish Game context. ---@param gameMode string The game mode. ---@return SkirmishGameClass function SkirmishGameClass:New(gameMode) ScriptMessage("Initializing Skirmish game...") local self = setmetatable(TacticalGameClass:New(gameMode), SkirmishGameClass) ---@cast self SkirmishGameClass self:_FindSpectators() self.IsLocalSpectator = self:_GetLocalSpectator() self:_BuildTeams() ScriptMessage("Skirmish Game initialized!") return self end ---Services the Skirmish Game. function SkirmishGameClass:Service() -- Service TacticalGame TacticalGameClass.Service(self) ScriptMessage("Servicing Skirmish Game...") for _, team in pairs(self.Teams) do local credits = self:CalculateTeamTotalCredits(team.Id) local income = self:CalculateTeamTotalIncome(team.Id) GUIManager:DisplayTeamCredits(team, credits, income) end end -- ================================================== -- Unit event handlers -- ================================================== ---Displays unit built combat text. ---@param unit UnitClass The built unit. function SkirmishGameClass:CombatTextUnitBuilt(unit) local owner = self.Players[unit.OwnerId] if not owner then return end local team = self.Teams[owner.TeamId] if not team then return end local timeText = FormatTime(unit.BuildTime) local text = string.format("%s\t [%s]: BUILT %s ($%d)", timeText, team.Number, owner.Name, unit.DisplayName, unit.BuildCost) local faction = Factions[owner.Faction] ---@type ColorStruct local color if faction then color = faction.Color else color = ColorStruct:New(1, 1, 1, 1) end self.CombatFeed:Append(text, -1, color) TextManager:SetCurrentView("combat_feed") end ---Displays killed unit combat text. ---@param unit UnitClass The killed unit. function SkirmishGameClass:CombatTextUnitKilled(unit) local owner = self.Players[unit.OwnerId] if not owner then return end local killer = self.Players[unit.KillerId] local timeText = FormatTime(unit.DeathTime) if not killer then local team = self.Teams[owner.TeamId] if not team then return end local text = string.format("%s\t [%s]: MISTAKES WERE MADE %s", timeText, team.Number, owner.Name, unit.DisplayName) local color = ColorStruct:New(0.8, 0.8, 0.8, 1) self.CombatFeed:Append(text, -1, color) else local team = self.Teams[killer.TeamId] if not team then return end local text = string.format("%s\t [%s]: KILLED %s (%s)", timeText, team.Number, killer.Name, unit .DisplayName, owner.Name) local faction = Factions[killer.Faction] ---@type ColorStruct local color = nil if faction then color = faction.Color else color = ColorStruct:New(1, 1, 1, 1) end self.CombatFeed:Append(text, -1, color) end end -- ================================================== -- Player functions -- ================================================== ---Gets the Spectator by Player ID. ---@param id integer Player ID ---@return SpectatorStruct|nil function SkirmishGameClass:GetSpectator(id) return self.Spectators[id] end ---Gets the Team by ID. ---@param id integer Team ID ---@return TeamStruct|nil function SkirmishGameClass:GetTeam(id) return self.Teams[id] end ---Gets the Players for the Team ID. ---@param id integer Team ID ---@return PlayerClass[] function SkirmishGameClass:GetPlayersOnTeam(id) ---@type PlayerClass[] local players = {} for playerId, player in pairs(self.Players) do if player.TeamId == id then players[playerId] = player end end return players end -- ================================================== -- Team functions -- ================================================== ---Calculates the Team ID's current total credits. ---@param id integer Team ID. ---@return integer function SkirmishGameClass:CalculateTeamTotalCredits(id) local players = self:GetPlayersOnTeam(id) local totalCredits = 0 for playerId, player in pairs(players) do totalCredits = totalCredits + player.Resource.Credits end return totalCredits end ---Calculates the Team ID's current total income. ---@param id integer Team ID. ---@return integer function SkirmishGameClass:CalculateTeamTotalIncome(id) local players = self:GetPlayersOnTeam(id) local totalIncome = 0 for playerId, player in pairs(players) do totalIncome = totalIncome + player.Resource.Income end return totalIncome end -- ================================================== -- Private functions -- ================================================== ---@private ---Finds all spectators in the game. function SkirmishGameClass:_FindSpectators() ---@type SpectatorStruct[] local spectators = {} ---@type string local spectatorMarker = nil if StringCompare(self.GameMode, "Space") then spectatorMarker = Spectator_Marker_Space elseif StringCompare(self.GameMode, "Land") then spectatorMarker = Spectator_Marker_Land end if spectatorMarker then for k, marker in pairs(Find_All_Objects_Of_Type(spectatorMarker)) do local playerWrapper = marker.Get_Owner() local playerId = playerWrapper.Get_ID() if not spectators[playerId] then local spectator = SpectatorStruct:New(playerWrapper) spectators[playerId] = spectator ScriptMessage("Found Spectator: %s", spectator:Debug()) end end end self.Spectators = spectators end ---@private ---Gets whether the local player is a spectator. ---@returns boolean function SkirmishGameClass:_GetLocalSpectator() if not LocalPlayer then return false end return self:GetSpectator(LocalPlayer.Get_ID()) ~= nil end ---@private ---Builds all teams in the game. function SkirmishGameClass:_BuildTeams() ---@type TeamStruct[] local teams = {} -- Build combatant player teams for playerId, player in pairs(self.Players) do local teamId = player.TeamId if teamId >= 0 then if teams[teamId] == nil then teams[teamId] = TeamStruct:New(teamId, player.Faction, false) end end end -- Build spectator player teams for playerId, spectator in pairs(self.Spectators) do local teamId = spectator.TeamId if teamId >= 0 then local team = teams[teamId] if team == nil then team = TeamStruct:New(teamId, spectator.Faction, true) teams[teamId] = team ScriptMessage("Found Team: %s", team:Debug()) else team.IsSpectator = true end end end self.Teams = teams end