diff --git a/packages/web/src/Replay.svelte b/packages/web/src/Replay.svelte index abd512b..7cec500 100644 --- a/packages/web/src/Replay.svelte +++ b/packages/web/src/Replay.svelte @@ -284,6 +284,29 @@ // cutaway: step outside yourself and watch. if (cell) return { ...cell, self: true }; } + // Last resort, only for the reel's own wizard's step: wherever the + // fx layer is about to play something visible — an impact, a + // projectile's landing — the eyes should already be. This covers + // every effect that exists and every one added later. + if (step.actor === povId) { + for (const e of step.events) { + if (e.type === "creatureMoved" && "by" in e && e.by === povId) { + 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) { + const at = (e as { at: { x: number; y: number } }).at; + return { ...at, self: at.x === me.position.x && at.y === me.position.y }; + } + } + for (const { fx } of fpFxForEvents(step.events, v, povId)) { + const spot = fx.kind === "impact" ? fx.at : fx.kind === "projectile" ? fx.to : null; + if (!spot) continue; + const cx = Math.floor(spot.x), cy = Math.floor(spot.y); + if (cx === me.position.x && cy === me.position.y) return { x: cx, y: cy, self: true }; + return { x: cx, y: cy }; + } + } return null; })() as ({ x: number; y: number; self?: boolean } | null); // A leap the legs cannot explain (first frame, teleport, the return