From 846cf56ffe3f3392b0fdfbc81fbfa5c76f06ff7c Mon Sep 17 00:00:00 2001 From: Eric Wagoner Date: Sun, 23 Aug 2026 20:48:41 -0400 Subject: [PATCH] A laden wizard shows their burden MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A carried treasure rendered nowhere in first person — the thief hauling your gold looked exactly like an innocent. The treasure now rides its carrier at chest height, drawn just in front of their card (a sort bias wins the tie), gliding along with their tweened strides and showing through warp mouths like everything else. The workshop rehearses it with ?carry=Rival. Co-Authored-By: Claude Fable 5 --- packages/web/src/fpv/FpvWorkshop.svelte | 6 ++++++ packages/web/src/fpv/raycast.ts | 19 ++++++++++++++++--- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/packages/web/src/fpv/FpvWorkshop.svelte b/packages/web/src/fpv/FpvWorkshop.svelte index af3ed94..74d9d61 100644 --- a/packages/web/src/fpv/FpvWorkshop.svelte +++ b/packages/web/src/fpv/FpvWorkshop.svelte @@ -38,6 +38,12 @@ const [k, n] = spec.split("@") as [string, string?]; view.wallDamage[k] = Number(n ?? 1) || 1; } + // ?carry=Rival hands the first treasure to that wizard, for viewing + // what a laden thief looks like. + const carrier = q.get("carry"); + if (carrier && view.treasures[0]) { + view.treasures[0] = { ...view.treasures[0], carriedBy: carrier, position: null }; + } // ?terrain=pit@3,7;thornbush@4,7 — furnish squares for the renderer // (and the artist) to rehearse. dimwarp@x,y opens a floor mouth. for (const spec of (q.get("terrain") ?? "").split(";").filter(Boolean)) { diff --git a/packages/web/src/fpv/raycast.ts b/packages/web/src/fpv/raycast.ts index 6e2fe3b..f6b8155 100644 --- a/packages/web/src/fpv/raycast.ts +++ b/packages/web/src/fpv/raycast.ts @@ -387,11 +387,24 @@ export function billboards( }); } for (const t of view.treasures) { - if (!t.position || t.carriedBy) continue; + const src = art(`treasure-${(view.players.find((p) => p.id === t.owner)?.colorIndex ?? 0) % 6}`, "objects"); + if (t.carriedBy) { + // A carried treasure rides its carrier at chest height, drawn just + // in front of them — the most important status in the game should + // be visible on the thief's own body. + const carrier = view.players.find((p) => p.id === t.carriedBy && p.alive); + if (!carrier || carrier.id === povId) continue; + const o = posOverride?.[carrier.id]; + out.push({ + x: o?.x ?? carrier.position.x + 0.5, y: o?.y ?? carrier.position.y + 0.5, + src, scale: 0.26, rise: 0.2, bias: 0.12, label: "treasure", + }); + continue; + } + if (!t.position) continue; out.push({ x: t.position.x + 0.5, y: t.position.y + 0.5, - src: art(`treasure-${(view.players.find((p) => p.id === t.owner)?.colorIndex ?? 0) % 6}`, "objects"), - scale: 0.4, rise: 0, label: "treasure", + src, scale: 0.4, rise: 0, label: "treasure", }); } // The floor's furniture, standing in the room. Bushes fill the square