Index: binaries/data/mods/public/simulation/components/Heal.js =================================================================== --- binaries/data/mods/public/simulation/components/Heal.js +++ binaries/data/mods/public/simulation/components/Heal.js @@ -87,6 +87,38 @@ return this.template.HealableClasses._string || ""; }; +Heal.prototype.CanHeal = function(target) +{ + let cmpFormation = Engine.QueryInterface(target, IID_Formation); + if (cmpFormation) + return true; + + // Verify that the target is alive + // and that the target is not unhealable (or at max health). + let cmpHealth = Engine.QueryInterface(target, IID_Health); + if (!cmpHealth || cmpHealth.IsUnhealable()) + return false; + + // Verify that the target is owned by the same player as the entity or of an ally. + let cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership); + if (!cmpOwnership || !(IsOwnedByPlayer(cmpOwnership.GetOwner(), target) || IsOwnedByAllyOfPlayer(cmpOwnership.GetOwner(), target))) + return false; + + // Verify that the target has no unhealable class. + let cmpIdentity = Engine.QueryInterface(target, IID_Identity); + if (!cmpIdentity) + return false; + + if (MatchesClassList(cmpIdentity.GetClassesList(), this.GetUnhealableClasses())) + return false; + + // Verify that the target is a healable class. + if (MatchesClassList(cmpIdentity.GetClassesList(), this.GetHealableClasses())) + return true; + + return false; +}; + Heal.prototype.GetRangeOverlays = function() { if (!this.template.RangeOverlay) 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 @@ -5818,37 +5818,8 @@ return true; // Verify that we're able to respond to Heal commands - var cmpHeal = Engine.QueryInterface(this.entity, IID_Heal); - if (!cmpHeal) - return false; - - // Verify that the target is alive - if (!this.TargetIsAlive(target)) - return false; - - // Verify that the target is owned by the same player as the entity or of an ally - var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership); - if (!cmpOwnership || !(IsOwnedByPlayer(cmpOwnership.GetOwner(), target) || IsOwnedByAllyOfPlayer(cmpOwnership.GetOwner(), target))) - return false; - - // Verify that the target is not unhealable (or at max health) - var cmpHealth = Engine.QueryInterface(target, IID_Health); - if (!cmpHealth || cmpHealth.IsUnhealable()) - return false; - - // Verify that the target has no unhealable class - var cmpIdentity = Engine.QueryInterface(target, IID_Identity); - if (!cmpIdentity) - return false; - - if (MatchesClassList(cmpIdentity.GetClassesList(), cmpHeal.GetUnhealableClasses())) - return false; - - // Verify that the target is a healable class - if (MatchesClassList(cmpIdentity.GetClassesList(), cmpHeal.GetHealableClasses())) - return true; - - return false; + let cmpHeal = Engine.QueryInterface(this.entity, IID_Heal); + return cmpHeal && cmpHeal.CanHeal(target); }; UnitAI.prototype.CanReturnResource = function(target, checkCarriedResource) Index: binaries/data/mods/public/simulation/components/tests/test_Heal.js =================================================================== --- binaries/data/mods/public/simulation/components/tests/test_Heal.js +++ binaries/data/mods/public/simulation/components/tests/test_Heal.js @@ -1,4 +1,6 @@ Engine.LoadHelperScript("ValueModification.js"); +Engine.LoadHelperScript("Player.js"); +Engine.LoadComponentScript("interfaces/Formation.js"); Engine.LoadComponentScript("interfaces/Heal.js"); Engine.LoadComponentScript("interfaces/Health.js"); Engine.LoadComponentScript("interfaces/Loot.js"); @@ -6,7 +8,8 @@ Engine.LoadComponentScript("interfaces/UnitAI.js"); Engine.LoadComponentScript("Heal.js"); -const entity= 60; +const entity = 60; +const player = 1; let template = { "Range": 20, @@ -21,6 +24,18 @@ "HealableClasses": { "_string": "Support Infantry" }, }; +AddMock(entity, IID_Ownership, { + "GetOwner": () => player +}); + +AddMock(SYSTEM_ENTITY, IID_PlayerManager, { + "GetPlayerByID": () => player +}); + +AddMock(player, IID_Player, { + "GetPlayerID": () => player +}); + ApplyValueModificationsToEntity = function(value, stat, ent) { if (ent != entity) @@ -70,7 +85,8 @@ increased = true; TS_ASSERT_EQUALS(amount, 5 + 100); return { "old": 600, "new": 600 + 5 + 100 }; - } + }, + "IsUnhealable": () => false }); cmpHeal.PerformHeal(target); @@ -108,3 +124,39 @@ cmpHeal.OnValueModification({ "component": "Heal", "valueNames": ["Heal/Range"] }); TS_ASSERT(updated); + +// Test CanHeal. +let targets = [71, 72, 73, 74, 75]; +for (let target of targets) +{ + AddMock(target, IID_Ownership, { + "GetOwner": () => player + }); + + if (target == 71) + AddMock(target, IID_Identity, { + "GetClassesList": () => ["Infantry", "Hero"] + }); + else if (target == 72) + AddMock(target, IID_Identity, { + "GetClassesList": () => ["Hero"] + }); + else if (target == 73) + AddMock(target, IID_Identity, { + "GetClassesList": () => ["Infantry", "Cavalry"] + }); + else if (target == 74) + AddMock(target, IID_Identity, { + "GetClassesList": () => ["Cavalry"] + }); + else if (target == 75) + AddMock(target, IID_Identity, { + "GetClassesList": () => ["Infantry"] + }); + + AddMock(target, IID_Health, { + "IsUnhealable": () => target == 75 + }); + + TS_ASSERT_UNEVAL_EQUALS(cmpHeal.CanHeal(target), target == 71); +}