> For the complete documentation index, see [llms.txt](https://realtime-dev.gitbook.io/realtime-dev-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://realtime-dev.gitbook.io/realtime-dev-docs/realtime-scripts/rt-garages-coming-soon.md).

# 🅿️ RT GARAGES (¡Coming Soon!)

Realistic **spot-based parking**, in-game garage & impound builders, rentals, police impound, and tow dispatch for QBX and QB-Core.

> ESX is not supported. Future support is not guaranteed.

***

### 📋 Requirements

* FXServer build 17000+
* MySQL + `oxmysql`
* `ox_lib`
* `ox_target`
* `qbx_core` or `qb-core`
* Recommended: `rt-vehiclekeys` (auto-detected for keys on take-out / rental)
* Optional: fuel script (`ox_fuel`, `LegacyFuel`, `lc_fuel`), `ox_inventory` (rental contract item)

***

### 📦 Installation

**Step 1 — Upload**

```
resources/[qbx]/rt-garages

```

**Step 2 — Minimum config**

Edit `config/config.lua`:

```lua
Config.Framework = 'auto',        -- auto | qbx_core | qb-core
Config.Locale    = '',            -- '' = ox:locale convar · en, es, fr, de, pt-BR, it

Config.Creator = {
    command     = 'rtgarage',
    ace         = 'rt.garages.admin',
    adminGroups = { 'admin', 'god' },
}

Config.Impound.creator = {
    command     = 'rtimpound',
    ace         = 'rt.garages.admin',
    adminGroups = { 'admin', 'god' },
}
```

QB-Core only — if the framework is not detected, force it:

```lua
Config.Framework = 'qb-core'

```

**Step 3 — server.cfg**

QBX example:

```cfg
ensure ox_lib
ensure oxmysql
ensure qbx_core
ensure ox_target
ensure rt-vehiclekeys
ensure rt-garages

```

QB-Core example:

```cfg
ensure ox_lib
ensure oxmysql
ensure qb-core
ensure ox_target
ensure rt-garages

```

**Step 4 — Permissions (optional)**

Garage & impound builders use ACE or framework admin groups:

```cfg
add_ace group.admin rt.garages.admin allow
```

**Step 5 — Restart**

Tables `rt_garages`, `rt_garage_spots`, `rt_garage_fleet`, `rt_garage_fleet_out`, `rt_impounds`, `rt_impound_spots`, `rt_garage_rental_catalog`, `rt_garage_rental_out` and `rt_garage_tow_calls` are created automatically from `sql/install.sql`. No manual import required.

***

### ✅ Quick check

1. Join the server with a loaded character.
2. Run `/rtgarage` (admin) — the garage builder opens.
3. Create a public garage: place the NPC, add parking spots with the gizmo, save.
4. Drive to a spot inside the garage zone, press **H** to park (or exit the vehicle if `storeOnExit` is on).
5. Walk to the NPC and press **E** — the garage panel opens; take the vehicle out.

Builder won't open? Check ACE / admin group. UI not updating? Clear NUI cache: `%localappdata%\FiveM\FiveM.app\data\cache\files\rt-garages`.

***

### 🎮 Parking (players)

Each garage has **physical spots**. Vehicles are stored on the exact spot where you park them and respawn there on take-out.

| Action                                     | Default key                                      |
| ------------------------------------------ | ------------------------------------------------ |
| Open garage menu (at NPC)                  | `E`                                              |
| Park manually (in vehicle, on a free spot) | `H`                                              |
| Park on exit                               | Automatic if `Config.Parking.storeOnExit = true` |
| Take out vehicle                           | Garage panel or walk to parked prop + `E`        |

**Rules (configurable in `Config.Parking`):**

* You must be on a valid spot (`spotRadius`, optional heading check).
* Occupied spots are blocked when `blockOccupied = true`.
* Keys required when `requireKeys = true` (uses your keys provider).
* Parked vehicles show as **props** near the player (distance-optimized).

Uses `player_vehicles.state` (`0` = out, `1` = parked) and JSON `coords` with `spotId` + exact position.

***

### 🛠️ Garage builder (admin)

```
/rtgarage

```

In-game wizard — no coordinates in config. Everything is saved to the database.

**Garage types:** `public` · `job` · `gang` · `private` · `rental`\
**Vehicle types:** `car` · `air` · `sea`

**Typical flow:**

1. Name, slug, type, vehicle type, access rules (job/gang/owners).
2. Place the **attendant NPC** (blip spawns at the same point).
3. Add **parking spots** with the gizmo (raycast to ground, ghost vehicle for heading).
4. Optional: **fleet catalog** (job garages) or **rental catalog** (rental garages).
5. Save — clients sync automatically.

**Job garages — fleet:** shared job vehicles with configurable plates (`Config.JobGarage.fleetPlates`), optional full-performance mods on take-out, spots used as spawn points only (`fleetNoSpotOccupancy`).

***

### 🚓 Impound builder (admin)

```
/rtimpound

```

Same gizmo pattern as garages: NPC, spots, blip, default release price.

Owners retrieve impounded vehicles at the impound NPC (**E**). Price comes from `default_price` on the impound or `depotprice` on the vehicle row.

Set the slug used by persistence cleanup:

```lua
Config.Persistence.defaultImpoundSlug = 'innocence-boulevard'  -- must match an impound you created
```

***

### 👮 Police impound (ox\_target)

Police jobs (`Config.Impound.policeJobs`) can impound any nearby vehicle via **ox\_target**.

* Opens an RT impound menu (notepad animation).
* Pick nearest impound from a distance-sorted list.
* Vehicle fades out; stored in `player_vehicles` with impound metadata.

```lua
Config.Impound = {
    policeJobs     = { 'police', 'sheriff', 'lspd', 'bcso', 'sasp' },
    minGrade       = 0,
    defaultPrice   = 500,
    targetDistance = 4.0,
}
```

Requires `ox_target`. If it is not started, police impound is disabled (console warning).

***

### 🚗 Rental garages

Create a garage with type **`rental`** in `/rtgarage`, then add vehicles to the rental catalog (model, price, duration, stock).

**Flow:**

1. Player opens rental garage → picks a vehicle.
2. Pickup progress UI (clipboard animation) at the NPC.
3. Vehicle spawns on a spot; player receives **`rt_rental_contract`** (ox\_inventory item with metadata).
4. Contract can be **read** or **presented** to nearby players.
5. Late return fees apply (`lateFeeFlat`, `lateFeePerMinute`).

**ox\_inventory item** (add to `ox_inventory/data/items.lua` if not present):

```lua
['rt_rental_contract'] = {
    label = 'Rental contract',
    weight = 50,
    stack = false,
    close = true,
    consume = 0,
    client = {
        export = 'rt-garages.useRentalContract',
    },
},
```

```lua
Config.Rental = {
    contractItem           = 'rt_rental_contract',
    platePattern           = 'RENT%03d',
    defaultDurationMinutes = 60,
    maxActivePerPlayer     = 1,
    lateFeeFlat            = 250,
    lateFeePerMinute       = 50,
}
```

***

### 🛻 Tow service & dispatch

Abandoned vehicles on the street (engine off, outside garage spots) enter a grace period, then appear as **tow calls** for authorized jobs.

```lua
Config.TowService = {
    enabled            = true,
    authorizedJobs     = { 'mechanic', 'bennys' },
    minGrade           = 0,
    requireDuty        = true,
    minAbandonedMinutes = 2,
    ownerGraceMinutes  = 1,
    towVehicleModels   = { 'flatbed', 'towtruck', 'towtruck2' },
    requireTowVehicle  = true,
    impoundFee         = 500,   -- owner pays on retrieval
    mechanicPayout     = 350,   -- paid on delivery
    payAccount         = 'bank',
    dispatchAutoShow   = false, -- true = open panel when going on duty
}
```

**Dispatch panel (mechanics on duty):**

| Key / action        | What it does                                                                                          |
| ------------------- | ----------------------------------------------------------------------------------------------------- |
| **P**               | Show / **fully hide** the dispatch (stays hidden until you press P again; new calls do not reopen it) |
| **Y**               | Move panel position (drag · **Enter** save · **Esc** cancel). Panel must be open first.               |
| **↑ / ↓**           | Navigate calls                                                                                        |
| **Enter**           | Accept call                                                                                           |
| **←**               | Dismiss call                                                                                          |
| **E**               | Deliver at impound (when in zone with vehicle hooked)                                                 |
| `/towdispatch`      | Open / minimize / expand                                                                              |
| `/towdispatch move` | Same as **Y** (move mode)                                                                             |

Panel position is saved **per player** (client KVP) and persists across restarts.

**Delivery flow:** accept call → GPS to vehicle → hook with tow truck → GPS to impound → press **E** in zone to complete.

Debug a plate eligibility:

```
/towdebug [PLATE]
```

***

### 🌍 Street persistence (optional)

Keeps owned vehicles in the world when left outside garages; can auto-impound after cleanup timer.

```lua
Config.Persistence = {
    enabled            = true,
    useQbxNative       = 'auto',   -- use qbx_core persistence when available
    saveIntervalMs     = 300000,   -- save position every 5 min
    spawnDistance      = 75.0,     -- respawn radius after restart
    cleanupHours       = 48,         -- offline owner → impound
    cleanupFee         = 250,
    defaultImpoundSlug = 'innocence-boulevard',
}
```

Respects rt-garages parking spots when `Config.TowService.respectGarageSpots = true`.

***

### ⚙️ Main settings

File: `config/config.lua`

| Block                               | What it does                                         |
| ----------------------------------- | ---------------------------------------------------- |
| `Config.Framework`                  | `auto`, `qbx_core` or `qb-core`                      |
| `Config.Locale`                     | UI language or `''` for ox convar                    |
| `Config.Creator`                    | `/rtgarage` command, ACE, admin groups               |
| `Config.Npc`                        | Default ped models/scenarios per garage type         |
| `Config.Parking`                    | Spot radius, keys, fade, store keys, world UI        |
| `Config.Persistence`                | World vehicles, cleanup, default impound             |
| `Config.TowService`                 | Tow jobs, timers, dispatch, payouts                  |
| `Config.BlipSprites` / `BlipColors` | Map icons by vehicle/garage type                     |
| `Config.Keys`                       | Vehicle keys provider (`auto`, rt-vehiclekeys, etc.) |
| `Config.Fuel`                       | Optional fuel save on park                           |
| `Config.JobGarage`                  | Fleet plates, full-performance mods                  |
| `Config.Rental`                     | Contract item, fees, pickup animation                |
| `Config.Impound`                    | Impound creator, police jobs, animations             |

All options have comments inside `config/config.lua`.

***

### 🔑 Vehicle keys

Auto-detects `rt-vehiclekeys`, `qbx_vehiclekeys`, `qb-vehiclekeys`, `wasabi_carlock`:

```lua
Config.Keys = {
    provider = 'auto',
    autoDetect = {
        ['rt-vehiclekeys']  = 'rt-vehiclekeys',
        ['qb-vehiclekeys']  = 'qb-vehiclekeys',
        ['wasabi_carlock']  = 'wasabi_carlock',
    },
    custom = {
        give   = { type = 'export', resource = 'my-keys', export = 'GiveKeys' },
        remove = { type = 'export', resource = 'my-keys', export = 'RemoveKeys' },
        has    = { type = 'export', resource = 'my-keys', export = 'HasKeys' },
    },
}
```

See `integrations/keys.lua` for hook details.

***

### 🧩 Exports

```lua
-- Client (rental contract · ox_inventory)
exports['rt-garages']:useRentalContract(_, slot)
exports['rt-garages']:presentRentalContract(_, slot)
```

Rental contract server event (show contract to another player):

```lua
TriggerServerEvent('rt-garages:server:presentRentalContract', metadata)
```

Client reload events (after admin saves in builder):

```lua
'rt-garages:client:reloadGarages'
'rt-garages:client:reloadImpounds'
'rt-garages:client:syncGarages'
'rt-garages:client:syncImpounds'
```

***

### 👮 Admin & permissions

| Command      | Permission                                         | Purpose         |
| ------------ | -------------------------------------------------- | --------------- |
| `/rtgarage`  | `rt.garages.admin` or `Config.Creator.adminGroups` | Garage builder  |
| `/rtimpound` | Same ACE / groups                                  | Impound builder |

ACE: `rt.garages.admin`\
Groups: `Config.Creator.adminGroups` / `Config.Impound.creator.adminGroups` (default `admin`, `god`).

***

### 📁 Config files

| File                    | Purpose                                                          |
| ----------------------- | ---------------------------------------------------------------- |
| `config/config.lua`     | All settings                                                     |
| `bridge/framework.lua`  | QBX / QB-Core bridge                                             |
| `integrations/keys.lua` | Keys provider hooks                                              |
| `locales/*.json`        | UI + server translations (`en`, `es`, `fr`, `de`, `pt-BR`, `it`) |
| `sql/install.sql`       | Optional manual table import                                     |

***

### 🛠️ Troubleshooting

| Symptom                            | Fix                                                                      |
| ---------------------------------- | ------------------------------------------------------------------------ |
| Builder won't open                 | Add ACE `rt.garages.admin` or use an admin group from config             |
| `attempt to index nil` (framework) | Start `qbx_core` / `qb-core`, or set `Config.Framework`                  |
| `rt_garages*` table errors         | Configure `oxmysql` connection; restart resource                         |
| UI changes not showing             | Clear NUI cache for `rt-garages`                                         |
| Cannot park                        | Not on a spot, spot occupied, or missing keys                            |
| Police impound missing             | Ensure `ox_target` is started                                            |
| Rental contract does nothing       | Add `rt_rental_contract` to ox\_inventory with export                    |
| Tow dispatch won't show            | On duty, authorized job in `authorizedJobs`, `TowService.enabled = true` |
| Dispatch won't hide                | Press **P** again; hidden state persists until you reopen with **P**     |
| Cleanup sends to wrong impound     | Create impound with slug matching `defaultImpoundSlug`                   |
| Garages hidden on map              | DB row `enabled = 0` — edit via `/rtgarage` or set `enabled = 1`         |

***

### **❤️ Support**

Developed by RT Dev. Support through your Tebex purchase channel. © RealTime Dev — all rights reserved.


---

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

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

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

```
GET https://realtime-dev.gitbook.io/realtime-dev-docs/realtime-scripts/rt-garages-coming-soon.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
