mirror of
https://gitea.wildfiregames.com/0ad/0ad
synced 2026-06-17 13:53:57 -07:00
Remove the world population setting from the game setup. Add a dropdown for choosing the "Population Cap Type". (-> containing Player Population, World Population, Team Population) Use a single "Population Cap" dropdown adapting to the pop cap types. Move all population data into a single .json file. New system component "PopulationCapManager" for distributing pop caps. Resolves: #6918
155 lines
4.1 KiB
JavaScript
155 lines
4.1 KiB
JavaScript
function PlayerManager() {}
|
|
|
|
PlayerManager.prototype.Schema =
|
|
"<a:component type='system'/><empty/>";
|
|
|
|
PlayerManager.prototype.Init = function()
|
|
{
|
|
// List of player entity IDs.
|
|
this.playerEntities = [];
|
|
};
|
|
|
|
/**
|
|
* @param {string} templateName - The template name of the player to add.
|
|
* @return {number} - The player's ID (player number).
|
|
*/
|
|
PlayerManager.prototype.AddPlayer = function(templateName)
|
|
{
|
|
const ent = Engine.AddEntity(templateName);
|
|
const id = this.playerEntities.length;
|
|
Engine.QueryInterface(ent, IID_Player).SetPlayerID(id);
|
|
this.playerEntities.push(ent);
|
|
|
|
const newDiplo = [];
|
|
for (let i = 0; i < id; i++)
|
|
{
|
|
Engine.QueryInterface(this.GetPlayerByID(i), IID_Diplomacy).diplomacy[id] = -1;
|
|
newDiplo[i] = -1;
|
|
}
|
|
newDiplo[id] = 1;
|
|
Engine.QueryInterface(ent, IID_Diplomacy).SetDiplomacy(newDiplo);
|
|
|
|
Engine.BroadcastMessage(MT_PlayerEntityChanged, {
|
|
"player": id,
|
|
"from": INVALID_ENTITY,
|
|
"to": ent
|
|
});
|
|
|
|
return id;
|
|
};
|
|
|
|
/**
|
|
* To avoid possible problems,
|
|
* we first remove all entities from this player, and add them back after the replacement.
|
|
* Note: This should only be called during setup/init and not during the game
|
|
* @param {number} id - The player number to replace.
|
|
* @param {string} newTemplateName - The new template name for the player.
|
|
*/
|
|
PlayerManager.prototype.ReplacePlayerTemplate = function(id, newTemplateName)
|
|
{
|
|
const ent = Engine.AddEntity(newTemplateName);
|
|
const entities = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager).GetEntitiesByPlayer(id);
|
|
for (const e of entities)
|
|
Engine.QueryInterface(e, IID_Ownership)?.SetOwner(INVALID_PLAYER);
|
|
|
|
const oldent = this.playerEntities[id];
|
|
const oldCmpPlayer = Engine.QueryInterface(oldent, IID_Player);
|
|
const newCmpPlayer = Engine.QueryInterface(ent, IID_Player);
|
|
|
|
newCmpPlayer.SetPlayerID(id);
|
|
this.playerEntities[id] = ent;
|
|
|
|
newCmpPlayer.SetColor(oldCmpPlayer.GetColor());
|
|
Engine.QueryInterface(ent, IID_Diplomacy).SetDiplomacy(Engine.QueryInterface(oldent, IID_Diplomacy).GetDiplomacy());
|
|
|
|
Engine.BroadcastMessage(MT_PlayerEntityChanged, {
|
|
"player": id,
|
|
"from": oldent,
|
|
"to": ent
|
|
});
|
|
|
|
for (const e of entities)
|
|
Engine.QueryInterface(e, IID_Ownership)?.SetOwner(id);
|
|
|
|
Engine.DestroyEntity(oldent);
|
|
Engine.FlushDestroyedEntities();
|
|
};
|
|
|
|
/**
|
|
* Returns the player entity ID for the given player ID.
|
|
* The player ID must be valid (else there will be an error message).
|
|
*/
|
|
PlayerManager.prototype.GetPlayerByID = function(id)
|
|
{
|
|
if (id in this.playerEntities)
|
|
return this.playerEntities[id];
|
|
|
|
// Observers don't have player data.
|
|
if (id == INVALID_PLAYER)
|
|
return INVALID_ENTITY;
|
|
|
|
const stack = new Error().stack.trimRight().replace(/^/mg, ' '); // indent each line
|
|
warn("GetPlayerByID: no player defined for id '"+id+"'\n"+stack);
|
|
|
|
return INVALID_ENTITY;
|
|
};
|
|
|
|
/**
|
|
* Returns the number of players including gaia.
|
|
*/
|
|
PlayerManager.prototype.GetNumPlayers = function()
|
|
{
|
|
return this.playerEntities.length;
|
|
};
|
|
|
|
/**
|
|
* Returns IDs of all players including gaia.
|
|
*/
|
|
PlayerManager.prototype.GetAllPlayers = function()
|
|
{
|
|
const players = [];
|
|
for (let i = 0; i < this.playerEntities.length; ++i)
|
|
players.push(i);
|
|
return players;
|
|
};
|
|
|
|
/**
|
|
* Returns IDs of all players excluding gaia.
|
|
*/
|
|
PlayerManager.prototype.GetNonGaiaPlayers = function()
|
|
{
|
|
const players = [];
|
|
for (let i = 1; i < this.playerEntities.length; ++i)
|
|
players.push(i);
|
|
return players;
|
|
};
|
|
|
|
/**
|
|
* Returns IDs of all players excluding gaia that are not defeated nor have won.
|
|
*/
|
|
PlayerManager.prototype.GetActivePlayers = function()
|
|
{
|
|
return this.GetNonGaiaPlayers().filter(playerID =>
|
|
Engine.QueryInterface(this.GetPlayerByID(playerID), IID_Player).IsActive()
|
|
);
|
|
};
|
|
|
|
/**
|
|
* Note: This should only be called during setup/init and not during a match
|
|
* since it doesn't change the owned entities.
|
|
*/
|
|
PlayerManager.prototype.RemoveLastPlayer = function()
|
|
{
|
|
if (!this.playerEntities.length)
|
|
return;
|
|
|
|
const lastId = this.playerEntities.pop();
|
|
Engine.BroadcastMessage(MT_PlayerEntityChanged, {
|
|
"player": this.playerEntities.length + 1,
|
|
"from": lastId,
|
|
"to": INVALID_ENTITY
|
|
});
|
|
Engine.DestroyEntity(lastId);
|
|
};
|
|
|
|
Engine.RegisterSystemComponentType(IID_PlayerManager, "PlayerManager", PlayerManager);
|