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

13 KiB

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 (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 = 6const 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:

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