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

# Installation

> Drop the resource in, add the ox_inventory items, ensure after cc_heistcontracts.

## Requirements

* A FiveM server already running [cc\_heistcontracts](/cc_heistcontracts/installation).
* [ox\_lib](https://github.com/overextended/ox_lib) and [oxmysql](https://github.com/overextended/oxmysql).
* A working `cc_lib` resource.
* An inventory system (defaults assume **ox\_inventory**).

## Steps

<Steps>
  <Step title="Place the resource">
    Copy `cc_paletoheist` into a resources directory the server loads. The repo ships under `resources/[cc]/cc_paletoheist/`.
  </Step>

  <Step title="Add the inventory items">
    <Tabs>
      <Tab title="ox_inventory">
        Add the following items to `ox_inventory/data/items.lua`

        ```lua theme={null}
        hacking_device = { label = 'DataJack', weight = 600, stack = false },
        laptop_pro = { label = 'Jackbox Pro', weight = 2800, stack = false },
        frequency_tuner = { label = 'Signal Modulator', weight = 250 },
        electric_drill = { label = 'Cordless Drill', weight = 1800, stack = false },
        ```

        Drop the matching item images into `ox_inventory/web/images/` (filenames must match the name of the item).

        <Note>
          The `weapon_smg` requirement is a standard ox\_inventory weapon — no extra config needed if you're on the stock weapons list.
        </Note>
      </Tab>

      <Tab title="qb-inventory">
        Add the following items to `qb-core/shared/items.lua`

        ```lua theme={null}
        hacking_device = { name = 'hacking_device', label = 'DataJack', weight = 600, unique = true, type = 'item', image = 'hacking_device.png', useable = false },
        laptop_pro = { name = 'laptop_pro', label = 'Jackbox Pro', weight = 2800, unique = true, type = 'item', image = 'laptop_pro.png', useable = false },
        frequency_tuner = { name = 'frequency_tuner', label = 'Signal Modulator', weight = 250, unique = false, type = 'item', image = 'frequency_tuner.png', useable = false },
        electric_drill = { name = 'electric_drill', label = 'Cordless Drill', weight = 1800, unique = true, type = 'item', image = 'electric_drill.png', useable = false },
        ```

        Drop the matching item images into `qb-inventory/html/images/` (filenames must match the image field).

        <Note>
          The `weapon_smg` requirement is a standard qb-inventory weapon — no extra config needed if you're on the stock weapons list.
        </Note>
      </Tab>
    </Tabs>
  </Step>

  <Step title="Configure gabz map-data">
    Changes need to be made in `cfx-gabz-mapdata/gabz_entityset_mods1.lua`

    Replace the `gabz_paletobank_milo_` entry with this:

    ```lua theme={null}
      {
          ipl = 'gabz_paletobank_milo_',
          coords = { x = -106.037, y = 6467.548, z = 32.169 },
          entitySets = {
              { name = 'palbank_vault_trolleys', enable = false }, -- gold and cash trolleys (cc_paletoheist spawns its own)
          }
      },
    ```

    The `palbank_vault_trolleys` entry must be disabled — `cc_paletoheist` spawns its own trolley props during the run and the gabz set would duplicate them.
  </Step>

  <Step title="Ensure after cc_heistcontracts">
    Order in `server.cfg`:

    ```
    ensure oxmysql
    ensure ox_lib
    ensure cc_lib
    ensure cc_heistcontracts
    ensure cc_paletoheist
    ```

    `cc_paletoheist`'s `fxmanifest.lua` already declares `cc_heistcontracts` as a dependency, so FXServer enforces this.
  </Step>

  <Step title="(Optional) Tune the vault timer">
    Default vault open delay is 60 seconds. Edit `shared/config.lua`:

    ```lua theme={null}
    cfg.vault_timer = 60   -- seconds
    ```

    Set it lower for testing, higher for harder runs.
  </Step>

  <Step title="Doors integration">
    <Tabs>
      <Tab title="ox_doorlock">
        Set `cfg.auto_insert_doors = true` in `shared/config.lua` and the resource will insert these doors into the `ox_doorlock` table on first start (skipping any names already present). Leave it `false` if you manage doors manually.
      </Tab>

      <Tab title="qb-doorlock">
        `cfg.auto_insert_doors` only targets `ox_doorlock`. On `qb-doorlock`, paste these entries into `qb-doorlock/config/locations.lua` (inside `Config.DoorList`) and restart `qb-doorlock`:

        ```lua theme={null}
        Config.DoorList['PaletoThermiteDoor'] = {
            objHash = 1309269072,
            objCoords  = vec3(-106.47130584716, 6476.1577148438, 31.9547996521),
            textCoords = vec3(-106.47130584716, 6476.1577148438, 31.9547996521),
            objYaw = 315, locked = true, pickable = false, distance = 2
        }
        Config.DoorList['paleto-security_backdoor'] = {
            objHash = 1248599813,
            objCoords  = vec3(-96.708656311036, 6474.056640625, 31.787979125976),
            textCoords = vec3(-96.708656311036, 6474.056640625, 31.787979125976),
            objYaw = 135, locked = true, pickable = false, distance = 2
        }
        Config.DoorList['paleto-office1'] = {
            objHash = 2110946875,
            objCoords  = vec3(-104.83712768554, 6463.7739257812, 31.79334640503),
            textCoords = vec3(-104.83712768554, 6463.7739257812, 31.79334640503),
            objYaw = 225, locked = true, pickable = false, distance = 2
        }
        Config.DoorList['paleto-office2'] = {
            objHash = 1754616769,
            objCoords  = vec3(-100.62174224854, 6467.9892578125, 31.79334640503),
            textCoords = vec3(-100.62174224854, 6467.9892578125, 31.79334640503),
            objYaw = 45, locked = true, pickable = false, distance = 2
        }
        Config.DoorList['paleto-office3'] = {
            objHash = -368548260,
            objCoords  = vec3(-104.70573425292, 6473.91796875, 31.787982940674),
            textCoords = vec3(-104.70573425292, 6473.91796875, 31.787982940674),
            objYaw = 45, locked = true, pickable = false, distance = 2
        }
        Config.DoorList['paleto-security_front'] = {
            objHash = -147325430,
            objCoords  = vec3(-100.1122970581, 6474.3920898438, 31.787979125976),
            textCoords = vec3(-100.1122970581, 6474.3920898438, 31.787979125976),
            objYaw = 315, locked = true, pickable = false, distance = 2
        }
        Config.DoorList['paleto-hall'] = {
            objHash = -56652918,
            objCoords  = vec3(-111.0426940918, 6475.328125, 31.787979125976),
            textCoords = vec3(-111.0426940918, 6475.328125, 31.787979125976),
            objYaw = 225, locked = true, pickable = false, distance = 2
        }
        Config.DoorList['paleto-control_room'] = {
            objHash = -147325430,
            objCoords  = vec3(-92.232231140136, 6468.9604492188, 31.787979125976),
            textCoords = vec3(-92.232231140136, 6468.9604492188, 31.787979125976),
            objYaw = 225, locked = true, pickable = false, distance = 2
        }
        Config.DoorList['paleto-vault'] = {
            objHash = -2050208642,
            objCoords  = vec3(-100.24186706542, 6464.5493164062, 31.884603500366),
            textCoords = vec3(-100.24186706542, 6464.5493164062, 31.884603500366),
            objYaw = 225, locked = true, pickable = false, distance = 2
        }
        ```
      </Tab>
    </Tabs>
  </Step>

  <Step title="Verify in-game">
    1. Set a profile to **level 3** (the contract is gated) — use `/heist:grantxp <playerId> 500` if you've enabled the admin command.
    2. Open the dashboard via the `heist_tablet`. **Paleto Bank Heist** should drip into the marketplace.
    3. Buy it for 2,500 VICE, start the slot, drive to Paleto.

    <Tip>
      Want the listing instantly? Lower `config.rotation.dripIntervalMs` in `cc_heistcontracts/shared/config.lua`.
    </Tip>
  </Step>
</Steps>

## Customising loot

`shared/rewards.lua` defines the **global loot table**. When `cfg.use_global_loot_table = true` (default), the rolled totals are split evenly across all lockers and all trolleys.

```lua theme={null}
return {
    lockers = {
        { type = 'item', item = 'black_money', amount = { min = 1000, max = 2000 } },
        { type = 'money',                       amount = { min = 1000, max = 2000 } },
    },
    trolleys = {
        { type = 'item', item = 'black_money', amount = { min = 1000, max = 2000 } },
        { type = 'money',                       amount = { min = 1000, max = 2000 } },
    },
}
```

Set `use_global_loot_table = false` to define loot per-unit inside `shared/location.lua` (each locker and each trolley accepts its own `rewards` table).
