> For the complete documentation index, see [llms.txt](https://ccfivem.gitbook.io/ccfivem-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://ccfivem.gitbook.io/ccfivem-docs/police-ems-and-justice/police-cc_police.md).

# Police (cc\_police)

**CrankChaos Police**: a complete police job with duty, armory, fleet, arrests, fines, barriers and a full MDT.

Supported frameworks: **ESX Legacy**, **QBCore** and **QBox**. The framework is detected automatically through the CrankChaos framework bridge.

{% hint style="info" %}
The script is protected by Cfx asset escrow. Everything in `config/`, `locales/` and the framework bridge files (`shared/cc_framework.lua`, `shared/cc_characters.lua`, `shared/cc_society.lua`, `shared/cc_vehicles.lua`) stays editable.
{% endhint %}

## Features

### Station and duty

* Duty on/off with a personal **callsign** (validated by the server)
* Locker room with rank-based uniforms per gender (via cc\_character/00%20Overview\.md))
* Armory with **serial-numbered weapons** (via cc\_inventory/00%20Overview\.md)), per-item limits, cooldown, hourly limit and optional prices paid from the society account
* Station stash and evidence storage (cc\_inventory)
* Fleet garage (ground and air) with vehicle extras, liveries and **plates generated from the callsign**; keys via cc\_keys/00%20Overview\.md)

### Actions on citizens (all validated server-side)

* Cuff / uncuff, escort, carry, put in / take out of vehicle
* Search a person or vehicle (cuffed or downed persons only)
* ID check (with consent unless the person is cuffed or downed), license display via cc\_licenses/00%20Overview\.md)
* Fines from a catalog (up to 5 entries, the citizen must accept, cash first then bank, money goes to the society account)
* Vehicle impound (to the tow yard with cc\_garage/00%20Overview\.md))
* Cuffed players cannot run, jump, shoot or drive; weapon is removed and the inventory is locked

### Scene tools

* Cones, barriers, tape, signs, work lights and **spike strips** with per-officer limits and automatic cleanup

### MDT (F6 or `/mdt`)

* Dashboard, people and vehicle search, notes and flags
* Charges with an editable **penal code**, fines and jail (jail requires cc\_prison/00%20Overview\.md))
* Warrants, BOLOs, incident reports with trash/restore
* **Plate reader** in service vehicles (stolen, wanted, BOLO hits)
* Staff management with duty times, announcements, 10-codes, activity log
* **Live map** with units and calls (requires cc\_dispatch/00%20Overview\.md))
* Mugshots via cc\_images%20(cc\_images)/00%20Overview\.md), lab button via cc\_evidence/00%20Overview\.md), cameras/tracking via cc\_policetools/00%20Overview\.md)
* Rank-based permissions, checked on every server action

### Dispatch integration

* Panic, backup and automatic **officer down** alerts via cc\_dispatch

## Pages

* Installation
* Configuration
* API (exports, events, commands)
* FAQ & troubleshooting

Need help? See Support.

## Installation

General steps (download, escrow, folder layout) are described in Getting started: Installation.

### Requirements

**Required**

* `oxmysql`
* ESX Legacy, QBCore or QBox with a job named `police`
* A society account for the job: ESX `society_police` (esx\_addonaccount), QBCore/QBox via the management/banking resource
* **No other police script** running at the same time (e.g. esx\_policejob, qb-policejob)

**Optional** (each checked at runtime; if missing, only that feature is disabled or hidden)

