The Interfaces#
Dispatch and MDT has four screens, and it helps to know which is which from the start:
Screen | Opened with | What it is for |
|---|---|---|
Small dispatch | K or | A pop-up in the corner of the screen showing incoming calls while you drive. Answer without opening anything. |
Dispatch panel | L or | The full screen: every call, the live map, the units, TAC groups, radio, CCTV and bodycams. |
MDT |
| Records: citizens, licences, vehicles, incidents, BOLOs, bills, the penal code and sending suspects to jail. |
Camera creator |
| Placing, listing, visiting and deleting CCTV cameras around the map. |
Every key can be changed by each player in Settings → Key Bindings → FiveM, and the defaults are set in Config.Keys, Config.MoveRight, Config.MoveLeft and Config.Respond.
Jobs and Duty#
Only the jobs in Config.JobsAllowed use the dispatch — police, ambulance and mechanic by default — and only while on duty. Off duty, every panel closes, calls stop arriving and the player's blip leaves the map.
Config.JobsAllowed = {
'police',
'mechanic',
'ambulance',
-- 'sheriff',
}Players switch with /onduty and /offduty. On QBCore the framework's own duty toggle is followed automatically, and any other duty script can call the ToggleDuty export — see Commands and Exports.
Receiving and Answering Calls#
A call reaches every on-duty player whose job is in the call's job list. It plays a tone, appears in the small dispatch and the panel, and drops a blip on the map that fades out when its time runs out.
Each call shows its code (for example 10-24 · Store Robbery), the message, the street and zone, how long ago it happened, extra details such as the vehicle model, colour and plate, and a photo of the scene when screenshots are enabled.
The small dispatch#
Key | Does |
|---|---|
← → | Step through the pending calls. |
G | Respond to the call shown — you are added to its units and a waypoint is set. Press again to cancel. |
K | Show or hide the small dispatch. |
U | Drag the pop-up anywhere on screen, then press Confirm Edit. Also |
The dispatch panel#
The left column lists every active call. Each card has a menu with Respond (which becomes Cancel Call once you are on it), Delete and Delete All. Responding sets a GPS waypoint to the call and shows your name and callsign under it for the rest of the department; cancelling clears the waypoint.
The Live Map#
The centre of the panel is a map of San Andreas with four styles — Atlas, Satellite, Grid and Dark — and three layers you can switch on and off:
Layer | Shows |
|---|---|
Calls | Every active call where it happened. |
Colleagues | Every on-duty unit, with an icon for walking, car, motorbike, helicopter, plane or boat. Click one to mark their 10-20 (set a waypoint) or view their bodycam. |
Cameras | Every CCTV camera placed with the creator. Click one and choose Connect to CCTV. |
Positions refresh every Config.PlayerLocationTick seconds (5 by default). Lowering it makes the map smoother but costs performance for every player — leave it as it is unless you have a reason. Set Config.useVehicleIconsInDispatchLargueMap = true to use vehicle icons instead of player icons, and Config.useLogo with Config.logoURL to put your department's logo in the header.
Units, Callsigns and Radio#
The right sidebar of the panel lists every on-duty colleague of your department, grouped by assignment. The icons along the top toggle the radio, the vehicle speed radar, MPH or km/h, and open the settings.
Callsigns#
Open Settings, type your callsign and press Save Callsign. It is stored in the database and shown next to your name on the map, on the calls you respond to, and on your GPS blip. The same window sets how many minutes old calls stay before they are removed.
TAC groups and radio channels#
Every unit starts in Asignation, on the department's default channel. Drag a unit into a group — TAC 1, Patrol 3 — and their radio moves to that group's channel through pma-voice or SaltyChat. Drag them back and they return to the default channel. Units who prefer to manage their radio themselves switch the radio icon off.
Config.Dispatch = {
EnabledRadios = true, -- move units between channels automatically
['police'] = {
DefaultChannel = 10, -- the channel every unit starts on
Groups = {
{ id = 1, name = 'TAC 1', description = 'TAC 1', radiochannel = 11 },
{ id = 2, name = 'TAC 2', description = 'TAC 2', radiochannel = 12 },
{ id = 6, name = 'Patrol 1', description = 'Patrol 1', radiochannel = 16 },
-- ...
}
},
['ambulance'] = {
DefaultChannel = 35,
Groups = {
{ id = 1, name = 'H RNK', description = 'H RNK', radiochannel = 36 },
{ id = 2, name = 'Hospital', description = 'Hospital', radiochannel = 37 },
{ id = 3, name = 'Patroll', description = 'Patroll', radiochannel = 38 },
}
}
}Police ship with five TAC groups and nineteen patrols on channels 11 to 34; EMS with three groups on 36 to 38. With pma-voice, every channel listed here is locked to its job, so civilians cannot tune in.
GPS blips#
Each department's units appear on the pause-menu map with a sprite that changes with what they are in, their name and callsign, and optionally a cone showing where they are looking. showJobs decides which other departments a job can see — by default police and EMS see each other, mechanics see only themselves.
Config.ShowOwnBlip = true
Config.JobsBlips = {
['police'] = {
show = true,
color = 38,
sprite = {
['walking'] = 1, ['automobile'] = 225, ['bike'] = 559,
['boat'] = 404, ['heli'] = 422, ['plane'] = 307,
},
showJobs = { 'ambulance' }, -- that job needs its own entry here too
scale = 1.0,
showConeOfView = true,
},
}Citizen Calls and the Panic Button#
Anyone can call a service from chat. The message is sent with their location and, for police, a photo of the scene. Each command has a 20-second cooldown.
Command | Reaches |
|---|---|
| Police — a 911 call with a screenshot. |
| EMS. |
| Mechanics. |
| Taxi drivers — add |
| Police — a flashing PANIC CALL that stays on the map for five minutes. |
These commands live in client/custom/misc/commands.lua, which you can edit freely to rename them, change the cooldown or add new services. Automatic alerts — gunshots, car theft, fights — come from the Outlaw Alert DLC, and alerts from robbery or job scripts from Create Dispatch Call.
The MDT#
The Mobile Data Terminal opens with /openmdt, or by using the mdt item when Config.NeedItemForMDT = true. The player holds a tablet while it is open. Its sidebar has these sections:
Section | What it is |
|---|---|
Profiles | Search any citizen by name. The profile shows birth date, sex, phone and a photo you can update, their licences, tags, a rich-text notes page, their properties (with a button that sets a waypoint), their vehicles, their incidents, their bills, and their jail record with a button to release them. |
Incidents | Reports with a title, rich-text content, the officers involved, the citizens involved and the suspects, tags and charges. Search, open and edit existing ones. |
B.O.L.O's | Be-on-the-lookout notices for a person or vehicle, with content and the officers assigned. |
Find Plate | Search a plate, even partially. Shows the model, the type, the owner (with a link to their profile) and the vehicle's history: notes added by officers and every speed-camera infraction. |
Penal Code | Every charge your department can apply, with its fine and jail time. |
Closest Citizens | The players within 5 metres. Pick one and assign charges from the penal code — see Charges, Wanted Level and Jail below. Only for jobs allowed to send to jail. |
Bills come from your billing script and can be hidden with Config.showBillsInMDT = false. Profiles, notes, tags and photos are kept per department: what the police write on a citizen is not what EMS see.
Who can use the MDT#
Each department has its own entry in Config.MDT.JobsAllowedToMDT. A job that is not listed cannot open the MDT, and only the grades in gradesAllowedToEdit can — by number or by grade name.
Config.MDT = {
newMdt = true, -- false falls back to the classic MDT
JobsAllowedToMDT = {
['police'] = {
gradesAllowedToEdit = {
[0] = true, [1] = true, [2] = true, [3] = true, [4] = true,
['officer'] = true, ['sergeant'] = true, ['lieutenant'] = true, ['boss'] = true
},
categoryes = {
['citizens'] = {
enabled = true,
CanManageLicences = true, -- add and remove licences
CanManageTags = true, -- add and remove tags
CanViewVehicles = true, -- see the citizen's vehicles
CanViewHouses = true -- see the citizen's properties
},
['incidents'] = { enabled = true },
['bolos'] = { enabled = true }
},
availableLicences = { 'driver', 'drive', 'weapon', 'aircraft' },
readDatabaseFor = { 'mechanic', 'ambulance' } -- also read these departments' incidents
},
['ambulance'] = {
gradesAllowedToEdit = { [3] = true, [4] = true, ['chief_doctor'] = true, ['boss'] = true },
categoryes = {
['citizens'] = { enabled = true, CanManageLicences = false, CanManageTags = false, CanViewVehicles = false, CanViewHouses = false },
['incidents'] = { enabled = true },
['bolos'] = { enabled = true }
}
},
}
}availableLicences must use the licence names your framework stores: user_licenses types on ESX, metadata.licences keys on QBCore. To add a department, copy an entry, rename the key to the job name, and add the same job to Config.JobsAllowed.
Your own pages in the MDT. Another resource can add a section to the MDT sidebar — an evidence locker, a fleet manager — with the
addCustomPageexport. See Commands and Exports.
The Penal Code#
config/jobsdata.lua holds one or more books of charges. Each book lists the jobs that can see it; a job that appears in several books sees them all. The shipped files contain the Penal Code of San Andreas for police, sheriff and FBI, and an EMS services list for ambulance.
JobsData = {
[0] = {
title = 'Penal Code of San Andreas',
desc = 'The primary set of laws governing the state of San Andreas.',
jobs = { 'police', 'sheriff', 'fbi' },
PenalCode = {
{
id = 'code_theft', -- unique in the whole file
title = 'Theft',
desc = 'Taking property without consent, with intent to keep.',
fine = 300, -- shown as a reference only
jailTime = 1, -- minutes; 0 or 1 and above, never between
},
-- ...
}
},
}Charges, Wanted Level and Jail#
Arrests follow one loop: charge the suspect, keep them in sight, and bring them to a booking point.
Charge the suspect
In the MDT, open Closest Citizens, pick the suspect and add charges from the penal code. They get one wanted star per charge, up to six, and officers see the charges floating above them when close. Every on-duty officer sees a search area on the map around them — yellow, or red above three charges.
Keep them on camera
While a CCTV prop or a police vehicle from
Config.CameraModelsis near the suspect, the search area follows them. Out of view, it freezes at the last place they were seen and fades. If they stay out of view long enough, the charges are dropped:lua Config.Penitencial.TimeToRemoveCodes = { [1] = 1, -- 1 star: charges dropped after 1 minute out of view [2] = 5, [3] = 10, [4] = 15, [5] = 20, [6] = 25, -- 6 stars: 25 minutes }Book them
Bring the suspect to a booking point — a red marker at Mission Row by default — and press E. Every charged player within 5 metres is sent to prison. The sentence is the sum of the jail time of their charges, and the reason is the list of charges.
Prison
The prisoner sees an arrest cutscene, is moved inside Bolingbroke, loses the items in
IlegalItems, and gets a countdown on screen. The sentence is stored with an end time, so it keeps counting while they are offline and is restored when they reconnect. When it ends they are released at the exit point.
Config.Penitencial = {
keyForSendToJail = 'E',
JobsAllowedToSendToJail = { 'police' },
IlegalItems = { 'weapon_pistol', 'pistol_ammo' }, -- removed on entering prison
SendToJailPoints = {
{ title = 'Mission Row PD', coords = vector3(460.0216, -1001.5779, 24.9149) },
},
Jail = {
name = 'Jail of paleto',
coords = vector3(1691.7264, 2582.1084, 45.5648),
radius = 150, -- leaving this sphere counts as an escape
spawnPoints = { vector4(1678.5844, 2541.4470, 45.5645, 267.97) },
exitPoints = { vector4(1850.7671, 2586.0156, 45.6720, 274.4039) },
ReturnToJailIfScaped = false,
onEscaped = function(playerId) --[[ sends an Escaped prisoner call ]] end,
}
}A prisoner who leaves the prison sphere has escaped. With ReturnToJailIfScaped = true they are put back inside; with false they go free and onEscaped runs — by default an Escaped prisoner call with a photo to every police job. Officers can release a prisoner early from the jail section of their MDT profile (the button labelled by the REMOVE_FROM_JAIL locale key).
The Vehicle Speed Radar#
Inside a car, the allowed jobs see a radar that reads the vehicles ahead and behind: plate, model, colour, speed in km/h and MPH, and whether the siren is on. A vehicle over Config.DefaultSpeedLimit is flagged and the reading freezes for Config.TimeToFreeze milliseconds so the officer can note it. /disablespeedradar or the radar icon in the panel turns it off.
Config.Radar = {
enabled = true,
needVehicleInWhitelist = false, -- true: only in the vehicles below
jobsAllowedToUseRadar = { 'police' },
vehiclesWhitelist = { 'police3', 'police' }
}
Config.DefaultSpeedLimit = 100 -- km/h
Config.TimeToFreeze = 2000 -- msSpeed Cameras#
Fixed speed cameras catch any driver who enters their zone too fast. Depending on the zone, the driver sees a flash, receives a fine or a bill, the police get a High Speed call, and the infraction is written into the vehicle's history in the MDT. Jobs in ignoredjobs are never caught, nor are aircraft.
Config.VelocityRadar = {
enabled = true,
activateFXFlash = true, -- flash the driver's screen
sendDirectTheBill = true, -- always send a bill instead of taking money
account = 'bank', -- with sendDirectTheBill = false: 'money', 'bank' or 'bill'
useMph = false,
ignoredjobs = { --[['police', 'ambulance']] },
zones = {
[1] = {
label = 'Zone 1',
velocityRanges = {
{ limitFrom = 105, price = 8500 }, -- from 105 km/h
{ limitFrom = 200, price = 11000 }, -- from 200 km/h
},
coords = vector3(365.8156, 134.4366, 103.0974),
width = 30, -- radius
beforeEnterInZoneAlert = true, -- warn the driver before the camera
beforeEnterInZoneAlertMargin = 40,
autoBill = true, -- charge the fine
notifyInfractor = true, -- tell the driver
sendAlertToPolice = true, -- dispatch call to police
sendHistoryToMDT = true, -- record in the vehicle's MDT history
blip = { enabled = true, color = 3, sprite = 184, scale = 0.8, text = 'Velocity Radar' }
},
}
}With sendDirectTheBill = false, the fine is taken from account — and if the driver cannot pay, a bill is sent instead. The call sent to police and the MDT record are written in onDispatchCall and onHistoryToMDT in the same table, so you can change them or point them at another script.
CCTV Cameras#
Any camera placed with the creator shows on the panel's map. Click it and choose Connect to CCTV to watch through it:
Key | Does |
|---|---|
Arrow keys | Turn the camera left, right, up and down. |
W / S | Zoom in and out. |
Backspace | Leave the camera. |
Only the jobs in Config.CCTV.jobsAllowed can connect.
Placing cameras#
/createcameras opens the creator with a table of every camera — id, name, type, model and coordinates — with buttons to teleport to it or delete it. Press Enter Creator Mode, give the camera a name, choose a model and press Add Camera. A ghost camera follows where you aim:
Key | Does |
|---|---|
← → | Rotate the camera. |
↑ ↓ | Raise or lower it. |
E | Place it. |
Backspace | Cancel. |
Placed cameras are saved in the database and appear for everyone. The creator needs the aces described in Installation.
Cameras that see suspects.
Config.CameraModelslists the props and vehicles that count as a camera when tracking wanted suspects — the twelve GTA CCTV props pluspolice3andpolmav. Any CCTV prop already in the map counts, not only the ones you place. Add more props from gta-objects.xyz.
Bodycams#
From the map or the units list, choose View the bodycam on a colleague to watch a live feed from their chest, with their name on screen. Press Backspace or Esc to leave. The feed ends on its own if the colleague goes off duty.
Config.DispatchBodyCamZones = {
enabled = true,
jobsAllowed = { 'police', 'ambulance' },
needIsInZone = false, -- true: only from inside one of these zones
zones = {
[1] = { label = 'Zone 1', coords = vector3(456.6222, -985.9254, 30.6832), width = 30 },
}
}With needIsInZone = true, bodycams can only be watched from a control room — by default, Mission Row PD — and players are told when they enter or leave that zone.
Photos in Calls#
With Config.AllowImages = true, calls that ask for it — /police, the escaped prisoner, gunshots from the DLC — take a screenshot from the caller's screen at that moment, upload it to the Discord channel of Config.DiscordWebHook, and show it on the call. Taking a photo adds a short delay to the call; turn it off if you prefer speed.
The Classic MDT#
Setting Config.MDT.newMdt = false brings back the previous, simpler MDT: find people by first and last name, find a plate, read and write notes and history entries on a person or vehicle, and view their bills. It uses the same database, so you can switch back and forth without losing anything.



