Index: binaries/data/mods/public/simulation/components/Foundation.js =================================================================== --- binaries/data/mods/public/simulation/components/Foundation.js +++ binaries/data/mods/public/simulation/components/Foundation.js @@ -75,6 +75,16 @@ 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; Index: binaries/data/mods/public/simulation/components/Repairable.js =================================================================== --- binaries/data/mods/public/simulation/components/Repairable.js +++ binaries/data/mods/public/simulation/components/Repairable.js @@ -33,6 +33,16 @@ 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; 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 @@ -2687,37 +2687,41 @@ this.order.data.force = false; - this.repairTarget = this.order.data.target; // temporary, deleted in "leave". - // Check we can still reach and repair the target - if (!this.CanRepair(this.repairTarget)) + let target = this.order.data.target; + + // Needed to remove the entity from the builder list when leaving this state. + this.repairTarget = target; + + // Check we can still reach and repair the target. + if (!this.CanRepair(target)) { - // 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; } - if (!this.CheckTargetRange(this.repairTarget, IID_Builder)) + if (!this.CheckTargetRange(target, IID_Builder)) { 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(target, IID_Health); if (cmpHealth && cmpHealth.GetHitpoints() >= cmpHealth.GetMaxHitpoints()) { // The building was already finished/fully repaired before we arrived; // let the ConstructionFinished handler handle this. - this.OnGlobalConstructionFinished({"entity": this.repairTarget, "newentity": this.repairTarget}); + this.OnGlobalConstructionFinished({"entity": target, "newentity": target}); return true; } this.StopMoving(); - let cmpBuilderList = QueryBuilderListInterface(this.repairTarget); + let cmpBuilderList = QueryBuilderListInterface(target); if (cmpBuilderList) cmpBuilderList.AddBuilder(this.entity); - this.FaceTowardsTarget(this.order.data.target); + this.FaceTowardsTarget(target); this.SelectAnimation("build"); this.StartTimer(1000, 1000); @@ -2734,24 +2738,29 @@ }, "Timer": function(msg) { - // Check we can still reach and repair the target - if (!this.CanRepair(this.repairTarget)) + let target = this.order.data.target; + + // Needed to remove the entity from the builder list when leaving this state. + this.repairTarget = target; + + // Check we can still reach and repair the target. + if (!this.CanRepair(target)) { - // 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(target); 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 + cmpBuilder.PerformBuilding(target); + // 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)) + if (!this.CheckTargetRange(target, IID_Builder)) this.SetNextState("APPROACHING"); }, }, Index: binaries/data/mods/public/simulation/components/tests/test_Pack.js =================================================================== --- binaries/data/mods/public/simulation/components/tests/test_Pack.js +++ binaries/data/mods/public/simulation/components/tests/test_Pack.js @@ -4,12 +4,14 @@ 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/Timer.js"); Engine.LoadComponentScript("interfaces/UnitAI.js"); 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 @@ -53,6 +53,12 @@ cmpNewHealth.SetHitpoints(cmpNewHealth.GetMaxHitpoints() * healthLevel); } + let cmpBuilderList = QueryBuilderListInterface(oldEnt); + let cmpNewBuilderList = QueryBuilderListInterface(newEnt); + if (cmpBuilderList && cmpNewBuilderList) + for (let builder of cmpBuilderList.GetBuilders()) + cmpNewBuilderList.AddBuilder(builder); + var cmpUnitAI = Engine.QueryInterface(oldEnt, IID_UnitAI); var cmpNewUnitAI = Engine.QueryInterface(newEnt, IID_UnitAI); if (cmpUnitAI && cmpNewUnitAI)