Teleport waits for a second tap
One tap cast the jump, and a player reaching for click-per-square movement spent their teleport on the adjacent floor. Now the first tap only marks the destination (the familiar pulsing square), and the jump commits on a second tap of the same square or the hint-bar button — with the hint spelling out the four-square, walls-ignored range. The escape teleport gets the same two-tap arming; a counter wasted on a misclick is a counter wasted. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
22153b1e1b
commit
04dc9bc750
@@ -95,6 +95,8 @@
|
||||
let rotateCW = $state(true);
|
||||
/** mega-monster: which stat the chosen monster doubles. */
|
||||
let megaBoost = $state<"life" | "movement">("life");
|
||||
/** teleport: the marked destination awaiting its confirming second tap. */
|
||||
let pendingTeleport = $state<{ x: number; y: number } | null>(null);
|
||||
/** Cards marked for discard. */
|
||||
let discardSelection = $state<Set<string>>(new Set());
|
||||
/** Voluntary discard mode: hand clicks mark cards instead of playing them. */
|
||||
@@ -171,6 +173,16 @@
|
||||
return out;
|
||||
});
|
||||
|
||||
function confirmTeleport() {
|
||||
if (!selectedCard || !pendingTeleport) return;
|
||||
dispatch({
|
||||
type: "cast", instanceId: selectedCard.instanceId,
|
||||
target: { kind: "cell", cell: pendingTeleport },
|
||||
...(attachedNumber ? { numberInstanceIds: [attachedNumber.instanceId] } : {}),
|
||||
});
|
||||
clearSelection();
|
||||
}
|
||||
|
||||
function clickGhostSlot(origin: { x: number; y: number }) {
|
||||
if (!selectedCard || !pendingSectorFrom) return;
|
||||
dispatch({
|
||||
@@ -237,6 +249,7 @@
|
||||
selectedCreature = null;
|
||||
selectedCard = null;
|
||||
megaBoost = "life";
|
||||
pendingTeleport = null;
|
||||
attachedNumber = null;
|
||||
attachedMods = [];
|
||||
wbDamage = 0;
|
||||
@@ -419,6 +432,12 @@
|
||||
function clickCell(cell: { x: number; y: number }) {
|
||||
if (!view) return;
|
||||
if (youMustRespond && selectedCard?.cardId === "teleport") {
|
||||
// Mark first, jump on the second tap: an escape spent on a misclick
|
||||
// is an escape wasted.
|
||||
if (!pendingTeleport || cellKey(pendingTeleport) !== cellKey(cell)) {
|
||||
pendingTeleport = cell;
|
||||
return;
|
||||
}
|
||||
dispatch({ type: "counteract", instanceId: selectedCard.instanceId, params: { cell } });
|
||||
clearSelection();
|
||||
return;
|
||||
@@ -434,6 +453,16 @@
|
||||
clearSelection();
|
||||
return;
|
||||
}
|
||||
if (selectedCard?.cardId === "teleport") {
|
||||
// Teleport is one jump, not a walk: the first tap only marks the
|
||||
// destination, the second (or the hint-bar button) commits it.
|
||||
if (!pendingTeleport || cellKey(pendingTeleport) !== cellKey(cell)) {
|
||||
pendingTeleport = cell;
|
||||
return;
|
||||
}
|
||||
confirmTeleport();
|
||||
return;
|
||||
}
|
||||
if (selectedCard?.cardId === "relocate-sector") {
|
||||
// Any board click (re-)picks the sector; the landing is chosen from the
|
||||
// dashed ghost slots beyond the maze, since every on-board slot is taken.
|
||||
@@ -1194,7 +1223,7 @@
|
||||
onPlayerClick={clickPlayer}
|
||||
onCreatureClick={clickCreature}
|
||||
onWarpClick={clickWarp}
|
||||
markedCell={tradeFrom}
|
||||
markedCell={tradeFrom ?? pendingTeleport}
|
||||
markedSector={pendingSectorOrigin}
|
||||
ghostSlots={relocateGhosts}
|
||||
onGhostClick={clickGhostSlot}
|
||||
@@ -1381,7 +1410,9 @@
|
||||
{#if youMustRespond && view.stack}
|
||||
<span class="hint-alert">
|
||||
{#if view.stack.defenderId === view.you && selectedCard?.cardId === "teleport"}
|
||||
Escaping by teleport — click a square within four spaces.
|
||||
{pendingTeleport
|
||||
? "Escaping by teleport — tap the marked square again to jump."
|
||||
: "Escaping by teleport — tap a square within four spaces to mark it."}
|
||||
{:else if view.stack.defenderId === view.you}
|
||||
{view.stack.attackerId} attacks with
|
||||
{attackingCreature ? `the ${cardDef(attackingCreature.kind).name}` : view.stack.attackCard ? cardDef(view.stack.attackCard.cardId).name : "a punch"} —
|
||||
@@ -1422,6 +1453,14 @@
|
||||
{:else if selectedCard && TWO_CELL_CARDS.has(selectedCard.cardId)}
|
||||
<span>{tradeFrom ? "— now the second square" : "— click the first square"}</span>
|
||||
{/if}
|
||||
{#if selectedCard?.cardId === "teleport" && !youMustRespond}
|
||||
<span>{pendingTeleport
|
||||
? "— tap the marked square again to jump, or pick another"
|
||||
: "— tap a destination (up to four squares, walls ignored)"}</span>
|
||||
{#if pendingTeleport}
|
||||
<button class="stamp tiny" onclick={confirmTeleport}>teleport!</button>
|
||||
{/if}
|
||||
{/if}
|
||||
{#if selectedCard?.cardId === "mega-monster"}
|
||||
<span>— double its</span>
|
||||
<button class="stamp tiny" class:lit={megaBoost === "life"}
|
||||
|
||||
Reference in New Issue
Block a user