# 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.

```lua
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,
})
```

| Field | Type | What it is |
|---|---|---|
| `id` | `string` | Unique id. Also used by `run` |
| `say` | `string[]` | Phrases that trigger it: lowercase words, numbers spelled out |
| `verb` | `'request' \| 'cancel' \| nil` | Which verb it needs. "Send" / "roll" / "requesting" are request; "cancel" / "disregard" are cancel |
| `confirm` | `boolean` | Ask affirmative / negative before running |
| `slot` | `'plate' \| 'code'` | Optional: read a plate or a code out of the transmission into `ctx` |
| `run` | `function(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.

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

**Built-in ids:**

| Group | Ids |
|---|---|
| Units | `request_ambulance`, `request_police`, `request_tow`, `request_coroner`, `request_fire`, `request_mechanic`, `request_roadservice`, `request_animalrescue`, `request_taxi`, `request_cover`, and `cancel_<same>` |
| Checks | `plate_check`, `name_check` |
| Duty and status | `on_duty`, `off_duty`, `status_10-8`, `status_10-6`, `status_10-97`, `status_check`, `panic` |
| Callouts | `accept_callout`, `complete_callout`, `request_callout`, `hold_callouts`, `resume_callouts`, `where_call` |
| Pursuit | `pursuit_backup`, `air_support`, `cancel_backup` |
| Around you | `hold_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.

```lua
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

| Export | Returns | What it is |
|---|---|---|
| `getCallsign()` | `string` | The player's callsign (signed on in the MDT, else from `/control`), or `''` |
| `getStatus()` | `string` | The recognizer's state, e.g. `'loading'`, `'idle'` |
| `openSettings()` | | Opens the `/control` panel |

## Events

All client events.

| Event | Arguments | When |
|---|---|---|
| `lwk_control:ran` | `id, ctx` | After every command runs, spoken or through `run`. The MDT logs them to the incident timeline |
| `lwk_control:status` | `code` | The player set their status: `'10-8'`, `'10-6'` or `'10-97'` |
| `lwk_control:panic` | | "10-99" / "officer down", from the default `Config.OnPanic` |

```lua
AddEventHandler('lwk_control:ran', function(id, ctx)
    if id == 'panic' then
        -- alert your Discord, start a siren...
    end
end)
```
