# 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 ` 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 (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 ```