feedback1 integrate: 坚固维式重锤's lock belongs to the deployment - a lent hammer and in-place revives follow it (QA)

The lock and its re-arm hook lived in the carrier's hammer grants, so a hammer lent by 萨尔贡 × 娜仁图亚 came back spent
in the borrower's next deployment once the lend had run out while it was down, and a window started through the lend
ended with it. deploymentOf marks the deployment whose lock is spent; one battle-level hook holds every running window
(holdsUndying, also what 信仰搅拌机 S2 steps aside for), so a window outlasts the lend. M3茧甲 and 埃芒加德 revive in place
for PRTS's 0-time / 0-cost redeploy and now open a new deployment (revivedInPlace), like 阿戈尔 5's real redeploy.
This commit is contained in:
sganggs committed 2026-10-03 17:47:07 +08:00
1 parent 842e1e13c4
commit d6b1d1bd26
5 files changed
+187 -34

No files matched your search

+27 -1
View File
@@ -9,6 +9,7 @@ import { test } from 'node:test';
import assert from 'node:assert/strict';
import { makeBattle, enemyRec, checkInvariants } from '../helpers/battleHarness.js';
import { getData } from '../../server/data.js';
import { holdsUndying } from '../../server/sim/content/items/battle.js';
const DATA = getData({ log: { warn() {}, error() {}, info() {} } });
@@ -84,7 +85,7 @@ test('信仰搅拌机 S2 steps aside while she holds 不死 (坚固维式重锤\
const foe = h.b.enemies[0];
const lethal = () => h.b.dealDamage(foe, u, { amount: u.s.maxHp * 10, type: 'true', tags: ['test'] });
lethal(); // before the skill: the hammer's lock starts (8 s of 不死)
assert.ok(u.alive && u.mem.undyingUntil > h.b.time, 'the hammer holds her');
assert.ok(u.alive && holdsUndying(h.b, u), 'the hammer holds her');
assert.ok(u.skill.activate('test', { free: true }), 'S2 on');
const ammo = u.skill.ammoLeft;
lethal();
@@ -97,3 +98,28 @@ test('信仰搅拌机 S2 steps aside while she holds 不死 (坚固维式重锤\
assert.equal(u.skill.ammoLeft, ammo - 30);
assert.equal(h.b.errorCount, 0);
});
test('信仰搅拌机 S2 guards again in a new deployment although the old 不死 window has not run out (holdsUndying is per deployment)', () => {
const id = 'chess_char_4_01_a';
const h = makeBattle({
defs: { enemies: { e_hit: enemyRec({ key: 'e_hit', hp: 1e8, atk: 0, speed: 0 }) } },
units: [{ chessId: id, row: 9, col: 5, skillIndex: 1, items: ['chess_item_3_09_e_a'] }], enemies: [{ key: 'e_hit', pos: [9, 8] }],
timeLimit: 60, autoFinish: false,
});
h.step(2);
const u = h.unit(id);
const foe = h.b.enemies[0];
const lethal = () => h.b.dealDamage(foe, u, { amount: u.s.maxHp * 10, type: 'true', tags: ['test'] });
lethal();
assert.ok(holdsUndying(h.b, u), 'the hammer\'s window runs');
h.run(1);
h.b.retreat(u, { reason: 'raid' }); // a 突袭-style retreat + redeploy 3 s into the window
assert.ok(h.b.redeploy(u, { free: true, tile: [9, 6] }), 'redeployed');
assert.ok(!holdsUndying(h.b, u), 'the window ended with its deployment');
assert.ok(u.skill.activate('test', { free: true }), 'S2 on');
const ammo = u.skill.ammoLeft;
lethal();
assert.ok(u.alive, 'S2 blocks it');
assert.equal(u.skill.ammoLeft, ammo - 30, 'she holds no 不死 in this deployment: S2 spends its bullets');
assert.equal(h.b.errorCount, 0);
});