fix: correct community-reported combat and strategy draft behavior

Guard lethal stuns against a replacement deployment; keep bard auras running
through stun; require an active Aegir bond for Clementia's strategy; allow
Compass SP to bypass recovery locks; and refresh Hidden Core gun mitigation
against current gun/spring companions. Set multiplayer strategy picks to 50s
and describe renderer fallback without diagnosing unsupported hardware.

Golden moves (full 285-scenario regeneration):
- roster-008: inactive Aegir no longer gains 18 strategy layers.
- boss-boss_4-solo: bard regeneration continues through stun.
- hidden-boss_9-pair: mitigation covers first hits/current companions.
- standin-07: hammer stun cannot follow an immediate revival deployment.
No ending-reason changes. Sources and report-by-report findings: DESIGN 28.25.
This commit is contained in:
sganggs committed 2026-10-10 00:45:41 +08:00
1 parent 77cd29f07a
commit 708caf7d06
37 files changed
+277 -103

No files matched your search

+2 -2
View File
@@ -164,7 +164,7 @@ describe('server: automatic assignments never duplicate a teammate\'s strategy',
test('every human idle: the turn timeouts assign distinct strategies (no separate step cap)', () => {
const h = draftOf({ humans: 4, seed: 9 });
const m = h.m;
h.run(() => m.phase !== PHASE.BAND_DRAFT, { maxTime: 120000 });
h.run(() => m.phase !== PHASE.BAND_DRAFT, { maxTime: 4 * TURN_MS + 1 });
assert.equal(m.phase, PHASE.BATTLE_CHECK);
const ids = distinct(m);
assert.ok(ids.includes('band_bldsk'), 'the first idle player still gets the official default');
@@ -194,7 +194,7 @@ describe('server: automatic assignments never duplicate a teammate\'s strategy',
m.dispose();
for (const seed of [1, 2, 3, 4]) {
const h2 = draftOf({ humans: 2, bots: 2, seed });
h2.run(() => h2.m.phase !== PHASE.BAND_DRAFT, { maxTime: 120000 });
h2.run(() => h2.m.phase !== PHASE.BAND_DRAFT, { maxTime: 4 * TURN_MS + 1 });
distinct(h2.m);
h2.m.dispose();
}
+1 -1
View File
@@ -365,7 +365,7 @@ describe('user playtest #2 item 10 — boss-round prep on the boss field (real s
for (const c of [host, guest]) await c.waitFor((s) => s.phase === 'INFO_CHECK', 'briefing', 30000);
for (const c of [host, guest]) await c.click('.brief__foot .btn--primary', '准备就绪');
// the draft first (a client still in the briefing would count as done without picking: its turn then runs out —
// Match.BAND_TURN_SECONDS, 30 s each since user playtest #4 item 4)
// Match.BAND_TURN_SECONDS, 50 s each since the 2026-10-10 official-play report)
for (const c of [host, guest]) await c.waitFor((s) => s.phase !== 'INFO_CHECK', 'band draft', 40000);
// band draft: whoever's turn it is picks a free strategy
const picked = new Set();
+1 -1
View File
@@ -88,7 +88,7 @@ describe('DESIGN §16 — a teammate\'s unit shows its owner\'s loadout (real se
assert.deepEqual(await loOf(host), {}, 'the host fights with the defaults');
for (const c of [host, guest]) await c.click('.brief__foot .btn--primary', '准备就绪');
// the draft first (a client still in the briefing would count as done without picking: its turn then runs out —
// Match.BAND_TURN_SECONDS, 30 s each since user playtest #4 item 4)
// Match.BAND_TURN_SECONDS, 50 s each since the 2026-10-10 official-play report)
for (const c of [host, guest]) await c.waitFor((s) => s.phase !== 'INFO_CHECK', 'band draft', 40000);
const picked = new Set();
const t0 = Date.now();