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

229 lines
6.5 KiB
Lua

require("PGBase")
require("GameManager/Constants")
require("GameManager/PlayerClass")
require("GameManager/TutorialTextFeed")
---@class TacticalGameClass
---@field GameMode string The tactical game mode.
---@field StartTime integer The start time.
---@field Players PlayerClass[] The combatant players in this game.
---@field CombatFeed TutorialTextFeed Text feed for unit builds and kills.
TacticalGameClass = {}
TacticalGameClass.__index = TacticalGameClass
---Creates a new Tactical Game context.
---@param gameMode string The game mode.
---@return TacticalGameClass
function TacticalGameClass:New(gameMode)
ScriptMessage("Initializing Tactical game...")
local self = setmetatable({}, TacticalGameClass)
self.GameMode = gameMode
self.StartTime = GetCurrentTime()
self.Players = self:_FindPlayers(gameMode)
self.CombatFeed = TutorialTextFeed:New("combat_feed", 6)
ScriptMessage("Tactical Game initialized!")
return self
end
---Services the Tactical Game.
function TacticalGameClass:Service()
ScriptMessage("Servicing Tactical Game...")
-- Service Players
for _, player in pairs(self.Players) do
player:Service()
end
local gameTime = GetCurrentTime() - self.StartTime
GUIManager:DisplayGameTime(gameTime)
end
-- ==================================================
-- State functions
-- ==================================================
---Whether this Tactical game is in space mode.
---@return boolean
function TacticalGameClass:IsSpaceMode()
return StringCompare(self.GameMode, "Space")
end
---Whether this Tactical game is in land mode.
function TacticalGameClass:IsLandMode()
return StringCompare(self.GameMode, "Land")
end
-- ==================================================
-- Player functions
-- ==================================================
---Gets the Player by ID.
---@param id integer Player ID
---@return PlayerClass|nil
function TacticalGameClass:GetPlayer(id)
return self.Players[id]
end
---Records the Player ID as having quit at the current time.
---@param id integer Player ID.
function TacticalGameClass:PlayerQuit(id)
local player = self.Players[id]
if player then
player:Quit()
end
end
-- ==================================================
-- Unit event handlers
-- ==================================================
---Adds a built unit to the Unit table.
---@param objectType GameObjectType The FoC GameObjectTypeWrapper object type that was built.
---@param player PlayerObject The FoC PlayerWrapper object that owns the new Unit.
function TacticalGameClass:UnitBuilt(objectType, player)
local playerId = player.Get_ID()
local playerEntry = self.Players[playerId]
if playerEntry then
local unit = playerEntry:AddUnit(objectType)
self:CombatTextUnitBuilt(unit)
end
end
---Displays unit built combat text.
---@param unit UnitClass The built unit.
function TacticalGameClass:CombatTextUnitBuilt(unit)
local owner = self.Players[unit.OwnerId]
if not owner then
return
end
if not StringCompare(LocalPlayer.Get_Faction_Name(), owner.Faction) then
-- Do not display combat feed for players on opposite factions
return
end
local timeText = FormatTime(unit.BuildTime)
local text = string.format("%s\t[%s]: BUILT %s ($%d)", timeText, owner.Name, unit.Name, 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)
end
---Sets a unit as killed.
---@param gameObject GameObject The FoC GameObjectWrapper object that was killed.
---@param killer PlayerObject The FoC PlayerWrapper object that killed the Unit.
function TacticalGameClass: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:CombatTextUnitKilled(killedUnit)
end
end
---Displays killed unit combat text.
---@param unit UnitClass The killed unit.
function TacticalGameClass:CombatTextUnitKilled(unit)
local owner = self.Players[unit.OwnerId]
if not owner then
return
end
if not StringCompare(LocalPlayer.Get_Faction_Name(), owner.Faction) then
-- Do not display combat feed for players on opposite factions
return
end
local killer = self.Players[unit.KillerId]
local timeText = FormatTime(unit.DeathTime)
if not killer then
local text = string.format("%s\t[%s]: MISTAKES WERE MADE %s", timeText, owner.Name, unit.Name)
local color = ColorStruct:New(0.8, 0.8, 0.8, 1)
self.CombatFeed:Append(text, -1, color)
else
local text = string.format("%s\t[%s]: KILLED %s (%s)", timeText, killer.Name, unit.Name, 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
-- ==================================================
-- Private functions
-- ==================================================
---@private
---@param gameMode string The current game mode.
---@return PlayerClass[]
function TacticalGameClass:_FindPlayers(gameMode)
---@type PlayerClass[]
local players = {}
for k, faction in pairs(Factions) do
local startingUnit = nil
if StringCompare(gameMode, "Land") then
startingUnit = faction.LandStartUnitName
elseif StringCompare(gameMode, "Space") then
startingUnit = faction.SpaceStartUnitName
end
if startingUnit then
for i, unit in pairs(Find_All_Objects_Of_Type(startingUnit)) do
local playerWrapper = unit.Get_Owner()
local playerId = playerWrapper.Get_ID()
if players[playerId] == nil then
local player = PlayerClass:New(playerWrapper)
players[playerId] = player
ScriptMessage("Found Player: %s", player:Debug())
end
end
end
end
return players
end