Skip to content

Lua trace/veto hooks for the ambient bed and level music - #644

Open
damiansirbu wants to merge 2 commits into
themrdemonized:all-in-one-vs2022-wpofrom
damiansirbu:feat-ambient-bed-hook
Open

Lua trace/veto hooks for the ambient bed and level music#644
damiansirbu wants to merge 2 commits into
themrdemonized:all-in-one-vs2022-wpofrom
damiansirbu:feat-ambient-bed-hook

Conversation

@damiansirbu

Copy link
Copy Markdown
Contributor

Summary

Only HUD sounds have a Lua seam (COnBeforePlayHudSound). Mods driving atmosphere can neither trace nor suppress the engine's own ambient plays. This adds a named _G callback at two ambient sound play sites, same pattern: the engine calls it only when the global is set (zero cost when absent) and applies { volume_mult } from the return - 0 vetoes/silences, <1 attenuates, nil = vanilla. Neutral lever, no engine-side condition.

Hooks

  • COnAmbientBed(section, file, pos) - the per-weather background bed play site in CGamePersistent::WeathersUpdate (the sound_channels static bed, the one ambient path scripts cannot reach: sound_ambient.script owns only sound_channels_dynamic). Skip on veto, set_volume on attenuate; the channel reschedules on its own period either way.
  • COnLevelMusic(file) - level music track in SMusicTrack::Play (level_sounds.cpp). Volume-only: applied via SetVolume (0 silences the track), since skipping the play would make IsPlaying() false and the manager would re-select every frame.

Use cases

  • Ambient/atmosphere mods that trace what the engine bed is playing (section, file, position) to coordinate their own layers with it.
  • Suppressing or ducking the engine bed for a clean listen window (e.g. auditioning a sound in true silence) or replacing it wholesale with a script-driven soundscape.
  • Music-replacement mods silencing the built-in level tracks without touching level configs.

Files changed

  • src/xrGame/GamePersistent.cpp (+28) - bed hook + shared ambient_hook_volume_mult helper.
  • src/xrGame/level_sounds.cpp (+24) - music hook (same helper, static linkage).
  • gamedata/scripts/lua_help_ex.script (+6) - manifest entries for both callbacks.

Lua usage

-- trace + veto the background bed
_G.COnAmbientBed = function(section, file, pos)
    printf("bed: [%s] %s at %.0f,%.0f,%.0f", section, file, pos.x, pos.y, pos.z)
    if my_mod.bed_muted then return { volume_mult = 0 } end
    return nil -- vanilla
end

Testing

Built locally (DX11, 0 errors) and deployed to a live install; a Lua consumer registered both callbacks and returned { volume_mult = 0 }. Verified engine-side via a temporary Msg at both branches (removed for this commit):

  • Bed: trace + veto confirmed across levels and channels - Cordon background_forest_day, Agroprom Underground ugrnd_ambient + ugrnd_bkg_1 (multi-channel bed). 400+ veto events logged: play_at_pos skipped, channel cadence intact (~26s period unchanged).
  • Music: callback fired with the real track file (music\level\day_normal\music_05, music_06).
  • Passthrough (nil return / no global defined): bed plays vanilla (PLAYED vol[1.00] observed before the consumer registered).
  • The attenuate branch (0 < volume_mult < 1) reuses the veto-tested return-parse and the same set_volume call sound_ambient.script makes; not separately exercised in-game.

Only HUD sounds had a Lua seam (COnBeforePlayHudSound). Mods driving
atmosphere could neither trace nor suppress the engine's own ambient
plays. Add a named _G callback at each site, mirroring COnBeforePlayHudSound:
the engine calls it only when the global is set (zero cost when absent)
and applies { volume_mult } from the return (0 vetoes/silences, <1
attenuates, nil = vanilla). Neutral lever, no engine-side condition.

- COnAmbientBed: System A per-weather background bed (WeathersUpdate);
  skip on veto, set_volume on attenuate.
- COnLevelMusic: level music track (SMusicTrack::Play); volume-only.

Manifest entries added to lua_help_ex.script.
@themrdemonized

Copy link
Copy Markdown
Owner

Add _G.COnAmbientBed and _G.COnLevelMusic into g_patches script and make respective callbacks via AddScriptCallback for 3rd party manipulation

Add the _G.C* relay plus AddScriptCallback for on_before_play_ambient_bed
and on_before_play_level_music, so a third party subscribes via
RegisterScriptCallback and scales or vetoes through the result table.
Mirrors COnBeforePlayHudSound. Drop the lua_help_ex engine-callbacks block:
a script callback is documented at its registration, not in the bind manifest.
@damiansirbu

Copy link
Copy Markdown
Contributor Author

Done. Both PRs now define the _G.C* relay and an AddScriptCallback for each hook.
A third party subscribes via RegisterScriptCallback and mutates result.volume_mult (0 vetoes, below 1 attenuates, nil leaves vanilla), the COnBeforePlayHudSound shape.

I put the relays in callbacks_gameobject.script, alongside COnBeforePlayHudSound and the other AddScriptCallback relays. g_patches has none. I can move them there if you prefer.

Tested in-game (Anomaly 1.5.3, DX11): all six register and fire with correct args. A volume_mult=0 return silences the bed and rain.
In-game music and radio reach COnBeforePlayScriptSound (verified with a radio track), so the same return scales or silences them.
COnLevelMusic stays inert on Anomaly since no level defines music_tracks, so it fires only on builds that do.

@themrdemonized

Copy link
Copy Markdown
Owner

Yea, callbacks_ script is the better place. Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants