> 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/server-management/door-lock-cc_doorlock.md).

# Door Lock (cc\_doorlock)

**CrankChaos Door Lock**: create and secure doors right in the game – with job, gang, item or PIN access and schedules.

## Features

* Create doors in game with in-world selection; the door type is detected automatically
* Single, double and sliding doors, garage doors and barriers
* Switches and door groups
* Access by job and grade, gang, owner (character identifier) or item (e.g. key card)
* PIN codes, bcrypt-hashed, with per-player and per-door lockout
* Schedules (open from/to, based on the server clock) and custom conditions from other scripts
* Lockpicking with a server-validated minigame, optional police alert via cc\_dispatch/00%20Overview\.md)
* Police battering ram
* Templates for police station (MRPD), hospital (Pillbox) and workshop
* Import and export as JSON
* Job bosses manage their own job's doors

## Frameworks

ESX Legacy, QBCore and QBox (auto-detected via the framework bridge).

## Works with

* cc\_lib/00%20Overview\.md) – shared notifications and hints
* cc\_inventory/00%20Overview\.md) – key card and lockpick items (falls back to `ox_inventory`, then the framework inventory)
* cc\_dispatch/00%20Overview\.md) – police alert on lockpicking

{% hint style="info" %}
The program code is protected by Cfx asset escrow. `config/`, `locales/` and `shared/cc_framework.lua` stay editable. Doors themselves are stored in the database, not in the config.
{% endhint %}

## Pages

* Installation
* Configuration
* API
* FAQ

Need help? See Support.

## Installation

See also the general installation guide and dependencies.

### Requirements

| Resource                         | Required | Notes                                                             |
| -------------------------------- | -------- | ----------------------------------------------------------------- |
| `oxmysql`                        | yes      | fxmanifest dependency                                             |
| ESX Legacy / QBCore / QBox       | yes      | auto-detected                                                     |
| cc\_lib/00%20Overview\.md)       | optional | shared notifications; otherwise built-in ones                     |
| cc\_inventory/00%20Overview\.md) | optional | items; falls back to `ox_inventory`, then the framework inventory |
| cc\_dispatch/00%20Overview\.md)  | optional | police alert on lockpicking                                       |

{% hint style="warning" %}
PIN doors need the FXServer native `GetPasswordHash`. If it is missing, the console shows a warning and PIN doors cannot be created. Use a current FXServer build.
{% endhint %}

### Steps

1. Copy the folder to `resources/[crankchaos]/cc_doorlock` (including `web/dist`).
2. Add to `server.cfg`:

```cfg
ensure oxmysql
ensure es_extended        # or qb-core / qbx_core
ensure cc_lib             # optional
ensure cc_inventory       # optional
ensure cc_dispatch        # optional
ensure cc_doorlock

add_ace group.admin cc_doorlock.admin allow
```

3. Join the server and open the editor with `/doorlock`. New doors are active immediately.

### Database

No SQL import needed. The tables `cc_doorlock_doors` and `cc_doorlock_switches` are created on first start.

### Permissions

```cfg
add_ace group.admin cc_doorlock.admin allow
```

`cc_doorlock.admin` (from `Config.AdminAce`) allows managing all doors, import/export and templates. With `Config.AdminBypass = true` it also opens every door.

Without the ACE, the highest grade of a job can manage doors of its own job if `Config.JobBossCanEdit = true`.

## Configuration

Editable files:

* `config/config.lua` – permissions, limits, keys, security
* `config/models.lua` – known door models for type detection
* `config/templates.lua` – door templates (MRPD, Pillbox, workshop)
* `config/ui.lua` – look and language
* `locales/de.json`, `locales/en.json`
* `shared/cc_framework.lua` – framework bridge

### Permissions

