Standardized YAML frontmatter on all 115 sprint briefing files across sprints 1-26 with title, description, type, status, sprint number, and team fields. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
10 KiB
10 KiB
title, description, type, status, sprint, team
| title | description | type | status | sprint | team |
|---|---|---|---|---|---|
| Sprint 8 — Client Briefing | Dialogue response selection, walk-away mechanic, confrontation text styling | sprint | archived | 8 | client |
Sprint 8: React — Client Tasks
Goal: Activate the dialogue pipeline end-to-end — player talks to NPCs, NPCs respond, the world reacts.
Branch: client
Agents: Stig (dev), Tyre (arch), Hoshe (QA)
Carry-over from Sprint 7
| # | Title | Status | Notes |
|---|---|---|---|
| #431 | Fog entity visualization — sound pings, cognitive delay anim | in_progress | Protocol v7 bump + visualization implementation |
New Tickets
| # | Title | Blocked by |
|---|---|---|
| #435 | Dialogue response selection — max 3 visible, invisible locks | #434 (done) |
| #437 | Walk-away mechanic — WASD detect during dialogue, 300ms fade | — |
| #436 | Confrontation text styling — italic voice, monologue beat | #435 |
Use db/connectors/ticket show <id> for full details.
Key Decisions
decisions/content.md— D-062 (invisible locked dialogue options), D-063 (confrontation same box different weight), D-064 (walk-away 3-phase consequences)decisions/perception.md— D-059 (fog shader 5 layers), D-060 (cognitive delay), D-061 (dialogue box max 20% height)decisions/architecture.md— D-066 (dual-scale grid 0.5m sim / 1m visual)
Open Questions to Resolve Early
None.
Notes
#431: Fog entity visualization — sound pings, cognitive delay anim (HIGH, carry-over)
What exists:
client/scripts/rendering/fog_shader.gd— FogShader node with 5-layer shader (D-059), noise animationclient/scripts/protocol/protocol.gd— MessagePack decoder for ObserverSnapshot (protocol v6)- Fog layers 1-3 (clear, light fog, deep fog) render via shader, no entity visualization yet
What the ticket needs to deliver:
- Protocol v7 bump: Add
pending_recognitionsandsound_eventsfields to ObserverSnapshot in protocol.gd decode logic - Sound ping rendering: On FogState layer 6 (insert overlay, NOT affected by fog shader), render 2-3 thin concentric expanding rings from sound source direction. Sonar-style. Insert white-blue color. Loud = 3 rings bright fast. Quiet = 1 ring faint slow. Fade over 1.5s. Use simple Sprite2D or Line2D, not particles.
- Recognized entity in fog: Entity with
pending: falserenders on layer 6 as: D-033 color glow (via PointLight2D ~40% blend) + faint silhouette feature (cached sprite at ~20% opacity) + 0.8s breathing pulse (shader uniform or tween) + ±0.5 tile position drift (approx position, not exact). Silhouette feature: Kael's vest, Lera's apron (sprite metadata from entity.silhouette_feature field). - Unrecognized entity in fog: Entity with
pending: truerenders as neutral grey #555566 blob (simple circle sprite, no identifying features). No silhouette. No D-033 color. - Recognition transition: When
pendingflips from true → false, tween grey blob → color+silhouette over 0.3s (within the 0.6s cognitive delay window per D-060). Monologue fires during this tween.
Integration points:
- Pairs with server #423 (cognitive delay system, done Sprint 7)
- Protocol v7 wire format must match server ObserverSnapshot struct additions
- Builds on fog shader from Sprint 6
Non-obvious gotchas:
- Sound pings and fog entities render on layer 6 (insert overlay), NOT layer 5 (fog shader). Insert data is computational, not perceptual — not affected by vision cone.
- ±0.5 tile drift is VISUAL only (client-side randomness for "approximate" feel). Server sends exact position; client adds noise.
- Silhouette feature sprite is entity metadata, not a full sprite. Think "identifying accessory" not "full character render."
- Tween recognition over 0.3s to align with monologue timing (D-060: monologue fires DURING delay, not after)
#435: Dialogue response selection — max 3 visible, invisible locks (HIGH)
What exists:
client/ui/interaction_list.gd— Vertical list for entity interaction verbs (Talk, Observe, etc.)client/scripts/protocol/protocol.gd— Decodes NearbyInteraction from snapshot- D-061 dialogue box spec: bottom screen, max 20% height, max-width, no portraits
What the ticket needs to deliver:
- New scene:
dialogue_box.tscn— Bottom-screen container with two sections: NPC speech (Label, top), player response options (VBoxContainer, bottom). Max 20% viewport height, max-width (exact value: viewport width minus 40px margin). Left-aligned text. Insert-styled per D-057/D-061. - Response option rendering: Each response is a Button (or custom Control with hover state). Show max 3 visible options. Sort by priority (server provides sorted list). D-062: locked options are invisible (not rendered at all). No grayed-out options. No lock icons. Player doesn't know what they don't know.
- New protocol field:
dialogue_responsein ObserverSnapshot — array of {text: String, response_id: String, priority: int}. Decode in protocol.gd. - Integration: When player selects Talk verb from interaction_list, server sends snapshot with dialogue_response populated. Client shows dialogue_box, hides interaction_list. Player clicks response → send PlayerInput::DialogueResponse{response_id}.
- Monologue interaction: Monologue floats ABOVE dialogue box on z-layer 7 (spatial separation, D-061). Both can be visible simultaneously — character thinks one thing while NPC says another.
Integration points:
- Blocked by #434 (interaction verb execution, done Sprint 7)
- Pairs with server #305 (dialogue selection pipeline)
- Blocks #436 (confrontation styling)
Non-obvious gotchas:
- Max 3 VISIBLE means if server sends 5 options, show top 3 by priority. But D-062 invisible locks mean server should never send locked options at all (server filters before protocol). Client just renders what it receives.
- Player response text can be variable length (confrontation lines are longer than casual small talk). Use word wrap, auto-expand button height.
- No close button per D-064 — walk-away is the exit. Dialogue box stays until player walks away or server sends empty dialogue_response (conversation ended).
#437: Walk-away mechanic — WASD detect during dialogue, 300ms fade (MEDIUM)
What exists:
- Input handling in
client/scripts/main.gdcaptures WASD for movement, sends PlayerInput::Move - Dialogue box (#435) renders dialogue but doesn't handle walk-away yet
What the ticket needs to deliver:
- Input override: When dialogue_box is visible, WASD input triggers walk-away instead of movement. Send PlayerInput::WalkAway{npc_id} to server.
- Visual fade: Dialogue box fades out over 300ms (Tween modulate alpha 1.0 → 0.0). No sound. Silence. D-064 phase 1.
- NPC may react: Server may send updated NPC animation or monologue after walk-away (D-064 phase 2). Client renders these as normal snapshot updates — no special walk-away animation on client.
- KG recording: Server handles D-064 phase 3 (#427). Client just sends WalkAway input.
Integration points:
- Pairs with server #427 (walk-away KG recording)
- Depends on #435 (dialogue box exists)
Non-obvious gotchas:
- Walk-away is ANY WASD press during dialogue, not just "walk away from NPC." Even pressing W (toward NPC) triggers walk-away. The direction doesn't matter — the intent to move ends the conversation.
- After WalkAway input sent, dialogue box fades but player can't move until fade completes (300ms input block). Prevents "walk through NPC" edge case.
- If server sends new dialogue_response during fade (NPC talks again), cancel fade and re-show dialogue. Rare edge case but possible (NPC calls after player).
#436: Confrontation text styling — italic voice, monologue beat (MEDIUM)
What exists:
- Dialogue box (#435) renders NPC speech + player responses
- D-063 spec: confrontation uses same UI, different weight via styling + monologue beat
What the ticket needs to deliver:
- Confrontation option styling: Response options marked as
confrontation: true(new protocol field) render in italic + first-person voice. Example: regular = "Shift schedule", confrontation = "I saw you in corridor B-7" (italic BBCode tag). - Pre-delivery monologue beat: When player clicks confrontation option, 1-2 second pause before sending DialogueResponse input. During pause, show monologue: "This changes things. No taking it back." (hardcoded v0.1 line, future from content pools). Monologue displays on layer 7, dialogue box dims slightly (reduce opacity to 70%).
- Audio dip: Ambient audio volume drops to 50% during confrontation selection (via AudioServer bus manipulation). Restore after response sent.
- No camera change: D-063 defers camera tighten to post-v0.1. Same camera position throughout.
Integration points:
- Blocked by #435 (dialogue box)
- Pairs with server #305 (dialogue pipeline marks confrontation lines)
Non-obvious gotchas:
- Monologue beat is client-side delay (pause before sending input). Server doesn't know about the pause — from server's view, DialogueResponse arrives 1-2s after Talk verb.
- Italic rendering: use BBCode
[i]...[/i]in RichTextLabel. Standard Label doesn't support italics. - Don't apply italic to NPC speech — only to player confrontation responses. Regular dialogue responses stay non-italic.
- Audio dip is temporary (duration of monologue beat only). Restore ambient volume after response sent, not after NPC replies.
Dependency Chain
#431 (fog visualization) → standalone, protocol v7 prerequisite for other features
#435 (dialogue box) → #437 (walk-away) depends on this, #436 (confrontation styling) depends on this
#437 (walk-away) → standalone once #435 exists
#436 (confrontation styling) → depends on #435
PR Workflow
When ready to submit, create a PR with tea CLI. All flags are required to avoid TTY prompts (see CLAUDE.md "Gitea access" section):
tea pr create --repo jpmschweitzer/settled-reach --login schweitz --title "feat(ui): dialogue pipeline client (Sprint 8 client)" --description "Implements #431 #435 #437 #436 — fog entity viz, dialogue response selection, walk-away, confrontation styling" --base main --head client