Differential D2296 Diff 12233 ps/trunk/binaries/data/mods/public/simulation/components/tests/test_StatusEffectsReceiver.js
Changeset View
Changeset View
Standalone View
Standalone View
ps/trunk/binaries/data/mods/public/simulation/components/tests/test_StatusEffectsReceiver.js
Engine.LoadHelperScript("MultiKeyMap.js"); | |||||
Engine.LoadHelperScript("Player.js"); | |||||
Engine.LoadHelperScript("ValueModification.js"); | |||||
Engine.LoadComponentScript("interfaces/Health.js"); | |||||
Engine.LoadComponentScript("interfaces/ModifiersManager.js"); | |||||
Engine.LoadComponentScript("interfaces/StatusEffectsReceiver.js"); | Engine.LoadComponentScript("interfaces/StatusEffectsReceiver.js"); | ||||
Engine.LoadComponentScript("interfaces/Timer.js"); | Engine.LoadComponentScript("interfaces/Timer.js"); | ||||
Engine.LoadComponentScript("Health.js"); | |||||
Engine.LoadComponentScript("ModifiersManager.js"); | |||||
Engine.LoadComponentScript("StatusEffectsReceiver.js"); | Engine.LoadComponentScript("StatusEffectsReceiver.js"); | ||||
Engine.LoadComponentScript("Timer.js"); | Engine.LoadComponentScript("Timer.js"); | ||||
var target = 42; | let target = 42; | ||||
var cmpStatusReceiver; | let cmpStatusReceiver = ConstructComponent(target, "StatusEffectsReceiver"); | ||||
var cmpTimer; | let cmpTimer = ConstructComponent(SYSTEM_ENTITY, "Timer"); | ||||
var dealtDamage; | let dealtDamage = 0; | ||||
var enemyEntity = 4; | let enemyEntity = 4; | ||||
var enemy = 2; | let enemy = 2; | ||||
let statusName; | |||||
function setup() | let Attacking = { | ||||
"HandleAttackEffects": (_, attackData) => { | |||||
for (let type in attackData.Damage) | |||||
dealtDamage += attackData.Damage[type]; | |||||
} | |||||
}; | |||||
Engine.RegisterGlobal("Attacking", Attacking); | |||||
function reset() | |||||
{ | { | ||||
cmpStatusReceiver = ConstructComponent(target, "StatusEffectsReceiver"); | for (let status in cmpStatusReceiver.GetActiveStatuses()) | ||||
cmpTimer = ConstructComponent(SYSTEM_ENTITY, "Timer"); | cmpStatusReceiver.RemoveStatus(status); | ||||
dealtDamage = 0; | dealtDamage = 0; | ||||
} | } | ||||
function testInflictEffects() | // Test adding a single effect. | ||||
{ | statusName = "Burn"; | ||||
setup(); | |||||
let statusName = "Burn"; | |||||
let Attacking = { | |||||
"HandleAttackEffects": (_, attackData) => { dealtDamage += attackData.Damage[statusName]; } | |||||
}; | |||||
Engine.RegisterGlobal("Attacking", Attacking); | |||||
// damage scheduled: 0, 10, 20 sec | // Damage scheduled: 0, 10, 20 seconds. | ||||
cmpStatusReceiver.AddStatus(statusName, { | cmpStatusReceiver.AddStatus(statusName, { | ||||
"Duration": 20000, | "Duration": 20000, | ||||
"Interval": 10000, | "Interval": 10000, | ||||
"Damage": { | "Damage": { | ||||
[statusName]: 1 | [statusName]: 1 | ||||
} | } | ||||
}, | }, | ||||
{ | { | ||||
"entity": enemyEntity, | "entity": enemyEntity, | ||||
"owner": enemy, | "owner": enemy, | ||||
}); | }); | ||||
cmpTimer.OnUpdate({ "turnLength": 1 }); | cmpTimer.OnUpdate({ "turnLength": 1 }); | ||||
TS_ASSERT_EQUALS(dealtDamage, 1); // 1 sec | TS_ASSERT_EQUALS(dealtDamage, 1); // 1 sec | ||||
cmpTimer.OnUpdate({ "turnLength": 8 }); | cmpTimer.OnUpdate({ "turnLength": 8 }); | ||||
TS_ASSERT_EQUALS(dealtDamage, 1); // 9 sec | TS_ASSERT_EQUALS(dealtDamage, 1); // 9 sec | ||||
cmpTimer.OnUpdate({ "turnLength": 1 }); | cmpTimer.OnUpdate({ "turnLength": 1 }); | ||||
TS_ASSERT_EQUALS(dealtDamage, 2); // 10 sec | TS_ASSERT_EQUALS(dealtDamage, 2); // 10 sec | ||||
cmpTimer.OnUpdate({ "turnLength": 10 }); | cmpTimer.OnUpdate({ "turnLength": 10 }); | ||||
TS_ASSERT_EQUALS(dealtDamage, 3); // 20 sec | TS_ASSERT_EQUALS(dealtDamage, 3); // 20 sec | ||||
cmpTimer.OnUpdate({ "turnLength": 10 }); | cmpTimer.OnUpdate({ "turnLength": 10 }); | ||||
TS_ASSERT_EQUALS(dealtDamage, 3); // 30 sec | TS_ASSERT_EQUALS(dealtDamage, 3); // 30 sec | ||||
} | |||||
testInflictEffects(); | |||||
function testMultipleEffects() | // Test adding multiple effects. | ||||
{ | reset(); | ||||
setup(); | |||||
let Attacking = { | |||||
"HandleAttackEffects": (_, attackData) => { | |||||
if (attackData.Damage.Burn) dealtDamage += attackData.Damage.Burn; | |||||
if (attackData.Damage.Poison) dealtDamage += attackData.Damage.Poison; | |||||
}, | |||||
}; | |||||
Engine.RegisterGlobal("Attacking", Attacking); | |||||
// damage scheduled: 0, 1, 2, 10 sec | // Damage scheduled: 0, 1, 2, 10 seconds. | ||||
cmpStatusReceiver.ApplyStatus({ | cmpStatusReceiver.ApplyStatus({ | ||||
"Burn": { | "Burn": { | ||||
"Duration": 20000, | "Duration": 20000, | ||||
"Interval": 10000, | "Interval": 10000, | ||||
"Damage": { | "Damage": { | ||||
"Burn": 10 | "Burn": 10 | ||||
} | } | ||||
}, | }, | ||||
"Poison": { | "Poison": { | ||||
"Duration": 3000, | "Duration": 3000, | ||||
"Interval": 1000, | "Interval": 1000, | ||||
"Damage": { | "Damage": { | ||||
"Poison": 1 | "Poison": 1 | ||||
} | } | ||||
} | } | ||||
}); | }); | ||||
cmpTimer.OnUpdate({ "turnLength": 1 }); | cmpTimer.OnUpdate({ "turnLength": 1 }); | ||||
TS_ASSERT_EQUALS(dealtDamage, 12); // 1 sec | TS_ASSERT_EQUALS(dealtDamage, 12); // 1 sec | ||||
cmpTimer.OnUpdate({ "turnLength": 1 }); | cmpTimer.OnUpdate({ "turnLength": 1 }); | ||||
TS_ASSERT_EQUALS(dealtDamage, 13); // 2 sec | TS_ASSERT_EQUALS(dealtDamage, 13); // 2 sec | ||||
cmpTimer.OnUpdate({ "turnLength": 1 }); | cmpTimer.OnUpdate({ "turnLength": 1 }); | ||||
TS_ASSERT_EQUALS(dealtDamage, 13); // 3 sec | TS_ASSERT_EQUALS(dealtDamage, 13); // 3 sec | ||||
cmpTimer.OnUpdate({ "turnLength": 7 }); | cmpTimer.OnUpdate({ "turnLength": 7 }); | ||||
TS_ASSERT_EQUALS(dealtDamage, 23); // 10 sec | TS_ASSERT_EQUALS(dealtDamage, 23); // 10 sec | ||||
} | |||||
testMultipleEffects(); | |||||
function testRemoveStatus() | // Test removing a status removes effects. | ||||
{ | reset(); | ||||
setup(); | statusName = "Poison"; | ||||
let statusName = "Poison"; | |||||
let Attacking = { | |||||
"HandleAttackEffects": (_, attackData) => { dealtDamage += attackData.Damage[statusName]; } | |||||
}; | |||||
Engine.RegisterGlobal("Attacking", Attacking); | |||||
// damage scheduled: 0, 10, 20 sec | // Damage scheduled: 0, 10, 20 seconds. | ||||
cmpStatusReceiver.AddStatus(statusName, { | cmpStatusReceiver.AddStatus(statusName, { | ||||
"Duration": 20000, | "Duration": 20000, | ||||
"Interval": 10000, | "Interval": 10000, | ||||
"Damage": { | "Damage": { | ||||
[statusName]: 1 | [statusName]: 1 | ||||
} | } | ||||
}, | }, | ||||
{ | { | ||||
"entity": enemyEntity, | "entity": enemyEntity, | ||||
"owner": enemy, | "owner": enemy, | ||||
}); | }); | ||||
cmpTimer.OnUpdate({ "turnLength": 1 }); | cmpTimer.OnUpdate({ "turnLength": 1 }); | ||||
TS_ASSERT_EQUALS(dealtDamage, 1); // 1 sec | TS_ASSERT_EQUALS(dealtDamage, 1); // 1 sec | ||||
cmpStatusReceiver.RemoveStatus(statusName); | cmpStatusReceiver.RemoveStatus(statusName); | ||||
cmpTimer.OnUpdate({ "turnLength": 10 }); | cmpTimer.OnUpdate({ "turnLength": 10 }); | ||||
TS_ASSERT_EQUALS(dealtDamage, 1); // 11 sec | TS_ASSERT_EQUALS(dealtDamage, 1); // 11 sec | ||||
// Test that a status effect with modifications modifies. | |||||
reset(); | |||||
AddMock(target, IID_Identity, { | |||||
"GetClassesList": () => ["AffectedClass"] | |||||
}); | |||||
let cmpModifiersManager = ConstructComponent(SYSTEM_ENTITY, "ModifiersManager"); | |||||
let maxHealth = 100; | |||||
AddMock(target, IID_Health, { | |||||
"GetMaxHitpoints": () => ApplyValueModificationsToEntity("Health/Max", maxHealth, target) | |||||
}); | |||||
statusName = "Haste"; | |||||
let factor = 0.5; | |||||
cmpStatusReceiver.AddStatus(statusName, { | |||||
"Duration": 5000, | |||||
"Modifiers": { | |||||
[statusName]: { | |||||
"Paths": { | |||||
"_string": "Health/Max" | |||||
}, | |||||
"Affects": { | |||||
"_string": "AffectedClass" | |||||
}, | |||||
"Multiply": factor | |||||
} | } | ||||
} | |||||
}, | |||||
{ | |||||
"entity": enemyEntity, | |||||
"owner": enemy, | |||||
}); | |||||
let cmpHealth = Engine.QueryInterface(target, IID_Health); | |||||
// Test that the modification is applied. | |||||
TS_ASSERT_EQUALS(cmpHealth.GetMaxHitpoints(), maxHealth * factor); | |||||
cmpTimer.OnUpdate({ "turnLength": 1 }); | |||||
TS_ASSERT_EQUALS(cmpHealth.GetMaxHitpoints(), maxHealth * factor); | |||||
// Test that the modification is removed after the appropriate time. | |||||
cmpTimer.OnUpdate({ "turnLength": 4 }); | |||||
TS_ASSERT_EQUALS(cmpHealth.GetMaxHitpoints(), maxHealth); | |||||
// Test addition. | |||||
let addition = 50; | |||||
cmpStatusReceiver.AddStatus(statusName, { | |||||
"Duration": 5000, | |||||
"Modifiers": { | |||||
[statusName]: { | |||||
"Paths": { | |||||
"_string": "Health/Max" | |||||
}, | |||||
"Affects": { | |||||
"_string": "AffectedClass" | |||||
}, | |||||
"Add": addition | |||||
} | |||||
} | |||||
}, | |||||
{ | |||||
"entity": enemyEntity, | |||||
"owner": enemy, | |||||
}); | |||||
// Test that the addition modification is applied. | |||||
TS_ASSERT_EQUALS(cmpHealth.GetMaxHitpoints(), maxHealth + addition); | |||||
cmpTimer.OnUpdate({ "turnLength": 1 }); | |||||
TS_ASSERT_EQUALS(cmpHealth.GetMaxHitpoints(), maxHealth + addition); | |||||
// Test that the modification is removed after the appropriate time. | |||||
cmpTimer.OnUpdate({ "turnLength": 4 }); | |||||
TS_ASSERT_EQUALS(cmpHealth.GetMaxHitpoints(), maxHealth); | |||||
testRemoveStatus(); | |||||
// Test replacement. | |||||
let newValue = 50; | |||||
cmpStatusReceiver.AddStatus(statusName, { | |||||
"Duration": 5000, | |||||
"Modifiers": { | |||||
[statusName]: { | |||||
"Paths": { | |||||
"_string": "Health/Max" | |||||
}, | |||||
"Affects": { | |||||
"_string": "AffectedClass" | |||||
}, | |||||
"Replace": newValue | |||||
} | |||||
} | |||||
}, | |||||
{ | |||||
"entity": enemyEntity, | |||||
"owner": enemy, | |||||
}); | |||||
// Test that the replacement modification is applied. | |||||
TS_ASSERT_EQUALS(cmpHealth.GetMaxHitpoints(), newValue); | |||||
cmpTimer.OnUpdate({ "turnLength": 1 }); | |||||
TS_ASSERT_EQUALS(cmpHealth.GetMaxHitpoints(), newValue); | |||||
// Test that the modification is removed after the appropriate time. | |||||
cmpTimer.OnUpdate({ "turnLength": 4 }); | |||||
TS_ASSERT_EQUALS(cmpHealth.GetMaxHitpoints(), maxHealth); | |||||
function applyStatus(stackability) | |||||
{ | |||||
cmpStatusReceiver.ApplyStatus({ | |||||
"randomName": { | |||||
"Duration": 3000, | |||||
"Interval": 1000, | |||||
"Damage": { | |||||
"randomName": 1 | |||||
}, | |||||
"Stackability": stackability | |||||
} | |||||
}); | |||||
} | |||||
// Test different stackabilities. | |||||
// First ignoring, i.e. next time the same status is added it is just ignored. | |||||
reset(); | |||||
applyStatus("Ignore"); | |||||
// 1 Second: 1 update and lateness. | |||||
cmpTimer.OnUpdate({ "turnLength": 1 }); | |||||
TS_ASSERT_EQUALS(dealtDamage, 2); | |||||
applyStatus("Ignore"); | |||||
// 2 Seconds. | |||||
cmpTimer.OnUpdate({ "turnLength": 1 }); | |||||
TS_ASSERT_EQUALS(dealtDamage, 3); | |||||
// 3 Seconds: finished in previous turn. | |||||
cmpTimer.OnUpdate({ "turnLength": 1 }); | |||||
TS_ASSERT_EQUALS(dealtDamage, 3); | |||||
// Extending, i.e. next time the same status is applied the times are added. | |||||
reset(); | |||||
applyStatus("Extend"); | |||||
// 1 Second: 1 update and lateness. | |||||
cmpTimer.OnUpdate({ "turnLength": 1 }); | |||||
TS_ASSERT_EQUALS(dealtDamage, 2); | |||||
// Add 3 seconds. | |||||
applyStatus("Extend"); | |||||
// 2 Seconds. | |||||
cmpTimer.OnUpdate({ "turnLength": 1 }); | |||||
TS_ASSERT_EQUALS(dealtDamage, 3); | |||||
// 3 Seconds: extended in previous turn. | |||||
cmpTimer.OnUpdate({ "turnLength": 1 }); | |||||
TS_ASSERT_EQUALS(dealtDamage, 4); | |||||
// 4 Seconds. | |||||
cmpTimer.OnUpdate({ "turnLength": 1 }); | |||||
TS_ASSERT_EQUALS(dealtDamage, 5); | |||||
// 5 Seconds. | |||||
cmpTimer.OnUpdate({ "turnLength": 1 }); | |||||
TS_ASSERT_EQUALS(dealtDamage, 6); | |||||
// 6 Seconds: finished in previous turn (3 + 3). | |||||
cmpTimer.OnUpdate({ "turnLength": 1 }); | |||||
TS_ASSERT_EQUALS(dealtDamage, 6); | |||||
// Replacing, i.e. the next applied status replaces the former. | |||||
reset(); | |||||
applyStatus("Replace"); | |||||
// 1 Second: 1 update and lateness. | |||||
cmpTimer.OnUpdate({ "turnLength": 1 }); | |||||
TS_ASSERT_EQUALS(dealtDamage, 2); | |||||
applyStatus("Replace"); | |||||
// 2 Seconds: 1 update and lateness of the new status. | |||||
cmpTimer.OnUpdate({ "turnLength": 1 }); | |||||
TS_ASSERT_EQUALS(dealtDamage, 4); | |||||
// 3 Seconds. | |||||
cmpTimer.OnUpdate({ "turnLength": 1 }); | |||||
TS_ASSERT_EQUALS(dealtDamage, 5); | |||||
// 4 Seconds: finished in previous turn. | |||||
cmpTimer.OnUpdate({ "turnLength": 1 }); | |||||
TS_ASSERT_EQUALS(dealtDamage, 5); | |||||
// Stacking, every new status just applies besides the rest. | |||||
reset(); | |||||
applyStatus("Stack"); | |||||
// 1 Second: 1 update and lateness. | |||||
cmpTimer.OnUpdate({ "turnLength": 1 }); | |||||
TS_ASSERT_EQUALS(dealtDamage, 2); | |||||
applyStatus("Stack"); | |||||
// 2 Seconds: 1 damage from the previous status + 2 from the new (1 turn + lateness). | |||||
cmpTimer.OnUpdate({ "turnLength": 1 }); | |||||
TS_ASSERT_EQUALS(dealtDamage, 5); | |||||
// 3 Seconds: first one finished in the previous turn, +1 from the new. | |||||
cmpTimer.OnUpdate({ "turnLength": 1 }); | |||||
TS_ASSERT_EQUALS(dealtDamage, 6); | |||||
// 4 Seconds: new status finished in previous turn. | |||||
cmpTimer.OnUpdate({ "turnLength": 1 }); | |||||
TS_ASSERT_EQUALS(dealtDamage, 6); |
Wildfire Games · Phabricator