Configuration
wasabi_mdt is configured through shared, client, server, department, and open-source integration files.
Restart wasabi_mdt after changing Lua configuration. Test department permissions, framework data, dispatch, cameras, and optional integrations in-game before deploying to production.
Configuration files
| File | Purpose |
|---|---|
config/shared/config.lua | UI, locale, open methods, AutoSync, dispatch, radio, BodyCam, alerts, catalogs, staff groups, and resource names |
config/client/config.lua | Tablet animation, dispatch keybinds/blips, CCTV streaming, and BodyCam stop-keybind enablement/description |
config/server/config.lua | Pagination, dispatch persistence, link graph limits, external dispatch ingestion, audit logging, and update checks |
config/shared/departments/*.lua | Department labels, colors, and per-grade permissions |
config/server/opensource.lua | FiveManage API key, Discord webhook, billing, jail, and charge-link hooks |
Shared configuration
UI and locale
-- Default accent color. A department may override it.
Config.UIColor = '#29b181'
-- Locale loaded from locales/<locale>.json.
Config.Locale = 'en'
-- Weapon images are read from nui://{ImgDirectory}{weapon_type}.png.
Config.ImgDirectory = 'wasabi_inventory/ui/images/'
The current release includes locales/en.json. Add another JSON locale file before selecting a different locale code.
Opening the MDT
Config.OpenMDT = {
item = {
enabled = true,
name = 'mdt_tablet',
},
command = {
enabled = true,
cmd = 'mdt',
keybind = false, -- Example: 'F4', or false to disable
},
}
- The item is registered through the active framework bridge.
- The command opens the MDT for authorized officers.
- A string keybind registers a FiveM key mapping for the configured command.
- Access still requires a department with
mdt.openpermission or staff override.
Announcements
Config.Announcements = {
maxAnnouncements = 10,
defaultExpireDays = 7,
}
AutoSync
AutoSync reads identity and ownership data from the framework and a supported housing resource instead of requiring officers to manually duplicate every record.
Config.IgnoredJobs = {
'taxi',
'bloods',
'ballas',
'vagos',
}
Config.IgnoredJobDisplay = 'unemployed'
Config.SyncData = {
enabled = true,
citizens = true,
vehicles = true,
housing = false,
}
| Setting | Description |
|---|---|
enabled | Master switch. Set false to use standalone MDT records. |
citizens | Reads citizens from the active framework's character/player storage. |
vehicles | Reads owned vehicles from the active framework's vehicle storage. |
housing | false or the exact started housing resource name. |
IgnoredJobs | Jobs hidden from MDT records and job selectors. |
IgnoredJobDisplay | Replacement label shown instead of an ignored job. |
Included housing adapters:
RxHousingbcs_housingrtx_housingvms_housing
For another housing resource, copy bridge/housing/template.lua to bridge/housing/<resource>.lua, implement its functions, and set Config.SyncData.housing to that resource name.
Dispatch types and premade calls
Config.DispatchTypes = {
['traffic_stop'] = { label = 'Traffic Stop', icon = 'car' },
['disturbance'] = { label = 'Disturbance', icon = 'volume-up' },
['theft'] = { label = 'Theft', icon = 'shopping-bag' },
['assault'] = { label = 'Assault', icon = 'user-minus' },
['robbery'] = { label = 'Robbery', icon = 'dollar' },
['shooting'] = { label = 'Shots Fired', icon = 'exclamation-triangle' },
['officer_down'] = { label = 'Officer Down', icon = 'shield' },
['panic'] = { label = 'Panic Button', icon = 'exclamation-circle' },
}
Premade dispatches provide defaults for the SendPremadeDispatch client export:
Config.PremadeDispatches = {
['store_robbery'] = {
type = 'robbery',
title = 'Store Robbery in Progress',
description = 'Suspect(s) robbing convenience store, weapon may be involved',
priority = 4,
location = 'Store Location',
},
}
Automatic alerts
Config.Alerts = {
shots_fired = {
enabled = true,
timeout = 15 * 60 * 1000,
},
}
The built-in gunshot detector ignores jobs configured as MDT departments and uses the shots_fired premade dispatch template.
Radio and patrol
Config.Radio = {
enabled = true,
channels = {
{ id = 'TAC-1', label = 'TAC-1', channel = 1 },
{ id = 'TAC-2', label = 'TAC-2', channel = 2 },
},
callChannelStart = 50,
callChannelEnd = 99,
}
This integration uses pma-voice. Disable it if pma-voice is not installed.
BodyCam
Config.BodyCam = {
enabled = true,
stopKey = 'F10',
maxClipDuration = 300,
segmentIntervalMs = 240000,
alertType = 'OverlayOnly',
}
| Setting | Description |
|---|---|
enabled | Enables BodyCam controls and HUD. |
stopKey | Key used to stop an active recording. |
maxClipDuration | Maximum seconds requested when saving a Medal clip. |
segmentIntervalMs | Saves intermediate clips during long sessions; 0 saves only when stopping. |
alertType | Medal desktop alert style. |
Officers using BodyCam recording need Medal installed and should configure an Instant Replay buffer at least as long as maxClipDuration.
Automatic dispatch arrival
Config.Dispatch = {
arrivalDistance = 35.0,
}
Responding officers are automatically marked on scene when they enter this radius around a call with coordinates.
Record catalogs
Config.PropertyTypes, Config.EvidenceTypes, Config.Weapons, and Config.VehicleTypes populate selection fields and labels throughout the MDT. Add or remove entries while preserving each entry's expected keys.
Staff override
Config.StaffGroups = {
'superadmin',
'admin',
'god',
'mod',
}
You can alternatively grant the ACE permission:
add_ace group.admin mdt.staff allow
Resource names and debug output
Resources = {
SCREENBASIC = { name = 'screenshot-basic', export = 'all' },
OBJECTGIZMO = { name = 'object_gizmo', export = 'all' },
}
Config.ShowDebugPrints = false
Change resource names only if those dependencies were renamed. Leave debug output disabled in production because record data may be printed to the server console.
Client configuration
Tablet animation
ClientConfig.TabletAnim = {
dict = 'amb@code_human_in_bus_passenger_idles@female@tablet@idle_a',
name = 'idle_a',
prop = 'prop_cs_tablet',
bone = 28422,
offset = vec3(-0.05, 0.0, 0.0),
rotation = vec3(0.0, -90.0, 0.0),
}
Dispatch keybinds
ClientConfig.DispatchKeybinds = {
panicButton = {
enabled = true,
key = 'F9',
description = 'Activate Panic Button',
},
toggleDispatchHud = {
enabled = true,
key = 'F11',
description = 'Toggle Dispatch HUD',
},
toggleDispatchFocus = {
enabled = true,
key = 'Z',
description = 'Toggle Dispatch HUD Focus',
},
holdDispatchFocus = {
enabled = true,
key = 'G',
modifierControl = 19,
keyControl = 47,
requireModifier = true,
hint = 'Press ALT + G to interact',
},
}
CCTV streaming
ClientConfig.Cameras = {
spawnDistance = 40.0,
checkInterval = 1000,
repositionGhostAlpha = 90,
models = {
{
model = 'prop_cctv_cam_01a',
label = 'Standard CCTV Camera',
viewOffset = { x = 0, y = 0, z = -0.1 },
rotationOffset = { x = -10.0, y = 0, z = 180.0 },
},
},
}
Add supported camera models to models. Each entry controls its label and view/rotation offsets.
Dispatch blips
ClientConfig.DispatchBlips = {
enabled = true,
sprite = 161,
color = 1,
scale = 0.9,
duration = 60000,
}
BodyCam stop keybind
ClientConfig.BodyCam = {
stopKeybind = {
enabled = true,
description = 'Stop BodyCam Recording',
},
}
The key itself comes from Config.BodyCam.stopKey. This keybind stops an active recording; officers start recording from the MDT header.
Server configuration
Pagination
ServerConfig.Pagination = {
defaultLimit = 30,
maxLimit = 100,
}
Keep these values modest on large servers; the UI requests record pages on demand.
Dispatch persistence
ServerConfig.PersistDispatch = false
When enabled, active calls are stored in wsb_mdt_dispatches and restored after a resource/server restart.
Report Link Graph
ServerConfig.LinkGraph = {
maxNodes = 60,
maxDepth = 2,
}
These limits prevent heavily linked records from creating an unbounded graph payload.
External dispatch ingestion
ServerConfig.IngestExternalDispatch = false
When enabled, supported ps-dispatch or cd_dispatch calls are ingested into the MDT. MDT calls are mirrored outward whenever those resources are detected, even when ingestion is disabled.
Audit logging
ServerConfig.AuditLog = {
enabled = false,
logCreate = true,
logDelete = true,
logServe = true,
logClose = true,
}
Set Config.DiscordWebhook in config/server/opensource.lua before enabling this feature.
Update checks
ServerConfig.UpdateCheck = {
enabled = true,
repo = 'wasabihq/wasabi_mdt',
}
Department configuration
Create one file per framework job in config/shared/departments/:
Config.Departments['police'] = {
label = 'Los Santos Police Department',
color = '#3b82f6',
permissions = {
['mdt.open'] = '*',
['mdt.incidents.create'] = { 1, 2, 3, 4, 5 },
['mdt.incidents.delete'] = { 3, 4, 5 },
['mdt.dispatch.view'] = '*',
['mdt.dispatch.create'] = { 1, 2, 3, 4, 5 },
},
}
Permission values:
'*'permits every grade in the department.{ 1, 2, 3 }permits only the listed numeric grades.- Missing keys deny actions that pass through the server permission gate unless the player has staff override.
Server-enforced permission keys
mdt.openmdt.announcements.create,mdt.announcements.edit,mdt.announcements.deletemdt.citizens.create,mdt.citizens.edit,mdt.citizens.deletemdt.vehicles.create,mdt.vehicles.edit,mdt.vehicles.delete,mdt.vehicles.flagmdt.weapons.create,mdt.weapons.edit,mdt.weapons.delete,mdt.weapons.flagmdt.properties.create,mdt.properties.edit,mdt.properties.delete,mdt.properties.flagmdt.evidence.create,mdt.evidence.edit,mdt.evidence.delete,mdt.evidence.checkout,mdt.evidence.checkinmdt.charges.create,mdt.charges.edit,mdt.charges.deletemdt.warrants.create,mdt.warrants.edit,mdt.warrants.serve,mdt.warrants.cancel,mdt.warrants.deletemdt.bolos.create,mdt.bolos.edit,mdt.bolos.resolve,mdt.bolos.deletemdt.incidents.create,mdt.incidents.edit,mdt.incidents.delete,mdt.incidents.close,mdt.incidents.manualmdt.dispatch.create,mdt.dispatch.delete,mdt.dispatch.pin,mdt.dispatch.incident,mdt.dispatch.radiomdt.patrol.managemdt.penalcodes.view,mdt.penalcodes.create,mdt.penalcodes.edit,mdt.penalcodes.deletemdt.cameras.view,mdt.cameras.place,mdt.cameras.manage,mdt.cameras.repair
mdt.dispatch.view, mdt.dispatch.respond, and mdt.panic.trigger are present in the current department/client permission map, but are not complete server-side authorization boundaries in this release. Do not rely on those three keys to secure access; restrict mdt.open appropriately and treat dispatch/panic access as available to officers who can open the MDT.
Open-source server integrations
Keep private keys and custom billing/jail integrations in config/server/opensource.lua:
Config.FIVEMANAGE_API_KEY = ''
Config.DiscordWebhook = ''
The same file includes listeners for:
wasabi_mdt:onChargeLinkedwasabi_mdt:onChargeUnlinked
Use these hooks to create/refund invoices or send/remove jail actions when charges are linked to an incident. See Events for parameter details.