Flourishes: the spells become visible (branch only — not for the droplet yet)

A cosmetic effects layer on the board svg, fed by the same event
stream that writes the log. Fireballs streak and burst; waterbolts
arc and splash; lightning jags and flickers; teleports shimmer at
both ends; walls rise and fall in dust; stopped attacks flash a
golden shield; hits ring red; misses whiff; other attack spells
sparkle at the caster. Successive visuals from one command stagger by
a beat, everything self-expires, reduced-motion hides the layer
whole, and nothing here touches game state — the effects are mapped
from events in fx.ts and drawn in Board.svelte, online and hotseat
alike.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Eric Wagoner
2026-08-16 23:43:16 -04:00
co-authored by Claude Fable 5
parent b01e27c644
commit bca34ae9e4
5 changed files with 326 additions and 0 deletions
+3
View File
@@ -51,6 +51,8 @@ class LocalGame {
/** The finished game as a reel, each step from its actor's own seat. */
/** The opening roll-off, shown once as the boards flip. */
openingRolls = $state<{ rolls: Record<string, number[]>; first: string; players: string[] } | null>(null);
/** Board flourishes: the app hooks in to animate command results. */
onFx: ((events: GameEvent[]) => void) | null = null;
replaySteps = $state<{ seq: number; actor: PlayerId; events: GameEvent[]; view: GameView }[] | null>(null);
view = $derived(
this.gameState && this.viewerId ? viewFor(this.gameState, this.viewerId) : null,
@@ -220,6 +222,7 @@ class LocalGame {
this.log = [...this.log, `${result.error}`];
return;
}
this.onFx?.(result.events);
this.gameState = result.state;
this.commands = [...this.commands, { playerId: this.viewerId, command }];
const now = Date.now();