Configuration
np_mdt splits its configuration by module:
config/core.lua modules on / off, locale, bridge overrides
config/server.lua MDT URL and API key (server only)
config/<module>/*.lua settings per moduleEverything except config/server.lua is a shared script, so it's also loaded on the client. Don't put secrets there. Most module files fill in their defaults instead of replacing the table, so you can set values in your own file without worrying about load order.
Core
config/core.lua
| Option | Default | Description |
|---|---|---|
Config.Modules.medic | true | Medical simulation and its sync to the MDT. See Medic module |
Config.Modules.dispatch | true | Calls to the dispatch board, for other resources via ReportCall |
Config.Modules.ranks | false | Job grade → InGame rank in the MDT. Needs a job mapping first |
Config.Modules.timeclock | false | On duty in game → clocked in in the MDT. Needs a job list first |
Config.Modules.funk | false | Own unit's status and a panic button |
Config.Modules.kiosk | false | Queue ticket machine in the hospital |
Config.Modules.ausweis | false | Service ID card as an item |
Config.Modules.tablet | false | The real MDT as an in-game tablet. Needs the sessions:ingame.tablet_login scope |
Config.Modules.platform | false | Versioned platform contract. Stays off until the MDT issues scopes for it |
Config.Locale | "de" | Language of player-facing texts (locales/<Locale>.json). German is the fallback |
Config.Bridge | {} | Override auto-detection, e.g. { inventory = "builtin" }. See Bridges |
A module that's off is still loaded (the manifest has no conditions), but it isn't started: no thread, no queue, no HTTP.
Server
config/server.lua is listed only under server_scripts. Its values come from convars:
| Convar | Fallback | Description |
|---|---|---|
np_mdt_url | np_medic_mdt_url, then https://mdt.npdev.eu | MDT base URL |
np_mdt_api_key | np_medic_api_key, then empty | API key of your guild |
np_mdt_environment | live | test marks everything sent as a test ([TEST] in call titles) |
Fixed values in Config.Mdt:
| Option | Default | Description |
|---|---|---|
maxBatchEvents | 256 | Events per medic batch (mirrors the server limit) |
maxBatchBytes | 1048576 | Bytes per medic batch |
maxQueueEvents | 10000 | From here on the queue drops vital-sign samples. Injuries, treatments and artefacts are never dropped |
persistDebounceMs | 2000 | Queue checkpoint interval. A hard crash can lose changes since the last checkpoint |
Dispatch
config/dispatch/dispatch.lua
Config.Dispatch = {
source = "np_mdt", -- `source` of calls that don't bring their own
maxPending = 200, -- in-memory outbox size
maxAttempts = 10, -- attempts per call
maxAgeS = 900, -- calls older than this aren't sent any more
notifyUnits = true, -- blip, route and hint for the crew of an assigned unit (needs calls:read)
pollS = 10, -- how often calls are read back from the MDT
blips = {
sprites = { notruf = 153, panik = 161, alarm = 161, hinweis = 280 },
colours = { [1] = 1, [2] = 47, [3] = 3 }, -- per priority
scale = 1.0,
route = true,
},
hooks = {}, -- bind other resources' events, see below
auto = { -- reports a resident would make: shots and heavy crashes
enabled = false,
shot = { enabled = true, chance = 0.6, delayS = { 10, 40 } },
crash = { enabled = true, chance = 0.4, delayS = { 15, 60 }, minSpeedKmh = 80 },
exemptJobs = { "police", "ambulance" },
quietZones = {}, -- { x, y, radius } where shots are never reported (shooting range)
cellSize = 150, -- shots in the same cell (m) and window are one call
windowS = 300,
clientCooldownS = 10,
},
command = { -- simple `/notruf <text>` chat command
enabled = false,
name = "notruf",
cooldownS = 30,
},
}Hooks
Hooks connect resources you don't want to edit. Each entry maps an event to a function that builds a call from the event's arguments (return nil to skip):
Config.Dispatch.hooks = {
{ event = "myrobbery:alarm", call = function(store, coords)
return { externalId = "raub:" .. store, kind = "alarm", priority = 1,
title = "Stiller Alarm " .. store, location = { x = coords.x, y = coords.y } }
end },
}Hooks listen to server events. Set net = true only if the other resource sends the event from the client. Then the function gets the player's source first, and a per-player cooldownS (default 30) applies.
Funk
config/funk/funk.lua. Funk means radio.
| Option | Default | Description |
|---|---|---|
keyStatuses | { "1", … "8" } | Statuses that get a bindable key. /status <label> always works |
statusCooldownS | 1 | |
panic.enabled | true | Panic button |
panic.key | "" | Default key. Empty means players bind it themselves |
panic.cooldownS | 60 | |
panic.status | nil | Status the own unit jumps to on panic (e.g. "9"). nil keeps the status |
Tablet
config/tablet/tablet.lua
| Option | Default | Description |
|---|---|---|
command | "mdt" | Command that opens and closes the tablet |
key | "F10" | Default key. Players can rebind it in Settings → Key Bindings → FiveM |
jobs | {} | Only these jobs may open it. Empty means everyone (the MDT still checks employment) |
cooldownMs | 10000 | At most one new login link per player in this time |
reuseMs | 11 h | An already loaded tablet is shown again instead of logging in anew while the session is valid |
prop | prop_cs_tablet in the left hand | Model, bone, offset, rotation. false turns it off |
animation | amb@code_human_in_bus_passenger_idles@female@tablet@base / base | false turns it off |
messages | German texts | What players read in chat (cooldown, no Discord, not allowed, not an employee, suspended …) |
Ranks
config/ranks/ranks.lua
Config.Ranks = {
jobs = {
ambulance = {
[0] = "trainee",
[2] = "paramedic",
[4] = { "paramedic", "instructor" }, -- one grade can carry several keys
},
},
clearOnOtherJob = true, -- switching to an unmapped job clears the InGame ranks
}The values are rank keys, the InGame-Schlüssel (inGameKey) of a rank in the MDT under Einstellungen → Ränge. A grade without an entry uses the highest mapped grade below it.
Timeclock
config/timeclock/timeclock.lua
| Option | Default | Description |
|---|---|---|
jobs | {} | Jobs whose duty is clocked in the MDT, e.g. { "ambulance" } |
clockOutOnDisconnect | true | Clock out whoever leaves the server while on duty |
Kiosk
config/kiosk/kiosk.lua
| Option | Default | Description |
|---|---|---|
locations | {} | { x, y, z, radius, label } per machine |
cooldownS | 300 | One ticket per player in this time |
command | "wartenummer" | Command to draw a ticket in range |
Queue tickets (Wartenummern) must also be enabled in the facility's settings in the MDT.
Ausweis
config/ausweis/ausweis.lua. Dienstausweis means service ID card.
| Option | Default | Description |
|---|---|---|
item | "mdt_dienstausweis" | The usable item. It must exist in your inventory |
radius | 3.0 | Players within this many metres see the card |
Medic
The medic module has its own folder, config/medic/. The main switches are covered on the Medic module page.
| File | Contents |
|---|---|
gameplay.lua | Debug, health authority, timeline, damage, bleeding, self-care, assist level, tiers, minigames, body view, treatment |
runtime.lua | Main switch Runtime.enabled, conflicts with ambulance scripts, health pinning, downed, sensory, bystanders, respawn, plausibility |
items.lua | Treatment items (medic_*), all renamable |
props.lua | Props and animations for treatments |
notruf.lua | In-game emergency call (item, keys, who receives it, blips) |
transport.lua | Drag, carry, spineboard, stretcher, ambulance, arrival |
hospital.lua | In-game hospital: builder ACE, tiers per action, imaging, surgery |
monitor.lua | Patient monitor and defibrillator |
integration.lua | Integration exports, toxicology |