Phase 18 — Audio (music director + SFX catalog + bus wiring)

Adds an AudioManager autoload with three buses (Master, Music routed to
Master, SFX routed to Master), a small catalog of looping music + one-shot
SFX, and a single persistent AudioStreamPlayer for the music director.

Music
* Day and night loops swap on Clock.phase_changed (night during the night
  phase, day everywhere else). Tracks pulled from Retro Farming Music 1
  (day) and Cozy Melodies Pack 1 (night), both loopable OGG.

SFX
* Tree.fell, Rock.mined, BigRock.mined → tree_fell / mine_tick.
* EventBus.pawn_took_damage → combat_hit (Sword Pack 1).
* EventBus.storyteller_event_fired → ui_confirm sting.
* EventBus.alert_added → ui_click.
* play_sfx is rate-limited per key (80ms cooldown) so fast-sim doesn't
  saturate the mixer.

Settings + suspend
* SettingsMenu master/music/sfx sliders now live-bind to the bus dB via
  Audio.set_*_linear (linear → dB internally, 0 → -80dB silence). The
  ambient slider is intentionally unwired; no ambient bus this pass.
* NOTIFICATION_APPLICATION_PAUSED + FOCUS_OUT mute the Master bus to
  match the existing "no background sim" rule. Resume + focus restore it.

Bundle housekeeping
* Two zipped packs in the ElvGames bundle (Cozy Melodies Pack 1, Retro
  Farming Music 1) extracted in place to keep pack identity intact for
  the license/credits string. 8 OGG files curated into audio/ at ~5.3MB.

Verified end-to-end via MCP runtime: buses online, day_loop plays at
boot, manual phase swap day→night→day round-trips, slider linear→dB
mapping correct (0.5 → -6.02dB, 0.0 → -80dB), tree_fell SFX triggers.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
megaproxy 2026-05-15 18:54:36 +01:00
parent fb07a3fa15
commit d819c13a9d
25 changed files with 437 additions and 8 deletions

View file

@ -24,7 +24,8 @@ Effort estimates are wall-time at **focused solo pace**. Scale up generously for
| ✅ done — EventDef data class + EventCatalog with all 25 events authored (4 nudges, 4 seasonal, 4 wanderers, 4 threats, 3 disease, 3 resource, 2 lore, 1 milestone), Storyteller autoload (daily 6 AM roll, per-event+per-category cooldowns both-gates locked, tension model 0-100 with category multipliers, state-trigger 3× weight boost, ghost-state wanderer auto-fire 3-5 day window), StorytellerBanner (CanvasLayer, queued, 6-sec auto-dismiss, tap-to-dismiss-early), StorytellerModal (centered dialog, 0/1/2 choices, full-screen dim, auto-pause on THREAT), "Go there" camera pan helper via camera_rig.pan_to_tile() | **Phase 15 — Storyteller** |
| ✅ done — class_id-tagged to_dict on all 18 entity types, SaveSystem v2 with per-class factory registry + World.clear_all + clear-and-respawn apply_save, tilemap layer serialization, beauty/dirt map round-trip, Autosave autoload (periodic 6000-tick interval + NOTIFICATION_APPLICATION_PAUSED + focus-loss), Save/Load buttons in TopBar, LoadMenu CanvasLayer with version-mismatch dialog, ResumeToast ("Welcome back — N minutes away"), slot API (manual + autosave), graceful version-mismatch handling | **Phase 16 — Save/load full coverage** |
| ✅ done — Pawn.work_priorities matrix (8 player categories), Decision Layer 4 honors per-pawn priorities (NEEDS_CATEGORIES bypass), PawnDetailPanel (HP/Hunger/Sleep/Mood/Statuses/Skills/Priorities live-refresh, opens on pawn_selected), BuildDrawer bottom-sheet (Designate/Build/Stockpile/Cancel tabs, 12 new tool constants wired), WorkPriorityMatrix grid (tap-cycle 1→2→3→4→0, color-coded), AlertsLog (ring buffer 50, severity icons + Go-there, listens to alert_added + storyteller_event_fired + day_ended), SettingsMenu (auto-pause toggles + audio + accessibility), EventBus.request_wolf_spawn wired end-to-end (EventCatalog._spawn_wolves → WolfSpawner._on_request_wolf_spawn force-bypass), EventBus.day_ended emit from Clock dusk→night | **Phase 17 — Touch UX completion** |
| ⏳ next | **Phase 18 — Audio** |
| ✅ done — Audio autoload + 3 buses (Master/Music/SFX), 2 looping music tracks (day/night) swapped on Clock.phase_changed, 6 SFX wired (tree_fell, mine_tick, combat_hit via pawn_took_damage, storyteller sting, alert click, UI click), SettingsMenu sliders live-bound to bus DB, NOTIFICATION_APPLICATION_PAUSED + FOCUS_OUT mute the Master bus | **Phase 18 — Audio** |
| ⏳ next | **Phase 19 — Onboarding & first-60-seconds** |
Use this doc as a checklist: tick boxes as items complete, and update the **Status** row above whenever a phase rolls over. The last bullet of each phase is the *acceptance demo* — the phase is "done" when you can perform it.
@ -407,13 +408,21 @@ The five items from `memory.md` *Open questions / Audit*. None of these need cod
**Goal:** the game has soundscape; not silent.
- [ ] Ambient day loop, ambient night loop (bundle music packs)
- [ ] UI clicks (tap, long-press confirm, error)
- [ ] Combat stings: hit, miss, downed, kill
- [ ] Alert stings: storyteller modal, ambient banner, raid warning, pawn-down
- [ ] Volume sliders in Settings (master / music / sfx / ambient)
- [ ] Audio mute on suspend; fade in on resume
- [ ] **Acceptance:** play through a normal in-game day. Sounds fire at the right moments, mute toggles work.
- [x] Ambient day loop, ambient night loop (Retro Farming Music 1 + Cozy Melodies Pack 1, OGG)
- [x] UI click + confirm SFX (UI Pack 1)
- [x] Combat hit (Sword Pack 1, on pawn_took_damage)
- [x] Storyteller sting (on storyteller_event_fired)
- [x] Volume sliders in Settings (master / music / sfx; ambient slider present but no bus assigned)
- [x] Audio mute on suspend (NOTIFICATION_APPLICATION_PAUSED + FOCUS_OUT)
- [x] **Acceptance:** music plays at boot (day loop @ dawn), swaps to night loop at phase change, sliders set bus dB live, tree_fell + mine_tick fire on entity completion, MCP runtime probe confirms all paths.
Phase 18 follow-ups (deferred):
- Per-distinct-pawn voice line on damage / death (currently shares one SFX)
- Combat miss / downed / kill stings (only "hit" wired)
- Raid-warning sting on wolf_spawn / threat events (only generic sting today)
- Weather ambient (rain hiss, storm thunder)
- Crossfade between music tracks (current swap is instant)
- Ambient bus + nature SFX (the "ambient" slider has no bus assigned yet)
---