diff --git a/packages/web/src/App.svelte b/packages/web/src/App.svelte index 7c5dea3..b2b0465 100644 --- a/packages/web/src/App.svelte +++ b/packages/web/src/App.svelte @@ -263,6 +263,17 @@ } } + function clickWarp(cell: { x: number; y: number }, side: Side) { + if (!view || !isYourTurn || !me) return; + // Standing on the opening: step through. Otherwise treat it as a cell + // click on the opening square (e.g. to walk toward it). + if (me.position.x === cell.x && me.position.y === cell.y) { + net.command({ type: "move", direction: side }); + } else { + clickCell(cell); + } + } + function clickEdge(cell: { x: number; y: number }, side: Side) { if (!selectedCard || !edgeSelectMode) return; net.command({ @@ -453,6 +464,7 @@ onEdgeClick={clickEdge} onPlayerClick={clickPlayer} onCreatureClick={clickCreature} + onWarpClick={clickWarp} /> diff --git a/packages/web/src/Board.svelte b/packages/web/src/Board.svelte index a4f0c2c..63e5f13 100644 --- a/packages/web/src/Board.svelte +++ b/packages/web/src/Board.svelte @@ -13,6 +13,7 @@ onEdgeClick, onPlayerClick, onCreatureClick, + onWarpClick, }: { view: GameView; edgeSelectMode?: boolean; @@ -21,6 +22,7 @@ onEdgeClick?: (cell: { x: number; y: number }, side: Side) => void; onPlayerClick?: (playerId: string) => void; onCreatureClick?: (creatureId: string) => void; + onWarpClick?: (cell: { x: number; y: number }, side: Side) => void; } = $props(); const PLAYER_COLORS = ["#1a9c46", "#d3352b", "#c9308f", "#3a3ac0", "#2ab0c9", "#c9a72a"]; @@ -199,15 +201,24 @@ {/if} {/each} - + {#each view.board.warps as w, i (i)} - {w.from.side === "N" ? "↑" : w.from.side === "S" ? "↓" : w.from.side === "E" ? "→" : "←"} + {@const wx = w.from.cell.x * CELL + CELL / 2 + + (w.from.side === "E" ? CELL * 0.42 : w.from.side === "W" ? -CELL * 0.42 : 0)} + {@const wy = w.from.cell.y * CELL + CELL / 2 + + (w.from.side === "S" ? CELL * 0.42 : w.from.side === "N" ? -CELL * 0.42 : 0)} + {@const standing = view.players.some((p) => + p.id === view.you && p.position.x === w.from.cell.x && p.position.y === w.from.cell.y)} + { ev.stopPropagation(); onWarpClick?.(w.from.cell, w.from.side); }} + onkeydown={() => {}} + > + + {w.from.side === "N" ? "↑" : w.from.side === "S" ? "↓" : w.from.side === "E" ? "→" : "←"} + {/each} @@ -321,7 +332,16 @@ .treasure { stroke: #2b2218; stroke-width: 1.3; } .treasure-swirl { fill: none; stroke: #2b2218; stroke-width: 1.2; stroke-dasharray: 5 2.2; } .treasure-core { fill: #2b2218; } - .warp { font-size: 14px; text-anchor: middle; fill: #2b2218; font-weight: bold; opacity: 0.65; } + .warp { font-size: 14px; text-anchor: middle; fill: #2b2218; font-weight: bold; opacity: 0.65; pointer-events: none; } + .warp-g { cursor: pointer; } + .warp-hit { fill: transparent; } + .warp-g:hover .warp-hit { fill: rgba(43, 34, 24, 0.12); } + .warp-g.standing .warp-hit { + fill: rgba(46, 125, 50, 0.25); + stroke: #2e7d32; + stroke-width: 2; + } + .warp-g.standing .warp { opacity: 1; } .wizard { cursor: pointer; } .wizard-label { font-family: "Oswald", sans-serif;