10 Commits
Author SHA1 Message Date
Hails 378ce835bf Dev test mod: a different sound per autotest step, a compact top-left HUD
The audible autotest used one beep for eight steps, so steps couldn't be told apart.
Each step now has its own self-made sound (synthesize.py): bell (map Baby_Cry_1), chime
(F6 post, Buoy_Bell patch 88), wood block (F8), triangle (F10), low horn (F11 landing),
click (pop rule), whistle (Digit5), shaker (Digit6), boing (honk rule). HUD: one compact
box top-left, every line fits one row, live countdown; camera return after step 3.
2026-10-04 17:47:01 -06:00
Hails 3bd9b2c8d6 Dev test mod: Digit3 taxis on separate rings (no six-car beating)
Six identical taxis at one rpm and level, each detuned once by C04's own Random op,
beat at 4-8 Hz (the "lawn mower" heard in the audible autotest). Each taxi now drives its
own ring (radius 3+3i m, 2+2i m/s), headless engine-band modulation at single-taxi level.
2026-10-04 16:49:10 -06:00
Hails c4c98243e1 Dev test mod: autotest mode (timed steps, read-back checks, audible / muted HUD)
mods/audio-content-test runs every action on a timer once the map's native audio runs
(settings autotest, autotest_step, autotest_gap, autotest_muted) and logs one
AUTOTEST <check> ok|fail line per read-back check; one bottom-left HUD box with the step,
what to listen for and a red MUTED TEST header on muted runs. Doc 16 M8b.
2026-10-04 16:36:37 -06:00
Hails fda3382e9e Audio modding 2: mod cars and peds get their own MixMap instance by default
- sdk.world_audio.spawn(key, 'traffic'|'ped', ...) without slots gets its own instance on
  the private MixMap, as mod emitters do; slots = 'shared' (alias 'retail') opts into
  retail's pools. Capability world_audio 4. Engine-published objects are unchanged.
- Full private pool (16 cars + 16 peds, all mods): the nearest play, the rest in reach wait
  silently; never refused, never in retail's pools. read(key).waiting / .slots,
  info().own, a one-time log line.
- Dev mods: audio-content-test uses the default; world-audio-test asks for 'shared'
  (retail's limits) with an "Own instances" setting.
- No mod active: e2e bench byte-identical (84 / 84); suites pass (known failures only).
2026-10-04 15:15:18 -06:00
Hails 39debf506d Audio modding 2: hot swap, hot reload, MixMap inputs, own instances, Csis projects, seed
Completes the "Later" list (doc 16 section M):
- Hot swap: an audio mod turning on / off is swapped into the running audio in place.
  Banks keep their runtime id and constructor order, held posts are re-bound with their
  payload; Splice trees, wheel streams, projects, tuning and speech swap too. Only a
  MixMap or grain-bed change (or a swap error) still restarts the sound.
  sdk.audio.info().swaps / last_change.
- Hot reload: editing audio.json or the files it names swaps the overlay while the
  script keeps running.
- MixMap inputs: sdk.audio.set_mixmap_input / mixmap_inputs drive retail's own
  controllers (validated, owned, 16 per mod / 64 total, released values restored).
- Own instances: world_audio spawn {slots='own'} plays mod cars / peds on a private
  MixMap (16 + 16), retail pools untouched.
- Csis projects: audio.json add.projects ships a mod's own classes, functions and
  globals; name clashes are refused; installed / removed without a restart.
- Seed: sdk.audio.seed / SKATE_AUDIO_SEED seeds all audio generators.
- Rules: play.frame = 'owner' puts offsets in the owner's axes; rule sounds follow
  moving published emitters.
- Capabilities: audio 4, audio_content 3, audio_events 3, world_audio 3.
- Dev test mod: Digit1-6, a second HUD line, its own self-made dev.csi.
- No mod active: e2e bench byte-identical 84 / 84 after every step.
2026-10-04 14:38:56 -06:00
Hails b321f77799 Audio modding 2: the decided defaults (own emitter slots, native routing, positional rules)
- Mod emitters get their own instances by default (ModEmitterSlots::Extra); "shared" stays
  selectable, SKATE_AUDIO_MOD_EMITTER_SLOTS overrides either way.
- Mod WAVs route through the native mixer by default when the native audio runs and a voice
  is free, else the Bevy path; native = true / false forces one. Positional native sounds
  default to a 40 m squared reach.
- Replace / layer rule sounds are positional: `at` = owner (default, followed each frame,
  optional offset), world (fixed position) or centre; optional falloff; default reach is the
  owner's retail one (emitter record, cars 40 m, peds 50 m, skaters 30 m).
- Dev test mod, Skyline and audio-example use the defaults; SDK docs and doc 16 updated
  (section L questions written as decisions).
- No mod active: e2e bench byte-identical, 84 / 84; new tests for each default.
2026-10-04 11:21:27 -06:00
Hails b1af7ab819 Merge branch 'audio/moddability' into audio/moddability-2
# Conflicts:
#	docs/hails-additions/16-audio-modding.md
#	mods/audio-content-test/mod.json
2026-10-04 10:13:18 -06:00
Hails fc38e09039 Audio modding 2: native mod voices, live tuning, mod emitters and zones, sound rules
- Mod WAVs can play through the game's own mixer (per-mod mixer banks, retail emitter
  words, a private MixMap), beside the existing Bevy path (mod_voices.rs).
- Tuning can change while the game runs: sdk.audio.set_tuning / tuning / tuned, applied
  between passes, exact restore on nil or mod disable (tuning.rs, audio_tuning.rs).
- Mods add world emitters and reverb zones through the published WorldEmitter /
  ReverbZoneVolume components (world_audio kinds).
- Sound rules: mods mute, replace or layer the game's own sounds by identity, from
  audio.json `rules` or sdk.audio.rule (mod_rules.rs, audio_rules.rs); empty or
  rules-only overlays no longer restart the sound.
- Capabilities: audio 3, audio_tuning 1, audio_events 2, audio_content 2, world_audio 2.
- Dev test mod: F8 native voices, F9 tuning, F10 emitter + reverb zone, F11 a mute rule.
- Headless e2e bench byte-identical to the #36 head after every step; doc 16 section L.
2026-10-04 10:04:07 -06:00
Hails 8403400fe3 Audio modding: review gaps closed, empty Lua tables read as lists
- Mod crossfade banks play: crossfade layouts come from the bank's program or from
  `add.crossfade_layouts` (crossfade.rs, crossfade_layouts.rs); dev test mod fade sample.
- Speech clips and takes are checked at merge time and by check_mod.
- Empty Lua tables (`{}`) were parsed as maps and rejected by list fields; one helper
  (lua_list.rs) now reads them as empty lists in every list field of every mod command.
- Traffic lights answered in the world-audio spec (Skate 3 has none).
- Doc 16 and PULL-REQUESTS.md updated.
2026-10-04 10:03:45 -06:00
Hails f7de66731e Audio modding R6: modding guide, sdk example and dev test mod 2026-10-03 20:13:05 -06:00