diff --git a/packages/web/src/Replay.svelte b/packages/web/src/Replay.svelte index 7cec500..74ab34e 100644 --- a/packages/web/src/Replay.svelte +++ b/packages/web/src/Replay.svelte @@ -294,7 +294,10 @@ const to = (e as { to: { x: number; y: number } }).to; if (to.x !== me.position.x || to.y !== me.position.y) return to; } - if (e.type === "treasurePickedUp" && "player" in e && (e as { player: string }).player === povId) { + if ( + (e.type === "treasurePickedUp" || e.type === "treasureDropped" || e.type === "objectDropped") && + "player" in e && (e as { player: string }).player === povId + ) { const at = (e as { at: { x: number; y: number } }).at; return { ...at, self: at.x === me.position.x && at.y === me.position.y }; } diff --git a/packages/web/src/fpv/fx3d.ts b/packages/web/src/fpv/fx3d.ts index e1de799..4217c28 100644 --- a/packages/web/src/fpv/fx3d.ts +++ b/packages/web/src/fpv/fx3d.ts @@ -210,6 +210,16 @@ export function fpFxForEvents( out.push({ fx: { id: nextId++, kind: "flash", color: "#e0b34a", peak: 0.22, t0: 0, dur: 550 }, delay: i * 300 + 120 }); } } + if ((e.type === "treasureDropped" || e.type === "objectDropped") && "at" in e) { + // Gold hits the flags: a glint where it lands, a beat after the + // blow when one knocked it loose. + const at = (e as { at: { x: number; y: number } }).at; + const spilled = events.some((x) => x.type === "attackResolved" || x.type === "damaged"); + out.push({ + fx: { id: nextId++, kind: "impact", art: "spark", at: { x: at.x + 0.5, y: at.y + 0.5 }, t0: 0, dur: 500 }, + delay: spilled ? 400 : 0, + }); + } if (e.type === "wallDestroyed" && "edge" in e) { const at = edgeMid((e as { edge: { cell: { x: number; y: number }; side: "N" | "E" | "S" | "W" } }).edge.cell, (e as { edge: { side: "N" | "E" | "S" | "W" } }).edge.side);