HZ Scripts

Exports & Events

HZ-AudioMixer ships a complete client-side API for embedding the mixer (or your own custom UI) inside any other resource. All exports are under the HZ-AudioMixer resource name.

The internal audio engine (mapping, scene activation, KVP persistence) stays inside the encrypted client.lua. Exports are the public surface — everything else is sealed by Asset Escrow.


UI Control

open()

Opens the bundled Ghost Protocol mixer UI.

exports['HZ-AudioMixer']:open()

close()

Closes the bundled mixer UI.

exports['HZ-AudioMixer']:close()

toggle()

Toggles the bundled mixer UI.

exports['HZ-AudioMixer']:toggle()

isOpen()

Returns true if the bundled mixer UI is currently open.

local open = exports['HZ-AudioMixer']:isOpen()

Read API

getCategories()

Returns an array of enabled category IDs.

local ids = exports['HZ-AudioMixer']:getCategories()
-- { 'weapons', 'vehicles', 'ambience', 'weather', 'speech', 'peds', 'scripted', 'music', 'radio' }

getCategoriesData()

Returns full category metadata — use this to build your own UI. Labels and descriptions are pre-translated using Config.Locale.

local data = exports['HZ-AudioMixer']:getCategoriesData()

Returned shape :

{
    {
        id    = 'weather',
        label = 'Weather',           -- localized
        desc  = 'Rain, thunder, wind', -- localized
        icon  = 'weather',
        value = 70,                  -- 0-100 (1% precision)
        min   = 0,
        max   = 100,
        step  = 1,
    },
    -- ... 8 more
}

getVolume(categoryId)

Returns the current volume of a single category (0–100), or nil if the ID is invalid.

local vol = exports['HZ-AudioMixer']:getVolume('weather')  -- e.g. 70

getAllVolumes()

Returns a map of { categoryId = volume } for all enabled categories.

local volumes = exports['HZ-AudioMixer']:getAllVolumes()
-- { weapons = 100, vehicles = 80, weather = 30, ... }

Write API

setVolume(categoryId, value)

Sets the volume of a single category. Saves to KVP, applies the audio change immediately, and triggers the volumeChanged event.

-- Volumes are 0-100 (1% precision)
local ok = exports['HZ-AudioMixer']:setVolume('weather', 30)
ParamTypeDescription
categoryIdstringOne of the 9 category IDs (see getCategories())
valuenumber0–100 (clamped). 0 = muted, 100 = full volume
Returns true on success, false if the category is invalid or disabled in Config.Categories.

setVolumes(map)

Sets multiple volumes at once. Skips invalid keys silently. Returns the count of successfully applied changes.

local count = exports['HZ-AudioMixer']:setVolumes({
    weather  = 30,
    weapons  = 100,
    vehicles = 70,
})

resetAll()

Resets every enabled category to Config.DefaultVolume and saves to KVP.

exports['HZ-AudioMixer']:resetAll()

Events

hz-audiomixer:volumeChanged

Triggered every time a volume changes (from any source: bundled UI, exports, resetAll). Use it to keep your custom UI in sync.

AddEventHandler('hz-audiomixer:volumeChanged', function(categoryId, value)
    print(('%s set to %d%%'):format(categoryId, value))
end)
ArgumentTypeDescription
categoryIdstringThe category whose volume changed
valuenumberThe new value (0–100)

Integration Examples

Open the mixer from a custom pause menu

-- In your custom pause menu Lua
RegisterCommand('mymenu_open_mixer', function()
    exports['HZ-AudioMixer']:open()
end)

Build your own sliders inside your NUI

Lua side :
RegisterNUICallback('mymenu:getMixerData', function(_, cb)
    cb({
        categories = exports['HZ-AudioMixer']:getCategoriesData()
    })
end)

RegisterNUICallback('mymenu:setMixerVolume', function(data, cb)
exports['HZ-AudioMixer']:setVolume(data.id, data.value)
cb('ok')
end)

-- Push updates to your NUI when volume changes anywhere
AddEventHandler('hz-audiomixer:volumeChanged', function(id, value)
SendNUIMessage({
action = 'audioVolumeUpdate',
id = id,
value = value,
})
end)

HTML/JS side :
// On menu open — fetch the categories
fetch('https://my-pausemenu/mymenu:getMixerData', {
    method: 'POST',
    body:   '{}'
})
.then(r => r.json())
.then(data => {
    data.categories.forEach(cat => {
        // cat = { id, label, desc, icon, value (0-100), min:0, max:100, step:1 }
        renderSlider(cat)
    })
})

// On slider change
slider.oninput = (e) => {
fetch('https://my-pausemenu/mymenu:setMixerVolume', {
method: 'POST',
body: JSON.stringify({
id: 'weather',
value: parseInt(e.target.value, 10),
}),
})
}

// Listen for external updates
window.addEventListener('message', (e) => {
if (e.data.action === 'audioVolumeUpdate') {
const slider = document.querySelector([data-id="${e.data.id}"])
if (slider) slider.value = e.data.value
}
})

Mute weapons during a cutscene

local backup = exports['HZ-AudioMixer']:getVolume('weapons')

exports['HZ-AudioMixer']:setVolume('weapons', 0)
PlayCutscene(...)
Wait(cutsceneDuration)
exports['HZ-AudioMixer']:setVolume('weapons', backup)

Quick-mute toggle for streamers

RegisterCommand('streamerMode', function()
    exports['HZ-AudioMixer']:setVolumes({
        music = 0,
        radio = 0,
    })
    print('Streamer mode: music + radio muted')
end)

Available Category IDs

IDDescription
weaponsFirearms, explosions, gun mechanics
vehiclesEngines, horns, sirens, helicopters
ambienceBirds, insects, city background
weatherRain, thunder, wind
speechNPC voices, scripted dialogue
pedsFootsteps, clothing, ped sounds
scriptedAlarms, TV, mission sounds
musicGame score, ambient music
radioIn-vehicle radio

Next Step