Skip to content

Voice dispatch

Exports and events

Add your own radio commands, run existing ones from buttons, and react to what was said. Everything here is client side.

addIntent

Adds a command dispatch understands. The recognizer's word list rebuilds on the next press of H.

exports.lwk_control:addIntent({
    id = 'request_k9',
    say = { 'k nine', 'canine unit', 'dog unit' }, -- plain lowercase words, numbers spelled out
    verb = 'request',                              -- 'request' | 'cancel' | nil
    confirm = false,                               -- ask "affirmative?" first
    run = function(ctx)
        TriggerEvent('my_k9:spawn')
    end,
})
FieldTypeWhat it is
idstringUnique id. Also used by run
saystring[]Phrases that trigger it: lowercase words, numbers spelled out
verb'request' | 'cancel' | nilWhich verb it needs. "Send" / "roll" / "requesting" are request; "cancel" / "disregard" are cancel
confirmbooleanAsk affirmative / negative before running
slot'plate' | 'code'Optional: read a plate or a code out of the transmission into ctx
runfunction(ctx)What happens

ctx contains verb and text (what was heard), plus plate when slot = 'plate' or code when slot = 'code'.

run

Runs a command by id as if it had been said, without the confirm prompt (a button press is deliberate). The MDT's status bar buttons use it.

local ok = exports.lwk_control:run('request_tow') -- false for an unknown id

Built-in ids:

GroupIds
Unitsrequest_ambulance, request_police, request_tow, request_coroner, request_fire, request_mechanic, request_roadservice, request_animalrescue, request_taxi, request_cover, and cancel_<same>
Checksplate_check, name_check
Duty and statuson_duty, off_duty, status_10-8, status_10-6, status_10-97, status_check, panic
Calloutsaccept_callout, complete_callout, request_callout, hold_callouts, resume_callouts, where_call
Pursuitpursuit_backup, air_support, cancel_backup
Around youhold_traffic, release_traffic, cancel_traffic_hold, nearest_unit, meet_unit, time_check, weather_check, repeat_last

say

Speaks a dispatch transmission from your resource, queued with dispatch's own replies. Give it text, clips, or both.

exports.lwk_control:say({ 'copy' }, 'Copy, K9 unit en route.')

Clips are keys from lwk_control_assets/nui/voice (a random variant is picked), nui/ paths, or https://cfx-nui-<resource>/... URLs from your own resource.

Other exports

ExportReturnsWhat it is
getCallsign()stringThe player's callsign (signed on in the MDT, else from /control), or ''
getStatus()stringThe recognizer's state, e.g. 'loading', 'idle'
openSettings()Opens the /control panel

Events

All client events.

EventArgumentsWhen
lwk_control:ranid, ctxAfter every command runs, spoken or through run. The MDT logs them to the incident timeline
lwk_control:statuscodeThe player set their status: '10-8', '10-6' or '10-97'
lwk_control:panic"10-99" / "officer down", from the default Config.OnPanic
AddEventHandler('lwk_control:ran', function(id, ctx)
    if id == 'panic' then
        -- alert your Discord, start a siren...
    end
end)