Boobytrap tokens land where you can see them
The four placements accumulated invisibly until the last click cast the spell. Each token now marks its square as it is placed, numbered in click order — the 1 is the real trap — and tapping a placed token lifts it again, since the four must be distinct squares. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
04dc9bc750
commit
ee6a08f25c
@@ -470,7 +470,11 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (selectedCard?.cardId === "boobytrap") {
|
if (selectedCard?.cardId === "boobytrap") {
|
||||||
trapCells = [...trapCells, cell];
|
// Tapping a placed token lifts it again; the four must be distinct.
|
||||||
|
const already = trapCells.findIndex((c) => cellKey(c) === cellKey(cell));
|
||||||
|
trapCells = already !== -1
|
||||||
|
? trapCells.filter((_, i) => i !== already)
|
||||||
|
: [...trapCells, cell];
|
||||||
if (trapCells.length === 4) {
|
if (trapCells.length === 4) {
|
||||||
dispatch({ type: "cast", instanceId: selectedCard.instanceId, params: { cells: trapCells } });
|
dispatch({ type: "cast", instanceId: selectedCard.instanceId, params: { cells: trapCells } });
|
||||||
clearSelection();
|
clearSelection();
|
||||||
@@ -1224,6 +1228,7 @@
|
|||||||
onCreatureClick={clickCreature}
|
onCreatureClick={clickCreature}
|
||||||
onWarpClick={clickWarp}
|
onWarpClick={clickWarp}
|
||||||
markedCell={tradeFrom ?? pendingTeleport}
|
markedCell={tradeFrom ?? pendingTeleport}
|
||||||
|
markedCells={trapCells.length > 0 ? trapCells : null}
|
||||||
markedSector={pendingSectorOrigin}
|
markedSector={pendingSectorOrigin}
|
||||||
ghostSlots={relocateGhosts}
|
ghostSlots={relocateGhosts}
|
||||||
onGhostClick={clickGhostSlot}
|
onGhostClick={clickGhostSlot}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
onWarpClick,
|
onWarpClick,
|
||||||
onCellPeek,
|
onCellPeek,
|
||||||
markedCell = null,
|
markedCell = null,
|
||||||
|
markedCells = null,
|
||||||
litCells = null,
|
litCells = null,
|
||||||
markedSector = null,
|
markedSector = null,
|
||||||
ghostSlots = null,
|
ghostSlots = null,
|
||||||
@@ -34,6 +35,9 @@
|
|||||||
onCellPeek?: (cell: { x: number; y: number }) => void;
|
onCellPeek?: (cell: { x: number; y: number }) => void;
|
||||||
/** First square of a two-square spell: marked so the click reads as taken. */
|
/** First square of a two-square spell: marked so the click reads as taken. */
|
||||||
markedCell?: { x: number; y: number } | null;
|
markedCell?: { x: number; y: number } | null;
|
||||||
|
/** A multi-square placement in progress (boobytrap tokens), in click
|
||||||
|
* order — the first is the real trap, so each mark shows its number. */
|
||||||
|
markedCells?: { x: number; y: number }[] | null;
|
||||||
/** When set, squares NOT in this set dim — the targeting aid. */
|
/** When set, squares NOT in this set dim — the targeting aid. */
|
||||||
litCells?: Set<string> | null;
|
litCells?: Set<string> | null;
|
||||||
/** Origin of a picked-up 5x5 sector: the whole sector outlines as taken. */
|
/** Origin of a picked-up 5x5 sector: the whole sector outlines as taken. */
|
||||||
@@ -430,6 +434,19 @@
|
|||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
<!-- placements so far of a multi-square spell, numbered in click order -->
|
||||||
|
{#each markedCells ?? [] as m, i (`${m.x},${m.y}`)}
|
||||||
|
<rect
|
||||||
|
x={m.x * CELL + 3} y={m.y * CELL + 3}
|
||||||
|
width={CELL - 6} height={CELL - 6}
|
||||||
|
rx="6" class="marked-cell"
|
||||||
|
/>
|
||||||
|
<text
|
||||||
|
x={m.x * CELL + CELL / 2} y={m.y * CELL + CELL / 2}
|
||||||
|
class="marked-count" text-anchor="middle" dominant-baseline="central"
|
||||||
|
>{i + 1}</text>
|
||||||
|
{/each}
|
||||||
|
|
||||||
<!-- the sector picked up, awaiting its new ground -->
|
<!-- the sector picked up, awaiting its new ground -->
|
||||||
{#if markedSector}
|
{#if markedSector}
|
||||||
<rect
|
<rect
|
||||||
@@ -664,6 +681,13 @@
|
|||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
animation: warp-pulse 1.6s ease-in-out infinite;
|
animation: warp-pulse 1.6s ease-in-out infinite;
|
||||||
}
|
}
|
||||||
|
.marked-count {
|
||||||
|
font-family: "Oswald", sans-serif;
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: 600;
|
||||||
|
fill: #d3852b;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
.marked-sector {
|
.marked-sector {
|
||||||
fill: rgba(211, 133, 43, 0.12);
|
fill: rgba(211, 133, 43, 0.12);
|
||||||
stroke: #d3852b;
|
stroke: #d3852b;
|
||||||
|
|||||||
Reference in New Issue
Block a user