> For the complete documentation index, see [llms.txt](https://docs.cuxial.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.cuxial.com/scripts/police-and-medical/cuxial-medical/developers.md).

# Exports & events

Public API of Cuxial Medical: exports, hooks, state bags and events to use from other resources.

Read the medical state of a player, revive, heal or injure them, and react to what happens from your own resources. All exports are called as `exports.cuxial_medical:Name(...)`.

## Shared values

| Value      | Options                                                                                               |
| ---------- | ----------------------------------------------------------------------------------------------------- |
| State      | `'alive'`, `'laststand'`, `'dead'`                                                                    |
| Body zone  | `head`, `neck`, `spine`, `upper_body`, `lower_body`, `left_arm`, `right_arm`, `left_leg`, `right_leg` |
| Wound type | `shot`, `stabbed`, `beat`, `burned`                                                                   |
| Level      | 1 to 4                                                                                                |
| CPR mode   | `'fast'`, `'full'`                                                                                    |

Exports that act in the name of a medic return `ok, reason`. Possible reasons:

| Reason                 | Meaning                             |
| ---------------------- | ----------------------------------- |
| `no_ems_duty`          | The medic is not EMS on duty.       |
| `no_target`            | The target does not exist.          |
| `not_dead`             | The target is not downed.           |
| `is_down`              | The target is downed.               |
| `too_far`              | Medic and target are too far apart. |
| `cooldown`             | The medic acted too recently.       |
| `rate_limit`           | Too many requests.                  |
| `no_item`              | The medic lacks the required item.  |
| `no_injury`            | There is nothing to treat.          |
| `no_config`, `no_zone` | Missing config block or body zone.  |

## Server exports

### State

| Export                      | Returns                                                                                                |
| --------------------------- | ------------------------------------------------------------------------------------------------------ |
| `IsPlayerDead(src)`         | `false`, `'laststand'` or `'dead'`.                                                                    |
| `GetPlayerPhase(src)`       | `0` when alive, otherwise the phase number.                                                            |
| `GetPlayerDeathInjury(src)` | `{ injury, location, name }` for the hit that downed the player, or `nil`. `name` is the weapon label. |
| `GetMedicalState(src)`      | `{ isDead, phase, deathInjury, injuries }`.                                                            |
| `GetAllDeadPlayers()`       | `{ [src] = state }` for every downed player.                                                           |
| `GetAllMedicalStates()`     | `{ [src] = { state, phase, deathInjury, injuries } }` for every downed player.                         |

```lua
if exports.cuxial_medical:IsPlayerDead(source) then
    return -- the player is downed
end
```

### KillPlayer

Downs a player. On a player who is already downed, moves them to the next phase.

```lua
exports.cuxial_medical:KillPlayer(target)
```

**Returns:** `boolean`. `false` when the player does not exist.

### RevivePlayer

Revives a player, clears their injuries and resets hunger, thirst and stress. Works on any player, with no item and no distance check.

```lua
exports.cuxial_medical:RevivePlayer(target, options)
```

| Parameter      | Type                   | Description                                                                                              |
| -------------- | ---------------------- | -------------------------------------------------------------------------------------------------------- |
| `target`       | number                 | Server id of the player.                                                                                 |
| `options`      | table \| number \| nil | A table `{ anim, hp, by }`, or the server id of whoever revives.                                         |
| `options.anim` | boolean                | `true` plays the get-up animation. With a table it is off unless set; with a number or nothing it is on. |
| `options.hp`   | number                 | Final health, up to 200. Full health when omitted.                                                       |
| `options.by`   | number                 | Server id of whoever revives, for the log.                                                               |

**Returns:** `boolean`.

```lua
exports.cuxial_medical:RevivePlayer(target, { anim = true, by = source })
```

### RevivePlayerWithHP

Revives a player without animation and with an exact health.

```lua
exports.cuxial_medical:RevivePlayerWithHP(target, hp)
```

| Parameter | Type   | Description                                                      |
| --------- | ------ | ---------------------------------------------------------------- |
| `target`  | number | Server id of the player.                                         |
| `hp`      | number | Final health, from 1 to 200. The player never gets up below 101. |

**Returns:** `boolean`.

### HealPlayer

Heals a player, clears their injuries and resets hunger, thirst and stress. A downed player is revived first, without animation.

```lua
exports.cuxial_medical:HealPlayer(target, full, quiet)
```

| Parameter | Type    | Description                                     |
| --------- | ------- | ----------------------------------------------- |
| `target`  | number  | Server id of the player.                        |
| `full`    | boolean | `true` restores full health. Otherwise adds 25. |
| `quiet`   | boolean | `true` hides the notification.                  |

**Returns:** `boolean`.

```lua
exports.cuxial_medical:HealPlayer(source, true, true)
```

### Other treatment exports

| Export                         | What it does                                                              | Returns   |
| ------------------------------ | ------------------------------------------------------------------------- | --------- |
| `HealPlayerBy(target, amount)` | Adds `amount` health, up to 200. Does not touch injuries.                 | `boolean` |
| `SedatePlayer(target)`         | Sedates the player for `items.sedate.duration`. Fails on a downed player. | `boolean` |
| `ResetPlayerNeeds(src)`        | Sets hunger and thirst to 100 and stress to 0.                            | nothing   |

### Acting as a medic

These exports apply the same rules as the medic's own actions: EMS on duty, distance, cooldown and items.

| Export                                    | What it does                                                                          | Returns                    |
| ----------------------------------------- | ------------------------------------------------------------------------------------- | -------------------------- |
| `GetPatientReport(medic, target)`         | Full report of a patient.                                                             | `report`, or `nil, reason` |
| `CanResuscitate(medic, target, mode)`     | Checks whether the medic can revive the patient.                                      | `ok, reason`               |
| `ResuscitatePatient(medic, target, mode)` | Revives the patient and consumes the item of the CPR mode.                            | `ok, reason`               |
| `TreatZone(medic, target, bodyZone)`      | Bandages one zone: removes that injury and restores health. Uses `treatment.bandage`. | `ok, reason`               |

The report contains `targetId`, `firstname`, `lastname`, `fullName`, `citizenid`, `isDead`, `state`, `phase`, `phaseKey`, `phaseLabel`, `health`, `maxHealth`, `hpPercent`, `deathInjury`, `injuries`, `maxSeverity`, `totalBleed` and `timestamp`. Each entry of `injuries` is indexed by body zone and has `injury`, `level`, `bleed`, `label` and `injuryLabel`.

```lua
local ok, reason = exports.cuxial_medical:ResuscitatePatient(source, target, 'fast')
if not ok then print(reason) end
```

### EMS

| Export             | Returns                |
| ------------------ | ---------------------- |
| `GetEMSCount()`    | Number of EMS on duty. |
| `IsEMSOnDuty(src)` | `boolean`.             |

### Injuries

| Export                                            | What it does                                                     | Returns                                                                       |
| ------------------------------------------------- | ---------------------------------------------------------------- | ----------------------------------------------------------------------------- |
| `InjurePlayer(src, bodyZone, type, level, bleed)` | Adds or replaces the injury of a zone. `bleed` goes from 0 to 4. | `boolean`                                                                     |
| `ClearInjury(src, bodyZone)`                      | Removes the injury of a zone.                                    | nothing                                                                       |
| `ClearInjuryType(src, type)`                      | Removes every injury of a type.                                  | nothing                                                                       |
| `ClearPlayerInjuries(src)`                        | Removes every injury.                                            | nothing                                                                       |
| `GetPlayerInjuries(src)`                          |                                                                  | `{ [zone] = { bodyPart, injury, level, bleed } }`                             |
| `GetInjuryAt(src, bodyZone)`                      |                                                                  | The injury of that zone, or `nil`.                                            |
| `HasInjury(src, bodyZone)`                        | Without `bodyZone`, checks for any injury.                       | `boolean`                                                                     |
| `GetMaxSeverity(src)`                             |                                                                  | Highest level, `0` with no injuries.                                          |
| `GetTotalBleed(src)`                              |                                                                  | Sum of the bleeding of all injuries.                                          |
| `DiagnosePlayer(src)`                             |                                                                  | `{ injuries, maxSeverity, totalBleed, deathInjury }`, with translated labels. |
| `GetAllInjuredPlayers()`                          |                                                                  | `{ [src] = { count, maxSeverity, totalBleed } }`                              |

```lua
exports.cuxial_medical:InjurePlayer(source, 'left_leg', 'stabbed', 2, 1)
```

### Medical history

Stored in `cuxial_medical_logs`. Writing is skipped with `logs.persistence = false`.

| Export                                                       | What it does                                                                                                                     | Returns                                                                                   |
| ------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- |
| `LogMedicalEvent(patientSrc, eventType, doctorSrc, payload)` | Saves an event. `eventType` is `death`, `revive`, `treat`, `diagnose` or `heal`. `doctorSrc` and `payload` (table) are optional. | nothing                                                                                   |
| `GetMedicalHistory(citizenid, limit)`                        | Latest events of a character. `limit` is 25 by default, 100 at most.                                                             | Rows with `id`, `event_type`, `doctor_citizenid`, `doctor_name`, `payload`, `created_at`. |
| `GetDoctorMedicalStats(doctorCitizenid, since)`              | Counts the actions of a medic. `since` is a timestamp in milliseconds.                                                           | `{ revives, treats, diagnoses, heals }`                                                   |

```lua
local history = exports.cuxial_medical:GetMedicalHistory(citizenid, 10)
```

### getSetting

Returns the live value of a settings section.

```lua
local phases = exports.cuxial_medical:getSetting('config.death').phases
```

Valid identifiers: `config.jobs`, `config.death`, `config.respawn`, `config.injury`, `config.treatment`, `config.items`, `config.stretcher`, `config.finisher`, `config.extras`, `config.dispatch`, `config.logs` and `data.hospitals`. Any other returns `nil`.

## Server hooks

Register a function that runs when something happens. Each `on…` export returns the function, to pass to the matching `off…` export.

```lua
exports.cuxial_medical:onTreatment('revive', function(medic, target, data)
    print(('%s revived %s (%s)'):format(medic, target, data.mode))
end)
```

| Export                         | Event                        | Arguments                                                                |
| ------------------------------ | ---------------------------- | ------------------------------------------------------------------------ |
| `onTreatment` / `offTreatment` | `revive`                     | `medic, target, { health, injury, mode }`. Only revives done by a medic. |
|                                | `heal`                       | `medic, target`                                                          |
|                                | `treatStart`, `treatEnd`     | `medic, target, woundType`                                               |
|                                | `diagnose`                   | `medic, target`                                                          |
| `onFinisher` / `offFinisher`   | `finished`                   | `attacker, victim`                                                       |
| `onHospital` / `offHospital`   | `bedReserved`, `bedReleased` | `src, hospitalId, bedIndex`                                              |
|                                | `charged`                    | `src, account, cost, hospitalId`                                         |
| `onStretcher` / `offStretcher` | `add`, `remove`              | `{ netId, owner }`                                                       |
|                                | `seat`                       | `{ netId, target, medic, pose }`                                         |
|                                | `unseat`                     | `{ netId, target, reason }`                                              |
| `onDispatch` / `offDispatch`   | `requestAdded`               | `src, name`                                                              |
|                                | `requestRemoved`             | `src`                                                                    |

## Client exports

### State

| Export                                            | Returns                                                                    |
| ------------------------------------------------- | -------------------------------------------------------------------------- |
| `isPlayerDead(serverId)`                          | `false`, `'laststand'` or `'dead'`. Without `serverId`, the local player.  |
| `getDeathPhase()`                                 | Phase of the local player, `0` when alive.                                 |
| `getDeathPhaseKey()`                              | `id` of the current phase, or `nil`.                                       |
| `getMedicalState()`                               | `{ isDead, phase, phaseKey, injury, location, weapon }`                    |
| `isZoomActive()`                                  | `boolean`                                                                  |
| `pauseDeathAnimation()`, `resumeDeathAnimation()` | Stop and resume the downed animation, to play your own on a downed player. |

```lua
if exports.cuxial_medical:isPlayerDead() then return end
```

### Injuries

All of them act on the local player.

| Export                                                                 | Returns                                    |
| ---------------------------------------------------------------------- | ------------------------------------------ |
| `GetPlayerInjuries()`                                                  | `{ [zone] = injury }`                      |
| `GetInjuryAt(bodyZone)`                                                | The injury, or `nil`.                      |
| `HasInjury(bodyZone)`                                                  | `boolean`. Without `bodyZone`, any injury. |
| `IsInjured()`, `IsLimping()`, `IsBleeding()`                           | `boolean`                                  |
| `GetMaxSeverity()`, `GetTotalBleed()`                                  | `number`                                   |
| `AddInjury(bodyZone, type, level, bleed)`                              | `boolean`                                  |
| `ClearInjury(bodyZone)`, `ClearInjuryType(type)`, `ClearAllInjuries()` | nothing                                    |

### Hospital

| Export                             | What it does                                                                                                                                          | Returns          |
| ---------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------- |
| `requestCheckIn(hospitalId)`       | Check-in with the rules of the reception: hospital enabled, player standing, within the radius, medics allowing it. Notifies the player when refused. | `boolean`        |
| `attemptCheckIn(hospitalId)`       | Starts the check-in without those rules.                                                                                                              | `boolean`        |
| `layOnBed(hospitalId, bedIndex)`   | Lays the player on a bed.                                                                                                                             | `boolean`        |
| `getUpFromBed()`                   | Gets the player up.                                                                                                                                   | nothing          |
| `resolveBed(hospitalId, bedIndex)` | Position, heading and animations of a bed.                                                                                                            | `table` or `nil` |

`hospitalId` is optional in both check-in exports: the nearest enabled hospital is used. They wait until the treatment ends.

```lua
exports.cuxial_medical:requestCheckIn()
```

### Medic actions

For menus and radial wheels. They act on the nearest player, need EMS on duty and follow the item rules.

| Export                    | What it does                                                              | Returns            |
| ------------------------- | ------------------------------------------------------------------------- | ------------------ |
| `reviveTarget(options)`   | CPR on the nearest downed player. `options.mode` is `'fast'` or `'full'`. | `boolean`          |
| `healTarget()`            | Heals the nearest player, or yourself.                                    | `boolean`          |
| `useSedative()`           | Sedates the nearest player.                                               | `boolean`          |
| `treatPatient(woundType)` | Treats one wound type.                                                    | `boolean`          |
| `diagnosePlayer()`        | Diagnoses the nearest player and shows the result.                        | `report` or `nil`  |
| `ToggleDuty()`            | Switches the EMS duty.                                                    | `ok, onduty`       |
| `GetDistressRequests()`   | Open distress calls.                                                      | `{ [src] = name }` |
| `PlaceInVehicle()`        | Puts the nearest downed or sedated player in the nearest vehicle.         | `boolean`          |
| `RemoveFromVehicle()`     | Makes the occupants of the nearest vehicle leave it.                      | `boolean`          |
| `IntoVehicle()`           | Warps the local player into a free seat of the nearest vehicle.           | `boolean`          |
| `RemoveWeapons()`         | Removes every weapon of the local player.                                 | nothing            |

```lua
exports.cuxial_medical:reviveTarget({ mode = 'full' })
```

### CPR animation

| Export                             | What it does                                                                                                   | Returns                  |
| ---------------------------------- | -------------------------------------------------------------------------------------------------------------- | ------------------------ |
| `ReviveAnimation(target, options)` | Plays the CPR animation on medic and patient. `options`: `mode`, `lockCamera`, `unarmTarget`. Does not revive. | `true` when it completes |
| `CancelReviveAnimation(target)`    | Cancels it.                                                                                                    | `boolean`                |
| `IsReviveInProgress()`             |                                                                                                                | `busy, target, mode`     |
| `GetReviveAnimDuration(mode)`      |                                                                                                                | Milliseconds             |

### Stretcher

| Export                          | What it does                                                                     |
| ------------------------------- | -------------------------------------------------------------------------------- |
| `toggleStretcher()`             | Same as `/stretcher`.                                                            |
| `spawnStretcher()`              | Places a stretcher. Returns `entity, netId`.                                     |
| `pickupStretcher()`             | Picks up the stretcher within 3 metres. Returns `boolean`.                       |
| `deleteStretcher()`             | Removes the stretcher within 5 metres.                                           |
| `placeNearestOnStretcher(pose)` | Places the nearest downed or sedated player on the nearest stretcher.            |
| `removeFromStretcher()`         | Takes the patient off the nearest stretcher.                                     |
| `toggleStretcherExtra(name)`    | Toggles an accessory: `headrest`, `backboard`, `monitor`, `redbag` or `bluebag`. |
| `isPlayerUsingStretcher()`      | `true` when the local player lies on a stretcher.                                |

Poses: `lie_back` (default), `lie_left`, `lie_prone`, `sit_up`, `sit_end`, `sit_left`, `sit_right`, `cpr`.

```lua
exports.cuxial_medical:placeNearestOnStretcher('sit_up')
```

### Finisher and knockout

| Export                       | What it does                                                         |
| ---------------------------- | -------------------------------------------------------------------- |
| `performFinisher(victimPed)` | Starts the finisher on that ped. Returns `boolean`.                  |
| `isFinisherBusy()`           | `boolean`                                                            |
| `manuallyKnockout()`         | Knocks out the local player. Needs `extras.knockout.enabled = true`. |
| `disableKnockoutLoop(state)` | `true` blocks knockouts, `false` allows them again.                  |

## Client hooks

Same pattern as the server hooks.

```lua
exports.cuxial_medical:onDeath('playerDeath', function(data)
    print(data.state, data.injury, data.bodyPart)
end)
```

| Export                           | Event                                 | Arguments                                                                     |
| -------------------------------- | ------------------------------------- | ----------------------------------------------------------------------------- |
| `onDamage` / `offDamage`         | `damaged`                             | `{ ped, weapon, bone, healthDiff, armourDiff, currentHealth, currentArmour }` |
|                                  | `died`                                | `{ ped, weapon, bone, cause, via }`                                           |
| `onInjury` / `offInjury`         | `applied`                             | `{ bodyPart, injury, level, bleed, weapon }`                                  |
|                                  | `cleared`                             | `{ bodyPart }`                                                                |
|                                  | `allCleared`, `limpStart`, `limpStop` | none                                                                          |
|                                  | `blackout`                            | `{ bodyPart, level, duration }`                                               |
| `onDeath` / `offDeath`           | `playerDeath`                         | `{ state, injury, bodyPart, weapon }`                                         |
|                                  | `phaseChange`, `resume`               | `phaseIndex, phaseId`                                                         |
|                                  | `playerSpawn`                         | none                                                                          |
| `onReviveAnim` / `offReviveAnim` | `started`, `complete`, `cancelled`    | `target, mode`                                                                |

## State bags

Written by the server. Read them, do not write them.

| State bag                | Scope  | Value                                                                        |
| ------------------------ | ------ | ---------------------------------------------------------------------------- |
| `cuxial:state`           | Player | `'alive'`, `'laststand'` or `'dead'`                                         |
| `cuxial:phase`           | Player | Phase number, `0` when alive                                                 |
| `cuxial:injuries`        | Player | `{ [zone] = { bodyPart, injury, level, bleed } }`, or `nil`                  |
| `isDead`                 | Player | `boolean`                                                                    |
| `qbx_medical:deathState` | Player | `1` alive, `2` last stand, `3` dead. With `compat.qbxMedicalStateBag = true` |
| `cuxialEmsOnline`        | Global | EMS on duty                                                                  |

```lua
local downed = Player(source).state['cuxial:state'] ~= 'alive'
local medics = GlobalState.cuxialEmsOnline or 0
```

The player metadata `isdead` and `inlaststand` are kept up to date too.

### Excluding a player

Set the player state bag `inDuel` or `inEvent` to any value and Cuxial Medical ignores the damage and the death of that player. Set it back to `nil` to return to normal.

```lua
Player(source).state:set('inEvent', true, true)
```

## Events

### Distress call

Sends a distress call for the player, downed or not. Use it from a phone or a panic button.

```lua
TriggerServerEvent('cuxial_medical:server:Dispatch', { street = 'Alta Street' })
```

`street` is optional. The position is taken from the player on the server. The cooldown of `dispatch.cooldownMs` applies.

### Compatibility events

Resources written for the ambulance job of QBCore keep working with these events:

| Event                            | Side   | What it does                                                                                |
| -------------------------------- | ------ | ------------------------------------------------------------------------------------------- |
| `hospital:client:Revive`         | Client | Asks for a self revive. Accepted only for staff and for players with `inDuel` or `inEvent`. |
| `hospital:client:RevivePlayer`   | Client | The medic revives the nearest player.                                                       |
| `hospital:client:TreatWounds`    | Client | The medic heals the nearest player.                                                         |
| `hospital:client:CheckStatus`    | Client | The medic diagnoses the nearest player.                                                     |
| `hospital:server:emergencyAlert` | Server | Sends a distress call.                                                                      |

With `compat.qbxMedicalEvents = true` the script also triggers `qbx_medical:client:onPlayerDied`, `qbx_medical:client:onPlayerLaststand` and `qbx_medical:client:playerRevived` on the player.


---

# 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://docs.cuxial.com/scripts/police-and-medical/cuxial-medical/developers.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.
