Building a Department
End-to-end guide to creating and operating an Oxide Police department.
End-to-end walkthrough for standing up a police department on a fresh server. Part 1 takes you from "resource not installed" to "officer clocked in and using the MDT." Part 2 covers every optional subsystem in depth. Part 3 is a one-page cheat sheet.
For per-key configuration reference, see Configuration. For the full admin / player command reference, see Admin. For framework-specific item and weapon registration, see the per-framework guides linked at the bottom of Installation.
Part 1 — Quickstart: Minimum Viable Department
The goal of Part 1 is the smallest set of steps that produces a working department. At the end you will have one department, one station, one garage with one vehicle, one armory loadout, one hired officer who can clock in, and a working MDT. Everything else (radio, doors, custody, bodycam, CCTV, evidence, prison, speed cameras, multi-department) is optional and deferred to Part 2.
1.1 Prerequisites
| Resource | Required? | Purpose |
|---|---|---|
ox_lib | Required | Locales, callbacks, keybinds, UI helpers |
oxmysql | Required | Database persistence |
o-link | Required | Framework abstraction (character, job, money, inventory, notify, target) |
screenshot-basic | Required | Mugshot and bodycam capture |
oxide-banking | Recommended | Department treasury, fine invoicing |
oxide-dispatch | Recommended | Powers the MDT Dispatch tab |
pma-voice or yaca-voice | Optional | Police radio channels, megaphone voice routing |
Conflicts to disable: qb-policejob, esx_policejob, qb-prison. oxide-police declares provide 'qb-policejob' so legacy resources that import exports['qb-policejob']:IsHandcuffed() keep working after the legacy resource is removed.
1.2 Install the resource
-
Place
oxide-policeinside yourresourcesfolder. -
Run
sql/install.sqlagainst your database.- If you are upgrading an existing install, run files from
sql/migrations/in numeric order (001through005). Fresh installs only needinstall.sql.
- If you are upgrading an existing install, run files from
-
Add the startup block to
server.cfg. Dependencies must start beforeoxide-police:ensure ox_lib ensure oxmysql ensure screenshot-basic ensure o-link ensure oxide-banking ensure oxide-dispatch ensure oxide-police -
Make sure your account is a server admin. The admin panel and admin commands are available to anyone in a group with the standard
adminpermission. If your admins can already use other Oxide admin tools (or txAdmin), they can use these too. If you have not set up an admin group yet, add these two lines to yourserver.cfg(replace the licence with your own) and restart:add_principal identifier.license:abc123 group.admin add_ace group.admin admin allow
1.3 Register items in your inventory system
oxide-police does not register items itself — registration is handled by the inventory resource behind your o-link.inventory adapter. The full item list (with images and per-item purpose) lives in Installation → Register items. For copy-paste registration syntax, follow the framework guide that matches your stack:
Each guide also covers registering WEAPON_RADAR (the streamed handheld speed radar weapon) and copying item images from ../items/ into your inventory image directory.
You can skip handheld-radar registration during initial setup if you only want the vehicle-mounted radar — the handheld is an enhancement, not a dependency.
1.4 First in-game setup with /padmin
Restart the server, join with an admin account (one in a group with the admin permission — see step 4 above), and run /padmin. The Overview screen displays a 7-item Setup Checklist. Complete the items in order — the order matches the dependency chain (you can't add a vehicle before you have a garage).
The checklist labels are exactly what the UI shows:
| # | Checklist label | Where | What to do |
|---|---|---|---|
| 1 | Define ranks | Departments → Grades | Add one grade row per framework rank (e.g. 0 cadet, 1 officer, 2 sergeant). Set salary per grade. Mark the highest grade is_boss |
| 2 | Create at least one station | Stations → Create | Set label and type (main or substation). Click "Create at position" to use your current location |
| 3 | Set clock-in point on a station | Stations → [station] → Interaction → Clock-in | Place it at the front desk or muster point (the panel uses your aim to position it) |
| 4 | Set armory point on a station | Stations → [station] → Interaction → Armory | Place it at the armory counter |
| 5 | Create at least one garage | Fleet → Garages → Create | Set label, type (car / boat / helicopter), attach to a station, add at least one spawn coord |
| 6 | Add at least one vehicle | Fleet → Vehicles → Add | Pick a model from Config.FleetCatalog, assign to the garage, set min_grade. Cost debits the department treasury |
| 7 | Create a loadout | Loadouts → Create | Set label, min_grade, add items (name, count, optional cost). Officers purchase these at the armory zone |
Before checklist step 1, create the department itself: Departments → Create. The name must match the framework job name exactly (e.g. police, lspd, bcso) — case-sensitive. label is the display name. New departments are seeded with Config.BankingAccountStartBalance ($30,000 default) when Config.UseBankingAccount = true.
When all seven checklist items show as done, the department is functionally complete.
1.5 Hire and verify
-
Hire a test player into the department:
/phire <serverID> <deptName> 0Example:
/phire 5 police 0hires player 5 at grade 0. Default grade is0if omitted. -
The test player walks to the clock-in zone you placed in step 3 of the checklist. An
ox_targetprompt appears — interact to clock in. (By defaultConfig.RequireStationClockIn = true, so the clock-in zone is the only way to toggle duty. Set it tofalseto also enable the/dutycommand and the duty toggle inside the police radial menu, which clock in at the first station in the officer's department.) -
The test player runs
/mdtto open the Mobile Data Terminal. Ifoxide-dispatchis started, the Dispatch tab is live; otherwise setConfig.MDT.dispatchEnabled = falseto hide it. -
Verification checklist:
-
/padminopens with no console errors - Department appears in the Departments tab
- All 7 setup items show as done
-
/phirereturnsHired player <id> into <dept> at grade 0 (badge #<n>) - Test officer can clock in (interaction prompt appears at the zone)
- (If
Config.RequireStationClockIn = false)/dutytoggles state from anywhere - Vehicle spawns from the garage
- Armory loadout equips at the armory zone
-
/mdtopens and shows the dashboard - No errors in the server or client console
-
At this point the department works. Continue to Part 2 only for the features you actually want.
Part 2 — Subsystem Reference
Each section is self-contained: what the subsystem does, what it depends on, what to configure, what the admin panel screen looks like, what officers see at runtime, and how to verify it works.
2.1 Department treasury and payroll
What it does. Each department holds a treasury balance. Salaries debit the treasury on a tick (Config.SalaryInterval, default 15 minutes). If the treasury is empty, the unpaid tick accrues in police_unpaid_payroll so the boss can settle later. Fines collected through the MDT can route a configurable share back to the treasury.
Dependencies. oxide-banking is recommended for treasury accounts and fine invoicing. Without it, set Config.UseBankingAccount = false to skip account creation.
Config (shared/config.lua).
| Key | Default | Purpose |
|---|---|---|
Config.UseBankingAccount | true | Create a banking account per department |
Config.BankingAccountStartBalance | 30000 | Initial treasury balance for new departments |
Config.SalaryInterval | 15 * 60 * 1000 | Salary tick frequency, ms |
Config.PlayerManagement | true | When true, salaries debit the treasury; when false, paid directly from the framework with no treasury impact |
Config.UnpaidHoursDecayDays | 30 | Auto-prune unpaid payroll rows older than this |
Config.MaxLoadoutItems | 50 | Maximum items per armory loadout |
Admin panel. /padmin → Overview → Treasury. Shows current balance, deposit / withdraw buttons, and the transaction ledger. Armory funding is per-department: the boss controls armory_treasury_funded from the in-game boss menu.
Verify. Wait one salary tick after clocking in an officer and confirm the treasury balance decreases by the configured salary.
2.2 Fleet expansion
What it does. Garages are spawn points for fleet vehicles. Each vehicle is a row in police_vehicles with model, plate, livery, extras, radar / megaphone flags, and a min_grade gate.
Config (shared/config/fleet_catalog.lua). Defines the menu of vehicles available in the admin panel when adding a vehicle to the fleet. Each entry: model, label, cost. Addon surcharges are also configurable: Config.FleetAddons.radar (default $5,000) and Config.FleetAddons.megaphone (default $2,500).
Admin panel.
- Fleet → Garages. Create multiple garages per department. Each garage has a label, type (car / boat / helicopter), an optional station tag, and one or more spawn coords (vehicles cycle through spawn points round-robin).
- Fleet → Vehicles. Add vehicles from
Config.FleetCatalog. Per vehicle:plate,min_grade,has_radar,has_megaphone. Cost debits the treasury at add-time. Mark a vehicle as available / disabled without deleting it.
Officer flow. At a garage's interact zone, the officer sees only vehicles in their assigned garage that meet min_grade. Spawn deducts nothing further. Return returns the vehicle to the garage and saves its health/fuel back to police_vehicles. If a fleet vehicle is destroyed, the replacement cost debits the treasury (or accrues if empty).
Verify. Add two vehicles with different min_grade values. Hire a low-grade officer and confirm only the lower-grade vehicle appears in the spawn menu.
2.3 Uniforms
What it does. Saved outfit presets that officers put on at a station's personal locker point. Each uniform has a slot mask (which body components it overwrites) and separate male / female component data.
Admin panel. /padmin → Uniforms (per department). For each uniform: label, min_grade, slot mask, male model, female model. Build a uniform by equipping the look in-character with your appearance system, then importing the components. Don't forget to place a personal locker point on the station (Stations → [station] → Interaction).
Officer flow. The station's personal locker point lists every uniform the officer's grade can access. Apply replaces the masked components on the officer's character; remove restores their own clothes. Any applied uniform is removed automatically on clock-out.
Verify. Create one uniform with the slot mask set to "torso + legs + shoes." Apply it on a test officer and confirm hair / face / accessories are preserved while uniform components are replaced.
2.4 Radio channels
What it does. Department-scoped voice channels routed through pma-voice or yaca-voice. Channels are gated by min_grade.
Dependencies. A voice resource (pma-voice or yaca-voice). The integration hooks are in shared/config/radio.lua.
Config (shared/config/radio.lua). Channel-name mapping for the voice provider, the radio item (police_radio), the toggle hotkey (Y), and the radio animation.
Admin panel. /padmin → Radio (per department). For each channel: channel number, label, min_grade. Mark one channel as default.
Officer flow. Press Y while holding police_radio to open the radio overlay. Pick a channel from the list (filtered to channels the officer's grade can access). Channels are department-scoped — officers from LSPD and BCSO do not share channels unless the voice provider is configured to bridge them.
Verify. Create channels 1 and 2 with different min_grade values. Have a low-grade officer confirm only channel 1 is listed in the overlay.
2.5 Doors
What it does. Station doors with department + min_grade gating, toggled with the L hotkey or ox_target.
Config (shared/config.lua → Config.Doors). ToggleKey = 'L', ToggleMaxDistance = 2.0, PickerMaxDistance = 10.0, lock / unlock sounds. The door picker (placement UI) uses PickerMaxDistance as its raycast range.
Admin panel. /padmin → Doors. The "Place door" action starts an in-world picker: aim at the door you want to control and confirm. Per door: model, coords, min_grade, double-door pair, door type, default locked state.
Officer flow. Walk up to a placed door. Press L to toggle the lock if your grade meets min_grade. Sound plays from Config.Doors.LockSound / UnlockSound.
Verify. Place a door with min_grade = 2. Press L as a grade-0 officer and confirm the lock does not toggle and a denial notify fires.
2.6 Field tools and actions
What it does. The full officer toolkit: cuff / uncuff, search, tackle, hands-up, ziptie / scissors, carry, escort, wheel clamp, mouth tape, tracking band, headbag, impound.
Config files.
shared/config/interactions.lua— cuffing, escort, search, tackle, hands-up, carry, target-menu range and keybindshared/config/field_actions.lua— tickets, cuffs / lockpick, ziptie, headbag, station servicesshared/config/field_tools.lua— wheel clamp, mouth tape, tracking band, impound (duration, fee, auto-save)
Default keybinds (rebindable in Settings → Key Bindings → FiveM):
| Key | Action |
|---|---|
F2 | Police actions menu |
G | Tackle |
X | Hands up |
E | Stop carrying |
L | Toggle nearest door |
Y | Police radio overlay |
F6 | Manual bodycam clip while watching a feed |
Officer flow. Press F2 near a target to open the action menu. Available actions are context-aware (e.g. "Search" appears only when the target is cuffed). Cuff / uncuff are also runnable as commands: /cuff [serverID] and /uncuff [serverID] — defaults to the nearest player within Config.OfficerTargetMenu.Distance (2.5m default).
Verify. /cuff a test player, confirm they cannot use their hands; then /uncuff and confirm restoration.
2.7 Charges catalog
What it does. The catalog of criminal charges shown in the MDT for booking, fines, and citations. Each charge has a code, title, category (infraction / misdemeanor / felony), fine amount, and jail time.
Important seed behaviour. Config.DefaultCharges (100 entries in shared/config/charges.lua) is seeded into the police_charges_catalog table on first run if the table is empty. Editing shared/config/charges.lua after the first seed does not retroactively update the database. From the second run onwards, manage the catalog through the MDT, not the Lua file.
Admin panel / MDT. MDT → Catalog tab (admins only). Add, edit, archive entries. Archived charges remain in historical records but cannot be attached to new cases.
Verify. Run the server once after install, then query SELECT COUNT(*) FROM police_charges_catalog; — you should see 100 rows.
2.8 MDT (Mobile Data Terminal)
What it does. Officer-facing terminal for everything investigative: dispatch alerts, citizen and vehicle search, case files, charge processing, fines, warrants, BOLOs, bodycam viewer, video storage.
Tabs.
| Tab | Requires | Purpose |
|---|---|---|
| Dashboard | — | Activity feed, on-duty officers, KPIs |
| Dispatch | oxide-dispatch | Live alerts; respond / close calls |
| Persons | — | Citizen profile, criminal record, warrants, mugshots, licenses |
| Vehicle Search | — | Lookup by plate or owner |
| Reports | — | Case files (create, search, narrative editor) |
| Charges | — | Process arrests; attach charges to cases |
| Fines | — | Issue field fines (routed through oxide-banking invoices) |
| Warrants | — | Issue, search, recall warrants (expiry from Config.MDT.warrants) |
| BOLOs | — | Person / vehicle BOLOs (expiry from Config.MDT.bolos) |
| Catalog | Admin only | Edit the charge catalog |
Config (shared/config/mdt.lua). Per-action grade requirements (Config.MDT.permissions), warrant / BOLO expiry, fine caps, search limits, dashboard metric windows, the fine revenue share routed to the department treasury, character hide list, the tablet animation, and the dispatchEnabled toggle.
Verify. Open the MDT, perform a citizen search, create a test case, attach a charge from the catalog.
2.9 Booking and custody
What it does. End-to-end jail workflow: book a suspect at the booking desk, capture a mugshot, attach charges, set sentence length, move to a holding cell, then release at the configured release point when the sentence ticks down.
Config (shared/config/custody.lua). Jail uniform components (male / female), locker stash size for stripped items, prison revive cutscene timings, Config.Custody.SecondsPerMonth (default 60 = 1 RP-month per real minute), offline-time reduction rules.
Admin panel.
/padmin→ Detention Holding → [station] — place the booking desk, holding cells, jail cell, and release point/padmin→ Jail Policy — pick stripping mode (none/locker/wipe) and edit the keep-item whitelist (items the inmate always keeps, applied in bothlockerandwipemodes)
Officer flow. Cuff the suspect → escort to booking desk → interact → MDT booking flow opens → attach charges → set months → confirm. The suspect is moved to a holding cell and starts the sentence tick. On release, they spawn at the release coords with their stripped items returned from the locker (if locker mode).
Direct jail (skips booking). /jail <serverID> <months> [reason] — admin shortcut for testing or out-of-band custody. /unjail <serverID> releases immediately.
Verify. Book a test suspect with a 1-month sentence (1 minute real time) and confirm auto-release at the configured release coords.
2.10 Mugshots
What it does. Photo capture at the booking booth, uploaded to FiveManage, linked to the criminal record. Used in the MDT Persons tab and on warrants.
Dependencies. screenshot-basic (required). Upload requires FIVEMANAGE_MEDIA_API_KEY set as a server convar. Without the convar, mugshot capture will fail.
set FIVEMANAGE_MEDIA_API_KEY "your_key_here"Config (shared/config/mugshot.lua). Upload endpoint, optional Discord webhook for audit, camera position offset, photo resolution, lighting, rotation speed.
Admin panel. /padmin → Detention Mugshot → [station]. Place camera coords (camera position) and suspect mark coords (where the suspect stands). Use the Preview button to put yourself at the mark and see the framing — note that Preview only shows the shot; it does not take or upload a photo.
Verify. Book a test suspect and confirm the mugshot uploads and appears on their record (this exercises screenshot-basic, the API key, and the upload wiring end to end).
2.11 Evidence locker and forensics
What it does. Officers register physical evidence against a case, queue items for lab processing, and view results in the Evidence Terminal NUI. Evidence at the scene is collected from auto-spawned markers (blood, bullets, fingerprints).
Case-based lockers. Evidence lockers are keyed by case number — each case file has its own locker. The station's evidence locker point is only the access gate (the officer must be on duty with access to the station's department); the case selected in the terminal decides which locker actually opens. Officers select a case before opening, processing, or registering evidence.
Config (shared/config/evidence.lua). Evidence types (blood, bullet, fingerprint, GSR), marker spawn chances, GSR swab item, fingerprint chance on vehicle entry, processing durations per item, registrable item list, weapon ballistics. Two drop controls let you keep evidence clean during non-RP play: Config.Evidence.OfficersDropBullets (default true; set false so on-duty officers leave no casings during range training or duty firefights) and Config.Evidence.IsDropExempt (a function you can edit to suppress all world-evidence drops for a player, e.g. inside a paintball minigame).
Optional oxide-medical integration. Blood evidence has two sources, and only one is active at a time. By default (no oxide-medical), blood is dropped when a player takes damage and is tagged with their character ID. If you run oxide-medical, it takes over blood entirely: a bleeding suspect drops DNA-tagged blood evidence (DNA, character ID, and wounded body part), and the basic damage-triggered drop is automatically turned off so the two never both appear for one wound. The trade-off: blood then only appears for an actual bleeding wound, not for every hit.
Admin panel. /padmin → Stations → [station] → Interaction Points → Evidence locker (storage) and Evidence lab (processing queue). Both point types support multiple placements per station.
Officer flow. At a scene, walk to a marker and interact to collect. Bring items back, select a case, and register against it — the item is logged and moved into that case's locker. Queue items at the evidence lab; processing runs on a timer (Config.Evidence.processing.<item>.duration, in seconds); results appear on the Evidence Terminal Forensics screen.
Weapon registry link. Registering a firearm (weapon_*) to a case also records its serial in the weapon registry as a seized weapon — a ghost gun with no owner data lands with no owner, flagging it as unregistered. See the Weapon registry and firearm registration section below.
Verify. Fire a weapon, walk to the bullet marker, collect, select a case, register against it, confirm it appears in the case's evidence list in the MDT.
Upgrade note. If you are upgrading from a version with per-station evidence lockers, evidence left in the old per-station lockers is orphaned — the items still exist in your inventory backend's stash storage but there is no in-game path to them, and there is no automatic migration. Relocate any live evidence through your inventory admin tools before upgrading.
2.12 Weapon registry and firearm registration
What it does. A statewide firearm registry, keyed by weapon serial, that records who each gun is registered to and survives the physical item being sold, destroyed, or carried offline.
Civilian firearm registration desk. A civilian-facing service point where any player can register the firearms they carry. Only firearms with a serial that have never been registered are eligible — ghost guns and already-registered weapons are excluded. A per-firearm fee (Config.FieldActions.StationServices.firearmRegistrationFee, default $250) is taken from the registrant's bank and deposited into the station's department treasury.
Config (shared/config/field_actions.lua). Config.FieldActions.StationServices.firearmRegistrationEnabled (default true) and firearmRegistrationFee (default 250).
Admin panel. /padmin → Stations → [station] → Services → Firearm Registration. Add one or more desks per station (each entry has a label, coords, min grade, and enabled toggle), alongside station bells and trash bins.
Officer flow. Officers work the registry from the MDT → Weapons tab: search by serial or owner name, view a weapon's owner of record, and set its status (registered / stolen / seized / revoked — stolen and revoked auto-flag). The registry is populated by the registration desk and by evidence submission of weapon_* items.
Verify. Carry an unregistered serialized weapon, target the firearm registration desk, register it, then search its serial in the MDT Weapons tab and confirm it shows you as the owner.
2.13 Bodycam
What it does. Officer POV streaming to other officers (/bodycams viewer). Manual clip recording with F6. Recordings uploaded to FiveManage or pushed to a Discord webhook, and attachable to MDT cases.
Dependencies. screenshot-basic. Upload provider is either FiveManage (FIVEMANAGE_MEDIA_API_KEY convar) or Discord webhook (configured in shared/config/bodycam.lua).
Config (shared/config/bodycam.lua). Item name (body_cam), recording provider, video resolution, storage limits, Config.Bodycam.sameDepartmentOnly (default true — restricts the viewer to officers in the same department), the F6 recording hotkey, placement settings.
Officer flow. Equip the body_cam item — the wearer indicator appears on screen. Any officer runs /bodycams to open the roster and watch a feed. While watching, the viewer can press F6 to start a manual clip; releasing F6 ends and uploads the clip. Uploaded clips are listed in the MDT Video Storage tab and can be attached to cases.
Verify. Officer A equips body_cam. Officer B runs /bodycams and confirms officer A is listed. Open the feed, press F6, release, and confirm the clip appears in the MDT Video Storage tab.
2.14 CCTV
What it does. Placed cameras that any officer can view through /cameras. Two tiers: temporary (placed by officers in the field) and permanent (placed by admins via /padmin).
Config (shared/config/cctv.lua). Camera models, viewer FOV, recording toggle, thermal toggle, view range, placement rules.
Admin panel. /padmin → CCTV. List all cameras; rename, promote temporary to permanent, or delete. Use "Place camera" to enter the in-world placement UI.
Officer flow. With the cctv_camera item, an officer can place a temporary camera in the field. Permanent cameras are admin-only. Any hired officer runs /cameras to open the roster and cycle through feeds.
Verify. Place one camera via /padmin → CCTV → Place camera. Run /cameras and confirm the feed renders.
2.15 Speed cameras
What it does. Automated speed enforcement. Cameras detect passing vehicles over the configured speed limit, fine the driver, and optionally email them the ticket.
Config (shared/config.lua → Config.SpeedCam and Config.CitizenEmail.Speedcam). Camera prop models, catch cooldown (CatchCooldown, default 30s), default sensor radius, max fine multiplier (MaxFineMultiplier, default 3), blip styling. Speed unit follows Config.SpeedUnit (MPH or KMH).
Admin panel. /padmin → Speed Cameras. Edit existing cameras (label, limit, fine, sensor radius, multiplier flag, blip / screen / light effects). The top "ignored jobs" chip list exempts framework jobs (e.g. police, ambulance) from triggers. Place new cameras with the in-world /speedcam_create command (faster than the panel form). Remove the nearest camera with /speedcam_remove.
Officer / civilian flow. A vehicle passing the camera over the limit triggers a catch. The driver receives a fine via oxide-banking invoice and (if Config.CitizenEmail.Speedcam.Enabled = true) an email from traffic@<dept>.gov with the photo and ticket detail.
Verify. Place a camera with limit 20 MPH on a road. Drive past at 40 MPH and confirm the fine and email arrive.
2.16 Handheld radar (WEAPON_RADAR)
What it does. Pistol-style handheld speed radar. Officer aims at a vehicle and reads its speed on an in-world overlay.
Setup. Register WEAPON_RADAR as both an inventory item (weapon_radar) and a weapon in your framework — see the per-framework install guide. The model and meta files stream from oxide-police/stream/ automatically.
Config (shared/config.lua → Config.Radar). Vehicle radar keybinds (K toggle, J lock front, M lock rear), handheld weapon hash (WEAPON_RADAR), handheld range (100m default), vehicle-radar raycast tick rate (Config.Radar.TickMs, 250ms; the handheld updates every frame), overlay scaling and grace period.
Officer flow. Equip WEAPON_RADAR, aim at a vehicle, the overlay shows the vehicle's speed. The handheld has no separate keybinds — aiming activates it. Vehicle radar is independent and requires the fleet vehicle to have has_radar = true set in /padmin.
Verify. Equip the weapon, aim at a moving vehicle, confirm the overlay reads the speed in the units defined by Config.SpeedUnit.
2.17 Breathalyzer
What it does. DUI test device. Officer applies the breathalyzer to a suspect, reads their BAC, attaches the result to the case.
Setup. Register the breathalyzer item in inventory.
Config (shared/config/breathalyzer.lua). Test duration, BAC thresholds (pass / impaired / DUI), and the Config.Breathalyzer.sources list — pointers to whatever drunk system your server uses. The breathalyzer reads BAC from those sources rather than running its own simulation.
Officer flow. Use the breathalyzer item on a suspect → progress bar → result UI shows BAC and pass/fail. Result can be attached to a charge.
Verify. Have a test player drink alcohol from your drunk system, run the breathalyzer, and confirm the BAC matches the expected value.
2.18 Megaphone
What it does. Handheld PA and vehicle PA. Handheld broadcasts at a configurable range; vehicle PA broadcasts from any fleet vehicle marked with has_megaphone = true.
Setup. Register the megaphone item. Optional voice-bridge integration in shared/config/megaphone.lua for pma-voice / yaca-voice.
Config (shared/config/megaphone.lua). Range, animation, voice provider hooks, vehicle PA keybind (B, Config.Megaphone.vehicleKey).
Officer flow. Equip the megaphone and speak (voice routed at extended range). Inside a fleet vehicle marked has_megaphone, press B to toggle vehicle PA — no item required.
Verify. Two test players. Officer A on the megaphone speaks; officer B confirms audio at extended range.
2.19 Prison operations
Prison covers three independent subsystems: a revive point (mandatory for the prison death cutscene), a prison shop (optional commissary), and prisoner jobs (optional minigames).
2.19.1 Revive point
/padmin → Revive Point. One global revive point per server. Set position to your current location, or clear it. Without a revive point, the prison death cutscene cannot fire — inmates who die mid-sentence fall through to the framework medical resource and may break out of jail.
2.19.2 Prison shop
/padmin → Prison Shop.
- Vendor location. Set vendor coords + heading. The vendor ped spawns at this point using the
WORLD_HUMAN_CLIPBOARDscenario. - Meal windows. Time ranges (HH:MM format) when inmates can claim a free
prison_food_tray. Each window has a unique ID; an inmate can claim once per window per day (tracked inpolice_prison_shop_claims). - Paid catalog. Item, label, price, category (categories from
Config.PrisonShop.categories).
Config in shared/config/prisonshop.lua: free meal restore amount, default categories.
2.19.3 Prisoner jobs
/padmin → Prisoner Jobs. Three tabs:
- Mining. Place rock spawn points. Inmate breaks rocks for pay.
- Cleaning. Place trash spawn zones. Inmate clears trash for pay.
- Electrical. Place meter points (and optionally bind a specific entity). Inmate solves the electrical minigame (wire match / circuit trace / voltage tune) for pay.
Config in shared/config/prisonerjobs.lua: payouts, tools, minigame difficulty.
Verify the full chain. Jail a test player with /jail 1 1 test. They spawn at a holding cell, can buy from the shop during a meal window, can complete a prisoner job at a placed point, and (if you kill them) respawn at the revive point.
2.20 Placeable objects
What it does. Officer-placeable props for scene control: spike strips, cones, barricades, litter baskets, prison beds.
Config (shared/config/objects.lua). Each prop entry: model, dimensions, placement rules (max range, ground-snap), function (spike strip flattens tires, cone is decorative, etc.).
Officer flow. Open the police actions menu (F2), select "Place object," pick a prop from the list, place via raycast. Rotate with mouse wheel before confirming. Delete by interacting with the placed object.
2.21 Multi-department setup
oxide-police is designed for multi-department servers (LSPD + BCSO + SAHP + Park Rangers + Sheriff, etc.). Everything is department-scoped — fleet, uniforms, loadouts, radio channels, grades, treasury, MDT data — except the global charge catalog and the prison revive point.
Setup pattern.
- Create one department per framework job. Department
namemust match the job exactly. - Define grades per department independently. LSPD grade
0and BCSO grade0are unrelated rows. - Build station / fleet / loadout / uniform / radio for each department in its own
/padminselector. - Cross-department views in the MDT (Dispatch, Persons, Vehicles, Warrants, BOLOs) show records from all departments by default. Per-tab filters narrow the view.
- Radio channels are department-scoped. To bridge two departments on a shared frequency, configure the voice provider (
pma-voice/yaca-voice) to alias channels —oxide-policedoes not bridge channels itself.
Officer flow. When hired with /phire 5 bcso 2, the officer joins BCSO at grade 2 — they cannot clock in at an LSPD station, see LSPD radio channels, or spawn LSPD vehicles. The MDT shows cross-department data (e.g. an LSPD-issued warrant is visible to BCSO).
One officer in two departments. By default a character belongs to exactly one department — hiring them into a second moves them out of the first. Set Config.AllowMultiDepartment = true in shared/config.lua to let a character hold several departments at once (each with its own badge, callsign, grade, and pay). Their active department is whichever police job they currently have selected; everything stays scoped to that active department. This is also what makes Oxide Police work with multi-job menus like g-multijob — see the g-multijob section of ESX Installation.
Part 3 — Operational Cheat Sheet
Admin commands
| Command | Use |
|---|---|
/padmin | Open the admin panel |
/phire <id> <dept> [grade] | Hire player into a department |
/pfire <id> [dept] | Fire player from a department (their current one by default) |
/jail <id> <months> [reason] | Direct jail (skips booking) |
/unjail <id> | Release from custody |
/addtime <id> <±minutes> [reason] | Add or reduce a prisoner's remaining sentence |
/setsentence <id> <minutes> [reason] | Set a prisoner's remaining sentence |
/speedcam_create | In-world speed camera placement |
/speedcam_remove | Remove nearest speed camera |
Officer commands
| Command | Use |
|---|---|
/duty | Toggle duty from anywhere (only when Config.RequireStationClockIn = false) |
/mdt | Open the MDT (on-duty only) |
/cuff [id] / /uncuff [id] | Cuff / uncuff (on-duty only) |
/bodycams | Open the bodycam roster viewer |
/cameras | Open the CCTV roster viewer |
Default keybinds
| Key | Action |
|---|---|
F2 | Police actions menu |
B | Vehicle PA (megaphone) |
E | Stop carrying |
G | Tackle |
X | Hands up |
Y | Police radio overlay |
L | Toggle nearest door |
F6 | Manual bodycam clip while watching a feed |
K / J / M | Vehicle radar toggle / lock front / lock rear |
Common gotchas
- Department
namemust match the framework job name (case-sensitive).lspdandLSPDare different. - The charges catalog is seeded once. Editing
shared/config/charges.luaafter first run does not retroactively update the database. Use the MDT's Catalog tab instead. FIVEMANAGE_MEDIA_API_KEYconvar is required for mugshot and bodycam uploads. Without it, the upload step fails silently.- Set
Config.MDT.dispatchEnabled = falseif you are not runningoxide-dispatch, or the Dispatch tab will show as unavailable. - Configure a prison revive point before booking any real suspects, or in-jail deaths fall through to the framework medical resource.
- Editing
shared/config/*.luarequires a resource restart — DB-driven settings (departments, stations, fleet, loadouts, charges, channels, custody points, speed cameras, CCTV) update live. o-linkmust start beforeoxide-police. A missing or late-loadedo-linkcausesolink.<ns>calls to fall back to no-op defaults and many features will appear to silently do nothing.
Where to go next
- Features — full feature catalogue
- Configuration — per-key reference for every
shared/config/*.luafile - Admin — full command and
/padminreference - Exports — integration API for other resources
- Troubleshooting — known issues and diagnostic flags
- Per-framework install: QBCore · ESX · Qbox