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

+16 -1
View File
@@ -52,6 +52,10 @@
// reward card armed for a purchase that completes a merge lights, in gold, the board tile its elite will take (the
// deployed copy that deploys first, gameLogic.mergeTarget — none when no copy is deployed: the elite goes to the hand);
// the elite then appears there with the promotion cue (render/app.js setPrep → fx.promote).
// Round start (PR #416 by @Cromemadnd; the maintainer's confirmation from official play, 2026-10-13): in 回合开始 the own
// board's pieces replay their Start clip and landing sound one after another in deployment order, once per round and on
// the own board only (gameLogic roundStartReplay → render/app.js replayDeploys); a purchase and a move onto or across the
// board play it too ([ASSUMED], the PR author's account: render/app.js setPrep).
// The bond strip, its popup and a unit card's bond chips follow the player on screen (DESIGN §20.15, ui/watchBonds.js):
// a scouted / watched / auto-observed teammate's field → that teammate's bonds (m.public players[].bonds, tagged
// "👁 name"); 联防 / 最终攻势 → the player on the ‹ › half (全景: yours when you fight there, else the teammate picked
@@ -99,7 +103,7 @@ import {
terrainInfo, deviceInfo, deviceTipAt, noteDeviceUnits, deviceUnitsForEntry,
countdownState, shopBlockReason, stageOverrides, effectiveStage, watchTarget, dropFailureReason,
previewEnemyKey, prepCamera, prepCameraFor, foldCamera, deployFieldOf, fieldTile, panelSide, panelSlots, bondPopupPlace, unitLoadout, deployedRecord,
mergeTarget, modeOffBonds, readyFundsPrompt, readyShopFold, ownerBandId, ownDiyRecord, ownStandIn,
mergeTarget, modeOffBonds, readyFundsPrompt, readyShopFold, ownerBandId, ownDiyRecord, ownStandIn, roundStartReplay,
} from '../ui/gameLogic.js';
import { toast } from '../ui/toasts.js';
import { BriefingScreen } from './briefing.js';
@@ -516,6 +520,17 @@ function MatchScreen() {
}
}, [view, showPrep, priv, editable, field, combat, mode, watchingOther, watching, holdSeq]);
// the round start (PR #416 by @Cromemadnd; the maintainer's confirmation from official play, 2026-10-13): the own board's
// pieces replay their Start clip and landing sound one after another in deployment order — once per round, in 回合开始, on
// the own board only (gameLogic roundStartReplay). After the wiring effect above, so the view already holds this state's
// pieces; the round counts as replayed only once the view took the sequence (a view still loading or a board not built
// yet is asked again on the next render of the phase), and a reconnect or a re-render of the round plays nothing more.
const replayedRef = useRef(null);
useEffect(() => {
const plan = roundStartReplay({ phase, round: pub?.round, replayed: replayedRef.current, ownBoard: showPrep && alive && !spectator, board: priv?.board });
if (plan && view && view.replayDeploys?.(plan.uids) > 0) replayedRef.current = plan.round;
}, [view, phase, pub?.round, priv, showPrep, alive, spectator]);
// battle frames straight from the socket (server-run combat, 20 Hz) or from the local simulation (client-side combat,
// battle/runner.js, every animation frame) — never through the store. Frames go to the view as received: the game
// time travels as `gt` and the render engine reads it (render/interp.js frameTime).