Index: binaries/data/mods/public/simulation/components/BuildingAI.js
===================================================================
--- binaries/data/mods/public/simulation/components/BuildingAI.js
+++ binaries/data/mods/public/simulation/components/BuildingAI.js
@@ -37,7 +37,7 @@
for (let ent of msg.added)
{
let cmpIdentity = Engine.QueryInterface(ent, IID_Identity);
- if (!cmpIdentity)
+ if (msg.visible[ent] || !cmpIdentity)
continue;
if (MatchesClassList(cmpIdentity.GetClassesList(), classes))
++this.archersGarrisoned;
@@ -46,7 +46,7 @@
for (let ent of msg.removed)
{
let cmpIdentity = Engine.QueryInterface(ent, IID_Identity);
- if (!cmpIdentity)
+ if (msg.visible[ent] || !cmpIdentity)
continue;
if (MatchesClassList(cmpIdentity.GetClassesList(), classes))
--this.archersGarrisoned;
Index: binaries/data/mods/public/simulation/components/GarrisonHolder.js
===================================================================
--- binaries/data/mods/public/simulation/components/GarrisonHolder.js
+++ binaries/data/mods/public/simulation/components/GarrisonHolder.js
@@ -46,6 +46,14 @@
"" +
"" +
"" +
+ "" +
+ "" +
+ "tokens" +
+ "" +
+ "" +
+ "" +
+ ""+
+ "" +
"" +
"" +
"" +
@@ -72,15 +80,18 @@
{
let points = this.template.VisibleGarrisonPoints;
for (let point in points)
+ {
this.visibleGarrisonPoints.push({
"offset": {
"x": +points[point].X,
"y": +points[point].Y,
- "z": +points[point].Z
+ "z": +points[point].Z,
+ "allowedClasses": points[point].VisibleGarrisonAllowedClasses ? points[point].VisibleGarrisonAllowedClasses : "Infantry+Ranged"
},
"angle": points[point].Angle ? +points[point].Angle * Math.PI / 180 : null,
- "entity": null
+ "entity": null,
});
+ }
}
};
@@ -179,6 +190,22 @@
};
/**
+* Return string of allowed classes in the form "Class1 Class2+Class3" from visibleGarrisonPoint to handle default value
+*/
+GarrisonHolder.prototype.GetVisibleAllowedClasses = function (visibleGarrisonPoint)
+{
+ return !visibleGarrisonPoint ? "" : visibleGarrisonPoint.offset.allowedClasses._string || visibleGarrisonPoint.offset.allowedClasses;
+};
+
+/**
+ * Returns true if the unit is allowed be visible on that garrison point, false otherwise.
+ */
+GarrisonHolder.prototype.AllowedToVisibleGarrisoning = function (visibleGarrisonPoint, entity)
+{
+ return MatchesClassList(Engine.QueryInterface(entity, IID_Identity).GetClassesList(), this.GetVisibleAllowedClasses(visibleGarrisonPoint));
+};
+
+/**
* Garrison a unit inside. The timer for AutoHeal is started here.
* @param {number} vgpEntity - The visual garrison point that will be used.
* If vgpEntity is given, this visualGarrisonPoint will be used for the entity.
@@ -199,11 +226,15 @@
{
if (vgp.entity)
continue;
+
+ if (!this.AllowedToVisibleGarrisoning(vgp, entity))
+ continue;
+
visibleGarrisonPoint = vgp;
break;
}
- if (visibleGarrisonPoint)
+ if (visibleGarrisonPoint && this.AllowedToVisibleGarrisoning(visibleGarrisonPoint, entity))
{
visibleGarrisonPoint.entity = entity;
// Angle of turrets:
@@ -228,6 +259,14 @@
else
cmpPosition.MoveOutOfWorld();
+ let visible = {};
+ visible[entity] = this.IsVisiblyGarrisoned(entity);
+ // Should only be called after the garrison has been performed else the visible Garrison Points are not updated yet.
+ Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, {
+ "added": [entity],
+ "removed": [],
+ "visible": visible
+ });
return true;
};
@@ -268,7 +307,14 @@
if (cmpAura && cmpAura.HasGarrisonAura())
cmpAura.ApplyGarrisonAura(this.entity);
- Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { "added": [entity], "removed": [] });
+ let visible = {};
+ visible[entity] = this.IsVisiblyGarrisoned(entity);
+ // Should only be called after the garrison has been performed else the visible Garrison Points are not updated yet.
+ Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, {
+ "added": [entity],
+ "removed": [],
+ "visible": visible
+ });
return true;
};
@@ -313,6 +359,14 @@
let cmpEntPosition = Engine.QueryInterface(entity, IID_Position);
let cmpEntUnitAI = Engine.QueryInterface(entity, IID_UnitAI);
+ let visible = {};
+ visible[entity] = this.IsVisiblyGarrisoned(entity);
+ // Should only be called before the ejection has been performed else the visible Garrison Points will be empty.
+ Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, {
+ "added": [],
+ "removed": [entity],
+ "visible": visible
+ });
for (let vgp of this.visibleGarrisonPoints)
{
if (vgp.entity != entity)
@@ -345,7 +399,13 @@
if (cmpPosition)
cmpEntPosition.SetYRotation(cmpPosition.GetPosition().horizAngleTo(pos));
- Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { "added": [], "removed": [entity] });
+ visible[entity] = this.IsVisiblyGarrisoned(entity);
+ // Should only be called before the ejection has been performed else the visible Garrison Points will be empty.
+ Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, {
+ "added": [],
+ "removed": [entity],
+ "visible": visible
+ });
return true;
};
@@ -581,7 +641,13 @@
if (cmpHealth && cmpHealth.GetHitpoints() == 0)
{
this.entities.splice(entityIndex, 1);
- Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { "added": [], "removed": [msg.entity] });
+ let visible = {};
+ visible[msg.entity] = this.IsVisiblyGarrisoned(msg.entity);
+ Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, {
+ "added": [],
+ "removed": [msg.entity],
+ "visible": visible
+ });
this.UpdateGarrisonFlag();
for (let point of this.visibleGarrisonPoints)
@@ -595,6 +661,8 @@
/**
* Update list of garrisoned entities if one gets renamed (e.g. by promotion).
+ * vgpEntity is only defined in some peculiar case where we want to reuse the same visibleGarrisonPoint,
+ * in case of promotion for example, and thus should always be allowed.
*/
GarrisonHolder.prototype.OnGlobalEntityRenamed = function(msg)
{
@@ -670,11 +738,30 @@
}
if (killedEntities.length)
- Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { "added": [], "removed": killedEntities });
+ {
+ let visibleEntitiesIds = {};
+ for (let ent of killedEntities)
+ visibleEntitiesIds[ent] = this.IsVisiblyGarrisoned(ent);
+ Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, {
+ "added": [],
+ "removed": killedEntities,
+ "visible": visibleEntitiesIds
+ });
+ }
this.UpdateGarrisonFlag();
};
/**
+* Gives insight about the unit type of garrisoning.
+* @return{bool} returns true if the unit is visible on the structure
+* @param {int} the entity's id
+*/
+GarrisonHolder.prototype.IsVisiblyGarrisoned = function (entity)
+{
+ return this.visibleGarrisonPoints.some(point => point.entity == entity);
+};
+
+/**
* Whether an entity is ejectable.
* @param {number} entity - The entity-ID to be tested.
* @return {boolean} - Whether the entity is ejectable.