Files
settled-reach/docs/sprints/sprint-7/client.md
T
jpmschweitzerandClaude Opus 4.6 88fc344ed9 docs(sprints): add protocol v7 bump requirement to client briefing
Server PR #23 bumped PROTOCOL_VERSION to 7 (pending_recognitions field).
Client must match before #431 fog entity visualization or joint testing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 01:08:29 +01:00

284 lines
13 KiB
Markdown

# Sprint 7: Talk — Client Tasks
**Goal:** Complete interaction UI layer and activate basic dialogue system with NPC conversations.
**Branch:** `client`
**Agents:** Stig (dev), Tyre (arch), Hoshe (QA)
## Carry-over from Sprint 6
| # | Title | Status | Notes |
|---|-------|--------|-------|
| #429 | Cursor state machine — 4 states, Araminta spec, 150ms transitions | backlog | Blocks #432 entity interaction list |
| #430 | Fog shader rebuild — 5-layer, CanvasGroup Layer 5, animated noise | backlog | Blocks #431 fog entity visualization; CRITICAL — full shader rewrite |
| #432 | Entity interaction vertical list — insert-styled, z-layer 6 | backlog | Blocked by #429; integration with server verb system |
| #433 | World radial menu — 2 spokes v0.1 (Observe + Insert) | backlog | Standalone ticket, no blockers |
| #438 | Inventory UI — 3x3 grid, 1-9 hotkeys | backlog | Wire data from ObserverSnapshot v6 (Sprint 6 done) |
| #439 | Stance toggle UI — keybind + HUD indicator | backlog | Wire data from ObserverSnapshot v6 (Sprint 6 done) |
## New Tickets
| # | Title | Blocked by |
|---|-------|------------|
| #431 | Fog entity visualization — sound pings, recognized/unrecognized, cognitive delay anim | #430, #423 (server) |
| #434 | Dialogue box — max 20% height, max-width, NPC speech + options + monologue | — |
Use `db/connectors/ticket show <id>` for full details.
## Key Decisions
- `decisions/perception.md` — D-056 (cursor states), D-057 (entity interaction list), D-058 (world radial menu), D-059 (fog shader), D-060 (cognitive delay), D-061 (dialogue box), D-049 (z-level rendering stack)
- `decisions/architecture.md` — D-042 (UI microcopy format), D-066 (dual-scale grid)
## Notes
### #429: Cursor state machine (Sprint 6 carry-over)
**What exists:**
- Default cursor (basic mouse pointer)
- Entity hover detection in `client/scripts/rendering/world_renderer.gd`
- D-033 entity color system (relationship-based)
**What the ticket needs:**
- Four cursor states per D-056:
- **Default:** Four thin inward-pointing ticks, white-blue #c8d0e0, bloom shader
- **Entity hover:** Ticks expand outward (150ms), corner brackets, D-033 color shift
- **Object hover:** Ticks rotate 45° to X-shape, muted grey #8b8ba0
- **Weapon aim:** Hard transition, ticks extend, center gap widens, warm white #f0e8d8, no bloom
- Transition timing: 150ms linear for all state changes
- z-layer 7 (above insert overlay)
- LOS-based triggering (cursor state changes on line-of-sight, not just proximity)
**Integration points:**
- Blocks #432 (interaction list anchors to cursor position)
- Uses D-033 entity color data from ObserverSnapshot
- Weapon aim mode: deferred to future sprint (no weapon selection in Sprint 7)
**Gotchas:**
- Cursor is diegetic (insert's own interface per D-056) — it's NOT a traditional OS cursor
- Bloom effect: PointLight2D or CanvasItemMaterial shader
- State transitions must be smooth (no jarring snaps)
### #430: Fog shader rebuild (Sprint 6 carry-over, CRITICAL)
**What exists:**
- `client/scripts/rendering/fog_renderer.gd` — current TileMapLayer-based fog (Sprint 2)
- Basic vision cone rendering
- D-011 fog of perception foundation
**What the ticket needs:**
- COMPLETE REBUILD per D-059 — replace TileMapLayer approach with CanvasGroup + fragment shader
- Five fog layers:
1. **Clear (vision cone):** Soft gradient edge over 6-8 sim tiles (= 3-4 visual tiles per D-066), PointLight2D approach
2. **Light fog (peripheral):** Desaturated 40-50%, brightness -30%, animated Perlin noise (8-10s cycle)
3. **Deep fog (explored):** Near-monochrome + 10% zone temperature tint, slower noise (15-20s cycle)
4. **Unexplored + maps:** Geometric wireframe outlines #333340, insert aesthetic
5. **Unexplored, no maps:** Solid near-black #12141a
- CanvasGroup on Layer 5 per D-049 z-stack
- Fragment shader for noise animation (use OpenSimplex or Perlin noise function)
- Performance target: <1ms/frame total fog rendering
**Integration points:**
- Blocks #431 (fog entity visualization renders on top of fog shader)
- Uses FogState autoload (`client/scripts/autoloads/fog_state.gd`)
- Vision cone data from ObserverSnapshot
**Gotchas:**
- This is a LARGE rewrite — current fog system is discarded completely
- Test performance early (Godot profiler) — noise shaders can be expensive
- Zone temperature tint data: hardcoded per location for v0.1 (bar=warm, hub=cool, corridor=neutral)
- Unexplored vs explored state tracked in FogState autoload
### #432: Entity interaction vertical list (Sprint 6 carry-over)
**What exists:**
- Interaction prompt system (`client/scripts/protocol/interaction_prompt.gd` from Sprint 5)
- ObserverSnapshot.nearby_interactions field (populated by server two-phase verb computation, Sprint 6 #422)
- D-057 vertical list spec
**What the ticket needs:**
- Vertical list UI (2-4 verb options max) anchored to entity position
- Insert-styled rendering (geometric aesthetic per D-048, D-056)
- New option highlighting: gradient glow background when verb appears for first time
- z-layer 6 (insert overlay layer)
- Click verb → send PlayerAction::Interact with target entity + verb name
- Diegetic test: list disappears when insert is off
**Integration points:**
- Blocked by #429 (cursor states define hover detection that triggers list)
- Uses server ObserverSnapshot.nearby_interactions data (Sprint 6 #422 done)
- Verb data includes: verb name, display text, tooltip (optional)
**Gotchas:**
- Anchoring to entity position: use screen-space transform from world coordinates
- Max 3 visible options in dialogue context (different from world interaction which shows 2-4)
- Highlight new options without moving geometry (UX constraint per D-057)
### #433: World radial menu (Sprint 6 carry-over)
**What exists:**
- Right-click detection in input_mapper.gd autoload
- Insert overlay rendering foundation
**What the ticket needs:**
- Radial menu with 4 spokes per D-058 (v0.1: 2 spokes only)
- Spokes: Observe (eye icon), Insert (phone icon); deferred: Comms, Wait
- Insert-styled: geometric lines, thin spokes, nearly transparent
- z-layer 6 (insert overlay)
- Interaction modes: drag-release (power users) and click-click (newcomers)
- Right-click world tile → menu opens at cursor position
**Integration points:**
- Standalone (no blockers)
- Uses insert visual aesthetic (D-048, D-056)
- Observe action: future integration with perception modes (not Sprint 7)
- Insert action: opens insert UI (future integration)
**Gotchas:**
- Drag-release: detect drag distance + direction, select spoke on release
- Click-click: first click opens, second click on spoke selects
- Menu must close on Esc or click outside
- v0.1 only 2 spokes (Observe + Insert), but structure supports 4-6 spokes for future
### #438: Inventory UI (Sprint 6 carry-over)
**What exists:**
- `client/scripts/autoloads/game_state.gd` — receives ObserverSnapshot
- ObserverSnapshot v6 with player_inventory field (Sprint 6 #449 done)
- D-065 inventory spec (3x3 grid, 1-9 hotkeys)
**What the ticket needs:**
- 3x3 grid UI, bottom-right screen position
- Item icons rendered from ObserverSnapshot.player_inventory data
- 1-9 number key direct access (highlight selected slot)
- Empty slots not displayed (icons appear when items carried per D-065)
- Insert-styled rendering (geometric frames, D-048)
- z-layer 6 (insert overlay)
**Integration points:**
- Wire data from ObserverSnapshot v6 (already exists, Sprint 6 #449)
- Item icon assets: placeholder colored squares for v0.1 (real sprites deferred)
- Selection feedback: highlight border on selected slot
**Gotchas:**
- ObserverSnapshot.player_inventory is Vec<VisibleItem> (item_id, icon_path, name)
- Icons appear dynamically as items are carried (grid is NOT always 9 slots visible)
- Number keys 1-9 map to grid positions (top-left to bottom-right, row-major)
### #439: Stance toggle UI (Sprint 6 carry-over)
**What exists:**
- `client/scripts/autoloads/game_state.gd` — receives ObserverSnapshot
- ObserverSnapshot v6 with player_stance field (Sprint 6 #449 done)
- D-053 stance system (Sprint/Walk/Careful/Crouch)
**What the ticket needs:**
- HUD indicator showing current stance (text label + icon)
- Position: top-left or top-right (TBD, not bottom where dialogue appears)
- Keybind: C key or Ctrl key to cycle stances
- Stance labels: Sprint/Walk/Careful/Crouch (or per OQ-25 resolution if answered)
- Insert-styled rendering
- z-layer 7 (UI layer, always visible)
**Integration points:**
- Wire data from ObserverSnapshot v6 (already exists)
- Keybind sends PlayerAction::ToggleStance to server
- Visual feedback: stance name + movement speed indication
**Gotchas:**
- OQ-25 (stance name "Careful" or "Sneak") is low-priority open question — use "Careful" for now
- Stance affects movement speed visibly — player should see slower/faster movement after toggle
- UI updates on ObserverSnapshot.player_stance change (not client prediction)
### #431: Fog entity visualization
**What exists:**
- Fog shader foundation (#430, blocked until that ticket completes)
- Sound propagation events in ObserverSnapshot (D-018 three-range model)
- D-033 entity color system
**What the ticket needs:**
- Sound pings per D-059: 2-3 thin concentric expanding rings (sonar-style), insert white-blue
- Recognized entity rendering: D-033 color glow + faint silhouette + 0.8s breathing pulse + ±0.5 tile position drift
- Unrecognized entity rendering: neutral grey #555566 blob, no silhouette
- Recognition transition governed by server cognitive delay (#423)
- Render layer: on top of fog shader, below insert overlay (between Layer 5 and Layer 6)
**Integration points:**
- Blocked by #430 (fog shader), #423 (server cognitive delay)
- Uses ObserverSnapshot.pending_recognitions data (server #423 provides this)
- Uses D-033 entity color for recognized entities
- Sound events from ObserverSnapshot.sound_events
**Gotchas:**
- Cognitive delay visualization: grey blob → color + silhouette transition over ~0.3s
- Position drift is client-side interpolation (server provides approximate position, not exact)
- Sound ping animation: spawn sprite, expand + fade over 1.5s, then remove
- Recognized silhouette: use simplified sprite (just identifying feature like "vest" or "apron")
### #434: Dialogue box
**What exists:**
- Monologue display system (`client/scripts/rendering/` — Sprint 3-4)
- D-061 dialogue box spec
- D-062 invisible locked options
- D-064 walk-away mechanic
**What the ticket needs:**
- Dialogue UI at bottom screen, max 20% height, max-width (exact pixel value per OQ-29 or reasonable default)
- Layout: NPC speech top, player response options below, left-aligned
- Max 3 response options visible
- NO portraits (NPC is on screen)
- Monologue floats ABOVE dialogue box (z-layer 7) — spatial separation
- Walk-away: WASD during dialogue → fade over 300ms, no close button
- z-layer 6 (insert overlay — dialogue box is diegetic)
**Integration points:**
- Server dialogue system (future sprint #305) will populate dialogue data
- For Sprint 7: build UI skeleton, test with mock NPC dialogue data
- Walk-away sends PlayerAction::DialogueEnd to server
- Monologue continues above dialogue (both can be visible simultaneously)
**Gotchas:**
- OQ-29 (dialogue max-width pixel value) is low-priority — use 60-70% screen width as reasonable default
- NO close button — only way to exit is walk-away (WASD) or select dialogue option
- Response options are buttons/selectable text, not just labels
- Auto-pause integration: future sprint (single-player pause when dialogue active)
## Protocol Version Bump (REQUIRED)
Server PR #23 bumped `PROTOCOL_VERSION` from 6 to 7 (new `pending_recognitions` field in `ObserverSnapshot`). The client **must** update to match before the next joint test.
**File:** `client/scripts/protocol/protocol.gd:14`
**Change:** `const PROTOCOL_VERSION: int = 6``const PROTOCOL_VERSION: int = 7`
This is a prerequisite for #431 (fog entity visualization), which reads `pending_recognitions` to render cognitive delay grey blobs. Without the bump, the client will reject server handshakes or silently corrupt snapshot data.
## Dependency Chain
```
Carry-over critical path:
#429 (cursor states) → #432 (interaction list)
#430 (fog shader rebuild) → #431 (fog entity viz)
Parallel standalone:
#433 (world radial menu)
#438 (inventory UI)
#439 (stance UI)
#434 (dialogue box)
Server dependency:
#423 (server cognitive delay) → #431 (fog entity viz)
Protocol sync (REQUIRED before joint test):
Protocol v7 bump → #431 (fog entity viz)
```
## Sprint 7 Client Load
Sprint 7 has **8 client tickets** (6 carry-overs + 2 new), making it the heaviest client sprint yet. Focus on:
1. **Finishing Sprint 6 UI carry-overs** (cursor, fog, interaction list, radial menu, inventory, stance)
2. **Fog shader rebuild (#430)** is the largest technical risk — complete rebuild, performance-sensitive
3. **Dialogue box (#434)** lays foundation for Sprint 8 dialogue system activation
If #430 (fog shader) proves too complex, scale back noise animation (simpler shader) or defer #431 to Sprint 8.
## PR Workflow
When ready to submit, create a PR with `tea` CLI. All flags are required to avoid TTY prompts:
```bash
tea pr create --repo jpmschweitzer/settled-reach --login schweitz --title "feat(client): Sprint 7 — UI completion (cursor, fog, interaction, radial, inventory, stance, dialogue)" --description "See docs/sprints/sprint-7/client.md" --base main --head client
```