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

# EMS (cc\_ambulance)

**CrankChaos EMS**: injury and death system, EMS job, a hospital with check-in and a dedicated EMS tablet.

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

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

## Features

### Death system

* **Down** and **dead** states. The server only accepts a death if the ped is really dead on the server side.
* While down: look around, chat and radio work; no shooting, driving, walking or inventory.
* `G` sends a call for help to cc\_dispatch/00%20Overview\.md) (with cooldown).
* After the bleed-out time the player is `dead`; after the respawn delay, hold `E` to wake up in a hospital bed for a fee (paid to the society account).
* Optional item loss on respawn (off by default, with a keep list).
* **Combat-log protection:** state and remaining time are stored in the database; logging out while down puts you back down on rejoin. A resource restart heals nobody.

### Injuries

* Every hit is mapped by bone to a zone (head, torso, arms, legs), level 0-4.
* Effects: limping (legs), shaky aim (arms), short blur (head). Painkillers suppress them for a while; bandages lower the worst zone.

### EMS job (on duty)

* `F6` action panel for the nearest patient: body chart, findings, actions
* Revive (`medikit`), bandage (`bandage`), painkillers (`painkillers`)
* Carry, stretcher (fetch, load/unload, push), put in / take out of vehicles
* Invoices from a catalog, **only with the patient's consent** (configurable); money goes to the society account
* Timed actions are validated server-side (start and end); `X` cancels at no cost

### Hospital and station

* Check-in NPC (only when few medics are on duty), hospital beds, respawn fee
* Station NPC: duty with callsign, locker room (via cc\_character/00%20Overview\.md)), equipment and pharmacy cabinets (free or paid, cooldown and hourly limit)
* Stash (via cc\_inventory/00%20Overview\.md)), ground garage and helipad, one vehicle per medic, keys via cc\_keys/00%20Overview\.md)
* Boss menu via cc\_bossmenu/00%20Overview\.md)

### EMS tablet (MDT)

* Dashboard with open EMS calls from cc\_dispatch (with waypoint), crew, announcements, recent reports
* Citizens: search, nearby, blood type, allergies, profile photo (cc\_images%20(cc\_images)/00%20Overview\.md)), notes, timeline, bills, medications, documents
* Reports with templates, treatments and medications; trash with restore
* Bills from reports (amount always from the current catalog)
* Print **prescriptions** and **medical reports** as cc\_inventory items
* Catalog, templates, announcements, 10-codes, dress code, internal reports, staff with duty time (7/30 days), audit log
* Rank-based permissions, checked on every server action

### Locations

* The highest rank can place station, hospital and garage points in-game via cc\_jobs/00%20Overview\.md); otherwise the config is used.

## Pages

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

Need help? See Support.

## Installation

General steps are described in Getting started: Installation.

### Requirements

**Required**

* `oxmysql`
* ESX Legacy, QBCore or QBox with a job named `ambulance`
* A society account for fees, bills and equipment: ESX `esx_addonaccount` (account `society_ambulance`); QBCore/QBox via `qbx_management`, `qb-management` or `qb-banking` (detected automatically)
* **No other death/ambulance script** (e.g. esx\_ambulancejob, qb-ambulancejob, wasabi). Two scripts handling the same death will revive each other.

**Optional**

| Resource                                     | Used for                                                                                  | Without it                                    |
| -------------------------------------------- | ----------------------------------------------------------------------------------------- | --------------------------------------------- |
| cc\_lib/00%20Overview\.md)                   | shared notifications / hints                                                              | built-in notifications                        |
| cc\_inventory/00%20Overview\.md)             | `bandage`, `medikit`, `painkillers`, stash, lock while down, item loss, printed documents | with ox\_inventory only the items work        |
| cc\_character/00%20Overview\.md)             | duty uniforms                                                                             | no uniforms                                   |
| cc\_dispatch/00%20Overview\.md)              | help call while down, calls in tablet                                                     | "no dispatch reachable", tablet without calls |
| cc\_keys/00%20Overview\.md)                  | keys for service vehicles                                                                 | no keys handed out                            |
| cc\_images%20(cc\_images)/00%20Overview\.md) | profile photo in tablet                                                                   | no photo                                      |
| cc\_jobs/00%20Overview\.md)                  | place locations in-game                                                                   | config locations                              |
| cc\_bossmenu/00%20Overview\.md)              | boss menu                                                                                 | no boss menu                                  |

See also Dependencies.

### Steps

1. Copy the folder to `resources/[crankchaos]/cc_ambulance`.
2. Create the job `ambulance` if missing (ESX: `jobs` / `job_grades`; QBCore/QBox: `shared/jobs.lua`).
3. ESX only: make sure the `addon_account` `society_ambulance` exists.
4. Add to `server.cfg` in this order:

