# Moh-jobgarage

A QBCore FiveM resource that provides job and gang-specific vehicle garages with a fully themed NUI menu, ped spawning, key/fuel integration, and keyboard navigation.

## Overview

`moh-jobgarage` lets server owners define an unlimited number of garage locations, each linked to one or more jobs or a gang. When a player interacts with a spawned garage ped, the NUI menu opens and displays only the vehicles their job grade allows them to access. Spawning, storing, fuelling, and key handoff are all handled automatically.

Key features:

* Per-garage theming (colors, logo, panel gradient)
* Support for **qb-target** and **ox\_target**
* Support for multiple fuel resources (**LegacyFuel**, **ps-fuel**, **lj-fuel**, **cdn-fuel**, **qb-fuel**, **ox\_fuel**)
* Support for **qb-vehiclekeys** and **qs-vehiclekeys** (plus generic export fallback)
* Grade-based vehicle filtering
* Keyboard navigation (Arrow keys + Enter + Escape)
* One active vehicle per player — auto-deleted on re-spawn

## Installation

1. Drop the `moh-jobgarage` folder into your `resources` directory.
2. Add `ensure moh-jobgarage` to your `server.cfg` **after** QBCore and your target/fuel/keys resources.
3. Open `config.lua` and configure your target, keys, fuel, and locations (see below).
4. Add logo images for each garage under `html/logos/` (PNG with transparency recommended).
5. Restart the resource or restart the server.

{% hint style="warning" %}
**Dependency order matters.** `moh-jobgarage` must start after `qb-core`, your target resource, your fuel resource, and your vehicle-keys resource.
{% endhint %}

## Configuration

All configuration lives in `config.lua`.

### Target System

```lua
Config.TargetType = 'qb-target' -- 'qb-target' | 'ox_target'
Config.TargetResource = 'qb-target' -- exact resource name on your server
```

Set `TargetType` to match the interaction library you use, and `TargetResource` to its *exact* resource name (important if you have renamed it).

### Vehicle Keys

```lua
Config.VehicleKeys = 'qb-vehiclekeys' -- Other supported values: 'qs-vehiclekeys'
-- Set to false to disable key handoff entirely
```

When set to `false` or when the resource is not started, no keys will be issued (useful if your framework handles keys differently).

### Fuel System

```lua
Config.FuelSystem = 'LegacyFuel' -- Supported: 'LegacyFuel', 'ps-fuel', 'lj-fuel', 'cdn-fuel', 'qb-fuel', 'ox_fuel'
-- Set to false to disable (vehicle spawns at native fuel level)
```

If set to `false` or if the resource is not running, the script falls back to GTA's native `SetVehicleFuelLevel`.

### Locations

Locations are defined in the `Config.Locations` table, indexed by integer keys:

```lua
Config.Locations = {
  [1] = { ... },
  [2] = { ... },
}
```

## Location Structure

Each location entry accepts the following fields:

