fix: handle round/game end during mid-walk adventure resolution
Add ADV_SESSION_END_MARKERS to detect when a round or game ends as a direct continuation of resolving a mid-walk window choice. Previously, neither event carried a `.seat` nor was a walk-resumption type, so ADV_RESUME_MARKERS alone couldn't detect this boundary. Now, when events contain 'roundEnd' or 'gameOver', split them so the modal closes before playing anything from the new round/game-over screen, preventing narration/step queue folding into the current session.
This commit is contained in:
parent
8c8bce814f
commit
4b35876a34
|
|
@ -78,6 +78,16 @@ const ADV_WALK_TYPES = new Set([
|
|||
// to completion, synchronously, before advance() gets a chance to resume the
|
||||
// walk — so the first occurrence of one of these always marks that boundary.
|
||||
const ADV_RESUME_MARKERS = ['roomHits', 'adventurePause', 'heroEnters', 'bossWounded', 'eliminated'];
|
||||
// A round (or the whole game) can end as a direct, uninterrupted continuation
|
||||
// of resolving a mid-walk window choice — e.g. the last hero on the board
|
||||
// dies and there's nothing left anywhere to react to, so stepAdventure runs
|
||||
// straight through endRound()/startRound() (or endGame()) in the same
|
||||
// takeEvents() batch. Neither event carries a `.seat`, and neither is a
|
||||
// walk-resumption type, so ADV_RESUME_MARKERS alone can't see this boundary —
|
||||
// see applyAdventureWindowChoice, which must close this modal BEFORE playing
|
||||
// anything from this point on (a new round's own heroRevealed reveal, or the
|
||||
// game-over screen), not fold it into this session's own narration/step queue.
|
||||
const ADV_SESSION_END_MARKERS = ['roundEnd', 'gameOver'];
|
||||
const ADV_HERO_ROW = { x0: 40, x1: 860, y: 200, maxW: 120 };
|
||||
const ADV_ROOM_ROW = { x0: 900, x1: 1880, y: 200, maxW: 150 };
|
||||
const ADV_STAGE_HERO = { x: 380, y: 680 };
|
||||
|
|
@ -3033,6 +3043,22 @@ export default class DungeonBossGame extends Phaser.Scene {
|
|||
return;
|
||||
}
|
||||
const events = takeEvents(this.gs);
|
||||
const endIdx = events.findIndex((e) => ADV_SESSION_END_MARKERS.includes(e.type));
|
||||
if (endIdx !== -1) {
|
||||
// See ADV_SESSION_END_MARKERS — everything from here on belongs to a
|
||||
// new round/phase (or the game-over screen), not this seat's walk.
|
||||
// Close this modal first, then hand the rest to the normal pipeline —
|
||||
// exactly like onSessionDrained does for the ordinary drain path, just
|
||||
// using the fresh tail of THIS takeEvents() call rather than whatever
|
||||
// (by now almost certainly empty) batch this session originally opened
|
||||
// with.
|
||||
const narration = events.slice(0, endIdx);
|
||||
const rest = events.slice(endIdx);
|
||||
this.playAdventureNarration(narration, () => {
|
||||
this.closeAdventureModal(() => { this.busy = false; this.playEvents(rest); });
|
||||
});
|
||||
return;
|
||||
}
|
||||
const boundary = events.findIndex((e) => ADV_RESUME_MARKERS.includes(e.type));
|
||||
const narration = boundary === -1 ? events : events.slice(0, boundary);
|
||||
const resumed = boundary === -1 ? [] : events.slice(boundary);
|
||||
|
|
|
|||
Loading…
Reference in New Issue