Index: ps/trunk/binaries/data/mods/public/globalscripts/Templates.js
===================================================================
--- ps/trunk/binaries/data/mods/public/globalscripts/Templates.js
+++ ps/trunk/binaries/data/mods/public/globalscripts/Templates.js
@@ -327,6 +327,11 @@
warn("GetTemplateDataHelper(): Unrecognized Footprint type");
}
+ if (template.Garrisonable)
+ ret.garrisonable = {
+ "size": getEntityValue("Garrisonable/Size")
+ };
+
if (template.GarrisonHolder)
{
ret.garrisonHolder = {
Index: ps/trunk/binaries/data/mods/public/gui/common/tooltips.js
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/common/tooltips.js
+++ ps/trunk/binaries/data/mods/public/gui/common/tooltips.js
@@ -536,27 +536,45 @@
function getGarrisonTooltip(template)
{
- if (!template.garrisonHolder)
- return "";
-
- let tooltips = [
- sprintf(translate("%(label)s: %(garrisonLimit)s"), {
- "label": headerFont(translate("Garrison Limit")),
- "garrisonLimit": template.garrisonHolder.capacity
- })
- ];
-
- if (template.garrisonHolder.buffHeal)
- tooltips.push(
- sprintf(translate("%(healRateLabel)s %(value)s %(health)s / %(second)s"), {
- "healRateLabel": headerFont(translate("Heal:")),
- "value": Math.round(template.garrisonHolder.buffHeal),
- "health": unitFont(translate("Health")),
- "second": unitFont(translate("second")),
+ let tooltips = [];
+ if (template.garrisonHolder)
+ {
+ tooltips.push (
+ sprintf(translate("%(label)s: %(garrisonLimit)s"), {
+ "label": headerFont(translate("Garrison Limit")),
+ "garrisonLimit": template.garrisonHolder.capacity
})
);
- return tooltips.join(commaFont(translate(", ")));
+ if (template.garrisonHolder.buffHeal)
+ tooltips.push(
+ sprintf(translate("%(healRateLabel)s %(value)s %(health)s / %(second)s"), {
+ "healRateLabel": headerFont(translate("Heal:")),
+ "value": Math.round(template.garrisonHolder.buffHeal),
+ "health": unitFont(translate("Health")),
+ "second": unitFont(translate("second")),
+ })
+ );
+
+ tooltips.join(commaFont(translate(", ")));
+ }
+ if (template.garrisonable)
+ {
+ let extraSize;
+ if (template.garrisonHolder)
+ extraSize = template.garrisonHolder.occupiedSlots;
+ if (template.garrisonable.size > 1 || extraSize)
+ tooltips.push (
+ sprintf(translate("%(label)s: %(garrisonSize)s %(extraSize)s"), {
+ "label": headerFont(translate("Garrison Size")),
+ "garrisonSize": template.garrisonable.size,
+ "extraSize": extraSize ?
+ translateWithContext("nested garrison", "+ ") + extraSize : ""
+ })
+ );
+ }
+
+ return tooltips.join("\n");
}
function getProjectilesTooltip(template)
Index: ps/trunk/binaries/data/mods/public/gui/session/selection_details.js
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/session/selection_details.js
+++ ps/trunk/binaries/data/mods/public/gui/session/selection_details.js
@@ -366,6 +366,7 @@
let playerID = 0;
let totalCarrying = {};
let totalLoot = {};
+ let garrisonSize = 0;
for (let entState of entStates)
{
@@ -395,6 +396,12 @@
totalCarrying[type] = (totalCarrying[type] || 0) + carrying[type];
totalLoot[type] = (totalLoot[type] || 0) + carrying[type];
}
+
+ if (entState.garrisonable)
+ garrisonSize += entState.garrisonable.size;
+
+ if (entState.garrisonHolder)
+ garrisonSize += entState.garrisonHolder.occupiedSlots;
}
Engine.GetGUIObjectByName("healthMultiple").hidden = averageHealth <= 0;
@@ -448,6 +455,12 @@
numberOfUnits.caption = entStates.length;
numberOfUnits.tooltip = "";
+ if (garrisonSize)
+ numberOfUnits.tooltip = sprintf(translate("%(label)s: %(details)s\n"), {
+ "label": headerFont(translate("Garrison Size")),
+ "details": bodyFont(garrisonSize)
+ });
+
if (Object.keys(totalCarrying).length)
numberOfUnits.tooltip = sprintf(translate("%(label)s %(details)s\n"), {
"label": headerFont(translate("Carrying:")),
Index: ps/trunk/binaries/data/mods/public/gui/session/unit_actions.js
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/session/unit_actions.js
+++ ps/trunk/binaries/data/mods/public/gui/session/unit_actions.js
@@ -702,15 +702,15 @@
return false;
let tooltip = sprintf(translate("Current garrison: %(garrisoned)s/%(capacity)s"), {
- "garrisoned": targetState.garrisonHolder.garrisonedEntitiesCount,
+ "garrisoned": targetState.garrisonHolder.occupiedSlots,
"capacity": targetState.garrisonHolder.capacity
});
- let extraCount = 0;
+ let extraCount = entState.garrisonable.size;
if (entState.garrisonHolder)
- extraCount += entState.garrisonHolder.garrisonedEntitiesCount;
+ extraCount += entState.garrisonHolder.occupiedSlots;
- if (targetState.garrisonHolder.garrisonedEntitiesCount + extraCount >= targetState.garrisonHolder.capacity)
+ if (targetState.garrisonHolder.occupiedSlots + extraCount > targetState.garrisonHolder.capacity)
tooltip = coloredText(tooltip, "orange");
if (!MatchesClassList(entState.identity.classes, targetState.garrisonHolder.allowedClasses))
@@ -921,11 +921,11 @@
cursor = "action-garrison";
tooltip = sprintf(translate("Current garrison: %(garrisoned)s/%(capacity)s"), {
- "garrisoned": targetState.garrisonHolder.garrisonedEntitiesCount,
+ "garrisoned": targetState.garrisonHolder.occupiedSlots,
"capacity": targetState.garrisonHolder.capacity
});
- if (targetState.garrisonHolder.garrisonedEntitiesCount >=
+ if (targetState.garrisonHolder.occupiedSlots >=
targetState.garrisonHolder.capacity)
tooltip = coloredText(tooltip, "orange");
}
Index: ps/trunk/binaries/data/mods/public/simulation/ai/common-api/entity.js
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/ai/common-api/entity.js
+++ ps/trunk/binaries/data/mods/public/simulation/ai/common-api/entity.js
@@ -419,6 +419,8 @@
"garrisonMax": function() { return this.get("GarrisonHolder/Max"); },
+ "garrisonSize": function() { return this.get("Garrisonable/Size"); },
+
"garrisonEjectHealth": function() { return +this.get("GarrisonHolder/EjectHealth"); },
"getDefaultArrow": function() { return +this.get("BuildingAI/DefaultArrowCount"); },
@@ -735,7 +737,21 @@
},
"garrisoned": function() { return this._entity.garrisoned; },
- "canGarrisonInside": function() { return this._entity.garrisoned.length < this.garrisonMax(); },
+
+ "garrisonedSlots": function() {
+ let count = 0;
+
+ if (this._entity.garrisoned)
+ for (let ent of this._entity.garrisoned)
+ count += +this._ai._entities.get(ent).garrisonSize();
+
+ return count;
+ },
+
+ "canGarrisonInside": function()
+ {
+ return this.garrisonedSlots() < this.garrisonMax();
+ },
/**
* returns true if the entity can attack (including capture) the given class.
Index: ps/trunk/binaries/data/mods/public/simulation/ai/petra/defenseManager.js
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/ai/petra/defenseManager.js
+++ ps/trunk/binaries/data/mods/public/simulation/ai/petra/defenseManager.js
@@ -748,7 +748,7 @@
if (target.hitpoints() < target.garrisonEjectHealth() * target.maxHitpoints())
return false;
let minGarrison = data.min || target.garrisonMax();
- if (gameState.ai.HQ.garrisonManager.numberOfGarrisonedUnits(target) >= minGarrison)
+ if (gameState.ai.HQ.garrisonManager.numberOfGarrisonedSlots(target) >= minGarrison)
return false;
if (data.attacker)
{
@@ -800,7 +800,7 @@
let ret = false;
for (let ent of units.values())
{
- if (garrisonManager.numberOfGarrisonedUnits(target) >= minGarrison)
+ if (garrisonManager.numberOfGarrisonedSlots(target) >= minGarrison)
break;
if (ent.getMetadata(PlayerID, "plan") !== undefined && ent.getMetadata(PlayerID, "plan") >= 0)
{
@@ -830,7 +830,7 @@
continue;
if (!MatchesClassList(unit.classes(), ent.garrisonableClasses()))
continue;
- if (garrisonManager.numberOfGarrisonedUnits(ent) >= ent.garrisonMax())
+ if (garrisonManager.numberOfGarrisonedSlots(ent) >= ent.garrisonMax())
continue;
if (ent.hitpoints() < ent.garrisonEjectHealth() * ent.maxHitpoints())
continue;
@@ -866,7 +866,7 @@
continue;
if (!MatchesClassList(unit.classes(), ent.garrisonableClasses()))
continue;
- if (garrisonManager.numberOfGarrisonedUnits(ent) >= ent.garrisonMax() &&
+ if (garrisonManager.numberOfGarrisonedSlots(ent) >= ent.garrisonMax() &&
(!emergency || !ent.garrisoned().length))
continue;
if (ent.hitpoints() < ent.garrisonEjectHealth() * ent.maxHitpoints())
@@ -887,7 +887,7 @@
garrisonManager.garrison(gameState, unit, nearest, "protection");
return true;
}
- if (garrisonManager.numberOfGarrisonedUnits(nearest) >= nearest.garrisonMax()) // make room for this ent
+ if (garrisonManager.numberOfGarrisonedSlots(nearest) >= nearest.garrisonMax()) // make room for this ent
nearest.unload(nearest.garrisoned()[0]);
garrisonManager.garrison(gameState, unit, nearest, nearest.buffHeal() ? "protection" : "emergency");
Index: ps/trunk/binaries/data/mods/public/simulation/ai/petra/garrisonManager.js
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/ai/petra/garrisonManager.js
+++ ps/trunk/binaries/data/mods/public/simulation/ai/petra/garrisonManager.js
@@ -179,7 +179,7 @@
}
list.splice(j--, 1);
}
- if (this.numberOfGarrisonedUnits(holder) === 0)
+ if (this.numberOfGarrisonedSlots(holder) === 0)
this.holders.delete(id);
else
holder.setMetadata(PlayerID, "holderTimeUpdate", gameState.ai.elapsedTime);
@@ -193,7 +193,7 @@
let ent = gameState.getEntityById(id);
if (!ent || ent.owner() !== PlayerID)
this.decayingStructures.delete(id);
- else if (this.numberOfGarrisonedUnits(ent) < gmin)
+ else if (this.numberOfGarrisonedSlots(ent) < gmin)
gameState.ai.HQ.defenseManager.garrisonUnitsInside(gameState, ent, { "min": gmin, "type": "decay" });
}
};
@@ -207,6 +207,15 @@
return holder.garrisoned().length + this.holders.get(holder.id()).list.length;
};
+/** TODO should add the units garrisoned inside garrisoned units */
+PETRA.GarrisonManager.prototype.numberOfGarrisonedSlots = function(holder)
+{
+ if (!this.holders.has(holder.id()))
+ return holder.garrisonedSlots();
+
+ return holder.garrisonedSlots() + this.holders.get(holder.id()).list.length;
+};
+
PETRA.GarrisonManager.prototype.allowMelee = function(holder)
{
if (!this.holders.has(holder.id()))
@@ -218,7 +227,7 @@
/** This is just a pre-garrison state, while the entity walk to the garrison holder */
PETRA.GarrisonManager.prototype.garrison = function(gameState, ent, holder, type)
{
- if (this.numberOfGarrisonedUnits(holder) >= holder.garrisonMax() || !ent.canGarrison())
+ if (this.numberOfGarrisonedSlots(holder) >= holder.garrisonMax() || !ent.canGarrison())
return;
this.registerHolder(gameState, holder);
Index: ps/trunk/binaries/data/mods/public/simulation/ai/petra/headquarters.js
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/ai/petra/headquarters.js
+++ ps/trunk/binaries/data/mods/public/simulation/ai/petra/headquarters.js
@@ -2108,7 +2108,7 @@
// We will choose randomly ranged and melee units, except when garrisonHolder is full
// in which case we prefer melee units
- let numGarrisoned = this.garrisonManager.numberOfGarrisonedUnits(nearestAnchor);
+ let numGarrisoned = this.garrisonManager.numberOfGarrisonedSlots(nearestAnchor);
if (nearestAnchor._entity.trainingQueue)
{
for (let item of nearestAnchor._entity.trainingQueue)
Index: ps/trunk/binaries/data/mods/public/simulation/components/AlertRaiser.js
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/components/AlertRaiser.js
+++ ps/trunk/binaries/data/mods/public/simulation/components/AlertRaiser.js
@@ -63,7 +63,7 @@
let cmpGarrisonHolder = Engine.QueryInterface(ent, IID_GarrisonHolder);
if (!reserved.has(ent))
- reserved.set(ent, cmpGarrisonHolder.GetCapacity() - cmpGarrisonHolder.GetGarrisonedEntitiesCount());
+ reserved.set(ent, cmpGarrisonHolder.GetCapacity() - cmpGarrisonHolder.OccupiedSlots());
return cmpGarrisonHolder.IsAllowedToGarrison(unit) && reserved.get(ent);
});
Index: ps/trunk/binaries/data/mods/public/simulation/components/GarrisonHolder.js
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/components/GarrisonHolder.js
+++ ps/trunk/binaries/data/mods/public/simulation/components/GarrisonHolder.js
@@ -93,7 +93,7 @@
GarrisonHolder.prototype.IsFull = function()
{
- return this.GetGarrisonedEntitiesCount() >= this.GetCapacity();
+ return this.OccupiedSlots() >= this.GetCapacity();
};
GarrisonHolder.prototype.GetHealRate = function()
@@ -134,6 +134,18 @@
return count;
};
+GarrisonHolder.prototype.OccupiedSlots = function()
+{
+ let count = 0;
+ for (let ent of this.entities)
+ {
+ let cmpGarrisonable = Engine.QueryInterface(ent, IID_Garrisonable);
+ if (cmpGarrisonable)
+ count += cmpGarrisonable.TotalSize();
+ }
+ return count;
+};
+
GarrisonHolder.prototype.IsAllowedToGarrison = function(entity)
{
if (!this.IsGarrisoningAllowed())
@@ -142,11 +154,8 @@
if (!IsOwnedByMutualAllyOfEntity(entity, this.entity))
return false;
- let extraCount = 0;
- let cmpGarrisonHolder = Engine.QueryInterface(entity, IID_GarrisonHolder);
- if (cmpGarrisonHolder)
- extraCount += cmpGarrisonHolder.GetGarrisonedEntitiesCount();
- if (this.GetGarrisonedEntitiesCount() + extraCount >= this.GetCapacity())
+ let cmpGarrisonable = Engine.QueryInterface(entity, IID_Garrisonable);
+ if (!cmpGarrisonable || this.OccupiedSlots() + cmpGarrisonable.TotalSize() > this.GetCapacity())
return false;
let cmpIdentity = Engine.QueryInterface(entity, IID_Identity);
Index: ps/trunk/binaries/data/mods/public/simulation/components/Garrisonable.js
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/components/Garrisonable.js
+++ ps/trunk/binaries/data/mods/public/simulation/components/Garrisonable.js
@@ -1,12 +1,42 @@
function Garrisonable() {}
-Garrisonable.prototype.Schema = "";
+Garrisonable.prototype.Schema =
+ "Controls the garrisonability of an entity." +
+ "" +
+ "10" +
+ "" +
+ "" +
+ "" +
+ "";
Garrisonable.prototype.Init = function()
{
};
/**
+ * @return {number} - The number of slots this unit takes in a garrisonHolder.
+ */
+Garrisonable.prototype.UnitSize = function()
+{
+ return ApplyValueModificationsToEntity("Garrisonable/Size", +this.template.Size, this.entity);
+};
+
+/**
+ * Calculates the number of slots this unit takes in a garrisonHolder by
+ * adding the number of garrisoned slots to the equation.
+ *
+ * @return {number} - The number of slots this unit and its garrison takes in a garrisonHolder.
+ */
+Garrisonable.prototype.TotalSize = function()
+{
+ let size = this.UnitSize();
+ let cmpGarrisonHolder = Engine.QueryInterface(this.entity, IID_GarrisonHolder);
+ if (cmpGarrisonHolder)
+ size += cmpGarrisonHolder.OccupiedSlots();
+ return size;
+};
+
+/**
* @return {number} - The entity ID of the entity this entity is garrisoned in.
*/
Garrisonable.prototype.HolderID = function()
Index: ps/trunk/binaries/data/mods/public/simulation/components/GuiInterface.js
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/components/GuiInterface.js
+++ ps/trunk/binaries/data/mods/public/simulation/components/GuiInterface.js
@@ -368,7 +368,7 @@
"buffHeal": cmpGarrisonHolder.GetHealRate(),
"allowedClasses": cmpGarrisonHolder.GetAllowedClasses(),
"capacity": cmpGarrisonHolder.GetCapacity(),
- "garrisonedEntitiesCount": cmpGarrisonHolder.GetGarrisonedEntitiesCount()
+ "occupiedSlots": cmpGarrisonHolder.OccupiedSlots()
};
let cmpTurretHolder = Engine.QueryInterface(ent, IID_TurretHolder);
@@ -380,7 +380,8 @@
let cmpGarrisonable = Engine.QueryInterface(ent, IID_Garrisonable);
if (cmpGarrisonable)
ret.garrisonable = {
- "holder": cmpGarrisonable.HolderID()
+ "holder": cmpGarrisonable.HolderID(),
+ "size": cmpGarrisonable.UnitSize()
};
let cmpUnitAI = Engine.QueryInterface(ent, IID_UnitAI);
Index: ps/trunk/binaries/data/mods/public/simulation/components/tests/test_GarrisonHolder.js
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/components/tests/test_GarrisonHolder.js
+++ ps/trunk/binaries/data/mods/public/simulation/components/tests/test_GarrisonHolder.js
@@ -12,6 +12,7 @@
const garrisonHolderId = 15;
const unitToGarrisonId = 24;
const enemyUnitId = 34;
+const largeUnitId = 35;
const player = 1;
const friendlyPlayer = 2;
const enemyPlayer = 3;
@@ -45,7 +46,7 @@
"GetPlayerByID": id => id
});
-for (let i = 24; i <= 34; ++i)
+for (let i = 24; i <= 35; ++i)
{
AddMock(i, IID_Identity, {
"GetClassesList": () => ["Infantry", "Cavalry"],
@@ -65,10 +66,20 @@
"GetOwner": () => friendlyPlayer
});
- AddMock(i, IID_Garrisonable, {
- "Garrison": entity => true,
- "UnGarrison": () => true
- });
+ if (i == largeUnitId)
+ AddMock(i, IID_Garrisonable, {
+ "UnitSize": () => 9,
+ "TotalSize": () => 9,
+ "Garrison": entity => true,
+ "UnGarrison": () => true
+ });
+ else
+ AddMock(i, IID_Garrisonable, {
+ "UnitSize": () => 1,
+ "TotalSize": () => 1,
+ "Garrison": entity => true,
+ "UnGarrison": () => true
+ });
AddMock(i, IID_Position, {
"GetHeightOffset": () => 0,
@@ -100,10 +111,14 @@
TS_ASSERT_EQUALS(cmpGarrisonHolder.HasEnoughHealth(), true);
TS_ASSERT_EQUALS(cmpGarrisonHolder.Garrison(enemyUnitId), false);
TS_ASSERT_EQUALS(cmpGarrisonHolder.Garrison(unitToGarrisonId), true);
+ TS_ASSERT_EQUALS(cmpGarrisonHolder.Garrison(largeUnitId), true);
+ TS_ASSERT_EQUALS(cmpGarrisonHolder.IsFull(), true);
+ TS_ASSERT_EQUALS(cmpGarrisonHolder.Eject(largeUnitId), true);
TS_ASSERT_EQUALS(cmpGarrisonHolder.Eject(unitToGarrisonId), true);
TS_ASSERT_EQUALS(cmpGarrisonHolder.Garrison(unitToGarrisonId), true);
for (let entity of garrisonedEntitiesList)
TS_ASSERT_EQUALS(cmpGarrisonHolder.Garrison(entity), true);
+ TS_ASSERT_EQUALS(cmpGarrisonHolder.Garrison(largeUnitId), false);
TS_ASSERT_EQUALS(cmpGarrisonHolder.IsFull(), true);
TS_ASSERT_EQUALS(cmpGarrisonHolder.CanPickup(unitToGarrisonId), false);
@@ -120,6 +135,7 @@
TS_ASSERT_UNEVAL_EQUALS(cmpGarrisonHolder.GetEntities(), [24, 26, 27]);
TS_ASSERT_EQUALS(cmpGarrisonHolder.GetGarrisonedEntitiesCount(), 3);
TS_ASSERT_EQUALS(cmpGarrisonHolder.IsFull(), false);
+ TS_ASSERT_EQUALS(cmpGarrisonHolder.Garrison(largeUnitId), false);
TS_ASSERT_EQUALS(cmpGarrisonHolder.UnloadAll(), true);
TS_ASSERT_UNEVAL_EQUALS(cmpGarrisonHolder.GetEntities(), []);
};
@@ -152,6 +168,7 @@
TS_ASSERT_EQUALS(cmpGarrisonHolder.CanPickup(enemyUnitId), false);
TS_ASSERT_EQUALS(cmpGarrisonHolder.IsFull(), false);
TS_ASSERT_EQUALS(cmpGarrisonHolder.IsAllowedToGarrison(enemyUnitId), false);
+TS_ASSERT_EQUALS(cmpGarrisonHolder.IsAllowedToGarrison(largeUnitId), true);
TS_ASSERT_EQUALS(cmpGarrisonHolder.IsAllowedToGarrison(unitToGarrisonId), true);
TS_ASSERT_EQUALS(cmpGarrisonHolder.HasEnoughHealth(), false);
TS_ASSERT_EQUALS(cmpGarrisonHolder.Garrison(unitToGarrisonId), false);
@@ -213,6 +230,8 @@
"GetOwner": () => currentSiegePlayer
});
AddMock(siegeEngineId, IID_Garrisonable, {
+ "UnitSize": () => 1,
+ "TotalSize": () => 1,
"Garrison": entity => true,
"UnGarrison": () => true
});
@@ -234,6 +253,8 @@
"GetOwner": () => currentCavalryPlayer
});
AddMock(cavalryId, IID_Garrisonable, {
+ "UnitSize": () => 1,
+ "TotalSize": () => 1,
"Garrison": entity => true,
"UnGarrison": () => true
});
Index: ps/trunk/binaries/data/mods/public/simulation/components/tests/test_Garrisonable.js
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/components/tests/test_Garrisonable.js
+++ ps/trunk/binaries/data/mods/public/simulation/components/tests/test_Garrisonable.js
@@ -1,15 +1,31 @@
Engine.LoadComponentScript("interfaces/Auras.js");
Engine.LoadComponentScript("interfaces/Garrisonable.js");
+Engine.LoadComponentScript("interfaces/GarrisonHolder.js");
Engine.LoadComponentScript("interfaces/ProductionQueue.js");
Engine.LoadComponentScript("interfaces/UnitAI.js");
Engine.LoadComponentScript("Garrisonable.js");
+Engine.RegisterGlobal("ApplyValueModificationsToEntity", (prop, oVal, ent) => oVal);
+
const garrisonHolderID = 1;
const garrisonableID = 2;
+let size = 1
let cmpGarrisonable = ConstructComponent(garrisonableID, "Garrisonable", {
+ "Size": size
});
+TS_ASSERT_EQUALS(cmpGarrisonable.UnitSize(garrisonHolderID), size);
+TS_ASSERT_EQUALS(cmpGarrisonable.TotalSize(garrisonHolderID), size);
+
+let extraSize = 2;
+AddMock(garrisonableID, IID_GarrisonHolder, {
+ "OccupiedSlots": () => extraSize
+});
+
+TS_ASSERT_EQUALS(cmpGarrisonable.UnitSize(garrisonHolderID), size);
+TS_ASSERT_EQUALS(cmpGarrisonable.TotalSize(garrisonHolderID), size + extraSize);
+
TS_ASSERT(cmpGarrisonable.Garrison(garrisonHolderID));
TS_ASSERT_UNEVAL_EQUALS(cmpGarrisonable.HolderID(), garrisonHolderID);
Index: ps/trunk/binaries/data/mods/public/simulation/templates/template_unit.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/template_unit.xml
+++ ps/trunk/binaries/data/mods/public/simulation/templates/template_unit.xml
@@ -22,7 +22,9 @@
4.0
-
+
+ 1
+
corpse