Configuration Reference
Per-key reference for the shipped oxide-police config files and DB-backed settings.
Reference for the shipped oxide-police config files and DB-backed settings.
Use /police settings for resource-wide settings. On first boot, the current config-file values are seeded into oxide_settings; after that, the database is the source of truth and file values are factory defaults used by reset-to-default and new-key backfill. Departments, stations, grades, garages, armories, uniforms, channels, detention points, and placed cameras remain in their existing admin/database workflows under /police admin.
SpeedCam.Models, FleetCatalog, and PlaceableObjects.props contain locale-baked labels. Those labels are frozen into the database when their top-level key is first seeded. After changing ox:locale, delete the corresponding oxide_settings rows and restart oxide-police to seed the new labels (this also discards saved edits to those keys):
DELETE FROM oxide_settings
WHERE resource = 'oxide-police'
AND setting_key IN ('SpeedCam', 'FleetCatalog', 'PlaceableObjects');shared/config.lua
Global
| Setting | Default | Description |
|---|---|---|
Config.Debug | false | Enables verbose console output from each module |
Config.UseBankingAccount | true | Creates a department banking account through oxide-banking |
Config.BankingAccountStartBalance | 30000 | Starting treasury balance for newly created departments |
Config.SalaryInterval | 15 * 60 * 1000 | Payroll tick interval (ms). Default 15 minutes |
Config.PlayerManagement | true | When true, salaries debit the department treasury and unpaid ticks accrue in police_unpaid_payroll for boss settlement. When false, salaries are paid directly from the framework with no treasury impact |
Config.UnpaidHoursDecayDays | 30 | Days after which unpaid payroll rows are pruned |
Config.AllowBossSetup | false | Lets a department boss open /police admin for their own department only to set up its stations, interaction points, garages, doors, CCTV, speed cameras, detention points and jail policy — without server-level admin. Bosses can never create/delete/rename a department, fund a treasury, or reach the server-wide screens. Enforced server-side. See Admin → Letting department bosses set up their own stations |
Config.MaxLoadoutItems | 50 | Max items per armory loadout |
Config.FleetRecoveryFee | 750 | Charged to the department treasury each time a boss tows a checked-out fleet vehicle back from the field (Fleet screen). 0 = free |
Config.InteractionDistance | 3.0 | Generic interaction reach |
Config.StationZoneSize | vec3(1.4, 1.4, 1.8) | Default ox_target box size for station zones |
Config.StationZoneDistance | 2.0 | ox_target per-option reach for station zones |
Config.RequireStationClockIn | true | When true, officers can only go on/off duty at a station's clock-in zone, and the /police duty command and the duty toggle inside the police radial menu are disabled. Set to false to let officers toggle duty from anywhere |
Config.AllowMultiDepartment | false | When true, a character can belong to several departments at once (each with its own badge, callsign, rank, and payroll); their active department follows whichever police job is selected in the framework / multi-job menu. When false, hiring into a second department transfers them out of the first. Required for g-multijob — see the ESX setup guide |
Config.ActionMenuKey | 'F2' | Default keybind for the police actions menu (+policeactions) |
Admin tools are not gated by a custom ACE permission. The /police admin panel and admin commands use your server's standard admin permission — the same one used elsewhere on your server. See Admin → Permissions.
Doors
| Setting | Default | Description |
|---|---|---|
Config.Doors.InteractionDistance | 0.8 | ox_target sphere radius around each door |
Config.Doors.ZoneDistance | 1.8 | ox_target per-option reach for door zones |
Config.Doors.ToggleKey | 'L' | Hotkey to toggle the nearest door's lock |
Config.Doors.ToggleMaxDistance | 2.0 | Max range (m) the hotkey will pick up a door |
Config.Doors.PickerMaxDistance | 10.0 | Door-picker max range |
Config.Doors.LockSound / UnlockSound | DOOR_LOCK / DOOR_UNLOCK | Audio bank settings |
Speed unit
| Setting | Default | Description |
|---|---|---|
Config.SpeedUnit | 'MPH' | 'MPH' or 'KMH'. Used by both radar and speed cameras |
Radar
| Setting | Default | Description |
|---|---|---|
Config.Radar.KeyToggle | 'K' | Vehicle radar on/off |
Config.Radar.KeyLockFront | 'J' | Lock the front-facing target |
Config.Radar.KeyLockRear | 'M' | Lock the rear-facing target |
Config.Radar.TickMs | 250 | Raycast interval while radar is on |
Config.Radar.OffsetFront | vec2(5.0, 50.0) | Front raycast start.x / end.y relative to vehicle |
Config.Radar.OffsetRear | vec2(-5.0, -50.0) | Rear raycast offset |
Config.Radar.HandheldWeapon | 'WEAPON_RADAR' | The handheld radar weapon name |
Config.Radar.HandheldRange | 100.0 | Max range (m) of the handheld radar |
Config.Radar.LineStartZOffset | 0.05 | Visual lift on the aim line |
Config.Radar.Overlay.* | — | NUI card placement, scaling, and anti-flicker grace. Config.Radar.Overlay.updateInterval (default 0) caps how often the floating speed readout refreshes, in ms; 0 = every frame |
CitizenEmail
Controls outbound auto-emails sent to citizens via olink.phone / oxide-phone after a speed camera catch or a field citation. The From strings use a single %s substitution that is filled with the department name (e.g. traffic@lspd.gov).
| Setting | Default | Description |
|---|---|---|
Config.CitizenEmail.Enabled | true | Master toggle for all auto-emails |
Config.CitizenEmail.Speedcam.Enabled | true | Email the driver when a speed camera issues a fine |
Config.CitizenEmail.Speedcam.From | 'traffic@%s.gov' | Sender address for speed-camera emails |
Config.CitizenEmail.Citation.Enabled | true | Email the citizen when an officer issues a field citation |
Config.CitizenEmail.Citation.From | 'citations@%s.gov' | Sender address for citation emails |
SpeedCam
| Setting | Default | Description |
|---|---|---|
Config.SpeedCam.Models | { ['prop_cctv_pole_03'] = { label = 'CCTV Pole' } } | Camera prop models offered in the placement dialog |
Config.SpeedCam.CatchCooldown | 30000 | ms a camera ignores re-triggers after a catch |
Config.SpeedCam.SoundVolume | 0.3 | Catch sound volume (0.0 - 1.0) |
Config.SpeedCam.BlipSprite / BlipColor / BlipScale | 184 / 1 / 0.85 | Map blip styling |
Config.SpeedCam.DefaultSensorRadius | 3.0 | Default detection radius (m) |
Config.SpeedCam.MaxPlacementDistance | 15.0 | Max placement reach from the admin |
Config.SpeedCam.MaxFineMultiplier | 3 | Caps the fine multiplier configurable per camera |
shared/config/bodycam.lua
| Setting | Default | Description |
|---|---|---|
Config.Bodycam.itemName | 'body_cam' | Inventory item that toggles the bodycam when used |
Config.Bodycam.maxWatchDistance | 60.0 | Distance (m) before the camera resets to the wearer's location |
Config.Bodycam.pollIntervalMs | 2500 | Interval for distance / wearer-alive checks |
Config.Bodycam.headBone | 46240 | Bone the camera attaches to |
Config.Bodycam.cameraOffset | vector3(0.0, 0.18, 0.05) | Camera offset relative to head bone |
Config.Bodycam.cameraRotation | vector3(0.0, 0.0, 0.0) | Per-frame rotation bias on top of wearer heading |
Config.Bodycam.fov | 50.0 | Bodycam field of view |
Config.Bodycam.timecycleEffect | 'Island_CCTV_ChannelFuzz' | Visual fuzz overlay |
Config.Bodycam.timecycleStrength | 0.20 | Fuzz strength |
Config.Bodycam.sameDepartmentOnly | true | Filter /police bodycams roster to the watcher's department |
Config.Bodycam.tabletAnimation | true | Hold a tablet prop while browsing the bodycam viewer |
Bodycam recording
Officers actively watching another officer's feed can capture clips that upload to Fivemanage or post to a Discord webhook. Recording happens on the watcher's machine — wearers never produce frames themselves. Native game audio cannot be captured from the browser layer; only mic and page audio are recorded.
| Setting | Default | Description |
|---|---|---|
Config.Bodycam.recording.enabled | true | Master toggle for the recorder |
Config.Bodycam.recording.provider | 'fivemanage' | 'fivemanage' or 'discord' |
Config.Bodycam.recording.maxDurationS | 45 | Max clip length in seconds |
Config.Bodycam.recording.framerate | 24 | Capture framerate |
Config.Bodycam.recording.videoBitrate | 600000 | Video bitrate in bps (600 kbps × 45 s ≈ 3.4 MB) |
Config.Bodycam.recording.audio.enabled | true | Capture audio |
Config.Bodycam.recording.audio.echoCancellation | true | Apply echo cancellation to mic input |
Config.Bodycam.recording.audio.noiseSuppression | true | Apply noise suppression to mic input |
Config.Bodycam.recording.audio.capturePageAudio | true | Best-effort page-audio capture |
Config.Bodycam.recording.hotkey | 'F6' | Toggle a manual clip while watching |
Config.Bodycam.recording.thumbnail.enabled | true | Capture a thumbnail frame for the recording row |
Config.Bodycam.recording.thumbnail.captureSeconds | 1.0 | When in the clip the thumbnail is grabbed |
Config.Bodycam.recording.thumbnail.quality | 0.7 | JPEG quality (0.0 - 1.0) |
Config.Bodycam.recording.discordWebhook | '' | Webhook URL when provider = 'discord' (leave blank to disable) |
Config.Bodycam.recording.autoRecordOnWatchStart | true | Start a recording automatically on watch start |
Config.Bodycam.recording.cooldownBetweenManualClipsS | 2 | Cooldown between manual hotkey toggles (s) |
Config.Bodycam.recording.discordMaxBytes | 26214400 | Max file size posted to Discord (25 * 1024 * 1024) |
Fivemanage uploads require the FIVEMANAGE_MEDIA_API_KEY convar (the same key used by the mugshot pipeline).
shared/config/breathalyzer.lua
The breathalyzer reads BAC from your drunk system. Edit Config.Breathalyzer.sources to plug in whichever resource your server uses; the first source that returns a numeric value wins.
| Setting | Default | Description |
|---|---|---|
Config.Breathalyzer.sources | { metadata: alcohol, metadata: drunk } | Ordered list of source descriptors |
Config.Breathalyzer.multiplier | 1.0 | Multiplied with the raw value before display |
Config.Breathalyzer.maxDisplay | 200 | Display is clamped to [0, maxDisplay] |
Config.Breathalyzer.overLimit | 80 | Threshold (post-multiplier) for the OVER LIMIT flash |
Config.Breathalyzer.cautionLimit | 50 | Threshold for the caution color |
Source descriptor types:
{ type = 'metadata', key = '<key>' }— character metadata viao-link{ type = 'export', resource = '<res>', fn = '<fn>' }— server-side export{ type = 'client_export', resource = '<res>', fn = '<fn>' }— client-side export{ type = 'client_callback' }— registersoxide:police:client:reportBacfor adapter use
shared/config/cctv.lua
| Setting | Default | Description |
|---|---|---|
Config.Cctv.defaultModel | 'p_cctv_s' | Default CCTV prop model |
Config.Cctv.placementKeyHelpPlace | [LMB] Place ... | Help text during placement |
Config.Cctv.placementKeyHelpAim | [Arrow Keys] ... | Help text during default-view aim |
Config.Cctv.raycastDistance | 25.0 | Placement raycast reach |
Config.Cctv.propZOffset | -0.10 | Z offset to correct ceiling-mount origin |
Config.Cctv.placementWheelRotateStep | 5.0 | Degrees per scroll step |
Config.Cctv.placementOutlineColor | { r = 0, g = 220, b = 255, a = 220 } | Placement preview color (red, green, blue, alpha, each 0-255) |
Config.Cctv.temporaryDurationSeconds | 86400 | Lifetime (s) for officer-placed cameras |
Config.Cctv.viewerFov | 50.0 | Viewer FOV |
Config.Cctv.viewerYawSpeed | 0.4 | Yaw rotation speed |
Config.Cctv.viewerPitchSpeed | 0.3 | Pitch rotation speed |
Config.Cctv.viewerPitchClampDeg | 89.0 | Max pitch (deg) |
Config.Cctv.viewerMaxDistance | 200.0 | Camera far-clip distance (m); geometry beyond this is not drawn in the feed |
Config.Cctv.timecycleEffect | 'Island_CCTV_ChannelFuzz' | Visual fuzz overlay |
Config.Cctv.timecycleStrength | 0.25 | Fuzz strength |
Config.Cctv.expiryTickSeconds | 600 | Server tick for expiring temporary cameras |
Config.Cctv.tabletAnimation | true | Hold a tablet prop while browsing the CCTV viewer |
shared/config/charges.lua
Config.DefaultCharges is the seed catalog imported into the police_charges_catalog table the first time the resource starts with an empty catalog. It ships with 100 entries spanning traffic infractions (1xx), traffic misdemeanors (2xx), public order (3xx-4xx), property (5xx), violent (6xx), weapons (7xx), drugs (8xx), financial (9xx), and miscellaneous (10xx).
Each entry has:
| Field | Type | Description |
|---|---|---|
code | string | Penal code reference (e.g. 1-01) |
title | string | Charge title |
category | string | 'infraction', 'misdemeanor', or 'felony' |
description | string | Long-form description shown in the MDT |
fine_amount | number | Default fine in dollars |
jail_time | number | Default jail time in months (0 for fine-only) |
After first import, charges are managed through the MDT's Catalog tab (admin only). Editing this file does not retroactively modify the database; use the MDT to update charges already in the catalog.
shared/config/compat.lua
Per-framework compatibility shim toggles.
Global
| Setting | Default | Description |
|---|---|---|
Config.Compatibility.enabled | true | Master toggle for every compatibility shim. Set to false to disable all framework shims |
Config.Compatibility.debug | false | Verbose logging for the shim modules |
Config.Compatibility['qb-core']
| Setting | Default | Description |
|---|---|---|
enabled | true | Enable QBCore back-compat shim |
copCount.enabled | true | Broadcast cop count to QB robbery scripts |
copCount.refreshIntervalMs | 60000 | Forced refresh interval |
copCount.debounceMs | 500 | Debounce for duty change events |
copCount.eventName | 'police:SetCopCount' | Event triggered with (count) |
callbacks.enabled | true | Register QB-style callbacks (police:GetCops, etc.) |
callbacks.policeForcePresentMinGrade | 2 | Min grade counted by police:server:IsPoliceForcePresent |
handcuff.exportIsHandcuffed | true | Expose exports['qb-policejob']:IsHandcuffed() |
handcuff.allowLegacyClearOnly | true | Legacy clear-cuffs event only clears, never applies |
Config.Compatibility['g-multijob']
| Setting | Default | Description |
|---|---|---|
enabled | true | Mirror oxide-police hires, fires, and promotions into the in-game g-multijob menu so officers can switch into and out of their police job. Has no effect unless g-multijob is installed and Config.AllowMultiDepartment is true (see the Global section above). Set to false to stop oxide-police from touching the g-multijob list |
Config.Compatibility['es_extended']
| Setting | Default | Description |
|---|---|---|
enabled | true | Enable ESX shim |
jobs | { police, lspd, bcso, sasp, sheriff, statetrooper } | ESX jobs treated as LEO |
jobSync.enabled | false | Mirror Oxide departments into ESX jobs table |
jobSync.syncOnStart | true | Run sync at resource start |
jobSync.syncOnChange | true | Run sync when departments change |
jobSync.setSalaryToZero | true | Force ESX salary to 0 (Oxide pays salaries) |
jobSync.jobType | 'leo' | ESX job_type value written for synced jobs |
callbacks.enabled | true | Register ESX-style callbacks |
callbacks.registerPoliceJobCallbacks | true | Register esx_policejob-style callbacks |
callbacks.registerServiceCallbacks | false | Register esx_service callbacks (off by default; Oxide manages duty) |
inventory.syncInvBusyWithCuffs | true | Sync ox_inventory busy state with cuffs |
shared/config/custody.lua
Per-station jail config (jail cells, stripping mode, holding cells, mugshot booth) lives in the database and is set through /police admin. This file holds resource-wide constants only.
| Setting | Default | Description |
|---|---|---|
Config.Custody.TickInterval | 3000 | Sentence-tick interval (ms) |
Config.Custody.ReduceOfflineTime | false | When true, sentences continue counting down while the inmate is offline. The server decrements remaining_seconds on the same cadence as the online tick and auto-releases records that hit zero |
Config.Custody.SecondsPerMonth | 60 | Conversion factor used by /police jail <id> <months>: real seconds per RP-month |
Config.Custody.Cutscene.FadeOut | 500 | Pre-jail fade-out (ms) |
Config.Custody.Cutscene.FadeIn | 500 | In-cell fade-in (ms) |
Config.Custody.Cutscene.BeforeShot | 2000 | Pause before mugshot |
Config.Custody.Cutscene.AfterShot | 2000 | Pause after mugshot |
Config.Custody.Revive.Enabled | true | Use prison revive on inmate death |
Config.Custody.Revive.Cutscene.* | — | Fade and groggy timings for revive |
Config.Custody.Uniform.Male / Female | — | Inmate uniform component drawables |
Config.Custody.Animation | mp_character_creation@customise@male_a / loop | Idle anim for stripping |
Config.Custody.Locker.StashPrefix | 'police_jail_locker_' | Stash ID prefix for stripped items |
Config.Custody.Locker.Slots | 50 | Locker slot count |
Config.Custody.Locker.MaxWeight | 500000 | Locker weight cap (g) |
Config.Custody.RemoveAfterRelease | {} | String array of items wiped on release regardless of stripping mode |
Config.Custody.ZoneRecheckMs | 1500 | Inmate zone-recheck interval |
shared/config/evidence.lua
| Setting | Default | Description |
|---|---|---|
Config.Evidence.types.blood.expire | 60 | Minutes until auto-cleanup |
Config.Evidence.types.blood.cooldown | 10 | Seconds between blood spawns per player |
Config.Evidence.types.blood.chance | 70 | % chance on taking damage |
Config.Evidence.types.bullet.expire | 60 | Minutes until auto-cleanup |
Config.Evidence.types.fingerprint.expire | 120 | Minutes until auto-cleanup |
Config.Evidence.gsr.duration | 600 | Seconds GSR persists on the suspect |
Config.Evidence.gsr.washInWater | true | Water (IsPedSwimming) wipes GSR |
Config.Evidence.fingerprints.chance | 80 | % chance to leave a print on vehicle entry without gloves |
Config.Evidence.fingerprints.expire | 120 | Vehicle fingerprint expiry (min) |
Config.Evidence.processing | — | Per-evidence-item processing duration and result label |
Config.Evidence.registrableItems | (large list) | Items submittable to the evidence registry |
Config.Evidence.registrablePatterns | { 'weapon_' } | Item-name prefixes treated as evidence |
Config.Evidence.locker.slots / weight / minGrade | 50 / 100000 / 0 | Evidence locker size and min grade (lockers are per case; the station point is the access gate) |
Config.Evidence.locker.sealOnCaseClose | false | Seal a case's evidence locker once the case is closed |
Config.Evidence.includeWeaponSerial | true | Record the firing weapon's serial on spent casings |
Config.Evidence.collectDistance | 2.0 | Max distance to collect a drop |
Config.Evidence.collectAnim | — | Animation played during collection |
Config.Evidence.renderSleep | 0 | Milliseconds the evidence draw loop waits between frames while a marker is on screen. 0 means every frame (smoothest). Raise it slightly to reduce client load at the cost of marker smoothness |
Config.Evidence.idleSleep | 1000 | Milliseconds the evidence draw loop waits when no markers are nearby. Higher saves performance when there is nothing to draw |
Config.Evidence.OfficersDropBullets | true | When false, on-duty officers leave no bullet casings (so range training / duty firefights don't litter collectable evidence). Off-duty officers and civilians always drop |
Config.Hooks.EvidenceIsDropExempt | function | Return true to suppress every world-evidence drop the local player would create (bullet casings, blood, vehicle fingerprints). See example below |
Config.Hooks.EvidenceCheckPlayerGloves | function | Returns true if the player has gloves equipped |
Config.EvidenceWeapons | (table) | File-authoritative weapon name + ammo type catalog used by ballistics reports |
Tracing a casing back to a gun
With includeWeaponSerial on, a spent casing records the serial of the weapon that fired it. When an officer collects the casing, the evidence locker shows the serial and the name it is registered to, and the same serial can be looked up in the MDT's Weapons tab.
The serial is worked out on the server from the weapons the shooter is actually carrying, so a modified game client cannot invent a serial or hide its own. Two situations deliberately record no serial rather than guess:
- the shooter is carrying two of the same model with different serials, or one of them has no serial at all — there is no single right answer;
- the weapon isn't an inventory item, which is how some frameworks handle weapons.
Turn includeWeaponSerial off if your server doesn't use weapon registration. Casings collected before you turned it on simply show no serial; nothing breaks.
Sealing evidence lockers when a case closes
Every case gets its own evidence locker, and by default those lockers stay open forever — including for cases closed years ago. Turning on locker.sealOnCaseClose means that closing a case seals its locker: officers can still see everything inside from the evidence screen, but the locker itself will not open, so nothing can be added, removed or swapped after the fact.
Reopening the case unseals the locker again, and the contents are untouched throughout.
This is off by default, so updating changes nothing. Turn it on deliberately — officers used to closing a case and then reaching back into the locker will notice.
To reclaim the space, an admin can permanently empty a sealed locker with /police purgeevidence (see the admin guide). That destroys the contents and cannot be undone, which is why it is admin-only and why the locker has to be sealed first.
Excluding players from evidence drops (EvidenceIsDropExempt)
Config.Hooks.EvidenceIsDropExempt runs client-side before any drop is sent. Return true and the local player leaves no bullet casings, blood, or vehicle fingerprints. Use it to exempt minigames or other special states with your own resource's exports:
Config.Hooks.EvidenceIsDropExempt = function()
if exports['pug-paintball']:IsInPaintball() then return true end
return false
endThe function is wrapped in a pcall, so an error inside it won't break evidence generation — it just falls back to "not exempt".
shared/config/field_actions.lua
Tickets
| Setting | Default | Description |
|---|---|---|
Config.FieldActions.Tickets.enabled | true | Allow field citations |
Config.FieldActions.Tickets.requireDuty | true | Officer must be on duty |
Config.FieldActions.Tickets.maxFine | 10000 | Max fine per ticket |
Config.FieldActions.Tickets.allowManualFine | true | Allow officer to override the catalog amount |
Config.FieldActions.Tickets.useChargeCatalog | true | Source charges from the MDT catalog |
Config.FieldActions.Tickets.defaultNotes | 'Field citation' | Default note text |
Carry
| Setting | Default | Description |
|---|---|---|
Config.FieldActions.Carry.enabled | true | Allow fireman's carry |
Config.FieldActions.Carry.requireTargetRestrained | false | Target must be cuffed / zip-tied |
Config.FieldActions.Carry.stopKey | 'E' | Key to stop carrying |
Config.FieldActions.Carry.maxDistance | 2.0 | Engage reach (m) |
Config.FieldActions.Carry.animations.* | — | Carrier and carried anims, attach offsets |
Headbag
| Setting | Default | Description |
|---|---|---|
Config.FieldActions.Headbag.enabled | true | Allow headbag usage |
Config.FieldActions.Headbag.requireItem | false | Require headbag item |
Config.FieldActions.Headbag.requireTargetRestrainedOrHandsUp | true | Target must be restrained or have hands up |
Config.FieldActions.Headbag.itemName | 'headbag' | Item to consume / require |
Config.FieldActions.Headbag.model | 'prop_money_bag_01' | Prop model |
Config.FieldActions.Headbag.bone / offset / rotation | — | Attach config |
Config.FieldActions.Headbag.blackoutOpacity | 0.98 | Target overlay opacity |
Cuffs
| Setting | Default | Description |
|---|---|---|
Config.FieldActions.Cuffs.hardCuffEnabled | true | Allow officer-side hard-cuff |
Config.FieldActions.Cuffs.lockpickEnabled | true | Allow lockpicking out of cuffs |
Config.FieldActions.Cuffs.lockpickItem | 'lockpick' | Item required to lockpick |
Config.FieldActions.Cuffs.lockpickConsumesOnSuccess | false | Consume on success |
Config.FieldActions.Cuffs.lockpickConsumesOnFailure | false | Consume on failure |
Config.FieldActions.Cuffs.hardCuffDisableSprint | true | Force-disable sprint while hard-cuffed |
Config.FieldActions.Cuffs.lockpickSkillCheck | { 30 / 1.5 x3 } | lib.skillCheck rounds |
Ziptie
| Setting | Default | Description |
|---|---|---|
Config.FieldActions.Ziptie.enabled | true | Allow zip-tie usage |
Config.FieldActions.Ziptie.requireDuty | false | Whether zip-ties are officer-only (off by default so civilians can use them) |
Config.FieldActions.Ziptie.requireTargetAlive | true | Target must be alive |
Config.FieldActions.Ziptie.itemName | 'ziptie' | Item to consume |
Config.FieldActions.Ziptie.consumeOnApply | true | Consume the zip-tie on apply |
Config.FieldActions.Ziptie.applyDuration | 3500 | Apply duration (ms) |
Config.FieldActions.Ziptie.maxDistance | 2.5 | Engage reach (m) |
Config.FieldActions.Ziptie.autoReleaseSeconds | 300 | Auto-release after (s); 0 disables |
Config.FieldActions.Ziptie.cutItems | { 'scissors' } | Items that can cut a zip-tie |
Config.FieldActions.Ziptie.cutIcon | 'fas fa-scissors' | FontAwesome icon shown on the "cut zip-tie" target option |
Config.FieldActions.Ziptie.cutDuration | 4000 | Cut duration (ms) |
Config.FieldActions.Ziptie.consumeCutItemOnSuccess | false | Consume the cutting item after a successful cut |
StationServices
| Setting | Default | Description |
|---|---|---|
Config.FieldActions.StationServices.bellsEnabled | true | Enable station bells |
Config.FieldActions.StationServices.trashEnabled | true | Enable trash bins |
Config.FieldActions.StationServices.trashClearable | true | Allow officers to clear the bin |
Config.FieldActions.StationServices.bellCooldownMs | 30000 | Cooldown between bell rings |
Config.FieldActions.StationServices.trashSlots | 30 | Slots per bin |
Config.FieldActions.StationServices.trashWeight | 50000 | Bin weight cap (g) |
Config.FieldActions.StationServices.trashClearMinGrade | 0 | Min grade to clear bins |
Config.FieldActions.StationServices.trashAutoClearMs | 3600000 | Auto-clear interval; 0 disables |
Config.FieldActions.StationServices.firearmRegistrationEnabled | true | Enable the civilian firearm registration desk |
Config.FieldActions.StationServices.firearmRegistrationFee | 250 | Fee charged per firearm, taken from the registrant's bank and deposited into the station's department treasury |
shared/config/field_tools.lua
WheelClamp
| Setting | Default | Description |
|---|---|---|
Config.FieldTools.WheelClamp.enabled | true | Enable wheel clamps |
Config.FieldTools.WheelClamp.requireDuty | true | Officer must be on duty |
Config.FieldTools.WheelClamp.requireItem | true | Require wheel_clamp item |
Config.FieldTools.WheelClamp.itemName | 'wheel_clamp' | Item name |
Config.FieldTools.WheelClamp.model | 'tire_clamp' | Streamed prop |
Config.FieldTools.WheelClamp.installDuration | 5000 | Install duration (ms) |
Config.FieldTools.WheelClamp.removeDuration | 4000 | Removal duration (ms) |
Config.FieldTools.WheelClamp.maxDistance | 3.0 | Engage reach (m) |
Config.FieldTools.WheelClamp.wheelBone | 'wheel_lf' | Bone the clamp attaches to |
Config.FieldTools.WheelClamp.externalJobs | {} | Non-police jobs allowed to work on clamps |
Config.FieldTools.WheelClamp.externalCommand | 'removeclamp' | Chat command for those jobs; false registers none |
Letting tow drivers remove clamps. By default only police touch wheel clamps, so a clamped car stays clamped until an officer is free. externalJobs lets you name other jobs that may help, keyed by the job name your framework uses:
externalJobs = {
['tow'] = { allowApply = false, requireOnDuty = false },
['mechanic'] = { allowApply = false, requireOnDuty = true },
},| Key | Default | Meaning |
|---|---|---|
allowApply | false | Also allows fitting clamps, not just removing them |
requireOnDuty | false | The player must be clocked on in that job |
These jobs remove clamps through their targeting menu (aim at the clamped vehicle) or the externalCommand chat command, which is there for servers running no targeting script.
Removal by one of these jobs never hands back a wheel_clamp item — that is police equipment, and refunding it would give every tow driver a way to stock up. Officers still get theirs back as normal. And leaving externalJobs empty keeps the old police-only behaviour exactly, so upgrading changes nothing until you fill it in.
MouthTape
| Setting | Default | Description |
|---|---|---|
Config.FieldTools.MouthTape.enabled | true | Enable mouth tape |
Config.FieldTools.MouthTape.requireDuty | true | Officer must be on duty |
Config.FieldTools.MouthTape.requireItem | true | Require the item in inventory |
Config.FieldTools.MouthTape.itemName | 'mouthtape' | Item name |
Config.FieldTools.MouthTape.model | 'e_ducktape' | Streamed tape prop |
Config.FieldTools.MouthTape.requireTargetRestrainedOrHandsUp | true | Target must be restrained or have hands up |
Config.FieldTools.MouthTape.applyDuration | 2500 | Apply duration (ms) |
Config.FieldTools.MouthTape.removeDuration | 2000 | Removal duration (ms) |
Config.FieldTools.MouthTape.bone / attach | — | Prop attach point |
Config.FieldTools.MouthTape.voice.pmaVoice | true | Disable pma-voice on tape |
Config.FieldTools.MouthTape.voice.yacaVoice | true | Disable yaca-voice on tape |
TrackingBand
| Setting | Default | Description |
|---|---|---|
Config.FieldTools.TrackingBand.enabled | true | Enable tracking bands |
Config.FieldTools.TrackingBand.requireDuty | true | Officer must be on duty |
Config.FieldTools.TrackingBand.requireItem | true | Require the item in inventory |
Config.FieldTools.TrackingBand.itemName | 'tracking_band' | Item name |
Config.FieldTools.TrackingBand.model | 'gps_tracker' | Streamed band prop |
Config.FieldTools.TrackingBand.requireTargetRestrainedOrHandsUp | true | Target must be restrained or have hands up |
Config.FieldTools.TrackingBand.applyDuration | 4000 | Apply duration (ms) |
Config.FieldTools.TrackingBand.removeDuration | 3500 | Removal duration (ms) |
Config.FieldTools.TrackingBand.updateCoordsMs | 1000 | GPS update interval (ms) |
Config.FieldTools.TrackingBand.blipRefreshMs | 1100 | Blip refresh interval (ms) |
Config.FieldTools.TrackingBand.bone / attach | — | Prop attach point |
Config.FieldTools.TrackingBand.blip.* | — | Blip sprite, color, scale, pulse, heading, name prefix |
Impound
| Setting | Default | Description |
|---|---|---|
Config.FieldTools.Impound.enabled | true | Enable vehicle impound |
Config.FieldTools.Impound.requireDuty | true | Officer must be on duty |
Config.FieldTools.Impound.registeredVehiclesOnly | true | Only impound owned vehicles |
Config.FieldTools.Impound.defaultFee | 500 | Default impound fee |
Config.FieldTools.Impound.defaultLot | 'main' | Default impound lot |
Config.FieldTools.Impound.maxFee | 50000 | Max impound fee |
Config.FieldTools.Impound.duration | 6000 | Impound action duration (ms) |
Config.FieldTools.Impound.saveVehicleProps | true | Save vehicle properties on impound |
Want impounded cars sent to your own impound/garage system? See Custom Impound.
shared/config/fleet_catalog.lua
| Setting | Default | Description |
|---|---|---|
Config.FleetAddons.radar | 5000 | Per-unit surcharge for the radar addon (rolled into replacement_cost) |
Config.FleetAddons.megaphone | 2500 | Per-unit surcharge for the megaphone addon |
Config.FleetCatalog | (table) | Vehicle catalog grouped by category. Each entry: model, label, cost |
Shipped categories: Patrol, Pursuit, Tactical, Motorcycle. cost is both purchase price and replacement cost when added to a department.
shared/config/interactions.lua
Cuffing
| Setting | Default | Description |
|---|---|---|
Config.Cuffing.Animation | 'advanced' | 'basic' (front only) or 'advanced' (front/back detection) |
Config.Cuffing.Models.cuffs | — | Cuff prop model + per-mode coords / rotation |
Config.Cuffing.Models.ziptie | — | Ziptie prop model + per-mode coords / rotation |
Config.Cuffing.Anims.rear / front / dead | — | Officer / target / attach anims per mode |
Config.Cuffing.UncuffAnims | — | Uncuff anim and durations |
Config.Cuffing.Idle.rear / front | — | Idle anim while cuffed |
Config.Cuffing.BreakMinigame | true | Allow target to attempt to break free |
Config.Cuffing.SkillCheck | { easy, easy, medium } | lib.skillCheck rounds for break attempt |
Config.Cuffing.EscapeCooldown | 30000 | Cooldown between break attempts (ms) |
Config.Cuffing.Bone | 60309 | Cuff attach bone |
Escort
| Setting | Default | Description |
|---|---|---|
Config.Escort.Bone | 11816 | Officer-target attach bone |
Config.Escort.Offset | vector2(0.25, 0.25) | Escort offset |
Config.Escort.RecheckMs | 500 | Position recheck interval |
Config.Escort.OfficerAnim / TargetAnim.* | — | Walk / idle animations |
Search
| Setting | Default | Description |
|---|---|---|
Config.Search.Officer | anim@gangops@facility@servers@bodysearch@ | Officer anim |
Config.Search.Duration | 5500 | Search duration (ms) |
Vehicle
| Setting | Default | Description |
|---|---|---|
Config.Vehicle.SearchRadius | 5.0 | Vehicle action search radius (m) |
Tackle
| Setting | Default | Description |
|---|---|---|
Config.Tackle.Enable | true | Enable tackle |
Config.Tackle.Key | 'G' | Default keybind |
Config.Tackle.Command | '+policetackle' | Command name (used by RegisterKeyMapping) |
Config.Tackle.Distance | 3.0 | Tackle reach (m) |
Config.Tackle.Cooldown | 10000 | Tackle cooldown (ms) |
Config.Tackle.Type | 'animation' | 'animation' or 'ragdoll' |
Config.Tackle.RagdollAfter | 4000 | Ragdoll the victim after (ms) |
HandsUp
| Setting | Default | Description |
|---|---|---|
Config.HandsUp.Command | 'handsup' | Command name |
Config.HandsUp.Key | 'X' | Default keybind |
Config.HandsUp.Cooldown | 2000 | Cooldown between toggles (ms) |
Config.HandsUp.CheckInterval | 250 | Hands-up state check interval (ms) |
Config.HandsUp.Anim | missminuteman_1ig_2 / handsup_base | Standing hands-up animation |
Config.HandsUp.KneelEnabled | true | Allow the kneeling pose |
Config.HandsUp.HoldThreshold | 400 | How long the key must be held to kneel (ms) |
Config.HandsUp.KneelSticky | true | Kneel stays after the key is released |
Config.HandsUp.KneelAnim | rcmminute2 / kneeling_arrest_idle | Kneeling animation |
Config.HandsUp.KneelExitAnim | rcmminute2 / kneeling_arrest_get_up | Stand-up animation |
Tap vs hold. Tapping the key puts the player's hands up standing, exactly as before. Holding it past HoldThreshold drops them to a knee instead. Either pose counts as "hands up", so officers can still search, cuff and use field tools on a kneeling suspect.
With KneelSticky on (the default), the kneel stays put once you let go of the key and clears on the next tap — nobody wants to hold a key down for a whole traffic stop. Set it to false if you would rather releasing the key stand the player back up.
If you swap the animation, keep the flag at 1. The standing pose uses flag 50, which only moves the upper body — reuse it on the kneel and the player stays standing and just waves their arms.
Upgrading: the keybind is now registered as +handsup so the resource can tell a tap from a hold. Anyone who rebound hands-up to a different key keeps a working hands-up, but will need to rebind to get hold-to-kneel. /handsup in chat still works and always uses the standing pose.
OfficerTargetMenu
Powers the on-duty officer's contextual ox_target options on other players plus the /cuff and /uncuff chat commands. Each action is toggled with its own enable flag and shows a FontAwesome icon. The cuff, search, and escort options are on by default; every other action is off by default. Options only appear when they make sense (for example, take-out-of-vehicle shows only for a cuffed suspect who is seated in a vehicle). Because aiming at a seated suspect actually hits the vehicle's body or glass, "Take Out of Vehicle" also appears when you third-eye the vehicle itself while it has a restrained occupant — no need to catch the ped through a window.
| Setting | Default | Description |
|---|---|---|
Config.OfficerTargetMenu.Enable | true | Register the player target options and chat commands |
Config.OfficerTargetMenu.Distance | 2.5 | ox_target reach and command fallback radius (m) when no serverID is passed |
Config.OfficerTargetMenu.RequireDuty | true | Default duty requirement for actions without their own requireDuty |
Config.OfficerTargetMenu.CuffCommand | 'cuff' | Chat command name for cuffing |
Config.OfficerTargetMenu.UncuffCommand | 'uncuff' | Chat command name for uncuffing |
Config.OfficerTargetMenu.Actions.cuff.enable / icon | true / fas fa-handcuffs | Cuff and uncuff options |
Config.OfficerTargetMenu.Actions.search.enable / icon | true / fas fa-magnifying-glass | Search option (cuffed suspects) |
Config.OfficerTargetMenu.Actions.escort.enable / icon / requireDuty | true / fas fa-person-walking / true | Escort / stop-escort options (cuffed suspects); requireDuty = false allows civilians |
Config.OfficerTargetMenu.Actions.hard_cuff.enable / icon | false / fas fa-lock | Hard cuff option (also requires Config.FieldActions.Cuffs.hardCuffEnabled) |
Config.OfficerTargetMenu.Actions.carry.enable / icon / requireDuty | false / fas fa-user-plus / true | Carry / stop-carry options (also requires Config.FieldActions.Carry.enabled); requireDuty = false allows civilians |
Config.OfficerTargetMenu.Actions.headbag.enable / icon / requireDuty | false / fas fa-user-secret / true | Put / remove headbag options (also requires Config.FieldActions.Headbag.enabled); requireDuty = false allows civilians |
Config.OfficerTargetMenu.Actions.vehicle.enable / icon / requireDuty | false / fas fa-car-side / true | Put in / take out of vehicle options (cuffed suspects); take-out also shows on the vehicle itself when it holds a restrained occupant; requireDuty = false allows civilians |
Config.OfficerTargetMenu.Actions.gsr.enable / icon | false / fas fa-hand-dots | Gunshot residue (GSR) check option |
Config.OfficerTargetMenu.Actions.ticket.enable / icon | false / fas fa-receipt | Issue ticket option (also requires Config.FieldActions.Tickets.enabled) |
Allowing non-police use. Escort, carry, headbag, and vehicle each carry a per-action requireDuty flag (default true). Set it to false to let any player use that action — civilians restrain targets with zip-ties (see Config.FieldActions.Ziptie), which satisfy the "must be restrained" requirement for escort and vehicle (carry never requires restraint; headbag accepts restrained-or-hands-up). Police handcuffs always stay on-duty-only. To fully enable a civilian action that is off by default (e.g. carry), set both Actions.carry.enable = true and Actions.carry.requireDuty = false (and keep Config.FieldActions.Carry.enabled = true). Actions without a requireDuty key fall back to RequireDuty.
Sounds
| Setting | Default | Description |
|---|---|---|
Config.Sounds.Enabled | true | Enable interaction sounds |
Config.Sounds.Cuff / Uncuff / Search / Tackle | — | Sound name + audio bank |
CuffedDisabledControls
| Setting | Default | Description |
|---|---|---|
Config.CuffedDisabledControls | (list of control IDs) | Controls disabled while cuffed (attack, aim, sprint, jump, vehicle entry, etc.) |
shared/config/licenses.lua
License types offered in the MDT person profile's Licenses tab. IDs are passed straight to olink.license.*, so each id must also exist in the framework's licenses table (e.g. on ESX, as a row in the licenses table) for native UIs to label it.
| Setting | Default | Description |
|---|---|---|
Config.Licenses.Types | { driver, weapon, business, pilot, boat } | List of license definitions; each entry has id (framework key) and label (display name) |
Default shipped licenses: Driver's License, Weapons Permit, Business License, Pilot's License, Boating License. Add new entries or remove existing ones to match the licenses your server uses.
shared/config/mdt.lua
| Setting | Default | Description |
|---|---|---|
Config.MDT.fineRevenueSplit | 50 | % of fine revenue routed to the department treasury (the rest is the state's share and leaves the economy) |
Config.MDT.caseNumberPrefix | true | Prefix MDT case numbers with the department code |
Config.MDT.dispatchEnabled | true | Enable the Dispatch tab. Requires oxide-dispatch. Set false for ps-dispatch / cd_dispatch / qs-dispatch / wasabi_mdt / etc. |
Config.MDT.tabletAnimation | true | Play a tablet-holding animation and attach a tablet prop to the officer's hand while the MDT panel is open |
Config.MDT.allowOffDuty | false | Allow officers to open and use the MDT while off duty. When false, the MDT requires clocking in first. The Config.MDT.permissions.accessMdt minimum grade is enforced either way |
Config.MDT.useItem | false | When true, the MDT can only be opened by using the Config.MDT.itemName inventory item and /police mdt refuses access. When false, the MDT opens with /police mdt and no item is required. The duty / allowOffDuty and accessMdt checks apply either way |
Config.MDT.itemName | 'police_tablet' | Inventory item that opens the MDT when useItem is true. The item must be registered in your inventory — see Installation → Register items |
Config.MDT.hidden.charIds | {} | List of char_id strings hidden from MDT person search, profile, and vehicle-owner lookups |
Config.MDT.hidden.bypassMinGrade | -1 | Officers at this grade rank or higher still see hidden characters. Set to -1 to disable bypass entirely |
Config.MDT.warrants.defaultExpiryHours | 72 | Default warrant expiry |
Config.MDT.warrants.maxActivePerPerson | 3 | Max simultaneous active warrants per person |
Config.MDT.bolos.defaultExpiryHours | 48 | Default BOLO expiry |
Config.MDT.bolos.maxActive | 50 | Max simultaneous active BOLOs |
Config.MDT.bolos.notifyOnCreate | true | Notify all officers when a BOLO is created |
Config.MDT.dashboard.recentActivityCount | 20 | Rows shown on the dashboard |
Config.MDT.search.maxResults | 20 | Max search results |
Config.MDT.search.minQueryLength | 2 | Min characters before search runs |
Config.MDT.permissions.accessMdt | 0 | Min grade to open the MDT |
Config.MDT.permissions.createCase | 0 | Min grade to create a case |
Config.MDT.permissions.closeCase | 2 | Min grade to close a case |
Config.MDT.permissions.issueWarrant | 2 | Min grade to issue a warrant |
Config.MDT.permissions.recallWarrant | 3 | Min grade to recall a warrant |
Config.MDT.permissions.issueFine | 0 | Min grade to issue a fine |
Config.MDT.permissions.processArrest | 0 | Min grade to process an arrest |
Config.MDT.permissions.manageLicenses | 1 | Min grade to grant or revoke licenses via the MDT person profile |
Config.MDT.permissions.overrideJail | 0 | Min grade to adjust jail time before booking. 0 lets any officer who can process an arrest adjust it |
Config.MDT.allowJailOverride | true | Let officers adjust the total jail time before finalising an arrest — for time served, a plea agreement, or an interruption during booking. Set false to remove the field entirely |
Config.MDT.limits.maxCountPerCharge | 10 | Max occurrences of a charge per call |
Config.MDT.limits.maxFinePerCall | 250000 | Max fine per call |
Config.MDT.limits.maxTextLength | 500 | Max chars in warrant / BOLO reason fields |
Config.MDT.limits.maxPlateLength | 16 | Max plate length |
Config.MDT.limits.maxJailPerCall | 2000 | Ceiling on an adjusted sentence, in the same units as the catalog's jail_time. Stops a mistyped sentence |
Config.MDT.limits.maxImportRows | 500 | Max rows accepted in one charge-catalog CSV import |
The MDT's charge-catalog editor (the Catalog tab) is not grade-based — it is only available to server admins (the admin permission, the same one that gates /police admin — see Admin → Permissions).
Adjusting jail time before booking
When allowJailOverride is on, the jail total in the Charges tab and the station booking panel becomes an editable field instead of a fixed label. The officer can raise or lower it — for time served, a plea deal, or a booking that got interrupted — up to limits.maxJailPerCall. Setting it to 0 books the arrest and its fine with no jail time at all.
Two things to know:
- The charge records never change. Each charge keeps the jail time from the catalog; only the sentence actually served is adjusted. Every adjustment is written to the department activity log and the server log with the original total, the new total, and the officer who made the change.
- The rule is enforced on the server. Hiding the field with
allowJailOverride = false, or restricting it withpermissions.overrideJail, cannot be bypassed by a modified client.
Turning individual MDT tabs off
Config.MDT.modules has one true/false per tab. Leaving it alone changes nothing — every tab defaults to on.
| Key | Tab |
|---|---|
dashboard | Dashboard |
dispatch | Dispatch |
personSearch | Persons |
vehicleSearch | Vehicles |
weaponSearch | Weapons |
reports | Reports / cases |
charges | Charges (arrest processing) |
fines | Fines |
warrants | Warrants |
bolos | BOLOs |
videos | Video storage |
catalog | Charge catalog editor (admin only) |
A disabled tab disappears from the navigation for every officer and its server actions are refused, so it cannot be reached by a modified client. If you disable the tab an officer is currently on, the MDT opens on the first tab that is still enabled.
Turning off charges only removes the MDT's arrest tab — booking a suspect at a station still works.
dispatchEnabled above still works and is treated as modules.dispatch when you haven't set that key, so existing configs need no changes.
shared/config/megaphone.lua
| Setting | Default | Description |
|---|---|---|
Config.Megaphone.handheldRange | 30.0 | Hard-cutoff radius (m) for handheld megaphone |
Config.Megaphone.vehicleRange | 50.0 | Hard-cutoff radius (m) for vehicle PA |
Config.Megaphone.animDict / animClip | — | Megaphone animation |
Config.Megaphone.propModel | 'prop_megaphone_01' | Megaphone prop |
Config.Megaphone.propBone / propOffset / propRotation | — | Prop attach |
Config.Megaphone.pmaVoice | true | Hook pma-voice channels |
Config.Megaphone.yacaVoice | true | Hook yaca-voice channels |
Config.Megaphone.vehicleKey | 'B' | Default vehicle PA toggle key |
Config.Megaphone.vehicleKeyDescription | 'Police: Toggle vehicle PA' | Keybind label |
Config.Megaphone.driverOnly | true | Restrict vehicle PA to the driver |
shared/config/mugshot.lua
Requires the convar:
set FIVEMANAGE_MEDIA_API_KEY "your_key_here"| Setting | Default | Description |
|---|---|---|
Config.Mugshot.PresignedUrlEndpoint | https://api.fivemanage.com/api/v3/file/presigned-url | Upload endpoint |
Config.Mugshot.PhotoCheckRadius | 1.5 | Client-side range check for the mugshot mark (m) |
Config.Mugshot.ServerGraceDistance | 3.0 | Server-side grace range (m) |
Config.Mugshot.Webhook | '' | Optional Discord webhook for capture posts (leave blank to disable) |
Config.Mugshot.Branding.username / iconUrl / title / color | — | Webhook branding |
Config.Hooks.MugshotBuildEmbed(data) | function | Returns the Discord embed payload |
Config.Hooks.MugshotSendPhoto(data) | function | Override to route captures elsewhere (Loki / S3 / etc.) |
Setting up FiveManage media uploads
Three features in this resource save pictures and video to the cloud so officers can view them later:
- Mugshots — booking photos taken during arrests
- Bodycam clips — short video recordings captured while watching an officer's feed
- Bait car dashcam clips — video from the
oxide-baitcarresource (these upload through this resource's pipeline)
All three use a service called FiveManage to store the files. You only need one FiveManage key, and that single key powers all three features. The key is not set in any config file — it lives in your server.cfg (the text file that tells your server which resources to start and holds your server's settings).
Follow these steps once:
Create a free account. Go to https://app.fivemanage.com and sign up. The free tier is enough to get started and does not ask for a credit card.
Create a team. After signing in, create a team — pick any name and team type you like.
Open the Tokens page. In the dashboard menu, go to Tokens (Dashboard → Tokens).
Create a token. Click Create token, choose the Media scope (this one scope covers both images and videos — so it works for mugshots, bodycam, and bait car clips), and give the token a name you'll recognize.
Copy the token. FiveManage shows you the token once. Copy it now.
Paste it into server.cfg. Open your server.cfg and add this line, replacing the example with the token you copied:
set FIVEMANAGE_MEDIA_API_KEY "the_token_you_copied"Restart your server (or refresh the convar) so the new setting takes effect.
What "working" looks like: after this is set, taking a mugshot during an arrest, recording a bodycam clip, or triggering a bait car dashcam clip will upload successfully and the media will appear in the relevant record. If uploads fail, double-check that the line above is in server.cfg, that the token was copied in full, and that you restarted the server.
shared/config/objects.lua
| Setting | Default | Description |
|---|---|---|
Config.PlaceableObjects.maxPerOfficer | 15 | Max placed props per officer |
Config.PlaceableObjects.placementMaxDepth | 10.0 | Max raycast depth |
Config.PlaceableObjects.props | (list) | Each entry: id, label, model, icon, optional spikeStrip |
Shipped props: do-not-cross barrier, A-frame barrier (with and without lights), road-work-ahead barrier, traffic barrier (with and without lights), traffic cone, taller traffic cone, traffic road pole, unmarked traffic cone, spike strip.
shared/config/prisonerjobs.lua
| Setting | Default | Description |
|---|---|---|
Config.PrisonerJobs.Enabled | true | Enable prisoner jobs |
Config.PrisonerJobs.SwingCooldownMs | 1500 | Server-side cooldown between swings |
Mining
| Setting | Default | Description |
|---|---|---|
Mining.SecondsPerSwing | 10 | Seconds taken off the remaining sentence per successful swing |
Mining.SwingsToBreak | 8 | Swings to break a rock |
Mining.CooldownMs | 30000 | Cooldown after a rock is broken |
Mining.SwingDistance | 2.0 | Engage reach (m) |
Mining.WalkAwayDistance | 6.0 | Distance that silently resets the session |
Mining.Money.account / amount | cash / 0 | Money reward per break |
Mining.ItemDrops | {} | Item drop table: { item, chance, min, max } |
Mining.RockModels | (list) | Models eligible as rocks |
Mining.Pickaxe.* | — | Prop attach: model, bone, offset, rotation |
Mining.Anim.* | — | Pickaxe swing anim |
Cleaning
| Setting | Default | Description |
|---|---|---|
Cleaning.SecondsPerPickup | 8 | Seconds taken off the remaining sentence per pickup |
Cleaning.PickupDurationMs | 3000 | Pickup duration (ms) |
Cleaning.InteractDistance | 1.8 | Engage reach (m) |
Cleaning.MaxDistance | 3.0 | Latency-tolerant max reach (m) |
Cleaning.ActiveCount | 5 | Concurrent active trash points |
Cleaning.PointCooldownMs | 90000 | Cooldown per cleaned point |
Cleaning.Money.* / ItemDrops | — | Reward configuration |
Cleaning.TrashModels | (list) | Models eligible as trash |
Electrical
| Setting | Default | Description |
|---|---|---|
Electrical.SecondsOnSuccess | 60 | Seconds taken off the remaining sentence on success |
Electrical.FailCooldownMs | 30000 | Cooldown on failure |
Electrical.SuccessCooldownMs | 15000 | Cooldown on success (anti-camping) |
Electrical.InteractDistance | 2.0 | Engage reach (m) |
Electrical.MaxDistance | 3.0 | Latency-tolerant max reach (m) |
Electrical.Anim.scenario | WORLD_HUMAN_WELDING | Welding scenario |
Electrical.SkillCheck | { easy, easy, medium } | Difficulty of the repair skill-check rounds |
Electrical.Money.* / ItemDrops | — | Reward configuration |
shared/config/prisonshop.lua
The shop location, meal windows, and paid catalog are admin-configured through /police admin → Detention → Prison Shop. Until a location is placed, the shop is dormant.
| Setting | Default | Description |
|---|---|---|
Config.PrisonShop.enabled | true | Enable prison shop |
Config.PrisonShop.model | 's_m_y_prismuscl_01' | Vendor ped model |
Config.PrisonShop.scenario | 'WORLD_HUMAN_CLIPBOARD' | Vendor scenario |
Config.PrisonShop.interactDistance | 2.5 | Engage reach (m) |
Config.PrisonShop.targetRadius | 1.5 | ox_target sphere radius |
Config.PrisonShop.blip.* | — | Map blip styling |
Config.PrisonShop.freeItem | 'prison_food_tray' | Item handed out free during meal windows |
Config.PrisonShop.freeMealRestore.hunger | 50 | Hunger restored when the free meal tray is consumed |
Config.PrisonShop.freeMealRestore.thirst | 15 | Thirst restored when the free meal tray is consumed |
Config.PrisonShop.categories | { food, drink, misc } | Menu category headers |