Skip to content

In-game modules ​

Each module is switched on in Config.Modules (see Configuration). All of them identify a player by their Discord id, so players need a linked Discord account. For the API key each module needs, see Installation.

Who is this player in the MDT? ​

The core links a player to their employee record in the MDT through their Discord id (GET /integrations/ingame/employees/:userId). Results are cached for a minute, and parallel lookups for the same person share one request. Other resources can use this too, see GetEmployee.

dispatch ​

Brings calls from the game onto the dispatch board, under Meldungen aus dem Spiel (calls from the game). The dispatcher takes a call as an incident there, or dismisses it.

  • From other resources: phones, robbery scripts, alarm systems call ReportCall on the server, or trigger the server event np_mdt:dispatch:report. Resources you don't want to edit are bound with Config.Dispatch.hooks. None of these can be triggered by a client.
  • Chat command: /notruf <text> (off by default, Config.Dispatch.command).
  • Resident reports (Config.Dispatch.auto, off by default): gunshots and heavy crashes turn into calls with a chance and a delay, the way a resident would call them in. The client only reports the event. Location, quiet zones, exempt jobs, chance and delay are decided on the server. Suppressed weapons report nothing. Several shots in the same area and time window become one call, "N× gemeldet" (reported N times).
  • Back into the game: when dispatch assigns a unit to a call, its crew gets a blip with a route and a hint. The blip disappears when the call ends or the unit changes. The resource polls every pollS seconds (scope calls:read). Turn it off with Config.Dispatch.notifyUnits = false.

Calls wait in a small in-memory outbox, not on disk: in order, with growing back-off on network errors, and at most maxAgeS (15 minutes) old. A call from a quarter of an hour ago doesn't help anyone.

funk ​

Funk (radio): the own unit's status and a panic button.

  • /status <label> sets the status of the unit you're crewing on the dispatch board. Statuses in keyStatuses also get bindable keys (Settings → Key Bindings → FiveM, "MDT: Status …"). The MDT checks that you're in the unit and that the status exists.
  • Panic button (bindable key "MDT: Panikknopf", command np_mdt_panic): only for people on duty in the MDT. The location comes from the server. It shows up as a high-priority Panikknopf call. Optionally the own unit jumps to an alarm status (panic.status).

tablet ​

Instead of rebuilding MDT views in game, the tablet shows the real web MDT in a window. /mdt or F10 opens and closes it, and Esc closes it too. The character holds a tablet prop while it's open.

  1. The client asks the server for a link. The request carries nothing: who is meant is decided by source alone. At most one link per player every cooldownMs, optionally only for certain jobs.
  2. The server requests a one-time link with its key (POST /integrations/ingame/tablet-links). The link is valid for 60 seconds. The server only passes it on if it points at this exact MDT.
  3. The NUI loads the link in an iframe. The MDT creates a 12-hour session with exactly that person's rights, limited to the key's instance. Until then, reopening the tablet just shows it again. Neu anmelden (log in again) in the frame fetches a fresh link.

Requirements:

  • Config.Modules.tablet = true and a scoped key with sessions:ingame.tablet_login.
  • The person is an active, non-suspended employee.
  • The person has logged in to the MDT once in a browser with Discord. The tablet never creates an account.

Every tablet login is recorded in the MDT's audit log with the key and the Discord id.

Cookies in FiveM's browser

The tablet session uses a third-party cookie (SameSite=None; Secure; Partitioned). If FiveM's CEF has trouble with Partitioned, the MDT operator can turn it off with INGAME_TABLET_COOKIE_PARTITIONED=false.

ranks ​

Maps job grades to rank keys (Config.Ranks). On join and on job change, the resource sends the keys to PUT /integrations/ingame/employees/:discordId/ranks. That replaces only the person's InGame ranks. Discord and manual ranks stay. It only sends when something changed. In the MDT, set each rank's InGame-Schlüssel (inGameKey) under Einstellungen → Ränge.

timeclock ​

Anyone in one of the configured jobs who goes on duty is clocked in in the MDT. Going off duty, changing jobs or (if enabled) leaving the server clocks them out.

  • "On duty" comes from job.onduty (QBCore), job.onDuty (ESX 1.10+) or the ESX off<job> convention.
  • Someone who is already clocked in through Discord when they join isn't clocked out just because they aren't on duty in game yet.
  • Like the Discord panel, clocking in requires the badge in the server nickname.

kiosk ​

A queue ticket machine (Wartenummer-Automat). At a configured location, /wartenummer draws a ticket in the facility's queue, just like at the counter. The server checks that the player is actually at the machine. Queue tickets must be enabled in the facility's settings in the MDT.

ausweis ​

A service ID card (Dienstausweis) as a usable item (default mdt_dienstausweis). Using it shows players within radius the holder's name, badge number, rank and duty status, read fresh from the MDT each time. Suspended people and non-employees show an invalid card.

The NUI shell ​

The resource has a single NUI page, a shell with one view per module, built with the Nimbus UI design system. Fonts and icons are bundled offline.

ViewOpened byFocus
tabletThe tablet module (/mdt)Keyboard and mouse
menuTreatment menu, when ox_lib isn't runningKeyboard and mouse
progressTimed actions, when ox_lib isn't runningNone
cpr, intubation, iv, decompressionThe four medic minigamesKeyboard and mouse
debug/medic panel (debug switch and ACE)Keyboard and mouse

A modal view replaces the previous one (a minigame closes the tablet). The progress bar stays on top. Esc closes the most recently opened modal view. Anything that comes back from the NUI is only a request: whatever changes the game is decided on the server.

np_* FiveM resources