feedback5 WJ: 伺夜's 狼群 takes its official 战术点形态 and S1 领袖的呼唤 acts by the pack's state (PRTS 狼群领袖 / S1 备注)

The fatal hit on the last 狼影, or a 撤退 while 伺夜 stands, no longer kills the pack. It enters its 战术点形态, the
remake's knocked-out piece: off the fight (no block, no attack, not targetable), kept, its tile reserved, 0 狼影. After
the 狼影 recovery time it comes back on its tile at full HP with 1 狼影 and a fresh 狼影 cycle. That time is the token
talent's interval, read from the data: 25 s on both chess. Until now it came back after the token's 10 s redeploy time
with 2 狼影.

Both packs share this (tokens.js installWolfTacticalPoint): the prep-placed 狼群 piece and the 伺夜 kit's own pack.
- A return timer carries the form's seq and a return cancels it, so a stale timer never revives the pack early.
- When 伺夜 leaves, a standing pack still leaves with him ('expired', no form). A pack in its form ends it with no
  return; his redeploy brings a fresh pack.

S1 casts when ready while the pack is on the field in either form, and always pays +cost DP:
① in its 战术点形态 the pack comes back at once with 1 狼影 and a fresh cycle;
② below the cap, +1 狼影, the pack's own cycle untouched;
③ at the cap, the pack's HP is reset to max.
S2 still needs a standing pack: its 备注 says nothing of the form [ASSUMED]. A held S2 gift stays on the pack through
the form [ASSUMED].

fx: the kit's pack keeps 'summon' / 'revive', the piece keeps 'wolfShadow' / 'wolfShadowLost'. Entering the form shows
'wolfShadowLost' with count 0. No new kinds, no client change. Data unchanged.

Docs: DESIGN §5.6 (SP_FULL note), PLAYING (作战中, 自动触发), SIM (token pieces), the tokens.js / kit comments.

Tests:
- kits_alt_t3, new: 3_19 战术点形态 (both chess × both packs), S1 ①②③ with the stale-timer guard, 撤退 / 伺夜 leaving.
- kits_alt_t3, rewritten: the S1 no-pack test, and the S2 auto-cast test (no cast in the form, a cast once the pack is
  back).
- kits_t3 3_19 wolf pack and tokens_devices 狼群 board piece: the form, then a return with 1 狼影.

Golden (each fields 伺夜 with his pack knocked out at its last 狼影 while he stands: 25 s out and 1 狼影 instead of
10 s and 2):
- roster-007 and roster-009: the fights change.
- roster-028 (elite S1): S1 brings the pack back at once.
- roster-026 and roster-040: 伺夜 falls before the old return; only the new 'wolfShadowLost' fx moves.
- bond-siracusaShip-high.
- matches solo-NORMAL-1, coop2-NORMAL-3, coop3-ABYSS-5, coop2-NORMAL-8-serverrun: the bots field 伺夜.
This commit is contained in:
sganggs committed 2026-10-05 19:47:12 +08:00
1 parent a98b02477d
commit 4304eb057c
11 files changed
+577 -222

No files matched your search

+14 -6
View File
@@ -5,7 +5,7 @@ import assert from 'node:assert/strict';
import { makeBattle, chessRec, enemyRec, checkInvariants } from '../helpers/battleHarness.js';
import { hasGeneratedData, getDefaultSource } from '../../server/sim/simdata.js';
import { genericKit } from '../../server/sim/content/generic.js';
import { spawnYanyou, spawnMapChar, TOKEN_IDS, wolfShadows, tileFree, findSummonTile, summonToken } from '../../server/sim/content/tokens.js';
import { spawnYanyou, spawnMapChar, TOKEN_IDS, wolfShadows, wolfShadowInterval, wolfTacticalPoint, tileFree, findSummonTile, summonToken } from '../../server/sim/content/tokens.js';
import { startColdWind, kjeragColdWind, activateTurrets, terrainAt, deviceOverridesOf } from '../../server/sim/content/devices.js';
import { HUSK_REBIRTH } from '../../server/sim/content/enemies.js';
@@ -202,7 +202,7 @@ test('纸偶: appear burst = its ATK × damage_scale arts on the 8 surrounding t
checkInvariants(h.b);
});
test('狼群: board piece becomes 伺夜\'s 援军; 2→3 狼影 (block & hits), fatal sheds a shadow, DEF ignore vs blocked, respawn', REAL, () => {
test('狼群: board piece becomes 伺夜\'s 援军; 2→3 狼影 (block & hits), fatal sheds a shadow, DEF ignore vs blocked, 战术点形态 after the last one', REAL, () => {
let wolfHits = 0;
const h = makeBattle({
defs: { enemies: { enemy_walker: walker({ def: 200, atk: 0 }) } },
@@ -238,11 +238,19 @@ test('狼群: board piece becomes 伺夜\'s 援军; 2→3 狼影 (block & hits),
assert.equal(wolf.hp, wolf.s.maxHp);
h.b.dealDamage(null, wolf, { amount: 1e6, type: 'true' });
h.b.dealDamage(null, wolf, { amount: 1e6, type: 'true' });
// the last shadow falls: 战术点形态 (PRTS 狼群 备注) — off the field, kept, 0 狼影, for the 狼影 interval (data), then
// back on its tile with one 狼影 (no longer a full pack after the token's redeploy time)
assert.equal(wolf.alive, false, 'last shadow falls');
const died = h.b.time;
assert.ok(h.runUntil(() => wolf.alive, 20), 'respawns');
approx(h.b.time - died, wolf.base.respawnTime, 0.3);
assert.equal(wolfShadows(wolf), 2, 'fresh pack');
assert.ok(wolfTacticalPoint(wolf), '战术点形态');
assert.equal(wolf.removed, false);
assert.equal(wolfShadows(wolf), 0);
const died = h.b.time, iv = wolfShadowInterval(wolf.def);
assert.equal(iv, tokDef(TOKEN_IDS.wolfPack, 'chess_char_3_19_b').talents[0].bb.interval, 'the talent interval');
assert.ok(h.runUntil(() => wolf.alive, iv + 1), 'back');
approx(h.b.time - died, iv, 0.004);
assert.deepEqual([wolf.tileR, wolf.tileC], [9, 6], 'on its tile');
assert.equal(wolfShadows(wolf), 1, 'one 狼影');
assert.equal(wolf.s.blockCnt, 1);
checkInvariants(h.b);
});