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.