From 759bc754c31bafd98641e8782000750aad0a9441 Mon Sep 17 00:00:00 2001 From: wraitii Date: Sat, 6 Jun 2020 10:19:42 +0000 Subject: [PATCH] Fix arrow count not being properly calculated when autogarrisoning. 423b3cbcaa Moved the message sent that an entity garrisons from `PerformGarrison` to `Garrison`. However, when an entity is autogarrisoned from `ProductionQueue` `PerformGarrison` is called thus not triggering the message. When ejecting the entity from the structure there is a message sent that the entity is removed, thus allowing for a negative amount of archers/arrows in `BuildingAI` (see 423b3cbcaa#42654). Note that `PerformGarrison` was explicitly split in 2102648f7c when introducing autogarrisoning. It probably has something to do with the position, since that was split. But I couldn't find any reason why it cannot be used now. A side effect of this is that when autogarrisoning an entity with visible garrison points those will be occupied as well now. Reviewed By: wraitii Differential Revision: https://code.wildfiregames.com/D2790 This was SVN commit r23743. --- .../simulation/components/GarrisonHolder.js | 78 ++++++++----------- .../simulation/components/ProductionQueue.js | 2 +- .../components/tests/test_GarrisonHolder.js | 2 +- 3 files changed, 34 insertions(+), 48 deletions(-) diff --git a/binaries/data/mods/public/simulation/components/GarrisonHolder.js b/binaries/data/mods/public/simulation/components/GarrisonHolder.js index 2070928656..84145e9259 100644 --- a/binaries/data/mods/public/simulation/components/GarrisonHolder.js +++ b/binaries/data/mods/public/simulation/components/GarrisonHolder.js @@ -173,20 +173,27 @@ GarrisonHolder.prototype.GetGarrisonedEntitiesCount = function() return count; }; -GarrisonHolder.prototype.IsAllowedToGarrison = function(ent) +GarrisonHolder.prototype.IsAllowedToGarrison = function(entity) { if (!this.IsGarrisoningAllowed()) return false; - if (!IsOwnedByMutualAllyOfEntity(ent, this.entity)) + if (!IsOwnedByMutualAllyOfEntity(entity, this.entity)) return false; - let cmpIdentity = Engine.QueryInterface(ent, IID_Identity); + let extraCount = 0; + let cmpGarrisonHolder = Engine.QueryInterface(entity, IID_GarrisonHolder); + if (cmpGarrisonHolder) + extraCount += cmpGarrisonHolder.GetGarrisonedEntitiesCount(); + if (this.GetGarrisonedEntitiesCount() + extraCount >= this.GetCapacity()) + return false; + + let cmpIdentity = Engine.QueryInterface(entity, IID_Identity); if (!cmpIdentity) 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) && !!Engine.QueryInterface(entity, IID_Garrisonable); }; /** @@ -214,12 +221,31 @@ GarrisonHolder.prototype.AllowedToVisibleGarrisoning = function(entity, visibleG */ GarrisonHolder.prototype.Garrison = function(entity, vgpEntity) { + if (!this.IsAllowedToGarrison(entity)) + return false; + + if (!this.HasEnoughHealth()) + return false; + let cmpPosition = Engine.QueryInterface(entity, IID_Position); if (!cmpPosition) return false; - if (!this.PerformGarrison(entity)) - return false; + if (!this.timer && this.GetHealRate() > 0) + { + let cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); + this.timer = cmpTimer.SetTimeout(this.entity, IID_GarrisonHolder, "HealTimeout", 1000, {}); + } + + this.entities.push(entity); + this.UpdateGarrisonFlag(); + let cmpProductionQueue = Engine.QueryInterface(entity, IID_ProductionQueue); + if (cmpProductionQueue) + cmpProductionQueue.PauseProduction(); + + let cmpAura = Engine.QueryInterface(entity, IID_Auras); + if (cmpAura && cmpAura.HasGarrisonAura()) + cmpAura.ApplyGarrisonAura(this.entity); let visibleGarrisonPoint; if (vgpEntity && this.AllowedToVisibleGarrisoning(entity, vgpEntity)) @@ -273,46 +299,6 @@ GarrisonHolder.prototype.Garrison = function(entity, vgpEntity) return true; }; -/** - * @return {boolean} Whether the entity was garrisonned. - */ -GarrisonHolder.prototype.PerformGarrison = function(entity) -{ - if (!this.HasEnoughHealth()) - return false; - - // Check if the unit is allowed to be garrisoned inside the building - if (!this.IsAllowedToGarrison(entity)) - return false; - - // Check the capacity - let extraCount = 0; - let cmpGarrisonHolder = Engine.QueryInterface(entity, IID_GarrisonHolder); - if (cmpGarrisonHolder) - extraCount += cmpGarrisonHolder.GetGarrisonedEntitiesCount(); - if (this.GetGarrisonedEntitiesCount() + extraCount >= this.GetCapacity()) - return false; - - if (!this.timer && this.GetHealRate() > 0) - { - let cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); - this.timer = cmpTimer.SetTimeout(this.entity, IID_GarrisonHolder, "HealTimeout", 1000, {}); - } - - // Actual garrisoning happens here - this.entities.push(entity); - this.UpdateGarrisonFlag(); - let cmpProductionQueue = Engine.QueryInterface(entity, IID_ProductionQueue); - if (cmpProductionQueue) - cmpProductionQueue.PauseProduction(); - - let cmpAura = Engine.QueryInterface(entity, IID_Auras); - if (cmpAura && cmpAura.HasGarrisonAura()) - cmpAura.ApplyGarrisonAura(this.entity); - - return true; -}; - /** * Simply eject the unit from the garrisoning entity without moving it * @param {number} entity - Id of the entity to be ejected. diff --git a/binaries/data/mods/public/simulation/components/ProductionQueue.js b/binaries/data/mods/public/simulation/components/ProductionQueue.js index d8173d3104..244629a990 100644 --- a/binaries/data/mods/public/simulation/components/ProductionQueue.js +++ b/binaries/data/mods/public/simulation/components/ProductionQueue.js @@ -626,7 +626,7 @@ ProductionQueue.prototype.SpawnUnits = function(templateName, count, metadata) { // Temporary owner affectation needed for GarrisonHolder checks. cmpNewOwnership.SetOwnerQuiet(cmpOwnership.GetOwner()); - garrisoned = cmpAutoGarrison.PerformGarrison(ent); + garrisoned = cmpAutoGarrison.Garrison(ent); cmpNewOwnership.SetOwnerQuiet(INVALID_PLAYER); } diff --git a/binaries/data/mods/public/simulation/components/tests/test_GarrisonHolder.js b/binaries/data/mods/public/simulation/components/tests/test_GarrisonHolder.js index 255f48a297..3984882bf3 100644 --- a/binaries/data/mods/public/simulation/components/tests/test_GarrisonHolder.js +++ b/binaries/data/mods/public/simulation/components/tests/test_GarrisonHolder.js @@ -168,7 +168,7 @@ TS_ASSERT_EQUALS(cmpGarrisonHolder.IsFull(), false); TS_ASSERT_EQUALS(cmpGarrisonHolder.IsAllowedToGarrison(enemyUnitId), false); TS_ASSERT_EQUALS(cmpGarrisonHolder.IsAllowedToGarrison(unitToGarrisonId), true); TS_ASSERT_EQUALS(cmpGarrisonHolder.HasEnoughHealth(), false); -TS_ASSERT_EQUALS(cmpGarrisonHolder.PerformGarrison(unitToGarrisonId), false); +TS_ASSERT_EQUALS(cmpGarrisonHolder.Garrison(unitToGarrisonId), false); AddMock(garrisonHolderId, IID_Health, { "GetHitpoints": () => 600,