Settings keys
Every key below can be read with GetSetting(key) and changed with SetSetting(key, value). Admins change the same keys in game with /dispatchadmin (groups in Config.Admin.groups or the ACE koja-dispatcher.admin). Changes are saved in the koja_dispatch_settings table and survive restarts; until something is saved, the defaults come from the config files.
local dispatch = exports['koja-dispatcher']
print(dispatch:GetSetting('calls.patience')) -- 45
local ok, err = dispatch:SetSetting('calls.patience', 60)Value rules
| Type | SetSetting accepts | Notes |
|---|---|---|
| bool | true or false | Strings like 'true' are rejected with invalid. |
| int | any number | Rounded, then clamped to the range. |
| number | any number | Clamped to the range. The step is only used by the admin slider. |
| enum | one of the listed strings | Exact match, otherwise invalid. |
Every change fires the settingChanged hook and event. GetSetting returns nil for an unknown key.
Core
The core keys are shown on the Modes, Calls, Units, Pay, Features and Integration pages of the admin menu.
| Key | Type | Range or values | Default | Effect |
|---|---|---|---|---|
mode.calls | enum | generated, real, mixed | mixed (Config.Modes.calls) | Where calls come from. generated: only AI callers; player and API calls skip the console. real: only players, sensors, API and MDT; no generated calls. |
mode.units | enum | ai, players, mixed | mixed | Which units exist. ai: no player units. players: AI units go offline. |
mode.noDispatcher | enum | reject, auto, mdt | reject | What the call router does when nobody is on shift. |
access.maxDispatchers | int | 0 to 32 | 0 | Dispatchers on shift at once. 0 = no limit. |
access.remote | bool | false (Config.Dispatcher.remote) | Allowed jobs can open the CAD anywhere with /cad. | |
calls.intervalMin | int | 10 to 600 s | 35 | Shortest gap between generated calls. |
calls.intervalMax | int | 10 to 900 s | 80 | Longest gap between generated calls. |
calls.maxRinging | int | 1 to 12 | 4 | No new generated call while this many ring. |
calls.maxActiveIncidents | int | 1 to 50 | 10 | No new generated call while this many incidents are active. |
calls.patience | int | 15 to 300 s | 45 | How long a generated caller waits before hanging up (missed call). |
calls.playerReplyWindow | int | 30 to 900 s | 180 | How long a player's 911 line stays open for follow-up messages. |
calls.perDispatcherSpeedup | number | 0 to 1, step 0.05 | 0.15 | Calls come this much faster for every extra dispatcher. |
units.disableWhenPlayers | int | 0 to 32 | 3 | AI units of a department go off duty when this many players of it are on duty. 0 = never. |
pay.enabled | bool | true | Pay dispatchers when a shift ends. | |
pay.perMinute | int | 0 to 1000 | 6 | Money per minute on shift. |
pay.perPoint | int | 0 to 100 | 2 | Bonus per score point. |
pay.minimumMinutes | int | 0 to 120 | 3 | Shorter shifts are not paid. |
pay.maximum | int | 0 to 1 000 000 | 15000 | Cap per shift. 0 = no cap. |
features.cinematic | bool | true | Camera fly-in when a dispatcher clocks in. | |
features.aiCallers | bool | false (Config.AI.enabled) | Live AI voice callers (needs the OpenAI / ElevenLabs keys). | |
features.sensorDowned | bool | true | A call when a player stays down. | |
features.sensorShots | bool | true | A call when someone shoots in the city. | |
features.sensorCrash | bool | true | A call after a heavy vehicle crash. | |
features.showCivilians | bool | true | Players without a service job appear on the map. | |
features.showNpcPeds | bool | false | NPC peds on the map (costs performance). | |
features.fieldScenes | bool | true | Field units see props and peds at the scene. | |
features.fieldWaypoint | bool | true | GPS waypoint for assigned field units. | |
mdt.enabled | bool | true | The koja-mdt integration as a whole. | |
mdt.pushIncidents | enum | off, real, all | real | Send incidents to the MDT. real: from players, API, manual and MDT. all: also generated calls. |
mdt.pullCalls | enum | off, calls, incidents | calls | MDT calls ring in the CAD (calls) or open as incidents (incidents). |
mdt.syncStatus | bool | true | Unit status and assignments sync both ways. | |
mdt.useCallsigns | bool | true | Player units use their MDT callsign. | |
api.clientAlerts | bool | false (Config.Api.clientAlerts) | Allow the client export SendAlert. |
Modules
Module keys are registered by the feature files and shown on the Modules page of the admin menu, one group each.
| Key | Type | Range or values | Default | Effect |
|---|---|---|---|---|
career.enabled | bool | true | XP, ranks, simultaneous lines, call gates and supervisor powers. | |
career.xpMultiplier | number | 0.1 to 5, step 0.1 | 1.0 | Scales XP from score, incidents, codes and instructions. |
career.xpTimeMultiplier | number | 0 to 5, step 0.1 | 1.0 | Scales XP per minute on shift. |
career.xpPenaltyMultiplier | number | 0 to 5, step 0.1 | 1.0 | Scales XP lost for missed calls and failed incidents. |
career.gateCalls | bool | true | Low ranks cannot answer gated calls (pursuit, hostage, MCI). | |
career.gateOwnership | bool | true | Only supervisors can reassign, cancel or reprioritise another dispatcher's incident. | |
compat.enabled | bool | true | Accept alerts from other dispatch scripts. | |
compat.mode | enum | call, incident | call | Alerts ring at the console (call) or go straight to the map (incident). |
compat.autoAssign | bool | true | Incidents from alerts get the nearest free units at once. | |
discord.enabled | bool | true | Discord logging (webhooks from server convars). | |
discord.shifts | bool | true | Log shift start and end. | |
discord.incidents | bool | true | Log ended incidents. | |
discord.calls | bool | true | Log missed and dropped calls. | |
discord.admin | bool | true | Log setting and admin changes. | |
discord.events | bool | true | Log pursuits and mass casualty incidents. | |
discord.minPriority | int | 1 to 3 | 3 | Lowest incident priority to log. 3 logs all, 1 only priority 1. |
dynamics.events | bool | true | Scenario events during and after calls. | |
dynamics.stages | bool | true | Multi-stage incidents. | |
dynamics.weather | bool | true | Generated calls weighted by in-game hour and weather. | |
dynamics.strength | number | 0 to 2, step 0.1 | 1.0 | How strong the weighting is. 0 off, 2 double. |
fleet.enabled | bool | true | AI unit fatigue and damage. | |
fleet.fatigueRate | number | 0 to 30, step 0.5 | 6.0 | Fatigue points an AI unit gains per minute on scene (travel counts about a third). |
fleet.restSeconds | int | 15 to 1800 | 180 | Rest time at the station. |
fleet.repairSeconds | int | 15 to 1800 | 240 | Repair time at the station. |
fleet.damageChance | number | 0 to 1, step 0.05 | 0.25 | Chance a unit on a violent call gets damaged. |
hospitals.enabled | bool | true | Transports fill hospital beds (Config.HospitalBeds). | |
hospitals.turnoverSeconds | int | 30 to 7200 | 600 | Seconds until an occupied bed frees up. |
mdt_status.enabled | bool | true | Field status codes (keys, /tencode, quick menu). Synced to clients. | |
mdt_status.hud | bool | true | Status chip on the field unit's HUD. Synced to clients. | |
mdt_status.backupUnits | int | 1 to 6 | 2 | Extra units auto-assigned on a backup request. |
mdt_status.cooldown | int | 5 to 600 s | 45 | Per officer, for backup and the panic fallback. |
mdt_status.panicFallback | bool | true | Without koja-mdt, 10-99 creates a priority 1 incident. | |
mdt_tools.monitor | bool | true | MDT workspace drawer in the CAD (key B). | |
mdt_tools.boloSource | enum | auto, mdt, internal | auto | Where BOLOs live (also for CreateBolo). auto: koja-mdt when running, internal otherwise. mdt: refuse new BOLOs while the MDT is down. |
mdt_tools.alpr | bool | true | Alert dispatchers on ALPR hits (ReportPlate, koja-mdt:anpr:hit). | |
mdt_tools.notifyUnits | bool | true | Send internal BOLOs to on-duty police units. | |
patrol.enabled | bool | true | Patrol zones idle AI units drive in. | |
patrol.maxZones | int | 1 to 32 | 8 | Maximum patrol zones. |
patrol.speedFactor | number | 0.2 to 1, step 0.05 | 0.6 | AI speed inside a patrol zone. |
phones.enabled | bool | true | Phone calls and texts (PhoneCall, koja-dispatcher:phone:call, supported phones) reach the dispatcher. | |
phones.resource | enum | auto, lb-phone, qs-smartphone-pro, gksphone, npwd, yseries | auto | Phone resource; auto takes the first running one in Config.Phones.order. |
phones.number | int | 1 to 99999 | 911 | Service number players dial or text. |
pursuit.enabled | bool | true | Pursuit incidents get a moving suspect vehicle. | |
pursuit.maxActive | int | 0 to 10 | 2 | Live pursuits at once; more stay normal incidents. |
pursuit.loseSeconds | int | 10 to 300 | 40 | Suspect is lost after this long without visual. |
pursuit.spikes | int | 0 to 10 | 3 | Spike strips per pursuit. |
pursuit.roadblocks | int | 0 to 10 | 2 | Roadblocks per pursuit. |
pursuit.spikeChance | number | 0 to 1, step 0.05 | 0.65 | Chance a spike strip slows the suspect. |
pursuit.roadblockChance | number | 0 to 1, step 0.05 | 0.5 | Chance the suspect stops at a roadblock. |
pursuit.speedFactor | number | 0.5 to 2, step 0.05 | 1.15 | Suspect speed relative to a patrol car. |
pursuit.escalationChance | number | 0 to 1, step 0.05 | 0.3 | Chance a suspect flees in a vehicle when a robbery, assault or shooting escalates. |
stats.enabled | bool | true | Store closed incidents for the heatmap and statistics. | |
stats.retentionDays | int | 1 to 365 | 30 | Older history rows are deleted. |
training.enabled | bool | true | Guided tutorial from the top bar. Synced to clients. | |
training.offerFirstShift | bool | true | Offer the tutorial to dispatchers with no finished shifts. Synced to clients. | |
training.practiceCalls | bool | true | Private practice calls for trainees. Synced to clients. | |
voice.enabled | bool | true | Voice channel between dispatcher and player caller. Turning it off ends every voice call. | |
voice.provider | enum | auto, pma-voice, mumble-voip | auto | Voice resource; auto tries pma-voice first. |
voice.channelBase | int | 1000 to 9 000 000 | 91100 | First call channel id; the next 900 ids are used. |
voice.endOnDispatch | bool | true | Off: the caller stays on the line after dispatch until the dispatcher ends it. | |
voice.allowTransfer | bool | true | Dispatchers can hand the voice call to a player unit. |
Module defaults come from the config files in shared/config/ (career.lua, integrations.lua, dynamics.lua, fleet.lua, pursuit.lua, stats.lua, voice.lua). The mdt_status.*, mdt_tools.*, career.xp*, career.gate* and training.* defaults are fixed in code.
Side effects of a change
| Key | Extra effect |
|---|---|
mode.units, units.disableWhenPlayers | Player and AI unit membership is re-applied at once. |
mode.calls | The generated call timer restarts. |
mdt.*, mdt_tools.* | The koja-mdt link and BOLO list refresh. |
access.remote, features.cinematic, features.fieldScenes, features.fieldWaypoint and the client module keys | Pushed to every client (koja-dispatcher:client:sync). |
career.enabled | Rank state is pushed to dispatchers. |
dynamics.weather, dynamics.strength | The weather state is re-broadcast. |
voice.enabled = false | Every running voice call ends (reason = 'disabled'). |
Adding your own setting
Register your own keys with the RegisterSetting export from another resource, or with KOJA.Server.Settings.Register in a file in server/custom/ inside koja-dispatcher. Both appear on the Modules page and work with GetSetting / SetSetting. See Register your own admin setting for the full recipe and the difference between the two.