| Resource                                                            | Used for                                                           | Without it                                                |
| ------------------------------------------------------------------- | ------------------------------------------------------------------ | --------------------------------------------------------- |
| cc\_lib/00%20Overview\.md)                                          | shared notifications / hints                                       | built-in notifications                                    |
| cc\_inventory/00%20Overview\.md)                                    | serial-numbered armory, search, stashes, spike strips, cuffed lock | no search, no serial weapons, no stashes, no spike strips |
| cc\_character/00%20Overview\.md)                                    | duty uniforms                                                      | no uniforms                                               |
| cc\_garage/00%20Overview\.md)                                       | impound to tow yard                                                | vehicle is only deleted                                   |
| cc\_licenses/00%20Overview\.md)                                     | licenses on ID check and in MDT                                    | section hidden                                            |
| cc\_dispatch/00%20Overview\.md)                                     | panic, backup, officer down, dashboard alerts, MDT live map        | map and alerts hidden                                     |
| cc\_ambulance/00%20Overview\.md)                                    | `ccDown` state for carry/search of downed players                  | cuffed players only                                       |
| cc\_keys/00%20Overview\.md)                                         | keys for service vehicles                                          | no keys handed out                                        |
| cc\_images%20(cc\_images)/00%20Overview\.md) (+ `screenshot-basic`) | mugshot in MDT                                                     | no photo                                                  |
| cc\_jobs/00%20Overview\.md)                                         | place locations in-game                                            | `Config.Places` is used                                   |
| cc\_prison/00%20Overview\.md)                                       | "Jail" and sentence status in MDT                                  | sentence only stored in the record                        |
| cc\_evidence/00%20Overview\.md)                                     | lab button in MDT                                                  | hidden                                                    |
| cc\_policetools/00%20Overview\.md)                                  | cameras and tracking in MDT                                        | hidden                                                    |

See also Dependencies.

### Steps

1. Copy the folder to `resources/[crankchaos]/cc_police`.
2. Make sure the job `police` exists (ESX: `jobs` / `job_grades`; QBCore/QBox: `shared/jobs.lua`). The default config expects ranks 0-4 (recruit, officer, sergeant, lieutenant, boss).
3. ESX only: make sure the `society_police` addon account exists.
4. Add the resources to `server.cfg` in this order:

```cfg
ensure oxmysql
ensure es_extended          # or qb-core / qbx_core
ensure esx_addonaccount     # ESX only: society account
ensure cc_lib               # optional
ensure cc_character         # optional
ensure cc_inventory         # optional
ensure cc_keys              # optional
ensure cc_garage            # optional
ensure cc_licenses          # optional
ensure cc_dispatch          # optional
ensure cc_ambulance         # optional
ensure cc_images            # optional (needs screenshot-basic)
ensure cc_jobs              # optional, must start BEFORE cc_police
ensure cc_police
```

### Database

**No SQL file is required** (there is no `sql/` folder). On first start the script creates its tables itself:

`cc_police_staff`, `cc_police_meta`, `cc_police_profiles`, `cc_police_notes`, `cc_police_vehicles`, `cc_police_penal`, `cc_police_records`, `cc_police_warrants`, `cc_police_bolos`, `cc_police_reports`, `cc_police_report_people`, `cc_police_announcements`, `cc_police_codes`, `cc_police_sessions`, `cc_police_log`.

The penal code and 10-codes are seeded **once** from `Config.Mdt.seed`; afterwards they are maintained in the MDT.

### ACE permissions

```cfg
## /uncuff [id] for admins
add_ace group.admin command.uncuff allow

## optional: location editor in the MDT without being the highest rank
add_ace group.admin cc_jobs.admin allow
```

### Framework notes

| Framework     | Notes                                                                      |
| ------------- | -------------------------------------------------------------------------- |
| ESX Legacy    | Job in `jobs`/`job_grades`, society `society_police` via esx\_addonaccount |
| QBCore / QBox | Job in `shared/jobs.lua`, society via the management resource              |

The script reads the framework's player and vehicle tables (read-only) for the MDT. See Framework bridge.

## Configuration

Editable files:

| File                                 | Contents                                                                                     |
| ------------------------------------ | -------------------------------------------------------------------------------------------- |
| `config/config.lua`                  | gameplay: job, keys, places, outfits, armory, garage, interactions, fines, objects, dispatch |
| `config/mdt.lua`                     | MDT: command, rank permissions, limits, plate reader, map, seed data                         |
| `config/ui.lua`                      | look and language                                                                            |
| `locales/de.json`, `locales/en.json` | texts                                                                                        |

{% hint style="info" %}
Prices, amounts and quantities are always read by the server from the config; the client only sends IDs.
{% endhint %}

### General

```lua
Config.Debug = false
Config.Job = 'police'       -- job name in the framework
Config.Society = 'police'   -- society account (ESX: society_police)
```

### Keys

```lua
Config.Keys = {
    menu = 'F6',     -- action menu / MDT (RegisterKeyMapping, rebindable)
    interact = 38,   -- E (control ID)
    park = 47,       -- G, park service vehicle from inside
}
```