```lua
Config.Commands = { 'doorlock', 'tueren' }  -- open the editor
Config.AdminAce = 'cc_doorlock.admin'
Config.JobBossCanEdit = true    -- highest grade manages own job's doors
Config.AdminBypass = false      -- admins open every door
Config.GangFallbackToJob = true -- ESX: job counts as gang
```

Import/export and templates are always admin-only.

### Limits

```lua
Config.Limits = {
    maxDoors = 2500, maxPerJob = 120, maxSwitches = 600,
    maxParts = 2,
    maxJobs = 16, maxIdentifiers = 64, maxItems = 8,
    maxConditions = 8, maxTargets = 24,
}
Config.Place = { maxDistance = 25.0, serverSlack = 3.0 }
Config.InteractSlack = 2.5
```

### Defaults for new doors

```lua
Config.Defaults = {
    locked = true,
    distance = 2.0,
    autoLock = 0,        -- seconds, 0 = off
    display = 'icon',    -- 'icon' | 'text' | 'hint' | 'none'
    sound = 'default',
    anim = true,
}
```

All of these can be changed per door in the editor.

### Streaming and performance

```lua
Config.Stream = { cell = 100.0, radius = 90.0, interval = 1000, snapDistance = 35.0 }
Config.Loop = { displayExtra = 1.5, nearWait = 200, farWait = 1000, nearRange = 20.0 }
```

Only nearby doors are registered. Stored positions snap to the real object when a player comes close.

### Keys

```lua
Config.Keys = { use = 38, lockpick = 47, ram = 74 }        -- GTA controls
Config.KeyLabels = { use = 'E', lockpick = 'G', ram = 'H' }
```

### PIN doors

```lua
Config.Pin = {
    minLength = 4, maxLength = 8,
    maxAttempts = 4, lockSeconds = 300,          -- per player and door
    doorMaxAttempts = 12, doorWindow = 600,      -- all players combined
    doorLockSeconds = 900,
    graceSeconds = 60,  -- relock without re-entering the PIN
}
```

PINs are never stored, logged or sent to clients in plain text.

### Lockpicking

```lua
Config.Lockpick = {
    item = 'lockpick',
    difficulty = { { rounds = 3, zone = 56, speed = 150 }, ... },  -- levels 1-5
    tolerance = 5,
    minRoundMs = 350,
    timeout = 45,
    breakOnSuccess = 5,   -- % chance the lockpick breaks on success
    dispatch = { kind = 'robbery', code = '10-31', chance = 100 },
}
```

Lockpicking must be allowed per door in the editor.

### Battering ram

```lua
Config.Ram = {
    jobs = { police = 0, sheriff = 0 },  -- job = minimum grade
    item = false,                        -- e.g. 'police_ram'
    duration = 4500,
}
```

### Schedules and rate limits

```lua
Config.Schedule = { interval = 30 }  -- seconds, uses the real server clock
Config.RateLimit = { toggle = 700, pin = 1500, pick = 2500, ram = 3000, editor = 800,
                     write = 500, search = 700, sync = 5000, io = 3000 }
```

### Display

* `Config.Sounds` – lock/unlock sounds (`default`, `keypad`, `heavy`), selectable per door; own entries allowed
* `Config.Anims` – animations for unlock, keypad, lockpick and ram
* `Config.Colors` – selection colours in the world (RGBA)
* `Config.JobSuggestions`, `Config.ItemSuggestions` – suggestions in the editor (free input always works)
* `Config.Areas` – area filters in the door list (`MRPD`, `Pillbox`, `Werkstatt`)

### Door models (`config/models.lua`)

`Config.Models` maps model names to a type (`single`, `double`, `gate`, `garage`, `sliding`). Unlisted models are detected by size. Sliding doors cannot be detected by size and must be listed here.

### Templates (`config/templates.lua`)

`Config.Templates` contains ready-made door sets that an admin imports from the editor. Nothing is created automatically, and doors whose object already belongs to another door are skipped. The MRPD template targets the original GTA station, not MLO versions.

