> For the complete documentation index, see [llms.txt](https://docs.rainmad.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.rainmad.com/resources/bank-truck-robbery-4-in-1/configuration.md).

# Configuration

Everything lives in `rm_banktruckrobbery/cfg.lua` and the three files under `rm_banktruckrobbery/data/` .

## Locale & bridges

```lua
cfg.locale = 'en'            -- locales/<locale>.json
cfg.bridge = {
    framework    = 'auto',   -- 'auto' | 'qb' | 'esx'
    target       = 'auto',   -- 'auto' | 'ox_target' | 'qb-target' | false
    minigame     = 'ox_lib', -- device placement check; false = no check
    notification = 'ox_lib',
    textUI       = 'ox_lib',
    vehiclelock  = 'auto',   -- hands the truck's keys to whoever kills the driver
    dispatch     = false,    -- police alerts; see bridge/dispatch/ for adapters
}
```

Every value is the name of an open adapter file under `rm_banktruckrobbery/bridge/<category>/`; the annotations in `cfg.lua` list the full set. `'auto'` picks the first matching resource that is running, `false` disables the category (with `target = false` the NPC uses a keypress prompt instead). Copy an adapter to integrate a resource we don't cover.

Only the placement check is wired to a minigame. To gate one device behind its own check, assign it by item name in the adapter:

```lua
bridge.minigame[cfg.items.c4] = function() return lib.skillCheck('hard') end
```

## Police, dispatch & black money

```lua
cfg.police = {
    requiredCount = 0,    -- minimum on-duty police before a truck spawns; 0 disables
    jobs = { 'police', 'sasp', 'bcso', 'sheriff' },
    countMethod = 'fast', -- 'fast' = event-cached; 'scan' = iterate players
}

cfg.driverKillDispatchChance = 0   -- % chance to alert when a player kills the driver
cfg.safeOpenedDispatchChance = 100 -- % chance to alert when the rear safe opens

cfg.blackMoney = {
    type = 'item',         -- 'item' | 'account' | 'markedbills'
    item = 'black_money',
    account = 'black_money',
    metadataKey = 'worth', -- 'markedbills': metadata key holding a bill's value
}
```

`cfg.police.jobs` is both the spawn gate and the job list dispatch alerts are sent to. On QBCore a job whose `type` is `'leo'` counts even if it isn't named there.

`cfg.blackMoney` decides what `moneyType = 'black_money'` means in the reward and price files: a plain item whose count is the value, a framework account, or marked-bill items whose value sits in metadata (change is given back automatically).

## Spawning

```lua
cfg.autoTruckSpawn = false          -- trucks appear on their own; the NPC stops selling locations
cfg.truckAutoSpawnInterval = 10     -- minutes between auto spawns
cfg.maxNumberOfTrucksNotRobbed = 1  -- no new truck spawns while this many are unrobbed
cfg.truckLifetime = 60              -- minutes an unrobbed truck stays in the world; 0 disables
cfg.manualTruckSpawnCooldown = 0    -- minutes between location buys, across all players
cfg.serversideSpawn = false         -- build the truck server-side instead of via a player's client
```

With `autoTruckSpawn` off, a truck is spawned when a player buys its location. If one is already out there, the buyer is pointed at that truck instead of a new one.

`truckLifetime` is a cleanup backstop. The crew is spawned with the engine's reclaim disabled so the truck survives driving across the map with nobody near it; without a cap, one that nobody ever robs would stay for the rest of the session. It only culls once the location has expired for everyone who bought it and no player is close enough to own the vehicle, so it cannot take a truck out from under someone chasing it.

`serversideSpawn` is sturdier against a player disconnecting mid-spawn. It needs the model's vehicle type, which the first spawn reads off a client and the server then caches; `cfg.truckVehicleType` is only the fallback for when that read fails.

## The truck and its crew

```lua
cfg.truckModel = `stockade`
cfg.truckPassengerModel = `mp_m_securoguard_01`
cfg.truckPassengerWeapon = `WEAPON_MICROSMG`
cfg.truckPassengerHealth = 200
cfg.truckPassengerArmor = 100

cfg.guardCombatRadius = 60.0  -- how far a guard that has left the truck looks for a target
cfg.truckAlertDuration = 45   -- seconds the truck keeps driving hard after the last trouble
```

Health and armour are handed out once, when a guard spawns. A wounded guard stays wounded.

`truckAlertDuration` is why the truck doesn't calm down the moment you break line of sight. Anyone who damages the truck or a guard is also recorded for the rest of the job, along with everyone riding in their vehicle, so the crew attacks those players rather than sweeping for whoever happens to be standing nearby.

### Speech

```lua
cfg.guardSpeech = {
    enabled = true,
    breach = { 'GENERIC_CURSE_MED', 'CHALLENGE_THREATEN', 'GENERIC_INSULT_HIGH' },
    combat = { 'GENERIC_WAR_CRY', 'GENERIC_CURSE_HIGH', 'GENERIC_INSULT_HIGH' },
    cooldown = 6, -- seconds a guard stays quiet after a line
}
```

The rear guards react while someone works the doors open, and call out when they pick a new target after getting out.

{% hint style="info" %}
These are ambient speech contexts and they belong to the ped model's voice, not to the game at large. A context the model doesn't carry plays nothing at all rather than erroring, so changing `cfg.truckPassengerModel` may mean revisiting these lists. Set `enabled = false` to keep them quiet.
{% endhint %}

## Breaking in

```lua
cfg.drillingSpeed = 0.03      -- progress per frame, out of 100, while the drill is on a hinge
cfg.drillingDistance = 0.3    -- metres the drill bit may be from a hinge and still count

cfg.c4DetonationDuration = 10 -- seconds
cfg.hackingDuration = 20      -- seconds
cfg.gassingDuration = 30      -- seconds

cfg.rewardCollectingDuration = 20 -- seconds at the open safe before it pays out
cfg.showLocationDuration = 5      -- minutes a bought location stays on the GPS
cfg.cooldownPerPlayer = 5         -- minutes a player is locked out after opening a safe
```

Drilling is the only method that leaves the rear guards alive and shooting; hacking does too. A gassing or an explosion kills them on the way in.

`cooldownPerPlayer` blocks both taking a new job and collecting from someone else's robbed truck.

## Rewards

```lua
cfg.truckReward = {
    money = { 10000, 25000 }, -- a number, or a { min, max } range
    moneyType = 'cash',       -- 'cash' | 'money' | 'black_money'
    items = {
        chance = 0,           -- % chance the item list is handed out at all; 0 = never
        list = {
            ['goldbar'] = { chance = 50, amount = { 1, 10 } },
        },
    },
}

cfg.enableMultiplePersonCollect = true
```

With multi-person collect on, the timer starts with the first collector and the money splits evenly between everyone who joined before it ran out. The item list, if it rolls, goes to one of them at random.

## Data files

* **`data/npcs.lua`**: the mission NPCs (model, coords, blip) and how long the NPC takes to look up a location.
* **`data/prices.lua`**: the item names, the buy menu (`cfg.prices.buy`), the location price (`cfg.prices.locationInfo`), the purchase cap (`cfg.prices.maxBuyQuantity`) and `cfg.deleteItemOnUse`. Set `cfg.prices.buy` to `false` or an empty table to hide the shop. Any `moneyType` accepts `'cash'` or `'black_money'`.
* **`data/offsets.lua`**: where the drill hinges sit on the truck, and the attach positions and props for the money crates and the three devices. Uncommenting the extra hinge offsets adds more to drill through.

## Optional blocks

Both ship commented out in `cfg.lua`.

```lua
cfg.requiredItemsForManualSpawn = {
    ['bandage'] = { label = 'Bandage', count = 1, remove = true },
}
```

Items a player must hold to buy a location. `remove = false` checks without taking.

```lua
cfg.drivingRules = {
    safe = { style = 1074284731, speed = 15.0 },
    fast = { style = 1074268257, speed = 20.0 },
}
```

How the truck drives. `safe` is its normal route; it switches to `fast` when a guard opens fire, and stays on `fast` for good once the driver is killed.
