Changeset View
Changeset View
Standalone View
Standalone View
binaries/data/mods/public/simulation/components/tests/test_Attack.js
Engine.LoadHelperScript("Attacking.js"); | Engine.LoadHelperScript("Attacking.js"); | ||||
Engine.LoadHelperScript("Player.js"); | Engine.LoadHelperScript("Player.js"); | ||||
Engine.LoadHelperScript("ValueModification.js"); | Engine.LoadHelperScript("ValueModification.js"); | ||||
Engine.LoadComponentScript("interfaces/Auras.js"); | Engine.LoadComponentScript("interfaces/Auras.js"); | ||||
Engine.LoadComponentScript("interfaces/Capturable.js"); | Engine.LoadComponentScript("interfaces/Capturable.js"); | ||||
Engine.LoadComponentScript("interfaces/ModifiersManager.js"); | Engine.LoadComponentScript("interfaces/ModifiersManager.js"); | ||||
Engine.LoadComponentScript("interfaces/Formation.js"); | Engine.LoadComponentScript("interfaces/Formation.js"); | ||||
Engine.LoadComponentScript("interfaces/Health.js"); | Engine.LoadComponentScript("interfaces/Health.js"); | ||||
Engine.LoadComponentScript("interfaces/StatusEffectsReceiver.js"); | |||||
Engine.LoadComponentScript("interfaces/TechnologyManager.js"); | Engine.LoadComponentScript("interfaces/TechnologyManager.js"); | ||||
Engine.LoadComponentScript("Attack.js"); | Engine.LoadComponentScript("Attack.js"); | ||||
let entityID = 903; | let entityID = 903; | ||||
function attackComponentTest(defenderClass, isEnemy, test_function) | function attackComponentTest(defenderClass, isEnemy, test_function) | ||||
{ | { | ||||
let playerEnt1 = 5; | let playerEnt1 = 5; | ||||
AddMock(SYSTEM_ENTITY, IID_PlayerManager, { | AddMock(SYSTEM_ENTITY, IID_PlayerManager, { | ||||
"GetPlayerByID": () => playerEnt1 | "GetPlayerByID": () => playerEnt1 | ||||
}); | }); | ||||
AddMock(SYSTEM_ENTITY, IID_ObstructionManager, { | |||||
"IsInTargetRange": () => true, | |||||
"DistanceToTarget": (ent, target) => 10 | |||||
}); | |||||
AddMock(playerEnt1, IID_Player, { | AddMock(playerEnt1, IID_Player, { | ||||
"GetPlayerID": () => 1, | "GetPlayerID": () => 1 | ||||
"IsEnemy": () => isEnemy | |||||
}); | }); | ||||
let attacker = entityID; | let attacker = entityID; | ||||
AddMock(attacker, IID_Position, { | AddMock(attacker, IID_Position, { | ||||
"IsInWorld": () => true, | "IsInWorld": () => true, | ||||
"GetTurretParent": () => INVALID_ENTITY, | |||||
"GetHeightOffset": () => 5, | "GetHeightOffset": () => 5, | ||||
"GetPosition2D": () => new Vector2D(1, 2) | "GetPosition2D": () => new Vector2D(1, 2) | ||||
}); | }); | ||||
AddMock(attacker, IID_Ownership, { | AddMock(attacker, IID_Ownership, { | ||||
"GetOwner": () => 1 | "GetOwner": () => 1 | ||||
}); | }); | ||||
let cmpAttack = ConstructComponent(attacker, "Attack", { | let cmpAttack = ConstructComponent(attacker, "Attack", { | ||||
"Melee": { | "Spear": { | ||||
"Damage": { | "Damage": { | ||||
"Hack": 11, | "Hack": 11, | ||||
"Pierce": 5, | "Pierce": 5, | ||||
"Crush": 0 | "Crush": 0 | ||||
}, | }, | ||||
"MinRange": 3, | "MinRange": 3, | ||||
"MaxRange": 5, | "MaxRange": 5, | ||||
"PrepareTime": 0, | |||||
"RepeatTime": 1000, | |||||
"PreferredClasses": { | "PreferredClasses": { | ||||
"_string": "FemaleCitizen" | "_string": "FemaleCitizen" | ||||
}, | }, | ||||
"RestrictedClasses": { | "RestrictedClasses": { | ||||
"_string": "Elephant Archer" | "_string": "Elephant Archer" | ||||
}, | }, | ||||
"Bonuses": | "Bonuses": | ||||
{ | { | ||||
"BonusCav": { | "BonusCav": { | ||||
"Classes": "Cavalry", | "Classes": "Cavalry", | ||||
"Multiplier": 2 | "Multiplier": 2 | ||||
} | } | ||||
} | } | ||||
}, | }, | ||||
"Ranged": { | "Bow": { | ||||
"Damage": { | "Damage": { | ||||
"Hack": 0, | "Hack": 0, | ||||
"Pierce": 10, | "Pierce": 10, | ||||
"Crush": 0 | "Crush": 0 | ||||
}, | }, | ||||
"MinRange": 10, | "MinRange": 10, | ||||
"MaxRange": 80, | "MaxRange": 80, | ||||
"PrepareTime": 300, | "PrepareTime": 300, | ||||
Show All 25 Lines | "Bow": { | ||||
"Multiplier": 3 | "Multiplier": 3 | ||||
} | } | ||||
} | } | ||||
} | } | ||||
}, | }, | ||||
"Capture": { | "Capture": { | ||||
"Capture": 8, | "Capture": 8, | ||||
"MaxRange": 10, | "MaxRange": 10, | ||||
"PrepareTime": 0, | |||||
"RepeatTime": 1000 | |||||
}, | |||||
"Slaughter": { | |||||
"Damage": { | |||||
"Hack": 100, | |||||
"Pierce": 0, | |||||
"Crush": 0 | |||||
}, | |||||
"MaxRange": 5, | |||||
"PrepareTime": 0, | |||||
"RepeatTime": 1000, | |||||
"RestrictedClasses": { | |||||
"_string": "!Domestic" | |||||
} | |||||
}, | }, | ||||
"Slaughter": {}, | |||||
"StatusEffect": { | "StatusEffect": { | ||||
"ApplyStatus": { | "ApplyStatus": { | ||||
"StatusInternalName": { | "StatusInternalName": { | ||||
"StatusName": "StatusShownName", | "StatusName": "StatusShownName", | ||||
"ApplierTooltip": "ApplierTooltip", | "ApplierTooltip": "ApplierTooltip", | ||||
"ReceiverTooltip": "ReceiverTooltip", | "ReceiverTooltip": "ReceiverTooltip", | ||||
"Duration": 5000, | "Duration": 5000, | ||||
"Stackability": "Stacks", | "Stackability": "Stacks", | ||||
"Modifiers": { | "Modifiers": { | ||||
"SE": { | "SE": { | ||||
"Paths": { | "Paths": { | ||||
"_string": "Health/Max" | "_string": "Health/Max" | ||||
}, | }, | ||||
"Affects": { | "Affects": { | ||||
"_string": "Unit" | "_string": "Unit" | ||||
}, | }, | ||||
"Add": 10 | "Add": 10 | ||||
} | } | ||||
} | } | ||||
} | } | ||||
}, | }, | ||||
"MinRange": "10", | "MinRange": "10", | ||||
"MaxRange": "80" | "MaxRange": "80", | ||||
"PrepareTime": 0, | |||||
"RepeatTime": 1000, | |||||
"RestrictedClasses": { | |||||
"_string": "Elephant" | |||||
} | |||||
} | } | ||||
}); | }); | ||||
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, | ||||
"GetCiv": () => "civ" | "GetCiv": () => "civ" | ||||
}); | }); | ||||
AddMock(defender, IID_Ownership, { | AddMock(defender, IID_Ownership, { | ||||
"GetOwner": () => 1 | "GetOwner": () => 1 | ||||
}); | }); | ||||
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, | ||||
"GetRelativeDamage": (attackEffects, effectType) => { | |||||
if (!isEnemy && defenderClass != "Domestic") | |||||
return 0; | |||||
let strength = 0; | |||||
if (attackEffects[effectType]) | |||||
for (let damageType in attackEffects[effectType]) | |||||
strength += attackEffects[effectType][damageType]; | |||||
return strength / 100; | |||||
} | |||||
}); | |||||
AddMock(defender, IID_StatusEffectsReceiver, { | |||||
"GetRelativeStatusEffect": () => 0.0000000001 | |||||
}); | }); | ||||
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(), ["Spear", "Bow", "Capture", "Slaughter", "StatusEffect"]); | |||||
TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetAttackTypes(), ["Melee", "Ranged", "Capture"]); | TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetAttackTypes([]), ["Spear", "Bow", "Capture", "Slaughter", "StatusEffect"]); | ||||
TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetAttackTypes([]), ["Melee", "Ranged", "Capture"]); | TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetAttackTypes(["Spear", "Bow", "Capture"]), ["Spear", "Bow", "Capture"]); | ||||
TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetAttackTypes(["Melee", "Ranged", "Capture"]), ["Melee", "Ranged", "Capture"]); | TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetAttackTypes(["Spear", "Bow"]), ["Spear", "Bow"]); | ||||
TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetAttackTypes(["Melee", "Ranged"]), ["Melee", "Ranged"]); | |||||
TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetAttackTypes(["Capture"]), ["Capture"]); | TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetAttackTypes(["Capture"]), ["Capture"]); | ||||
TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetAttackTypes(["Melee", "!Melee"]), []); | TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetAttackTypes(["Spear", "!Spear"]), []); | ||||
TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetAttackTypes(["!Melee"]), ["Ranged", "Capture"]); | TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetAttackTypes(["!Spear"]), ["Bow", "Capture", "Slaughter", "StatusEffect"]); | ||||
TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetAttackTypes(["!Melee", "!Ranged"]), ["Capture"]); | TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetAttackTypes(["!Spear", "!Bow"]), ["Capture", "Slaughter", "StatusEffect"]); | ||||
TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetAttackTypes(["Capture", "!Ranged"]), ["Capture"]); | TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetAttackTypes(["Capture", "!Bow"]), ["Capture"]); | ||||
TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetAttackTypes(["Capture", "Melee", "!Ranged"]), ["Melee", "Capture"]); | TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetAttackTypes(["Capture", "Spear", "!Bow"]), ["Spear", "Capture"]); | ||||
TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetPreferredClasses("Melee"), ["FemaleCitizen"]); | TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetPreferredClasses("Spear"), ["FemaleCitizen"]); | ||||
TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetRestrictedClasses("Melee"), ["Elephant", "Archer"]); | TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetRestrictedClasses("Spear"), ["Elephant", "Archer"]); | ||||
TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetFullAttackRange(), { "min": 0, "max": 80 }); | TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetFullAttackRange(), { "min": 0, "max": 80 }); | ||||
TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetAttackEffectsData("Capture"), { "Capture": 8 }); | TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetAttackEffectsData("Capture"), { "Capture": 8 }); | ||||
TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetAttackEffectsData("Ranged"), { | TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetAttackEffectsData("Bow"), { | ||||
"Damage": { | "Damage": { | ||||
"Hack": 0, | "Hack": 0, | ||||
"Pierce": 10, | "Pierce": 10, | ||||
"Crush": 0 | "Crush": 0 | ||||
} | } | ||||
}); | }); | ||||
TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetAttackEffectsData("Ranged", true), { | TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetAttackEffectsData("Bow", true), { | ||||
"Damage": { | "Damage": { | ||||
"Hack": 0.0, | "Hack": 0.0, | ||||
"Pierce": 15.0, | "Pierce": 15.0, | ||||
"Crush": 35.0 | "Crush": 35.0 | ||||
}, | }, | ||||
"Bonuses": { | "Bonuses": { | ||||
"BonusCav": { | "BonusCav": { | ||||
"Classes": "Cavalry", | "Classes": "Cavalry", | ||||
Show All 18 Lines | "ApplyStatus": { | ||||
}, | }, | ||||
"Add": 10 | "Add": 10 | ||||
} | } | ||||
} | } | ||||
} | } | ||||
} | } | ||||
}); | }); | ||||
TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetTimers("Ranged"), { | TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetTimers("Bow"), { | ||||
"prepare": 300, | "prepare": 300, | ||||
"repeat": 500 | "repeat": 500 | ||||
}); | }); | ||||
TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetRepeatTime("Bow"), 500); | |||||
TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetRepeatTime("Ranged"), 500); | |||||
TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetTimers("Capture"), { | TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetTimers("Capture"), { | ||||
"prepare": 0, | "prepare": 0, | ||||
"repeat": 1000 | "repeat": 1000 | ||||
}); | }); | ||||
TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetRepeatTime("Capture"), 1000); | TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetRepeatTime("Capture"), 1000); | ||||
TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetSplashData("Ranged"), { | TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetTimers("StatusEffect"), { | ||||
"prepare": 0, | |||||
"repeat": 1000 | |||||
}); | |||||
TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetRepeatTime("StatusEffect"), 1000); | |||||
TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetSplashData("Bow"), { | |||||
"attackData": { | "attackData": { | ||||
"Damage": { | "Damage": { | ||||
"Hack": 0, | "Hack": 0, | ||||
"Pierce": 15, | "Pierce": 15, | ||||
"Crush": 35, | "Crush": 35, | ||||
}, | }, | ||||
"Bonuses": { | "Bonuses": { | ||||
"BonusCav": { | "BonusCav": { | ||||
"Classes": "Cavalry", | "Classes": "Cavalry", | ||||
"Multiplier": 3 | "Multiplier": 3 | ||||
} | } | ||||
} | } | ||||
}, | }, | ||||
"friendlyFire": false, | "friendlyFire": false, | ||||
"radius": 10, | "radius": 10, | ||||
"shape": "Circular" | "shape": "Circular" | ||||
}); | }); | ||||
}); | }); | ||||
for (let className of ["Infantry", "Cavalry"]) | for (let className of ["Infantry", "Cavalry"]) | ||||
attackComponentTest(className, true, (attacker, cmpAttack, defender) => { | attackComponentTest(className, true, (attacker, cmpAttack, defender) => { | ||||
TS_ASSERT_EQUALS(cmpAttack.GetAttackEffectsData("Melee").Bonuses.BonusCav.Multiplier, 2); | TS_ASSERT_EQUALS(cmpAttack.GetAttackEffectsData("Spear").Bonuses.BonusCav.Multiplier, 2); | ||||
TS_ASSERT_EQUALS(cmpAttack.GetAttackEffectsData("Capture").Bonuses || null, null); | TS_ASSERT_EQUALS(cmpAttack.GetAttackEffectsData("Capture").Bonuses || null, null); | ||||
let getAttackBonus = (s, t, e, splash) => Attacking.GetAttackBonus(s, e, t, cmpAttack.GetAttackEffectsData(t, splash).Bonuses || null); | let getAttackBonus = (s, t, e, splash) => Attacking.GetAttackBonus(s, e, t, cmpAttack.GetAttackEffectsData(t, splash).Bonuses || null); | ||||
TS_ASSERT_UNEVAL_EQUALS(getAttackBonus(attacker, "Melee", defender), className == "Cavalry" ? 2 : 1); | TS_ASSERT_UNEVAL_EQUALS(getAttackBonus(attacker, "Spear", defender), className == "Cavalry" ? 2 : 1); | ||||
TS_ASSERT_UNEVAL_EQUALS(getAttackBonus(attacker, "Ranged", defender), 1); | TS_ASSERT_UNEVAL_EQUALS(getAttackBonus(attacker, "Bow", defender), 1); | ||||
TS_ASSERT_UNEVAL_EQUALS(getAttackBonus(attacker, "Ranged", defender, true), className == "Cavalry" ? 3 : 1); | TS_ASSERT_UNEVAL_EQUALS(getAttackBonus(attacker, "Bow", defender, true), className == "Cavalry" ? 3 : 1); | ||||
TS_ASSERT_UNEVAL_EQUALS(getAttackBonus(attacker, "Capture", defender), 1); | TS_ASSERT_UNEVAL_EQUALS(getAttackBonus(attacker, "Capture", defender), 1); | ||||
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, bestAllyAttack, isBuilding = false) | function testGetBestAttackAgainst(defenderClass, bestAttack, isBuilding = 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; | ||||
} | }, | ||||
"GetRelativeCapture": (attackEffects, effectType) => attackEffects[effectType] / 10 | |||||
}); | }); | ||||
TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender), true); | TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender), true); | ||||
TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, []), true); | TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, false), true); | ||||
TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, ["Ranged"]), true); | TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, false, {}), true); | ||||
TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, ["!Melee"]), true); | TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, false, {}, []), true); | ||||
TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, ["Capture"]), isBuilding); | |||||
TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, ["Melee", "Capture"]), defenderClass != "Archer"); | TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, false, {}, ["Bow"]), true); | ||||
TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, ["Ranged", "Capture"]), true); | TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, false, {}, ["!Spear"]), true); | ||||
TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, ["!Ranged", "!Melee"]), isBuilding || defenderClass == "Domestic"); | TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, false, {}, ["Capture"]), isBuilding); | ||||
TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, ["Melee", "!Melee"]), false); | TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, false, { "Damage": true, "ApplyStatus": true }), isBuilding); | ||||
TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, false, { "Damage": true, "ApplyStatus": true }, ["!Capture"]), false); | |||||
let allowCapturing = [true]; | TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, false, { "Damage": true, "ApplyStatus": true }, ["Bow"]), false); | ||||
if (!isBuilding) | TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, false, { "Damage": true, "ApplyStatus": true }, ["Capture"]), isBuilding); | ||||
allowCapturing.push(false); | |||||
TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, false, {}, ["Slaughter"]), defenderClass == "Domestic"); | |||||
TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, false, {}, ["!Slaughter"]), true); | |||||
TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, false, {}, ["Spear", "Capture"]), defenderClass != "Archer"); | |||||
TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, false, {}, ["Bow", "Capture"]), true); | |||||
TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, false, {}, ["!Bow", "!Spear", "!StatusEffect"]), isBuilding || defenderClass == "Domestic"); | |||||
TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, false, {}, ["Spear", "!Spear"]), false); | |||||
TS_ASSERT_EQUALS(cmpAttack.GetBestAttackAgainst(defender), bestAttack); | |||||
TS_ASSERT_EQUALS(cmpAttack.GetBestAttackAgainst(defender, false), bestAttack); | |||||
TS_ASSERT_EQUALS(cmpAttack.GetBestAttackAgainst(defender, false, {}), bestAttack); | |||||
TS_ASSERT_EQUALS(cmpAttack.GetBestAttackAgainst(defender, false, {}, []), bestAttack); | |||||
TS_ASSERT_EQUALS(cmpAttack.GetBestAttackAgainst(defender, false, {}, ["Slaughter"]), bestAttack); | |||||
TS_ASSERT_EQUALS(cmpAttack.GetBestAttackAgainst(defender, false, {}, ["!Slaughter"]), bestAttack == "Slaughter" ? "Bow" : bestAttack); | |||||
TS_ASSERT_EQUALS(cmpAttack.GetBestAttackAgainst(defender, false, {}, ["Bow"]), "Bow"); | |||||
TS_ASSERT_EQUALS(cmpAttack.GetBestAttackAgainst(defender, false, {}, ["!Spear"]), bestAttack); | |||||
TS_ASSERT_EQUALS(cmpAttack.GetBestAttackAgainst(defender, false, {}, ["Capture"]), bestAttack); | |||||
TS_ASSERT_EQUALS(cmpAttack.GetBestAttackAgainst(defender, false, { "Capture": true }), bestAttack == "Capture" ? "Bow" : bestAttack); | |||||
TS_ASSERT_EQUALS(cmpAttack.GetBestAttackAgainst(defender, false, { "Capture": true }, ["Bow"]), "Bow"); | |||||
TS_ASSERT_EQUALS(cmpAttack.GetBestAttackAgainst(defender, false, { "Capture": true }, ["!Capture"]), bestAttack == "Capture" ? "Bow" : bestAttack); | |||||
TS_ASSERT_EQUALS(cmpAttack.GetBestAttackAgainst(defender, false, { "Capture": true }, ["Capture"]), bestAttack == "Capture" ? "Bow" : bestAttack); | |||||
TS_ASSERT_EQUALS(cmpAttack.GetBestAttackAgainst(defender, false, {}, ["Spear", "Capture"]), isBuilding ? "Capture" : defenderClass == "Archer" ? "Bow" : "Spear"); | |||||
TS_ASSERT_EQUALS(cmpAttack.GetBestAttackAgainst(defender, false, {}, ["Bow", "Capture"]), isBuilding ? "Capture" : "Bow"); | |||||
TS_ASSERT_EQUALS(cmpAttack.GetBestAttackAgainst(defender, false, {}, ["!Bow", "!Spear", "!StatusEffect"]), isBuilding ? "Capture" : defenderClass == "Domestic" ? "Slaughter" : bestAttack); | |||||
TS_ASSERT_EQUALS(cmpAttack.GetBestAttackAgainst(defender, false, {}, ["Spear", "!Spear"]), bestAttack); | |||||
for (let ac of allowCapturing) | |||||
TS_ASSERT_EQUALS(cmpAttack.GetBestAttackAgainst(defender, ac), bestAttack); | |||||
}); | }); | ||||
attackComponentTest(defenderClass, false, (attacker, cmpAttack, defender) => { | attackComponentTest(defenderClass, false, (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; | ||||
} | }, | ||||
"GetRelativeCapture": (attackEffects, effectType) => attackEffects[effectType] / 10 | |||||
}); | }); | ||||
TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender), isBuilding || defenderClass == "Domestic"); | TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender), true); | ||||
TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, []), isBuilding || defenderClass == "Domestic"); | TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, false), true); | ||||
TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, ["Ranged"]), false); | TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, false, {}), true); | ||||
TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, ["!Melee"]), isBuilding || defenderClass == "Domestic"); | TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, false, {}, []), true); | ||||
TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, ["Capture"]), isBuilding); | |||||
TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, ["Melee", "Capture"]), isBuilding); | TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, false, {}, ["!StatusEffect"]), isBuilding || defenderClass == "Domestic"); | ||||
TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, ["Ranged", "Capture"]), isBuilding); | TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, false, {}, ["!StatusEffect"]), isBuilding || defenderClass == "Domestic"); | ||||
TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, ["!Ranged", "!Melee"]), isBuilding || defenderClass == "Domestic"); | TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, false, {}, ["Bow", "!StatusEffect"]), defenderClass == "Domestic"); | ||||
TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, ["Melee", "!Melee"]), false); | TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, false, {}, ["!Spear", "!StatusEffect"]), isBuilding || defenderClass == "Domestic"); | ||||
TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, false, {}, ["Capture", "!StatusEffect"]), isBuilding); | |||||
let allowCapturing = [true]; | TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, false, {}, ["Spear", "Capture", "!StatusEffect"]), isBuilding || defenderClass == "Domestic"); | ||||
if (!isBuilding) | TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, false, {}, ["Bow", "Capture", "!StatusEffect"]), isBuilding || defenderClass == "Domestic"); | ||||
allowCapturing.push(false); | TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, false, {}, ["Slaughter", "!StatusEffect"]), defenderClass == "Domestic"); | ||||
TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, false, {}, ["!Bow", "!Spear", "!StatusEffect"]), isBuilding || defenderClass == "Domestic"); | |||||
for (let ac of allowCapturing) | TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, false, {}, ["Spear", "!Spear"]), false); | ||||
TS_ASSERT_EQUALS(cmpAttack.GetBestAttackAgainst(defender, ac), bestAllyAttack); | |||||
TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, false, { "Capture": true }, ["!StatusEffect"]), defenderClass == "Domestic"); | |||||
TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, false, { "Damage": true, "ApplyStatus": true }), isBuilding); | |||||
TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, false, { "Damage": true, "ApplyStatus": true }, ["!Capture"]), false); | |||||
TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, false, { "Damage": true, "ApplyStatus": true }, ["Bow"]), false); | |||||
TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, false, { "Damage": true, "ApplyStatus": true }, ["Capture"]), isBuilding); | |||||
TS_ASSERT_EQUALS(cmpAttack.GetBestAttackAgainst(defender), isBuilding ? "Capture" : defenderClass == "Domestic" ? "Slaughter" : "StatusEffect"); | |||||
TS_ASSERT_EQUALS(cmpAttack.GetBestAttackAgainst(defender, false), isBuilding ? "Capture" : defenderClass == "Domestic" ? "Slaughter" : "StatusEffect"); | |||||
TS_ASSERT_EQUALS(cmpAttack.GetBestAttackAgainst(defender, false, {}), isBuilding ? "Capture" : defenderClass == "Domestic" ? "Slaughter" : "StatusEffect"); | |||||
TS_ASSERT_EQUALS(cmpAttack.GetBestAttackAgainst(defender, false, {}, []), isBuilding ? "Capture" : defenderClass == "Domestic" ? "Slaughter" : "StatusEffect"); | |||||
TS_ASSERT_EQUALS(cmpAttack.GetBestAttackAgainst(defender, false, {}, ["!StatusEffect"]), isBuilding ? "Capture" : defenderClass == "Domestic" ? "Slaughter" : "StatusEffect"); | |||||
TS_ASSERT_EQUALS(cmpAttack.GetBestAttackAgainst(defender, false, {}, ["Slaughter"]), isBuilding ? "Capture" : defenderClass == "Domestic" ? "Slaughter" : "StatusEffect"); | |||||
TS_ASSERT_EQUALS(cmpAttack.GetBestAttackAgainst(defender, false, {}, ["!Slaughter"]), isBuilding ? "Capture" : defenderClass == "Domestic" ? "Bow" : "StatusEffect"); | |||||
TS_ASSERT_EQUALS(cmpAttack.GetBestAttackAgainst(defender, false, {}, ["Bow"]), isBuilding ? "Capture" : defenderClass == "Domestic" ? "Bow" : "StatusEffect"); | |||||
TS_ASSERT_EQUALS(cmpAttack.GetBestAttackAgainst(defender, false, {}, ["Spear"]), isBuilding ? "Capture" : defenderClass == "Domestic" ? "Spear" : "StatusEffect"); | |||||
TS_ASSERT_EQUALS(cmpAttack.GetBestAttackAgainst(defender, false, {}, ["!Spear"]), isBuilding ? "Capture" : defenderClass == "Domestic" ? "Slaughter" : "StatusEffect"); | |||||
TS_ASSERT_EQUALS(cmpAttack.GetBestAttackAgainst(defender, false, {}, ["Capture"]), isBuilding ? "Capture" : defenderClass == "Domestic" ? "Slaughter" : "StatusEffect"); | |||||
// When we have a domestic animal, we will end up doing the first in the array, since we ignore Damage. | |||||
TS_ASSERT_EQUALS(cmpAttack.GetBestAttackAgainst(defender, false, { "Damage": true, "ApplyStatus": true }), isBuilding ? "Capture" : defenderClass == "Domestic" ? "Spear" : "StatusEffect"); | |||||
TS_ASSERT_EQUALS(cmpAttack.GetBestAttackAgainst(defender, false, { "Damage": true, "ApplyStatus": true }, ["Bow"]), isBuilding ? "Capture" : defenderClass == "Domestic" ? "Spear" : "StatusEffect"); | |||||
TS_ASSERT_EQUALS(cmpAttack.GetBestAttackAgainst(defender, false, { "Damage": true, "ApplyStatus": true }, ["!Capture"]), isBuilding ? "Capture" : defenderClass == "Domestic" ? "Spear" : "StatusEffect"); | |||||
TS_ASSERT_EQUALS(cmpAttack.GetBestAttackAgainst(defender, false, { "Damage": true, "ApplyStatus": true }, ["Capture"]), isBuilding ? "Capture" : defenderClass == "Domestic" ? "Spear" : "StatusEffect"); | |||||
TS_ASSERT_EQUALS(cmpAttack.GetBestAttackAgainst(defender, false, {}, ["Spear", "Capture"]), isBuilding ? "Capture" : defenderClass == "Domestic" ? "Spear" : "StatusEffect"); | |||||
TS_ASSERT_EQUALS(cmpAttack.GetBestAttackAgainst(defender, false, {}, ["Bow", "Capture"]), isBuilding ? "Capture" : defenderClass == "Domestic" ? "Bow" : "StatusEffect"); | |||||
TS_ASSERT_EQUALS(cmpAttack.GetBestAttackAgainst(defender, false, {}, ["!Bow", "!Spear"]), isBuilding ? "Capture" : defenderClass == "Domestic" ? "Slaughter" : "StatusEffect"); | |||||
TS_ASSERT_EQUALS(cmpAttack.GetBestAttackAgainst(defender, false, {}, ["Spear", "!Spear"]), isBuilding ? "Capture" : defenderClass == "Domestic" ? "Slaughter" : "StatusEffect"); | |||||
}); | }); | ||||
} | } | ||||
testGetBestAttackAgainst("FemaleCitizen", "Melee", undefined); | testGetBestAttackAgainst("FemaleCitizen", "Bow"); | ||||
testGetBestAttackAgainst("Archer", "Ranged", undefined); | testGetBestAttackAgainst("Archer", "Bow"); | ||||
testGetBestAttackAgainst("Domestic", "Slaughter", "Slaughter"); | testGetBestAttackAgainst("Domestic", "Slaughter"); | ||||
testGetBestAttackAgainst("Structure", "Capture", "Capture", true); | testGetBestAttackAgainst("Structure", "Capture", true); | ||||
testGetBestAttackAgainst("Structure", "Ranged", undefined, false); | testGetBestAttackAgainst("Structure", "Bow", false); |
Wildfire Games · Phabricator