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) if not self.IsLocalSpectator then -- No Text feed for combatants return end 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 [%s]: BUILT %s ($ %d)", timeText, team.Number, owner.Faction, 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) -- Right now, we don't really care about seeing killed units in the combat feed -- If we want it in the future, uncomment the lines below. return -- if not self.IsLocalSpectator then -- -- No Text feed for combatants -- return -- end -- 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