```cfg
ensure oxmysql
ensure es_extended          # or qb-core / qbx_core
ensure esx_addonaccount     # ESX only: society account
ensure cc_lib               # optional
ensure cc_character         # optional
ensure cc_inventory         # optional
ensure cc_keys              # optional
ensure cc_dispatch          # optional
ensure cc_images            # optional
ensure cc_jobs              # optional, before cc_ambulance
ensure cc_ambulance
ensure cc_bossmenu          # optional
```

5. **Printed documents (cc\_inventory):** register the items `prescription` and `medical_record` so that using them calls the server export `cc_ambulance.UseDocument` (item is kept). Item names can be changed in `Config.Mdt.items`.

### Database

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

`cc_ambulance_state`, `cc_ambulance_staff`, `cc_ems_meta`, `cc_ems_profiles`, `cc_ems_notes`, `cc_ems_reports`, `cc_ems_report_patients`, `cc_ems_catalog`, `cc_ems_bills`, `cc_ems_documents`, `cc_ems_internal`, `cc_ems_announcements`, `cc_ems_codes`, `cc_ems_dress`, `cc_ems_templates`, `cc_ems_sessions`, `cc_ems_log`.

Catalog, codes, dress code and templates are seeded **once** from `Config.Mdt.seed` (texts in the server language).

### ACE permissions

```cfg
add_ace group.admin command.revive allow
add_ace group.admin command.heal allow
```

### Framework notes

| Framework     | Notes                                                                                                                                                                |
| ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| ESX Legacy    | society `society_ambulance` via esx\_addonaccount                                                                                                                    |
| QBCore / QBox | society via qbx\_management, qb-management or qb-banking. QBCore metadata `isdead` / `inlaststand` is **not** set; other scripts should read the `ccDown` state bag. |

See Framework bridge.

## Configuration

| File                                 | Contents                                            |
| ------------------------------------ | --------------------------------------------------- |
| `config/config.lua`                  | gameplay (fully commented)                          |
| `config/mdt.lua`                     | EMS tablet: command, permissions, limits, seed data |
| `config/ui.lua`                      | look (default red `#EF4444`), language              |
| `locales/de.json`, `locales/en.json` | texts                                               |

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

### General

```lua
Config.Debug = false
Config.Job = 'ambulance'
Config.Society = 'ambulance'   -- ESX: society_ambulance
```

### Keys

```lua
Config.Keys = {
    ems = 'F6',      -- EMS panel / tablet (rebindable)
    help = 47,       -- G, call for help while down (control ID)
    respawn = 38,    -- E (hold)
    interact = 38,   -- E
}
```

### Down / dead

```lua
Config.Down = {
    bleedTime = 300,      -- seconds down until dead
    respawnDelay = 120,   -- seconds dead before respawn is possible
    respawnHold = 3000,   -- ms to hold E
    helpCooldown = 90,
    autoDispatch = false, -- send a call automatically when going down
    downHealth = 150,
    reviveHealth = 150,
    respawnHealth = 200,
    reviveDead = true,    -- dead players can still be revived
}
```

### Respawn

```lua
Config.Respawn = {
    fee = 1500,                 -- to the society account
    allowWithoutMoney = true,   -- respawn without fee if broke
    clearInventory = false,     -- item loss, off by default
    keepItems = { 'money', 'phone', 'id_card', 'driver_license' },
    coords = vector4(298.62, -584.53, 43.29, 77.5), -- if no bed is free
    bedTime = 8,
}
```

### Injuries

```lua
Config.Injuries = {
    enabled = true,
    limpFrom = 2, shakeFrom = 2, blurFrom = 3,
    severity = { weapon = 2, melee = 1, vehicle = 1, fall = 1, fire = 1, other = 1 },
    painkillerTime = 600,
    bandageHeals = 2,     -- levels removed from the worst zone
    bandageHealth = 30,
}
```

### EMS actions

```lua
Config.Ems = {
    distance = 3.0,
    reviveTime = 10000, healTime = 6000, painkillerTime = 3000,
    reviveItem = 'medikit', healItem = 'bandage', painkillerItem = 'painkillers', -- false = no item
    carryOnlyDown = true,
    billMinGrade = 0,
    stretcherModel = 'v_med_emptybed',
    stretcherPush = { x = 0.0, y = 1.3, z = -0.45, rz = 90.0 },
    stretcherLie = { x = 0.0, y = 0.0, z = 1.05, rz = 90.0 },
    vehicleDistance = 7.0,
}
```

### Billing

```lua
Config.Billing = {
    requireConsent = true,  -- false = charged directly (cash, then bank)
    timeout = 45,
    catalog = {
        { id = 'exam', label = 'ambulance.bill.exam', price = 250 },
        { id = 'revive', label = 'ambulance.bill.revive', price = 1500 },
        -- ...
    },
}
```

### Hospital