| Field         | Type                         | Required | Description                                                                        |
| ------------- | ---------------------------- | -------- | ---------------------------------------------------------------------------------- |
| `Job`         | `string` or `table` or `nil` | No       | Job name(s) that can access this garage. Use a table for multiple jobs.            |
| `Gang`        | `string` or `nil`            | No       | Gang name that can access this garage. Set to `nil` for no gang access.            |
| `Logo`        | `string`                     | Yes      | Path to the logo image relative to the `html/` folder (e.g. `'logos/police.png'`). |
| `Theme`       | `table`                      | Yes      | Color theme for the NUI panel. See [Theming](#theming).                            |
| `Ped`         | `table`                      | Yes      | Ped model, spawn coordinates, display name, and target label.                      |
| `SpawnCoords` | `vector4`                    | Yes      | Where vehicles are spawned (x, y, z, heading).                                     |
| `Vehicles`    | `table`                      | Yes      | List of vehicle entries available from this garage.                                |

### Ped sub-table

| Field         | Type      | Description                                   |
| ------------- | --------- | --------------------------------------------- |
| `model`       | `string`  | Ped model hash name (e.g. `'s_m_y_cop_01'`).  |
| `coords`      | `vector4` | Spawn position and heading of the ped.        |
| `name`        | `string`  | Displayed as the panel title in the NUI menu. |
| `targetLabel` | `string`  | Label shown in the target interaction prompt. |

Example:

```lua
Ped = {
  model = 's_m_y_cop_01',
  coords = vector4(435.45, -972.96, 25.70, 183.43),
  name = 'Police Garage',
  targetLabel = 'Open Police Garage'
},
```

## Vehicle Entry Structure

Each entry inside the `Vehicles` table accepts:

| Field              | Type                         | Required | Description                                                                                                      |
| ------------------ | ---------------------------- | -------- | ---------------------------------------------------------------------------------------------------------------- |
| `VehicleName`      | `string`                     | Yes      | Display name shown in the menu button.                                                                           |
| `VehicleSpawnName` | `string`                     | Yes      | The spawn model name used by QBCore (matches the vehicle's `model` key).                                         |
| `Grade`            | `number`                     | Yes      | Minimum job grade required to see this vehicle. Use `0` for all grades.                                          |
| `livery`           | `number`                     | Yes      | Livery index to apply on spawn. `0` for default. Falls back to mod slot 48 if the vehicle has no liveries.       |
| `colors`           | `table {primary, secondary}` | Yes      | GTA color indices for primary and secondary paint. Use `{0, 0}` for black/black.                                 |
| `extras`           | `table`                      | Yes      | List of extra indices to enable on spawn. All other extras are disabled first. Pass an empty table `{}` to skip. |

Example:

```lua
{ VehicleName = 'Police Car 2', VehicleSpawnName = 'nfsexpl', Grade = 0, livery = 2, colors = {0, 0}, extras = {1,2,3,4,5,6,7} },
```

## Theming

Each location has a `Theme` table that controls the NUI panel appearance. All values are hex color strings.

| Key        | Description                                           |
| ---------- | ----------------------------------------------------- |
| `accent`   | Main highlight color — selection glow, focused state. |
| `accent2`  | Secondary color — borders, scrollbar thumb.           |
| `panelTop` | Top color of the panel background gradient.           |
| `panelBot` | Bottom color of the panel background gradient.        |
| `btnTop`   | Top color of vehicle button gradient.                 |
| `btnBot`   | Bottom color of vehicle button gradient.              |

Example — blue police theme:

```lua
Theme = { accent = '#3B82F6', accent2 = '#1E3A8A', panelTop = '#121623', panelBot = '#0A0C14', btnTop = '#5078C8', btnBot = '#1E326E' },
```

## Logos

Place PNG logo files inside `html/logos/`. Transparent backgrounds are recommended — the script applies a white glow and a subtle pulse animation automatically.

Reference them in config with the path relative to `html/`:

```lua
Logo = 'logos/police.png',
```

Recommended dimensions: **160 × 80 px** minimum, transparent PNG.

## Default Locations

The resource ships with 19 pre-configured locations:

| ID | Name                | Access Type | Job / Gang   |
| -- | ------------------- | ----------- | ------------ |
| 1  | Sheriff Garage      | Job         | sheriff      |
| 2  | Ambulance Garage    | Job         | ambulance    |
| 3  | Police Garage       | Job         | police, swat |
| 4  | Ballas Garage       | Gang        | ballas       |
| 5  | ATK Garage          | Gang        | atk          |
| 6  | Vagos Garage        | Gang        | vagos        |
| 7  | Bloods Garage       | Gang        | bloods       |
| 8  | Families Garage     | Gang        | families     |
| 9  | 410 Garage          | Gang        | th           |
| 10 | BlackPistone Garage | Gang        | blackpistone |
| 11 | Favelas Garage      | Gang        | favelas      |
| 12 | OBlock Garage       | Gang        | oblock       |
| 13 | Yakuza Garage       | Gang        | yakuza       |
| 14 | Marabunta Garage    | Gang        | marabunta    |
| 15 | SWAT Garage         | Job         | swat         |
| 16 | Police Helipad      | Job         | police       |
| 17 | Mafia Garage        | Gang        | mafia        |
| 18 | Blancos Garage      | Gang        | blancos      |
| 19 | Ambulance Helipad   | Job         | ambulance    |

## NUI Controls

| Key         | Action                                |
| ----------- | ------------------------------------- |
| `↑` / `↓`   | Navigate vehicle list                 |
| `Enter`     | Spawn selected vehicle                |
| `Escape`    | Close menu                            |
| Mouse click | Spawn clicked vehicle / Store / Close |

The **Store Vehicle** button only appears when the player has an active spawned vehicle from this garage. Clicking it deletes the vehicle and clears the reference.

## Events & Callbacks

### Client Events

| Event                               | Parameters            | Description                                                                                                                          |
| ----------------------------------- | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| `moh-jobgarage:client:OpenMenu`     | `locationId` (number) | Opens the NUI garage menu for the given location. Called internally by target interaction. Can also be called from external scripts. |
| `moh-jobgarage:client:SpawnVehicle` | `data` (table)        | Spawns the vehicle defined in `data`. Called internally from the NUI callback.                                                       |

### NUI Callbacks

| Callback       | Triggered by              | Action                                                           |
| -------------- | ------------------------- | ---------------------------------------------------------------- |
| `spawnVehicle` | Vehicle button click      | Fires `moh-jobgarage:client:SpawnVehicle`, closes menu.          |
| `storeVehicle` | Store Vehicle button      | Deletes active spawned vehicle, shows notification, closes menu. |
| `close`        | Close button / Escape key | Removes NUI focus, hides menu.                                   |

## Adding a New Location

{% stepper %}
{% step %}

#### Open `config.lua` and add a new entry at the next available index

```lua
[20] = {
  Job = {'mechanic'}, -- or Gang = 'yourgang'
  Gang = nil,
  Logo = 'logos/mechanic.png',
  Theme = {
    accent = '#F97316',
    accent2 = '#C2410C',
    panelTop = '#1C1008',
    panelBot = '#0E0804',
    btnTop = '#EA580C',
    btnBot = '#7C2D12'
  },
  Ped = {
    model = 's_m_y_mechanic_01',
    coords = vector4(0.0, 0.0, 0.0, 0.0), -- replace with real coords
    name = 'Mechanic Garage',
    targetLabel = 'Open Mechanic Garage'
  },
  SpawnCoords = vector4(0.0, 0.0, 0.0, 0.0), -- replace with real coords
  Vehicles = {
    { VehicleName = 'Tow Truck', VehicleSpawnName = 'towtruck', Grade = 0, livery = 0, colors = {0,0}, extras = {} },
  }
},
```

{% endstep %}

{% step %}

#### Add `html/logos/mechanic.png`

Use a transparent PNG, around **160×80 px**.
{% endstep %}

{% step %}

#### Save and `ensure moh-jobgarage` in the server console

Or restart the server.
{% endstep %}
{% endstepper %}

{% hint style="info" %}
**Tip:** To allow multiple jobs, use a table: `Job = {'police', 'sheriff'}`. A player only needs to match *one* of the listed jobs. Jobs and gangs are checked independently — a player with the right gang will also gain access even if they don't match any job.
{% endhint %}

## FAQ

<details>

<summary>The ped spawns but the target interaction doesn't appear.</summary>

Check that `Config.TargetType` and `Config.TargetResource` match exactly the resource name and type running on your server. Run `ensure qb-target` (or your target resource) before `moh-jobgarage`.

</details>

<details>

<summary>The vehicle spawns without fuel.</summary>

Make sure `Config.FuelSystem` is set to the exact resource name of your fuel script and that the resource is started before `moh-jobgarage`. If you don't use a fuel resource, set it to `false`.

</details>

<details>

<summary>The player gets no keys after spawning.</summary>

Verify `Config.VehicleKeys` matches your keys resource name and that the resource is started. Supported out-of-the-box: `qb-vehiclekeys`, `qs-vehiclekeys`. Any resource that exposes a `GiveKeys(plate)` export will work via the generic fallback.

</details>

<details>

<summary>A player can't see any vehicles in the menu.</summary>

Two possible causes: (1) their job/gang doesn't match the location's `Job` or `Gang` value, or (2) their grade is below the minimum `Grade` set on all vehicles. Check `QBCore.Functions.GetPlayerData().job` in F8 console.

</details>

<details>

<summary>Can I give access to both a job and a gang on the same garage?</summary>

Yes. Set both `Job` and `Gang`. If the player matches either, they gain access.

</details>

<details>

<summary>How do I change the position of the NUI panel?</summary>

Edit `html/style.css`. The `.menu-container` class controls position. By default it is anchored to the right side, vertically centered.

</details>

<details>

<summary>Can a player have two vehicles out at the same time?</summary>

No. The script tracks a single `SpawnedVehicle` entity per client. Spawning a new vehicle automatically deletes the previous one.

</details>


---

# Agent Instructions: Querying This Documentation

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

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

```
GET https://mohssins.gitbook.io/mohscriptsdocs/moh-jobgarage.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
