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 @@ -167,10 +167,6 @@ if (!this.HasEnoughHealth()) return false; - let cmpGarrisonable = Engine.QueryInterface(entity, IID_Garrisonable); - if (!cmpGarrisonable || !cmpGarrisonable.Garrison(this.entity)) - return false; - if (!this.timer && this.GetHealRate() > 0) { let cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); @@ -532,7 +528,9 @@ if (entityIndex != -1) { this.Eject(msg.entity, true, true); - this.Garrison(msg.newentity, true); + let cmpGarrisonable = Engine.QueryInterface(msg.newentity, IID_Garrisonable); + if (cmpGarrisonable) + cmpGarrisonable.Garrison(this.entity, true); // TurretHolder is not subscribed to GarrisonChanged, so we must inform it explicitly. // Otherwise a renaming entity may re-occupy another turret instead of its previous one, @@ -648,9 +646,9 @@ for (let ent of this.initGarrison) { - let cmpUnitAI = Engine.QueryInterface(ent, IID_UnitAI); - if (cmpUnitAI && cmpUnitAI.CanGarrison(this.entity) && this.Garrison(ent)) - cmpUnitAI.Autogarrison(this.entity); + let cmpGarrisonable = Engine.QueryInterface(ent, IID_Garrisonable); + if (cmpGarrisonable) + cmpGarrisonable.Autogarrison(this.entity); } this.initGarrison = undefined; }; @@ -683,4 +681,3 @@ }; Engine.RegisterComponentType(IID_GarrisonHolder, "GarrisonHolder", GarrisonHolder); - 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 @@ -14,20 +14,44 @@ return this.holder || INVALID_ENTITY; }; +Garrisonable.prototype.CanGarrison = function(entity) +{ + let cmpGarrisonHolder = Engine.QueryInterface(entity, IID_GarrisonHolder); + return cmpGarrisonHolder && cmpGarrisonHolder.IsAllowedToGarrison(this.entity); +}; + /** * @param {number} entity - The entity ID of the entity this entity is being garrisoned in. * @return {boolean} - Whether garrisoning succeeded. */ -Garrisonable.prototype.Garrison = function(entity) +Garrisonable.prototype.Garrison = function(entity, renamed = false) { if (this.holder) return false; + let cmpGarrisonHolder = Engine.QueryInterface(entity, IID_GarrisonHolder); + if (!cmpGarrisonHolder || !cmpGarrisonHolder.Garrison(this.entity, renamed)) + return false; + this.holder = entity; return true; }; /** + * Called on game init when the entity was part of init garrison. + * @param {number} entity - The entityID to autogarrison. + */ +Garrisonable.prototype.Autogarrison = function(entity) +{ + if (!this.Garrison(entity)) + return; + + let cmpUnitAI = Engine.QueryInterface(this.entity, IID_UnitAI); + if (cmpUnitAI) + cmpUnitAI.Autogarrison(this.entity); +}; + +/** * Resets the garrisonHolder. */ Garrisonable.prototype.UnGarrison = 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 @@ -1,15 +1,16 @@ Engine.LoadHelperScript("ValueModification.js"); Engine.LoadHelperScript("Player.js"); -Engine.LoadComponentScript("interfaces/GarrisonHolder.js"); Engine.LoadComponentScript("interfaces/Garrisonable.js"); +Engine.LoadComponentScript("interfaces/GarrisonHolder.js"); Engine.LoadComponentScript("interfaces/TurretHolder.js"); -Engine.LoadComponentScript("GarrisonHolder.js"); Engine.LoadComponentScript("interfaces/Auras.js"); Engine.LoadComponentScript("interfaces/Health.js"); Engine.LoadComponentScript("interfaces/ProductionQueue.js"); Engine.LoadComponentScript("interfaces/ModifiersManager.js"); Engine.LoadComponentScript("interfaces/Timer.js"); Engine.LoadComponentScript("interfaces/UnitAI.js"); +Engine.LoadComponentScript("Garrisonable.js"); +Engine.LoadComponentScript("GarrisonHolder.js"); const garrisonedEntitiesList = [25, 26, 27, 28, 29, 30, 31, 32, 33]; const garrisonHolderId = 15; @@ -68,9 +69,7 @@ "GetOwner": () => friendlyPlayer }); - AddMock(i, IID_Garrisonable, { - "Garrison": entity => true, - "UnGarrison": () => {} + ConstructComponent(i, "Garrisonable", { }); AddMock(i, IID_Position, { @@ -215,9 +214,7 @@ AddMock(siegeEngineId, IID_Ownership, { "GetOwner": () => currentSiegePlayer }); -AddMock(siegeEngineId, IID_Garrisonable, { - "Garrison": entity => true, - "UnGarrison": () => {} +ConstructComponent(siegeEngineId, "Garrisonable", { }); let cavalryId = 46; AddMock(cavalryId, IID_Identity, { @@ -236,9 +233,7 @@ AddMock(cavalryId, IID_Ownership, { "GetOwner": () => currentCavalryPlayer }); -AddMock(cavalryId, IID_Garrisonable, { - "Garrison": entity => true, - "UnGarrison": () => {} +ConstructComponent(cavalryId, "Garrisonable", { }); TS_ASSERT(cmpGarrisonHolder.Garrison(siegeEngineId)); TS_ASSERT_EQUALS(cmpGarrisonHolder.GetGarrisonedEntitiesCount(), 1); Index: binaries/data/mods/public/simulation/components/tests/test_Garrisonable.js =================================================================== --- binaries/data/mods/public/simulation/components/tests/test_Garrisonable.js +++ binaries/data/mods/public/simulation/components/tests/test_Garrisonable.js @@ -3,6 +3,9 @@ const garrisonHolderID = 1; const garrisonableID = 2; +AddMock(garrisonHolderID, IID_GarrisonHolder, { + "Garrison": () => true +}); let cmpGarrisonable = ConstructComponent(garrisonableID, "Garrisonable", { }); Index: binaries/data/mods/public/simulation/helpers/Transform.js =================================================================== --- binaries/data/mods/public/simulation/helpers/Transform.js +++ binaries/data/mods/public/simulation/helpers/Transform.js @@ -268,11 +268,10 @@ cmpOldGarrison.Eject(ent); if (!cmpNewGarrison) continue; - let cmpUnitAI = Engine.QueryInterface(ent, IID_UnitAI); - if (!cmpUnitAI) + let cmpGarrisonable = Engine.QueryInterface(ent, IID_Garrisonable); + if (!cmpGarrisonable) continue; - cmpUnitAI.Autogarrison(newEnt); - cmpNewGarrison.Garrison(ent); + cmpGarrisonable.Autogarrison(newEnt); } }