Full audio architecture sprint: AudioManager completion, zone crossfade, dip profiles, recognition chime, murmur pipeline. Server gauntlet expansion and OQ-09 resolution. Visual monologue display spec unblocks copy pipeline. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
61 lines
5.5 KiB
Markdown
61 lines
5.5 KiB
Markdown
# Sprint 13: Sound — Client Tasks
|
|
|
|
**Goal:** Wire the full audio architecture end-to-end — AudioManager, zone crossfades, dip profiles, recognition chime, and conversation murmur — and complete v0.1 content authoring so opening hooks, tutorial monologue, and all content packs are done.
|
|
|
|
**Branch:** `client`
|
|
**Agents:** Stig (client dev), Tyre (architect), Hoshe (QA)
|
|
|
|
## Carry-over from Sprint 12
|
|
|
|
None. All Sprint 12 client tickets done.
|
|
|
|
## New Tickets
|
|
|
|
| # | Title | Blocked by |
|
|
|---|-------|------------|
|
|
| #528 | AudioManager full implementation — 5-bus setup, directory registry, volume sliders | — |
|
|
| #529 | Zone crossfade implementation — 1.5-2s tween on zone_id change | #528 |
|
|
| #530 | Audio dip profiles — dialogue, confrontation, ListeningFocus boost | #528 |
|
|
| #531 | Recognition chime — fires at cognitive delay onset (D-067) | #528 |
|
|
| #533 | Wire NPC conversation murmur to World SFX bus — event-driven playback | #528, #532 (audio) |
|
|
|
|
Use `db/connectors/ticket show <id>` for full details.
|
|
|
|
## Key Decisions
|
|
|
|
- `decisions/architecture.md` — D-068 (5-bus audio architecture), D-073 (zone crossfade approach)
|
|
- `decisions/perception.md` — D-067 (recognition chime timing), D-069 (audio dip profiles), D-070 (confrontation as cognitive vulnerability), D-071 (ListeningFocus boost), D-072 (NPC conversation murmur)
|
|
|
|
## Notes
|
|
|
|
- **#528 — AudioManager full implementation:** `client/scripts/autoloads/audio_manager.gd` already exists and is substantially built. The 5-bus setup, directory-scan registry, `play()`, `play_at()`, `apply_dip()`, `clear_dip()`, and `set_volume()` methods are all implemented. What remains: (1) `set_zone()` is a stub (`pass`) — this becomes the zone crossfade implementation for #529; (2) volume slider persistence (save/load player preferences); (3) settings UI bindings for the 5 sliders; (4) ensure the Godot project's AudioServer bus layout matches the 5 bus names in code. Before starting, verify bus names in `Project > Audio` match `BUS_MUSIC`, `BUS_AMBIENT`, `BUS_WORLD_SFX`, `BUS_PLAYER_ACTIONS`, `BUS_UI_SOUNDS`.
|
|
|
|
- **#529 — Zone crossfade:** Implement `set_zone(zone_id: String)` in `audio_manager.gd`. `SimBridge` already receives tile data from `ObserverSnapshot` — determine the player's current tile zone and call `AudioManager.set_zone()` on zone change. Crossfade logic: kill any active ambient tweens, start a 1.5-2s `create_tween()` that fades out the current `_ambient_players` entry and fades in the new zone asset. Zone-to-asset mapping for v0.1: hub/workplace → `amb_hub_layer`, bar → `amb_bar_layer`, smuggling corridor → `amb_corridor_layer` (names must match filenames in `res://audio/`). Crossfade is interruptible — walking back across a boundary starts the reverse tween.
|
|
|
|
- **#530 — Audio dip profiles:** `DIP_SPECS` and `apply_dip()` / `clear_dip()` are already implemented in `audio_manager.gd`. What remains: wire call sites. Dialogue open/close → `apply_dip("dialogue")` / `clear_dip()`. Confrontation start/end → `apply_dip("confrontation")` / `clear_dip()`. ListeningFocus: the tick gate (30+ stationary ticks) is the caller's responsibility (per existing comment in `audio_manager.gd`); `sim_bridge.gd` or `game_state.gd` must track `stationary_ticks` from the server's `ListeningFocus` field in the snapshot and call `apply_dip("listening_focus")` / `clear_dip()` accordingly. D-070: no UI indicator — the muffling is felt, not announced.
|
|
|
|
- **#531 — Recognition chime:** `CHIME_RECOGNITION = "sfx_monologue_chime"` is already defined in `audio_manager.gd`. Wire it: when `fog_entities.gd` or `entity_renderer.gd` begins a recognition sequence (detecting `RecognitionTrigger` in the snapshot), call `AudioManager.play(AudioManager.CHIME_RECOGNITION)` at the ONSET of the cognitive delay — not at completion. The chime routes to the `UISounds` bus automatically (default bus in `play()`). Full sequence per D-067: entity detected → chime plays (300-400ms) → 0.6s cognitive delay begins concurrently → monologue text appears during delay → blob transitions to D-033 color + silhouette → recognition complete. The chime is the "unresolved" signal — it precedes recognition, does not confirm it.
|
|
|
|
- **#533 — NPC murmur wiring:** Blocked by #532 (audio team produces the asset). Once the murmur asset exists in `res://audio/`, wire event-driven playback: when `SimBridge` receives conversation/voice events from `ObserverSnapshot`, call `AudioManager.play_at(asset_key, world_pos, BUS_WORLD_SFX)` for proximity or `AudioManager.play(asset_key, BUS_WORLD_SFX)` for ambient murmur. Single universal asset — zone ambient provides natural conspicuousness (bar's `amb_bar_layer` buries it, corridor's low ambient exposes it). No zone-specific murmur variants.
|
|
|
|
## Dependency Chain
|
|
|
|
```
|
|
#528 (AudioManager — complete set_zone + settings UI + slider persistence)
|
|
→ #529 (zone crossfade — implement set_zone body)
|
|
→ #530 (dip profiles — wire call sites in sim_bridge / game_state)
|
|
→ #531 (recognition chime — wire ONSET trigger in fog_entities / entity_renderer)
|
|
→ #533 (murmur wiring) ← also blocked by #532 (audio team asset)
|
|
```
|
|
|
|
#528 can start immediately. #529, #530, #531 can proceed in parallel once #528 is done.
|
|
#533 waits for both #528 and #532.
|
|
|
|
## 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):
|
|
|
|
```bash
|
|
tea pr create --repo jpmschweitzer/settled-reach --login schweitz --title "feat(audio): description" --description "body" --base main --head client
|
|
```
|