diff --git a/packages/web/src/App.svelte b/packages/web/src/App.svelte index ac61596..a9e9404 100644 --- a/packages/web/src/App.svelte +++ b/packages/web/src/App.svelte @@ -379,8 +379,9 @@ let trapCells = $state<{ x: number; y: number }[]>([]); /** trader: first item square picked. */ let tradeFrom = $state<{ x: number; y: number } | null>(null); - /** rotate-sector direction. */ - let rotateCW = $state(true); + /** ROTATE SECTOR: the square tapped first marks the sector; the turn is + * chosen by its own button, so no sector spins the way nobody meant. */ + let pendingRotate = $state<{ x: number; y: number } | null>(null); /** pick-lock / master-key: prop the door for others once it opens. */ let holdDoor = $state(false); /** MEGA-MONSTER aimed at a monster: which of its two numbers to double. */ @@ -435,13 +436,12 @@ : null, ); - /** The 5x5 sector a picked-up square belongs to (its origin), or null. */ + /** The 5x5 sector a picked-up or marked square belongs to (its origin), or null. */ const pendingSectorOrigin = $derived.by(() => { - if (!view || !pendingSectorFrom) return null; + const at = pendingSectorFrom ?? pendingRotate; + if (!view || !at) return null; const p = view.board.placements.find( - (p) => - pendingSectorFrom!.x >= p.origin.x && pendingSectorFrom!.x < p.origin.x + 5 && - pendingSectorFrom!.y >= p.origin.y && pendingSectorFrom!.y < p.origin.y + 5, + (p) => at.x >= p.origin.x && at.x < p.origin.x + 5 && at.y >= p.origin.y && at.y < p.origin.y + 5, ); return p ? p.origin : null; }); @@ -475,6 +475,15 @@ return out; }); + function rotateSector(clockwise: boolean) { + if (!selectedCard || !pendingRotate) return; + dispatch({ + type: "cast", instanceId: selectedCard.instanceId, + target: { kind: "cell", cell: pendingRotate }, params: { clockwise }, + }); + clearSelection(); + } + function confirmTeleport() { if (!selectedCard || !pendingTeleport) return; dispatch({ @@ -634,6 +643,9 @@ ? "Tap the marked square again to jump · or pick another" : "Choose a destination · lit squares are within 4 · ends your movement"; if (id === "mental-force") return "Choose the wizard, then where they go · within 3 walked squares"; + if (id === "rotate-sector") return pendingRotate + ? "The marked sector turns · choose which way, or tap another sector" + : "Tap a square in the sector to turn · then choose which way"; if (EDGE_CARDS.has(id)) return "Tap a wall line · lit lines are legal"; if (cellSelectMode) return "Choose a square · lit squares are legal targets"; if (selectedDef.cardType === "attack") return selectedDef.adjacent @@ -666,6 +678,7 @@ holdDoor = false; pickChoice = false; pendingTeleport = null; + pendingRotate = null; attachedNumber = null; attachedMods = []; wbDamage = 0; @@ -973,11 +986,8 @@ return; } if (selectedCard?.cardId === "rotate-sector") { - dispatch({ - type: "cast", instanceId: selectedCard.instanceId, - target: { kind: "cell", cell }, params: { clockwise: rotateCW }, - }); - clearSelection(); + // The tap marks the sector; the way it turns is the next decision. + pendingRotate = cell; return; } if (selectedCard && CELL_CARDS.has(selectedCard.cardId)) { @@ -3008,8 +3018,13 @@ {/if} {#if selectedCard?.cardId === "rotate-sector"} - - — click the sector + {#if pendingRotate} + — the marked sector turns a quarter + + + {:else} + — tap a square in the sector to turn + {/if} {/if} {#if selectedCard?.cardId === "relocate-sector"} {pendingSectorFrom @@ -3567,6 +3582,10 @@ {#if selectedCard?.cardId === "teleport" && pendingTeleport} {/if} + {#if selectedCard?.cardId === "rotate-sector" && pendingRotate} + + + {/if} {#if selectedCard && isNumberCard(selectedCard.cardId)} {@const needsAdd = view.turn.numberPlayedForMovement} {@const haveAdd = view.yourHand.some((c) => c.cardId === "add")}