> For the complete documentation index, see [llms.txt](https://code-after-sex.gitbook.io/script-documentation/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://code-after-sex.gitbook.io/script-documentation/cas-police/configuration.md).

# Configuration

Every CAS Advanced Police & Law System setting: offices, ranks, duty, cuffs, hogtie, search, badge, garage, gallows, records book, warrants, bounties, jails, escapes and the penal code.

[Back to the guide](/script-documentation/cas-police/cas-advanced-police-and-law-system.md)

Every setting lives in five files under `config/`. Each file is commented line by line, and this page walks through all of them.

| File                   | What it holds                                                                                                                                                                                              |
| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `config/config.lua`    | Framework, language, notices, the radial menu, commands, keys, duty, permissions, cuffs, drag, hogtie, search, badge, the records book, warrants, bounty hunters, fines, alerts, webhooks, branding, items |
| `config/offices.lua`   | Statewide or regional, ranks, towns, offices (jobs, stations, desks, lockers), regions, the society                                                                                                        |
| `config/jails.lua`     | Jails and cells, work details, booking and transport, release, escape                                                                                                                                      |
| `config/gallows.lua`   | The public hanging and the four gallows                                                                                                                                                                    |
| `config/penalcode.lua` | How charges add up, and the penal code                                                                                                                                                                     |

Changes take effect when cas-police restarts. `/lawcoords` (admins) prints where you stand as `vector4(x, y, z, heading)`, ready to paste. Where a setting wants a `vector3`, use the first three numbers.

***

## config/config.lua

### General

| Setting            | Default       | What it does                                                                                                                                                                                                                               |
| ------------------ | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `Config.Framework` | `'auto'`      | Finds VORP or RSG by itself. Set `'vorp'` or `'rsg'` to force one.                                                                                                                                                                         |
| `Config.Locale`    | `'en'`        | Language of every text: `en`, `tr`, `de`, `fr`, `es`, `pt-br` (files in `locales/`). A word missing in a language falls back to English.                                                                                                   |
| `Config.Debug`     | `false`       | `true` = every call a client makes to the server is printed to the server console as `[cas-police] rpc <name> from <id>`. Use it while you set up or hunt a problem, then turn it off.                                                     |
| `Config.Notify`    | `'framework'` | How short messages show. `'framework'` = your framework's own notifications (see below). `'nui'` = the script's own Smoke & Brush notices at the top right. The in-world screens (cuffing, jail, alerts) always use the script's own look. |

With `'framework'`:

* **VORP:** every message is VORP's left notification. The title is the short heading and the text is the line plus its sub line. When CAS Notification is installed it takes VORP's notifications over, so they show in its look.
* **RSG:** every message is an ox\_lib notification (title, description, and the type error, success or inform). Without ox\_lib running, the script falls back to its own notices.

The server never shows a message itself: it sends every notice to the player's client, which shows it as set here.

`Config.NotifyStyle` tunes the framework notifications:

| Setting          | Default                                                 | What it does                                                           |
| ---------------- | ------------------------------------------------------- | ---------------------------------------------------------------------- |
| `duration`       | `5000`                                                  | Milliseconds a message stays on screen                                 |
| `vorpIcons.gold` | `{ 'generic_textures', 'tick', 'COLOR_WHITE' }`         | VORP: the picture beside good news (on duty, paid, booked)             |
| `vorpIcons.red`  | `{ 'menu_textures', 'menu_icon_alert', 'COLOR_RED' }`   | VORP: the picture beside a refusal or bad news (cuffed, jailed, fined) |
| `vorpIcons.dim`  | `{ 'menu_textures', 'menu_icon_alert', 'COLOR_WHITE' }` | VORP: the picture beside plain news                                    |

Each icon is a texture dictionary, a texture and a colour.

### The radial menu (`Config.Radial`)

When CAS Radial Menu (`cas-radialmenu`) runs, cas-police adds its own wheel to it by itself. There is nothing to set up in the radial menu. See [Gameplay](/script-documentation/cas-police/gameplay.md#the-radial-menu) for what is on the wheel.

| Setting           | Default | What it does                                                                                                                  |
| ----------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------- |
| `enabled`         | `true`  | Add the cas-police wheel to the radial menu                                                                                   |
| `parent`          | `'law'` | The wheel of the radial menu it goes into. `'law'` is "Law & Aid" in the radial menu's own config, `'main'` is its first tab. |
| `blockWhileBound` | `true`  | The radial menu stays shut while the player is cuffed or hogtied                                                              |

The radial menu also stays shut while a cas-police screen has the mouse or the keyboard (the book, the booking sheet, the badge, the alert form, the dispatch radio, the lockpick).

### 1. Commands (`Config.Commands`)

Rename any command here. An empty string `''` turns it off. See [Commands](/script-documentation/cas-police/commands.md) for who may use each one.

| Key          | Default      | Command                                                                                                 |
| ------------ | ------------ | ------------------------------------------------------------------------------------------------------- |
| `book`       | `'mdt'`      | Open the records book (bounty hunters get the hunter's board; admins open the board with `/mdt hunter`) |
| `desk`       | `'desk'`     | Open the marshal's desk (boss ranks, built-in society)                                                  |
| `jail`       | `'jail'`     | `/jail ID MINUTES [jail] [reason]`                                                                      |
| `unjail`     | `'unjail'`   | `/unjail ID`                                                                                            |
| `fine`       | `'fine'`     | `/fine ID AMOUNT [reason]`                                                                              |
| `alertLaw`   | `'alertlaw'` | Anyone: send for the law                                                                                |
| `dispatch`   | `'dispatch'` | Lawmen on duty: `/dispatch [text]`                                                                      |
| `clearAlert` | `'calert'`   | Lawmen: clear the last alert card                                                                       |
| `onDuty`     | `'onduty'`   | Go on duty                                                                                              |
| `offDuty`    | `'offduty'`  | Go off duty                                                                                             |
| `badge`      | `'badge'`    | `/badge` pins or takes off the badge, `/badge adjust` moves it                                          |
| `book_id`    | `'bookin'`   | `/bookin [ID]` opens the booking sheet for a prisoner next to you                                       |

When `Config.Book.openMode = 'item'`, the `book` command is not registered at all.

### 2. Keys (`Config.Keys`)

Keys are RedM control hashes. The key each one stands for is named in the comment.

| Key        | Default      | Key on the keyboard | Used for                                                                                 |
| ---------- | ------------ | ------------------- | ---------------------------------------------------------------------------------------- |
| `cuff`     | `0x3C0A40F2` | F6                  | Arrest or uncuff the person in front of you                                              |
| `drag`     | `0x80F28E95` | L                   | Take hold of, or let go of, a cuffed person                                              |
| `stopWork` | `0x760A9C6F` | G                   | A prisoner puts the work tools down                                                      |
| `struggle` | `0xD9D0E1C0` | SPACE               | Struggle out of a lasso                                                                  |
| `interact` | `0xCEFD9220` | E                   | Prompts: search, work, duty, sign out at the release guard                               |
| `pick`     | `0xE30CD707` | R                   | Pick the cuffs of a friend (hold, from behind)                                           |
| `desk`     | `0x760A9C6F` | G                   | Open the marshal's desk at a desk point                                                  |
| `locker`   | `0xE30CD707` | R                   | Open the office locker at a locker point                                                 |
| `detail`   | `0xB238FE0B` | TAB                 | A prisoner picks the next work detail                                                    |
| `ride`     | `0xC7B5340A` | ENTER               | Ride to the alert on the card (GPS)                                                      |
| `dispatch` | `0xF3830D8E` | J                   | Speak on the dispatch radio while an alert card shows                                    |
| `clear`    | `0x4AF4D473` | DEL                 | Clear the alert card                                                                     |
| `chain`    | `0x760A9C6F` | G                   | Chain the legs of a cuffed or hogtied man, or take the irons off                         |
| `garage`   | `0xD8F73058` | U                   | Outdoors at an office: the office garage. In the driver's seat of a law car: put it away |
| `stow`     | `0x7D326951` | R                   | Put a hogtied man across your horse (the game's own "place on mount" control)            |
| `unstow`   | `0xA1202C7B` | R                   | Take a hogtied man down from a horse                                                     |
| `unnoose`  | `0xE30CD707` | R                   | On the gallows: take the noose off (E puts it on and pulls the lever)                    |

**F6 and L.** In RedM, F6 opens photo mode and L opens the player menu. cas-police takes those two keys only while you can use the cuffs: a lawman on duty (any lawman when `requireForCuffs = false`), a bounty hunter when `hunterCanCuff = true`, and admins. Everyone else keeps F6 and L as normal. A lawman off duty keeps them too, with one exception: when he faces a player within cuffing distance, F6 tells him he is off duty instead of opening photo mode. To move the cuffs to other keys, change `cuff` and `drag` to other control hashes.

The keys inside the screens (ESC, TAB, ENTER, the arrows, SPACE on the lockpick dial) are fixed.

### 3. Duty (`Config.Duty`)

Duty is the gate for the cuffs, the badge, the book and the jail commands.

| Setting           | Default | What it does                                                                                                                                                                                                                              |
| ----------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `requireForCuffs` | `true`  | Lawmen cannot cuff or drag off duty                                                                                                                                                                                                       |
| `requireForBadge` | `true`  | The badge cannot be pinned off duty, and going off duty takes it off                                                                                                                                                                      |
| `requireForBook`  | `true`  | The records book will not open off duty (the hunter's board has no duty)                                                                                                                                                                  |
| `requireForJail`  | `true`  | `/jail`, `/unjail` and the booking sheet need duty                                                                                                                                                                                        |
| `stationsEnabled` | `true`  | `true` = a lawman goes on duty only inside a station of his own office (hold E at the prompt, or `/onduty` there). `false` = `/onduty` works anywhere and the station prompt is hidden. An office with no stations goes on duty anywhere. |
| `onAtLogin`       | `false` | `true` = a lawman who logged out on duty is put back on duty when he logs in, wherever he is (he already signed on at a station before he left). Works on VORP and RSG. `false` = every lawman logs in off duty.                          |
| `autoOffMinutes`  | `0`     | `0` = never. Otherwise a lawman who has not moved for this many minutes is taken off duty.                                                                                                                                                |

Going off duty works anywhere. A lawman who loses his law job is taken off duty at once.

### 4. Ranks and permissions (`Config.Permissions`, `Config.Admins`)

The ranks of each office live in `config/offices.lua`. This section decides which grade may do what.

| Setting                  | Default   | What it does                                                                        |
| ------------------------ | --------- | ----------------------------------------------------------------------------------- |
| `allGradesEqual`         | `true`    | `true` = every rank may do every action. `false` = use the lists below.             |
| `default`                | see below | The lowest grade for each action, for any office without a list of its own          |
| `<office key> = { ... }` | not set   | A list for one office, named by its key in `Config.Offices` (for example `marshal`) |

The grade is the framework job grade of the player. An action left out of a list is open to every grade.

| Action         | Default grade | What it gates                                                               |
| -------------- | ------------- | --------------------------------------------------------------------------- |
| `jail`         | 0             | `/jail`, `/unjail`, `/bookin` and the booking sheet                         |
| `fine`         | 0             | `/fine` and "Fine him" in the book                                          |
| `issueWarrant` | 1             | Issuing a warrant, from a report or a new entry                             |
| `clearWarrant` | 2             | Clearing (dropping) a warrant. Serving one is open to every lawman on duty. |
| `mugshot`      | 0             | Adding or removing the photograph link of a citizen                         |
| `editProfile`  | 0             | Writing the description of a citizen                                        |
| `hang`         | 3             | Putting the noose on a man and pulling the lever of the gallows             |

Example, with ranks for one office:

```lua
Config.Permissions = {
    allGradesEqual = false,
    default = { jail = 0, fine = 0, issueWarrant = 1, clearWarrant = 2, mugshot = 0, editProfile = 0 },
    marshal = { jail = 0, fine = 0, issueWarrant = 2, clearWarrant = 3, mugshot = 1, editProfile = 1 },
}
```

| Setting           | Default             | What it does                                                  |
| ----------------- | ------------------- | ------------------------------------------------------------- |
| `Config.Admins`   | empty               | Steam hex ids (`'steam:110000112345678'`) that count as admin |
| `Config.AdminAce` | `'caspolice.admin'` | The ace that counts as admin                                  |

Framework admins count as admins too (VORP group `admin`, `superadmin` or `god`; RSG permission `admin` or `god`). Admins open the records book, the marshal's desk and (with `/mdt hunter`) the hunter's board without a law job, and pass every rank and duty check.

### 5. Cuffs (`Config.Cuff`)

| Setting                | Default       | What it does                                                                                                                                                              |
| ---------------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `maxDistance`          | `2.5`         | How close (meters) the suspect must stand in front of you. The game's arrest walks in from about 2 meters.                                                                |
| `requireItem`          | `false`       | `true` = the lawman needs a `requiredItem` in his satchel to cuff                                                                                                         |
| `requiredItem`         | `'handcuffs'` | The item for `requireItem`                                                                                                                                                |
| `consumeItem`          | `false`       | With `requireItem = true`: the handcuffs leave the lawman's satchel when he cuffs and come back when he uncuffs                                                           |
| `hunterCanCuff`        | `true`        | Bounty hunters may cuff and drag too                                                                                                                                      |
| `anyoneCanUncuff`      | `false`       | `false` = only lawmen (and the hunter who cuffed him) take the cuffs off. `true` = anyone can, with F6.                                                                   |
| `arrest.drawSidearm`   | `true`        | `true` = an empty-handed lawman draws his revolver or pistol for the arrest, if he carries one                                                                            |
| `arrest.walkIn`        | `true`        | `true` = a lawman standing farther off than the arrest starts (about 2 meters) walks up to it first. `false` = the move starts at once and puts him at its starting spot. |
| `arrest.groundSeconds` | `1.5`         | A suspect who is hogtied or down is cuffed where he lies, after this many seconds                                                                                         |
| `prop`                 | see below     | The handcuff prop on the wrists                                                                                                                                           |

The arrest itself is the game's: Rockstar's paired arrest clips (`mech_melee@pistol@...` and `mech_melee@rifle@...`, `arrest_enter_from_<side>_aiming_v1`). Their lengths and the lawman's walk-in are measured from the game files and kept in `shared/arrest.lua`; there is nothing to set for them.

The prop:

| Setting         | Default                         | What it does                                                                                                                                                                            |
| --------------- | ------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `prop.enabled`  | `true`                          | Show the handcuff prop                                                                                                                                                                  |
| `prop.model`    | `'p_handcuffs02x'`              | The prop model: the game's closed cuffs, 30 cm (`p_handcuffs01x` is an open pair lying flat, 90 cm wide)                                                                                |
| `prop.boneName` | `'hands'`                       | `'hands'` = pinned to the right hand, midway between the two wrists and lying across them (measured on the cuffed pose), so it moves with the hands. Or the name of one bone to sit on. |
| `prop.offset`   | `{ x = 0.0, y = 0.0, z = 0.0 }` | Move it on 3 axes (meters; for `'hands'`: right, ahead, up)                                                                                                                             |
| `prop.rot`      | `{ x = 0.0, y = 0.0, z = 0.0 }` | Turn it on 3 axes (degrees)                                                                                                                                                             |

#### What a cuffed suspect may do (`Config.CuffedRules`)

| Setting        | Default | What it does                                                                                                                                               |
| -------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `canRun`       | `false` | `false` = no sprinting, held to a walk                                                                                                                     |
| `canMount`     | `false` | `false` = cannot get on a horse                                                                                                                            |
| `canBeHogtied` | `true`  | `true` = others can still lasso and hogtie him                                                                                                             |
| `canFight`     | `false` | `true` = he may still use the attack, aim and melee keys, with his fists only (he stays unarmed and the weapon wheel stays locked). `false` = no fighting. |
| `canUseItems`  | `false` | `false` = the satchel keys are blocked. On VORP the inventory is also locked while cuffed in any case.                                                     |

A cuffed man can always be searched, and jumping and crouching are blocked.

#### Picking the cuffs (`Config.Cuff.Lockpick`)

| Setting            | Default        | What it does                                                                                                                                       |
| ------------------ | -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| `enabled`          | `true`         | A free player may pick the cuffs of a friend                                                                                                       |
| `item`             | `'lockpick'`   | The item he needs                                                                                                                                  |
| `minigame`         | `'skillcheck'` | `'skillcheck'` = the dial (press SPACE when the needle sits in the red). `'animation'` = only a timed animation, the lock opens if he stays close. |
| `difficulty`       | `'medium'`     | `'easy'`, `'medium'` or `'hard'`: how fast the needle turns and how wide the red is                                                                |
| `pins`             | `3`            | Pins to set on the dial                                                                                                                            |
| `maxDistance`      | `2.0`          | How close he must stand                                                                                                                            |
| `requireBehind`    | `true`         | He must stand behind the cuffed man, not in front                                                                                                  |
| `cooldownSeconds`  | `120`          | Rest after every try, good or bad                                                                                                                  |
| `breakChance`      | `50`           | Percent chance the pick breaks on a failed try                                                                                                     |
| `animationSeconds` | `12`           | Length of the animation for `minigame = 'animation'`                                                                                               |
| `alertOfficer`     | `true`         | The lawman who cuffed the man hears that the lock was picked                                                                                       |

Lawmen cannot pick cuffs. They take them off with F6.

### 6. Drag and escort (`Config.Drag`)

| Setting       | Default                           | What it does                                         |
| ------------- | --------------------------------- | ---------------------------------------------------- |
| `maxDistance` | `2.0`                             | How close the cuffed man must be to take hold of him |
| `offset`      | `{ x = 0.32, y = 0.55, z = 0.0 }` | Where the prisoner walks, beside and in front of you |

The prisoner always faces and walks the way you walk. The hold lets go when you mount a horse or get on a wagon, or when you are more than 12 meters apart.

### 7. Hogtie (`Config.Hogtie`)

Hogtie works for every player, not only lawmen.

| Setting                             | Default | What it does                                                                                                                                                                                        |
| ----------------------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `serverWide`                        | `true`  | `true` = the rules below apply to every hogtied player. `false` = the script leaves lassos to the game: no rules, and a hogtied (not cuffed) player can no longer be searched or handed to the law. |
| `regularLasso.canBreakFree`         | `true`  | A regular lasso gives way to struggling                                                                                                                                                             |
| `regularLasso.breakFreeTimeSec`     | `30`    | Seconds of struggling to work loose                                                                                                                                                                 |
| `reinforcedLasso.canBreakFree`      | `false` | `false` = no struggling while the captor is close                                                                                                                                                   |
| `reinforcedLasso.breakFreeDistance` | `91.0`  | Meters (about 100 yards). Once the captor is this far away, the captive can struggle.                                                                                                               |
| `reinforcedLasso.breakFreeTimeSec`  | `45`    | Seconds of struggling once he may                                                                                                                                                                   |
| `stow.enabled`                      | `true`  | Anyone may put a hogtied man across his horse (R) and take him down again                                                                                                                           |
| `stow.horseRange`                   | `4.0`   | Meters the horse may stand from you                                                                                                                                                                 |

The rule: a captive may struggle when `canBreakFree = true`, or when the captor is past `breakFreeDistance`. If the captor cannot be found (he logged out, or it was not a player), the captive may struggle. The game's own break free is turned off, and struggling is SPACE.

If you set `canBreakFree = false` on the regular lasso, give it a `breakFreeDistance` too, or a regular lasso can never be struggled out of.

### 8. Search (`Config.Search`)

Search opens the target's inventory to the searcher.

| Setting        | Default                                                                          | What it does                                                                                                                                                                                                                                                                                                                          |
| -------------- | -------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `countyWide`   | `true`                                                                           | `true` = anyone can search a cuffed, hogtied or downed player. `false` = only lawmen and admins.                                                                                                                                                                                                                                      |
| `maxDistance`  | `2.5`                                                                            | How close the searcher must stand                                                                                                                                                                                                                                                                                                     |
| `blockMoney`   | `true`                                                                           | `true` = the money items of both frameworks can never be taken, on top of `blockedItems`: `cash`, `dollar`, `dollars`, `cent`, `money`, `gold`, `goldbar`, `gold_bar`, `bloodmoney`, `blood_money`, `money_clip`, `blood_money_clip`. The framework cash itself lives outside the inventory, so a search never reaches it either way. |
| `blockedItems` | `{ 'cash', 'dollars', 'gold_bar', 'money_clip', 'blood_money_clip', 'goldbar' }` | Items that can never be taken in a search. Add any other item that stands for money or that must stay with the player.                                                                                                                                                                                                                |
| `logRemovals`  | `true`                                                                           | Each item taken is sent to the `searchRemoval` webhook                                                                                                                                                                                                                                                                                |
| `watchSeconds` | `120`                                                                            | How long a search is watched for taken items                                                                                                                                                                                                                                                                                          |

How blocked items stay put: on VORP the full list (`blockedItems`, plus the money items when `blockMoney = true`) is handed to the inventory as its blacklist. On both frameworks, while the search is watched, a blocked item that leaves the target is taken back from the searcher and returned, and the searcher is told it cannot be taken.

### 9. Badge (`Config.Badge`)

| Setting         | Default                            | What it does                                                                                                                                        |
| --------------- | ---------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| `model`         | `'s_badgesherif01x'`               | The badge prop. An office can set its own with `badge` in `config/offices.lua`.                                                                     |
| `boneName`      | `'PH_L_Breast'`                    | The bone it is pinned to (others: `'SKEL_L_Clavicle'`, `'CP_Chest'`)                                                                                |
| `offset`        | `{ x = 0.002, y = 0.14, z = 0.0 }` | The starting position on 3 axes (meters from the bone): flat on the left breast of the coat                                                         |
| `rot`           | `{ x = 11.2, y = -85.8, z = 9.3 }` | The starting rotation on 3 axes (tilt, roll, spin, degrees). Set your own on the `/badge adjust` screen and copy the numbers here.                  |
| `adjustable`    | `true`                             | Players may move their badge with `/badge adjust`                                                                                                   |
| `savePerPlayer` | `true`                             | Each character's placement is saved and comes back next shift                                                                                       |
| `maxMove`       | `0.12`                             | Meters a player may move it away from the starting position on each axis (turning goes from -180 to 180 degrees)                                    |
| `item`          | `''`                               | `''` = command only. Or an item name: using that item pins or takes off the badge. The item is not created for you; add it to your inventory first. |
| `autoOnDuty`    | `true`                             | Pin the badge when going on duty and take it off when going off                                                                                     |

### Leg irons (`Config.Chains`)

| Setting        | Default | What it does                                 |
| -------------- | ------- | -------------------------------------------- |
| `enabled`      | `true`  | Lawmen put leg irons on with G               |
| `needsBound`   | `true`  | Only a cuffed or hogtied man is put in irons |
| `seconds`      | `2.5`   | How long the lawman works at the ankles      |
| `drawDistance` | `80.0`  | Meters the chain is drawn on others          |

A jail with `chainLegs = true` in `config/jails.lua` (Sisika by default) keeps its prisoners in irons while they serve.

### 9b. The office garage (`Config.Garage`)

| Setting        | Default           | What it does                                                                                                                                                           |
| -------------- | ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `enabled`      | `true`            | The garage is open                                                                                                                                                     |
| `needsDuty`    | `true`            | Only lawmen on duty take cars out                                                                                                                                      |
| `radius`       | `35.0`            | Meters from an office point where U opens the garage (outdoors). The points are the office's `garages` in `config/offices.lua`, or its duty stations when it has none. |
| `roadSide`     | `2.2`             | Meters from the middle of the road to where a car is set down                                                                                                          |
| `onePerLawman` | `true`            | One car out per lawman at a time                                                                                                                                       |
| `leaveOnQuit`  | `true`            | The car goes when its lawman leaves the server                                                                                                                         |
| `fullTank`     | `true`            | A car taken out has a full tank (cas-car1910)                                                                                                                          |
| `plate`        | `'LAW %03d'`      | The plate text; `%03d` is the car's number                                                                                                                             |
| `cars`         | the 4 police cars | `{ model, label, seats, minGrade }` per car. `minGrade` is the lowest rank grade that may take it.                                                                     |

The cars come from cas-carpack-police and are driven by cas-car1910 (siren, bell, beacon, the van's cell). To set a car down at a fixed spot instead of the nearest road, give the office `garages = { vector3(...) }` points and stand there.

### Jail cell doors (`Config.CellDoors`, in `config/jails.lua`)

| Setting         | Default  | What it does                                                                                    |
| --------------- | -------- | ----------------------------------------------------------------------------------------------- |
| `enabled`       | `true`   | The cells use the game's own doors (the door system)                                            |
| `lockedAtStart` | `true`   | Every cell door is locked when the server starts                                                |
| `list`          | 20 doors | `{ hash, coords, town }` of every cell door of the eight law offices, from the game's door list |

### The public hanging (`Config.Hanging`, in `config/gallows.lua`)

| Setting        | Default | What it does                                                                                                 |
| -------------- | ------- | ------------------------------------------------------------------------------------------------------------ |
| `enabled`      | `true`  | Lawmen may hang a cuffed man at the gallows                                                                  |
| `requireDuty`  | `true`  | The lawman must be on duty (admins never need to be)                                                         |
| `cutFrees`     | `true`  | A rope shot through before the drop sets the man loose and takes his cuffs off. `false` = he stays in cuffs. |
| `announce`     | `150.0` | Players this close are told who hangs and for what. `0` = nobody is told.                                    |
| `nooseMinutes` | `10`    | A noose nobody pulls the lever on comes off after this many minutes                                          |
| `bodySeconds`  | `600`   | The gallows are cleared this long after the drop at the latest                                               |
| `drawDistance` | `150.0` | Meters a hanging is shown to other players                                                                   |
| `nooseRange`   | `3.0`   | How near the trapdoor the lawman and the prisoner must stand                                                 |
| `leverRange`   | `1.75`  | How near the lever the lawman must stand (the game's own radius)                                             |

`Config.Gallows` holds the four gallows: the map's trapdoor (model and position) and lever, the beam the rope hangs from, the spot on the trapdoor, and the rope and drop lengths. Every number is the game's own, from its public hanging. Change them only if your map moved the gallows.

### 10. The records book (`Config.Book`)

| Setting                | Default                                                                        | What it does                                                                                                               |
| ---------------------- | ------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------- |
| `openMode`             | `'both'`                                                                       | `'command'` (`/mdt`), `'item'` (the `item` below) or `'both'`                                                              |
| `item`                 | `'mdt_book'`                                                                   | The item that opens the book                                                                                               |
| `admins`               | empty                                                                          | Extra steam hex ids that count as admin (with `Config.Admins`)                                                             |
| `penalCodeEditors`     | empty                                                                          | Steam hex ids that may edit the penal code inside the book. Admins always may.                                             |
| `gameYear`             | `1899`                                                                         | The year printed on records and on the public feed. `false` = the real year.                                               |
| `limits.homeRecent`    | `6`                                                                            | Recent reports on the home page                                                                                            |
| `limits.searchResults` | `100`                                                                          | Most results in the citizen list                                                                                           |
| `limits.reportsInTab`  | `15`                                                                           | Reports listed in the Reports tab                                                                                          |
| `homeLedger`           | `'boss'`                                                                       | Who sees the office ledger on the home page: `'boss'` (boss ranks) or `'all'`                                              |
| `photoHosts`           | `{ 'cdn.discordapp.com', 'media.discordapp.net', 'i.imgur.com', 'imgur.com' }` | Picture hosts allowed for citizen photographs. Links must start with `https://`. A subdomain of a listed host also passes. |
| `draftDays`            | `7`                                                                            | An unfiled report draft is thrown away after this many days                                                                |

### 11. Warrants and the public feed (`Config.Warrants`)

| Setting                | Default | What it does                                                                                                                                                                          |
| ---------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `toBountyDays`         | `3`     | A warrant nobody serves in this many days turns into a bounty                                                                                                                         |
| `checkIntervalMinutes` | `60`    | How often the script checks for warrants to turn (the first check runs a few seconds after start)                                                                                     |
| `publicFeed.enabled`   | `true`  | Post warrants and bounties to a public Discord channel as wanted notices, and delete each notice when the warrant is served or cleared                                                |
| `publicFeed.url`       | `''`    | The public channel webhook for both notices. A post goes to the `publicWarrant` or `publicBounty` URL in `Config.Webhooks` first, then to this URL, then to `Config.Webhooks.master`. |
| `staffLog.enabled`     | `true`  | Post a plain line to a staff channel for every warrant issued, served or cleared. These are never deleted.                                                                            |
| `staffLog.url`         | `''`    | The staff channel webhook. Empty = no staff log.                                                                                                                                      |

### 12. Bounty hunters (`Config.BountyHunter`)

| Setting             | Default              | What it does                                                                                                                               |
| ------------------- | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| `jobs`              | `{ 'bountyhunter' }` | Framework jobs that are bounty hunters. They get the hunter's board instead of the records book.                                           |
| `warrantAmount`     | `50`                 | What a fresh warrant pays when turned in                                                                                                   |
| `bountyAmount`      | `150`                | What a bounty pays when turned in                                                                                                          |
| `dailyMultiplier`   | `0`                  | Added for each full day since the warrant became a bounty. Payout = `bountyAmount + days x dailyMultiplier`.                               |
| `lockClaims`        | `true`               | One hunter to a bounty                                                                                                                     |
| `claimableStatuses` | `{ 'bounty' }`       | What hunters may claim. Add `'warrant'` to let them take fresh warrants too.                                                               |
| `paidFromLedger`    | `true`               | The payout leaves the ledger of the office of the lawman who takes the prisoner. `false` = the hunter is paid without touching any ledger. |
| `handOverDistance`  | `10.0`               | The prisoner and the lawman must be this close to the hunter when he files                                                                 |
| `claimHours`        | `48`                 | A claim nobody files drops back to the board after this many hours. `0` = never.                                                           |
| `alertOnNew`        | `true`               | Hunters get a notice for every new warrant and every new bounty                                                                            |

A hunter holds one claim at a time.

### 13. Fines and the ledger (`Config.Fines`)

| Setting                | Default | What it does                                                                                                                                                                                                                             |
| ---------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `toLedger`             | `true`  | `true` = fine money goes into the office ledger. `false` = it goes into the lawman's pocket.                                                                                                                                             |
| `currency`             | `0`     | `0` = dollars. `1` = gold on VORP, blood money on RSG. `2` = rol on VORP (cash on RSG).                                                                                                                                                  |
| `allowNegativeBalance` | `true`  | `true` = the fine is taken even if he cannot pay all of it. On VORP the balance can go below zero. RSG never lets cash go below zero, so it takes the cash and the rest from the bank. `false` = the fine fails with "Not enough money". |
| `maxAmount`            | `5000`  | The largest fine                                                                                                                                                                                                                         |
| `maxDistance`          | `15.0`  | The offender must be this close for a fine. `0` = anywhere.                                                                                                                                                                              |

### 14. Alerts and dispatch (`Config.Alerts`)

| Setting            | Default                                                             | What it does                                                                                                                     |
| ------------------ | ------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `alertCooldownSec` | `60`                                                                | Seconds between two alerts from the same character                                                                               |
| `showNotification` | `true`                                                              | Lawmen on duty get an alert card on screen                                                                                       |
| `showBlip`         | `true`                                                              | A pulsing map blip at the alert spot                                                                                             |
| `blipSeconds`      | `300`                                                               | How long the blip stays                                                                                                          |
| `dispatchEnabled`  | `true`                                                              | Master switch of the dispatch radio between lawmen on duty                                                                       |
| `kinds`            | `{ 'robbery', 'shooting', 'horsetheft', 'fight', 'fire', 'other' }` | What a citizen can pick on the alert form. For a new kind, add a `kind_<name>` line to the language files, or the raw key shows. |
| `maxLength`        | `80`                                                                | The most letters in an alert                                                                                                     |
| `regionOnly`       | `true`                                                              | Regional servers: only the office whose region holds the alert spot hears it. An alert outside every region goes to all.         |
| `fromRobberyPack`  | `false`                                                             | Also turn CAS Robbery Pack alerts into law alerts (the Robbery Pack sends its own already)                                       |
| `sound`            | `true`                                                              | A short sound with each new alert                                                                                                |

The script itself also raises alerts: a prison break (when `Config.Escape.alertLaw = true`) and, on RSG, the radial menu's Emergency Button ("Lawman down").

### 15. Discord webhooks (`Config.Webhooks`)

| Setting                  | Default                    | What it does                                                |
| ------------------------ | -------------------------- | ----------------------------------------------------------- |
| `master`                 | `''`                       | The webhook used by every action that has no URL of its own |
| `name`                   | `'County Marshal Service'` | The name the posts are made under                           |
| `actions.<name>.enabled` | see below                  | Turn one kind of post on or off                             |
| `actions.<name>.url`     | `''`                       | Its own webhook. Empty = `master`.                          |

Actions: `reportFiled`, `warrantIssued`, `warrantCleared`, `manualJail`, `manualUnjail`, `fineIssued`, `searchRemoval`, `bountyTurnin`, `alertLaw`, `dispatch` (off by default), `society`, `garage`, `hanging`, `escape`, `penalCode`, `publicWarrant`, `publicBounty`. What each one posts is in [Developers](/script-documentation/cas-police/developers.md#discord-webhooks).

The two public actions look one step further: `publicWarrant` and `publicBounty` use their own URL, then `Config.Warrants.publicFeed.url`, then `master`. Set one of the first two to your public channel. Left empty, the notices post to `master`, which is usually your staff log.

### 16. Branding (`Config.Branding`)

| Setting      | Default                    | What it does                                                                                                                     |
| ------------ | -------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `systemName` | `'County Marshal Service'` | The name of the law service, on the book, notices and webhooks                                                                   |
| `bookTitle`  | `'Territorial Justice'`    | The title of the records book                                                                                                    |
| `sealImage`  | `''`                       | `''` = the built-in seal. Or a picture link, or a file in the resource such as `'nui://cas-police/web/dist/img/your_seal.webp'`. |
| `feedColor`  | `9050642`                  | The default Discord embed colour (a decimal number). Offices can set their own.                                                  |
| `feedLogo`   | `''`                       | A picture link shown in the footer of the public feed notices                                                                    |

### 17. Items (`Config.Items`, `Config.RSGRegisterItems`)

`Config.Items` lists the three items (`handcuffs`, `lockpick`, `mdt_book`) with label, weight, limit, usable and description. On RSG, with `Config.RSGRegisterItems = true`, cas-police adds the missing ones to rsg-core at start. On VORP this list changes nothing: run `install/items_vorp.sql` instead.

***

## config/offices.lua

### Statewide or regional (`Config.Structure`)

```lua
Config.Structure = { mode = 'statewide' }   -- or 'regional'
```

* **`'statewide'`**: one office covers the whole map. Every lawman on duty hears every alert and shares one dispatch radio. On RSG, any job whose type is `leo` in rsg-core belongs to this office, even when it is not in its `jobs` list.
* **`'regional'`**: each office has its own region (see `Config.Regions`). An alert goes to the office whose region holds the spot (with `Config.Alerts.regionOnly`), and each office has its own dispatch radio.

In both modes every office keeps its own reports, patrol notes, captures, roll, locker, ranks, stations, default jail and (with `ledgerMode = 'separate'`) ledger. Warrants, bounties and citizen files are shared by all offices, so the record follows the offender across the map.

To go regional: set `mode = 'regional'`, replace `Config.Offices` with the regional block that is commented out in the file (or your own), and give each office a `region` that is a key of `Config.Regions`.

### Default ranks (`Config.DefaultRanks`)

The ranks an office uses when it has no `ranks` of its own.

| Grade | Name         | Pay | Boss |
| ----- | ------------ | --- | ---- |
| 0     | Recruit      | 4   |      |
| 1     | Deputy       | 6   |      |
| 2     | Deputy II    | 8   |      |
| 3     | Marshal      | 10  | yes  |
| 4     | Head Marshal | 12  | yes  |

* **grade** is the framework job grade. A player's rank is the highest row whose grade is at or below his job grade.
* **name** is shown in the book, on notices and on the roll.
* **pay** is dollars for each day on duty, paid by the pay roll (see the society below).
* **boss = true** may swear in, dismiss, change ranks and pay, and opens the marshal's desk.

A rank also counts as boss when its name is in `Config.Society.builtin.bossRanks`, or (RSG) when its rsg-core grade has `isboss`.

**RSG:** an office with no `ranks` uses the grades of its first job that exists in `rsg-core/shared/jobs.lua`, with the grade names and `isboss` from there, and pay 0. rsg-core pays its own wages, so the pay roll adds nothing on top. Set `ranks` on the office if you want cas-police to pay per day on duty instead.

### Towns (`Config.Towns`)

The sheriff office points of the base game: Valentine, Strawberry, Blackwater, Rhodes, Saint Denis, Tumbleweed, Armadillo and Annesburg. The offices below use them for stations, desks and lockers (`TOWNS.valentine.station`). The script also uses them for place names: an alert or report spot within 900 meters of a town takes its name, anything farther reads "Out in the wild". `TOWNS` is local to this file, so use it only inside `offices.lua`.

### Offices (`Config.Offices`)

Each office is a block with a key. The key (for example `marshal`) is the office id used by `Config.Permissions`, the ledger and the exports.

| Field      | Example                         | What it does                                                                                                                                                         |
| ---------- | ------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `label`    | `'Marshals Office'`             | The name shown everywhere                                                                                                                                            |
| `jobs`     | `{ 'marshal', 'sheriff', ... }` | Framework job names that belong to this office (any letter case)                                                                                                     |
| `hireJob`  | `'sheriff'`                     | The job a new man gets when the desk swears him in. On RSG it must exist in `rsg-core/shared/jobs.lua`; if it does not, the first job of `jobs` that exists is used. |
| `region`   | `'state'`                       | A key of `Config.Regions` (regional mode only). `'state'` covers the whole map.                                                                                      |
| `jail`     | `'sisika'`                      | The default jail of this office (a key of `Config.Jail.locations`)                                                                                                   |
| `badge`    | `'s_badgeusmarshal01x'`         | The badge model of this office                                                                                                                                       |
| `color`    | `9050642`                       | The Discord embed colour of this office's public notices                                                                                                             |
| `ranks`    | `nil`                           | Its own rank list, or `nil` for `Config.DefaultRanks` (RSG: the job grades)                                                                                          |
| `stations` | list                            | Duty stations: `{ coords = vector3, radius = 6.0, label = 'Valentine' }`                                                                                             |
| `desks`    | list                            | Where the marshal's desk opens: `{ coords = vector3, radius = 3.0 }`. Empty = `/desk` anywhere.                                                                      |
| `locker`   | table                           | The office locker: `{ slots = 50, weightKg = 100, coords = { vector3, ... }, radius = 4.0 }`                                                                         |

The default statewide office `marshal` lists the jobs `marshal`, `sheriff`, `deputy`, `police`, `lawman`, `vallaw`, `rholaw`, `blklaw`, `strlaw` and `stdenlaw`, has a duty station in all eight towns, desks and lockers in Blackwater, Valentine and Saint Denis, and books into `sisika`.

#### Example: add an office

Copy a block, rename the key, set the jobs, region and jail. This one is for a regional server:

```lua
Config.Offices = {
    -- ... your other offices ...
    naso = {
        label    = 'New Austin Sheriff Office',
        jobs     = { 'naso' },
        hireJob  = 'naso',
        region   = 'NewAustin',
        jail     = 'tumbleweed',
        badge    = 's_badgesherif01x',
        color    = 13408614,
        stations = {
            { coords = TOWNS.tumbleweed.station, radius = 6.0, label = 'Tumbleweed' },
            { coords = TOWNS.armadillo.station,  radius = 6.0, label = 'Armadillo' },
        },
        desks  = { { coords = TOWNS.armadillo.station, radius = 3.0 } },
        locker = { slots = 40, weightKg = 80, coords = { TOWNS.armadillo.station }, radius = 4.0 },
    },
}
```

#### Example: a rank list for one office

```lua
    naso = {
        -- ... the fields above ...
        ranks = {
            { grade = 0, name = 'Deputy',        pay = 5 },
            { grade = 1, name = 'Senior Deputy', pay = 7 },
            { grade = 2, name = 'Undersheriff',  pay = 9,  boss = true },
            { grade = 3, name = 'Sheriff',       pay = 12, boss = true },
        },
    },
```

The grades must match the job grades your framework gives.

#### Example: add a duty station

Stand where the station should be, type `/lawcoords`, and add a line to the office's `stations`:

```lua
        stations = {
            { coords = TOWNS.valentine.station, radius = 6.0, label = 'Valentine' },
            { coords = vector3(0.0, 0.0, 0.0),  radius = 6.0, label = 'My new post' },   -- your point from /lawcoords
        },
```

### Regions (`Config.Regions`)

Used only in regional mode. Each region is a polygon of x / y points (z is ignored). Add or move points to grow or shrink it.

```lua
Config.Regions = {
    NewAustin   = { polygon = { vector3(-6200.0, -4000.0, 0.0), vector3(-2000.0, -4000.0, 0.0), vector3(-2000.0, -1600.0, 0.0), vector3(-6200.0, -1600.0, 0.0) } },
    Lemoyne     = { polygon = { vector3(700.0, -2400.0, 0.0), vector3(3600.0, -2400.0, 0.0), vector3(3600.0, -200.0, 0.0), vector3(700.0, -200.0, 0.0) } },
    GreatPlains = { polygon = { vector3(-2000.0, -2400.0, 0.0), vector3(700.0, -2400.0, 0.0), vector3(700.0, -900.0, 0.0), vector3(-2000.0, -900.0, 0.0) } },
}
```

The shipped regions are rough boxes. Walk your borders with `/lawcoords` and paste the points in order around the region.

### The society (`Config.Society`)

| Setting | Default     | What it does                                                                          |
| ------- | ----------- | ------------------------------------------------------------------------------------- |
| `mode`  | `'builtin'` | `'builtin'` = this script's society (the marshal's desk). `'syn'` = use syn\_society. |

**Built-in** (`Config.Society.builtin`):

| Setting            | Default                         | What it does                                                                                                                                          |
| ------------------ | ------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| `bossRanks`        | `{ 'Marshal', 'Head Marshal' }` | Rank names that count as boss (besides `boss = true` on a rank)                                                                                       |
| `storageSlots`     | `50`                            | Locker slots for an office whose `locker` sets none                                                                                                   |
| `storageMaxWeight` | `100000`                        | Locker weight in grams for an office whose `locker` sets no `weightKg`                                                                                |
| `ledgerMode`       | `'separate'`                    | `'separate'` = one ledger per office. `'shared'` = one ledger for all.                                                                                |
| `emptyBehavior`    | `'stop'`                        | `'stop'` = nothing is paid out when the ledger cannot cover it (pay roll, bounty payouts, withdrawals). `'overdraft'` = the ledger may go below zero. |
| `payEveryDays`     | `7`                             | The pay roll is paid every this many days                                                                                                             |
| `payHour`          | `18`                            | ...at or after this hour of the server clock                                                                                                          |
| `minDutyMinutes`   | `30`                            | A day counts as a day on duty after this many minutes on duty that day                                                                                |
| `startBalance`     | `0`                             | What a new ledger starts with                                                                                                                         |
| `deskNeedsDuty`    | `false`                         | `true` = the boss must be on duty to open the desk                                                                                                    |
| `lockerNeedsDuty`  | `true`                          | `true` = members open the locker only on duty                                                                                                         |

**The pay roll.** Every minute a lawman spends on duty is counted per calendar day. A day with at least `minDutyMinutes` counts as one day on duty. Every `payEveryDays` days, at or after `payHour`, each member is paid his days on duty times his pay (the pay of his rank, or the pay the boss set for him at the desk). The money leaves the office ledger. With `emptyBehavior = 'stop'` and a ledger that cannot cover the whole roll, nobody is paid and the roll waits until the ledger is fed. A member who is offline on pay day is paid when he next logs in. A boss can also pay the roll early with "Pay the roll now" on the ledger page.

Example: a Deputy with pay 6 who spent 4 days on duty in the cycle is paid $24.

**syn\_society** (`Config.Society.syn`):

| Setting       | Default            | What it does                                             |
| ------------- | ------------------ | -------------------------------------------------------- |
| `ledgerTable` | `'society_ledger'` | syn\_society's ledger table (columns `job` and `ledger`) |

With `mode = 'syn'`: the marshal's desk is off (use syn\_society's own boss menu), cas-police pays nothing on its own pay roll, and fines and bounty payouts go into and out of the syn\_society ledger of the office's `hireJob` (or its first job). The office lockers still work.

***

## config/jails.lua

### The jail (`Config.Jail`)

| Setting             | Default                                                                           | What it does                                                                                                                                |
| ------------------- | --------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| `primary`           | `'sisika'`                                                                        | The jail used when an office names none (and for exports)                                                                                   |
| `invincible`        | `true`                                                                            | Prisoners cannot be hurt inside, until an escape stands                                                                                     |
| `cuffOnTransport`   | `true`                                                                            | A prisoner handed to a transport guard is cuffed for the ride (if he is not cuffed already). Every booking takes the cuffs off in the cell. |
| `minMinutes`        | `1`                                                                               | The shortest sentence                                                                                                                       |
| `maxMinutes`        | `240`                                                                             | The longest sentence (also the cap for jail time in the penal code editor)                                                                  |
| `timeCountsOffline` | `true`                                                                            | `true` = the clock keeps running while the prisoner is away. `false` = it pauses.                                                           |
| `takeWeapons`       | `true`                                                                            | Holster the weapon and lock the weapon wheel while jailed                                                                                   |
| `workSeconds`       | `12`                                                                              | How long one spot of work takes                                                                                                             |
| `minLeftSeconds`    | `30`                                                                              | Work never cuts the sentence below this many seconds                                                                                        |
| `releaseGuardModel` | `'s_m_m_skpguard_01'`                                                             | The release guard ped (release mode `'guard'`)                                                                                              |
| `blip`              | `{ enabled = true, sprite = 'blip_mp_roles_bounty_hunter_lock', label = 'Jail' }` | A map blip on each jail's `center`                                                                                                          |

### Jails (`Config.Jail.locations`)

Eight jails ship: `sisika` (the island prison, with work details and escapes), `tumbleweed`, `valentine`, `blackwater`, `rhodes`, `saintdenis`, `strawberry` and `annesburg`.

| Field          | What it does                                                                                                                              |
| -------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| `label`        | The name shown to prisoners and lawmen                                                                                                    |
| `cells`        | A list of `vector4` points. A new prisoner is put in one at random.                                                                       |
| `release`      | `vector4`: where a freed prisoner stands                                                                                                  |
| `releaseLabel` | The words for the release spot, shown on the jail screen                                                                                  |
| `releaseMode`  | `nil` = `Config.Booking.release.mode`. Or `'auto'`, `'point'` or `'guard'` for this jail only.                                            |
| `releaseGuard` | `vector4`: where the release guard stands (release mode `'guard'`). Only Sisika has one by default.                                       |
| `center`       | `vector3`: the middle of the jail. The blip sits here, the prison break alert points here, and the escape distance is measured from here. |
| `escape`       | `true` = escapes are possible here (with `Config.Escape.enabled`)                                                                         |
| `area`         | The yard as a polygon of x / y points. Leaving it starts the return countdown. Add or move points to resize it.                           |
| `work`         | The work details this jail offers: keys of `Config.Jail.WorkDetails`. `{}` = none.                                                        |

#### Example: add a jail

Copy a block, rename the key, set the points:

```lua
    -- inside Config.Jail.locations
    armadillo = {
        label        = 'Armadillo Jail',
        cells        = { vector4(0.0, 0.0, 0.0, 0.0) },   -- your points from /lawcoords
        release      = vector4(0.0, 0.0, 0.0, 0.0),
        releaseLabel = 'Outside the Armadillo office',
        center       = vector3(0.0, 0.0, 0.0),
        escape       = false,
        work         = {},
    },
```

Then point an office at it with `jail = 'armadillo'`, or a transport point with `jail = 'armadillo'`.

### Work details (`Config.Jail.WorkDetails`)

In-world jobs that cut the sentence. A jail lists the ones it offers in its `work`.

| Key     | Label               | Animation                                                                   | Stations | Minutes off per spot |
| ------- | ------------------- | --------------------------------------------------------------------------- | -------- | -------------------- |
| `sweep` | Sweep the cellblock | broom clip with a broom prop (`p_broom02x`) in the hand, and a women's clip | 5        | 2                    |
| `water` | Haul water          | scenario `WORLD_PLAYER_CHORES_BUCKET_POUR_LOW`                              | 4        | 2                    |
| `wood`  | Split firewood      | clip with an axe prop in the hand                                           | 3        | 3                    |

| Field            | What it does                                                                                                                                                                                                                                                                                                                                                                         |
| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `label`          | The name of the detail                                                                                                                                                                                                                                                                                                                                                               |
| `anim`           | Either a scenario: `{ scenario = 'NAME' }`. Or a clip: `{ dict = '...', name = '...', prop = 'model', bone = 'PH_R_Hand', loop = true }` (`prop`, `bone` and `loop` are optional). A clip can have a women's version with `dictFemale` and `nameFemale`. A scenario gives a player no tool in the hand, so a detail that needs one (a broom, an axe) uses a clip and names the prop. |
| `stations`       | A list of `vector3` work spots. The prisoner works them in order. When every spot is done, the detail starts over.                                                                                                                                                                                                                                                                   |
| `minutesReduced` | Minutes cut from the sentence for each spot done                                                                                                                                                                                                                                                                                                                                     |

#### Example: add a work detail

```lua
    -- inside Config.Jail.WorkDetails
    yard = {
        label    = 'Sweep the yard',
        anim     = { dict = 'amb_work@world_human_broom@working@male_a@idle_a', name = 'idle_a',
                     dictFemale = 'amb_work@world_human_broom@working@female_a@idle_a', nameFemale = 'idle_a',
                     prop = 'p_broom02x', bone = 'PH_R_Hand', loop = true },
        stations = {
            vector3(0.0, 0.0, 0.0),   -- your points from /lawcoords
            vector3(0.0, 0.0, 0.0),
        },
        minutesReduced = 1,
    },
```

Then add it to a jail: `work = { 'sweep', 'water', 'wood', 'yard' }`.

### Booking and transport (`Config.Booking`)

| Setting                     | Default                       | What it does                                                                                                                                                                      |
| --------------------------- | ----------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `mode`                      | `'both'`                      | `'command'` = `/jail` and "straight to the cell" on the booking sheet. `'transport'` = only the transport guard (lawmen cannot use `/jail`, admins still can). `'both'` = either. |
| `commandMaxDistance`        | `15.0`                        | `/jail` and "straight to the cell" need the prisoner this close. `0` = anywhere.                                                                                                  |
| `transport.animDurationSec` | `20`                          | Seconds the transport guard takes before the prisoner is in jail                                                                                                                  |
| `transport.guardModel`      | `'s_m_m_dispatchlawrural_01'` | The transport guard ped                                                                                                                                                           |
| `transport.radius`          | `6.0`                         | The lawman and the prisoner must be this close to the point                                                                                                                       |
| `transport.points`          | 5 points                      | Transport points: `{ coords = vector4, jail = 'key', label = 'Name' }`. Each sends its prisoners to its `jail`.                                                                   |
| `release.mode`              | `'auto'`                      | How a prisoner leaves at zero (see below)                                                                                                                                         |

The shipped transport points are Blackwater, Saint Denis, Valentine and Rhodes (all to `sisika`) and Tumbleweed (to `tumbleweed`).

#### Example: add a transport point

```lua
        points = {
            -- ... the shipped points ...
            { coords = vector4(0.0, 0.0, 0.0, 0.0), jail = 'sisika', label = 'Strawberry Point' },   -- your point from /lawcoords
        },
```

#### Release modes

| Mode      | At zero                                                                                                                      |
| --------- | ---------------------------------------------------------------------------------------------------------------------------- |
| `'auto'`  | He is freed and moved to the jail's `release` point                                                                          |
| `'point'` | He is freed where he stands and walks out on his own                                                                         |
| `'guard'` | He goes to the release guard and holds E to sign out, then is moved to the `release` point. The jail needs a `releaseGuard`. |

`/unjail` always moves him to the `release` point.

### Escape (`Config.Escape`)

Escapes happen only at a jail with `escape = true` and an `area`.

| Setting           | Default | What it does                                                                                        |
| ----------------- | ------- | --------------------------------------------------------------------------------------------------- |
| `enabled`         | `true`  | Master switch                                                                                       |
| `returnWindowSec` | `10`    | Seconds outside the yard before the escape stands. Back inside in time and nothing happens.         |
| `successDistance` | `450.0` | Meters from the jail `center` that count as clear                                                   |
| `successSeconds`  | `120`   | Alive and clear for this long = a successful escape                                                 |
| `alertLaw`        | `true`  | Lawmen on duty get a "Prison break" alert when an escape stands                                     |
| `warrantCharge`   | `240`   | The penal code id put on the fugitive warrant after a successful escape (240 = Escape from Custody) |

Guards (`Config.Escape.guards`):

| Setting          | Default                      | What it does                                                                          |
| ---------------- | ---------------------------- | ------------------------------------------------------------------------------------- |
| `enabled`        | `true`                       | Guards come when an escape stands                                                     |
| `model`          | `'s_m_m_skpguard_01'`        | The guard ped                                                                         |
| `fallbackModel`  | `'s_m_m_ambientlawrural_01'` | Used if `model` does not load                                                         |
| `accuracy`       | `60`                         | Guard accuracy                                                                        |
| `weapon`         | `'WEAPON_RIFLE_BOLTACTION'`  | Guard weapon                                                                          |
| `health`         | `150`                        | Guard health                                                                          |
| `staticSpawns`   | 4 points                     | `vector4` posts on the walls and at the gate. These guards hold their post and shoot. |
| `movingSpawns`   | 2 points                     | `vector4` points at the gate. These guards give chase.                                |
| `despawnSeconds` | `180`                        | The guards are removed after this long                                                |

Alligators (`Config.Escape.alligators`):

| Setting   | Default              | What it does                                                               |
| --------- | -------------------- | -------------------------------------------------------------------------- |
| `enabled` | `true`               | Alligators hunt an escapee in the water                                    |
| `count`   | `4`                  | How many                                                                   |
| `model`   | `'a_c_alligator_01'` | The animal                                                                 |
| `spawns`  | `{}`                 | Empty = they come up in the water around the escapee. Or a list of points. |
| `radius`  | `30.0`               | How far around the escapee they come up                                    |

On death (`Config.Escape.onDeath`):

| Setting              | Default | What it does                                                                                                                                             |
| -------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `teleportBackToJail` | `true`  | `true` = an escapee who dies is revived back inside with time added. `false` = the script does nothing on death and your framework's respawn takes over. |
| `location`           | `nil`   | `nil` = he wakes in a cell of his jail. Or a `vector4` drop point, for example `vector4(3330.66, -692.75, 43.95, 292.86)`.                               |
| `addTimeMinutes`     | `15`    | Minutes added for a failed escape. Also added when an escapee logs out after the escape stood.                                                           |

***

## config/penalcode.lua

### How charges add up (`Config.ChargeMode`)

| Mode                | What it does                                                                       |
| ------------------- | ---------------------------------------------------------------------------------- |
| `'stack'` (default) | Every charge on a report adds its fine and its minutes                             |
| `'top'`             | Only the most serious charge carries a fine and a sentence. The others count as 0. |

In `'top'` mode the most serious charge is picked by category first (1 before 2), then the longest jail time, then the largest fine.

Example: a report with Armed Robbery (300, 30 min), Resisting Arrest (100, 10 min) and Brandishing a Firearm (50, 5 min). In `'stack'` mode it totals $450 and 45 minutes. In `'top'` mode it totals $300 and 30 minutes.

### The penal code (`Config.PenalCode`)

The starter code has 65 charges in six sections: Against a person, Theft and property, The law and the courts, Weapons and violence, Public order, and Minor offences.

| Field      | What it does                                                    |
| ---------- | --------------------------------------------------------------- |
| `id`       | A unique number. Lawmen can find a charge by it.                |
| `label`    | The name of the charge                                          |
| `amount`   | The fine in dollars                                             |
| `jailtime` | The sentence in minutes                                         |
| `category` | `1` = a primary charge (the serious one), `2` = a lesser add-on |
| `section`  | The heading it is listed under in the book (any text)           |

#### Example: add a charge

Copy a line, give it a new id, change the values. No code editing.

```lua
    { id = 413, label = 'Fishing Without a Licence', amount = 10, jailtime = 0, category = 2, section = 'Minor offences' },
```

To remove a charge, delete its line. Reports already filed keep the numbers they were filed with.

### Editing the code inside the book

Players in `Config.Book.penalCodeEditors` (and admins) can change, add and strike charges from the Penal code page of the book. A change reaches every office at once. These edits are saved in the database (`cas_police_penal`) as the difference to this file and laid over it at every start, so this file stays your starter list.

An edit made in the book wins over this file for that charge, even if you later change its line here. To go back to the file for every charge, empty the `cas_police_penal` table and restart.
