The 伤判效果 that act after a barrier need it: 煌's 紧急除颤 lock (buff template huang_t_1[lock], an ON_TAKE_DAMAGE HpNoLessThanCertainPercentModifier; PRTS 备注 "该伤害减少(伤害值-煌当前生命值+煌最大生命值×50%)点") and 左乐's SBL-X 庇护 re-applied behind his 行险 barrier (PRTS S2 备注). Additive: without a handler the pipeline is unchanged, so golden is unchanged (every family matches). docs/SIM.md §4 / §5 name the hook; test/sim/feedback5-hpdamage-hook.test.js (2).
56 lines
2.8 KiB
JavaScript
56 lines
2.8 KiB
JavaScript
// 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);
|
|
});
|