> ## 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, register the ox_inventory items, ensure after cc_heistcontracts.

## Requirements

* A FiveM server already running [cc\_heistcontracts](/cc_heistcontracts/installation) — Fleeca is a module that registers a contract against it.
* [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_fleecaheist` into a resources directory the server loads. The repo ships under `resources/[cc]/cc_fleecaheist/`.
  </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_cheap = { label = 'Refurb LiteBook', weight = 2500, stack = false },
        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_pistol` 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_cheap = { name = 'laptop_cheap', label = 'Refurb LiteBook', weight = 2500, unique = true, type = 'item', image = 'laptop_cheap.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_pistol` 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\_fleeca0X\_milo\_ entries with this:

    ```lua theme={null}
      {
          ipl = 'gabz_fleeca01_milo_',
          coords = { x = 309.74646, y = -277.644165, z = 53.2345963 },
          entitySets = {
              { name = 'room04_cashtrolley', enable = false }, -- bags and cash trolleys
              { name = 'room05_cashtrolley', enable = false }, -- bags and cash trolleys
          }
      },
      {
          ipl = 'gabz_fleeca02_milo_',
          coords = { x = 1179.74475, y = 2706.985, z = 37.15784 },
          entitySets = {
              { name = 'room04_cashtrolley', enable = false }, -- bags and cash trolleys
              { name = 'room05_cashtrolley', enable = false }, -- bags and cash trolleys
          }
      },
      {
          ipl = 'gabz_fleeca03_milo_',
          coords = { x = 145.416824, y = -1039.277, z = 28.4378834 },
          entitySets = {
              { name = 'room04_cashtrolley', enable = false }, -- bags and cash trolleys
              { name = 'room05_cashtrolley', enable = false }, -- bags and cash trolleys
          }
      },
      {
          ipl = 'gabz_fleeca04_milo_',
          coords = { x = -1216.7616, y = -333.000763, z = 36.85084 },
          entitySets = {
              { name = 'room04_cashtrolley', enable = false }, -- bags and cash trolleys
              { name = 'room05_cashtrolley', enable = false }, -- bags and cash trolleys
          }
      },
      {
          ipl = 'gabz_fleeca05_milo_',
          coords = { x = -355.435852, y = -48.5326, z = 48.1063843 },
          entitySets = {
              { name = 'room04_cashtrolley', enable = false }, -- bags and cash trolleys
              { name = 'room05_cashtrolley', enable = false }, -- bags and cash trolleys
          }
      },
      {
          ipl = 'gabz_fleeca06_milo_',
          coords = { x = -2962.59131, y = 478.238037, z = 14.7668953 },
          entitySets = {
              { name = 'room04_cashtrolley', enable = false }, -- bags and cash trolleys
              { name = 'room05_cashtrolley', enable = false }, -- bags and cash trolleys
          }
      },
    ```
  </Step>

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

    ```
    ensure oxmysql
    ensure ox_lib
    ensure cc_lib
    ensure cc_heistcontracts
    ensure cc_fleecaheist
    ```

    `cc_fleecaheist`'s `fxmanifest.lua` already declares `cc_heistcontracts` as a dependency, so FXServer will refuse to start it before the parent is up. Wrong order = `No such export RegisterContract in resource cc_heistcontracts`.
  </Step>

  <Step title="Register the branch doors">
    Door entries are per-map — gabz and FM Fleeca Banks v2 use different door props at different positions, so use the set matching your map.

    <Note>
      On FM Fleeca Banks v2 the vault opens through the door system, so the six `fm-*-vault` doors are **required** — without them the vault never opens after the panel hack. On gabz the vault is animated by the script and needs no door entry.
    </Note>

    <Tabs>
      <Tab title="ox_doorlock">
        Set `cfg.auto_insert_doors = true` in `shared/config.lua` and the resource will insert the door set for your detected map 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 the entries for your map into `qb-doorlock/config/locations.lua` (inside `Config.DoorList`) and restart `qb-doorlock`.

        **FM Fleeca Banks v2:**

        ```lua theme={null}
        Config.DoorList['fm-harmony-reception'] = {
            objHash = 159592337,
            objCoords  = vec3(1173.33447265625, 2710.978759765625, 37.164787292480),
            textCoords = vec3(1173.33447265625, 2710.978759765625, 37.164787292480),
            objYaw = 0, locked = true, pickable = false, distance = 2
        }
        Config.DoorList['fm-harmony-vault'] = {
            objHash = -219621528,
            objCoords  = vec3(1174.5103759765626, 2716.89013671875, 38.389808654785),
            textCoords = vec3(1174.5103759765626, 2716.89013671875, 38.389808654785),
            objYaw = 0, locked = true, pickable = false, distance = 2
        }
        Config.DoorList['fm-hawick-reception'] = {
            objHash = 159592337,
            objCoords  = vec3(-350.68939208984, -54.407382965088, 48.113330841064),
            textCoords = vec3(-350.68939208984, -54.407382965088, 48.113330841064),
            objYaw = 161, locked = true, pickable = false, distance = 2
        }
        Config.DoorList['fm-hawick-vault'] = {
            objHash = -219621528,
            objCoords  = vec3(-353.73843383789, -59.606254577637, 49.338352203369),
            textCoords = vec3(-353.73843383789, -59.606254577637, 49.338352203369),
            objYaw = 161, locked = true, pickable = false, distance = 2
        }
        Config.DoorList['fm-legion-reception'] = {
            objHash = 159592337,
            objCoords  = vec3(150.05862426758, -1045.23486328125, 28.444828033447),
            textCoords = vec3(150.05862426758, -1045.23486328125, 28.444828033447),
            objYaw = 160, locked = true, pickable = false, distance = 2
        }
        Config.DoorList['fm-legion-vault'] = {
            objHash = -219621528,
            objCoords  = vec3(146.91809082031, -1050.37890625, 29.669849395752),
            textCoords = vec3(146.91809082031, -1050.37890625, 29.669849395752),
            objYaw = 160, locked = true, pickable = false, distance = 2
        }
        Config.DoorList['fm-ocean-reception'] = {
            objHash = 159592337,
            objCoords  = vec3(-2958.3439941406, 484.50921630859, 14.774741172791),
            textCoords = vec3(-2958.3439941406, 484.50921630859, 14.774741172791),
            objYaw = 268, locked = true, pickable = false, distance = 2
        }
        Config.DoorList['fm-ocean-vault'] = {
            objHash = -219621528,
            objCoords  = vec3(-2952.4812011719, 483.11196899414, 15.999762535095),
            textCoords = vec3(-2952.4812011719, 483.11196899414, 15.999762535095),
            objYaw = 268, locked = true, pickable = false, distance = 2
        }
        Config.DoorList['fm-dperro-reception'] = {
            objHash = 159592337,
            objCoords  = vec3(-1209.2384033203, -333.66687011719, 36.857788085938),
            textCoords = vec3(-1209.2384033203, -333.66687011719, 36.857788085938),
            objYaw = 207, locked = true, pickable = false, distance = 2
        }
        Config.DoorList['fm-dperro-vault'] = {
            objHash = -219621528,
            objCoords  = vec3(-1207.6163330078, -339.47152709961, 38.082809448242),
            textCoords = vec3(-1207.6163330078, -339.47152709961, 38.082809448242),
            objYaw = 207, locked = true, pickable = false, distance = 2
        }
        Config.DoorList['fm-pinkcage-reception'] = {
            objHash = 159592337,
            objCoords  = vec3(314.39031982422, -283.60040283203, 53.241542816162),
            textCoords = vec3(314.39031982422, -283.60040283203, 53.241542816162),
            objYaw = 160, locked = true, pickable = false, distance = 2
        }
        Config.DoorList['fm-pinkcage-vault'] = {
            objHash = -219621528,
            objCoords  = vec3(311.25155639648, -288.74560546875, 54.466564178467),
            textCoords = vec3(311.25155639648, -288.74560546875, 54.466564178467),
            objYaw = 160, locked = true, pickable = false, distance = 2
        }
        ```

        **Gabz:**

        ```lua theme={null}
        Config.DoorList['legion-gate'] = {
            objHash = -1591004109,
            objCoords  = vec3(150.31129455566, -1047.574584961, 29.678188323974),
            textCoords = vec3(150.31129455566, -1047.574584961, 29.678188323974),
            objYaw = 160, locked = true, pickable = false, distance = 2
        }
        Config.DoorList['legion-backdoor'] = {
            objHash = -147325430,
            objCoords  = vec3(144.35862731934, -1043.1907958984, 29.529350280762),
            textCoords = vec3(144.35862731934, -1043.1907958984, 29.529350280762),
            objYaw = 250, locked = true, pickable = false, distance = 2
        }
        Config.DoorList['legion-reception'] = {
            objHash = -147325430,
            objCoords  = vec3(145.36862182618, -1041.9357910156, 29.525213241578),
            textCoords = vec3(145.36862182618, -1041.9357910156, 29.525213241578),
            objYaw = 70, locked = true, pickable = false, distance = 2
        }
        Config.DoorList['hawick-gate'] = {
            objHash = -1591004109,
            objCoords  = vec3(-350.3953552246, -56.742294311524, 49.346691131592),
            textCoords = vec3(-350.3953552246, -56.742294311524, 49.346691131592),
            objYaw = 161, locked = true, pickable = false, distance = 2
        }
        Config.DoorList['hawick-backdoor'] = {
            objHash = -147325430,
            objCoords  = vec3(-356.4246520996, -52.464557647706, 49.197853088378),
            textCoords = vec3(-356.4246520996, -52.464557647706, 49.197853088378),
            objYaw = 251, locked = true, pickable = false, distance = 2
        }
        Config.DoorList['hawick-reception'] = {
            objHash = -147325430,
            objCoords  = vec3(-355.43701171875, -51.191829681396, 49.193714141846),
            textCoords = vec3(-355.43701171875, -51.191829681396, 49.193714141846),
            objYaw = 71, locked = true, pickable = false, distance = 2
        }
        Config.DoorList['harmony-gate'] = {
            objHash = -1591004109,
            objCoords  = vec3(1172.2911376954, 2713.0883789062, 38.398147583008),
            textCoords = vec3(1172.2911376954, 2713.0883789062, 38.398147583008),
            objYaw = 0, locked = true, pickable = false, distance = 2
        }
        Config.DoorList['harmony-backdoor'] = {
            objHash = -147325430,
            objCoords  = vec3(1179.3896484375, 2711.0239257812, 38.249309539794),
            textCoords = vec3(1179.3896484375, 2711.0239257812, 38.249309539794),
            objYaw = 90, locked = true, pickable = false, distance = 2
        }
        Config.DoorList['harmony-reception'] = {
            objHash = -147325430,
            objCoords  = vec3(1178.8739013672, 2709.4978027344, 38.245170593262),
            textCoords = vec3(1178.8739013672, 2709.4978027344, 38.245170593262),
            objYaw = 270, locked = true, pickable = false, distance = 2
        }
        Config.DoorList['dperro-reception'] = {
            objHash = -147325430,
            objCoords  = vec3(-1214.8493652344, -334.84872436524, 37.938171386718),
            textCoords = vec3(-1214.8493652344, -334.84872436524, 37.938171386718),
            objYaw = 117, locked = true, pickable = false, distance = 2
        }
        Config.DoorList['dperro-backdoor'] = {
            objHash = -147325430,
            objCoords  = vec3(-1214.6197509766, -336.44323730468, 37.942310333252),
            textCoords = vec3(-1214.6197509766, -336.44323730468, 37.942310333252),
            objYaw = 297, locked = true, pickable = false, distance = 2
        }
        Config.DoorList['dperro-gate'] = {
            objHash = -1591004109,
            objCoords  = vec3(-1207.3544921875, -335.07723999024, 38.091148376464),
            textCoords = vec3(-1207.3544921875, -335.07723999024, 38.091148376464),
            objYaw = 207, locked = true, pickable = false, distance = 2
        }
        Config.DoorList['ocean-gate'] = {
            objHash = -1591004109,
            objCoords  = vec3(-2956.1740722656, 485.42306518554, 16.007200241088),
            textCoords = vec3(-2956.1740722656, 485.42306518554, 16.007200241088),
            objYaw = 268, locked = true, pickable = false, distance = 2
        }
        Config.DoorList['ocean-backdoor'] = {
            objHash = -147325430,
            objCoords  = vec3(-2958.541015625, 478.41958618164, 15.85836315155),
            textCoords = vec3(-2958.541015625, 478.41958618164, 15.85836315155),
            objYaw = 358, locked = true, pickable = false, distance = 2
        }
        Config.DoorList['ocean-reception'] = {
            objHash = -147325430,
            objCoords  = vec3(-2960.0437011718, 479.0002746582, 15.854226112366),
            textCoords = vec3(-2960.0437011718, 479.0002746582, 15.854226112366),
            objYaw = 178, locked = true, pickable = false, distance = 2
        }
        Config.DoorList['pinkcage-gate'] = {
            objHash = -1591004109,
            objCoords  = vec3(314.64379882812, -285.94006347656, 54.47490310669),
            textCoords = vec3(314.64379882812, -285.94006347656, 54.47490310669),
            objYaw = 160, locked = true, pickable = false, distance = 2
        }
        Config.DoorList['pinkage-reception'] = {
            objHash = -147325430,
            objCoords  = vec3(309.69915771484, -280.30297851562, 54.321926116943),
            textCoords = vec3(309.69915771484, -280.30297851562, 54.321926116943),
            objYaw = 70, locked = true, pickable = false, distance = 2
        }
        ```
      </Tab>
    </Tabs>
  </Step>

  <Step title="(Optional) Tune the police gate">
    By default the contract refuses to start unless `≥ 2` on-duty `police` jobs are online. Edit `shared/contract.lua`:

    ```lua theme={null}
    requiredPolice = { jobs = { 'police' }, count = 2 }
    ```

    Set `count = 0` (or remove the field) to disable the gate for testing.
  </Step>

  <Step title="Verify in-game">
    1. Use a `heist_tablet` to open the dashboard.
    2. The **Fleeca Bank Heist** listing should drip into the marketplace within the configured interval (3 min default).
    3. Buy it for 2,500 VICE. The slot fills.
    4. Pick a branch from the active-slot dropdown and press **Start**. With debug off you'll need 2 cops online; with debug on (`cfg.debug = true` in `shared/config.lua`) the gate is bypassed.

    <Tip>
      Need it to appear instantly? Lower `config.rotation.dripIntervalMs` in `cc_heistcontracts/shared/config.lua` to `5 * 1000` and restart `cc_heistcontracts`.
    </Tip>
  </Step>
</Steps>

## Customising loot

`shared/rewards.lua` defines the **global loot table** — the totals that get distributed across all lockers and all trolleys when `cfg.use_global_loot_table = true` (the default).

```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 } },
    },
}
```

The rolled total is **split evenly across the units** in that category — if `black_money` rolls 1,500 and there are 3 lockers, each locker contains 500. Set `use_global_loot_table = false` in `shared/config.lua` and define loot per-unit inside each branch file under `shared/locations/`.

## Disabling a branch

Remove (or comment out) the matching entry in `shared/contract.lua`'s `locations` array. The default six branches are:

* `pinkcage` — Pinkcage Branch
* `delperro` — Del Perro Branch
* `greatocean` — Great Ocean Hwy Branch
* `harmony` — Harmony Branch
* `hawick` — Hawick Branch
* `legionsquare` — Legion Branch
