The cruel draw gets its modal, and its own words
GIFT FROM BELOW bit for three in the middle of end-of-turn noise and nobody saw it — not live, not in the replay, where its log line even claimed "lose a turn" (the other trap's fate). The trapSprung event now names its card; drawing a trap YOURSELF raises the full modal — the card, what it did, "Curse the deck" — and the chronicle tells each trap's true consequence. The amplify narration was already fixed; replays re-derive events, so both now show in old games' reels too. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
028ff813f3
commit
bed7d849eb
@@ -602,7 +602,7 @@ export type GameEvent =
|
||||
| { type: "cardDisplayed"; player: PlayerId; card: CardInstance }
|
||||
| { type: "extraTurnGranted"; player: PlayerId }
|
||||
| { type: "lifeTraded"; player: PlayerId; points: number; newAllowance: number }
|
||||
| { type: "trapSprung"; player: PlayerId }
|
||||
| { type: "trapSprung"; player: PlayerId; cardId?: string }
|
||||
| { type: "died"; player: PlayerId; killedBy: PlayerId | null }
|
||||
| { type: "handTaken"; from: PlayerId; to: PlayerId; count: number }
|
||||
| { type: "handTakenPrivate"; visibleTo: PlayerId; cards: CardInstance[] }
|
||||
@@ -5639,13 +5639,13 @@ function doEndTurn(prev: GameState, draw: number): CommandResult {
|
||||
if (isTrap(card.cardId)) {
|
||||
state.discard.push(card);
|
||||
p.lostTurns++;
|
||||
events.push({ type: "trapSprung", player: p.id });
|
||||
events.push({ type: "trapSprung", player: p.id, cardId: card.cardId });
|
||||
continue;
|
||||
}
|
||||
if (card.cardId === "gift-from-below") {
|
||||
// "You lose 3 points to magical damage, now ... then discard and redraw."
|
||||
state.discard.push(card);
|
||||
events.push({ type: "trapSprung", player: p.id });
|
||||
events.push({ type: "trapSprung", player: p.id, cardId: card.cardId });
|
||||
applyDamage(state, events, p, 3, "gift from below", null);
|
||||
checkVictory(state, events);
|
||||
if (!p.alive) break;
|
||||
|
||||
@@ -47,8 +47,13 @@
|
||||
/** Live spell flourishes on the board (cosmetic, self-expiring). */
|
||||
let boardFx = $state<BoardFx[]>([]);
|
||||
let fxCancels: (() => void)[] = [];
|
||||
/** A trap drawn by YOU earns a modal; buried log lines get missed. */
|
||||
let trapNotice = $state<string | null>(null);
|
||||
function playFx(events: Parameters<typeof scheduleFx>[0]) {
|
||||
if (!view) return;
|
||||
for (const e of events) {
|
||||
if (e.type === "trapSprung" && e.player === view.you && e.cardId) trapNotice = e.cardId;
|
||||
}
|
||||
fxCancels.push(scheduleFx(
|
||||
events, view,
|
||||
(fx) => (boardFx = [...boardFx, fx]),
|
||||
@@ -1029,6 +1034,21 @@
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if trapNotice}
|
||||
<div class="scrim attack-scrim" role="alertdialog" aria-label="a trap card">
|
||||
<div class="attack-notice">
|
||||
<div class="attack-headline">A cruel draw!</div>
|
||||
<div class="attack-card"><Card card={{ instanceId: "trap-notice", cardId: trapNotice }} /></div>
|
||||
<div class="attack-power">
|
||||
{trapNotice === "gift-from-below"
|
||||
? "It bites for 3 points, then the deck deals you another."
|
||||
: "The trap snaps shut — you lose a turn."}
|
||||
</div>
|
||||
<button class="stamp big" onclick={() => (trapNotice = null)}>Curse the deck</button>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if view && view.outOfTurnWindow?.playerId === view.you && !momentSeen}
|
||||
<div class="scrim attack-scrim" role="alertdialog" aria-label="your interruption">
|
||||
<div class="attack-notice">
|
||||
|
||||
@@ -57,7 +57,9 @@ export function humanize(e: GameEvent): string | null {
|
||||
case "wallCreated": return `A wall appears!`;
|
||||
case "wallDestroyed": return e.wasDoor ? `A door is blasted to rubble!` : `A wall crumbles!`;
|
||||
case "extraTurnGranted": return `${e.player} speeds up — extra turn banked.`;
|
||||
case "trapSprung": return `${e.player} walked into an old TRAP! Lose a turn.`;
|
||||
case "trapSprung": return e.cardId === "gift-from-below"
|
||||
? `${e.player} draws GIFT FROM BELOW — it bites for 3, then deals again!`
|
||||
: `${e.player} walked into an old TRAP! Lose a turn.`;
|
||||
case "attackMissed": return e.because === "invisible"
|
||||
? `The attack passes through empty air — ${e.defender} is invisible!`
|
||||
: `${e.defender} is too small to hit — the attack misses!`;
|
||||
|
||||
Reference in New Issue
Block a user