From 7dfd9e55dff2c3e3507f5429dd78334b3f2b4739 Mon Sep 17 00:00:00 2001 From: root Date: Sat, 7 Mar 2026 13:30:28 +0000 Subject: [PATCH] docs: add camera mode commands design doc Co-Authored-By: Claude Opus 4.6 --- .../2026-03-07-camera-mode-commands-design.md | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 docs/plans/2026-03-07-camera-mode-commands-design.md diff --git a/docs/plans/2026-03-07-camera-mode-commands-design.md b/docs/plans/2026-03-07-camera-mode-commands-design.md new file mode 100644 index 0000000..fbb2ec3 --- /dev/null +++ b/docs/plans/2026-03-07-camera-mode-commands-design.md @@ -0,0 +1,69 @@ +# Camera Mode Commands — Design + +## Overview + +Add a command system for camera mode, starting with a "Spawn NPC" command bound to the `1` key. A new command panel UI (bottom-right, EarthBound-styled) shows available commands when in camera mode. + +## Requirements + +- Press `1` in camera mode to spawn a new random NPC near the camera center +- NPC spawns at nearest walkable tile within 3-tile radius of camera center; falls back to any random walkable tile +- Server enforces a max NPC cap of 50 (`MAX_NPC_COUNT` constant) +- New NPC uses the same generation pipeline as initial NPCs (random appearance, name, needs, etc.) +- New NPC appears to all clients via the existing `state-update` tick (no special broadcast) +- Command panel UI visible only in camera mode, bottom-right corner + +## Approach + +New `spawn-npc` socket event (Approach A). Client sends tile coordinates, server validates and spawns. + +## Protocol + +**New client event** in `shared/src/types.ts`: +```typescript +'spawn-npc': (data: { x: number, y: number }) => void +``` + +**New constant** in `shared/src/constants.ts`: +```typescript +export const MAX_NPC_COUNT = 50; +``` + +## Server Changes + +### `GameMap` — `findNearestWalkable(x, y, radius)` +- Spiral outward from (x, y) up to `radius` tiles +- Return first walkable tile found, or `null` + +### `spawner.ts` — `spawnNPC(world, map, positionHint?)` +- Add optional `positionHint: { x: number, y: number }` parameter +- If hint provided and walkable, use it; otherwise fall back to `map.getRandomWalkable()` + +### `SocketServer.ts` — `spawn-npc` handler +- Count NPC entities; reject if >= `MAX_NPC_COUNT` +- Compute target tile: `map.findNearestWalkable(x, y, 3)` ?? `map.getRandomWalkable()` +- Call `spawnNPC(world, map, targetTile)` + +## Client Changes + +### `GameScene.ts` +- Listen for `1` key in camera mode +- Compute center tile from camera: `Math.floor((cam.scrollX + cam.width/2) / TILE_SIZE)` +- Emit `spawn-npc` via socket client +- Show `CommandPanel` on entering camera mode, hide on leaving + +### `SocketClient.ts` +- Add `spawnNpc(x, y)` method that emits `spawn-npc` + +### `CommandPanel.ts` (new file) +- HTML/CSS overlay, bottom-right corner +- Same EarthBound aesthetic as `NpcInfoPanel`: `EB` color palette, "Press Start 2P" font, double borders +- Compact list of commands with hotkeys +- `show()` / `hide()` methods + +## Out of Scope + +- Spawn animation or visual feedback +- Client-side error handling if cap reached +- Sound effects +- Cooldown between spawns