Changeset View
Standalone View
binaries/data/mods/public/simulation/components/tests/test_Attack.js
Engine.LoadHelperScript("DamageBonus.js"); | Engine.LoadHelperScript("DamageBonus.js"); | ||||
Engine.LoadHelperScript("DamageTypes.js"); | Engine.LoadHelperScript("DamageTypes.js"); | ||||
Engine.LoadHelperScript("Player.js"); | Engine.LoadHelperScript("Player.js"); | ||||
Engine.LoadHelperScript("ValueModification.js"); | Engine.LoadHelperScript("ValueModification.js"); | ||||
Engine.LoadComponentScript("interfaces/Attack.js"); | Engine.LoadComponentScript("interfaces/Attack.js"); | ||||
Engine.LoadComponentScript("interfaces/DamageReceiver.js"); | |||||
Engine.LoadComponentScript("interfaces/AuraManager.js"); | Engine.LoadComponentScript("interfaces/AuraManager.js"); | ||||
Engine.LoadComponentScript("interfaces/Auras.js"); | Engine.LoadComponentScript("interfaces/Auras.js"); | ||||
Engine.LoadComponentScript("interfaces/Capturable.js"); | Engine.LoadComponentScript("interfaces/Capturable.js"); | ||||
Engine.LoadComponentScript("interfaces/Formation.js"); | Engine.LoadComponentScript("interfaces/Formation.js"); | ||||
Engine.LoadComponentScript("interfaces/Health.js"); | Engine.LoadComponentScript("interfaces/Health.js"); | ||||
Engine.LoadComponentScript("interfaces/TechnologyManager.js"); | Engine.LoadComponentScript("interfaces/TechnologyManager.js"); | ||||
Engine.LoadComponentScript("Attack.js"); | Engine.LoadComponentScript("Attack.js"); | ||||
▲ Show 20 Lines • Show All 99 Lines • ▼ Show 20 Lines | function attackComponentTest(defenderClass, isEnemy, test_function) | ||||
let defender = ++entityID; | let defender = ++entityID; | ||||
AddMock(defender, IID_Identity, { | AddMock(defender, IID_Identity, { | ||||
"GetClassesList": () => [defenderClass], | "GetClassesList": () => [defenderClass], | ||||
"HasClass": className => className == defenderClass | "HasClass": className => className == defenderClass | ||||
}); | }); | ||||
AddMock(defender, IID_Ownership, { | AddMock(defender, IID_Ownership, { | ||||
"GetOwner": () => 1 | "GetOwner": () => 1 | ||||
Silier: defender has owner 1 and attacker too, so isEnemy is false | |||||
Done Inline ActionsYeah, I thought so as well, but the IsEnemy() is set in line 30 to be the value of isEnemy, which is set to true in line 219. If I read this correctly. Freagarach: Yeah, I thought so as well, but the `IsEnemy()` is set in line 30 to be the value of `isEnemy`… | |||||
}); | }); | ||||
AddMock(defender, IID_Position, { | AddMock(defender, IID_Position, { | ||||
"IsInWorld": () => true, | "IsInWorld": () => true, | ||||
"GetHeightOffset": () => 0 | "GetHeightOffset": () => 0 | ||||
}); | }); | ||||
AddMock(defender, IID_Health, { | AddMock(defender, IID_Health, { | ||||
"GetHitpoints": () => 100 | "GetHitpoints": () => 100 | ||||
}); | }); | ||||
AddMock(defender, IID_DamageReceiver, { | |||||
"GetArmourStrengths": () => ({ | |||||
"Hack": 0, | |||||
"Pierce": 0, | |||||
"Crush": 0 | |||||
}) | |||||
}); | |||||
test_function(attacker, cmpAttack, defender); | test_function(attacker, cmpAttack, defender); | ||||
} | } | ||||
// Validate template getter functions | // Validate template getter functions | ||||
attackComponentTest(undefined, true, (attacker, cmpAttack, defender) => { | attackComponentTest(undefined, true, (attacker, cmpAttack, defender) => { | ||||
TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetAttackTypes(), ["Melee", "Ranged", "Capture"]); | TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetAttackTypes(), ["Melee", "Ranged", "Capture"]); | ||||
TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetAttackTypes([]), ["Melee", "Ranged", "Capture"]); | TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetAttackTypes([]), ["Melee", "Ranged", "Capture"]); | ||||
▲ Show 20 Lines • Show All 59 Lines • ▼ Show 20 Lines | attackComponentTest(className, true, (attacker, cmpAttack, defender) => { | ||||
TS_ASSERT_UNEVAL_EQUALS(getAttackBonus(attacker, "Slaughter", defender), 1); | TS_ASSERT_UNEVAL_EQUALS(getAttackBonus(attacker, "Slaughter", defender), 1); | ||||
}); | }); | ||||
// CanAttack rejects elephant attack due to RestrictedClasses | // CanAttack rejects elephant attack due to RestrictedClasses | ||||
attackComponentTest("Elephant", true, (attacker, cmpAttack, defender) => { | attackComponentTest("Elephant", true, (attacker, cmpAttack, defender) => { | ||||
TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender), false); | TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender), false); | ||||
}); | }); | ||||
function testGetBestAttackAgainst(defenderClass, bestAttack, isBuilding = false) | function testGetBestAttackAgainst(defenderClass, bestAttack, isBuilding = false, hasSomeImmunity = false) | ||||
{ | { | ||||
attackComponentTest(defenderClass, true, (attacker, cmpAttack, defender) => { | attackComponentTest(defenderClass, true, (attacker, cmpAttack, defender) => { | ||||
if (isBuilding) | if (isBuilding) | ||||
AddMock(defender, IID_Capturable, { | AddMock(defender, IID_Capturable, { | ||||
"CanCapture": playerID => { | "CanCapture": playerID => { | ||||
TS_ASSERT_EQUALS(playerID, 1); | TS_ASSERT_EQUALS(playerID, 1); | ||||
return true; | return true; | ||||
Show All 13 Lines | attackComponentTest(defenderClass, true, (attacker, cmpAttack, defender) => { | ||||
let allowCapturing = [true]; | let allowCapturing = [true]; | ||||
if (!isBuilding) | if (!isBuilding) | ||||
allowCapturing.push(false); | allowCapturing.push(false); | ||||
for (let ac of allowCapturing) | for (let ac of allowCapturing) | ||||
TS_ASSERT_EQUALS(cmpAttack.GetBestAttackAgainst(defender, ac), bestAttack); | TS_ASSERT_EQUALS(cmpAttack.GetBestAttackAgainst(defender, ac), bestAttack); | ||||
}); | }); | ||||
// CanAttack rejects "Ranged" due to the fact that "Ranged" only has "Pierce" | |||||
// damage, to which the target is immune. | |||||
attackComponentTest(defenderClass, true, (attacker, cmpAttack, defender) => { | |||||
if (hasSomeImmunity) | |||||
AddMock(defender, IID_DamageReceiver, { | |||||
"GetArmourStrengths": () => ({ | |||||
"Hack": 0, | |||||
"Pierce": "Infinity", | |||||
"Crush": 0 | |||||
}) | |||||
}); | |||||
TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender), true); | |||||
TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, ["Ranged"]), !hasSomeImmunity); | |||||
if (hasSomeImmunity) | |||||
AddMock(defender, IID_DamageReceiver, { | |||||
"GetArmourStrengths": () => ({ | |||||
"Hack": "Infinity", | |||||
"Pierce": 0, | |||||
"Crush": "Infinity" | |||||
}) | |||||
}); | |||||
TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender), true); | |||||
TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, ["Ranged"]), true); | |||||
}); | |||||
attackComponentTest(defenderClass, false, (attacker, cmpAttack, defender) => { | attackComponentTest(defenderClass, false, (attacker, cmpAttack, defender) => { | ||||
Done Inline ActionsThis line tries to test to get best attack against not enemy entities, what currently using CanAttack as filter is not true. Do not execute this block unless expected attack is "Capture" or "Slaughter". Silier: This line tries to test to get best attack against not enemy entities, what currently using… | |||||
Done Inline ActionsOk, Ignore this one inline here I thought I removed it. Silier: Ok, Ignore this one inline here I thought I removed it. | |||||
if (isBuilding) | if (isBuilding) | ||||
AddMock(defender, IID_Capturable, { | AddMock(defender, IID_Capturable, { | ||||
"CanCapture": playerID => { | "CanCapture": playerID => { | ||||
TS_ASSERT_EQUALS(playerID, 1); | TS_ASSERT_EQUALS(playerID, 1); | ||||
return true; | return true; | ||||
} | } | ||||
}); | }); | ||||
Show All 11 Lines | attackComponentTest(defenderClass, false, (attacker, cmpAttack, defender) => { | ||||
let allowCapturing = [true]; | let allowCapturing = [true]; | ||||
if (!isBuilding) | if (!isBuilding) | ||||
allowCapturing.push(false); | allowCapturing.push(false); | ||||
let attack; | let attack; | ||||
if (defenderClass == "Domestic") | if (defenderClass == "Domestic") | ||||
attack = "Slaughter"; | attack = "Slaughter"; | ||||
else if (defenderClass == "Structure") | else if (defenderClass == "Structure") | ||||
attack = "Capture"; | attack = "Capture"; | ||||
Done Inline Actionsalso this lines are useless Silier: also this lines are useless | |||||
for (let ac of allowCapturing) | for (let ac of allowCapturing) | ||||
TS_ASSERT_EQUALS(cmpAttack.GetBestAttackAgainst(defender, ac), bestAttack); | TS_ASSERT_EQUALS(cmpAttack.GetBestAttackAgainst(defender, ac), attack); | ||||
Done Inline ActionsThis line tries to test to get best attack against not enemy entities, what currently using CanAttack as filter is not true. Do not execute this block unless expected attack is "Capture" or "Slaughter". Silier: This line tries to test to get best attack against not enemy entities, what currently using… | |||||
Done Inline ActionsOh, now I see! This is part of the block started in line 247! Thanks for pointing it out :) Freagarach: Oh, now I see! This is part of the block started in line 247! Thanks for pointing it out :) | |||||
}); | }); | ||||
} | } | ||||
testGetBestAttackAgainst("FemaleCitizen", "Melee"); | testGetBestAttackAgainst("FemaleCitizen", "Melee"); | ||||
testGetBestAttackAgainst("Archer", "Ranged"); | testGetBestAttackAgainst("Archer", "Ranged"); | ||||
testGetBestAttackAgainst("Domestic", "Slaughter"); | testGetBestAttackAgainst("Domestic", "Slaughter"); | ||||
testGetBestAttackAgainst("Structure", "Capture", true); | testGetBestAttackAgainst("Structure", "Capture", true); | ||||
testGetBestAttackAgainst("Hoplite", "Ranged", false, true); | |||||
function testPredictTimeToTarget(selfPosition, horizSpeed, targetPosition, targetVelocity) | function testPredictTimeToTarget(selfPosition, horizSpeed, targetPosition, targetVelocity) | ||||
{ | { | ||||
ResetState(); | ResetState(); | ||||
let cmpAttack = ConstructComponent(1, "Attack", {}); | let cmpAttack = ConstructComponent(1, "Attack", {}); | ||||
let timeToTarget = cmpAttack.PredictTimeToTarget(selfPosition, horizSpeed, targetPosition, targetVelocity); | let timeToTarget = cmpAttack.PredictTimeToTarget(selfPosition, horizSpeed, targetPosition, targetVelocity); | ||||
if (timeToTarget === false) | if (timeToTarget === false) | ||||
return; | return; | ||||
Show All 26 Lines |
defender has owner 1 and attacker too, so isEnemy is false