```lua
Config.Hospital = {
    label = 'Pillbox Hill Medical Center',
    blip = { coords = vector3(298.62, -584.53, 43.29), sprite = 61, colour = 1, scale = 0.8 },
    checkin = { ped = vector4(...), model = 's_f_y_scrubs_01', maxEms = 1, fee = 1000, duration = 20, requireInjury = false },
    beds = { vector4(353.10, -584.60, 43.11, 152.08), ... },
}
```

The check-in NPC only works while fewer than `maxEms` medics are on duty.

### Station

```lua
Config.Station = {
    locker = { ped = vector4(311.18, -599.25, 43.29, 70.0), model = 's_m_m_doctor_01' },
    stash = { coords = vector3(309.78, -596.60, 43.29), slots = 60, maxWeight = 200000, minGrade = 0 }, -- false = none
    callsignPattern = '^[%w%-]+$',
    callsignMax = 6,
}
```

### Outfits

`Config.Outfits.male` / `.female` with `id`, `label`, `minGrade` and `pieces` (cc\_inventory body slots, `{ drawable, texture }`). Defaults: trainee (0), paramedic (1).

### Equipment

```lua
Config.Armory = {
    cooldown = 5,
    hourlyLimit = 30,
    items = {
        { item = 'bandage', max = 10, price = 0, minGrade = 0, cabinet = 'armory' },
        { item = 'painkillers', max = 10, price = 0, minGrade = 0, cabinet = 'pharmacy' },
        { item = 'medikit', max = 5, price = 50, minGrade = 1, cabinet = 'armory' },
    },
}
```

`cabinet` is `armory` or `pharmacy`; without it the item is in both.

### Garage

```lua
Config.Garage = {
    platePrefix = 'EMS',
    limit = 1,   -- vehicles per medic at the same time
    points = {
        { id = 'ground', ped = vector4(...), spawn = vector4(...), returnRadius = 15.0,
          vehicles = { { id = 'ambulance', model = 'ambulance', minGrade = 0, type = 'automobile' }, ... } },
        { id = 'air', ..., vehicles = { { id = 'polmav', model = 'polmav', minGrade = 2, type = 'heli' } } },
    },
}
```

### Dispatch

```lua
Config.Dispatch = { code = '10-52', priority = 2, blip = { sprite = 153, colour = 1, scale = 1.0 }, expires = 600 }
```

### Places (cc\_jobs)

```lua
Config.Places = {
    useJobs = true,       -- false = config only
    configHeight = 1.0,
    bedHeight = 0.5,
    tolerance = 2.5,
}
```

| Kind                                     | Effect                    | Config fallback                |
| ---------------------------------------- | ------------------------- | ------------------------------ |
| `duty`, `wardrobe`, `armory`, `pharmacy` | station functions         | `Config.Station.locker.ped`    |
| `garage`                                 | vehicle NPC               | `Config.Garage.points[].ped`   |
| `garage_spawn` / `heli_spawn`            | spawn points              | `Config.Garage.points[].spawn` |
| `bed`                                    | check-in and respawn beds | `Config.Hospital.beds`         |
| `checkin`                                | check-in NPC              | `Config.Hospital.checkin.ped`  |
| `blip`                                   | map blip                  | `Config.Hospital.blip`         |

{% hint style="warning" %}
Default coordinates are the common Pillbox Hill MLO points. Without an MLO the building is empty inside; move the points outside or set them in-game.
{% endhint %}

### Marker

`Config.Marker`: type, scale, colour and distance of the vehicle return marker.

### EMS tablet (`config/mdt.lua`)

```lua
Config.Mdt = {
    command = 'emsmdt',   -- false = no command
    perms = {
        view = 0, reportsWrite = 0, reportsEditAll = 2, reportsDelete = 2,
        notes = 0, profileEdit = 1, bill = 0, print = 0, catalog = 3,
        templates = 2, internalWrite = 0, internalManage = 3, announce = 3,
        codes = 3, dress = 3, staff = 0, staffManage = 3, log = 3,
    },
    deleteGraceDays = 7,
    logDays = 60,
    nearbyRadius = 15.0,
    photoRadius = 5.0,
    billRadius = 0,       -- > 0 = patient must also be this close
    items = { prescription = 'prescription', record = 'medical_record' },
    printsPerHour = 10,
    ...
}
```

Also: `bloodTypes` (weighted random assignment), `limits` (text lengths and numbers) and `seed` (treatments, medications, codes, dress code, templates; applied once).

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

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

## Exports, Events & Commands

### Commands and keys

