From 17c9950ceef8a2b9a1acbf46ecac6f65bf029e22 Mon Sep 17 00:00:00 2001 From: Angen Date: Mon, 27 Jan 2020 17:14:30 +0000 Subject: [PATCH] Fix entities not retaining repair order after target transforms Update this.repairTarget in UnitAI when target renames. Transfer builders among renamed entities. Differential Revision: https://code.wildfiregames.com/D2360 Patch by: @Freagarach Comments by: Stan, elexis This was SVN commit r23449. --- .../simulation/components/Foundation.js | 71 +++++++++++++++---- .../simulation/components/Repairable.js | 21 ++++++ .../public/simulation/components/UnitAI.js | 29 ++++---- .../simulation/components/tests/test_Pack.js | 2 + .../public/simulation/helpers/Transform.js | 5 ++ 5 files changed, 102 insertions(+), 26 deletions(-) diff --git a/binaries/data/mods/public/simulation/components/Foundation.js b/binaries/data/mods/public/simulation/components/Foundation.js index fe1e848f0d..9ee81fabd2 100644 --- a/binaries/data/mods/public/simulation/components/Foundation.js +++ b/binaries/data/mods/public/simulation/components/Foundation.js @@ -75,6 +75,16 @@ Foundation.prototype.GetBuildPercentage = function() return Math.floor(this.GetBuildProgress() * 100); }; +/** + * Returns the current builders. + * + * @return {number[]} - An array containing the entity IDs of assigned builders. + */ +Foundation.prototype.GetBuilders = function() +{ + return Array.from(this.builders.keys()); +}; + Foundation.prototype.GetNumBuilders = function() { return this.builders.size; @@ -116,23 +126,48 @@ Foundation.prototype.OnDestroy = function() } }; +/** + * Adds an array of builders. + * + * @param {number[]} builders - An array containing the entity IDs of builders to assign. + */ +Foundation.prototype.AddBuilders = function(builders) +{ + let changed = false; + for (let builder of builders) + changed = this.AddBuilderHelper(builder) || changed; + + if (changed) + this.HandleBuildersChanged(); +}; + +/** + * Adds a single builder to this entity. + * + * @param {number} builderEnt - The entity to add. + * @return {boolean} - Whether the addition was successful. + */ +Foundation.prototype.AddBuilderHelper = function(builderEnt) +{ + if (this.builders.has(builderEnt)) + return false; + + let buildRate = Engine.QueryInterface(builderEnt, IID_Builder).GetRate(); + this.builders.set(builderEnt, buildRate); + this.totalBuilderRate += buildRate; + + return true; +} + /** * Adds a builder to the counter. + * + * @param {number} builderEnt - The entity to add. */ Foundation.prototype.AddBuilder = function(builderEnt) { - if (this.builders.has(builderEnt)) - return; - - this.builders.set(builderEnt, Engine.QueryInterface(builderEnt, IID_Builder).GetRate()); - this.totalBuilderRate += this.builders.get(builderEnt); - this.SetBuildMultiplier(); - - let cmpVisual = Engine.QueryInterface(this.entity, IID_Visual); - if (cmpVisual) - cmpVisual.SetVariable("numbuilders", this.builders.size); - - Engine.PostMessage(this.entity, MT_FoundationBuildersChanged, { "to": Array.from(this.builders.keys()) }); + if (this.AddBuilderHelper(builderEnt)) + this.HandleBuildersChanged(); }; Foundation.prototype.RemoveBuilder = function(builderEnt) @@ -142,14 +177,22 @@ Foundation.prototype.RemoveBuilder = function(builderEnt) this.totalBuilderRate -= this.builders.get(builderEnt); this.builders.delete(builderEnt); + this.HandleBuildersChanged(); +}; + +/** + * This has to be called whenever the number of builders change. + */ +Foundation.prototype.HandleBuildersChanged = function() +{ this.SetBuildMultiplier(); let cmpVisual = Engine.QueryInterface(this.entity, IID_Visual); if (cmpVisual) cmpVisual.SetVariable("numbuilders", this.builders.size); - Engine.PostMessage(this.entity, MT_FoundationBuildersChanged, { "to": Array.from(this.builders.keys()) }); -}; + Engine.PostMessage(this.entity, MT_FoundationBuildersChanged, { "to": this.GetBuilders() }); +} /** * The build multiplier is a penalty that is applied to each builder. diff --git a/binaries/data/mods/public/simulation/components/Repairable.js b/binaries/data/mods/public/simulation/components/Repairable.js index 8a2472ad5c..3d98f1f350 100644 --- a/binaries/data/mods/public/simulation/components/Repairable.js +++ b/binaries/data/mods/public/simulation/components/Repairable.js @@ -33,11 +33,32 @@ Repairable.prototype.GetBuildProgress = function() return hitpoints / maxHitpoints; }; +/** + * Returns the current builders. + * + * @return {number[]} - An array containing the entity IDs of assigned builders. + */ +Repairable.prototype.GetBuilders = function() +{ + return Array.from(this.builders.keys()); +}; + Repairable.prototype.GetNumBuilders = function() { return this.builders.size; }; +/** + * Adds an array of builders. + * + * @param {number[]} - An array containing the entity IDs of builders to assign. + */ +Repairable.prototype.AddBuilders = function(builders) +{ + for (let builder of builders) + this.AddBuilder(builder); +} + Repairable.prototype.AddBuilder = function(builderEnt) { if (this.builders.has(builderEnt)) diff --git a/binaries/data/mods/public/simulation/components/UnitAI.js b/binaries/data/mods/public/simulation/components/UnitAI.js index 0d86828601..063ca4c8bb 100644 --- a/binaries/data/mods/public/simulation/components/UnitAI.js +++ b/binaries/data/mods/public/simulation/components/UnitAI.js @@ -2754,11 +2754,13 @@ UnitAI.prototype.UnitFsmSpec = { this.order.data.force = false; - this.repairTarget = this.order.data.target; // temporary, deleted in "leave". - // Check we can still reach and repair the target + // Needed to remove the entity from the builder list when leaving this state. + this.repairTarget = this.order.data.target; + + // Check we can still reach and repair the target. if (!this.CanRepair(this.repairTarget)) { - // Can't reach it, no longer owned by ally, or it doesn't exist any more + // Can't reach it, no longer owned by ally, or it doesn't exist any more. this.FinishOrder(); return true; } @@ -2768,8 +2770,8 @@ UnitAI.prototype.UnitFsmSpec = { this.SetNextState("APPROACHING"); return true; } - // Check if the target is still repairable - var cmpHealth = Engine.QueryInterface(this.repairTarget, IID_Health); + // Check if the target is still repairable. + let cmpHealth = Engine.QueryInterface(this.repairTarget, IID_Health); if (cmpHealth && cmpHealth.GetHitpoints() >= cmpHealth.GetMaxHitpoints()) { // The building was already finished/fully repaired before we arrived; @@ -2784,7 +2786,7 @@ UnitAI.prototype.UnitFsmSpec = { if (cmpBuilderList) cmpBuilderList.AddBuilder(this.entity); - this.FaceTowardsTarget(this.order.data.target); + this.FaceTowardsTarget(this.repairTarget); this.SelectAnimation("build"); this.StartTimer(1000, 1000); @@ -2801,21 +2803,21 @@ UnitAI.prototype.UnitFsmSpec = { }, "Timer": function(msg) { - // Check we can still reach and repair the target + // Check we can still reach and repair the target. if (!this.CanRepair(this.repairTarget)) { - // No longer owned by ally, or it doesn't exist any more + // No longer owned by ally, or it doesn't exist any more. this.FinishOrder(); return; } - this.FaceTowardsTarget(this.order.data.target); + this.FaceTowardsTarget(this.repairTarget); let cmpBuilder = Engine.QueryInterface(this.entity, IID_Builder); cmpBuilder.PerformBuilding(this.repairTarget); - // if the building is completed, the leave() function will be called - // by the ConstructionFinished message - // in that case, the repairTarget is deleted, and we can just return + // If the building is completed, the leave() function will be called + // by the ConstructionFinished message. + // In that case, the repairTarget is deleted, and we can just return. if (!this.repairTarget) return; if (!this.CheckTargetRange(this.repairTarget, IID_Builder)) @@ -4093,6 +4095,9 @@ UnitAI.prototype.OnGlobalEntityRenamed = function(msg) order.data.formationTarget = msg.newentity; } } + if (this.repairTarget && this.repairTarget == msg.entity) + this.repairTarget = msg.newentity; + if (changed) Engine.PostMessage(this.entity, MT_UnitAIOrderDataChanged, { "to": this.GetOrderData() }); }; diff --git a/binaries/data/mods/public/simulation/components/tests/test_Pack.js b/binaries/data/mods/public/simulation/components/tests/test_Pack.js index 4e60bd8b33..7c6291202f 100644 --- a/binaries/data/mods/public/simulation/components/tests/test_Pack.js +++ b/binaries/data/mods/public/simulation/components/tests/test_Pack.js @@ -4,12 +4,14 @@ Engine.LoadHelperScript("Transform.js"); Engine.LoadHelperScript("ValueModification.js"); Engine.LoadComponentScript("interfaces/ModifiersManager.js"); Engine.LoadComponentScript("interfaces/Capturable.js"); +Engine.LoadComponentScript("interfaces/Foundation.js"); Engine.LoadComponentScript("interfaces/GarrisonHolder.js"); Engine.LoadComponentScript("interfaces/Guard.js"); Engine.LoadComponentScript("interfaces/Health.js"); Engine.LoadComponentScript("interfaces/Pack.js"); Engine.LoadComponentScript("interfaces/Player.js"); Engine.LoadComponentScript("interfaces/Promotion.js"); +Engine.LoadComponentScript("interfaces/Repairable.js"); Engine.LoadComponentScript("interfaces/ResourceGatherer.js"); Engine.LoadComponentScript("interfaces/StatusEffectsReceiver.js"); Engine.LoadComponentScript("interfaces/Timer.js"); diff --git a/binaries/data/mods/public/simulation/helpers/Transform.js b/binaries/data/mods/public/simulation/helpers/Transform.js index 645cd31487..d93e77539e 100644 --- a/binaries/data/mods/public/simulation/helpers/Transform.js +++ b/binaries/data/mods/public/simulation/helpers/Transform.js @@ -53,6 +53,11 @@ function ChangeEntityTemplate(oldEnt, newTemplate) cmpNewHealth.SetHitpoints(cmpNewHealth.GetMaxHitpoints() * healthLevel); } + let cmpBuilderList = QueryBuilderListInterface(oldEnt); + let cmpNewBuilderList = QueryBuilderListInterface(newEnt); + if (cmpBuilderList && cmpNewBuilderList) + cmpNewBuilderList.AddBuilders(cmpBuilderList.GetBuilders()); + var cmpUnitAI = Engine.QueryInterface(oldEnt, IID_UnitAI); var cmpNewUnitAI = Engine.QueryInterface(newEnt, IID_UnitAI); if (cmpUnitAI && cmpNewUnitAI)