Changeset View
Changeset View
Standalone View
Standalone View
binaries/data/mods/public/simulation/components/tests/test_Attack.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/AuraManager.js"); | Engine.LoadComponentScript("interfaces/AuraManager.js"); | ||||
Engine.LoadComponentScript("interfaces/Capturable.js"); | Engine.LoadComponentScript("interfaces/Capturable.js"); | ||||
Engine.LoadComponentScript("interfaces/TechnologyManager.js"); | Engine.LoadComponentScript("interfaces/TechnologyManager.js"); | ||||
Engine.LoadComponentScript("interfaces/Formation.js"); | Engine.LoadComponentScript("interfaces/Formation.js"); | ||||
Engine.LoadComponentScript("interfaces/Attack.js"); | Engine.LoadComponentScript("interfaces/Attack.js"); | ||||
Engine.LoadComponentScript("interfaces/Damage.js"); | |||||
Engine.LoadComponentScript("interfaces/Timer.js"); | |||||
Engine.LoadComponentScript("Attack.js"); | Engine.LoadComponentScript("Attack.js"); | ||||
Engine.LoadComponentScript("Timer.js"); | |||||
let entityID = 903; | let entityID = 903; | ||||
bb: Wondering why we need this component/object doesn't seem used | |||||
function attackComponentTest(defenderClass, isEnemy, test_function) | function attackComponentTest(defenderClass, isEnemy, test_function) | ||||
{ | { | ||||
ResetState(); | ResetState(); | ||||
{ | { | ||||
let playerEnt1 = 5; | let playerEnt1 = 5; | ||||
AddMock(SYSTEM_ENTITY, IID_PlayerManager, { | AddMock(SYSTEM_ENTITY, IID_PlayerManager, { | ||||
"GetPlayerByID": () => playerEnt1 | "GetPlayerByID": () => playerEnt1 | ||||
}); | }); | ||||
AddMock(playerEnt1, IID_Player, { | AddMock(playerEnt1, IID_Player, { | ||||
"GetPlayerID": () => 1, | "GetPlayerID": () => 1, | ||||
"IsEnemy": () => isEnemy | "IsEnemy": () => isEnemy | ||||
}); | }); | ||||
} | } | ||||
let attacker = entityID; | let attacker = entityID; | ||||
AddMock(attacker, IID_Position, { | AddMock(attacker, IID_Position, { | ||||
"IsInWorld": () => true, | "IsInWorld": () => true, | ||||
"GetHeightOffset": () => 5 | "GetHeightOffset": () => 5, | ||||
"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" : { | "Melee" : { | ||||
Show All 19 Lines | let cmpAttack = ConstructComponent(attacker, "Attack", { | ||||
"Ranged" : { | "Ranged" : { | ||||
"Hack": 0, | "Hack": 0, | ||||
"Pierce": 10, | "Pierce": 10, | ||||
"Crush": 0, | "Crush": 0, | ||||
"MinRange": 10, | "MinRange": 10, | ||||
"MaxRange": 80, | "MaxRange": 80, | ||||
"PrepareTime": 300, | "PrepareTime": 300, | ||||
"RepeatTime": 500, | "RepeatTime": 500, | ||||
"ProjectileSpeed": 50, | |||||
"Spread": 2.5, | |||||
"PreferredClasses": { | "PreferredClasses": { | ||||
"_string": "Archer" | "_string": "Archer" | ||||
}, | }, | ||||
"RestrictedClasses": { | "RestrictedClasses": { | ||||
"_string": "Elephant" | "_string": "Elephant" | ||||
}, | |||||
"Splash" : { | |||||
"Shape": "Circular", | |||||
"Range": 10, | |||||
"FriendlyFire": "false", | |||||
"Hack": 0.0, | |||||
"Pierce": 15.0, | |||||
"Crush": 35.0 | |||||
} | } | ||||
}, | }, | ||||
"Capture" : { | "Capture" : { | ||||
"Value": 8, | "Value": 8, | ||||
"MaxRange": 10, | "MaxRange": 10, | ||||
}, | }, | ||||
"Slaughter": {} | "Slaughter": {}, | ||||
"Death": { | |||||
"Shape": "Circular", | |||||
"Range": 20, | |||||
"FriendlyFire": "false", | |||||
"Hack": 1000.0, | |||||
"Pierce": 1000.0, | |||||
"Crush": 500.0 | |||||
} | |||||
}); | }); | ||||
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 | ||||
}); | }); | ||||
Show All 39 Lines | TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetTimers("Ranged"), { | ||||
"prepare": 300, | "prepare": 300, | ||||
"repeat": 500 | "repeat": 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.GetSplashDamage("Ranged"), { "hack": 0, "pierce": 15, "crush": 35, "friendlyFire": false, "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_UNEVAL_EQUALS(cmpAttack.GetAttackBonus("Melee", defender), className == "Cavalry" ? 2 : 1); | TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetAttackBonus("Melee", defender), className == "Cavalry" ? 2 : 1); | ||||
TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetAttackBonus("Ranged", defender), 1); | TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetAttackBonus("Ranged", defender), 1); | ||||
TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetAttackBonus("Capture", defender), 1); | TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetAttackBonus("Capture", defender), 1); | ||||
TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetAttackBonus("Slaughter", defender), 1); | TS_ASSERT_UNEVAL_EQUALS(cmpAttack.GetAttackBonus("Slaughter", defender), 1); | ||||
Show All 21 Lines | attackComponentTest(defenderClass, true, (attacker, cmpAttack, defender) => { | ||||
TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, ["Ranged"]), true); | TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, ["Ranged"]), true); | ||||
TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, ["!Melee"]), true); | TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, ["!Melee"]), true); | ||||
TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, ["Capture"]), isBuilding); | TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, ["Capture"]), isBuilding); | ||||
TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, ["Melee", "Capture"]), defenderClass != "Archer"); | TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, ["Melee", "Capture"]), defenderClass != "Archer"); | ||||
TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, ["Ranged", "Capture"]), true); | TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, ["Ranged", "Capture"]), true); | ||||
TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, ["!Ranged", "!Melee"]), isBuilding || defenderClass == "Domestic"); | TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, ["!Ranged", "!Melee"]), isBuilding || defenderClass == "Domestic"); | ||||
TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, ["Melee", "!Melee"]), false); | TS_ASSERT_EQUALS(cmpAttack.CanAttack(defender, ["Melee", "!Melee"]), false); | ||||
let allowCapturing = [true]; | let allowCapturing = [true]; | ||||
Done Inline ActionsUse arrow function bb: Use arrow function | |||||
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); | ||||
}); | }); | ||||
attackComponentTest(defenderClass, false, (attacker, cmpAttack, defender) => { | attackComponentTest(defenderClass, false, (attacker, cmpAttack, defender) => { | ||||
Show All 31 Lines | function testGetBestAttackAgainst(defenderClass, bestAttack, isBuilding = false) | ||||
}); | }); | ||||
} | } | ||||
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); | ||||
attackComponentTest(undefined, false, (attacker, cmpAttack, defender) => { | |||||
let causeSplashDamageArg = ""; | |||||
AddMock(SYSTEM_ENTITY, IID_Damage, { | |||||
"CauseDamage": () => false, | |||||
"SetTimeout": () => false, | |||||
"GetPlayersToDamage": () => [1, 2], | |||||
"CauseSplashDamage": (arg) => { causeSplashDamageArg = arg; } | |||||
}); | |||||
cmpAttack.CauseDeathDamage(); | |||||
TS_ASSERT_UNEVAL_EQUALS(causeSplashDamageArg, { | |||||
attacker: attacker, | |||||
origin: { "x": 1, "y": 2 }, | |||||
radius: 20, | |||||
shape: "Circular", | |||||
strengths: { "hack": 1000, "pierce": 1000, "crush": 500 }, | |||||
playersToDamage: [1, 2], | |||||
type: "Death", | |||||
attackerOwner: 1 | |||||
}); | |||||
}); | |||||
function testPredictTimeToTarget(selfPosition, horizSpeed, targetPosition, targetVelocity) | function testPredictTimeToTarget(selfPosition, horizSpeed, targetPosition, targetVelocity) | ||||
{ | { | ||||
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; | ||||
// Position of the target after that time. | // Position of the target after that time. | ||||
let targetPos = Vector3D.mult(targetVelocity, timeToTarget).add(targetPosition); | let targetPos = Vector3D.mult(targetVelocity, timeToTarget).add(targetPosition); | ||||
Show All 24 Lines |
Wildfire Games · Phabricator
Wondering why we need this component/object doesn't seem used