# Medical Help

***

<figure><img src="/files/1kQwmJ2ltnmMhaa9qy1W" alt=""><figcaption></figcaption></figure>

## Overview

XeX MedicalHelp is a premium heal, revive, and carry system for FiveM servers. It provides configurable NPC-based interaction points where players can heal themselves or revive nearby downed players, with EMS count restrictions to ensure medical roleplay is not bypassed when ambulance players are online. A fireman's carry system allows players to transport others. Supports all three major frameworks.

### Supported Frameworks

| Framework  | Version | Status                            |
| ---------- | ------- | --------------------------------- |
| ESX Legacy | 1.6.0+  | ✅ Full Support                    |
| QBCore     | Latest  | ✅ Full Support                    |
| QBox (QBx) | Latest  | ✅ Full Support (requires ox\_lib) |

***

## Features Summary

| Category     | Feature            | Description                                             |
| ------------ | ------------------ | ------------------------------------------------------- |
| **Medical**  | Heal Points        | NPC-based locations where players heal to full HP       |
| **Medical**  | Revive Points      | NPC-based locations to revive downed/dead players       |
| **Medical**  | Medical Animation  | 10-second medic tend animation during revive            |
| **Medical**  | Cost System        | Configurable cash cost per point (or free)              |
| **Carry**    | Fireman's Carry    | Pick up and carry other players                         |
| **Carry**    | Sync System        | Server-synced carry animations between players          |
| **Carry**    | Toggle Command     | Same command to start and stop carrying                 |
| **EMS**      | EMS Restriction    | Points hidden when EMS count exceeds threshold          |
| **EMS**      | Real-time Tracking | Server tracks EMS job changes and connections           |
| **Access**   | Job Whitelisting   | Restrict specific points to certain jobs                |
| **NPC**      | Custom Peds        | Spawn configurable NPC at each point                    |
| **NPC**      | NPC Animation      | Guard idle animation on spawned NPCs                    |
| **NPC**      | Invincible NPCs    | NPCs are frozen, invincible, and non-reactive           |
| **Map**      | Blips              | Per-point configurable map blips (sprite, scale, color) |
| **Map**      | Markers            | Per-point 3D markers with custom type and RGB color     |
| **Interact** | ox\_target         | Optional ox\_target sphere zones or entity targets      |
| **Interact** | Marker + E         | Traditional marker rendering + E key interaction        |
| **Webhook**  | Discord Logging    | Log heal and revive actions with player identifiers     |
| **System**   | Auto Updater       | JSON-based version checker                              |
| **I18n**     | 2 Languages        | English, Spanish                                        |

***

## Installation

### Requirements

