Dispatch & Schnittstellen
Das System leitet Notrufe über modulare Dispatch-Adapter weiter. Jeder in HM_Notrufsaeulen angelegte Dienst kann einen eigenen Dispatch-Adapter nutzen (z. B. Polizei über Emergency Dispatch, Pannenhilfe über Roadphone).
Emergency Dispatch (LoveRP Scripts)
Abschnitt betitelt „Emergency Dispatch (LoveRP Scripts)“Die Resource verfügt über eine vorkonfigurierte Integration für Emergency Dispatch von LoveRP Scripts.
Funktionsweise
Abschnitt betitelt „Funktionsweise“Die API von Emergency Dispatch erwartet einzelne Parameter statt eines Payload-Tables:
TriggerEvent('emergencydispatch:emergencycall:new', jobName, message, coords, true)Da das Event jeweils nur einen Ziel-Job aufnimmt, löst der Adapter das Event pro hinterlegtem Job des Notrufdienstes einmal aus. Besitzt ein Dienst z. B. die Jobs police und sheriff, erhalten beide Fraktionen den Einsatz.
Client- vs. Server-Modus
Abschnitt betitelt „Client- vs. Server-Modus“In der config/config.lua unter Config.Dispatch.emergencydispatch.mode:
mode = 'client'(Standard): Löst das Event auf dem Client des Anrufers aus. Emergency Dispatch entscheidet selbstständig zwischen Telefonanruf (falls Leitstelle besetzt ist) und Text-Notruf (falls unbesetzt), und ermittelt die Spielerposition automatisch:TriggerEvent('emergencydispatch:emergencycall:new', jobName, message, false)mode = 'server': Nutzt die serverseitige Auslösung mit exakter Säulen-Koordinate – erzeugt immer eine reine Text-Einsatzmeldung ohne Telefonie.
Wachen-Alarmierung
Abschnitt betitelt „Wachen-Alarmierung“Optional kann zusätzlich ein Alarm für eine Feuerwehr- oder Rettungswache ausgelöst werden (emergencydispatch:alarmierung:wache). Der im Dienst hinterlegte Dispatch-Code fungiert hierbei als alarmcode:
Config.Dispatch.emergencydispatch = { alertStation = false, -- Auf true setzen station = 'Wache 1', -- Name der Wache stationEvent = 'emergencydispatch:alarmierung:wache', ...}Format der Notrufmeldung
Abschnitt betitelt „Format der Notrufmeldung“Da die API von Emergency Dispatch kein separates Feld für den Meldernamen anbietet, setzt das Script den Spielernamen automatisch an den Anfang der Einsatzmeldung:
Melder: Frank Wolf | Notrufsäule: A9 Süd km 42 | Ort: Elgin Ave | gewählt: 112 | Meldung: FahrzeugbrandDienstprüfung (On-Duty Check)
Abschnitt betitelt „Dienstprüfung (On-Duty Check)“Vor dem Absenden fragt der Adapter die Personalstärke bei Emergency Dispatch ab:
exports['emergencydispatch']:mannedvehicles() -- Einsatzkräfte auf Fahrzeugenexports['emergencydispatch']:mannedcontrol() -- Disponenten in der Leitstelle- Ist im jeweiligen Job niemand im Dienst, wird der Notruf trotzdem an das Dispatch-System übergeben (damit der Einsatz nicht verloren geht).
- Gleichzeitig greift die Redundanz (
Config.Dispatch.fallback), und der Anrufer erhält an der Säule den Hinweis: „Meldung weitergeleitet (Bereitschaft übernimmt)“. - Über
notruf_dutyin der Serverkonsole kannst du prüfen, welche Jobnamen Emergency Dispatch aktuell meldet.
Telefon-Integration (optional)
Abschnitt betitelt „Telefon-Integration (optional)“Emergency Dispatch besitzt keine eigene Telefonie – für echte Sprachverbindungen kann ein Telefonskript über den Client-Hook Config.Phone.start(data) angebunden werden:
Config.Phone = { enabled = true, resource = 'lb-phone', start = function(data) exports['lb-phone']:StartCall(data.number, data.anonymous) end,}Das übergebene Objekt data enthält:
data.number: Rufnummer des gewählten Dienstes.data.service: Vollständiges Dienst-Objekt.data.serviceId: ID des Dienstes.data.anonymous: Boolean, ob anonym gemeldet wurde.data.pillar: Säulen-Objekt mit Standortdaten.
exports['lb-phone']:StartCall(data.number, data.anonymous)TriggerEvent('qb-phone:client:CallContact', { number = data.number })exports['gksphone']:CallContact(data.number)exports['roadphone']:callNumber(data.number)Eigene Dispatch-Adapter anbinden
Abschnitt betitelt „Eigene Dispatch-Adapter anbinden“Möchtest du ein anderes Notruf- oder Dispatch-System (z. B. Roadphone, Quasar Dispatch, Codesign, etc.) anbinden, lässt sich dies in wenigen Schritten modular umsetzen.
Schritt-für-Schritt-Anleitung
Abschnitt betitelt „Schritt-für-Schritt-Anleitung“-
Adapter-Datei anlegen:
Erstelle eine neue Lua-Datei im Ordnerserver/adapters/(z. B.server/adapters/roadphone.lua):--[[ Adapter: Roadphone ]]NRS.Dispatch.Register('roadphone', function(call)local cfg = Config.Dispatch.roadphone-- Prüfen, ob die Ziel-Resource läuftif GetResourceState(cfg.resource) ~= 'started' thenreturn false, ('Resource "%s" läuft nicht'):format(cfg.resource)endlocal message = ('%s an %s: %s'):format(call.service.label, call.street or call.pillar.label, call.message)exports[cfg.resource]:CreateCall({job = call.service.jobs[1],code = call.service.dispatchCode,text = message,coords = call.coords,caller = call.callerName,})return trueend) -
In der fxmanifest.lua registrieren:
Füge die Datei in derfxmanifest.luaunterserver_scriptsein (nachserver/dispatch.luaund vorserver/main.lua):server_scripts {'server/bridge.lua','server/storage.lua','server/permissions.lua','server/dispatch.lua','server/adapters/emergencydispatch.lua','server/adapters/roadphone.lua', -- Neu hinzugefügt'server/main.lua',} -
Im Tablet auswählbar machen:
Trage den Adapter inconfig/config.luaunterConfig.Dispatch.adaptersein:Config.Dispatch.adapters = {{ value = 'emergencydispatch', label = 'Emergency Dispatch' },{ value = 'roadphone', label = 'Roadphone' },} -
Eigenen Config-Block hinzufügen:
Füge derconfig/config.luadie nötigen Parameter für deinen Adapter hinzu:Config.Dispatch.roadphone = {resource = 'roadphone',priority = 2,} -
Dienst zuweisen:
Öffne im Tablet den Reiter Notrufdienste, wähle den gewünschten Dienst aus und stelle im Dropdown-Menü Dispatch-Adapter auf deinen neuen Eintrag um. Die Änderung ist sofort aktiv.
Was das call-Objekt enthält
Abschnitt betitelt „Was das call-Objekt enthält“Jeder Adapter empfängt beim Auslösen ein umfassendes call-Table:
| Feld | Typ | Beschreibung |
|---|---|---|
call.source | number | Server-ID des Anrufers (0, wenn ohne Spieler ausgelöst). |
call.callerName | string | RP-Name des Spielers (oder der Platzhalter bei anonymer Meldung). |
call.anonymous | boolean | true, wenn die Meldung als anonym markiert wurde. |
call.pillar | table | Säulen-Daten (id, label, road, km, code, coords, etc.). |
call.service | table | Dienst-Daten (id, label, number, jobs, dispatchCode, priority, etc.). |
call.coords | vector3 | Exakte 3D-Koordinaten der Notrufsäule. |
call.street / zone | string | Straßen- und Gebietsname der Säule. |
call.message | string | Eingegebener Freitext des Anrufers. |
call.time | number | Zeitstempel (os.time()). |
Rückgabewerte des Adapters
Abschnitt betitelt „Rückgabewerte des Adapters“Dein Adapter muss dem System das Ergebnis der Weiterleitung mitteilen:
return true: Notruf erfolgreich abgesetzt.return false, 'Fehlermeldung': Fehler aufgetreten – Grund wird im Server-Log vermerkt und das System greift auf die Redundanz zurück.return true, nil, { unstaffed = true }: Einsatz erfolgreich im System erstellt, jedoch ist aktuell kein Personal im Dienst. Das Notrufsäulen-Bedienfeld meldet dem Anrufer, dass die Meldung weitergeleitet wurde und die Bereitschaft übernimmt; gleichzeitig wird die Redundanz ausgeführt.
Notrufe per Event mitlesen
Abschnitt betitelt „Notrufe per Event mitlesen“Möchtest du externe Scripte über eingehende Notrufe informieren, ohne einen Adapter zu schreiben, kannst du auf diese Events lauschen:
-- Wird nach jedem erfolgreich abgesetzten Notruf getriggert:AddEventHandler('hm_Notrufsaeulen:callDispatched', function(call, adapterName, success) print(('Notruf an %s über Adapter %s (Erfolg: %s)'):format(call.service.label, adapterName, tostring(success)))end)
-- Wird beim Adapter 'custom' aufgerufen:AddEventHandler('hm_Notrufsaeulen:onDispatch', function(call) -- Enthält alle Daten: call.coords, call.message, call.service, etc.end)Exports & Befehlsübersicht
Abschnitt betitelt „Exports & Befehlsübersicht“Exports
Abschnitt betitelt „Exports“-- Serverseitig: Tablet für einen bestimmten Spieler öffnenexports.hm_Notrufsaeulen:openTablet(source)
-- Clientseitig: Notrufmenü einer bestimmten Säule öffnenexports.hm_Notrufsaeulen:openPillarMenu(pillarId)Vollständige Befehlsreferenz
Abschnitt betitelt „Vollständige Befehlsreferenz“| Befehl | Ausführbar durch | Funktion |
|---|---|---|
/notruf_config | Editor, Admin | Öffnet das Config-Tablet im Spiel. |
notruf_grant <ID|identifier> [level] | Admin, Serverkonsole | Weist admin- oder editor-Rechte zu. |
notruf_revoke <ID|identifier> | Admin, Serverkonsole | Entzieht vergebene Berechtigungen. |
notruf_perms | Admin, Serverkonsole | Listet alle Berechtigungs-Einträge auf. |
/notruf_id | Jeder Spieler | Zeigt die eigenen Identifier zum Kopieren an. |
notruf_map | Admin, Serverkonsole | Druckt aktuelle Kartengrenzen für die config.lua aus. |
notruf_duty | Admin, Serverkonsole | Prüft den Personalstatus bei Emergency Dispatch und gleicht Jobs ab. |
notruf_reload | Admin, Serverkonsole | Liest alle JSON-Dateien in data/ neu ein. |
notruf_seed | Admin, Serverkonsole | Legt Standarddienste aus config/services.lua erneut an. |
/notruf_model [name] | Jeder (Client) | Prüft, ob das angegebene Model im Client gültig und geladen ist. |