Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- ============================================================
- -- pda_radio_music_mute.script
- -- Place in: ...\Stalker Anomaly\gamedata\scripts\
- --
- -- What it does:
- -- Hooks action_radio_start / action_radio_stop in
- -- ui_pda_radio_tab to mute snd_volume_music while the PDA
- -- radio (or music player) is active, then restores it.
- --
- -- Shares the volume backup with xrs_dyn_music so combat
- -- music and the radio mute never fight over snd_volume_music.
- -- ============================================================
- -- ----------------------------------------------------------------
- -- State
- -- ----------------------------------------------------------------
- local is_radio_muted = false -- true while we have silenced the music
- local vol_backup = nil -- the volume we captured before muting
- -- ----------------------------------------------------------------
- -- Volume helpers
- -- Use exec_console_cmd to stay consistent with xrs_dyn_music
- -- ----------------------------------------------------------------
- local function get_vol()
- return get_console_cmd(2, "snd_volume_music")
- end
- local function set_vol(v)
- exec_console_cmd("snd_volume_music " .. tostring(v))
- end
- -- ----------------------------------------------------------------
- -- Sync backup into xrs_dyn_music so it does not clobber our mute
- -- when combat kicks in mid-radio.
- -- ----------------------------------------------------------------
- local function sync_dyn_music(vol)
- if xrs_dyn_music then
- xrs_dyn_music.ambient_vol = vol
- end
- end
- -- ----------------------------------------------------------------
- -- Core: mute
- -- ----------------------------------------------------------------
- local function mute()
- if is_radio_muted then return end
- is_radio_muted = true
- vol_backup = get_vol()
- sync_dyn_music(vol_backup)
- set_vol(0)
- end
- -- ----------------------------------------------------------------
- -- Core: restore
- -- ----------------------------------------------------------------
- local function restore()
- if not is_radio_muted then return end
- is_radio_muted = false
- if vol_backup ~= nil then
- set_vol(vol_backup)
- sync_dyn_music(vol_backup)
- vol_backup = nil
- end
- end
- -- ----------------------------------------------------------------
- -- Hook wrappers
- --
- -- We replace the global action_radio_start / action_radio_stop
- -- (and their music-player equivalents) in ui_pda_radio_tab with
- -- thin wrappers that call the original then fire our logic.
- --
- -- NOTE: radio_state / plyr_state are *local* inside ui_pda_radio_tab
- -- and cannot be read from outside the module. We call mute()
- -- unconditionally after start -- safe because mute() itself is
- -- idempotent (guards with is_radio_muted). The original start
- -- functions already guard against double-starts internally.
- --
- -- Known gap: action_plyr_next / action_plyr_previous can silently
- -- stop the player when the playlist is exhausted (without routing
- -- through action_plyr_stop). We cannot detect this without reading
- -- the local plyr_state, so ambient stays muted until the user
- -- presses stop manually. Hooking next/prev and calling restore()
- -- would un-mute on every normal track change, which is worse.
- -- ----------------------------------------------------------------
- local _orig_radio_start = nil
- local _orig_radio_stop = nil
- local _orig_plyr_start = nil
- local _orig_plyr_stop = nil
- local function install_hooks()
- if not ui_pda_radio_tab then
- printf("[radio_mute] ui_pda_radio_tab not found -- hooks skipped")
- return
- end
- if not _orig_radio_start then
- _orig_radio_start = ui_pda_radio_tab.action_radio_start
- ui_pda_radio_tab.action_radio_start = function(...)
- _orig_radio_start(...)
- mute()
- end
- end
- if not _orig_radio_stop then
- _orig_radio_stop = ui_pda_radio_tab.action_radio_stop
- ui_pda_radio_tab.action_radio_stop = function(...)
- _orig_radio_stop(...)
- restore()
- end
- end
- if not _orig_plyr_start then
- _orig_plyr_start = ui_pda_radio_tab.action_plyr_start
- ui_pda_radio_tab.action_plyr_start = function(...)
- _orig_plyr_start(...)
- mute()
- end
- end
- if not _orig_plyr_stop then
- _orig_plyr_stop = ui_pda_radio_tab.action_plyr_stop
- ui_pda_radio_tab.action_plyr_stop = function(...)
- _orig_plyr_stop(...)
- restore()
- end
- end
- end
- local function remove_hooks()
- if _orig_radio_start then ui_pda_radio_tab.action_radio_start = _orig_radio_start; _orig_radio_start = nil end
- if _orig_radio_stop then ui_pda_radio_tab.action_radio_stop = _orig_radio_stop; _orig_radio_stop = nil end
- if _orig_plyr_start then ui_pda_radio_tab.action_plyr_start = _orig_plyr_start; _orig_plyr_start = nil end
- if _orig_plyr_stop then ui_pda_radio_tab.action_plyr_stop = _orig_plyr_stop; _orig_plyr_stop = nil end
- end
- -- ----------------------------------------------------------------
- -- Lifecycle callbacks
- -- ----------------------------------------------------------------
- local function on_first_update()
- install_hooks()
- end
- local function on_load()
- if is_radio_muted then restore() end
- is_radio_muted = false
- vol_backup = nil
- _orig_radio_start = nil
- _orig_radio_stop = nil
- _orig_plyr_start = nil
- _orig_plyr_stop = nil
- install_hooks()
- end
- local function on_game_end()
- if is_radio_muted then restore() end
- remove_hooks()
- end
- -- ----------------------------------------------------------------
- -- Register
- -- ----------------------------------------------------------------
- function on_game_start()
- RegisterScriptCallback("actor_on_first_update", on_first_update)
- RegisterScriptCallback("on_game_load", on_load)
- RegisterScriptCallback("on_game_end", on_game_end)
- end
Advertisement