> ## Documentation Index
> Fetch the complete documentation index at: https://docs.shdevelopment.org/llms.txt
> Use this file to discover all available pages before exploring further.

# sh-vehiclekeys: Persistent Vehicle Key System for FiveM

> sh-vehiclekeys replaces default key-on-entry with a database-backed key system. Players lock, share, and manage keys via a NUI menu.

sh-vehiclekeys replaces GTA V's default behavior — where sitting in a vehicle is all it takes to drive it — with a realistic, database-persisted key management system. Keys are tied to a vehicle's plate number and stored in MySQL, so they survive server restarts and reconnects. Players lock and unlock vehicles from outside, share key access with other online players by server ID, and view their owned fleet through an in-game NUI panel that also shows mileage, insurance status, registration status, and parked state.

<Note>
  sh-vehiclekeys is currently in active development. The core feature set is stable and production-ready, but minor additions or adjustments may appear in future updates. Check the changelog in the resource folder after each update before restarting the resource on a live server.
</Note>

## Requirements

| Dependency   | Purpose                                                 |
| ------------ | ------------------------------------------------------- |
| QBCore       | Player identity, job data, inventory, and notifications |
| mysql-async  | Database persistence for shared key records             |
| t3\_lockpick | Lockpicking minigame item and logic                     |

All three must be started **before** `sh-vehiclekeys` in `server.cfg`.

## Installation

