# Welcome to QF Developers Documentation

Your complete guide to installing, configuring, and customizing our premium FiveM scripts — designed for maximum performance, flexibility, and ease of use.\
\
Here you’ll find everything you need to. Our goal is to make your setup process fast, clean, and developer-friendly.

### Let’s build something great together!


# How to Install Resources

Page dedicated to how to install our scripts

#### 📦 Installation & Configuration Guide

This video demonstrates the installation process using the **MDT LSPD** script as an example.\
However, the setup steps are nearly identical for all QF Developers scripts.\
You can follow this guide to install and configure **any** of our resources on your FiveM server.

{% embed url="<https://www.youtube.com/watch?v=KRD-V27kuSc>" %}


# How to use Key Mapping

Page dedicated how key mapping works in FiveM

#### 🎮 Keybinding System & Customization

We’ve implemented native `RegisterKeyMapping` support in our scripts to boost performance and eliminate the need for constant `while` loops monitoring key inputs.\
Thanks to this, key detection is now **event-based**, making the resource significantly more efficient.

With this system:

* Keybinds are assigned to specific chat commands.
* The associated actions are only triggered when the defined key is pressed.
* Players can fully customize their keybinds through the in-game menu:\
  **GTA V > Settings > Key Bindings > FiveM**

***

#### 🔧 How to Update or Unbind a Key

After first launching the script on your server, any changes to keybinds in `config.lua` **won’t apply** to players who have already joined.\
Only new players will receive the updated keybinds automatically.

If a player wants to reset or unbind the key manually, there are two options:

**Option 1 – via F8 Console:**

```
unbind keyboardinput_parameter
```

**Option 2 – via File Cleanup:**

1. Go to:\
   `C:\Users\[USERNAME]\AppData\Roaming\CitizenFX`
2. Open the `fivem.cfg` file.
3. Remove any lines related to the keybind for this script.
4. Restart FiveM.\
   → The keybind will now reset to the default value set in `config.lua.`


# FiveM Escrow Errors

Page dedicated on FiveM Escrow Errors

#### 🔐 Error: *You lack the required entitlement to use script\_name*

This error appears when the script cannot verify your ownership through the FiveM Escrow system.

***

#### 🧾 Why does this happen?

All escrow-protected scripts (like ours) are bound to the **FiveM account** used during the **Tebex purchase**.

To work correctly, the script must run on a server that uses a **server key** created by the **same FiveM account**.

***

#### 🔑 What is a server key?

* The **server key** is a license key generated via FiveM Keymaster.
* It is **not** a script key — FiveM servers can only use **one** server key at a time.

**Example:**

```cfg
sv_licenseKey "39dz2edscjkvnxklzciupczdijo"
```

***

#### ✅ How to check your server key?

Use the following command in your FiveM server console:

```
sv_licenseKey
```

Take note of the key being used.

***

#### ✅ How to confirm you're using the correct key?

1. Run `sv_licenseKey` in your server console to see the active key.
2. Go to FiveM Keymaster.
3. Log in with the account **that owns the purchased script(s)**.
4. Check if the server key was generated by the same account.
   * If **not**, you'll need to:
     * either **generate a new key** under your account,
     * or **transfer the script** to the account that created the current server key.

***

#### 🔄 How to transfer script ownership?

1. Go to **FiveM Keymaster** → **Purchased Assets** tab.
2. Click the **Transfer to another account** button (red).\
   ⚠️ *Note: Scripts can only be transferred **once** per FiveM policy.*

***

#### 🌐 ZAP-Hosting Users

If you're using **ZAP-Hosting**, you **don’t** need to add the key to `server.cfg`.\
Instead, paste it directly in the ZAP dashboard.\
For more info, see their official guide.


# Multicharacter

This category is for our Multicharacter

**Redefine the beginning of every story on your server with our Advanced Multicharacter.** The entry point to your server should be more than just a list – it should be an immersive experience that reflects the quality of your community.

**Much more than a character list.** Our system features cinematic intro cutscenes tailored to each character slot, automatic mugshot generation for a professional UI, and a unique "Starter Items" shop that allows players to spend a starting budget on essential gear before they even set foot in the city.

<figure><img src="/files/89BHHeNaSGfFJfuI99AI" alt=""><figcaption></figcaption></figure>


# Installation

Page dedicated to how to install our Multicharacter

## Step #1 - Drag & Drop

Just Drag & Drop the `qf_multicharacter` folder into your `resouces` folder.

## Step #2 - SQL Installation

{% hint style="info" %}
There’s no need to manually insert any SQL file into your database. Our script automatically handles all necessary database entries on first launch, so you can safely skip this step.
{% endhint %}

## Step #3 - Script start

You can easily start our script using one of the following methods:

1. Type `ensure qf_multicharacter` in your server console or F8 console.\
   This will start or restart the script live on your server.
2. Add `ensure qf_multicharacter` to your `server.cfg` in the appropriate place.\
   This ensures the script launches automatically every time your server starts.

{% hint style="warning" %}
**Warning: Fivemanage Mugshots** If you choose to use the Fivemanage API for generating and hosting character mugshots, you must define your API key as a console variable. Add this to your `server.cfg`: `setr qf_multicharacter_mugshot_fivemanage_api_key "YOUR_FIVEMANAGE_API_KEY_HERE"`
{% endhint %}


# Configuration

Page dedicated to how to configure our Multicharacter

#### Configuration Guide (`config.lua`)

**Framework & Inventory Detection** While the script attempts to auto-detect your framework, you must explicitly define your inventory system so starter items are distributed correctly.

```lua
-- Supported options: 'ox_inventory', 'esx', 'qb'
Config.Inventory = 'ox_inventory' 
```

**Language & Formatting** One option drives both the translation files in `locales/` and the number and date formatting inside the UI. Both notations are accepted, so `'de'` and `"de-DE"` resolve to the same translation.

```lua
Config.Locale = "en-US" -- en, de, es, fr, it, ja, ko, pl, pt
Config.Currency = "USD"
Config.DateFormat = "MM/dd/yyyy"
```

Missing keys in a translation fall back to English, so a partially translated locale never shows raw keys.

{% hint style="info" %}
Up to and including **1.3.1** `Config.Locale` was declared twice in `config.lua`, and the second declaration silently overwrote the first — the server then always fell back to English. Fixed in **1.3.2**. On older versions, make sure only one `Config.Locale` line exists in your `config.lua`.
{% endhint %}

**Character Slot Management** You have absolute control over how many characters a player can create. The `Config.Slots` array determines the maximum slot count and the properties of each slot.

```lua
Config.Slots = {
    { type = "free" }, -- Slot 1: Available immediately
    { type = "free" }, -- Slot 2: Available immediately
    { type = "paid", url = "https://yourtebex.com/category/slots" }, -- Slot 3: Shows a purchase prompt
    { type = "locked" }, -- Slot 4: Completely hidden until unlocked by an Admin
}
```

**Cinematic Cutscenes** You can map specific interior locations to specific character slots to create unique backdrops during selection.

```lua
Config.Cutscenes = {
    -- Slot 1 will load the Agency Office interior with a specific timecycle modifier
    [1] = { 
        name = "fix_agy_int1", 
        timecycle = "super_lod", 
        coords = vector3(-1147.0691, -1522.1497, 10.6327) 
    },
}
```

**Starter Items** Packages offered to a player during character creation. Every item accepts an optional `metadata` table, passed on as ox\_inventory metadata or qb-inventory info.

```lua
Config.StarterItems = {
    enable = true,
    packages = {
        {
            id = "basic",
            label = "Basic Starter Package",
            description = "Essential food, water, and tools to get you started.",
            default = true, -- given when the player is not asked to choose
            items = {
                { name = "burger", count = 3, label = "Burger", icon = "utensils" },
                { name = "water",  count = 5, label = "Water",  icon = "droplet" },
            }
        }
    }
}
```

`label` and `icon` are only used for the preview in the UI, `name` and `count` are what actually reaches the inventory.

**Metadata placeholders** Values inside `metadata` may contain placeholders that are filled with the freshly created character, so documents can be handed out already completed:

`%firstname%` `%lastname%` `%fullname%` `%birthdate%` `%gender%` `%sex%` `%nationality%` `%height%` `%citizenid%`

```lua
{
    name = "id_card", count = 1, label = "ID Card", icon = "id-card",
    metadata = {
        firstname   = "%firstname%",
        lastname    = "%lastname%",
        birthdate   = "%birthdate%",
        gender      = "%gender%",
        nationality = "%nationality%",
        citizenid   = "%citizenid%"
    }
},
{
    name = "driver_license", count = 1, label = "Driver License", icon = "id-card",
    metadata = {
        firstname = "%firstname%",
        lastname  = "%lastname%",
        birthdate = "%birthdate%",
        type      = "Class C Driver License"
    }
}
```

Adjust the item names and the metadata keys to whatever your ID card script expects. Items carrying metadata are never merged into a single stack, so two documents stay two separate entries. Unknown placeholders are left in the text untouched.

{% hint style="info" %}
`metadata` requires **1.3.2** or newer.
{% endhint %}

**Character Templates & Starting Wealth** If `Config.CharacterTemplate.enable = true`, players are prompted to select a "Background" (e.g., Gangster, Civilian, Police) during creation. This background defines their starting cash, bank balance, and potentially starting vehicles.

If templates are disabled, you must define the default starting money using a strict JSON string:

```lua
Config.DefaultMoneyQuery = '{"bank":50000,"money":500}'
```


# Additional Informations

Page dedicated to Additional Informations about our Multicharacter

#### Core Features

* **Universal Framework Support:** Built natively for ESX, QBCore, and QBox environments.
* **Mugshot Engine:** Integrates seamless mugshot generation directly within the UI, saving locally or via Fivemanage.
* **Starter Packages:** Define item kits (food, phone, ID) that are injected into the player's inventory upon first creation.
* **Admin Management:** In-game UI for administrators to wipe characters or grant additional slots to supporters.

#### Commands & Permissions

To utilize administrative commands, players must have the required Ace Permissions. Below is the mapping of commands to their required permissions.

| Command        | Permission Node     | Description                                                                                          |
| -------------- | ------------------- | ---------------------------------------------------------------------------------------------------- |
| `/relog`       | `qf.identity.relog` | Safely disconnects the player from their current character and returns them to the selection screen. |
| `/charadmin`   | `qf.identity.admin` | Opens the graphical Admin Management Panel.                                                          |
| `/delchar`     | `qf.identity.admin` | Forcefully deletes a specific character ID.                                                          |
| `/delallchars` | `qf.identity.admin` | Deletes every character belonging to a player.                                                       |
| `/unlockslot`  | `qf.identity.admin` | Grants a locked character slot to a specific player license.                                         |

**Assigning Permissions in `server.cfg`:**

```cfg
add_ace group.admin qf.identity.admin allow
add_ace group.admin qf.identity.relog allow
```

Command names, permission nodes and the required framework group are all configurable in `Config.Commands`, the panel itself in `Config.AdminPanel`. Besides the Ace permission, membership of the group configured there (`admin` by default) is accepted as well.

#### Developer API (Events & Lifecycle)

For server developers looking to synchronize external systems (like housing, garages, or custom spawn logic) with the character selection process, `qf_identity` triggers specific client and server-side events.

**1. Player Loaded Event (Client-Side)**

When a character is selected and loaded successfully into the active session, the script emits the following client-side event. This is the optimal place to initialize player HUDs, radars, or custom client scripts.

```lua
-- CLIENT-SIDE
-- Fired when a character is selected and loaded
RegisterNetEvent('qf_identity:bridge:playerLoaded', function(playerData)
    -- playerData contains core player details (identifier, accounts, job, etc.)
    print("Character loaded client-side! Initializing HUD...")
    exports['my_custom_hud']:EnableHud(true)
end)
```

Additionally, the script continues to emit standard framework events for backwards compatibility:

* **ESX:** `esx:playerLoaded`
* **QBCore / QBox:** `QBCore:Client:OnPlayerLoaded`

**2. Triggering Relog Programmatically**

To log a player out and return them to the character selection screen via code, you can use these events, grouped by execution side below:

{% tabs %}
{% tab title="Client-Side Trigger" %}

```lua
-- CLIENT-SIDE
-- Instantly log the local player out and return them to character selection
TriggerEvent('qf_identity:relog')
```

{% endtab %}

{% tab title="Server-Side Trigger" %}

```lua
-- SERVER-SIDE
-- Force a specific player ID to logout and return to character selection
local targetPlayerId = 1
exports['qf_identity']:Logout(targetPlayerId)
```

{% hint style="warning" %}
Use the export rather than triggering `qf_identity:relog_setup` yourself. The event only sends the player back to the character screen, it does **not** unload them from the framework — the core would still hold a loaded character for that source, which other resources do not expect. The export requires **1.3.2** or newer.
{% endhint %}
{% endtab %}
{% endtabs %}

***

#### Frequently Asked Questions (Q\&A)

**Q: Players are falling through the map during character selection. How do I fix this?**\
A: This occurs when the coordinates specified in `Config.Cutscenes` do not have the ground collision loaded in time. Ensure the `name` of the interior is a valid, natively loaded IPL or a reliably streamed MLO. You can also adjust `Config.SelectionCoords` to a safe coordinate.

**Q: How does the script handle skin creation for new characters?**\
A: By setting `Config.SkinManager = 'qf_skinmenu'`, our script will automatically yield to the skin creator menu. Once the player finishes creating their ped, the multicharacter sequence resumes and spawns them.

**Q: How can I change the background music of the selection screen?**\
A: You can configure the audio settings, including volume and music, directly within the `config.lua` file. Ensure the track links point to raw audio files (`.mp3` or `.ogg`).


# Loading Screen

This category is for our Loading Screen

**Make every second of waiting count with our Premium Loading Screen.** The first thing your players see is the standard you set for your server. Transform a simple loading bar into an immersive introduction to your community.

**Beyond just a loader.** Our loading screen is a high-performance information hub. Showcase your staff, teach your players with rotating tips, display your unique keybinds, and let them enjoy a curated playlist while they wait to join the action.

<figure><img src="/files/yOtjzGi41g1gKDjeSAdj" alt=""><figcaption></figcaption></figure>


# Installation

Page dedicated to how to install our Loading Screen

## Step #1 - Drag & Drop

Just Drag & Drop the `qf_loadscreen` folder into your `resouces` folder.

## Step #2 - SQL Installation

{% hint style="info" %}
There’s no need to manually insert any SQL file into your database. Our script automatically handles all necessary database entries on first launch, so you can safely skip this step.
{% endhint %}

## Step #3 - Script start

You can easily start our script using one of the following methods:

1. Type `ensure qf_loadscreen` in your server console or F8 console.\
   This will start or restart the script live on your server.
2. Add `ensure qf_loadscreen` to your `server.cfg` in the appropriate place.\
   This ensures the script launches automatically every time your server starts.


# Configuration

Page dedicated to how to configure our Loading Screen

#### Configuration Guide (`config/config.lua`)

The configuration file is structured to be self-explanatory, but below are the critical sections explained in depth.

**UI Branding & Colors** The loadscreen utilizes modern HSL (Hue, Saturation, Lightness) values for primary colors. This allows for dynamic theming across the UI components.

```lua
Config.Locale = "en-US"
-- HSL format (Hue Saturation% Lightness%) - Do NOT use HEX or RGB here.
Config.PrimaryColor = "223 99% 59%" 
Config.LogoUrl = "https://yourwebsite.com/logo.svg"
```

{% hint style="info" %}
**Tip: Asset Hosting** To significantly reduce client downloading times when they connect to your server, host all your media (Logos, Backgrounds, Audio) on an external Content Delivery Network (CDN) or Discord/Imgur, rather than streaming them directly from the FiveM server.
{% endhint %}

**Media & Backgrounds** You can define an array of background images that the loadscreen will cycle through.

```lua
Config.Background = {
    type = "images",
    images = {
        "https://link-to-your-image-1.jpg",
        "https://link-to-your-image-2.jpg"
    },
}
```

**Audio Engine** The built-in audio player supports multiple tracks.

```lua
Config.Songs = {
    {
        id = 1,
        title = "Los Santos Vibes",
        authors = { "Artist Name" },
        coverUrl = "https://link-to-album-art.jpg",
        audioUrl = "https://link-to-audio-track.mp3", -- Must be a direct raw audio file (.mp3, .ogg)
    },
}
```


# Additional Informations

Page dedicated to Additional Informations about our Loading Screen

#### Core Features

* **Component Modularity:** Toggle every single UI element on or off via `Config.Components` (Logo, Hotkeys, Audio Player, Staff Showcase, FAQ, etc.).
* **Dynamic Announcements:** Inform players about updates, sales, or events directly on the loading screen using the rich announcement cards.
* **Interactive UI:** Players can browse images, read FAQs, and control the music volume while waiting for the game engine to initialize.

#### Developer API (Natives & Loading Control)

While loading screens operate primarily in a NUI (browser) context separate from the main game loop, there are times when custom server frameworks need to manually control when the loadscreen disappears.

{% hint style="info" %}
**Manual Shutdown:** If your `fxmanifest.lua` has `loadscreen_manual_shutdown 'yes'` enabled, the loadscreen will stay open indefinitely until you explicitly close it. This is useful for keeping the loading screen active while custom character selectors or login scripts load assets.
{% endhint %}

To terminate the loading screen from another client resource (such as your spawning, login, or multicharacter script), you should call the standard FiveM client natives:

```lua
-- CLIENT-SIDE
-- Call this once the player character is fully loaded, spawned, and ready to play.
RegisterNetEvent('myFramework:playerFullyLoaded', function()
    -- Perform custom camera movements, ped spawning, etc.
    DoScreenFadeOut(0)
    
    -- Terminate the loading screen UI and native game overlay
    ShutdownLoadingScreen()
    ShutdownLoadingScreenNui()
    
    -- Fade the game back in smoothly
    Wait(1000)
    DoScreenFadeIn(1000)
end)
```

#### Frequently Asked Questions (Q\&A)

