feedback5: merge O3 — 自选 kits for 逻各斯, 真言 and 维伊; engine hook palsyTrigger (麻痹 interrupting an enemy attack); golden: only diy moved
This commit is contained in:
commit
8357149afa
11 files changed
+2270
-121
No files matched your search
@@ -0,0 +1,62 @@
|
||||
// test/sim/palsy-trigger.test.js — the engine hook `palsyTrigger` (server/sim/ai.js enemyAttack): fired when a 麻痹 stack
|
||||
// interrupts an enemy's normal attack (PRTS 真言 备注 "触发麻痹时指的是敌人的攻击被麻痹打断时"), once per interrupt; a
|
||||
// handler may keep the stack (`keep`) or kill the enemy. 真言's 噤声限域 (kits/ops/op-mantra.js) is its user.
|
||||
// Run: node --test test/sim/palsy-trigger.test.js
|
||||
|
||||
import { test } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { makeBattle, chessRec, enemyRec, checkInvariants } from '../helpers/battleHarness.js';
|
||||
|
||||
const guard = chessRec({ id: 't_guard', profession: 'WARRIOR', stats: { atk: 0, blockCnt: 2, maxHp: 1e6 }, skill: null });
|
||||
const shooter = enemyRec({ key: 'enemy_shooter', hp: 1e6, atk: 100, bat: 1, range: 3, speed: 0, mass: 0 });
|
||||
|
||||
function field(setup) {
|
||||
const h = makeBattle({
|
||||
defs: { chess: { t_guard: guard }, enemies: { enemy_shooter: shooter } },
|
||||
units: [{ chessId: 't_guard', row: 10, col: 5 }], content: 'none', autoFinish: false, setup,
|
||||
});
|
||||
h.step();
|
||||
return h;
|
||||
}
|
||||
|
||||
test('palsyTrigger: one event per interrupted attack, before the stack is used; no event without 麻痹', () => {
|
||||
const seen = [];
|
||||
const h = field((b) => b.on('palsyTrigger', (c) => seen.push({ t: b.time, stacks: c.buff.stacks, enemy: c.enemy })));
|
||||
const e = h.spawn('enemy_shooter', { pos: [10, 7] });
|
||||
h.run(3.05);
|
||||
assert.equal(seen.length, 0, 'no 麻痹, no event');
|
||||
const a0 = e.stats.attacks;
|
||||
h.b.applyStatus(e, 'palsy', { value: 2 });
|
||||
h.run(2.05);
|
||||
assert.deepEqual(seen.map((x) => [x.enemy, x.stacks]), [[e, 2], [e, 1]], 'each interrupt, the stack count before it is used');
|
||||
assert.equal(e.stats.attacks, a0, 'both attacks interrupted');
|
||||
assert.equal(e.findBuff('palsy'), null);
|
||||
h.run(1.1);
|
||||
assert.ok(e.stats.attacks > a0, 'attacks again');
|
||||
checkInvariants(h.b);
|
||||
});
|
||||
|
||||
test('palsyTrigger: `keep` leaves the stack; a handler that kills the enemy ends its turn', () => {
|
||||
let keepNext = true;
|
||||
const h = field((b) => b.on('palsyTrigger', (c) => { if (keepNext) { c.keep = true; keepNext = false; } }));
|
||||
const e = h.spawn('enemy_shooter', { pos: [10, 7] });
|
||||
h.step();
|
||||
h.b.applyStatus(e, 'palsy', { value: 1 });
|
||||
const a0 = e.stats.attacks;
|
||||
h.run(1.1);
|
||||
assert.equal(e.findBuff('palsy')?.stacks, 1, 'kept');
|
||||
assert.equal(e.stats.attacks, a0, 'still interrupted');
|
||||
h.run(1.05);
|
||||
assert.equal(e.findBuff('palsy'), null, 'used by the next interrupt');
|
||||
assert.equal(e.stats.attacks, a0);
|
||||
// a lethal handler
|
||||
const h2 = field((b) => b.on('palsyTrigger', (c) => b.kill(c.enemy, null)));
|
||||
const e2 = h2.spawn('enemy_shooter', { pos: [10, 7] });
|
||||
h2.step();
|
||||
h2.b.applyStatus(e2, 'palsy', { value: 3 });
|
||||
h2.run(1.2);
|
||||
assert.ok(!e2.alive);
|
||||
assert.equal(h2.b.errors.length, 0, JSON.stringify(h2.b.errors[0]));
|
||||
checkInvariants(h.b);
|
||||
checkInvariants(h2.b);
|
||||
});
|
||||
Reference in new issue
Block a user