<Steps>
  <Step title="Download and place the resource">
    Copy the `sh-vehiclekeys` folder into your server's `resources` directory.
  </Step>

  <Step title="Import the SQL schema">
    Run the following statement against your server's database. You can execute it directly in your database manager (e.g., phpMyAdmin, HeidiSQL) or add it to your automated SQL import process.

    ```sql theme={null}
    CREATE TABLE IF NOT EXISTS `shvehiclekeys` (
      `id`         int(11)      NOT NULL AUTO_INCREMENT,
      `plate`      varchar(50)  NOT NULL,
      `citizenid`  varchar(50)  NOT NULL,
      `customname` varchar(100) NOT NULL,
      PRIMARY KEY (`id`),
      UNIQUE KEY `unique_key_assignment` (`plate`, `citizenid`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;
    ```
  </Step>

  <Step title="Add to server.cfg">
    ```cfg server.cfg theme={null}
    ensure mysql-async
    ensure qb-core
    ensure t3_lockpick
    ensure sh-vehiclekeys
    ```
  </Step>

  <Step title="Configure shared/config.lua">
    Review and adjust the values described in the [Configuration](#configuration) section below.
  </Step>

  <Step title="Restart the resource">
    Run `refresh` then `restart sh-vehiclekeys` in the server console, or perform a full server restart.
  </Step>
</Steps>

## Default Keybinds

All keybinds are registered as GTA V input bindings and are fully remappable by each player in **Settings → Key Bindings → FiveM**.

| Action                       | Default Key                                          |
| ---------------------------- | ---------------------------------------------------- |
| Lock / Unlock nearby vehicle | `L`                                                  |
| Toggle engine on/off         | `G`                                                  |
| Open keys management menu    | *(blank — player sets this in their FiveM settings)* |

## Configuration

```lua shared/config.lua theme={null}
Config.Debug               = false  -- Enables /printkeys command for debugging key state
Config.VehicleLockDistance = 5.0    -- Max metres from the vehicle to lock/unlock
Config.ToggleLocks         = 'L'    -- Default keybind for lock/unlock
Config.ToggleEngine        = 'G'    -- Default keybind for engine toggle
Config.OpenVehicleKeys     = ''     -- Default keybind for keys menu (blank = player sets it)
Config.UseKeyFob           = false  -- true = requires a key_fob item in inventory to open the keys menu
Config.PoliceChance        = 50     -- % chance a lockpick attempt triggers a dispatch alert

Config.JobSharedVehicles = {
    ['police']    = { 'police', 'police2' },
    ['ambulance'] = { 'ambulance' },
}
```

<Tip>
  Keep `Config.Debug = false` in production. Debug mode enables a `/printkeys` command that prints every plate currently held in memory to the player's console — useful when troubleshooting, but unnecessary on a live server.
</Tip>

### Job-Shared Vehicles

`Config.JobSharedVehicles` lets you define a list of vehicle models that all players of a given job automatically hold keys to while on duty. This means your entire police department can drive any police-model vehicle without manually sharing keys — useful for departmental fleet management without giving out spawner access.

When a player's active job is checked, the resource grants temporary in-memory keys to the listed models. These keys are **not** persisted to the database and do not appear in the player's NUI key list.

## Lockpicking

Lockpicking is handled by the `t3_lockpick` resource. Two items are supported: `lockpick` (4-pin difficulty) and `advancedlockpick` (3-pin difficulty). Both must be present in the player's QBCore inventory to use. When a player attempts to pick a lock:

<Steps>
  <Step title="Minigame launches">
    The t3\_lockpick minigame starts client-side. The `lockpick` item uses 4 pins; the `advancedlockpick` uses 3 pins. Difficulty is fixed at level 2 — adjust it inside the t3\_lockpick resource configuration if needed.
  </Step>

  <Step title="Success or failure">
    On **success**, the vehicle is unlocked and the player receives persistent database keys if they are already seated in the driver's seat. If they are outside the vehicle, it is simply unlocked without granting keys. On **failure**, the lock remains engaged and the pick item is consumed.
  </Step>

  <Step title="Dispatch alert (optional)">
    Either outcome can trigger a police dispatch alert. `Config.PoliceChance` sets the percentage chance the alert fires. Set it to `0` to disable dispatch integration entirely, or `100` to always alert on every lockpick attempt.
  </Step>
</Steps>

<Warning>
  Lockpicking grants persistent database keys when performed from inside a vehicle. Ensure your server's roleplay rules and job permissions make sense for this behavior — staff may want to monitor for abuse if the lockpick item is freely obtainable.
</Warning>

## Keys NUI Menu

Open the keys management menu with your configured keybind (or via the `key_fob` item when `Config.UseKeyFob = true`). The panel lists every vehicle in your QBCore garage and displays the following per vehicle:

<Accordion title="Vehicle details shown in the NUI panel">
  * **Make and model** — derived from QBCore's shared vehicle data
  * **Plate** — the registered plate linked to the key record
  * **Insurance status** — valid or uninsured
  * **Registration status** — valid or expired
  * **Mileage** — tracked distance driven (`traveldistance` field from `player_vehicles`)
  * **Parked status** — whether the vehicle is currently stored (`state = 1`) or out in the world
</Accordion>

From within the panel you can also:

* **Locate vehicle** — sets a GPS waypoint to the vehicle's current position if it is spawned in the world.
* **Manage keys** — opens a sub-panel listing every `citizenid` that holds a shared key grant for that vehicle, with the option to revoke individual grants.

## Sharing and Revoking Keys

To give another player access to one of your vehicles, open the keys menu, select the vehicle, choose **Give Keys**, and enter the target player's server ID. You can optionally assign a custom display name that appears in their key list.

<Tabs>
  <Tab title="Giving Keys">
    1. Open the keys menu with your keybind.
    2. Select the vehicle you want to share.
    3. Choose **Give Keys** and enter the target's server ID.
    4. Optionally type a display name (e.g., `"Mechanic — temp"`).
    5. Confirm. The key record is written to the `shvehiclekeys` table immediately.
  </Tab>

  <Tab title="Revoking Keys">
    1. Open the keys menu and select the vehicle.
    2. Choose **Manage Keys**.
    3. You will see a list of every active key grant for that vehicle.
    4. Select a grant and choose **Revoke** to delete the record from the database.

    The revoked player loses access immediately — their next lock/unlock attempt will be rejected.
  </Tab>
</Tabs>

## Key Fob Item (Optional)

When `Config.UseKeyFob = true`, the keys menu can only be opened by using a `key_fob` item from the player's inventory rather than a keybind. To enable this:

1. Add the `key_fob` item to your QBCore `items.lua`:

   ```lua theme={null}
   key_fob = {
       name        = "key_fob",
       label       = "Key Fob",
       weight      = 100,
       type        = "item",
       image       = "sh_key_fob.png",
       unique      = false,
       useable     = true,
       shouldClose = true,
       combinable  = nil,
       description = "A key fob",
   },
   ```

2. Copy `sh_key_fob.png` from the `INSTALL/` folder into your inventory's `html/images/` directory (typically `qb-inventory/html/images/`).

3. Set `Config.UseKeyFob = true` in `shared/config.lua` and restart the resource.