* FiveM Server Build 5181+
* Framework: ESX Legacy, QBCore, or QBox
* Optional: [ox\_target](https://github.com/overextended/ox_target) (for target mode)
* Optional: [ox\_lib](https://github.com/overextended/ox_lib) (required for QBox)

### Dependencies by Framework

| Framework | Required                        | Optional   |
| --------- | ------------------------------- | ---------- |
| ESX       | es\_extended, esx\_ambulancejob | ox\_target |
| QBCore    | qb-core                         | ox\_target |
| QBox      | qbx\_core, ox\_lib              | ox\_target |

### Quick Start

{% stepper %}
{% step %}

### Place resource

Place `xex_medicalhelp` in your resources folder.
{% endstep %}

{% step %}

### Enable resource

Add to server.cfg:

```
ensure xex_medicalhelp
```

{% endstep %}

{% step %}

### Configure framework

Set `Config.Framework` to your framework (`'esx'`, `'qb'`, or `'qbx'`).
{% endstep %}

{% step %}

### Configure points

Configure `Config.HRPoints` with your heal/revive locations.
{% endstep %}

{% step %}

### Restart server

Restart server.
{% endstep %}
{% endstepper %}

> Note: If using QBox, ensure `ox_lib` is started before this resource.

***

## Configuration

### General Settings

```lua
Config.Language = 'en'              -- 'en' | 'es'
Config.CheckForUpdates = true       -- Auto version check on start
Config.UseOxTarget = true           -- true = ox_target | false = marker + E key
Config.DrawDistance = 20.0          -- Distance to render markers (marker mode only)
Config.EMSJobName = 'ambulance'     -- Job name used for EMS count tracking
```

| Option                | Default       | Description                                |
| --------------------- | ------------- | ------------------------------------------ |
| `Config.Language`     | `'en'`        | Locale for all text strings                |
| `Config.UseOxTarget`  | `true`        | Use ox\_target zones instead of 3D markers |
| `Config.DrawDistance` | `20.0`        | Distance to start rendering 3D markers     |
| `Config.EMSJobName`   | `'ambulance'` | Job name to track for EMS online count     |

### Framework Settings

```lua
Config.Framework = 'auto'  -- 'auto' | 'esx' | 'qb' | 'qbx'
```

| Value    | Behavior                          |
| -------- | --------------------------------- |
| `'auto'` | Auto-detects: QBox → QBCore → ESX |
| `'esx'`  | Force ESX Legacy                  |
| `'qb'`   | Force QBCore                      |
| `'qbx'`  | Force QBox (requires ox\_lib)     |

### Heal & Revive Points

Each entry in `Config.HRPoints` defines one interaction point:

```lua
Config.HRPoints = {
    {
        pointType = 'revive',           -- 'revive' | 'heal'
        maxEMS = 1,                     -- Hide point when EMS count > this
        cost = 5000,                    -- Cash cost (0 = free)
        location = {                    -- World coordinates
            x = 360.08,
            y = -585.10,
            z = 28.82,
        },
        NPCEnabled = true,             -- Spawn an NPC at this point
        NPCPed = 's_f_y_scrubs_01',    -- Ped model name
        NPCPedPosition = {             -- NPC spawn position + heading
            x = 359.62,
            y = -584.95,
            z = 27.82,
            h = 251.0,
        },
        whitelistedJobs = {},           -- {} = all jobs | {'gang', 'mafia'}
        blip = {
            enabled = true,
            sprite = 51,                -- GTA blip sprite ID
            scale = 0.9,
            color = 1,                  -- GTA blip color ID
        },
        marker = {
            type = 2,                   -- GTA marker type ID
            rgb = { r = 255, g = 0, b = 0 },
        },
    },
    -- ... more points
}
```

| Field             | Type    | Required | Description                              |
| ----------------- | ------- | -------- | ---------------------------------------- |
| `pointType`       | string  | ✅        | `'revive'` or `'heal'`                   |
| `maxEMS`          | number  | ✅        | Max EMS online before point is hidden    |
| `cost`            | number  | ✅        | Cash cost, 0 for free                    |
| `location`        | table   | ✅        | World coordinates `{x, y, z}`            |
| `NPCEnabled`      | boolean | ❌        | Whether to spawn an NPC (default: false) |
| `NPCPed`          | string  | ❌        | Ped model hash name                      |
| `NPCPedPosition`  | table   | ❌        | NPC position `{x, y, z, h}`              |
| `whitelistedJobs` | table   | ❌        | Empty = all jobs allowed                 |
| `blip`            | table   | ❌        | Map blip configuration                   |
| `marker`          | table   | ❌        | 3D marker configuration                  |

### Carry System

```lua
Config.CarryEnabled = true            -- Enable /carry command
Config.CarryCommand = 'carry'         -- Command name
```

### Discord Webhooks

```lua
Config.WebhookEnabled = false
Config.WebhookServerName = 'XeX Server'
Config.Webhook = ''                   -- Discord webhook URL
Config.DateFormat = '%d/%m/%Y [%X]'
Config.IconUrl = 'https://i.imgur.com/EpqKImZ.png'
Config.BotName = 'Auto Medical Bot'
```

***

## How It Works

### Complete Flow

Player approaches medical point → Marker/ox\_target appears (if allowed) → Player interacts (E key or ox\_target):

* Heal: Checks HP < max → charges cost → heals to full → webhook
* Revive: Finds nearest player → checks if dead → charges cost → plays medic animation (10s) → carries (optional) → revives → webhook
* Point hidden if EMS count exceeds maxEMS threshold

### EMS Count Restriction

The server tracks online EMS players in real-time:

* When a player loads with job matching `Config.EMSJobName`, count increments
* When a player changes to/from the EMS job, count updates
* When an EMS player disconnects, count decrements
* Count is broadcast to all clients via `xex_medicalhelp:updateEmsCount`
* Points with `maxEMS < currentEMSCount` are hidden

Use case: When enough real EMS players are online, NPC heal/revive points automatically disappear, encouraging roleplay with real medics.

### Job Whitelisting

Each point can restrict access to specific jobs:

```lua
whitelistedJobs = {}          -- Empty: open to everyone
whitelistedJobs = {'gang'}    -- Only 'gang' job can see/use this point
whitelistedJobs = {'gang', 'mafia'}  -- Multiple jobs allowed
```

This allows creating "illegal" medical points restricted to criminal organizations.

The `isAllowedJobForPoint()` function supports both:

* String job data (ESX format: `myJob = 'police'`)
* Table job data (QB/QBx format: `{name = 'police', grade = 2}`)

### ox\_target vs Marker Mode

| Feature       | ox\_target Mode             | Marker + E Mode                     |
| ------------- | --------------------------- | ----------------------------------- |
| Activation    | `Config.UseOxTarget = true` | `Config.UseOxTarget = false`        |
| Interaction   | Click target icon           | Press E key                         |
| NPC targeting | Entity target on NPC        | Proximity check                     |
| No NPC        | Sphere zone at coords       | Marker at coords                    |
| Performance   | Better (event-based)        | Polling loop (1ms near, 2500ms far) |
| Dependency    | Requires ox\_target         | None                                |

### Revive Mechanics

1. Player interacts with a revive point
2. Finds closest player within 5 units
3. Checks if target player is dead (`health == 0`)
4. If cost > 0, deducts cash via server callback
5. Plays `CODE_HUMAN_MEDIC_TEND_TO_DEAD` scenario (10 seconds)
6. Optionally triggers carry command
7. Triggers revive event:
   * ESX: `esx_ambulancejob:revive`
   * QB: `hospital:client:Revive`
   * QBx: `hospital:client:Revive` (via ox\_lib)

### Heal Mechanics

1. Player interacts with a heal point
2. Checks current HP < max HP
3. If cost > 0, deducts cash via server callback
4. Server triggers client-side heal (`SetEntityHealth` to max)
5. Shows notification

### Carry System Mechanics

The carry system uses a fireman's carry animation:

1. Player executes `/{CarryCommand}` (default: `/carry`)
2. Finds closest player within 5 units
3. First press: attaches target to carrier with carry animation
4. Second press: detaches target and stops animation
5. All carry operations sync through server events

***

## Interaction Modes

### Marker + E Key Mode

When `Config.UseOxTarget = false`:

* 3D markers render at each point within `Config.DrawDistance`
* Help text shows when within 1.5 units
* Press E to interact
* Dynamic wait loop: 1ms near markers, 2500ms when idle

### ox\_target Mode

When `Config.UseOxTarget = true`:

* If NPC is enabled: entity target registered on the NPC ped
* If no NPC: sphere zone at point coordinates (radius 1.5)
* `canInteract` checks: not busy, EMS count, job whitelist
* Icons: `fas fa-heartbeat` (revive), `fas fa-medkit` (heal)

***

## NPC System

Each point can optionally spawn an NPC:

```lua
NPCEnabled = true,
NPCPed = 's_f_y_scrubs_01',
NPCPedPosition = { x = 359.62, y = -584.95, z = 27.82, h = 251.0 },
```

NPCs are configured with:

* Invincible — cannot be killed
* Frozen — cannot be pushed or moved
* Non-reactive — blocks fleeing behavior and temporary events
* Animation — plays `missfbi_s4mop > guard_idle_a` idle animation
* Cleanup — model marked as no longer needed after spawn

***

## Exports & Events

### Server Exports

```lua
-- Trigger manual update check
exports['xex_medicalhelp']:CheckForUpdates()
```

### Server Callbacks

| Callback              | Parameters | Returns   | Description                            |
| --------------------- | ---------- | --------- | -------------------------------------- |
| `xex_revivehelp:paid` | `amount`   | `boolean` | Deduct cash and return success/failure |

### Server Events

| Event                    | Parameters | Description                    |
| ------------------------ | ---------- | ------------------------------ |
| `xex_medicalhelp:heal`   | —          | Heal the triggering player     |
| `xex_medicalhelp:revive` | `targetId` | Revive target player           |
| `xex_medicalhelp:sync`   | carry data | Sync carry animation to target |
| `xex_medicalhelp:stop`   | `targetId` | Stop carry on target           |

### Client Events

| Event                            | Parameters | Description                              |
| -------------------------------- | ---------- | ---------------------------------------- |
| `xex_medicalhelp:updateEmsCount` | `count`    | Update local EMS count                   |
| `xex_medicalhelp:setMyJob`       | `jobName`  | Update local player job                  |
| `xex_medicalhelp:heal`           | —          | Apply heal (set max HP)                  |
| `xex_medicalhelp:syncTarget`     | carry data | Apply carry animation to carried player  |
| `xex_medicalhelp:syncMe`         | carry data | Apply carry animation to carrying player |
| `xex_medicalhelp:cl_stop`        | —          | Stop carry animation and detach          |

### Commands

| Command              | Context        | Description                                            |
| -------------------- | -------------- | ------------------------------------------------------ |
| `/{CarryCommand}`    | Client         | Toggle carrying the nearest player (default: `/carry`) |
| `medicalhelp_update` | Server Console | Manual update check                                    |

***

## Localization

### Supported Languages

| Code | Language |
| ---- | -------- |
| `en` | English  |
| `es` | Español  |

### Locale Keys Reference

| Key                     | English                      | Description                      |
| ----------------------- | ---------------------------- | -------------------------------- |
| `heal_blip_text`        | Heal                         | Map blip label for heal points   |
| `revive_blip_text`      | Revive                       | Map blip label for revive points |
| `press_to_revive`       | Press \[E] to revive injured | Interaction prompt               |
| `press_to_heal`         | Press \[E] to heal wounds.   | Interaction prompt               |
| `heal_in_progress`      | Heal in progress...          | During animation                 |
| `healed`                | You have healed your wounds  | Heal success                     |
| `heal_completed_to`     | %s healed                    | Revive success (with name)       |
| `not_dead_player`       | Player is not dead           | Cannot revive living player      |
| `no_money`              | You don't have enough money  | Insufficient funds               |
| `not_nearby`            | There is no one around       | No player in range               |
| `already_full`          | You are already full health  | Cannot heal at max HP            |
| `webhook_heal_action`   | Heal                         | Webhook embed field              |
| `webhook_heal_title`    | Someone has been healed      | Webhook embed title              |
| `webhook_revive_action` | Has revived %s               | Webhook embed field              |
| `webhook_revive_title`  | Someone has been resurrected | Webhook embed title              |

### Adding Languages

Add a new entry in `locales.lua`:

```lua
Locales['fr'] = {
    ['heal_blip_text'] = 'Soigner',
    ['revive_blip_text'] = 'Réanimer',
    -- ... all keys
}
```

Then set `Config.Language = 'fr'` in `config.lua`.

***

## File Structure

```
xex_medicalhelp/
├── client/
│   ├── esx.lua               # ESX client — heal/revive/carry, markers, ox_target
│   ├── qb.lua                # QBCore client mirror
│   ├── qbx.lua               # QBox client (requires ox_lib)
│   └── utils.lua             # Shared: NPC spawning, job check, heal event
├── server/
│   ├── esx.lua               # ESX server — EMS tracking, payment, webhook
│   ├── qb.lua                # QBCore server mirror
│   ├── qbx.lua               # QBox server (requires ox_lib)
│   └── updater.lua           # Version checker
├── config.lua                # All configuration
├── locales.lua               # Translations (en/es)
├── fxmanifest.lua            # Resource manifest
├── readme.md                 # Quick start readme
└── DOCS.md                   # This documentation
```

***

## Security

| Measure                    | Description                                                    |
| -------------------------- | -------------------------------------------------------------- |
| Server-side payment        | Cash deduction validated on server via callback                |
| EMS count server-tracked   | Count managed entirely server-side, broadcast to clients       |
| Job validation client-side | `isAllowedJobForPoint()` checks job before showing interaction |
| Revive target validation   | Checks closest player exists, is within range, and is dead     |
| isBusy guard               | Prevents spamming interactions while animation plays           |
| Carry distance check       | Carry only works within 5 units of target player               |

***

## Performance

| Aspect          | Detail                                                  |
| --------------- | ------------------------------------------------------- |
| ox\_target mode | Event-based — zero polling when not interacting         |
| Marker mode     | 1ms near markers, 2500ms when idle                      |
| NPC spawn       | Model released after spawn (`SetModelAsNoLongerNeeded`) |
| Carry loop      | 1ms during carry, 1500ms when idle                      |
| EMS updates     | Only on job change/connect/disconnect events            |

***

## Troubleshooting

<details>

<summary>Points not showing</summary>

Check \`maxEMS\` — points hide when enough EMS are online.

</details>

<details>

<summary>Revive not working</summary>

Check \`esx\_ambulancejob\` is running (ESX) or death system is compatible.

</details>

<details>

<summary>ox_target not working</summary>

Verify \`ox\_target\` is started and \`Config.UseOxTarget = true\`.

</details>

<details>

<summary>NPC not spawning</summary>

Check \`NPCEnabled = true\` and ped model name is valid.

</details>

<details>

<summary>Carry not working</summary>

Check \`Config.CarryEnabled = true\` and target is within 5 units.

</details>

<details>

<summary>Job filter not working</summary>

Verify \`whitelistedJobs\` uses exact job names from your framework.

</details>

<details>

<summary>Payment failing</summary>

Check player has enough cash (cost is deducted from cash, not bank).

</details>

<details>

<summary>QBox errors</summary>

Ensure \`ox\_lib\` is started **before** this resource.

</details>

***

## Changelog

### v1.3.1

* Bug fixes and stability improvements

### v1.3.0

* Added QBox (QBx) framework support with ox\_lib integration
* Added modern JSON-based auto-updater system
* Removed legacy inline version check from framework files
* Optimized client marker loops (vector math, cached variables)
* Fixed `isBusy` variable casing inconsistency
* Fixed QB EMS count logic (job change tracking was inverted)
* Fixed blip names showing 'Heal' for revive points
* Added nil checks on server events
* Added `SetModelAsNoLongerNeeded` for NPC spawning
* Updated `isAllowedJobForPoint` for both string and table job data

### v1.2.0

* Major fix on EMS count for ESX + QBCore initial markers loading

### v1.1.1

* Distance check on /carry

### v1.1.0

* Reorganized configuration for unlimited map points
* Added configurable props, blips, and markers per point
* Added job restriction per point (illegal trades)

### v1.0.0

* Initial release

***

## Support

| Channel | Link                                                   |
| ------- | ------------------------------------------------------ |
| Discord | [discord.gg/9yY3Jxnhh8](https://discord.gg/9yY3Jxnhh8) |

***


---

# Agent Instructions: Querying This Documentation

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

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://jesus-gimenez.gitbook.io/xex-scripts/premium-mods/medical-help.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
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.
