Changeset View
Changeset View
Standalone View
Standalone View
binaries/data/mods/public/simulation/components/BattalionManager.js
- This file was added.
function BattalionManager() {} | |||||
BattalionManager.prototype.Schema = | |||||
"<a:component type='system'/><empty/>"; | |||||
BattalionManager.prototype.Init = function() | |||||
{ | |||||
this.battalions = []; | |||||
}; | |||||
/** | |||||
* Creates a new battalion. | |||||
* This now reuses IDs of disbanded battalions. | |||||
* @param {number[]} entities - The entity IDs to form the battalion with. | |||||
*/ | |||||
BattalionManager.prototype.FormBattalion = function(player, entities) | |||||
{ | |||||
// Use the first free battalion spot. | |||||
// If the IDs are required for more components in the future one might consider | |||||
// giving them truly unique IDs (keeping them incrementing like entity IDs). | |||||
// We fill the gaps now, by checking if the ID is a valid group, if there | |||||
// are no gaps, the highest value ID would need reach should be #groups + 1. | |||||
let index = this.battalions.length; | |||||
for (let id = 1; id <= index + 1; ++id) | |||||
{ | |||||
if (this.battalions.some(battalion => battalion.id == id)) | |||||
continue; | |||||
this.battalions[index] = { | |||||
"id": id, | |||||
Stan: won't you access one too far ? | |||||
Done Inline ActionsThis is the first free spot right? (Length = highest index +1 ?) Freagarach: This is the first free spot right? (Length = highest index +1 ?) | |||||
"player": player, | |||||
"entities": [] | |||||
}; | |||||
this.AddEntities(id, entities); | |||||
break; | |||||
} | |||||
}; | |||||
/** | |||||
* Removes battalion(s). | |||||
* @param {number[]} battalionIDs - The IDs of the battalions. If undefinded all battalions will be removed. | |||||
*/ | |||||
BattalionManager.prototype.DisbandBattalions = function(battalionIDs = undefined) | |||||
{ | |||||
if (battalionIDs) | |||||
this.battalions = this.battalions.filter(battalion => battalionIDs.indexOf(battalion.id) == -1); | |||||
else | |||||
this.battalions = []; | |||||
}; | |||||
/** | |||||
* Adds an entity/entities to the battalion. | |||||
* @param {number} battalionID - The unique ID of the battalion. | |||||
* @param {number} battalionID - The index of the battalion, passed by "formBattalion". | |||||
* @param {number[]} entities - The entity IDs to add to the battalion. | |||||
*/ | |||||
BattalionManager.prototype.AddEntities = function(battalionID, entities) | |||||
{ | |||||
let battalion = this.battalions.find(batt => batt.id == battalionID); | |||||
if (!battalion) | |||||
{ | |||||
error("Entity/Entities " + entities + " could not be added to battalion " + battalionID + " for that battalion does not exist."); | |||||
return; | |||||
} | |||||
let index = this.battalions.indexOf(battalion); | |||||
for (let entity of entities) | |||||
{ | |||||
// Entities cannot be in more than one battalion at the same time. | |||||
let bat = this.PartOfBattalion(entity); | |||||
if (bat) | |||||
this.RemoveEntities(bat, [entity]); | |||||
let cmpGuiInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface); | |||||
let entState = cmpGuiInterface.GetEntityState(this.battalions[index].player, entity); | |||||
// When this function is called during group rebuild, deleted | |||||
// entities will not yet have been removed, so entities might | |||||
// still be present in the group despite not existing. | |||||
if (!entState) | |||||
continue; | |||||
this.battalions[index].entities.push(entity); | |||||
if (!this.battalions[index].template) | |||||
this.battalions[index].template = entState.selectionGroupName || entState.template; | |||||
} | |||||
}; | |||||
/** | |||||
* Removes an entity/entities from the battalion. | |||||
* @param {number} battalionID - The unique ID of the battalion. | |||||
* @param {number} entities - The entity ID of the entities to remove. | |||||
*/ | |||||
BattalionManager.prototype.RemoveEntities = function(battalionID, entities) | |||||
{ | |||||
for (let battalion of this.battalions) | |||||
Not Done Inline ActionsCan't we know the bataillion id by storing it somewhere? Stan: Can't we know the bataillion id by storing it somewhere? | |||||
{ | |||||
if (battalion.id != battalionID) | |||||
continue; | |||||
let battalionIndex = this.battalions.indexOf(battalion); | |||||
for (let entity of entities) | |||||
{ | |||||
let entIndex = battalion.entities.indexOf(entity); | |||||
if (entIndex != -1) | |||||
this.battalions[battalionIndex].entities.splice(entIndex, 1); | |||||
else | |||||
warn("Entity " + entity + " could not removed from battalion " + battalion.id + " for it is no part of it."); | |||||
} | |||||
} | |||||
}; | |||||
/** | |||||
* Check wheter an entity is part of an battalion. | |||||
* @param {number} entity - The entity ID to check. | |||||
* @return {number} - Either a number when the entity is part of a battalion | |||||
* or "0" when it is not. | |||||
*/ | |||||
BattalionManager.prototype.PartOfBattalion = function(entity) | |||||
Done Inline ActionsCan't you just return true or false ? Stan: Can't you just return true or false ? | |||||
Done Inline ActionsNay, because we need the battalion number to be able to disband for example. I could create a seperate function for that. Freagarach: Nay, because we need the battalion number to be able to disband for example. I could create a… | |||||
{ | |||||
for (let battalion of this.battalions) | |||||
if (battalion.entities.indexOf(entity) != -1) | |||||
return battalion.id; | |||||
return 0; | |||||
}; | |||||
Done Inline ActionsMaybe -1 is a safer default Stan: Maybe -1 is a safer default | |||||
Done Inline ActionsAye, but the advantage of 0 is that it is seen as false in ifs :) (Is that bad coding?) Freagarach: Aye, but the advantage of `0` is that it is seen as `false` in ifs :) (Is that bad coding?) | |||||
/** | |||||
* Update the battalions. E.g. when units die or change ownership and such. | |||||
* ToDo: Run this when necessary. | |||||
*/ | |||||
BattalionManager.prototype.Update = function() | |||||
{ | |||||
this.CheckRenamedEntities(); | |||||
let battalionsToDisband = []; | |||||
for (let battalion of this.battalions) | |||||
{ | |||||
let entitiesToRemove = []; | |||||
for (let entity of battalion.entities) | |||||
{ | |||||
let cmpGuiInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface); | |||||
let entState = cmpGuiInterface.GetEntityState(battalion.player, entity); | |||||
// Remove deleted units or now unowned units. | |||||
if (!entState || entState.player != battalion.player) | |||||
entitiesToRemove.push(entity); | |||||
} | |||||
this.RemoveEntities(battalion.id, entitiesToRemove); | |||||
Not Done Inline ActionsWonder how that worked :P Stan: Wonder how that worked :P | |||||
if (!battalion.entities.length) | |||||
battalionsToDisband.push(battalion.id); | |||||
} | |||||
if (battalionsToDisband.length) | |||||
this.DisbandBattalions(battalionsToDisband); | |||||
}; | |||||
/** | |||||
* Update battalions if some entities in the battalion were renamed | |||||
* (in case of unit promotion or finishing building structure). | |||||
* ToDo: This needs some love. | |||||
*/ | |||||
BattalionManager.prototype.CheckRenamedEntities = function() | |||||
{ | |||||
let cmpGuiInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface); | |||||
// Reconstruct groups if at least one entity has been renamed. | |||||
let renamedEntities = cmpGuiInterface.GetRenamedEntities(); | |||||
if (renamedEntities.length == 0) | |||||
return; | |||||
Done Inline Actionsearly return ? Stan: early return ? | |||||
for (let battalion of this.battalions) | |||||
{ | |||||
renamedEntities = cmpGuiInterface.GetRenamedEntities(battalion.player); | |||||
for (let renamedEntity of renamedEntities) | |||||
{ | |||||
if (battalion.entities.indexOf(renamedEntity.entity) != -1) | |||||
{ | |||||
this.RemoveEntities(battalion.id, [renamedEntity.entity]); | |||||
let cmpOwner = Engine.QueryInterface(renamedEntity.newentity, IID_Ownership); | |||||
if (cmpOwner && cmpOwner.GetOwner() == battalion.player) | |||||
this.AddEntities(battalion.id, [renamedEntity.newentity]); | |||||
} | |||||
} | |||||
} | |||||
}; | |||||
/** | |||||
* Return the battalion(s). | |||||
* @param {number[]} players - Optionally the players we want to check. | |||||
* @return {object[]} battalions - The currently used battalions. | |||||
*/ | |||||
BattalionManager.prototype.GetBattalions = function(players = undefined) | |||||
{ | |||||
if (!players) | |||||
return this.battalions; | |||||
return this.battalions.filter(battalion => players.indexOf(battalion.player) != -1); | |||||
}; | |||||
/** | |||||
* Subscribe to all changes in ownership and such. | |||||
*/ | |||||
BattalionManager.prototype.OnGlobalOwnershipChanged = function(msg) | |||||
{ | |||||
if (this.PartOfBattalion(msg.entity)) | |||||
this.Update(); | |||||
}; | |||||
Engine.RegisterSystemComponentType(IID_BattalionManager, "BattalionManager", BattalionManager); |
Wildfire Games · Phabricator
won't you access one too far ?