The helm yields the glass while a card is aimed

The drive chevrons are buttons over the canvas edges, and the
back-stride strip owns the bottom band — exactly where an adjacent
square's floor renders. With a card selected, hovering there showed
no target and a click would have STEPPED backward instead of casting
(the tacks report: the pane refused what the map allowed). While a
card is aimed the strips now fade and stop catching the pointer, so
every pixel of the pane hovers and clicks as a target; the arrow keys
still steer throughout.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015RCWSTnb1KYTPyL4GmhGnF
This commit is contained in:
Eric Wagoner
2026-08-27 15:21:05 -04:00
co-authored by Claude Fable 5
parent 728f9fc28a
commit 0530ecb039
2 changed files with 11 additions and 6 deletions
+2 -1
View File
@@ -1914,7 +1914,8 @@
onbody={(id) => (fpvBody = id)} onbody={(id) => (fpvBody = id)}
onWarpStep={(creatureId) => dispatch(creatureId onWarpStep={(creatureId) => dispatch(creatureId
? { type: "creatureWarpStep", creatureId } ? { type: "creatureWarpStep", creatureId }
: { type: "warpStep" })} /> : { type: "warpStep" })}
targeting={!!selectedCard && yourMoment} />
{/if} {/if}
<Board <Board
{view} {view}
+9 -5
View File
@@ -17,7 +17,7 @@
import { untrack } from "svelte"; import { untrack } from "svelte";
import type { GameEvent, GameView, Side } from "@wizwar/engine"; import type { GameEvent, GameView, Side } from "@wizwar/engine";
let { view, batch, onhide, onstride = null, canStride = false, ontarget = null, onfacing = null, litCells = null, onpickup = null, onCreatureMove = null, onCreatureAttack = null, onbody = null, onWarpStep = null }: { let { view, batch, onhide, onstride = null, canStride = false, ontarget = null, onfacing = null, litCells = null, onpickup = null, onCreatureMove = null, onCreatureAttack = null, onbody = null, onWarpStep = null, targeting = false }: {
view: GameView; view: GameView;
/** The latest live event batch, numbered so each plays once, with /** The latest live event batch, numbered so each plays once, with
* the view the server sent alongside it. */ * the view the server sent alongside it. */
@@ -46,6 +46,9 @@
/** A dimensional-warp step for whichever body the pane is: the /** A dimensional-warp step for whichever body the pane is: the
* wizard (null) or the ridden creature (its id). */ * wizard (null) or the ridden creature (its id). */
onWarpStep?: ((creatureId: string | null) => void) | null; onWarpStep?: ((creatureId: string | null) => void) | null;
/** A card is aimed: the drive strips yield the glass so every pixel
* hovers and clicks as a target (keys still steer). */
targeting?: boolean;
} = $props(); } = $props();
const povId = $derived(view.you); const povId = $derived(view.you);
@@ -430,11 +433,11 @@
ontarget={handleTarget} {litCells} /> ontarget={handleTarget} {litCells} />
<button class="live-fp-hide" onclick={onhide} title="hide (re-enable in preferences)"></button> <button class="live-fp-hide" onclick={onhide} title="hide (re-enable in preferences)"></button>
<!-- The helm, tappable: edge strips turn and stride. --> <!-- The helm, tappable: edge strips turn and stride. -->
<button class="drive drive-left" onclick={() => manualTurn(-1)} aria-label="turn left"></button> <button class="drive drive-left" class:yielded={targeting} onclick={() => manualTurn(-1)} aria-label="turn left"></button>
<button class="drive drive-right" onclick={() => manualTurn(1)} aria-label="turn right"></button> <button class="drive drive-right" class:yielded={targeting} onclick={() => manualTurn(1)} aria-label="turn right"></button>
{#if canStride} {#if canStride}
<button class="drive drive-fwd" onclick={() => manualStride(false)} aria-label="step forward">︿</button> <button class="drive drive-fwd" class:yielded={targeting} onclick={() => manualStride(false)} aria-label="step forward">︿</button>
<button class="drive drive-back" onclick={() => manualStride(true)} aria-label="step back"></button> <button class="drive drive-back" class:yielded={targeting} onclick={() => manualStride(true)} aria-label="step back"></button>
<div class="live-fp-hint">← → turn · ↑ ↓ walk</div> <div class="live-fp-hint">← → turn · ↑ ↓ walk</div>
{/if} {/if}
{#if possessed} {#if possessed}
@@ -608,6 +611,7 @@
.feet-item img { width: 30px; height: 30px; object-fit: contain; } .feet-item img { width: 30px; height: 30px; object-fit: contain; }
.feet-fallback { font-size: 0.65rem; color: #d8d2c0; padding: 0 4px; } .feet-fallback { font-size: 0.65rem; color: #d8d2c0; padding: 0 4px; }
.feet-hazard { font-size: 0.7rem; color: #d98a4a; white-space: nowrap; } .feet-hazard { font-size: 0.7rem; color: #d98a4a; white-space: nowrap; }
.yielded { pointer-events: none; opacity: 0.12; }
.drive-fwd { top: 0; left: 20%; right: 20%; height: 16%; } .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-fwd:hover { background: linear-gradient(to bottom, rgba(0, 0, 0, 0.22), transparent); }
.drive-back { bottom: 0; left: 20%; right: 20%; height: 15%; } .drive-back { bottom: 0; left: 20%; right: 20%; height: 15%; }