## Exports, Events & Commands

### Commands and keys

| Command / key          | Who                                                                   | Effect                                          |
| ---------------------- | --------------------------------------------------------------------- | ----------------------------------------------- |
| `/doorlock`, `/tueren` | admin (`cc_doorlock.admin`) or highest job grade (own job doors only) | open the editor; permission checked server-side |
| `E`                    | anyone with access                                                    | lock/unlock, enter PIN                          |
| `G`                    | anyone with a lockpick                                                | pick the lock (if allowed on the door)          |
| `H`                    | jobs in `Config.Ram`                                                  | ram the door                                    |

### Server exports

| Export                        | Parameters                                      | Returns                            |
| ----------------------------- | ----------------------------------------------- | ---------------------------------- |
| `SetDoorState(id, locked)`    | door ID, `true`/`false`                         | `boolean` (`false` = unknown door) |
| `GetDoor(id)`                 | door ID                                         | copy of the door data or `nil`     |
| `IsLocked(id)`                | door ID                                         | `boolean`, or `nil` if unknown     |
| `RegisterCondition(name, fn)` | name (max 48 chars), `fn(src, door) -> boolean` | `boolean`                          |
| `AddOwner(id, identifier)`    | door ID, character identifier                   | `boolean` (saved to the database)  |
| `RemoveOwner(id, identifier)` | door ID, character identifier                   | `boolean`                          |

```lua
-- Lock a door from a script
exports.cc_doorlock:SetDoorState(12, true)

-- Housing script: add a tenant
exports.cc_doorlock:AddOwner(12, 'char1:abc123')

-- Custom condition, selectable per door in the editor
exports.cc_doorlock:RegisterCondition('bank_open', function(src, door)
    return GlobalState.bankOpen == true
end)
```

A condition only grants access when it returns `true`. Errors inside the function are caught and count as "no access".

### Client export

| Export             | Returns                                                                           |
| ------------------ | --------------------------------------------------------------------------------- |
| `GetNearestDoor()` | nearest door within 50 m: `{ id, name, type, locked, distance, coords }` or `nil` |

```lua
local door = exports.cc_doorlock:GetNearestDoor()
if door and door.locked then print(door.name .. ' is locked') end
```

### Events

Server-local `cc_doorlock:stateChanged` `(id, locked, source)` fires after every state change. `source` is `nil` for changes made by scripts.

```lua
AddEventHandler('cc_doorlock:stateChanged', function(id, locked, src) end)
```

cc\_doorlock listens to `cc:characterChanged` from the CrankChaos framework bridge.

## FAQ & Troubleshooting

**`/doorlock` does nothing or says I have no permission.** Add `add_ace group.admin cc_doorlock.admin allow` to `server.cfg`. Job bosses only see doors whose responsible job is their own (`Config.JobBossCanEdit`).

**I cannot create PIN doors.** Your FXServer build lacks the native `GetPasswordHash`; the console shows a warning. Update FXServer.

**A schedule opens the door at the wrong time.** Schedules use the real server clock, not the in-game time.

**Gang doors don't work on ESX.** ESX has no gangs. With `Config.GangFallbackToJob = true` the job name is used as gang.

**The key card / lockpick item is not recognised.** Items are checked in cc\_inventory/00%20Overview\.md), then `ox_inventory`, then the framework inventory. Make sure the item exists there and the name matches (`Config.Lockpick.item`, item set on the door).

**No police alert when picking a lock.** Needs cc\_dispatch/00%20Overview\.md) running and "notify police" enabled on the door.

**A sliding door is detected as a normal door.** Add its model to `config/models.lua` with type `sliding`.

**The MRPD template doesn't match my station.** The template is for the original GTA station. MLO stations have different doors; create them in the editor instead.

**Admins cannot open locked doors.** That is intended. Set `Config.AdminBypass = true` if you want it.

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/server-management/door-lock-cc_doorlock.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.