Off duty, the same F6 key belongs to the cc\_dispatch citizen tablet.

### Places

```lua
Config.UseJobPoints = true   -- use cc_jobs points when set, false = config only
Config.PlacesHeight = 1.0    -- height of config coords above ground
```

`Config.Places` lists points per kind: `duty`, `wardrobe`, `armory`, `stash`, `evidence`, `garage`, `garage_spawn`, `heli_spawn`, `blip`. Each entry has `id`, `coords` (vector4) and optionally `model` (ped, `false` = marker only). Stash/evidence entries have `slots`, `maxWeight`, `minGrade`; garages have `spawnKind`, `fleet` and `label`.

```lua
stash = {
    { id = 'mrpd', coords = vector4(459.5, -979.9, 30.69, 0.0), slots = 80, maxWeight = 400000, minGrade = 0 },
},
```

{% hint style="warning" %}
Default coordinates are for the vanilla Mission Row station. With an MLO, adjust `Config.Places` or set the points in-game with cc\_jobs.
{% endhint %}

### Callsign

```lua
Config.Callsign = { pattern = '^[%w%-]+$', max = 6 }
```

### Outfits

`Config.Outfits.male` / `.female`: list of outfits with `id`, `label`, `minGrade` and `pieces` (keys are cc\_inventory body slots: `hat`, `torso`, `jacket`, `vest`, `gloves`, `legs`, `shoes`, ...; each `{ drawable, texture }`). Defaults: recruit (0), patrol (1), tactical (2).

### Armory

```lua
Config.Armory = {
    cooldown = 3,          -- seconds between two withdrawals
    hourlyLimit = 120,     -- per item per hour
    registeredTo = 'LSPD', -- owner in the cc_inventory weapon register
    items = {
        { id = 'pistol', kind = 'weapon', item = 'WEAPON_COMBATPISTOL', label = 'police.item.pistol', max = 1, price = 0, minGrade = 0 },
        -- ...
    },
}
```

`kind`: `weapon` (serial number via cc\_inventory, `max` = how many at once), `item` (normal item) or `armour` (sets armour to `amount`). `price` is per piece from the society account (0 = free).

### Garage

```lua
Config.Garage = {
    platePrefix = 'LSPD',
    callsignPlate = true,  -- LSPD + callsign if free, otherwise random
    parkRadius = 25.0,
    fleets = {
        ground = { { id = 'police', model = 'police', type = 'automobile', minGrade = 0, extras = { [1] = true, [2] = true }, livery = 0 }, ... },
        air = { { id = 'polmav', model = 'polmav', type = 'heli', minGrade = 3, livery = 0 } },
    },
}
```

### Interactions

```lua
Config.Interact = { distance = 2.5, vehicleDistance = 6.0 }
Config.Cuffs = { duration = 3500, item = false, keepOnRelog = true }
Config.Escort = { maxDistance = 6.0 }
Config.Carry = { requireRestrained = true }
Config.Search = { distance = 3.0 }
Config.Identity = { timeout = 30, cardItems = { 'driver_license', 'boat_license', 'pilot_license' }, idItem = 'id_card' }
```

* `Cuffs.item`: item the officer needs (not consumed), `false` = none.
* `Cuffs.keepOnRelog`: cuffed players stay cuffed after relog (until resource restart).

### Fines

```lua
Config.Fines = {
    minGrade = 0,
    timeout = 45,
    maxEntries = 5,
    officerShare = 0,  -- percent paid to the issuing officer
    catalog = {
        { id = 'speed_small', category = 'traffic', label = 'police.fine.speedSmall', amount = 250 },
        -- ...
    },
}
```

### Vehicles

```lua
Config.Impound = { minGrade = 1, duration = 8000, protectService = true }
Config.VehicleSearch = { minGrade = 0 }
```

### Objects and spike strips

```lua
Config.Objects = {
    maxPerOfficer = 15, placeDistance = 6.0, pickupDistance = 3.0,
    lifetime = 60,          -- minutes
    clearOnDutyEnd = true,
    kinds = { { id = 'cone', model = 'prop_roadcone02a', max = 10, ahead = 1.2 }, ... },
}
Config.Spikes = { radius = 60.0, near = 15.0, farInterval = 250, halfLength = 1.9, halfWidth = 0.45, axis = 'y' }
```

