Expansion wave 2: the magic wand system, plus Deja-Vu
Wands charge on first use from the number card(s) played (Amplify and Add both work when setting charges), spend one charge per use with a hard once-per-turn limit, stay displayed while charged, and crumble to the discard when the last charge goes. They are isolated from their wielder — usable under NO SPELL — and Absorb Spell cannot eat them. BLASTER WAND fires 3-point bolts through the normal counteraction stack; STICKY WAND webs its victim (movement -3 for a turn, +2 to any fire damage, including hotter firewall crossings); SHIFT WAND shoves a wizard one space in any direction straight through stone walls; WARP WAND opens a wall section that snaps back at the end of the turn. DEJA-VU retrieves any discard except a wand. The wands' 5e-era "stick" subtype is renamed "wand" per Eric (the 6e faces say Wand; Exp2 shelf cards keep their period names). Client: charge badges, shove targeting, retrieve-by-name. 101 tests passing. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
df0675c735
commit
28949bdb7d
@@ -43,6 +43,7 @@
|
||||
const EDGE_CARDS = new Set([
|
||||
"create-wall", "destroy-wall", "wall-of-fire", "waterwall",
|
||||
"pick-lock", "jam-lock", "remove-lock", "master-key", "dispel-creation",
|
||||
"warp-wand",
|
||||
]);
|
||||
const CELL_CARDS = new Set([
|
||||
"teleport", "fill-square-with-stone", "thornbush", "dispel-creation", "drag",
|
||||
@@ -54,7 +55,7 @@
|
||||
const SELF_CARDS = new Set([
|
||||
"invisible", "shrink", "mist-body",
|
||||
]);
|
||||
const NAMED_CARDS = new Set(["card-erasure", "drop-object"]);
|
||||
const NAMED_CARDS = new Set(["card-erasure", "drop-object", "deja-vu"]);
|
||||
const edgeSelectMode = $derived(selectedCard != null && EDGE_CARDS.has(selectedCard.cardId));
|
||||
const cellSelectMode = $derived(
|
||||
(selectedCard != null && CELL_CARDS.has(selectedCard.cardId)) || pendingCellFor !== null,
|
||||
@@ -284,7 +285,7 @@
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (selectedCard.cardId === "teleport-opponent") {
|
||||
if (selectedCard.cardId === "teleport-opponent" || selectedCard.cardId === "shift-wand") {
|
||||
pendingCellFor = playerId;
|
||||
return; // next: click the destination cell
|
||||
}
|
||||
@@ -437,7 +438,17 @@
|
||||
{/if}
|
||||
{#if selectedCard && NAMED_CARDS.has(selectedCard.cardId)}
|
||||
<label>card name <input bind:value={nameInput} placeholder="e.g. Fireball or treasure" /></label>
|
||||
— then click the target wizard
|
||||
{#if selectedCard.cardId === "deja-vu"}
|
||||
<button onclick={() => {
|
||||
const id = nameToCardId(nameInput);
|
||||
if (id && selectedCard) {
|
||||
net.command({ type: "cast", instanceId: selectedCard.instanceId, params: { cardId: id } });
|
||||
clearSelection();
|
||||
}
|
||||
}}>Retrieve</button>
|
||||
{:else}
|
||||
— then click the target wizard
|
||||
{/if}
|
||||
{/if}
|
||||
{#if attachedMods.length > 0}
|
||||
[+ {attachedMods.map((m) => cardDef(m.cardId).name).join(", ")}]
|
||||
@@ -486,7 +497,9 @@
|
||||
<span class="card-type">{def.cardType}</span>
|
||||
<span class="card-name">{def.name}</span>
|
||||
{#if view.players.find((p) => p.id === view.you)?.displayed.some((c) => c.instanceId === card.instanceId)}
|
||||
<span class="displayed-badge">displayed</span>
|
||||
<span class="displayed-badge">
|
||||
displayed{view.wandCharges[card.instanceId] != null ? ` · ${view.wandCharges[card.instanceId]} ⚡` : ""}
|
||||
</span>
|
||||
{/if}
|
||||
</button>
|
||||
{/each}
|
||||
|
||||
Reference in New Issue
Block a user