| Command / key                    | Who                           | Effect                                             |
| -------------------------------- | ----------------------------- | -------------------------------------------------- |
| `F6` (`+ccems`, rebindable)      | EMS on duty                   | action panel (patient nearby) or tablet            |
| `/emsmdt` (`Config.Mdt.command`) | EMS on duty                   | EMS tablet                                         |
| `/revive [id]`                   | ACE `command.revive`, console | revive (no id: yourself)                           |
| `/heal [id]`                     | ACE `command.heal`, console   | full heal (no id: yourself)                        |
| `/ccinnenraum`                   | everyone                      | prints a hospital interior check to the F8 console |
| `G` / hold `E`                   | while down                    | call for help / respawn                            |

### Server exports

| Export                   | Parameters                                        | Returns                                                   |
| ------------------------ | ------------------------------------------------- | --------------------------------------------------------- |
| `Revive(src)`            | player ID                                         | `boolean`, stands up fully healed                         |
| `Heal(src, amount?)`     | player ID, optional amount                        | `boolean`, without amount heals everything incl. injuries |
| `IsDown(src)`            | player ID                                         | `boolean`                                                 |
| `Kill(src, cause)`       | player ID, cause                                  | `boolean`, immediately `down` (already down: `dead`)      |
| `IsOnDuty(src)`          | player ID                                         | `boolean`                                                 |
| `GetReport(src)`         | player ID                                         | findings table as in the panel, or `nil`                  |
| `OnDutyCount()`          | none                                              | number of medics on duty                                  |
| `UseDocument(src, item)` | player ID, item `{ name, slot, count, metadata }` | `boolean`, for cc\_inventory item use                     |

```lua
if exports.cc_ambulance:IsDown(src) then
    exports.cc_ambulance:Revive(src)
end
local medics = exports.cc_ambulance:OnDutyCount()
```

### Client exports

| Export     | Returns                       |
| ---------- | ----------------------------- |
| `IsDown()` | `boolean`, own player is down |

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

```lua
Player(src).state.ccDown = { state = 'down'|'dead', since = os.time(), cause = 'weapon'|'vehicle'|'fall'|'fire'|'drown'|'other' } -- or nil
Player(src).state.ccDuty = { job = 'ambulance', callsign = 'M-12', since = os.time() } -- or nil
```

### Events

Server (`AddEventHandler`):

* `cc_ambulance:wentDown (src, forced)`
* `cc_ambulance:revived (src)`
* `cc_ambulance:duty (src, on)`

Client-local:

* `cc_ambulance:down (state)`
* `cc_ambulance:up`

```lua
AddEventHandler('cc_ambulance:revived', function(src)
    print(('Player %s was revived'):format(src))
end)
```

## FAQ & Troubleshooting

#### Players revive each other randomly / death behaves oddly

Another death or ambulance script is running (esx\_ambulancejob, qb-ambulancejob, wasabi, ...). Remove it; only one script may handle death.

#### Pressing G says "no dispatch reachable"

The help call needs cc\_dispatch/00%20Overview\.md). Without it the tablet also shows no calls.

#### F6 does nothing

The EMS panel/tablet only opens on duty. Off duty, `/emsmdt` reports "not on duty".

#### The check-in NPC refuses me

The check-in NPC only works while fewer than `Config.Hospital.checkin.maxEms` medics are on duty.

#### Leaving the hospital bed early did not heal me

Intended: leaving the bed before `duration` means paid but not healed.

#### The hospital interior is empty

Default coordinates are for a Pillbox Hill MLO. Without an MLO, move the points outside in the config or set them in-game with cc\_jobs/00%20Overview\.md) (tablet: Locations, highest rank). `/ccinnenraum` prints an interior check to the F8 console.

#### Printed prescriptions / medical reports cannot be used

Register the items `prescription` and `medical_record` in cc\_inventory with the server export `cc_ambulance.UseDocument` (keep the item).

#### Items, stash or item loss do not work

Stash, item loss and printed documents require cc\_inventory/00%20Overview\.md). With ox\_inventory only the items themselves work.

#### Other QBCore scripts do not know a player is dead

QBCore metadata `isdead` / `inlaststand` is not set. Read the `ccDown` state bag or `exports.cc_ambulance:IsDown(src)`.

#### Uniform disappears on duty

Duty clothing is not an item. Wearing an inventory clothing piece replaces that slot; visit the wardrobe again to restore it.

#### Painkillers from the inventory have no effect

They only work when health is not full.

#### Stretcher looks misplaced

The stretcher is the base-game bed `v_med_emptybed`. Tune `Config.Ems.stretcherPush` / `stretcherLie` or set an addon model in `stretcherModel`.

#### Known limitations

* No crawling while down.
* Dying in a vehicle: the ped returns to its seat if free, otherwise lies next to the vehicle.
* Tablet: no simultaneous editing (last save wins), photos only via cc\_images, no fingerprint scanner.

Still stuck? See Support.


---

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

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

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

```
GET https://ccfivem.gitbook.io/ccfivem-docs/police-ems-and-justice/ems-cc_ambulance.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.
