diff --git a/packages/web/index.html b/packages/web/index.html index e6823c7..0b7725a 100644 --- a/packages/web/index.html +++ b/packages/web/index.html @@ -4,6 +4,9 @@ Wiz-War + + +
diff --git a/packages/web/src/App.svelte b/packages/web/src/App.svelte index d181f35..6eb22e5 100644 --- a/packages/web/src/App.svelte +++ b/packages/web/src/App.svelte @@ -1,6 +1,7 @@ -
-

Wiz-War 6th edition

+
+
+ Wiz-War + sixth edition + {#if net.roomId} + room {net.roomId} + {/if} + + {net.status === "connected" ? "" : "reconnecting…"} + +
{#if net.error} -
{net.error}
+ {/if} {#if !net.roomId} -
-

server: {net.status}

- -
- - or - - +
+
+
Wiz-War
+
A game of magical combat in a stone labyrinth
+ +
+ + or join one + + +
{:else if !net.started} -
-

Room {net.roomId}

-

Share the code with your opponents.

-
    - {#each net.players as p (p)} -
  • {p}{p === net.hostId ? " (host)" : ""}
  • - {/each} -
- {#if net.you === net.hostId} - - - {:else} -

Waiting for {net.hostId} to start…

- {/if} +
+
+
Room {net.roomId}
+
Share the code. Two or four wizards enter the maze.
+
    + {#each net.players as p (p)} +
  • {p}{p === net.hostId ? " — host" : ""}
  • + {/each} +
+ {#if net.you === net.hostId} + + + {:else} +

Waiting for {net.hostId} to flip the boards…

+ {/if} +
{:else if view}
-
+
-
+
-
+ +
+ +
+ {#if selectedDef || youMustDiscard || discardSelection.size > 0} +
+ {#if youMustDiscard} + Hand over the limit — mark cards and discard. + {/if} + {#if discardSelection.size > 0} + + {/if} + {#if selectedDef} + {selectedDef.name} + {#if edgeSelectMode}— click a wall line{/if} + {#if selectedDef.cardType === "attack" && !edgeSelectMode && !cellSelectMode} + — click a target{attachedNumber ? ` (powered by a ${numberTotal})` : " (tap a number card to power it)"} {/if} - {#if selectedCard?.cardId === "waterbolt"} - - (knockback {numberTotal - wbDamage}) + {#if attachedMods.length > 0} + [+ {attachedMods.map((m) => cardDef(m.cardId).name).join(", ")}] + {/if} + {#if selectedCard?.cardId === "boobytrap"} + — place 4 tokens ({trapCells.length}/4; the first is real) + {/if} + {#if selectedCard && TWO_CELL_CARDS.has(selectedCard.cardId)} + {tradeFrom ? "— now the second square" : "— click the first square"} + {/if} + {#if selectedCard?.cardId === "rotate-sector"} + + — click the sector + {/if} + {#if selectedCard?.cardId === "relocate-sector"} + {pendingSectorFrom ? "— now the destination area" : "— click the sector to move"} {/if} {#if selectedCard && NAMED_CARDS.has(selectedCard.cardId)} - + {#if selectedCard.cardId === "deja-vu"} - {:else} - — then click the target wizard + — then click the target {/if} {/if} - {#if attachedMods.length > 0} - [+ {attachedMods.map((m) => cardDef(m.cardId).name).join(", ")}] - {/if} - {#if selectedCard?.cardId === "rotate-sector"} - - — click a square in the sector to rotate - {/if} - {#if selectedCard?.cardId === "boobytrap"} - — place 4 tokens ({trapCells.length}/4; the FIRST is the real trap) - {/if} - {#if selectedCard && TWO_CELL_CARDS.has(selectedCard.cardId)} - {tradeFrom ? "— now the second square" : "— click the first square"} - {/if} - {#if selectedCard?.cardId === "power-attack"} - (select an attack first, then attach Power Attack via number input) - {/if} - {#if selectedCard?.cardId === "relocate-sector"} - {#if pendingSectorFrom} - — now click the destination area - {:else} - — click a square in the sector to move - {/if} + {#if selectedCard?.cardId === "waterbolt"} + + (knockback {numberTotal - wbDamage}) {/if} {#if selectedCard?.cardId === "power-run"} - - + + {/if} {#if selectedCard && SELF_CARDS.has(selectedCard.cardId)} - {/if} - {#if pendingCellFor} - — now click the destination square for {pendingCellFor} - {/if} - {#if selectedCard && CELL_CARDS.has(selectedCard.cardId)} - — click a square on the board - {/if} - -
+ + {/if} +
+ {/if} + +
+ {#if isYourTurn && view.dimWarps.some((w) => { + const me = view.players.find((p) => p.id === view.you)!; + return (w.a.x === me.position.x && w.a.y === me.position.y) || + (w.b.x === me.position.x && w.b.y === me.position.y); + })} + {/if} + {#if isYourTurn} + + + + + {/if} +
-
- {#each view.yourHand as card (card.instanceId)} - {@const def = cardDef(card.cardId)} - - {/each} -
- -
- {#if youMustDiscard} - - {/if} - {#if discardSelection.size > 0} - - {/if} - {#if isYourTurn && view.dimWarps.some((w) => { - const me = view.players.find((p) => p.id === view.you)!; - return (w.a.x === me.position.x && w.a.y === me.position.y) || - (w.b.x === me.position.x && w.b.y === me.position.y); - })} - - {/if} - {#if view.outOfTurnWindow?.playerId === view.you} - - - {/if} - {#if isYourTurn} - - - - - {/if} -
- -
- {#each net.log.slice(-40) as line, i (i)} -
{line}
- {/each} -
+
+ {#each view.yourHand as card (card.instanceId)} + m.instanceId === card.instanceId)} + marked={discardSelection.has(card.instanceId)} + displayed={view.players.find((p) => p.id === view.you)?.displayed.some((c) => c.instanceId === card.instanceId) ?? false} + charges={view.wandCharges[card.instanceId] ?? null} + onclick={() => selectCard(card)} + /> + {/each}
{/if} -
+ diff --git a/packages/web/src/Board.svelte b/packages/web/src/Board.svelte index 31433d7..a4f0c2c 100644 --- a/packages/web/src/Board.svelte +++ b/packages/web/src/Board.svelte @@ -91,17 +91,28 @@ {#each view.players as p (p.id)} - + {@const hx = p.home.x * CELL + CELL / 2} + {@const hy = p.home.y * CELL + CELL / 2} + {@const R = CELL * 0.36} + {@const r = CELL * 0.14} + { + const rad = (Math.PI / 8) * i - Math.PI / 2; + const len = i % 2 === 0 ? R : r; + return `${hx + Math.cos(rad) * len},${hy + Math.sin(rad) * len}`; + }).join(" ")} + class="home-star" fill={playerColor(p.id)} + /> {/each} {#each view.treasures as t (t.id)} {#if t.position} - + {@const tx = t.position.x * CELL + CELL / 2} + {@const ty = t.position.y * CELL + CELL * 0.72} + + + + + {/if} {/each} @@ -210,7 +221,7 @@ onkeydown={() => {}} class="wizard" > - + {p.id[0]?.toUpperCase()} {#if p.carriedTreasureId} @@ -256,21 +267,38 @@