diff --git a/packages/web/src/App.svelte b/packages/web/src/App.svelte index 1626f48..2bfe587 100644 --- a/packages/web/src/App.svelte +++ b/packages/web/src/App.svelte @@ -1911,7 +1911,10 @@ : { type: "pickUpObject", instanceId: w.id })} onCreatureMove={(creatureId, direction) => dispatch({ type: "moveCreature", creatureId, direction })} onCreatureAttack={(creatureId, targetId) => dispatch({ type: "creatureAttack", creatureId, targetId })} - onbody={(id) => (fpvBody = id)} /> + onbody={(id) => (fpvBody = id)} + onWarpStep={(creatureId) => dispatch(creatureId + ? { type: "creatureWarpStep", creatureId } + : { type: "warpStep" })} /> {/if} void) | null; + /** A dimensional-warp step for whichever body the pane is: the + * wizard (null) or the ridden creature (its id). */ + onWarpStep?: ((creatureId: string | null) => void) | null; } = $props(); const povId = $derived(view.you); @@ -113,6 +116,25 @@ cam.x = mx; cam.y = my; cam.facing = face; }); + /** What the ACTIVE body stands in or on: hazards it cannot see below + * itself, and the dimensional token it could step through. */ + const underfoot = $derived.by(() => { + const body = possessed ?? me; + if (!body || !canStride) return { hazard: null as string | null, warpHere: false }; + const k = `${body.position.x},${body.position.y}`; + const HAZARD_NAMES: Record = { + tacks: "tacks underfoot", slime: "green slime", dust: "a dust cloud", + pit: "an open pit", ooze: "the killer ooze", + }; + const kind = view.squareContents[k]?.kind; + return { + hazard: kind ? HAZARD_NAMES[kind] ?? null : null, + warpHere: view.dimWarps.some((w) => + (w.a.x === body.position.x && w.a.y === body.position.y) || + (w.b.x === body.position.x && w.b.y === body.position.y)), + }; + }); + /** Bodies sharing the active eyes' square: inside the near plane, so * the renderer cannot show them — the tray stands in for the sprite, * and clicking routes exactly as clicking the sprite would. */ @@ -441,19 +463,27 @@ {/each} {/if} - {#if onpickup && canStride && atFeet.length > 0 && !possessed} + {#if canStride && ((!possessed && atFeet.length > 0) || underfoot.hazard || underfoot.warpHere)}
at your feet - {#each atFeet as item (item.id)} - - {/each} + {#if !possessed && onpickup} + {#each atFeet as item (item.id)} + + {/each} + {/if} + {#if underfoot.hazard} + ⚠ {underfoot.hazard} + {/if} + {#if underfoot.warpHere && onWarpStep} + + {/if}
{/if} @@ -577,6 +607,7 @@ .feet-item:hover { border-color: #c9a72a; } .feet-item img { width: 30px; height: 30px; object-fit: contain; } .feet-fallback { font-size: 0.65rem; color: #d8d2c0; padding: 0 4px; } + .feet-hazard { font-size: 0.7rem; color: #d98a4a; white-space: nowrap; } .drive-fwd { top: 0; left: 20%; right: 20%; height: 16%; } .drive-fwd:hover { background: linear-gradient(to bottom, rgba(0, 0, 0, 0.22), transparent); } .drive-back { bottom: 0; left: 20%; right: 20%; height: 15%; }