> For the complete documentation index, see [llms.txt](https://safky.gitbook.io/product-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://safky.gitbook.io/product-docs/scripts/s_dispatch.md).

# DISPATCH

Dispatch calls, panic codes, gunshot alerts and live unit blips for police and EMS.

Dispatch calls, panic codes, gunshot alerts and live unit blips for police and EMS.

***

## ✅ Requirements

|                  |                                                   |
| ---------------- | ------------------------------------------------- |
| **Frameworks**   | ESX, QBCore, QBX (detected automatically)         |
| **Dependencies** | [ox\_lib](https://github.com/overextended/ox_lib) |
| **Database**     | None                                              |

***

## 📥 Installation

```
ensure ox_lib
ensure s_dispatch
```

There is no SQL. Calls live in memory and are removed after `CallDuration` seconds.

***

## ⚙️ Configuration

Everything is in `config/config.lua`. The options not covered here are commented in the file.

### Jobs and categories

```lua
Jobs = {
    ['police']    = { category = 'Police',    blipSprite = 1, blipColor = 3 },
    ['sheriff']   = { category = 'Police',    blipSprite = 1, blipColor = 25 },
    ['ambulance'] = { category = 'Ambulance', blipSprite = 1, blipColor = 1 },
},
```

A player receives calls only while on duty in one of these jobs. Units see the calls and the map blips of their own category only. `blipSprite` is the on-foot sprite; in a vehicle the sprite comes from `UnitBlips.vehicleSprites`.

On ESX there is no duty toggle, so everyone with the job counts as on duty. To use a duty script, change `onDuty` in `framework.GetJob` in `config/framework/sv-framework.lua`.

{% hint style="info" %}
Running s\_mdt or s\_radar as well? Use the same category names in `Jobs` in all three configs.
{% endhint %}

<figure><img src="https://3876653196-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwqRMsiuM4yL1gQLB2nlA%2Fuploads%2Fgit-blob-acba488f4d5b7644afd31d5278a28edc1f258e49%2F01-call.jpg?alt=media" alt="The dispatch panel with an active call, the distance and two units responding."><figcaption><p>The dispatch panel with an active call, the distance and two units responding.</p></figcaption></figure>

### Codes

```lua
Codes = {
    cooldown = 3,
    list = {
        c1  = { command = 'c1',  code = 'C1',  priority = 'low',  jobs = { 'police', 'sheriff' }, sendTo = 'job',      blip = { sprite = 41, color = 3 } },
        c3a = { command = 'c3a', code = 'C3A', priority = 'high', jobs = { 'police', 'sheriff' }, sendTo = 'category', blip = { sprite = 41, color = 1, flash = true } },
    },
},
```

* `jobs`: who can send the code.
* `sendTo`: `'job'` sends to units with the sender's job, `'category'` to every unit in the sender's category, and a list such as `{ 'police', 'ambulance' }` to those jobs.
* The key (`c1`, `c3a`) names the texts in the locales: `code_<key>_title`, `code_<key>_desc` and `code_<key>_help`. A new code needs its three keys in every locale you use. `code_<key>_desc` receives the sender's name and job label, in that order.

<figure><img src="https://3876653196-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwqRMsiuM4yL1gQLB2nlA%2Fuploads%2Fgit-blob-3e31c70c0e834e5a3d62a55601bd23dbd4f215fe%2F02-high-priority.jpg?alt=media" alt="A high priority call pulses red and plays its own sound."><figcaption><p>A high priority call pulses red and plays its own sound.</p></figcaption></figure>

### Gunshot alerts

```lua
GunShots = {
    enabled = true,
    category = 'Police',
    blip = { sprite = 313, color = 3, scale = 1.2, radius = 100 },
    whitelistedZones = {
        { coords = vector3(13.53, -1097.24, 29.83), distance = 40 },
    },
},
```

On-duty units of any job in `Jobs` never trigger an alert, and neither do silenced weapons. `radius` draws an area on the map instead of an exact pin; `0` removes it.

Weapon names in the alert come from the `weapons` table in the locale. A weapon missing there shows as `weapon_unknown`.

### Death check

Dead players cannot send codes or respond. `IsDead(source)` in `config/sv-functions.lua` reads `metadata.isdead` and `metadata.inlaststand` on QBCore and QBX, and the `isDead` statebag or the ped health on ESX. With another medical script, return its own check there.

***

## 💬 Commands

| Command                     | Default key | Who                                      |
| --------------------------- | ----------- | ---------------------------------------- |
| `/c1`, `/c2`, `/c3`, `/c3a` |             | Jobs in each code's `jobs`               |
| `/dispatch_respond`         | G           | On-duty units, sets the GPS to the call  |
| `/dispatch_prev`            | Left        | On-duty units                            |
| `/dispatch_next`            | Right       | On-duty units                            |
| `/dispatch_toggle`          | U           | On-duty units, shows or hides the panel  |
| `/dispatch_move`            |             | Frees the cursor to drag the panel       |
| `/dispatch_resetui`         |             | Puts the panel back in its default place |

Code commands are in `Codes.list`, the others in `Keybinds`. Players can rebind the keys in Settings, Key Bindings, FiveM.

***

## 🔌 Integration

### Send a call from the server

```lua
local callId = exports.s_dispatch:ServerNotify({
    title = 'Store Robbery',
    message = 'Silent alarm at the 24/7.',
    category = 'Police',               -- or job_table = { 'police', 'sheriff' }
    code = '10-90',
    priority = 'high',                 -- 'low', 'medium' or 'high'
    type = 'robbery',
    coords = vector3(25.7, -1347.3, 29.5), -- or { x = ..., y = ..., z = ... }
    blip = { sprite = 161, color = 1, scale = 1.0, radius = 0, flash = true },
})
```

`title`, `coords` and one of `category` or `job_table` are required. `category` must exist in `Jobs`; `job_table` takes up to 10 job names. `blip.colour` is read as well as `blip.color`. Returns the call id, or `nil` when the data was rejected.

### Send a call from a client script

```lua
TriggerServerEvent('s_dispatch:server:notify', {
    title = 'Medical assistance',
    message = 'A civilian needs help.',
    job_table = { 'ambulance' },
    code = '10-52',
    priority = 'low',
    type = 'medical',
    blip = { sprite = 103, color = 1, scale = 1.2 },
})
```

Same fields without `coords`: the call is placed at the sender's position, read on the server. One call per player every `NotifyCooldown` seconds.

### Read calls

| Export or event                    | Side         | Returns or does                                                                                                                                                                  |
| ---------------------------------- | ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `GetDispatchCalls()`               | server       | Active calls, newest first: `id`, `title`, `description`, `code`, `type`, `priority`, `coords`, `timestamp`, `time` (`HH:MM`), `sender`, `blipSprite`, `blipColor`, `blipRadius` |
| `GetDispatchCall(id)`              | server       | One call, or `nil`                                                                                                                                                               |
| `GetCurrentCalls()`                | client       | The calls this player has on the panel                                                                                                                                           |
| `s_dispatch:client:clearUnitBlips` | client event | Removes the unit blips on that client, for a script that takes a player off duty                                                                                                 |

With s\_mdt running, the dispatch takes each unit's callsign from it for the blip name, and the MDT dashboard lists the calls.

### Hooks

| Function                              | File                      | What it is for                      |
| ------------------------------------- | ------------------------- | ----------------------------------- |
| `Notify(msg, type, duration)`         | `config/cl-functions.lua` | Notifications on the client         |
| `Notify(source, msg, type, duration)` | `config/sv-functions.lua` | Notifications sent by the server    |
| `IsDead(source)`                      | `config/sv-functions.lua` | Blocks codes and respond while dead |
