Index: binaries/data/mods/public/gui/session/session.js =================================================================== --- binaries/data/mods/public/gui/session/session.js +++ binaries/data/mods/public/gui/session/session.js @@ -406,14 +406,13 @@ } /** - * Returns the entity itself except when garrisoned where it returns its garrisonHolder + * Returns the entity itself except when garrisoned where it returns its garrisonHolder. */ function getEntityOrHolder(ent) { let entState = GetEntityState(ent); - if (entState && !entState.position && entState.unitAI && entState.unitAI.orders.length && - entState.unitAI.orders[0].type == "Garrison") - return getEntityOrHolder(entState.unitAI.orders[0].data.target); + if (entState && !entState.position && entState.garrisonable && entState.garrisonable.garrisonHolder != INVALID_ENTITY) + return getEntityOrHolder(entState.garrisonable.garrisonHolder); return ent; } Index: binaries/data/mods/public/gui/session/unit_actions.js =================================================================== --- binaries/data/mods/public/gui/session/unit_actions.js +++ binaries/data/mods/public/gui/session/unit_actions.js @@ -705,7 +705,7 @@ }, "getActionInfo": function(entState, targetState) { - if (!entState.canGarrison || !targetState.garrisonHolder || + if (!entState.garrisonable || !targetState.garrisonHolder || !playerCheck(entState, targetState, ["Player", "MutualAlly"])) return false; 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 @@ -184,7 +184,7 @@ return false; let entityClasses = cmpIdentity.GetClassesList(); - return MatchesClassList(entityClasses, this.template.List._string) && !!Engine.QueryInterface(ent, IID_Garrisonable); + return MatchesClassList(entityClasses, this.template.List._string); }; /** @@ -267,18 +267,23 @@ }; /** - * @return {boolean} Whether the entity was garrisonned. + * @param {number} entity - The entity ID to garrison. + * @return {boolean} - Whether the entity was garrisoned. */ GarrisonHolder.prototype.PerformGarrison = function(entity) { if (!this.HasEnoughHealth()) return false; - // Check if the unit is allowed to be garrisoned inside the building + let cmpGarrisonable = Engine.QueryInterface(entity, IID_Garrisonable); + if (!cmpGarrisonable) + return false; + + // Check if the unit is allowed to be garrisoned inside the building. if (!this.IsAllowedToGarrison(entity)) return false; - // Check the capacity + // Check the capacity. let extraCount = 0; let cmpGarrisonHolder = Engine.QueryInterface(entity, IID_GarrisonHolder); if (cmpGarrisonHolder) @@ -292,7 +297,8 @@ this.timer = cmpTimer.SetTimeout(this.entity, IID_GarrisonHolder, "HealTimeout", 1000, {}); } - // Actual garrisoning happens here + // Actual garrisoning happens here. + cmpGarrisonable.Garrison(this.entity); this.entities.push(entity); this.UpdateGarrisonFlag(); let cmpProductionQueue = Engine.QueryInterface(entity, IID_ProductionQueue); @@ -384,6 +390,10 @@ if (cmpPosition) cmpEntPosition.SetYRotation(cmpPosition.GetPosition().horizAngleTo(pos)); + let cmpGarrisonable = Engine.QueryInterface(entity, IID_Garrisonable); + if (cmpGarrisonable) + cmpGarrisonable.UnGarrison(); + Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { "added": [], "removed": [entity], Index: binaries/data/mods/public/simulation/components/Garrisonable.js =================================================================== --- binaries/data/mods/public/simulation/components/Garrisonable.js +++ binaries/data/mods/public/simulation/components/Garrisonable.js @@ -1,11 +1,39 @@ -function Garrisonable() {} +class Garrisonable +{ + Init() + { + this.garrisonHolder = INVALID_ENTITY; + } -Garrisonable.prototype.Schema = ""; + /** + * Which garrisonholder this entity is garrisoned in. + * + * @return {number} - The entity ID of the entity this entity is garrisoned in. + */ + GetGarrisonHolder() + { + return this.garrisonHolder; + } -Garrisonable.prototype.Init = function() -{ -}; + /** + * Sets the garrisonholder, where this entity is garrisoned in. + * + * @param {number} entity - The entity ID of the entity this entity is garrisoned in. + */ + Garrison(entity) + { + this.garrisonHolder = entity; + } -Garrisonable.prototype.Serialize = null; + /** + * Resets the garrisonholder. + */ + UnGarrison() + { + this.garrisonHolder = INVALID_ENTITY; + } +} + +Garrisonable.prototype.Schema = ""; Engine.RegisterComponentType(IID_Garrisonable, "Garrisonable", Garrisonable); Index: binaries/data/mods/public/simulation/components/GuiInterface.js =================================================================== --- binaries/data/mods/public/simulation/components/GuiInterface.js +++ binaries/data/mods/public/simulation/components/GuiInterface.js @@ -358,7 +358,11 @@ "garrisonedEntitiesCount": cmpGarrisonHolder.GetGarrisonedEntitiesCount() }; - ret.canGarrison = !!Engine.QueryInterface(ent, IID_Garrisonable); + let cmpGarrisonable = Engine.QueryInterface(ent, IID_Garrisonable); + if (cmpGarrisonable) + ret.garrisonable = { + "garrisonHolder": cmpGarrisonable.GetGarrisonHolder() + }; let cmpUnitAI = Engine.QueryInterface(ent, IID_UnitAI); if (cmpUnitAI) Index: binaries/data/mods/public/simulation/components/UnitAI.js =================================================================== --- binaries/data/mods/public/simulation/components/UnitAI.js +++ binaries/data/mods/public/simulation/components/UnitAI.js @@ -3466,13 +3466,11 @@ UnitAI.prototype.GetGarrisonHolder = function() { - if (this.IsGarrisoned()) - { - for (let order of this.orderQueue) - if (order.type == "Garrison") - return order.data.target; - } - return INVALID_ENTITY; + if (!this.IsGarrisoned()) + return INVALID_ENTITY; + + let cmpGarrisonable = Engine.QueryInterface(this.entity, IID_Garrisonable); + return cmpGarrisonable ? cmpGarrisonable.GetGarrisonHolder() : INVALID_ENTITY; }; UnitAI.prototype.ShouldRespondToEndOfAlert = function() Index: binaries/data/mods/public/simulation/components/tests/test_GarrisonHolder.js =================================================================== --- binaries/data/mods/public/simulation/components/tests/test_GarrisonHolder.js +++ binaries/data/mods/public/simulation/components/tests/test_GarrisonHolder.js @@ -72,7 +72,10 @@ "GetOwner": () => friendlyPlayer }); - AddMock(i, IID_Garrisonable, {}); + AddMock(i, IID_Garrisonable, { + "Garrison": entity => {}, + "UnGarrison": () => {} + }); AddMock(i, IID_Position, { "GetHeightOffset": () => 0, @@ -241,7 +244,10 @@ AddMock(siegeEngineId, IID_Ownership, { "GetOwner": () => currentSiegePlayer }); -AddMock(siegeEngineId, IID_Garrisonable, {}); +AddMock(siegeEngineId, IID_Garrisonable, { + "Garrison": entity => {}, + "UnGarrison": () => {} +}); let cavalryId = 46; AddMock(cavalryId, IID_Identity, { "GetClassesList": () => ["Infantry", "Ranged"] @@ -262,7 +268,10 @@ AddMock(cavalryId, IID_Ownership, { "GetOwner": () => currentCavalryPlayer }); -AddMock(cavalryId, IID_Garrisonable, {}); +AddMock(cavalryId, IID_Garrisonable, { + "Garrison": entity => {}, + "UnGarrison": () => {} +}); TS_ASSERT(cmpGarrisonHolder.Garrison(siegeEngineId)); TS_ASSERT_EQUALS(cmpGarrisonHolder.GetGarrisonedEntitiesCount(), 1); TS_ASSERT(cmpGarrisonHolder.IsVisiblyGarrisoned(siegeEngineId)); Index: binaries/data/mods/public/simulation/components/tests/test_Garrisonable.js =================================================================== --- /dev/null +++ binaries/data/mods/public/simulation/components/tests/test_Garrisonable.js @@ -0,0 +1,14 @@ +Engine.LoadComponentScript("interfaces/Garrisonable.js"); +Engine.LoadComponentScript("Garrisonable.js"); + +const garrisonHolderID = 1; +const garrisonableID = 2; + +let cmpGarrisonable = ConstructComponent(garrisonableID, "Garrisonable", { +}); + +cmpGarrisonable.Garrison(garrisonHolderID); +TS_ASSERT_UNEVAL_EQUALS(cmpGarrisonable.GetGarrisonHolder(), garrisonHolderID); + +cmpGarrisonable.UnGarrison(); +TS_ASSERT_UNEVAL_EQUALS(cmpGarrisonable.GetGarrisonHolder(), INVALID_ENTITY); Index: binaries/data/mods/public/simulation/components/tests/test_GuiInterface.js =================================================================== --- binaries/data/mods/public/simulation/components/tests/test_GuiInterface.js +++ binaries/data/mods/public/simulation/components/tests/test_GuiInterface.js @@ -586,7 +586,6 @@ "needsRepair": false, "needsHeal": true, "builder": true, - "canGarrison": false, "visibility": "visible", "isBarterMarket": true, "resourceTrickle": {