0.2.6-dev: port PR #416 by Cromemadnd — at every round start the own board's pieces replay their Start clip and landing sound one after another in deployment order (the maintainer's confirmation from official play, 2026-10-13), and a purchase or a move onto / across the board plays them too ([ASSUMED], the PR author's account); one sound per landing, idle prep pieces only, the round marked once the view took the sequence, own board only, timers cleared when prep mode ends and on destroy; DESIGN §31.8; golden: unchanged

This commit is contained in:
sganggs committed 2026-10-13 04:36:56 +08:00
1 parent 281cf01ff0
commit 231da0efbc
16 files changed
+791 -22

No files matched your search

+59
View File
@@ -117,3 +117,62 @@ and its glass, which were matched to screenshots, and does not touch the scene m
lightmap page) stays [ASSUMED]. The water (#549's second half, PR #555) is unchanged here.
Tests: `test/render/board3d-scene.test.js`; the 3D board browser suite with the extracted scenes.
### 31.8 Deploy animation replays (PR #416)
PR #416 by @Cromemadnd, written against 0.2.2 and ported onto the current files.
**Seen.** A prep piece never played its Spine Start clip or a landing sound outside a battle. A piece put on the board
through the direction wheel played nothing: the state that shows the move arrives while the wheel's hold still pins the
piece on its tile, so `setPrep`'s branch for a piece entering the board was never reached. A purchase only flashed
(`fx.deploy`), and the board rebuilt after every battle stood still.
**Official / decision.** The maintainer confirmed from official play on 2026-10-13 that at the start of every round the
operators on the board replay their Start animation and landing sound one after another in deployment order. The PR also
plays them when an operator is bought and when it enters the board or swaps tiles; its author says the official client
does so. Those two triggers are [ASSUMED] on that account. The PR's late-model case (a deploy asked before the Spine model
has loaded) was fixed in 0.2.3 (§28.22: the late model continues Start at the elapsed game time) and stays as it is.
**Now.**
- `UnitView.land()` (render/units.js) plays the piece's Start clip again through `onDeploy` (its fade-in and the late-model
continuation) and asks `audio.deployCue` for the landing sound: the piece's battle deploy sound (`deploySfxUrl`: its own
ON_UNIT_BORN file at its bank gain, else b_char_set / b_char_tokenset at 0.5) through the SFX channel's volume and mute
and the battle limiter (≤ 2 copies of one sound, a 160 ms cooldown per piece). One landing makes one sound: a piece
whose Start still plays keeps it and sounds nothing more, whether the clip runs on its model, is owed to a model still
loading, or was cued less than a clip length ago. That covers a purchase followed by a move, and the round start's replay
reaching a piece just put down. Only an idle prep piece lands. A battle unit never does: the sim's `deploy` events keep
the silent `onDeploy`, and audio.handleBattleEvents makes their sound (the PR's view-side sound would have doubled every
battle deployment). Nor does a piece that is attacking, dying, lifted by a drag or in another clip, or any piece while the
tab is hidden (the clip and the suspended audio would play it stale on return).
- Round start (`ui/gameLogic roundStartReplay`, `screens/game.js`, `render/app.js replayDeploys`). During 回合开始 the own
board's pieces land one after another in deployment order, each turn chained 50 ms after the one before. The order is the
battle's (`deployOrder`, as Battle.start): operators by column from the left, top to bottom within a column, then the
summons the same way, in board coordinates. The PR used the m.private board list, which is reading order. The screen
asks after its field-view wiring effect, so the view already holds the round's pieces, and it marks the round only once
the view has taken the sequence. A view still loading or a board not built yet is asked again on the next render of
回合开始; the PR marked the round first, so a late view never replayed. A re-pushed state (a reconnect's resync) or a
re-render of the same round plays nothing more, and nothing is replayed outside 回合开始. The timers end with prep mode
(`enterBattle`, which a scouted board also uses), with a fresh prep scene and with `destroy()`; a turn whose piece is
gone or rebuilt passes over it.
- Spectators and watched boards: the replay plays on the viewer's own board only. A scouted or watched teammate's prep
board, a spectator seat (no m.private), an eliminated player and the boss partner's half in a Final Assault prep get none.
- Purchase and board triggers (`render/app.js setPrep`). An operator that has just arrived on the bench lands: a purchase,
a reward or a grant, and a merge's elite on its bench slot or on the copy's tile. A summon that arrives with its owner's
placement does not, nor does an item. A piece that a new state puts on a board tile it was not on lands when that state
arrives, whether it came from the bench, from another tile or as the partner of a swap. The PR also landed a piece at
the wheel's confirm, which sounded twice whenever the server answered after 0.3 s, and on every move on the bench and
every retreat. Here turning in place, a retreat and bench moves do not land. That is narrower than the PR's wheel hook,
which fired on every confirm. The deploy flash (`fx.deploy`) is unchanged.
**[ASSUMED]** The purchase and board triggers (the PR author's account). The 50 ms gap (`DEPLOY_REPLAY_MS`, the PR's
value; no source gives the official one). Summon pieces taking part in the replay after the operators, as in the battle's
deployment. The clip length a landing counts as playing when the model's own is unknown (`START_CLIP_FALLBACK` 1 s; the
operators' Start clips run 0.77–1.2 s). A page reloaded during 回合开始 replays once in the new page.
**Tests.** `test/render/deploy-replay.test.js` (the clip, one sound, a second trigger, a late model, the refusals, a hidden
tab; the app.js wiring), `test/ui/deploy-replay.test.js` (`deployOrder`, `roundStartReplay`, the screen wiring; `deployCue`:
the files, the limiter keys, volume and mute), `test/render/playtest6-promote.test.js` (the elite's cue), and the browser
check `test/ui/deploy-replay.e2e.test.js` (`SP_E2E=1`, mock harness: SETTLE → 回合开始 replays the board in deployment order
about 50 ms apart with one sound each, once per round and again the next round; in the 休整期 a purchase lands, a move
within its Start sounds nothing more, a later move lands, a turn in place does not). Golden: unchanged (client only).