Koja Scripts

Configuration

Every option in shared/config.lua grouped by block, with defaults and descriptions.

Configuration

Most settings live in shared/config.lua. Departments are in shared/departments.lua and the penal code in shared/penalcode.lua. These files, together with editable/ and locales/, are not escrowed, so you can edit them freely. Restart the resource after changes.

FilePurpose
shared/config.luaAll options below
shared/departments.luaDepartments, jobs, colors, crests, rank to access level. See Departments and permissions
shared/penalcode.luaConfig.PenalCode: 57 charges seeded into the database on first start. After that, charges are edited in game with the charges.manage permission
editable/server/framework.luaCitizen, vehicle, license and roster queries. See Integrations
editable/server/integrations.luaJail, impound, fine, society payout, medical bill adapters
editable/client/integrations.luaDeath check, vehicle-only rule, phone number, notifications
locales/*.jsonTranslations. See Translations

Values shown as {} or '' are empty by default. Percent and seconds are as named.

General

Config.Locale and Config.Languages

OptionDefaultDescription
Config.Locale'en'Server default language code. Falls back to en if the file does not exist.
Config.Languages.playerChoicetrueLets each player pick their own language in Settings.
Config.Languages.offered{}Whitelist of language codes players can choose from. Empty offers all languages. The server default is always offered.
Config.DebugfalsePrints extra debug lines in the server console.

Config.VersionCheck

OptionDefaultDescription
enabledtrueChecks for a new version at start and prints the result in the console.
url'https://versions.kojascripts.com'Version service address.
reportOtherResourcestrueAlso reports other Koja resources found on the server.

Config.Open

How the MDT is opened.

OptionDefaultDescription
command'mdt'Chat command. Empty string disables the command and the key.
keybind'F6'Default key. Players can rebind it in the FiveM keybind settings.
item'mdt_tablet'Inventory item that opens the MDT when used. Empty string turns the usable item off.
requireItemfalseWhen true, the player must carry the item to open the MDT.
vehicleOnlyfalseWhen true, the MDT only opens inside an emergency class vehicle (vehicle class 18).
allowWhenDeadfalseAllow opening the MDT while dead.
allowOffDutytrueWhen false, officers must be on duty to open the MDT.

Config.Tablet

Tablet prop and animation while the MDT is open.

OptionDefaultDescription
enabledtrueShow the tablet prop and play the animation.
prop'prop_cs_tablet'Prop model.
bone60309Ped bone the prop attaches to.
offsetvector3(0.03, 0.002, -0.0)Prop position offset.
rotationvector3(10.0, 160.0, 0.0)Prop rotation.
dict'amb@code_human_in_bus_passenger_idles@female@tablet@base'Animation dictionary.
clip'base'Animation clip.

Config.Ui

OptionDefaultDescription
scale1.0Overall tablet scale.
defaultTheme'department'Default theme source. department uses the department theme.
allowPersonalAccenttruePlayers can pick a personal accent color in Settings. It overrides the accent, not the surfaces.
fadeOutside0.4Tablet opacity when the mouse moves outside it.
clockFormat'24h'Clock format.
currency'$'Currency symbol shown in the UI.
dateLocale'en-US'Locale used to format dates.

Config.Interact

The quick interaction menu for officers: ask for ID, write a citation, run a plate, parking citation, open the MDT. It works with a radial menu or a target resource.

OptionDefaultDescription
enabledtrueTurn the interaction menu on or off.
key'LMENU'Default key (left Alt). Hidden when a radial or target provider takes over.
command'mdtinteract'Command behind the key (registered as +mdtinteract).
radial'auto'Radial menu provider: 'auto', a resource name (koja-police, ox_lib, qb-radialmenu), or false / 'off' / 'none'.
target'auto'Target provider: 'auto', a resource name (ox_target, koja-interactions, qb-target), or false / 'off' / 'none'.
keyWithProviderfalseKeep the key binding even when a provider is active.
replacePoliceItemstrueWith koja-police, replaces its own radial items (check ID, check plate, bill, MDT) with the MDT versions.
distance4.0Maximum distance to a person.
vehicleDistance7.0Maximum distance to a vehicle.
askConsenttrueThe other player is asked before their ID card is shown.
consentTimeout15Seconds the other player has to answer.

Config.DebugTools

Demo and test tools. Details in Demo mode.

OptionDefaultDescription
enabledtrueRegisters /mdtdebug and the demo seed. Set to false in production.
aces{ 'koja-mdt.debug', 'command' }Aces that may use the tools.
signChance0.75Chance that a fake citizen signs a citation when the mood is random.
officerModel's_m_y_cop_01'Ped model for fake officers (/mdtdebug cam).
citizenModelsfive civilian modelsPed models for fake citizens.
patrolVehicle'police'Vehicle for /mdtdebug cam drive.
citizenVehicle'sultan'Vehicle for /mdtdebug citizen car.

Records and justice

Config.Records

OptionDefaultDescription
sharedBetweenDepartmentstrueAll law enforcement departments see the same records. When false, records are split per department (DOJ still sees all).
citizenSearchLimit25Maximum people returned by a search.
vehicleSearchLimit25Maximum vehicles returned by a search.
maxNarrativeLength20000Maximum characters in a report narrative.
maxImagesPerRecord12Maximum photos per record.
vehicleStrikeLimit12Strike points on a vehicle at which the limit warning shows.
defaultWarrantHours72Default warrant lifetime in hours.
warrantsNeedApprovaltrueNew warrants wait for a judge (warrants.approve).
expireWarrantsEveryMinutes5How often expired warrants and overdue citations are checked.

Config.Processing

Sentencing a suspect from a report.

OptionDefaultDescription
enabledtrueAllow processing (fine and jail) from reports.
requireOnlinetrueThe suspect must be online.
maxDistance10.0Maximum distance between officer and suspect.
fineAccount'bank'Account the fine is taken from. If the balance is too low, cash is used.
fineSociety'society_police'Society account that receives fines. Empty string disables the payout.
allowNegativeBalancefalseAllow the bank balance to go below zero.
jailSystem'auto''auto', a jail resource name, or 'none'. See Integrations.
maxMonths999Highest jail sentence.
pointsLicense'driver'License type that receives penalty points.
pointsRevokeAt12Point total at which the license is revoked automatically.

Config.Custody

Jail and impound records. See also the custody guide in Features.

OptionDefaultDescription
enabledtrueTurn the Custody module on or off.
impoundSystem'auto''auto', 'koja-police', 'garage' or 'none'. auto uses koja-police when started, otherwise the garage fallback.
secondsPerMonth60Real seconds per sentence month. Keep it equal to your jail script.
maxMonths999Highest sentence the MDT stores.
autoReleasetrueCloses a jail record when its release time has passed.
trackedSystems{}Jail systems that report releases themselves; their records are never closed by the clock.
defaultFee500Default impound fee.
maxFee50000Highest impound fee.
defaultHours24Default hold time in hours.
maxHours720Longest hold time in hours.
despawnRadius15.0When an officer impounds in game, a vehicle with that plate within this radius is removed. 0 turns it off.
lotsfour lotsImpound lots: { id, label, coords }. Defaults are Mission Row, Davis, Sandy Shores and Paleto Bay.

Config.Citations

OptionDefaultDescription
enabledtrueTurn citations on or off.
item'citation'Inventory item for printed copies.
dueDays7Days to pay before a ticket becomes overdue.
lateFee{ percent = 25, flat = 0 }Added once when a ticket becomes overdue.
allowWebPaytruePay from the web portal. Works when the citizen is online, or when Bridge.ChargeOffline is added in editable/server/framework.lua.
applyPointstrueAdd the ticket's points to the license point total.
classes{ 'infraction' }Penal code classes that can be ticketed.
allowNoJailChargestrueAlso allow any charge with 0 months.
maxViolations12Maximum violations on one ticket.
handDistance5.0Maximum distance for handing over the ticket.
showOnHandovertrueShow the paper on the violator's screen after hand-over.
contestCreatesCasetrueA contested ticket files a court case.
contestGraceDays3Extra days to pay after a contest is upheld.
prefixeslspd = 'LS', bcso = 'BC', sahp = 'SA', default = 'SAN'Ticket number prefix per department id. Numbers look like LS-2026-000123.
quickeight charge codesCharge codes shown as quick-pick chips.
command'citation'Chat command for the ticket book. Empty disables it.
key''Optional default key for the ticket book.
bookInGametrueNew citation in the in-game MDT opens the ticket book. The web MDT always uses the form.
nearbyRadius10.0Radius of the nearby people list in the book.
requireOfficerSignaturetrueThe officer must sign before filing.
askCitizenSignaturetrueThe person receiving the ticket is asked to sign or refuse.
signTimeout30Seconds to answer. No answer counts as a refusal.
issueCooldown8Seconds between two tickets from one officer.
tearSoundtruePaper tear sound in the book.
readAnimclipboardAnimation and prop while reading the paper (enabled, dict, clip, prop, bone, offset, rotation).
writeAnimnotepad and pencilAnimation and props while writing (enabled, dict, clip, prop, bone, offset, rotation, pencil, pencilBone, pencilOffset, pencilRotation).
handAnimgive and takeHand-over animation (enabled, dict, give, take, prop, bone, offset, rotation, giveHold, takeAt, takeHold, signDelay).

Config.Doj

Court and DOJ options.

OptionDefaultDescription
caseNumberPrefix'SA'Case number prefix.
courtroomsCourtroom 1, Courtroom 2, Courtroom 3, ChambersRooms offered when scheduling.
caseTypescriminal, traffic, civil, appealCase types.
hearingKindsarraignment, preliminary, motion, trial, sentencing, appeal, otherHearing kinds.
docketKindsnote, filing, motion, ruling, orderDocket entry kinds.
linkKindsincident, evidence, bodycam, warrant, citation, documentRecord types that can be linked to a case.
sentence.enabledtrueAllow carrying out sentences from the court page.
sentence.requireOnlinetrueThe defendant must be online.
sentence.finetrueA sentence can apply the fine.
sentence.jailtrueA sentence can apply jail time.
expungement.enabledtrueExpungement requests.
expungement.portaltrueCitizens can request through the web portal.
expungement.maxPending2Open requests per person.
bar.rolesattorney, public_defender, prosecutor, judgeRoles in the bar registry.
bar.numberPrefix'SABAR'Bar number prefix.
seedFormstrueOn first start, DOJ departments get four form templates: subpoena, search warrant order, court order, expungement order.

Config.Police

Link to the koja-police resource.

OptionDefaultDescription
enabledtrueUse koja-police when it is started.
resource'koja-police'Resource name.
dispatchtrueLet koja-police use the MDT dispatch.
dutytrueShare duty state with koja-police.

Dispatch and units

Config.Dispatch

OptionDefaultDescription
enabledtrueTurn dispatch and the public call commands on or off.
publicCommands/911 (priority 1), /311 (priority 3)Commands players use to call. Each entry: command, code, title, priority.
publicCooldown30Seconds between public calls from one player.
anonymousCommand'911a'Anonymous call command. Empty disables it.
panicKey'F9'Default key for the panic button (10-99). Empty disables the key.
panicCooldown15Seconds between panic presses.
keepCallsMinutes30How long closed calls stay in the log.
maxCalls80Maximum calls kept.
blipSeconds90How long a call blip stays on the map.
alertSoundtruePlay a sound for new priority calls.
toastSeconds8How long the call toast shows.
callCodessix fire codesExtra call codes { code, title, priority, types }. types is the department types that receive the call (leo, ems, fire). Defaults: F-STR, F-VEH, F-BRU, F-ALM, F-RES, F-HAZ.

Config.Dispatch.gunshots

Automatic "shots fired" calls. The player's client watches for gunfire and the server turns it into a dispatch call to law enforcement, with a witness as the caller.

OptionDefaultDescription
enabledtrueTurn gunshot alerts on or off. Also needs Config.Dispatch.enabled.
code'10-71'Call code.
title'Shots fired'Call title.
priority1Call priority.
message'Caller reports gunshots in the area.'Call message.
vehicleMessage'Caller reports shots fired from a vehicle: %s %s.'Message when the shooter is in a vehicle. The two values are the vehicle color and model.
reportDelay{ 3, 8 }Random delay in seconds, { min, max }, before the call appears.
cooldownSeconds30Seconds between alerts from one player.
mergeRadius120.0Shots within this distance of a recent alert do not create a new call.
mergeSeconds60How long a recent alert blocks new ones inside mergeRadius.
fuzzRadius35.0The call location is moved by a random distance up to this value, so it is not exact.
ignoreOnDutytruePlayers on duty in one of the ignoreJobs do not trigger alerts.
ignoreJobs{ 'police', 'sheriff', 'sahp' }Jobs ignored while ignoreOnDuty is on.
ignoreSilencedtrueSilenced weapons do not trigger alerts.
ignoreWeaponsstun gun, fire extinguisher, petrol and hazard cans, flares, snowball, ball, Up-n-AtomizerWeapons that never trigger alerts. Weapon names, for example 'WEAPON_STUNGUN'.
ignoreZonesthree zonesPlaces where shooting is ignored, such as gun ranges. Each entry: { coords = vector3(...), radius = 25.0 }.

Config.QuickDispatch

The small call overlay shown on screen while the MDT is closed.

OptionDefaultDescription
enabledtrueTurn the overlay on or off.
side'right'Screen side.
maxVisible4Calls shown at once.
idleSeconds20Seconds before the overlay fades when idle.
dropMinutes15Minutes after which a call is dropped from the overlay.
keys.respond'Y'Respond to the focused call.
keys.dismiss'DELETE'Dismiss the focused call.
keys.previous'PAGEUP'Focus the previous call.
keys.next'PAGEDOWN'Focus the next call.
keys.toggle'HOME'Show or hide the overlay.

Config.DispatchVoice

A radio dispatcher reads new calls aloud. Officers can turn it off and change the volume in Settings.

OptionDefaultDescription
enabledtrueTurn the voice on or off.
language'en'Voice clip language (clips ship for English and Polish).
volume0.8Default volume.
radioFxtrueRadio effect on the voice.
alphabet'lapd'Phonetic alphabet, lapd or nato.
minPriority3Priority threshold for spoken calls. Priority 1 is the most urgent.
maxQueue4Maximum queued announcements.
staleSeconds25Announcements older than this are skipped.
speechFallbacktrueUse the browser speech synthesis when a clip is missing.
announce.newtrueAnnounce new calls.
announce.panictrueAnnounce panic alerts.
announce.attachtrueAnnounce responding units.
announce.closedfalseAnnounce closed calls.

Config.Units

Unit statuses shown on the unit board.

OptionDefaultDescription
statusesavailable 10-8, busy 10-6, enroute 10-97, onscene 10-23, traffic 10-38, break 10-7Default statuses { id, code, color }.
byTypeems, fire, doj listsStatus lists per department type. EMS adds transport and hospital, fire adds staging, DOJ uses court.
autoEnrouteOnAttachtrueAttaching to a call sets the status to en route.
setWaypointOnAttachtrueAttaching to a call sets a GPS waypoint.

A department can also define its own statuses list in shared/departments.lua.

Config.Duty

OptionDefaultDescription
trackTimetrueTrack duty time for hours and the heatmap.
syncWithFrameworktrueDuty in the MDT also sets the framework job duty.
toggleCommand'mdtduty'Chat command to toggle duty. Empty disables it.

Config.Roster

OptionDefaultDescription
selfCallsigntrueOfficers may set their own callsign and badge.
hireGrade0Job grade given when hiring a nearby player.
fireJob'unemployed'Job given when someone is fired.
fireGrade0Grade given when someone is fired.

Photos and cameras

Config.Camera

The Take a photo button for mugshots, evidence and reports. Needs screenshot-basic.

OptionDefaultDescription
enabledtrueTurn the photo button on or off.
uploadUrl''Keyless upload endpoint, for example a Discord webhook. This file is sent to every client, so never put an API key here. For Fivemanage or S3 use Config.Storage (below) with images = 'storage' instead, which uploads through the server. When both are empty the photo button is hidden. Image links can always be pasted by hand.
uploadField'files[]'Form field name for the file.
encoding'webp'Image format.
quality0.85Image quality (0 to 1).

Config.Storage

Where bodycam footage and MDT images are kept. The default keeps everything on the server disk and images inline in the database, exactly as before. See Storage and CDN for step by step setup of Cloudflare R2, AWS S3, Backblaze B2, MinIO and Fivemanage.

OptionDefaultDescription
driver'local''local', 's3' (any S3-compatible service) or 'fivemanage'.
images'inline''inline' stores uploaded pictures as data URLs in the database. 'storage' uploads them through the server to the driver and saves the public URL.
footage'local''local' keeps bodycam segments in recordings/ inside the resource. 'storage' uploads each segment to the driver and removes the local copy.
segmentSeconds10Seconds of footage packed into one segment file (2 to 60). At 8 fps that is 80 frames and 360 uploads per recording hour.
concurrency3Parallel uploads and deletes.
maxBacklog400Jobs held in memory. Extra segments wait on disk and are picked up every 30 seconds.
s3.endpoint''S3 API endpoint, for example https://<accountid>.r2.cloudflarestorage.com.
s3.region'auto''auto' for R2. AWS, B2 and MinIO need their real region, for example 'eu-central-1'.
s3.bucket''Bucket name.
s3.publicUrl''Public base URL of the bucket (r2.dev, a custom domain or a CDN). Required for images = 'storage'. When set, footage is also served from it instead of presigned links.
s3.pathStyletruetrue uses https://endpoint/bucket/key, false uses https://bucket.endpoint/key.
s3.presignMinutes10Lifetime of presigned playback links.
s3.prefix'koja-mdt/'Key prefix for every object.
fivemanage.path'koja-mdt'Folder used on Fivemanage.

Secrets never go in shared/config.lua, because that file is sent to every player. Set them as server convars in server.cfg. Use set, not setr or sets, so they stay on the server:

server.cfg
set koja_mdt_s3_access_key "your-access-key-id"
set koja_mdt_s3_secret_key "your-secret-access-key"
set koja_mdt_fivemanage_key "your-fivemanage-api-key"

You can also fill editable/server/storage.lua instead. It is loaded on the server only and a non-empty value there wins over the convar.

The startup banner prints a Storage line with the driver and the result of a self-test (HeadBucket for S3, a tiny upload and delete for Fivemanage). Any missing option is printed as a warning and the MDT falls back to local disk and inline images.

The bucket must allow GET from the MDT interface and from your web portal. Paste this CORS policy and replace the last origin with your portal address:

CORS policy
[
  {
    "AllowedOrigins": ["https://cfx-nui-koja-mdt", "nui://koja-mdt", "https://mdt.example.com"],
    "AllowedMethods": ["GET", "HEAD"],
    "AllowedHeaders": ["*"],
    "ExposeHeaders": ["Content-Length", "ETag"],
    "MaxAgeSeconds": 3600
  }
]

Config.Avatars

Profile pictures taken from the character's head shot.

OptionDefaultDescription
enabledtrueTurn avatars on or off.
captureOnLoadtrueCapture when the player loads in.
loadDelaySeconds10Delay after load before capture.
refreshMinutes20Automatic refresh interval.
command'mdtphoto'Command to refresh your photo. Empty disables it.
transparenttrueTransparent background.
size128Image size in pixels.
format'image/webp'Image format.
quality0.85Image quality.
minUploadSeconds60Minimum seconds between uploads.
maxLength150000Maximum stored image size.
selfie.enabledtrueSelfie photo for the profile. Needs screenshot-basic.
selfie.size256Selfie size.
selfie.quality0.88Selfie quality.
selfie.cooldownSeconds20Cooldown between selfies.
selfie.maxLength400000Maximum size of a selfie image in characters. The effective limit is the larger of this and maxLength. A bigger selfie is rejected and the reason is printed in the server console.
selfie.phone0Phone variant used for the selfie camera.
selfie.crop{ side = 0.7, centerX = 0.42, centerY = 0.45 }Crop area of the captured frame.

Config.Cameras

CCTV cameras and the camera viewer.

OptionDefaultDescription
enabledtrueTurn CCTV on or off.
adminAce'koja-mdt.cameras'Ace for placing and editing cameras.
seedDefaultstrueSeed default cameras on first start.
timecycle, timecycleStrength, extraTimecycle, brokenTimecycleCAMERA_secuirity, 1.0, scanline_cam_cheap, CAMERA_secuirity_FUZZScreen filter while viewing.
defaultFov, minFov, maxFov60.0, 8.0, 90.0Field of view and zoom limits.
lookSpeed, keySpeed, zoomStep6.0, 1.2, 4.0Control speeds.
hudInterval33HUD update interval in ms.
maxMoveSpeed3.0Maximum camera move speed.
propModel, propModelsprop_cctv_cam_01a and six moreCamera prop models offered when placing.
propDistance150.0Distance at which camera props are streamed.
limitspan -180 to 180, tilt -89 to 60panMin, panMax, tiltMin, tiltMax, defaultPan, defaultTiltDown, defaultTiltUp.
freecamspeedsspeed, fastMultiplier, slowMultiplier, lookSpeed, raycastDistance for the placement free camera.
placementplacement defaultspropByDefault, wallPan, lensGap, hiddenGap, poleHeight, poleLensDrop, frustumRange, reviewDistance, propHeadings.
keyscontrols and labelsKey controls used in the viewer and in placement mode. Each is { controls = { ... }, label = '...' }.
anprcamera plate readingSee below.

Camera ANPR (Config.Cameras.anpr):

OptionDefaultDescription
enabledtrueRead plates through CCTV cameras.
range80.0Reading range in meters.
interval200Scan interval in ms.
trackInterval33Tracking interval in ms.
maxVehicles12Vehicles tracked at once.
units'kmh'Speed units.
cacheSeconds60Result cache time.
maxPlatesPerRequest10Plates per lookup request.
hitSoundtrueSound on a hit.

Config.Bodycams

OptionDefaultDescription
enabledtrueTurn bodycams on or off.
item'bodycam'Item name.
requireItemfalseThe officer must carry the item.
key'F7'Default key to start or stop. Empty disables the key.
command'bodycam'Command: /bodycam [on, off, rec, stop]. Empty disables it.
auto.dutyfalseStart automatically when going on duty.
auto.sirentrueStart when sirens are switched on.
auto.weapontrueStart when a weapon is drawn.
auto.dispatchtrueStart when attached to a call.
auto.panictrueStart on panic.
idleStopSeconds0Stop after this many idle seconds. 0 turns it off.
breadcrumbSeconds15Position sample interval.
keepDays30Days sessions are kept. 0 keeps them forever.
crossDepartmentfalseAllow watching bodycams of other departments.
label'BODY 4'Label shown on the recording overlay.
shotCooldown3Seconds between recorded shot events.
viewcamera mountbone, offset, fov, shake, streamTimeout for the live view.
keysviewer controlsexit (Backspace), next (E), previous (Q).
recordingsee belowFootage capture and storage settings.

Config.Bodycams.recording

Footage is captured by the wearer's client as a series of pictures (needs screenshot-basic), sent to the server in batches and packed into segments. See Storage and CDN for where segments are kept.

OptionDefaultDescription
enabledtrueRecord footage. Live view still works without it.
intervalMs125Milliseconds between frames (50 to 10000). 125 is 8 frames per second. See the table below.
maxInFlight4Frames captured at the same time on the client (1 to 8). Higher keeps the frame rate steady on a slow machine but uses more CPU.
width560Frame width in pixels (160 to 1920).
quality0.42Image quality (0.1 to 1.0).
format'jpg''jpg' or 'webp'.
batchFrames16Frames sent to the server in one message (1 to 24).
latentBps400000Upload speed limit in bytes per second for frame batches. Raise it if frames are dropped at a high frame rate.
maxFrameKB80Largest accepted frame (8 to 512). Bigger frames are dropped.
keepDays14Days footage is kept (0 keeps it forever). Separate from Config.Bodycams.keepDays, which keeps the session data.
keepLinkedtrueFootage attached to an incident is deleted last when the disk limit is reached and is not deleted by keepDays.
maxMinutesPerSession60Longest footage per recording (1 to 720).
maxDiskMB20480Total disk limit for footage in MB. The oldest footage is deleted when it is exceeded. 0 turns the limit off.
httptrueServe footage to the player over the web route.
baseUrl''Public base URL for footage links. Empty uses the web portal address (Config.Web.publicUrl).
tokenMinutes10Lifetime of a playback link in minutes (1 to 120).

Frame rate is set with intervalMs:

intervalMsFrames per secondNotes
2005Lightest. Choppy but good enough for review.
1258Default. Smooth enough for most uses.
10010Smoother motion.
6615Smoothest. Heavy.

Config.Anpr and in-vehicle ALPR

OptionDefaultDescription
enabledtrueTurn plate lookups on or off.
cacheSeconds30Lookup cache time.
maxPlatesPerRequest10Plates per request.
requireDutytrueVehicle ALPR only works on duty.
hitCooldown120Seconds before the same plate alerts again.
unknownIsHitfalseTreat unregistered plates as hits.
hitFlags{}Extra vehicle flags that count as a hit. Stolen, BOLO and warrant are always hits.
autoDispatchtrueA hit creates a dispatch call.
dispatchCode'10-ALPR'Call code.
dispatchCooldown300Seconds between calls for the same plate.
blip{ sprite = 225, color = 1, scale = 1.0 }Call blip.
keepDays14Days the ANPR log is kept.
vehicle.enabledtrueTurn the in-vehicle ALPR on or off.
vehicle.modelspolice, police2, police3, police4, sheriff, sheriff2, fbi, fbi2, prangerVehicle models with ALPR.
vehicle.allowEmergencyClasstrueAlso allow any emergency class vehicle.
vehicle.range45.0Detection range.
vehicle.radius2.5Detection radius.
vehicle.cone22.0Detection cone angle.
vehicle.interval400Scan interval in ms.
vehicle.clientCacheSeconds25Client side cache.
vehicle.units'kmh'Speed units.
vehicle.position'bottom-right'Panel position.
vehicle.scale1.0Panel scale.
vehicle.soundtrueHit sound.
vehicle.history6Plates shown in the panel history.
vehicle.autoShowtrueShow the panel by default when sitting in an ALPR vehicle.
vehicle.keys.toggle'F10'Show or hide the panel.
vehicle.keys.lockFront'UP'Lock the front plate.
vehicle.keys.lockRear'DOWN'Lock the rear plate.
vehicle.keys.open'RIGHT'Open the locked vehicle in the MDT.

Inventory and forms

Config.Inventory

OptionDefaultDescription
system'auto''auto' uses koja_grid_inventory when started. 'framework' forces the framework inventory through koja-lib.
registerItemstrueWith koja_grid_inventory, register citation, mdt_document and bodycam automatically.
itemsthree itemsDefinitions { label, description, size, weight, image } for those items.

Config.Forms

OptionDefaultDescription
enabledtrueTurn forms on or off.
item'mdt_document'Item given when a form is filed.
requireSignaturetrueForms must be signed.
readAnimclipboardAnimation and prop while reading a document.

Config.Mail, Config.Notifications, Config.Calendar

OptionDefaultDescription
Config.Mail.maxRecipients30Recipients per mail.
Config.Mail.maxBodyLength10000Maximum characters in a mail.
Config.Mail.keepDays0Days mail is kept. 0 keeps it forever.
Config.Notifications.keepDays30Days notifications are kept.
Config.Calendar.remindMinutes30Reminder before an event.
Config.Calendar.notifyOnCreatetrueNotify attendees of new events.
Config.Calendar.notifyOnCommenttrueNotify on comments.
Config.Calendar.maxRangeDays62Longest range that can be loaded.
Config.Calendar.maxAttendees500Attendees per event.
Config.Calendar.maxCommentLength500Characters per comment.
Config.Calendar.reactionseight emojiReactions offered on events.
Config.Calendar.courttrueShow court hearings in the calendar.

Logs, admin and security

Config.Logs

OptionDefaultDescription
keepDays30Days audit entries are kept. 0 keeps them forever.
webhook''Discord webhook for all categories.
webhooksincidents, warrants, processing, roster, dispatchOne webhook per category, all empty by default.

Config.Admin

OptionDefaultDescription
ace'koja-mdt.admin'Ace that grants admin panel access.
allowCommandAcetrueThe generic command ace also grants access.
departmentOverridestrueAdmin panel can override departments, ranks and permissions.
jobEditingtrueAdmin panel can edit jobs and grades. Works on ESX with jobs and job_grades tables.
logsKeepDays30Age used by the purge logs button when Config.Logs.keepDays is 0.

Config.Security

Every request from the UI is rate limited and permission checked on the server.

OptionDefaultDescription
burst12Request bucket size per player.
perSecond6Bucket refill per second.
dropAfterFlags0Kick a player after this many suspicious flags. 0 never kicks.
dropMessage'koja-mdt: suspicious activity'Kick message.
limitsper endpointStricter buckets { burst, perSecond } for citizens:search, vehicles:search, incidents:process, dispatch:public, anpr:lookup, anpr:vehicle, anpr:camera, bodycam:toggle, bodycam:auto, bodycam:shot, bodycam:beat, bodycams:watch.

Web portal

Config.Web

See the portal section in Features.

OptionDefaultDescription
enabledtrueTurn the portal on or off.
publicUrl''Your own public address, for example behind nginx. Takes priority over the relay and the Cfx.re proxy.
allowCitizenstrueAny player can sign in to the citizen portal.
citizenRecordtrueCitizens see their own record and licenses.
loginCodeMinutes10How long the /mdtweb code is valid.
sessionDays30Session length, renewed on use.
maxSessionsPerAccount5Devices per account.
command'mdtweb'Command that gives a login code. Empty disables it.
allowedOrigins{}Extra origins allowed for cross-origin requests.
trustProxyHeadersfalseTrust the client IP from a reverse proxy, so rate limits see the real address.
relay.enabledtrueUse the relay for a short HTTPS address.
relay.url'https://mdt.kojascripts.com'Relay address.
relay.id''Readable server id (4 to 40 characters, a-z, 0-9, -). Empty generates a random one and keeps it.
relay.localUrl'http://127.0.0.1:30120'Local address the relay forwards requests to.

Staff data

Config.Divisions

List of default divisions created for each department on first start. Each entry has name, short, icon, color, description. Defaults: Firearms, Traffic Enforcement, Detective Bureau, K-9 Unit, S.W.A.T and Human Resources.

Config.Certifications

List of default certifications { id, label, color }. Defaults: fto, swat, k9, air, marine, motor, detective, traffic, negotiator, sniper.

Config.ProfileTags

Flags on a person's file { id, label, color }. Defaults: armed, gang, parole, probation, violent, officer_safety, mental, informant, flight_risk.

Config.IncidentTypes

Report types { id, label, icon, template }. The template is the starting text of the narrative. Defaults: arrest, citation, traffic, pursuit, investigation, use_of_force, death, other.

Config.EvidenceTypes

Evidence types { id, label }. Defaults: weapon, casing, blood, drugs, cash, document, electronic, photo, vehicle, other.

EMS

Config.Ems

OptionDefaultDescription
policeSummary.enabledfalseLets selected police ranks read a patient's medical summary (patients.summary). Every view is logged.
policeSummary.rankssupervisor, commandAccess levels that get it.
bloodTypeseight typesBlood types offered.
incidentTypeseleven typesePCR incident types { id, label }.
catalogprocedures and medicationsTreatment catalog { id, label, kind, dose, price }. kind is procedure or medication.
feesfive feesExtra fees { id, label, price }: call-out, ground transport, air transport, hospital admission, consultation.
hospitalsPillbox, Sandy Shores, Paleto BayHospitals { id, label, short, beds } for the bed board.
billing.enabledtrueMedical bills.
billing.account'bank'Account charged. Cash is used if the bank is short.
billing.society'society_ambulance'Society that receives the money.
billing.requireOnlinetruePatient must be online.
billing.maxDistance0.0Maximum medic to patient distance. 0 means no limit.
billing.allowCustomItemstrueAllow custom bill lines.
billing.maxCustomPrice25000Highest price of a custom line.
billing.maxTotal100000Highest bill total.
maxVitals, maxInjuries, maxTreatments6, 24, 40Limits per ePCR report.
OptionDefaultDescription
enabled'auto''auto' links when koja-ambulance is started. false turns the link off.
resource'koja-ambulance'Resource name.
jobs{ 'ambulance' }Must match Config.Jobs of koja-ambulance.
duty'sync''sync' the MDT toggle and /mdtduty switch koja-ambulance duty. 'follow' duty is only changed at the hospital. false keeps duty separate.
dutyPollSeconds5How often koja-ambulance duty is read.
importtrueImport from patient button in the ePCR editor.
historytrueShow koja-ambulance records and invoices on the patient page.
downtrueDashboard panel with downed patients.
billing'mdt''mdt' charges bills in the MDT. 'ambulance' sends them as koja-ambulance invoices.
treatmentWindowMinutes60How far back treatments are read for import.
dispatch.enabledtrueDistress signals appear as EMS calls.
dispatch.mirrortrueMirror calls koja-ambulance sends to medics.
dispatch.distresstrueCreate calls from distress signals.
dispatch.downedfalseCreate a call as soon as someone goes down.
dispatch.closeOnRevivetrueClose the call when the patient is revived.
dispatch.forwardfalseSend MDT calls for EMS to koja-ambulance.
dispatch.code'10-52'Call code.
beds.enabledtrueShow occupied koja-ambulance beds on the board.
beds.admittrueCheck-ins create an MDT admission.
beds.dischargetrueFreeing the bed discharges the admission.
beds.admitRestingfalseAlso admit patients who are only resting.
beds.map{}Bed mapping [hospital][index] to MDT beds. Empty uses the MDT bed list in order.
regionshead, chest, abdomen, arms, legsMaps koja-ambulance body zones to the ePCR body diagram.
injuryKindsgunshot, stab, laceration and moreMaps wound types to ePCR injury kinds.
treatmentsbandage, tourniquet, morphine and moreMaps koja-ambulance treatments to catalog ids.