Files
FoC-GameManager/Data/Scripts/Miscellaneous/GameManager/SkirmishGameClass.lua

288 lines
7.9 KiB
Lua

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 <T%d> [%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<T%d> [%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<T%d> [%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