feedback5: merge O5 — 自选 kits for 左乐, 重岳 and 煌; engine hook hpDamage after the shields (typed shields from O8 kept: absorbShields(…, type)); SIM.md / damage.js headers take both; golden: only diy moved
This commit is contained in:
commit
aebca2f6d8
12 files changed
+2157
-131
No files matched your search
@@ -0,0 +1,55 @@
|
||||
// test/sim/feedback5-hpdamage-hook.test.js — the `hpDamage` hook of damage.js dealDamage (0.2.0, the 自选 operator kits):
|
||||
// what passed the shields of a damage instance, before the HP loss; a handler may only lower it — the 伤判效果 that act
|
||||
// after a barrier (煌's 紧急除颤 HP floor, 左乐's 庇护 re-applied behind his 行险 barrier). A 流失 (Battle.loseHp) never
|
||||
// reaches it, a hit the shields absorb whole neither. docs/SIM.md §4 / §5.
|
||||
// Run: node --test test/sim/feedback5-hpdamage-hook.test.js
|
||||
|
||||
import { test } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { makeBattle, enemyRec, checkInvariants } from '../helpers/battleHarness.js';
|
||||
|
||||
function arena() {
|
||||
const h = makeBattle({
|
||||
defs: { enemies: { enemy_dummy: enemyRec({ key: 'enemy_dummy', hp: 1e6, speed: 0, mass: 0 }) } },
|
||||
units: [{ uid: 1, chessId: 'chess_char_1_02_a', row: 10, col: 5 }], timeLimit: 60, autoFinish: false,
|
||||
});
|
||||
h.step();
|
||||
const u = h.unit(1), e = h.spawn('enemy_dummy', { pos: [10, 8] });
|
||||
return { h, u, e };
|
||||
}
|
||||
|
||||
test('hpDamage: after the shields, before the HP loss — a handler lowers what reaches the HP; a raise is ignored', () => {
|
||||
const { h, u, e } = arena();
|
||||
const seen = [];
|
||||
const off = h.b.on('hpDamage', (c) => { if (c.target === u) { seen.push([c.amount, c.source, c.dmg.type]); c.amount = Math.min(c.amount, 100); } });
|
||||
h.b.addBuff(u, { key: 'test:shield', shield: 300 });
|
||||
const hp = u.hp;
|
||||
const dealt = h.b.dealDamage(e, u, { amount: 1000, type: 'true' });
|
||||
assert.deepEqual(seen, [[700, e, 'true']], 'the 300 shield first, then the hook sees the 700 that passed');
|
||||
assert.equal(u.findBuff('test:shield'), null, 'the shield was spent');
|
||||
assert.deepEqual([hp - u.hp, dealt], [100, 100], 'HP loss and the returned amount follow the lowered value');
|
||||
h.b.off(off);
|
||||
h.b.on('hpDamage', (c) => { if (c.target === u) c.amount = 1e9; });
|
||||
const hp2 = u.hp;
|
||||
h.b.dealDamage(e, u, { amount: 50, type: 'true' });
|
||||
assert.equal(hp2 - u.hp, 50, 'a raise is ignored');
|
||||
checkInvariants(h.b);
|
||||
});
|
||||
|
||||
test('hpDamage: no call for a 流失 nor for a hit the shields take whole; without a handler nothing changes', () => {
|
||||
const { h, u, e } = arena();
|
||||
let n = 0;
|
||||
h.b.on('hpDamage', (c) => { if (c.target === u) n++; });
|
||||
h.b.loseHp(u, 100, { source: e });
|
||||
assert.equal(n, 0, 'a 流失 skips it (no 伤判效果)');
|
||||
h.b.addBuff(u, { key: 'test:shield', shield: 500 });
|
||||
h.b.dealDamage(e, u, { amount: 200, type: 'true' });
|
||||
assert.equal(n, 0, 'absorbed whole: nothing reaches the HP');
|
||||
h.b.dealDamage(e, u, { amount: 400, type: 'true' });
|
||||
assert.equal(n, 1, 'the 100 that passed');
|
||||
const r = arena();
|
||||
const hp = r.u.hp;
|
||||
r.h.b.dealDamage(r.e, r.u, { amount: 250, type: 'true' });
|
||||
assert.equal(hp - r.u.hp, 250, 'no handler: the plain pipeline');
|
||||
checkInvariants(h.b);
|
||||
});
|
||||
Reference in new issue
Block a user