Skip to content

mi-policejob

All-in-one police suite in a single resource: forensic evidence and GSR, restraints (cuffs, zip-ties, hood, drag, carry, vehicle), speed radar with BOLO, deployables, CCTV, a field camera, licenses, and bodycam. It exposes the standard police contracts other resources expect, so nothing else on the server needs editing.

Install

ensure mi-policejob

Requires OneSync enabled. Ensure screenshot-basic first (field-camera photo upload). This resource adds no database table.

Config

Config is split across shared/config/*.lua and aggregated by init.lua. general.lua holds the core gates; per-feature tuning lives in the sibling files.

-- shared/config/general.lua: the core gates.
return {
    -- Law-enforcement jobs. name -> minimum grade.
    leoJobs = { police = 0, doc = 0 },

    requireDutyForLeo = true,   -- LEO must be on duty to restrain others

    -- Non-LEO groups allowed to use HANDCUFFS (zip-ties are never job gated).
    cuffGroups = { godfathers = 0, hotel = 1 },
    -- Groups allowed to put a bag/hood on someone's head.
    hoodGroups = { police = 0, doc = 0, godfathers = 0 },

    maxActionDistance = 5.0,    -- metres between actor and target for any restraint action
    actionCooldown    = 1.0,    -- seconds between restraint actions per actor (anti-spam)

    govJobs = { government = 0 }, -- job(s) allowed to grant/revoke licenses

    stations = { --[[ station map blips: { label = ..., coords = vec3(...) } ]] },
    armoryShopType = 'POLEmergency', -- documentation only; the armory shop is defined in ox_inventory
}

The sibling config files, all buyer-editable: restraints.lua (items, props, anims, timings), evidence.lua (evidence items, GSR, suspect statuses, the evidence-locker stash), radar.lua (radar jobs, ranges, keybinds F7/F9), deployables.lua, cctv.lua, fieldcam.lua, checkvin.lua, licenses.lua, misc.lua, bodycam.lua, and theme.lua (palette preset). Blank server/apiKeys.lua before packaging for sale.

Exports

These contracts are exposed for other resources (via the manifest provide lines). Internal code does not use them.

Export Signature What it does
CreateCasing (server) exports['mi-policejob']:CreateCasing(src, weapon, serial, coords) Drops a shell-casing evidence marker linked to the shooter.
CreateBloodDrop (server) exports['mi-policejob']:CreateBloodDrop(src, citizenid, bloodtype, coords) Drops a blood evidence marker linked to a citizen.
CreateFingerDrop (server) exports['mi-policejob']:CreateFingerDrop(src, coords) Drops a fingerprint evidence marker.
ClearCasings (server) exports['mi-policejob']:ClearCasings(src, casingList) Clears the listed casing markers.
ClearBlooddrops (server) exports['mi-policejob']:ClearBlooddrops(src, bloodDropList) Clears the listed blood markers.
UpdateStatus (server) exports['mi-policejob']:UpdateStatus(src, data) Sets transient suspect status flags (red hands, wide pupils, and so on).
GetPlayerStatus (server) exports['mi-policejob']:GetPlayerStatus(src) Returns the player's current status table.
GenerateFingerId (server) exports['mi-policejob']:GenerateFingerId() Returns a new collision-checked fingerprint id.
SetFakeFingerprint (server) exports['mi-policejob']:SetFakeFingerprint(targetSrc, fingerId) Overrides a target's fingerprint for the session.
LegacyAddCasingToInventory (server) exports['mi-policejob']:LegacyAddCasingToInventory(src, casingId, casingInfo) Collects a casing into a player's inventory using the legacy payload shape (ammolabel, serie), for third parties still calling the legacy casing-collection event.
LegacyAddBlooddropToInventory (server) exports['mi-policejob']:LegacyAddBlooddropToInventory(src, bloodId, bloodInfo) Same for a blood drop (legacy dnalabel, bloodtype fields).
LegacyAddFingerprintToInventory (server) exports['mi-policejob']:LegacyAddFingerprintToInventory(src, fingerId, fingerInfo) Same for a fingerprint (legacy fingerprint field).
grantLicense (server) exports['mi-policejob']:grantLicense({ id, license }) Grants a license to a player. Meant for trusted server code (no permission gate).
ForceFree (server) exports['mi-policejob']:ForceFree(src) Fully releases any restraint and hood on a player (used on respawn).
GetRestraint (server) exports['mi-policejob']:GetRestraint(src) Returns the player's current restraint state, or nil.

Client, invoked by the radial-menu and inventory-item bridges in compat/ so existing wheels and items keep working:

Export Signature What it does
runCheckVin (client) exports['mi-policejob']:runCheckVin() Runs the VIN / ANPR check on the nearest vehicle and shows its plate, model, owner, and flag status. LEO only.
runSeize (client) exports['mi-policejob']:runSeize() Impound-seizes the nearest vehicle after a confirm and progress bar. LEO only.
runDeploy (client) exports['mi-policejob']:runDeploy(kind) Deploys a police object of kind (cone, barrier, roadsign, spike) at your position.
removeNearest (client) exports['mi-policejob']:removeNearest() Removes the nearest deployed police object or spike strip.
UseShield (client) exports['mi-policejob']:UseShield(data, slot) ox_inventory use hook for the ballistic-shield item. LEO-gated, toggles the shield on or off.
ToggleBodycamVisible (client) exports['mi-policejob']:ToggleBodycamVisible() Toggles the bodycam REC overlay (turning it on is LEO only, off is always allowed).
ToggleCarCam (client) exports['mi-policejob']:ToggleCarCam() Toggles the in-vehicle dash-cam mode.
OpenBodycamSettings (client) exports['mi-policejob']:OpenBodycamSettings() Opens the bodycam settings panel (callsign, unit, scale).

Legacy radial-menu and inventory-item events are bridged to these exports in compat/, so existing wheels and items keep working with no edits.

Statebags

mi-policejob carries restraint, GSR, BOLO, and deployable state on statebags. This is how restraint, GSR, and BOLO state stays readable by other resources with no events.

Statebag Scope Set when Read by
restraint player A restraint is applied or changed. Holds the canonical rich state (mode, hood, drag, carry). mi-policejob clients drive the restraint effects; integrators that want full detail.
isHandcuffed player A restraint is applied or cleared. The standard cuffed flag other resources check.
hasBagOnHead player A hood is put on or taken off. Screen-blindfold and camera resources.
isBeingDragged player Drag starts or ends. Movement and animation consumers.
isBeingCarried player Carry starts or ends. Movement and animation consumers.
canUseWeapons player A restraint is applied or cleared (false while restrained). Weapon-disabling resources.
Dragging player An officer starts or stops dragging someone. Holds the target's server id, or false. mi-policejob and drag consumers.
isCarrying player An officer starts or stops carrying someone. Holds the target's server id, or false. mi-policejob and carry consumers.
gsr player The player fires a weapon (auto-clears after the configured duration, or early on washing hands). mi-policejob's GSR test and forensic integrations.
vehicleLock vehicle An officer carjacks a locked vehicle (forces { lock = 1, sound = true }). mi-keys clients apply the lock. This is the same vehicle bag mi-keys owns.
miPoliceBolo GlobalState A plate is added to or removed from the BOLO list. Officers' radar clients.
spikeStrips GlobalState A spike strip is deployed or removed. Holds their net ids. mi-policejob clients, for spike detection.
policeObjects GlobalState A cone, barrier, or road sign is deployed or removed. Holds their net ids. mi-policejob clients.
fixedCoords GlobalState A deployable is placed or removed. Fixed spawn coords keyed by net id. mi-policejob clients.

See the state reference for the core statebags and GlobalState.