A kind with `item` consumes that item on placement and returns it on pickup (default: `spikestrip`).

### Dispatch

```lua
Config.Dispatch = {
    panicCooldown = 30,
    backupCooldown = 20,
    officerDown = true,
    panic  = { code = '10-99', priority = 1, blip = { sprite = 526, colour = 1, scale = 1.2 } },
    backup = { code = '10-78', priority = 2, ... },
    down   = { code = '10-99', priority = 1, ... },
}
```

Only active when cc\_dispatch is running.

### Marker

`Config.Marker`: marker type, scale, colour and draw distance for the service vehicle return spot.

### MDT (`config/mdt.lua`)

```lua
Config.Mdt = {
    command = 'mdt',        -- false = no command
    perms = {
        view = 0, notes = 0, photo = 0, flags = 1, licences = 3,
        records = 0, recordsDelete = 3, jail = 0, penal = 3,
        warrants = 0, warrantIssue = 2, bolo = 0, vehicleFlag = 0,
        reportsWrite = 0, reportsEditAll = 2, reportsDelete = 3,
        announce = 3, codes = 3, staff = 4, staffManage = 4, log = 3,
    },
    ...
}
```

`perms` = minimum rank per right; the framework "boss" may do everything.

| Option                         | Default                                                                         | Meaning                                       |
| ------------------------------ | ------------------------------------------------------------------------------- | --------------------------------------------- |
| `flags`                        | `dangerous`, `armed`, `gang`, `escape`, `mental`                                | person flags                                  |
| `licences`                     | `car`, `bike`, `truck`, `boat`, `pilot`                                         | cc\_licenses licenses shown                   |
| `maxJail`                      | `120`                                                                           | max months per charge                         |
| `fineRadius`                   | `10.0`                                                                          | citizen distance for fines (0 = anywhere)     |
| `jail`                         | `{ radius = 5.0, requireCuffed = true }`                                        | jail from a charge (cc\_prison)               |
| `photoRadius` / `nearbyRadius` | `5.0` / `15.0`                                                                  | meters                                        |
| `deleteGraceDays`              | `7`                                                                             | restore window for deleted reports            |
| `logDays`                      | `60`                                                                            | log retention                                 |
| `evidenceHosts`                | `{ 'https://cfx-nui-cc_images/' }`                                              | allowed URL prefixes for evidence photo links |
| `plateReader`                  | `enabled = true, interval = 1000, distance = 30.0, cooldown = 90, sound = true` | plate reader                                  |
| `map`                          | `jobColors`, `places = { 'blip', 'garage' }`                                    | live map (cc\_dispatch)                       |
| `limits`                       | see file                                                                        | max text lengths and numbers                  |
| `seed`                         | `penal`, `codes`                                                                | seeded once on first start                    |

### UI (`config/ui.lua`)

```lua
Config.UI = {
    theme = 'default', primary = '#3B82F6', radius = 'md', scale = 1.0,
    locale = 'de', animations = true, blur = false, sounds = true,
}
```

Set `locale = 'en'` for English.

## Exports, Events & Commands

### Commands and keys

| Command / key                  | Who                                  | Purpose                                   |
| ------------------------------ | ------------------------------------ | ----------------------------------------- |
| `F6` (`+ccpolice`, rebindable) | police on duty                       | action menu (citizen within 2.5 m) or MDT |
| `/mdt` (`Config.Mdt.command`)  | police on duty                       | open the MDT                              |
| `/uncuff [id]`                 | ACE `command.uncuff`, server console | uncuff a player (no id: yourself)         |

### Server exports

| Export               | Returns                                                                        |
| -------------------- | ------------------------------------------------------------------------------ |
| `IsOnDuty(src)`      | `boolean`                                                                      |
| `OnDutyCount()`      | `number`                                                                       |
| `GetCallsign(src)`   | `string` or `nil`                                                              |
| `IsCuffed(src)`      | `boolean`                                                                      |
| `SetCuffed(src, on)` | `boolean`, for prison/admin scripts, no officer needed                         |
| `PlateFlags(plate)`  | `{ stolen, bolo, warrant, note }` or `nil` (5 s cache), e.g. for speed cameras |

