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 @@ -653,7 +653,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 @@ -268,6 +268,10 @@ if (cmpAura && cmpAura.HasGarrisonAura()) cmpAura.ApplyGarrisonAura(this.entity); + let cmpGarrisonable = Engine.QueryInterface(entity, IID_Garrisonable); + if (cmpGarrisonable) + cmpGarrisonable.Garrison(this.entity); + Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { "added": [entity], "removed": [] }); return true; }; @@ -345,6 +349,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] }); return true; 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,42 @@ -function Garrisonable() {} +class Garrisonable +{ + get Schema() + { + return ""; + } -Garrisonable.prototype.Schema = ""; + Init() + { + this.garrisonHolder = INVALID_ENTITY; + } -Garrisonable.prototype.Init = function() -{ -}; + /** + * Which garrisonholder this entity is garrisoned in. + * + * @return {number} - The entity ID of the entity this entity is garrisoned in. + */ + GetGarrisonHolder() + { + return this.garrisonHolder; + } + + /** + * 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; + } +} 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 @@ -366,7 +366,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 @@ -3400,13 +3400,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, 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": {