Initial commit
This commit is contained in:
27
Data/Scripts/Miscellaneous/GameManager/ColorStruct.lua
Normal file
27
Data/Scripts/Miscellaneous/GameManager/ColorStruct.lua
Normal file
@@ -0,0 +1,27 @@
|
||||
require("PGBase")
|
||||
|
||||
---@class ColorStruct
|
||||
---@field R number The red component.
|
||||
---@field G number The green component.
|
||||
---@field B number The blue component.
|
||||
ColorStruct = {}
|
||||
ColorStruct.__index = ColorStruct
|
||||
|
||||
---Creates a new Color object.
|
||||
---@param r number The red component
|
||||
---@param g number The green component
|
||||
---@param b number The blue component
|
||||
---@return ColorStruct
|
||||
function ColorStruct:New(r, g, b)
|
||||
local self = setmetatable({}, ColorStruct)
|
||||
|
||||
self.R = Clamp(r, 0, 1)
|
||||
self.G = Clamp(g, 0, 1)
|
||||
self.B = Clamp(b, 0, 1)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function ColorStruct:Debug()
|
||||
return string.format("RGB (%d, %d, %d)", self.R, self.G, self.B)
|
||||
end
|
||||
105
Data/Scripts/Miscellaneous/GameManager/Constants.lua
Normal file
105
Data/Scripts/Miscellaneous/GameManager/Constants.lua
Normal file
@@ -0,0 +1,105 @@
|
||||
require("FactionStruct")
|
||||
|
||||
-- ==================================================
|
||||
-- Define Faction constants
|
||||
-- ==================================================
|
||||
|
||||
---Defines tactical factions.
|
||||
---@return FactionStruct[]
|
||||
function DefineFactions()
|
||||
---@type FactionStruct[]
|
||||
local factions = {}
|
||||
|
||||
---Rebel Faction
|
||||
---@type FactionStruct
|
||||
local RebelFaction = FactionStruct:New("REBEL")
|
||||
|
||||
RebelFaction.DisplayName = "Rebellion"
|
||||
RebelFaction.Color = ColorStruct:New(1, 0, 0)
|
||||
RebelFaction.Icon = "I_ICON_SPECTATOR_REBEL.TGA"
|
||||
RebelFaction.LandStartUnitName = "Rebel_Infantry_Squad"
|
||||
RebelFaction.SpaceStartUnitName = "Rebel_X-Wing_Squadron"
|
||||
factions[RebelFaction.Name] = RebelFaction
|
||||
|
||||
---Empire Faction
|
||||
---@type FactionStruct
|
||||
local EmpireFaction = FactionStruct:New("EMPIRE")
|
||||
|
||||
EmpireFaction.DisplayName = "Empire"
|
||||
EmpireFaction.Color = ColorStruct:New(0, 1, 1)
|
||||
EmpireFaction.Icon = "I_ICON_SPECTATOR_EMPIRE.TGA"
|
||||
EmpireFaction.LandStartUnitName = "Imperial_Stormtrooper_Squad"
|
||||
EmpireFaction.SpaceStartUnitName = "TIE_Interceptor_Squadron_Container"
|
||||
factions[EmpireFaction.Name] = EmpireFaction
|
||||
|
||||
---Underworld Faction
|
||||
---@type FactionStruct
|
||||
local UnderworldFaction = FactionStruct:New("UNDERWORLD")
|
||||
|
||||
UnderworldFaction.DisplayName = "Zann Consortium"
|
||||
UnderworldFaction.Color = ColorStruct:New(1, 1, 0)
|
||||
UnderworldFaction.Icon = "I_ICON_SPECTATOR_UNDERWORLD.TGA"
|
||||
UnderworldFaction.LandStartUnitName = "Underworld_Merc_Squad"
|
||||
UnderworldFaction.SpaceStartUnitName = "StarViper_Team"
|
||||
factions[UnderworldFaction.Name] = UnderworldFaction
|
||||
|
||||
---Hutts Faction
|
||||
local HuttFaction = FactionStruct:New("HUTTS")
|
||||
|
||||
HuttFaction.DisplayName = "Hutt Cartel"
|
||||
HuttFaction.Color = ColorStruct:New(1, 0, 1)
|
||||
HuttFaction.Icon = "I_ICON_SPECTATOR_HUTTS.TGA"
|
||||
HuttFaction.LandStartUnitName = "Hutt_Soldier_Squad"
|
||||
HuttFaction.SpaceStartUnitName = "V_Wing_Squadron_Container"
|
||||
factions[HuttFaction.Name] = HuttFaction
|
||||
|
||||
---Pirates Faction
|
||||
local PirateFaction = FactionStruct:New("PIRATES")
|
||||
|
||||
PirateFaction.DisplayName = "Pirates"
|
||||
PirateFaction.Color = ColorStruct:New(0, 1, 0)
|
||||
PirateFaction.Icon = "I_ICON_SPECTATOR_PIRATES.TGA"
|
||||
PirateFaction.LandStartUnitName = "Pirate_Soldier_Squad"
|
||||
PirateFaction.SpaceStartUnitName = "Pirate_Fighter_Squadron"
|
||||
factions[PirateFaction.Name] = PirateFaction
|
||||
|
||||
return factions
|
||||
end
|
||||
|
||||
---Constant Global of all Tactical Factions
|
||||
---@type FactionStruct[]
|
||||
Factions = DefineFactions()
|
||||
|
||||
-- ==================================================
|
||||
-- Define UI Constants
|
||||
-- ==================================================
|
||||
|
||||
---GUI Component to display game time.
|
||||
UI_GameTime = "s_select_41"
|
||||
|
||||
---GUI Components to display Team 1 credits.
|
||||
UI_IconT1 = "s_health_42"
|
||||
UI_CreditsT1 = "s_health_41"
|
||||
|
||||
---GUI Component to display Team 2 credits.
|
||||
UI_IconT2 = "s_shield_42"
|
||||
UI_CreditsT2 = "s_shield_41"
|
||||
|
||||
---GUI Component to enable/disable population.
|
||||
UI_PlanetaryPop = "text_planetary_pop"
|
||||
|
||||
---GUI Component to enable/disable tactical credits.
|
||||
UI_CreditsTactical = "text_credits_tactical"
|
||||
|
||||
---Gets the specator marker for the game mode.
|
||||
---@param gameMode string Game mode.
|
||||
---@return string|nil
|
||||
function GetSpectatorMarkerName(gameMode)
|
||||
if StringCompare(gameMode, "Space") then
|
||||
return "Spectator_Reveal_Marker"
|
||||
elseif StringCompare(gameMode, "Land") then
|
||||
return "Spectator_Reveal_Marker_Land"
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
31
Data/Scripts/Miscellaneous/GameManager/FactionStruct.lua
Normal file
31
Data/Scripts/Miscellaneous/GameManager/FactionStruct.lua
Normal file
@@ -0,0 +1,31 @@
|
||||
require("ColorStruct")
|
||||
|
||||
---@class FactionStruct
|
||||
---@field Name string Faction name.
|
||||
---@field DisplayName string Display name.
|
||||
---@field Color ColorStruct Color.
|
||||
---@field Icon string Icon name.
|
||||
---@field LandStartUnitName string Land starting unit name.
|
||||
---@field SpaceStartUnitName string Space starting unit name.
|
||||
FactionStruct = {}
|
||||
FactionStruct.__index = FactionStruct
|
||||
|
||||
---Creates a new Faction struct.
|
||||
---@param name string The internal faction name.
|
||||
---@return FactionStruct
|
||||
function FactionStruct:New(name)
|
||||
local self = setmetatable({}, FactionStruct)
|
||||
|
||||
self.Name = name
|
||||
self.DisplayName = name
|
||||
self.Color = ColorStruct:New(1, 1, 1)
|
||||
self.Icon = ""
|
||||
self.LandStartUnitName = ""
|
||||
self.SpaceStartUnitName = ""
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function FactionStruct:Debug()
|
||||
return string.format("Faction %s (%s)", self.DisplayName, self.Name)
|
||||
end
|
||||
194
Data/Scripts/Miscellaneous/GameManager/GUIManager.lua
Normal file
194
Data/Scripts/Miscellaneous/GameManager/GUIManager.lua
Normal file
@@ -0,0 +1,194 @@
|
||||
require("PGBase")
|
||||
require("GameManager.Constants")
|
||||
|
||||
---@class GUIManager
|
||||
---@field TacticalGame TacticalGameClass|nil The local Tactical Game state.
|
||||
---@field SkirmishGame SkirmishGameClass|nil The local Skirmish Game state.
|
||||
---@field ShowTeamId integer The Team ID units to display.
|
||||
GUIManager = {}
|
||||
GUIManager.__index = GUIManager
|
||||
|
||||
---Creates a new GUI Manager.
|
||||
---@return GUIManager
|
||||
function GUIManager:New()
|
||||
local self = setmetatable({}, GUIManager)
|
||||
|
||||
self.TacticalGame = nil
|
||||
self.SkirmishGame = nil
|
||||
self.ShowTeamId = 0
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
---Initializes the GUI Manager for Skirmish mode.
|
||||
---@param game SkirmishGameClass The Skirmish Game state.
|
||||
function GUIManager:InitSkirmish(game)
|
||||
self.SkirmishGame = game
|
||||
self.TacticalGame = game.TacticalGame
|
||||
|
||||
GUI_Component_Visibility(UI_GameTime, true)
|
||||
|
||||
if self.SkirmishGame.IsLocalSpectator then
|
||||
GUI_Component_Visibility(UI_CreditsT1, true)
|
||||
GUI_Component_Visibility(UI_IconT1, true)
|
||||
|
||||
GUI_Component_Visibility(UI_CreditsT2, true)
|
||||
GUI_Component_Visibility(UI_IconT2, true)
|
||||
|
||||
GUI_Component_Visibility(UI_PlanetaryPop, false)
|
||||
GUI_Component_Visibility(UI_CreditsTactical, false)
|
||||
end
|
||||
end
|
||||
|
||||
---Initializes the GUI Manager for Tactical mode.
|
||||
---@param game TacticalGameClass The Tactical Game state.
|
||||
function GUIManager:InitTactical(game)
|
||||
self.TacticalGame = game
|
||||
|
||||
GUI_Component_Visibility(UI_GameTime, true)
|
||||
end
|
||||
|
||||
---Resets the GUI Manager.
|
||||
function GUIManager:Reset()
|
||||
self.SkirmishGame = nil
|
||||
self.TacticalGame = nil
|
||||
|
||||
GUI_Component_Text(UI_GameTime, "")
|
||||
GUI_Text_Color(UI_GameTime, 1, 1, 1, 1)
|
||||
GUI_Component_Visibility(UI_GameTime, false)
|
||||
|
||||
GUI_Component_Text(UI_CreditsT1, "")
|
||||
GUI_Text_Color(UI_CreditsT1, 1, 1, 1, 1)
|
||||
GUI_Component_Visibility(UI_CreditsT1, false)
|
||||
|
||||
GUI_Button_Icon(UI_IconT1, "", 1, 1, 1, 1)
|
||||
GUI_Component_Visibility(UI_IconT1, false)
|
||||
|
||||
GUI_Component_Text(UI_CreditsT2, "")
|
||||
GUI_Text_Color(UI_CreditsT2, 1, 1, 1, 1)
|
||||
GUI_Component_Visibility(UI_CreditsT2, false)
|
||||
|
||||
GUI_Button_Icon(UI_IconT2, "", 1, 1, 1, 1)
|
||||
GUI_Component_Visibility(UI_IconT2, false)
|
||||
|
||||
GUI_Component_Visibility(UI_PlanetaryPop, true)
|
||||
GUI_Component_Visibility(UI_CreditsTactical, true)
|
||||
end
|
||||
|
||||
---Services the GUI Manager.
|
||||
function GUIManager:Service()
|
||||
if not self.TacticalGame then
|
||||
-- Nothing to service
|
||||
return
|
||||
end
|
||||
|
||||
ScriptMessage("Servicing GUI Updates...")
|
||||
ServiceGameTime(self.TacticalGame)
|
||||
ServiceTeamCredits(self.SkirmishGame)
|
||||
--ServiceUnitDisplay(self.SkirmishGame, self.ShowTeamId)
|
||||
end
|
||||
|
||||
---Services Game Time display.
|
||||
---@param tacticalGame TacticalGameClass The current Tactical Game state
|
||||
function ServiceGameTime(tacticalGame)
|
||||
if not tacticalGame then
|
||||
return
|
||||
end
|
||||
|
||||
local gameTime = Dirty_Floor(GetCurrentTime()) - tacticalGame.StartTime
|
||||
local minutes = Dirty_Floor(gameTime / 60)
|
||||
local minutesText = tostring(minutes)
|
||||
|
||||
if tonumber(minutes) < 10 then
|
||||
minutesText = "0" .. minutesText
|
||||
end
|
||||
|
||||
local seconds = gameTime - (minutes * 60)
|
||||
local secondsText = tostring(seconds)
|
||||
|
||||
if tonumber(seconds) < 10 then
|
||||
secondsText = "0" .. secondsText
|
||||
end
|
||||
|
||||
local text = string.format("Time: %s:%s", minutesText, secondsText)
|
||||
|
||||
GUI_Component_Text(UI_GameTime, text)
|
||||
end
|
||||
|
||||
---Services Team Credits display.
|
||||
---@param skirmishGame SkirmishGameClass The current Skirmish Game state.
|
||||
function ServiceTeamCredits(skirmishGame)
|
||||
if not skirmishGame then
|
||||
return
|
||||
end
|
||||
|
||||
if not skirmishGame.IsLocalSpectator then
|
||||
return
|
||||
end
|
||||
|
||||
---Displays credits for the specified team
|
||||
---@param team TeamStruct The team to service.
|
||||
---@param uiText string The name of the UI Component to display Team credits in.
|
||||
---@param uiIcon string The name of the UI Component to display the Faction icon in.
|
||||
local function DisplayTeamCredits(team, uiText, uiIcon)
|
||||
local teamCredits = skirmishGame:CalculateTeamTotalCredits(team.Id)
|
||||
local teamIncome = skirmishGame:CalculateTeamTotalIncome(team.Id)
|
||||
local positiveText = "+"
|
||||
|
||||
if teamIncome < 0 then
|
||||
positiveText = ""
|
||||
end
|
||||
|
||||
local text = string.format("Team %d: $%d (%s%d)", team.Number, teamCredits, positiveText, teamIncome)
|
||||
local icon = team.Faction.Icon
|
||||
local color = team.Faction.Color
|
||||
|
||||
GUI_Button_Icon(uiIcon, icon, color.R, color.G, color.B, 1)
|
||||
GUI_Component_Text(uiText, text)
|
||||
GUI_Text_Color(uiText, color.R, color.G, color.B, 1)
|
||||
end
|
||||
|
||||
for _, team in pairs(skirmishGame.Teams) do
|
||||
if team.Number == 1 then
|
||||
DisplayTeamCredits(team, UI_CreditsT1, UI_IconT1)
|
||||
elseif team.Number == 2 then
|
||||
DisplayTeamCredits(team, UI_CreditsT2, UI_IconT2)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---Services Team Units display.
|
||||
---@param skirmishGame SkirmishGameClass The current Skirmish Game state.
|
||||
---@param teamId integer The Team ID's units to display.
|
||||
function ServiceUnitDisplay(skirmishGame, teamId)
|
||||
if not skirmishGame then
|
||||
return
|
||||
end
|
||||
|
||||
if not skirmishGame.IsLocalSpectator then
|
||||
return
|
||||
end
|
||||
|
||||
local function DisplayTeamUnit(unit, uiComponent)
|
||||
|
||||
end
|
||||
|
||||
local localPlayer = Find_Player("local")
|
||||
local players = skirmishGame:GetPlayersOnTeam(teamId)
|
||||
---@type table<string, integer> Units Table by name with alive count.
|
||||
local units = {}
|
||||
|
||||
for _, player in pairs(players) do
|
||||
local playerUnits = player:GetAliveUnits()
|
||||
|
||||
for _, playerUnit in pairs(playerUnits) do
|
||||
localPlayer.Select_Object(playerUnit.GameObjectWrapper)
|
||||
|
||||
if not units[playerUnit.Name] then
|
||||
units[playerUnit.Name] = 1
|
||||
else
|
||||
units[playerUnit.Name] = units[playerUnit.Name] + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
73
Data/Scripts/Miscellaneous/GameManager/GalacticGameClass.lua
Normal file
73
Data/Scripts/Miscellaneous/GameManager/GalacticGameClass.lua
Normal file
@@ -0,0 +1,73 @@
|
||||
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 Units UnitClass[] The units in this game.
|
||||
GalacticGameClass = {}
|
||||
GalacticGameClass.__index = GalacticGameClass
|
||||
|
||||
---Creates a new Galactic Game context.
|
||||
---@return GalacticGameClass
|
||||
function GalacticGameClass:New()
|
||||
ScriptMessage("Initializing Galactic game...")
|
||||
local self = setmetatable({}, GalacticGameClass)
|
||||
|
||||
---Finds all combatant players in the game.
|
||||
---@return PlayerClass[]
|
||||
local function FindPlayers()
|
||||
return {}
|
||||
end
|
||||
|
||||
self.StartTime = GetCurrentTime()
|
||||
self.Players = FindPlayers()
|
||||
self.Units = {}
|
||||
ScriptMessage("Galactic Game initialized!")
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
---Services the Galactic Game.
|
||||
function GalacticGameClass:Service()
|
||||
ScriptMessage("Servicing Galactic game...")
|
||||
|
||||
-- Service Players
|
||||
for playerId, player in pairs(self.Players) do
|
||||
player:Service()
|
||||
end
|
||||
end
|
||||
|
||||
---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
|
||||
|
||||
---Adds a built unit to the Unit table.
|
||||
---@param objectType table The FoC GameObjectTypeWrapper object type that was built.
|
||||
---@param player table The FoC PlayerWrapper object that owns the new Unit.
|
||||
function GalacticGameClass:UnitBuilt(objectType, player)
|
||||
local playerId = player.Get_ID()
|
||||
local player = self.Players[playerId]
|
||||
|
||||
if player then
|
||||
player:AddUnit(objectType)
|
||||
end
|
||||
end
|
||||
123
Data/Scripts/Miscellaneous/GameManager/PlayerClass.lua
Normal file
123
Data/Scripts/Miscellaneous/GameManager/PlayerClass.lua
Normal file
@@ -0,0 +1,123 @@
|
||||
require("PGBase")
|
||||
require("GameManager.ResourceClass")
|
||||
require("GameManager.UnitClass")
|
||||
|
||||
---@class PlayerClass
|
||||
---@field Id integer Player ID.
|
||||
---@field TeamId integer Team ID.
|
||||
---@field Name string Player name.
|
||||
---@field Faction string Faction name.
|
||||
---@field IsHuman boolean Whether this player is a human.
|
||||
---@field QuitTime integer The game time this player quit, or -1 if they are still in the game.
|
||||
---@field Resource ResourceClass The player's resources.
|
||||
---@field PlayerWrapper table The FoC PlayerWrapper object.
|
||||
---@field Units UnitClass[] The Units belonging to this player.
|
||||
PlayerClass = {}
|
||||
PlayerClass.__index = PlayerClass
|
||||
|
||||
---Constructs a new Player object.
|
||||
---@param player table FoC PlayerWrapper object
|
||||
---@return PlayerClass
|
||||
function PlayerClass:New(player)
|
||||
local self = setmetatable({}, PlayerClass)
|
||||
|
||||
self.Id = player.Get_ID()
|
||||
self.TeamId = player.Get_Team()
|
||||
self.Name = player.Get_Name()
|
||||
self.Faction = player.Get_Faction_Name()
|
||||
self.IsHuman = player.Is_Human()
|
||||
self.QuitTime = -1
|
||||
self.Resource = ResourceClass:New()
|
||||
self.PlayerWrapper = player
|
||||
self.Units = {}
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
---Updates credits and income.
|
||||
function PlayerClass:Service()
|
||||
if not self:HasQuit() then
|
||||
-- Update player resources
|
||||
self.Resource:SetCredits(self.PlayerWrapper.Get_Credits())
|
||||
|
||||
-- Service Alive Units
|
||||
local assignedUnits = {}
|
||||
|
||||
-- Pass 1: Collect assigned game object wrappers from alive units
|
||||
for _, unit in pairs(self:GetAliveUnits()) do
|
||||
if TestValid(unit.GameObjectWrapper) then
|
||||
assignedUnits[unit.GameObjectWrapper] = true
|
||||
else
|
||||
unit:SetDead()
|
||||
end
|
||||
end
|
||||
|
||||
-- Pass 2: Assign unclaimed wrappers to reinforcement units
|
||||
for k, unit in pairs(self:GetReinforcementUnits()) do
|
||||
local matchingUnits = Find_All_Objects_Of_Type(unit.Name, self.PlayerWrapper)
|
||||
|
||||
for _, object in pairs(matchingUnits) do
|
||||
if not assignedUnits[object] then
|
||||
unit:SetAlive(object)
|
||||
assignedUnits[object] = true
|
||||
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---Sets that the player has quit.
|
||||
function PlayerClass:Quit()
|
||||
self.QuitTime = GetCurrentTime()
|
||||
end
|
||||
|
||||
---Whether this player has quit the game.
|
||||
---@return boolean
|
||||
function PlayerClass:HasQuit()
|
||||
return self.QuitTime >= 0
|
||||
end
|
||||
|
||||
---Adds a Unit type to the Player's reinforcement list.
|
||||
---@param objectType table FoC GameObjectTypeWrapper object that was built.
|
||||
function PlayerClass:AddUnit(objectType)
|
||||
local unit = UnitClass:New(objectType, self.Id)
|
||||
|
||||
table.insert(self.Units, unit)
|
||||
ScriptMessage("Unit Added: %s", unit:Debug())
|
||||
end
|
||||
|
||||
---Gets all Reinforcement Units for this Player.
|
||||
---@return UnitClass[]
|
||||
function PlayerClass:GetReinforcementUnits()
|
||||
---@type UnitClass[]
|
||||
local units = {}
|
||||
|
||||
for k, unit in pairs(self.Units) do
|
||||
if unit:IsReinforcement() then
|
||||
table.insert(units, unit)
|
||||
end
|
||||
end
|
||||
|
||||
return units
|
||||
end
|
||||
|
||||
---Gets all Alive Units for this Player.
|
||||
---@return UnitClass[]
|
||||
function PlayerClass:GetAliveUnits()
|
||||
---@type UnitClass[]
|
||||
local units = {}
|
||||
|
||||
for k, unit in pairs(self.Units) do
|
||||
if unit:IsAlive() then
|
||||
table.insert(units, unit)
|
||||
end
|
||||
end
|
||||
|
||||
return units
|
||||
end
|
||||
|
||||
function PlayerClass:Debug()
|
||||
return string.format("Player %s (%d) on Faction %s, Team %d", self.Name, self.Id, self.Faction, self.TeamId)
|
||||
end
|
||||
36
Data/Scripts/Miscellaneous/GameManager/ResourceClass.lua
Normal file
36
Data/Scripts/Miscellaneous/GameManager/ResourceClass.lua
Normal file
@@ -0,0 +1,36 @@
|
||||
---@class ResourceClass
|
||||
---@field Credits number The current credits.
|
||||
---@field LastCredits number The credits on the last frame.
|
||||
---@field Income integer The current income.
|
||||
ResourceClass = {}
|
||||
ResourceClass.__index = ResourceClass
|
||||
|
||||
---Constructs a new Resource object.
|
||||
function ResourceClass:New()
|
||||
local self = setmetatable({}, ResourceClass)
|
||||
|
||||
self.Credits = 0
|
||||
self.LastCredits = 0
|
||||
self.Income = 0
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
---Sets the current credits and updates income.
|
||||
---@param credits number
|
||||
function ResourceClass:SetCredits(credits)
|
||||
self.LastCredits = self.Credits
|
||||
self.Credits = credits
|
||||
|
||||
if credits < 0 then
|
||||
self.Credits = 0
|
||||
else
|
||||
self.Credits = credits
|
||||
end
|
||||
|
||||
self.Income = self.Credits - self.LastCredits
|
||||
end
|
||||
|
||||
function ResourceClass:Debug()
|
||||
return string.format("Credits: %d, Income: %d", self.Credits, self.Income)
|
||||
end
|
||||
173
Data/Scripts/Miscellaneous/GameManager/SkirmishGameClass.lua
Normal file
173
Data/Scripts/Miscellaneous/GameManager/SkirmishGameClass.lua
Normal file
@@ -0,0 +1,173 @@
|
||||
require("PGBase")
|
||||
require("GameManager.Constants")
|
||||
require("GameManager.TacticalGameClass")
|
||||
require("GameManager.SpectatorStruct")
|
||||
require("GameManager.TeamStruct")
|
||||
|
||||
---@class SkirmishGameClass
|
||||
---@field TacticalGame TacticalGameClass The underlying Tactical Game context.
|
||||
---@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
|
||||
|
||||
---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({}, SkirmishGameClass)
|
||||
|
||||
---Finds all spectators in the game.
|
||||
---@return SpectatorStruct[]
|
||||
local function FindSpectators()
|
||||
---@type SpectatorStruct[]
|
||||
local spectators = {}
|
||||
local spectatorMarker = GetSpectatorMarkerName(gameMode)
|
||||
|
||||
if spectatorMarker ~= nil 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
|
||||
|
||||
return spectators
|
||||
end
|
||||
|
||||
self.TacticalGame = TacticalGameClass:New(gameMode)
|
||||
self.Spectators = FindSpectators()
|
||||
|
||||
---Gets whether the local player is a spectator.
|
||||
---@returns boolean
|
||||
local function GetLocalSpectator()
|
||||
local localPlayer = Find_Player("local")
|
||||
|
||||
return self:GetSpectator(localPlayer.Get_ID()) ~= nil
|
||||
end
|
||||
|
||||
self.IsLocalSpectator = GetLocalSpectator()
|
||||
|
||||
---Builds all teams in the game.
|
||||
---@return TeamStruct[]
|
||||
local function BuildTeams()
|
||||
---@type TeamStruct[]
|
||||
local teams = {}
|
||||
|
||||
-- Build combatant player teams
|
||||
for playerId, player in pairs(self.TacticalGame.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
|
||||
|
||||
return teams
|
||||
end
|
||||
|
||||
self.Teams = BuildTeams()
|
||||
ScriptMessage("Skirmish Game initialized!")
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
---Services the Skirmish Game.
|
||||
function SkirmishGameClass:Service()
|
||||
ScriptMessage("Servicing Skirmish Game...")
|
||||
-- Service TacticalGame
|
||||
self.TacticalGame:Service()
|
||||
end
|
||||
|
||||
---Gets the Spectator by Player ID.
|
||||
---@param id integer Player ID
|
||||
---@return SpectatorStruct|nil
|
||||
function SkirmishGameClass:GetSpectator(id)
|
||||
for playerId, spectator in pairs(self.Spectators) do
|
||||
if playerId == id then
|
||||
return spectator
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---Gets the Team by ID.
|
||||
---@param id integer Team ID
|
||||
---@return TeamStruct|nil
|
||||
function SkirmishGameClass:GetTeam(id)
|
||||
for teamId, team in pairs(self.Teams) do
|
||||
if teamId == id then
|
||||
return team
|
||||
end
|
||||
end
|
||||
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.TacticalGame.Players) do
|
||||
if player.TeamId == id then
|
||||
players[playerId] = player
|
||||
end
|
||||
end
|
||||
|
||||
return players
|
||||
end
|
||||
|
||||
---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
|
||||
26
Data/Scripts/Miscellaneous/GameManager/SpectatorStruct.lua
Normal file
26
Data/Scripts/Miscellaneous/GameManager/SpectatorStruct.lua
Normal file
@@ -0,0 +1,26 @@
|
||||
---@class SpectatorStruct
|
||||
---@field Id integer Player ID.
|
||||
---@field TeamId integer Team ID.
|
||||
---@field Name string Player name.
|
||||
---@field Faction string Faction name.
|
||||
---@field PlayerWrapper table The FoC PlayerWrapper object.
|
||||
SpectatorStruct = {}
|
||||
SpectatorStruct.__index = SpectatorStruct
|
||||
|
||||
---Constructs a new Spectator object.
|
||||
---@param wrapper table FoC PlayerWrapper
|
||||
function SpectatorStruct:New(wrapper)
|
||||
local self = setmetatable({}, SpectatorStruct)
|
||||
|
||||
self.Id = wrapper.Get_ID()
|
||||
self.TeamId = wrapper.Get_Team()
|
||||
self.Name = wrapper.Get_Name()
|
||||
self.Faction = wrapper.Get_Faction_Name()
|
||||
self.PlayerWrapper = wrapper
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function SpectatorStruct:Debug()
|
||||
return string.format("Spectator %s (%d) on Faction %s, Team %d", self.Name, self.Id, self.Faction, self.TeamId)
|
||||
end
|
||||
120
Data/Scripts/Miscellaneous/GameManager/TacticalGameClass.lua
Normal file
120
Data/Scripts/Miscellaneous/GameManager/TacticalGameClass.lua
Normal file
@@ -0,0 +1,120 @@
|
||||
require("PGBase")
|
||||
require("GameManager.PlayerClass")
|
||||
|
||||
---@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 ReinforcementUnitCount table<string, integer> Key: Unit Type, Value: Count
|
||||
---@field AliveUnitCount table<string, integer> Key: Unit Type, Value: Count
|
||||
---@field DeadUnitCount table<string, integer> Key: Unit Type, Value: Count
|
||||
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)
|
||||
|
||||
---Finds all combatant players in the game.
|
||||
---@return PlayerClass[]
|
||||
local function FindPlayers()
|
||||
---@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
|
||||
|
||||
self.GameMode = gameMode
|
||||
self.StartTime = GetCurrentTime()
|
||||
self.Players = FindPlayers()
|
||||
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
|
||||
end
|
||||
|
||||
---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
|
||||
|
||||
---Gets the Player by ID.
|
||||
---@param id integer Player ID
|
||||
---@return PlayerClass|nil
|
||||
function TacticalGameClass: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 TacticalGameClass:PlayerQuit(id)
|
||||
for playerId, player in pairs(self.Players) do
|
||||
if playerId == id then
|
||||
player:Quit()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---Adds a built unit to the Unit table.
|
||||
---@param objectType table The FoC GameObjectTypeWrapper object type that was built.
|
||||
---@param player table The FoC PlayerWrapper object that owns the new Unit.
|
||||
function TacticalGameClass:UnitBuilt(objectType, player)
|
||||
local playerId = player.Get_ID()
|
||||
local player = self.Players[playerId]
|
||||
|
||||
if player then
|
||||
player:AddUnit(objectType)
|
||||
end
|
||||
end
|
||||
|
||||
---Sets a unit as killed.
|
||||
---@param gameObject table The FoC GameObjectWrapper object that was killed.
|
||||
function TacticalGameClass:UnitKilled(gameObject)
|
||||
-- Find a way to set the unit as killed
|
||||
end
|
||||
28
Data/Scripts/Miscellaneous/GameManager/TeamStruct.lua
Executable file
28
Data/Scripts/Miscellaneous/GameManager/TeamStruct.lua
Executable file
@@ -0,0 +1,28 @@
|
||||
require("GameManager.Constants")
|
||||
|
||||
---@class TeamStruct
|
||||
---@field Id integer Team ID.
|
||||
---@field Number integer Team number.
|
||||
---@field Faction FactionStruct Faction struct for this team.
|
||||
---@field IsSpectator boolean Whether this team's players are spectators.
|
||||
TeamStruct = {}
|
||||
TeamStruct.__index = TeamStruct
|
||||
|
||||
---Constructs a new Team object.
|
||||
---@param id integer Team ID
|
||||
---@param faction string Faction name
|
||||
---@param isSpectator boolean Is a Spectator team
|
||||
function TeamStruct:New(id, faction, isSpectator)
|
||||
local self = setmetatable({}, TeamStruct)
|
||||
|
||||
self.Id = id
|
||||
self.Number = id + 1
|
||||
self.Faction = Factions[faction]
|
||||
self.IsSpectator = isSpectator
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function TeamStruct:Debug()
|
||||
return string.format("Team %d: %s (%d)", self.Number, self.Faction.Name, self.Id)
|
||||
end
|
||||
89
Data/Scripts/Miscellaneous/GameManager/UnitClass.lua
Normal file
89
Data/Scripts/Miscellaneous/GameManager/UnitClass.lua
Normal file
@@ -0,0 +1,89 @@
|
||||
require("PGBase")
|
||||
|
||||
---@class UnitClass
|
||||
---@field Name string Unit name.
|
||||
---@field OwnerId integer Owner Player ID.
|
||||
---@field BuildCost integer Tactical build cost.
|
||||
---@field CombatRating integer AI combat power rating.
|
||||
---@field BuildTime number Game time that this unit was built.
|
||||
---@field AliveTime number Game time that this unit became "alive".
|
||||
---@field DeathTime number Game time that this unit was killed.
|
||||
---@field GameObjectWrapper table|nil The FoC GameObjectWrapper object.
|
||||
---@field GameObjectTypeWrapper table The FoC GameObjectTypeWrapper object.
|
||||
---@field Icon string Name of the icon for this object.
|
||||
UnitClass = {}
|
||||
UnitClass.__index = UnitClass
|
||||
|
||||
---Constructs a new Unit object.
|
||||
---@param objectType table FoC GameObjectTypeWrapper object
|
||||
---@param playerId integer The Owner Player ID
|
||||
function UnitClass:New(objectType, playerId)
|
||||
local self = setmetatable({}, UnitClass)
|
||||
|
||||
self.Name = objectType.Get_Name()
|
||||
self.OwnerId = playerId
|
||||
self.BuildCost = objectType.Get_Tactical_Build_Cost()
|
||||
self.CombatRating = objectType.Get_Combat_Rating()
|
||||
self.BuildTime = GetCurrentTime()
|
||||
self.AliveTime = -1
|
||||
self.DeathTime = -1
|
||||
self.GameObjectWrapper = nil
|
||||
self.GameObjectTypeWrapper = objectType
|
||||
self.Icon = "I_BUTTON_COMMAND_BAR_PIRATE_SYMBOL.TGA"
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
---Whether this Unit is a reinforcement.
|
||||
---@return boolean
|
||||
function UnitClass:IsReinforcement()
|
||||
return self.AliveTime < 0 and self.DeathTime < 0
|
||||
end
|
||||
|
||||
---Whether this Unit is currently alive.
|
||||
---@return boolean
|
||||
function UnitClass:IsAlive()
|
||||
return self.AliveTime >= 0 and self.DeathTime < 0
|
||||
end
|
||||
|
||||
---Whether this Unit is dead.
|
||||
---@return boolean
|
||||
function UnitClass:IsDead()
|
||||
return self.DeathTime >= 0
|
||||
end
|
||||
|
||||
---Sets the time this unit became "alive".
|
||||
---@param object table FoC GameObjectWrapper object
|
||||
function UnitClass:SetAlive(object)
|
||||
if self.AliveTime >= 0 then
|
||||
-- Do not override once set
|
||||
return
|
||||
end
|
||||
|
||||
self.AliveTime = GetCurrentTime()
|
||||
self.GameObjectWrapper = object
|
||||
ScriptMessage("Unit Spawned: %s", self:Debug())
|
||||
end
|
||||
|
||||
---Sets the unit as dead.
|
||||
function UnitClass:SetDead()
|
||||
if self.DeathTime >= 0 then
|
||||
-- Do not override once set
|
||||
return
|
||||
end
|
||||
|
||||
self.DeathTime = GetCurrentTime()
|
||||
ScriptMessage("Unit Killed: %s", self:Debug())
|
||||
end
|
||||
|
||||
function UnitClass:Debug()
|
||||
if self:IsReinforcement() then
|
||||
return string.format("Reinforcement Unit %s, Owned by %d, Built at: %d", self.Name, self.OwnerId, self.BuildTime)
|
||||
elseif self:IsAlive() then
|
||||
return string.format("Alive Unit %s, Owned by %d, Alive at: %d", self.Name, self.OwnerId, self.AliveTime)
|
||||
elseif self:IsDead() then
|
||||
return string.format("Dead Unit %s, Owned by %d, Death at: %d", self.Name, self.OwnerId, self.DeathTime)
|
||||
else
|
||||
return string.format("Unit %s, Owned by %d, Unknown state", self.Name, self.OwnerId)
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user