Skip to main content

Configuration

wasabi_mdt is configured through shared, client, server, department, and open-source integration files.

tip

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

FilePurpose
config/shared/config.luaUI, locale, open methods, AutoSync, dispatch, radio, BodyCam, alerts, catalogs, staff groups, and resource names
config/client/config.luaTablet animation, dispatch keybinds/blips, CCTV streaming, and BodyCam stop-keybind enablement/description
config/server/config.luaPagination, dispatch persistence, link graph limits, external dispatch ingestion, audit logging, and update checks
config/shared/departments/*.luaDepartment labels, colors, and per-grade permissions
config/server/opensource.luaFiveManage 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.open permission 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,
}
SettingDescription
enabledMaster switch. Set false to use standalone MDT records.
citizensReads citizens from the active framework's character/player storage.
vehiclesReads owned vehicles from the active framework's vehicle storage.
housingfalse or the exact started housing resource name.
IgnoredJobsJobs hidden from MDT records and job selectors.
IgnoredJobDisplayReplacement label shown instead of an ignored job.

Included housing adapters:

  • RxHousing
  • bcs_housing
  • rtx_housing
  • vms_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',
}
SettingDescription
enabledEnables BodyCam controls and HUD.
stopKeyKey used to stop an active recording.
maxClipDurationMaximum seconds requested when saving a Medal clip.
segmentIntervalMsSaves intermediate clips during long sessions; 0 saves only when stopping.
alertTypeMedal 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.

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.open
  • mdt.announcements.create, mdt.announcements.edit, mdt.announcements.delete
  • mdt.citizens.create, mdt.citizens.edit, mdt.citizens.delete
  • mdt.vehicles.create, mdt.vehicles.edit, mdt.vehicles.delete, mdt.vehicles.flag
  • mdt.weapons.create, mdt.weapons.edit, mdt.weapons.delete, mdt.weapons.flag
  • mdt.properties.create, mdt.properties.edit, mdt.properties.delete, mdt.properties.flag
  • mdt.evidence.create, mdt.evidence.edit, mdt.evidence.delete, mdt.evidence.checkout, mdt.evidence.checkin
  • mdt.charges.create, mdt.charges.edit, mdt.charges.delete
  • mdt.warrants.create, mdt.warrants.edit, mdt.warrants.serve, mdt.warrants.cancel, mdt.warrants.delete
  • mdt.bolos.create, mdt.bolos.edit, mdt.bolos.resolve, mdt.bolos.delete
  • mdt.incidents.create, mdt.incidents.edit, mdt.incidents.delete, mdt.incidents.close, mdt.incidents.manual
  • mdt.dispatch.create, mdt.dispatch.delete, mdt.dispatch.pin, mdt.dispatch.incident, mdt.dispatch.radio
  • mdt.patrol.manage
  • mdt.penalcodes.view, mdt.penalcodes.create, mdt.penalcodes.edit, mdt.penalcodes.delete
  • mdt.cameras.view, mdt.cameras.place, mdt.cameras.manage, mdt.cameras.repair
warning

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:onChargeLinked
  • wasabi_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.