```lua
if exports.cc_police:IsOnDuty(source) then
    print(exports.cc_police:GetCallsign(source))
end

local flags = exports.cc_police:PlateFlags('LSPD 12')
if flags and flags.stolen then
    -- ...
end
```

### Client exports

| Export       | Returns   |
| ------------ | --------- |
| `IsOnDuty()` | `boolean` |
| `IsCuffed()` | `boolean` |

### Server events (local)

```lua
AddEventHandler('cc_police:duty', function(src, on) end)
AddEventHandler('cc_police:cuffed', function(src, on) end)

-- after every saved charge
AddEventHandler('cc_police:charged', function(officerSrc, targetIdentifier, info)
    -- info = { fine, months, charges = { { id, code, label, fine, jail, count } }, record }
end)

-- active = the person still has an open warrant
AddEventHandler('cc_police:warrant', function(identifier, active) end)

-- MDT tables are ready
AddEventHandler('cc_police:mdtReady', function() end)
```

### State bags (written by the server only)

| Entity  | Keys                                                                                     |
| ------- | ---------------------------------------------------------------------------------------- |
| Player  | `ccDuty = { job = 'police', callsign, since }`, `ccCuffed = { by, since }`, `ccCallsign` |
| Vehicle | `ccService` (service vehicle), `ccPlate`                                                 |
| Object  | `ccPoliceObject`                                                                         |

### Soft integrations used

cc\_police calls these exports only when the resource is running:

```lua
exports.cc_prison:Jail(officerSrc, targetSrc, months, reason)
exports.cc_prison:GetSentence(identifier)
exports.cc_evidence:OpenLab()
exports.cc_policetools:OpenCCTV() / OpenTracking()
exports.cc_jobs:OpenEditor('police')
exports.cc_dispatch:GetAlerts / GetUnitsFor / SubscribeUnits / SetWaypoint
exports.cc_garage:Impound(plate)
```

## FAQ & Troubleshooting

#### F6 opens the citizen tablet instead of the police menu

You are not on duty. Go on duty at the station. Off duty, F6 belongs to the cc\_dispatch/00%20Overview\.md) citizen tablet.

#### The MDT map and dispatch alerts are missing

The live map, units and alerts come exclusively from cc\_dispatch. Start cc\_dispatch (before cc\_police).

#### I cannot search people / no serial numbers / no spike strips

These features require cc\_inventory/00%20Overview\.md). Other inventories (e.g. ox\_inventory) are not tested for search.

#### "Jail" does nothing

cc\_police has no prison of its own. Jailing from a charge requires cc\_prison/00%20Overview\.md); the person must be online, within `Config.Mdt.jail.radius` and cuffed (if `requireCuffed`).

#### Impounded vehicles just disappear

Without cc\_garage/00%20Overview\.md) an impounded vehicle is only deleted.

#### Locations are wrong / NPCs stand in walls

Default coordinates are for vanilla Mission Row. Adjust `Config.Places` or set locations in-game with cc\_jobs/00%20Overview\.md) (MDT: highest rank or ACE `cc_jobs.admin`). Make sure cc\_jobs starts before cc\_police.

#### A player stays cuffed after relogging

Intended with `Config.Cuffs.keepOnRelog = true` (until cc\_police restarts). Use `/uncuff [id]` (ACE `command.uncuff`) or `exports.cc_police:SetCuffed(src, false)`.

#### Evidence photo link is rejected

Only URLs starting with an entry in `Config.Mdt.evidenceHosts` are accepted. Add other hosts explicitly.

#### Uniforms do not apply

Uniforms require cc\_character/00%20Overview\.md). Clothing IDs are defaults and should be checked on your server.

#### Two police scripts

Do not run esx\_policejob, qb-policejob or any other police script alongside cc\_police.

#### Known limitations

* Escort attaches the person without a walking animation.
* Carrying downed players may conflict with cc\_ambulance lying poses; prefer the stretcher.
* Licenses can only be changed for online players.
* The MDT map has no "accept" button for calls.
* No radar gun.
* Addon vehicle models unknown to the client show their model name or nothing.

Still stuck? See Support.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://ccfivem.gitbook.io/ccfivem-docs/police-ems-and-justice/police-cc_police.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
