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>
5.5 KiB
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.gdalready exists and is substantially built. The 5-bus setup, directory-scan registry,play(),play_at(),apply_dip(),clear_dip(), andset_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 inProject > AudiomatchBUS_MUSIC,BUS_AMBIENT,BUS_WORLD_SFX,BUS_PLAYER_ACTIONS,BUS_UI_SOUNDS. -
#529 — Zone crossfade: Implement
set_zone(zone_id: String)inaudio_manager.gd.SimBridgealready receives tile data fromObserverSnapshot— determine the player's current tile zone and callAudioManager.set_zone()on zone change. Crossfade logic: kill any active ambient tweens, start a 1.5-2screate_tween()that fades out the current_ambient_playersentry 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 inres://audio/). Crossfade is interruptible — walking back across a boundary starts the reverse tween. -
#530 — Audio dip profiles:
DIP_SPECSandapply_dip()/clear_dip()are already implemented inaudio_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 inaudio_manager.gd);sim_bridge.gdorgame_state.gdmust trackstationary_ticksfrom the server'sListeningFocusfield in the snapshot and callapply_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 inaudio_manager.gd. Wire it: whenfog_entities.gdorentity_renderer.gdbegins a recognition sequence (detectingRecognitionTriggerin the snapshot), callAudioManager.play(AudioManager.CHIME_RECOGNITION)at the ONSET of the cognitive delay — not at completion. The chime routes to theUISoundsbus automatically (default bus inplay()). 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: whenSimBridgereceives conversation/voice events fromObserverSnapshot, callAudioManager.play_at(asset_key, world_pos, BUS_WORLD_SFX)for proximity orAudioManager.play(asset_key, BUS_WORLD_SFX)for ambient murmur. Single universal asset — zone ambient provides natural conspicuousness (bar'samb_bar_layerburies 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):
tea pr create --repo jpmschweitzer/settled-reach --login schweitz --title "feat(audio): description" --description "body" --base main --head client