Lua veto/volume hooks for script sounds, weather effects, thunderbolt claps, and rain - #661
Merged
themrdemonized merged 6 commits intoSep 12, 2026
Conversation
…underbolt plays
Three _G callbacks at the ambient play sites, each fired only when Lua defines the global.
The return's { volume_mult } scales the play: 0 skips it, <1 attenuates, nil is vanilla.
The shape matches the merged COnBeforePlayHudSound.
- COnBeforePlayScriptSound(file, pos, obj): every sound_object play (CScriptSound Play, PlayAtPos, PlayNoFeedback).
- COnAmbientEffectSound(file, pos): the weather-effect recording in WeathersUpdate. The particle burst and wind blast play regardless.
- COnThunderboltSound(file, distance): the strike clap. CEffect_Thunderbolt has no script-engine reach, so it crosses through a new IGame_Persistent OnThunderboltSound virtual (default 1.0).
Manifest entries in lua_help_ex.script. No subscriber means vanilla at one functor lookup per play.
…nd the virtual Review follow-ups, no behavior change with or without a subscriber: - CScriptSound::Play read the object position on every call; move it behind the functor presence check so the no-subscriber path costs only the lookup. - Move IGame_Persistent::OnThunderboltSound to the end of the virtual block so it adds no vtable slot ahead of the existing methods.
Owner
|
See #644 (comment) |
damiansirbu
marked this pull request as draft
September 7, 2026 14:04
damiansirbu
marked this pull request as ready for review
September 8, 2026 01:24
damiansirbu
marked this pull request as draft
September 8, 2026 08:19
CEffect_Rain lives in xrEngine, which cannot reach the script engine, so it crosses through a new IGame_Persistent::OnRainSound virtual next to OnThunderboltSound. The functor fires once at the rain loop onset (stIdle to stWorking in CEffect_Rain::OnFrame), never per frame. The returned volume_mult caches on the effect and multiplies the per-frame set_volume. 0 skips the loop start, under 1 attenuates, an absent global is vanilla. Because rain is a loop sampled at onset, a veto toggled mid-rain takes effect at the next onset. Manifest entry added.
damiansirbu
marked this pull request as ready for review
September 8, 2026 10:21
…rain hooks Add the _G.C* relay plus AddScriptCallback for on_before_play_script_sound, on_before_play_ambient_effect, on_before_play_thunderbolt, and on_before_play_rain, 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.
Contributor
Author
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Lua veto/volume hooks at four ambient play sites: every sound_object play (CScriptSound) and the weather-effect recording (WeathersUpdate).
The other two are the lightning-strike clap (CEffect_Thunderbolt) and the looped rain ambient (CEffect_Rain).
Each site calls a _G functor only when Lua defines it.
The return's { volume_mult } scales the play: 0 skips it, <1 attenuates, nil is vanilla.
The shape matches the merged COnBeforePlayHudSound.
Motivation
Soundscape and dynamic-sound mods keep the engine as the scheduler, with its weather selection, placement, and cadence, and still decide at play time what is heard.
Today their only tools replace configs (static, no runtime awareness) or monkey-patch sound_ambient.script, whose one CreateTimeEvent slot is first-writer-wins, so two mods cannot both observe it.
With these hooks a horror-director mod mutes the base channel's copy of a sound it places itself, and the two never double.
A soundscape mod traces exactly what its channels fire in-game for curation.
An audition UI silences everything except the sound under review.
Any mod ducks ambient recordings during its own moments.
All of it still uses the engine's scheduling and costs nothing when no hook is defined.
Safety
All four sites run where Lua already runs: scripts invoke CScriptSound, and the effect block, the clap, and the rain loop run in the main-thread frame path.
The clap and rain sites (xrEngine) reach Lua through a new IGame_Persistent virtual (default 1.0), since xrEngine has no script-engine include.
The effect hook gates the recording only, and particles and wind blast are untouched.
Rain is a loop, so its functor fires once at onset and the returned mult applies at the per-frame volume.
A veto toggled mid-rain takes effect at the next onset.
No subscriber means vanilla behavior at one null-check per play.
Files changed
Note: the small static ambient_hook_volume_mult also appears in #644 (the bed and music hook PR), which writes it into GamePersistent.cpp as well.
If both land, the one merged second drops its copy in a one-line rebase.
Testing
Built locally on all-in-one-vs2022-wpo (DX11, 0 errors) and exercised in-game with a probe defining every global and counting each fire, across a GAMMA session and a vanilla 1.5.3 session.
Script sounds: fired 3740 times on GAMMA and 1013 on vanilla, each carrying the real file, position, and owner.
Returning { volume_mult = 0 } during a stand-still window silenced 6464 plays with no errors, and clearing the return restored vanilla playback.
Weather effects: fired 78 times on GAMMA and 17 on vanilla, where vanilla effects.ltx resolves the trx wind_gust recordings.
Each fire carried the real file and position, and the particle burst and wind blast kept playing.
Thunderbolt: fired 75 times under a forced w_storm2 on GAMMA and 39 on vanilla, each with the real clap file and its distance.
Rain: fired at each rain onset under a forced storm, carrying the loop file, and the cached mult scaled the per-frame volume.
The return parse is one shared helper across all four sites, so the script-sound veto above covers the veto and attenuate branches for every hook.
With no subscriber defined, each site is a single null-check and behavior is exact vanilla.
Lua usage