Files
ark-stronghold-protocol/test/content/feedback7-champagne-stealth.test.js
T
sganggs e733171b13 feedback7 R22-OSIM: 香槟炸弹 no longer goes off on an unrevealed 隐匿 enemy (nor a sleeping one) — it selects like the other contact traps; golden: bond-yanShip-high, coop2-HARD-4 move
Community report relayed by the owner: 「有人反馈香槟炸到没有破隐的隐匿敌人了」. Reproduced: a 隐匿 walker crossing
琳琅诗怀雅's bombs set them off (both kits checked hidden / flying / untargetable only). The rule: PRTS 作战机制 §隐匿
"隐匿效果使得获得该效果的单位无法被任何敌方的能力索敌选中…要选中隐匿的目标,则该单位自身需拥有无视隐匿的效果"; 异常效果 lists
隐匿 and 无敌 among the 无法选择 effects (沉睡 = "无敌且无法行动", gamedata_const ba.sleep). Neither the 香槟炸弹 page nor
琳琅诗怀雅's S2 carries a 无视隐匿 / 无视可选性 note, and the other contact traps of the sim (多萝西's 共振装置, 望's 棋子)
already select through canTargetEnemy.

Now both kits go off on a ground enemy canTargetEnemy accepts (tokens.js CHAMPAGNE_TRIGGER): a 隐匿 enemy sets one off
once it is revealed (反隐) or blocked (its 隐匿 lifts), a sleeping one once it wakes (until now the bomb was spent on it
for no damage). Placement is unchanged (it already aimed at selectable enemies only).

Golden: bond-yanShip-high and coop2-HARD-4 (bombs under 隐匿 enemies of rounds 10–11 — 隐形弩手组长, 访问团强攻冠军,
重弩突袭者 — and sleeping ones of round 7 — 宿主士兵, 粉碎攻坚手 — now wait).

Tests: test/content/feedback7-champagne-stealth.test.js (2; both fail on the parent).
2026-10-08 20:15:17 +08:00

57 lines
3.1 KiB
JavaScript

// test/content/feedback7-champagne-stealth.test.js — 琳琅诗怀雅's 香槟炸弹 does not go off on a 隐匿 enemy that is neither
// revealed nor blocked (community report: 「香槟炸到没有破隐的隐匿敌人了」). PRTS 作战机制 §隐匿: "隐匿效果使得获得该效果的单位无法被
// 任何敌方的能力索敌选中" — the bomb's pages carry no 无视隐匿 note, and the other contact traps (多萝西's 共振装置, 望's 棋子)
// select their enemies so too. A revealed (反隐) or blocked one, and every visible ground enemy, still set it off.
// Run: node --test test/content/feedback7-champagne-stealth.test.js
import { test } from 'node:test';
import assert from 'node:assert/strict';
import { makeBattle, enemyRec, checkInvariants } from '../helpers/battleHarness.js';
const TRAP = 'token_10031_swire2_gdtrap';
const trapHits = (h, e) => h.hooksOf('damaged').filter((c) => c.target === e && c.dmg?.tags?.includes('trap'));
test('her bombs: a 隐匿 walker crosses one unharmed; a visible walker after it sets it off', () => {
const h = makeBattle({
timeLimit: 120, autoFinish: false, hooks: ['damaged', 'death'], captureNoisy: true,
defs: { enemies: { e_w: enemyRec({ key: 'e_w', hp: 1e6, speed: 1, def: 0, atk: 0 }) } },
units: [{ uid: 1, chessId: 'chess_char_3_04_a', row: 9, col: 5 }],
});
h.step();
const sw = h.unit(1);
const bombAt = (r, c) => h.b.allyUnits.find((t) => t.alive && t.defId === TRAP && t.tileR === r && t.tileC === c);
for (let i = 0; i < 15 && !bombAt(9, 7); i++) { sw.mem.coins = 3; h.run(2); }
const bomb = bombAt(9, 7);
assert.ok(bomb, 'a bomb on (9,7), on the walkers\' road before her block');
const hidden = h.spawn('e_w', { route: 0 });
h.b.addBuff(hidden, { key: 'test:stealth', persist: true, flags: { stealth: true } });
assert.ok(h.runUntil(() => hidden.x < 6.6, 20), 'it walked over (9,7)');
assert.ok(bomb.alive, 'not set off');
assert.equal(trapHits(h, hidden).length, 0);
const seen = h.spawn('e_w', { route: 0 });
assert.ok(h.runUntil(() => !bomb.alive, 20), 'a visible walker sets it off');
assert.ok(trapHits(h, seen).length > 0 && seen.findBuff('sluggish'));
checkInvariants(h.b);
});
test('a bomb (the token kit) under a standing 隐匿 enemy waits; revealed (反隐), it goes off', () => {
const h = makeBattle({
timeLimit: 30, autoFinish: false, hooks: ['damaged'], captureNoisy: true,
defs: { enemies: { e_d: enemyRec({ key: 'e_d', hp: 1e6, speed: 0, def: 0, atk: 0 }) } },
units: [{ uid: 1, chessId: 'chess_char_3_04_a', row: 12, col: 3 }], enemies: [{ key: 'e_d', pos: [9, 7] }],
});
h.step();
const e = h.b.enemies.find((x) => x.alive);
h.b.addBuff(e, { key: 'test:stealth', persist: true, flags: { stealth: true } });
const bomb = h.b.spawnToken(h.unit(1), TRAP, 9, 7);
assert.ok(bomb);
h.run(2);
assert.ok(bomb.alive && !e.blockedBy, 'a 隐匿 enemy on its tile does not set it off');
assert.equal(trapHits(h, e).length, 0);
h.b.addBuff(e, { key: 'test:reveal', persist: true, flags: { reveal: true } });
h.step(2);
assert.ok(!bomb.alive, 'revealed: it goes off');
assert.ok(trapHits(h, e).length > 0);
checkInvariants(h.b);
});