**Q: How do I change the icons used in the menu?**\
A: The script utilizes the Iconify framework. You can search for thousands of free icons at [Iconify Design](https://icon-sets.iconify.design/). Simply copy the icon identifier (e.g., `lucide:home`) and paste it into your `Config.Icons`.

**Q: Why isn't the music playing automatically when I join?**\
A: Modern web browsers (including the Chromium Embedded Framework used by FiveM) enforce strict autoplay policies to prevent unwanted audio. Audio will only begin playing once the user interacts with the screen (e.g., clicking anywhere, pressing a hotkey).

**Q: How do I use local files instead of web URLs?**\
A: Place your media files inside the `web/dist` folder (we recommend creating an `assets` subfolder). You can then reference them using relative paths in your config: `"assets/background1.jpg"`.


# Spawn Selector \[V2]

This category is for our Spawn Selector \[V2]

**Redefine the player's entrance to your world with our Advanced Spawn Selector.** A high-end, visual gateway that provides a seamless transition from character selection to the game world.

**First impressions matter.** Give your players a modern, bird's-eye view of Los Santos. With interactive locations, preview images, and smooth camera transitions, your server's starting experience will feel premium and professional from the very first second.

<figure><img src="/files/7dvfkpP5jYszUXuyQogm" alt=""><figcaption></figcaption></figure>


# Installation

Page dedicated to how to install our Spawn Selector \[V2]

## Step #1 - Drag & Drop

Just Drag & Drop the `qf_spawnselector_v2` folder into your `resouces` folder.

## Step #2 - SQL Installation

{% hint style="info" %}
There’s no need to manually insert any SQL file into your database. Our script automatically handles all necessary database entries on first launch, so you can safely skip this step.
{% endhint %}

## Step #3 - Script start

You can easily start our script using one of the following methods:

1. Type `ensure qf_spawnselector_v2` in your server console or F8 console.\
   This will start or restart the script live on your server.
2. Add `ensure qf_spawnselector_v2` to your `server.cfg` in the appropriate place.\
   This ensures the script launches automatically every time your server starts.


# Configuration

Page dedicated to how to configure our Spawn Selector \[V2]

#### Configuration Guide (`config/config.lua` & `config/default_data.lua`)

**Behavioral Settings** The script's behavior drastically changes depending on whether you are using a character selection screen before it.

```lua
-- SET TO TRUE: If you are using qf_identity.
-- qf_identity will manually command the spawn selector to open when needed.
Config.UsingQFIdentity = true

-- Event fired by the "Back" button when you are NOT using qf_identity.
-- e.g. "esx:relog", "qb-multicharacter:client:chooseChar"
Config.RelogEvent = "esx:relog"

-- Shows the "Back" button that returns the player to the character selection.
Config.EnableBackButton = true

-- SET TO TRUE: ONLY if you are NOT using a multicharacter script.
-- This forces the spawn selector to automatically trigger the moment the player connects.
Config.AutoOpen = false

-- Toggles the iconic GTA V "zoom out to clouds, zoom into ground" cinematic camera effect.
Config.UseGTASwitch = true

-- Allows the player to select the exact coordinate where they previously disconnected.
Config.AllowLastLocation = true

-- Camera position while the player is choosing a spawn.
Config.SelectionCoords = vector4(-862.8547, -1606.7404, 52.8938, 353.5509)
```

{% hint style="danger" %}
**Danger: Conflicting Triggers** If `Config.AutoOpen` is set to `true` while a multicharacter script is active, players will experience overlapping UIs, broken cameras, and potential soft-locks. Ensure `AutoOpen` is strictly `false` when paired with multicharacter systems.
{% endhint %}

**Appearance & Language**

```lua
-- Accent colour of the interface.
Config.PrimaryColor = "#2F6AFE"

-- pl-PL, en-US, de-DE, es-ES, fr-FR, it-IT, ja-JP, ko-KR, pt-PT, ru-RU, tr-TR
Config.Locale = 'en-US'

-- Fallback icons, used when a spawn does not define its own `icon`.
Config.Icons = {
    location = "mdi:location",
    locationSelected = "mdi:location-circle",
    dollar = "lucide:dollar-sign",
    lock = "material-symbols:lock",
}
```

**Cinematic Spawn** The camera flight played once the player has confirmed their choice.

```lua
Config.CinematicSpawn = {
    enabled = true,
    skippable = true,    -- the player can skip the flight by pressing SPACE
    flyDuration = 4000,  -- ms, camera flying from top down in front of the character
    viewDuration = 2000, -- ms, how long the character is admired afterwards
    camOffset = vector3(0.0, 3.0, 0.5), -- camera position relative to the player
    scenarios = {
        "WORLD_HUMAN_SMOKING",
        "WORLD_HUMAN_AA_COFFEE",
        "WORLD_HUMAN_TOURIST_MAP"
    }
}
```

***

### Defining Spawn Locations

Locations are defined in `config/default_data.lua`, in the global table `DefaultSpawns`. You can restrict specific spawns to certain jobs or assign a cost to use a spawn point.

```lua
DefaultSpawns = {
    {
        id = "lspd_hq",
        label = "Mission Row PD",
        description = "Authorized personnel only.",
        type = "unlocked",
        price = 0,
        coords = vector4(425.1, -979.5, 30.7, 90.0),
        category = "Jobs",
        icon = "lock",
        -- JOB RESTRICTION: Only Police grade 0 or higher can see/use this spawn
        jobs = {
            { name = "police", grade = 0 }
        }
    },
    {
        id = "motel",
        label = "Pink Cage Motel",
        description = "A cheap place to crash.",
        type = "paid",
        price = 500, -- taken from cash first, then from the bank
        coords = vector4(314.5, -278.5, 54.1, 0.0),
        category = "Public",
        icon = "lucide:bed"
    }
}
```

#### Fields

| Field         | Required | Description                                                                                                                            |
| ------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| `id`          | yes      | Unique key. Also the primary key in the database.                                                                                      |
| `label`       | yes      | Title shown in the list. `name` is accepted as an alias.                                                                               |
| `description` | no       | Subtitle. `desc` is accepted as an alias. Only shown for `unlocked` spawns — `paid` and `locked` display a translated line instead.    |
| `type`        | no       | `unlocked`, `paid` or `locked`. Defaults to `unlocked`.                                                                                |
| `price`       | no       | Only used by `paid`. Taken from cash first, then from the bank.                                                                        |
| `coords`      | yes      | `vector4`, the `w` component is the heading.                                                                                           |
| `category`    | no       | Free text grouping.                                                                                                                    |
| `icon`        | no       | Any Iconify name (`lucide:tree-pine`) or a key of `Config.Icons` (`location`, `dollar`, `lock`). Falls back to the icon of the type.   |
| `jobs`        | no       | List of `{ name = "police", grade = 0 }`. Absent or empty means visible to everyone. The player needs the job and at least that grade. |

#### Spawn types

* **`unlocked`** — open to everyone, subject to `jobs`. `free`, `open` and `public` are accepted as aliases, and any unrecognised value falls back to `unlocked`.
* **`paid`** — costs `price`. Hidden for a brand new character, since a fresh character cannot pay for it yet.
* **`locked`** — shown greyed out and cannot be selected. Use it as a teaser for locations you unlock later.

{% hint style="warning" %}
**`default_data.lua` is only imported into an empty database.** On the first start the spawns are copied into the `qf_spawnselector_spawns` table, and from that moment the database is the source of truth — later edits to the file appear to do nothing.

While you are building your spawn list, set `Config.AlwaysSyncDefaultSpawns = true`. The file is then written over the stored rows on every restart. Turn it back off once you are done, otherwise it overwrites changes made in `/spawnadmin`.
{% endhint %}

#### Editing in game

`/spawnadmin` opens the admin panel, where spawns can be created, edited, reordered, deactivated and deleted — including their job restrictions and icons. Changes are written to the database and pushed to connected players immediately.


# Additional Informations

Page dedicated to Additional Informations about our Spawn Selector \[V2].

#### Core Features

* **Cinematic Engine:** Utilizes native GTA V sky-cam transitions (`SwitchOutPlayer`, `SwitchInPlayer`) for a premium feel.
* **Economic Integration:** Charge players money to spawn in premium or strategic locations.
* **Job Restriction:** Keep faction-specific spawns (like PDs, Hospitals, Gang HQs) hidden from the general public.
* **Audio Ambience:** Built-in music player to maintain atmosphere during the selection phase.

#### Developer API (Events & Hooks)

The Spawn Selector exposes specific events allowing developers to manually trigger the UI, or execute logic the exact moment a player finalizes their spawn choice.

{% tabs %}
{% tab title="Client-Side Trigger" %}
If you have a custom script (such as a tutorial sequence, unique login system, or custom character selection) and want to manually open the spawn selector UI, trigger this client-side event:

```lua
-- CLIENT-SIDE
-- Opens the spawn selector UI
-- @param isNew boolean - Indicates if the player is a brand new character.
-- (Set to true to filter out features like 'last location' and paid spawns for new characters)

local isNewCharacter = false
TriggerEvent('qf_spawnselector_v2:open', isNewCharacter)
```

{% endtab %}

{% tab title="Server-Side Hook" %}
Once the player selects a location and the cinematic sequence concludes, the script registers and handles the spawn completion. If you want other server-side resources to listen to this event, hook into this Net Event:

```lua
-- SERVER-SIDE
-- Listen for player spawn selection completion
RegisterNetEvent('qf_spawnselector_v2:playerSpawned', function(spawnId)
    local src = source -- Server ID of the player who spawned
    
    -- 'spawnId' matches the 'id' field of the selected location (or "last-location")
    if spawnId == "last-location" then
        print(("Player %s resumed from their last known coordinates."):format(src))
    else
        print(("Player %s chose to spawn at: %s"):format(src, spawnId))
    end
    
    -- Example: Set custom routing bucket or give clothing items based on spawn choice
    SetPlayerRoutingBucket(src, 0)
    
    if spawnId == "lspd_hq" then
        -- Trigger job-uniform equip logic
    end
end)
```

{% endtab %}

{% tab title="Client-Side Hook" %}
Fired locally once the ped has been placed, collision has streamed in and the player has control. In cinematic mode it fires **after** the camera flight, not before it — use it to decide when your HUD may come up.

```lua
-- CLIENT-SIDE
AddEventHandler('qf_spawnselector_v2:client:playerSpawned', function(spawnId)
    -- The player is now standing in the world and is in control.
    print(("Spawned at: %s"):format(spawnId))
end)
```

{% endtab %}
{% endtabs %}

***

#### Frequently Asked Questions (Q\&A)

**Q: The camera gets stuck in the sky and never drops down. What is wrong?**\
A: This happens when the framework (ESX/QBCore) fails to load the player's data in time, or another script is freezing the player entity. Press F8 to check for client-side errors. Ensure your framework is fully initialized before triggering the spawn sequence.

**Q: How do I remove the cinematic sky-drop effect?**\
A: Open `config.lua` and set `Config.UseGTASwitch = false`. The UI will simply fade out, and the player will instantly teleport to their selected coordinates.

**Q: How do I restrict specific spawn points to factions or jobs?**\
A: You can configure the jobs filter inside `config/default_data.lua` by specifying the required job names and minimum grades. Unallowed players will not see those spawn points in the UI.


# Skin Menu \[V2]

This category is for our Skin Menu \[V2]

**Elevate your server's character customization with our Advanced Skin Menu.** The ultimate, all-in-one appearance system to take your community's roleplay to the next level.

**Move beyond the basics.** Empower your players with a high-performance tool to manage their identity, style, and unique look in real-time. From detailed DNA manipulation to extensive wardrobe management, everything is seamlessly connected with a modern, intuitive interface.

<figure><img src="/files/4Hp68zbyhz4Hgyje6Dpr" alt=""><figcaption></figcaption></figure>


# Installation

Page dedicated to how to install our Skin Menu \[V2]

## Step #1 - Drag & Drop

Just Drag & Drop the `qf_skinmenu_v2` folder into your `resouces` folder.

## Step #2 - SQL Installation

{% hint style="info" %}
There’s no need to manually insert any SQL file into your database. Our script automatically handles all necessary database entries on first launch, so you can safely skip this step.
{% endhint %}

## Step #3 - Script start

You can easily start our script using one of the following methods:

1. Type `ensure qf_skinmenu_v2` in your server console or F8 console.\
   This will start or restart the script live on your server.
2. Add `ensure qf_skinmenu_v2` to your `server.cfg` in the appropriate place.\
   This ensures the script launches automatically every time your server starts.

{% hint style="danger" %}
**Critical Requirement: Purge Legacy Appearance Resources** You must completely stop and remove `esx_skin`, `skinchanger`, `qb-clothing`, `qb-appearance`, or `illenium-appearance` from your server. Having multiple skin managers active simultaneously will lead to data corruption, database collisions, and client errors.
{% endhint %}

1. **Purge Legacy Scripts:** Stop and remove the older systems from your resource directory.
2. **Dependencies:** The photo studio feature requires `screenshot-basic`. Ensure it is started *before* the skin menu.
3. Add the resource to your `server.cfg`:

   ```cfg
   ensure screenshot-basic
   ensure qf_skinmenu_v2
   ```


# Configuration

Page dedicated to how to configure our Skin Menu \[V2]

#### Configuration Guide (`config/config.lua` & `config/default_data.lua`)

**Targeting Integration** The script detects third-eye targeting systems on its own — you normally do not have to touch this. If none is running, it falls back to proximity-based 'E' interactions.

```lua
Config.Target = {
    ox_target = GetResourceState('ox_target') == 'started' and true or false,
    qtarget   = GetResourceState('qtarget') == 'started' and true or false,
    qb_target = GetResourceState('qb-target') == 'started' and true or false,
    useE      = not (GetResourceState('ox_target') == 'started'
                  or GetResourceState('qtarget') == 'started'
                  or GetResourceState('qb-target') == 'started'),
}
```

Override a value only if you want to force one specific method. `ox_target` is the recommended one.

**Shop Specialization** Unlike older scripts where every clothing store allowed DNA changes, `qf_skinmenu_v2` allows you to strictly segregate what players can modify based on the shop they interact with.

```lua
Config.ShopCategories = {
    ['clothing'] = { 'clothes', 'addons' }, -- Only apparel and props
    ['barber']   = { 'dna', 'face' },       -- Hair, makeup, and facial features
    ['tattoo']   = { 'tattoos' },           -- Exclusive to tattoo parlors
    ['surgeon']  = { 'dna', 'face' },       -- Plastic surgery (parents, structure)
    ['peds']     = { 'peds' },              -- Ped model switching
}

-- Which groups inside those pages a shop type may open.
Config.ShopGroups = {
    ['clothing'] = { 'top', 'bottom', 'props' },
    ['tattoo']   = { 'tattoos_torso', 'tattoos_head', 'tattoos_arms', 'tattoos_legs' },
    ['barber']   = { 'hair', 'makeup' },
    ['surgeon']  = { 'parents', 'features' }
}
```

**Photo Studio Coordinates** When a player creates a new character or takes a wardrobe photo, they are temporarily teleported to an isolated dimension. You must provide coordinates for a visually appealing, well-lit location. `screenshot-basic` is required for this feature.

```lua
Config.PhotoStudio = {
    coords = vector3(617.6306, 2766.3438, 42.0881),
    heading = 182.6283,
}
```

**Interface & Language**

```lua
Config.PrimaryColor = "#2F6AFE"
Config.Side = "left"                -- side of the menu: "left" or "right"
Config.Locale = "en"                -- en, de, es, fr, it, ja, ko, pl, pt
Config.DateFormat = "dd.MM.yyyy"
Config.RotateSides = false          -- flip the direction the ped rotates
Config.BlockNotifications = true    -- hide GTA notifications while the menu is open
Config.DisableIdleAnimations = true -- stop the ped fidgeting and the AFK camera
Config.OpenMenuOnFirstJoin = false  -- open the creator automatically for new players
```

**Preview Images** Thumbnails for clothes and props are loaded either from our CDN or from your own server.

```lua
Config.UseImages = true
Config.ImageSource = "remote" -- "local" or "remote"
Config.RemoteImagePath = "https://data.qfdevelopers.com/qf_skinmenu_v2/"
```

With `"local"` the images are served from the `images/` folder inside the resource.

**Outfits**

```lua
Config.OutfitPrefix = "qf"   -- prefix of shared outfit codes, e.g. qf123
Config.Outfits = {
    MaxSavedOutfits = 20     -- per character
}
```

**Tattoo Shop Integration** If you already run a dedicated tattoo resource, hand the tattoo page over to it instead of using the built-in list. Enable exactly one of these.

```lua
Config.ScriptTattoos = {
    buildIn = true,          -- use the tattoos defined in config/tattoos.lua
    rcore_tattoos = false,
    vms_tattooshop = false,
}
```

**Peds & Permissions**

```lua
Config.AdminGroup = "admin"   -- group seeded as admin for the panel on first start
Config.PedPermission = false  -- Ace permission or framework group required for the Peds page
Config.AllowedPeds = {}       -- managed in the admin panel, seeded from DefaultData.AllowedPeds
```

**Shop Interaction**

```lua
Config.ShopInteractionDelay = 5000    -- ms before the interaction can be used
Config.ShopInteractionCooldown = 5000 -- ms between two interactions

Config.ShopBlips = {
    ['clothing'] = { sprite = 73,  color = 47, scale = 0.7, label = "Clothing Store",  targetIcon = "fas fa-shirt" },
    ['barber']   = { sprite = 71,  color = 0,  scale = 0.7, label = "Barber Shop",     targetIcon = "fas fa-scissors" },
    ['tattoo']   = { sprite = 75,  color = 0,  scale = 0.7, label = "Tattoo Salon",    targetIcon = "fas fa-pen-nib" },
    ['surgeon']  = { sprite = 102, color = 0,  scale = 0.7, label = "Plastic Surgeon", targetIcon = "fas fa-user-md" }
}
```

***

### Shops, Prices & Commands

`Config.Shops`, `Config.Prices`, `Config.Commands` and `Config.AllowedPeds` are intentionally left empty in `config.lua` — they live in the database and are edited in game through `/skinadmin`. Their initial contents come from `config/default_data.lua`.

```lua
DefaultData.Prices = {
    ['clothing'] = 500,
    ['barber']   = 200,
    ['tattoo']   = 300,
    ['surgeon']  = 5000
}

DefaultData.Commands = {
    ['skinmenu']  = { name = 'skinmenu',  permission = false },
    ['outfits']   = { name = 'outfits',   permission = false },
    ['skinreset'] = { name = 'skinreset', permission = false },
    ['skingive']  = { name = 'skingive',  permission = "admin" },
    ['skinpeds']  = { name = 'skinpeds',  permission = "admin" },
}

DefaultData.Shops = {
    {
        type = 'clothing',                            -- clothing, barber, tattoo or surgeon
        coords = vec3(73.8728, -1392.0785, 29.3761),
        heading = 278.8409,
        range = 3.0,
        model = 'a_m_y_epsilon_01',                   -- ped standing at the shop
        label = "Clothing Store",
        jobs = { 'police' }                           -- optional, restricts the shop to jobs
    },
}
```

{% hint style="warning" %}
**`default_data.lua` is only imported into an empty database.** On the first start the shops, prices and commands are copied into the `qf_skinmenu_locations` and `qf_skinmenu_settings` tables, and from then on the database wins — later edits to the file do nothing.

Use `/skinadmin` to change them afterwards, or empty the corresponding table if you want the file to be imported again.
{% endhint %}


# Additional Informations

Page dedicated to Additional Informations about our Skin Menu \[V2].

#### Core Features

* **Native Overrides:** Acts as a master provider for `skinchanger` and `illenium-appearance`, ensuring 100% compatibility with older third-party scripts.
* **Unified Interface:** One cohesive UI handling clothes, DNA, parents, makeup, props, and tattoos.
* **Photo Studio:** Leverages `screenshot-basic` to take actual mugshots of the player's ped for Wardrobe saves.
* **Dynamic Peds:** Natively supports switching to animal peds, custom addon peds, or specific multiplayer models, locked behind admin permissions.

#### Commands & Permissions

| Command          | Default access | Description                                                                  |
| ---------------- | -------------- | ---------------------------------------------------------------------------- |
| `/skinmenu`      | everyone       | Opens the full skin menu for the player.                                     |
| `/outfits`       | everyone       | Opens the saved wardrobe list.                                               |
| `/skinreset`     | admin          | Resets the player's appearance back to `Config.DefaultSkin`.                 |
| `/skingive [id]` | admin          | Opens the surgeon menu for another player, e.g. to fix a broken appearance.  |
| `/skinpeds [id]` | admin          | Opens the ped selection for another player.                                  |
| `/skinadmin`     | admin          | Opens the Admin Panel — shops, prices, commands, peds, permissions, history. |

Command names and their required permission are stored in the database and editable in the Admin Panel; their initial values come from `DefaultData.Commands` in `config/default_data.lua`. The group that counts as admin on a fresh install is `Config.AdminGroup`, and both an Ace permission and a framework group are accepted.

#### UI Assets & Rendering Tools

To capture high-quality previews of clothes, props, and peds for custom wardrobe thumbnails, items, or UI assets, we recommend the open-source [**fivem-greenscreener**](https://github.com/Bentix-cs/fivem-greenscreener) tool. This script allows you to isolate and photograph peds or clothing items against a solid color backdrop (green screen) for seamless background removal, providing a clean and professional look for your server's custom asset library.

#### Developer API (Exports & Events)

`qf_skinmenu_v2` provides a rich developer API through client-side exports, client events, and legacy wrappers. You can choose the integration method that fits your codebase:

{% tabs %}
{% tab title="Client Exports" %}

#### 1. Appearance & Model Handlers

**getPedAppearance**

* **Usage:** Retrieves the complete appearance configuration of a specific ped (DNA, face features, clothing, tattoos).
* **Syntax:** `exports['qf_skinmenu_v2']:getPedAppearance(ped)`
* **Returns:** `table` representing the full appearance payload.

```lua
-- Example: Save player appearance to a custom database or backup table
local playerPed = PlayerPedId()
local appearanceData = exports['qf_skinmenu_v2']:getPedAppearance(playerPed)

-- Print the hair texture index from appearance payload
print("Active Hair Model: " .. tostring(appearanceData.hair_1))
```

**setPlayerAppearance**

* **Usage:** Applies a complete appearance payload directly to the local player's character.
* **Syntax:** `exports['qf_skinmenu_v2']:setPlayerAppearance(appearance)`

```lua
-- Example: Reload a previously saved appearance on spawn
local savedAppearance = TriggerServerCallback('getSavedAppearance') -- Custom callback
if savedAppearance then
    exports['qf_skinmenu_v2']:setPlayerAppearance(savedAppearance)
end
```

**setPedAppearance**

* **Usage:** Applies an appearance payload to a specific ped entity (such as NPCs, dummies, or showroom targets).
* **Syntax:** `exports['qf_skinmenu_v2']:setPedAppearance(ped, appearance)`

```lua
-- Example: Applying appearance payload to a dummy ped inside a showroom
local dummyPed = CreatePed(4, `mp_m_freemode_01`, coords.x, coords.y, coords.z, heading, false, false)
exports['qf_skinmenu_v2']:setPedAppearance(dummyPed, appearanceData)
```

***

#### 2. Ped Variations (Components & Props)

**getPedComponents**

* **Usage:** Retrieves an array of all clothing components currently equipped on the ped (torso, pants, undershirt, etc.).
* **Syntax:** `exports['qf_skinmenu_v2']:getPedComponents(ped)`
* **Returns:** `table` array containing the component ID, drawable, and texture.

```lua
-- Example structure returned:
-- { { component_id = 1, drawable = 4, texture = 2 }, ... }

local playerPed = PlayerPedId()
local components = exports['qf_skinmenu_v2']:getPedComponents(playerPed)

for _, comp in ipairs(components) do
    print(string.format("Component ID: %d | Drawable: %d | Texture: %d", comp.component_id, comp.drawable, comp.texture))
end
```

**setPedComponents**

* **Usage:** Programmatically applies a set of clothing components to a ped.
* **Syntax:** `exports['qf_skinmenu_v2']:setPedComponents(ped, components)`

```lua
-- Example: Equip a specific uniform setup
local policeUniform = {
    { component_id = 11, drawable = 55, texture = 0 }, -- Torso jacket
    { component_id = 4, drawable = 32, texture = 1 }   -- Pants
}
exports['qf_skinmenu_v2']:setPedComponents(PlayerPedId(), policeUniform)
```

**getPedProps**

* **Usage:** Retrieves an array of all props currently equipped on a ped (helmet, glasses, watch, bracelets, ears).
* **Syntax:** `exports['qf_skinmenu_v2']:getPedProps(ped)`
* **Returns:** `table` array containing the prop ID, drawable, and texture.

```lua
-- Example structure returned:
-- { { prop_id = 0, drawable = 12, texture = 0 }, ... }

local props = exports['qf_skinmenu_v2']:getPedProps(PlayerPedId())
for _, prop in ipairs(props) do
    print(string.format("Prop ID: %d | Drawable: %d | Texture: %d", prop.prop_id, prop.drawable, prop.texture))
end
```

**setPedProps**

* **Usage:** Programmatically applies specific props to a ped (or removes them by passing drawable `-1`).
* **Syntax:** `exports['qf_skinmenu_v2']:setPedProps(ped, props)`

```lua
-- Example: Put on police hat and sunglasses (Prop ID 0 = Helmet, Prop ID 1 = Glasses)
local policeProps = {
    { prop_id = 0, drawable = 46, texture = 0 },
    { prop_id = 1, drawable = 2, texture = 0 }
}
exports['qf_skinmenu_v2']:setPedProps(PlayerPedId(), policeProps)
```

***

#### 3. Face, Hair & Head Blend Features

**getPedHair**

* **Usage:** Retrieves styling and color properties of the ped's hair.
* **Syntax:** `exports['qf_skinmenu_v2']:getPedHair(ped)`
* **Returns:** `table` representing style, colors, and highlights.

```lua
-- Example structure returned:
-- { style = 12, color = 4, highlight = 2, texture = 0 }

local hairInfo = exports['qf_skinmenu_v2']:getPedHair(PlayerPedId())
print(string.format("Hair Style: %d | Main Color ID: %d", hairInfo.style, hairInfo.color))
```

**getPedHeadBlend**

* **Usage:** Retrieves genetic blending details of the face (mom/dad shapes and skin tones).
* **Syntax:** `exports['qf_skinmenu_v2']:getPedHeadBlend(ped)`
* **Returns:** `table` representing parent blend indices and mix values.

```lua
-- Example structure returned:
-- { shapeFirst = 2, shapeSecond = 5, skinFirst = 2, skinSecond = 2, shapeMix = 1.0, skinMix = 1.0 }

local blendData = exports['qf_skinmenu_v2']:getPedHeadBlend(PlayerPedId())
```

***

#### 4. Interactive UI & Camera Controls

**IsMenuOpen**

* **Usage:** Checks if the player is currently inside the skin menu UI.
* **Syntax:** `exports['qf_skinmenu_v2']:IsMenuOpen()`
* **Returns:** `boolean` (`true`/`false`).

```lua
-- Example: Block action commands while customizing character
RegisterCommand('robstore', function()
    if exports['qf_skinmenu_v2']:IsMenuOpen() then
        print("You cannot do this while in the clothing menu!")
        return
    end
    -- Trigger robbery logic
end)
```

**OpenWardrobe**

* **Usage:** Programmatically opens the player's saved wardrobe list.
* **Syntax:** `exports['qf_skinmenu_v2']:OpenWardrobe()`

```lua
-- Example: Open wardrobe list when selecting wardrobe target in housing script
RegisterNetEvent('myHousing:openCloset', function()
    exports['qf_skinmenu_v2']:OpenWardrobe()
end)
```

**OpenShop**

* **Usage:** Opens a specialized shop menu, the same one the target interaction opens.
* **Syntax:** `exports['qf_skinmenu_v2']:OpenShop(shopType)`
* **Valid types:** `clothing`, `barber`, `tattoo`, `surgeon`, `peds`

```lua
-- Example: Open the barber menu from a radial menu entry
exports['qf_skinmenu_v2']:OpenShop('barber')
```

**abortMenu**

* **Usage:** Force-closes the menu and restores the player, e.g. when your script needs to interrupt customization.
* **Syntax:** `exports['qf_skinmenu_v2']:abortMenu()`

***

#### 5. Additional Helpers

| Export                         | Description                                                                          |
| ------------------------------ | ------------------------------------------------------------------------------------ |
| `startCharacter(opts, ok, no)` | Opens the full character creator. Export equivalent of `openCreationMenu`.           |
| `getPedModel(ped)`             | Returns the model hash of the ped.                                                   |
| `setPlayerModel(model)`        | Switches the local player to another ped model, hash or name.                        |
| `getPedFaceFeatures(ped)`      | Returns the face feature values (nose, jaw, cheeks, …).                              |
| `getPedHeadOverlays(ped)`      | Returns the head overlays (beard, makeup, blemishes, …).                             |
| `reloadSkin()`                 | Reloads and reapplies the stored appearance, useful after a spawn or a model change. |
| `GetCurrentShop()`             | Returns the shop the player is currently interacting with, or `nil`.                 |
| `PreloadImages()`              | Preloads the clothing thumbnails so the first menu open is instant.                  |
| {% endtab %}                   |                                                                                      |

{% tab title="Client Events" %}
You can programmatically open customization menus using standard client events:

```lua
-- CLIENT-SIDE EXAMPLES

-- 1. Open the Full Character Creator (Typically triggered by your multicharacter script)
-- Takes success callback as the first argument, and cancel callback as the second.
TriggerEvent('qf_skinmenu_v2:openCreationMenu', function()
    print("Player finished and saved their character appearance!")
end, function()
    print("Player cancelled the character appearance creator!")
end)

-- 2. Open a specialized shop type manually (e.g., via a target system or radial menu)
-- Valid types: 'clothing', 'barber', 'tattoo', 'surgeon', 'peds'
TriggerEvent('qf_skinmenu_v2:openMenu', 'clothing')

-- 3. Reapply the stored appearance, e.g. after your script changed the ped model
TriggerEvent('qf_skinmenu_v2:reloadSkin')

-- 4. Force the menu closed
TriggerEvent('qf_skinmenu_v2:abortMenu')
```

{% endtab %}

{% tab title="Legacy Compatibility" %}
Because `qf_skinmenu_v2` registers as a provider for older systems, you do **not** need to rewrite your job scripts, wardrobes, or faction lockers. The following legacy wrappers will be intercepted and processed flawlessly:

```lua
-- CLIENT-SIDE EXAMPLES

-- Simulating illenium-appearance / fivem-appearance export
exports['illenium-appearance']:startPlayerCustomization(function(appearance)
    if appearance then
        print("Appearance saved successfully!")
    else
        print("Player cancelled customization.")
    end
end, {
    ped = true, headBlend = true, faceFeatures = true,
    headOverlays = true, components = true, props = true
})

-- Simulating skinchanger fetch
TriggerEvent('skinchanger:getSkin', function(skin)
    print("Player's current torso: " .. (skin.torso_1 or 0))
end)
```

{% endtab %}
{% endtabs %}

***

#### Frequently Asked Questions (Q\&A)

**Q: Can I use this alongside illenium-appearance?**\
A: **Absolutely not.** This script entirely replaces `illenium-appearance`. If both are running, the game engine will encounter fatal synchronization errors. `qf_skinmenu_v2` handles all appearance logic.

**Q: How do I add custom addon clothes (EUP)?**\
A: Stream your EUP files to your server as you normally would. The script dynamically reads all available clothing components directly from the GTA V engine at runtime. Any properly streamed clothing will automatically populate in the menu.

**Q: Why are wardrobe images failing to save?**\
A: This usually indicates an issue with `screenshot-basic`. Ensure it is updated. If you are using `Config.ImageSource = "remote"`, verify that your `RemoteImagePath` is a valid, accessible backend capable of receiving POST requests for image data.


# Police MDT \[V2]

This category is for our Police MDT \[V2]

**Elevate your server’s police force with our Advanced MDT.** The ultimate, all-in-one Mobile Data Terminal **to take your community’s roleplay to the next level**.

**Move beyond the basics.** Empower your officers with a high performance tool to manage investigations, track suspects, and coordinate operations in real time. From dispatch to evidence management, everything is seamlessly connected.

<figure><img src="/files/CjDMTSWRCub1k7HGvB6Y" alt=""><figcaption></figcaption></figure>


# Installation

Page dedicated to how to install our Police MDT \[V2]

## Step #1 - Drag & Drop

Just Drag & Drop the `qf_mdt_police_v2` folder into your `resouces` folder.

## Step #2 - SQL Installation

{% hint style="info" %}
There’s no need to manually insert any SQL file into your database. Our script automatically handles all necessary database entries on first launch, so you can safely skip this step.
{% endhint %}

## Step #3 - Script start

You can easily start our script using one of the following methods:

1. Type `ensure qf_mdt_police_v2` in your server console or F8 console.\
   This will start or restart the script live on your server.
2. Add `ensure qf_mdt_police_v2` to your `server.cfg` in the appropriate place.\
   This ensures the script launches automatically every time your server starts.


# Configuration

Page dedicated to how to configure our Police MDT \[V2]

## Languages

The language of the tablet is set inside `Config.NUI`.

* `en-US`: English
* `fr-FR`: French
* `pl-PL`: Polish
* `de-DE`: German
* `es-ES`: Spanish
* `pt-PT`: Portuguese
* `ja-JP`: Japanese
* `it-IT`: Italian
* `ko-KR`: Korean

```lua
Config.NUI = {
    defaultLangCode = "en-US",
    -- Languages offered in the tablet's own language switcher.
    -- Remove entries you do not want players to be able to pick.
    langs = {
        { code = "en-US", name = "English", iconUrl = "https://.../gb.webp" },
        { code = "pl-PL", name = "Polski",  iconUrl = "https://.../pl.webp" },
    }
}
```

### Commands & Keybinds <a href="#user-content-commands-keybinds" id="user-content-commands-keybinds"></a>

**General**

* `/qf_mdt_police_v2` (DELETE): Toggle the MDT Dashboard.
* `/qf_mdt_police_v2badge` (B): Show/Hide Officer Badge. `/badge` works as a short alias.
* `/bodycam`: Toggle the bodycam overlay. `/showbodycam` and `/hidebodycam` force one state.

**Dispatch**

* `/qf_mdt_police_v2_fastgps` (E): Set the GPS to the latest dispatch alert.
* `/qf_mdt_police_v2_dispatch` (HOME): Open the MDT straight on the dispatch page.
* `/panic`: Put a critical 10-13 on the board at your exact position. Takes an optional note and can be bound to a key.
* `/location`: Put a routine 10-20 on the board. Same options.
* `/911`: The civilian emergency line. `/911 anon <what happened>` hides the caller.

{% hint style="warning" %}
`/panic`, `/location` and `/911` are **opt-in** and stay unregistered until `Config.Dispatch.OfficerCommands` and `Config.Dispatch.CitizenCalls` exist in your config. Plenty of servers already own those command names.
{% endhint %}

**Camera Mode**

* `/qf_mdt_police_v2_capturephoto` (ENTER): Start capturing a photo.
* `/qf_mdt_police_v2_blocknuifocus` (L-ALT): Block the NUI focus.
* `/qf_mdt_police_v2_cameratakephoto` (SPACE): Take the photo.
* `/qf_mdt_police_v2_cameratogglefocus` (L-ALT): Toggle mouse focus.
* `/qf_mdt_police_v2_cameratoggleflashlight` (F): Toggle camera flashlight.
* `/qf_mdt_police_v2_cameratoggleside` (R): Switch between Front/Back camera.

**Radar**

* `/qf_mdt_police_v2radartoggle` (U): Toggle the entire Radar system.
* **Front Radar Settings**
  * `/qf_mdt_police_v2radarshowfront` (F5): Show Front Radar.
  * `/qf_mdt_police_v2radarhidefront` (F6): Hide Front Radar
  * `/qf_mdt_police_v2radartoggleinteractfront` (PGUP): Lock/Unlock Front Radar target
* **Back Radar Settings**
  * `/qf_mdt_police_v2radarshowback` (F7): Show Back Radar.
  * `/qf_mdt_police_v2radarhideback` (F8): Hide Back Radar
  * `/qf_mdt_police_v2radartoggleinteractback` (PGDN): Lock/Unlock Back Radar target

{% hint style="info" %} <mark style="color:$info;">**Note:**</mark> <mark style="color:$info;">Both the keys and the command names come from</mark> <mark style="color:$info;">`Config.ToggleMDT`</mark><mark style="color:$info;">,</mark> <mark style="color:$info;">`Config.Camera`</mark><mark style="color:$info;">,</mark> <mark style="color:$info;">`Config.Badge`</mark><mark style="color:$info;">,</mark> <mark style="color:$info;">`Config.Radar`</mark> <mark style="color:$info;">and</mark> <mark style="color:$info;">`Config.Dispatch`</mark> <mark style="color:$info;">in</mark> <mark style="color:$info;">`config/config.lua`</mark> <mark style="color:$info;">— the names above are the defaults.</mark>
{% endhint %}

#### Running several tablets side by side (`Config.Base`) <a href="#user-content-config-base" id="user-content-config-base"></a>

Every module stores its data in its own MySQL table, named after the resource (`qf_mdt_police_v2_*`). `Config.Base` lets you point any module at a **different** table, which is how you run more than one tablet at the same time — e.g. `qf_mdt_police_v2` plus a sheriff copy — each with its own events, exports and faction logic, while sharing selected data.

```lua
-- Make the sheriff tablet share the police fines, tags, records, warrants,
-- cases and evidences, but keep its own officers, announcements and radio codes.
Config.Base = {
    fines            = "qf_mdt_police_v2_fines",
    tags             = "qf_mdt_police_v2_tags",
    entityNotes      = "qf_mdt_police_v2_entity_notes",
    mugshots         = "qf_mdt_police_v2_mugshots",
    warrants         = "qf_mdt_police_v2_warrants",
    warrantOfficers  = "qf_mdt_police_v2_warrant_officers",
    warrantCitizens  = "qf_mdt_police_v2_warrant_citizens",
    cases            = "qf_mdt_police_v2_cases",
    caseOfficers     = "qf_mdt_police_v2_case_officers",
    caseCitizens     = "qf_mdt_police_v2_case_citizens",
    evidences        = "qf_mdt_police_v2_evidences",
    evidenceOfficers = "qf_mdt_police_v2_evidence_officers",
    evidenceCitizens = "qf_mdt_police_v2_evidence_citizens",
}
```

{% hint style="warning" %}
Anything you leave out keeps its own default table, so that data stays private to the faction. When a table **is** shared, every tablet pointing at it must use the same value, and related tables have to be shared together:

* `warrants` ↔ `warrantOfficers` + `warrantCitizens`
* `cases` ↔ `caseOfficers` + `caseCitizens`
* `evidences` ↔ `evidenceOfficers` + `evidenceCitizens`
  {% endhint %}

### Several departments on one tablet (`Config.Jobs`) <a href="#user-content-config-jobs" id="user-content-config-jobs"></a>

One resource can serve LSPD, Highway Patrol and BCSO at the same time, each with its own name, colour, ranks, society and radio codes.

With a single job nothing changes and there is nothing to configure:

```lua
Config.Jobs = { ['police'] = true }
```

To describe a department, replace `true` with a table. Every field is optional and falls back to the matching global setting, so you only write down what actually differs.

```lua
Config.Jobs = {
    ['police'] = {
        primary = true,              -- owns every row written before this update
    },
    ['hwp'] = {
        fractionName     = "HWP",
        fractionFullName = "Highway Patrol",
        title            = "MDT HWP",
        color            = { 250, 170, 20 },
        society          = { name = "society_hwp", jobname = "hwp", label = "HWP" },
        grades           = { { id = 0, name = "Trooper" }, { id = 1, name = "Sergeant" } },
    },
}
```

The full list of fields is documented above `Config.Jobs` in `config/config.lua`: `fractionName`, `fractionFullName`, `title`, `color`, `primaryColor`, `logo`, `grades`, `requiredGrades`, `gpsLostMinGrade`, `createCallGrades`, `society`, `officers`, `billingLimits`, `bodyCam`, `dispatchUnits`, `vehicles`, `stations`, `vCodesFaction`, `sharedWith`.

{% hint style="warning" %}
A department whose ladder is not 0–4 needs its own `requiredGrades`. A threshold written for five ranks lands somewhere else entirely on ten.

```lua
['hwp'] = {
    grades         = { { id = 0, name = "Trooper" }, { id = 1, name = "Sergeant" } },
    requiredGrades = { officers = { hire = 1, fire = 1 } },
},
```

{% endhint %}

#### What is shared and what is not <a href="#user-content-jobs-scope" id="user-content-jobs-scope"></a>

| Module                                                            | Scope                                                                 |
| ----------------------------------------------------------------- | --------------------------------------------------------------------- |
| Citizens, fines, tags, notes, mugshots, warrants, cases, evidence | shared by every department                                            |
| Announcements, radio codes, gallery, audit log                    | per department (`Config.PerJobData`)                                  |
| Dispatch — calls, patrols, units, actions, convoy, archive        | shared by default (`Config.PerJobData.dispatch`)                      |
| Officer list, officers on the map, "No GPS" list                  | own department only (`sharedWith` opens it up)                        |
| Society and invoices                                              | per department — a job without its own `society` gets `society_<job>` |

#### Own units and vehicles <a href="#user-content-jobs-units-vehicles" id="user-content-jobs-units-vehicles"></a>

A department can bring its own unit callsigns and its own vehicle list. Both are offered when creating a patrol, an action unit or a convoy unit, and both fall back to the global setting when a department does not define them.

```lua
Config.Jobs = {
    ['police'] = {
        primary = true,
        dispatchUnits = { 'pu1', 'pu2', 'mary' },
        vehicles = {
            { name = "vic11", label = "Crown Victoria 2011", unit = { "pu1", "pu2" } },
            { name = "tahoe", label = "Chevrolet Tahoe",     unit = { "pu1", "pu2" } },
        },
    },
    ['hwp'] = {
        dispatchUnits = { 'hp1', 'hp2' },
        vehicles = {
            { name = "dodge",   label = "Charger Highway Patrol" },
            { name = "police3", label = "Interceptor" },
        },
    },
    ['bcso'] = {},   -- no entry, so it uses Config.Dispatch.Units and Config.Vehicles
}
```

An entry with no `unit` key is offered to every unit. The label is read from the **department's own** list, so two departments can run the same model under different names.

{% hint style="warning" %}
The `unit` keys on a department's vehicles have to match that department's own `dispatchUnits`. Give Highway Patrol the callsigns `hp1` and `hp2` but leave its vehicles pointing at `pu1`, and the form has nothing to offer for either unit. The tablet says so rather than showing an empty dropdown, but the fix is in the config.
{% endhint %}

{% hint style="info" %}
Which vehicles are drawn on the live map is a separate question. A car counts as a service vehicle if it appears in **any** department's list, so a Highway Patrol cruiser still shows up for an LSPD dispatcher. Who sees whom is decided by `sharedWith`, not by the vehicle list.
{% endhint %}

#### Letting departments see each other (`sharedWith`) <a href="#user-content-sharedwith" id="user-content-sharedwith"></a>

`sharedWith` is **directional**. This lets LSPD see Highway Patrol officers, not the other way round:

```lua
Config.Jobs = {
    ['police'] = { sharedWith = { 'hwp' } },
    ['hwp']    = {},
}
```

Set it on both sides for mutual visibility. `sharedWith = true` means "see every job in `Config.Jobs`".

```lua
Config.Jobs = {
    ['police'] = { sharedWith = { 'bcso' } },
    ['bcso']   = { sharedWith = { 'police' } },
    ['hwp']    = {},
}
```

You can also write it as a map, which makes an exclusion visible at a glance:

```lua
['police'] = { sharedWith = { bcso = true, hwp = true, sasp = true, park = false } },
```

#### Splitting the dispatch (`Config.PerJobData.dispatch`) <a href="#user-content-perjobdata-dispatch" id="user-content-perjobdata-dispatch"></a>

```lua
Config.PerJobData = {
    announcements = true,
    radioCodes    = true,
    gallery       = true,
    auditLogs     = true,

    dispatch      = false,
}
```

`false` is one shared dispatch board for every department, which is how the tablet has always worked. It also **defaults to false when the key is missing**, so updating without touching your config changes nothing.

Set it to `true` and each department gets its own calls, patrols, units board, actions board, convoy and archive.

**Calls are split by who raised them.** A call created from the tablet, or raised with `/panic` or `/location`, belongs to the department that raised it. Automatic alerts, `/911` and calls coming from another resource carry no department and stay visible to everyone, because nobody raised them on behalf of one.

{% hint style="warning" %}
**Calls and patrols read `sharedWith` differently, and the reason matters.**

A call is read-only for anyone who did not raise it, so one-way `sharedWith` works there as it does everywhere else — LSPD can see BCSO calls without BCSO seeing theirs.

A patrol is something you **join and leave**. One-way sharing cannot be expressed: the moment LSPD could see a BCSO patrol, it could also join it, kick people from it and delete it. So patrols, units, actions and the convoy follow `sharedWith` **only when it is set on both sides**. A department that shares one way keeps its own board.
{% endhint %}

Grouping is transitive. `police ↔ bcso` plus `bcso ↔ hwp` puts all three on one board, even without a direct entry between `police` and `hwp`.

<details>

<summary>Five departments — worked examples</summary>

**All five share everything**

```lua
Config.Jobs = {
    ['police'] = { sharedWith = true },
    ['bcso']   = { sharedWith = true },
    ['hwp']    = { sharedWith = true },
    ['sasp']   = { sharedWith = true },
    ['park']   = { sharedWith = true },
}
```

**Four share, the fifth stays separate**

Do **not** use `sharedWith = true` here — it means "see everyone", including the department you want isolated. List them out:

```lua
Config.Jobs = {
    ['police'] = { sharedWith = { 'bcso', 'hwp', 'sasp' } },
    ['bcso']   = { sharedWith = { 'police', 'hwp', 'sasp' } },
    ['hwp']    = { sharedWith = { 'police', 'bcso', 'sasp' } },
    ['sasp']   = { sharedWith = { 'police', 'bcso', 'hwp' } },
    ['park']   = {},
}
```

If you give those four `sharedWith = true` and leave `park` empty, the patrol boards still come out right — grouping needs both sides and `park` does not reciprocate. But the four **will** see `park`'s calls, one way, which is almost certainly not what you wanted and is easy to miss.

</details>

***

#### 1. Configuring Ranks (Grades) <a href="#user-content-1-configuring-ranks-grades" id="user-content-1-configuring-ranks-grades"></a>

In config.lua, the `Config.Grades` table controls the hierarchy visible in the MDT. This **must** match your framework's job grades (ESX/QBCore/QBOX) to ensure correct label display.

```lua
-- config.lua
Config.Grades = {    
    {id = 0, name = "Cadet"},     
    {id = 1, name = "Officer I"},    
    {id = 2, name = "Officer II"},    
    {id = 3, name = "Sergeant"},    
    {id = 4, name = "Lieutenant"},    
    {id = 5, name = "Chief"}
}
-- Ensure 'id' corresponds to the grade integer in your database.
```

#### 2. Customizing Fines <a href="#user-content-2-customizing-fines" id="user-content-2-customizing-fines"></a>

You can add new categories and fines in `Config.FineList`.

```lua
-- config.lua
Config.FineList = {    
    {        
        id = "1", -- Unique Category ID        
        label = "Traffic Laws",        
        items = {            
            {                    
                id = "1",                 
                label = "Speeding (> 50 km/h)",                 
                fine = 500,                 
                jail = 0 -- Optional: Jail time in months/minutes            
            },            
            {                
                id = "2",                 
                label = "Reckless Driving",                 
                fine = 1000,                 
                jail = 5            
            }        
        }    
    }
}
```

#### 3. Dispatch Colors & Vehicles <a href="#user-content-3-dispatch-colors--vehicles" id="user-content-3-dispatch-colors--vehicles"></a>

The dispatch system uses specific color codes for vehicles. These are defined in `Config.Dispatch.Colors`. When creating custom alerts, you can use these or standard RGB values.

### Dispatch <a href="#user-content-dispatch" id="user-content-dispatch"></a>

Everything below lives under `Config.Dispatch` in `config/config.lua`. Every option falls back to a sensible default, so a server that copies nothing across still runs.

#### Call life cycle <a href="#user-content-dispatch-lifecycle" id="user-content-dispatch-lifecycle"></a>

A call moves `new → accepted (en route) → on scene → closed`, and closing asks for a reason that stays in the archive. The card lists **who** took it and with which unit, rather than a bare counter.

```lua
Lifecycle = {
    enabled = true,
    requireCloseReason = true,
    onlyAssignedCanClose = true,
    autoCloseAfter = 1800,  -- seconds of silence before an accepted call closes itself, 0 = never

    CloseReasons = { 'confirmed', 'unfounded', 'report', 'duplicate' },
},
```

Reason labels come from the translations — `confirmed` reads `dispatchCloseReasonConfirmed`, and an entry with no matching key falls back to the raw name, so adding your own never shows a blank option.

{% hint style="info" %}
Set `enabled = false` to keep the plain react counter exactly as it behaved in 1.9.x. The old `dispatch/alerts/react` endpoint still works either way and maps onto the new assignment.
{% endhint %}

**There is no officer limit.** Anyone can join a call, however many are already on it. The `maxOfficers` argument still exists on the export for compatibility, but nothing enforces it.

#### Priorities <a href="#user-content-dispatch-priorities" id="user-content-dispatch-priorities"></a>

One priority drives the chip colour, the list order, the blip size on the map and the sound played on arrival.

```lua
Priorities = {
    ['low']      = { weight = 1, color = { 34, 197, 94 },  sound = 'alert.mp3', repeatSound = 1, volumeScale = 0.6, blipScale = 0.8 },
    ['medium']   = { weight = 2, color = { 234, 179, 8 },  sound = 'alert.mp3', repeatSound = 1, volumeScale = 0.8, blipScale = 0.9 },
    ['high']     = { weight = 3, color = { 249, 115, 22 }, sound = 'alert.mp3', repeatSound = 1, volumeScale = 1.0, blipScale = 1.1 },
    ['critical'] = { weight = 4, color = { 239, 68, 68 },  sound = 'alert.mp3', repeatSound = 2, volumeScale = 1.0, blipScale = 1.3 },
},

DefaultPriority = 'medium',  -- used when an alert arrives without one
```

`repeatSound` plays the same file more than once, which is how a `10-13` ends up sounding different from a `10-55` without shipping extra audio.

#### Making one call impossible to miss <a href="#user-content-dispatch-emphasis" id="user-content-dispatch-emphasis"></a>

```lua
Emphasis = {
    enabled = true,
    alertTypes = { 'OfficerPanic' },
},
```

An alert type on this list gets the loudest treatment the tablet has: a breathing red frame on the on-screen alert, a larger pin with a second ring on the map, and a marked edge on the card in the list. An integration can also set `emphasis = true` on a single call.

{% hint style="warning" %}
Keep this list short. It works because it is rare — put every critical alert on it and an officer stops seeing any of them.
{% endhint %}

#### Creating a call from the tablet <a href="#user-content-dispatch-createcall" id="user-content-dispatch-createcall"></a>

```lua
CreateCall = {
    enabled = true,
    defaultPriority = 'medium',
    cooldown = 10000,      -- ms between two calls from the same officer
    allowedGrades = {},    -- empty = anyone with a job from Config.Jobs
    allowMapPick = true,   -- pick the location by clicking the live map

    Icons = { ... },       -- Font Awesome names offered in the form
},
```

The code is picked from your own radio codes. Grade gates are checked **on the server as well**, not only by hiding the button, so a modified client gains nothing by sending the request anyway.

#### Caller details and attachments <a href="#user-content-dispatch-calls" id="user-content-dispatch-calls"></a>

```lua
Calls = {
    callerInfo = true,       -- show who called
    allowAnonymous = true,   -- let a caller stay anonymous
    attachments = true,      -- allow a photo on a call
    attachmentHosts = { ... },
},
```

Turning `callerInfo` off strips caller details **server-side**, on the active board and in the archive, so they never reach a client at all.

#### Archive <a href="#user-content-dispatch-history" id="user-content-dispatch-history"></a>

```lua
History = {
    enabled = true,
    keepDays = 14,           -- archived calls older than this are deleted, 0 = keep forever
    pageSize = 25,
    defaultSort = 'newest',  -- or 'oldest'
},
```

Closed calls go to `qf_mdt_police_v2_dispatch_calls` and `qf_mdt_police_v2_dispatch_call_officers`. Both tables are created automatically on first start — there is no SQL file to import.

The archive is searchable by title, code and street, filterable by priority and closing reason, and sortable newest or oldest first. The order is resolved in SQL, so *oldest* really reaches the far end of the archive rather than reversing the page you can already see.

#### Quick actions and the sidebar counter <a href="#user-content-dispatch-quickactions" id="user-content-dispatch-quickactions"></a>

```lua
QuickActions = {
    enabled = true,
    accept  = { enabled = true, key = 'Z' },
    dismiss = { enabled = true, key = 'O' },
    expand  = { enabled = true, key = 'J' },
},

SidebarBadge = {
    enabled = true,
    count = 'new',  -- 'new' = only calls nobody took yet, 'active' = every open call
},
```

Quick actions work on the newest on-screen alert without opening the tablet. GPS stays on the existing `FastGPS` key.

#### Officer commands — `/panic` and `/location` <a href="#user-content-dispatch-officercommands" id="user-content-dispatch-officercommands"></a>

```lua
OfficerCommands = {
    enabled = true,

    panic = {
        enabled = true,
        command = 'panic',
        key = '',                  -- e.g. 'F9' to bind it
        code = '10-13',
        priority = 'critical',
        alertType = 'OfficerPanic',
        cooldown = 30,
    },

    location = {
        enabled = true,
        command = 'location',
        key = '',
        code = '10-20',
        priority = 'low',
        alertType = 'OfficerLocation',
        cooldown = 20,
    },

    maxNoteLength = 128,
},
```

Both take an optional note — `/panic pinned down behind the car`. Name, badge and position are read **on the server**, so nothing about them can be spoofed from the client.

#### Emergency line for civilians — `/911` <a href="#user-content-dispatch-citizencalls" id="user-content-dispatch-citizencalls"></a>

```lua
CitizenCalls = {
    enabled = true,
    command = '911',
    code = '911',
    priority = 'high',
    alertType = 'CitizenCall',

    minLength = 4,
    maxLength = 200,

    cooldown = 120,          -- seconds between two calls from the same person
    maxPerSession = 0,       -- hard cap per connection, 0 = no cap
    duplicateWindow = 600,   -- seconds in which the same text from the same person is dropped
    nearbyRadius = 60.0,     -- another call within this radius and window counts as the same event
    nearbyWindow = 90,

    anonymous = false,
    allowAnonymousFlag = true,   -- lets the caller choose: /911 anon <what happened>
    anonymousKeyword = 'anon',

    blockedJobs = {},        -- jobs that may not use the civilian line
},
```

A call from `/911` carries what a citizen could actually know — what they saw and roughly where they are — and none of the officer-side fields. Rate limiting works on four axes at once, so a crowd witnessing one event produces one call rather than fifteen.

{% hint style="danger" %}
**`/panic`, `/location` and `/911` are opt-in.** They are only registered when `Config.Dispatch.OfficerCommands` and `Config.Dispatch.CitizenCalls` exist in your config.

Every other new option falls back to a default, but a command name is different: plenty of servers already have a `/panic` or a `/911` from a phone or panic-button resource, and updating this tablet must not take it from them. Copy the sections across to switch the commands on, and rename them there if they clash.
{% endhint %}

***

### Server-side Exports <a href="#user-content-server-side-exports" id="user-content-server-side-exports"></a>

Use these exports in your other resources to interact with the MDT backend.

#### `AddLog` <a href="#user-content-addlog" id="user-content-addlog"></a>

Adds an entry to the Audit Log. Useful for tracking evidence locker access, armory usage, or boss menu actions.

**Syntax:**

```lua
exports.qf_mdt_police_v2:AddLog(source, tag, text, color, fields, args)
```

**Parameters:**

| Parameter | Type   | Description                                                     |
| --------- | ------ | --------------------------------------------------------------- |
| `source`  | number | Player Source ID.                                               |
| `tag`     | string | Category tag (e.g., 'armory', 'evidence', 'boss').              |
| `text`    | string | Log message.                                                    |
| `color`   | string | Color theme ('blue', 'red', 'green', 'orange').                 |
| `fields`  | table  | (Optional) Key-value pairs for extra metadata.                  |
| `args`    | table  | (Optional) Arguments for translation if `text` is a locale key. |

**Example (Armory Usage):**

```lua
-- Triggered when a player withdraws a weapon
local weaponName = "WEAPON_PISTOL"
local ammoCount = 50

exports.qf_mdt_police_v2:AddLog(    
    source,     
    "armory",     
    "Withdrew weapon from armory",     
    "red",     
    {         
        weapon = weaponName,         
        ammo = ammoCount,        
        serialNumber = "WX-12345"     
    }
)
```

#### `CreateCall` <a href="#user-content-createcall" id="user-content-createcall"></a>

Raises a call from another resource. Everything except the title and coordinates is optional.

```lua
local id = exports.qf_mdt_police_v2:CreateCall({
    title = 'Robbery in progress',
    x = 425.1, y = -979.5, z = 30.7,   -- or coords = vector3(...)

    code        = '10-90',
    description = 'Silent alarm at the Fleeca on Vespucci',
    priority    = 'high',              -- low | medium | high | critical, also 1-4
    icon        = 'fa-sack-dollar',    -- pin on the live map
    street      = 'Vespucci Blvd',
    alertType   = 'Robbery',           -- key from Config.Map.AlertSettings.Types
    attachment  = 'https://...',       -- https only
    emphasis    = false,               -- true = the panic treatment
    job         = 'police',            -- only this department sees it, see Config.PerJobData.dispatch
})
```

**Returns** the id of the call, or `nil` when it never reached the board.

{% hint style="warning" %}
A `nil` return is not an error — a free zone or the deduplication window can drop a call on purpose. Check it before you store the id, because `CloseCall` on an id that was never created will fail later.
{% endhint %}

#### `CreateCitizenCall` <a href="#user-content-createcitizencall" id="user-content-createcitizencall"></a>

Raises a call on behalf of somebody who is not police — a phone app, a panic button, an alarm. Pass the player's server id and the caller block is filled in from the framework.

```lua
exports.qf_mdt_police_v2:CreateCitizenCall(playerSource, {
    title       = 'Emergency call',
    description = 'Man with a gun outside the store',
    priority    = 'high',
    anonymous   = false,
})
```

Coordinates default to the caller's position. The phone number comes from `EDITABLE.GetPhoneNumber`, and is only looked up when the call is not anonymous.

#### `CloseCall` <a href="#user-content-closecall" id="user-content-closecall"></a>

Closes an active call from another resource and writes it to the archive.

```lua
exports.qf_mdt_police_v2:CloseCall(id, 'confirmed')
```

***

### Client-side Exports <a href="#user-content--client-side-exports" id="user-content--client-side-exports"></a>

Use these exports to integrate the MDT UI and systems with other scripts (e.g., Robbery scripts, Radar systems).

#### `CreateDispatchAlert` <a href="#user-content-createdispatchalert" id="user-content-createdispatchalert"></a>

Triggers a dispatch notification for all on-duty police.

**Syntax:**

```lua
exports.qf_mdt_police_v2:CreateDispatchAlert(coords, title, description, code, colorRGB, maxOfficers, duration)
```

**Parameters:**

| Parameter     | Type    | Description                                                                                                     |
| ------------- | ------- | --------------------------------------------------------------------------------------------------------------- |
| `coords`      | vector3 | Location of the alert.                                                                                          |
| `title`       | string  | Alert Header.                                                                                                   |
| `description` | string  | Detailed info (e.g., street name, vehicle info).                                                                |
| `code`        | string  | 10-Code (e.g., '10-90').                                                                                        |
| `colorRGB`    | table   | `{r, g, b}` format.                                                                                             |
| `maxOfficers` | number  | Ignored since 1.10.0. Calls have no officer limit, but the slot stays so `duration` does not shift. Pass `nil`. |
| `duration`    | number  | (Optional) Time in ms the alert stays on screen.                                                                |

**Example (Bank Robbery):**

```lua
-- Triggered when a player starts hacking a vault
local plyPed = PlayerPedId()
local coords = GetEntityCoords(plyPed)
local streetName = GetStreetNameFromHashKey(GetStreetNameAtCoord(coords.x, coords.y, coords.z))

exports.qf_mdt_police_v2:CreateDispatchAlert(
    coords,    
    "Bank Robbery in Progress",    
    "Silent alarm triggered at " .. streetName .. " Fleeca Bank.",    
    "10-90",    
    {255, 0, 0}, 
    nil, -- former maxOfficers slot, ignored
    10000
)
```

#### `showOfficerBadge` <a href="#user-content-showofficerbadge" id="user-content-showofficerbadge"></a>

Displays the badge ID card on screen.

**Syntax:**

```lua
exports.qf_mdt_police_v2:showOfficerBadge(data)
```

**Data Structure:**

```lua
{    
    name = "Officer Name",    
    badge = "Badge Number",    
    gradeLabel = "Rank Name",    
    mugshot = "URL to image (optional)",    
    licenses = {        
        { label = "Weapon License", active = true },        
        { label = "Driving License", active = false }    
    }
}
```

**Example:**

```lua
exports.qf_mdt_police_v2:showOfficerBadge(
{    
    name = "Robert Smith",    
    badge = "9921",    
    gradeLabel = "Chief of Police",    
    licenses = {        
        { label = "Advanced Driving", active = true },        
        { label = "SWAT Tactics", active = true }    
    }
})
```

#### `AddHeistZone` (Map) <a href="#user-content-addheistzone-map" id="user-content-addheistzone-map"></a>

Adds a visual zone to the live map, useful for ongoing robberies.

**Syntax:**

```lua
exports.qf_mdt_police_v2:AddHeistZone(zoneData)
```

**Example:**

```lua
exports.qf_mdt_police_v2:AddHeistZone({    
    id = "pacific_standard",    
    name = "Pacific Standard Robbery",    
    position = { x = 255.2, y = 210.0 }, 
    radius = 60.0,    street = "Vinewood Blvd",    
    thumbnailUrl = "https://example.com/bank-image.jpg"
})
```

#### `RemoveHeistZone` <a href="#user-content-removeheistzone" id="user-content-removeheistzone"></a>

Removes a heist zone when the event is over.

**Example:**

```lua
exports.qf_mdt_police_v2:RemoveHeistZone("pacific_standard")
```

***

### Camera & Radar Exports <a href="#user-content--camera--radar-exports" id="user-content--camera--radar-exports"></a>

#### Bodycam <a href="#user-content-bodycam" id="user-content-bodycam"></a>

Control the immersion overlays.

```lua
exports.qf_mdt_police_v2:showBodycam()

exports.qf_mdt_police_v2:hideBodycam()

exports.qf_mdt_police_v2:toggleBodycam()
```

#### Radar <a href="#user-content-radar" id="user-content-radar"></a>

Control the vehicle radar system programmatically.

```lua
-- Force show / hide a radar side ("front" or "back")
exports.qf_mdt_police_v2:showRadar("front")
exports.qf_mdt_police_v2:hideRadar("front")

-- Lock or unlock the current target of a radar side
exports.qf_mdt_police_v2:toggleRadarInteractMode("front")

-- Manually update radar data (e.g. for a tutorial or scripted event)
exports.qf_mdt_police_v2:setRadarData("front", {    
    plate = "FAKE-123",    model = "Buffalo",    speed = 150,    speedDisplay = "km/h"
})
```

#### Other exports <a href="#user-content-other-exports" id="user-content-other-exports"></a>

| Export                                           | Description                                                                 |
| ------------------------------------------------ | --------------------------------------------------------------------------- |
| `GetMugShotBase64(ped, transparent)`             | Renders a mugshot of the ped and returns it as a base64 string.             |
| `showDispatchAlert(data)`                        | Draws a dispatch alert on screen without going through the dispatch system. |
| `updateReactions(data)`                          | Updates the unit reactions shown on an alert that is already on screen.     |
| `ShowHeistZones(zones)` / `SetHeistZones(zones)` | Replaces the whole list of heist zones on the live map at once.             |
| `SetShootingZones(zones)`                        | Replaces the whole list of shots-fired zones on the live map.               |
| `AddShootingZone(zone)`                          | Adds a single shots-fired zone. Same shape as `AddHeistZone`.               |
| `RemoveShootingZone(id)`                         | Removes a shots-fired zone by id.                                           |

### Editable functions <a href="#user-content-editable-functions" id="user-content-editable-functions"></a>

These live in `config/server/editable.lua`, which is **yours to edit** and is not encrypted. Each one ships with a working default.

#### `EDITABLE.GetPhoneNumber(xPlayer)` <a href="#user-content-getphonenumber" id="user-content-getphonenumber"></a>

Fills the **Phone** line on a call raised by a citizen. It ships reading the number the framework itself stores — `users.phone_number` on ESX, `charinfo.phone` on QB and QBox.

Point it at your own phone resource if you run a standalone one:

```lua
function EDITABLE.GetPhoneNumber(xPlayer)
    return exports['lb-phone']:GetEquippedPhoneNumber(xPlayer.source)
end
```

Return `nil` and the tablet simply leaves the field out, which is the honest result for a character who owns no phone. It is never called for an anonymous call.

#### Department labels on outgoing text <a href="#user-content-editable-job-labels" id="user-content-editable-job-labels"></a>

On a server with several departments, a citizen fined by the Sheriff's Office should not be told "Police Fine". These four decide what leaves the tablet:

| Function                                               | Used for                                                       |
| ------------------------------------------------------ | -------------------------------------------------------------- |
| `EDITABLE.GetJobLabel(jobName)`                        | the department label the other three build on                  |
| `EDITABLE.FormatCitizenNotification(jobName, message)` | notifications a citizen receives about a fine, jail or warrant |
| `EDITABLE.GetFineReason(jobName)`                      | the reason your billing resource shows on the invoice          |
| `EDITABLE.GetJailReason(jobName)`                      | the reason your prison resource records                        |

Defaults produce `[LSPD] You received 1 fine(s) totaling $500` and `LSPD - Police Fine`. The label comes from `fractionName`, falling back to `society.label` and then `Config.Society.label`.

#### `EDITABLE.SendLog(logname, message, jobName)` <a href="#user-content-sendlog" id="user-content-sendlog"></a>

Posts to the Discord webhook configured in `Config.Webhooks`. Passing `jobName` puts the department in the embed heading and title, so logs from two departments can be told apart. Leave it out and the embed looks exactly as it did before.

***

### Dispatch Integrations & Custom Alerts

#### Compatibility

Enable 3rd party script compatibility by editing `config/config.lua`.

```lua
-- Enable external dispatch scripts in config/config.lua
Config.Dispatch = {
    Integration = {
        rcore_dispatch = true, -- Set to true to automatically bridge alerts
        core_dispatch = false,
        opto_dispatch = false,
        tk_dispatch = false,
        _0r_dispatch = false,
        frkn_police_dispatch = false
    },

    -- Set to false if your external dispatch already draws its own alerts
    -- and you end up seeing every alert twice.
    ShowOnScreenAlerts = true
}
```

#### Custom Alerts

Control and send dispatch alerts to the MDT programmatically.

```lua
-- Send a custom dispatch alert manually from any server script
TriggerEvent('qf_mdt_police_v2/server/addCustomDispatch', {
    id = "custom_robbery_123",        -- (Optional) Unique ID, system generates one if empty
    title = "Store Robbery",          -- Alert title/name
    code = "10-90",                   -- Dispatch code
    color = {255, 0, 0},              -- RGB color table or HEX string (e.g., "#FF0000")
    street = "Route 68",              -- (Optional) Street name or location description
    x = 100.5,                        -- X coordinate of the alert
    y = -213.2,                       -- Y coordinate of the alert
    z = 32.5,                         -- Z coordinate of the alert
    duration = 5000                   -- (Optional) Duration the alert stays on screen in ms (default: 5000)
})
```

#### 1. Client-Side Export <a href="#user-content-1-client-side-export" id="user-content-1-client-side-export"></a>

You can use the following export directly in any client-side script.

```lua
-- @param coords vector3 - The coordinates of the incident
-- @param title string - The title of the dispatch alert
-- @param description string - The detailed description
-- @param code string - The dispatch code (e.g., "10-13")
-- @param colorRGB table - An array containing RGB values (e.g., { 251, 45, 55 })
-- @param maxOfficers number - Ignored since 1.10.0. Pass nil; the slot stays so duration does not shift
-- @param duration number - The duration the alert shows on screen in milliseconds (e.g., 5000)

local coords = GetEntityCoords(PlayerPedId())
exports['qf_mdt_police_v2']:CreateDispatchAlert(    
    coords,     
    "Officer Down",     
    "An officer has been injured and requires immediate assistance.",     
    "10-13",     
    { 251, 45, 55 },     
    nil, -- former maxOfficers slot, ignored
    5000
)
```

#### 2. Server-Side Event (or Client `TriggerServerEvent`) <a href="#user-content-2-server-side-event-or-client-triggerserverevent" id="user-content-2-server-side-event-or-client-triggerserverevent"></a>

If you need to trigger a dispatch from the server, or prefer passing a data table, you can use the built-in server event.

```lua
local dispatchData = {    
    x = 100.0,           -- [Required] Coordinate X    
    y = -200.0,          -- [Required] Coordinate Y    
    z = 30.0,            -- [Required] Coordinate Z    
    title = "Robbery",   -- [Required] Dispatch Title    
    code = "10-90",      -- [Required] Dispatch Code        
    color = {255, 0, 0}, -- [Optional] RGB table or HEX string (e.g., "#FF0000"). Defaults to blue.    
    street = "Route 68", -- [Optional] Street name. Defaults to empty.    
    duration = 5000,     -- [Optional] Screen duration in ms. Defaults to 5000.    
    id = "custom_id_1"   -- [Optional] A custom unique ID if you need to manage it later
}

-- If triggering from a SERVER script:
TriggerEvent('qf_mdt_police_v2/server/addCustomDispatch', dispatchData)

-- If triggering from a CLIENT script:
TriggerServerEvent('qf_mdt_police_v2/server/addCustomDispatch', dispatchData)
```

## Resetting Officer Hours <a href="#user-content-4-resetting-officer-hours-police" id="user-content-4-resetting-officer-hours-police"></a>

The Police MDT tracks on-duty hours for all officers. These hours can be manually reset via a server callback. The system verifies if the player executing the reset has the appropriate job permissions defined in `Config.Jobs`.

* **Callback Name:** `qf_mdt_police_v2/resetOfficerHours`
* **Target Identifier:** `id` (Character Identifier / CitizenID / License)

**Code Example**

```lua
local officerId = "POLICE_001"

CALLBACK.TriggerServerCallback('qf_mdt_police_v2/resetOfficerHours', function(result)    
    if result.success then        
        print("Officer hours have been reset successfully.")    
    else        
        print("Error: " .. result.error)    
    end
end, officerId)
```

## Duty Status Change Hook <a href="#user-content-6-duty-status-change-hook-police" id="user-content-6-duty-status-change-hook-police"></a>

We have added a server-side hook that triggers whenever an officer changes their duty status via the MDT (e.g., clicking "Available" or "Unavailable"). This is useful for synchronizing the MDT state with other job-related systems or triggering custom events.

* **Location:** `config/server/editable.lua`
* **Function:** `EDITABLE.OnStatusChange(source, status)`

**Usage Example**

This hook is defined in the editable configuration file and can be used to trigger framework-specific duty events:

```lua
function EDITABLE.OnStatusChange(source, status)
    -- Triggered for status: "available", "unavailable"
    
    if status == "available" then
        -- Example: Triggering a custom onDuty event
        TriggerEvent('examplepolicejob:onDuty', source)
    elseif status == "unavailable" then
        -- Example: Triggering a custom offDuty event
        TriggerEvent('examplepolicejob:offDuty', source)
    end
end
```


# Additional Informations

Page dedicated to Additional Informations about our Police MDT \[V2]

### Localization (Adding New Languages) <a href="#user-content--localization-adding-new-languages" id="user-content--localization-adding-new-languages"></a>

The MDT supports multiple languages. Follow these steps to add a new one (e.g., Dutch `nl`).

1. **Create the File:**
   * Navigate to `config/translations/`.
   * Copy `en.lua` and paste it as `nl.lua`.
   * Open `nl.lua` and translate the content. **Important:** Change the language code at the top:

     ```
     luaTRANSLATIONS['nl-NL'] = { -- Change code here    code = "nl-NL",    -- ... translations}
     ```
2. **Register in Manifest:**
   * Open `fxmanifest.lua`.
   * Add your new file to `shared_scripts`:

     ```
     luashared_scripts {    -- ... others    'config/translations/nl.lua', -- Add this line    'config/config.lua',}
     ```
   * Add it to `escrow_ignore` (to ensure it loads for you):

     ```
     luaescrow_ignore {    -- ... others    'config/translations/nl.lua', -- Add this line}
     ```
3. **Update Config:**
   * Open `config/config.lua`.
   * Set `Config.Locale = "nl-NL"`.
   * (Optional) Add it to the login screen format options in `Config.NUI` if you want players to select it manually.

***

### UI & Branding Customization <a href="#user-content--ui--branding-customization" id="user-content--ui--branding-customization"></a>

Most branding can be done without editing the HTML/CSS directly.

#### Changing Logotypes and Colors <a href="#user-content-changing-logotypes-and-colors" id="user-content-changing-logotypes-and-colors"></a>

* **Primary Color:** In `config.lua`, find `Config.Basics.primaryColor`. This accepts a HSL value (e.g., `"233 99% 59%"`).
* **Images:** You can change the sidebar icons and rank icons in `config.lua` by providing direct URLs (Discord webhooks or Imgur links recommended).
* **Bodycam:** The bodycam logo and overlay text are fully editable in `Config.NUI.bodyCam`.

#### Advanced UI Edits <a href="#user-content-advanced-ui-edits" id="user-content-advanced-ui-edits"></a>

The UI is built with React and bundled. You cannot directly edit `.jsx` files without the source code. However, you can:

* **Replace Static Assets:** If you need to replace specific bundled images, check `web/dist/assets/`. *Note: Most images should be changed via Config URLs instead.*

***

### Advanced Script Configuration <a href="#user-content--advanced-script-configuration" id="user-content--advanced-script-configuration"></a>

#### Customizing Animations & Props <a href="#user-content-customizing-animations--props" id="user-content-customizing-animations--props"></a>

If you have a custom tablet prop or animation dictionary you prefer:

1. Open `client/main.lua` (Note: This file is open source in some versions, but core logic might be locked. If accessible:).
2. Look for `CLIENT.tabletModel`, `CLIENT.tabletDict`, and `CLIENT.tabletAnim`.
3. Change these values to your preferred animation.
   * *Warning:* Converting this to a different item (e.g., clipboard) may require adjusting the `AttachEntityToEntity` bone index and offsets in `attachObject()` function.

#### Death Logic <a href="#user-content-death-logic" id="user-content-death-logic"></a>

By default, the MDT closes when a player dies.

* **File:** `config/client/death.lua`
* **Customization:** You can remove the `CLIENT.CloseMDT()` call if you want the MDT to remain open (e.g., for EMS to see details), or add extra logic to check for specific injury states.

***

### Database & Manual Fixes <a href="#user-content-database-manual-fixes" id="user-content-database-manual-fixes"></a>

The script uses `oxmysql`. Key tables include:

* `qf_mdt_police_officers`: Stores police specific data (hours, badge, active duty status).
  * *Issue:* Player cannot go on duty?
  * *Fix:* Check if they exist in this table. If `fireJob` config is used, ensure they haven't been "fired" in the database (removed row).
* `qf_mdt_police_warrants`: Active warrants.
* `qf_mdt_police_audit_logs`: All history.

**Tip:** If you wipe your server database (users/players), **you must also wipe** `qf_mdt_police_officers` to prevent "ghost" officers appearing in lists who no longer exist in the main users table.

***

### FAQ & Troubleshooting <a href="#user-content--faq--troubleshooting" id="user-content--faq--troubleshooting"></a>

#### Q: The MDT won't open when I press the key. <a href="#user-content-q-the-mdt-wont-open-when-i-press-the-key" id="user-content-q-the-mdt-wont-open-when-i-press-the-key"></a>

**A:**

1. Check `config.lua`: Is your job named `'police'`? If you use `'lspd'`, change `Config.Jobs = {['lspd'] = true}`.
2. Check `config/client/editable.lua`: The `CanOpenMDT` function might have custom restrictions (e.g., must be in vehicle).
3. Check Server Console: Are there any SQL errors during startup?

#### Q: Images in the Gallery/Mugshots are broken. <a href="#user-content-q-images-in-the-gallerymugshots-are-broken" id="user-content-q-images-in-the-gallerymugshots-are-broken"></a>

**A:**

* This is usually a Discord/imgur hotlinking issue.
* Ensure the URL is a distinct image link (ends in .png/.jpg).
* If using Discord, their links now expire. We recommend using a dedicated image host or a self-hosted proxy if you store many images.

#### Q: How do I add a new vehicle class color for dispatch? <a href="#user-content-q-how-do-i-add-a-new-vehicle-class-color-for-dispatch" id="user-content-q-how-do-i-add-a-new-vehicle-class-color-for-dispatch"></a>

**A:** In `config.lua` -> `Config.Dispatch.Colors`. You can add new mappings based on the vehicle class ID (GTA V assumes class 0-21).

```lua
['22'] = 'Bright Pink' -- Example for a custom class
```

#### Q: "You are not a police officer" error, but I have the job. <a href="#user-content-q-you-are-not-a-police-officer-error-but-i-have-the-job" id="user-content-q-you-are-not-a-police-officer-error-but-i-have-the-job"></a>

**A:** Ensure `Config.Grades` matches your `esx_addonaccount` or `qb-core` shared configuration **exactly**. If your database grade is `4` but config only goes to `3`, the script may fail to validate the officer.


# Ambulance MDT \[V2]

This category is for our Ambulance MDT \[V2]

**Elevate your server’s police force with our Advanced MDT.** The ultimate, all-in-one Mobile Data Terminal **to take your community’s roleplay to the next level**.

**Move beyond the basics.** Empower your officers with a high performance tool to manage investigations, track suspects, and coordinate operations in real time. From dispatch to evidence management, everything is seamlessly connected.

<figure><img src="/files/EKEw0VEJNFZB9bBxkHfg" alt=""><figcaption></figcaption></figure>


# Installation

Page dedicated to how to install our Ambulance MDT \[V2]

## Step #1 - Drag & Drop

Just Drag & Drop the `qf_mdt_ambulance_v2` folder into your `resouces` folder.

## Step #2 - SQL Installation

{% hint style="info" %}
There’s no need to manually insert any SQL file into your database. Our script automatically handles all necessary database entries on first launch, so you can safely skip this step.
{% endhint %}

## Step #3 - Script start

You can easily start our script using one of the following methods:

1. Type `ensure qf_mdt_ambulance_v2` in your server console or F8 console.\
   This will start or restart the script live on your server.
2. Add `ensure qf_mdt_ambulance_v2` to your `server.cfg` in the appropriate place.\
   This ensures the script launches automatically every time your server starts.


# Configuration

Page dedicated to how to configure our Ambulance MDT \[V2]

## Languages

The language of the tablet is set inside `Config.NUI`.

* `en-US`: English
* `fr-FR`: French
* `pl-PL`: Polish
* `de-DE`: German
* `es-ES`: Spanish
* `pt-PT`: Portuguese
* `ja-JP`: Japanese
* `it-IT`: Italian
* `ko-KR`: Korean

```lua
Config.NUI = {
    defaultLangCode = "en-US",
    -- Languages offered in the tablet's own language switcher.
    langs = {
        { code = "en-US", name = "English", iconUrl = "https://.../gb.webp" },
        { code = "pl-PL", name = "Polski",  iconUrl = "https://.../pl.webp" },
    }
}
```

### Commands & Keybinds <a href="#user-content--new-section-commands--keybinds" id="user-content--new-section-commands--keybinds"></a>

**General**

* `/qf_mdt_ambulance_v2` (DELETE): Toggle the MDT Dashboard.
* `/qf_mdt_ambulance_v2_badge` (B): Show/Hide Medic Badge. `/badge` works as a short alias.
* `/bodycam`: Toggle Bodycam Overlay.

**Dispatch**

* `/qf_mdt_ambulance_v2_fastgps` (E): Set the GPS to the latest dispatch alert.
* `/qf_mdt_ambulance_v2_dispatch` (HOME): Open the MDT straight on the dispatch page.

**Camera Mode**

* `/qf_mdt_ambulance_v2_startcapturephoto` (ENTER): Start capturing a photo.
* `/qf_mdt_ambulance_v2_blocknuifocus` (L-ALT): Block the NUI focus.
* `/qf_mdt_ambulance_v2_cameratakephoto` (SPACE): Take the photo.
* `/qf_mdt_ambulance_v2_cameratogglefocus` (L-ALT): Toggle mouse focus.
* `/qf_mdt_ambulance_v2_cameratoggleflashlight` (F): Toggle camera flashlight.
* `/qf_mdt_ambulance_v2_cameratoggleside` (R): Switch between Front/Back camera.

{% hint style="info" %} <mark style="color:$info;">Note: Both the keys and the command names come from</mark> <mark style="color:$info;">`Config.ToggleMDT`</mark><mark style="color:$info;">,</mark> <mark style="color:$info;"></mark><mark style="color:$info;">`Config.Camera`</mark><mark style="color:$info;">,</mark> <mark style="color:$info;"></mark><mark style="color:$info;">`Config.Badge`</mark> <mark style="color:$info;">and</mark> <mark style="color:$info;">`Config.Dispatch`</mark> <mark style="color:$info;">in</mark> <mark style="color:$info;">`config/config.lua`</mark> <mark style="color:$info;">— the names above are the defaults.</mark>
{% endhint %}

#### Running several tablets side by side (`Config.Base`)

Every module stores its data in its own MySQL table, named after the resource (`qf_mdt_ambulance_v2_*`). `Config.Base` lets you point any module at a different table, so a second medical tablet — a fire department copy, for example — can share selected data while keeping its own medics, announcements and radio codes. Leave an entry unset to keep the default, private table, and always share related tables together.

### Configuration <a href="#user-content-configuration" id="user-content-configuration"></a>

The `config/config.lua` file contains the core settings for the resource. Below is a breakdown of the key sections:

#### Main Settings <a href="#user-content-main-settings" id="user-content-main-settings"></a>

| Option              | Description                                        | Example                             |
| ------------------- | -------------------------------------------------- | ----------------------------------- |
| `Config.Frameworks` | Enable or disable support for specific frameworks. | `{ ESX = { enabled = true }, ... }` |
| `Config.Debug`      | Enables debug prints in the server console.        | `true` / `false`                    |

#### Features <a href="#user-content-features" id="user-content-features"></a>

| Option             | Description                                                                  |
| ------------------ | ---------------------------------------------------------------------------- |
| `Config.ToggleMDT` | Controls the keybind and command to open the MDT.                            |
| `Config.Camera`    | Settings for the integrated camera system (blocking NUI focus, capture key). |
| `Config.Badge`     | Settings for the medic badge display (keybind, command).                     |
| `Config.Basics`    | Visual customization, primarily the primary color using HSL format.          |

#### NUI Settings (`Config.NUI`) <a href="#user-content-nui-settings-confignui" id="user-content-nui-settings-confignui"></a>

This section controls the visual aspect and functionality of the UI:

* **`fractionName`**: The short name displayed for the department (e.g., "EMS").
* **`primaryColor`**: The implementation of the primary color in RGB format for the UI.
* **`sidebarPages`**: Toggle visibility of specific sidebar pages (e.g., set `home = { show = false }` to hide the home page).
* **`medications`**: Define available medications, their dosage rates, and units.
* **`medProtocols`**: Define medical protocols, side effects, and contraindications for each medication.

#### Gameplay Systems <a href="#user-content-gameplay-systems" id="user-content-gameplay-systems"></a>

* **`Config.Pharmacy`**: Configures the pharmacy NPC, location, and blip. Supported `targetSystem` options include `ox_target`, `qb-target`, `qtarget`, or `auto`.
* **`Config.PrescriptionSettings`**: logical settings for prescriptions, including the item name and effects of specific drugs (speed, armor, health regeneration).
* **`Config.Map`**: Configuration for the live map, including hospital locations and vehicle types to track.
* **`Config.Dispatch`**: Settings for the dispatch system, including ignored jobs and alert history duration.

***

### Exports (Server-side) <a href="#user-content--exports-server-side" id="user-content--exports-server-side"></a>

#### `AddLog` <a href="#user-content-addlog" id="user-content-addlog"></a>

Adds a new entry to the audit log system. This is useful for logging actions from other scripts into the MDT.

**Parameters:**

* `source` (number|nil): The player source ID. If `nil`, it is logged as "System".
* `tag` (string): The category tag for the log (e.g., "Admission", "Prescription", "Hospital").
* `text` (string): The main content of the log message.
* `color` (string): The color tag for the entry. Supported: `"blue"`, `"red"`, `"green"`, `"orange"`, `"black"`.
* `fields` (table|nil): Key-value pairs of additional data to store (e.g., `{ patient = "Name", amount = 500 }`).
* `args` (table|nil): Arguments for translation placeholders if `text` is a translation key.

**Return:** `void`

**Example:**

```lua
-- Log a patient admission

exports.qf_mdt_ambulance_v2:AddLog(    
    source,     
    "New Patient",     
    "Admitted John Doe to the hospital",     
    "blue",     
    {         
        patient = "John Doe",         
        reason = "Fractured Arm",         
        room = "204"     
    }
)
```

***

### Exports (Client-side) <a href="#user-content--exports-client-side" id="user-content--exports-client-side"></a>

#### `CreateDispatchAlert` <a href="#user-content-createdispatchalert" id="user-content-createdispatchalert"></a>

Creates a dispatch alert that appears on the MDT map and list for on-duty medics.

**Parameters:**

* `coords` (vector3): The world coordinates of the alert.
* `title` (string): The title of the alert (e.g., "Cardiac Arrest", "Injured Person").
* `description` (string): A detailed description of the incident.
* `code` (string): The dispatch code (e.g., "10-13", "10-99").
* `colorRGB` (table): A table `{r, g, b}` representing the alert color.
* `maxMedics` (number): The maximum number of units that can attach to this alert.
* `duration` (number): How long (in ms) the alert stays active.

**Return:** `void`

**Example:**

```lua
local playerCoords = GetEntityCoords(PlayerPedId())

exports.qf_mdt_ambulance_v2:CreateDispatchAlert(    
    playerCoords,    
    "Car Accident",    
    "Reported vehicle collision with injuries",    
    "10-50",    
    { 255, 165, 0 },   
    3,  
    15000
)
```

#### `showBodycam` <a href="#user-content-showbodycam" id="user-content-showbodycam"></a>

Forces the Bodycam UI to become visible.

**Example:**

```lua
exports.qf_mdt_ambulance_v2:showBodycam()
```

#### `hideBodycam` <a href="#user-content-hidebodycam" id="user-content-hidebodycam"></a>

Forces the Bodycam UI to hide.

**Example:**

```lua
exports.qf_mdt_ambulance_v2:hideBodycam()
```

#### `toggleBodycam` <a href="#user-content-togglebodycam" id="user-content-togglebodycam"></a>

Toggles the current state of the Bodycam UI.

**Example:**

```lua
exports.qf_mdt_ambulance_v2:toggleBodycam()
```

#### `showMedicBadge` <a href="#user-content-showmedicbadge" id="user-content-showmedicbadge"></a>

Displays the medic badge card on the screen.

**Parameters:**

* `data` (table): A table containing the badge details.
  * `name` (string): The name displayed on the badge.
  * `gradeLabel` (string): The rank or title.
  * `badge` (string): The badge number.
  * `mugshot` (string): URL to the image or base64 string.
  * `duration` (number): Time in ms to display the badge.
  * `licenses` (table): List of licenses `{ {label="Driver", active=true}, ... }`.

**Example:**

```lua
exports.qf_mdt_ambulance_v2:showMedicBadge(
    {    
        name = "Dr. House",    
        gradeLabel = "Chief of Medicine",    
        badge = "001",    
        mugshot = "https://example.com/house.jpg", -- or Base64    
        duration = 5000,    
        licenses = {        
            { label = "Medical License", active = true },        
            { label = "Driver License", active = true }    
        }
    }
)
```

#### `GetMugShotBase64` <a href="#user-content-getmugshotbase64" id="user-content-getmugshotbase64"></a>

Captures a mugshot of the specified ped and returns it as a Base64 string.

**Parameters:**

* `Ped` (entity): The ped handle to capture.
* `Transparent` (boolean): If `true`, attempts to remove the background (requires game support).

**Return:**

* `string`: The Base64 encoded image.

**Example:**

```lua
local ped = PlayerPedId()
local base64 = exports.qf_mdt_ambulance_v2:GetMugShotBase64(ped, false)

print("Captured mugshot length:", #base64)
```

***

### Events <a href="#user-content--events" id="user-content--events"></a>

#### Client Events <a href="#user-content-client-events" id="user-content-client-events"></a>

**`qf_mdt_ambulance_v2:client:openPharmacy`**

Opens the pharmacy prescription redemption menu. This can be used by third-party target systems or interaction scripts.

**Usage:**

```lua
TriggerEvent('qf_mdt_ambulance_v2:client:openPharmacy')
```

### Dispatch Integrations & Custom Alerts

#### Compatibility

Enable 3rd party script compatibility by editing `config/config.lua`.

```lua
-- Enable external dispatch scripts in config/config.lua
Config.Dispatch = {
    Integration = {
        rcore_dispatch = true, -- Set to true to automatically bridge alerts
        core_dispatch = false,
        opto_dispatch = false,
        tk_dispatch = false
    }
}
```

#### Custom Alerts

Control and send dispatch alerts to the MDT programmatically.

```lua
-- Send a custom dispatch alert manually from any server script
TriggerEvent('qf_mdt_ambulance_v2/server/addCustomDispatch', {
    id = "custom_alert_123",          -- (Optional) Unique ID, system generates one if empty
    title = "Injured Person",         -- Alert title/name
    code = "10-90",                   -- Dispatch code
    color = {255, 0, 0},              -- RGB color table or HEX string (e.g., "#FF0000")
    street = "Route 68",              -- (Optional) Street name or location description
    x = 100.5,                        -- X coordinate of the alert
    y = -213.2,                       -- Y coordinate of the alert
    z = 32.5,                         -- Z coordinate of the alert
    max_medics = 6,                   -- (Optional) Maximum medics that can react (default: 10)
    duration = 5000                   -- (Optional) Duration the alert stays on screen in ms (default: 5000)
})
```

## Resetting Medic Hours <a href="#user-content-5-resetting-medic-hours-ambulance" id="user-content-5-resetting-medic-hours-ambulance"></a>

The Ambulance MDT tracks on-duty hours for all medical personnel. To clear these hours (e.g., at the end of a month), you can trigger the internal server callback. The requester must be on-duty and authorized to perform this action.

* **Callback Name:** `qf_mdt_ambulance_v2/resetMedicHours`
* **Target Identifier:** `id` (Character Identifier / CitizenID / License)

```lua
local medicId = "MEDIC_001"

CALLBACK.TriggerServerCallback('qf_mdt_ambulance_v2/resetMedicHours', function(result)
    if result.success then
        print("Medic hours have been reset successfully.")
    else
        print("Error: " .. result.error)
    end
end, medicId)
```

## Duty Status Change Hook <a href="#user-content-7-duty-status-change-hook-ambulance" id="user-content-7-duty-status-change-hook-ambulance"></a>

Similar to the Police MDT, the Ambulance MDT includes a hook for medic status changes. This allows you to run custom server-side logic whenever a medic toggles their availability or is kicked from duty by a supervisor.

* **Location:** `config/server/editable.lua`
* **Function:** `EDITABLE.OnStatusChange(source, status)`

**Usage Example**

You can use this to keep the player's job state in sync with the MDT interface:

```lua
function EDITABLE.OnStatusChange(source, status)
    -- Triggered for status: "available", "unavailable"
    
    if status == "available" then
        -- Example: Triggering a custom onDuty event
        TriggerEvent('exampleambulancejob:onDuty', source)
    elseif status == "unavailable" then
        -- Example: Triggering a custom offDuty event
        TriggerEvent('exampleambulancejob:offDuty', source)
    end
end
```


# Additional Informations

Page dedicated to Additional Informations about our Ambulance MDT \[V2]

### Installation Guide <a href="#user-content--installation-guide" id="user-content--installation-guide"></a>

#### 1. Requirements <a href="#user-content-1-requirements" id="user-content-1-requirements"></a>

Ensure you have the following dependencies installed and started **before** the MDT:

* `ox_lib` (Latest version)
* `oxmysql`
* `es_extended` OR `qb-core` OR `qbx_core`
* `ox_target` OR `qb-target` (if you want target interactions)

#### 2. Database Setup <a href="#user-content-2-database-setup" id="user-content-2-database-setup"></a>

1. Locate the `.sql` file provided with your download.
2. Import it into your server's database (e.g., using HeidiSQL or phpMyAdmin).
   * *Note: This script requires specific tables such as `qf_mdt_ambulance_radio_codes` to function.*

#### 3. Inventory Setup (Ox Inventory) <a href="#user-content-3-inventory-setup-ox-inventory" id="user-content-3-inventory-setup-ox-inventory"></a>

If you are using `ox_inventory`, add the following items to your `data/items.lua` (or `ox_inventory/data/items.lua`):

*Ensure you also copy the images to the inventory's `web/images/` directory.*

***

### Advanced Configuration <a href="#user-content-advanced-configuration" id="user-content-advanced-configuration"></a>

#### Adding a New Drug <a href="#user-content-adding-a-new-drug" id="user-content-adding-a-new-drug"></a>

To add a new medication, you must update two sections in

config/config.lua:

**Step 1: Define the Item and Effect** In `Config.PrescriptionSettings.medications`:

```lua
{     
    item = "tramadol",          -- Item name in inventory    
    label = "Tramadol",         -- Label in menus    
    type = "health",            -- Effect type: 'health', 'armor', or 'speed'    
    amount = 15,                -- Amount of health/armor restored    
    animDict = "mp_suicide",    
    anim = "pill",    
    flags = 49
}
```

**Step 2: Define Dosage Rules** In `Config.NUI.medications`:

```lua
{ 
    name = "Tramadol", 
    dosageRate = 2, 
    unit = "mg" 
}
```

**Step 3: Define Medical Protocols** In `Config.NUI.medProtocols`:

```lua
['Tramadol'] = {    
    maxSafeDose = 400.0,    
    description = "Opioid pain medication.",    
    sideEffects = "Nausea, dizziness",    
    contraindications = "Alcohol use, respiratory problems"
}
```

#### Adding a New Hospital <a href="#user-content-adding-a-new-hospital" id="user-content-adding-a-new-hospital"></a>

To add a new hospital location to the map, add an entry to `Config.Map.Hospitals`:

```lua
{    
    id = "custom_hospital",                 -- Unique ID    
    name = "Custom Memorial Hospital",      -- Display Name    
    position = {123.45, -678.90},           -- Coordinates {x, y}    
    radius = 60.0,                          -- Zone radius    
    street = "Custom Street",               -- Street name    
    thumbnailUrl = "img/map/hospitals/custom.webp" -- Path to image in web/build folder
}
```

#### Customizing Colors <a href="#user-content-customizing-colors" id="user-content-customizing-colors"></a>

You can change the primary theme color in `Config.NUI.primaryColor`. Use an RGB table format:

```luau
primaryColor = ParseRGB({ 0, 122, 255 }) -- Blue theme
```

*Note: Some parts of the UI (specifically HSL values in audit logs) might need separate manual adjustments if you drastically change the theme.*

***

### Localization (Adding Languages) <a href="#user-content--localization-adding-languages" id="user-content--localization-adding-languages"></a>

1. Navigate to `config/translations/`.
2. Duplicate `en.lua` and rename it (e.g., `es.lua` for Spanish).
3. Open the file and change the code at the top:

   ```lua
   TRANSLATIONS['es-ES'] = {    
       code = "es-ES",    
       currency = "USD",
   }
   ```
4. Open `config/config.lua` and update `Config.NUI.langs` to include your new language:

   <pre class="language-lua"><code class="lang-lua"><strong>{    
   </strong>    code = "es-ES",    
       name = "Español",    
       iconUrl = "URL_TO_FLAG_ICON"
   }
   </code></pre>
5. Set `Config.Locale = "es-ES"` to make it default.

***

### Troubleshooting (FAQ) <a href="#user-content--troubleshooting-faq" id="user-content--troubleshooting-faq"></a>

#### 1. "The MDT won't open!" <a href="#user-content-1-the-mdt-wont-open" id="user-content-1-the-mdt-wont-open"></a>

* **Check Job**: Ensure your player has the `ambulance` job (or whatever is configured in `Config.Jobs`).
* **Check Keybind**: Press `DELETE` (default). Check `F8` console for errors.
* **Check Resource State**: Ensure the resource is strictly named `qf_mdt_ambulance_v2` if the code references it by name.

#### 2. "I can't see any items in the Pharmacy/Prescriptions." <a href="#user-content-2-i-cant-see-any-items-in-the-pharmacyprescriptions" id="user-content-2-i-cant-see-any-items-in-the-pharmacyprescriptions"></a>

* **Check Inventory**: Ensure `ox_inventory` is started and the items are added to `data/items.lua`.
* **Check Console**: Note any errors related to "Item not found".

#### 3. "Database errors in console." <a href="#user-content-3-database-errors-in-console" id="user-content-3-database-errors-in-console"></a>

* **Import SQL**: Confirm you imported the provided `.sql` file.
* **MySQL Connection**: Ensure `oxmysql` is connected and working for other resources.

#### 4. "Images are broken." <a href="#user-content-4-images-are-broken" id="user-content-4-images-are-broken"></a>

* **Mugshots**: Mugshots require a valid heavy-duty hosting or accurate Discord webhook if modified.
* **Inventory Images**: Move the images from the script's `img` folder (if provided) to your inventory's image directory.

#### 5. "I can't fire/hire medics." <a href="#user-content-5-i-cant-firehire-medics" id="user-content-5-i-cant-firehire-medics"></a>

* **Permissions**: Ensure your character has a high enough grade in the database.
* **Config Check**: Check `Config.NUI.requiredGrades` to see what grade level is required for those actions.


# Mechanic MDT \[V2]

This category is for our Mechanic MDT \[V2]

**Give your workshop the same tooling the emergency services get.** The Mechanic MDT is a full Mobile Data Terminal built for Los Santos Customs and every other repair shop on your server.

**More than an invoice book.** Employees manage clients and vehicles, issue invoices, run cases and reports, coordinate through dispatch and the live map, and take on generated repair jobs out in the city — recovery, tyre changes, engine work — all from one tablet.

<figure><img src="/files/spaE88noXW6vm7T73fLB" alt=""><figcaption></figcaption></figure>


# Installation

Page dedicated to how to install our Mechanic MDT \[V2]

## Step #1 - Drag & Drop

Just Drag & Drop the `qf_mdt_mechanic_v2` folder into your `resouces` folder.

## Step #2 - SQL Installation

{% hint style="info" %}
There’s no need to manually insert any SQL file into your database. Our script automatically handles all necessary database entries on first launch, so you can safely skip this step.
{% endhint %}

## Step #3 - Script start

You can easily start our script using one of the following methods:

1. Type `ensure qf_mdt_mechanic_v2` in your server console or F8 console.\
   This will start or restart the script live on your server.
2. Add `ensure qf_mdt_mechanic_v2` to your `server.cfg` in the appropriate place.\
   This ensures the script launches automatically every time your server starts.

## Requirements

* `oxmysql`
* FiveM server build **4752** or newer
* `screenshot-basic` if you want the mugshot feature to work

{% hint style="warning" %}
The tablet prop is streamed by the resource itself through `stream/prop_cs_tablet_mdt_mechanic.ytyp`. Do not remove the `stream` folder, otherwise the tablet will be invisible in the player's hands.
{% endhint %}


# Configuration

Page dedicated to how to configure our Mechanic MDT \[V2]

## Languages

The language of the tablet is set inside `Config.NUI`.

* `en-US`: English
* `fr-FR`: French
* `pl-PL`: Polish
* `de-DE`: German
* `es-ES`: Spanish
* `pt-PT`: Portuguese
* `ja-JP`: Japanese
* `it-IT`: Italian
* `ko-KR`: Korean

```lua
Config.NUI = {
    defaultLangCode = "en-US",
    -- Languages offered in the tablet's own language switcher.
    langs = {
        { code = "en-US", name = "English", iconUrl = "https://.../gb.webp" },
        { code = "pl-PL", name = "Polski",  iconUrl = "https://.../pl.webp" },
    }
}
```

### Commands & Keybinds

**General**

* `/qf_mdt_mechanic_v2` (DELETE): Toggle the MDT Dashboard.
* `/qf_mdt_mechanic_v2badge` (B): Show/Hide Employee Badge. `/badge` works as a short alias.
* `/bodycam`: Toggle the bodycam overlay. `/showbodycam` and `/hidebodycam` force one state.

**Dispatch**

* `/qf_mdt_mechanic_v2_fastgps` (E): Set the GPS to the latest dispatch alert.
* `/qf_mdt_mechanic_v2_dispatch` (HOME): Open the MDT straight on the dispatch page.

**Camera Mode**

* `/qf_mdt_mechanic_v2_capturephoto` (ENTER): Start capturing a photo.
* `/qf_mdt_mechanic_v2_blocknuifocus` (L-ALT): Block the NUI focus.
* `/qf_mdt_mechanic_v2_cameratakephoto` (SPACE): Take the photo.
* `/qf_mdt_mechanic_v2_cameratogglefocus` (L-ALT): Toggle mouse focus.
* `/qf_mdt_mechanic_v2_cameratoggleflashlight` (F): Toggle camera flashlight.
* `/qf_mdt_mechanic_v2_cameratoggleside` (R): Switch between Front/Back camera.

{% hint style="info" %} <mark style="color:$info;">Note: Both the keys and the command names come from</mark> <mark style="color:$info;">`Config.ToggleMDT`</mark><mark style="color:$info;">,</mark> <mark style="color:$info;"></mark><mark style="color:$info;">`Config.Camera`</mark><mark style="color:$info;">,</mark> <mark style="color:$info;"></mark><mark style="color:$info;">`Config.Badge`</mark> <mark style="color:$info;">and</mark> <mark style="color:$info;">`Config.Dispatch`</mark> <mark style="color:$info;">in</mark> <mark style="color:$info;">`config/config.lua`</mark> <mark style="color:$info;">— the names above are the defaults.</mark>
{% endhint %}

***

## Job & Ranks

`Config.Jobs` decides which framework job may open the tablet, and `Config.Grades` supplies the rank labels shown inside it. The `id` values **must** match the grade integers in your framework.

```lua
Config.Jobs = { ['mechanic'] = true }

Config.Grades = {
    { id = 0, name = "Recruit" },
    { id = 1, name = "Novice" },
    { id = 2, name = "Experienced" },
    { id = 3, name = "Leader" },
    { id = 4, name = "Boss" }
}

Config.Officers = {
    fireJob = "unemployed", -- job given to a fired employee
    fireGrade = 0,
    KickFromDutyJob = {     -- optional off-duty job
        enabled = false,
        name = "offmechanic"
    }
}
```

## Society & Billing

```lua
Config.Society = {
    name = "society_mechanic",
    jobname = "mechanic",
    label = "LSC",
    percentToBoss = 0.80,   -- share of an invoice that goes to the company
    percentToWorker = 0.20, -- share that goes to the employee who issued it
}
```

`Config.Billings` and `Config.Banks` are long lists of supported third-party billing and banking resources — set exactly one entry in each to `true` to bridge invoices and society money into the resource you already run. Leave everything `false` to use the framework's own society account.

## Service Price List

`Config.FineList` drives the price list used when issuing an invoice. The categories and their items are entirely yours to change.

```lua
Config.FineList = {
    {
        id = "1",
        label = "Repair & Maintenance Services",
        items = {
            { id = "1", label = "Standard Repair",      fine = 6000 },
            { id = "2", label = "Engine Overhaul",      fine = 6500 },
            { id = "3", label = "Bodywork & Painting",  fine = 5000 },
        }
    }
}
```

`Config.BillingLimits` caps how much a single invoice may be worth, per grade.

## Repair Jobs (`Config.Tasks`)

The tablet generates repair jobs around the map that employees can accept from the Tasks page. A job spawns a client vehicle with a specific fault, and the employee has to carry out the steps on the right part of the car.

```lua
Config.Tasks = {
    UseProgressBar = true,
    ManagementGrade = 3,        -- grade required to manage jobs
    RefreshInterval = 10,       -- minutes between job refreshes
    MaxAvailableJobs = 4,       -- jobs offered at the same time
    JobsGeneratedPerRefresh = { min = 1, max = 3 },
    VehicleDeleteDelay = 30000, -- ms before an abandoned job vehicle despawns

    EnableClientPeds = true,    -- spawn the waiting client next to the vehicle
    CustomTowScript = {
        jo_towtruck = true,     -- hand recovery jobs over to jo_towtruck
    },

    PaymentAccount = 'bank',    -- where the payout lands

    VehicleTypes = {
        mechanic = { 'towtruck', 'towtruck2' },
        tow      = { 'flatbed', 'flatbed2', 'flatbed3' },
        service  = { 'towtruck', 'towtruck2' },
    },

    DeliveryLocations = {
        workshop_ls = { name = "LS Customs", coords = vector3(-370.6018, -108.1824, 38.6807), heading = 162.9936 },
    },

    Clients = { "Michael Thompson", "David Garcia", "Sarah Jenkins" },

    Locations = {
        { name = "Cypress Flats", coords = vector3(725.2015, -2033.3895, 29.2840), heading = 354.6791 },
    },
}
```

### Adding your own fault type

Every entry in `Config.Tasks.IssueTypes` describes what is broken on the vehicle and the steps needed to fix it. `targetBone` decides where the employee has to stand, and `action` decides what the step actually repairs.

```lua
Config.Tasks.IssueTypes = {
    ["Engine overheating"] = {
        damage = { engineHealth = 200.0, popTires = false },
        effects = {},
        steps = {
            { targetBone = "engine", labelKey = "tasksOpenHood",     action = "open_hood",     duration = 2000 },
            { targetBone = "engine", labelKey = "tasksRepairEngine", action = "repair_engine", duration = 10000,
              animDict = "mini@repair", animName = "fixing_a_ped" },
            { targetBone = "engine", labelKey = "tasksCloseHood",    action = "close_hood",    duration = 2000 }
        }
    },
    ["Flat tire"] = {
        damage = { engineHealth = 1000.0, popTires = true, tiresToPop = { 0, 1 } },
        effects = {},
        steps = {
            { targetBone = "wheel_lf", labelKey = "tasksInspectTire", action = "inspect",     duration = 3000 },
            { targetBone = "wheel_lf", labelKey = "tasksReplaceTire", action = "repair_tire", duration = 8000 }
        }
    },
}
```

`labelKey` is a translation key — add it to `config/translations/*.lua` if you introduce a new one, otherwise the raw key is displayed.

## Dispatch

```lua
Config.Dispatch = {
    IgnoredJobs = { ... },      -- jobs whose alerts the tablet ignores
    Units = { ... },            -- unit callsigns available to employees
    ShowOnScreenAlerts = true,  -- set false if an external dispatch already draws alerts

    Integration = {
        rcore_dispatch = false,
        core_dispatch = false,
        opto_dispatch = false,
        tk_dispatch = false,
        _0r_dispatch = false,
        frkn_police_dispatch = false,
    },

    DeduplicationDistance = 20.0,
    AlertHistoryDuration = 600000, -- ms an alert stays in the history and on the map
}
```

## Interface

```lua
Config.NUI = {
    fractionName = "LSC",
    fractionFullName = "Los Santos Customs",
    title = "MDT LSC",
    primaryColor = ParseRGB({ 231, 149, 74 }),
    showLicenses = true,
    enableRadar = true,
    enableBodycam = true,
    enableBadge = true,

    -- Every page can be hidden by setting show = false
    sidebarPages = {
        home    = { icon = "fa-house",  show = true },
        tasks   = { icon = "fa-wrench", show = true },
        map     = { icon = "fa-map",    show = true },
        -- ...
    },
}
```

Other useful options:

| Option                             | Description                                                                |
| ---------------------------------- | -------------------------------------------------------------------------- |
| `Config.UseFrameworkNotifications` | Route notifications through your framework instead of the built-in ones.   |
| `Config.Mugshot`                   | `autoTake` and `uploadType` (`localfiles` or `fivemanage`).                |
| `Config.CitizenLicenses`           | Which licenses employees may view, grant and revoke, and from which grade. |
| `Config.Vehicles` / `Config.Map`   | Workshop locations and the vehicle classes tracked on the live map.        |
| `Config.UsableItems`               | Items that open the tablet from the inventory.                             |
| `Config.SSN`                       | Which database column is used as the citizen identifier.                   |
| `Config.Customization`             | Additional cosmetic tweaks of the interface.                               |
| `Config.Debug`                     | Debug prints in the server console.                                        |

## Running several tablets side by side (`Config.Base`)

Every module stores its data in its own MySQL table, named after the resource (`qf_mdt_mechanic_v2_*`). `Config.Base` lets you point any module at a different table, so a second workshop tablet can share selected data — the client records or the price list, for example — while keeping its own employees, announcements and radio codes.

```lua
Config.Base = {
    -- fines       = "qf_mdt_mechanic_v2_fines",
    -- tags        = "qf_mdt_mechanic_v2_tags",
    -- entityNotes = "qf_mdt_mechanic_v2_entity_notes",
    -- mugshots    = "qf_mdt_mechanic_v2_mugshots",
}
```

{% hint style="warning" %}
Anything you leave out keeps its own default table, so that data stays private to the company. When a table **is** shared, every tablet pointing at it must use the same value, and related tables (cases, evidences, warrants and their officer/citizen tables) have to be shared together.
{% endhint %}


# Additional Informations

Page dedicated to Additional Informations about our Mechanic MDT \[V2].

#### Core Features

* **Universal Framework Support:** Works with ESX, QBCore and QBox.
* **Repair Jobs:** Generated jobs around the map with per-fault repair steps, client peds, tow integration and automatic payouts.
* **Client & Vehicle Records:** Searchable citizens and vehicles with notes, tags, mugshots and license overview.
* **Invoicing:** Configurable price list, per-grade limits and bridges into most popular billing and banking resources.
* **Dispatch & Live Map:** Alerts, units and patrols shared with the other QF tablets, plus a live map of workshops and vehicles.

***

#### Developer API (Exports & Events)

{% tabs %}
{% tab title="Server Exports" %}
**AddLog**

Adds an entry to the Audit Log — useful for logging tool usage, parts withdrawal or boss menu actions from other resources.

**Syntax:**

```lua
exports.qf_mdt_mechanic_v2:AddLog(source, tag, text, color, fields, args)
```

| Parameter | Type   | Description                                                     |
| --------- | ------ | --------------------------------------------------------------- |
| `source`  | number | Player source ID. `nil` is logged as "System".                  |
| `tag`     | string | Category tag (e.g. 'parts', 'tasks', 'boss').                   |
| `text`    | string | Log message.                                                    |
| `color`   | string | Color theme: `blue`, `red`, `green`, `orange`, `black`.         |
| `fields`  | table  | (Optional) Key-value pairs with extra metadata.                 |
| `args`    | table  | (Optional) Arguments for translation if `text` is a locale key. |

```lua
exports.qf_mdt_mechanic_v2:AddLog(
    source,
    "parts",
    "Withdrew parts from the workshop stock",
    "orange",
    {
        part = "Turbocharger",
        amount = 1,
        vehicle = "ABC 123"
    }
)
```

{% endtab %}

{% tab title="Client Exports" %}
**CreateDispatchAlert**

Sends a dispatch alert to every employee on duty.

```lua
exports.qf_mdt_mechanic_v2:CreateDispatchAlert(coords, title, description, code, colorRGB, maxUnits, duration)
```

| Parameter     | Type    | Description                                      |
| ------------- | ------- | ------------------------------------------------ |
| `coords`      | vector3 | Location of the alert.                           |
| `title`       | string  | Alert header.                                    |
| `description` | string  | Detailed info, e.g. street name and vehicle.     |
| `code`        | string  | Dispatch code.                                   |
| `colorRGB`    | table   | `{r, g, b}` format.                              |
| `maxUnits`    | number  | (Optional) How many units may attach.            |
| `duration`    | number  | (Optional) Time in ms the alert stays on screen. |

```lua
local coords = GetEntityCoords(PlayerPedId())

exports.qf_mdt_mechanic_v2:CreateDispatchAlert(
    coords,
    "Vehicle Recovery Requested",
    "Broken down vehicle blocking the highway.",
    "10-50",
    { 231, 149, 74 },
    4,
    10000
)
```

**Badge & Bodycam**

```lua
exports.qf_mdt_mechanic_v2:showOfficerBadge({
    name = "Robert Smith",
    badge = "LSC-14",
    gradeLabel = "Leader",
    mugshot = "https://example.com/photo.png", -- optional
    licenses = {
        { label = "Heavy Vehicle", active = true },
        { label = "Tuning Certificate", active = false }
    }
})

exports.qf_mdt_mechanic_v2:showBodycam()
exports.qf_mdt_mechanic_v2:hideBodycam()
exports.qf_mdt_mechanic_v2:toggleBodycam()
```

**Other exports**

| Export                               | Description                                                                 |
| ------------------------------------ | --------------------------------------------------------------------------- |
| `GetMugShotBase64(ped, transparent)` | Renders a mugshot of the ped and returns it as a base64 string.             |
| `showDispatchAlert(data)`            | Draws a dispatch alert on screen without going through the dispatch system. |
| `updateReactions(data)`              | Updates the unit reactions shown on an alert that is already on screen.     |
| {% endtab %}                         |                                                                             |

{% tab title="Editable Hooks" %}
`config/server/editable.lua` and `config/client/editable.lua` hold the functions that talk to the rest of your server. They are plain Lua and meant to be edited — this is where you adapt the tablet to a custom licence system, a custom billing resource or your own name lookup.

Frequently changed hooks:

| Hook                                          | Purpose                                                        |
| --------------------------------------------- | -------------------------------------------------------------- |
| `EDITABLE.GetBadge(xPlayer)`                  | Badge number shown on the employee badge.                      |
| `EDITABLE.GetName(identifier)`                | How a citizen's name is resolved from your database.           |
| `EDITABLE.GetPlayerLicenses(identifier)`      | Where licenses are read from.                                  |
| `EDITABLE.GiveLicense` / `RevokeLicense`      | How licenses are granted and revoked.                          |
| `EDITABLE.GetPlayerVehicles(identifier)`      | Vehicle lookup for the records page.                           |
| `EDITABLE.GetVehicleModel(source, modelID)`   | Turning a model hash into a readable name.                     |
| `EDITABLE.ChargePlayer(source, amount, why)`  | How a client is charged for an invoice.                        |
| `EDITABLE.AddMoneyToSociety(amount, jobName)` | Where the company share of an invoice goes.                    |
| `EDITABLE.CreateBilling(...)`                 | Bridge into your billing resource.                             |
| `EDITABLE.TakeMugshot(playerId)`              | Mugshot capture.                                               |
| `EDITABLE.OnStatusChange(source, status)`     | Fired when an employee goes available/unavailable — see below. |
| `EDITABLE.CanOpenMDT()` (client)              | Extra conditions before the tablet may open.                   |

**Duty status hook**

```lua
function EDITABLE.OnStatusChange(source, status)
    -- status: "available" or "unavailable"

    if status == "available" then
        TriggerEvent('examplemechanicjob:onDuty', source)
    elseif status == "unavailable" then
        TriggerEvent('examplemechanicjob:offDuty', source)
    end
end
```

{% endtab %}
{% endtabs %}

***

#### Frequently Asked Questions (Q\&A)

**Q: The tablet does not open at all.**\
A: Check that the player's job matches `Config.Jobs` and that their grade exists in `Config.Grades`. `Config.Debug = true` prints the resolved job and grade to the server console.

**Q: Repair jobs never appear on the Tasks page.**\
A: Jobs are generated on an interval — `Config.Tasks.RefreshInterval` — up to `MaxAvailableJobs` at a time. Right after a restart the first batch takes one interval to appear.

**Q: Recovery jobs should use my tow script instead.**\
A: Set the matching entry in `Config.Tasks.CustomTowScript`, e.g. `jo_towtruck = true`. The tablet then hands the vehicle over instead of running its own recovery logic.

**Q: Invoices do not show up in my billing resource.**\
A: Enable exactly one entry in `Config.Billings`. If your resource is not listed, implement `EDITABLE.CreateBilling` in `config/server/editable.lua` instead.

**Q: Alerts appear twice on screen.**\
A: An external dispatch is drawing them as well. Set `Config.Dispatch.ShowOnScreenAlerts = false`.


# NPC Dialogs

This category is for our NPC Dialogs

**Bring your world to life with our NPC Dialogs.** A completely **FREE**, standalone-capable NPC dialog system designed to create immersive interactions for your players.

\
**Cinematic Experience.** engage players with dynamic camera angles that focus on the NPC, making every conversation feel personal and professional.

<figure><img src="/files/qbZehZc4Mpgzg4YE67Wm" alt=""><figcaption></figcaption></figure>


# Installation

Page dedicated to how to install our NPC Dialogs

## Step #1 - Drag & Drop

Just Drag & Drop the `qf_npc_dialogs` folder into your `resouces` folder.

## Step #2 - SQL Installat~~i~~on

{% hint style="info" %}
There’s no need to manually insert any SQL file into your database. Our script automatically handles all necessary database entries on first launch, so you can safely skip this step.
{% endhint %}

## Step #3 - Script start

You can easily start our script using one of the following methods:

1. Type `ensure qf_npc_dialogs` in your server console or F8 console.\
   This will start or restart the script live on your server.
2. Add `ensure qf_npc_dialogs` to your `server.cfg` in the appropriate place.\
   This ensures the script launches automatically every time your server starts.


# Configuration

Page dedicated to how to configure our NPC Dialogs

### Target Systems

Select the targeting system you are using on your server.

* `ox_target`: Support for OX Target
* `qtarget`: Support for QTarget
* `qb_target`: Support for QB Target

<figure><img src="/files/XOPfS6KVVM7hERN7UJ9m" alt=""><figcaption></figcaption></figure>

### Camera Settings

Adjust the camera behavior during NPC interactions.

* `transitionTime`: Camera transition duration (in ms)
* `offset`: Camera offset relative to the NPC's head bone (vec3)

<figure><img src="/files/6tQrpby2LJeT1I9OgwUE" alt=""><figcaption></figcaption></figure>

### NPC Setup

Configure the models and locations of NPCs available on the map.

* `id`: Unique identifier for the NPC entry
* `model`: Ped model name (e.g., 'a\_m\_y\_business\_02')
* `coords`: Coordinates and heading (vec4)
* `animation`: Animation played by the NPC (dictionary and name)
* `dialogId`: The ID of the initial dialog to open
* `icon`: FontAwesome icon displayed in the target
* `label`: Text label displayed in the target

<figure><img src="/files/d03kJsSSedJA6Gvfe5fa" alt=""><figcaption></figcaption></figure>

### Dialog Configuration

Define the structure and content of the conversations.

* `id`: Unique identifier for the dialog node
* `npc.name`: Name of the NPC displayed in the UI
* `npc.role`: Role or title of the NPC displayed in the UI
* `question`: The main text spoken by the NPC
* `options`: A list of possible responses or actions for the player

<figure><img src="/files/T9Lve406lr039ZMkxH2D" alt=""><figcaption></figcaption></figure>

### Dialog Actions

Various types of actions that can be triggered when a dialog option is selected.

* `nextDialog`: ID of the next dialog node to jump to (or a function returning the ID)
* `clientEvent`: Name of a client-side event to trigger
* `serverEvent`: Name of a server-side event to trigger
* `export`: Resource export to call (format: 'resource:exportName')
* `command`: Console command to execute
* `action`: Special built-in actions (e.g., 'close' to end the dialog)
* `condition`: A Lua function that returns true/false to determine if the option is visible (e.g., Check for a specific job or item)

### Dialog Actions Examples:

* Client Event:

<figure><img src="/files/12Yjr1icw2ssgSwbn6rQ" alt=""><figcaption></figcaption></figure>

* Server Event:

<figure><img src="/files/spbUVTLpDOeI89b9TEnF" alt=""><figcaption></figcaption></figure>

* Export:

<figure><img src="/files/pBGX0Npx0hOCk1iAQxue" alt=""><figcaption></figcaption></figure>

* Condition:

<figure><img src="/files/8QOn8t6CpcSMLgJevNtT" alt=""><figcaption></figcaption></figure>

***

## Triggering Dialogs from External Scripts

You can trigger a dialog from any other client-side script using the **TriggerEvent** function.

### Syntax

<figure><img src="/files/dMaFBhGcADlyo9ihePuQ" alt=""><figcaption></figcaption></figure>

### Example Usage

#### 1. Simple Trigger

This example assumes you have a ped entity handle (e.g., from a raycast or efficient ped loop) and want to open a configured dialog.

<figure><img src="/files/pUyBSsdCz50WObiUoSds" alt=""><figcaption></figcaption></figure>

#### 2. Integration with qtarget/ox\_target

If you are adding a target option manually in another script and want to open a dialog:

<figure><img src="/files/6Ixl7XTIAMqIlyB6cCn5" alt=""><figcaption></figcaption></figure>


# Billing System

This category is for our Billing System

Take full control of your server’s economy with a realistic and fully functional billing experience. Players and factions can create and send invoices, make payments, and check detailed statistics and history through a clean and modern interface. The system integrates perfectly with roleplay servers, allowing smooth transactions between players, jobs, and businesses. Everything is fully configurable and optimized for the best performance, giving you both style and stability. Give your community an easy and professional way to manage money and bring your in-game economy to the next level.

<figure><img src="/files/0mUdaHTKfTOS82u6ZW5A" alt=""><figcaption></figcaption></figure>


# Installation

Page dedicated to how to install our Spawn Selector

## Step #1 - Drag & Drop

Just Drag & Drop the `qf_billingsystem` folder into your `resouces` folder.

## Step #2 - SQL Installation

{% hint style="info" %}
There’s no need to manually insert any SQL file into your database. Our script automatically handles all necessary database entries on first launch, so you can safely skip this step.
{% endhint %}

## Step #3 - Script start

You can easily start our script using one of the following methods:

1. Type `ensure qf_billingsystem` in your server console or F8 console.\
   This will start or restart the script live on your server.
2. Add `ensure qf_billingsystem` to your `server.cfg` in the appropriate place.\
   This ensures the script launches automatically every time your server starts.


# Configuration

Page dedicated to how to configure our Billing System

## Languages

You can set the language of the script in the configuration file.

* `en`: English
* `fr`: French
* `pl`: Polish
* `de`: German
* `es`: Spanish

<figure><img src="/files/ig9o7wm8oX8fWWbPFHXs" alt=""><figcaption></figcaption></figure>

## Exports (Server-side)

<table><thead><tr><th width="249">Category</th><th>Export Name</th><th>Description</th></tr></thead><tbody><tr><td>Creation</td><td><code>CreateInvoice</code></td><td>Create an invoice from one player to another</td></tr><tr><td>Creation</td><td><code>CreateInvoiceForSociety</code></td><td>Create an invoice addressed to a company/society</td></tr><tr><td>Data Retrieval</td><td><code>GetPlayerInvoices</code></td><td>Retrieve all invoices related to a player</td></tr><tr><td>Data Retrieval</td><td><code>GetInvoiceById</code></td><td>Fetch a single invoice by ID</td></tr><tr><td>Data Retrieval</td><td><code>GetUnpaidInvoicesCount</code></td><td>Count unpaid invoices for a player</td></tr><tr><td>Data Retrieval</td><td><code>HasUnpaidInvoices</code></td><td>Quick boolean check for unpaid invoices</td></tr><tr><td>Data Retrieval</td><td><code>GetSocietiesList</code></td><td>Get all registered societies</td></tr><tr><td>Management</td><td><code>ForcePayInvoice</code></td><td>Force the payment of an invoice (admin only)</td></tr><tr><td>Management</td><td><code>CancelInvoice</code></td><td>Cancel an invoice (admin only)</td></tr><tr><td>Statistics</td><td><code>GetPlayerStatistics</code></td><td>Get billing statistics for a player</td></tr><tr><td>Analytics</td><td><code>AddIncomeToChart</code></td><td>Add an income entry to the analytics chart</td></tr></tbody></table>

### 1. CreateInvoice

**Description:**\
Creates a new invoice from one player to another.

**Parameters:**

| Name           | Type   | Required | Description                                        |
| -------------- | ------ | -------- | -------------------------------------------------- |
| `sourcePlayer` | number | yes      | ID of the player creating the invoice              |
| `targetPlayer` | number | yes      | ID of the player receiving the invoice             |
| `items`        | table  | yes      | Table of billed items `{ label, price, quantity }` |
| `invoiceType`  | string | yes      | Type of invoice (`personal` or `society`)          |

**Returns:**\
`boolean` — true if successfully created.

**Example:**

```lua
exports.qfbilling:CreateInvoice(
    source, 
    targetId, 
    {
        { label = 'Traffic Violation', price = 500, quantity = 1 },
        { label = 'Parking Fee', price = 200, quantity = 1 }
    },
    'personal'
)
```

### 2. CreateInvoiceForSociety <a href="#id-2-createinvoiceforsociety" id="id-2-createinvoiceforsociety"></a>

**Description:**\
Creates an invoice addressed to a company or registered society.

**Parameters:**

| Name            | Type   | Required | Description                                      |
| --------------- | ------ | -------- | ------------------------------------------------ |
| `sourcePlayer`  | number | yes      | ID of the player issuing the invoice             |
| `targetSociety` | string | yes      | Target society name (e.g. `police`, `ambulance`) |
| `items`         | table  | yes      | Items list `{ label, price, quantity }`          |
| `invoiceType`   | string | no       | Defaults to `society`                            |

**Example:**

```lua
exports.qfbilling:CreateInvoiceForSociety(
    source,
    'mechanic',
    {
        { label = 'Vehicle Service', price = 5000, quantity = 1 },
        { label = 'Spare Parts', price = 1200, quantity = 2 }
    }
)
```

### 3. GetPlayerInvoices <a href="#id-3-getplayerinvoices" id="id-3-getplayerinvoices"></a>

**Description:**\
Retrieves all invoices belonging to a player (personal, society, and sent).

**Parameters:**

| Name       | Type     | Required | Description                                      |
| ---------- | -------- | -------- | ------------------------------------------------ |
| `source`   | number   | yes      | Player ID                                        |
| `callback` | function | yes      | Called with `invoices` table and `money` balance |

**Example:**

```lua
exports.qfbilling:GetPlayerInvoices(source, function(invoices, money)
    print("Wallet: " .. money)
    print("Personal invoices: " .. #invoices.personal)
    print("Society invoices: " .. #invoices.society)
end)
```

### 4. GetInvoiceById <a href="#id-4-getinvoicebyid" id="id-4-getinvoicebyid"></a>

**Description:**\
Fetches all details of a specific invoice by its unique ID.

**Callback Result Example:**

```lua
{
  id = 42,
  sendername = "John Doe",
  sendersociety = "police",
  targetname = "Jane Roe",
  amount = 1500,
  items = { { label = "Fine", price = 1500, quantity = 1 } },
  status = "unpaid"
}
```

**Example:**

```lua
exports.qfbilling:GetInvoiceById(42, function(invoice)
    if invoice then
        print("Invoice ID:", invoice.id)
        print("Total:", invoice.amount)
        print("Status:", invoice.status)
    end
end)
```

### 5. GetUnpaidInvoicesCount <a href="#id-5-getunpaidinvoicescount" id="id-5-getunpaidinvoicescount"></a>

**Description:**\
Gets the count of unpaid invoices for a player along with summary data.

**Example:**

```lua
exports.qfbilling:GetUnpaidInvoicesCount(source, function(count, data)
    if count > 0 then
        print("You have " .. count .. " unpaid invoices.")
    end
end)
```

### 6. HasUnpaidInvoices <a href="#id-6-hasunpaidinvoices" id="id-6-hasunpaidinvoices"></a>

**Description:**\
Lightweight boolean check to quickly verify if a player has outstanding invoices.

**Example:**

```lua
exports.qfbilling:HasUnpaidInvoices(source, function(hasUnpaid)
    if hasUnpaid then
        print("Player cannot proceed - unpaid invoices detected.")
    else
        print("No outstanding debt.")
    end
end)
```

### 7. GetSocietiesList <a href="#id-7-getsocietieslist" id="id-7-getsocietieslist"></a>

**Description:**\
Retrieves all available societies from the database.

**Callback Example:**

```lua
exports.qfbilling:GetSocietiesList(source, function(societies)
    for _, society in ipairs(societies) do
        print(society.label .. " (" .. society.name .. ")")
    end
end)
```

### 8. ForcePayInvoice (Admin Only) <a href="#id-8-forcepayinvoice-admin-only" id="id-8-forcepayinvoice-admin-only"></a>

**Description:**\
Allows administrators to enforce payment of any invoice.

**Example:**

```lua
exports.qfbilling:ForcePayInvoice(invoiceId, playerId, function(success, message)
    print(message)
end)
```

### 9. CancelInvoice (Admin Only) <a href="#id-9-cancelinvoice-admin-only" id="id-9-cancelinvoice-admin-only"></a>

**Description:**\
Cancels a given invoice (admin privilege required).

**Example:**

```lua
exports.qfbilling:CancelInvoice(invoiceId, function(success)
    if success then
        print("Invoice has been successfully cancelled.")
    end
end)
```

### 10. GetPlayerStatistics <a href="#id-10-getplayerstatistics" id="id-10-getplayerstatistics"></a>

**Description:**\
Returns detailed billing statistics (daily, weekly, monthly).

**Example:**

```lua
exports.qfbilling:GetPlayerStatistics(source, function(data)
    print("Invoices Today: " .. data.personal.stats.totalInvoices.today)
    print("Monthly Income: " .. data.personal.stats.totalIncome.month)
end)
```

### 11. AddIncomeToChart <a href="#id-11-addincometochart" id="id-11-addincometochart"></a>

**Description:**\
Adds income data to analytics. This function updates the internal income chart.

**Example:**

```lua
exports.qfbilling:AddIncomeToChart("char1123456", "mechanic", 5000)
```

### Data Structures <a href="#data-structures" id="data-structures"></a>

| Data Type       | Description                                         |
| --------------- | --------------------------------------------------- |
| `invoiceType`   | `personal`, `society`                               |
| `invoiceStatus` | `unpaid`, `paid`, `request`, `rejected`, `canceled` |
| `item`          | `{ label, price, quantity }`                        |

## Other

### 1. Framework Detection <a href="#id-1-framework-detection" id="id-1-framework-detection"></a>

Detect which framework your server is running to enable integration automatically.

```lua
Config.Frameworks = {
    ESX = { enabled = GetResourceState('es_extended') == 'started' },
    QBCore = { enabled = GetResourceState('qb-core') == 'started' },
    QBox = { enabled = GetResourceState('qbx-core') == 'started' },
    VRP = { enabled = false },
}
```

**Explanation:**

* The script checks for the presence of common frameworks (`es_extended`, `qb-core`, etc.) and enables relevant functionality.
* You don’t have to manually toggle these unless you use a less common framework.

***

### 2. Society Names Mapping <a href="#id-2-society-names-mapping" id="id-2-society-names-mapping"></a>

Define friendly display names for your in-game jobs/societies.

```lua
Config.Societies = {
    ["police"] = "LSPD",
    ["ambulance"] = "EMS",
    ["mechanic"] = "Benny's Garage",
    ["taxi"] = "Downtown Cab Co.",
    -- Add others as needed
}
```

**Usage:** The script uses these names in invoices and UI elements. Make sure keys match your job names.

***

### 3. Invoice Amount Limits <a href="#id-3-invoice-amount-limits" id="id-3-invoice-amount-limits"></a>

Control the invoice value range.

```lua
Config.MinimumInvoiceAmount = 1
Config.MaximumInvoiceAmount = 999999
```

**Example:**

* Prevent invoices smaller than 1 unit or larger than 999,999 units.
* Set these based on your server economy scale.

***

### 4. Invoice Cancellation <a href="#id-4-invoice-cancellation" id="id-4-invoice-cancellation"></a>

Allow users to cancel invoices (both sent and received).

```lua
Config.AllowCancelInvoices = true
Config.AllowCancelReceivedInvoices = true
```

**Example:**

* Enabling these lets players cancel invoices they created or those sent to them, preventing disputes.

***

### 5. Proximity Check for Invoice Creation <a href="#id-5-proximity-check-for-invoice-creation" id="id-5-proximity-check-for-invoice-creation"></a>

Ensure realism by only allowing invoicing nearby players.

```lua
Config.RequireNearbyTarget = 0      -- 0 = disabled
Config.MaxDistanceForNearbyPlayers = 5.0  -- meters
```

**Example:**

* If enabled (>0), the biller must be within 5 meters to create an invoice.
* Helps prevent abuse and adds immersion.

***

### 6. Job and Grade Restrictions <a href="#id-6-job-and-grade-restrictions" id="id-6-job-and-grade-restrictions"></a>

Restrict who can create or pay society invoices.

```lua
Config.EnableGradeRestriction = true
Config.MinimumGradeLevel = 2
Config.SocietyGradePermissions = {
    viewAndCreate = 0,
    pay = 0,
    analytics = 4,
    viewSentInvoices = 0,
}
```

**Explanation:**

* Setting `viewAndCreate` to 0 means all grades in the job can invoice.
* Increasing numbers require higher job ranks (grades) for specific permissions.
* `analytics = 4` means only higher ranked members can see financial charts.

***

### 7. Notification Settings <a href="#id-7-notification-settings" id="id-7-notification-settings"></a>

Control how players get informed about billing events.

```lua
Config.ShowNotifications = true
Config.NotificationSystem = "nui"
Config.NotificationDuration = 5000  -- milliseconds
Config.NotificationColors = {
    success = "#4CAF50",
    error = "#f44336",
    info = "#2196F3",
    warning = "#ff9800",
}
```

**Example:**

* Players receive colorful pop-up messages for invoice payments, errors, etc.
* Notification colors are customizable per message type.

***

### 8. Discord Logging Configuration <a href="#id-8-discord-logging-configuration" id="id-8-discord-logging-configuration"></a>

Send billing events to Discord for audit/logging.

```lua
Config.EnableDiscordLogs = true
Config.DiscordWebhooks = {
    main = "https://discord.com/api/webhooks/your-main-webhook",
    created = "https://discord.com/api/webhooks/created-webhook",
    paid = "https://discord.com/api/webhooks/paid-webhook",
}
Config.DiscordColors = {
    created = 3447003,   -- Blue
    paid = 3066993,      -- Green
    canceled = 15158332, -- Red
}
```

**Use case:**

* Administrator can monitor billing events remotely.
* Set different webhooks for detailed logs (invoice created, paid, canceled).

***

### 9. Sound and Hotkey Settings <a href="#id-9-sound-and-hotkey-settings" id="id-9-sound-and-hotkey-settings"></a>

Enhance user experience with sounds and quick access.

```lua
Config.EnableSounds = true
Config.PlaySoundOnCreate = true
Config.PlaySoundOnPay = true
Config.EnableKeybind = true
Config.DefaultKey = "F7"
```

**Example:**

* Plays audio feedback on invoice creation and payment.
* Pressing F7 opens billing UI instantly.


# Electrician Multiplayer Job

This category is for our Electrician Multiplayer Job

Bring a new level of realism and teamwork to your FiveM server with our Electrician Multiplayer Job script. This innovative job system offers a fresh and immersive experience for your players, featuring skill-based mini-games, dynamic difficulty levels, and seamless multiplayer collaboration. Work together with friends, set custom earnings percentages for each team member, and enjoy a variety of randomized tasks that keep gameplay exciting and unpredictable. With extensive configuration options, you can easily tailor the script to fit your server’s unique style and economy. Fully optimized and ready to use, this job is the perfect way to enrich your roleplay server and keep your players coming back for more!

<figure><img src="/files/KDXVJM4kACFiWchQSqKY" alt=""><figcaption></figcaption></figure>


# Installation

Page dedicated to how to install our Electrician Multiplayer Job

## Step #1 - Drag & Drop

Just Drag & Drop the `qf_electrician` folder into your `resouces` folder.

## Step #2 - SQL Installation

{% hint style="info" %}
There’s no need to manually insert any SQL file into your database. Our script automatically handles all necessary database entries on first launch, so you can safely skip this step.
{% endhint %}

## Step #3 - Script start

You can easily start our script using one of the following methods:

1. Type `ensure qf_electrician` in your server console or F8 console.\
   This will start or restart the script live on your server.
2. Add `ensure qf_electrician` to your `server.cfg` in the appropriate place.\
   This ensures the script launches automatically every time your server starts.


# Configuration

Page dedicated to how to configure our Electrician Multiplayer Job

## Languages

You can set the language of the script in the configuration file.

* `en`: English
* `fr`: French
* `pl`: Polish
* `de`: German
* `es`: Spanish

<figure><img src="/files/ig9o7wm8oX8fWWbPFHXs" alt=""><figcaption></figcaption></figure>

## Compatibility

Defines compatibility settings for notification, vehicle key, and fuel systems:

***

**`notifications`:**

Select which notification system should be used by the script:

* `script_custom_notify`: Set to `true` to use the built-in notification system.
* `qf_notify`: Set to `true` to use **QF Developers'** notification system.
* `esx`: Set to `true` to use default **ESX notifications** (requires ESX).
* `qb`: Set to `true` to use default **QB notifications** (requires QBCore).
* `qbox`: Set to `true` to use default **QBox notifications** (requires QBox).

***

**`vehiclekeys`:**

Defines compatibility with different vehicle key systems:

* `qb_vehiclekeys`: For **qb-vehiclekeys**.
* `qbox_vehiclekeys`: For **qbox vehicle key** system.
* `wasabi_carlock`: For **wasabi\_carlock** integration.
* `renewed_vehiclekeys`: For **renewed-vehiclekeys**.
* `sna_vehiclekeys`: For **sna-vehiclekeys**.
* `custom`: Set to `true` if you're using a custom key system (requires manual setup in `client/editable.lua`).

***

**`fuel`:**

Defines fuel system compatibility and starting fuel level:

* `CDNFuel`: Set to `true` for **cdn-fuel**.
* `LegacyFuel`: Set to `true` for **LegacyFuel**.
* `ox_fuel`: Set to `true` for **ox\_fuel**.
* `fuellevel`: Fuel level (percentage) assigned to the spawned vehicle (e.g., `100` for full tank).

> ⚠️ Only one system per category (notifications, keys, fuel) should be enabled at a time to avoid conflicts.

<figure><img src="/files/csXPmX7ohZxzH89cZTzj" alt=""><figcaption></figcaption></figure>

## Job Data

Defines general job configuration, access restrictions, and blip settings:

***

**`Lobby.maxPlayers`:**

Maximum number of players that can join a single electrician job session (e.g., `4`).

***

**`Job`:**

Controls job restriction and role assignment:

* `requiredJob`:\
  Set to `true` to require a specific job to access the system.
* `name`:\
  Name of the job required (e.g., `'electrician'`). Ignored if `requiredJob = false`.

***

**`Blip`:**

Map blip configuration for the electrician job start point:

* `coords`: Location where the blip appears on the map.
* `sprite`: Icon used for the blip (e.g., `643`).
* `colour`: Color of the blip (e.g., `28`).
* `scale`: Size of the blip (e.g., `0.8`).
* `label`: Text label shown on the map. Uses localization via `TRANSLATIONS.LOCALE('BLIP_LABEL')`.

> 📌 This section controls how and where the job becomes accessible to players.

<figure><img src="/files/9Xw6KAg4LtydEjXoJoP1" alt=""><figcaption></figcaption></figure>

## Salary

Defines payment settings for completing electrician tasks:

* `amount`:\
  The amount of money awarded to each player upon job completion (e.g., `5000`).
* `moneyType`:\
  Automatically selects the currency type based on your active framework:\
  • `'money'` for **ESX**\
  • `'cash'` for **QBCore** and **QBox**\
  • `'yourcustomtypeofmoney'` if you're using a custom or unsupported system

> 📌 You can override the default selection by manually setting the `moneyType` string to match your economy system.

<figure><img src="/files/iHw8fuWa93O9eIsmVCsr" alt=""><figcaption></figcaption></figure>

## Target

Defines the targeting system used to interact with job zones, props, and objects:

* `ox_target`: Set to `true` to use **ox\_target**.
* `qtarget`: Set to `true` to use **qtarget**.
* `qb_target`: Set to `true` to use **qb-target**.
* `own`: Set to `true` if you're using a **custom targeting system**. Requires implementation in `client/editable.lua`.
* `useE`: Set to `true` to enable interaction using the **E key** instead of a target system.

> 📌 Only one system should be enabled at a time to avoid conflicts.

<figure><img src="/files/iJ4ioMD4OnzS50l4zrLL" alt=""><figcaption></figcaption></figure>

## Freeze Props

Determines whether placed job-related props (e.g., fuse boxes, ladders, tools) should be frozen in place:

* `FreezeProps`:\
  Set to `true` to **prevent props from being moved or knocked over** by players or vehicles.\
  Set to `false` to allow natural physics interactions.

> 📌 Recommended to keep enabled for stable and immersive job scenes.

<figure><img src="/files/T814CUIPiUOYGnnMxCxg" alt=""><figcaption></figcaption></figure>

## Zones

Defines the NPC interaction zone for starting the electrician job:

* `targetLabel`:\
  Text displayed when targeting the NPC (uses localization via `TRANSLATIONS.LOCALE('LABEL_STARTJOB_TARGET')`).
* `icon`:\
  Font Awesome icon shown in the interaction menu (e.g., `'fa-solid fa-play'`).
* `model`:\
  Ped model spawned at the zone (e.g., `'s_m_m_dockwork_01'`).
* `coords`:\
  Position where the ped and interaction zone are created (`vec3`).
* `heading`:\
  Direction the NPC will face.
* `distance`:\
  Maximum interaction distance (e.g., `1.5` meters).
* `groups`:\
  Restricts interaction to a specific job if `Config.JobData.Job.requiredJob = true`.\
  Uses the job name defined in `Config.JobData.Job.name`.

> 📌 This is the main entry point where players initiate the job.

<figure><img src="/files/GYScLTPUqztJPEeb09Yg" alt=""><figcaption></figcaption></figure>

## Markers

Defines visual marker settings used in the job system:

***

**`PedMarkers`:**

Displayed under job-related NPCs (e.g., start job ped).

* `id`:\
  Marker type ID (e.g., `2` – vertical cylinder).
* `color`:\
  RGB color of the marker (e.g., `{243, 207, 7}` for yellow).

***

**`DeleteCar`:**

Displayed at vehicle return zone (e.g., garage marker).

* `id`:\
  Marker type ID (e.g., `25` – vehicle garage marker).
* `color`:\
  RGB color of the marker (same format as above).

> 🎨 You can customize marker types and colors to match your server’s visual style.

<figure><img src="/files/mguemLUHnTCsGwqDKVWc" alt=""><figcaption></figcaption></figure>

## Remove Vehicle Timeout

Controls automatic deletion of the job vehicle after a delay:

* `enabled`:\
  Set to `true` to enable automatic vehicle removal after a set time.
* `time`:\
  Time in **seconds** before the vehicle is deleted (e.g., `30`).

> 📌 Useful for preventing abandoned electrician vehicles from cluttering the map.

<figure><img src="/files/NaXfJNLA7qyFtImvgHOL" alt=""><figcaption></figcaption></figure>

## Garage

Defines vehicle spawn and return settings for the electrician job:

* `SpawnPoints`:\
  List of `vec4` coordinates where the job vehicle will be spawned.\
  Format: `vec4(x, y, z, heading)`.
* `DeleteCar`:\
  List of `vec4` coordinates where players can return (delete) their job vehicle.
* `vehicleModel`:\
  Model name of the electrician job vehicle (e.g., `'burrito_electrician'`).

> 📌 You can add multiple spawn or return points if you want to support different garage zones.

<figure><img src="/files/IhYCYLfwvUjzgEvRevmH" alt=""><figcaption></figcaption></figure>

## Uniforms

Defines the electrician job uniform applied to players when starting the job:

* `male`:\
  Clothing components for male characters:\
  • `tshirt_1`, `tshirt_2` – T-shirt base and variation\
  • `torso_1`, `torso_2` – Upper body/clothing\
  • `arms` – Arm style (sleeves)\
  • `pants_1`, `pants_2` – Pants and variation\
  • `shoes_1`, `shoes_2` – Footwear\
  • `helmet_1`, `helmet_2` – Helmet or headgear
* `female`:\
  Same structure as male, adjusted for female ped model clothing indexes.

> 📌 You can customize these values to fit your server’s clothing packs or RP uniform standards.

<figure><img src="/files/uKByoOr3UC1Qp2IbB4Zt" alt=""><figcaption></figcaption></figure>

## Places

Defines electrician job locations and task types for each mission:

Each entry represents a **mission zone** with a waypoint and multiple job objectives:

* `waypoint_coords`:\
  Coordinates (`x`, `y`, `z`) shown on the map/GPS for player navigation to the job location.
* `jobs`:\
  A list of tasks that need to be completed within the mission area. Each task includes:

  • `player_position`:\
  Position and heading (`x`, `y`, `z`, `h`) where the player must stand to perform the task.

  • `job_type`:\
  Type of electrician task to be performed at the position:

  * `'Light'`: Replace or repair street lighting.
  * `'Key'`: Access and reconfigure fuse boxes.
  * `'Cable'`: Connect or repair electrical cabling.

> 📌 You can create additional mission zones by duplicating the structure and customizing the coordinates and job types.

<figure><img src="/files/gdWYwGeLhS3FHIcrf8Ja" alt=""><figcaption></figcaption></figure>

## Mini Games Options

Defines task-specific settings for each type of electrician job:

***

**`['Light']`**

Configuration for light replacement or repair tasks:

* `time`:\
  Duration of the task in **seconds** (randomized range, e.g., `25–35`).
* `fuses`:\
  Number of fuses the player needs to find during the mini-task (randomized, e.g., `2–4`).

***

**`['Cable']`**

Configuration for cable connection or repair tasks:

* `time`:\
  Duration of the task in **seconds** (randomized range, e.g., `8–12`).

> 📌 You can adjust the timing and complexity of each task type independently for better balance and immersion.

<figure><img src="/files/o8btGJpJ5aMCmWUQsdWt" alt=""><figcaption></figcaption></figure>


# Gardener Multiplayer Job

This category is for our Gardener Multiplayer Job

Step into the role of a city gardener with our innovative multiplayer job script. Designed for engaging gameplay, this script features interactive mini-games that test your precision, timing, and teamwork. Join forces with friends to complete diverse gardening tasks and keep parks vibrant and green. Whether you're trimming hedges, planting flowers, or cleaning up public spaces, every activity is designed to be fun, challenging, and rewarding. Fully optimized and ready to use, it's a perfect addition to any FiveM server looking to add cooperative, skill-based jobs. Start your journey today – and find out if you’ve got what it takes to be a top-tier gardener!

<figure><img src="/files/Z0Ab5NEVHkPzUo694lVJ" alt=""><figcaption></figcaption></figure>


# Installation

Page dedicated to how to install our Gardener Multiplayer Job

## Step #1 - Drag & Drop

Just Drag & Drop the `qf_gardener` folder into your `resouces` folder.

## Step #2 - SQL Installation

{% hint style="info" %}
There’s no need to manually insert any SQL file into your database. Our script automatically handles all necessary database entries on first launch, so you can safely skip this step.
{% endhint %}

## Step #3 - Script start

You can easily start our script using one of the following methods:

1. Type `ensure qf_gardener` in your server console or F8 console.\
   This will start or restart the script live on your server.
2. Add `ensure qf_gardener` to your `server.cfg` in the appropriate place.\
   This ensures the script launches automatically every time your server starts.


# Configuration

Page dedicated to how to configure our Gardener Multiplayer Job

## Languages

You can set the language of the script in the configuration file.

* `en`: English
* `fr`: French
* `pl`: Polish
* `de`: German
* `es`: Spanish

<figure><img src="/files/ig9o7wm8oX8fWWbPFHXs" alt=""><figcaption></figcaption></figure>

## Compatibility

Defines compatibility settings for notification, vehicle key, and fuel systems:

***

**`notifications`:**

Select which notification system should be used by the script:

* `script_custom_notify`: Set to `true` to use the built-in notification system.
* `qf_notify`: Set to `true` to use **QF Developers'** notification system.
* `esx`: Set to `true` to use default **ESX notifications** (requires ESX).
* `qb`: Set to `true` to use default **QB notifications** (requires QBCore).
* `qbox`: Set to `true` to use default **QBox notifications** (requires QBox).

***

**`vehiclekeys`:**

Defines compatibility with different vehicle key systems:

* `qb_vehiclekeys`: For **qb-vehiclekeys**.
* `qbox_vehiclekeys`: For **qbox vehicle key** system.
* `wasabi_carlock`: For **wasabi\_carlock** integration.
* `renewed_vehiclekeys`: For **renewed-vehiclekeys**.
* `sna_vehiclekeys`: For **sna-vehiclekeys**.
* `custom`: Set to `true` if you're using a custom key system (requires manual setup in `client/editable.lua`).

***

**`fuel`:**

Defines fuel system compatibility and starting fuel level:

* `CDNFuel`: Set to `true` for **cdn-fuel**.
* `LegacyFuel`: Set to `true` for **LegacyFuel**.
* `ox_fuel`: Set to `true` for **ox\_fuel**.
* `fuellevel`: Fuel level (percentage) assigned to the spawned vehicle (e.g., `100` for full tank).

> ⚠️ Only one system per category (notifications, keys, fuel) should be enabled at a time to avoid conflicts.

<figure><img src="/files/csXPmX7ohZxzH89cZTzj" alt=""><figcaption></figcaption></figure>

## Job Data

Defines general job configuration, access restrictions, and blip settings:

***

**`Lobby.maxPlayers`:**

Maximum number of players that can join a single electrician job session (e.g., `4`).

***

**`Job`:**

Controls job restriction and role assignment:

* `requiredJob`:\
  Set to `true` to require a specific job to access the system.
* `name`:\
  Name of the job required (e.g., `'gardener'`). Ignored if `requiredJob = false`.

***

**`Blip`:**

Map blip configuration for the electrician job start point:

* `coords`: Location where the blip appears on the map.
* `sprite`: Icon used for the blip (e.g., `643`).
* `colour`: Color of the blip (e.g., `28`).
* `scale`: Size of the blip (e.g., `0.8`).
* `label`: Text label shown on the map. Uses localization via `TRANSLATIONS.LOCALE('BLIP_LABEL')`.

> 📌 This section controls how and where the job becomes accessible to players.

<figure><img src="/files/spzJwBkRKRwU07uitBFv" alt=""><figcaption></figcaption></figure>

## Salary & XP System

Defines the payment and XP system for the gardener job:

* `amount`:\
  Base salary awarded to the player after completing a gardening task (e.g., `5000`).
* `moneyType`:\
  Currency type used for payment, selected automatically based on active framework:\
  • `'money'` for **ESX**\
  • `'cash'` for **QBCore** and **QBox**\
  • `'yourcustomtypeofmoney'` for custom or unsupported systems
* `levelMultiplier`:\
  Percentage-based salary boost per player level (e.g., `0.5` = +0.5% per level).\
  Example: Level 10 = +5% bonus to base salary.
* `jobFinishedXP`:\
  Amount of XP granted per completed task (e.g., `100` XP).

> 📈 This system supports progression-based rewards and allows players to earn more as they level up.

<figure><img src="/files/UjfUVJvmhRuS2N0a3HPt" alt=""><figcaption></figcaption></figure>

## Target

Defines the targeting system used to interact with job zones, props, and objects:

* `ox_target`: Set to `true` to use **ox\_target**.
* `qtarget`: Set to `true` to use **qtarget**.
* `qb_target`: Set to `true` to use **qb-target**.
* `own`: Set to `true` if you're using a **custom targeting system**. Requires implementation in `client/editable.lua`.
* `useE`: Set to `true` to enable interaction using the **E key** instead of a target system.

> 📌 Only one system should be enabled at a time to avoid conflicts.

<figure><img src="/files/iJ4ioMD4OnzS50l4zrLL" alt=""><figcaption></figcaption></figure>

## Zones

Defines the NPC interaction zone for starting the electrician job:

* `targetLabel`:\
  Text displayed when targeting the NPC (uses localization via `TRANSLATIONS.LOCALE('LABEL_STARTJOB_TARGET')`).
* `icon`:\
  Font Awesome icon shown in the interaction menu (e.g., `'fa-solid fa-play'`).
* `model`:\
  Ped model spawned at the zone (e.g., `'s_m_m_dockwork_01'`).
* `coords`:\
  Position where the ped and interaction zone are created (`vec3`).
* `heading`:\
  Direction the NPC will face.
* `distance`:\
  Maximum interaction distance (e.g., `1.5` meters).
* `groups`:\
  Restricts interaction to a specific job if `Config.JobData.Job.requiredJob = true`.\
  Uses the job name defined in `Config.JobData.Job.name`.

> 📌 This is the main entry point where players initiate the job.

<figure><img src="/files/dKQguiotsq5WUYLImbvH" alt=""><figcaption></figcaption></figure>

## Markers

Defines visual marker settings used in the job system:

***

**`PedMarkers`:**

Displayed under job-related NPCs (e.g., start job ped).

* `id`:\
  Marker type ID (e.g., `2` – vertical cylinder).
* `color`:\
  RGB color of the marker (e.g., `{243, 207, 7}` for yellow).

***

**`DeleteCar`:**

Displayed at vehicle return zone (e.g., garage marker).

* `id`:\
  Marker type ID (e.g., `25` – vehicle garage marker).
* `color`:\
  RGB color of the marker (same format as above).

> 🎨 You can customize marker types and colors to match your server’s visual style.

<figure><img src="/files/mguemLUHnTCsGwqDKVWc" alt=""><figcaption></figcaption></figure>

## Remove Vehicle Timeout

Controls automatic deletion of the job vehicle after a delay:

* `enabled`:\
  Set to `true` to enable automatic vehicle removal after a set time.
* `time`:\
  Time in **seconds** before the vehicle is deleted (e.g., `30`).

> 📌 Useful for preventing abandoned electrician vehicles from cluttering the map.

<figure><img src="/files/NaXfJNLA7qyFtImvgHOL" alt=""><figcaption></figcaption></figure>

## Garage

Defines vehicle spawn and return settings for the electrician job:

* `SpawnPoints`:\
  List of `vec4` coordinates where the job vehicle will be spawned.\
  Format: `vec4(x, y, z, heading)`.
* `DeleteCar`:\
  List of `vec4` coordinates where players can return (delete) their job vehicle.
* `vehicleModel`:\
  Model name of the electrician job vehicle (e.g., `'burrito_electrician'`).

> 📌 You can add multiple spawn or return points if you want to support different garage zones.

<figure><img src="/files/67FxjZM6DjpQKVua1d3R" alt=""><figcaption></figcaption></figure>

## Uniforms

Defines the electrician job uniform applied to players when starting the job:

* `male`:\
  Clothing components for male characters:\
  • `tshirt_1`, `tshirt_2` – T-shirt base and variation\
  • `torso_1`, `torso_2` – Upper body/clothing\
  • `arms` – Arm style (sleeves)\
  • `pants_1`, `pants_2` – Pants and variation\
  • `shoes_1`, `shoes_2` – Footwear\
  • `helmet_1`, `helmet_2` – Helmet or headgear
* `female`:\
  Same structure as male, adjusted for female ped model clothing indexes.

> 📌 You can customize these values to fit your server’s clothing packs or RP uniform standards.

<figure><img src="/files/wWpm7ajkVCeOSMzNkrmj" alt=""><figcaption></figcaption></figure>

## Places

Defines job areas, types of gardening tasks, and the specific task positions within each zone.

Each entry represents a **job location** with a waypoint and three task types: `pulling`, `digging`, and `cleaning`.

***

**`waypoint_coords`:**

Coordinates (`x`, `y`, `z`) used to place the waypoint/GPS marker for the general task area.

***

**`jobs`:**

Dictionary of task types available in the location.

**🔸 `pulling` – Removing weeds or plants:**

* `amount`:\
  Number of random points selected from `data`. If you don’t want randomness, replace with exact amount of entries in `data`.
* `data`:\
  List of coordinates with `x`, `y`, `z`, `h` (heading), and `r` (radius) where pulling tasks take place.

**🔸 `digging` – Digging & planting new plants:**

* `amount`:\
  Same logic as above.
* `data`:\
  List of dig points with positions and headings (`x`, `y`, `z`, `h`).

**🔸 `cleaning` – Cleaning up debris or garden waste:**

* `amount`:\
  Randomly chosen task positions from `data`.
* `data`:\
  List of spots where players perform cleaning interactions (`x`, `y`, `z`, `h`).

***

> 📌 You can define multiple job locations by duplicating the structure.\
> Each zone is fully independent, allowing you to place unique sets of gardening tasks around the map.

<figure><img src="/files/C6MbVaRJdwsfDIdKP2nc" alt=""><figcaption></figcaption></figure>

## Mini Games Options

Defines task-specific settings for different gardener job types:

***

**`['digging']`**

Configuration for the digging phase (before planting):

* `holes`:\
  Number of holes the player must dig (randomized, e.g., `3–8`).

***

**`['planting']`**

Configuration for the planting phase after digging:

* `time`:\
  Time in **seconds** required to plant each plant (e.g., `10`).
* `props`:\
  List of plant prop models used during the planting process (e.g., `'prop_plant_paradise'`).

***

**`['cleaning']`**

Configuration for garden cleaning tasks:

* `time`:\
  Time in **seconds** it takes to clean each trash or dirt spot.

***

**`['pulling']`**

Configuration for plant/weed pulling tasks:

* `props`:\
  List of props to be removed by the player during the task (e.g., `'h4_prop_bush_cocaplant_01'`, `'v_med_p_ext_plant'`).

***

> 📌 Each job type can be independently adjusted to control difficulty, immersion, and task duration. You can also add more plant or weed models for variety.

<figure><img src="/files/6zd7JpHtgTJcVFlzxUye" alt=""><figcaption></figcaption></figure>


# Road Repair Job

This category is for our Road Repair Job

Immerse your players in the world of public works with the Road Repair Job script – designed to enhance roleplay and help players truly step into their character. This script offers an innovative and dynamic workspace where players can perform realistic repair tasks that contribute to the environment around them. From fixing potholes and managing roadblocks to coordinating with teammates, every task is crafted to promote immersive, hands-on gameplay. Packed with modern features and fully customizable settings, this job is an excellent addition for any server focused on quality roleplay. Give your players a meaningful new way to engage – the streets won’t fix themselves!

<figure><img src="/files/fuoDLauffw5KvuAKNHMg" alt=""><figcaption></figcaption></figure>


# Installation

Page dedicated to how to install our Road Repair Job

## Step #1 - Drag & Drop

Just Drag & Drop the `qf_roadrepairjob` folder into your `resouces` folder.

## Step #2 - SQL Installation

{% hint style="info" %}
There’s no need to manually insert any SQL file into your database. Our script automatically handles all necessary database entries on first launch, so you can safely skip this step.
{% endhint %}

## Step #3 - Script start

You can easily start our script using one of the following methods:

1. Type `ensure qf_roadrepairjob` in your server console or F8 console.\
   This will start or restart the script live on your server.
2. Add `ensure qf_roadrepairjob` to your `server.cfg` in the appropriate place.\
   This ensures the script launches automatically every time your server starts.


# Configuration

Page dedicated to how to configure our Road Repair Job

## Languages

You can set the language of the script in the configuration file.

* `en`: English
* `fr`: French
* `pl`: Polish
* `de`: German
* `es`: Spanish

<figure><img src="/files/ig9o7wm8oX8fWWbPFHXs" alt=""><figcaption></figcaption></figure>

## Props

Defines the object models used during roadwork tasks:

* `Props.sign`:\
  Road sign prop placed at work zones (e.g., `'prop_consign_01a'`).
* `Props.cone`:\
  Traffic cone used to mark or block off areas (e.g., `'prop_roadcone01a'`).
* `Props.barrier`:\
  Barrier model used to restrict access (e.g., `'prop_barrier_work06b'`).
* `Props.toolbox`:\
  Large toolbox model used in certain tasks (e.g., `'prop_tool_box_04'`).
* `Props.toolbox_handy`:\
  Smaller, portable toolbox (e.g., `'prop_tool_box_02'`).
* `Props.crate`:\
  Crate used for storage or task objectives (e.g., `'hei_prop_cash_crate_empty'`).

> 📌 You can replace these models with your own custom props to match your server's visual style.

<figure><img src="/files/AmxnGCuHw0r1jK6AGXoX" alt=""><figcaption></figcaption></figure>

## Keys

Defines compatibility with vehicle key systems used for job vehicles:

* `Keys.qb_vehiclekeys`: Set to `true` if you're using **qb-vehiclekeys**.
* `Keys.wasabi_carlock`: Set to `true` if you're using **wasabi\_carlock**.
* `Keys.renewed_vehiclekeys`: Set to `true` if you're using **renewed-vehiclekeys**.
* `Keys.sna_vehiclekeys`: Set to `true` if you're using **sna\_vehiclekeys**.

> 📌 Only one key system should be enabled at a time.\
> If none are used, leave all values set to `false` — the vehicle will be freely usable.

<figure><img src="/files/4hOoh2S20P6ShhgCIkvC" alt=""><figcaption></figcaption></figure>

## Fuel

Defines compatibility with fuel systems and default fuel level for job vehicles:

* `Fuel.CDNFuel`: Set to `true` if you're using **cdn-fuel**.
* `Fuel.LegacyFuel`: Set to `true` if you're using **LegacyFuel**.
* `Fuel.ox_fuel`: Set to `true` if you're using **ox\_fuel**.
* `Fuel.FuelLevel`:\
  Default fuel percentage assigned to the spawned job vehicle (e.g., `100` for full tank).

> 📌 Only one fuel system should be enabled at a time.\
> If you don't use any fuel script, leave all values set to `false`.

<figure><img src="/files/hpiyphQkzGXpjyC0QyjN" alt=""><figcaption></figcaption></figure>

## Target

Defines the targeting system used for interacting with job elements (e.g., NPCs, props, zones):

* `Target.ox_target`: Set to `true` to use **ox\_target**.
* `Target.qtarget`: Set to `true` to use **qtarget**.
* `Target.qb_target`: Set to `true` to use **qb-target**.
* `Target.own`: Set to `true` if you're using a **custom target system**. Requires manual implementation in `client/editable.lua`.
* `Target.useE`: Set to `true` to enable interaction using the **E key** instead of any target system.

<figure><img src="/files/P75OxRIvGzNTnieM12pF" alt=""><figcaption></figcaption></figure>

## Jobs

Defines job restriction settings for the roadwork system:

* `EnableJob`:\
  Set to `true` to **restrict access** to the roadwork job based on player’s job name.
* `JobName`:\
  Specifies the **exact job name** required to access the road repair system (e.g., `'unemployed'`).

> 📌 If `EnableJob` is set to `false`, all players can perform the job regardless of their assigned job.

<figure><img src="/files/ffkp7mtTqd6KvLEFIrrK" alt=""><figcaption></figcaption></figure>

## Target

Defines the targeting system used for interacting with job elements (e.g., NPCs, props, zones):

* `Target.ox_target`: Set to `true` to use **ox\_target**.
* `Target.qtarget`: Set to `true` to use **qtarget**.
* `Target.qb_target`: Set to `true` to use **qb-target**.
* `Target.own`: Set to `true` if you're using a **custom target system**. Requires manual implementation in `client/editable.lua`.
* `Target.useE`: Set to `true` to enable interaction using the **E key** instead of any target system.

<figure><img src="/files/P75OxRIvGzNTnieM12pF" alt=""><figcaption></figcaption></figure>

## Blip

Defines the map blip settings for the road repair job location:

* `Blip.sprite`:\
  Blip icon ID used on the map (e.g., `643`).
* `Blip.colour`:\
  Blip color ID (e.g., `47`).
* `Blip.scale`:\
  Size of the blip on the map (e.g., `0.8`).
* `Blip.label`:\
  Text label shown on the map (e.g., `_L('BLIP_LABEL')`).\
  This uses the localization system to support multiple languages.

> 📌 Customize these values to fit your server’s visual style.

<figure><img src="/files/g8gGOE8b7j100BQjBtw1" alt=""><figcaption></figcaption></figure>

## Garage

Defines vehicle spawn settings for the road repair job:

* `Garage.SpawnPoints`:\
  A list of vector4 positions where job vehicles will spawn.\
  Format: `vec4(x, y, z, heading)`.
* `Garage.vehicleModel`:\
  Model name of the vehicle used for the job (e.g., `'rumpo2'`).

> 📌 You can add multiple spawn points to support dynamic or multi-location spawning.

<figure><img src="/files/OLyI89I4SOa7W5USsxHr" alt=""><figcaption></figcaption></figure>

## Salary

Defines the payment system for completing road repair tasks:

* `Salary.amount`:\
  The amount of money the player receives per completed task (e.g., `5000`).
* `Salary.moneyType`:\
  The type of money given, automatically selected based on the active framework:\
  • `'money'` for **ESX**\
  • `'cash'` for **QBCore** and **QBox**\
  • `'money'` or custom type for **vRP**

> 📌 You can customize the payment type manually if using a non-standard or modified money system.

<figure><img src="/files/iHw8fuWa93O9eIsmVCsr" alt=""><figcaption></figcaption></figure>

## Stop Traffic

Defines traffic control behavior near active roadwork zones:

* `StopTraffic.enabled`:\
  If `true`, disables vehicle AI around active job areas to prevent traffic interference.
* `StopTraffic.distance`:\
  Radius (in meters) around the work zone where traffic will be halted (e.g., `100.0`).

> 📌 Useful for immersive and safe roleplay during road repair tasks.

<figure><img src="/files/HW0NVJMEHT3OHS0lEBKW" alt=""><figcaption></figcaption></figure>

## Zones

Defines interaction zones and NPCs for starting, ending, and managing the road repair job:

#### `Zones.StartJob`:

Zone where players begin the job.

* `labelTarget`: Text shown when using a target system (localized).
* `labelNoTarget`: Text shown when using key-based interaction (localized).
* `icon`: Font Awesome icon displayed in the UI.
* `pedModel`: Ped model spawned at the location.
* `coords`: Coordinates of the zone.
* `pedHeading`: Direction the ped is facing.
* `distance`: Max distance for interaction.
* `groups`: Job access restriction based on `Config.JobName`.

***

#### `Zones.Garage`:

Zone where players retrieve their job vehicle.

* `labelTarget`: Target interaction text (localized).
* `labelNoTarget`: Key-based interaction text (localized).
* `icon`: Font Awesome icon for the garage.
* `pedModel`: Ped model spawned at the garage.
* `coords`: Vehicle spawn location.
* `pedHeading`: Heading for the garage ped.
* `distance`: Max interaction distance.
* `groups`: Job access restriction (same as above).

***

#### `Zones.EndJob`:

Zone where players finish their shift and return equipment.

* `labelTarget`: Target interaction text (localized).
* `labelNoTarget`: Key-based interaction text (localized).
* `icon`: Font Awesome icon for ending the job.
* `pedModel`: Ped model for the end zone.
* `coords`: Coordinates where players end the job.
* `pedHeading`: Ped heading.
* `distance`: Interaction distance.
* `groups`: Restricts access based on job if `Config.EnableJob = true`.

> 📌 All texts (`_L(...)`) use the localization system for multi-language support.

<figure><img src="/files/CqJRKksIvESM5c9qD6QD" alt=""><figcaption></figcaption></figure>

## Missions

Defines available repair missions and their step-by-step task sequences:

Each mission entry includes:

* `disabled`:\
  Set to `true` to temporarily disable the mission.
* `label`:\
  Localized mission name shown in the UI (e.g., `_L('REPAIR_BRIDGE')`).
* `coords`:\
  Center location of the mission area (`vec3`).
* `size`:\
  Radius (in meters) of the work zone area.
* `tasks`:\
  Ordered list of tasks that must be completed to finish the mission:

***

#### Supported Task Types:

* `stop_traffic`:\
  Temporarily disables traffic in the mission zone.
* `cones`:\
  Spawns and requires placement of traffic cones.\
  • `coords`: List of positions where cones must be placed.
* `barriers`:\
  Spawns and requires placement of barriers.\
  • `coords`: List of positions where barriers must be placed.
* `toolbox`:\
  Places a toolbox prop at a specific location.\
  • `toolboxCoords`: Coordinates where the player must interact.
* `build`:\
  Starts a simulated repair/building animation (no additional data required).
* `drilling`:\
  Requires player to drill at a designated point.\
  • `toolboxCoords`: Interaction point for starting the drilling.
* `run_traffic`:\
  Re-enables normal vehicle traffic in the area once work is complete.

> 🛠️ You can create multiple missions by duplicating this structure and adjusting coordinates, labels, and tasks as needed.

<figure><img src="/files/q5hC3jGlR5m1kXILXVdC" alt=""><figcaption></figcaption></figure>

## Uniforms

Defines the job-specific uniforms assigned to players when starting the road repair job:

* `Uniforms.male`:\
  Clothing components for male characters:\
  • `tshirt`, `torso`, `arms`, `pants`, `shoes`, `helmet` — each defined with part index (`_1`) and texture variation (`_2`).
* `Uniforms.female`:\
  Clothing components for female characters:\
  • Follows the same structure as male configuration.

> 👷 These outfits are automatically applied when starting the job.\
> You can freely adjust component IDs to match your server’s clothing pack or uniform style.

<figure><img src="/files/uKByoOr3UC1Qp2IbB4Zt" alt=""><figcaption></figcaption></figure>


# Graffiti

This category is for our Graffiti

Our graffiti creation script takes roleplay immersion to the next level. Players can create their own graffiti based on their ideas – whether it's text, a drawing, or an image from a URL. They can also save graffiti designs, name them freely, use our custom painting tools, save favorite colors in a quick-access menu, scale their artworks, and fully express their creativity. The script offers extensive customization options, is optimized for high performance, includes anti-cheat protection, and features a built-in webhook system to keep you informed about everything that matters. The main goal of our script is to provide players with maximum enjoyment and creativity during gameplay.

<figure><img src="/files/CoZjBuczFASRBAF83xIj" alt=""><figcaption></figcaption></figure>


# Installation

Page dedicated to how to install our Graffiti

## Step #1 - Drag & Drop

Just Drag & Drop the `qf_graffiti` folder into your `resouces` folder.

## Step #2 - Script start

You can easily start our script using one of the following methods:

1. Type `ensure qf_graffiti` in your server console or F8 console.\
   This will start or restart the script live on your server.
2. Add `ensure qf_graffiti` to your `server.cfg` in the appropriate place.\
   This ensures the script launches automatically every time your server starts.


# Configuration

Page dedicated to how to configure our Graffiti

## Languages

You can set the language of the script in the configuration file.

* `en`: English
* `fr`: French
* `pl`: Polish
* `de`: German
* `es`: Spanish

<figure><img src="/files/ig9o7wm8oX8fWWbPFHXs" alt=""><figcaption></figcaption></figure>

## Basics

Defines general behavior and interaction settings for graffiti functionality:

* `Basics.RenderDistance`:\
  Maximum distance (in meters) from which graffiti can be seen.
* `Basics.AutomaticlyWash`:\
  Controls automatic graffiti removal over time:\
  • `status`: Set to `true` to enable automatic cleaning.\
  • `time`: Time (in seconds) after which graffiti is removed.
* `Basics.Spraying`:\
  Configuration for the spraying process:\
  • `time`: Time (in seconds) it takes to spray graffiti.\
  • `allowImages`: If `true`, allows using custom images instead of preset text.\
  • `MaxImageResoultion`: Maximum allowed dimensions for custom image graffiti.\
  • `MaxDistanceToDraw`: Max distance from player to surface for placing graffiti.
* `Basics.Washing`:\
  Configuration for graffiti removal process:\
  • `time`: Time (in seconds) it takes to wash off graffiti.
* `Basics.Items`:\
  Item-based compatibility settings (ESX / QBCore / QBox supported):\
  • `menu.name`: Item required to open the graffiti menu (e.g., `'graffiti_can'`).\
  • `menu.enabled`: If `true`, item is required to use the spray function.\
  • `remove.name`: Item required to remove graffiti (e.g., `'graffiti_remover'`).\
  • `remove.enabled`: If `true`, item is required to clean graffiti.\
  • `removeAfterUse`: Whether items are removed after usage. *(Configure in `config/server/config_framework.lua`)*

<figure><img src="/files/2mAyDXfRB2eACrvXJpE9" alt=""><figcaption></figcaption></figure>

## Admin

Defines admin-related tools and permissions for graffiti management:

* `Admin.aceName`:\
  ACE permission required to access graffiti management features (e.g., `'manageGraffiti'`).
* `Admin.tags`:\
  Displays graffiti metadata (creator name and creation time) when nearby:\
  • `enabled`: If `true`, shows admin tags on graffiti.\
  • `distance`: Maximum distance from graffiti to display tag info.

<figure><img src="/files/mnIJ2fnFo5DsS5XcnG3V" alt=""><figcaption></figcaption></figure>

## Commands

Defines the commands used to interact with graffiti features:

* `Commands.menu`:\
  • `name`: Command to open the graffiti menu (e.g., `/graffitimenu`).\
  • `enabled`: If `true`, the command is available for use.
* `Commands.remove`:\
  • `name`: Command to remove nearby graffiti (e.g., `/graffitiremove`).\
  • `enabled`: If `true`, the command is available for use.
* `Commands.toggleVisiblity`:\
  • `name`: Command to toggle the visibility of all graffiti (e.g., `/graffititoggle`).\
  *(Primarily for debugging or admin purposes.)*

<figure><img src="/files/DeSfqstLoy0sHklsMMTE" alt=""><figcaption></figcaption></figure>

## Exports

Defines the exports available for triggering graffiti actions from other scripts:

* `Exports.menu`:\
  • `name`: Name of the export function used to open the graffiti menu (e.g., `exports.resourceName:graffitimenu()`).\
  • `enabled`: If `true`, the export is active and can be called externally.
* `Exports.remove`:\
  • `name`: Name of the export function used to remove nearby graffiti (e.g., `exports.resourceName:graffitiremove()`).\
  • `enabled`: If `true`, the export is active and can be called externally.

<figure><img src="/files/03kT8MfoVMzQ9dN2Ac3j" alt=""><figcaption></figcaption></figure>


# Notify

This category is for our Notify

Our Notify script is a fully standalone, highly optimized and cheat-protected notification system that works with any framework. Packed with modern notifications, progress bars, and textUIs – all fully configurable and ready to use out of the box. Clean design, lightweight performance, and constant updates based on community feedback make it the perfect choice for any server. Upgrade your server’s experience today – your players will feel the difference!

<figure><img src="/files/yAzuLXDuIWRZ5yoQjQ9H" alt=""><figcaption></figcaption></figure>


# Installation

Page dedicated to how to install our Notify

## Step #1 - Drag & Drop

Just Drag & Drop the `qf_notify` folder into your `resouces` folder.

## Step #2 - Script start

You can easily start our script using one of the following methods:

1. Type `ensure qf_notify` in your server console or F8 console.\
   This will start or restart the script live on your server.
2. Add `ensure qf_notify` to your `server.cfg` in the appropriate place.\
   This ensures the script launches automatically every time your server starts.


# Configuration

Page dedicated to how to configure our Notify

## Languages

You can set the language of the script in the configuration file.

* `en`: English
* `fr`: French
* `pl`: Polish
* `de`: German
* `es`: Spanish

<figure><img src="/files/ig9o7wm8oX8fWWbPFHXs" alt=""><figcaption></figcaption></figure>

## Production Mode

Defines the mode in which the script operates, intended for general or production use:

* `Production`: If `true`, enables recommended settings optimized for live/production servers.\
  This is the suggested option for most users, especially non-technical ones.

<figure><img src="/files/h3ZS62Vg6E0BWGEVWcxI" alt=""><figcaption></figcaption></figure>

## Menu Command

Defines the command and keybind used to open the notification settings menu:

* `MenuCommand.Enabled`: If `true`, enables the settings menu for players.
* `MenuCommand.Name`: Name of the command used to open the menu (e.g., `/notifysettings`).
* `MenuCommand.Key`: Keybind to open the menu (e.g., `'F9'`). Set to `false` to disable the keybind.

<figure><img src="/files/Ethtgzp2tNmVOJ3CqsAe" alt=""><figcaption></figcaption></figure>

## Reset Command

Defines the command used to reset notification settings to default values:

* `ResetCommand.Enabled`: If `true`, enables the reset command for players.
* `ResetCommand.Name`: Name of the command used to reset settings (e.g., `/qf_resetnotify`).

<figure><img src="/files/Xyb27nOKJrq6T9u9wzNz" alt=""><figcaption></figcaption></figure>

## Debug Commands

Enables a set of debug/test commands used during development. **Do not use in production!**

* `DebugCommands.Enabled`: If `true`, allows access to testing commands for notifications and UI elements:\
  • `/notify_error`\
  • `/notify_success`\
  • `/notify_info`\
  • `/notify_warning`\
  • `/progress`\
  • `/textui`

> 🔒 Recommended to disable (`false`) or set `Config.Production = true` on live servers.

<figure><img src="/files/a88FyKNWZCScDPB97DX5" alt=""><figcaption></figcaption></figure>

## Advanced

Defines advanced internal settings for stability and protection:

* `Advanced.SafeguardsEnabled`: If `true`, enables internal safety checks to prevent potential issues or misuse during script execution. Recommended to keep enabled.

<figure><img src="/files/geGaD94oJ1krWCzsIQSx" alt=""><figcaption></figcaption></figure>

## Other settings

Handles conditional logic based on configuration settings:

* When `Config.Production` is set to `true`:\
  • `DebugCommands.Enabled` is automatically disabled.\
  • `Advanced.SafeguardsEnabled` is enforced for stability.
* If either `MenuCommand.Enabled` or `MenuCommand.Key` is set:\
  • Registers a keybind for opening the notification settings menu using `RegisterKeyMapping`.\
  • This allows players to access the menu via a keyboard shortcut (e.g., `F9`).

<figure><img src="/files/hcDMzYG5qqdjuPCgjXi5" alt=""><figcaption></figcaption></figure>

## Compatibility - ox\_lib

Replace function lib.notify with this from the screenshot.

<figure><img src="/files/x9dyV2YXfO7aUVwW1ULC" alt=""><figcaption></figcaption></figure>

## Exports - Client-side

These native exports allow client-side scripts to trigger notifications, progress bars, and text UI prompts safely and efficiently.\
All exports include **type and length validation** when `Config.Advanced.SafeguardsEnabled = true`.

***

**📢 `exports('notify', function(data) {...})`**

Displays a styled notification.

```lua
exports.qf_notify:notify({
    type = 'success',          -- string: 'success', 'info', 'error', 'warning'
    title = 'Notification',    -- string: max 100 characters
    description = 'You did it!', -- string: max 300 characters
    timeout = 5000             -- number: duration in milliseconds
})
```

**Validation:**

* Ensures proper types (`string` / `number`)
* Title max: 100 characters
* Description max: 300 characters

***

**⏳ `exports('progress', function(data) {...})`**

Displays a timed progress bar with optional callback.

```lua
exports.qf_notify:progress({
    time = 5000,               -- number: duration in milliseconds (max 60000)
    text = 'Processing...',    -- string
    callback = function()
        print("Progress finished")
    end,
    force = false              -- (optional) bypass running progress
})
```

**Validation:**

* Ensures `callback` is a valid `function`
* Time must be ≤ 60000 ms
* Only one progress bar can run at a time unless `force = true`

***

**💬 `exports('textui', function(data) {...})`**

Displays a temporary key-based text prompt on screen.

```lua
exports.qf_notify:textui({
    key = 'E',                        -- string: key shown in UI
    title = 'Interact',              -- string: max 100 characters
    description = 'Press E to use',  -- string: max 300 characters
    state = true                     -- boolean: true = show, false = hide
})
```

**Validation:**

* Type safety on all fields
* Character limits for title and description

***

> 🛡️ When `Config.Advanced.SafeguardsEnabled = true`, each export performs strict validation to prevent script errors or abuse.\
> ✅ Use these exports to create unified and modern UI feedback in any of your client-side systems.

## Triggers - Client-side & Server-side

#### 🧩 Server → Client Events

**🔔 `qf_notify/showNotification`**

Displays a standard notification using the provided `data`.

```lua
TriggerClientEvent('qf_notify/showNotification', source, {
    type = 'success',
    title = 'Success',
    description = 'Action completed successfully!',
    timeout = 5000
})
```

* Delegates to: `exports.qf_notify:notify(data)`
* See: `exports.qf_notify:notify(...)`

***

**⏳ `qf_notify/showProgressBar`**

Displays a progress bar with optional callback (client-side only).

```lua
TriggerClientEvent('qf_notify/showProgressBar', source, {
    time = 7000,
    text = 'Processing...'
})
```

* Delegates to: `exports.qf_notify:progress(data)`

***

**💬 `qf_notify/showTextUI`**

Displays a temporary text UI element above the minimap or at the screen edge.

```lua
TriggerClientEvent('qf_notify/showTextUI', source, {
    state = true,
    key = 'E',
    title = 'Talk to the NPC',
    description = 'Press E to interact.'
})
```

* Delegates to: `exports.qf_notify:textui(data)`

> 📌 These events can be triggered from both client and server, making integration with other scripts easy and flexible.

#### 🧩 Client → Client Events (local usage)

These events allow you to trigger notifications, progress bars, and text UI directly from another **client-side script**.

***

**🔔 `qf_notify/showNotification`**

Displays a notification with the given data:

```lua
TriggerEvent('qf_notify/showNotification', {
    type = 'info',
    title = 'Info',
    description = 'This is a local test notification.',
    timeout = 4000
})
```

* Internally calls: `exports.qf_notify:notify(data)`
* Supported types: `success`, `info`, `error`, `warning`

***

**⏳ `qf_notify/showProgressBar`**

Displays a progress bar:

```lua
TriggerEvent('qf_notify/showProgressBar', {
    time = 5000,
    text = 'Cleaning up area...'
})
```

* Internally calls: `exports.qf_notify:progress(data)`
* Does **not** support callback when triggered via event (only via export)

***

**💬 `qf_notify/showTextUI`**

Displays a key-based UI prompt:

```lua
TriggerEvent('qf_notify/showTextUI', {
    state = true,
    key = 'E',
    title = 'Open Locker',
    description = 'Press E to open your locker.'
})
```

* Internally calls: `exports.qf_notify:textui(data)`

***

> ✅ Use these events when triggering `qf_notify` features **locally from another client-side script**, without the need to go through the server.


# Job Center

This category is for our Job Center

Our Job Center script is compatible with the most popular FiveM frameworks, including ESX, QB, and QBOX, and can be easily adapted to work with any other framework. It’s highly optimized for performance, protected against exploits, and ready to use right out of the box. The script features a built-in logging system and full configuration through easy-to-edit config files. With a clean, user-friendly design, lightweight footprint, and frequent updates based on community feedback, it’s the ideal solution for any FiveM server. Upgrade your server experience today – your players will notice the difference!

<figure><img src="/files/gKWrWRYZ0dehcobqfwG0" alt=""><figcaption></figcaption></figure>


# Installation

Page dedicated to how to install our Job Center

## Step #1 - Drag & Drop

Just Drag & Drop the `qf_jobcenter` folder into your `resouces` folder.

## Step #2 - Script start

You can easily start our script using one of the following methods:

1. Type `ensure qf_jobcenter` in your server console or F8 console.\
   This will start or restart the script live on your server.
2. Add `ensure qf_jobcenter` to your `server.cfg` in the appropriate place.\
   This ensures the script launches automatically every time your server starts.


# Configuration

Page dedicated to how to configure our Job Center

## Languages

You can set the language of the script in the configuration file.

* `en`: English
* `fr`: French
* `pl`: Polish
* `de`: German
* `es`: Spanish

<figure><img src="/files/ig9o7wm8oX8fWWbPFHXs" alt=""><figcaption></figcaption></figure>

## Compatibility

Defines compatibility settings for third-party notification systems:

* `Compatibility.notifications.qf_notify`:\
  Set to `true` if you're using the `qf_notify` system.\
  Enables full integration with QF Developers’ notifications.

<figure><img src="/files/BI6nPl9s12dgf5SL0Q54" alt=""><figcaption></figcaption></figure>

## Access

Defines how players can access the job center menu:

* `Access.openMenuAnywhere`:\
  If `true`, allows players to open the job center menu from any location.
* `Access.command`:\
  • `enabled`: Enables access via command.\
  • `name`: Command name used to open the menu (e.g., `/openjobcenter`).
* `Access.export`:\
  • `enabled`: Enables access via export from other scripts.\
  • `name`: Name of the export function (e.g., `exports.qf_jobcenter:openJobCenter()`).

<figure><img src="/files/YdRY2sbC35J498xcGr2I" alt=""><figcaption></figcaption></figure>

## Target

Defines which targeting system is used for interaction zones:

* `Target.ox_target`: Set to `true` to use `ox_target`.
* `Target.qtarget`: Set to `true` to use `qtarget`.
* `Target.qb_target`: Set to `true` to use `qb-target`.
* `Target.own`: Set to `true` if you're using a custom targeting system. You must implement it manually in `client/editable.lua`.
* `Target.useE`: Set to `true` to allow interactions using the **E key** instead of any target system.

<figure><img src="/files/P75OxRIvGzNTnieM12pF" alt=""><figcaption></figcaption></figure>

## Blip

Defines the map blip settings for the job center location:

* `Blip.coords`: Coordinates where the blip will appear on the map (`vec3`).
* `Blip.sprite`: Blip icon ID (see FiveM blip list for reference).
* `Blip.colour`: Blip color ID.
* `Blip.scale`: Size of the blip on the map.
* `Blip.label`: Text label displayed on the map when hovering over the blip.

<figure><img src="/files/R2iKqJXe9C2HuIqtaQNB" alt=""><figcaption></figcaption></figure>

## Zones

Defines NPC and interaction zone settings for accessing the job center menu:

* `Zones.jobMenu.targetLabel`:\
  Label shown when targeting the NPC (e.g., `'Talk'`).
* `Zones.jobMenu.icon`:\
  Font Awesome icon used in the interaction menu (e.g., `'fa-solid fa-building-circle-exclamation'`).
* `Zones.jobMenu.model`:\
  Ped model spawned at the job center location (e.g., `'a_m_y_business_03'`).
* `Zones.jobMenu.coords`:\
  Vector3 position where the NPC will be placed.
* `Zones.jobMenu.heading`:\
  Direction the NPC will face.
* `Zones.jobMenu.distance`:\
  Maximum interaction distance between the player and the NPC.

<figure><img src="/files/aXxryM3t5RxP1eW6SSCq" alt=""><figcaption></figcaption></figure>

## Jobs - Basics

Defines the list of available jobs that can be selected through the job center menu:

Each job entry includes the following fields:

* `jobtitle`: Display name of the job shown in the menu (e.g., `'Policeman'`).
* `jobname`: Internal job identifier used by your framework (e.g., `'police'`).
* `grade`: Grade assigned to the player when selecting the job (usually `0` for new recruits).
* `imagename`: Image filename used in the UI (should match the image placed in the UI folder, e.g., `police.png`).
* `description`: Description of the job shown in the UI to give players context and roleplay purpose.

> 💡 You can add as many jobs as you want by following this structure.

<figure><img src="/files/k7IYFo9mbJrVj0jWiFn5" alt=""><figcaption></figcaption></figure>

## Jobs - Default

Defines the default job assigned to players who have not selected a specific profession:

* `DefaultJob.name`: Internal job name (e.g., `'unemployed'`).
* `DefaultJob.grade`: Default grade assigned within the job (typically `0`).

> 📌 This job is usually used as the fallback or starting role for new players.

<figure><img src="/files/uBvcIqjKKfvyPCV1F0fb" alt=""><figcaption></figcaption></figure>


# Car Races

This category is for our Car Races

Bring the thrill of illegal street racing to your server with our Car Races script – a fast-paced and exciting system designed for adrenaline junkies and competitive players alike. Create your own race routes, challenge friends and rivals, and place bets to raise the stakes. The script offers a simple yet powerful experience with intuitive controls, dynamic race creation, and fully configurable options to suit your server’s style. Whether you're racing for glory or cash, this script captures the essence of underground racing with smooth performance and a clean design. Start your engines – it’s time to prove who rules the streets!

<figure><img src="/files/qAsZACs15MECMsLnTGra" alt=""><figcaption></figcaption></figure>


# Installation

Page dedicated to how to install our Car Races

## Step #1 - Drag & Drop

Just Drag & Drop the `qf_carraces` folder into your `resouces` folder.

## Step #2 - SQL Installation

{% hint style="info" %}
There’s no need to manually insert any SQL file into your database. Our script automatically handles all necessary database entries on first launch, so you can safely skip this step.
{% endhint %}

## Step #3 - Script start

You can easily start our script using one of the following methods:

1. Type `ensure qf_carraces` in your server console or F8 console.\
   This will start or restart the script live on your server.
2. Add `ensure qf_carraces` to your `server.cfg` in the appropriate place.\
   This ensures the script launches automatically every time your server starts.


# Configuration

Page dedicated to how to configure our Car Races

## Languages

You can set the language of the script in the configuration file.

* `en`: English
* `fr`: French
* `pl`: Polish
* `de`: German
* `es`: Spanish

<figure><img src="/files/ig9o7wm8oX8fWWbPFHXs" alt=""><figcaption></figcaption></figure>

## Command

Defines the command used to open the race menu:

* `Command.enabled`:\
  Set to `true` to allow players to access the race system using a command.
* `Command.name`:\
  Name of the command used to open the race menu (e.g., `/racing`).

<figure><img src="/files/SieI450HtURjJlIAxy5s" alt=""><figcaption></figcaption></figure>

## Target

Defines the targeting system used for interacting with race-related NPCs or zones:

* `Target.ox_target`: Set to `true` to use `ox_target`.
* `Target.qtarget`: Set to `true` to use `qtarget`.
* `Target.QBCore_target`: Set to `true` to use `qb-target`.
* `Target.own`: Set to `true` if you are using a custom target system. Requires manual implementation in `client/editable.lua`.
* `Target.useE`: Set to `true` to allow interaction using the **E key** instead of a target system.

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

## Locations

Defines NPC spawn locations for accessing the race system menu:

Each location includes the following properties:

* `model`:\
  Ped model to be spawned (e.g., `'s_m_y_doorman_01'`).
* `coords`:\
  Vector3 coordinates where the NPC will be placed.
* `heading`:\
  Direction the NPC should face.
* `icon`:\
  Font Awesome icon shown in the interaction prompt (e.g., `'fa-solid fa-play'`).
* `label`:\
  Text label displayed when targeting the NPC (e.g., `'Open menu'`).

> 📌 You can add multiple entries using the same structure to place race access points in different parts of the map.

<figure><img src="/files/gNDLPdmEnbX5EpSA4Wjq" alt=""><figcaption></figcaption></figure>

## XP System

Defines XP system settings for racing progression:

* `XP.win`:\
  Amount of XP awarded to the winner of a race.
* `XP.lose`:\
  Amount of XP awarded to players who participate but do not win.
* `XP.nextLevel`:\
  Total XP required to level up. Can be used for unlocking rewards or tracking player progression.

<figure><img src="/files/HmU3tg0WZI5LI6FMasCs" alt=""><figcaption></figcaption></figure>

## Other Data

Defines core race behavior settings and gameplay parameters:

* `Data.joinProximity`:\
  Distance (in meters) within which players can join a race.
* `Data.joinKeybind`:\
  Key code (default `51`, which is the **E** key) used to join a race.
* `Data.joinDuration`:\
  Time (in milliseconds) players have to join after the race is created.
* `Data.freezeDuration`:\
  Duration (in milliseconds) that players are frozen at the start before the race begins.
* `Data.checkpointProximity`:\
  Distance (in meters) required to trigger checkpoint validation.
* `Data.checkpointRadius`:\
  Radius of the visible checkpoint area.
* `Data.checkpointHeight`:\
  Height of the checkpoint marker.
* `Data.checkpointBlipColor`:\
  Blip color ID used for checkpoints on the map.
* `Data.finishTimeout`:\
  Maximum time (in milliseconds) a race remains active after the first player finishes.

<figure><img src="/files/oqBC9Yu8kcemfEYP91Tu" alt=""><figcaption></figcaption></figure>


# Banking

This category is for our Banking

Upgrade your server’s economy with our Banking System script – a polished and immersive solution that brings real-world banking features into the game. Players can manage their accounts, transfer money, view transaction history, and interact with in-game currency in a realistic and intuitive way. Whether you’re running a serious roleplay server or just want to improve financial interactions between players, this system offers full configurability and seamless integration with popular frameworks. Designed for performance and ease of use, it enhances immersion and adds depth to your server’s economy. Secure, user-friendly, and essential for modern gameplay – your players will thank you!

<figure><img src="/files/Fa2dMFqNOUVdWNIHe886" alt=""><figcaption></figcaption></figure>


# Installation

Page dedicated to how to install our Banking

## Step #1 - Drag & Drop

Just Drag & Drop the `qf_banking` folder into your `resouces` folder.

## Step #2 - SQL Installation

{% hint style="info" %}
There’s no need to manually insert any SQL file into your database. Our script automatically handles all necessary database entries on first launch, so you can safely skip this step.
{% endhint %}

## Step #3 - Script start

You can easily start our script using one of the following methods:

1. Type `ensure qf_banking` in your server console or F8 console.\
   This will start or restart the script live on your server.
2. Add `ensure qf_banking` to your `server.cfg` in the appropriate place.\
   This ensures the script launches automatically every time your server starts.


# Configuration

Page dedicated to how to configure our Banking

## Languages

You can set the language of the script in the configuration file.

* `en`: English
* `fr`: French
* `pl`: Polish
* `de`: German
* `es`: Spanish

<figure><img src="/files/ig9o7wm8oX8fWWbPFHXs" alt=""><figcaption></figcaption></figure>

## ATM's

Defines ATM models that can be used for interactions via target systems:

* `AtmModels`:\
  A list of object model names (hashes) recognized as ATMs.\
  These are used to place interaction zones for opening the banking UI.

> 📌 Default supported models:\
> • `prop_fleeca_atm`\
> • `prop_atm_01`\
> • `prop_atm_02`\
> • `prop_atm_03`\
> You can add or remove models based on your server's mapping.

<figure><img src="/files/uzT5fKkm4Qzbt31Ul472" alt=""><figcaption></figcaption></figure>

## Target

Defines the targeting system used for ATM and bank interactions:

* `Target.ox_target`: Set to `true` if you're using **ox\_target**.
* `Target.qtarget`: Set to `true` if you're using **qtarget**.
* `Target.qb_target`: Set to `true` if you're using **qb-target**.
* `Target.own`: Set to `true` if you're using a **custom targeting system**. Requires manual implementation in `client/editable.lua`.
* `Target.useE`: Set to `true` to allow interactions using the **E key** instead of a target system.

<figure><img src="/files/yMCZB2clRZ1CLO00l6CB" alt=""><figcaption></figcaption></figure>

## Zones

Defines all coordinates, labels, and settings for bank and ATM interaction zones:

#### `Zones.Bank`:

Settings for in-world bank locations with optional NPCs and interaction support.

* `Color`: Blip color ID for the map.
* `Label`: Name shown on the blip (e.g., `'Bank'`).
* `Sprite`: Blip icon ID used for banks.
* `Scale`: Size of the blip icon.
* `labelTarget`: Text shown when targeting the bank with a targeting system.
* `labelATMtarget`: Text for ATM interaction via target.
* `labelNoTarget`: Prompt shown if using interaction without a target system (e.g., "Press ~~INPUT\_CONTEXT~~").
* `icon`: Font Awesome icon used in the target interaction (e.g., `'fa fa-bank'`).
* `pedModel`: Ped model spawned at the bank.
* `scenario`: Animation scenario used by the ped.
* `coords`: List of bank locations (vector3).
* `pedHeading`: Heading values (one for each ped location).
* `distance`: Max distance required to interact.
* `groups`: Job restriction (set to `nil` for no restriction).
* `bank`: Set to `true` to mark this as a bank zone.

***

#### `Zones.ATM`:

Settings for ATM locations used when not relying on target models.

* `labelNoTarget`: Prompt shown for ATM interaction without target.
* `labelATMtarget`: Text for ATM interaction via target system.
* `coords`: List of ATM coordinates to be used without model-based detection.
* `pedHeading`: Heading for optional NPC near the ATM.
* `distance`: Max interaction distance.
* `groups`: Job restriction (set to `nil` for no restriction).
* `bank`: Set to `false` to mark this zone as ATM (not a bank).

> 📌 If you're using a targeting system, ATMs will automatically work based on models defined in `Config.AtmModels`. If not, you must manually define ATM coordinates here.

<figure><img src="/files/7AHw2jas7AkIeRxjUl72" alt=""><figcaption></figcaption></figure>

## Banks

Defines standalone bank locations with optional blip configuration:

* `Position`:\
  Coordinates and heading (`vector4`) for the bank location.
* `Blip`:\
  Controls whether a map blip is displayed at this location:\
  • `Enabled`: Set to `true` to show the blip on the map.\
  • `Color`: Blip color ID.\
  • `Label`: Name shown on the map (e.g., `'Bank'`).\
  • `Sprite`: Icon used for the blip (e.g., `108` for banks).\
  • `Scale`: Size of the blip icon on the map.

> 📌 You can define multiple bank locations by adding more entries to the list.

<figure><img src="/files/eOjZJZnKwtkVIF2bzl6Y" alt=""><figcaption></figcaption></figure>

## Exports

Server-side exports for the our banking resource

### GetAccountBalance

Retrieves the current bank account balance of a player.

**Parameters:**

* `playerId` *(number)* – The server ID of the player.

**Returns:**

* `success` *(boolean)* – Whether the operation was successful.
* `result` *(number|string)* – The account balance if successful, or an error message if failed.

<figure><img src="/files/vCVGpbTDJsDPCWw4uX9W" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/inlFt6wReTHfgoK4eNPb" alt=""><figcaption></figcaption></figure>

### CreateLog

Logs a transaction to the banking history without modifying the balance. Useful for third-party resources that handle money internally but want to show it in the banking history.

**Parameters:**

* `playerId` (number): The server ID of the player source.
* `amount` (number): The amount of the transaction.
* `transactionType` (string): A short description or type of the transaction (e.g., "Fine", "Shop Purchase").
* `accountType` (string, optional): The type of account ('bank', 'money'/'cash'). Defaults to `'bank'`.
* `beforeBalance` (number, optional): The balance of the player *before* the transaction occurred. If not provided, it will attempt to fetch the current balance.
* `targetId` (number, optional): The server ID of a target player (if this is a transfer). Defaults to `-1`.
* `targetBeforeBalance` (number, optional): The balance of the target player *before* the transaction (if this is a transfer).

<figure><img src="/files/V5Dy43MjJNKMT0MJaUyP" alt=""><figcaption></figcaption></figure>

### AddMoney

Adds money to a player's bank account.

**Parameters:**

* `playerId` *(number)* – The server ID of the player.
* `amount` *(number)* – The amount of money to add.

**Returns:**

* `success` *(boolean)* – Whether the operation was successful.
* `result` *(string)* – Success or error message.

<figure><img src="/files/2sw3ywFQS7JRcwD7piVu" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/VAEYOw7d5RixZhBB5FZ0" alt=""><figcaption></figcaption></figure>

### RemoveMoney

Removes money from a player's bank account.

**Parameters:**

* `playerId` *(number)* – The server ID of the player.
* `amount` *(number)* – The amount of money to remove.

**Returns:**

* `success` *(boolean)* – Whether the operation was successful.
* `result` *(string)* – Success or error message.

<figure><img src="/files/EktfQbHhZ1LYWVW9Yy1x" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/hkZpB1DOoMuW2FDX2O8p" alt=""><figcaption></figcaption></figure>


# Skin Menu

This category is for our Skin Menu

Upgrade your character system with our Skin Menu – a sleek and fully optimized solution designed to offer a smooth and immersive customization experience. Featuring a modern and minimalistic interface, this script makes character management effortless and enjoyable for players. Thanks to plug-and-play setup, there’s no need for complex configuration. The menu provides instant access to clothing stores, barber shops, tattoo parlors, dressing rooms, and more – all in one cohesive system. Whether you’re running a roleplay or freeroam server, this script fits seamlessly and elevates overall player experience. Stylish, efficient, and packed with functionality – it’s the customization tool your server deserves.

<figure><img src="/files/BzlOUsDNHsGjNzHJK9jJ" alt=""><figcaption></figcaption></figure>


# Installation

Page dedicated to how to install our Skin Menu

## Step #1 - Drag & Drop

Just Drag & Drop the `qf_skinmenu` folder into your `resouces` folder.

## Step #2 - SQL Installation

{% hint style="info" %}
There’s no need to manually insert any SQL file into your database. Our script automatically handles all necessary database entries on first launch, so you can safely skip this step.
{% endhint %}

## Step #3 - Script start

You can easily start our script using one of the following methods:

1. Type `ensure qf_skinmenu` in your server console or F8 console.\
   This will start or restart the script live on your server.
2. Add `ensure qf_skinmenu` to your `server.cfg` in the appropriate place.\
   This ensures the script launches automatically every time your server starts.


# Configuration

Page dedicated to how to configure our Skin Menu

## Languages

You can set the language of the script in the configuration file.

* `en`: English
* `fr`: French
* `pl`: Polish
* `de`: German
* `es`: Spanish

<figure><img src="/files/ig9o7wm8oX8fWWbPFHXs" alt=""><figcaption></figcaption></figure>

## Tattoos Compatibility

Defines compatibility with external tattoo systems:

* `rcore`:\
  Set to `true` if you are using **rcore\_tattoos**.
* `vms`:\
  Set to `true` if you are using **vms\_tattoos**.

> 📌 These settings allow tattoos to persist and display correctly when changing outfits or reopening the skin menu. Enable only the system you're actually using.

<figure><img src="/files/luuhZjNzvzE7QCi9DfEI" alt=""><figcaption></figcaption></figure>

## Target

Defines which targeting system is used for interacting with skin menu NPCs or zones:

* `ox_target`:\
  Set to `true` to use **ox\_target**.
* `qtarget`:\
  Set to `true` to use **qtarget**.
* `qb_target`:\
  Set to `true` to use **qb-target**.
* `useE`:\
  Set to `true` to enable interaction using the **E key** instead of any target system.

> 📌 Only one system should be enabled at a time. Make sure to disable others to avoid conflicts.

<figure><img src="/files/y9VSu9rnrQ8ZlueNBRS0" alt=""><figcaption></figcaption></figure>

## Permissions

To use the `/skin` command or receive access to peds in the skin menu, a player must have the ACE permission: **`manageSkinMenu`**

**How to Add Permission**

Add the following line to your `server.cfg` to grant access to a specific player (replace `YOUR_IDENTIFIER` with the correct identifier, e.g. `identifier.discord:XXXXXXXXX` or `identifier.license:XXXXXXXXX`):

```cfg
add_ace identifier.discord:YOUR_DISCORD_ID manageSkinMenu allow
```

**Example (for Discord):**

```cfg
add_ace identifier.discord:541714961576099853 manageSkinMenu allow
```

**Example (for FiveM license):**

```cfg
add_ace identifier.license:5a351fe45f0428603e660fda37244dac8eecfbdc manageSkinMenu allow
```

You can also give this permission to a whole ACE group (e.g. `group.admin`):

```cfg
add_ace group.admin manageSkinMenu allow
```

**How to Use**

* Only players with the `manageSkinMenu` permission can use the `/skin` command and receive peds in the skin menu.
* If a player does **not** have the permission, the command and menu will not be available for them.

**Important**

> **Make sure to grant this permission only to trusted players or staff!**

<figure><img src="/files/BT86pNRKkozoC3dneeUj" alt=""><figcaption></figcaption></figure>

## Stores - Prices

Defines the cost for accessing customization menus:

* `clotheshop`:\
  Price (in your server's currency) for using the **clothing shop**.
* `barbershop`:\
  Price for using the **barber shop** (e.g., hair, beard, eyebrows).

> 📌 Set to `0` to make either shop free.\
> Prices are automatically deducted using your framework’s billing or money system.

<figure><img src="/files/tiSkoOHCkLfUEinuAv8B" alt=""><figcaption></figcaption></figure>

## Stores - Locations

Defines the locations of clothing and barber shops across the map:

Each entry represents a single store location with the following properties:

* `type`:\
  Type of store available at the location. Accepted values:\
  • `"clothing"` – opens the clothing customization menu\
  • `"barber"` – opens the barber/hair customization menu
* `coords`:\
  Position and heading (`vector4`) where the store is placed. Format: `vector4(x, y, z, heading)`

> 📌 You can add as many stores as you like by duplicating the structure. Each store will automatically support your selected target system or "E" key interaction.

<figure><img src="/files/HYVYmyUx283Achko3NSM" alt=""><figcaption></figcaption></figure>

## Stores - Blips

Controls the appearance of map blips for clothing and barber shops:

***

**`["clothing"]`:**

Blip settings for clothing stores:

* `Show`:\
  Set to `true` to display the blip on the map.
* `Sprite`:\
  Blip icon ID (e.g., `73` for T-shirt icon).
* `Color`:\
  Blip color ID (e.g., `47` – light green).
* `Scale`:\
  Blip size on the map (e.g., `0.7`).
* `Name`:\
  Label displayed when hovering over the blip. Uses localization via `_L('shops_clothing')`.

***

**`["barber"]`:**

Blip settings for barbershops:

* `Show`:\
  Set to `true` to show barbershop blips on the map.
* `Sprite`:\
  Blip icon ID (e.g., `71` for scissors icon).
* `Color`:\
  Blip color ID (e.g., `0` – white).
* `Scale`:\
  Blip size on the map.
* `Name`:\
  Localized blip label shown on the map via `_L('shops_barbershop')`.

> 📌 You can freely customize icons, colors, and visibility to match your server's visual style.

<figure><img src="/files/oi1BUx3af6iDcIzQPRSs" alt=""><figcaption></figcaption></figure>

## Stores - Target Config

Defines ped models, interaction labels, and icons for each targetable skin-related location:

***

**`["clothing"]` – Clothing Shop Target**

* `model`: Ped model used at the clothing shop (e.g., `"s_f_m_shop_high"`).
* `scenario`: Ped idle animation (e.g., `"WORLD_HUMAN_STAND_MOBILE"`).
* `icon`: Font Awesome icon used in the target UI (e.g., `"fas fa-tshirt"`).
* `label`: Localized text label shown during interaction (e.g., `_L('shops_clothing')`).
* `distance`: Maximum interaction range in meters (e.g., `5`).

***

**`["barber"]` – Barber Shop Target**

* `model`: Barber NPC model (`"s_m_m_hairdress_01"`).
* `scenario`: Idle animation.
* `icon`: Icon for barber (e.g., `"fas fa-scissors"`).
* `label`: Localized label (`_L('shops_barbershop')`).
* `distance`: Interaction range.

***

**`["clothingroom"]` – Public Outfit Room**

* `model`: Ped model for accessing shared outfit presets.
* `scenario`: Animation used by the NPC.
* `icon`: Icon for outfit room (e.g., `"fas fa-sign-in-alt"`).
* `label`: Localized label (`_L('shops_outfits')`).
* `distance`: Interaction range.

***

**`["playeroutfitroom"]` – Personal Wardrobe**

* Same structure as `clothingroom`, but refers to player's saved outfits.
* `label`: Localized as `_L('shops_warderobe')`.

> 📌 These NPCs appear where store coordinates are defined and support all target systems configured in `Config.Targets`.\
> You can modify ped models and icons to better match your server’s visual identity.

<figure><img src="/files/LgPP4QrIsdIqAMvTYxt0" alt=""><figcaption></figcaption></figure>

## Exports - Client-side

These exports allow you to trigger clothing, barber, wardrobe, and character creation menus from external scripts.

***

**🧥 `exports.qf_skinmenu:openWardrobe()`**

Opens the **player's saved outfit wardrobe** (from stored outfits).

***

**👚 `exports.qf_skinmenu:openClothingShop()`**

Opens the **standard clothing shop menu** (T-shirt icon zone).

***

**💈 `exports.qf_skinmenu:openBarberShop()`**

Opens the **barber shop menu** (hair, beard, eyebrows, etc.).

***

**🧍 `exports.qf_skinmenu:openSkinMenu()`**

Opens the **full skin customization menu**, including model, face, and body details.

***

**🏠 `exports.qf_skinmenu:openClothingShopMenuHousing()`**

Opens the clothing shop menu **with a custom label**, useful for housing systems or private wardrobes.

> 📌 Uses localized title from: `TRANSLATIONS[Config.Locale]['shops_warderobe']`

***

**👤 `exports.qf_skinmenu:startCharacter()`**

Starts the **character creation flow** with model/gender selector.

> 📌 Automatically detects gender using `FRAMEWORK.GetGender(true)`

***

> ✅ These exports are fully client-side and can be used in job scripts, housing systems, spawn selectors, or onboarding flows.


# Spawn Selector

This category is for our Spawn Selector

Enhance the way players join your server with our Spawn Selector script – designed with a focus on simplicity, style, and performance. Featuring a modern and minimalistic UI, it offers a polished first impression while remaining fully optimized for any server environment. Built on a plug-and-play system, it requires no complex setup. Just install and go. The script receives regular weekly updates, continuously evolving based on community feedback and buyer requests – bringing in new features, improvements, and customization options. Don’t wait – improve your server’s entry experience today and give your players a smoother, more professional welcome!

<figure><img src="/files/e29AN5QTTzpx5w1YFjhs" alt=""><figcaption></figcaption></figure>


# Installation

Page dedicated to how to install our Spawn Selector

## Step #1 - Drag & Drop

Just Drag & Drop the `qf_spawnselector` folder into your `resouces` folder.

## Step #2 - SQL Installation

{% hint style="info" %}
There’s no need to manually insert any SQL file into your database. Our script automatically handles all necessary database entries on first launch, so you can safely skip this step.
{% endhint %}

## Step #3 - Script start

You can easily start our script using one of the following methods:

1. Type `ensure qf_spawnselector` in your server console or F8 console.\
   This will start or restart the script live on your server.
2. Add `ensure qf_spawnselector` to your `server.cfg` in the appropriate place.\
   This ensures the script launches automatically every time your server starts.


# Configuration

Page dedicated to how to configure our Spawn Selector

## Languages

You can set the language of the script in the configuration file.

* `en`: English
* `fr`: French
* `pl`: Polish
* `de`: German
* `es`: Spanish

<figure><img src="/files/ig9o7wm8oX8fWWbPFHXs" alt=""><figcaption></figcaption></figure>

## Weather

Defines the required weather condition for displaying the spawn selector scene:

* `WeatherState`:\
  Set to `'CLEAR'` to ensure the scene appears only during clear weather.\
  If you're using `renewed-weathersync` or a similar weather system, you can replace `'CLEAR'` with `GlobalState.weather.weather` for dynamic synchronization.

<figure><img src="/files/10OBUeWP5IkitzqKPLYn" alt=""><figcaption></figcaption></figure>

## Events

Defines whether the Spawn Selector can be triggered via events:

* `useEvents`:\
  Set to `true` if you want to open the Spawn Selector using an external event (e.g., `TriggerEvent`).\
  If `false`, the selector must be triggered using predefined methods (command, export, etc.).

<figure><img src="/files/fgeLCEDOzXtfh5Zl1Wi7" alt=""><figcaption></figcaption></figure>

### Server-Side to Client-Side

<figure><img src="/files/tEKMQbx76LKUeXyJYEMa" alt=""><figcaption></figcaption></figure>

• `true`: Opens the spawn selector with the "Last Location" option.\
• `false`: Opens the spawn selector without the "Last Location" option.

***

### Client-Side to Server-Side

<figure><img src="/files/g2ICf15YZzagrwoyMp0s" alt=""><figcaption></figcaption></figure>

• `source`: The player's server ID.\
• `true`: Opens with "Last Location" option.\
• `false`: Opens without it.

> 📌 These events are useful if you're integrating the spawn selector with login systems, multicharacter scripts, or custom logic.

## Exports - Open NUI

Triggers the Spawn Selector UI manually from another script:

* `true`: Opens the spawn selector **with** the "Last Location" option.
* `false`: Opens the spawn selector **without** the "Last Location" option.

> 💡 Useful for custom login flows, character selectors, or admin tools.

<figure><img src="/files/P41vuDmjWn3BDhkoUO3b" alt=""><figcaption></figcaption></figure>

## Command

Defines command settings for opening the Spawn Selector:

* `Command.use`:\
  Set to `true` to enable the command for opening the spawn selector.
* `Command.useLastLocation`:\
  If `true`, the selector will include an option to spawn at the player's last known location.
* `Command.name`:\
  Name of the command (e.g., `/spawnselector`) that triggers the spawn selection menu.

<figure><img src="/files/HYVYmyUx283Achko3NSM" alt=""><figcaption></figcaption></figure>

## Locations

Defines the available spawn points displayed in the Spawn Selector map:

Each location entry includes the following fields:

* `coords`:\
  A table containing X, Y, Z coordinates and heading (e.g., `{x, y, z, h}`) where the player will spawn.
* `title`:\
  Name displayed on the map marker (e.g., `"Los Santos"`).
* `iconUrl`:\
  Path to the icon image shown on the map when not hovered.
* `iconHoverUrl`:\
  Path to the icon image shown when hovered over with the mouse.
* `iconSize`:\
  Size of the icon in pixels (e.g., `{40, 40}`).
* `iconAnchor`:\
  Anchor point of the icon (center reference for placement), typically half of `iconSize`.
* `popupAnchor`:\
  Offset position for the text popup tooltip relative to the marker.

> 📌 You can freely add or remove locations by copying the format shown above.

<figure><img src="/files/ug4S39bJS2nF6Thqp822" alt=""><figcaption></figcaption></figure>


# MDT LSPD \[V1]

This category is for our MDT LSPD \[V1]

An advanced police MDT script that brings realism to your server. Manage announcements, notes, citizen and vehicle databases. Create reports, warrants, and investigations with full attachments. Fully immersive and ready for action. Seamlessly integrates with your framework to enhance every aspect of police roleplay.

<figure><img src="/files/JYfXFyS7ZN5NH4X965OO" alt=""><figcaption></figcaption></figure>


# Installation

Page dedicated to how to install our MDT LSPD

## Step #1 - Drag & Drop

Just Drag & Drop the `qf_mdt` folder into your `resouces` folder.

## Step #2 - SQL Installation

{% hint style="info" %}
There’s no need to manually insert any SQL file into your database. Our script automatically handles all necessary database entries on first launch, so you can safely skip this step.
{% endhint %}

## Step #3 - Script start

You can easily start our script using one of the following methods:

1. Type `ensure qf_mdt` in your server console or F8 console.\
   This will start or restart the script live on your server.
2. Add `ensure qf_mdt` to your `server.cfg` in the appropriate place.\
   This ensures the script launches automatically every time your server starts.


# Configuration

Page dedicated to how to configure our MDT LSPD

## Languages

You can set the language of the script in the configuration file.

* `en`: English
* `fr`: French
* `pl`: Polish
* `de`: German
* `es`: Spanish

<figure><img src="/files/ig9o7wm8oX8fWWbPFHXs" alt=""><figcaption></figcaption></figure>

## Society

Defines the society settings used for billing and fine distribution.

* `name`: Society account name used for transactions.
* `jobname`: Job identifier that will access the system.
* `label`: Display name of the organization.
* `percentToBoss`: Percentage of the fine that goes to the society account.
* `percentToWorker`: Percentage of the fine paid directly to the officer.

<figure><img src="/files/cqSA1oVPcCfKfIxqLeBk" alt=""><figcaption></figcaption></figure>

## Billings

Enables integration with external billing systems.\
Set the desired system to `true` to allow fines and charges to be processed through that billing resource. Only one billing system should be enabled at a time to avoid conflicts.

<figure><img src="/files/qkDrsBdr8CtsW3G9o6IM" alt=""><figcaption></figcaption></figure>

## Banks

Selects the banking system used for processing payments.\
Set the appropriate option to `true` to enable compatibility with your server's banking resource.\
Only one banking system should be enabled at a time.

<figure><img src="/files/posm6LkEt7MIFvfxVXqM" alt=""><figcaption></figcaption></figure>

## Phones

Specifies the in-game phone system used for sending notifications and alerts.\
Set the matching phone resource to `true` to enable integration.\
Only one phone system should be active at a time.

<figure><img src="/files/IFCQ7r6fIceWzoFQTfQ4" alt=""><figcaption></figcaption></figure>

## Licenses

Determines which license system is used for managing player licenses (e.g., driving, weapon).\
Set the appropriate license system to `true` based on your server's framework.\
Only one license system should be enabled at a time.

<figure><img src="/files/RXBcjuPdPO0SHAyGYcJf" alt=""><figcaption></figcaption></figure>

## Max Distance to Jail or Fine

Defines the maximum distance (in meters) between the officer and the suspect required to issue a jail sentence or fine. If the suspect is farther than this value, the action will be blocked.

<figure><img src="/files/wMuX0hHvxMO9Az6pjoOK" alt=""><figcaption></figcaption></figure>

## Show

Controls the visibility of specific UI elements and features:

* `Radio`: Shows the player's radio channel.
* `Nearest`: Displays the nearest players in the MDT.
* `BadgeSystem`: Enables integration with a badge/ID system (if available).

<figure><img src="/files/4JYV5ywyUQmtlfJIsrsS" alt=""><figcaption></figcaption></figure>

## Using Radio

Specifies which radio system is used for displaying the player's active radio channel.\
Set the radio system your server uses to `true` (e.g., `pma_voice`).\
Only one radio integration should be enabled.

<figure><img src="/files/Nunm0cbOIOAWNetZfjTW" alt=""><figcaption></figcaption></figure>

## Jobs

Defines job-related permissions and behavior for accessing and managing the MDT system:

* `OneJob`: If `true`, each job has its own separate reports and dispatches. If `false`, all authorized jobs share the same system.
* `OnDuty`: List of job names allowed to access the MDT (e.g., `'police'`).
* `KickDuty`: Settings applied when a player is removed from duty:
  * `name`: Job to assign after being kicked from duty.
  * `data`: Controls how the grade is set (new grade, same grade, etc.).
* `AccessToManagementFunctions.fromGrade`: Minimum job grade required to access management features.
* `CityStatus.Message`: Enables city-wide announcement events with a customizable prefix and icon.
* `ShowHours`: If `true`, shows officers' total service hours in the MDT.
* `ShowFines`: If `true`, enables the fines system in the MDT.
* `BlockProfiles`, `ResetHours`, `AddRemoveLicense`: Minimum job grades required to block profiles, reset duty hours, or manage licenses.

<figure><img src="/files/RzelCvYpEMajo5THURqs" alt=""><figcaption></figcaption></figure>

## Message Colors

Defines RGB color codes used for different types of messages or alerts in the MDT Dispatch:

* `BlackCode`: Default or neutral messages.
* `RedCode`: Critical or high-priority alerts.
* `OrangeCode`: Warnings or medium-priority events.
* `GreenCode`: Informational or low-priority notifications.

<figure><img src="/files/3mwavSo6Z3sjktLOJYkY" alt=""><figcaption></figcaption></figure>

## ToggleMDT

Configures how players can open the MDT interface:

* `key`: Default keybind assigned to open the MDT (can be changed by the player in GTA settings).
* `commandName`: Chat command that gets triggered by the keybind.
* `keymappingLabel`: Label shown in GTA V settings under **Key Bindings > FiveM**, allowing players to rebind the key.

<figure><img src="/files/nAUyRMDcHPfCI6OuqXQH" alt=""><figcaption></figcaption></figure>

## Properties

Enables compatibility with housing and property systems used on your server.\
Set the corresponding option to `true` based on the property resource you use (e.g., `qs_housing`, `esx_property_legacy`, `qb_apartments`, etc.). Only enable the one that matches your server setup to ensure correct address detection and property integration in the MDT.

<figure><img src="/files/k0fnriYgcXPgkGymofov" alt=""><figcaption></figcaption></figure>

## Jails

Defines which jail system is used for handling arrests through the MDT.\
Set the jail system used on your server to `true` (only one should be enabled at a time). Some systems, like `pickle_prisons`, may require an additional jail name (e.g., `pickle_prisons_jailName = "default"`).

<figure><img src="/files/QdssIcURTYfd0oDkWdHg" alt=""><figcaption></figcaption></figure>

## Gender Table

Configures how the script reads player gender from your database (for ESX-based servers only).

* `sqlUserName`: The column name in your `users` table that stores gender information (e.g., `'sex'` or `'gender'`).
* `sqlNames`: Maps gender values from your database to standard terms:
  * `'male'`: Value used to represent male players (e.g., `'m'`, `1`, etc.).
  * `'female'`: Value used to represent female players (e.g., `'f'`, `0`, etc.).

> **Note:** This section is not required if you're using **QBCore**, as gender is handled differently.

<figure><img src="/files/ZRH2Y5yjKDHHFZ3KbSzi" alt=""><figcaption></figcaption></figure>

## Citizens Licenses

Defines how player licenses are displayed in the MDT (e.g., driving or weapon licenses).\
Each entry represents one license type pulled from your database.

* `sqlName`: The name of the license in your database (e.g., `'drive'`, `'weapon'`).
* `isText`: Set to `true` to display the license as text (e.g., `"A"`, `"B"`), or `false` to show it as an icon.
* `translateLicense`: Text label shown if `isText` is `true` (e.g., `"A"` for motorcycle). Leave empty if using an icon.
* `licenseIcon`: Font Awesome icon name used if `isText` is `false`. Leave empty when using text.\
  → Browse available icons here: <https://fontawesome.com/icons>

> You can freely customize this list to match your license structure (e.g., weapon permits, truck licenses, etc.).

<figure><img src="/files/zZYIX6gvYAPCC2ksDNcw" alt=""><figcaption></figcaption></figure>

## Navigation bar

Controls the visibility of navigation tabs in the MDT interface.\
Set each option to `true` to show the corresponding section or `false` to hide it.

* `home`: Main dashboard
* `annoucements`: Internal police announcements
* `files`: Case and report management
* `sep_files`: Separate files tab (if needed for custom setups)
* `police_list`: List of active officers
* `house_list`: Property and address records
* `radio_codes`: List of radio/code signals
* `warrants`: Active warrants database
* `evidences`: Evidence tracking and storage
* `notifications`: Internal system notifications
* `dispatch`: Dispatch alert system
* `customcars`: Custom vehicle database (if used on server)

<figure><img src="/files/fljuxOJz4g8Sz1RviGxw" alt=""><figcaption></figcaption></figure>

## Dispatch - Basic configuration

Configures integration with external dispatch systems.\
Set the dispatch system used on your server to `true` (e.g., `qf_dispatch`, `cd_dispatch`, `linden_dispatch`, etc.).\
Only one dispatch integration should be active at a time.

* `notif_dispatch`: Enables native MDT dispatch alerts using `TriggerClientEvent(...)` with full customization (title, subtitle, code, color, and responder limit).
* `IgnoredJobs`: List of jobs that should not receive dispatch alerts from this system.

<figure><img src="/files/cftOw2ayetuWwZ6rjtXw" alt=""><figcaption></figcaption></figure>

## Dispatch - Alerts

You can trigger a dispatch alert in the MDT either from the **client-side** or **server-side**.\
For better security and control, we recommend using the **server-side** method.<br>

* `coords`: Vector3 or table with x, y, z
* `'title'`: Main alert text
* `'subtitle'`: Additional context
* `'code'`: Optional call code (e.g., `10-90`)
* `'rgb(r, g, b)'`: Color of the alert
* `10`: Max number of players who can respond (set to `0` to disable limit)<br>

### Server-Side to Client-Side

<figure><img src="/files/KioK4hRrTjhG2XNXO9m6" alt=""><figcaption></figcaption></figure>

### Client-Side to Server-Side

<figure><img src="/files/jpCZgrnJNk4wH1h5hAaU" alt=""><figcaption></figcaption></figure>

## Dispatch - Notify alerts

Enables visual notifications for dispatch alerts. When set to `true`, players will receive a top-right notification whenever a new alert is added to the MDT.

<figure><img src="/files/niXsKpoK4a0s6OQVjz3x" alt=""><figcaption></figcaption></figure>

## Dispatch - Defaults & Blacklist

* `DefaultAlertsDelay`: Sets the delay (in seconds) between repeated automatic alerts to avoid spam.
* `DefaultAlerts`: Enables or disables predefined automatic alerts such as:
  * `'Speeding'`: Vehicle speeding detection
  * `'Shooting'`: Gunfire detection
  * `'Autotheft'`: Vehicle theft
  * `'Melee'`: Melee combat detection
  * `'PlayerDowned'`: Player down or incapacitated
* `WeaponBlacklist`: List of weapons that are ignored by the automatic shooting alert system (e.g., snowballs, stun guns, grenades).\
  Useful for preventing non-lethal or non-threatening items from triggering dispatch alerts.

<figure><img src="/files/UImlDRt9vBj7jvvmq5cq" alt=""><figcaption></figcaption></figure>

## Dispatch - Sounds

Controls sound notifications when a new dispatch alert is received:

* `Default`: Enables the use of GTA V’s native frontend sound.
  * `frontArgs1` and `frontArgs2` define the specific sound to be played.
  * Set `use` to `true` to activate.
* `Custom`: Allows playing a custom `.ogg` sound file from your `sounds` folder using an external sound system like `InteractSound`.
  * `triggerName`: Name of the client event to play the sound.
  * `fileName`: Name of the sound file (without extension).
  * `volume`: Volume level (e.g., `0.2`).
  * Set `use` to `true` to enable custom sound playback.

<figure><img src="/files/4QWh49hhv1vNyoYxuVWr" alt=""><figcaption></figcaption></figure>

## Dispatch - Colors

Defines the list of vehicle color names used in the MDT when displaying or searching vehicle data.\
Each entry maps a color index (as used in vehicle properties) to its corresponding readable name (e.g., `'0' = "Metallic Black"`). You can freely expand, remove, or modify entries to match your server’s needs or limit the visible palette.

<figure><img src="/files/EnyOTBmm8i5XyI70ukW0" alt=""><figcaption></figcaption></figure>


# MDT EMS \[V1]

This category is for our MDT EMS \[V1]

An advanced MDT EMS script that brings immersive medical roleplay to your server. Manage announcements, notes, and search citizen records. Identify unpaid invoices, blacklist individuals, and document incidents with detailed reports and photo attachments. A complete tool for realistic and engaging EMS operations.

<figure><img src="/files/St4RNKAc2BYZ6DK0WtaU" alt=""><figcaption></figcaption></figure>


# Installation

Page dedicated to how to install our MDT EMS

## Step #1 - Drag & Drop

Just Drag & Drop the `qf_mdt_ems` folder into your `resouces` folder.

## Step #2 - SQL Installation

{% hint style="info" %}
There’s no need to manually insert any SQL file into your database. Our script automatically handles all necessary database entries on first launch, so you can safely skip this step.
{% endhint %}

## Step #3 - Script start

You can easily start our script using one of the following methods:

1. Type `ensure qf_mdt_ems` in your server console or F8 console.\
   This will start or restart the script live on your server.
2. Add `ensure qf_mdt_ems` to your `server.cfg` in the appropriate place.\
   This ensures the script launches automatically every time your server starts.


# Configuration

Page dedicated to how to configure our MDT EMS

## Languages

You can set the language of the script in the configuration file.

* `en`: English
* `fr`: French
* `pl`: Polish
* `de`: German
* `es`: Spanish

<figure><img src="/files/ig9o7wm8oX8fWWbPFHXs" alt=""><figcaption></figcaption></figure>

## Society

Defines the society settings used for billing and fine distribution.

* `name`: Society account name used for transactions.
* `jobname`: Job identifier that will access the system.
* `label`: Display name of the organization.
* `percentToBoss`: Percentage of the fine that goes to the society account.
* `percentToWorker`: Percentage of the fine paid directly to the officer.

<figure><img src="/files/xuIGzZxKqTaHcNF2Y5fp" alt=""><figcaption></figcaption></figure>

## Billings

Enables integration with external billing systems.\
Set the desired system to `true` to allow fines and charges to be processed through that billing resource. Only one billing system should be enabled at a time to avoid conflicts.

<figure><img src="/files/qkDrsBdr8CtsW3G9o6IM" alt=""><figcaption></figcaption></figure>

## Banks

Selects the banking system used for processing payments.\
Set the appropriate option to `true` to enable compatibility with your server's banking resource.\
Only one banking system should be enabled at a time.

<figure><img src="/files/posm6LkEt7MIFvfxVXqM" alt=""><figcaption></figcaption></figure>

## Phones

Specifies the in-game phone system used for sending notifications and alerts.\
Set the matching phone resource to `true` to enable integration.\
Only one phone system should be active at a time.

<figure><img src="/files/IFCQ7r6fIceWzoFQTfQ4" alt=""><figcaption></figcaption></figure>

## Licenses

Determines which license system is used for managing player licenses (e.g., driving, weapon).\
Set the appropriate license system to `true` based on your server's framework.\
Only one license system should be enabled at a time.

<figure><img src="/files/RXBcjuPdPO0SHAyGYcJf" alt=""><figcaption></figcaption></figure>

## Max Distance to Invoice

Defines the maximum distance (in meters) between the doctor and the client required to issue a invoice. If the client is farther than this value, the action will be blocked.

<figure><img src="/files/mstP7fXqMA3xx3mqxoTl" alt=""><figcaption></figcaption></figure>

## Show

Controls the visibility of specific UI elements and features:

* `Radio`: Shows the player's radio channel.
* `Nearest`: Displays the nearest players in the MDT.
* `BadgeSystem`: Enables integration with a badge/ID system (if available).

<figure><img src="/files/4JYV5ywyUQmtlfJIsrsS" alt=""><figcaption></figcaption></figure>

## Using Radio

Specifies which radio system is used for displaying the player's active radio channel.\
Set the radio system your server uses to `true` (e.g., `pma_voice`).\
Only one radio integration should be enabled.

<figure><img src="/files/Nunm0cbOIOAWNetZfjTW" alt=""><figcaption></figcaption></figure>

## Jobs

Defines job-related permissions and behavior for accessing and managing job features:

* `OneJob`: If `true`, each job has its own separate access and systems. If `false`, all authorized jobs share the same logic.
* `OnDuty`: List of job names allowed to access the system while on duty (e.g., `'ambulance'`).
* `KickDuty`: Settings applied when a player is removed from duty:\
  ○ `name`: Job to assign after being kicked from duty.\
  ○ `data`: Controls how the grade is set (`new grade`, `same grade`, etc.).
* `AccessToManagementFunctions.fromGrade`: Minimum job grade required to access management features.
* `ShowHours`: If `true`, shows employees' total work hours.
* `ShowInvoices`: If `true`, enables the invoice system for the job.
* `ResetHours`, `AddRemoveLicense`: Minimum job grades required to reset duty hours or manage licenses.

<figure><img src="/files/T9KJK5MKJBjcY7F4GXb0" alt=""><figcaption></figcaption></figure>

## ToggleMDT

Configures how players can open the MDT interface:

* `key`: Default keybind assigned to open the MDT (can be changed by the player in GTA settings).
* `commandName`: Chat command that gets triggered by the keybind.
* `keymappingLabel`: Label shown in GTA V settings under **Key Bindings > FiveM**, allowing players to rebind the key.

<figure><img src="/files/BZxpFw7KkYNuljbESLHx" alt=""><figcaption></figcaption></figure>

## Gender Table

Configures how the script reads player gender from your database (for ESX-based servers only).

* `sqlUserName`: The column name in your `users` table that stores gender information (e.g., `'sex'` or `'gender'`).
* `sqlNames`: Maps gender values from your database to standard terms:
  * `'male'`: Value used to represent male players (e.g., `'m'`, `1`, etc.).
  * `'female'`: Value used to represent female players (e.g., `'f'`, `0`, etc.).

> **Note:** This section is not required if you're using **QBCore**, as gender is handled differently.

<figure><img src="/files/ZRH2Y5yjKDHHFZ3KbSzi" alt=""><figcaption></figcaption></figure>

## Citizens Licenses

Defines how player licenses are displayed in the MDT (e.g., driving or weapon licenses).\
Each entry represents one license type pulled from your database.

* `sqlName`: The name of the license in your database (e.g., `'drive'`, `'weapon'`).
* `isText`: Set to `true` to display the license as text (e.g., `"A"`, `"B"`), or `false` to show it as an icon.
* `translateLicense`: Text label shown if `isText` is `true` (e.g., `"A"` for motorcycle). Leave empty if using an icon.
* `licenseIcon`: Font Awesome icon name used if `isText` is `false`. Leave empty when using text.\
  → Browse available icons here: <https://fontawesome.com/icons>

> You can freely customize this list to match your license structure (e.g., insurance permits, etc.).

<figure><img src="/files/KApS6WZjLPTP4svdsH4x" alt=""><figcaption></figcaption></figure>

## Navigation bar

Controls the visibility of navigation tabs in the MDT interface.\
Set each option to `true` to show the corresponding section or `false` to hide it.

* `home`: Main dashboard
* `annoucements`: Internal announcements
* `files`: Case and report management
* `doctor_list`: List of active doctors
* `radio_codes`: List of radio/code signals
* `evidences`: Evidence tracking and storage
* `notifications`: Internal system notifications
* `dispatch`: Dispatch alert system

<figure><img src="/files/hucIOP4RXVINLsR3Kn49" alt=""><figcaption></figcaption></figure>

## Dispatch - Basic configuration

Configures integration with external dispatch systems.\
Set the dispatch system used on your server to `true` (e.g., `qf_dispatch`, `cd_dispatch`, `linden_dispatch`, etc.).\
Only one dispatch integration should be active at a time.

* `notif_dispatch`: Enables native MDT dispatch alerts using `TriggerClientEvent(...)` with full customization (title, subtitle, code, color, and responder limit).
* `IgnoredJobs`: List of jobs that should not receive dispatch alerts from this system.

<figure><img src="/files/4NTIWweCzWvpgWHMUDmz" alt=""><figcaption></figcaption></figure>

## Dispatch - Alerts

You can trigger a dispatch alert in the MDT either from the **client-side** or **server-side**.\
For better security and control, we recommend using the **server-side** method.<br>

* `coords`: Vector3 or table with x, y, z
* `'title'`: Main alert text
* `'subtitle'`: Additional context
* `'code'`: Optional call code (e.g., `10-90`)
* `'rgb(r, g, b)'`: Color of the alert
* `10`: Max number of players who can respond (set to `0` to disable limit)<br>

### Server-Side to Client-Side

<figure><img src="/files/S0UyJwGZLGKQRZ0YN6fg" alt=""><figcaption></figcaption></figure>

### Client-Side to Server-Side

<figure><img src="/files/WTQnd9FnEa6YToXeCscp" alt=""><figcaption></figcaption></figure>

## Dispatch - Notify alerts

Enables visual notifications for dispatch alerts. When set to `true`, players will receive a top-right notification whenever a new alert is added to the MDT.

<figure><img src="/files/niXsKpoK4a0s6OQVjz3x" alt=""><figcaption></figcaption></figure>

## Dispatch - Defaults & Blacklist

* `DefaultAlertsDelay`: Sets the delay (in seconds) between repeated automatic alerts to avoid spam.
* `DefaultAlerts`: Enables or disables predefined automatic alerts such as:
  * `'PlayerDowned'`: Player down or incapacitated

<figure><img src="/files/l1W519aKa11mlPl8OJrg" alt=""><figcaption></figcaption></figure>

## Dispatch - Sounds

Controls sound notifications when a new dispatch alert is received:

* `Default`: Enables the use of GTA V’s native frontend sound.
  * `frontArgs1` and `frontArgs2` define the specific sound to be played.
  * Set `use` to `true` to activate.
* `Custom`: Allows playing a custom `.ogg` sound file from your `sounds` folder using an external sound system like `InteractSound`.
  * `triggerName`: Name of the client event to play the sound.
  * `fileName`: Name of the sound file (without extension).
  * `volume`: Volume level (e.g., `0.2`).
  * Set `use` to `true` to enable custom sound playback.

<figure><img src="/files/4QWh49hhv1vNyoYxuVWr" alt=""><figcaption></figcaption></figure>


# MDT LSC \[V1]

This category is for our MDT LSC \[V1]

An advanced MDT system for the Mechanics faction (Los Santos Customs), designed to manage tasks, report repairs, issue invoices, and access player or vehicle data. Track repair history, document damage, and organize player profiles and notes. Highly optimized and secure, this script enhances roleplay depth and efficiency while offering full customization and broad compatibility with other scripts.

<figure><img src="/files/CLTOgtT8xPL3Z9ClmjBn" alt=""><figcaption></figcaption></figure>


# Installation

Page dedicated to how to install our MDT LSC

## Step #1 - Drag & Drop

Just Drag & Drop the `qf_mdt_lsc` folder into your `resouces` folder.

## Step #2 - SQL Installation

{% hint style="info" %}
There’s no need to manually insert any SQL file into your database. Our script automatically handles all necessary database entries on first launch, so you can safely skip this step.
{% endhint %}

## Step #3 - Script start

You can easily start our script using one of the following methods:

1. Type `ensure qf_mdt_lsc` in your server console or F8 console.\
   This will start or restart the script live on your server.
2. Add `ensure qf_mdt_lsc` to your `server.cfg` in the appropriate place.\
   This ensures the script launches automatically every time your server starts.


# Configuration

Page dedicated to how to configure our MDT LSC

## Languages

You can set the language of the script in the configuration file.

* `en`: English
* `fr`: French
* `pl`: Polish
* `de`: German
* `es`: Spanish

<figure><img src="/files/ig9o7wm8oX8fWWbPFHXs" alt=""><figcaption></figcaption></figure>

## Society

Defines the society settings used for billing and fine distribution.

* `name`: Society account name used for transactions.
* `jobname`: Job identifier that will access the system.
* `label`: Display name of the organization.
* `percentToBoss`: Percentage of the fine that goes to the society account.
* `percentToWorker`: Percentage of the fine paid directly to the officer.

<figure><img src="/files/KAG9HM1IpJyZE5qjmzbN" alt=""><figcaption></figcaption></figure>

## Billings

Enables integration with external billing systems.\
Set the desired system to `true` to allow fines and charges to be processed through that billing resource. Only one billing system should be enabled at a time to avoid conflicts.

<figure><img src="/files/qkDrsBdr8CtsW3G9o6IM" alt=""><figcaption></figcaption></figure>

## Banks

Selects the banking system used for processing payments.\
Set the appropriate option to `true` to enable compatibility with your server's banking resource.\
Only one banking system should be enabled at a time.

<figure><img src="/files/posm6LkEt7MIFvfxVXqM" alt=""><figcaption></figcaption></figure>

## Phones

Specifies the in-game phone system used for sending notifications and alerts.\
Set the matching phone resource to `true` to enable integration.\
Only one phone system should be active at a time.

<figure><img src="/files/IFCQ7r6fIceWzoFQTfQ4" alt=""><figcaption></figcaption></figure>

## Licenses

Determines which license system is used for managing player licenses (e.g., driving, weapon).\
Set the appropriate license system to `true` based on your server's framework.\
Only one license system should be enabled at a time.

<figure><img src="/files/RXBcjuPdPO0SHAyGYcJf" alt=""><figcaption></figcaption></figure>

## Max Distance to Invoice

Defines the maximum distance (in meters) between the doctor and the client required to issue a invoice. If the client is farther than this value, the action will be blocked.

<figure><img src="/files/mstP7fXqMA3xx3mqxoTl" alt=""><figcaption></figcaption></figure>

## Show

Controls the visibility of specific UI elements and features:

* `Radio`: Shows the player's radio channel.
* `Nearest`: Displays the nearest players in the MDT.
* `BadgeSystem`: Enables integration with a badge/ID system (if available).

<figure><img src="/files/4JYV5ywyUQmtlfJIsrsS" alt=""><figcaption></figcaption></figure>

## Using Radio

Specifies which radio system is used for displaying the player's active radio channel.\
Set the radio system your server uses to `true` (e.g., `pma_voice`).\
Only one radio integration should be enabled.

<figure><img src="/files/Nunm0cbOIOAWNetZfjTW" alt=""><figcaption></figcaption></figure>

## Jobs

Defines job-related permissions and behavior for accessing and managing job features:

* `OneJob`: If `true`, each job has its own separate access and systems. If `false`, all authorized jobs share the same logic.
* `OnDuty`: List of job names allowed to access the system while on duty (e.g., `'ambulance'`).
* `KickDuty`: Settings applied when a player is removed from duty:\
  ○ `name`: Job to assign after being kicked from duty.\
  ○ `data`: Controls how the grade is set (`new grade`, `same grade`, etc.).
* `AccessToManagementFunctions.fromGrade`: Minimum job grade required to access management features.
* `ShowHours`: If `true`, shows employees' total work hours.
* `ShowInvoices`: If `true`, enables the invoice system for the job.
* `ResetHours`, `AddRemoveLicense`: Minimum job grades required to reset duty hours or manage licenses.

<figure><img src="/files/6eMzX5woRSjTGd6umpJH" alt=""><figcaption></figcaption></figure>

## ToggleMDT

Configures how players can open the MDT interface:

* `key`: Default keybind assigned to open the MDT (can be changed by the player in GTA settings).
* `commandName`: Chat command that gets triggered by the keybind.
* `keymappingLabel`: Label shown in GTA V settings under **Key Bindings > FiveM**, allowing players to rebind the key.

<figure><img src="/files/r7SoDHe7P05mFUeAa6aU" alt=""><figcaption></figcaption></figure>

## Gender Table

Configures how the script reads player gender from your database (for ESX-based servers only).

* `sqlUserName`: The column name in your `users` table that stores gender information (e.g., `'sex'` or `'gender'`).
* `sqlNames`: Maps gender values from your database to standard terms:
  * `'male'`: Value used to represent male players (e.g., `'m'`, `1`, etc.).
  * `'female'`: Value used to represent female players (e.g., `'f'`, `0`, etc.).

> **Note:** This section is not required if you're using **QBCore**, as gender is handled differently.

<figure><img src="/files/ZRH2Y5yjKDHHFZ3KbSzi" alt=""><figcaption></figcaption></figure>

## Citizens Licenses

Defines how player licenses are displayed in the MDT (e.g., driving or weapon licenses).\
Each entry represents one license type pulled from your database.

* `sqlName`: The name of the license in your database (e.g., `'drive'`, `'weapon'`).
* `isText`: Set to `true` to display the license as text (e.g., `"A"`, `"B"`), or `false` to show it as an icon.
* `translateLicense`: Text label shown if `isText` is `true` (e.g., `"A"` for motorcycle). Leave empty if using an icon.
* `licenseIcon`: Font Awesome icon name used if `isText` is `false`. Leave empty when using text.\
  → Browse available icons here: <https://fontawesome.com/icons>

> You can freely customize this list to match your license structure (e.g., insurance permits, etc.).

<figure><img src="/files/Z5RB0ijkDZvpeBWtljiz" alt=""><figcaption></figcaption></figure>

## Navigation bar

Controls the visibility of navigation tabs in the MDT interface.\
Set each option to `true` to show the corresponding section or `false` to hide it.

* `home`: Main dashboard
* `annoucements`: Internal announcements
* `files`: Case and report management
* `sep_files`: Separate files tab (if needed for custom setups)
* `mechanic_list`: List of active mechanics
* `radio_codes`: List of radio/code signals
* `reviews`: Active reviews database
* `notifications`: Internal system notifications
* `dispatch`: Dispatch alert system

<figure><img src="/files/geWM7NHkqMxGVAyS1xiy" alt=""><figcaption></figcaption></figure>

## Dispatch - Basic configuration

Configures integration with external dispatch systems.\
Set the dispatch system used on your server to `true` (e.g., `qf_dispatch`, `cd_dispatch`, `linden_dispatch`, etc.).\
Only one dispatch integration should be active at a time.

* `notif_dispatch`: Enables native MDT dispatch alerts using `TriggerClientEvent(...)` with full customization (title, subtitle, code, color, and responder limit).
* `IgnoredJobs`: List of jobs that should not receive dispatch alerts from this system.

<figure><img src="/files/U7zTS8uiDvNgGxUrGmea" alt=""><figcaption></figcaption></figure>

## Dispatch - Alerts

You can trigger a dispatch alert in the MDT either from the **client-side** or **server-side**.\
For better security and control, we recommend using the **server-side** method.<br>

* `coords`: Vector3 or table with x, y, z
* `'title'`: Main alert text
* `'subtitle'`: Additional context
* `'code'`: Optional call code (e.g., `10-90`)
* `'rgb(r, g, b)'`: Color of the alert
* `10`: Max number of players who can respond (set to `0` to disable limit)<br>

### Server-Side to Client-Side

<figure><img src="/files/BDC9tfC4LClD4ZCyDEwU" alt=""><figcaption></figcaption></figure>

### Client-Side to Server-Side

<figure><img src="/files/ud4pdy2q3qYuPmQxgl8C" alt=""><figcaption></figcaption></figure>

## Dispatch - Notify alerts

Enables visual notifications for dispatch alerts. When set to `true`, players will receive a top-right notification whenever a new alert is added to the MDT.

<figure><img src="/files/niXsKpoK4a0s6OQVjz3x" alt=""><figcaption></figcaption></figure>

## Dispatch - Defaults & Blacklist

* `DefaultAlertsDelay`: Sets the delay (in seconds) between repeated automatic alerts to avoid spam.
* `DefaultAlerts`: Enables or disables predefined automatic alerts such as:
  * `'Autotheft'`: Vehicle theft

<figure><img src="/files/Kl1SVj8y2BhsaxE3KvIx" alt=""><figcaption></figcaption></figure>

## Dispatch - Sounds

Controls sound notifications when a new dispatch alert is received:

* `Default`: Enables the use of GTA V’s native frontend sound.
  * `frontArgs1` and `frontArgs2` define the specific sound to be played.
  * Set `use` to `true` to activate.
* `Custom`: Allows playing a custom `.ogg` sound file from your `sounds` folder using an external sound system like `InteractSound`.
  * `triggerName`: Name of the client event to play the sound.
  * `fileName`: Name of the sound file (without extension).
  * `volume`: Volume level (e.g., `0.2`).
  * Set `use` to `true` to enable custom sound playback.

<figure><img src="/files/4QWh49hhv1vNyoYxuVWr" alt=""><figcaption></figcaption></figure>


# MDT DOJ \[V1]

This category is for our MDT DOJ \[V1]

An advanced MDT system for the Department of Justice, designed to manage legal cases, track invoices and crime history, and issue judgments. Access player and vehicle data, organize profiles, and report activities efficiently. Optimized, secure, and fully customizable, this script enhances DOJ roleplay with structure, realism, and wide script compatibility for seamless server integration.

<figure><img src="/files/QZRbwtUldkGyb495QrAK" alt=""><figcaption></figcaption></figure>


# Installation

Page dedicated to how to install our MDT DOJ

## Step #1 - Drag & Drop

Just Drag & Drop the `qf_mdt_doj` folder into your `resouces` folder.

## Step #2 - SQL Installation

{% hint style="info" %}
There’s no need to manually insert any SQL file into your database. Our script automatically handles all necessary database entries on first launch, so you can safely skip this step.
{% endhint %}

## Step #3 - Script start

You can easily start our script using one of the following methods:

1. Type `ensure qf_mdt_doj` in your server console or F8 console.\
   This will start or restart the script live on your server.
2. Add `ensure qf_mdt_doj` to your `server.cfg` in the appropriate place.\
   This ensures the script launches automatically every time your server starts.


# Configuration

Page dedicated to how to configure our MDT DOJ

## Languages

You can set the language of the script in the configuration file.

* `en`: English
* `fr`: French
* `pl`: Polish
* `de`: German
* `es`: Spanish

<figure><img src="/files/ig9o7wm8oX8fWWbPFHXs" alt=""><figcaption></figcaption></figure>

## Society

Defines the society settings used for billing and fine distribution.

* `name`: Society account name used for transactions.
* `jobname`: Job identifier that will access the system.
* `label`: Display name of the organization.
* `percentToBoss`: Percentage of the fine that goes to the society account.
* `percentToWorker`: Percentage of the fine paid directly to the officer.

<figure><img src="/files/unYjTMvr4vkfAQgGBiuN" alt=""><figcaption></figcaption></figure>

## Billings

Enables integration with external billing systems.\
Set the desired system to `true` to allow fines and charges to be processed through that billing resource. Only one billing system should be enabled at a time to avoid conflicts.

<figure><img src="/files/qkDrsBdr8CtsW3G9o6IM" alt=""><figcaption></figcaption></figure>

## Banks

Selects the banking system used for processing payments.\
Set the appropriate option to `true` to enable compatibility with your server's banking resource.\
Only one banking system should be enabled at a time.

<figure><img src="/files/posm6LkEt7MIFvfxVXqM" alt=""><figcaption></figcaption></figure>

## Phones

Specifies the in-game phone system used for sending notifications and alerts.\
Set the matching phone resource to `true` to enable integration.\
Only one phone system should be active at a time.

<figure><img src="/files/IFCQ7r6fIceWzoFQTfQ4" alt=""><figcaption></figcaption></figure>

## Licenses

Determines which license system is used for managing player licenses (e.g., driving, weapon).\
Set the appropriate license system to `true` based on your server's framework.\
Only one license system should be enabled at a time.

<figure><img src="/files/RXBcjuPdPO0SHAyGYcJf" alt=""><figcaption></figcaption></figure>

## Max Distance to Jail or Fine

Defines the maximum distance (in meters) between the officer and the suspect required to issue a jail sentence or fine. If the suspect is farther than this value, the action will be blocked.

<figure><img src="/files/wMuX0hHvxMO9Az6pjoOK" alt=""><figcaption></figcaption></figure>

## Show

Controls the visibility of specific UI elements and features:

* `Radio`: Shows the player's radio channel.
* `Nearest`: Displays the nearest players in the MDT.
* `BadgeSystem`: Enables integration with a badge/ID system (if available).

<figure><img src="/files/4JYV5ywyUQmtlfJIsrsS" alt=""><figcaption></figcaption></figure>

## Using Radio

Specifies which radio system is used for displaying the player's active radio channel.\
Set the radio system your server uses to `true` (e.g., `pma_voice`).\
Only one radio integration should be enabled.

<figure><img src="/files/Nunm0cbOIOAWNetZfjTW" alt=""><figcaption></figcaption></figure>

## Jobs

Defines job-related permissions and behavior for accessing and managing the MDT system:

* `OneJob`: If `true`, each job has its own separate reports and dispatches. If `false`, all authorized jobs share the same system.
* `OnDuty`: List of job names allowed to access the MDT (e.g., `'police'`).
* `KickDuty`: Settings applied when a player is removed from duty:
  * `name`: Job to assign after being kicked from duty.
  * `data`: Controls how the grade is set (new grade, same grade, etc.).
* `AccessToManagementFunctions.fromGrade`: Minimum job grade required to access management features.
* `CityStatus.Message`: Enables city-wide announcement events with a customizable prefix and icon.
* `ShowHours`: If `true`, shows officers' total service hours in the MDT.
* `ShowFines`: If `true`, enables the fines system in the MDT.
* `BlockProfiles`, `ResetHours`, `AddRemoveLicense`: Minimum job grades required to block profiles, reset duty hours, or manage licenses.

<figure><img src="/files/9LDNGUQVypOEI6D6WOof" alt=""><figcaption></figcaption></figure>

## ToggleMDT

Configures how players can open the MDT interface:

* `key`: Default keybind assigned to open the MDT (can be changed by the player in GTA settings).
* `commandName`: Chat command that gets triggered by the keybind.
* `keymappingLabel`: Label shown in GTA V settings under **Key Bindings > FiveM**, allowing players to rebind the key.

<figure><img src="/files/I0zXaQiwrueNVvoxntaZ" alt=""><figcaption></figcaption></figure>

## Properties

Enables compatibility with housing and property systems used on your server.\
Set the corresponding option to `true` based on the property resource you use (e.g., `qs_housing`, `esx_property_legacy`, `qb_apartments`, etc.). Only enable the one that matches your server setup to ensure correct address detection and property integration in the MDT.

<figure><img src="/files/k0fnriYgcXPgkGymofov" alt=""><figcaption></figcaption></figure>

## Jails

Defines which jail system is used for handling arrests through the MDT.\
Set the jail system used on your server to `true` (only one should be enabled at a time). Some systems, like `pickle_prisons`, may require an additional jail name (e.g., `pickle_prisons_jailName = "default"`).

<figure><img src="/files/QdssIcURTYfd0oDkWdHg" alt=""><figcaption></figcaption></figure>

## Gender Table

Configures how the script reads player gender from your database (for ESX-based servers only).

* `sqlUserName`: The column name in your `users` table that stores gender information (e.g., `'sex'` or `'gender'`).
* `sqlNames`: Maps gender values from your database to standard terms:
  * `'male'`: Value used to represent male players (e.g., `'m'`, `1`, etc.).
  * `'female'`: Value used to represent female players (e.g., `'f'`, `0`, etc.).

> **Note:** This section is not required if you're using **QBCore**, as gender is handled differently.

<figure><img src="/files/ZRH2Y5yjKDHHFZ3KbSzi" alt=""><figcaption></figcaption></figure>

## Citizens Licenses

Defines how player licenses are displayed in the MDT (e.g., driving or weapon licenses).\
Each entry represents one license type pulled from your database.

* `sqlName`: The name of the license in your database (e.g., `'drive'`, `'weapon'`).
* `isText`: Set to `true` to display the license as text (e.g., `"A"`, `"B"`), or `false` to show it as an icon.
* `translateLicense`: Text label shown if `isText` is `true` (e.g., `"A"` for motorcycle). Leave empty if using an icon.
* `licenseIcon`: Font Awesome icon name used if `isText` is `false`. Leave empty when using text.\
  → Browse available icons here: <https://fontawesome.com/icons>

> You can freely customize this list to match your license structure (e.g., weapon permits, truck licenses, etc.).

<figure><img src="/files/zZYIX6gvYAPCC2ksDNcw" alt=""><figcaption></figcaption></figure>

## Navigation bar

Controls the visibility of navigation tabs in the MDT interface.\
Set each option to `true` to show the corresponding section or `false` to hide it.

* `home`: Main dashboard
* `annoucements`: Internal announcements
* `files`: Case and report management
* `sep_files`: Separate files tab (if needed for custom setups)
* `lawyer_list`: List of active lawyers
* `house_list`: Property and address records
* `radio_codes`: List of radio/code signals
* `warrants`: Active warrants database
* `evidences`: Evidence tracking and storage

<figure><img src="/files/xfOPZ9KA0EqliYEc2HJ0" alt=""><figcaption></figcaption></figure>


