# FAQs
Source: https://docs.projectx.gg/faqs
Frequently asked questions about Project X resources
Scripts that use the Project X Bridge expose an open source client file at `opensource/client/client.lua`. Inside this file there is a minigame callback where each robbery step is mapped to a minigame export. You can swap any step to a different minigame resource by editing that file.
You can also return `true` directly for any step to skip it entirely.
Since the file is fully open source, no escrow access is needed to make these changes.
Our scripts support the following frameworks by default:
* [Qbox](https://github.com/Qbox-project)
* QBCore
* ESX
Since all of our scripts are 50% open source, any framework can be easily integrated using the open source functions!
Bridge-based scripts support the following inventory systems. Set `Inventory` to `'auto'` in the [bridge config](/resources/bridge/installation) to detect automatically, or set the matching config value manually:
| Config value | Inventory |
| ------------ | ---------------------------------------------------------------------- |
| `ox` | [ox\_inventory](https://github.com/CommunityOx/ox_inventory) |
| `qb` | [qb-inventory](https://github.com/qbcore-framework/qb-inventory) |
| `ps` / `lj` | ps-inventory / lj-inventory |
| `codem` | [CodeM Inventory](https://codem.tebex.io/package/5900973) |
| `origen` | [Origen Inventory](https://www.origennetwork.store/package/5881161) |
| `tgiann` | [Tgiann Inventory](https://www.tgiann.com/en/package/6273000) |
| `ak47` | [Menan AK 47 Inventory](https://menanak47.tebex.io/package/6436604) |
| `jpr` | [JP Resources Inventory](https://jpresources.tebex.io/package/7028434) |
| `one` | One Inventory (`one_inventory`) |
| `esx` | ESX default inventory |
| `other` | Custom — edit the open source inventory functions in the bridge |
Since all of our scripts are 50% open source, any inventory system can also be integrated manually using the open source functions.
Our scripts support the following interaction systems by default:
* [ox\_target](https://github.com/CommunityOx/ox_target)
* [qb-target](https://github.com/qbcore-framework/qb-target)
* [World Interact](https://github.com/darktrovx/interact)
* Drawtext
Since all of our scripts are 50% open source, any interaction system can be easily integrated using the open source functions!
Bridge-based scripts support the following XP systems. Set `XPSystem` to `'auto'` in the [bridge config](/resources/bridge/installation) to detect automatically:
* [Project X XP](/resources/xp/installation) (`projectx-xp`)
* [pickle\_xp](https://pickle.tebex.io)
* [sd-levels](https://github.com/sd-scripts/sd-levels)
* [cw-rep](https://github.com/cw-scripts/cw-rep)
* OT\_skills
Config values: `'projectx'`, `'pickle'`, `'sd-levels'`, `'cw-rep'`, `'ot_skills'`, or `'none'`.
If your system is not listed, you can integrate it using the open source functions in the bridge.
Bridge-based scripts support the following evidence systems for fingerprint drops. Set `Evidence` to `'auto'` in the [bridge config](/resources/bridge/installation) to detect automatically:
* qbx\_police / qb-police
* [Wasabi Evidence](https://www.wasabiscripts.com)
* [Snipe Evidence](https://github.com/snipe-scripts/snipe-evidence)
* [D Labs Evidence](https://github.com/d-labs-evidence)
* [TK Evidence](https://tkscripts.com)
* dusa\_evidence
* r14-evidence
* Kartik Evidence (`kartik-evidence`)
If no evidence system is detected or configured, fingerprint drops are disabled.
Bridge-based scripts support **30+ dispatch systems**. Set `Dispatch` to `'auto'` in the [bridge config](/resources/bridge/installation) for automatic detection, or set the config value manually:
* [CodeSign Dispatch](https://codesign.pro/product/4206357) (`cd`)
* CodeSign 3D Dispatch (`cd3d`)
* [PS Dispatch](https://github.com/Project-Sloth/ps-dispatch) (`ps`)
* [FD Dispatch](https://felis.gg/product/dispatch) (`fd`)
* [Outlaw Dispatch](https://github.com/thelindat/linden_outlawalert) (`outlaw`)
* [CodeM Dispatch](https://codem.tebex.io/package/6354183) (`codem`)
* [Five-Dispatch](https://github.com/cinquina/five-dispatch) (`five-dispatch`)
* [QF MDT Dispatch](https://wiki.qfdevelopers.com/scripts/editor-14/installation) (`qf`)
* [ATY Dispatch](https://github.com/atiysuu/aty_dispatch) (`aty`)
* [ZAT MDT](https://zatv.tebex.io/package/6559736) (`zat-mdt`)
* [Opto Dispatch](https://github.com/ErrorMauw/op-dispatch) (`opto`)
* [Kartik MDT](https://kartik-scripts.tebex.io/package/6652876) (`kartik`)
* [Brutal Police Job](https://brutal-scripts.tebex.io/package/5805815) (`brutal`)
* [Origen Police](https://www.origennetwork.store/package/5884106) (`origen`)
* [TK Dispatch](https://tkscripts.com/product/dispatch) (`tk`)
* [Rcore Dispatch](https://store.rcore.cz/package/5789351) (`rcore`)
* [LB Tablet](https://lbscripts.com/package/tablet) (`lb`)
* [Redutzu MDT](https://store.redutzu.com/package/6242151) (`redutzu`)
* [LG Mods Dispatch](https://store.lgmods.co.uk/package/6885074) (`lg`)
* VX MDT (`vx`)
* [L2S Dispatch](https://l2s.dev/post/dispatch-script) (`l2s`)
* [Sonoran CAD](https://sonorancad.com/) (`sonoran`)
* pScripts MDT v1 (`piotreqv1`)
* [pScripts MDT v2](https://tebex.pscripts.store/product/6632004) (`piotreqv2`)
* Pixel Precision MDT (`pp-mdt`)
* [Core Dispatch](https://www.c8re.store/package/4462305) (`core`)
* Oxide Dispatch (`oxide`)
* [LoveRP Emergency Dispatch](https://shop.loverp-scripts.de/package/4887641) (`emergencydispatch`)
* [Wasabi MDT](https://www.wasabiscripts.com/product/6989465) (`wasabimdt`)
* [Next Scripts 5M Dispatch](https://github.com/nextscripts-5m/dispatch) (`nextscripts`)
* [Kibra Dispatch](https://0resmon.tebex.io/package/kibra-dispatch-system-open-source-0r-lib-escrowed) (`kibra`)
* [Imperial CAD](https://imperialcad.app/) (`imperial`)
For unsupported dispatch systems, set `Dispatch` to `'customsv'` or `'customcl'` and edit the open source dispatch functions in the bridge.
Scripts that do not use the bridge (such as House Robbery V2) configure dispatch in their own config file instead.
If you don't want your players to use explosive items, you can create a new item called 'stickybomb' for example and place it in your items.lua file instead of weapons.
After doing so, switch out the sticky bomb weapon to the new item you created in your config's Config.Items
Support for our free scripts (such as tasks, burner phone, masks, sellshop, and XP) is available in our [Discord server](https://discord.gg/projectxdev) through the **#📚・𝗙𝗿𝗲𝗲-𝗦𝘂𝗽𝗽𝗼𝗿𝘁** channel. Please do not open tickets for free scripts or request support for paid scripts in that channel.
Support for paid scripts is available through our [Discord server](https://discord.gg/projectxdev). Simply open a support ticket and provide your Tebex transaction ID to receive assistance.
This error is typically caused by your file transfer application, most commonly with [FileZilla](https://filezilla-project.org/).
**Fix for FileZilla users:** Go to Transfer > Transfer Type > Binary at the top left menu.
If that doesn't work, try switching to a different FTP client such as [WinSCP](https://winscp.net/eng/download.php).
If you purchased the wrong version (for example, you wanted Fleeca for the default GTA 5 map but bought the FM version), we can help:
* **Within 2 weeks:** Open a ticket and we'll exchange it for free
* **After 2 weeks:** We can offer you 40% off the version you want
Simply open a ticket in our [Discord server](https://discord.gg/projectxdev) and we'll generate a code for you.
Unfortunately, we cannot provide the assets again as we don't have the tools to remove them from your previous account. Please contact Tebex or CFX.re directly for more information about what can be done in your situation.
The subscription lasts one month. If you don't renew it, you'll lose access to the assets, but you won't lose your files or configuration. The scripts simply won't start until the subscription is renewed.
You can cancel your subscription using the [Tebex Payment History Page](https://checkout.tebex.io/payment-history). After logging in, go to the Subscription tab and select the subscription you want to cancel.
Yes, we offer several discount options:
* **10% off** on 3+ products
* **15% off** on 6+ products
* **25% off** for loyal customers on any future purchase
To claim bulk discounts, open a presale ticket in our [Discord server](https://discord.gg/projectxdev) and we'll generate a code for you.
Also, check our **📢・𝗔𝗻𝗻𝗼𝘂𝗻𝗰𝗲𝗺𝗲𝗻𝘁𝘀** channel in [Discord](https://discord.gg/projectxdev) for any active sales.
The Loyal Customer role is granted to customers who have either:
* Purchased all of our scripts (at least one version of each)
* Purchased the All Scripts Bundle
Loyal customers receive **25% off** any future purchase.
**How to claim:** Join our [Discord server](https://discord.gg/projectxdev) and use `/claim` in the **#🛒・𝗧𝗲𝗯𝗲𝘅-𝗖𝗹𝗮𝗶𝗺** channel. You can also use `/loyalcheck` to see which scripts you need to become a loyal customer.
If you want to purchase all remaining scripts at once, open a ticket and we'll give you 25% off your purchase!
# Information
Source: https://docs.projectx.gg/index
Welcome to Project X Documentation - Find installation guides, exports, solutions and more
## Welcome to Project X
Project X is the ultimate destination for premium FiveM crime scripts, crafted to elevate your roleplaying experience. Whether you're looking to enhance your server with immersive features or offer a range of crime scripts from low to high-end for seamless progression, we have everything you need.
Join thousands of satisfied server owners
Multilingual support team ready to help
Lightning-fast scripts at 0.00ms
## About This Documentation
This documentation is your comprehensive guide to installing, configuring, and getting the most out of your Project X resources. Here you will find everything you need to successfully set up our scripts on your FiveM server.
### What You Will Find
Step-by-step instructions to get each resource up and running on your server
Configure framework, inventory, dispatch, and more in one place
Complete list of available exports for developers to integrate with other scripts
Supported inventories, dispatch systems, evidence, and XP systems
Answers to common questions and troubleshooting tips
## How to Navigate
Use the **sidebar on the left** to browse through our resources. Each resource has its own section containing:
* **Installation** - Dependencies, setup steps, and configuration
* **Exports** - Client and server exports for developers
* **FAQs** - Resource-specific questions and answers
## Need Help?
Check our frequently asked questions
Join our community for 24/7 support
# Commands
Source: https://docs.projectx.gg/resources/ammunation-robbery-default/commands
Admin commands for the Default Ammunation Robbery resource
## Admin Commands
**Usage**: `/projectxammunation`
**Permission**: Admin (configurable via `CheckPerms` in the bridge)
**Description**: Resets the nearest Ammunation location within 50 units of your position.
To reset a specific location programmatically, use the `Reset(location)` export. See the [Exports](/resources/ammunation-robbery-default/exports) page.
# Configuration
Source: https://docs.projectx.gg/resources/ammunation-robbery-default/configuration
Full reference for all configuration options in the Default Ammunation Robbery resource
## config/config.lua
The default variant uses the same configuration structure as the other Ammunation robbery scripts but targets vanilla GTA Ammunation interiors. See the [FM Ammunation Configuration](/resources/ammunation-robbery-fm/configuration) page for the full field reference.
### Main Settings
Shows polyzones created inside the game.
Disables all minigames for testing.
Requires a `bag` item to loot crates.
Minimum police required online. Set to `0` to disable.
Maximum simultaneous active robberies. Set to `0` to disable.
Disables the loud approach path.
Disables the silent approach path.
***
### Cooldowns & Limits
When `true`, all locations share one cooldown after a robbery.
Cooldown duration in minutes.
***
### Required Items
```lua theme={null}
Items = {
["Circuit"] = "x_circuittester",
["TrojanUSB"] = "x_trojanusb",
["TrojanUSB2"] = "x_trojanusb2",
["Lockpick"] = "advancedlockpick",
["Bag"] = "bag",
["Key"] = "ammunation_key",
["Phone"] = "x_phone",
}
```
***
### Store Locations
* `Config.ShootingRanges`
* `Config.GunStores`
* `Config.Stores`
Reward tables: `Config.RegisterGunStores`, `Config.RegisterShootingRanges`, `Config.Loot`, and `Config.Props`.
***
### Logs
Configured in `config/logs.lua`.
# Exports
Source: https://docs.projectx.gg/resources/ammunation-robbery-default/exports
Server-side exports available for the Default Ammunation Robbery resource
## Server Exports
All exports require a valid location key from `Config.Stores`.
### Reset
```lua theme={null}
exports['projectx-ammunationrobbery-default']:Reset('PillboxHill')
```
**Returns** — `true` if the location exists and was reset successfully
***
### IsRobberyInProgress
```lua theme={null}
local active = exports['projectx-ammunationrobbery-default']:IsRobberyInProgress('PillboxHill')
```
**Returns** — `true` if a robbery is in progress at that location, `false` otherwise
***
### GetActiveRobberyCount
```lua theme={null}
local count = exports['projectx-ammunationrobbery-default']:GetActiveRobberyCount()
```
**Returns** — `count` (number) total active robberies
# FAQs
Source: https://docs.projectx.gg/resources/ammunation-robbery-default/faqs
Frequently asked questions about the Default Ammunation Robbery resource
## General Questions
QBCore, Qbox, and ESX through the Project X Bridge.
No. This variant uses the default GTA Ammunation interiors and does not require a third-party map.
Use `/projectxammunation` or:
```lua theme={null}
exports['projectx-ammunationrobbery-default']:Reset('PillboxHill')
```
Edit `opensource/client/client.lua`. See the [Open Source](/resources/ammunation-robbery-default/opensource) page.
## Troubleshooting
Verify `boii_minigames`, `bl_ui`, `pure-minigames`, and `SN-Hacking` are started before the script.
# Installation
Source: https://docs.projectx.gg/resources/ammunation-robbery-default/installation
Step by step instructions to install the Default Ammunation Robbery resource
## Installation Steps
Verify all dependencies below are started **before** this script in your `server.cfg`.
Download ox\_lib
Required Project X Bridge
This variant uses the default GTA Ammunation interiors — no third-party map is required.
Download the minigames zip and place each resource into your standalone or dependencies folder.
Download and place in your standalone or minigames folder
Make sure the minigames are **not** in the same folder as the robbery script.
Extract the script from the zip file and place it into your scripts folder.
Add the required items and their images to your inventory resource. See the [items section](#items-required) below for the full list.
Item images done by [Artwork Inventory](https://discord.gg/Z2awpnXKdw) - Use code **ProjectX** for 10% off!
Open `config/config.lua` and adjust the settings to match your server.
```cfg theme={null}
ensure ox_lib
ensure projectx-bridge
ensure boii_minigames
ensure bl_ui
ensure pure-minigames
ensure SN-Hacking
ensure projectx-ammunationrobbery-default
```
## Items Required
### Items Required from Outside the Robbery
* `ammunation_key`
### Items Required from Shop/Black Market
* `x_phone`
* `x_circuittester`
* `x_trojanusb`
* `advancedlockpick`
* `bag`
The rest of the items are obtained within the robbery itself.
### Item Configuration
```lua theme={null}
["bag"] = { label = "Duffel Bag", weight = 250, stack = false, close = false, description = "Duffel bag", client = { image = "bag.png" } },
["x_trojanusb"] = { label = "X Trojan USB", weight = 125, stack = false, close = false, description = "?????????", client = { image = "x_trojanusb.png" } },
["x_trojanusb2"] = { label = "X Encrypted Trojan", weight = 125, stack = false, close = false, description = "?????????", client = { image = "x_trojanusb2.png" } },
["x_circuittester"] = { label = "X Circuit Tester", weight = 125, stack = false, close = false, description = "?????????", client = { image = "x_circuittester.png" } },
["ammunation_key"] = { label = "Ammunation Key", weight = 125, stack = false, close = false, description = "?????????", client = { image = "ammunation_key.png" } },
["x_phone"] = { label = "X Phone", weight = 125, stack = false, close = false, description = "?????????", client = { image = "x_phone.png" } },
["advancedlockpick"] = { label = "Advanced Lockpick", weight = 500, stack = true, close = true, description = "If you lose your keys a lot this is very useful... Also useful to open your beers", client = { image = "advancedlockpick.png" } },
```
```lua theme={null}
['x_phone'] = {['name'] = 'x_phone', ['label'] = 'X Phone', ['weight'] = 50, ['type'] = 'item', ['image'] = 'x_phone.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '?????????'},
['bag'] = {['name'] = 'bag', ['label'] = 'Bag', ['weight'] = 50, ['type'] = 'item', ['image'] = 'bag.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '?????????'},
['x_circuittester'] = {['name'] = 'x_circuittester', ['label'] = 'X Circuit Tester', ['weight'] = 200, ['type'] = 'item', ['image'] = 'x_circuittester.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '????'},
['x_trojanusb'] = {['name'] = 'x_trojanusb', ['label'] = 'X Trojan USB', ['weight'] = 200, ['type'] = 'item', ['image'] = 'x_trojanusb.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '????'},
['x_trojanusb2'] = {['name'] = 'x_trojanusb2', ['label'] = 'X Encrypted Trojan', ['weight'] = 200, ['type'] = 'item', ['image'] = 'x_trojanusb2.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '????'},
['ammunation_key'] = {['name'] = 'ammunation_key', ['label'] = 'Ammunation Key', ['weight'] = 200, ['type'] = 'item', ['image'] = 'ammunation_key.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '????'},
['advancedlockpick'] = {['name'] = 'advancedlockpick', ['label'] = 'Advanced Lockpick', ['weight'] = 500, ['type'] = 'item', ['image'] = 'advancedlockpick.png', ['unique'] = false, ['useable'] = true, ['shouldClose'] = true, ['combinable'] = nil, ['description'] = 'If you lose your keys a lot this is very useful... Also useful to open your beers'},
```
# Open Source
Source: https://docs.projectx.gg/resources/ammunation-robbery-default/opensource
Open source files available for customization in the Default Ammunation Robbery resource
## opensource/client/client.lua
Each robbery step triggers the `projectx-ammunationrobbery-default:client:Minigames` callback.
```lua theme={null}
lib.callback.register('projectx-ammunationrobbery-default:client:Minigames', function(Step)
local p = promise.new()
if Step == "Fusebox" then
if not exports['projectx-bridge']:MinigameCheck("boii_minigames") then p:resolve(false) return Citizen.Await(p) end
exports['boii_minigames']:wire_cut({style = 'default', timer = 60000}, function(success)
p:resolve(success)
end)
elseif Step == "Register" then
if not exports['projectx-bridge']:MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:CircleShake(1, 50, 2)
p:resolve(success)
elseif Step == "Computer1" then
if not exports['projectx-bridge']:MinigameCheck("boii_minigames") then p:resolve(false) return Citizen.Await(p) end
exports['boii_minigames']:chip_hack({style = 'default', loading_time = 8000, chips = 2, timer = 20000}, function(success)
p:resolve(success)
end)
elseif Step == "Computer2" then
if not exports['projectx-bridge']:MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:Untangle(1, {numberOfNodes = 10, duration = 15000})
p:resolve(success)
elseif Step == "GunCrate" then
if not exports['projectx-bridge']:MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:RapidLines(2, 50, 4)
p:resolve(success)
elseif Step == "ExplosivesCrate" then
if not exports['projectx-bridge']:MinigameCheck("boii_minigames") then p:resolve(false) return Citizen.Await(p) end
exports['boii_minigames']:pincode({style = 'default', difficulty = 1, guesses = 10}, function(success)
p:resolve(success)
end)
elseif Step == "ArmorCrate" then
if not exports['projectx-bridge']:MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:CircleProgress(3, 75)
p:resolve(success)
elseif Step == "Timer" then
if not exports['projectx-bridge']:MinigameCheck("boii_minigames") then p:resolve(false) return Citizen.Await(p) end
exports['boii_minigames']:safe_crack({style = 'default', difficulty = 1}, function(success)
p:resolve(success)
end)
elseif Step == "Gun" then
local success = lib.skillCheck({'easy', 'easy', 'medium', 'hard'}, {'w', 'a', 's', 'd'})
p:resolve(success)
elseif Step == "Ammo" then
if not exports['projectx-bridge']:MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:KeySpam(2, 50)
p:resolve(success)
elseif Step == "Keypad" then
if not exports['projectx-bridge']:MinigameCheck("pure-minigames") then p:resolve(false) return Citizen.Await(p) end
local gameData = {totalNumbers = 20, seconds = 20, timesToChangeNumbers = 4, amountOfGames = 1, incrementByAmount = 5}
local success = exports['pure-minigames']:numberCounter(gameData)
p:resolve(success)
elseif Step == "Code" then
if not exports['projectx-bridge']:MinigameCheck("SN-Hacking") then p:resolve(false) return Citizen.Await(p) end
local success = exports['SN-Hacking']:SkillBar({2000, 3000}, 10, 2)
p:resolve(success)
end
return Citizen.Await(p)
end)
```
| Step | Minigame Resource | Function |
| ----------------- | ----------------- | ---------------- |
| `Fusebox` | `boii_minigames` | `wire_cut` |
| `Register` | `bl_ui` | `CircleShake` |
| `Computer1` | `boii_minigames` | `chip_hack` |
| `Computer2` | `bl_ui` | `Untangle` |
| `GunCrate` | `bl_ui` | `RapidLines` |
| `ExplosivesCrate` | `boii_minigames` | `pincode` |
| `ArmorCrate` | `bl_ui` | `CircleProgress` |
| `Timer` | `boii_minigames` | `safe_crack` |
| `Gun` | `ox_lib` | `skillCheck` |
| `Ammo` | `bl_ui` | `KeySpam` |
| `Keypad` | `pure-minigames` | `numberCounter` |
| `Code` | `SN-Hacking` | `SkillBar` |
***
## opensource/server/server.lua
Hooks: `SuccessfulStep(source, location, step)`, `FailedStep(source, location, step)`, `InitialCheck(src, Location, Interaction)`, and `RobberyResetHook(location)`.
# Commands
Source: https://docs.projectx.gg/resources/ammunation-robbery-fm/commands
Admin commands for the FM Ammunation Robbery resource
## Admin Commands
**Usage**: `/projectxammunation`
**Permission**: Admin (configurable via `CheckPerms` in the bridge)
**Description**: Resets the nearest Ammunation location within 50 units of your position. Useful for testing or recovering from a stuck robbery.
**Example**:
```
/projectxammunation
```
This command resets the closest location automatically. To reset a specific location programmatically, use the `Reset(location)` export instead. See the [Exports](/resources/ammunation-robbery-fm/exports) page for details.
# Configuration
Source: https://docs.projectx.gg/resources/ammunation-robbery-fm/configuration
Full reference for all configuration options in the FM Ammunation Robbery resource
## config/config.lua
### Main Settings
Shows polyzones created inside the game. Useful for testing zone placement.
Disables all minigames. Useful for testing the full robbery flow without completing minigame challenges.
The key code used to trigger drawtext interactions. `38` is `[E]` by default.
The size of the drawtext interaction zone.
The default rotation of the drawtext interaction zone. Individual stores can override this in `Config.Stores`.
Spawns networked props server side. Set to `false` to spawn them client side instead.
Spawns networked peds server side. Set to `false` to spawn them client side instead.
Requires players to have a `bag` item in order to loot crates.
Minimum number of police required online before a robbery can be started. Set to `0` to disable.
The jobs that count as police for the `MinimumPolice` check and dispatch alerts.
```lua theme={null}
PoliceJobs = {"police", "fbi"}
```
Requires a minimum number of players nearby to start a robbery.
```lua theme={null}
RequiredPlayersNearby = {amount = 0, radius = 20.0}
```
Set `amount` to `0` or `false` to disable.
Maximum number of Ammunation robberies that can be active at the same time. Set to `0` to disable.
Disables the loud approach path entirely.
Disables the silent approach path entirely.
Disables all particle effects during robberies.
Disables weapon removal during robberies. Only enable this if you use a weapon wheel resource.
***
### Cooldowns & Limits
When `true`, robbing one location puts all Ammunation locations on cooldown. When `false`, each location has its own cooldown.
Cooldown duration in minutes.
Per-player cooldown in minutes after completing a robbery. Set to `0` to disable.
Maximum robberies per server restart, split by location type. Set each value to `0` to disable.
```lua theme={null}
TotalRobberiesPerRestart = {
['ShootingRanges'] = 0,
['GunStores'] = 0,
}
```
Maximum robberies a single player can complete per restart, split by location type. Set each value to `0` to disable.
```lua theme={null}
RobberiesPerPlayer = {
['ShootingRanges'] = 0,
['GunStores'] = 0,
}
```
***
### Skill System
Requires players to meet a minimum level from an integrated XP/skill system before starting a robbery. Must have an XP system configured in the bridge.
Minimum level required to initiate a robbery. Only applies when `SkillSystem` is `true`.
***
### Dispatch
Title shown in the dispatch alert.
Message body shown in the dispatch alert.
Radio code shown in the dispatch alert.
Time in seconds the dispatch alert remains visible. Not all dispatch systems support this.
Blip settings for the dispatch map marker.
```lua theme={null}
Blip = {
Text = 'Ammunation Robbery',
Color = 1,
Sprite = 41,
Scale = 0.8
}
```
Controls which steps trigger dispatch alerts. `Loud` and `Silent` can be enabled independently. Only one of the step-based options should be enabled at a time.
```lua theme={null}
DispatchLocation = {
["Loud"] = true,
["Silent"] = false,
["Register"] = true,
["Keypad"] = false,
["ElectricBox"] = false,
}
```
***
### Bonus Items
Enables or disables bonus item drops at the end of a robbery.
Percentage chance that any bonus item is given at all.
Number of items that can be given from the bonus items table.
Table of possible bonus items. Each entry has a `Name`, `Chance` (%), and `Amount` range.
The total chance across all items needs to add up to 100%.
```lua theme={null}
Items = {
{Name = "x_device", Chance = 30, Amount = {min = 1, max = 1}},
{Name = "x_phone", Chance = 50, Amount = {min = 1, max = 1}},
{Name = "x_stethoscope", Chance = 20, Amount = {min = 1, max = 1}},
}
```
***
### Evidence & Stress
Enables fingerprint evidence drops at the crime scene.
Percentage chance that fingerprint evidence is left behind.
Enables the stress system. Stress is only applied when a minigame is failed.
Percentage chance that stress is applied on a minigame fail.
The minimum and maximum amount of stress applied per failure.
***
### Required Items
Maps logical item names to your inventory item names.
```lua theme={null}
Items = {
["Circuit"] = "x_circuittester",
["TrojanUSB"] = "x_trojanusb",
["TrojanUSB2"] = "x_trojanusb2",
["Lockpick"] = "advancedlockpick",
["Bag"] = "bag",
["Key"] = "ammunation_key",
["Phone"] = "x_phone",
}
```
Break chance (%) for each item when used during a robbery.
```lua theme={null}
ItemsBreak = {
["Circuit"] = 0,
["Device"] = 0,
["Lockpick"] = 0,
["Phone"] = 0,
}
```
***
### Rewards
Register and crate loot are configured per location type.
| Table | Description |
| ------------------------------- | ------------------------------------------------------------------------------------ |
| `Config.RegisterGunStores` | Register cash loot from gun stores |
| `Config.RegisterShootingRanges` | Register cash loot from shooting ranges |
| `Config.Loot` | Crate, ammo, armor, and weapon loot tables split by `GunStores` and `ShootingRanges` |
Set to `true` to give money directly. Set to `false` to give a cash item instead.
The item name used when `Cash` is `false`.
The minimum and maximum cash or item amount per register reward.
```lua theme={null}
StackAmount = {min = 450, max = 1250}
```
Optional item metadata. Used if `markedbills` or similar items carry random value data in their info table.
Gun crate prop models and their matching weapon rewards are configured in `Config.Props`.
***
### Store Locations
Enable or disable location types and individual stores using these tables:
* `Config.ShootingRanges` — Large shooting range locations (e.g. `"PillboxHill"`, `"CypressFlats"`)
* `Config.GunStores` — Small gun store locations (e.g. `"PaletoBay"`, `"Hawick"`, `"LaMesa"`)
Each enabled location has a full entry in `Config.Stores` with coordinates, NPCs, interactions, per-location reset timers, and optional overrides such as `FuseboxProp` and `DrawTextRotation`. Use the store key when calling exports.
You can add custom locations by copying an existing entry in `Config.Stores` and adjusting the coordinates and interaction zones.
***
### Other Settings
Controls the crate code UI text for split-code crate interactions.
How long the alarm lasts in minutes.
Weapons allowed for threatening the employee during the loud approach.
Door lock definitions for each location. Adjust if your map uses different door names.
**Step durations** (`FuseboxDuration`, `RegisterDuration`, `Computer1Duration`, etc.) control how long progress bars run for each interaction step.
***
### Logs
Configured in `config/logs.lua`.
Enables or disables the logging system.
Your Discord webhook URL, or your Fivemerr/Fivemanage API key.
The Fivemanage dataset to log activity to. Leave as `"default"` unless you have a specific dataset configured.
# Exports
Source: https://docs.projectx.gg/resources/ammunation-robbery-fm/exports
Server-side exports available for the FM Ammunation Robbery resource
## Server Exports
All exports require a valid location key from `Config.Stores` (e.g. `"PillboxHill"`, `"PaletoBay"`, `"CypressFlats"`).
### Reset
Resets the robbery at the given location, clearing active state and restoring the store.
```lua theme={null}
exports['projectx-ammunationrobbery-fm']:Reset('PillboxHill')
```
**Returns**
* `true` if the location exists and was reset successfully
***
### IsRobberyInProgress
Returns whether a robbery is currently active at the given location.
```lua theme={null}
local active = exports['projectx-ammunationrobbery-fm']:IsRobberyInProgress('PillboxHill')
```
**Returns**
* `true` if a robbery is in progress at that location, `false` otherwise
**Example**
```lua theme={null}
local active = exports['projectx-ammunationrobbery-fm']:IsRobberyInProgress('PaletoBay')
if active then
print("Paleto Bay Ammunation is being robbed")
end
```
***
### GetActiveRobberyCount
Returns the total number of active Ammunation robberies across all locations.
```lua theme={null}
local count = exports['projectx-ammunationrobbery-fm']:GetActiveRobberyCount()
```
**Returns**
* `count` (number) — total active robberies
**Example**
```lua theme={null}
local count = exports['projectx-ammunationrobbery-fm']:GetActiveRobberyCount()
print("Active Ammunation robberies: " .. count)
```
# FAQs
Source: https://docs.projectx.gg/resources/ammunation-robbery-fm/faqs
Frequently asked questions about the FM Ammunation Robbery resource
## General Questions
The script supports QBCore, Qbox, and ESX through the Project X Bridge. Set `Framework` to `'auto'` in the bridge config and it will detect your framework automatically.
Yes. The bridge is required for this script to function. It handles framework detection, inventory, dispatch, notifications, progressbars, XP, evidence, logs, and global cooldowns. See the [Bridge Installation](/resources/bridge/installation) page for setup instructions.
When you purchase FM Ammunation Robbery, the `projectx-bridge` asset is automatically delivered to your CFX portal.
The bridge supports 25+ dispatch systems including PS Dispatch, CodeSign, LB Tablet, FD Dispatch, Wasabi MDT, Sonoran CAD, and many more. Set `Dispatch` to `'auto'` in the bridge config for automatic detection. See the [Bridge Overview](/resources/bridge/overview) for the full list.
The script supports two location types:
* **Shooting Ranges** — Large locations such as Pillbox Hill and Cypress Flats
* **Gun Stores** — Smaller Ammunation locations across the map
Enable or disable individual locations in `Config.ShootingRanges` and `Config.GunStores`.
The **loud approach** involves threatening the employee with an allowed weapon. Dispatch can trigger immediately when the loud approach begins.
The **silent approach** focuses on hacking, lockpicking, and stealth interactions. Dispatch timing is controlled by `DispatchLocation`.
Open `opensource/client/client.lua` and find the `projectx-ammunationrobbery-fm:client:Minigames` callback. Each robbery step has its own `elseif` block where you can swap the minigame export for any resource you prefer. You can also return `true` inside any block to skip that minigame entirely.
See the [Open Source](/resources/ammunation-robbery-fm/opensource) page for the full callback code and a table of the default minigame assignments.
Use the `/projectxammunation` in-game command (requires admin permissions) to reset the nearest location, or call the `Reset(location)` server export from another resource:
```lua theme={null}
exports['projectx-ammunationrobbery-fm']:Reset('PillboxHill')
```
See the [Commands](/resources/ammunation-robbery-fm/commands) and [Exports](/resources/ammunation-robbery-fm/exports) pages for more details.
## Configuration Questions
Set `MinimumPolice` to the number you want in `config/config.lua`, and make sure the correct jobs are listed in `PoliceJobs`.
```lua theme={null}
MinimumPolice = 2,
PoliceJobs = {"police", "fbi"},
```
Set `SkillSystem` to `true` and configure `MinimumLevel` in `config/config.lua`. You also need a compatible XP system integrated in the bridge config (`XPSystem`).
Supported systems include `pickle_xp`, `sd-levels`, `cw-rep`, and `OT_skills`.
Enable `Bonus.Status` and configure the `Bonus.Items` table in `config/config.lua`. Each item has a `Chance` percentage and an `Amount` range.
```lua theme={null}
Bonus = {
Status = true,
BonusChance = 15,
ItemCount = 1,
Items = {
{Name = "x_device", Chance = 30, Amount = {min = 1, max = 1}},
}
}
```
Set `Cooldown.Global` to `true` to lock all Ammunation locations when one is robbed. Set it to `false` for individual per-location cooldowns. Adjust the duration with `Cooldown.Timer` (in minutes).
## Troubleshooting
Make sure you have all required dependencies started before the script in your `server.cfg` (`projectx-bridge`, `ox_lib`, minigames).
Verify all minigame resources (`boii_minigames`, `bl_ui`, `pure-minigames`, `SN-Hacking`) are started and placed outside the robbery script folder. The bridge's `MinigameCheck` will return `false` if a minigame resource is missing.
# Installation
Source: https://docs.projectx.gg/resources/ammunation-robbery-fm/installation
Step by step instructions to install the FM Ammunation Robbery resource
## Installation Steps
Verify all dependencies below are started **before** this script in your `server.cfg`.
Download ox\_lib
Required map by FM Shop
Required Project X Bridge
Download the minigames zip and place each resource into your standalone or dependencies folder.
Download and place in your standalone or minigames folder
Make sure the minigames are **not** in the same folder as the robbery script.
Extract the script from the zip file and place it into your scripts folder.
Add the required items and their images to your inventory resource. See the [items section](#items-required) below for the full list.
Item images done by [Artwork Inventory](https://discord.gg/Z2awpnXKdw) - Use code **ProjectX** for 10% off!
Open `config/config.lua` and adjust the settings to match your server. The bridge handles framework, inventory, dispatch, and interaction automatically if set to `'auto'`.
Make sure dispatch starts before the bridge, and the bridge and minigames start before the robbery script.
```cfg theme={null}
ensure ox_lib
ensure projectx-bridge
ensure boii_minigames
ensure bl_ui
ensure pure-minigames
ensure SN-Hacking
ensure projectx-ammunationrobbery-fm
```
## Items Required
### Items Required from Outside the Robbery
The `ammunation_key` must be obtained externally (e.g. from another robbery or side mission) before the robbery can be started.
* `ammunation_key`
### Items Required from Shop/Black Market
* `x_phone`
* `x_circuittester`
* `x_trojanusb`
* `advancedlockpick`
* `bag`
The rest of the items (`x_trojanusb2`, etc.) are obtained within the robbery itself.
### Item Configuration
```lua theme={null}
["bag"] = {
label = "Duffel Bag",
weight = 250,
stack = false,
close = false,
description = "Duffel bag",
client = { image = "bag.png" },
},
["x_trojanusb"] = {
label = "X Trojan USB",
weight = 125,
stack = false,
close = false,
description = "?????????",
client = { image = "x_trojanusb.png" },
},
["x_trojanusb2"] = {
label = "X Encrypted Trojan",
weight = 125,
stack = false,
close = false,
description = "?????????",
client = { image = "x_trojanusb2.png" },
},
["x_circuittester"] = {
label = "X Circuit Tester",
weight = 125,
stack = false,
close = false,
description = "?????????",
client = { image = "x_circuittester.png" },
},
["ammunation_key"] = {
label = "Ammunation Key",
weight = 125,
stack = false,
close = false,
description = "?????????",
client = { image = "ammunation_key.png" },
},
["x_phone"] = {
label = "X Phone",
weight = 125,
stack = false,
close = false,
description = "?????????",
client = { image = "x_phone.png" },
},
["advancedlockpick"] = {
label = "Advanced Lockpick",
weight = 500,
stack = true,
close = true,
description = "If you lose your keys a lot this is very useful... Also useful to open your beers",
client = { image = "advancedlockpick.png" },
},
```
```lua theme={null}
['x_phone'] = {['name'] = 'x_phone', ['label'] = 'X Phone', ['weight'] = 50, ['type'] = 'item', ['image'] = 'x_phone.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '?????????'},
['bag'] = {['name'] = 'bag', ['label'] = 'Bag', ['weight'] = 50, ['type'] = 'item', ['image'] = 'bag.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '?????????'},
['x_circuittester'] = {['name'] = 'x_circuittester', ['label'] = 'X Circuit Tester', ['weight'] = 200, ['type'] = 'item', ['image'] = 'x_circuittester.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '????'},
['x_trojanusb'] = {['name'] = 'x_trojanusb', ['label'] = 'X Trojan USB', ['weight'] = 200, ['type'] = 'item', ['image'] = 'x_trojanusb.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '????'},
['x_trojanusb2'] = {['name'] = 'x_trojanusb2', ['label'] = 'X Encrypted Trojan', ['weight'] = 200, ['type'] = 'item', ['image'] = 'x_trojanusb2.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '????'},
['ammunation_key'] = {['name'] = 'ammunation_key', ['label'] = 'Ammunation Key', ['weight'] = 200, ['type'] = 'item', ['image'] = 'ammunation_key.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '????'},
['advancedlockpick'] = {['name'] = 'advancedlockpick', ['label'] = 'Advanced Lockpick', ['weight'] = 500, ['type'] = 'item', ['image'] = 'advancedlockpick.png', ['unique'] = false, ['useable'] = true, ['shouldClose'] = true, ['combinable'] = nil, ['description'] = 'If you lose your keys a lot this is very useful... Also useful to open your beers'},
```
# Open Source
Source: https://docs.projectx.gg/resources/ammunation-robbery-fm/opensource
Open source files available for customization in the FM Ammunation Robbery resource
Most of the core logic in this resource is handled by the bridge. The open source files are provided so you can customize minigames, add hooks for custom systems, and extend the script without touching escrow.
## opensource/client/client.lua
This file handles zone creation, drawtext, evidence, stress, and most importantly, the minigame callback. If you want to change the minigames used for each step, this is the only file you need to edit.
### Minigame Callback
Each robbery step triggers the `projectx-ammunationrobbery-fm:client:Minigames` callback with the step name. You can swap any minigame by replacing the export call inside the matching `elseif` block.
```lua theme={null}
lib.callback.register('projectx-ammunationrobbery-fm:client:Minigames', function(Step)
local p = promise.new()
if Step == "Fusebox" then
if not exports['projectx-bridge']:MinigameCheck("boii_minigames") then p:resolve(false) return Citizen.Await(p) end
exports['boii_minigames']:wire_cut({style = 'default', timer = 60000}, function(success)
p:resolve(success)
end)
elseif Step == "Register" then
if not exports['projectx-bridge']:MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:CircleShake(1, 50, 2)
p:resolve(success)
elseif Step == "Computer1" then
if not exports['projectx-bridge']:MinigameCheck("boii_minigames") then p:resolve(false) return Citizen.Await(p) end
exports['boii_minigames']:chip_hack({style = 'default', loading_time = 8000, chips = 2, timer = 20000}, function(success)
p:resolve(success)
end)
elseif Step == "Computer2" then
if not exports['projectx-bridge']:MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:Untangle(1, {numberOfNodes = 10, duration = 15000})
p:resolve(success)
elseif Step == "GunCrate" then
if not exports['projectx-bridge']:MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:RapidLines(2, 50, 4)
p:resolve(success)
elseif Step == "ExplosivesCrate" then
if not exports['projectx-bridge']:MinigameCheck("boii_minigames") then p:resolve(false) return Citizen.Await(p) end
exports['boii_minigames']:pincode({style = 'default', difficulty = 1, guesses = 10}, function(success)
p:resolve(success)
end)
elseif Step == "ArmorCrate" then
if not exports['projectx-bridge']:MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:CircleProgress(3, 75)
p:resolve(success)
elseif Step == "Timer" then
if not exports['projectx-bridge']:MinigameCheck("boii_minigames") then p:resolve(false) return Citizen.Await(p) end
exports['boii_minigames']:safe_crack({style = 'default', difficulty = 1}, function(success)
p:resolve(success)
end)
elseif Step == "Gun" then
local success = lib.skillCheck({'easy', 'easy', 'medium', 'hard'}, {'w', 'a', 's', 'd'})
p:resolve(success)
elseif Step == "ElectricBox" then
if not exports['projectx-bridge']:MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:MineSweeper(3, {grid = 7, duration = 10000, target = 10, previewDuration = 2000})
p:resolve(success)
elseif Step == "Ammo" then
if not exports['projectx-bridge']:MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:KeySpam(2, 50)
p:resolve(success)
elseif Step == "OfficeDoor" then
if not exports['projectx-bridge']:MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:CircleShake(1, 25, 1)
p:resolve(success)
elseif Step == "Keypad" then
if not exports['projectx-bridge']:MinigameCheck("pure-minigames") then p:resolve(false) return Citizen.Await(p) end
local gameData = {totalNumbers = 20, seconds = 20, timesToChangeNumbers = 4, amountOfGames = 1, incrementByAmount = 5}
local success = exports['pure-minigames']:numberCounter(gameData)
p:resolve(success)
elseif Step == "Code" then
if not exports['projectx-bridge']:MinigameCheck("SN-Hacking") then p:resolve(false) return Citizen.Await(p) end
local success = exports['SN-Hacking']:SkillBar({2000, 3000}, 10, 2)
p:resolve(success)
end
return Citizen.Await(p)
end)
```
You can return `true` unconditionally inside any step block to skip that minigame entirely. This can be useful for testing or for steps you want to make automatic.
The default minigames per step are:
| Step | Minigame Resource | Function |
| ----------------- | ----------------- | ---------------- |
| `Fusebox` | `boii_minigames` | `wire_cut` |
| `Register` | `bl_ui` | `CircleShake` |
| `Computer1` | `boii_minigames` | `chip_hack` |
| `Computer2` | `bl_ui` | `Untangle` |
| `GunCrate` | `bl_ui` | `RapidLines` |
| `ExplosivesCrate` | `boii_minigames` | `pincode` |
| `ArmorCrate` | `bl_ui` | `CircleProgress` |
| `Timer` | `boii_minigames` | `safe_crack` |
| `Gun` | `ox_lib` | `skillCheck` |
| `ElectricBox` | `bl_ui` | `MineSweeper` |
| `Ammo` | `bl_ui` | `KeySpam` |
| `OfficeDoor` | `bl_ui` | `CircleShake` |
| `Keypad` | `pure-minigames` | `numberCounter` |
| `Code` | `SN-Hacking` | `SkillBar` |
***
## opensource/server/server.lua
This file handles dispatch, item/money functions, logging, and exposes several hooks you can use to run custom logic at specific points in the robbery.
### Hooks
Called whenever a player successfully completes a robbery step. Use this to award XP, trigger events, or log individual step completions.
```lua theme={null}
function SuccessfulStep(source, location, step)
if step == "Fusebox" then
-- exports['projectx-bridge']:AddExperience(source, 'criminal', 10)
elseif step == "Register" then
-- exports['projectx-bridge']:AddExperience(source, 'criminal', 10)
end
end
```
Step names match the minigame callback steps and interaction keys defined in `Config.Stores`.
Called whenever a player fails a robbery step. Use this to remove XP, items, or apply penalties.
```lua theme={null}
function FailedStep(source, location, step)
if step == "Fusebox" then
-- RemoveItem(source, 'x_circuittester', 1)
elseif step == "Register" then
-- Apply custom penalty
end
end
```
Called before a player can start a robbery at a location. Return `false` to block them.
```lua theme={null}
function InitialCheck(src, Location, Interaction)
return true
-- Add a group check, tablet requirement, or any other gate here
end
```
Called whenever a location resets. Use this to update a scoreboard, trigger an external event, or notify players.
```lua theme={null}
function RobberyResetHook(location)
-- TriggerEvent('my-scoreboard:update', location)
end
```
# Commands
Source: https://docs.projectx.gg/resources/ammunation-robbery-gabz/commands
Admin commands for the Gabz Ammunation Robbery resource
## Admin Commands
**Usage**: `/projectxammunation`
**Permission**: Admin (configurable via `CheckPerms` in the bridge)
**Description**: Resets the nearest Ammunation location within 50 units of your position.
To reset a specific location programmatically, use the `Reset(location)` export. See the [Exports](/resources/ammunation-robbery-gabz/exports) page.
# Configuration
Source: https://docs.projectx.gg/resources/ammunation-robbery-gabz/configuration
Full reference for all configuration options in the Gabz Ammunation Robbery resource
## config/config.lua
The Gabz variant uses the same configuration structure as the other Ammunation robbery scripts. See the [FM Ammunation Configuration](/resources/ammunation-robbery-fm/configuration) page for the full field reference.
### Main Settings
Shows polyzones created inside the game.
Disables all minigames for testing.
Requires a `bag` item to loot crates.
Minimum police required online. Set to `0` to disable.
Maximum simultaneous active robberies. Set to `0` to disable.
***
### Cooldowns & Limits
When `true`, all locations share one cooldown after a robbery.
Cooldown duration in minutes.
***
### Required Items
```lua theme={null}
Items = {
["Circuit"] = "x_circuittester",
["TrojanUSB"] = "x_trojanusb",
["TrojanUSB2"] = "x_trojanusb2",
["Lockpick"] = "advancedlockpick",
["Bag"] = "bag",
["Key"] = "ammunation_key",
["Phone"] = "x_phone",
}
```
***
### Store Locations
* `Config.ShootingRanges`
* `Config.GunStores`
* `Config.Stores`
Reward tables: `Config.RegisterGunStores`, `Config.RegisterShootingRanges`, `Config.Loot`, and `Config.Props`.
***
### Logs
Configured in `config/logs.lua`.
# Exports
Source: https://docs.projectx.gg/resources/ammunation-robbery-gabz/exports
Server-side exports available for the Gabz Ammunation Robbery resource
## Server Exports
All exports require a valid location key from `Config.Stores`.
### Reset
```lua theme={null}
exports['projectx-ammunationrobbery-gabz']:Reset('PillboxHill')
```
**Returns** — `true` if the location exists and was reset successfully
***
### IsRobberyInProgress
```lua theme={null}
local active = exports['projectx-ammunationrobbery-gabz']:IsRobberyInProgress('PillboxHill')
```
**Returns** — `true` if a robbery is in progress at that location, `false` otherwise
***
### GetActiveRobberyCount
```lua theme={null}
local count = exports['projectx-ammunationrobbery-gabz']:GetActiveRobberyCount()
```
**Returns** — `count` (number) total active robberies
# FAQs
Source: https://docs.projectx.gg/resources/ammunation-robbery-gabz/faqs
Frequently asked questions about the Gabz Ammunation Robbery resource
## General Questions
QBCore, Qbox, and ESX through the Project X Bridge.
Yes. This variant requires the [Gabz Ammunation map](https://fivem.gabzv.com/package/5024631).
Use `/projectxammunation` or:
```lua theme={null}
exports['projectx-ammunationrobbery-gabz']:Reset('PillboxHill')
```
## Troubleshooting
Verify `boii_minigames`, `bl_ui`, `pure-minigames`, and `SN-Hacking` are started before the script.
# Installation
Source: https://docs.projectx.gg/resources/ammunation-robbery-gabz/installation
Step by step instructions to install the Gabz Ammunation Robbery resource
## Installation Steps
Verify all dependencies below are started **before** this script in your `server.cfg`.
Download ox\_lib
Required map by Gabz
Required Project X Bridge
Download the minigames zip and place each resource into your standalone or dependencies folder.
Download and place in your standalone or minigames folder
Make sure the minigames are **not** in the same folder as the robbery script.
Extract the script from the zip file and place it into your scripts folder.
Add the required items and their images to your inventory resource. See the [items section](#items-required) below for the full list.
Item images done by [Artwork Inventory](https://discord.gg/Z2awpnXKdw) - Use code **ProjectX** for 10% off!
Open `config/config.lua` and adjust the settings to match your server.
```cfg theme={null}
ensure ox_lib
ensure projectx-bridge
ensure boii_minigames
ensure bl_ui
ensure pure-minigames
ensure SN-Hacking
ensure projectx-ammunationrobbery-gabz
```
## Items Required
### Items Required from Outside the Robbery
* `ammunation_key`
### Items Required from Shop/Black Market
* `x_phone`
* `x_circuittester`
* `x_trojanusb`
* `advancedlockpick`
* `bag`
The rest of the items are obtained within the robbery itself.
### Item Configuration
```lua theme={null}
["bag"] = { label = "Duffel Bag", weight = 250, stack = false, close = false, description = "Duffel bag", client = { image = "bag.png" } },
["x_trojanusb"] = { label = "X Trojan USB", weight = 125, stack = false, close = false, description = "?????????", client = { image = "x_trojanusb.png" } },
["x_trojanusb2"] = { label = "X Encrypted Trojan", weight = 125, stack = false, close = false, description = "?????????", client = { image = "x_trojanusb2.png" } },
["x_circuittester"] = { label = "X Circuit Tester", weight = 125, stack = false, close = false, description = "?????????", client = { image = "x_circuittester.png" } },
["ammunation_key"] = { label = "Ammunation Key", weight = 125, stack = false, close = false, description = "?????????", client = { image = "ammunation_key.png" } },
["x_phone"] = { label = "X Phone", weight = 125, stack = false, close = false, description = "?????????", client = { image = "x_phone.png" } },
["advancedlockpick"] = { label = "Advanced Lockpick", weight = 500, stack = true, close = true, description = "If you lose your keys a lot this is very useful... Also useful to open your beers", client = { image = "advancedlockpick.png" } },
```
```lua theme={null}
['x_phone'] = {['name'] = 'x_phone', ['label'] = 'X Phone', ['weight'] = 50, ['type'] = 'item', ['image'] = 'x_phone.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '?????????'},
['bag'] = {['name'] = 'bag', ['label'] = 'Bag', ['weight'] = 50, ['type'] = 'item', ['image'] = 'bag.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '?????????'},
['x_circuittester'] = {['name'] = 'x_circuittester', ['label'] = 'X Circuit Tester', ['weight'] = 200, ['type'] = 'item', ['image'] = 'x_circuittester.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '????'},
['x_trojanusb'] = {['name'] = 'x_trojanusb', ['label'] = 'X Trojan USB', ['weight'] = 200, ['type'] = 'item', ['image'] = 'x_trojanusb.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '????'},
['x_trojanusb2'] = {['name'] = 'x_trojanusb2', ['label'] = 'X Encrypted Trojan', ['weight'] = 200, ['type'] = 'item', ['image'] = 'x_trojanusb2.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '????'},
['ammunation_key'] = {['name'] = 'ammunation_key', ['label'] = 'Ammunation Key', ['weight'] = 200, ['type'] = 'item', ['image'] = 'ammunation_key.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '????'},
['advancedlockpick'] = {['name'] = 'advancedlockpick', ['label'] = 'Advanced Lockpick', ['weight'] = 500, ['type'] = 'item', ['image'] = 'advancedlockpick.png', ['unique'] = false, ['useable'] = true, ['shouldClose'] = true, ['combinable'] = nil, ['description'] = 'If you lose your keys a lot this is very useful... Also useful to open your beers'},
```
# Open Source
Source: https://docs.projectx.gg/resources/ammunation-robbery-gabz/opensource
Open source files available for customization in the Gabz Ammunation Robbery resource
## opensource/client/client.lua
Each robbery step triggers the `projectx-ammunationrobbery-gabz:client:Minigames` callback.
```lua theme={null}
lib.callback.register('projectx-ammunationrobbery-gabz:client:Minigames', function(Step)
local p = promise.new()
if Step == "Fusebox" then
if not exports['projectx-bridge']:MinigameCheck("boii_minigames") then p:resolve(false) return Citizen.Await(p) end
exports['boii_minigames']:wire_cut({style = 'default', timer = 60000}, function(success)
p:resolve(success)
end)
elseif Step == "Register" then
if not exports['projectx-bridge']:MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:CircleShake(1, 50, 2)
p:resolve(success)
elseif Step == "Computer1" then
if not exports['projectx-bridge']:MinigameCheck("boii_minigames") then p:resolve(false) return Citizen.Await(p) end
exports['boii_minigames']:chip_hack({style = 'default', loading_time = 8000, chips = 2, timer = 20000}, function(success)
p:resolve(success)
end)
elseif Step == "Computer2" then
if not exports['projectx-bridge']:MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:Untangle(1, {numberOfNodes = 10, duration = 15000})
p:resolve(success)
elseif Step == "GunCrate" then
if not exports['projectx-bridge']:MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:RapidLines(2, 50, 4)
p:resolve(success)
elseif Step == "ExplosivesCrate" then
if not exports['projectx-bridge']:MinigameCheck("boii_minigames") then p:resolve(false) return Citizen.Await(p) end
exports['boii_minigames']:pincode({style = 'default', difficulty = 1, guesses = 10}, function(success)
p:resolve(success)
end)
elseif Step == "ArmorCrate" then
if not exports['projectx-bridge']:MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:CircleProgress(3, 75)
p:resolve(success)
elseif Step == "Timer" then
if not exports['projectx-bridge']:MinigameCheck("boii_minigames") then p:resolve(false) return Citizen.Await(p) end
exports['boii_minigames']:safe_crack({style = 'default', difficulty = 1}, function(success)
p:resolve(success)
end)
elseif Step == "Gun" then
local success = lib.skillCheck({'easy', 'easy', 'medium', 'hard'}, {'w', 'a', 's', 'd'})
p:resolve(success)
elseif Step == "Ammo" then
if not exports['projectx-bridge']:MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:KeySpam(2, 50)
p:resolve(success)
elseif Step == "Keypad" then
if not exports['projectx-bridge']:MinigameCheck("pure-minigames") then p:resolve(false) return Citizen.Await(p) end
local gameData = {totalNumbers = 20, seconds = 20, timesToChangeNumbers = 4, amountOfGames = 1, incrementByAmount = 5}
local success = exports['pure-minigames']:numberCounter(gameData)
p:resolve(success)
elseif Step == "Code" then
if not exports['projectx-bridge']:MinigameCheck("SN-Hacking") then p:resolve(false) return Citizen.Await(p) end
local success = exports['SN-Hacking']:SkillBar({2000, 3000}, 10, 2)
p:resolve(success)
end
return Citizen.Await(p)
end)
```
| Step | Minigame Resource | Function |
| ----------------- | ----------------- | ---------------- |
| `Fusebox` | `boii_minigames` | `wire_cut` |
| `Register` | `bl_ui` | `CircleShake` |
| `Computer1` | `boii_minigames` | `chip_hack` |
| `Computer2` | `bl_ui` | `Untangle` |
| `GunCrate` | `bl_ui` | `RapidLines` |
| `ExplosivesCrate` | `boii_minigames` | `pincode` |
| `ArmorCrate` | `bl_ui` | `CircleProgress` |
| `Timer` | `boii_minigames` | `safe_crack` |
| `Gun` | `ox_lib` | `skillCheck` |
| `Ammo` | `bl_ui` | `KeySpam` |
| `Keypad` | `pure-minigames` | `numberCounter` |
| `Code` | `SN-Hacking` | `SkillBar` |
***
## opensource/server/server.lua
Hooks: `SuccessfulStep(source, location, step)`, `FailedStep(source, location, step)`, `InitialCheck(src, Location, Interaction)`, and `RobberyResetHook(location)`.
# Commands
Source: https://docs.projectx.gg/resources/ammunation-robbery-prompt/commands
Admin commands for the Prompt Ammunation Robbery resource
## Admin Commands
**Usage**: `/projectxammunation`
**Permission**: Admin (configurable via `CheckPerms` in the bridge)
**Description**: Resets the nearest Ammunation location within 50 units of your position. Useful for testing or recovering from a stuck robbery.
**Example**:
```
/projectxammunation
```
This command resets the closest location automatically. To reset a specific location programmatically, use the `Reset(location)` export instead. See the [Exports](/resources/ammunation-robbery-prompt/exports) page for details.
# Configuration
Source: https://docs.projectx.gg/resources/ammunation-robbery-prompt/configuration
Full reference for all configuration options in the Prompt Ammunation Robbery resource
## config/config.lua
The Prompt variant uses the same configuration structure as the other Ammunation robbery scripts. Key settings are documented below. See the [FM Ammunation Configuration](/resources/ammunation-robbery-fm/configuration) page for the full field reference — all shared options apply here as well.
### Main Settings
Shows polyzones created inside the game.
Disables all minigames for testing.
Requires a `bag` item to loot crates.
Minimum police required online. Set to `0` to disable.
Maximum simultaneous active robberies. Set to `0` to disable.
Disables the loud approach path.
Disables the silent approach path.
***
### Cooldowns & Limits
When `true`, all locations share one cooldown after a robbery.
Cooldown duration in minutes.
Per-restart limits split by `ShootingRanges` and `Gunstores`.
***
### Required Items
```lua theme={null}
Items = {
["Circuit"] = "x_circuittester",
["TrojanUSB"] = "x_trojanusb",
["TrojanUSB2"] = "x_trojanusb2",
["Lockpick"] = "advancedlockpick",
["Bag"] = "bag",
["Key"] = "ammunation_key",
["Phone"] = "x_phone",
}
```
***
### Dispatch
```lua theme={null}
DispatchLocation = {
["Loud"] = true,
["Silent"] = false,
["Register"] = true,
["Keypad"] = false,
["ElectricBox"] = false,
}
```
***
### Store Locations
* `Config.ShootingRanges` — Enable/disable shooting range locations
* `Config.GunStores` — Enable/disable gun store locations
* `Config.Stores` — Full per-location configuration (coords, NPCs, interactions, reset timers)
Reward tables: `Config.RegisterGunStores`, `Config.RegisterShootingRanges`, `Config.Loot`, and `Config.Props`.
UI text for split-code crate interactions.
***
### Logs
Configured in `config/logs.lua`.
# Exports
Source: https://docs.projectx.gg/resources/ammunation-robbery-prompt/exports
Server-side exports available for the Prompt Ammunation Robbery resource
## Server Exports
All exports require a valid location key from `Config.Stores` (e.g. `"PillboxHill"`, `"PaletoBay"`, `"CypressFlats"`).
### Reset
Resets the robbery at the given location, clearing active state and restoring the store.
```lua theme={null}
exports['projectx-ammunationrobbery-prompt']:Reset('PillboxHill')
```
**Returns**
* `true` if the location exists and was reset successfully
***
### IsRobberyInProgress
Returns whether a robbery is currently active at the given location.
```lua theme={null}
local active = exports['projectx-ammunationrobbery-prompt']:IsRobberyInProgress('PillboxHill')
```
**Returns**
* `true` if a robbery is in progress at that location, `false` otherwise
***
### GetActiveRobberyCount
Returns the total number of active Ammunation robberies across all locations.
```lua theme={null}
local count = exports['projectx-ammunationrobbery-prompt']:GetActiveRobberyCount()
```
**Returns**
* `count` (number) — total active robberies
# FAQs
Source: https://docs.projectx.gg/resources/ammunation-robbery-prompt/faqs
Frequently asked questions about the Prompt Ammunation Robbery resource
## General Questions
QBCore, Qbox, and ESX through the Project X Bridge. Set `Framework` to `'auto'` in the bridge config.
Yes. This variant requires the [Prompt Ammunation map](https://store.prompt-mods.com/package/6713220).
Use `/projectxammunation` or:
```lua theme={null}
exports['projectx-ammunationrobbery-prompt']:Reset('PillboxHill')
```
Edit `opensource/client/client.lua`. See the [Open Source](/resources/ammunation-robbery-prompt/opensource) page.
## Troubleshooting
Verify `boii_minigames`, `bl_ui`, `pure-minigames`, and `SN-Hacking` are started before the script.
# Installation
Source: https://docs.projectx.gg/resources/ammunation-robbery-prompt/installation
Step by step instructions to install the Prompt Ammunation Robbery resource
## Installation Steps
Verify all dependencies below are started **before** this script in your `server.cfg`.
Download ox\_lib
Required map by Prompt Mods
Required Project X Bridge
Download the minigames zip and place each resource into your standalone or dependencies folder.
Download and place in your standalone or minigames folder
Make sure the minigames are **not** in the same folder as the robbery script.
Extract the script from the zip file and place it into your scripts folder.
Add the required items and their images to your inventory resource. See the [items section](#items-required) below for the full list.
Item images done by [Artwork Inventory](https://discord.gg/Z2awpnXKdw) - Use code **ProjectX** for 10% off!
Open `config/config.lua` and adjust the settings to match your server. The bridge handles framework, inventory, dispatch, and interaction automatically if set to `'auto'`.
Make sure dispatch starts before the bridge, and the bridge and minigames start before the robbery script.
```cfg theme={null}
ensure ox_lib
ensure projectx-bridge
ensure boii_minigames
ensure bl_ui
ensure pure-minigames
ensure SN-Hacking
ensure projectx-ammunationrobbery-prompt
```
## Items Required
### Items Required from Outside the Robbery
The `ammunation_key` must be obtained externally (e.g. from another robbery or side mission) before the robbery can be started.
* `ammunation_key`
### Items Required from Shop/Black Market
* `x_phone`
* `x_circuittester`
* `x_trojanusb`
* `advancedlockpick`
* `bag`
The rest of the items (`x_trojanusb2`, etc.) are obtained within the robbery itself.
### Item Configuration
```lua theme={null}
["bag"] = {
label = "Duffel Bag",
weight = 250,
stack = false,
close = false,
description = "Duffel bag",
client = { image = "bag.png" },
},
["x_trojanusb"] = {
label = "X Trojan USB",
weight = 125,
stack = false,
close = false,
description = "?????????",
client = { image = "x_trojanusb.png" },
},
["x_trojanusb2"] = {
label = "X Encrypted Trojan",
weight = 125,
stack = false,
close = false,
description = "?????????",
client = { image = "x_trojanusb2.png" },
},
["x_circuittester"] = {
label = "X Circuit Tester",
weight = 125,
stack = false,
close = false,
description = "?????????",
client = { image = "x_circuittester.png" },
},
["ammunation_key"] = {
label = "Ammunation Key",
weight = 125,
stack = false,
close = false,
description = "?????????",
client = { image = "ammunation_key.png" },
},
["x_phone"] = {
label = "X Phone",
weight = 125,
stack = false,
close = false,
description = "?????????",
client = { image = "x_phone.png" },
},
["advancedlockpick"] = {
label = "Advanced Lockpick",
weight = 500,
stack = true,
close = true,
description = "If you lose your keys a lot this is very useful... Also useful to open your beers",
client = { image = "advancedlockpick.png" },
},
```
```lua theme={null}
['x_phone'] = {['name'] = 'x_phone', ['label'] = 'X Phone', ['weight'] = 50, ['type'] = 'item', ['image'] = 'x_phone.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '?????????'},
['bag'] = {['name'] = 'bag', ['label'] = 'Bag', ['weight'] = 50, ['type'] = 'item', ['image'] = 'bag.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '?????????'},
['x_circuittester'] = {['name'] = 'x_circuittester', ['label'] = 'X Circuit Tester', ['weight'] = 200, ['type'] = 'item', ['image'] = 'x_circuittester.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '????'},
['x_trojanusb'] = {['name'] = 'x_trojanusb', ['label'] = 'X Trojan USB', ['weight'] = 200, ['type'] = 'item', ['image'] = 'x_trojanusb.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '????'},
['x_trojanusb2'] = {['name'] = 'x_trojanusb2', ['label'] = 'X Encrypted Trojan', ['weight'] = 200, ['type'] = 'item', ['image'] = 'x_trojanusb2.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '????'},
['ammunation_key'] = {['name'] = 'ammunation_key', ['label'] = 'Ammunation Key', ['weight'] = 200, ['type'] = 'item', ['image'] = 'ammunation_key.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '????'},
['advancedlockpick'] = {['name'] = 'advancedlockpick', ['label'] = 'Advanced Lockpick', ['weight'] = 500, ['type'] = 'item', ['image'] = 'advancedlockpick.png', ['unique'] = false, ['useable'] = true, ['shouldClose'] = true, ['combinable'] = nil, ['description'] = 'If you lose your keys a lot this is very useful... Also useful to open your beers'},
```
# Open Source
Source: https://docs.projectx.gg/resources/ammunation-robbery-prompt/opensource
Open source files available for customization in the Prompt Ammunation Robbery resource
Most of the core logic in this resource is handled by the bridge. The open source files are provided so you can customize minigames, add hooks for custom systems, and extend the script without touching escrow.
## opensource/client/client.lua
Each robbery step triggers the `projectx-ammunationrobbery-prompt:client:Minigames` callback with the step name.
```lua theme={null}
lib.callback.register('projectx-ammunationrobbery-prompt:client:Minigames', function(Step)
local p = promise.new()
if Step == "Fusebox" then
if not exports['projectx-bridge']:MinigameCheck("boii_minigames") then p:resolve(false) return Citizen.Await(p) end
exports['boii_minigames']:wire_cut({style = 'default', timer = 60000}, function(success)
p:resolve(success)
end)
elseif Step == "Register" then
if not exports['projectx-bridge']:MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:CircleShake(1, 50, 2)
p:resolve(success)
elseif Step == "Computer1" then
if not exports['projectx-bridge']:MinigameCheck("boii_minigames") then p:resolve(false) return Citizen.Await(p) end
exports['boii_minigames']:chip_hack({style = 'default', loading_time = 8000, chips = 2, timer = 30000}, function(success)
p:resolve(success)
end)
elseif Step == "Computer2" then
if not exports['projectx-bridge']:MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:Untangle(1, {numberOfNodes = 10, duration = 15000})
p:resolve(success)
elseif Step == "GunCrate" then
if not exports['projectx-bridge']:MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:RapidLines(2, 50, 4)
p:resolve(success)
elseif Step == "ExplosivesCrate" then
if not exports['projectx-bridge']:MinigameCheck("boii_minigames") then p:resolve(false) return Citizen.Await(p) end
exports['boii_minigames']:pincode({style = 'default', difficulty = 1, guesses = 10}, function(success)
p:resolve(success)
end)
elseif Step == "ArmorCrate" then
if not exports['projectx-bridge']:MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:CircleProgress(3, 75)
p:resolve(success)
elseif Step == "ElectricBox" then
if not exports['projectx-bridge']:MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:MineSweeper(3, {grid = 7, duration = 10000, target = 10, previewDuration = 2000})
p:resolve(success)
elseif Step == "Timer" then
if not exports['projectx-bridge']:MinigameCheck("boii_minigames") then p:resolve(false) return Citizen.Await(p) end
exports['boii_minigames']:safe_crack({style = 'default', difficulty = 1}, function(success)
p:resolve(success)
end)
elseif Step == "OfficeDoor" then
if not exports['projectx-bridge']:MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:CircleShake(1, 25, 1)
p:resolve(success)
elseif Step == "Gun" then
local success = lib.skillCheck({'easy', 'easy', 'medium', 'hard'}, {'w', 'a', 's', 'd'})
p:resolve(success)
elseif Step == "Ammo" then
if not exports['projectx-bridge']:MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:KeySpam(2, 50)
p:resolve(success)
elseif Step == "Keypad" then
if not exports['projectx-bridge']:MinigameCheck("pure-minigames") then p:resolve(false) return Citizen.Await(p) end
local gameData = {totalNumbers = 20, seconds = 20, timesToChangeNumbers = 4, amountOfGames = 1, incrementByAmount = 5}
local success = exports['pure-minigames']:numberCounter(gameData)
p:resolve(success)
elseif Step == "Code" then
if not exports['projectx-bridge']:MinigameCheck("SN-Hacking") then p:resolve(false) return Citizen.Await(p) end
local success = exports['SN-Hacking']:SkillBar({2000, 3000}, 10, 2)
p:resolve(success)
end
return Citizen.Await(p)
end)
```
| Step | Minigame Resource | Function |
| ----------------- | ----------------- | ---------------- |
| `Fusebox` | `boii_minigames` | `wire_cut` |
| `Register` | `bl_ui` | `CircleShake` |
| `Computer1` | `boii_minigames` | `chip_hack` |
| `Computer2` | `bl_ui` | `Untangle` |
| `GunCrate` | `bl_ui` | `RapidLines` |
| `ExplosivesCrate` | `boii_minigames` | `pincode` |
| `ArmorCrate` | `bl_ui` | `CircleProgress` |
| `ElectricBox` | `bl_ui` | `MineSweeper` |
| `Timer` | `boii_minigames` | `safe_crack` |
| `OfficeDoor` | `bl_ui` | `CircleShake` |
| `Gun` | `ox_lib` | `skillCheck` |
| `Ammo` | `bl_ui` | `KeySpam` |
| `Keypad` | `pure-minigames` | `numberCounter` |
| `Code` | `SN-Hacking` | `SkillBar` |
***
## opensource/server/server.lua
Hooks: `SuccessfulStep(source, location, step)`, `FailedStep(source, location, step)`, `InitialCheck(src, Location, Interaction)`, and `RobberyResetHook(location)`.
# Commands
Source: https://docs.projectx.gg/resources/ammunation-robbery-tstudio/commands
Admin commands for the TStudio Ammunation Robbery resource
## Admin Commands
**Usage**: `/projectxammunation`
**Permission**: Admin (configurable via `CheckPerms` in the bridge)
**Description**: Resets the nearest Ammunation location within 50 units of your position. Useful for testing or recovering from a stuck robbery.
**Example**:
```
/projectxammunation
```
This command resets the closest location automatically. To reset a specific location programmatically, use the `Reset(location)` export instead. See the [Exports](/resources/ammunation-robbery-tstudio/exports) page for details.
# Configuration
Source: https://docs.projectx.gg/resources/ammunation-robbery-tstudio/configuration
Full reference for all configuration options in the TStudio Ammunation Robbery resource
## config/config.lua
### Main Settings
Shows polyzones created inside the game. Useful for testing zone placement.
Disables all minigames. Useful for testing the full robbery flow without completing minigame challenges.
The key code used to trigger drawtext interactions. `38` is `[E]` by default.
The size of the drawtext interaction zone.
The default rotation of the drawtext interaction zone. Individual stores can override this in `Config.Stores`.
Spawns networked props server side. Set to `false` to spawn them client side instead.
Spawns networked peds server side. Set to `false` to spawn them client side instead.
Requires players to have a `bag` item in order to loot crates.
Minimum number of police required online before a robbery can be started. Set to `0` to disable.
The jobs that count as police for the `MinimumPolice` check and dispatch alerts.
Requires a minimum number of players nearby to start a robbery. Set `amount` to `0` or `false` to disable.
Maximum number of Ammunation robberies that can be active at the same time. Set to `0` to disable.
Disables the loud approach path entirely.
Disables the silent approach path entirely.
Disables all particle effects during robberies.
Disables weapon removal during robberies. Only enable this if you use a weapon wheel resource.
***
### Cooldowns & Limits
When `true`, robbing one location puts all Ammunation locations on cooldown. When `false`, each location has its own cooldown.
Cooldown duration in minutes.
Per-player cooldown in minutes after completing a robbery. Set to `0` to disable.
Maximum robberies per server restart, split by location type. Set each value to `0` to disable.
Maximum robberies a single player can complete per restart, split by location type. Set each value to `0` to disable.
***
### Skill System
Requires players to meet a minimum level from an integrated XP/skill system before starting a robbery.
Minimum level required to initiate a robbery. Only applies when `SkillSystem` is `true`.
***
### Dispatch
Title shown in the dispatch alert.
Message body shown in the dispatch alert.
Controls which steps trigger dispatch alerts. The TStudio variant includes fingerprint and keypad steps.
```lua theme={null}
DispatchLocation = {
["Loud"] = true,
["Silent"] = false,
["Register"] = false,
["Keypad"] = true,
["Fingerprint"] = false,
["ElectricBox"] = false,
["FingerprintKeypad2"] = false,
}
```
***
### Bonus Items
Enables or disables bonus item drops at the end of a robbery.
Table of possible bonus items with `Name`, `Chance` (%), and `Amount` range.
***
### Evidence & Stress
Enables fingerprint evidence drops at the crime scene.
Enables the stress system. Stress is only applied when a minigame is failed.
***
### Required Items
Maps logical item names to your inventory item names.
```lua theme={null}
Items = {
["TrojanUSB"] = "x_trojanusb",
["TrojanUSB2"] = "x_trojanusb2",
["Circuit"] = "x_circuittester",
["Stethoscope"] = "x_stethoscope",
["FingerprintBag"] = "x_fingerprintbag",
["FingerprintTape"] = "x_fingerprinttape",
["Tablet"] = "x_cyberdeck",
["Lockpick"] = "advancedlockpick",
["Bag"] = "bag",
["Keycard"] = "ammunation_keycard",
}
```
***
### Rewards
Register and crate loot are configured per location type in `Config.RegisterGunStores`, `Config.RegisterShootingRanges`, and `Config.Loot`.
Gun crate prop models and their matching weapon rewards are configured in `Config.Props`.
***
### Store Locations
Enable or disable location types and individual stores using:
* `Config.ShootingRanges`
* `Config.GunStores`
* `Config.Stores`
Use the store key when calling exports.
***
### Other Settings
Controls the safe code range and UI text for safe interactions.
```lua theme={null}
Password = {
Input = {Title = 'Safe Code', Label = 'Code', Description = 'Enter the code', Icon = 'fas fa-lock'},
CodeRange = {min = 1000, max = 9999},
}
```
Weapons allowed for threatening the employee during the loud approach.
Door lock definitions for each location.
**Step durations** (`FuseboxDuration`, `RegisterDuration`, `ComputerDuration`, etc.) control progress bar length for each interaction.
***
### Logs
Configured in `config/logs.lua`.
Enables or disables the logging system.
Your Discord webhook URL, or your Fivemerr/Fivemanage API key.
# Exports
Source: https://docs.projectx.gg/resources/ammunation-robbery-tstudio/exports
Server-side exports available for the TStudio Ammunation Robbery resource
## Server Exports
All exports require a valid location key from `Config.Stores` (e.g. `"PillboxHill"`, `"PaletoBay"`, `"CypressFlats"`).
### Reset
Resets the robbery at the given location, clearing active state and restoring the store.
```lua theme={null}
exports['projectx-ammunationrobbery-tstudio']:Reset('PillboxHill')
```
**Returns**
* `true` if the location exists and was reset successfully
***
### IsRobberyInProgress
Returns whether a robbery is currently active at the given location.
```lua theme={null}
local active = exports['projectx-ammunationrobbery-tstudio']:IsRobberyInProgress('PillboxHill')
```
**Returns**
* `true` if a robbery is in progress at that location, `false` otherwise
**Example**
```lua theme={null}
local active = exports['projectx-ammunationrobbery-tstudio']:IsRobberyInProgress('PaletoBay')
if active then
print("Paleto Bay Ammunation is being robbed")
end
```
***
### GetActiveRobberyCount
Returns the total number of active Ammunation robberies across all locations.
```lua theme={null}
local count = exports['projectx-ammunationrobbery-tstudio']:GetActiveRobberyCount()
```
**Returns**
* `count` (number) — total active robberies
**Example**
```lua theme={null}
local count = exports['projectx-ammunationrobbery-tstudio']:GetActiveRobberyCount()
print("Active Ammunation robberies: " .. count)
```
# FAQs
Source: https://docs.projectx.gg/resources/ammunation-robbery-tstudio/faqs
Frequently asked questions about the TStudio Ammunation Robbery resource
## General Questions
The script supports QBCore, Qbox, and ESX through the Project X Bridge. Set `Framework` to `'auto'` in the bridge config and it will detect your framework automatically.
Yes. The bridge is required for this script to function. See the [Bridge Installation](/resources/bridge/installation) page for setup instructions.
The TStudio variant uses the TStudio Ammunation map and includes fingerprint, safe, and keycard progression mechanics. Progression requires `ammunation_keycard` instead of `ammunation_key`.
Open `opensource/client/client.lua` and find the `projectx-ammunationrobbery-tstudio:client:Minigames` callback. See the [Open Source](/resources/ammunation-robbery-tstudio/opensource) page for the full callback and default assignments.
Use `/projectxammunation` or call the export:
```lua theme={null}
exports['projectx-ammunationrobbery-tstudio']:Reset('PillboxHill')
```
## Troubleshooting
Verify all minigame resources (`bl_ui`, `SN-Hacking`, `pure-minigames`, `pd-safe`) are started and placed outside the robbery script folder.
# Installation
Source: https://docs.projectx.gg/resources/ammunation-robbery-tstudio/installation
Step by step instructions to install the TStudio Ammunation Robbery resource
## Installation Steps
Verify all dependencies below are started **before** this script in your `server.cfg`.
Download ox\_lib
Required map by TStudio
Required Project X Bridge
Download the minigames zip and place each resource into your standalone or dependencies folder.
Download and place in your standalone or minigames folder
Make sure the minigames are **not** in the same folder as the robbery script.
Extract the script from the zip file and place it into your scripts folder.
Add the required items and their images to your inventory resource. See the [items section](#items-required) below for the full list.
Item images done by [Artwork Inventory](https://discord.gg/Z2awpnXKdw) - Use code **ProjectX** for 10% off!
Open `config/config.lua` and adjust the settings to match your server. The bridge handles framework, inventory, dispatch, and interaction automatically if set to `'auto'`.
Make sure dispatch starts before the bridge, and the bridge and minigames start before the robbery script.
```cfg theme={null}
ensure ox_lib
ensure projectx-bridge
ensure bl_ui
ensure SN-Hacking
ensure pure-minigames
ensure pd-safe
ensure projectx-ammunationrobbery-tstudio
```
## Items Required
### Items Required from Outside the Robbery
The `ammunation_keycard` must be obtained externally (e.g. from another robbery or side mission) before the robbery can be started.
* `ammunation_keycard`
### Items Required from Shop/Black Market
* `x_circuittester`
* `advancedlockpick`
* `x_cyberdeck`
* `x_fingerprinttape`
* `x_stethoscope`
* `x_trojanusb`
* `bag`
The rest of the items (`x_trojanusb2`, `x_fingerprintbag`, etc.) are obtained within the robbery itself.
### Item Configuration
```lua theme={null}
["bag"] = {
label = "Duffel Bag",
weight = 250,
stack = false,
close = false,
description = "Duffel bag",
},
["x_circuittester"] = {
label = "X Circuit Tester",
weight = 125,
stack = false,
close = false,
description = "?????????",
},
["ammunation_keycard"] = {
label = "Ammunation Keycard",
weight = 125,
stack = false,
close = false,
description = "?????????",
},
["advancedlockpick"] = {
label = "Advanced Lockpick",
weight = 500,
stack = true,
close = true,
description = "If you lose your keys a lot this is very useful... Also useful to open your beers",
},
["x_cyberdeck"] = {
label = "X Cyberdeck",
weight = 100,
stack = false,
close = false,
description = "Nothing suspicious about this cyberdeck..",
},
["x_fingerprinttape"] = {
label = "Fingerprint Tape",
weight = 125,
stack = false,
close = false,
description = "?????????",
},
["x_fingerprintbag"] = {
label = "Fingerprint Bag",
weight = 125,
stack = false,
close = false,
description = "?????????",
},
["x_stethoscope"] = {
label = "X Stethoscope",
weight = 200,
stack = false,
close = false,
description = "click click",
},
["x_trojanusb"] = {
label = "X Trojan USB",
weight = 125,
stack = false,
close = false,
description = "?????????",
},
["x_trojanusb2"] = {
label = "X Encrypted Trojan",
weight = 125,
stack = false,
close = false,
description = "?????????",
},
```
```lua theme={null}
['bag'] = {['name'] = 'bag', ['label'] = 'Bag', ['weight'] = 50, ['type'] = 'item', ['image'] = 'bag.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '?????????'},
['x_circuittester'] = {['name'] = 'x_circuittester', ['label'] = 'X Circuit Tester', ['weight'] = 200, ['type'] = 'item', ['image'] = 'x_circuittester.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '????'},
['ammunation_keycard'] = {['name'] = 'ammunation_keycard', ['label'] = 'Ammunation Keycard', ['weight'] = 200, ['type'] = 'item', ['image'] = 'ammunation_keycard.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '????'},
['advancedlockpick'] = {['name'] = 'advancedlockpick', ['label'] = 'Advanced Lockpick', ['weight'] = 500, ['type'] = 'item', ['image'] = 'advancedlockpick.png', ['unique'] = false, ['useable'] = true, ['shouldClose'] = true, ['combinable'] = nil, ['description'] = 'If you lose your keys a lot this is very useful... Also useful to open your beers'},
['x_cyberdeck'] = {['name'] = 'x_cyberdeck', ['label'] = 'X Cyberdeck', ['weight'] = 100, ['type'] = 'item', ['image'] = 'x_cyberdeck.png', ['unique'] = true, ['useable'] = true, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'Nothing suspicious about this cyberdeck..'},
['x_fingerprinttape'] = {['name'] = 'x_fingerprinttape', ['label'] = 'Fingerprint Tape', ['weight'] = 200, ['type'] = 'item', ['image'] = 'x_fingerprinttape.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '????'},
['x_trojanusb'] = {['name'] = 'x_trojanusb', ['label'] = 'X Trojan USB', ['weight'] = 200, ['type'] = 'item', ['image'] = 'x_trojanusb.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '????'},
['x_trojanusb2'] = {['name'] = 'x_trojanusb2', ['label'] = 'X Encrypted Trojan', ['weight'] = 200, ['type'] = 'item', ['image'] = 'x_trojanusb2.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '????'},
['x_fingerprintbag'] = {['name'] = 'x_fingerprintbag', ['label'] = 'Fingerprint Bag', ['weight'] = 200, ['type'] = 'item', ['image'] = 'x_fingerprintbag.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '????'},
['x_stethoscope'] = {['name'] = 'x_stethoscope', ['label'] = 'X Stethoscope', ['weight'] = 200, ['type'] = 'item', ['image'] = 'x_stethoscope.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'click click'},
```
# Open Source
Source: https://docs.projectx.gg/resources/ammunation-robbery-tstudio/opensource
Open source files available for customization in the TStudio Ammunation Robbery resource
Most of the core logic in this resource is handled by the bridge. The open source files are provided so you can customize minigames, add hooks for custom systems, and extend the script without touching escrow.
## opensource/client/client.lua
This file handles zone creation, drawtext, evidence, stress, and most importantly, the minigame callback. If you want to change the minigames used for each step, this is the only file you need to edit.
### Minigame Callback
Each robbery step triggers the `projectx-ammunationrobbery-tstudio:client:Minigames` callback with the step name. You can swap any minigame by replacing the export call inside the matching `elseif` block.
```lua theme={null}
lib.callback.register('projectx-ammunationrobbery-tstudio:client:Minigames', function(Step)
local p = promise.new()
if Step == "Fusebox" then
if not exports['projectx-bridge']:MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:WaveMatch(1, {duration = 30000})
p:resolve(success)
elseif Step == "Register" then
if not exports['projectx-bridge']:MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:KeySpam(3, 60)
p:resolve(success)
elseif Step == "Computer" then
if not exports['projectx-bridge']:MinigameCheck("SN-Hacking") then p:resolve(false) return Citizen.Await(p) end
local success = exports['SN-Hacking']:MemoryCards('medium')
p:resolve(success)
elseif Step == "GunCrate" then
if not exports['projectx-bridge']:MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:RapidLines(2, 50, 4)
p:resolve(success)
elseif Step == "ExplosivesCrate" then
if not exports['projectx-bridge']:MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:MineSweeper(3, {grid = 7, duration = 10000, target = 10, previewDuration = 2000})
p:resolve(success)
elseif Step == "ArmorCrate" then
if not exports['projectx-bridge']:MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:CircleProgress(3, 75)
p:resolve(success)
elseif Step == "Gun" then
local success = lib.skillCheck({'easy', 'easy', 'medium', 'hard'}, {'w', 'a', 's', 'd'})
p:resolve(success)
elseif Step == "Ammo" then
if not exports['projectx-bridge']:MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:KeySpam(2, 50)
p:resolve(success)
elseif Step == "ElectricBox1" then
if not exports['projectx-bridge']:MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:KeySpam(3, 50)
p:resolve(success)
elseif Step == "ElectricBox2" then
if not exports['projectx-bridge']:MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:PathFind(1, {numberOfNodes = 10, duration = 7500})
p:resolve(success)
elseif Step == "Fingerprint" then
if not exports['projectx-bridge']:MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:PrintLock(1, {grid = 5, duration = 15000, target = 5 })
p:resolve(success)
elseif Step == "FingerprintKeypad1" then
if not exports['projectx-bridge']:MinigameCheck("SN-Hacking") then p:resolve(false) return Citizen.Await(p) end
local success = exports['SN-Hacking']:Thermite(7, 5, 10000, 1, 2, 3000)
p:resolve(success)
elseif Step == "FingerprintKeypad2" then
if not exports['projectx-bridge']:MinigameCheck("SN-Hacking") then p:resolve(false) return Citizen.Await(p) end
local success = exports['SN-Hacking']:Thermite(7, 5, 10000, 1, 2, 3000)
p:resolve(success)
elseif Step == "Safe" then
if not exports['projectx-bridge']:MinigameCheck("pure-minigames") then p:resolve(false) return Citizen.Await(p) end
local gameData = {totalNumbers = 20, seconds = 20, timesToChangeNumbers = 4, amountOfGames = 1, incrementByAmount = 5}
local success = exports['pure-minigames']:numberCounter(gameData)
p:resolve(success)
elseif Step == "MiniSafe" then
if not exports['projectx-bridge']:MinigameCheck("pd-safe") then p:resolve(false) return Citizen.Await(p) end
local success = exports["pd-safe"]:createSafe({math.random(0,99)})
p:resolve(success)
elseif Step == "Keypad" then
if not exports['projectx-bridge']:MinigameCheck("pure-minigames") then p:resolve(false) return Citizen.Await(p) end
local gameData = {totalNumbers = 20, seconds = 20, timesToChangeNumbers = 4, amountOfGames = 1, incrementByAmount = 5}
local success = exports['pure-minigames']:numberCounter(gameData)
p:resolve(success)
end
return Citizen.Await(p)
end)
```
You can return `true` unconditionally inside any step block to skip that minigame entirely.
The default minigames per step are:
| Step | Minigame Resource | Function |
| -------------------- | ----------------- | ---------------- |
| `Fusebox` | `bl_ui` | `WaveMatch` |
| `Register` | `bl_ui` | `KeySpam` |
| `Computer` | `SN-Hacking` | `MemoryCards` |
| `GunCrate` | `bl_ui` | `RapidLines` |
| `ExplosivesCrate` | `bl_ui` | `MineSweeper` |
| `ArmorCrate` | `bl_ui` | `CircleProgress` |
| `Gun` | `ox_lib` | `skillCheck` |
| `Ammo` | `bl_ui` | `KeySpam` |
| `ElectricBox1` | `bl_ui` | `KeySpam` |
| `ElectricBox2` | `bl_ui` | `PathFind` |
| `Fingerprint` | `bl_ui` | `PrintLock` |
| `FingerprintKeypad1` | `SN-Hacking` | `Thermite` |
| `FingerprintKeypad2` | `SN-Hacking` | `Thermite` |
| `Safe` | `pure-minigames` | `numberCounter` |
| `MiniSafe` | `pd-safe` | `createSafe` |
| `Keypad` | `pure-minigames` | `numberCounter` |
***
## opensource/server/server.lua
This file handles dispatch, item/money functions, logging, and exposes several hooks you can use to run custom logic at specific points in the robbery.
### Hooks
Called whenever a player successfully completes a robbery step.
```lua theme={null}
function SuccessfulStep(source, location, step)
if step == "Fusebox" then
-- exports['projectx-bridge']:AddExperience(source, 'criminal', 10)
end
end
```
Called whenever a player fails a robbery step.
Called before a player can start a robbery at a location. Return `false` to block them.
Called whenever a location resets.
# Commands
Source: https://docs.projectx.gg/resources/atm-robbery/commands
Player commands for the Project X ATM Robbery resource
## Player Commands
**Usage**: `/removerope`
**Permission**: Any player (keybind via RegisterKeyMapping)
**Description**: Cancels and removes the nylon rope from the player's hand during the rope approach.
**Default keybind**: `X` (from `Config.RopeCancelButton`)
**Example**:
```
/removerope
```
Change the default key in `config/config.lua` with `RopeCancelButton`. Players can also rebind it in FiveM keybinds under **Remove Atm Rope**.
# Configuration
Source: https://docs.projectx.gg/resources/atm-robbery/configuration
Full reference for all configuration options in the Project X ATM Robbery resource
## config/config.lua
### Main Settings
Shows polyzones created inside the game.
Enables exploit check box zones. Disable if this causes polyzone issues.
Disables all minigames for flow testing.
Interaction system. Must match the bridge setting: `ox_target`, `qb-target`, or `interact`.
Disables particle effects during robberies.
Disables the C4 explosion when blowing up ATMs. Keep `true` if your anticheat blocks explosion events.
Disables weapon removal during the robbery. Only enable this if you use a weapon wheel resource.
Jobs that count as police for approach cop checks and dispatch alerts.
```lua theme={null}
PoliceJobs = {"police", "fbi"}
```
Client wait interval for rope handling. Higher values lower resmon (rope loads slower); lower values increase responsiveness (higher resmon).
Physics weight of the ATM while being dragged by a vehicle. Lower values weigh the car down less.
When cooldown starts: `'initiation'` (starting the robbery) or `'rope'` (attaching the rope to the car).
Removes step items after each step. Set to `false` to keep items for crafting, pawn shops, etc.
Default key for `/removerope` (RegisterKeyMapping). See the [Commands](/resources/atm-robbery/commands) page.
Control ID to stop the beating approach. `38` is `[E]` by default.
Shows the destroy ATM interaction on placed consoles.
Duration in milliseconds for success and error notifications.
Requires players to meet per-approach `RequiredLevel` via the bridge XP system before starting that approach.
Resets ATM consoles after cooldown (rope and explosive approaches).
***
### Cooldowns
Enables a global cooldown shared across approaches. When active, per-approach cooldowns are disabled.
Global cooldown duration in minutes.
Enables per-player cooldowns.
Per-player cooldown duration in minutes.
***
### Dispatch
Dispatch alert settings used by the bridge.
```lua theme={null}
Dispatch = {
Title = 'ATM Robbery',
Message = 'ATM being robbed',
Code = '10-35',
Time = 3,
Blip = {
Text = '911 - ATM Robbery',
Color = 1,
Sprite = 272,
Scale = 1.0,
},
}
```
***
### Bonus Items
Enables or disables bonus item drops at the end of a robbery.
Percentage chance that any bonus item is given at all.
Number of items that can be given from the bonus items table.
Table of possible bonus items. Each entry has a `Name`, `Chance` (%), and `Amount` range. Total chance across items should add up to 100%.
```lua theme={null}
Items = {
{Name = "x_device", Chance = 30, Amount = {min = 1, max = 1}},
{Name = "x_phone", Chance = 50, Amount = {min = 1, max = 1}},
{Name = "x_stethoscope", Chance = 20, Amount = {min = 1, max = 1}},
}
```
***
### Evidence & Stress
Enables fingerprint evidence drops at the crime scene.
Percentage chance that fingerprint evidence is left behind.
Enables stress on minigame failure.
Percentage chance that stress is applied on a minigame fail.
Minimum and maximum stress applied per failure.
***
### Approaches
Each entry in `Config.Approaches` can be enabled or disabled with `Status`. Toggle approaches independently to suit your server economy.
| Approach | Required items | Notes |
| --------------- | ------------------------------------------- | ----------------------------------------------------------------- |
| `Rope` | `laserdrill`, `nylonrope`, `screwdriverset` | Drill holes → rope to vehicle → pull console → place & break down |
| `Drill` | `laserdrill` | Direct drill loot on the ATM |
| `C4` | `weapon_stickybomb` | Plant sticky bomb and loot exploded console |
| `Thermite` | `thermite` | Burn through the ATM |
| `Hacking` | `x_device` | Device hack for smaller payout |
| `GasTank` | `x_gastank`, `lighter` | Ignite a gas tank on the ATM |
| `Beating` | Weapons in `Config.Weapons` | Melee smash; lowest payout |
| `Impersonation` | `x_fakecredit` | Fake credit card swipe |
All approaches share the same config structure. Fields common to most approaches:
* `Status`, `RequiredItem` / `RequiredItem2` / `RequiredItem3`
* `ItemsBreak`, `Cooldown`, `ProgressBarDuration`
* `RobberyTimeFrame`, `CopsRequired`, `RequiredLevel`, `Exp`
* `Jackpot` (`Status`, `Chance`, `Multiplier`)
* `Dispatch` / `Reward` (`ItemForCash`, `CashName`, `CashItem`, `CashAmount`, `ItemInfo`)
The Rope approach also has pull timing (`MinimumDurationToRemoveAtmFromWall`, `SpeedFactor`), pickup timer, tracker, and extra dispatch flags.
```lua theme={null}
["Drill"] = {
["Status"] = true,
["RequiredItem"] = "laserdrill",
["ItemsBreak"] = { ["Drill"] = 100 },
["Cooldown"] = 5,
["ProgressBarDuration"] = 25,
['RobberyTimeFrame'] = {min = 20, max = 5},
['CopsRequired'] = 0,
['RequiredLevel'] = 10,
['Exp'] = 1,
['Jackpot'] = {
['Status'] = true,
['Chance'] = 10,
['Multiplier'] = 2,
},
['Dispatch'] = {
['Status'] = true,
['Chance'] = 100,
},
["Reward"] = {
['ItemForCash'] = false,
['CashName'] = 'cash',
['CashItem'] = "markedbills",
['CashAmount'] = {min = 1000, max = 2000},
['ItemInfo'] = false,
}
},
```
***
### Props
```lua theme={null}
Config.Props = {
["Default"] = {"prop_atm_02", "prop_atm_03", "prop_fleeca_atm"},
["CustomConsoles"] = {"projectx_atm_02", "projectx_atm_03", "projectx_fleeca_atm"},
["CustomFrames"] = {"projectx_atm_02_frame", "projectx_atm_03_frame", "projectx_fleeca_atm_frame"},
["ExplodedConsoles"] = {"projectx_atm_02_exploded", "projectx_atm_03_exploded", "projectx_fleeca_atm_exploded"},
}
```
Default GTA ATM models are targeted for approaches. Custom console/frame/exploded models come from `projectx-atmprops`.
***
### Placeable ATM Settings
`Config.Settings` controls placing pulled ATM consoles:
```lua theme={null}
Config.Settings = {
['PlacementMinDistance'] = 2.5,
['Atms'] = {
['Atmred'] = { ['Prop'] = 'projectx_atm_03', ['ItemName'] = 'atmred' },
['Atmblue'] = { ['Prop'] = 'projectx_atm_02', ['ItemName'] = 'atmblue' },
['Atmgreen'] = { ['Prop'] = 'projectx_fleeca_atm', ['ItemName'] = 'atmgreen' },
}
}
```
***
### Breakdown Steps
After placing a pulled console, players break it down in three steps (`Config.Steps`):
| Step | Tool | Reward |
| ------------ | ----------- | --------------------------------------------- |
| `FirstStep` | `blowtorch` | `atmpanel` |
| `SecondStep` | `atmpanel` | `atmcables` |
| `ThirdStep` | `atmcables` | `atmmotherboard` (also required to take cash) |
***
### Vehicle Classes (Rope)
`Config.Vehicles` is a **blacklist** of vehicle classes for the rope pull. Commented-out classes are **whitelisted**.
By default, SUVs (2), Off-road (9), Industrials (10), Utility (11), Vans (12), Military (19), and Commercial (20) are allowed.
***
### Beating Weapons
`Config.Weapons` lists melee weapons allowed to start the beating approach (nightstick, hammer, bat, crowbar, golf club, hatchet, machete, wrench, battle axe).
***
### Logs
Configured in `config/logs.lua`.
Enables or disables the logging system.
Your Discord webhook URL, or your Fivemerr/Fivemanage API key.
The Fivemanage dataset to log activity to.
# Exports
Source: https://docs.projectx.gg/resources/atm-robbery/exports
Public exports for the Project X ATM Robbery resource
## Public Exports
This resource does **not** expose any public exports.
Integrate custom logic through the open source hooks instead — client `Robbed()`, and server `RobbedServer`, `SuccessfulStep`, `FailedStep`, `SuccessfulApproach`, and `FailedApproach`.
See the [Open Source](/resources/atm-robbery/opensource) page for the full hook reference and minigame callback.
# FAQs
Source: https://docs.projectx.gg/resources/atm-robbery/faqs
Frequently asked questions about the Project X ATM Robbery resource
## General Questions
Yes. `projectx-bridge` is a hard dependency in the fxmanifest. It handles framework detection, inventory, dispatch, notifications, XP, evidence, and logs. See the [Bridge Installation](/resources/bridge/installation) page for setup instructions.
When you purchase ATM Robbery, the `projectx-bridge` asset is automatically delivered to your CFX portal.
Yes. Custom ATM consoles, frames, and exploded models come from `projectx-atmprops`, which is included in the package zip and listed as a fxmanifest dependency. Do not remove or split it from the package unless you know what you are doing.
Eight approaches can be toggled independently via `Config.Approaches[*].Status`:
| Approach | Required items |
| ------------- | ------------------------------------------- |
| Rope | `laserdrill`, `nylonrope`, `screwdriverset` |
| Drill | `laserdrill` |
| C4 | `weapon_stickybomb` |
| Thermite | `thermite` |
| Hacking | `x_device` |
| GasTank | `x_gastank`, `lighter` |
| Beating | melee weapons from `Config.Weapons` |
| Impersonation | `x_fakecredit` |
See the [Configuration](/resources/atm-robbery/configuration) page for full option details.
1. Park a vehicle close to an ATM.
2. Use `nylonrope` and attach it to an allowed vehicle class.
3. Drill the ATM (`laserdrill`) to prepare it.
4. Drive to pull the console off the wall.
5. Pick up the console (`atmred` / `atmblue` / `atmgreen`) and place it somewhere safe.
6. Break it down: `blowtorch` + `screwdriverset` → panel → cables → motherboard → take cash.
Use `/removerope` (default key `X`) to cancel the rope in hand.
Open `opensource/client/client.lua` and find the `projectx-atmrobbery:client:Minigames` callback. Each step has its own `elseif` block where you can swap the minigame export. You can also return `true` inside any block to skip that minigame entirely.
See the [Open Source](/resources/atm-robbery/opensource) page for the full callback and step-to-minigame table.
* **Global cooldown** (`Cooldowns.GlobalCooldown`): one shared cooldown for the whole server. When enabled, per-approach cooldowns are disabled.
* **Individual cooldown** (`Cooldowns.IndividualCooldown`): per-player cooldown after robbing.
* Each approach also has its own `Cooldown` field used when global cooldown is off.
`CooldownPlace` controls whether cooldown starts at initiation or when attaching the rope.
Set `SkillSystem` to `true` in `config/config.lua` and configure each approach's `RequiredLevel` and `Exp`. You also need a compatible XP system in the bridge (`XPSystem`), such as `projectx-xp`, `pickle_xp`, `sd-levels`, `cw-rep`, or `OT_skills`. See the [FAQs](/faqs) for bridge XP config values.
Enable `Bonus.Status` and configure `Bonus.Items` in `config/config.lua`. Each item has a `Chance` percentage and an `Amount` range.
```lua theme={null}
Bonus = {
Status = true,
BonusChance = 15,
ItemCount = 1,
Items = {
{Name = "x_device", Chance = 30, Amount = {min = 1, max = 1}},
}
}
```
`Config.Vehicles` is a blacklist of vehicle classes. Commented-out classes are whitelisted. By default SUVs, Off-road, Industrials, Utility, Vans, Military, and Commercial can pull.
The bridge supports 30+ dispatch systems including PS Dispatch, CodeSign, CodeSign 3D, LB Tablet, FD Dispatch, Wasabi MDT, Oxide Dispatch, VX MDT, Sonoran CAD, and many more. Set `Dispatch` to `'auto'` in the bridge config for automatic detection. See the [FAQs](/faqs) for the full list with config values and links.
Free support is not available for this paid script. Open a ticket in the [Project X Discord](https://discord.gg/bJNxYDAm5u) for paid-script support.
## Troubleshooting
Ensure start order in `server.cfg` is: `ox_lib` → `projectx-bridge` → `bl_ui` → `projectx-atmprops` → `projectx-atmrobbery`. Missing `projectx-atmprops` will prevent the resource from starting.
# Installation
Source: https://docs.projectx.gg/resources/atm-robbery/installation
Step by step instructions to install the Project X ATM Robbery resource
## Installation Steps
Verify all dependencies below are started **before** this script in your `server.cfg`.
Download ox\_lib
Required Project X Bridge
Required custom ATM props (included in the package zip)
Required minigame resource
Install `bl_ui` into your standalone or dependencies folder.
Download and place in your standalone or minigames folder
Make sure minigames are **not** in the same folder as the robbery script.
Extract the script from the zip file and place it into your scripts folder.
Do **not** split the folders from the zip unless you know what you are doing. Keep `projectx-atmrobbery` and `projectx-atmprops` together — the props resource is a hard dependency.
Add the required items and their images to your inventory resource. See the [items section](#items-required) below for the full list.
Item images done by [Artwork Inventory](https://discord.gg/Z2awpnXKdw) - Use code **ProjectX** for 10% off!
Open `config/config.lua` and adjust the settings to match your server. Set `Config.Interaction` to match your bridge interaction (`ox_target`, `qb-target`, or `interact`). Framework, inventory, and dispatch are handled by the bridge when set to `'auto'`.
Start order matters. Ensure dependencies in this order:
```cfg theme={null}
ensure ox_lib
ensure projectx-bridge
ensure bl_ui
ensure projectx-atmprops
ensure projectx-atmrobbery
```
## Optional: Renewed-Carryitems
If you want players to visually carry placeable ATM consoles (`atmred`, `atmblue`, `atmgreen`), you can optionally install [Renewed-Carryitems](https://github.com/Renewed-Scripts/Renewed-Carryitems) and add those three items to its config. This is **not required** for the robbery to function.
## Items Required
### Items Required from Shop/Black Market
* `nylonrope`
* `blowtorch`
* `laserdrill`
* `x_fakecredit`
* `x_gastank`
* `x_device`
* `thermite`
* `screwdriverset`
* `lighter`
The C4 approach uses `weapon_stickybomb` (a weapon, not a custom item).
### Items Obtained Within the Robbery
Placeable ATM consoles and breakdown parts are obtained during the rope approach:
* `atmred`
* `atmblue`
* `atmgreen`
* `atmpanel`
* `atmcables`
* `atmmotherboard`
### Item Configuration
```lua theme={null}
['nylonrope'] = {
label = 'Nylon Rope',
description = 'The strongest rope material..',
weight = 125,
close = true,
stack = true,
client = {
image = "nylonrope.png",
event = 'projectx-atmrobbery:client:UseRope',
}
},
['atmred'] = {
label = 'Red ATM',
description = 'A console of an automated teller.',
weight = 350,
close = true,
stack = false,
client = {
image = "atmred.png",
event = 'projectx-atmrobbery:client:UseAtm-Red',
}
},
['atmblue'] = {
label = 'Blue ATM',
description = 'A console of an automated teller.',
weight = 350,
close = true,
stack = false,
client = {
image = "atmblue.png",
event = 'projectx-atmrobbery:client:UseAtm-Blue',
}
},
['atmgreen'] = {
label = 'Green ATM',
description = 'A console of an automated teller.',
weight = 350,
close = true,
stack = false,
client = {
image = "atmgreen.png",
event = 'projectx-atmrobbery:client:UseAtm-Green',
}
},
['atmpanel'] = {
label = 'ATM Panel',
description = 'A back panel from an automated teller.',
weight = 125,
close = true,
stack = false,
client = {
image = "atmpanel.png",
}
},
['atmcables'] = {
label = 'ATM Cables',
description = 'Cables from an automated teller.',
weight = 125,
close = true,
stack = false,
client = {
image = "atmcables.png",
}
},
['atmmotherboard'] = {
label = 'ATM Motherboard',
description = 'A motherboard from an automated teller.',
weight = 125,
close = true,
stack = false,
client = {
image = "atmmotherboard.png",
}
},
['blowtorch'] = {
label = 'Blow Torch',
description = 'Ooo hot...',
weight = 125,
close = true,
stack = false,
client = {
image = "blowtorch.png",
}
},
['laserdrill'] = {
label = 'Laser Drill',
description = 'I wonder what this does...',
weight = 125,
close = true,
stack = false,
client = {
image = "laserdrill.png",
}
},
['screwdriverset'] = {
label = 'Screwdriverset',
description = 'A Screw driver set',
weight = 50,
close = true,
stack = false,
client = {
image = "screwdriverset.png",
}
},
["x_gastank"] = {
label = "X Gas Tank",
weight = 200,
stack = true,
close = false,
description = "????",
client = {
image = "x_gastank.png",
}
},
["x_fakecredit"] = {
label = "X Credit Card",
weight = 200,
stack = true,
close = false,
description = "????",
client = {
image = "x_fakecredit.png",
}
},
["x_device"] = {
label = "X Device",
weight = 50,
stack = false,
close = false,
description = "?????????",
client = {
image = "x_device.png",
}
},
["thermite"] = {
label = "Thermite",
weight = 1000,
stack = true,
close = true,
description = "Sometimes you'd wish for everything to burn",
client = {
image = "thermite.png",
}
},
["lighter"] = {
label = "Lighter",
weight = 0,
stack = true,
close = true,
description = "On new years eve a nice fire to stand next to",
client = {
image = "lighter.png",
}
},
```
```lua theme={null}
['nylonrope'] = {['name'] = 'nylonrope', ['label'] = 'Nylon Rope', ['weight'] = 500, ['type'] = 'item', ['image'] = 'nylonrope.png', ['unique'] = false, ['useable'] = true, ['shouldClose'] = true, ['combinable'] = nil, ['description'] = 'The strongest rope material..'},
['atmred'] = {['name'] = 'atmred', ['label'] = 'Red Atm', ['weight'] = 25000, ['type'] = 'item', ['image'] = 'atmred.png', ['unique'] = true, ['useable'] = true, ['shouldClose'] = true, ['combinable'] = nil, ['description'] = 'A console of an ATM'},
['atmblue'] = {['name'] = 'atmblue', ['label'] = 'Blue Atm', ['weight'] = 25000, ['type'] = 'item', ['image'] = 'atmblue.png', ['unique'] = true, ['useable'] = true, ['shouldClose'] = true, ['combinable'] = nil, ['description'] = 'A console of an ATM'},
['atmgreen'] = {['name'] = 'atmgreen', ['label'] = 'Green Atm', ['weight'] = 25000, ['type'] = 'item', ['image'] = 'atmgreen.png', ['unique'] = true, ['useable'] = true, ['shouldClose'] = true, ['combinable'] = nil, ['description'] = 'A console of an ATM'},
['atmpanel'] = {['name'] = 'atmpanel', ['label'] = 'Atm Panel', ['weight'] = 5000, ['type'] = 'item', ['image'] = 'atmpanel.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = true, ['combinable'] = nil, ['description'] = 'A back panel for an ATM'},
['atmcables'] = {['name'] = 'atmcables', ['label'] = 'Atm Cables', ['weight'] = 2000, ['type'] = 'item', ['image'] = 'atmcables.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = true, ['combinable'] = nil, ['description'] = 'Cables..'},
['atmmotherboard'] = {['name'] = 'atmmotherboard', ['label'] = 'Atm Motherboard', ['weight'] = 2000, ['type'] = 'item', ['image'] = 'atmmotherboard.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = true, ['combinable'] = nil, ['description'] = 'A motherboard for an ATM'},
['blowtorch'] = {['name'] = 'blowtorch', ['label'] = 'Blow Torch', ['weight'] = 1000, ['type'] = 'item', ['image'] = 'blowtorch.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = true, ['combinable'] = nil, ['description'] = 'Ooo hot..'},
['laserdrill'] = {['name'] = 'laserdrill', ['label'] = 'Laser Drill', ['weight'] = 1000, ['type'] = 'item', ['image'] = 'laserdrill.png', ['unique'] = true, ['useable'] = true, ['shouldClose'] = true, ['combinable'] = nil, ['description'] = ''},
['x_fakecredit'] = {['name'] = 'x_fakecredit', ['label'] = 'X Credit Card', ['weight'] = 1000, ['type'] = 'item', ['image'] = 'x_fakecredit.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = true, ['combinable'] = nil, ['description'] = '..'},
['x_gastank'] = {['name'] = 'x_gastank', ['label'] = 'X Gas Tank', ['weight'] = 1000, ['type'] = 'item', ['image'] = 'x_gastank.png', ['unique'] = true, ['useable'] = true, ['shouldClose'] = true, ['combinable'] = nil, ['description'] = '..'},
['x_device'] = {['name'] = 'x_device', ['label'] = 'X Device', ['weight'] = 50, ['type'] = 'item', ['image'] = 'x_device.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '?????????'},
['thermite'] = {['name'] = 'thermite', ['label'] = 'Thermite', ['weight'] = 1000, ['type'] = 'item', ['image'] = 'thermite.png', ['unique'] = false, ['useable'] = true, ['shouldClose'] = true, ['combinable'] = nil, ['description'] = 'Sometimes you\'d wish for everything to burn'},
['screwdriverset'] = {['name'] = 'screwdriverset', ['label'] = 'Toolkit', ['weight'] = 1000, ['type'] = 'item', ['image'] = 'screwdriverset.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'Very useful to screw... screws...'},
['lighter'] = {['name'] = 'lighter', ['label'] = 'Lighter', ['weight'] = 0, ['type'] = 'item', ['image'] = 'lighter.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = true, ['combinable'] = nil, ['description'] = 'On new years eve a nice fire to stand next to'},
```
# Open Source
Source: https://docs.projectx.gg/resources/atm-robbery/opensource
Open source files available for customization in the Project X ATM Robbery resource
Most of the core logic in this resource is handled by the bridge and escrow. The open source files are provided so you can customize minigames, add hooks for custom systems, and extend the script without touching escrow.
## opensource/client/client.lua
This file handles notifications, zones, evidence, stress, interaction targets, and the minigame callback. If you want to change the minigames used for each step, this is the file to edit.
### Minigame Callback
Each approach or ATM breakdown step triggers the `projectx-atmrobbery:client:Minigames` callback with the step name. You can swap any minigame by replacing the export call inside the matching `elseif` block.
```lua theme={null}
lib.callback.register('projectx-atmrobbery:client:Minigames', function(step)
if Config.TestingMode then return true end
local p = promise.new()
if not exports['projectx-bridge']:MinigameCheck("bl_ui") then
p:resolve(false)
return Citizen.Await(p)
end
if step == 'RopeDrill' then
local success = exports["bl_ui"]:CircleSum(3, {length = 4, duration = 15000})
p:resolve(success)
elseif step == 'Drill' then
local success = exports["bl_ui"]:WaveMatch(1, {duration = 30000})
p:resolve(success)
elseif step == 'C4' then
local success = exports["bl_ui"]:MineSweeper(3, {grid = 7, duration = 10000, target = 10, previewDuration = 2000})
p:resolve(success)
elseif step == 'Thermite' then
local success = exports["bl_ui"]:DigitDazzle(1, {length = 4, duration = 10000})
p:resolve(success)
elseif step == 'GasTank' then
local success = exports["bl_ui"]:Untangle(1, {numberOfNodes = 10, duration = 15000})
p:resolve(success)
elseif step == 'Impersonation' then
local success = exports["bl_ui"]:PrintLock(1, {grid = 5, duration = 15000, target = 5})
p:resolve(success)
elseif step == 'Hacking' then
local success = exports["bl_ui"]:WordWiz(1, {length = 4, duration = 40000})
p:resolve(success)
elseif step == 'Beating' then
local success = exports["bl_ui"]:WaveMatch(1, {duration = 30000})
p:resolve(success)
elseif step == "AtmStep1" then
local success = exports["bl_ui"]:KeySpam(4, 50)
p:resolve(success)
elseif step == "AtmStep2" then
local success = exports["bl_ui"]:CircleProgress(4, 50)
p:resolve(success)
elseif step == "AtmStep3" then
local success = exports["bl_ui"]:RapidLines(3, 50, 5)
p:resolve(success)
elseif step == "AtmStep4" then
local success = exports["bl_ui"]:CircleShake(1, 50, 3)
p:resolve(success)
end
return Citizen.Await(p)
end)
```
You can return `true` unconditionally inside any step block to skip that minigame entirely. This is useful for testing or for steps you want to make automatic.
The default minigames per step are:
| Step | Minigame Resource | Function |
| --------------- | ----------------- | ---------------- |
| `RopeDrill` | `bl_ui` | `CircleSum` |
| `Drill` | `bl_ui` | `WaveMatch` |
| `C4` | `bl_ui` | `MineSweeper` |
| `Thermite` | `bl_ui` | `DigitDazzle` |
| `GasTank` | `bl_ui` | `Untangle` |
| `Impersonation` | `bl_ui` | `PrintLock` |
| `Hacking` | `bl_ui` | `WordWiz` |
| `Beating` | `bl_ui` | `WaveMatch` |
| `AtmStep1` | `bl_ui` | `KeySpam` |
| `AtmStep2` | `bl_ui` | `CircleProgress` |
| `AtmStep3` | `bl_ui` | `RapidLines` |
| `AtmStep4` | `bl_ui` | `CircleShake` |
### Client Hook
Called on the client after successfully pulling an ATM from the wall (rope approach). Use this for local effects or client-side XP/UI.
```lua theme={null}
function Robbed()
-- Trigger something here after pulling the atm from the wall
end
```
***
## opensource/server/server.lua
This file handles dispatch, items, money, logging, police checks, and exposes hooks you can use to run custom logic at specific points.
### Hooks
Called after the ATM is looted and the approach is finished.
```lua theme={null}
function RobbedServer(source, Approach)
-- Award bonus XP, update a scoreboard, etc.
end
```
Called when a player successfully completes a placed-ATM breakdown step (`AtmStep1`–`AtmStep4`). By default this awards Rope approach XP when `SkillSystem` is enabled.
```lua theme={null}
function SuccessfulStep(source, step)
-- Custom logic per breakdown step
end
```
Called whenever a player fails a breakdown step.
```lua theme={null}
function FailedStep(source, step)
-- Apply penalties if needed
end
```
Called when a player successfully completes an approach (e.g. `Drill`, `C4`, `Hacking`).
```lua theme={null}
function SuccessfulApproach(source, approach)
-- Custom reward / XP logic
end
```
Called whenever a player fails an approach.
```lua theme={null}
function FailedApproach(source, approach)
-- Custom fail handling
end
```
# Commands
Source: https://docs.projectx.gg/resources/bobcat-heist-default/commands
Admin commands for the Default Bobcat Heist resource
## Admin Commands
**Usage**: `/projectxbobcat`
**Permission**: Admin (configurable via `CheckPerms` in the bridge)
**Description**: Forces a full heist reset, unlocking doors and clearing any active robbery state. Useful for testing or recovering from a stuck robbery.
**Example**:
```
/projectxbobcat
```
This command internally calls the `Reset()` export. See the [Exports](/resources/bobcat-heist-default/exports) page for details.
# Configuration
Source: https://docs.projectx.gg/resources/bobcat-heist-default/configuration
Full reference for all configuration options in the Default Bobcat Heist resource
## config/config.lua
The Default Bobcat Heist uses the same configuration structure as the [K4MB1 Bobcat Heist](/resources/bobcat-heist-k4mb1/configuration). All options below apply — only map coordinates and door definitions differ for the free `BOBCAT_MLO`.
### Main Settings
Shows polyzones created inside the game.
Disables all minigames for flow testing.
Minutes before the heist resets after a completed robbery.
Disables the loud approach path entirely.
Disables the silent approach path entirely.
Disables client-side explosions during C4 steps.
Requires a `bag` item to loot trolleys.
Minimum police required online. Set to `0` to disable.
***
### Strike System
Maximum trolleys that can spawn.
Strike limit before rewards are reduced (silent approach).
Maximum weapon crates that can spawn.
***
### Bonus Items
The default variant ships with `fleecacard` in the bonus items table instead of `x_device`:
```lua theme={null}
Bonus = {
Status = false,
Items = {
{Name = "fleecacard", Chance = 30, Amount = {min = 1, max = 1}},
{Name = "x_phone", Chance = 50, Amount = {min = 1, max = 1}},
{Name = "x_stethoscope", Chance = 20, Amount = {min = 1, max = 1}},
},
}
```
***
### Full Reference
For dispatch, computer password, rewards, security guards, sounds, evidence/stress, and logging options, see the [K4MB1 Bobcat Configuration](/resources/bobcat-heist-k4mb1/configuration) page.
# Exports
Source: https://docs.projectx.gg/resources/bobcat-heist-default/exports
Server-side exports available for the Default Bobcat Heist resource
## Server Exports
### Reset
Resets the heist, unlocking the facility and clearing any active robbery state.
```lua theme={null}
exports['projectx-bobcatheist-default']:Reset()
```
### IsRobberyInitiated
Returns whether a robbery is currently active.
```lua theme={null}
local active = exports['projectx-bobcatheist-default']:IsRobberyInitiated()
```
**Returns**
* `active` (boolean) - `true` if a robbery is in progress, `false` otherwise
**Example**
```lua theme={null}
local active = exports['projectx-bobcatheist-default']:IsRobberyInitiated()
if active then
print("A robbery is currently in progress")
end
```
# FAQs
Source: https://docs.projectx.gg/resources/bobcat-heist-default/faqs
Frequently asked questions about the Default Bobcat Heist resource
## General Questions
The free `BOBCAT_MLO` from the [QBCore Bobcat Heist repository](https://github.com/Buildman-Bob/QBCore-Bobcat-Heist). Only extract the `BOBCAT_MLO` folder — ignore the rest of the download.
Yes. See the [Bridge Installation](/resources/bridge/installation) page for setup instructions.
Use `/projectxbobcat` or call:
```lua theme={null}
exports['projectx-bobcatheist-default']:Reset()
```
Edit `opensource/client/client.lua` — see the [Open Source](/resources/bobcat-heist-default/opensource) page.
## Troubleshooting
Ensure `BOBCAT_MLO`, `projectx-bridge`, `ox_lib`, `mka-lasers`, and all minigames from the zip are started before `projectx-bobcatheist-default`.
# Installation
Source: https://docs.projectx.gg/resources/bobcat-heist-default/installation
Step by step instructions to install the Default Bobcat Heist resource
## Installation Steps
Verify all dependencies below are started **before** this script in your `server.cfg`. Start order should be: Dispatch → Bridge → Minigames → Script.
Download ox\_lib
Required Project X Bridge
Download the free Bobcat MLO and extract only the `BOBCAT_MLO` folder into your maps folder.
QBCore Bobcat Heist repository (use BOBCAT\_MLO only)
Open the `[Interior]` folder from the download and move **only** `BOBCAT_MLO` to your maps folder. Delete everything else from the download — you only need that one folder.
Download the minigames zip and place each resource into your standalone or dependencies folder.
Download and place in your standalone or minigames folder
Make sure the minigames are **not** in the same folder as the robbery script.
Extract the script from the zip file and place it into your scripts folder.
Add the required items and their images to your inventory resource. See the [items section](#items-required) below for the full list.
Item images done by [Artwork Inventory](https://discord.gg/Z2awpnXKdw) - Use code **ProjectX** for 10% off!
Open `config/config.lua` and adjust the settings to match your server. The bridge handles framework, inventory, dispatch, and interaction automatically if set to `'auto'`.
Make sure the bridge, ox\_lib, your target, dispatch, inventory, minigames, and `mka-lasers` are all started before the robbery script.
```cfg theme={null}
ensure ox_lib
ensure projectx-bridge
ensure BOBCAT_MLO
ensure mka-lasers
ensure lightsout
ensure SN-Hacking
ensure utk_fingerprint
ensure projectx-bobcatheist-default
```
## Items Required
### Items Required from Outside the Robbery
The `bobcatcard2` must be obtained externally (e.g. from another robbery or side mission) before the heist can be started.
* `bobcatcard2`
### Items Required from Shop/Black Market
* `x_device`
* `x_phone`
* `pliers`
* `bag`
The rest of the items (`bobcatcard`, C4, smoke grenades, etc.) are obtained within the heist itself.
### Item Configuration
```lua theme={null}
["x_device"] = {
label = "Flapper Hero",
weight = 125,
stack = false,
close = false,
description = "?????????",
},
["bag"] = {
label = "Duffel Bag",
weight = 250,
stack = false,
close = false,
description = "Duffel bag",
},
["pliers"] = {
label = "Pliers",
weight = 125,
stack = false,
close = false,
description = "A pair of pliers",
},
["x_phone"] = {
label = "x Phone",
weight = 300,
stack = false,
close = false,
description = "?????????",
},
["bobcatcard"] = {
label = "Bobcat Keycard A",
weight = 50,
stack = false,
close = false,
description = "A Security card for Bobcat",
},
["bobcatcard2"] = {
label = "Bobcat Keycard B",
weight = 50,
stack = false,
close = false,
description = "A Security card for Bobcat",
},
```
```lua theme={null}
['x_device'] = {['name'] = 'x_device', ['label'] = 'X Device', ['weight'] = 50, ['type'] = 'item', ['image'] = 'x_device.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '?????????'},
['bag'] = {['name'] = 'bag', ['label'] = 'Bag', ['weight'] = 400, ['type'] = 'item', ['image'] = 'bag.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'Duffel bag'},
['pliers'] = {['name'] = 'pliers', ['label'] = 'Pliers', ['weight'] = 200, ['type'] = 'item', ['image'] = 'pliers.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'Pliers..?'},
['x_phone'] = {['name'] = 'x_phone', ['label'] = 'X Phone', ['weight'] = 50, ['type'] = 'item', ['image'] = 'x_phone.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '?????????'},
['bobcatcard'] = {['name'] = 'bobcatcard', ['label'] = 'Bobcat Keycard A', ['weight'] = 200, ['type'] = 'item', ['image'] = 'bobcatcard.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = ''},
['bobcatcard2'] = {['name'] = 'bobcatcard2', ['label'] = 'Bobcat Keycard B', ['weight'] = 200, ['type'] = 'item', ['image'] = 'bobcatcard2.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = ''},
```
# Open Source
Source: https://docs.projectx.gg/resources/bobcat-heist-default/opensource
Open source files available for customization in the Default Bobcat Heist resource
Most of the core logic in this resource is handled by the bridge. The open source files are provided so you can customize minigames, add hooks for custom systems, and extend the script without touching escrow.
## opensource/client/client.lua
Each robbery step triggers the `projectx-bobcatheist-default:client:Minigames` callback with the step name.
```lua theme={null}
lib.callback.register('projectx-bobcatheist-default:client:Minigames', function(Step)
local p = promise.new()
if Step == "C4Entrance" then
if not exports['projectx-bridge']:MinigameCheck("lightsout") then p:resolve(false) return Citizen.Await(p) end
local success = exports['lightsout']:StartLightsOut(4, 20)
p:resolve(success)
elseif Step == "EntranceKeypad" then
if not exports['projectx-bridge']:MinigameCheck("SN-Hacking") then p:resolve(false) return Citizen.Await(p) end
local success = exports['SN-Hacking']:Thermite(7, 5, 10000, 2, 2, 3000)
p:resolve(success)
elseif Step == "MainKeypad" then
if not exports['projectx-bridge']:MinigameCheck("SN-Hacking") then p:resolve(false) return Citizen.Await(p) end
local success = exports['SN-Hacking']:MemoryCards('hard')
p:resolve(success)
end
return Citizen.Await(p)
end)
```
You can return `true` unconditionally inside any step block to skip that minigame entirely.
The default minigames per step are:
| Step | Minigame Resource | Function |
| ------------------------ | ----------------- | ---------------- |
| `C4Entrance` | `lightsout` | `StartLightsOut` |
| `EntranceKeypad` | `SN-Hacking` | `Thermite` |
| `C4Security` | `lightsout` | `StartLightsOut` |
| `SecurityFingerprint` | `utk_fingerprint` | `Start` (event) |
| `SearchDesk` | `ox_lib` | `skillCheck` |
| `SearchBelongings` | `ox_lib` | `skillCheck` |
| `ComputerDesk` | `SN-Hacking` | `Thermite` |
| `SmokeHallway` | `lightsout` | `StartLightsOut` |
| `MainKeypad` | `SN-Hacking` | `MemoryCards` |
| `Fusebox` | `ox_lib` | `skillCheck` |
| `SurveillanceRoomKeypad` | `SN-Hacking` | `Thermite` |
| `Computer` | `SN-Hacking` | `MemoryCards` |
| `C4Vault` | `lightsout` | `StartLightsOut` |
| `VaultPanel` | `SN-Hacking` | `ColorPicker` |
| `Crate` | `ox_lib` | `skillCheck` |
***
## opensource/server/server.lua
### Hooks
Called whenever a player successfully completes a robbery step. Step names are listed in `Config.BobcatSteps` inside `config/config.lua`.
Called whenever a player fails a robbery step.
Called before a player can start the robbery. Return `false` to block them.
Called whenever the heist resets.
See the [K4MB1 Bobcat Open Source](/resources/bobcat-heist-k4mb1/opensource) page for full hook examples.
# Commands
Source: https://docs.projectx.gg/resources/bobcat-heist-gabz/commands
Admin commands for the Gabz Bobcat Heist resource
## Admin Commands
**Usage**: `/projectxbobcatgabz`
**Permission**: Admin (configurable via `CheckPerms` in the bridge)
**Description**: Forces a full heist reset, unlocking doors and clearing any active robbery state. Useful for testing or recovering from a stuck robbery.
**Example**:
```
/projectxbobcatgabz
```
This command internally calls the `Reset()` export. See the [Exports](/resources/bobcat-heist-gabz/exports) page for details.
# Configuration
Source: https://docs.projectx.gg/resources/bobcat-heist-gabz/configuration
Full reference for all configuration options in the Gabz Bobcat Heist resource
## config/config.lua
The Gabz Bobcat Heist uses the same configuration structure as the [K4MB1 Bobcat Heist](/resources/bobcat-heist-k4mb1/configuration). All options below apply to both variants — only map coordinates and door definitions differ.
### Main Settings
Shows polyzones created inside the game.
Disables all minigames for flow testing.
Minutes before the heist resets after a completed robbery.
Disables the loud approach path entirely.
Disables the silent approach path entirely.
Disables client-side explosions during C4 steps.
Requires a `bag` item to loot trolleys.
Minimum police required online. Set to `0` to disable.
***
### Strike System
Maximum trolleys that can spawn.
Strike limit before rewards are reduced (silent approach).
Trolleys removed when strike limit is reached (silent).
Trolleys spawned during loud approach.
Maximum weapon crates that can spawn.
Crates removed when strike limit is reached (silent).
Crates spawned during loud approach.
***
### Dispatch
```lua theme={null}
DispatchLocation = {
["Loud"] = true,
["Silent"] = false,
["SecurityFingerprint"] = false,
["ComputerDesk"] = false,
["MainKeypad"] = true,
}
```
***
### Rewards, Security & Logs
Trolley and crate rewards, security guard settings, computer password ranges, bonus items, evidence/stress, and logging are configured identically to the K4MB1 variant. See the [K4MB1 Bobcat Configuration](/resources/bobcat-heist-k4mb1/configuration) page for the full reference on:
* `Config.Rewardcash`, `Config.Rewardgold`, `Config.Rewarddiamond`
* `Config.CrateRewards` and `Config.CrateItemCount`
* `Config.SecurityGuards` and `Config.SecurityOptions`
* `Config.ComputerPassword`
* `config/logs.lua`
# Exports
Source: https://docs.projectx.gg/resources/bobcat-heist-gabz/exports
Server-side exports available for the Gabz Bobcat Heist resource
## Server Exports
### Reset
Resets the heist, unlocking the facility and clearing any active robbery state.
```lua theme={null}
exports['projectx-bobcatheist-gabz']:Reset()
```
### IsRobberyInitiated
Returns whether a robbery is currently active.
```lua theme={null}
local active = exports['projectx-bobcatheist-gabz']:IsRobberyInitiated()
```
**Returns**
* `active` (boolean) - `true` if a robbery is in progress, `false` otherwise
**Example**
```lua theme={null}
local active = exports['projectx-bobcatheist-gabz']:IsRobberyInitiated()
if active then
print("A robbery is currently in progress")
end
```
# FAQs
Source: https://docs.projectx.gg/resources/bobcat-heist-gabz/faqs
Frequently asked questions about the Gabz Bobcat Heist resource
## General Questions
Yes. This variant requires the Gabz Bobcat MLO from the [Gabz subscription store](https://fivem.gabzv.com/category/subscription).
Yes. See the [Bridge Installation](/resources/bridge/installation) page for setup instructions.
The gameplay, items, and configuration options are the same. This version is mapped to the Gabz Bobcat interior with Gabz-specific door coordinates in `Config.DoorList`.
Use `/projectxbobcatgabz` or call:
```lua theme={null}
exports['projectx-bobcatheist-gabz']:Reset()
```
Edit `opensource/client/client.lua` — see the [Open Source](/resources/bobcat-heist-gabz/opensource) page.
## Troubleshooting
Ensure `projectx-bridge`, `ox_lib`, `mka-lasers`, and all minigames from the zip are started before `projectx-bobcatheist-gabz`.
# Installation
Source: https://docs.projectx.gg/resources/bobcat-heist-gabz/installation
Step by step instructions to install the Gabz Bobcat Heist resource
## Installation Steps
Verify all dependencies below are started **before** this script in your `server.cfg`. Start order should be: Dispatch → Bridge → Minigames → Script.
Download ox\_lib
Required Gabz Bobcat MLO (subscription)
Required Project X Bridge
Download the minigames zip and place each resource into your standalone or dependencies folder.
Download and place in your standalone or minigames folder
Make sure the minigames are **not** in the same folder as the robbery script.
Extract the script from the zip file and place it into your scripts folder.
Add the required items and their images to your inventory resource. See the [items section](#items-required) below for the full list.
Item images done by [Artwork Inventory](https://discord.gg/Z2awpnXKdw) - Use code **ProjectX** for 10% off!
Open `config/config.lua` and adjust the settings to match your server. The bridge handles framework, inventory, dispatch, and interaction automatically if set to `'auto'`.
Make sure the bridge, ox\_lib, your target, dispatch, inventory, minigames, and `mka-lasers` are all started before the robbery script.
```cfg theme={null}
ensure ox_lib
ensure projectx-bridge
ensure mka-lasers
ensure lightsout
ensure SN-Hacking
ensure utk_fingerprint
ensure projectx-bobcatheist-gabz
```
## Items Required
### Items Required from Outside the Robbery
The `bobcatcard2` must be obtained externally (e.g. from another robbery or side mission) before the heist can be started.
* `bobcatcard2`
### Items Required from Shop/Black Market
* `x_device`
* `x_phone`
* `pliers`
* `bag`
The rest of the items (`bobcatcard`, C4, smoke grenades, etc.) are obtained within the heist itself.
### Item Configuration
```lua theme={null}
["x_device"] = {
label = "Flapper Hero",
weight = 125,
stack = false,
close = false,
description = "?????????",
},
["bag"] = {
label = "Duffel Bag",
weight = 250,
stack = false,
close = false,
description = "Duffel bag",
},
["pliers"] = {
label = "Pliers",
weight = 125,
stack = false,
close = false,
description = "A pair of pliers",
},
["x_phone"] = {
label = "x Phone",
weight = 300,
stack = false,
close = false,
description = "?????????",
},
["bobcatcard"] = {
label = "Bobcat Keycard A",
weight = 50,
stack = false,
close = false,
description = "A Security card for Bobcat",
},
["bobcatcard2"] = {
label = "Bobcat Keycard B",
weight = 50,
stack = false,
close = false,
description = "A Security card for Bobcat",
},
```
```lua theme={null}
['x_device'] = {['name'] = 'x_device', ['label'] = 'X Device', ['weight'] = 50, ['type'] = 'item', ['image'] = 'x_device.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '?????????'},
['bag'] = {['name'] = 'bag', ['label'] = 'Bag', ['weight'] = 400, ['type'] = 'item', ['image'] = 'bag.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'Duffel bag'},
['pliers'] = {['name'] = 'pliers', ['label'] = 'Pliers', ['weight'] = 200, ['type'] = 'item', ['image'] = 'pliers.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'Pliers..?'},
['x_phone'] = {['name'] = 'x_phone', ['label'] = 'X Phone', ['weight'] = 50, ['type'] = 'item', ['image'] = 'x_phone.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '?????????'},
['bobcatcard'] = {['name'] = 'bobcatcard', ['label'] = 'Bobcat Keycard A', ['weight'] = 200, ['type'] = 'item', ['image'] = 'bobcatcard.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = ''},
['bobcatcard2'] = {['name'] = 'bobcatcard2', ['label'] = 'Bobcat Keycard B', ['weight'] = 200, ['type'] = 'item', ['image'] = 'bobcatcard2.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = ''},
```
# Open Source
Source: https://docs.projectx.gg/resources/bobcat-heist-gabz/opensource
Open source files available for customization in the Gabz Bobcat Heist resource
Most of the core logic in this resource is handled by the bridge. The open source files are provided so you can customize minigames, add hooks for custom systems, and extend the script without touching escrow.
## opensource/client/client.lua
This file handles zone creation, drawtext, evidence, stress, and the minigame callback.
### Minigame Callback
Each robbery step triggers the `projectx-bobcatheist-gabz:client:Minigames` callback with the step name.
```lua theme={null}
lib.callback.register('projectx-bobcatheist-gabz:client:Minigames', function(Step)
local p = promise.new()
if Step == "C4Entrance" then
if not exports['projectx-bridge']:MinigameCheck("lightsout") then p:resolve(false) return Citizen.Await(p) end
local success = exports['lightsout']:StartLightsOut(4, 20)
p:resolve(success)
elseif Step == "EntranceKeypad" then
if not exports['projectx-bridge']:MinigameCheck("SN-Hacking") then p:resolve(false) return Citizen.Await(p) end
local success = exports['SN-Hacking']:Thermite(7, 5, 10000, 2, 2, 3000)
p:resolve(success)
elseif Step == "MainKeypad" then
if not exports['projectx-bridge']:MinigameCheck("SN-Hacking") then p:resolve(false) return Citizen.Await(p) end
local success = exports['SN-Hacking']:MemoryCards('hard')
p:resolve(success)
end
return Citizen.Await(p)
end)
```
You can return `true` unconditionally inside any step block to skip that minigame entirely.
The default minigames per step are:
| Step | Minigame Resource | Function |
| ------------------------ | ----------------- | ---------------- |
| `C4Entrance` | `lightsout` | `StartLightsOut` |
| `EntranceKeypad` | `SN-Hacking` | `Thermite` |
| `C4Security` | `lightsout` | `StartLightsOut` |
| `SecurityFingerprint` | `utk_fingerprint` | `Start` (event) |
| `SearchDesk` | `ox_lib` | `skillCheck` |
| `SearchBelongings` | `ox_lib` | `skillCheck` |
| `ComputerDesk` | `SN-Hacking` | `Thermite` |
| `SmokeHallway` | `lightsout` | `StartLightsOut` |
| `MainKeypad` | `SN-Hacking` | `MemoryCards` |
| `Fusebox` | `ox_lib` | `skillCheck` |
| `SurveillanceRoomKeypad` | `SN-Hacking` | `Thermite` |
| `Computer` | `SN-Hacking` | `MemoryCards` |
| `C4Vault` | `lightsout` | `StartLightsOut` |
| `VaultPanel` | `SN-Hacking` | `ColorPicker` |
| `Crate` | `ox_lib` | `skillCheck` |
***
## opensource/server/server.lua
### Hooks
Called whenever a player successfully completes a robbery step. Step names are listed in `Config.BobcatSteps` inside `config/config.lua`.
Called whenever a player fails a robbery step.
Called before a player can start the robbery. Return `false` to block them.
Called whenever the heist resets.
See the [K4MB1 Bobcat Open Source](/resources/bobcat-heist-k4mb1/opensource) page for full hook examples — the server hook structure is identical across Bobcat variants.
# Commands
Source: https://docs.projectx.gg/resources/bobcat-heist-k4mb1/commands
Admin commands for the K4MB1 Bobcat Heist resource
## Admin Commands
**Usage**: `/projectxbobcatk4mb1`
**Permission**: Admin (configurable via `CheckPerms` in the bridge)
**Description**: Forces a full heist reset, unlocking doors and clearing any active robbery state. Useful for testing or recovering from a stuck robbery.
**Example**:
```
/projectxbobcatk4mb1
```
This command internally calls the `Reset()` export. You can also trigger a reset programmatically from another resource using that export. See the [Exports](/resources/bobcat-heist-k4mb1/exports) page for details.
# Configuration
Source: https://docs.projectx.gg/resources/bobcat-heist-k4mb1/configuration
Full reference for all configuration options in the K4MB1 Bobcat Heist resource
## config/config.lua
### Main Settings
Shows polyzones created inside the game. Useful for testing zone placement.
Disables all minigames. Useful for testing the full heist flow without completing minigame challenges.
Time in minutes before the heist resets and becomes available to rob again after a completed robbery.
The key code used to trigger drawtext interactions. `38` is `[E]` by default.
The size of the drawtext interaction zone.
The rotation of the drawtext interaction zone.
Disables the loud approach path entirely.
Disables the silent approach path entirely.
Disables all particle effects during the robbery.
Disables client-side explosions. Set to `false` only if your anticheat allows explosion events.
Disables damage dealt by lasers in the vault area.
Disables weapon removal during the robbery. Only enable this if you use a weapon wheel resource.
Door indices from `Config.DoorList` to unlock after the robbery starts, adding extra entry/exit options for criminals and police.
```lua theme={null}
UnlockAllEntrances = {1, 2, 3}
```
Spawns networked props server side. Set to `false` to spawn them client side instead.
Spawns networked peds server side. Set to `false` to spawn them client side instead.
Requires players to have a `bag` item in order to loot the trolleys.
Minimum number of police required online before the robbery can be started. Set to `0` to disable.
The jobs that count as police for the `MinimumPolice` check and dispatch alerts.
```lua theme={null}
PoliceJobs = {"police", "fbi"}
```
Requires a minimum number of players nearby to start the robbery.
```lua theme={null}
RequiredPlayersNearby = {amount = 0, radius = 20.0}
```
Set `amount` to `0` or `false` to disable.
***
### Cooldowns & Limits
Per-player cooldown in minutes after completing a robbery. Set to `0` to disable.
Maximum number of total robberies allowed per server restart. Set to `0` to disable.
Maximum number of robberies a single player can complete per server restart. Set to `0` to disable.
***
### Strike System
Maximum number of trolleys that can spawn. Actual count depends on the strike system and approach used.
Number of strikes players can accumulate before their reward is cut.
(Silent Approach only) Number of trolleys removed from the reward when the strike limit is reached.
(Loud Approach only) Number of trolleys that spawn during a loud approach.
Maximum number of weapon crates that can spawn.
(Silent Approach only) Number of crates removed when the strike limit is reached.
(Loud Approach only) Number of crates that spawn during a loud approach.
***
### Skill System
Requires players to meet a minimum level from an integrated XP/skill system before starting the heist. Must have an XP system configured in the bridge.
Minimum level required to initiate the heist. Only applies when `SkillSystem` is `true`.
***
### Dispatch
Title shown in the dispatch alert.
Message body shown in the dispatch alert.
Radio code shown in the dispatch alert.
Time in seconds the dispatch alert remains visible. Not all dispatch systems support this.
Blip settings for the dispatch map marker.
```lua theme={null}
Blip = {
Text = 'Bobcat Robbery',
Color = 1,
Sprite = 41,
Scale = 0.8
}
```
Controls which step triggers the dispatch alert. Only one should be enabled at a time (excluding `Loud` and `Silent`).
```lua theme={null}
DispatchLocation = {
["Loud"] = true,
["Silent"] = false,
["SecurityFingerprint"] = false,
["ComputerDesk"] = false,
["MainKeypad"] = true,
}
```
***
### Computer Password
Random code range for the main computer password prompt.
Random code range for the first half of the split password.
Random code range for the second half of the split password.
***
### Bonus Items
Enables or disables bonus item drops at the end of the heist.
Percentage chance that any bonus item is given at all.
Number of items that can be given from the bonus items table.
Table of possible bonus items. Each entry has a `Name`, `Chance` (%), and `Amount` range.
```lua theme={null}
Items = {
{Name = "x_device", Chance = 30, Amount = {min = 1, max = 1}},
{Name = "x_phone", Chance = 50, Amount = {min = 1, max = 1}},
{Name = "x_stethoscope", Chance = 20, Amount = {min = 1, max = 1}},
}
```
***
### Evidence & Stress
Enables fingerprint evidence drops at the crime scene.
Percentage chance that fingerprint evidence is left behind.
Enables the stress system. Stress is only applied when a minigame is failed.
Percentage chance that stress is applied on a minigame fail.
The minimum and maximum amount of stress applied per failure.
***
### Items & Break Chance
Item names used throughout the heist are mapped in `Config.Items`. Break chances on use are set in `Config.ItemsBreak`.
```lua theme={null}
Config.Items = {
["C4"] = "weapon_stickybomb",
["Pliers"] = "pliers",
["Device"] = "x_device",
["Phone"] = "x_phone",
["Bag"] = "bag",
["Keycard"] = "bobcatcard",
["Keycard2"] = "bobcatcard2",
}
```
***
### Rewards
Trolley rewards (`Config.Rewardcash`, `Config.Rewardgold`, `Config.Rewarddiamond`) follow the same format as other Project X heists. Crate weapon rewards are configured in `Config.CrateRewards` with `Config.CrateItemCount` controlling how many items drop per crate.
If `true`, items are given per individual pickup from the trolley. If `false`, the reward is given at the end of the full trolley animation.
Set to `true` to give money directly. Set to `false` to give a cash item instead.
The item name used when `Cash` is `false`.
The minimum and maximum cash or item amount per pickup or per trolley completion.
***
### Security Guards
List of armed guard peds spawned during the heist. Each entry supports `Status`, `Model`, `Coords`, `Weapon`, and `Ammo`.
Global combat settings applied to all security guard peds (`MaxHealth`, `Health`, `Armour`, `Accuracy`, etc.).
***
### Sounds
World position where the alarm sound plays.
How long the alarm lasts, in minutes.
***
### Logs
Configured in `config/logs.lua`.
Enables or disables the logging system.
Your Discord webhook URL, or your Fivemerr/Fivemanage API key.
The Fivemanage dataset to log activity to. Leave as `"default"` unless you have a specific dataset configured.
# Exports
Source: https://docs.projectx.gg/resources/bobcat-heist-k4mb1/exports
Server-side exports available for the K4MB1 Bobcat Heist resource
## Server Exports
### Reset
Resets the heist, unlocking the facility and clearing any active robbery state. Useful for admin commands or external integrations.
```lua theme={null}
exports['projectx-bobcatheist-k4mb1']:Reset()
```
### IsRobberyInitiated
Returns whether a robbery is currently active.
```lua theme={null}
local active = exports['projectx-bobcatheist-k4mb1']:IsRobberyInitiated()
```
**Returns**
* `active` (boolean) - `true` if a robbery is in progress, `false` otherwise
**Example**
```lua theme={null}
local active = exports['projectx-bobcatheist-k4mb1']:IsRobberyInitiated()
if active then
print("A robbery is currently in progress")
end
```
# FAQs
Source: https://docs.projectx.gg/resources/bobcat-heist-k4mb1/faqs
Frequently asked questions about the K4MB1 Bobcat Heist resource
## General Questions
The script supports QBCore, Qbox, and ESX through the Project X Bridge. Set `Framework` to `'auto'` in the bridge config and it will detect your framework automatically.
Yes. The bridge is required for this script to function. It handles framework detection, inventory, dispatch, notifications, progressbars, XP, evidence, logs, and global cooldowns. See the [Bridge Installation](/resources/bridge/installation) page for setup instructions.
When you purchase Bobcat Heist, the `projectx-bridge` asset is automatically delivered to your CFX portal.
The bridge supports 25+ dispatch systems including PS Dispatch, CodeSign, LB Tablet, FD Dispatch, Wasabi MDT, Sonoran CAD, and many more. Set `Dispatch` to `'auto'` in the bridge config for automatic detection. See the [Bridge Overview](/resources/bridge/overview) for the full list.
The silent approach is higher risk but offers a higher potential reward. Failing minigames during silent accumulates strikes, which reduce the number of trolleys and crates available at the end. The loud approach is lower risk with fixed counts controlled by `StrikeLoud` and `CrateStrikeLoud`.
Open `opensource/client/client.lua` and find the `projectx-bobcatheist-k4mb1:client:Minigames` callback. Each robbery step has its own `elseif` block where you can swap the minigame export for any resource you prefer. You can also return `true` inside any block to skip that minigame entirely.
See the [Open Source](/resources/bobcat-heist-k4mb1/opensource) page for the full callback code and a table of the default minigame assignments.
Use the `/projectxbobcatk4mb1` in-game command (requires admin permissions), or call the `Reset()` server export from another resource:
```lua theme={null}
exports['projectx-bobcatheist-k4mb1']:Reset()
```
See the [Commands](/resources/bobcat-heist-k4mb1/commands) and [Exports](/resources/bobcat-heist-k4mb1/exports) pages for more details.
## Configuration Questions
Set `MinimumPolice` to the number you want in `config/config.lua`, and make sure the correct jobs are listed in `PoliceJobs`.
```lua theme={null}
MinimumPolice = 2,
PoliceJobs = {"police", "fbi"},
```
Set `SkillSystem` to `true` and configure `MinimumLevel` in `config/config.lua`. You also need a compatible XP system integrated in the bridge config (`XPSystem`).
Supported systems include `pickle_xp`, `sd-levels`, `cw-rep`, and `OT_skills`.
Edit the `SecurityGuards` table in `config/config.lua`. Each entry supports `Status`, `Model`, `Coords`, `Weapon`, and `Ammo`. Global ped behavior is controlled by `SecurityOptions`.
## Troubleshooting
Make sure you have all required dependencies started before the script in your `server.cfg` (`projectx-bridge`, `ox_lib`, `mka-lasers`, and minigames).
# Installation
Source: https://docs.projectx.gg/resources/bobcat-heist-k4mb1/installation
Step by step instructions to install the K4MB1 Bobcat Heist resource
## Installation Steps
Verify all dependencies below are started **before** this script in your `server.cfg`.
Download ox\_lib
Required map by K4MB1
Required Project X Bridge
Download the minigames zip and place each resource into your standalone or dependencies folder.
Download and place in your standalone or minigames folder
Make sure the minigames are **not** in the same folder as the robbery script.
Extract the script from the zip file and place it into your scripts folder.
Add the required items and their images to your inventory resource. See the [items section](#items-required) below for the full list.
Item images done by [Artwork Inventory](https://discord.gg/Z2awpnXKdw) - Use code **ProjectX** for 10% off!
Open `config/config.lua` and adjust the settings to match your server. The bridge handles framework, inventory, dispatch, and interaction automatically if set to `'auto'`.
Make sure the bridge, ox\_lib, your target, dispatch, inventory, minigames, and `mka-lasers` are all started before the robbery script.
```cfg theme={null}
ensure ox_lib
ensure projectx-bridge
ensure mka-lasers
ensure lightsout
ensure SN-Hacking
ensure utk_fingerprint
ensure projectx-bobcatheist-k4mb1
```
## Items Required
### Items Required from Outside the Robbery
The `bobcatcard2` must be obtained externally (e.g. from another robbery or side mission) before the heist can be started.
* `bobcatcard2`
### Items Required from Shop/Black Market
* `x_device`
* `x_phone`
* `pliers`
* `bag`
The rest of the items (`bobcatcard`, C4, smoke grenades, etc.) are obtained within the heist itself.
### Item Configuration
```lua theme={null}
["x_device"] = {
label = "Flapper Hero",
weight = 125,
stack = false,
close = false,
description = "?????????",
},
["bag"] = {
label = "Duffel Bag",
weight = 250,
stack = false,
close = false,
description = "Duffel bag",
},
["pliers"] = {
label = "Pliers",
weight = 125,
stack = false,
close = false,
description = "A pair of pliers",
},
["x_phone"] = {
label = "x Phone",
weight = 300,
stack = false,
close = false,
description = "?????????",
},
["bobcatcard"] = {
label = "Bobcat Keycard A",
weight = 50,
stack = false,
close = false,
description = "A Security card for Bobcat",
},
["bobcatcard2"] = {
label = "Bobcat Keycard B",
weight = 50,
stack = false,
close = false,
description = "A Security card for Bobcat",
},
```
```lua theme={null}
['x_device'] = {['name'] = 'x_device', ['label'] = 'X Device', ['weight'] = 50, ['type'] = 'item', ['image'] = 'x_device.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '?????????'},
['bag'] = {['name'] = 'bag', ['label'] = 'Bag', ['weight'] = 400, ['type'] = 'item', ['image'] = 'bag.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'Duffel bag'},
['pliers'] = {['name'] = 'pliers', ['label'] = 'Pliers', ['weight'] = 200, ['type'] = 'item', ['image'] = 'pliers.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'Pliers..?'},
['x_phone'] = {['name'] = 'x_phone', ['label'] = 'X Phone', ['weight'] = 50, ['type'] = 'item', ['image'] = 'x_phone.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '?????????'},
['bobcatcard'] = {['name'] = 'bobcatcard', ['label'] = 'Bobcat Keycard A', ['weight'] = 200, ['type'] = 'item', ['image'] = 'bobcatcard.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = ''},
['bobcatcard2'] = {['name'] = 'bobcatcard2', ['label'] = 'Bobcat Keycard B', ['weight'] = 200, ['type'] = 'item', ['image'] = 'bobcatcard2.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = ''},
```
# Open Source
Source: https://docs.projectx.gg/resources/bobcat-heist-k4mb1/opensource
Open source files available for customization in the K4MB1 Bobcat Heist resource
Most of the core logic in this resource is handled by the bridge. The open source files are provided so you can customize minigames, add hooks for custom systems, and extend the script without touching escrow.
## opensource/client/client.lua
This file handles zone creation, drawtext, evidence, stress, and most importantly, the minigame callback. If you want to change the minigames used for each step, this is the only file you need to edit.
### Minigame Callback
Each robbery step triggers the `projectx-bobcatheist-k4mb1:client:Minigames` callback with the step name. You can swap any minigame by replacing the export call inside the matching `elseif` block.
```lua theme={null}
lib.callback.register('projectx-bobcatheist-k4mb1:client:Minigames', function(Step)
local p = promise.new()
if Step == "C4Entrance" then
if not exports['projectx-bridge']:MinigameCheck("lightsout") then p:resolve(false) return Citizen.Await(p) end
local success = exports['lightsout']:StartLightsOut(4, 20)
p:resolve(success)
elseif Step == "EntranceKeypad" then
if not exports['projectx-bridge']:MinigameCheck("SN-Hacking") then p:resolve(false) return Citizen.Await(p) end
local success = exports['SN-Hacking']:Thermite(7, 5, 10000, 2, 2, 3000)
p:resolve(success)
elseif Step == "SecurityFingerprint" then
if not exports['projectx-bridge']:MinigameCheck("utk_fingerprint") then p:resolve(false) return Citizen.Await(p) end
TriggerEvent("utk_fingerprint:Start", 4, 6, 2, function(success)
p:resolve(success)
end)
elseif Step == "MainKeypad" then
if not exports['projectx-bridge']:MinigameCheck("SN-Hacking") then p:resolve(false) return Citizen.Await(p) end
local success = exports['SN-Hacking']:MemoryCards('hard')
p:resolve(success)
elseif Step == "VaultPanel" then
if not exports['projectx-bridge']:MinigameCheck("SN-Hacking") then p:resolve(false) return Citizen.Await(p) end
local success = exports['SN-Hacking']:ColorPicker(5, 7000, 3000)
p:resolve(success)
end
return Citizen.Await(p)
end)
```
You can return `true` unconditionally inside any step block to skip that minigame entirely. This can be useful for testing or for steps you want to make automatic.
The default minigames per step are:
| Step | Minigame Resource | Function |
| ------------------------ | ----------------- | ---------------- |
| `C4Entrance` | `lightsout` | `StartLightsOut` |
| `EntranceKeypad` | `SN-Hacking` | `Thermite` |
| `C4Security` | `lightsout` | `StartLightsOut` |
| `SecurityFingerprint` | `utk_fingerprint` | `Start` (event) |
| `SearchDesk` | `ox_lib` | `skillCheck` |
| `SearchBelongings` | `ox_lib` | `skillCheck` |
| `ComputerDesk` | `SN-Hacking` | `Thermite` |
| `SmokeHallway` | `lightsout` | `StartLightsOut` |
| `MainKeypad` | `SN-Hacking` | `MemoryCards` |
| `Fusebox` | `ox_lib` | `skillCheck` |
| `SurveillanceRoomKeypad` | `SN-Hacking` | `Thermite` |
| `Computer` | `SN-Hacking` | `MemoryCards` |
| `C4Vault` | `lightsout` | `StartLightsOut` |
| `VaultPanel` | `SN-Hacking` | `ColorPicker` |
| `Crate` | `ox_lib` | `skillCheck` |
***
## opensource/server/server.lua
This file handles dispatch, item/money functions, logging, and exposes several hooks you can use to run custom logic at specific points in the robbery.
### Hooks
Called whenever a player successfully completes a robbery step. Use this to award XP, trigger events, or log individual step completions.
```lua theme={null}
function SuccessfulStep(source, step)
if step == "EntranceKeypad" then
-- exports['projectx-bridge']:AddExperience(source, 'criminal', 10)
end
end
```
All available step names can be found in `Config.BobcatSteps` inside `config/config.lua`.
Called whenever a player fails a robbery step. Use this to remove XP, items, or apply penalties.
```lua theme={null}
function FailedStep(source, step)
if step == "EntranceKeypad" then
-- RemoveItem(source, 'x_device', 1)
end
end
```
Called before a player can start the robbery. Return `false` to block them.
```lua theme={null}
function InitialCheck(Interaction)
return true
-- Add a group check, tablet requirement, or any other gate here
end
```
Called whenever the heist resets. Use this to update a scoreboard, trigger an external event, or notify players.
```lua theme={null}
function RobberyResetHook()
-- TriggerEvent('my-scoreboard:update')
end
```
# Installation
Source: https://docs.projectx.gg/resources/bridge/installation
Step by step instructions to install and configure the Project X Bridge
## Installation Steps
Verify all dependencies below are started **before** this script in your `server.cfg`.
Download ox\_lib
The bridge is provided **free with the purchase** of any script that requires it.
1. Go to your [CFX Portal - Granted Assets](https://portal.cfx.re/assets/granted-assets?page=1\&sort=asset.updated_at\&direction=asc\&search=projectx-bridge)
2. Search for `projectx-bridge`
3. Download and extract the resource
If you don't see the bridge in your portal, make sure you have purchased a script that includes it. The asset is granted automatically with those purchases.
Extract the bridge from the zip file and place it into your standalone folder or a folder that is started **before** your Project X scripts.
Open `config/config.lua` and adjust the settings to match your server setup. See the [configuration](#configuration) section below.
Most settings support `'auto'` which will automatically detect your resources at startup.
Add the bridge **before** any script that depends on it:
```cfg theme={null}
ensure ox_lib
ensure projectx-bridge
ensure projectx-sandybankrobbery-prompt
ensure projectx-ammunationrobbery-tstudio
```
The bridge must be started **before** any script that depends on it in your `server.cfg`. Scripts will fail to load if the bridge is not running.
## Configuration
Below is the full configuration with explanations for every option.
```lua theme={null}
Config = {
Lan = 'en',
Framework = 'auto',
ESX = "new",
Inventory = "auto",
Notification = "ox",
Progressbar = "ox",
XPSystem = "auto",
Interaction = "auto",
Drawtext = "ox",
Evidence = "auto",
LogsService = "discord",
Dispatch = "auto",
GlobalCooldownDuration = 15,
EnableGlobalCooldown = {
["projectx-sandybankrobbery-prompt"] = false,
["projectx-ammunationrobbery-tstudio"] = false,
["projectx-ammunationrobbery-fm"] = false,
-- ... all other scripts
}
}
```
### Core Settings
The language for all scripts using the bridge. Supported values: `en`, `pl`, `de`, `da`, `fr`, `in`, `am`, `ph`, `no`, `nl`, `ja`, `ru`, `gr`, `se`, `lt`, `ar`, `bg`, `bs`, `cn`, `cs`, `ee`, `es`, `et`, `fa`, `fi`, `ge`, `he`, `hu`, `id`, `is`, `it`, `lv`, `pt`, `pt-br`, `ro`, `rs`, `sl`, `sv`, `th`, `tr`, `vn`
Your server framework. Use `'auto'` to detect automatically, or set manually:
* `'qbox'` - Qbox
* `'qb-core'` - QBCore
* `'esx'` - ESX
* `'custom'` - Custom (requires editing the open source functions)
ESX version, only relevant if you are using ESX as your framework:
* `'new'` - ESX 1.5+
* `'old'` - ESX 1.4 and below
Your inventory system. Use `'auto'` to detect automatically, or set manually:
* `'ox'` - ox\_inventory
* `'qb'` - qb-inventory
* `'ps'` / `'lj'` - ps-inventory / lj-inventory
* `'codem'` - codem-inventory
* `'origen'` - origen\_inventory
* `'tgiann'` - tgiann-inventory
* `'ak47'` - ak47\_inventory (Menan AK 47 Inventory)
* `'jpr'` - jpr-inventory (JP Resources Inventory)
* `'one'` - one\_inventory (One Inventory)
* `'esx'` - ESX default inventory
* `'other'` - Custom (requires editing the open source inventory export)
See the [FAQs](/faqs) for links to each inventory resource.
Notification system to use:
* `'ox'` - ox\_lib notifications
* `'qb'` - QBCore notifications
* `'esx'` - ESX notifications
Progress bar system to use:
* `'ox'` - ox\_lib progress circle
* `'qb'` - QBCore progressbar
XP/skills system. Use `'auto'` to detect automatically, or set manually:
* `'projectx'` - projectx-xp
* `'pickle'` - pickle\_xp
* `'sd-levels'` - sd-levels
* `'cw-rep'` - cw-rep
* `'ot_skills'` - OT\_skills
* `'none'` - No XP system
Interaction/target system. Use `'auto'` to detect automatically, or set manually:
* `'ox_target'` - ox\_target
* `'qb-target'` - qb-target
* `'interact'` - World Interact (darktrovx/interact)
* `'drawtext'` - Drawtext fallback (no target system)
Drawtext system used when Interaction is set to `'drawtext'`:
* `'ox'` - ox\_lib TextUI
* `'qb'` - QBCore DrawText
* `'OLDQB'` - qb-drawtext (legacy)
Evidence system for fingerprint drops. Use `'auto'` to detect automatically, or set manually:
* `'qbx_police'` / `'qb-police'`
* `'wasabi'` - wasabi\_evidence
* `'snipe'` - snipe-evidence
* `'dlab'` - d\_labs\_evidence
* `'tk'` - tk\_evidence
* `'dusa'` - dusa\_evidence
* `'r14'` - r14-evidence
* `'kartik'` - kartik-evidence
* `'none'` - Disabled
Logging service for script activity:
* `'discord'` - Discord webhooks
* `'fivemerr'` - Fivemerr
* `'fivemanage'` - Fivemanage
* `'custom'` - Custom (requires editing the open source logs function)
Dispatch system. Use `'auto'` to detect automatically, or set manually using one of the config values below. See the [FAQs](/faqs) for the full list with resource links.
Supported config values: `cd`, `cd3d`, `ps`, `fd`, `outlaw`, `codem`, `five-dispatch`, `qf`, `aty`, `zat-mdt`, `opto`, `kartik`, `brutal`, `origen`, `tk`, `rcore`, `lb`, `redutzu`, `lg`, `vx`, `l2s`, `sonoran`, `piotreqv1`, `piotreqv2`, `pp-mdt`, `core`, `oxide`, `emergencydispatch`, `wasabimdt`, `nextscripts`, `kibra`, `imperial`
For unsupported dispatch systems:
* Set to `'customsv'` and edit `opensource/server.lua` for server-side dispatch
* Set to `'customcl'` and edit `opensource/client.lua` for client-side dispatch
### Global Cooldown
How long the global cooldown lasts in minutes. When a robbery is completed on a script that has the cooldown enabled, all other scripts with cooldowns enabled will be locked for this duration.
A table of resource names and whether the global cooldown applies to them. Set a script to `true` to include it in the global cooldown system, or `false` to exclude it.
```lua theme={null}
EnableGlobalCooldown = {
["projectx-sandybankrobbery-prompt"] = true,
["projectx-storerobbery-fmv2"] = true,
["projectx-ammunationrobbery-tstudio"] = true,
["projectx-bobcatheist-k4mb1"] = false,
["projectx-cashexchangerobbery-k4mb1"] = false,
-- See config.lua in projectx-bridge for the full list of script names
}
```
# Overview
Source: https://docs.projectx.gg/resources/bridge/overview
The Project X Bridge is a **shared resource** that acts as the compatibility layer between your server's resources (framework, inventory, dispatch, etc.) and Project X scripts. Instead of configuring each script individually, you configure the bridge once and every script that uses it inherits those settings automatically.
Set your framework, inventory, dispatch, and more in a single config file. All bridge-dependent scripts pick it up automatically.
Most settings support `'auto'` mode. The bridge scans your started resources and picks the correct system without manual setup.
A built-in cross-script cooldown system. Completing one robbery can lock others for a configurable duration, preventing farming.
Every integration function is open source. If your system isn't supported by default, you can add it yourself without touching escrow.
## What It Handles
The bridge manages the following systems across all dependent scripts:
| System | What it does |
| ------------------- | ------------------------------------------------------------------ |
| **Framework** | Player data, money, permissions (QBCore, Qbox, ESX) |
| **Inventory** | Item checks, adding and removing items |
| **Dispatch** | Sending police alerts to 30+ dispatch systems |
| **Interaction** | Door/zone interactions (ox\_target, qb-target, interact, drawtext) |
| **Notification** | Player notifications |
| **Progressbar** | Progress circles and bars |
| **XP System** | Experience and level integration |
| **Evidence** | Fingerprint drops at crime scenes |
| **Logs** | Discord, Fivemerr, and Fivemanage activity logging |
| **Global Cooldown** | Cross-script robbery cooldown system |
## Supported Scripts
The bridge is required by the following documented scripts. Configure compatibility once in the bridge — each script below inherits those settings automatically.
* [`projectx-sandybankrobbery-prompt`](/resources/sandy-bank-robbery/installation)
* [`projectx-fleecabankrobbery-default`](/resources/fleeca-bank-robbery-default/installation) (Default)
* [`projectx-fleecabankrobbery-k4mb1`](/resources/fleeca-bank-robbery-k4mb1/installation) (K4MB1)
* [`projectx-fleecabankrobbery-gabz`](/resources/fleeca-bank-robbery-gabz/installation) (Gabz)
* [`projectx-fleecabankrobbery-fmv2`](/resources/fleeca-bank-robbery-fmv2/installation) (FM V2)
* [`projectx-fleecabankrobbery-tstudio`](/resources/fleeca-bank-robbery-tstudio/installation) (TStudio)
* [`projectx-fleecabankrobbery-nteam`](/resources/fleeca-bank-robbery-nteam/installation) (NTeam)
* [`projectx-storerobbery-fmv2`](/resources/store-robbery-fmv2/installation) (FM V2)
* [`projectx-storerobbery-fm`](/resources/store-robbery-fm/installation) (FM)
* [`projectx-storerobbery-gabz`](/resources/store-robbery-gabz/installation) (Gabz)
* [`projectx-storerobbery-default`](/resources/store-robbery-default/installation) (Default)
* [`projectx-ammunationrobbery-fm`](/resources/ammunation-robbery-fm/installation) (FM)
* [`projectx-ammunationrobbery-tstudio`](/resources/ammunation-robbery-tstudio/installation) (TStudio)
* [`projectx-ammunationrobbery-prompt`](/resources/ammunation-robbery-prompt/installation) (Prompt)
* [`projectx-ammunationrobbery-gabz`](/resources/ammunation-robbery-gabz/installation) (Gabz)
* [`projectx-ammunationrobbery-default`](/resources/ammunation-robbery-default/installation) (Default)
* [`projectx-bobcatheist-k4mb1`](/resources/bobcat-heist-k4mb1/installation) (K4MB1)
* [`projectx-bobcatheist-gabz`](/resources/bobcat-heist-gabz/installation) (Gabz)
* [`projectx-bobcatheist-default`](/resources/bobcat-heist-default/installation) (Default)
* [`projectx-cashexchangerobbery-k4mb1`](/resources/cash-exchange-robbery-k4mb1/installation) (Cash Exchange 1)
* [`projectx-cashexchange2robbery-k4mb1`](/resources/cash-exchange-robbery-2-k4mb1/installation) (Cash Exchange 2)
* [`projectx-laundromatrobbery-k4mb1`](/resources/laundromat-robbery-k4mb1/installation) (K4MB1)
* [`projectx-atmrobbery`](/resources/atm-robbery/installation)
Other documented scripts — House Robbery V2, Tasks, Burner Phone, Masks, and Sell Shop — do **not** use the bridge and configure framework, inventory, and dispatch in their own config files. Project X XP integrates with the bridge when `XPSystem` is set to `'projectx'` or `'auto'`.
See [Supported integrations](/faqs) for the full list of compatible inventories, dispatch systems, evidence systems, and XP systems.
Future Project X releases will also use the bridge as the standard integration layer.
When purchasing any script that requires the bridge, the `projectx-bridge` asset will automatically be delivered to your [CFX portal](https://portal.cfx.re/assets/granted-assets?page=1\&sort=asset.updated_at\&direction=asc\&search=projectx-bridge). You do not need to purchase it separately.
## Getting Started
Download the bridge from your CFX portal and follow the step by step setup guide.
# Exports
Source: https://docs.projectx.gg/resources/burner-phone/exports
Available exports for the Burner Phone resource
## Client Exports
### SendMessage
Sends a message to a contact and automatically registers that contact in the local contact history if it does not already exist.
```lua theme={null}
exports['projectx-burner']:SendMessage(sender, message, duration)
```
Contact name or identifier
Message content to display
Message display duration in milliseconds
**Example**
```lua theme={null}
exports['projectx-burner']:SendMessage("Unknown Number", "Meet me at the docks.", 5000)
```
***
### OpenContact
Opens the message history for a specific contact and displays all previously received messages from that contact.
```lua theme={null}
exports['projectx-burner']:OpenContact(contact)
```
The contact name to open
**Example**
```lua theme={null}
exports['projectx-burner']:OpenContact("Unknown Number")
```
# FAQs
Source: https://docs.projectx.gg/resources/burner-phone/faqs
Frequently asked questions about the Burner Phone resource
No, the item is optional. It's only needed if you want to use the contacts history feature where players can view their message history. You can disable it by setting `ContactsHistory.EnableItem` to `false` in the config.
Contacts are automatically tracked when using the `SendMessage` export. You don't need to manually add contacts.
Yes, you can change the `Position` option in the config to either `"left"` or `"right"`.
You have two options:
* Set a higher value for `Duration` in the config (in seconds)
* Enable `DurationBasedOnLength` to automatically calculate duration based on message length
Yes, set `EnableProfilePics` to `false` in the config to hide the profile picture above the sender name.
The script supports QBX, QBCore, and ESX frameworks. You need ox\_lib as a dependency. You can also implement your own logic in `server.lua` for custom frameworks.
# Installation
Source: https://docs.projectx.gg/resources/burner-phone/installation
Step by step instructions to install the Burner Phone resource
## Installation Steps
Verify all dependencies below are started **before** this script in your `server.cfg`.
Download ox\_lib
Extract the script from the zip file and place it into your standalone folder or a folder that starts before your scripts.
Add the items from below and the images from the `images` folder to your inventory. This is optional if you want to use the contacts history feature.
```lua theme={null}
["x_burner"] = {
label = "Burner Phone",
weight = 100,
stack = false,
close = false,
description = "Nothing suspicious about this phone..",
}
```
```lua theme={null}
["x_burner"] = {["name"] = "x_burner", ["label"] = "Burner Phone", ["weight"] = 100, ["type"] = "item", ["image"] = "x_burner.png", ["unique"] = true, ["useable"] = false, ["shouldClose"] = true, ["combinable"] = nil, ["description"] = "To receive anonymous calls"},
```
The image is provided in the folder that you downloaded.
Open `config.lua` and adjust the settings to your liking. See the configuration section below for details.
Make sure that the Framework, ox\_lib, and Inventory are started before the script.
```cfg theme={null}
ensure ox_lib
ensure projectx-burner
```
## Configuration
Below is the full configuration file with explanations for each option.
```lua theme={null}
Config = Config or {}
Config = {
Position = 'right',
Duration = 10,
DurationBasedOnLength = false,
EnableProfilePics = true,
ContactsHistory = {
EnableItem = true,
NoContactsNotification = "You don't have any active contacts",
Duration = 15
}
}
```
### General Settings
The position of the phone on the screen. Options: `"left"` or `"right"`
Duration in seconds that the phone will stay on screen after receiving a message
If enabled, the duration will be calculated based on the length of the message instead of using the fixed `Duration` value
Enable or disable the profile picture displayed above the sender name
### Contacts History Settings
Enable the burner phone item for viewing contact history. If enabled, you need a supported framework (QBX, QB, ESX) or implement your own logic in `server.lua`. Don't forget to add the item to your inventory!
The notification message shown when the player has no active contacts (no messages received)
Duration in seconds that the contact history UI will stay open after selecting a contact
# Commands
Source: https://docs.projectx.gg/resources/cash-exchange-robbery-2-k4mb1/commands
Admin commands for the K4MB1 Cash Exchange 2 Robbery resource
## Admin Commands
**Usage**: `/projectxk4mb1cashexchange2`
**Permission**: Admin (configurable via `CheckPerms` in the bridge)
**Description**: Forces a full heist reset, unlocking the location and clearing any active robbery state.
**Example**:
```
/projectxk4mb1cashexchange2
```
This command internally calls the `Reset()` export. See the [Exports](/resources/cash-exchange-robbery-2-k4mb1/exports) page for details.
# Configuration
Source: https://docs.projectx.gg/resources/cash-exchange-robbery-2-k4mb1/configuration
Full reference for all configuration options in the K4MB1 Cash Exchange 2 Robbery resource
## config/config.lua
### Main Settings
Shows polyzones created inside the game.
Disables all minigames for flow testing.
Minutes before the heist resets after a completed robbery.
Disables the loud approach path entirely.
Disables the silent approach path entirely.
How long smoke particles last, in minutes.
Requires a `bag` item to loot trolleys.
Minimum police required online. Set to `0` to disable.
***
### Dispatch
```lua theme={null}
DispatchLocation = {
["Loud"] = true,
["Silent"] = false,
["Security"] = false,
["Key"] = false,
["Fusebox"] = true,
}
```
***
### Starting Point & NPCs
Legion Square contact NPC (`Npc`, `Model`, `Animation`).
Interior NPCs for security and employees.
***
### Rewards
Trolley cash rewards. Supports `ObtainPerPickup`, `Cash`, `Item`, and `StackAmount`.
Envelope prop rewards (`Prop1`, `Prop2`, `Prop3`).
***
### Sounds
World position where the alarm sound plays.
Alarm duration in minutes.
***
### Items
```lua theme={null}
Config.Items = {
["USB"] = "x_device",
["USB2"] = "x_device_pin",
["Key"] = "cashexchange2key",
["Bag"] = "bag",
["Circuit"] = "x_circuittester",
}
```
For cooldowns, limits, skill system, evidence/stress, and logging options, see the [Cash Exchange Robbery Configuration](/resources/cash-exchange-robbery-k4mb1/configuration) page — the structure is identical.
# Exports
Source: https://docs.projectx.gg/resources/cash-exchange-robbery-2-k4mb1/exports
Server-side exports available for the K4MB1 Cash Exchange 2 Robbery resource
## Server Exports
### Reset
Resets the heist, unlocking the location and clearing any active robbery state.
```lua theme={null}
exports['projectx-cashexchange2robbery-k4mb1']:Reset()
```
### IsRobberyInitiated
Returns whether a robbery is currently active.
```lua theme={null}
local active = exports['projectx-cashexchange2robbery-k4mb1']:IsRobberyInitiated()
```
**Returns**
* `active` (boolean) - `true` if a robbery is in progress, `false` otherwise
**Example**
```lua theme={null}
local active = exports['projectx-cashexchange2robbery-k4mb1']:IsRobberyInitiated()
if active then
print("A robbery is currently in progress")
end
```
# FAQs
Source: https://docs.projectx.gg/resources/cash-exchange-robbery-2-k4mb1/faqs
Frequently asked questions about the K4MB1 Cash Exchange 2 Robbery resource
## General Questions
This is the Legion Square K4MB1 map variant. It uses `cashexchange2key` as the progression item, includes trolley loot, and has a different step layout (`PowerBox`, `Fusebox`, `Key` steps).
Obtain it externally — configure it as a bonus from another heist, shop, or custom script.
Use `/projectxk4mb1cashexchange2` or call:
```lua theme={null}
exports['projectx-cashexchange2robbery-k4mb1']:Reset()
```
## Troubleshooting
Ensure `projectx-bridge`, `ox_lib`, `bl_ui`, and `boii_minigames` are started before `projectx-cashexchange2robbery-k4mb1`.
# Installation
Source: https://docs.projectx.gg/resources/cash-exchange-robbery-2-k4mb1/installation
Step by step instructions to install the K4MB1 Cash Exchange 2 Robbery resource
## Installation Steps
Verify all dependencies below are started **before** this script in your `server.cfg`. Start order should be: Dispatch → Bridge → Minigames → Script.
Download ox\_lib
Required map by K4MB1
Required Project X Bridge
Download the minigames zip and place each resource into your standalone or dependencies folder.
Download and place in your standalone or minigames folder
Make sure the minigames are **not** in the same folder as the robbery script.
Extract the script from the zip file and place it into your scripts folder.
Add the required items and their images to your inventory resource. See the [items section](#items-required) below for the full list.
Item images done by [Artwork Inventory](https://discord.gg/Z2awpnXKdw) - Use code **ProjectX** for 10% off!
Open `config/config.lua` and adjust the settings to match your server. The bridge handles framework, inventory, dispatch, and interaction automatically if set to `'auto'`.
Make sure the bridge, ox\_lib, your target, dispatch, inventory, and minigames are all started before the robbery script.
```cfg theme={null}
ensure ox_lib
ensure projectx-bridge
ensure bl_ui
ensure boii_minigames
ensure projectx-cashexchange2robbery-k4mb1
```
## Items Required
### Items Required from Outside the Robbery
The `cashexchange2key` must be obtained externally before the robbery can be started.
* `cashexchange2key`
### Items Required from Shop/Black Market
* `x_device`
* `x_circuittester`
* `bag`
The `x_device_pin` item is obtained within the robbery itself.
### Item Configuration
```lua theme={null}
['x_device'] = {
label = "X Device",
weight = 50,
stack = false,
close = false,
description = "?????????",
},
["x_device_pin"] = {
label = "Decrypted Device",
weight = 200,
stack = false,
close = false,
description = "",
},
['bag'] = {
label = "Bag",
weight = 400,
stack = false,
close = false,
description = "Duffel bag",
},
['cashexchange2key'] = {
label = "Cash Exchange 2 Key",
weight = 400,
stack = false,
close = false,
description = "Cash Exchange 2 Key",
},
["x_circuittester"] = {
label = "X Circuit Tester",
weight = 125,
stack = false,
close = false,
description = "?????????",
},
```
```lua theme={null}
['x_device'] = {['name'] = 'x_device', ['label'] = 'X Device', ['weight'] = 50, ['type'] = 'item', ['image'] = 'x_device.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '?????????'},
['bag'] = {['name'] = 'bag', ['label'] = 'Bag', ['weight'] = 400, ['type'] = 'item', ['image'] = 'bag.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'Duffel bag'},
['cashexchange2key'] = {['name'] = 'cashexchange2key', ['label'] = 'Cash Exchange 2 Key', ['weight'] = 400, ['type'] = 'item', ['image'] = 'cashexchange2key.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'Cash Exchange 2 Key'},
['x_device_pin'] = {['name'] = 'x_device_pin', ['label'] = 'Decrypted USB', ['weight'] = 200, ['type'] = 'item', ['image'] = 'x_device.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '????'},
['x_circuittester'] = {['name'] = 'x_circuittester', ['label'] = 'X Circuit Tester', ['weight'] = 200, ['type'] = 'item', ['image'] = 'x_circuittester.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '????'},
```
# Open Source
Source: https://docs.projectx.gg/resources/cash-exchange-robbery-2-k4mb1/opensource
Open source files available for customization in the K4MB1 Cash Exchange 2 Robbery resource
## opensource/client/client.lua
Each robbery step triggers the `projectx-cashexchange2robbery-k4mb1:client:Minigames` callback with the step name.
```lua theme={null}
lib.callback.register('projectx-cashexchange2robbery-k4mb1:client:Minigames', function(Step)
local p = promise.new()
if Step == "Ventilation" then
if not exports['projectx-bridge']:MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:CircleSum(3, {length = 4, duration = 15000})
p:resolve(success)
elseif Step == "Fusebox" then
if not exports['projectx-bridge']:MinigameCheck("boii_minigames") then p:resolve(false) return Citizen.Await(p) end
exports['boii_minigames']:wire_cut({style = 'default', timer = 60000}, function(success)
p:resolve(success)
end)
elseif Step == "Keypad" then
if not exports['projectx-bridge']:MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:DigitDazzle(1, {length = 4, duration = 20000})
p:resolve(success)
end
return Citizen.Await(p)
end)
```
You can return `true` unconditionally inside any step block to skip that minigame entirely.
The default minigames per step are:
| Step | Minigame Resource | Function |
| ------------- | ----------------- | ------------- |
| `Ventilation` | `bl_ui` | `CircleSum` |
| `Prop` | `bl_ui` | `RapidLines` |
| `Key` | `bl_ui` | `CircleShake` |
| `Fusebox` | `boii_minigames` | `wire_cut` |
| `Keypad` | `bl_ui` | `DigitDazzle` |
***
## opensource/server/server.lua
### Hooks
Step names are listed in `Config.CashExchangeSteps` inside `config/config.lua`.
Called whenever a player fails a robbery step.
Return `false` to block a player from starting the robbery.
Called whenever the heist resets.
# Commands
Source: https://docs.projectx.gg/resources/cash-exchange-robbery-k4mb1/commands
Admin commands for the K4MB1 Cash Exchange Robbery resource
## Admin Commands
**Usage**: `/projectxk4mb1cashexchange`
**Permission**: Admin (configurable via `CheckPerms` in the bridge)
**Description**: Forces a full heist reset, unlocking the location and clearing any active robbery state.
**Example**:
```
/projectxk4mb1cashexchange
```
This command internally calls the `Reset()` export. See the [Exports](/resources/cash-exchange-robbery-k4mb1/exports) page for details.
# Configuration
Source: https://docs.projectx.gg/resources/cash-exchange-robbery-k4mb1/configuration
Full reference for all configuration options in the K4MB1 Cash Exchange Robbery resource
## config/config.lua
### Main Settings
Shows polyzones created inside the game.
Disables all minigames. Useful for testing the full robbery flow.
Time in minutes before the heist resets after a completed robbery.
Disables the loud approach path entirely.
Disables the silent approach path entirely.
Disables client-side explosions.
How long smoke particles last, in minutes.
Requires a `bag` item to collect loot.
Minimum police required online. Set to `0` to disable.
Jobs that count as police for dispatch and minimum police checks.
***
### Cooldowns & Limits
Per-player cooldown in minutes after completing a robbery.
Maximum total robberies per server restart. Set to `0` to disable.
Maximum robberies per player per restart. Set to `0` to disable.
***
### Skill System
Requires a minimum criminal level before starting the heist.
Minimum level required when `SkillSystem` is enabled.
***
### Dispatch
Controls which step triggers the dispatch alert.
```lua theme={null}
DispatchLocation = {
["Loud"] = true,
["Silent"] = false,
["Security"] = false,
["Search"] = false,
["Computer"] = true,
}
```
***
### Keypad Code
Random code range for the keypad password prompt.
***
### Starting Point & NPCs
NPC contact that initiates the robbery (`Npc`, `Model`, `Animation`).
Interior NPCs including security and employees (`Security`, `Employee1`, `Employee2`, `Employee3`).
***
### Rewards
Reward from the safe when data is not corrupted. Supports direct cash or item payout via `Cash`, `Item`, and `StackAmount`.
Reward from the cash pile pickup area.
Per-prop rewards (`Prop1`, `Prop2`, `Prop3`). Set `CashReward = true` for cash or configure an `Item` and `Amount` range.
***
### Items
```lua theme={null}
Config.Items = {
["USB"] = "x_device",
["USB2"] = "x_device_pin",
["Key"] = "cashexchangekey",
["Bag"] = "bag",
["Circuit"] = "x_circuittester",
["FadedCode"] = "x_code_faded",
["Code"] = "x_code",
}
```
***
### Evidence, Stress & Logs
Enables fingerprint evidence drops.
Enables stress on minigame failure.
Logging is configured in `config/logs.lua` (`Enable`, `APIKey`, `FivemanageDataset`).
# Exports
Source: https://docs.projectx.gg/resources/cash-exchange-robbery-k4mb1/exports
Server-side exports available for the K4MB1 Cash Exchange Robbery resource
## Server Exports
### Reset
Resets the heist, unlocking the location and clearing any active robbery state.
```lua theme={null}
exports['projectx-cashexchangerobbery-k4mb1']:Reset()
```
### IsRobberyInitiated
Returns whether a robbery is currently active.
```lua theme={null}
local active = exports['projectx-cashexchangerobbery-k4mb1']:IsRobberyInitiated()
```
**Returns**
* `active` (boolean) - `true` if a robbery is in progress, `false` otherwise
**Example**
```lua theme={null}
local active = exports['projectx-cashexchangerobbery-k4mb1']:IsRobberyInitiated()
if active then
print("A robbery is currently in progress")
end
```
# FAQs
Source: https://docs.projectx.gg/resources/cash-exchange-robbery-k4mb1/faqs
Frequently asked questions about the K4MB1 Cash Exchange Robbery resource
## General Questions
Yes. See the [Bridge Installation](/resources/bridge/installation) page for setup instructions.
The `cashexchangekey` is a progression item obtained outside this robbery — configure it as a bonus drop from another heist, shop, or custom script.
Use `/projectxk4mb1cashexchange` or call:
```lua theme={null}
exports['projectx-cashexchangerobbery-k4mb1']:Reset()
```
Edit `opensource/client/client.lua` — see the [Open Source](/resources/cash-exchange-robbery-k4mb1/opensource) page for the full step-to-minigame table.
## Troubleshooting
Ensure `projectx-bridge`, `ox_lib`, `bl_ui`, and `boii_minigames` are started before `projectx-cashexchangerobbery-k4mb1`.
# Installation
Source: https://docs.projectx.gg/resources/cash-exchange-robbery-k4mb1/installation
Step by step instructions to install the K4MB1 Cash Exchange Robbery resource
## Installation Steps
Verify all dependencies below are started **before** this script in your `server.cfg`. Start order should be: Dispatch → Bridge → Minigames → Script.
Download ox\_lib
Required map by K4MB1
Required Project X Bridge
Download the minigames zip and place each resource into your standalone or dependencies folder.
Download and place in your standalone or minigames folder
Make sure the minigames are **not** in the same folder as the robbery script.
Extract the script from the zip file and place it into your scripts folder.
Add the required items and their images to your inventory resource. See the [items section](#items-required) below for the full list.
Item images done by [Artwork Inventory](https://discord.gg/Z2awpnXKdw) - Use code **ProjectX** for 10% off!
Open `config/config.lua` and adjust the settings to match your server. The bridge handles framework, inventory, dispatch, and interaction automatically if set to `'auto'`.
Make sure the bridge, ox\_lib, your target, dispatch, inventory, and minigames are all started before the robbery script.
```cfg theme={null}
ensure ox_lib
ensure projectx-bridge
ensure bl_ui
ensure boii_minigames
ensure projectx-cashexchangerobbery-k4mb1
```
## Items Required
### Items Required from Outside the Robbery
The `cashexchangekey` must be obtained externally before the robbery can be started.
* `cashexchangekey`
### Items Required from Shop/Black Market
* `x_device`
* `x_circuittester`
* `bag`
The rest of the items (`x_device_pin`, `x_code`, `x_code_faded`) are obtained within the robbery itself.
### Item Configuration
```lua theme={null}
['x_device'] = {
label = "X Device",
weight = 50,
stack = false,
close = false,
description = "?????????",
},
["x_device_pin"] = {
label = "Decrypted Device",
weight = 200,
stack = false,
close = false,
description = "",
},
['bag'] = {
label = "Bag",
weight = 400,
stack = false,
close = false,
description = "Duffel bag",
},
['cashexchangekey'] = {
label = "Cash Exchange Key",
weight = 400,
stack = false,
close = false,
description = "Cash Exchange Key",
},
["x_circuittester"] = {
label = "X Circuit Tester",
weight = 125,
stack = false,
close = false,
description = "?????????",
},
["x_code"] = {
label = "Code note",
weight = 50,
stack = false,
close = false,
description = "?????????",
},
["x_code_faded"] = {
label = "Faded Code note",
weight = 50,
stack = false,
close = false,
description = "?????????",
},
```
```lua theme={null}
['x_device'] = {['name'] = 'x_device', ['label'] = 'X Device', ['weight'] = 50, ['type'] = 'item', ['image'] = 'x_device.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '?????????'},
['bag'] = {['name'] = 'bag', ['label'] = 'Bag', ['weight'] = 400, ['type'] = 'item', ['image'] = 'bag.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'Duffel bag'},
['cashexchangekey'] = {['name'] = 'cashexchangekey', ['label'] = 'Cash Exchange Key', ['weight'] = 400, ['type'] = 'item', ['image'] = 'cashexchangekey.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'Cash Exchange Key'},
['x_device_pin'] = {['name'] = 'x_device_pin', ['label'] = 'Decrypted USB', ['weight'] = 200, ['type'] = 'item', ['image'] = 'x_device.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '????'},
['x_circuittester'] = {['name'] = 'x_circuittester', ['label'] = 'X Circuit Tester', ['weight'] = 200, ['type'] = 'item', ['image'] = 'x_circuittester.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '????'},
['x_code'] = {['name'] = 'x_code', ['label'] = 'Code note', ['weight'] = 50, ['type'] = 'item', ['image'] = 'x_code.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '????'},
['x_code_faded'] = {['name'] = 'x_code_faded', ['label'] = 'Faded Code note', ['weight'] = 50, ['type'] = 'item', ['image'] = 'x_code_faded.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '????'},
```
# Open Source
Source: https://docs.projectx.gg/resources/cash-exchange-robbery-k4mb1/opensource
Open source files available for customization in the K4MB1 Cash Exchange Robbery resource
Most of the core logic in this resource is handled by the bridge. The open source files are provided so you can customize minigames, add hooks for custom systems, and extend the script without touching escrow.
## opensource/client/client.lua
Each robbery step triggers the `projectx-cashexchangerobbery-k4mb1:client:Minigames` callback with the step name.
```lua theme={null}
lib.callback.register('projectx-cashexchangerobbery-k4mb1:client:Minigames', function(Step)
local p = promise.new()
if Step == "Ventilation" then
if not exports['projectx-bridge']:MinigameCheck("lightsout") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:WaveMatch(1, {duration = 30000})
p:resolve(success)
elseif Step == "Computer" then
if not exports['projectx-bridge']:MinigameCheck("boii_minigames") then p:resolve(false) return Citizen.Await(p) end
exports['boii_minigames']:chip_hack({style = 'default', loading_time = 8000, chips = 2, timer = 20000}, function(success)
p:resolve(success)
end)
elseif Step == "Keypad" then
if not exports['projectx-bridge']:MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:PrintLock(1, {grid = 5, duration = 15000, target = 5})
p:resolve(success)
end
return Citizen.Await(p)
end)
```
You can return `true` unconditionally inside any step block to skip that minigame entirely.
The default minigames per step are:
| Step | Minigame Resource | Function |
| ------------- | ----------------- | ---------------- |
| `Ventilation` | `bl_ui` | `WaveMatch` |
| `Prop` | `bl_ui` | `Progress` |
| `Search` | `bl_ui` | `CircleProgress` |
| `Computer` | `boii_minigames` | `chip_hack` |
| `Safe` | `boii_minigames` | `safe_crack` |
| `Keypad` | `bl_ui` | `PrintLock` |
***
## opensource/server/server.lua
### Hooks
Called whenever a player successfully completes a robbery step. Step names are listed in `Config.CashExchangeSteps` inside `config/config.lua`.
Called whenever a player fails a robbery step.
Called before a player can start the robbery. Return `false` to block them.
Called whenever the heist resets.
# Commands
Source: https://docs.projectx.gg/resources/fleeca-bank-robbery-default/commands
Admin commands for the Default Fleeca Bank Robbery resource
## Admin Commands
**Usage**: `/projectxfleeca`
**Permission**: Admin (configurable via `CheckPerms` in the bridge)
**Description**: Resets the nearest Fleeca bank within 50 units of your position. Useful for testing or recovering from a stuck robbery.
**Example**:
```
/projectxfleeca
```
This command resets the closest bank location automatically. To reset a specific bank programmatically, use the `Reset(location)` export instead. See the [Exports](/resources/fleeca-bank-robbery-default/exports) page for details.
# Configuration
Source: https://docs.projectx.gg/resources/fleeca-bank-robbery-default/configuration
Full reference for all configuration options in the Default Fleeca Bank Robbery resource
## config/config.lua
### Main Settings
Shows polyzones created inside the game. Useful for testing zone placement.
Disables all minigames. Useful for testing the full robbery flow without completing minigame challenges.
The key code used to trigger drawtext interactions. `38` is `[E]` by default.
The size of the drawtext interaction zone.
Spawns networked props server side. Set to `false` to spawn them client side instead.
Minimum number of police required online before a robbery can be started. Set to `0` to disable.
The jobs that count as police for the `MinimumPolice` check and dispatch alerts.
```lua theme={null}
PoliceJobs = {"police", "fbi"}
```
Requires a minimum number of players nearby to start a robbery.
```lua theme={null}
RequiredPlayersNearby = {amount = 0, radius = 20.0}
```
Set `amount` to `0` or `false` to disable.
Maximum number of Fleeca robberies that can be active at the same time. Set to `0` to disable.
Requires players to have a `bag` item in order to loot the trolleys.
Length of the employee list that appears on the board during the employee puzzle.
Disables the employee puzzle. Defaults to `true` on the vanilla map variant.
Disables all particle effects during the robbery.
Disables weapon removal during the robbery. Only enable this if you use a weapon wheel resource.
Enables compatibility with the Gruppe Sechs Job by 17mov.
Disables the loud approach path entirely.
Disables the silent approach path entirely.
***
### Cooldowns & Limits
When `true`, robbing one Fleeca puts all Fleecas on cooldown. When `false`, each location has its own cooldown.
Cooldown duration in minutes.
Per-player cooldown in minutes after completing a robbery. Set to `0` to disable.
Maximum number of total robberies allowed per server restart. Set to `0` to disable.
Maximum number of robberies a single player can complete per server restart. Set to `0` to disable.
***
### Strike System
Maximum number of trolleys that can spawn. Actual count depends on the strike system and approach used.
Number of strikes players can accumulate before their reward is cut. Set to `false` to disable.
(Silent Approach only) Number of trolleys removed from the reward when the strike limit is reached.
(Loud Approach only) Number of trolleys that spawn during a loud approach.
***
### Skill System
Requires players to meet a minimum level from an integrated XP/skill system before starting the heist. Must have an XP system configured in the bridge.
Minimum level required to initiate the heist. Only applies when `SkillSystem` is `true`.
***
### Dispatch
Title shown in the dispatch alert.
Message body shown in the dispatch alert.
Radio code shown in the dispatch alert.
Time in seconds the dispatch alert remains visible. Not all dispatch systems support this.
Blip settings for the dispatch map marker.
```lua theme={null}
Blip = {
Text = 'Fleeca bank Robbery',
Color = 1,
Sprite = 41,
Scale = 0.8
}
```
Controls which step triggers the dispatch alert. Only one of the step keys should be enabled at a time (excluding Loud/Silent).
```lua theme={null}
DispatchLocation = {
["Loud"] = true,
["Silent"] = false,
["KeypadOne"] = true,
["KeypadTwo"] = false,
["Vault"] = false,
}
```
***
### Bonus Items
Enables or disables bonus item drops at the end of the heist.
Percentage chance that any bonus item is given at all.
Number of items that can be given from the bonus items table.
Table of possible bonus items. Each entry has a `Name`, `Chance` (%), and `Amount` range.
The total chance across all items needs to add up to 100%.
```lua theme={null}
Items = {
{Name = "x_device", Chance = 30, Amount = {min = 1, max = 1}},
{Name = "x_phone", Chance = 50, Amount = {min = 1, max = 1}},
{Name = "x_stethoscope", Chance = 20, Amount = {min = 1, max = 1}},
}
```
***
### Evidence & Stress
Enables fingerprint evidence drops at the crime scene.
Percentage chance that fingerprint evidence is left behind.
Enables the stress system. Stress is only applied when a minigame is failed.
Percentage chance that stress is applied on a minigame fail.
The minimum and maximum amount of stress applied per failure.
***
### Durations
Progressbar durations in milliseconds:
| Setting | Default |
| ------------------------ | ------- |
| `NotificationDuration` | `2500` |
| `FingerprintDuration` | `6000` |
| `FuseboxDuration` | `6000` |
| `ShelfDuration` | `5000` |
| `KeypadOneDuration` | `6000` |
| `KeypadTwoDuration` | `6000` |
| `SearchDuration` | `6000` |
| `PrinterDuration` | `7500` |
| `VaultDuration` | `6000` |
| `JailDoorDuration` | `5000` |
| `JailDoorKeypadDuration` | `6000` |
***
### Items
Maps logical item roles to inventory item names.
```lua theme={null}
Config.Items = {
["Device"] = "x_device",
["Pliers"] = "pliers",
["Pictures"] = "employeepictures",
["Bag"] = "bag",
["Keys"] = "fleeca_key",
["Keycard"] = "fleecacard",
["Laptop"] = "x_laptop",
}
```
Percentage chance that an item breaks on use. Set to `0` to disable.
```lua theme={null}
Config.ItemsBreak = {
["Device"] = 0,
["Pliers"] = 0,
["Laptop"] = 0,
}
```
***
### Locations
Enable or disable each of the 6 Fleeca banks.
```lua theme={null}
Config.FleecaLocations = {
["RockfordHills"] = true,
["Legion"] = true,
["Burton"] = true,
["Alta"] = true,
["GrandSenoraDesert"] = true,
["BanhamCanyon"] = true,
}
```
Per-location interaction coordinates live in `Config.Fleecas` and trolley spawn/loot points in `Config.Trollys`. Edit those tables if you need to move targets — you do not need to copy every coordinate from the default config for normal setup.
***
### Rewards
Rewards are split into three types: **cash**, **gold**, and **diamond** (`Config.Rewardcash`, `Config.Rewardgold`, `Config.Rewarddiamond`). Each follows the same format.
If `true`, items are given per individual stack pickup from the trolley. If `false`, the reward is given at the end of the full trolley animation.
Set to `true` to give money directly. Set to `false` to give a cash item instead.
The item name used when `Cash` is `false`. Gold defaults to `goldbar`, diamond to `diamond`.
The minimum and maximum cash or item amount per pickup or per trolley completion. Gold and diamond use their own ranges.
Optional item metadata. Used if `markedbills` or similar items carry random value data in their info table.
***
### Logs
Configured in `config/logs.lua`.
Enables or disables the logging system.
Your Discord webhook URL, or your Fivemerr/Fivemanage API key.
The Fivemanage dataset to log activity to. Leave as `"default"` unless you have a specific dataset configured.
# Exports
Source: https://docs.projectx.gg/resources/fleeca-bank-robbery-default/exports
Server-side exports available for the Default Fleeca Bank Robbery resource
## Server Exports
All location-based exports require a valid Fleeca location key from `Config.FleecaLocations` (e.g. `"RockfordHills"`, `"Legion"`, `"Burton"`, `"Alta"`, `"GrandSenoraDesert"`, `"BanhamCanyon"`).
### Reset
Resets the robbery at the given location, clearing active state and restoring the bank.
```lua theme={null}
exports['projectx-fleecabankrobbery-default']:Reset('RockfordHills')
```
**Returns**
* `true` if the location exists and was reset successfully
***
### IsRobberyInProgress
Returns whether a robbery is currently active at the given location.
```lua theme={null}
local active = exports['projectx-fleecabankrobbery-default']:IsRobberyInProgress('Legion')
```
**Returns**
* `true` if a robbery is in progress at that location, `false` otherwise
**Example**
```lua theme={null}
local active = exports['projectx-fleecabankrobbery-default']:IsRobberyInProgress('Burton')
if active then
print("Burton Fleeca is being robbed")
end
```
***
### GetActiveRobberyCount
Returns the total number of active Fleeca robberies across all locations.
```lua theme={null}
local count = exports['projectx-fleecabankrobbery-default']:GetActiveRobberyCount()
```
**Returns**
* `count` (number) — total active robberies
**Example**
```lua theme={null}
local count = exports['projectx-fleecabankrobbery-default']:GetActiveRobberyCount()
print("Active Fleeca robberies: " .. count)
```
# FAQs
Source: https://docs.projectx.gg/resources/fleeca-bank-robbery-default/faqs
Frequently asked questions about the Default Fleeca Bank Robbery resource
## General Questions
The script supports QBCore, Qbox, and ESX through the Project X Bridge. Set `Framework` to `'auto'` in the bridge config and it will detect your framework automatically.
Yes. The bridge is required for this script to function. It handles framework detection, inventory, dispatch, notifications, progressbars, XP, evidence, logs, and global cooldowns. See the [Bridge Installation](/resources/bridge/installation) page for setup instructions.
When you purchase Default Fleeca Bank Robbery, the `projectx-bridge` asset is automatically delivered to your CFX portal.
Inventory is handled through the Project X Bridge. Set `Inventory` to `'auto'` in the bridge config for automatic detection. Supported values include ox\_inventory, qb-inventory, ps/lj-inventory, codem-inventory, origen\_inventory, tgiann-inventory, ak47\_inventory, jpr-inventory, one\_inventory, and ESX default inventory. See the [FAQs](/faqs) for the full list with config values and links.
The bridge supports 30+ dispatch systems including PS Dispatch, CodeSign, CodeSign 3D, LB Tablet, FD Dispatch, Wasabi MDT, Oxide Dispatch, VX MDT, Sonoran CAD, and many more. Set `Dispatch` to `'auto'` in the bridge config for automatic detection. See the [FAQs](/faqs) for the full list with config values and links.
Six locations: RockfordHills, Legion, Burton, Alta, GrandSenoraDesert, and BanhamCanyon. Enable or disable each one in `Config.FleecaLocations`.
The silent approach is higher risk but offers a higher potential reward. Failing minigames during silent accumulates strikes, which reduce the number of trolleys available at the end. The loud approach is lower risk with a fixed trolley count controlled by `StrikeLoud`, but may trigger dispatch immediately.
Open `opensource/client/client.lua` and find the `projectx-fleecabankrobbery-default:client:Minigames` callback. Each robbery step has its own `elseif` block where you can swap the minigame export for any resource you prefer. You can also return `true` inside any block to skip that minigame entirely.
See the [Open Source](/resources/fleeca-bank-robbery-default/opensource) page for the full callback code and a table of the default minigame assignments.
Use the `/projectxfleeca` in-game command (requires admin permissions) to reset the nearest bank within 50m, or call the `Reset(location)` server export from another resource:
```lua theme={null}
exports['projectx-fleecabankrobbery-default']:Reset('RockfordHills')
```
See the [Commands](/resources/fleeca-bank-robbery-default/commands) and [Exports](/resources/fleeca-bank-robbery-default/exports) pages for more details.
## Configuration Questions
Set `MinimumPolice` to the number you want in `config/config.lua`, and make sure the correct jobs are listed in `PoliceJobs`.
```lua theme={null}
MinimumPolice = 2,
PoliceJobs = {"police", "fbi"},
```
Set `SkillSystem` to `true` and configure `MinimumLevel` in `config/config.lua`. You also need a compatible XP system integrated in the bridge config (`XPSystem`).
Supported systems include `projectx-xp`, `pickle_xp`, `sd-levels`, `cw-rep`, and `OT_skills`. See the [FAQs](/faqs) for bridge XP config values.
Enable `Bonus.Status` and configure the `Bonus.Items` table in `config/config.lua`. Each item has a `Chance` percentage and an `Amount` range. Bonus drops are off by default.
```lua theme={null}
Bonus = {
Status = true,
BonusChance = 15,
ItemCount = 1,
Items = {
{Name = "x_device", Chance = 30, Amount = {min = 1, max = 1}},
{Name = "x_phone", Chance = 50, Amount = {min = 1, max = 1}},
{Name = "x_stethoscope", Chance = 20, Amount = {min = 1, max = 1}},
}
}
```
Set `Cooldown.Global` to `true` to lock all Fleecas when one is robbed. Set it to `false` for individual per-location cooldowns. Adjust the duration with `Cooldown.Timer` (in minutes).
Toggle each location in `Config.FleecaLocations`:
```lua theme={null}
Config.FleecaLocations = {
["RockfordHills"] = true,
["Legion"] = true,
["Burton"] = false,
["Alta"] = true,
["GrandSenoraDesert"] = true,
["BanhamCanyon"] = true,
}
```
## Troubleshooting
Make sure you have all required dependencies started before the script in your `server.cfg` (`ox_lib`, `projectx-bridge`, then minigames, then the robbery script).
Verify all minigame resources (`SN-Hacking`, `utk_fingerprint`, `simonsays`, `lightsout`, `pd-safe`) are started and placed outside the robbery script folder. The bridge's `MinigameCheck` will return `false` if a minigame resource is missing.
# Installation
Source: https://docs.projectx.gg/resources/fleeca-bank-robbery-default/installation
Step by step instructions to install the Default Fleeca Bank Robbery resource
## Installation Steps
Verify all dependencies below are started **before** this script in your `server.cfg`.
Download ox\_lib
Required Project X Bridge
This variant uses **vanilla GTA** Fleeca interiors. No third-party map purchase is required.
Download the minigames zip and place each resource into your standalone or dependencies folder.
Download and place in your standalone or minigames folder
Make sure the minigames are **not** in the same folder as the robbery script.
Extract the script from the zip file and place it into your scripts folder.
Add the required items and their images to your inventory resource. See the [items section](#items-required) below for the full list.
Item images done by [Artwork Inventory](https://discord.gg/Z2awpnXKdw) - Use code **ProjectX** for 10% off!
Open `config/config.lua` and adjust the settings to match your server. The bridge handles framework, inventory, dispatch, and interaction automatically if set to `'auto'`.
Make sure the bridge, ox\_lib, your target, dispatch, inventory, and minigames are all started before the robbery script.
```cfg theme={null}
ensure ox_lib
ensure projectx-bridge
ensure SN-Hacking
ensure utk_fingerprint
ensure simonsays
ensure lightsout
ensure pd-safe
ensure projectx-fleecabankrobbery-default
```
## Items Required
### Items Required from Outside the Robbery
The `fleecacard` must be obtained externally (e.g. from another robbery or side mission) before the robbery can be started.
* `fleecacard`
### Items Required from Shop/Black Market
* `x_device`
* `x_laptop`
* `pliers`
* `fleeca_key`
* `bag`
The rest of the items (`employeepictures`) are obtained within the robbery itself.
### Item Configuration
```lua theme={null}
["fleeca_key"] = {
label = "Fleeca Key",
weight = 50,
stack = false,
close = false,
description = "Key!",
},
["employeepictures"] = {
label = "Employee Pictures",
weight = 25,
stack = false,
close = false,
description = "Faces of employees",
},
["pliers"] = {
label = "Pliers",
weight = 125,
stack = false,
close = false,
description = "A pair of pliers",
},
["x_device"] = {
label = "X Device",
weight = 125,
stack = false,
close = false,
description = "?????????",
},
["bag"] = {
label = "Duffel Bag",
weight = 250,
stack = false,
close = false,
description = "Duffel bag",
},
["x_laptop"] = {
label = "X Laptop",
weight = 50,
stack = false,
close = false,
description = "?????????",
},
["fleecacard"] = {
label = "Fleeca Card",
weight = 300,
stack = false,
close = false,
description = "A Security card for Fleeca Bank",
},
```
```lua theme={null}
['fleeca_key'] = {['name'] = 'fleeca_key', ['label'] = 'Fleeca Key', ['weight'] = 50, ['type'] = 'item', ['image'] = 'fleeca_key.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'Key!'},
['employeepictures'] = {['name'] = 'employeepictures', ['label'] = 'Employee Pictures', ['weight'] = 25, ['type'] = 'item', ['image'] = 'employeepictures.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'Faces of employees'},
['fleecacard'] = {['name'] = 'fleecacard', ['label'] = 'Fleeca Keycard', ['weight'] = 25, ['type'] = 'item', ['image'] = 'fleecacard.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'A Security card for Fleeca Bank'},
['x_laptop'] = {['name'] = 'x_laptop', ['label'] = 'X Laptop', ['weight'] = 50, ['type'] = 'item', ['image'] = 'x_laptop.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '?????????'},
['x_device'] = {['name'] = 'x_device', ['label'] = 'X Device', ['weight'] = 50, ['type'] = 'item', ['image'] = 'x_device.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '?????????'},
['pliers'] = {['name'] = 'pliers', ['label'] = 'Pliers', ['weight'] = 200, ['type'] = 'item', ['image'] = 'pliers.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'Pliers..?'},
['bag'] = {['name'] = 'bag', ['label'] = 'Bag', ['weight'] = 400, ['type'] = 'item', ['image'] = 'bag.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'Duffel bag'},
```
# Open Source
Source: https://docs.projectx.gg/resources/fleeca-bank-robbery-default/opensource
Open source files available for customization in the Default Fleeca Bank Robbery resource
Most of the core logic in this resource is handled by the bridge. The open source files are provided so you can customize minigames, add hooks for custom systems, and extend the script without touching escrow.
## opensource/client/client.lua
This file handles zone creation, drawtext, evidence, stress, and most importantly, the minigame callback. If you want to change the minigames used for each step, this is the only file you need to edit.
### Minigame Callback
Each robbery step triggers the `projectx-fleecabankrobbery-default:client:Minigames` callback with the step name. You can swap any minigame by replacing the export call inside the matching `elseif` block.
```lua theme={null}
lib.callback.register('projectx-fleecabankrobbery-default:client:Minigames', function(Step)
local p = promise.new()
if Step == "Fusebox" then
if not exports['projectx-bridge']:MinigameCheck("SN-Hacking") then p:resolve(false) return Citizen.Await(p) end
local success = exports['SN-Hacking']:MemoryCards('hard')
p:resolve(success)
elseif Step == "Fingerprint" then
if not exports['projectx-bridge']:MinigameCheck("utk_fingerprint") then p:resolve(false) return Citizen.Await(p) end
TriggerEvent("utk_fingerprint:Start", 4, 6, 2, function(success)
p:resolve(success)
end)
elseif Step == "KeypadOne" then
if not exports['projectx-bridge']:MinigameCheck("simonsays") then p:resolve(false) return Citizen.Await(p) end
local success = exports['simonsays']:StartSimonSays(5, 5)
p:resolve(success)
elseif Step == "Printer" then
if not exports['projectx-bridge']:MinigameCheck("lightsout") then p:resolve(false) return Citizen.Await(p) end
local success = exports['lightsout']:StartLightsOut(4, 20)
p:resolve(success)
elseif Step == "Search" then
if not exports['projectx-bridge']:MinigameCheck("pd-safe") then p:resolve(false) return Citizen.Await(p) end
local success = exports["pd-safe"]:createSafe({math.random(0,99)})
p:resolve(success)
elseif Step == "Vault" then
if not exports['projectx-bridge']:MinigameCheck("SN-Hacking") then p:resolve(false) return Citizen.Await(p) end
local success = exports['SN-Hacking']:ColorPicker(5, 7000, 3000)
p:resolve(success)
elseif Step == "JailDoorKeypad" then
if not exports['projectx-bridge']:MinigameCheck("SN-Hacking") then p:resolve(false) return Citizen.Await(p) end
local success = exports['SN-Hacking']:ColorPicker(5, 7000, 3000)
p:resolve(success)
elseif Step == "JailDoor" then
return true
else
p:resolve(false)
end
return Citizen.Await(p)
end)
```
You can return `true` unconditionally inside any step block to skip that minigame entirely. This can be useful for testing or for steps you want to make automatic.
The default minigames per step are:
| Step | Minigame Resource | Function |
| ---------------- | ----------------- | ----------------------- |
| `Fusebox` | `SN-Hacking` | `MemoryCards` |
| `Fingerprint` | `utk_fingerprint` | `Start` |
| `KeypadOne` | `simonsays` | `StartSimonSays` |
| `Printer` | `lightsout` | `StartLightsOut` |
| `Search` | `pd-safe` | `createSafe` |
| `Vault` | `SN-Hacking` | `ColorPicker` |
| `JailDoorKeypad` | `SN-Hacking` | `ColorPicker` |
| `JailDoor` | — | Skipped (`return true`) |
***
## opensource/server/server.lua
This file handles dispatch, item/money functions, logging, and exposes several hooks you can use to run custom logic at specific points in the robbery.
### Hooks
Called whenever a player successfully completes a robbery step. Use this to award XP, trigger events, or log individual step completions.
```lua theme={null}
function SuccessfulStep(source, location, step)
if step == "Fusebox" then
-- exports['projectx-bridge']:AddExperience(source, 'criminal', 10)
elseif step == "Register" then
-- exports['projectx-bridge']:AddExperience(source, 'criminal', 10)
end
end
```
Step names match the minigame callback steps and interaction keys defined in `config/config.lua`.
Called whenever a player fails a robbery step. Use this to remove XP, items, or apply penalties.
```lua theme={null}
function FailedStep(source, location, step)
if step == "Fusebox" then
-- RemoveItem(source, 'x_device', 1)
elseif step == "Register" then
-- Apply custom penalty
end
end
```
Called before a player can start a robbery at a location. Return `false` to block them.
```lua theme={null}
function InitialCheck(src, Location, Interaction)
return true
-- Add a group check, tablet requirement, or any other gate here
end
```
Called whenever a Fleeca location resets. Use this to update a scoreboard, trigger an external event, or notify players.
```lua theme={null}
function RobberyResetHook(location)
-- TriggerEvent('my-scoreboard:update', location)
end
```
# Commands
Source: https://docs.projectx.gg/resources/fleeca-bank-robbery-fmv2/commands
Admin commands for the FM V2 Fleeca Bank Robbery resource
## Admin Commands
**Usage**: `/projectxfleeca`
**Permission**: Admin (configurable via `CheckPerms` in the bridge)
**Description**: Resets the nearest Fleeca bank within approximately 50 units of your position. Useful for testing or recovering from a stuck robbery.
**Example**:
```
/projectxfleeca
```
This command resets the closest Fleeca location automatically. To reset a specific bank programmatically, use the `Reset(location)` export instead. See the [Exports](/resources/fleeca-bank-robbery-fmv2/exports) page for details.
# Configuration
Source: https://docs.projectx.gg/resources/fleeca-bank-robbery-fmv2/configuration
Full reference for all configuration options in the FM V2 Fleeca Bank Robbery resource
## config/config.lua
### Main Settings
Shows polyzones created inside the game. Useful for testing zone placement.
Disables all minigames. Useful for testing the full robbery flow without completing minigame challenges.
The key code used to trigger drawtext interactions. `38` is `[E]` by default.
The size of the drawtext interaction zone.
Spawns networked props server side. Set to `false` to spawn them client side instead.
Requires players to have a `bag` item in order to loot trolleys.
Length of the employee list that appears on the board during the employee puzzle.
Disables the employee puzzle step entirely.
Disables all particle effects during the robbery.
Disables weapon removal during the robbery. Only enable this if you use a weapon wheel resource.
Enables GruppeSechs Job compatibility by 17mov.
Minimum number of police required online before a robbery can be started. Set to `0` to disable.
The jobs that count as police for the `MinimumPolice` check and dispatch alerts.
```lua theme={null}
PoliceJobs = {"police", "fbi"}
```
Requires a minimum number of players nearby to start a robbery.
```lua theme={null}
RequiredPlayersNearby = {amount = 0, radius = 20.0}
```
Set `amount` to `0` or `false` to disable.
Maximum number of Fleeca robberies that can be active at the same time. Set to `0` to disable.
Disables the loud approach path entirely.
Disables the silent approach path entirely.
***
### Cooldowns & Limits
When `true`, robbing one Fleeca puts all Fleeca banks on cooldown. When `false`, each bank has its own cooldown.
Cooldown duration in minutes.
Per-player cooldown in minutes after completing a robbery. Set to `0` to disable.
Maximum number of total robberies allowed per server restart. Set to `0` to disable.
Maximum number of robberies a single player can complete per server restart. Set to `0` to disable.
***
### Strike System
Maximum number of trolleys that can spawn. Actual count depends on the strike system and approach used.
Number of strikes players can accumulate before their reward is cut. Set to `false` to disable the strike system.
(Silent Approach only) Number of trolleys removed from the reward when the strike limit is reached.
(Loud Approach only) Number of trolleys that spawn during a loud approach.
***
### Skill System
Requires players to meet a minimum level from an integrated XP/skill system before starting a robbery. Must have an XP system configured in the bridge.
Minimum level required to initiate a robbery. Only applies when `SkillSystem` is `true`.
***
### Dispatch
Title shown in the dispatch alert.
Message body shown in the dispatch alert.
Radio code shown in the dispatch alert.
Time in seconds the dispatch alert remains visible. Not all dispatch systems support this.
Blip settings for the dispatch map marker.
```lua theme={null}
Blip = {
Text = 'Fleeca bank Robbery',
Color = 1,
Sprite = 41,
Scale = 0.8
}
```
Controls which steps trigger dispatch alerts. `Loud` and `Silent` can be enabled independently. Only one of the step-based options should be enabled at a time.
```lua theme={null}
DispatchLocation = {
["Loud"] = true,
["Silent"] = false,
["KeypadOne"] = false,
["KeypadTwo"] = true,
["ElectricBox"] = false,
["Vault"] = false,
}
```
***
### Bonus Items
Enables or disables bonus item drops at the end of a robbery.
Percentage chance that any bonus item is given at all.
Number of items that can be given from the bonus items table.
Table of possible bonus items. Each entry has a `Name`, `Chance` (%), and `Amount` range.
The total chance across all items needs to add up to 100%.
```lua theme={null}
Items = {
{Name = "x_device", Chance = 30, Amount = {min = 1, max = 1}},
{Name = "x_phone", Chance = 50, Amount = {min = 1, max = 1}},
{Name = "x_stethoscope", Chance = 20, Amount = {min = 1, max = 1}},
}
```
***
### Evidence & Stress
Enables fingerprint evidence drops at the crime scene.
Percentage chance that fingerprint evidence is left behind.
Enables the stress system. Stress is only applied when a minigame is failed.
Percentage chance that stress is applied on a minigame fail.
The minimum and maximum amount of stress applied per failure.
***
### Required Items
Maps logical item names to your inventory item names.
```lua theme={null}
Items = {
["Device"] = "x_device",
["Pliers"] = "pliers",
["Pictures"] = "employeepictures",
["Bag"] = "bag",
["Keycard"] = "fleecacard",
["Laptop"] = "x_laptop",
}
```
Break chance (%) for each item when used during a robbery.
```lua theme={null}
ItemsBreak = {
["Device"] = 0,
["Pliers"] = 0,
["Laptop"] = 0,
}
```
***
### Step Durations
Progress bar durations (milliseconds) for each interaction step:
| Field | Default |
| ---------------------- | ------- |
| `NotificationDuration` | `2500` |
| `FingerprintDuration` | `6000` |
| `FuseboxDuration` | `6000` |
| `ShelfDuration` | `5000` |
| `KeypadOneDuration` | `6000` |
| `KeypadTwoDuration` | `6000` |
| `SearchDuration` | `6000` |
| `ElectricBoxDuration` | `7500` |
| `PrinterDuration` | `7500` |
| `CardKeypadDuration` | `15000` |
| `VaultDuration` | `6000` |
***
### Rewards
Trolley rewards are split into **cash**, **gold**, and **diamond** tables (`Config.Rewardcash`, `Config.Rewardgold`, `Config.Rewarddiamond`). Each follows the same format:
If `true`, items are given per individual stack pickup from the trolley. If `false`, the reward is given at the end of the full trolley animation.
Set to `true` to give money directly. Set to `false` to give a cash item instead.
The item name used when `Cash` is `false`.
The minimum and maximum cash or item amount per pickup or per trolley completion.
Optional item metadata. Used if `markedbills` or similar items carry random value data in their info table.
Trolley spawn positions and loot types per bank are configured in `Config.Trollys`.
***
### Fleeca Locations
Enable or disable individual banks with `Config.FleecaLocations`:
```lua theme={null}
FleecaLocations = {
["RockfordHills"] = true,
["Legion"] = true,
["Burton"] = true,
["Alta"] = true,
["GrandSenoraDesert"] = true,
["BanhamCanyon"] = true,
}
```
Full per-bank coordinates, interactions, and props live in `Config.Fleecas`. Use the location key when calling exports.
***
### Other Settings
ox\_lib input text for the hidden password step (`Title`, `Label`, `Description`, `Icon`).
Alarm settings including `AlarmDuration` (minutes), `AudioName`, `AudioRef`, and `Range`.
Employee puzzle difficulty options (`ShowFirstLetter`, `ShowLastLetter`, `HideOneClue`).
Employee name/clue data used by the employee puzzle board.
***
### Logs
Configured in `config/logs.lua`.
Enables or disables the logging system.
Your Discord webhook URL, or your Fivemerr/Fivemanage API key.
The Fivemanage dataset to log activity to. Leave as `"default"` unless you have a specific dataset configured.
# Exports
Source: https://docs.projectx.gg/resources/fleeca-bank-robbery-fmv2/exports
Server-side exports available for the FM V2 Fleeca Bank Robbery resource
## Server Exports
All location-based exports require a valid Fleeca key from `Config.FleecaLocations` / `Config.Fleecas` (e.g. `"RockfordHills"`, `"Legion"`, `"Burton"`, `"Alta"`, `"GrandSenoraDesert"`, `"BanhamCanyon"`).
### Reset
Resets the robbery at the given location, clearing active state and restoring the bank.
```lua theme={null}
exports['projectx-fleecabankrobbery-fmv2']:Reset('RockfordHills')
```
**Returns**
* `true` if the location exists and was reset successfully
***
### IsRobberyInProgress
Returns whether a robbery is currently active at the given location.
```lua theme={null}
local active = exports['projectx-fleecabankrobbery-fmv2']:IsRobberyInProgress('RockfordHills')
```
**Returns**
* `true` if a robbery is in progress at that location, `false` otherwise
**Example**
```lua theme={null}
local active = exports['projectx-fleecabankrobbery-fmv2']:IsRobberyInProgress('Legion')
if active then
print("Legion Fleeca is being robbed")
end
```
***
### GetActiveRobberyCount
Returns the total number of active Fleeca robberies across all locations.
```lua theme={null}
local count = exports['projectx-fleecabankrobbery-fmv2']:GetActiveRobberyCount()
```
**Returns**
* `count` (number) — total active robberies
**Example**
```lua theme={null}
local count = exports['projectx-fleecabankrobbery-fmv2']:GetActiveRobberyCount()
print("Active Fleeca robberies: " .. count)
```
# FAQs
Source: https://docs.projectx.gg/resources/fleeca-bank-robbery-fmv2/faqs
Frequently asked questions about the FM V2 Fleeca Bank Robbery resource
## General Questions
The script supports QBCore, Qbox, and ESX through the Project X Bridge. Set `Framework` to `'auto'` in the bridge config and it will detect your framework automatically.
Yes. The bridge is required for this script to function. It handles framework detection, inventory, dispatch, notifications, progressbars, XP, evidence, logs, and global cooldowns. See the [Bridge Installation](/resources/bridge/installation) page for setup instructions.
When you purchase FM V2 Fleeca Bank Robbery, the `projectx-bridge` asset is automatically delivered to your CFX portal.
Inventory is handled through the Project X Bridge. Set `Inventory` to `'auto'` in the bridge config for automatic detection. Supported values include ox\_inventory, qb-inventory, ps/lj-inventory, codem-inventory, origen\_inventory, tgiann-inventory, ak47\_inventory, jpr-inventory, one\_inventory, and ESX default inventory. See the [FAQs](/faqs) for the full list with config values and links.
The bridge supports 30+ dispatch systems including PS Dispatch, CodeSign, CodeSign 3D, LB Tablet, FD Dispatch, Wasabi MDT, Oxide Dispatch, VX MDT, Sonoran CAD, and many more. Set `Dispatch` to `'auto'` in the bridge config for automatic detection. See the [FAQs](/faqs) for the full list with config values and links.
Six banks are supported via `Config.FleecaLocations`: RockfordHills, Legion, Burton, Alta, GrandSenoraDesert, and BanhamCanyon. Enable or disable each location independently.
The silent approach is higher risk but offers a higher potential reward. Failing minigames during silent accumulates strikes, which reduce the number of trolleys available at the end. The loud approach is lower risk with a fixed trolley count controlled by `StrikeLoud`, but may trigger dispatch immediately.
Open `opensource/client/client.lua` and find the `projectx-fleecabankrobbery-fmv2:client:Minigames` callback. Each robbery step has its own `elseif` block where you can swap the minigame export for any resource you prefer. You can also return `true` inside any block to skip that minigame entirely.
See the [Open Source](/resources/fleeca-bank-robbery-fmv2/opensource) page for the full callback code and a table of the default minigame assignments.
Use the `/projectxfleeca` in-game command (requires admin permissions) to reset the nearest bank within \~50m, or call the `Reset(location)` server export from another resource:
```lua theme={null}
exports['projectx-fleecabankrobbery-fmv2']:Reset('RockfordHills')
```
See the [Commands](/resources/fleeca-bank-robbery-fmv2/commands) and [Exports](/resources/fleeca-bank-robbery-fmv2/exports) pages for more details.
## Configuration Questions
Set `MinimumPolice` to the number you want in `config/config.lua`, and make sure the correct jobs are listed in `PoliceJobs`.
```lua theme={null}
MinimumPolice = 2,
PoliceJobs = {"police", "fbi"},
```
Set `SkillSystem` to `true` and configure `MinimumLevel` in `config/config.lua`. You also need a compatible XP system integrated in the bridge config (`XPSystem`).
Supported systems include `projectx-xp`, `pickle_xp`, `sd-levels`, `cw-rep`, and `OT_skills`. See the [FAQs](/faqs) for bridge XP config values.
Enable `Bonus.Status` and configure the `Bonus.Items` table in `config/config.lua`. Each item has a `Chance` percentage and an `Amount` range.
```lua theme={null}
Bonus = {
Status = true,
BonusChance = 15,
ItemCount = 1,
Items = {
{Name = "x_device", Chance = 30, Amount = {min = 1, max = 1}},
}
}
```
Set `Cooldown.Global` to `true` to lock all Fleeca banks when one is robbed. Set it to `false` for individual per-bank cooldowns. Adjust the duration with `Cooldown.Timer` (in minutes).
## Troubleshooting
Make sure you have all required dependencies started before the script in your `server.cfg` (`projectx-bridge`, `ox_lib`, minigames).
Verify all minigame resources (`SN-Hacking`, `utk_fingerprint`, `simonsays`, `lightsout`) are started and placed outside the robbery script folder. The bridge's `MinigameCheck` will return `false` if a minigame resource is missing.
# Installation
Source: https://docs.projectx.gg/resources/fleeca-bank-robbery-fmv2/installation
Step by step instructions to install the FM V2 Fleeca Bank Robbery resource
## Installation Steps
Verify all dependencies below are started **before** this script in your `server.cfg`.
Download ox\_lib
Required map by FM Shop
Required Project X Bridge
Download the minigames zip and place each resource into your standalone or dependencies folder.
Download and place in your standalone or minigames folder
Make sure the minigames are **not** in the same folder as the robbery script.
Extract the script from the zip file and place it into your scripts folder.
Add the required items and their images to your inventory resource. See the [items section](#items-required) below for the full list.
Item images done by [Artwork Inventory](https://discord.gg/Z2awpnXKdw) - Use code **ProjectX** for 10% off!
Open `config/config.lua` and adjust the settings to match your server. The bridge handles framework, inventory, dispatch, and interaction automatically if set to `'auto'`.
Make sure the bridge, ox\_lib, your target, dispatch, inventory, and minigames are all started before the robbery script.
```cfg theme={null}
ensure ox_lib
ensure projectx-bridge
ensure SN-Hacking
ensure utk_fingerprint
ensure simonsays
ensure lightsout
ensure projectx-fleecabankrobbery-fmv2
```
## Items Required
### Items Required from Outside the Robbery
The `fleecacard` must be obtained externally (e.g. from another robbery or side mission) before the robbery can be started.
* `fleecacard`
### Items Required from Shop/Black Market
* `x_device`
* `x_laptop`
* `pliers`
* `bag`
The rest of the items (`employeepictures`) are obtained within the robbery itself.
### Item Configuration
```lua theme={null}
["employeepictures"] = {
label = "Employee Pictures",
weight = 25,
stack = false,
close = false,
description = "Faces of employees",
},
["pliers"] = {
label = "Pliers",
weight = 125,
stack = false,
close = false,
description = "A pair of pliers",
},
["x_device"] = {
label = "X Device",
weight = 125,
stack = false,
close = false,
description = "?????????",
},
["bag"] = {
label = "Duffel Bag",
weight = 250,
stack = false,
close = false,
description = "Duffel bag",
},
["x_laptop"] = {
label = "X Laptop",
weight = 50,
stack = false,
close = false,
description = "?????????",
},
["fleecacard"] = {
label = "Fleeca Card",
weight = 300,
stack = false,
close = false,
description = "A Security card for Fleeca Bank",
},
```
```lua theme={null}
['employeepictures'] = {['name'] = 'employeepictures', ['label'] = 'Employee Pictures', ['weight'] = 25, ['type'] = 'item', ['image'] = 'employeepictures.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'Faces of employees'},
['fleecacard'] = {['name'] = 'fleecacard', ['label'] = 'Fleeca Keycard', ['weight'] = 25, ['type'] = 'item', ['image'] = 'fleecacard.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'A Security card for Fleeca Bank'},
['x_laptop'] = {['name'] = 'x_laptop', ['label'] = 'X Laptop', ['weight'] = 50, ['type'] = 'item', ['image'] = 'x_laptop.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '?????????'},
['x_device'] = {['name'] = 'x_device', ['label'] = 'X Device', ['weight'] = 50, ['type'] = 'item', ['image'] = 'x_device.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '?????????'},
['pliers'] = {['name'] = 'pliers', ['label'] = 'Pliers', ['weight'] = 200, ['type'] = 'item', ['image'] = 'pliers.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'Pliers..?'},
['bag'] = {['name'] = 'bag', ['label'] = 'Bag', ['weight'] = 400, ['type'] = 'item', ['image'] = 'bag.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'Duffel bag'},
```
# Open Source
Source: https://docs.projectx.gg/resources/fleeca-bank-robbery-fmv2/opensource
Open source files available for customization in the FM V2 Fleeca Bank Robbery resource
Most of the core logic in this resource is handled by the bridge. The open source files are provided so you can customize minigames, add hooks for custom systems, and extend the script without touching escrow.
## opensource/client/client.lua
This file handles zone creation, drawtext, evidence, stress, and most importantly, the minigame callback. If you want to change the minigames used for each step, this is the only file you need to edit.
### Minigame Callback
Each robbery step triggers the `projectx-fleecabankrobbery-fmv2:client:Minigames` callback with the step name. You can swap any minigame by replacing the export call inside the matching `elseif` block.
```lua theme={null}
lib.callback.register('projectx-fleecabankrobbery-fmv2:client:Minigames', function(Step)
local p = promise.new()
if Step == "Fusebox" then
if not exports['projectx-bridge']:MinigameCheck("SN-Hacking") then p:resolve(false) return Citizen.Await(p) end
local success = exports['SN-Hacking']:MemoryCards('hard')
p:resolve(success)
elseif Step == "Fingerprint" then
if not exports['projectx-bridge']:MinigameCheck("utk_fingerprint") then p:resolve(false) return Citizen.Await(p) end
TriggerEvent("utk_fingerprint:Start", 4, 6, 2, function(success)
p:resolve(success)
end)
elseif Step == "KeypadOne" then
if not exports['projectx-bridge']:MinigameCheck("simonsays") then p:resolve(false) return Citizen.Await(p) end
local success = exports['simonsays']:StartSimonSays(5, 5)
p:resolve(success)
elseif Step == "Printer" then
if not exports['projectx-bridge']:MinigameCheck("lightsout") then p:resolve(false) return Citizen.Await(p) end
local success = exports['lightsout']:StartLightsOut(4, 20)
p:resolve(success)
elseif Step == "ElectricBox" then
if not exports['projectx-bridge']:MinigameCheck("SN-Hacking") then p:resolve(false) return Citizen.Await(p) end
local success = exports['SN-Hacking']:MemoryCards('medium')
p:resolve(success)
elseif Step == "Vault" then
if not exports['projectx-bridge']:MinigameCheck("SN-Hacking") then p:resolve(false) return Citizen.Await(p) end
local success = exports['SN-Hacking']:ColorPicker(5, 7000, 3000)
p:resolve(success)
elseif Step == "CardKeypad" then
if not exports['projectx-bridge']:MinigameCheck("SN-Hacking") then p:resolve(false) return Citizen.Await(p) end
local success = exports['SN-Hacking']:ColorPicker(5, 7000, 3000)
p:resolve(success)
else
p:resolve(false)
end
return Citizen.Await(p)
end)
```
You can return `true` unconditionally inside any step block to skip that minigame entirely. This can be useful for testing or for steps you want to make automatic.
The default minigames per step are:
| Step | Minigame Resource | Function |
| ------------- | ----------------- | ----------------------- |
| `Fusebox` | `SN-Hacking` | `MemoryCards('hard')` |
| `Fingerprint` | `utk_fingerprint` | `utk_fingerprint:Start` |
| `KeypadOne` | `simonsays` | `StartSimonSays` |
| `Printer` | `lightsout` | `StartLightsOut` |
| `ElectricBox` | `SN-Hacking` | `MemoryCards('medium')` |
| `Vault` | `SN-Hacking` | `ColorPicker` |
| `CardKeypad` | `SN-Hacking` | `ColorPicker` |
***
## opensource/server/server.lua
This file handles dispatch, item/money functions, logging, and exposes several hooks you can use to run custom logic at specific points in the robbery.
### Hooks
Called whenever a player successfully completes a robbery step. Use this to award XP, trigger events, or log individual step completions.
```lua theme={null}
function SuccessfulStep(source, location, step)
if step == "Fusebox" then
-- exports['projectx-bridge']:AddExperience(source, 'criminal', 10)
elseif step == "Vault" then
-- exports['projectx-bridge']:AddExperience(source, 'criminal', 10)
end
end
```
Common step names include `Fusebox`, `Fingerprint`, `KeypadOne`, `Printer`, `ElectricBox`, `Vault`, and `CardKeypad`.
Called whenever a player fails a robbery step. Use this to remove XP, items, or apply penalties.
```lua theme={null}
function FailedStep(source, location, step)
if step == "Fusebox" then
-- RemoveItem(source, 'x_device', 1)
end
end
```
Called before a player can start a robbery at a location. Return `false` to block them.
```lua theme={null}
function InitialCheck(src, Location, Interaction)
return true
-- Add a group check, tablet requirement, or any other gate here
end
```
Called whenever a Fleeca location resets. Use this to update a scoreboard, trigger an external event, or notify players.
```lua theme={null}
function RobberyResetHook(location)
-- TriggerEvent('my-scoreboard:update', location)
end
```
# Commands
Source: https://docs.projectx.gg/resources/fleeca-bank-robbery-gabz/commands
Admin commands for the Gabz Fleeca Bank Robbery resource
## Admin Commands
**Usage**: `/projectxfleeca`
**Permission**: Admin (configurable via `CheckPerms` in the bridge)
**Description**: Resets the nearest Fleeca bank within 50 units of your position. Useful for testing or recovering from a stuck robbery.
**Example**:
```
/projectxfleeca
```
This command resets the closest bank location automatically. To reset a specific bank programmatically, use the `Reset(location)` export instead. See the [Exports](/resources/fleeca-bank-robbery-gabz/exports) page for details.
# Configuration
Source: https://docs.projectx.gg/resources/fleeca-bank-robbery-gabz/configuration
Full reference for all configuration options in the Gabz Fleeca Bank Robbery resource
## config/config.lua
### Main Settings
Shows polyzones created inside the game. Useful for testing zone placement.
Disables all minigames. Useful for testing the full robbery flow without completing minigame challenges.
The key code used to trigger drawtext interactions. `38` is `[E]` by default.
The size of the drawtext interaction zone.
Spawns networked props server side. Set to `false` to spawn them client side instead.
Minimum number of police required online before a robbery can be started. Set to `0` to disable.
The jobs that count as police for the `MinimumPolice` check and dispatch alerts.
```lua theme={null}
PoliceJobs = {"police", "fbi"}
```
Requires a minimum number of players nearby to start a robbery.
```lua theme={null}
RequiredPlayersNearby = {amount = 0, radius = 20.0}
```
Set `amount` to `0` or `false` to disable.
Maximum number of Fleeca robberies that can be active at the same time. Set to `0` to disable.
Requires players to have a `bag` item in order to loot the trolleys.
Length of the employee list that appears on the board during the employee puzzle.
Disables the employee puzzle. Defaults to `false` on the Gabz map variant.
Disables all particle effects during the robbery.
Disables weapon removal during the robbery. Only enable this if you use a weapon wheel resource.
Enables compatibility with the Gruppe Sechs Job by 17mov.
Disables the loud approach path entirely.
Disables the silent approach path entirely.
***
### Cooldowns & Limits
When `true`, robbing one Fleeca puts all Fleecas on cooldown. When `false`, each location has its own cooldown.
Cooldown duration in minutes.
Per-player cooldown in minutes after completing a robbery. Set to `0` to disable.
Maximum number of total robberies allowed per server restart. Set to `0` to disable.
Maximum number of robberies a single player can complete per server restart. Set to `0` to disable.
***
### Strike System
Maximum number of trolleys that can spawn. Actual count depends on the strike system and approach used.
Number of strikes players can accumulate before their reward is cut. Set to `false` to disable.
(Silent Approach only) Number of trolleys removed from the reward when the strike limit is reached.
(Loud Approach only) Number of trolleys that spawn during a loud approach.
***
### Skill System
Requires players to meet a minimum level from an integrated XP/skill system before starting the heist. Must have an XP system configured in the bridge.
Minimum level required to initiate the heist. Only applies when `SkillSystem` is `true`.
***
### Dispatch
Title shown in the dispatch alert.
Message body shown in the dispatch alert.
Radio code shown in the dispatch alert.
Time in seconds the dispatch alert remains visible. Not all dispatch systems support this.
Blip settings for the dispatch map marker.
```lua theme={null}
Blip = {
Text = 'Fleeca bank Robbery',
Color = 1,
Sprite = 41,
Scale = 0.8
}
```
Controls which step triggers the dispatch alert. Only one of the step keys should be enabled at a time (excluding Loud/Silent).
```lua theme={null}
DispatchLocation = {
["Loud"] = true,
["Silent"] = false,
["KeypadOne"] = true,
["KeypadTwo"] = false,
["Vault"] = false,
}
```
***
### Bonus Items
Enables or disables bonus item drops at the end of the heist.
Percentage chance that any bonus item is given at all.
Number of items that can be given from the bonus items table.
Table of possible bonus items. Each entry has a `Name`, `Chance` (%), and `Amount` range.
The total chance across all items needs to add up to 100%.
```lua theme={null}
Items = {
{Name = "x_device", Chance = 30, Amount = {min = 1, max = 1}},
{Name = "x_phone", Chance = 50, Amount = {min = 1, max = 1}},
{Name = "x_stethoscope", Chance = 20, Amount = {min = 1, max = 1}},
}
```
***
### Evidence & Stress
Enables fingerprint evidence drops at the crime scene.
Percentage chance that fingerprint evidence is left behind.
Enables the stress system. Stress is only applied when a minigame is failed.
Percentage chance that stress is applied on a minigame fail.
The minimum and maximum amount of stress applied per failure.
***
### Durations
Progressbar durations in milliseconds:
| Setting | Default |
| ------------------------ | ------- |
| `NotificationDuration` | `2500` |
| `FingerprintDuration` | `6000` |
| `FuseboxDuration` | `6000` |
| `ShelfDuration` | `5000` |
| `KeypadOneDuration` | `6000` |
| `KeypadTwoDuration` | `6000` |
| `SearchDuration` | `6000` |
| `PrinterDuration` | `7500` |
| `VaultDuration` | `6000` |
| `JailDoorDuration` | `5000` |
| `JailDoorKeypadDuration` | `6000` |
***
### Items
Maps logical item roles to inventory item names.
```lua theme={null}
Config.Items = {
["Device"] = "x_device",
["Pliers"] = "pliers",
["Pictures"] = "employeepictures",
["Bag"] = "bag",
["Keys"] = "fleeca_key",
["Keycard"] = "fleecacard",
["Laptop"] = "x_laptop",
}
```
Percentage chance that an item breaks on use. Set to `0` to disable.
```lua theme={null}
Config.ItemsBreak = {
["Device"] = 0,
["Pliers"] = 0,
["Laptop"] = 0,
}
```
***
### Locations
Enable or disable each of the 6 Fleeca banks.
```lua theme={null}
Config.FleecaLocations = {
["RockfordHills"] = true,
["Legion"] = true,
["Burton"] = true,
["Alta"] = true,
["GrandSenoraDesert"] = true,
["BanhamCanyon"] = true,
}
```
Per-location interaction coordinates live in `Config.Fleecas` and trolley spawn/loot points in `Config.Trollys`. Edit those tables if you need to move targets — you do not need to copy every coordinate from the default config for normal setup.
***
### Rewards
Rewards are split into three types: **cash**, **gold**, and **diamond** (`Config.Rewardcash`, `Config.Rewardgold`, `Config.Rewarddiamond`). Each follows the same format.
If `true`, items are given per individual stack pickup from the trolley. If `false`, the reward is given at the end of the full trolley animation.
Set to `true` to give money directly. Set to `false` to give a cash item instead.
The item name used when `Cash` is `false`. Gold defaults to `goldbar`, diamond to `diamond`.
The minimum and maximum cash or item amount per pickup or per trolley completion. Gold and diamond use their own ranges.
Optional item metadata. Used if `markedbills` or similar items carry random value data in their info table.
***
### Logs
Configured in `config/logs.lua`.
Enables or disables the logging system.
Your Discord webhook URL, or your Fivemerr/Fivemanage API key.
The Fivemanage dataset to log activity to. Leave as `"default"` unless you have a specific dataset configured.
# Exports
Source: https://docs.projectx.gg/resources/fleeca-bank-robbery-gabz/exports
Server-side exports available for the Gabz Fleeca Bank Robbery resource
## Server Exports
All location-based exports require a valid Fleeca location key from `Config.FleecaLocations` (e.g. `"RockfordHills"`, `"Legion"`, `"Burton"`, `"Alta"`, `"GrandSenoraDesert"`, `"BanhamCanyon"`).
### Reset
Resets the robbery at the given location, clearing active state and restoring the bank.
```lua theme={null}
exports['projectx-fleecabankrobbery-gabz']:Reset('RockfordHills')
```
**Returns**
* `true` if the location exists and was reset successfully
***
### IsRobberyInProgress
Returns whether a robbery is currently active at the given location.
```lua theme={null}
local active = exports['projectx-fleecabankrobbery-gabz']:IsRobberyInProgress('Legion')
```
**Returns**
* `true` if a robbery is in progress at that location, `false` otherwise
**Example**
```lua theme={null}
local active = exports['projectx-fleecabankrobbery-gabz']:IsRobberyInProgress('Burton')
if active then
print("Burton Fleeca is being robbed")
end
```
***
### GetActiveRobberyCount
Returns the total number of active Fleeca robberies across all locations.
```lua theme={null}
local count = exports['projectx-fleecabankrobbery-gabz']:GetActiveRobberyCount()
```
**Returns**
* `count` (number) — total active robberies
**Example**
```lua theme={null}
local count = exports['projectx-fleecabankrobbery-gabz']:GetActiveRobberyCount()
print("Active Fleeca robberies: " .. count)
```
# FAQs
Source: https://docs.projectx.gg/resources/fleeca-bank-robbery-gabz/faqs
Frequently asked questions about the Gabz Fleeca Bank Robbery resource
## General Questions
The script supports QBCore, Qbox, and ESX through the Project X Bridge. Set `Framework` to `'auto'` in the bridge config and it will detect your framework automatically.
Yes. The bridge is required for this script to function. It handles framework detection, inventory, dispatch, notifications, progressbars, XP, evidence, logs, and global cooldowns. See the [Bridge Installation](/resources/bridge/installation) page for setup instructions.
When you purchase Gabz Fleeca Bank Robbery, the `projectx-bridge` asset is automatically delivered to your CFX portal.
Inventory is handled through the Project X Bridge. Set `Inventory` to `'auto'` in the bridge config for automatic detection. Supported values include ox\_inventory, qb-inventory, ps/lj-inventory, codem-inventory, origen\_inventory, tgiann-inventory, ak47\_inventory, jpr-inventory, one\_inventory, and ESX default inventory. See the [FAQs](/faqs) for the full list with config values and links.
The bridge supports 30+ dispatch systems including PS Dispatch, CodeSign, CodeSign 3D, LB Tablet, FD Dispatch, Wasabi MDT, Oxide Dispatch, VX MDT, Sonoran CAD, and many more. Set `Dispatch` to `'auto'` in the bridge config for automatic detection. See the [FAQs](/faqs) for the full list with config values and links.
Six locations: RockfordHills, Legion, Burton, Alta, GrandSenoraDesert, and BanhamCanyon. Enable or disable each one in `Config.FleecaLocations`.
The silent approach is higher risk but offers a higher potential reward. Failing minigames during silent accumulates strikes, which reduce the number of trolleys available at the end. The loud approach is lower risk with a fixed trolley count controlled by `StrikeLoud`, but may trigger dispatch immediately.
Open `opensource/client/client.lua` and find the `projectx-fleecabankrobbery-gabz:client:Minigames` callback. Each robbery step has its own `elseif` block where you can swap the minigame export for any resource you prefer. You can also return `true` inside any block to skip that minigame entirely.
See the [Open Source](/resources/fleeca-bank-robbery-gabz/opensource) page for the full callback code and a table of the default minigame assignments.
Use the `/projectxfleeca` in-game command (requires admin permissions) to reset the nearest bank within 50m, or call the `Reset(location)` server export from another resource:
```lua theme={null}
exports['projectx-fleecabankrobbery-gabz']:Reset('RockfordHills')
```
See the [Commands](/resources/fleeca-bank-robbery-gabz/commands) and [Exports](/resources/fleeca-bank-robbery-gabz/exports) pages for more details.
## Configuration Questions
Set `MinimumPolice` to the number you want in `config/config.lua`, and make sure the correct jobs are listed in `PoliceJobs`.
```lua theme={null}
MinimumPolice = 2,
PoliceJobs = {"police", "fbi"},
```
Set `SkillSystem` to `true` and configure `MinimumLevel` in `config/config.lua`. You also need a compatible XP system integrated in the bridge config (`XPSystem`).
Supported systems include `projectx-xp`, `pickle_xp`, `sd-levels`, `cw-rep`, and `OT_skills`. See the [FAQs](/faqs) for bridge XP config values.
Enable `Bonus.Status` and configure the `Bonus.Items` table in `config/config.lua`. Each item has a `Chance` percentage and an `Amount` range. Bonus drops are off by default.
```lua theme={null}
Bonus = {
Status = true,
BonusChance = 15,
ItemCount = 1,
Items = {
{Name = "x_device", Chance = 30, Amount = {min = 1, max = 1}},
{Name = "x_phone", Chance = 50, Amount = {min = 1, max = 1}},
{Name = "x_stethoscope", Chance = 20, Amount = {min = 1, max = 1}},
}
}
```
Set `Cooldown.Global` to `true` to lock all Fleecas when one is robbed. Set it to `false` for individual per-location cooldowns. Adjust the duration with `Cooldown.Timer` (in minutes).
Toggle each location in `Config.FleecaLocations`:
```lua theme={null}
Config.FleecaLocations = {
["RockfordHills"] = true,
["Legion"] = true,
["Burton"] = false,
["Alta"] = true,
["GrandSenoraDesert"] = true,
["BanhamCanyon"] = true,
}
```
## Troubleshooting
Make sure you have all required dependencies started before the script in your `server.cfg` (`ox_lib`, `projectx-bridge`, then minigames, then the robbery script).
Verify all minigame resources (`SN-Hacking`, `utk_fingerprint`, `simonsays`, `lightsout`, `pd-safe`) are started and placed outside the robbery script folder. The bridge's `MinigameCheck` will return `false` if a minigame resource is missing.
# Installation
Source: https://docs.projectx.gg/resources/fleeca-bank-robbery-gabz/installation
Step by step instructions to install the Gabz Fleeca Bank Robbery resource
## Installation Steps
Verify all dependencies below are started **before** this script in your `server.cfg`.
Download ox\_lib
Required Gabz Fleeca map (subscription)
Required Project X Bridge
Gabz mapdata can leave vault entity sets enabled, which conflicts with this robbery. Edit `cfx-gabz-mapdata` → `gabz_entityset_mods1`, search for `fleeca`, and set `enable` to `false` for those entries. Reference: [imgur.com/nYKgnKB](https://imgur.com/nYKgnKB).
Download the minigames zip and place each resource into your standalone or dependencies folder.
Download and place in your standalone or minigames folder
Make sure the minigames are **not** in the same folder as the robbery script.
Extract the script from the zip file and place it into your scripts folder.
Add the required items and their images to your inventory resource. See the [items section](#items-required) below for the full list.
Item images done by [Artwork Inventory](https://discord.gg/Z2awpnXKdw) - Use code **ProjectX** for 10% off!
Open `config/config.lua` and adjust the settings to match your server. The bridge handles framework, inventory, dispatch, and interaction automatically if set to `'auto'`.
Make sure the bridge, ox\_lib, your target, dispatch, inventory, and minigames are all started before the robbery script.
```cfg theme={null}
ensure ox_lib
ensure projectx-bridge
ensure SN-Hacking
ensure utk_fingerprint
ensure simonsays
ensure lightsout
ensure pd-safe
ensure projectx-fleecabankrobbery-gabz
```
## Items Required
### Items Required from Outside the Robbery
The `fleecacard` must be obtained externally (e.g. from another robbery or side mission) before the robbery can be started.
* `fleecacard`
### Items Required from Shop/Black Market
* `x_device`
* `x_laptop`
* `pliers`
* `fleeca_key`
* `bag`
The rest of the items (`employeepictures`) are obtained within the robbery itself.
### Item Configuration
```lua theme={null}
["fleeca_key"] = {
label = "Fleeca Key",
weight = 50,
stack = false,
close = false,
description = "Key!",
},
["employeepictures"] = {
label = "Employee Pictures",
weight = 25,
stack = false,
close = false,
description = "Faces of employees",
},
["pliers"] = {
label = "Pliers",
weight = 125,
stack = false,
close = false,
description = "A pair of pliers",
},
["x_device"] = {
label = "X Device",
weight = 125,
stack = false,
close = false,
description = "?????????",
},
["bag"] = {
label = "Duffel Bag",
weight = 250,
stack = false,
close = false,
description = "Duffel bag",
},
["x_laptop"] = {
label = "X Laptop",
weight = 50,
stack = false,
close = false,
description = "?????????",
},
["fleecacard"] = {
label = "Fleeca Card",
weight = 300,
stack = false,
close = false,
description = "A Security card for Fleeca Bank",
},
```
```lua theme={null}
['fleeca_key'] = {['name'] = 'fleeca_key', ['label'] = 'Fleeca Key', ['weight'] = 50, ['type'] = 'item', ['image'] = 'fleeca_key.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'Key!'},
['employeepictures'] = {['name'] = 'employeepictures', ['label'] = 'Employee Pictures', ['weight'] = 25, ['type'] = 'item', ['image'] = 'employeepictures.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'Faces of employees'},
['fleecacard'] = {['name'] = 'fleecacard', ['label'] = 'Fleeca Keycard', ['weight'] = 25, ['type'] = 'item', ['image'] = 'fleecacard.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'A Security card for Fleeca Bank'},
['x_laptop'] = {['name'] = 'x_laptop', ['label'] = 'X Laptop', ['weight'] = 50, ['type'] = 'item', ['image'] = 'x_laptop.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '?????????'},
['x_device'] = {['name'] = 'x_device', ['label'] = 'X Device', ['weight'] = 50, ['type'] = 'item', ['image'] = 'x_device.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '?????????'},
['pliers'] = {['name'] = 'pliers', ['label'] = 'Pliers', ['weight'] = 200, ['type'] = 'item', ['image'] = 'pliers.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'Pliers..?'},
['bag'] = {['name'] = 'bag', ['label'] = 'Bag', ['weight'] = 400, ['type'] = 'item', ['image'] = 'bag.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'Duffel bag'},
```
# Open Source
Source: https://docs.projectx.gg/resources/fleeca-bank-robbery-gabz/opensource
Open source files available for customization in the Gabz Fleeca Bank Robbery resource
Most of the core logic in this resource is handled by the bridge. The open source files are provided so you can customize minigames, add hooks for custom systems, and extend the script without touching escrow.
## opensource/client/client.lua
This file handles zone creation, drawtext, evidence, stress, and most importantly, the minigame callback. If you want to change the minigames used for each step, this is the only file you need to edit.
### Minigame Callback
Each robbery step triggers the `projectx-fleecabankrobbery-gabz:client:Minigames` callback with the step name. You can swap any minigame by replacing the export call inside the matching `elseif` block.
```lua theme={null}
lib.callback.register('projectx-fleecabankrobbery-gabz:client:Minigames', function(Step)
local p = promise.new()
if Step == "Fusebox" then
if not exports['projectx-bridge']:MinigameCheck("SN-Hacking") then p:resolve(false) return Citizen.Await(p) end
local success = exports['SN-Hacking']:MemoryCards('hard')
p:resolve(success)
elseif Step == "Fingerprint" then
if not exports['projectx-bridge']:MinigameCheck("utk_fingerprint") then p:resolve(false) return Citizen.Await(p) end
TriggerEvent("utk_fingerprint:Start", 4, 6, 2, function(success)
p:resolve(success)
end)
elseif Step == "KeypadOne" then
if not exports['projectx-bridge']:MinigameCheck("simonsays") then p:resolve(false) return Citizen.Await(p) end
local success = exports['simonsays']:StartSimonSays(5, 5)
p:resolve(success)
elseif Step == "Printer" then
if not exports['projectx-bridge']:MinigameCheck("lightsout") then p:resolve(false) return Citizen.Await(p) end
local success = exports['lightsout']:StartLightsOut(4, 20)
p:resolve(success)
elseif Step == "Search" then
if not exports['projectx-bridge']:MinigameCheck("pd-safe") then p:resolve(false) return Citizen.Await(p) end
local success = exports["pd-safe"]:createSafe({math.random(0,99)})
p:resolve(success)
elseif Step == "ElectricBox" then
if not exports['projectx-bridge']:MinigameCheck("simonsays") then p:resolve(false) return Citizen.Await(p) end
local success = exports['simonsays']:StartSimonSays(5, 5)
p:resolve(success)
elseif Step == "Vault" then
if not exports['projectx-bridge']:MinigameCheck("SN-Hacking") then p:resolve(false) return Citizen.Await(p) end
local success = exports['SN-Hacking']:ColorPicker(5, 7000, 3000)
p:resolve(success)
elseif Step == "JailDoorKeypad" then
if not exports['projectx-bridge']:MinigameCheck("SN-Hacking") then p:resolve(false) return Citizen.Await(p) end
local success = exports['SN-Hacking']:ColorPicker(5, 7000, 3000)
p:resolve(success)
elseif Step == "JailDoor" then
return true
else
p:resolve(false)
end
return Citizen.Await(p)
end)
```
You can return `true` unconditionally inside any step block to skip that minigame entirely. This can be useful for testing or for steps you want to make automatic.
The default minigames per step are:
| Step | Minigame Resource | Function |
| ---------------- | ----------------- | ----------------------- |
| `Fusebox` | `SN-Hacking` | `MemoryCards` |
| `Fingerprint` | `utk_fingerprint` | `Start` |
| `KeypadOne` | `simonsays` | `StartSimonSays` |
| `Printer` | `lightsout` | `StartLightsOut` |
| `Search` | `pd-safe` | `createSafe` |
| `ElectricBox` | `simonsays` | `StartSimonSays` |
| `Vault` | `SN-Hacking` | `ColorPicker` |
| `JailDoorKeypad` | `SN-Hacking` | `ColorPicker` |
| `JailDoor` | — | Skipped (`return true`) |
***
## opensource/server/server.lua
This file handles dispatch, item/money functions, logging, and exposes several hooks you can use to run custom logic at specific points in the robbery.
### Hooks
Called whenever a player successfully completes a robbery step. Use this to award XP, trigger events, or log individual step completions.
```lua theme={null}
function SuccessfulStep(source, location, step)
if step == "Fusebox" then
-- exports['projectx-bridge']:AddExperience(source, 'criminal', 10)
elseif step == "Register" then
-- exports['projectx-bridge']:AddExperience(source, 'criminal', 10)
end
end
```
Step names match the minigame callback steps and interaction keys defined in `config/config.lua`.
Called whenever a player fails a robbery step. Use this to remove XP, items, or apply penalties.
```lua theme={null}
function FailedStep(source, location, step)
if step == "Fusebox" then
-- RemoveItem(source, 'x_device', 1)
elseif step == "Register" then
-- Apply custom penalty
end
end
```
Called before a player can start a robbery at a location. Return `false` to block them.
```lua theme={null}
function InitialCheck(src, Location, Interaction)
return true
-- Add a group check, tablet requirement, or any other gate here
end
```
Called whenever a Fleeca location resets. Use this to update a scoreboard, trigger an external event, or notify players.
```lua theme={null}
function RobberyResetHook(location)
-- TriggerEvent('my-scoreboard:update', location)
end
```
# Commands
Source: https://docs.projectx.gg/resources/fleeca-bank-robbery-k4mb1/commands
Admin commands for the K4MB1 Fleeca Bank Robbery resource
## Admin Commands
**Usage**: `/projectxfleeca`
**Permission**: Admin (configurable via `CheckPerms` in the bridge)
**Description**: Resets the nearest Fleeca bank within 50 units of your position. Useful for testing or recovering from a stuck robbery.
**Example**:
```
/projectxfleeca
```
This command resets the closest bank location automatically. To reset a specific bank programmatically, use the `Reset(location)` export instead. See the [Exports](/resources/fleeca-bank-robbery-k4mb1/exports) page for details.
# Configuration
Source: https://docs.projectx.gg/resources/fleeca-bank-robbery-k4mb1/configuration
Full reference for all configuration options in the K4MB1 Fleeca Bank Robbery resource
## config/config.lua
### Main Settings
Shows polyzones created inside the game. Useful for testing zone placement.
Disables all minigames. Useful for testing the full robbery flow without completing minigame challenges.
The key code used to trigger drawtext interactions. `38` is `[E]` by default.
The size of the drawtext interaction zone.
Spawns networked props server side. Set to `false` to spawn them client side instead.
Minimum number of police required online before a robbery can be started. Set to `0` to disable.
The jobs that count as police for the `MinimumPolice` check and dispatch alerts.
```lua theme={null}
PoliceJobs = {"police", "fbi"}
```
Requires a minimum number of players nearby to start a robbery.
```lua theme={null}
RequiredPlayersNearby = {amount = 0, radius = 20.0}
```
Set `amount` to `0` or `false` to disable.
Maximum number of Fleeca robberies that can be active at the same time. Set to `0` to disable.
Requires players to have a `bag` item in order to loot the trolleys.
Length of the employee list that appears on the board during the employee puzzle.
Disables the employee puzzle. Defaults to `false` on the K4MB1 map variant.
Disables all particle effects during the robbery.
Disables weapon removal during the robbery. Only enable this if you use a weapon wheel resource.
Enables compatibility with the Gruppe Sechs Job by 17mov.
Disables the loud approach path entirely.
Disables the silent approach path entirely.
***
### Cooldowns & Limits
When `true`, robbing one Fleeca puts all Fleecas on cooldown. When `false`, each location has its own cooldown.
Cooldown duration in minutes.
Per-player cooldown in minutes after completing a robbery. Set to `0` to disable.
Maximum number of total robberies allowed per server restart. Set to `0` to disable.
Maximum number of robberies a single player can complete per server restart. Set to `0` to disable.
***
### Strike System
Maximum number of trolleys that can spawn. Actual count depends on the strike system and approach used.
Number of strikes players can accumulate before their reward is cut. Set to `false` to disable.
(Silent Approach only) Number of trolleys removed from the reward when the strike limit is reached.
(Loud Approach only) Number of trolleys that spawn during a loud approach.
***
### Skill System
Requires players to meet a minimum level from an integrated XP/skill system before starting the heist. Must have an XP system configured in the bridge.
Minimum level required to initiate the heist. Only applies when `SkillSystem` is `true`.
***
### Dispatch
Title shown in the dispatch alert.
Message body shown in the dispatch alert.
Radio code shown in the dispatch alert.
Time in seconds the dispatch alert remains visible. Not all dispatch systems support this.
Blip settings for the dispatch map marker.
```lua theme={null}
Blip = {
Text = 'Fleeca bank Robbery',
Color = 1,
Sprite = 41,
Scale = 0.8
}
```
Controls which step triggers the dispatch alert. Only one of the step keys should be enabled at a time (excluding Loud/Silent).
```lua theme={null}
DispatchLocation = {
["Loud"] = true,
["Silent"] = false,
["KeypadOne"] = true,
["KeypadTwo"] = false,
["Vault"] = false,
}
```
***
### Bonus Items
Enables or disables bonus item drops at the end of the heist.
Percentage chance that any bonus item is given at all.
Number of items that can be given from the bonus items table.
Table of possible bonus items. Each entry has a `Name`, `Chance` (%), and `Amount` range.
The total chance across all items needs to add up to 100%.
```lua theme={null}
Items = {
{Name = "x_device", Chance = 30, Amount = {min = 1, max = 1}},
{Name = "x_phone", Chance = 50, Amount = {min = 1, max = 1}},
{Name = "x_stethoscope", Chance = 20, Amount = {min = 1, max = 1}},
}
```
***
### Evidence & Stress
Enables fingerprint evidence drops at the crime scene.
Percentage chance that fingerprint evidence is left behind.
Enables the stress system. Stress is only applied when a minigame is failed.
Percentage chance that stress is applied on a minigame fail.
The minimum and maximum amount of stress applied per failure.
***
### Durations
Progressbar durations in milliseconds:
| Setting | Default |
| ------------------------ | ------- |
| `NotificationDuration` | `2500` |
| `FingerprintDuration` | `6000` |
| `FuseboxDuration` | `6000` |
| `ShelfDuration` | `5000` |
| `KeypadOneDuration` | `6000` |
| `KeypadTwoDuration` | `6000` |
| `SearchDuration` | `6000` |
| `PrinterDuration` | `7500` |
| `VaultDuration` | `6000` |
| `JailDoorDuration` | `5000` |
| `JailDoorKeypadDuration` | `6000` |
***
### Items
Maps logical item roles to inventory item names.
```lua theme={null}
Config.Items = {
["Device"] = "x_device",
["Pliers"] = "pliers",
["Pictures"] = "employeepictures",
["Bag"] = "bag",
["Keys"] = "fleeca_key",
["Keycard"] = "fleecacard",
["Laptop"] = "x_laptop",
}
```
Percentage chance that an item breaks on use. Set to `0` to disable.
```lua theme={null}
Config.ItemsBreak = {
["Device"] = 0,
["Pliers"] = 0,
["Laptop"] = 0,
}
```
***
### Locations
Enable or disable each of the 6 Fleeca banks.
```lua theme={null}
Config.FleecaLocations = {
["RockfordHills"] = true,
["Legion"] = true,
["Burton"] = true,
["Alta"] = true,
["GrandSenoraDesert"] = true,
["BanhamCanyon"] = true,
}
```
Per-location interaction coordinates live in `Config.Fleecas` and trolley spawn/loot points in `Config.Trollys`. Edit those tables if you need to move targets — you do not need to copy every coordinate from the default config for normal setup.
***
### Rewards
Rewards are split into three types: **cash**, **gold**, and **diamond** (`Config.Rewardcash`, `Config.Rewardgold`, `Config.Rewarddiamond`). Each follows the same format.
If `true`, items are given per individual stack pickup from the trolley. If `false`, the reward is given at the end of the full trolley animation.
Set to `true` to give money directly. Set to `false` to give a cash item instead.
The item name used when `Cash` is `false`. Gold defaults to `goldbar`, diamond to `diamond`.
The minimum and maximum cash or item amount per pickup or per trolley completion. Gold and diamond use their own ranges.
Optional item metadata. Used if `markedbills` or similar items carry random value data in their info table.
***
### Logs
Configured in `config/logs.lua`.
Enables or disables the logging system.
Your Discord webhook URL, or your Fivemerr/Fivemanage API key.
The Fivemanage dataset to log activity to. Leave as `"default"` unless you have a specific dataset configured.
# Exports
Source: https://docs.projectx.gg/resources/fleeca-bank-robbery-k4mb1/exports
Server-side exports available for the K4MB1 Fleeca Bank Robbery resource
## Server Exports
All location-based exports require a valid Fleeca location key from `Config.FleecaLocations` (e.g. `"RockfordHills"`, `"Legion"`, `"Burton"`, `"Alta"`, `"GrandSenoraDesert"`, `"BanhamCanyon"`).
### Reset
Resets the robbery at the given location, clearing active state and restoring the bank.
```lua theme={null}
exports['projectx-fleecabankrobbery-k4mb1']:Reset('RockfordHills')
```
**Returns**
* `true` if the location exists and was reset successfully
***
### IsRobberyInProgress
Returns whether a robbery is currently active at the given location.
```lua theme={null}
local active = exports['projectx-fleecabankrobbery-k4mb1']:IsRobberyInProgress('Legion')
```
**Returns**
* `true` if a robbery is in progress at that location, `false` otherwise
**Example**
```lua theme={null}
local active = exports['projectx-fleecabankrobbery-k4mb1']:IsRobberyInProgress('Burton')
if active then
print("Burton Fleeca is being robbed")
end
```
***
### GetActiveRobberyCount
Returns the total number of active Fleeca robberies across all locations.
```lua theme={null}
local count = exports['projectx-fleecabankrobbery-k4mb1']:GetActiveRobberyCount()
```
**Returns**
* `count` (number) — total active robberies
**Example**
```lua theme={null}
local count = exports['projectx-fleecabankrobbery-k4mb1']:GetActiveRobberyCount()
print("Active Fleeca robberies: " .. count)
```
# FAQs
Source: https://docs.projectx.gg/resources/fleeca-bank-robbery-k4mb1/faqs
Frequently asked questions about the K4MB1 Fleeca Bank Robbery resource
## General Questions
The script supports QBCore, Qbox, and ESX through the Project X Bridge. Set `Framework` to `'auto'` in the bridge config and it will detect your framework automatically.
Yes. The bridge is required for this script to function. It handles framework detection, inventory, dispatch, notifications, progressbars, XP, evidence, logs, and global cooldowns. See the [Bridge Installation](/resources/bridge/installation) page for setup instructions.
When you purchase K4MB1 Fleeca Bank Robbery, the `projectx-bridge` asset is automatically delivered to your CFX portal.
Inventory is handled through the Project X Bridge. Set `Inventory` to `'auto'` in the bridge config for automatic detection. Supported values include ox\_inventory, qb-inventory, ps/lj-inventory, codem-inventory, origen\_inventory, tgiann-inventory, ak47\_inventory, jpr-inventory, one\_inventory, and ESX default inventory. See the [FAQs](/faqs) for the full list with config values and links.
The bridge supports 30+ dispatch systems including PS Dispatch, CodeSign, CodeSign 3D, LB Tablet, FD Dispatch, Wasabi MDT, Oxide Dispatch, VX MDT, Sonoran CAD, and many more. Set `Dispatch` to `'auto'` in the bridge config for automatic detection. See the [FAQs](/faqs) for the full list with config values and links.
Six locations: RockfordHills, Legion, Burton, Alta, GrandSenoraDesert, and BanhamCanyon. Enable or disable each one in `Config.FleecaLocations`.
The silent approach is higher risk but offers a higher potential reward. Failing minigames during silent accumulates strikes, which reduce the number of trolleys available at the end. The loud approach is lower risk with a fixed trolley count controlled by `StrikeLoud`, but may trigger dispatch immediately.
Open `opensource/client/client.lua` and find the `projectx-fleecabankrobbery-k4mb1:client:Minigames` callback. Each robbery step has its own `elseif` block where you can swap the minigame export for any resource you prefer. You can also return `true` inside any block to skip that minigame entirely.
See the [Open Source](/resources/fleeca-bank-robbery-k4mb1/opensource) page for the full callback code and a table of the default minigame assignments.
Use the `/projectxfleeca` in-game command (requires admin permissions) to reset the nearest bank within 50m, or call the `Reset(location)` server export from another resource:
```lua theme={null}
exports['projectx-fleecabankrobbery-k4mb1']:Reset('RockfordHills')
```
See the [Commands](/resources/fleeca-bank-robbery-k4mb1/commands) and [Exports](/resources/fleeca-bank-robbery-k4mb1/exports) pages for more details.
## Configuration Questions
Set `MinimumPolice` to the number you want in `config/config.lua`, and make sure the correct jobs are listed in `PoliceJobs`.
```lua theme={null}
MinimumPolice = 2,
PoliceJobs = {"police", "fbi"},
```
Set `SkillSystem` to `true` and configure `MinimumLevel` in `config/config.lua`. You also need a compatible XP system integrated in the bridge config (`XPSystem`).
Supported systems include `projectx-xp`, `pickle_xp`, `sd-levels`, `cw-rep`, and `OT_skills`. See the [FAQs](/faqs) for bridge XP config values.
Enable `Bonus.Status` and configure the `Bonus.Items` table in `config/config.lua`. Each item has a `Chance` percentage and an `Amount` range. Bonus drops are off by default.
```lua theme={null}
Bonus = {
Status = true,
BonusChance = 15,
ItemCount = 1,
Items = {
{Name = "x_device", Chance = 30, Amount = {min = 1, max = 1}},
{Name = "x_phone", Chance = 50, Amount = {min = 1, max = 1}},
{Name = "x_stethoscope", Chance = 20, Amount = {min = 1, max = 1}},
}
}
```
Set `Cooldown.Global` to `true` to lock all Fleecas when one is robbed. Set it to `false` for individual per-location cooldowns. Adjust the duration with `Cooldown.Timer` (in minutes).
Toggle each location in `Config.FleecaLocations`:
```lua theme={null}
Config.FleecaLocations = {
["RockfordHills"] = true,
["Legion"] = true,
["Burton"] = false,
["Alta"] = true,
["GrandSenoraDesert"] = true,
["BanhamCanyon"] = true,
}
```
## Troubleshooting
Make sure you have all required dependencies started before the script in your `server.cfg` (`ox_lib`, `projectx-bridge`, then minigames, then the robbery script).
Verify all minigame resources (`SN-Hacking`, `utk_fingerprint`, `simonsays`, `lightsout`, `pd-safe`) are started and placed outside the robbery script folder. The bridge's `MinigameCheck` will return `false` if a minigame resource is missing.
# Installation
Source: https://docs.projectx.gg/resources/fleeca-bank-robbery-k4mb1/installation
Step by step instructions to install the K4MB1 Fleeca Bank Robbery resource
## Installation Steps
Verify all dependencies below are started **before** this script in your `server.cfg`.
Download ox\_lib
Required map by K4MB1
Required Project X Bridge
Download the minigames zip and place each resource into your standalone or dependencies folder.
Download and place in your standalone or minigames folder
Make sure the minigames are **not** in the same folder as the robbery script.
Extract the script from the zip file and place it into your scripts folder.
Add the required items and their images to your inventory resource. See the [items section](#items-required) below for the full list.
Item images done by [Artwork Inventory](https://discord.gg/Z2awpnXKdw) - Use code **ProjectX** for 10% off!
Open `config/config.lua` and adjust the settings to match your server. The bridge handles framework, inventory, dispatch, and interaction automatically if set to `'auto'`.
Make sure the bridge, ox\_lib, your target, dispatch, inventory, and minigames are all started before the robbery script.
```cfg theme={null}
ensure ox_lib
ensure projectx-bridge
ensure SN-Hacking
ensure utk_fingerprint
ensure simonsays
ensure lightsout
ensure pd-safe
ensure projectx-fleecabankrobbery-k4mb1
```
## Items Required
### Items Required from Outside the Robbery
The `fleecacard` must be obtained externally (e.g. from another robbery or side mission) before the robbery can be started.
* `fleecacard`
### Items Required from Shop/Black Market
* `x_device`
* `x_laptop`
* `pliers`
* `fleeca_key`
* `bag`
The rest of the items (`employeepictures`) are obtained within the robbery itself.
### Item Configuration
```lua theme={null}
["fleeca_key"] = {
label = "Fleeca Key",
weight = 50,
stack = false,
close = false,
description = "Key!",
},
["employeepictures"] = {
label = "Employee Pictures",
weight = 25,
stack = false,
close = false,
description = "Faces of employees",
},
["pliers"] = {
label = "Pliers",
weight = 125,
stack = false,
close = false,
description = "A pair of pliers",
},
["x_device"] = {
label = "X Device",
weight = 125,
stack = false,
close = false,
description = "?????????",
},
["bag"] = {
label = "Duffel Bag",
weight = 250,
stack = false,
close = false,
description = "Duffel bag",
},
["x_laptop"] = {
label = "X Laptop",
weight = 50,
stack = false,
close = false,
description = "?????????",
},
["fleecacard"] = {
label = "Fleeca Card",
weight = 300,
stack = false,
close = false,
description = "A Security card for Fleeca Bank",
},
```
```lua theme={null}
['fleeca_key'] = {['name'] = 'fleeca_key', ['label'] = 'Fleeca Key', ['weight'] = 50, ['type'] = 'item', ['image'] = 'fleeca_key.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'Key!'},
['employeepictures'] = {['name'] = 'employeepictures', ['label'] = 'Employee Pictures', ['weight'] = 25, ['type'] = 'item', ['image'] = 'employeepictures.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'Faces of employees'},
['fleecacard'] = {['name'] = 'fleecacard', ['label'] = 'Fleeca Keycard', ['weight'] = 25, ['type'] = 'item', ['image'] = 'fleecacard.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'A Security card for Fleeca Bank'},
['x_laptop'] = {['name'] = 'x_laptop', ['label'] = 'X Laptop', ['weight'] = 50, ['type'] = 'item', ['image'] = 'x_laptop.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '?????????'},
['x_device'] = {['name'] = 'x_device', ['label'] = 'X Device', ['weight'] = 50, ['type'] = 'item', ['image'] = 'x_device.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '?????????'},
['pliers'] = {['name'] = 'pliers', ['label'] = 'Pliers', ['weight'] = 200, ['type'] = 'item', ['image'] = 'pliers.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'Pliers..?'},
['bag'] = {['name'] = 'bag', ['label'] = 'Bag', ['weight'] = 400, ['type'] = 'item', ['image'] = 'bag.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'Duffel bag'},
```
# Open Source
Source: https://docs.projectx.gg/resources/fleeca-bank-robbery-k4mb1/opensource
Open source files available for customization in the K4MB1 Fleeca Bank Robbery resource
Most of the core logic in this resource is handled by the bridge. The open source files are provided so you can customize minigames, add hooks for custom systems, and extend the script without touching escrow.
## opensource/client/client.lua
This file handles zone creation, drawtext, evidence, stress, and most importantly, the minigame callback. If you want to change the minigames used for each step, this is the only file you need to edit.
### Minigame Callback
Each robbery step triggers the `projectx-fleecabankrobbery-k4mb1:client:Minigames` callback with the step name. You can swap any minigame by replacing the export call inside the matching `elseif` block.
```lua theme={null}
lib.callback.register('projectx-fleecabankrobbery-k4mb1:client:Minigames', function(Step)
local p = promise.new()
if Step == "Fusebox" then
if not exports['projectx-bridge']:MinigameCheck("SN-Hacking") then p:resolve(false) return Citizen.Await(p) end
local success = exports['SN-Hacking']:MemoryCards('hard')
p:resolve(success)
elseif Step == "Fingerprint" then
if not exports['projectx-bridge']:MinigameCheck("utk_fingerprint") then p:resolve(false) return Citizen.Await(p) end
TriggerEvent("utk_fingerprint:Start", 4, 6, 2, function(success)
p:resolve(success)
end)
elseif Step == "KeypadOne" then
if not exports['projectx-bridge']:MinigameCheck("simonsays") then p:resolve(false) return Citizen.Await(p) end
local success = exports['simonsays']:StartSimonSays(5, 5)
p:resolve(success)
elseif Step == "Printer" then
if not exports['projectx-bridge']:MinigameCheck("lightsout") then p:resolve(false) return Citizen.Await(p) end
local success = exports['lightsout']:StartLightsOut(4, 20)
p:resolve(success)
elseif Step == "Search" then
if not exports['projectx-bridge']:MinigameCheck("pd-safe") then p:resolve(false) return Citizen.Await(p) end
local success = exports["pd-safe"]:createSafe({math.random(0,99)})
p:resolve(success)
elseif Step == "Vault" then
if not exports['projectx-bridge']:MinigameCheck("SN-Hacking") then p:resolve(false) return Citizen.Await(p) end
local success = exports['SN-Hacking']:ColorPicker(5, 7000, 3000)
p:resolve(success)
elseif Step == "JailDoorKeypad" then
if not exports['projectx-bridge']:MinigameCheck("SN-Hacking") then p:resolve(false) return Citizen.Await(p) end
local success = exports['SN-Hacking']:ColorPicker(5, 7000, 3000)
p:resolve(success)
elseif Step == "JailDoor" then
return true
else
p:resolve(false)
end
return Citizen.Await(p)
end)
```
You can return `true` unconditionally inside any step block to skip that minigame entirely. This can be useful for testing or for steps you want to make automatic.
The default minigames per step are:
| Step | Minigame Resource | Function |
| ---------------- | ----------------- | ----------------------- |
| `Fusebox` | `SN-Hacking` | `MemoryCards` |
| `Fingerprint` | `utk_fingerprint` | `Start` |
| `KeypadOne` | `simonsays` | `StartSimonSays` |
| `Printer` | `lightsout` | `StartLightsOut` |
| `Search` | `pd-safe` | `createSafe` |
| `Vault` | `SN-Hacking` | `ColorPicker` |
| `JailDoorKeypad` | `SN-Hacking` | `ColorPicker` |
| `JailDoor` | — | Skipped (`return true`) |
***
## opensource/server/server.lua
This file handles dispatch, item/money functions, logging, and exposes several hooks you can use to run custom logic at specific points in the robbery.
### Hooks
Called whenever a player successfully completes a robbery step. Use this to award XP, trigger events, or log individual step completions.
```lua theme={null}
function SuccessfulStep(source, location, step)
if step == "Fusebox" then
-- exports['projectx-bridge']:AddExperience(source, 'criminal', 10)
elseif step == "Register" then
-- exports['projectx-bridge']:AddExperience(source, 'criminal', 10)
end
end
```
Step names match the minigame callback steps and interaction keys defined in `config/config.lua`.
Called whenever a player fails a robbery step. Use this to remove XP, items, or apply penalties.
```lua theme={null}
function FailedStep(source, location, step)
if step == "Fusebox" then
-- RemoveItem(source, 'x_device', 1)
elseif step == "Register" then
-- Apply custom penalty
end
end
```
Called before a player can start a robbery at a location. Return `false` to block them.
```lua theme={null}
function InitialCheck(src, Location, Interaction)
return true
-- Add a group check, tablet requirement, or any other gate here
end
```
Called whenever a Fleeca location resets. Use this to update a scoreboard, trigger an external event, or notify players.
```lua theme={null}
function RobberyResetHook(location)
-- TriggerEvent('my-scoreboard:update', location)
end
```
# Commands
Source: https://docs.projectx.gg/resources/fleeca-bank-robbery-nteam/commands
Admin commands for the NTeam Fleeca Bank Robbery resource
## Admin Commands
**Usage**: `/projectxfleeca`
**Permission**: Admin (configurable via `CheckPerms` in the bridge)
**Description**: Resets the nearest Fleeca bank within 50 units of your position. Useful for testing or recovering from a stuck robbery.
**Example**:
```
/projectxfleeca
```
This command resets the closest bank location automatically. To reset a specific bank programmatically, use the `Reset(location)` export instead. See the [Exports](/resources/fleeca-bank-robbery-nteam/exports) page for details.
# Configuration
Source: https://docs.projectx.gg/resources/fleeca-bank-robbery-nteam/configuration
Full reference for all configuration options in the NTeam Fleeca Bank Robbery resource
## config/config.lua
### Main Settings
Shows polyzones created inside the game. Useful for testing zone placement.
Disables all minigames. Useful for testing the full robbery flow without completing minigame challenges.
The key code used to trigger drawtext interactions. `38` is `[E]` by default.
The size of the drawtext interaction zone.
Spawns networked props server side. Set to `false` to spawn them client side instead.
Minimum number of police required online before a robbery can be started. Set to `0` to disable.
The jobs that count as police for the `MinimumPolice` check and dispatch alerts.
```lua theme={null}
PoliceJobs = {"police", "fbi"}
```
Requires a minimum number of players nearby to start a robbery.
```lua theme={null}
RequiredPlayersNearby = {amount = 0, radius = 20.0}
```
Set `amount` to `0` or `false` to disable.
Maximum number of Fleeca robberies that can be active at the same time. Set to `0` to disable.
Requires players to have a `bag` item in order to loot the trolleys.
Length of the employee list that appears on the board during the employee puzzle.
Disables the employee puzzle. Defaults to `false` on the NTeam map variant.
Disables all particle effects during the robbery.
Disables weapon removal during the robbery. Only enable this if you use a weapon wheel resource.
Enables compatibility with the Gruppe Sechs Job by 17mov.
Disables the loud approach path entirely.
Disables the silent approach path entirely.
***
### Cooldowns & Limits
When `true`, robbing one Fleeca puts all Fleecas on cooldown. When `false`, each location has its own cooldown.
Cooldown duration in minutes.
Per-player cooldown in minutes after completing a robbery. Set to `0` to disable.
Maximum number of total robberies allowed per server restart. Set to `0` to disable.
Maximum number of robberies a single player can complete per server restart. Set to `0` to disable.
***
### Strike System
Maximum number of trolleys that can spawn. Actual count depends on the strike system and approach used.
Number of strikes players can accumulate before their reward is cut. Set to `false` to disable.
(Silent Approach only) Number of trolleys removed from the reward when the strike limit is reached.
(Loud Approach only) Number of trolleys that spawn during a loud approach.
***
### Skill System
Requires players to meet a minimum level from an integrated XP/skill system before starting the heist. Must have an XP system configured in the bridge.
Minimum level required to initiate the heist. Only applies when `SkillSystem` is `true`.
***
### Dispatch
Title shown in the dispatch alert.
Message body shown in the dispatch alert.
Radio code shown in the dispatch alert.
Time in seconds the dispatch alert remains visible. Not all dispatch systems support this.
Blip settings for the dispatch map marker.
```lua theme={null}
Blip = {
Text = 'Fleeca bank Robbery',
Color = 1,
Sprite = 41,
Scale = 0.8
}
```
Controls which step triggers the dispatch alert. Only one of the step keys should be enabled at a time (excluding Loud/Silent).
```lua theme={null}
DispatchLocation = {
["Loud"] = true,
["Silent"] = false,
["KeypadOne"] = true,
["KeypadTwo"] = false,
["Vault"] = false,
}
```
***
### Bonus Items
Enables or disables bonus item drops at the end of the heist.
Percentage chance that any bonus item is given at all.
Number of items that can be given from the bonus items table.
Table of possible bonus items. Each entry has a `Name`, `Chance` (%), and `Amount` range.
The total chance across all items needs to add up to 100%.
```lua theme={null}
Items = {
{Name = "x_device", Chance = 30, Amount = {min = 1, max = 1}},
{Name = "x_phone", Chance = 50, Amount = {min = 1, max = 1}},
{Name = "x_stethoscope", Chance = 20, Amount = {min = 1, max = 1}},
}
```
***
### Evidence & Stress
Enables fingerprint evidence drops at the crime scene.
Percentage chance that fingerprint evidence is left behind.
Enables the stress system. Stress is only applied when a minigame is failed.
Percentage chance that stress is applied on a minigame fail.
The minimum and maximum amount of stress applied per failure.
***
### Durations
Progressbar durations in milliseconds:
| Setting | Default |
| ------------------------ | ------- |
| `NotificationDuration` | `2500` |
| `FingerprintDuration` | `6000` |
| `FuseboxDuration` | `6000` |
| `ShelfDuration` | `5000` |
| `KeypadOneDuration` | `6000` |
| `KeypadTwoDuration` | `6000` |
| `SearchDuration` | `6000` |
| `PrinterDuration` | `7500` |
| `VaultDuration` | `6000` |
| `JailDoorDuration` | `5000` |
| `JailDoorKeypadDuration` | `6000` |
***
### Items
Maps logical item roles to inventory item names.
```lua theme={null}
Config.Items = {
["Device"] = "x_device",
["Pliers"] = "pliers",
["Pictures"] = "employeepictures",
["Bag"] = "bag",
["Keys"] = "fleeca_key",
["Keycard"] = "fleecacard",
["Laptop"] = "x_laptop",
}
```
Percentage chance that an item breaks on use. Set to `0` to disable.
```lua theme={null}
Config.ItemsBreak = {
["Device"] = 0,
["Pliers"] = 0,
["Laptop"] = 0,
}
```
***
### Locations
Enable or disable each of the 6 Fleeca banks.
```lua theme={null}
Config.FleecaLocations = {
["RockfordHills"] = true,
["Legion"] = true,
["Burton"] = true,
["Alta"] = true,
["GrandSenoraDesert"] = true,
["BanhamCanyon"] = true,
}
```
Per-location interaction coordinates live in `Config.Fleecas` and trolley spawn/loot points in `Config.Trollys`. Edit those tables if you need to move targets — you do not need to copy every coordinate from the default config for normal setup.
***
### Rewards
Rewards are split into three types: **cash**, **gold**, and **diamond** (`Config.Rewardcash`, `Config.Rewardgold`, `Config.Rewarddiamond`). Each follows the same format.
If `true`, items are given per individual stack pickup from the trolley. If `false`, the reward is given at the end of the full trolley animation.
Set to `true` to give money directly. Set to `false` to give a cash item instead.
The item name used when `Cash` is `false`. Gold defaults to `goldbar`, diamond to `diamond`.
The minimum and maximum cash or item amount per pickup or per trolley completion. Gold and diamond use their own ranges.
Optional item metadata. Used if `markedbills` or similar items carry random value data in their info table.
***
### Logs
Configured in `config/logs.lua`.
Enables or disables the logging system.
Your Discord webhook URL, or your Fivemerr/Fivemanage API key.
The Fivemanage dataset to log activity to. Leave as `"default"` unless you have a specific dataset configured.
# Exports
Source: https://docs.projectx.gg/resources/fleeca-bank-robbery-nteam/exports
Server-side exports available for the NTeam Fleeca Bank Robbery resource
## Server Exports
All location-based exports require a valid Fleeca location key from `Config.FleecaLocations` (e.g. `"RockfordHills"`, `"Legion"`, `"Burton"`, `"Alta"`, `"GrandSenoraDesert"`, `"BanhamCanyon"`).
### Reset
Resets the robbery at the given location, clearing active state and restoring the bank.
```lua theme={null}
exports['projectx-fleecabankrobbery-nteam']:Reset('RockfordHills')
```
**Returns**
* `true` if the location exists and was reset successfully
***
### IsRobberyInProgress
Returns whether a robbery is currently active at the given location.
```lua theme={null}
local active = exports['projectx-fleecabankrobbery-nteam']:IsRobberyInProgress('Legion')
```
**Returns**
* `true` if a robbery is in progress at that location, `false` otherwise
**Example**
```lua theme={null}
local active = exports['projectx-fleecabankrobbery-nteam']:IsRobberyInProgress('Burton')
if active then
print("Burton Fleeca is being robbed")
end
```
***
### GetActiveRobberyCount
Returns the total number of active Fleeca robberies across all locations.
```lua theme={null}
local count = exports['projectx-fleecabankrobbery-nteam']:GetActiveRobberyCount()
```
**Returns**
* `count` (number) — total active robberies
**Example**
```lua theme={null}
local count = exports['projectx-fleecabankrobbery-nteam']:GetActiveRobberyCount()
print("Active Fleeca robberies: " .. count)
```
# FAQs
Source: https://docs.projectx.gg/resources/fleeca-bank-robbery-nteam/faqs
Frequently asked questions about the NTeam Fleeca Bank Robbery resource
## General Questions
The script supports QBCore, Qbox, and ESX through the Project X Bridge. Set `Framework` to `'auto'` in the bridge config and it will detect your framework automatically.
Yes. The bridge is required for this script to function. It handles framework detection, inventory, dispatch, notifications, progressbars, XP, evidence, logs, and global cooldowns. See the [Bridge Installation](/resources/bridge/installation) page for setup instructions.
When you purchase NTeam Fleeca Bank Robbery, the `projectx-bridge` asset is automatically delivered to your CFX portal.
Inventory is handled through the Project X Bridge. Set `Inventory` to `'auto'` in the bridge config for automatic detection. Supported values include ox\_inventory, qb-inventory, ps/lj-inventory, codem-inventory, origen\_inventory, tgiann-inventory, ak47\_inventory, jpr-inventory, one\_inventory, and ESX default inventory. See the [FAQs](/faqs) for the full list with config values and links.
The bridge supports 30+ dispatch systems including PS Dispatch, CodeSign, CodeSign 3D, LB Tablet, FD Dispatch, Wasabi MDT, Oxide Dispatch, VX MDT, Sonoran CAD, and many more. Set `Dispatch` to `'auto'` in the bridge config for automatic detection. See the [FAQs](/faqs) for the full list with config values and links.
Six locations: RockfordHills, Legion, Burton, Alta, GrandSenoraDesert, and BanhamCanyon. Enable or disable each one in `Config.FleecaLocations`.
The silent approach is higher risk but offers a higher potential reward. Failing minigames during silent accumulates strikes, which reduce the number of trolleys available at the end. The loud approach is lower risk with a fixed trolley count controlled by `StrikeLoud`, but may trigger dispatch immediately.
Open `opensource/client/client.lua` and find the `projectx-fleecabankrobbery-nteam:client:Minigames` callback. Each robbery step has its own `elseif` block where you can swap the minigame export for any resource you prefer. You can also return `true` inside any block to skip that minigame entirely.
See the [Open Source](/resources/fleeca-bank-robbery-nteam/opensource) page for the full callback code and a table of the default minigame assignments.
Use the `/projectxfleeca` in-game command (requires admin permissions) to reset the nearest bank within 50m, or call the `Reset(location)` server export from another resource:
```lua theme={null}
exports['projectx-fleecabankrobbery-nteam']:Reset('RockfordHills')
```
See the [Commands](/resources/fleeca-bank-robbery-nteam/commands) and [Exports](/resources/fleeca-bank-robbery-nteam/exports) pages for more details.
## Configuration Questions
Set `MinimumPolice` to the number you want in `config/config.lua`, and make sure the correct jobs are listed in `PoliceJobs`.
```lua theme={null}
MinimumPolice = 2,
PoliceJobs = {"police", "fbi"},
```
Set `SkillSystem` to `true` and configure `MinimumLevel` in `config/config.lua`. You also need a compatible XP system integrated in the bridge config (`XPSystem`).
Supported systems include `projectx-xp`, `pickle_xp`, `sd-levels`, `cw-rep`, and `OT_skills`. See the [FAQs](/faqs) for bridge XP config values.
Enable `Bonus.Status` and configure the `Bonus.Items` table in `config/config.lua`. Each item has a `Chance` percentage and an `Amount` range. Bonus drops are off by default.
```lua theme={null}
Bonus = {
Status = true,
BonusChance = 15,
ItemCount = 1,
Items = {
{Name = "x_device", Chance = 30, Amount = {min = 1, max = 1}},
{Name = "x_phone", Chance = 50, Amount = {min = 1, max = 1}},
{Name = "x_stethoscope", Chance = 20, Amount = {min = 1, max = 1}},
}
}
```
Set `Cooldown.Global` to `true` to lock all Fleecas when one is robbed. Set it to `false` for individual per-location cooldowns. Adjust the duration with `Cooldown.Timer` (in minutes).
Toggle each location in `Config.FleecaLocations`:
```lua theme={null}
Config.FleecaLocations = {
["RockfordHills"] = true,
["Legion"] = true,
["Burton"] = false,
["Alta"] = true,
["GrandSenoraDesert"] = true,
["BanhamCanyon"] = true,
}
```
## Troubleshooting
Make sure you have all required dependencies started before the script in your `server.cfg` (`ox_lib`, `projectx-bridge`, then minigames, then the robbery script).
Verify all minigame resources (`SN-Hacking`, `utk_fingerprint`, `simonsays`, `lightsout`, `pd-safe`) are started and placed outside the robbery script folder. The bridge's `MinigameCheck` will return `false` if a minigame resource is missing.
# Installation
Source: https://docs.projectx.gg/resources/fleeca-bank-robbery-nteam/installation
Step by step instructions to install the NTeam Fleeca Bank Robbery resource
## Installation Steps
Verify all dependencies below are started **before** this script in your `server.cfg`.
Download ox\_lib
Required map by NTeam
Required Project X Bridge
Download the minigames zip and place each resource into your standalone or dependencies folder.
Download and place in your standalone or minigames folder
Make sure the minigames are **not** in the same folder as the robbery script.
Extract the script from the zip file and place it into your scripts folder.
Add the required items and their images to your inventory resource. See the [items section](#items-required) below for the full list.
Item images done by [Artwork Inventory](https://discord.gg/Z2awpnXKdw) - Use code **ProjectX** for 10% off!
Open `config/config.lua` and adjust the settings to match your server. The bridge handles framework, inventory, dispatch, and interaction automatically if set to `'auto'`.
Make sure the bridge, ox\_lib, your target, dispatch, inventory, and minigames are all started before the robbery script.
```cfg theme={null}
ensure ox_lib
ensure projectx-bridge
ensure SN-Hacking
ensure utk_fingerprint
ensure simonsays
ensure lightsout
ensure pd-safe
ensure projectx-fleecabankrobbery-nteam
```
## Items Required
### Items Required from Outside the Robbery
The `fleecacard` must be obtained externally (e.g. from another robbery or side mission) before the robbery can be started.
* `fleecacard`
### Items Required from Shop/Black Market
* `x_device`
* `x_laptop`
* `pliers`
* `fleeca_key`
* `bag`
The rest of the items (`employeepictures`) are obtained within the robbery itself.
### Item Configuration
```lua theme={null}
["fleeca_key"] = {
label = "Fleeca Key",
weight = 50,
stack = false,
close = false,
description = "Key!",
},
["employeepictures"] = {
label = "Employee Pictures",
weight = 25,
stack = false,
close = false,
description = "Faces of employees",
},
["pliers"] = {
label = "Pliers",
weight = 125,
stack = false,
close = false,
description = "A pair of pliers",
},
["x_device"] = {
label = "X Device",
weight = 125,
stack = false,
close = false,
description = "?????????",
},
["bag"] = {
label = "Duffel Bag",
weight = 250,
stack = false,
close = false,
description = "Duffel bag",
},
["x_laptop"] = {
label = "X Laptop",
weight = 50,
stack = false,
close = false,
description = "?????????",
},
["fleecacard"] = {
label = "Fleeca Card",
weight = 300,
stack = false,
close = false,
description = "A Security card for Fleeca Bank",
},
```
```lua theme={null}
['fleeca_key'] = {['name'] = 'fleeca_key', ['label'] = 'Fleeca Key', ['weight'] = 50, ['type'] = 'item', ['image'] = 'fleeca_key.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'Key!'},
['employeepictures'] = {['name'] = 'employeepictures', ['label'] = 'Employee Pictures', ['weight'] = 25, ['type'] = 'item', ['image'] = 'employeepictures.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'Faces of employees'},
['fleecacard'] = {['name'] = 'fleecacard', ['label'] = 'Fleeca Keycard', ['weight'] = 25, ['type'] = 'item', ['image'] = 'fleecacard.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'A Security card for Fleeca Bank'},
['x_laptop'] = {['name'] = 'x_laptop', ['label'] = 'X Laptop', ['weight'] = 50, ['type'] = 'item', ['image'] = 'x_laptop.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '?????????'},
['x_device'] = {['name'] = 'x_device', ['label'] = 'X Device', ['weight'] = 50, ['type'] = 'item', ['image'] = 'x_device.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '?????????'},
['pliers'] = {['name'] = 'pliers', ['label'] = 'Pliers', ['weight'] = 200, ['type'] = 'item', ['image'] = 'pliers.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'Pliers..?'},
['bag'] = {['name'] = 'bag', ['label'] = 'Bag', ['weight'] = 400, ['type'] = 'item', ['image'] = 'bag.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'Duffel bag'},
```
# Open Source
Source: https://docs.projectx.gg/resources/fleeca-bank-robbery-nteam/opensource
Open source files available for customization in the NTeam Fleeca Bank Robbery resource
Most of the core logic in this resource is handled by the bridge. The open source files are provided so you can customize minigames, add hooks for custom systems, and extend the script without touching escrow.
## opensource/client/client.lua
This file handles zone creation, drawtext, evidence, stress, and most importantly, the minigame callback. If you want to change the minigames used for each step, this is the only file you need to edit.
### Minigame Callback
Each robbery step triggers the `projectx-fleecabankrobbery-nteam:client:Minigames` callback with the step name. You can swap any minigame by replacing the export call inside the matching `elseif` block.
```lua theme={null}
lib.callback.register('projectx-fleecabankrobbery-nteam:client:Minigames', function(Step)
local p = promise.new()
if Step == "Fusebox" then
if not exports['projectx-bridge']:MinigameCheck("SN-Hacking") then p:resolve(false) return Citizen.Await(p) end
local success = exports['SN-Hacking']:MemoryCards('hard')
p:resolve(success)
elseif Step == "Fingerprint" then
if not exports['projectx-bridge']:MinigameCheck("utk_fingerprint") then p:resolve(false) return Citizen.Await(p) end
TriggerEvent("utk_fingerprint:Start", 4, 6, 2, function(success)
p:resolve(success)
end)
elseif Step == "KeypadOne" then
if not exports['projectx-bridge']:MinigameCheck("simonsays") then p:resolve(false) return Citizen.Await(p) end
local success = exports['simonsays']:StartSimonSays(5, 5)
p:resolve(success)
elseif Step == "Printer" then
if not exports['projectx-bridge']:MinigameCheck("lightsout") then p:resolve(false) return Citizen.Await(p) end
local success = exports['lightsout']:StartLightsOut(4, 20)
p:resolve(success)
elseif Step == "Search" then
if not exports['projectx-bridge']:MinigameCheck("pd-safe") then p:resolve(false) return Citizen.Await(p) end
local success = exports["pd-safe"]:createSafe({math.random(0,99)})
p:resolve(success)
elseif Step == "Vault" then
if not exports['projectx-bridge']:MinigameCheck("SN-Hacking") then p:resolve(false) return Citizen.Await(p) end
local success = exports['SN-Hacking']:ColorPicker(5, 7000, 3000)
p:resolve(success)
elseif Step == "JailDoorKeypad" then
if not exports['projectx-bridge']:MinigameCheck("SN-Hacking") then p:resolve(false) return Citizen.Await(p) end
local success = exports['SN-Hacking']:ColorPicker(5, 7000, 3000)
p:resolve(success)
elseif Step == "JailDoor" then
return true
else
p:resolve(false)
end
return Citizen.Await(p)
end)
```
You can return `true` unconditionally inside any step block to skip that minigame entirely. This can be useful for testing or for steps you want to make automatic.
The default minigames per step are:
| Step | Minigame Resource | Function |
| ---------------- | ----------------- | ----------------------- |
| `Fusebox` | `SN-Hacking` | `MemoryCards` |
| `Fingerprint` | `utk_fingerprint` | `Start` |
| `KeypadOne` | `simonsays` | `StartSimonSays` |
| `Printer` | `lightsout` | `StartLightsOut` |
| `Search` | `pd-safe` | `createSafe` |
| `Vault` | `SN-Hacking` | `ColorPicker` |
| `JailDoorKeypad` | `SN-Hacking` | `ColorPicker` |
| `JailDoor` | — | Skipped (`return true`) |
***
## opensource/server/server.lua
This file handles dispatch, item/money functions, logging, and exposes several hooks you can use to run custom logic at specific points in the robbery.
### Hooks
Called whenever a player successfully completes a robbery step. Use this to award XP, trigger events, or log individual step completions.
```lua theme={null}
function SuccessfulStep(source, location, step)
if step == "Fusebox" then
-- exports['projectx-bridge']:AddExperience(source, 'criminal', 10)
elseif step == "Register" then
-- exports['projectx-bridge']:AddExperience(source, 'criminal', 10)
end
end
```
Step names match the minigame callback steps and interaction keys defined in `config/config.lua`.
Called whenever a player fails a robbery step. Use this to remove XP, items, or apply penalties.
```lua theme={null}
function FailedStep(source, location, step)
if step == "Fusebox" then
-- RemoveItem(source, 'x_device', 1)
elseif step == "Register" then
-- Apply custom penalty
end
end
```
Called before a player can start a robbery at a location. Return `false` to block them.
```lua theme={null}
function InitialCheck(src, Location, Interaction)
return true
-- Add a group check, tablet requirement, or any other gate here
end
```
Called whenever a Fleeca location resets. Use this to update a scoreboard, trigger an external event, or notify players.
```lua theme={null}
function RobberyResetHook(location)
-- TriggerEvent('my-scoreboard:update', location)
end
```
# Commands
Source: https://docs.projectx.gg/resources/fleeca-bank-robbery-tstudio/commands
Admin commands for the TStudio Fleeca Bank Robbery resource
## Admin Commands
**Usage**: `/projectxfleeca`
**Permission**: Admin (configurable via `CheckPerms` in the bridge)
**Description**: Resets the nearest Fleeca bank within approximately 50 units of your position. Useful for testing or recovering from a stuck robbery.
**Example**:
```
/projectxfleeca
```
This command resets the closest Fleeca location automatically. To reset a specific bank programmatically, use the `Reset(location)` export instead. See the [Exports](/resources/fleeca-bank-robbery-tstudio/exports) page for details.
# Configuration
Source: https://docs.projectx.gg/resources/fleeca-bank-robbery-tstudio/configuration
Full reference for all configuration options in the TStudio Fleeca Bank Robbery resource
## config/config.lua
### Main Settings
Shows polyzones created inside the game. Useful for testing zone placement.
Disables all minigames. Useful for testing the full robbery flow without completing minigame challenges.
The key code used to trigger drawtext interactions. `38` is `[E]` by default.
The size of the drawtext interaction zone.
Spawns networked props server side. Set to `false` to spawn them client side instead.
Requires players to have a `bag` item in order to loot trolleys.
Length of the employee list that appears on the board during the employee puzzle.
Disables the employee puzzle step entirely.
Disables all particle effects during the robbery.
Disables weapon removal during the robbery. Only enable this if you use a weapon wheel resource.
Enables GruppeSechs Job compatibility by 17mov.
Minimum number of police required online before a robbery can be started. Set to `0` to disable.
The jobs that count as police for the `MinimumPolice` check and dispatch alerts.
```lua theme={null}
PoliceJobs = {"police", "fbi"}
```
Requires a minimum number of players nearby to start a robbery.
```lua theme={null}
RequiredPlayersNearby = {amount = 0, radius = 20.0}
```
Set `amount` to `0` or `false` to disable.
Maximum number of Fleeca robberies that can be active at the same time. Set to `0` to disable.
Disables the loud approach path entirely.
Disables the silent approach path entirely.
***
### Cooldowns & Limits
When `true`, robbing one Fleeca puts all Fleeca banks on cooldown. When `false`, each bank has its own cooldown.
Cooldown duration in minutes.
Per-player cooldown in minutes after completing a robbery. Set to `0` to disable.
Maximum number of total robberies allowed per server restart. Set to `0` to disable.
Maximum number of robberies a single player can complete per server restart. Set to `0` to disable.
***
### Strike System
Maximum number of trolleys that can spawn. Actual count depends on the strike system and approach used.
Number of strikes players can accumulate before their reward is cut. Set to `false` to disable the strike system.
(Silent Approach only) Number of trolleys removed from the reward when the strike limit is reached.
(Loud Approach only) Number of trolleys that spawn during a loud approach.
***
### Skill System
Requires players to meet a minimum level from an integrated XP/skill system before starting a robbery. Must have an XP system configured in the bridge.
Minimum level required to initiate a robbery. Only applies when `SkillSystem` is `true`.
***
### Dispatch
Title shown in the dispatch alert.
Message body shown in the dispatch alert.
Radio code shown in the dispatch alert.
Time in seconds the dispatch alert remains visible. Not all dispatch systems support this.
Blip settings for the dispatch map marker.
```lua theme={null}
Blip = {
Text = 'Fleeca bank Robbery',
Color = 1,
Sprite = 41,
Scale = 0.8
}
```
Controls which steps trigger dispatch alerts. `Loud` and `Silent` can be enabled independently. Only one of the step-based options should be enabled at a time.
```lua theme={null}
DispatchLocation = {
["Loud"] = true,
["Silent"] = false,
["KeypadOne"] = true,
["ElectricBox"] = false,
["Vault"] = false,
}
```
***
### Bonus Items
Enables or disables bonus item drops at the end of a robbery.
Percentage chance that any bonus item is given at all.
Number of items that can be given from the bonus items table.
Table of possible bonus items. Each entry has a `Name`, `Chance` (%), and `Amount` range.
The total chance across all items needs to add up to 100%.
```lua theme={null}
Items = {
{Name = "x_device", Chance = 30, Amount = {min = 1, max = 1}},
{Name = "x_phone", Chance = 50, Amount = {min = 1, max = 1}},
{Name = "x_stethoscope", Chance = 20, Amount = {min = 1, max = 1}},
}
```
***
### Evidence & Stress
Enables fingerprint evidence drops at the crime scene.
Percentage chance that fingerprint evidence is left behind.
Enables the stress system. Stress is only applied when a minigame is failed.
Percentage chance that stress is applied on a minigame fail.
The minimum and maximum amount of stress applied per failure.
***
### Required Items
Maps logical item names to your inventory item names.
```lua theme={null}
Items = {
["Device"] = "x_device",
["Pliers"] = "pliers",
["Pictures"] = "employeepictures",
["Bag"] = "bag",
["Keycard"] = "fleecacard",
["Laptop"] = "x_laptop",
}
```
Break chance (%) for each item when used during a robbery.
```lua theme={null}
ItemsBreak = {
["Device"] = 0,
["Pliers"] = 0,
["Laptop"] = 0,
}
```
***
### Step Durations
Progress bar durations (milliseconds) for each interaction step:
| Field | Default |
| ---------------------- | ------- |
| `NotificationDuration` | `2500` |
| `FingerprintDuration` | `6000` |
| `FuseboxDuration` | `6000` |
| `ShelfDuration` | `5000` |
| `KeypadOneDuration` | `6000` |
| `SearchDuration` | `6000` |
| `ElectricBoxDuration` | `7500` |
| `PrinterDuration` | `7500` |
| `VaultDuration` | `6000` |
| `JailDoorDuration` | `5000` |
***
### Rewards
Trolley rewards are split into **cash**, **gold**, and **diamond** tables (`Config.Rewardcash`, `Config.Rewardgold`, `Config.Rewarddiamond`). Each follows the same format:
If `true`, items are given per individual stack pickup from the trolley. If `false`, the reward is given at the end of the full trolley animation.
Set to `true` to give money directly. Set to `false` to give a cash item instead.
The item name used when `Cash` is `false`.
The minimum and maximum cash or item amount per pickup or per trolley completion.
Optional item metadata. Used if `markedbills` or similar items carry random value data in their info table.
**Table loot** is configured separately in `Config.TableRewardcash` (cash tables, not trolleys):
```lua theme={null}
Config.TableRewardcash = {
['Cash'] = true,
['Item'] = "markedbills",
['StackAmount'] = {min = 8360, max = 8360},
['ItemInfo'] = false,
}
```
Table interaction positions per bank are in `Config.LootTables`. Trolley spawn positions and loot types are in `Config.Trollys`.
***
### Fleeca Locations
Enable or disable individual banks with `Config.FleecaLocations`:
```lua theme={null}
FleecaLocations = {
["RockfordHills"] = true,
["Legion"] = true,
["Burton"] = true,
["Alta"] = true,
["GrandSenoraDesert"] = true,
["BanhamCanyon"] = true,
}
```
Full per-bank coordinates, interactions, and props live in `Config.Fleecas`. Door lock definitions are in `Config.DoorList`. Use the location key when calling exports.
***
### Other Settings
ox\_lib input text for the hidden password step (`Title`, `Label`, `Description`, `Icon`).
Alarm settings including `AlarmDuration` (minutes), `AudioName`, `AudioRef`, and `Range`.
Employee puzzle difficulty options (`ShowFirstLetter`, `ShowLastLetter`, `HideOneClue`).
Employee name/clue data used by the employee puzzle board.
***
### Logs
Configured in `config/logs.lua`.
Enables or disables the logging system.
Your Discord webhook URL, or your Fivemerr/Fivemanage API key.
The Fivemanage dataset to log activity to. Leave as `"default"` unless you have a specific dataset configured.
# Exports
Source: https://docs.projectx.gg/resources/fleeca-bank-robbery-tstudio/exports
Server-side exports available for the TStudio Fleeca Bank Robbery resource
## Server Exports
All location-based exports require a valid Fleeca key from `Config.FleecaLocations` / `Config.Fleecas` (e.g. `"RockfordHills"`, `"Legion"`, `"Burton"`, `"Alta"`, `"GrandSenoraDesert"`, `"BanhamCanyon"`).
### Reset
Resets the robbery at the given location, clearing active state and restoring the bank.
```lua theme={null}
exports['projectx-fleecabankrobbery-tstudio']:Reset('RockfordHills')
```
**Returns**
* `true` if the location exists and was reset successfully
***
### IsRobberyInProgress
Returns whether a robbery is currently active at the given location.
```lua theme={null}
local active = exports['projectx-fleecabankrobbery-tstudio']:IsRobberyInProgress('RockfordHills')
```
**Returns**
* `true` if a robbery is in progress at that location, `false` otherwise
**Example**
```lua theme={null}
local active = exports['projectx-fleecabankrobbery-tstudio']:IsRobberyInProgress('Legion')
if active then
print("Legion Fleeca is being robbed")
end
```
***
### GetActiveRobberyCount
Returns the total number of active Fleeca robberies across all locations.
```lua theme={null}
local count = exports['projectx-fleecabankrobbery-tstudio']:GetActiveRobberyCount()
```
**Returns**
* `count` (number) — total active robberies
**Example**
```lua theme={null}
local count = exports['projectx-fleecabankrobbery-tstudio']:GetActiveRobberyCount()
print("Active Fleeca robberies: " .. count)
```
# FAQs
Source: https://docs.projectx.gg/resources/fleeca-bank-robbery-tstudio/faqs
Frequently asked questions about the TStudio Fleeca Bank Robbery resource
## General Questions
The script supports QBCore, Qbox, and ESX through the Project X Bridge. Set `Framework` to `'auto'` in the bridge config and it will detect your framework automatically.
Yes. The bridge is required for this script to function. It handles framework detection, inventory, dispatch, notifications, progressbars, XP, evidence, logs, and global cooldowns. See the [Bridge Installation](/resources/bridge/installation) page for setup instructions.
When you purchase TStudio Fleeca Bank Robbery, the `projectx-bridge` asset is automatically delivered to your CFX portal.
Inventory is handled through the Project X Bridge. Set `Inventory` to `'auto'` in the bridge config for automatic detection. Supported values include ox\_inventory, qb-inventory, ps/lj-inventory, codem-inventory, origen\_inventory, tgiann-inventory, ak47\_inventory, jpr-inventory, one\_inventory, and ESX default inventory. See the [FAQs](/faqs) for the full list with config values and links.
The bridge supports 30+ dispatch systems including PS Dispatch, CodeSign, CodeSign 3D, LB Tablet, FD Dispatch, Wasabi MDT, Oxide Dispatch, VX MDT, Sonoran CAD, and many more. Set `Dispatch` to `'auto'` in the bridge config for automatic detection. See the [FAQs](/faqs) for the full list with config values and links.
Six banks are supported via `Config.FleecaLocations`: RockfordHills, Legion, Burton, Alta, GrandSenoraDesert, and BanhamCanyon. Enable or disable each location independently.
The silent approach is higher risk but offers a higher potential reward. Failing minigames during silent accumulates strikes, which reduce the number of trolleys available at the end. The loud approach is lower risk with a fixed trolley count controlled by `StrikeLoud`, but may trigger dispatch immediately.
Open `opensource/client/client.lua` and find the `projectx-fleecabankrobbery-tstudio:client:Minigames` callback. Each robbery step has its own `elseif` block where you can swap the minigame export for any resource you prefer. You can also return `true` inside any block to skip that minigame entirely.
See the [Open Source](/resources/fleeca-bank-robbery-tstudio/opensource) page for the full callback code and a table of the default minigame assignments.
Use the `/projectxfleeca` in-game command (requires admin permissions) to reset the nearest bank within \~50m, or call the `Reset(location)` server export from another resource:
```lua theme={null}
exports['projectx-fleecabankrobbery-tstudio']:Reset('RockfordHills')
```
See the [Commands](/resources/fleeca-bank-robbery-tstudio/commands) and [Exports](/resources/fleeca-bank-robbery-tstudio/exports) pages for more details.
## Configuration Questions
Set `MinimumPolice` to the number you want in `config/config.lua`, and make sure the correct jobs are listed in `PoliceJobs`.
```lua theme={null}
MinimumPolice = 2,
PoliceJobs = {"police", "fbi"},
```
Set `SkillSystem` to `true` and configure `MinimumLevel` in `config/config.lua`. You also need a compatible XP system integrated in the bridge config (`XPSystem`).
Supported systems include `projectx-xp`, `pickle_xp`, `sd-levels`, `cw-rep`, and `OT_skills`. See the [FAQs](/faqs) for bridge XP config values.
Enable `Bonus.Status` and configure the `Bonus.Items` table in `config/config.lua`. Each item has a `Chance` percentage and an `Amount` range.
```lua theme={null}
Bonus = {
Status = true,
BonusChance = 15,
ItemCount = 1,
Items = {
{Name = "x_device", Chance = 30, Amount = {min = 1, max = 1}},
}
}
```
Set `Cooldown.Global` to `true` to lock all Fleeca banks when one is robbed. Set it to `false` for individual per-bank cooldowns. Adjust the duration with `Cooldown.Timer` (in minutes).
`Config.TableRewardcash` controls loot from cash tables (separate from trolley rewards). It uses the same `Cash` / `Item` / `StackAmount` / `ItemInfo` format as trolley rewards. See the [Configuration](/resources/fleeca-bank-robbery-tstudio/configuration) page.
## Troubleshooting
Make sure you have all required dependencies started before the script in your `server.cfg` (`projectx-bridge`, `ox_lib`, minigames).
Verify all minigame resources (`SN-Hacking`, `utk_fingerprint`, `simonsays`, `lightsout`) are started and placed outside the robbery script folder. The bridge's `MinigameCheck` will return `false` if a minigame resource is missing.
# Installation
Source: https://docs.projectx.gg/resources/fleeca-bank-robbery-tstudio/installation
Step by step instructions to install the TStudio Fleeca Bank Robbery resource
## Installation Steps
Verify all dependencies below are started **before** this script in your `server.cfg`.
Download ox\_lib
Required map by TStudio
Required Project X Bridge
Download the minigames zip and place each resource into your standalone or dependencies folder.
Download and place in your standalone or minigames folder
Make sure the minigames are **not** in the same folder as the robbery script.
Extract the script from the zip file and place it into your scripts folder.
Add the required items and their images to your inventory resource. See the [items section](#items-required) below for the full list.
Item images done by [Artwork Inventory](https://discord.gg/Z2awpnXKdw) - Use code **ProjectX** for 10% off!
Open `config/config.lua` and adjust the settings to match your server. The bridge handles framework, inventory, dispatch, and interaction automatically if set to `'auto'`.
Make sure the bridge, ox\_lib, your target, dispatch, inventory, and minigames are all started before the robbery script.
```cfg theme={null}
ensure ox_lib
ensure projectx-bridge
ensure SN-Hacking
ensure utk_fingerprint
ensure simonsays
ensure lightsout
ensure projectx-fleecabankrobbery-tstudio
```
## Items Required
### Items Required from Outside the Robbery
The `fleecacard` must be obtained externally (e.g. from another robbery or side mission) before the robbery can be started.
* `fleecacard`
### Items Required from Shop/Black Market
* `x_device`
* `x_laptop`
* `pliers`
* `bag`
The rest of the items (`employeepictures`) are obtained within the robbery itself.
### Item Configuration
```lua theme={null}
["employeepictures"] = {
label = "Employee Pictures",
weight = 25,
stack = false,
close = false,
description = "Faces of employees",
},
["pliers"] = {
label = "Pliers",
weight = 125,
stack = false,
close = false,
description = "A pair of pliers",
},
["x_device"] = {
label = "X Device",
weight = 125,
stack = false,
close = false,
description = "?????????",
},
["bag"] = {
label = "Duffel Bag",
weight = 250,
stack = false,
close = false,
description = "Duffel bag",
},
["x_laptop"] = {
label = "X Laptop",
weight = 50,
stack = false,
close = false,
description = "?????????",
},
["fleecacard"] = {
label = "Fleeca Card",
weight = 300,
stack = false,
close = false,
description = "A Security card for Fleeca Bank",
},
```
```lua theme={null}
['employeepictures'] = {['name'] = 'employeepictures', ['label'] = 'Employee Pictures', ['weight'] = 25, ['type'] = 'item', ['image'] = 'employeepictures.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'Faces of employees'},
['fleecacard'] = {['name'] = 'fleecacard', ['label'] = 'Fleeca Keycard', ['weight'] = 25, ['type'] = 'item', ['image'] = 'fleecacard.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'A Security card for Fleeca Bank'},
['x_laptop'] = {['name'] = 'x_laptop', ['label'] = 'X Laptop', ['weight'] = 50, ['type'] = 'item', ['image'] = 'x_laptop.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '?????????'},
['x_device'] = {['name'] = 'x_device', ['label'] = 'X Device', ['weight'] = 50, ['type'] = 'item', ['image'] = 'x_device.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '?????????'},
['pliers'] = {['name'] = 'pliers', ['label'] = 'Pliers', ['weight'] = 200, ['type'] = 'item', ['image'] = 'pliers.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'Pliers..?'},
['bag'] = {['name'] = 'bag', ['label'] = 'Bag', ['weight'] = 400, ['type'] = 'item', ['image'] = 'bag.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'Duffel bag'},
```
# Open Source
Source: https://docs.projectx.gg/resources/fleeca-bank-robbery-tstudio/opensource
Open source files available for customization in the TStudio Fleeca Bank Robbery resource
Most of the core logic in this resource is handled by the bridge. The open source files are provided so you can customize minigames, add hooks for custom systems, and extend the script without touching escrow.
## opensource/client/client.lua
This file handles zone creation, drawtext, evidence, stress, and most importantly, the minigame callback. If you want to change the minigames used for each step, this is the only file you need to edit.
### Minigame Callback
Each robbery step triggers the `projectx-fleecabankrobbery-tstudio:client:Minigames` callback with the step name. You can swap any minigame by replacing the export call inside the matching `elseif` block.
```lua theme={null}
lib.callback.register('projectx-fleecabankrobbery-tstudio:client:Minigames', function(Step)
local p = promise.new()
if Step == "Fusebox" then
if not exports['projectx-bridge']:MinigameCheck("SN-Hacking") then p:resolve(false) return Citizen.Await(p) end
local success = exports['SN-Hacking']:MemoryCards('hard')
p:resolve(success)
elseif Step == "Fingerprint" then
if not exports['projectx-bridge']:MinigameCheck("utk_fingerprint") then p:resolve(false) return Citizen.Await(p) end
TriggerEvent("utk_fingerprint:Start", 4, 6, 2, function(success)
p:resolve(success)
end)
elseif Step == "KeypadOne" then
if not exports['projectx-bridge']:MinigameCheck("simonsays") then p:resolve(false) return Citizen.Await(p) end
local success = exports['simonsays']:StartSimonSays(5, 5)
p:resolve(success)
elseif Step == "Printer" then
if not exports['projectx-bridge']:MinigameCheck("lightsout") then p:resolve(false) return Citizen.Await(p) end
local success = exports['lightsout']:StartLightsOut(4, 20)
p:resolve(success)
elseif Step == "ElectricBox" then
if not exports['projectx-bridge']:MinigameCheck("SN-Hacking") then p:resolve(false) return Citizen.Await(p) end
local success = exports['SN-Hacking']:MemoryCards('medium')
p:resolve(success)
elseif Step == "Vault" then
if not exports['projectx-bridge']:MinigameCheck("SN-Hacking") then p:resolve(false) return Citizen.Await(p) end
local success = exports['SN-Hacking']:ColorPicker(5, 7000, 3000)
p:resolve(success)
elseif Step == "JailDoor" then
if not exports['projectx-bridge']:MinigameCheck("SN-Hacking") then p:resolve(false) return Citizen.Await(p) end
local success = exports['SN-Hacking']:ColorPicker(5, 7000, 3000)
p:resolve(success)
else
p:resolve(false)
end
return Citizen.Await(p)
end)
```
You can return `true` unconditionally inside any step block to skip that minigame entirely. This can be useful for testing or for steps you want to make automatic.
The default minigames per step are:
| Step | Minigame Resource | Function |
| ------------- | ----------------- | ----------------------- |
| `Fusebox` | `SN-Hacking` | `MemoryCards('hard')` |
| `Fingerprint` | `utk_fingerprint` | `utk_fingerprint:Start` |
| `KeypadOne` | `simonsays` | `StartSimonSays` |
| `Printer` | `lightsout` | `StartLightsOut` |
| `ElectricBox` | `SN-Hacking` | `MemoryCards('medium')` |
| `Vault` | `SN-Hacking` | `ColorPicker` |
| `JailDoor` | `SN-Hacking` | `ColorPicker` |
***
## opensource/server/server.lua
This file handles dispatch, item/money functions, logging, and exposes several hooks you can use to run custom logic at specific points in the robbery.
### Hooks
Called whenever a player successfully completes a robbery step. Use this to award XP, trigger events, or log individual step completions.
```lua theme={null}
function SuccessfulStep(source, location, step)
if step == "Fusebox" then
-- exports['projectx-bridge']:AddExperience(source, 'criminal', 10)
elseif step == "JailDoor" then
-- exports['projectx-bridge']:AddExperience(source, 'criminal', 10)
end
end
```
Common step names include `Fusebox`, `Fingerprint`, `KeypadOne`, `Printer`, `ElectricBox`, `Vault`, and `JailDoor`.
Called whenever a player fails a robbery step. Use this to remove XP, items, or apply penalties.
```lua theme={null}
function FailedStep(source, location, step)
if step == "Fusebox" then
-- RemoveItem(source, 'x_device', 1)
end
end
```
Called before a player can start a robbery at a location. Return `false` to block them.
```lua theme={null}
function InitialCheck(src, Location, Interaction)
return true
-- Add a group check, tablet requirement, or any other gate here
end
```
Called whenever a Fleeca location resets. Use this to update a scoreboard, trigger an external event, or notify players.
```lua theme={null}
function RobberyResetHook(location)
-- TriggerEvent('my-scoreboard:update', location)
end
```
# Commands
Source: https://docs.projectx.gg/resources/house-robbery-v2/commands
Admin and development commands for House Robbery V2
## Development Commands
**Usage**: `/getoffset [x] [y] [z]`
**Permission**: Admin (configurable)
**Description**: Gets the offset coordinates for positioning items inside a shell. This is essential when creating custom presets.
**Parameters**:
* `x, y, z` (optional) - World coordinates to convert to offset
* If no parameters are provided, uses your current character position
**Returns**: Offset coordinates that can be used in preset configurations
**Use Case**: Use this command while inside a shell to get the correct offset coordinates for:
* Lootable spots positions
* Prop placements
* Cash locations
* Safe positions
* Painting coordinates
* Display case positions
* High value item locations
* Tenant spawn points
* Pet spawn points
* Laser system positions
* Alarm box positions
**Example Workflow**:
1. Enter a shell interior
2. Stand at the location where you want to place an item
3. Run `/getoffset`
4. Paste the returned coordinates into your preset configuration
**Example Output**:
```lua theme={null}
-- If you run /getoffset while standing at a location
-- The command returns: vector3(-771.69, 335.96, 195.94)
-- Use this in your preset like:
["Coords"] = vector3(-771.69, 335.96, 195.94)
```
This command is crucial for creating accurate presets. See the [Presets Guide](/resources/house-robbery-v2/guides/presets) for detailed information on using these coordinates.
**Usage**: `/polycreate`
**Permission**: Admin (configurable)
**Requirements**: `Config.PolyTool` must be set to `true` in the main config
**Description**: Creates detection zones around tenants (NPCs) inside houses. This defines the area where tenants can detect players during robberies.
**Returns**: Polyzone coordinates that can be used in tenant detection configuration
**Use Case**: Use this command to create detection zones for tenants in your preset:
1. Enable `Config.PolyTool = true` in config
2. Place a tenant NPC in the house
3. Run `/polycreate` near the tenant
4. Walk around the area to define the detection boundaries
5. Complete the zone creation (follow on-screen instructions)
6. Paste the returned coordinates into your preset
**Example Output**:
```lua theme={null}
-- The command returns coordinates like:
vec(-773.58, 313.86, 195.89),
vec(-773.48, 323.12, 195.89),
vec(-780.63, 322.83, 195.89),
vec(-780.67, 313.86, 195.89)
-- Use these in your tenant configuration:
["Tenants"] = {
{
["Coords"] = vector4(-774.9, 318.97, 195.89, 91.18),
["Model"] = "s_m_m_strpreach_01",
["Animation"] = {Dict = "timetable@ron@ig_3_couch", Anim = "base"},
["Detection"] = {
["Enable"] = true,
["ZoneCoords"] = {
vec(-773.58, 313.86, 195.89),
vec(-773.48, 323.12, 195.89),
vec(-780.63, 322.83, 195.89),
vec(-780.67, 313.86, 195.89)
},
["ZoneHeight"] = 4.0
}
}
}
```
Remember to set `Config.PolyTool = false` in production to prevent players from accessing this command.
See the [Presets Guide](/resources/house-robbery-v2/guides/presets#tenants) for more information on tenant detection zones.
## Administration Commands
**Usage**: `/lockhouse`
**Permission**: Admin by default (can be configured for police)
**Description**: Resets and re-locks the closest house to your character. This is useful for testing or when a robbery needs to be manually reset.
**Requirements**: Must be standing outside near a house door
**What it does**:
* Finds the closest house to your position
* Resets the house's robbery state
* Locks the house doors
* Respawns all lootable items
* Resets all security systems (alarms, lasers)
* Removes any active tenants/pets
* Clears the house cooldown
**Use Cases**:
* Testing house configurations after changes
* Manually resetting a bugged house
* Clearing a house after a failed robbery
* Admin intervention during police scenarios
* Resetting houses for events or testing
**Configuration**:
By default, this command is set up for admins only. You can configure it to allow police officers to use it by modifying the permission check in the script.
**Example Scenario**:
1. A robbery gets stuck or bugged
2. Admin goes to the house entrance
3. Runs `/lockhouse`
4. House is reset and ready for another robbery
This command is essential for server administration and testing. Make sure only trusted users have access to it.
## Configuration
All commands respect your server's permission system. By default:
* **Development Commands** (`getoffset`, `polycreate`): Admin only
* **Administration Commands** (`lockhouse`): Admin only (configurable for police)
You can modify command permissions in your server's admin/permissions system or by editing the script's permission checks.
## Tips for Using Commands
### Creating Presets
1. **Use getoffset extensively**: When creating a new preset, use `/getoffset` for every single item, spot, and prop position
2. **Test as you go**: After adding each item to your preset, restart the resource and test it in-game
3. **Document your work**: Keep notes of what each coordinate represents while building presets
### Setting Up Detection Zones
1. **Enable PolyTool first**: Set `Config.PolyTool = true` before using `/polycreate`
2. **Walk the area**: Create detection zones by walking the boundaries you want
3. **Test detection**: After setting up zones, test them by entering as a player
4. **Adjust height**: Set appropriate `ZoneHeight` values based on the room's ceiling height
5. **Disable in production**: Always set `Config.PolyTool = false` before going live
### Testing Houses
1. **Use lockhouse for quick resets**: Instead of waiting for cooldowns, use `/lockhouse` to instantly reset
2. **Test all security features**: After using `/lockhouse`, verify alarms, lasers, and detection zones work
3. **Check loot spawning**: Ensure all props, spots, and items respawn correctly after reset
## Troubleshooting
**Possible causes**:
* Not inside a shell interior
* Incorrect admin permissions
* Command not registered properly
**Solutions**:
* Verify you're inside a shell (not IPL)
* Check your admin permissions level
* Restart the resource
* Check server console for errors
**Possible causes**:
* `Config.PolyTool` is set to `false`
* Incorrect admin permissions
* ox\_lib not properly installed
**Solutions**:
* Set `Config.PolyTool = true` in config/main.lua
* Verify admin permissions
* Ensure ox\_lib is started before the resource
* Restart the resource after config changes
**Possible causes**:
* Standing too far from the house door
* House not properly configured
* Wrong coordinates in house config
**Solutions**:
* Stand directly at the door location
* Verify house exists in config/houses.lua
* Check door coordinates are correct
* Try moving closer to the entrance
**Possible causes**:
* Using world coordinates instead of offset coordinates
* Wrong interior type (Shell vs IPL)
* Preset doesn't match the shell being used
**Solutions**:
* Always use `/getoffset` inside the shell, never world coordinates
* Verify the shell name matches your preset name
* Double-check you're using the correct shell model
* Test coordinates immediately after getting them
# Exports
Source: https://docs.projectx.gg/resources/house-robbery-v2/exports
Available exports for the House Robbery V2 resource
## Server Exports
### GetPhoneNumber
Gets the current phone number for the payphone approach.
```lua theme={null}
local phoneNumber = exports["projectx-houserobbery-v2"]:GetPhoneNumber()
```
**Returns**
* `phoneNumber` (string) - The current payphone number used for the robbery approach
**Example**
```lua theme={null}
local number = exports["projectx-houserobbery-v2"]:GetPhoneNumber()
print("Current payphone number: " .. number)
```
# FAQs
Source: https://docs.projectx.gg/resources/house-robbery-v2/faqs
Frequently asked questions about the House Robbery V2 resource
## General Questions
Yes, if you want to use the preset houses. The K4MB1-Starter-Shells are free and required for the default shell configurations. If you don't have them, you'll need to configure your own shells or use IPL interiors.
You can also find community-created presets in our [Discord Snippets channel](https://discord.gg/projectxdev) that use different shell packs.
The script supports QBCore, QBOX, and ESX frameworks. Make sure to configure the Framework setting in `config/main.lua` to match your server.
While the script works best with Project-X-Burner and Project-X-Tasks (both free), you can modify the config to disable these features if you don't want to use them. However, using these scripts provides a more complete criminal progression system.
House Robbery V2 configures inventory directly in `config/config.lua` rather than through the bridge. Supported values: `ox`, `qb`, `ps`, `lj`, `codem`, `origen`, `tgiann`, `esx`, or `other` for custom integration via the open source inventory functions.
Set `Inventory` to `'auto'` to detect automatically, or set the matching config value manually. See the [FAQs](/faqs) for links to each inventory resource.
House Robbery V2 configures dispatch directly in `config/config.lua` under `Config.Dispatch.Resource`. Set it to `'auto'` for automatic detection, or use a supported config value such as `cd`, `ps`, `fd`, `lb`, `codem`, `wasabimdt`, `sonoran`, `imperial`, and others listed in the config comment.
For the full list with resource links (including newer bridge-only systems), see the [FAQs](/faqs). If your dispatch is not supported, set the resource to `customsv` or `customcl` and edit the open source dispatch functions.
Place the minigames in your standalone or minigames folder. Make sure they are started in your server.cfg before the House Robbery V2 resource.
Open `opensource/client/client.lua` and find the minigame callback. Each robbery step has its own block where you can swap the minigame export for any resource you prefer. You can also return `true` inside any block to skip that minigame entirely.
See the global [FAQs](/faqs) for a general overview of editing minigames in Project X scripts.
Some items like `x_burner` and `x_tablet` are optional and can be disabled in the config. However, items like `advancedlockpick`, `x_device`, `x_stethoscope`, `glass_cutter`, and `bag` are required for the robbery mechanics. Items such as loot and props are not required if you want to fully use your own, Check the installation guide for the complete items list.
* Enable `EnableLasers` in house config
* Ensure preset has laser configuration
* Make sure mka-lasers resource is running
## Configuration Questions
House presets define the interior layout and lootable spots. You can create custom presets using the `LoadHousePreset()` function in `config/presets.lua`.
Check our [Presets Guide](/resources/house-robbery-v2/guides/presets) for detailed instructions on:
* Creating exit coordinates
* Adding lootable spots, props, and cash
* Configuring safes, paintings, and displays
* Setting up tenants and pets
* Adding lasers and alarms
You can also find community presets in our Discord Snippets channel.
Tiers control the difficulty, rewards, and features of robberies. Configure them in `config/tiers.lua`.
Tips for balancing:
* Start with low spawn chances in Tier 1 (10-30%)
* Gradually increase spawn chances in higher tiers (70-90%)
* Give better items in higher tier loot tables
* Increase XP rewards for higher tiers
* Add more security features (tenants, pets, lasers) in higher tiers
* Require better tools for higher tiers
See our [Tiers Guide](/resources/house-robbery-v2/guides/tiers) for complete configuration details.
**Shells** are custom interior props that can be placed anywhere on the map. They're more flexible and easier to configure.
**IPLs** are built-in GTA V interiors at fixed coordinates. They're more detailed but limited to specific locations.
Check the [Houses Guide](/resources/house-robbery-v2/guides/houses) for detailed setup instructions.
Add new houses in `config/houses.lua` under either `["Shells"]` or `["IPL"]` categories.
Each house needs:
* **Tier**: Difficulty level (1-6)
* **DoorCoords**: Entrance location with heading
* Optional: ScoutingSpots, security features, dispatch settings
Use the [Houses Guide](/resources/house-robbery-v2/guides/houses) for step-by-step instructions and examples.
Carryable props allow players to physically carry stolen items to their vehicles. Configure them in `config/main.lua` under `Config.CarryProps`.
For each prop you need:
* Item name (matching your inventory)
* Prop model name
* Bone ID for attachment
* Offset and rotation values
* Animation dictionary and name
See our [Carryable Props Guide](/resources/house-robbery-v2/guides/carryable-props) for complete instructions on adding and adjusting props.
Yes, most features can be toggled on/off:
* **Tenants/Pets**: Disable in tier config or set spawn chance to 0
* **Safes/Paintings/Displays**: Set `Enable = false` in tier config
* **Lasers/Alarms**: Disable per-tier or per-house
* **Carryable Props**: Set `Config.CarryProps.Enable = false`
* **Scouting**: Disable scouting spots in house config
* **Phone/Tablet**: Disable in main config
All features are modular and can be customized to fit your server's needs.
Go to the tiers.lua file and change the assigned approaches in each tier to one of the approaches or a table of approaches
or remove a certain approach by not including it in any of the tiers, approaches that are not included in any tier will not be used in the script.
Valid approaches: `door`, `gangster`, `payphone`, `locksmith`, `hacking`, `maid`, `valet`
## Troubleshooting
Console warnings help identify configuration issues. Here's what each warning means and how to fix it:
### Shell Configuration Warnings
**Invalid shell model: \[HouseName]**
* The shell model specified in your tier configuration doesn't exist or isn't loaded
* Check that the shell name in `config/tiers.lua` matches an actual shell resource
* Make sure the shell resource is started
### Tier Configuration Warnings
**Invalid approach in tier \[X]: '\[approach]'**
* You specified an approach type that doesn't exist (e.g., 'van' or 'Gangster' instead of 'gangster')
* Valid approaches: `door`, `gangster`, `payphone`, `locksmith`, `hacking`, `maid`, `valet`
* Check your tier configuration in `config/tiers.lua` for typos
* Approach names are case-sensitive
### Preset Configuration Warnings
**House preset "\[name]" already exists in Config.PresetHouseCoords\[InteriorType]. Overwriting it...**
* You have duplicate preset names in your configuration
* This can happen if you're using multiple preset files or added the same preset twice
* The script will use the last defined preset with that name
* Rename one of the presets to avoid conflicts
### Missing Resource Warnings
**projectx-tasks resource was not detected, either turn off Project X Tasks config option or download it from our website**
* You have tasks integration enabled but the resource isn't installed
* Solution 1: Download Project X Tasks from [projectx.gg](https://www.projectx.gg)
* Solution 2: Set `Config.[Project X Tasks] = false` in `config/config.lua`
**projectx-burner resource was not detected, either turn off Project X Burner config option or download it from our website**
* You have burner phone integration enabled but the resource isn't installed
* Solution 1: Download Project X Burner from [projectx.gg](https://www.projectx.gg)
* Solution 2: Set `Config.[Project X Burner] = false` in `config/config.lua`
**bl\_dialog resource was not detected, either set Config.Dialog = 'ox', or download it from the minigame zip in the README**
* You have bl\_dialog selected but it's not installed or started
* Solution 1: Download bl\_dialog from the [minigame zip file](/resources/house-robbery-v2/installation#installation-steps)
* Solution 2: Set `Config.Dialog = 'ox'` in `config/config.lua` to use ox\_lib dialog
**pickle\_xp resource was not detected, either turn off XPSystem config option or download pickle\_xp**
* You have XP system integration enabled but pickle\_xp isn't installed
* Solution 1: Download pickle\_xp from [github.com/PickleModifications/pickle\_xp](https://github.com/PickleModifications/pickle_xp)
* Solution 2: Set `Config.XPSystem = false` in `config/config.lua` to disable XP integration
### Conflicting Resource Warnings
**Remove or delete qb-houserobbery or the script will not work properly**
* You have the old QBCore house robbery script running alongside this one
* This will cause conflicts and errors
* Remove qb-houserobbery from your resources folder or stop it in server.cfg
**Remove or delete qbx\_houserobbery or the script will not work properly**
* You have the QBOX house robbery script running alongside this one
* This will cause conflicts and errors
* Remove qbx\_houserobbery from your resources folder or stop it in server.cfg
### Auto-Detection Warnings
**\[Config.Dispatch.Resource] You have auto detection on for dispatch resource, but your dispatch resource is not started or supported by default**
* Auto-detection couldn't find a supported dispatch system
* Solution: Manually set `Config.Dispatch.Resource` in `config/config.lua` to your dispatch system name
* Check the supported dispatch list in the FAQ above, if we still dont support it you will need to manually integrate it in the opensource folder, if its server side set the resource name in `Config.Dispatch.Resource` to `customsv` and edit opensource/server.lua, if its client side set the resource name in `Config.Dispatch.Resource` to `customcl` and edit opensource/client.lua
**\[Config.Framework] You have auto detection on for framework resource, but your framework resource is not started or supported by default**
* Auto-detection couldn't find a supported framework (QBCore, QBOX, ESX)
* Solution: Manually set `Config.Framework` in `config/config.lua` to your framework name
* Supported values: `'qb-core'`, `'qbx'`, `'esx'`, if we dont support your framework you will need to manually integrate it in the opensource folder.
### Interaction System Warnings
**Your interaction system is set to "ox-target", which is incorrect. The correct value is "ox\_target"**
* You have a typo in your interaction system configuration
* Change `Config.Interaction = "ox-target"` to `Config.Interaction = "ox_target"` in `config/main.lua`
**Your interaction system is set to "qb\_target", which is incorrect. The correct value is "qb-target"**
* You have a typo in your interaction system configuration
* Change `Config.Interaction = "qb_target"` to `Config.Interaction = "qb-target"` in `config/main.lua`
# Carryable Props
Source: https://docs.projectx.gg/resources/house-robbery-v2/guides/carryable-props
Configure props that can be carried and stored in vehicles
## Carryable Props System
The carryable props system allows players to physically carry items during robberies and store them in vehicle trunks. This guide covers how to configure the system and add new carryable props.
***
## Configuration Structure
The carryable props system is configured in `config/main.lua` with three main sections:
1. **CarryProps Settings** - Global enable/disable and vehicle interaction settings
2. **Props Definition** - Individual prop configurations with models and animations
3. **AllowedVehicleClasses** - Which vehicle types can store props
***
## Global Settings
Enable or disable the entire carryable props system. When disabled, players cannot carry or store props in vehicles.
When `true`, players must target the trunk specifically to store props. When `false`, targeting anywhere on the vehicle works.
Setting to `false` is recommended for vehicles without traditional trunks (motorcycles, front-engine vehicles).
When `true`, players can only store props in unlocked vehicles. When `false`, props can be stored in any vehicle regardless of lock status.
***
## Adding New Props
To add a new carryable prop, add an entry to the `Props` table within `Config.CarryProps`:
```lua theme={null}
Config.CarryProps = {
["Enable"] = true,
["TrunkTargetOnly"] = true,
["UnlockedVehiclesOnly"] = true,
["Props"] = {
["item_name_here"] = {
Model = "prop_model_name",
Bone = 24817,
Offset = vec3(0.0, 0.0, 0.0),
Rotation = vec3(0.0, 0.0, 0.0),
Animation = {dict = "anim_dict", anim = "anim_name"}
},
},
}
```
### Prop Configuration Parameters
The item name that matches your inventory item. This should be the exact item name from your items configuration (e.g., `x_television`, `x_microwave`).
Must match the item names defined in your tier's `LootTable` or `HighValueItems` configuration.
The prop model to attach to the player when carrying. Use GTA V prop models without the hash.
Common prop models:
* `prop_tv_03` - Television
* `prop_coffee_mac_02` - Coffee maker
* `v_res_printer` - Printer
* `prop_microwave_1` - Microwave
* `prop_el_guitar_01` - Electric guitar
* `prop_rad_con_01` - Radio
* `prop_boombox_01` - Boombox
The player bone ID to attach the prop to. Determines which part of the body holds the prop.
Common bones:
* `24817` - Left hand carry (single-handed items)
* `18905` - Two-handed carry (larger items)
* `28422` - Right hand
* `57005` - Head
Position offset from the bone attachment point using `vec3(x, y, z)` format.
Adjust these values to position the prop correctly:
* **X axis**: Left (-) / Right (+)
* **Y axis**: Forward (+) / Backward (-)
* **Z axis**: Up (+) / Down (-)
Values typically range from -1.0 to 1.0 but may vary by prop size.
Rotation angles for the prop using `vec3(pitch, roll, yaw)` format in degrees.
Adjust these values to orient the prop correctly:
* **Pitch**: Tilt forward/backward (0-360)
* **Roll**: Rotate left/right (0-360)
* **Yaw**: Spin clockwise/counterclockwise (0-360)
Animation to play while carrying the prop.
Contains two required fields:
* `dict` - Animation dictionary
* `anim` - Animation name
Common carry animations:
* `anim@heists@box_carry@` / `idle` - Standard box carry
***
## Vehicle Class Configuration
Control which vehicle types can store carryable props using `Config.AllowedVehicleClasses`:
```lua theme={null}
Config.AllowedVehicleClasses = {
[VehicleClass.COMPACTS] = true,
[VehicleClass.SEDANS] = true,
[VehicleClass.SUVS] = true,
[VehicleClass.MOTORCYCLES] = false,
[VehicleClass.BOATS] = false,
}
```
### Available Vehicle Classes
| Class | Recommended | Notes |
| ----------------- | ----------- | ------------------------------- |
| `COMPACTS` | `true` | Small cars with trunks |
| `SEDANS` | `true` | Standard 4-door vehicles |
| `SUVS` | `true` | Large vehicles with cargo space |
| `COUPES` | `true` | 2-door sports cars |
| `MUSCLE` | `true` | Classic muscle cars |
| `SPORTS_CLASSICS` | `true` | Vintage sports cars |
| `SPORTS` | `true` | Modern sports cars |
| `SUPER` | `true` | Supercars |
| `MOTORCYCLES` | `false` | No storage capacity |
| `OFF_ROAD` | `true` | Trucks and off-road vehicles |
| `INDUSTRIAL` | `true` | Work vehicles |
| `UTILITY` | `true` | Utility trucks |
| `VANS` | `true` | Cargo vans |
| `CYCLES` | `false` | Bicycles |
| `BOATS` | `false` | Watercraft |
| `HELICOPTERS` | `false` | Aircraft |
| `PLANES` | `false` | Aircraft |
| `SERVICE` | `false` | Service vehicles |
| `EMERGENCY` | `false` | Police/EMS/Fire |
| `MILITARY` | `false` | Military vehicles |
| `COMMERCIAL` | `false` | Commercial trucks |
| `TRAINS` | `false` | Trains |
| `OPEN_WHEEL` | `false` | F1 style cars |
Do not modify the `VehicleClass` table at the top of the config. This is a reference table used by the script.
***
## Complete Examples
### Example 1: Coffee Maker
```lua theme={null}
["x_coffeemaker"] = {
Model = "prop_coffee_mac_02",
Bone = 24817,
Offset = vec3(0.02, 0.43, 0.03),
Rotation = vec3(91.0, 0.0, -265.0),
Animation = {dict = "anim@heists@box_carry@", anim = "idle"}
}
```
Small appliance carried in left hand with standard box carry animation.
### Example 2: Television
```lua theme={null}
["x_television"] = {
Model = "prop_tv_03",
Bone = 18905,
Offset = vec3(0.25, 0.3, 0.4),
Rotation = vec3(235.0, 95.0, 15.0),
Animation = {dict = "anim@heists@box_carry@", anim = "idle"}
}
```
Large item requiring two-handed carry position with adjusted rotation for screen visibility.
### Example 3: Electric Guitar
```lua theme={null}
["x_electricguitar"] = {
Model = "prop_el_guitar_01",
Bone = 18905,
Offset = vec3(0.15, 0.0, 0.1),
Rotation = vec3(-10.0, 15.0, 190.0),
Animation = {dict = "anim@heists@box_carry@", anim = "idle"}
}
```
Long item with custom rotation to prevent clipping through the player model.
### Example 4: Laptop
```lua theme={null}
["x_laptop"] = {
Model = "prop_laptop_01a",
Bone = 24817,
Offset = vec3(0.10, 0.35, 0.0),
Rotation = vec3(90.0, 0.0, -90.0),
Animation = {dict = "anim@heists@box_carry@", anim = "idle"}
}
```
Compact electronic device carried in one hand.
***
## Full Configuration Example
```lua theme={null}
Config.CarryProps = {
["Enable"] = true,
["TrunkTargetOnly"] = true,
["UnlockedVehiclesOnly"] = true,
["Props"] = {
["x_coffeemaker"] = {
Model = "prop_coffee_mac_02",
Bone = 24817,
Offset = vec3(0.02, 0.43, 0.03),
Rotation = vec3(91.0, 0.0, -265.0),
Animation = {dict = "anim@heists@box_carry@", anim = "idle"}
},
["x_television"] = {
Model = "prop_tv_03",
Bone = 18905,
Offset = vec3(0.25, 0.3, 0.4),
Rotation = vec3(235.0, 95.0, 15.0),
Animation = {dict = "anim@heists@box_carry@", anim = "idle"}
},
["x_printer"] = {
Model = "v_res_printer",
Bone = 18905,
Offset = vec3(0.3, 0.0, 0.25),
Rotation = vec3(-75.0, -5.0, 35.0),
Animation = {dict = "anim@heists@box_carry@", anim = "idle"}
},
["x_microwave"] = {
Model = "prop_microwave_1",
Bone = 24817,
Offset = vec3(-0.20, 0.43, 0.05),
Rotation = vec3(91.0, 0.0, -265.0),
Animation = {dict = "anim@heists@box_carry@", anim = "idle"}
},
["x_electricguitar"] = {
Model = "prop_el_guitar_01",
Bone = 18905,
Offset = vec3(0.15, 0.0, 0.1),
Rotation = vec3(-10.0, 15.0, 190.0),
Animation = {dict = "anim@heists@box_carry@", anim = "idle"}
},
["x_laptop"] = {
Model = "prop_laptop_01a",
Bone = 24817,
Offset = vec3(0.10, 0.35, 0.0),
Rotation = vec3(90.0, 0.0, -90.0),
Animation = {dict = "anim@heists@box_carry@", anim = "idle"}
},
["x_boombox"] = {
Model = "prop_boombox_01",
Bone = 18905,
Offset = vec3(0.27, 0.0, 0.2),
Rotation = vec3(-80.0, 0.0, 0.0),
Animation = {dict = "anim@heists@box_carry@", anim = "idle"}
},
},
}
VehicleClass = {
COMPACTS = 0,
SEDANS = 1,
SUVS = 2,
COUPES = 3,
MUSCLE = 4,
SPORTS_CLASSICS = 5,
SPORTS = 6,
SUPER = 7,
MOTORCYCLES = 8,
OFF_ROAD = 9,
INDUSTRIAL = 10,
UTILITY = 11,
VANS = 12,
CYCLES = 13,
BOATS = 14,
HELICOPTERS = 15,
PLANES = 16,
SERVICE = 17,
EMERGENCY = 18,
MILITARY = 19,
COMMERCIAL = 20,
TRAINS = 21,
OPEN_WHEEL = 22,
}
Config.AllowedVehicleClasses = {
[VehicleClass.COMPACTS] = true,
[VehicleClass.SEDANS] = true,
[VehicleClass.SUVS] = true,
[VehicleClass.COUPES] = true,
[VehicleClass.MUSCLE] = true,
[VehicleClass.SPORTS_CLASSICS] = true,
[VehicleClass.SPORTS] = true,
[VehicleClass.SUPER] = true,
[VehicleClass.MOTORCYCLES] = false,
[VehicleClass.OFF_ROAD] = true,
[VehicleClass.INDUSTRIAL] = true,
[VehicleClass.UTILITY] = true,
[VehicleClass.VANS] = true,
[VehicleClass.CYCLES] = false,
[VehicleClass.BOATS] = false,
[VehicleClass.HELICOPTERS] = false,
[VehicleClass.PLANES] = false,
[VehicleClass.SERVICE] = false,
[VehicleClass.EMERGENCY] = false,
[VehicleClass.MILITARY] = false,
[VehicleClass.COMMERCIAL] = false,
[VehicleClass.TRAINS] = false,
[VehicleClass.OPEN_WHEEL] = false,
}
```
***
## Tips for Adding Props
### Finding Prop Models
1. Use a prop spawner resource to test different models in-game
2. Check the [GTA V Props Database](https://forge.plebmasters.de/) for prop names
3. Look at existing house interiors to find suitable props
4. Test props in-game before adding to production
### Adjusting Attachment
1. Start with similar existing prop configurations as templates
2. Use small incremental changes (0.05-0.1) when adjusting offsets
3. Test both walking and running animations with the prop
4. Ensure props don't clip through walls or the player model
5. Check prop visibility from third-person camera angles
### Animation Selection
The `anim@heists@box_carry@` dictionary with `idle` animation works for most props, but consider alternatives:
* **Heavy items**: Use slower, more strained animations
* **Fragile items**: Use careful, steady animations
* **Long items**: Ensure animation supports the prop length
* **One-handed items**: Use animations with free hand movement
### Vehicle Storage Testing
1. Test with locked and unlocked vehicles if `UnlockedVehiclesOnly = true`
2. Verify trunk targeting works correctly with `TrunkTargetOnly = true`
3. Test with front-engine vehicles (some have front trunks)
4. Ensure props can be retrieved from trunks after storage
5. Check that disallowed vehicle classes properly reject storage
### Item Integration
1. Ensure item names match exactly between:
* Carryable props configuration
* Tier loot tables
* Inventory items configuration
2. Add appropriate item images to your inventory
3. Set reasonable item weights for gameplay balance
4. Consider making carryable props non-stackable
# Contracts System
Source: https://docs.projectx.gg/resources/house-robbery-v2/guides/contracts
Learn how to configure and add custom contracts for House Robbery V2
## What Are Contracts?
Contracts are optional side tasks that players can accept from NPCs located around the map. These contracts add variety to house robberies by giving players specific objectives like breaking objects, stealing items, or littering. Contracts spawn randomly inside houses and reward players upon completion.
Contracts are configured in `config/contracts.lua` and provide an additional layer of gameplay beyond standard house robberies.
## Global Configuration
### Basic Settings
Enable or disable the entire contracts system. When disabled, contract NPCs won't spawn and contracts won't appear in houses.
If `true`, reward amounts are hidden in the contract acceptance dialog. Players won't see the exact payout until they complete the contract.
### Required Items
Configure which items players need to complete different contract types:
Item required to break objects. Use `"melee"` to allow any melee weapon, a specific item name, or `false` for no requirement.
Item required to steal objects. Set to a specific item name or `false` for no requirement.
Item required for littering contracts. Set to a specific item name or `false` for no requirement.
Item required to take pictures of completed contracts. Using `"x_burner"` is recommended for immersion with the messaging system.
**Example:**
```lua theme={null}
["RequiredItems"] = {
["Break Objects"] = "melee",
["Steal Objects"] = "bag",
["Littering"] = false,
["TakingPictures"] = "x_burner"
}
```
***
## Contract NPCs
NPCs are the characters players interact with to accept and turn in contracts. You can set up multiple npc coords which allows the npc to spawn randomly at one of the locations instead of always spawning in one spot.
### NPC Configuration
The ped model to use for the contract NPC. Example: `"g_m_y_korean_01"`
Position and heading where the NPC spawns
Scenario animation for the NPC (standing, sitting, etc.). Example: `"WORLD_HUMAN_STAND_IMPATIENT_UPRIGHT"`
Use this OR Animation, not both.
Custom animation for the NPC with `Dict` and `Anim` properties
Use this OR Scenario, not both.
You can use either `Scenario` (simpler, just a scenario name) or `Animation` (more control with dict/anim), but not both at the same time.
**Example with Scenario:**
```lua theme={null}
["Peds"] = {
{
["PedModel"] = "g_m_y_korean_01",
["Coords"] = vector4(1023.52, -1870.82, 30.89, 359.91),
["Scenario"] = "WORLD_HUMAN_STAND_IMPATIENT_UPRIGHT"
}
}
```
**Example with Animation:**
```lua theme={null}
["Peds"] = {
{
["PedModel"] = "g_m_y_korean_01",
["Coords"] = vector4(-22.72, -1250.14, 29.23, 359.6),
["Animation"] = {Dict = "anim@amb@casino@hangout@ped_male@stand@02b@idles", Anim = "idle_a"}
}
}
```
***
## Dialog Configuration
Customize the text that appears when players interact with contract NPCs.
### Initial Dialog
The first message shown when approaching the NPC
Text for the accept button
Text for the decline button
### Accepting Contracts
Message shown when viewing available contracts
Text for the accept contracts button
Text for the decline button
### End Conversation
Final message after accepting contracts
Text for the goodbye button
**Example:**
```lua theme={null}
["DialogTexts"] = {
["InitialDialog"] = {
["Content"] = "I have some contracts, would you like to take a look? I will give u a reward for each one you complete.",
["Confirm"] = "Sure",
["Cancel"] = "No, thanks, I'll think about it"
},
["AcceptingContracts"] = {
["Content"] = "Here are the available contracts:",
["Confirm"] = "Accept Contracts",
["Cancel"] = "Maybe later"
},
["EndConversation"] = {
["Content"] = "Bring back the items I asked for, or take a picture (Breaking or Littering) with your burner phone, then come back for your reward.",
["Confirm"] = "Will do, Goodbye"
}
}
```
***
## Contract Types
There are three types of contracts, each with unique mechanics and configuration options.
### 1. Steal Objects Contracts
Players must steal specific items from houses and return them to the NPC.
Contract title shown in the UI
Contract description shown in the UI
Font Awesome icon for the contract. Example: `"fas fa-briefcase"`
Prop model that spawns in the house
Animation configuration with `Dict` and `Anim` properties OR `Scenario` property (use one or the other)
Seconds before the animation stops
If `true`, player turns to face the prop before interacting
Optional prop attached to player during animation with `Model`, `Bone`, `Offset`, and `Rotation`
Reward configuration including `Exp`, `Type` (money/item), `Item`, `Amount` (min/max), and `MetaData`
**Example:**
```lua theme={null}
["Steal Objects"] = {
["Briefcase"] = {
["Label"] = "Snatch the Briefcase",
["Description"] = "Sneak in and grab the briefcase",
["Icon"] = "fas fa-briefcase",
["Model"] = "prop_ld_case_01",
["Animation"] = {Dict = "random@domestic", Anim = "pickup_low"},
["DelayUntilCancelled"] = 1,
["TurnToFaceProp"] = false,
["AnimationProp"] = {
["Model"] = "prop_ld_case_01",
["Bone"] = 57005,
["Offset"] = vector3(0.1, 0.0, -0.03),
["Rotation"] = vector3(-90.0, 0.0, 0.0)
},
["Reward"] = {
["Exp"] = 20,
["Type"] = "money",
["Item"] = "",
["Amount"] = {min = 275, max = 300},
["MetaData"] = false
}
}
}
```
**Example with Scenario instead of Animation:**
```lua theme={null}
["Steal Objects"] = {
["Documents"] = {
["Label"] = "Grab the Documents",
["Description"] = "Pick up the important papers",
["Icon"] = "fas fa-file",
["Model"] = "prop_paper_bag_small",
["Scenario"] = "WORLD_HUMAN_STAND_MOBILE",
["DelayUntilCancelled"] = 2,
["TurnToFaceProp"] = false,
["Reward"] = {
["Exp"] = 15,
["Type"] = "money",
["Item"] = "",
["Amount"] = {min = 200, max = 250},
["MetaData"] = false
}
}
}
```
### 2. Break Objects Contracts
Players must break specific objects and take a picture as proof.
Prop model for the intact object
Prop model that replaces the intact object after breaking
Sound effect when breaking: `"glass"`, `"electronics"`, `"thud"`, or `false` for no sound
Animation configuration for breaking the object including `Animation` (with `Dict` and `Anim`) OR `Scenario`, `DelayUntilCancelled`, `TurnToFaceProp`, and optional `AnimationProp`
Animation configuration for taking the picture including `Animation` (with `Dict` and `Anim`) OR `Scenario`, `DelayUntilCancelled`, `TurnToFaceProp`, and optional `AnimationProp`
**Example:**
```lua theme={null}
["Break Objects"] = {
["Laptop"] = {
["Label"] = "Smash the Laptop's Screen",
["Description"] = "Teach this overpriced laptop a lesson.",
["Icon"] = "fas fa-laptop",
["Model"] = "prop_laptop_lester",
["BrokenModel"] = "gr_prop_gr_laptop_01c",
["Sound"] = "electronics",
["Animation"] = {
["Breaking"] = {
["Animation"] = {Dict = "anim@melee@machete@streamed_core@", Anim = "plyr_walking_attack_a"},
["DelayUntilCancelled"] = 1,
["TurnToFaceProp"] = false
},
["TakingPicture"] = {
["Scenario"] = "WORLD_HUMAN_STAND_MOBILE",
["DelayUntilCancelled"] = 4,
["TurnToFaceProp"] = false
}
},
["Reward"] = {
["Exp"] = 20,
["Type"] = "money",
["Item"] = "",
["Amount"] = {min = 275, max = 300},
["MetaData"] = false
}
}
}
```
### 3. Littering Contracts
Players must pick up an object, scatter litter, and take a picture as proof.
Prop model for the initial item to pick up
Prop model that spawns as scattered litter
Sound effect when littering: `"poop"`, `"spill"`, `"trash"`, or `false` for no sound
Animation for picking up the initial object (can use `Animation` with `Dict`/`Anim` OR `Scenario`)
Animation for scattering the litter (can use `Animation` with `Dict`/`Anim` OR `Scenario`)
Animation for taking the picture proof (can use `Animation` with `Dict`/`Anim` OR `Scenario`)
**Example:**
```lua theme={null}
["Littering"] = {
["Cans"] = {
["Label"] = "Scatter cans",
["Description"] = "Scatter cans around like you own the place.",
["Icon"] = "fas fa-trash-can",
["Model"] = "v_ret_247_popcan2",
["LitteredModel"] = "prop_rub_litter_01",
["Sound"] = "trash",
["Animation"] = {
["Pickup"] = {
["Animation"] = {Dict = "anim@melee@machete@streamed_core@", Anim = "plyr_walking_attack_a"},
["DelayUntilCancelled"] = 1,
["TurnToFaceProp"] = false
},
["Litter"] = {
["Animation"] = {Dict = "anim@melee@machete@streamed_core@", Anim = "plyr_walking_attack_a"},
["DelayUntilCancelled"] = 3,
["TurnToFaceProp"] = false
},
["TakingPicture"] = {
["Scenario"] = "WORLD_HUMAN_STAND_MOBILE",
["DelayUntilCancelled"] = 4,
["TurnToFaceProp"] = false
}
},
["Reward"] = {
["Exp"] = 15,
["Type"] = "money",
["Item"] = "",
["Amount"] = {min = 200, max = 250},
["MetaData"] = false
}
}
}
```
Players must also take pictures of specific objects or situations. This is tied to Breaking and Littering contracts as proof of completion.
***
## Reward Configuration
All contracts share the same reward structure:
Experience points awarded upon completion (if using an XP system)
Type of reward: `"money"` for direct cash or `"item"` for inventory items
Item name if `Type = "item"`. Leave empty if `Type = "money"`
Reward amount with `min` and `max` values for randomization
If `true`, adds metadata to the reward item (used for marked money or item info)
**Money Reward Example:**
```lua theme={null}
["Reward"] = {
["Exp"] = 20,
["Type"] = "money",
["Item"] = "",
["Amount"] = {min = 275, max = 300},
["MetaData"] = false
}
```
**Item Reward Example:**
```lua theme={null}
["Reward"] = {
["Exp"] = 15,
["Type"] = "item",
["Item"] = "markedbills",
["Amount"] = {min = 1, max = 3},
["MetaData"] = true
}
```
***
## Animation Props
Animation props are optional attachments that appear on the player during animations, making interactions more immersive.
Prop model to attach to the player
Bone ID where the prop attaches. Common bones:
* `57005` - Head
* `18905` - Left hand
* `60309` - Right hand
* `24817` - Weapon slot
Position offset from the bone attachment point
Rotation angles for the prop in degrees
**Example:**
```lua theme={null}
["AnimationProp"] = {
["Model"] = "prop_ld_case_01",
["Bone"] = 57005,
["Offset"] = vector3(0.1, 0.0, -0.03),
["Rotation"] = vector3(-90.0, 0.0, 0.0)
}
```
Remove the entire `AnimationProp` table if you don't want a prop to appear during the animation.
***
## Adding Contracts to Presets
Contracts are linked to house presets. In your preset configuration, specify which contracts can spawn:
```lua theme={null}
["Contracts"] = {
["ChanceOfSpawning"] = 100,
["PossibleContracts"] = {
["1"] = {
["Contract"] = "Briefcase",
["Type"] = "Steal Objects",
["PickupCoords"] = vector3(-764.00, 321.12, 199.17),
["PickupRotation"] = vector3(0.0, 0.0, 343.53)
},
["2"] = {
["Contract"] = "Laptop",
["Type"] = "Break Objects",
["PickupCoords"] = vector3(-772.97, 328.25, 195.91),
["PickupRotation"] = vector3(0.0, 0.0, 227.85)
},
["3"] = {
["Contract"] = "Cans",
["Type"] = "Littering",
["PickupCoords"] = vector3(-764.00, 321.12, 199.17),
["PickupRotation"] = vector3(0.0, 0.0, 343.53),
["LitteredCoords"] = vector3(-764.00, 321.12, 199.17),
["LitteredRotation"] = vector3(0.0, 0.0, 343.53)
}
}
}
```
See the [Presets Guide](/resources/house-robbery-v2/guides/presets#contracts) for detailed preset configuration.
***
## Complete Configuration Example
```lua theme={null}
Config.Contracts = {
["Enable"] = true,
["HideRewardsOnDialogs"] = false,
["RequiredItems"] = {
["Break Objects"] = "melee",
["Steal Objects"] = "bag",
["Littering"] = false,
["TakingPictures"] = "x_burner"
},
["Peds"] = {
{
["PedModel"] = "g_m_y_korean_01",
["Coords"] = vector4(1023.52, -1870.82, 30.89, 359.91),
["Scenario"] = "WORLD_HUMAN_STAND_IMPATIENT_UPRIGHT"
}
},
["DialogTexts"] = {
["InitialDialog"] = {
["Content"] = "I have some contracts, would you like to take a look? I will give u a reward for each one you complete.",
["Confirm"] = "Sure",
["Cancel"] = "No, thanks, I'll think about it"
},
["AcceptingContracts"] = {
["Content"] = "Here are the available contracts:",
["Confirm"] = "Accept Contracts",
["Cancel"] = "Maybe later"
},
["EndConversation"] = {
["Content"] = "Bring back the items I asked for, or take a picture (Breaking or Littering) with your burner phone, then come back for your reward.",
["Confirm"] = "Will do, Goodbye"
}
},
["PossibleContracts"] = {
["Steal Objects"] = {
["Briefcase"] = {
["Label"] = "Snatch the Briefcase",
["Description"] = "Sneak in and grab the briefcase",
["Icon"] = "fas fa-briefcase",
["Model"] = "prop_ld_case_01",
["Animation"] = {Dict = "random@domestic", Anim = "pickup_low"},
["DelayUntilCancelled"] = 1,
["TurnToFaceProp"] = false,
["AnimationProp"] = {
["Model"] = "prop_ld_case_01",
["Bone"] = 57005,
["Offset"] = vector3(0.1, 0.0, -0.03),
["Rotation"] = vector3(-90.0, 0.0, 0.0)
},
["Reward"] = {
["Exp"] = 20,
["Type"] = "money",
["Item"] = "",
["Amount"] = {min = 275, max = 300},
["MetaData"] = false
}
},
["Harddrive"] = {
["Label"] = "Retrieve the Harddrive",
["Description"] = "Steal the owner's harddrive",
["Icon"] = "fas fa-hard-drive",
["Model"] = "v_res_harddrive",
["Animation"] = {Dict = "anim@heists@ornate_bank@hack", Anim = "hack_loop"},
["DelayUntilCancelled"] = 1,
["TurnToFaceProp"] = false,
["AnimationProp"] = {
["Model"] = "v_res_harddrive",
["Bone"] = 57005,
["Offset"] = vector3(0.1, 0.0, -0.03),
["Rotation"] = vector3(-90.0, 0.0, 0.0)
},
["Reward"] = {
["Exp"] = 20,
["Type"] = "money",
["Item"] = "",
["Amount"] = {min = 275, max = 300},
["MetaData"] = false
}
}
},
["Break Objects"] = {
["Laptop"] = {
["Label"] = "Smash the Laptop's Screen",
["Description"] = "Teach this overpriced laptop a lesson.",
["Icon"] = "fas fa-laptop",
["Model"] = "prop_laptop_lester",
["BrokenModel"] = "gr_prop_gr_laptop_01c",
["Sound"] = "electronics",
["Animation"] = {
["Breaking"] = {
["Animation"] = {Dict = "anim@melee@machete@streamed_core@", Anim = "plyr_walking_attack_a"},
["DelayUntilCancelled"] = 1,
["TurnToFaceProp"] = false
},
["TakingPicture"] = {
["Scenario"] = "WORLD_HUMAN_STAND_MOBILE",
["DelayUntilCancelled"] = 4,
["TurnToFaceProp"] = false
}
},
["Reward"] = {
["Exp"] = 20,
["Type"] = "money",
["Item"] = "",
["Amount"] = {min = 275, max = 300},
["MetaData"] = false
}
},
["Phone"] = {
["Label"] = "Smash their Phone",
["Description"] = "Disconnect them from brainrot",
["Icon"] = "fas fa-phone-flip",
["Model"] = "prop_npc_phone",
["BrokenModel"] = "sf_prop_sf_art_phone_01a",
["Sound"] = "electronics",
["Animation"] = {
["Breaking"] = {
["Animation"] = {Dict = "anim@melee@machete@streamed_core@", Anim = "plyr_walking_attack_a"},
["DelayUntilCancelled"] = 1,
["TurnToFaceProp"] = false
},
["TakingPicture"] = {
["Scenario"] = "WORLD_HUMAN_STAND_MOBILE",
["DelayUntilCancelled"] = 4,
["TurnToFaceProp"] = false
}
},
["Reward"] = {
["Exp"] = 20,
["Type"] = "money",
["Item"] = "",
["Amount"] = {min = 275, max = 300},
["MetaData"] = false
}
}
},
["Littering"] = {
["Cans"] = {
["Label"] = "Scatter cans",
["Description"] = "Scatter cans around like you own the place.",
["Icon"] = "fas fa-trash-can",
["Model"] = "v_ret_247_popcan2",
["LitteredModel"] = "prop_rub_litter_01",
["Sound"] = "trash",
["Animation"] = {
["Pickup"] = {
["Animation"] = {Dict = "anim@melee@machete@streamed_core@", Anim = "plyr_walking_attack_a"},
["DelayUntilCancelled"] = 1,
["TurnToFaceProp"] = false
},
["Litter"] = {
["Animation"] = {Dict = "anim@melee@machete@streamed_core@", Anim = "plyr_walking_attack_a"},
["DelayUntilCancelled"] = 3,
["TurnToFaceProp"] = false
},
["TakingPicture"] = {
["Scenario"] = "WORLD_HUMAN_STAND_MOBILE",
["DelayUntilCancelled"] = 4,
["TurnToFaceProp"] = false
}
},
["Reward"] = {
["Exp"] = 15,
["Type"] = "money",
["Item"] = "",
["Amount"] = {min = 200, max = 250},
["MetaData"] = false
}
},
["Stain"] = {
["Label"] = "Stain the floor",
["Description"] = "Paint the Floor with some spilled drink",
["Icon"] = "fas fa-wine-bottle",
["Model"] = "p_whiskey_bottle_s",
["LitteredModel"] = "p_oil_slick_01",
["Sound"] = "spill",
["Animation"] = {
["Pickup"] = {
["Animation"] = {Dict = "mp_common", Anim = "givetake1_b"},
["DelayUntilCancelled"] = 1,
["TurnToFaceProp"] = false,
["AnimationProp"] = {
["Model"] = "p_whiskey_bottle_s",
["Bone"] = 57005,
["Offset"] = vector3(0.1, 0.0, -0.03),
["Rotation"] = vector3(-90.0, 0.0, 0.0)
}
},
["Litter"] = {
["Animation"] = {Dict = "anim@amb@clubhouse@tutorial@bkr_tut_ig3@", Anim = "machinic_loop_mechandplayer"},
["DelayUntilCancelled"] = 1,
["TurnToFaceProp"] = false,
["AnimationProp"] = {
["Model"] = "p_whiskey_bottle_s",
["Bone"] = 57005,
["Offset"] = vector3(0.15, 0.1, 0.0),
["Rotation"] = vector3(60.0, 25.0, 180.0)
}
},
["TakingPicture"] = {
["Scenario"] = "WORLD_HUMAN_STAND_MOBILE",
["DelayUntilCancelled"] = 4,
["TurnToFaceProp"] = false
}
},
["Reward"] = {
["Exp"] = 15,
["Type"] = "money",
["Item"] = "",
["Amount"] = {min = 200, max = 250},
["MetaData"] = false
}
}
}
}
}
```
***
## Tips for Creating Contracts
### Balance Rewards
* **Steal Objects**: Higher rewards as they require carrying items out
* **Break Objects**: Medium-high rewards requiring breaking and photo proof
* **Littering**: Lower rewards as they're simpler tasks
* Scale rewards based on contract difficulty and time investment
### Choose Appropriate Props
* Check the [GTA V Props Database](https://forge.plebmasters.de/) for prop names
* Use recognizable models that fit the contract theme
* Ensure broken models clearly show damage
* Consider prop size for littering contracts (smaller = more realistic)
### Animation Selection
* Match animations to the action (punching for breaking, bending for picking up)
* Keep `DelayUntilCancelled` values reasonable (1-4 seconds)
* Use scenarios for simple standing animations
* Test animations with different character models
**Using Scenarios Instead**:
For simpler interactions, you can use scenarios instead of animations:
* `"WORLD_HUMAN_STAND_MOBILE"` - Standing with phone
* `"WORLD_HUMAN_BINOCULARS"` - Looking through binoculars
* `"WORLD_HUMAN_GUARD_STAND"` - Standing guard
* `"WORLD_HUMAN_CLIPBOARD"` - Writing on clipboard
Replace `["Animation"] = {Dict = "...", Anim = "..."}` with `["Scenario"] = "SCENARIO_NAME"`
### Sound Effects
* **Glass**: Picture frames, windows, glass items
* **Electronics**: Phones, laptops, tablets, TVs
* **Thud**: Heavy objects, furniture
* **Trash**: Cans, garbage, paper
* **Spill**: Liquids, drinks
* **Poop**: Organic materials (use sparingly)
### Required Items
* Set `"melee"` for break contracts to encourage weapon use
* Require a bag for steal contracts to create more immersion
* Use `"x_burner"` for pictures to integrate with burner phone system
* Set to `false` if you want contracts accessible to everyone
### Dialog Text
* Keep initial dialog friendly and inviting
* Make confirmation buttons clear ("Accept" vs "Decline")
* Provide instructions in the end conversation
* Consider your server's roleplay style and lore
# Adding House Locations
Source: https://docs.projectx.gg/resources/house-robbery-v2/guides/houses
Learn how to add robbable house locations to the config/houses.lua file
## What Are House Locations?
House locations are the physical spots on the map where players can initiate house robberies. These are the door coordinates and settings for each individual house, not the interior layouts (which are configured in presets).
## Configuration Structure
The houses configuration is organized into two main categories based on interior type:
```lua theme={null}
Config.Houses = {
["Shells"] = {},
["IPLs"] = {}
}
```
**Shells** use external shell systems (like K4MB1), while **IPLs** use GTA's built-in interior systems. Both categories support the exact same configuration parameters, so you can use all features regardless of interior type.
## Adding a New House
To add a new house location, create an entry under either `["Shells"]` or `["IPLs"]` with a unique house name as the key.
### Basic Structure
```lua theme={null}
Config.Houses = {
["Shells"] = {
["House Name"] = {
["Tier"] = 1,
["DoorCoords"] = vector3(0.0, 0.0, 0.0),
["SilentDispatch"] = false,
["SilentDispatchChance"] = 50,
["AlarmRemovesDispatch"] = false,
["ScoutingExp"] = 10,
["EnableAlarmProp"] = true,
["EnableLasers"] = false,
["ScoutingTablet"] = true,
["PedsSpawnRegardlessOfTime"] = false
}
},
["IPLs"] = {
["House Name"] = {
["Tier"] = 4,
["DoorCoords"] = vector3(0.0, 0.0, 0.0),
["SilentDispatch"] = false,
["SilentDispatchChance"] = 50,
["AlarmRemovesDispatch"] = false,
["ScoutingExp"] = 10,
["EnableAlarmProp"] = true,
["EnableLasers"] = false,
["ScoutingTablet"] = true,
["PedsSpawnRegardlessOfTime"] = false,
["ScoutingSpots"] = {
["ScoutingForTenantCount"] = {
["Coords"] = vector4(0.0, 0.0, 0.0, 0.0),
["Label"] = "Eavesdrop",
["Animation"] = {Dict = "cover@move@base@core", Anim = "high_idle_r_peek"},
["Icon"] = "fas fa-ear-listen"
},
["ScoutingForTime"] = {
["Coords"] = vector4(0.0, 0.0, 0.0, 0.0),
["Label"] = "Peek through window",
["Animation"] = {Dict = "cover@peek@ai@1h@high@_a", Anim = "peek_r_corner"},
["Icon"] = "fas fa-eye"
}
}
}
}
}
```
Both Shells and IPLs support all the same parameters including `EnableAlarmProp` and `EnableLasers`. The categorization is purely organizational based on your tier's interior type.
## Configuration Parameters
### Basic Settings
The tier level of this house. Must match a tier configured in `config/tiers.lua`
The coordinates of the house door where players initiate the robbery
If `true`, sends a dispatch alert without triggering the alarm when someone enters. Useful for remote houses far from the city
The chance (in percentage) that a silent dispatch will be sent when someone enters. Only applicable if `SilentDispatch` is enabled.
If `true`, completing the alarm step inside prevents police dispatch from being sent
Experience points awarded for scouting this house
If `true`, allows using a tablet to scout the house remotely instead of physical scouting spots
If `true`, NPCs spawn even during the configured safe time window. By default, robbing during safe hours prevents NPC spawns
### Security Features
Enable the physical alarm box prop that can be disabled inside the house. Works for both Shells and IPLs
Enable laser security systems inside the house. Works for both Shells and IPLs (must be configured in the preset)
### Advanced Scouting (Optional)
You can define custom scouting spots around the house instead of using the tablet:
Spot to discover how many tenants are inside
* `Coords` - Position and heading for the player
* `Label` - Interaction text
* `Animation` - Animation with `Dict` and `Anim` properties OR `Scenario` - Scenario name (use one or the other)
* `Icon` - Font Awesome icon
Spot to discover the time remaining until alarm triggers
* `Coords` - Position and heading for the player
* `Label` - Interaction text
* `Animation` - Animation with `Dict` and `Anim` properties OR `Scenario` - Scenario name (use one or the other)
* `Icon` - Font Awesome icon
**Example with Animation:**
```lua theme={null}
-- Add this to any house configuration (Shells or IPLs)
["ScoutingSpots"] = {
["ScoutingForTenantCount"] = {
["Coords"] = vector4(1385.0, 3660.0, 34.93, 180.0),
["Label"] = "Eavesdrop",
["Animation"] = {Dict = "cover@move@base@core", Anim = "high_idle_r_peek"},
["Icon"] = "fas fa-ear-listen"
},
["ScoutingForTime"] = {
["Coords"] = vector4(1384.0, 3659.0, 34.93, 90.0),
["Label"] = "Peek through window",
["Animation"] = {Dict = "cover@peek@ai@1h@high@_a", Anim = "peek_r_corner"},
["Icon"] = "fas fa-eye"
}
}
```
**Example with Scenario:**
```lua theme={null}
-- Add this to any house configuration (Shells or IPLs)
["ScoutingSpots"] = {
["ScoutingForTenantCount"] = {
["Coords"] = vector4(1385.0, 3660.0, 34.93, 180.0),
["Label"] = "Eavesdrop",
["Scenario"] = "WORLD_HUMAN_BINOCULARS",
["Icon"] = "fas fa-ear-listen"
},
["ScoutingForTime"] = {
["Coords"] = vector4(1384.0, 3659.0, 34.93, 90.0),
["Label"] = "Peek through window",
["Scenario"] = "WORLD_HUMAN_STAND_IMPATIENT",
["Icon"] = "fas fa-eye"
}
}
```
Scouting spots and scouting tablet can be used together or independently. If both are configured, players can choose their preferred method.
## Shell Houses vs IPL Houses
### Shells
* Use external shell systems (K4MB1, LevLevLev, etc.)
* Generally for lower to mid-tier houses
* Support all features (alarm props, lasers, scouting, etc.)
### IPLs
* Use GTA V's built-in interiors
* Generally for higher-tier houses
* More detailed and realistic interiors
* Support all features (alarm props, lasers, scouting, etc.)
**Important**: Both Shells and IPLs support the exact same configuration parameters. The only difference is the interior system used by the tier. All features like `EnableAlarmProp`, `EnableLasers`, and `ScoutingSpots` work identically in both categories.
Make sure your house is added to the correct category based on what interior type the tier uses. Check your tier configuration in `config/tiers.lua` to see if it uses a Shell or IPL interior.
## Tips for Adding Houses
1. **Unique Names**: Each house must have a unique name. Use location-based naming like `"Sandy Shores 1"`, `"Vinewood Hills 12"`, etc.
2. **Tier Assignment**: Assign tiers based on:
* Location difficulty (city vs remote)
* Neighborhood wealth level
* Desired loot quality
3. **Door Coordinates**: Stand at the house door and use `/vector4` or a similar command to get precise coordinates
4. **Silent Dispatch**: Enable for houses far from the city to give police more warning time
5. **Alarm Removal**: Consider enabling `AlarmRemovesDispatch` for higher-tier houses to reward skilled players who disable alarms
6. **Scouting Options**:
* Tablet scouting, convenient if you dont want to set up physical spots
* Physical scouting spots add realism and risk
* Mix both for variety
7. **Laser Systems**: Only enable lasers for high-tier houses where the preset has laser configurations
## Example: Shell House
```lua theme={null}
["Shells"] = {
["Sandy Shores 1"] = {
["Tier"] = 1,
["DoorCoords"] = vector3(1385.09, 3659.43, 34.93),
["SilentDispatch"] = false,
["SilentDispatchChance"] = 50,
["AlarmRemovesDispatch"] = false,
["ScoutingExp"] = 10,
["EnableAlarmProp"] = true,
["EnableLasers"] = false,
["ScoutingTablet"] = true,
["PedsSpawnRegardlessOfTime"] = false
["ScoutingSpots"] = {
["ScoutingForTenantCount"] = {["Coords"] = vector4(1385.0, 3660.0, 34.93, 180.0), ["Label"] = "Eavesdrop", ["Animation"] = {Dict = "cover@move@base@core", Anim = "high_idle_r_peek"}, ["Icon"] = "fas fa-ear-listen"},
["ScoutingForTime"] = {["Coords"] = vector4(1384.0, 3659.0, 34.93, 90.0), ["Label"] = "Peek through window", ["Animation"] = {Dict = "cover@peek@ai@1h@high@_a", Anim = "peek_r_corner"}, ["Icon"] = "fas fa-eye"}
}
}
}
```
## Example: IPL House
```lua theme={null}
["IPLs"] = {
["El Burro Heights 1"] = {
["Tier"] = 4,
["DoorCoords"] = vector3(1193.4, -1622.28, 45.22),
["SilentDispatch"] = false,
["SilentDispatchChance"] = 50,
["AlarmRemovesDispatch"] = false,
["ScoutingExp"] = 10,
["EnableAlarmProp"] = true,
["EnableLasers"] = false,
["ScoutingTablet"] = true,
["PedsSpawnRegardlessOfTime"] = false
["ScoutingSpots"] = {
["ScoutingForTenantCount"] = {["Coords"] = vector4(1193.4, -1623.0, 45.22, 180.0), ["Label"] = "Eavesdrop", ["Animation"] = {Dict = "cover@move@base@core", Anim = "high_idle_r_peek"}, ["Icon"] = "fas fa-ear-listen"},
["ScoutingForTime"] = {["Coords"] = vector4(1192.5, -1622.0, 45.22, 90.0), ["Label"] = "Peek through window", ["Animation"] = {Dict = "cover@peek@ai@1h@high@_a", Anim = "peek_r_corner"}, ["Icon"] = "fas fa-eye"}
}
}
}
```
## Complete Example
Here's a complete configuration showing multiple houses across different tiers and types. This demonstrates proper organization and variety in house setups.
This example shows houses organized by neighborhood and tier progression. Notice how higher tiers often include `EnableAlarmProp` and `EnableLasers` for added difficulty.
```lua theme={null}
Config.Houses = {
["Shells"] = {
["Sandy Shores 1"] = {
["Tier"] = 1,
["DoorCoords"] = vector3(1385.09, 3659.43, 34.93),
["SilentDispatch"] = false,
["SilentDispatchChance"] = 50,
["AlarmRemovesDispatch"] = false,
["ScoutingExp"] = 10,
["EnableAlarmProp"] = true,
["EnableLasers"] = false,
["ScoutingTablet"] = true,
["PedsSpawnRegardlessOfTime"] = false
},
["Sandy Shores 2"] = {
["Tier"] = 1,
["DoorCoords"] = vector3(1436.2, 3639.08, 34.95),
["SilentDispatch"] = false,
["SilentDispatchChance"] = 50,
["AlarmRemovesDispatch"] = false,
["ScoutingExp"] = 10,
["EnableAlarmProp"] = false,
["EnableLasers"] = false,
["ScoutingTablet"] = true,
["PedsSpawnRegardlessOfTime"] = false
},
["Rancho 1"] = {
["Tier"] = 1,
["DoorCoords"] = vector3(338.63, -1829.58, 28.34),
["SilentDispatch"] = false,
["SilentDispatchChance"] = 50,
["AlarmRemovesDispatch"] = false,
["ScoutingExp"] = 10,
["EnableAlarmProp"] = false,
["EnableLasers"] = false,
["ScoutingTablet"] = true,
["PedsSpawnRegardlessOfTime"] = false
},
["Chamberlain Hills 1"] = {
["Tier"] = 1,
["DoorCoords"] = vector3(-219.37, -1580.04, 34.87),
["SilentDispatch"] = false,
["SilentDispatchChance"] = 50,
["AlarmRemovesDispatch"] = false,
["ScoutingExp"] = 10,
["EnableAlarmProp"] = false,
["EnableLasers"] = false,
["ScoutingTablet"] = true,
["PedsSpawnRegardlessOfTime"] = false
},
["Alta 1"] = {
["Tier"] = 2,
["DoorCoords"] = vector3(115.67, -271.43, 46.33),
["SilentDispatch"] = false,
["SilentDispatchChance"] = 50,
["AlarmRemovesDispatch"] = false,
["ScoutingExp"] = 10,
["EnableAlarmProp"] = true,
["EnableLasers"] = false,
["ScoutingTablet"] = true,
["PedsSpawnRegardlessOfTime"] = false
},
["Burton 1"] = {
["Tier"] = 2,
["DoorCoords"] = vector3(-97.43, -357.71, 42.37),
["SilentDispatch"] = false,
["SilentDispatchChance"] = 50,
["AlarmRemovesDispatch"] = false,
["ScoutingExp"] = 10,
["EnableAlarmProp"] = true,
["EnableLasers"] = false,
["ScoutingTablet"] = true,
["PedsSpawnRegardlessOfTime"] = false
},
["Mirror Park 1"] = {
["Tier"] = 3,
["DoorCoords"] = vector3(1060.45, -378.2, 68.23),
["SilentDispatch"] = false,
["SilentDispatchChance"] = 50,
["AlarmRemovesDispatch"] = false,
["ScoutingExp"] = 10,
["EnableAlarmProp"] = true,
["EnableLasers"] = false,
["ScoutingTablet"] = true,
["PedsSpawnRegardlessOfTime"] = false
},
["East Vinewood 1"] = {
["Tier"] = 3,
["DoorCoords"] = vector3(861.46, -509.1, 57.71),
["SilentDispatch"] = false,
["SilentDispatchChance"] = 50,
["AlarmRemovesDispatch"] = false,
["ScoutingExp"] = 10,
["EnableAlarmProp"] = true,
["EnableLasers"] = false,
["ScoutingTablet"] = true,
["PedsSpawnRegardlessOfTime"] = false
},
["Vinewood Hills 1"] = {
["Tier"] = 3,
["DoorCoords"] = vector3(-873.24, 562.68, 96.62),
["SilentDispatch"] = false,
["SilentDispatchChance"] = 50,
["AlarmRemovesDispatch"] = false,
["ScoutingExp"] = 10,
["EnableAlarmProp"] = true,
["EnableLasers"] = true,
["ScoutingTablet"] = true,
["PedsSpawnRegardlessOfTime"] = false
}
},
["IPLs"] = {
["El Burro Heights 1"] = {
["Tier"] = 4,
["DoorCoords"] = vector3(1193.4, -1622.28, 45.22),
["SilentDispatch"] = false,
["SilentDispatchChance"] = 50,
["EnableAlarmProp"] = true,
["AlarmRemovesDispatch"] = false,
["EnableLasers"] = false,
["ScoutingExp"] = 10,
["ScoutingTablet"] = true,
["PedsSpawnRegardlessOfTime"] = false,
["ScoutingSpots"] = {
["ScoutingForTenantCount"] = {["Coords"] = vector4(1193.4, -1623.0, 45.22, 180.0), ["Label"] = "Eavesdrop", ["Animation"] = {Dict = "cover@move@base@core", Anim = "high_idle_r_peek"}, ["Icon"] = "fas fa-ear-listen"},
["ScoutingForTime"] = {["Coords"] = vector4(1192.5, -1622.0, 45.22, 90.0), ["Label"] = "Peek through window", ["Animation"] = {Dict = "cover@peek@ai@1h@high@_a", Anim = "peek_r_corner"}, ["Icon"] = "fas fa-eye"}
}
},
["El Burro Heights 2"] = {
["Tier"] = 4,
["DoorCoords"] = vector3(1245.47, -1626.94, 53.28),
["SilentDispatch"] = false,
["SilentDispatchChance"] = 50,
["EnableAlarmProp"] = true,
["AlarmRemovesDispatch"] = false,
["EnableLasers"] = false,
["ScoutingExp"] = 10,
["ScoutingTablet"] = true,
["PedsSpawnRegardlessOfTime"] = false
},
["Vespucci 1"] = {
["Tier"] = 4,
["DoorCoords"] = vector3(-1247.08, -1358.31, 7.82),
["SilentDispatch"] = false,
["SilentDispatchChance"] = 50,
["EnableAlarmProp"] = true,
["AlarmRemovesDispatch"] = false,
["EnableLasers"] = false,
["ScoutingExp"] = 10,
["ScoutingTablet"] = true,
["PedsSpawnRegardlessOfTime"] = false
},
["Richman 1"] = {
["Tier"] = 5,
["DoorCoords"] = vector3(-1629.96, 36.4, 62.94),
["SilentDispatch"] = false,
["SilentDispatchChance"] = 50,
["EnableAlarmProp"] = true,
["AlarmRemovesDispatch"] = false,
["EnableLasers"] = true,
["ScoutingExp"] = 10,
["ScoutingTablet"] = true,
["PedsSpawnRegardlessOfTime"] = false
},
["Richman 2"] = {
["Tier"] = 5,
["DoorCoords"] = vector3(-1570.71, 22.4, 59.55),
["SilentDispatch"] = false,
["SilentDispatchChance"] = 50,
["EnableAlarmProp"] = true,
["AlarmRemovesDispatch"] = false,
["EnableLasers"] = true,
["ScoutingExp"] = 10,
["ScoutingTablet"] = true,
["PedsSpawnRegardlessOfTime"] = false
},
["Vinewood Hills 10"] = {
["Tier"] = 6,
["DoorCoords"] = vector3(-339.93, 625.51, 171.36),
["SilentDispatch"] = false,
["SilentDispatchChance"] = 50,
["EnableAlarmProp"] = true,
["AlarmRemovesDispatch"] = false,
["EnableLasers"] = true,
["ScoutingExp"] = 10,
["ScoutingTablet"] = true,
["PedsSpawnRegardlessOfTime"] = false
},
["Vinewood Hills 11"] = {
["Tier"] = 6,
["DoorCoords"] = vector3(-446.17, 686.33, 153.11),
["SilentDispatch"] = false,
["SilentDispatchChance"] = 50,
["EnableAlarmProp"] = true,
["AlarmRemovesDispatch"] = false,
["EnableLasers"] = true,
["ScoutingExp"] = 10,
["ScoutingTablet"] = true,
["PedsSpawnRegardlessOfTime"] = false
}
}
}
```
## Testing Your Houses
After adding houses, test them to ensure:
1. **Door Coordinates**: Player can interact with the door properly
2. **Tier Match**: The house uses the correct interior for its tier
3. **Dispatch**: Silent dispatch works as intended for remote locations
4. **Scouting**: Tablet or physical scouting spots function correctly
5. **Security**: Alarm props and lasers spawn if enabled
6. **NPCs**: Tenants spawn according to time and configuration
# House Presets
Source: https://docs.projectx.gg/resources/house-robbery-v2/guides/presets
Learn how to use and create house presets for House Robbery V2
## What Are Presets?
Presets are pre-configured house interiors that you can easily add to your server. The House Robbery V2 resource includes a `presets` folder where you can simply drag and drop preset files shared by the community in our Discord's **Snippets** channel.
Join our Discord at [discord.gg/projectxdev](https://discord.gg/projectxdev) and check the **Snippets** channel for community-shared presets!
## How to Use Presets
1. Download a preset file from the Discord Snippets channel
2. Place the preset file in the `presets` folder of your House Robbery V2 resource
3. Restart the resource or your server
4. The preset will automatically load and be available for use
When creating custom presets, use the `/getoffset` command to get accurate coordinates for all items, spots, and props inside shells. See the [Commands](/resources/house-robbery-v2/commands) page for details.
## Preset Structure
Here's a complete example of a preset with all possible options:
```lua theme={null}
LoadHousePreset("Shells", "example", {
["ExitCoords"] = vector4(-779.21, 339.86, 196.69, 177.92),
["Spots"] = {},
["Props"] = {},
["Cash"] = {},
["Safe"] = {},
["Painting"] = {},
["Display"] = {},
["HighValueItems"] = {},
["Tenants"] = {},
["Pets"] = {},
["Laser"] = {},
["Alarms"] = {},
["Contracts"] = {}
})
```
## Function Parameters
The type of interior system used. Values: `"Shells"`, `"IPL"`
Unique identifier for the house. Must match the house name configured in your housing script
Configuration table containing all house preset data
## Configuration Options
### ExitCoords
Coordinates where the player will exit the house interior. Includes position (x, y, z) and heading (w)
**Example:**
```lua theme={null}
["ExitCoords"] = vector4(-779.21, 339.86, 196.69, 177.92)
```
### Spots
Searchable spots in the house that can be looted for random items.
Type of spot being searched. Examples: `"drawer"`, `"cabinet"`, `"kitchen"`, `"closet"`, `"bathroom"`
Position of the searchable spot
Font Awesome icon for the interaction. Example: `'fas fa-search'`
Text displayed for the interaction
Animation played when searching the spot. Can use `Dict` and `Anim` properties OR `Scenario` property (use one or the other)
**Example with Animation:**
```lua theme={null}
["Spots"] = {
["1"] = {
["Type"] = "drawer",
["Coords"] = vector3(-771.69, 335.96, 195.94),
["Icon"] = 'fas fa-search',
["Label"] = "Search drawer",
["Animation"] = {Dict = "amb@prop_human_bum_shopping_cart@male@idle_a", Anim = "idle_c"}
}
}
```
**Example with Scenario:**
```lua theme={null}
["Spots"] = {
["1"] = {
["Type"] = "drawer",
["Coords"] = vector3(-771.69, 335.96, 195.94),
["Icon"] = 'fas fa-search',
["Label"] = "Search drawer",
["Scenario"] = "WORLD_HUMAN_STAND_MOBILE"
}
}
```
### Props
Stealable props that spawn in the house and can be looted for specific items.
Item name that will be given when looting this prop
Experience points awarded for looting this prop
Prop model name to spawn
Position where the prop will spawn
Rotation of the prop (pitch, roll, yaw)
Font Awesome icon for the interaction
Text displayed for the interaction
Animation played when stealing the prop. Can use `Dict` and `Anim` properties OR `Scenario` property
**Example:**
```lua theme={null}
["Props"] = {
["1"] = {
["Reward"] = "laptop",
["Exp"] = 5,
["Prop"] = "reh_prop_reh_laptop_01a",
["Coords"] = vector3(-772.97, 328.25, 195.91),
["Rotation"] = vector3(0.0, 0.0, 227.85),
["Icon"] = 'fas fa-box-archive',
["Label"] = "Steal laptop",
["Animation"] = {Dict = "random@train_tracks", Anim = "idle_e"}
}
}
```
### Cash
Props that contain cash or marked bills.
If `true`, gives actual cash. If `false`, gives the cash item specified in `CashItem`
Item name to give when `Cash` is `false`. Example: `"markedbills"`
Cash amount range with `min` and `max` values
Metadata to attach to the cash item. Set to `false` for no metadata
Experience points awarded for looting
Prop model name (wallet, purse, etc.)
Position of the cash prop
Rotation of the prop
Font Awesome icon for the interaction
Text displayed for the interaction
Animation played when stealing cash. Can use `Dict` and `Anim` properties OR `Scenario` property
**Example:**
```lua theme={null}
["Cash"] = {
["1"] = {
['Cash'] = true,
['CashItem'] = "markedbills",
['Amount'] = {min = 25, max = 100},
['MetaData'] = false,
["Exp"] = 5,
["Prop"] = "prop_ld_wallet_pickup",
["Coords"] = vector3(-771.40, 336.41, 196.15),
["Rotation"] = vector3(-91.413, -0.000, -107.493),
["Icon"] = 'fas fa-money-bill-wave',
["Label"] = "Steal Cash",
["Animation"] = {Dict = "mini@repair", Anim = "fixing_a_player"}
}
}
```
### Safe
Safes that require cracking and contain valuable loot.
Experience points awarded for cracking the safe
Position of the safe
Rotation of the safe prop
Font Awesome icon for the interaction
Text displayed for the interaction
**Example:**
```lua theme={null}
["Safe"] = {
["1"] = {
["Exp"] = 10,
["Coords"] = vector3(-763.27, 331.14, 199.49),
["Rotation"] = vector3(0.0, 0.0, -0.67),
["Icon"] = 'fab fa-keycdn',
["Label"] = "Unlock Safe"
}
}
```
### Painting
Paintings that can be stolen from walls.
Item name given when stealing the painting
Experience points awarded
Position of the painting on the wall
Rotation of the painting
Rotation the player faces when stealing
Position where the player stands when stealing
Painting prop model name
Font Awesome icon for the interaction
Text displayed for the interaction
**Example:**
```lua theme={null}
["Painting"] = {
["1"] = {
["Reward"] = "x_painting",
["Exp"] = 10,
["Coords"] = vector3(-769.91, 324.92, 199.63),
["Rotation"] = vec3(0.00, -0.00, 88.01),
["AnimRotation"] = vec3(0.00, -0.00, 90.10),
["AnimPosition"] = vector3(-769.48, 324.99, 199.49),
["Prop"] = "ch_prop_vault_painting_01g",
["Icon"] = 'fas fa-paintbrush',
["Label"] = "Steal Painting"
}
}
```
### Display
Glass display cases containing valuable items.
Item name given when breaking the display
Experience points awarded
Position of the glass display case
Heading rotation of the display case
Item prop model shown inside the display
Position of the item inside the display
Heading rotation of the item prop
If `true`, the stand inside the display will not spawn
Font Awesome icon for the interaction
Text displayed for the interaction
**Example:**
```lua theme={null}
["Display"] = {
["1"] = {
["Reward"] = "x_goldenknife",
["Exp"] = 10,
["DisplayCoords"] = vector3(-761.311, 332.210, 196.090),
["DisplayHeading"] = 269.22,
["Prop"] = "w_me_knife_xm3_08",
["PropCoords"] = vector3(-761.311, 332.210, 196.090),
["PropHeading"] = 269.22,
["RemoveStand"] = true,
["Icon"] = 'fas fa-gem',
["Label"] = "Break Glass"
}
}
```
### HighValueItems
High value items that can be stolen from the house.
Item name given when stealing
Experience points awarded
Prop model name
Position of the item
Rotation of the prop
Font Awesome icon for the interaction
Text displayed for the interaction
Animation played when stealing. Can use `Dict` and `Anim` properties OR `Scenario` property
**Example:**
```lua theme={null}
["HighValueItems"] = {
["1"] = {
["Reward"] = "emerald_necklace",
["Exp"] = 5,
["Prop"] = "sf_prop_sf_necklace_01a",
["Coords"] = vector3(-765.17, 328.56, 199.35),
["Rotation"] = vector3(0.0, 0.0, 43.255),
["Icon"] = 'fas fa-box-archive',
["Label"] = "Steal necklace",
["Animation"] = {Dict = "anim@amb@carmeet@checkout_car@female_d@base", Anim = "base"}
}
}
```
### Tenants
NPCs that live in the house and can detect the player.
Spawn position and heading of the tenant
Ped model name for the tenant
Animation the tenant performs. Can use `Dict` and `Anim` properties OR `Scenario` property
Enable or disable detection for this tenant
Polyzone coordinates defining the detection area (only if `Enable` is `true`)
Height of the detection zone (only if `Enable` is `true`)
**Example:**
```lua theme={null}
["Tenants"] = {
{
["Coords"] = vector4(-774.9, 318.97, 195.89, 91.18),
["Model"] = "s_m_m_strpreach_01",
["Animation"] = {Dict = "timetable@ron@ig_3_couch", Anim = "base"},
["Detection"] = {
["Enable"] = true,
["ZoneCoords"] = {
vec(-773.58, 313.86, 195.89),
vec(-773.48, 323.12, 195.89),
vec(-780.63, 322.83, 195.89),
vec(-780.67, 313.86, 195.89)
},
["ZoneHeight"] = 4.0
}
}
}
```
### Pets
Animals in the house that can alert tenants.
Spawn position and heading of the pet
Animal model name
Animation the pet performs. Can use `Dict` and `Anim` properties OR `Scenario` property
**Example:**
```lua theme={null}
["Pets"] = {
{
["Coords"] = vector4(-777.54, 321.39, 195.89, 280.85),
["Model"] = "a_c_chop",
["Animation"] = {Dict = "creatures@rottweiler@amb@sleep_in_kennel@", Anim = "sleep_in_kennel"}
}
}
```
### Laser
Laser security system that must be disabled.
Prop model for the laser control panel
Position and heading of the control panel (as offset)
Text displayed for the interaction
Font Awesome icon for the interaction
Item required to disable lasers. Set to `false` for no requirement
Start position of the laser beam
End position of the laser beam
Detection range around the laser beam
**Example:**
```lua theme={null}
["Laser"] = {
["LasersProp"] = {
["Model"] = "ch_prop_fingerprint_scanner_01e",
["Coords"] = vector4(-767.87, 332.73, 196.30, 178.250),
["Label"] = "Turn off the lasers",
["Icon"] = "fas fa-barcode"
},
["RequiredLaserItem"] = "x_device",
["LaserCoords"] = {
{["Coords1"] = vector3(-766.6, 334.14, 195.09), ["Coords2"] = vector3(-766.6, 334.14, 197.09), ["Range"] = 5.0},
{["Coords1"] = vector3(-766.67, 333.47, 195.09), ["Coords2"] = vector3(-766.67, 333.47, 197.09), ["Range"] = 5.0}
}
}
```
### Alarms
Alarm system that can be disabled.
Prop model for the alarm box
Position and heading of the alarm box (as offset)
Text displayed for the interaction
Font Awesome icon for the interaction
Item required to disable alarm. Set to `false` for no requirement
**Example:**
```lua theme={null}
["Alarms"] = {
["AlarmProp"] = {
Model = "v_res_tre_alarmbox",
Coords = vector4(-767.25, 326.49, 199.69, 0.0),
Label = "Disable Alarm",
Icon = "fas fa-bell-slash"
},
["RequiredItem"] = "x_device"
}
```
### Contracts
Special contracts that can spawn in the house.
Percentage chance (0-100) that a contract will spawn
Contract name from the contracts.lua file
Contract type: `"Break Objects"`, `"Littering"`, or `"Steal Objects"`
Position where the contract object spawns
Rotation of the contract object
Position where littered items spawn (for `"Littering"` type)
Rotation of littered items (for `"Littering"` type)
**Example:**
```lua theme={null}
["Contracts"] = {
["ChanceOfSpawning"] = 100,
["PossibleContracts"] = {
["1"] = {
["Contract"] = "Trashcan",
["Type"] = "Littering",
["PickupCoords"] = vector3(-764.00, 321.12, 199.17),
["PickupRotation"] = vector3(0.0, 0.0, 343.53),
["LitteredCoords"] = vector3(-764.00, 321.12, 199.17),
["LitteredRotation"] = vector3(0.0, 0.0, 343.53)
}
}
}
```
## Creating Your Own Preset
When creating your own preset:
1. Start with the basic structure using `LoadHousePreset()`
2. Add the `ExitCoords` (required)
3. Use `/getoffset` command while inside the shell to get accurate coordinates for each item
4. Add any of the optional sections you want (Spots, Props, Cash, etc.)
5. For tenant detection zones, enable `Config.PolyTool` and use `/polycreate` command
6. Test in-game to ensure all coordinates and rotations are correct
7. Share your preset in the Discord Snippets channel for others to use!
**Pro Tip**: Use `/getoffset` for every single position in your preset. This ensures items spawn exactly where you want them inside the shell interior.
### Using Development Commands
* **`/getoffset`**: Stand at the desired location inside the shell and run this command to get the offset coordinates
* **`/polycreate`**: Create detection zones around tenants by defining the area boundaries
See the [Commands](/resources/house-robbery-v2/commands) page for detailed command usage and examples.
## Complete Example
Here's a full example preset with all possible sections:
```lua theme={null}
LoadHousePreset("Shells", "example", {
["ExitCoords"] = vector4(-779.21, 339.86, 196.69, 177.92),
["Spots"] = {
["1"] = {
["Type"] = "drawer",
["Coords"] = vector3(-771.69, 335.96, 195.94),
["Icon"] = 'fas fa-search',
["Label"] = "Search drawer",
["Animation"] = {Dict = "amb@prop_human_bum_shopping_cart@male@idle_a", Anim = "idle_c"},
},
["2"] = {
["Type"] = "cabinet",
["Coords"] = vector3(-771.69, 337.52, 195.97),
["Icon"] = 'fas fa-search',
["Label"] = "Search cabinet",
["Animation"] = {Dict = "amb@prop_human_bum_shopping_cart@male@idle_a", Anim = "idle_c"},
},
["3"] = {
["Type"] = "kitchen",
["Coords"] = vector3(-779.37, 325.99, 195.92),
["Icon"] = 'fas fa-search',
["Label"] = "Search kitchen",
["Animation"] = {Dict = "anim@amb@clubhouse@tutorial@bkr_tut_ig3@", Anim = "machinic_loop_mechandplayer"},
},
["4"] = {
["Type"] = "cabinet",
["Coords"] = vector3(-770.91, 321.59, 195.70),
["Icon"] = 'fas fa-search',
["Label"] = "Search cabinet",
["Animation"] = {Dict = "anim@amb@clubhouse@tutorial@bkr_tut_ig3@", Anim = "machinic_loop_mechandplayer"},
},
["5"] = {
["Type"] = "drawer",
["Coords"] = vector3(-760.55, 319.66, 199.29),
["Icon"] = 'fas fa-search',
["Label"] = "Search drawer",
["Animation"] = {Dict = "anim@amb@clubhouse@tutorial@bkr_tut_ig3@", Anim = "machinic_loop_mechandplayer"},
},
},
["Props"] = {
["1"] = {
["Reward"] = "x_plush",
["Exp"] = 5,
["Prop"] = "sum_prop_sum_arcade_plush_04a",
["Coords"] = vector3(-763.83, 322.41, 199.17),
["Rotation"] = vector3(0.0, 0.0, 95.0),
["Icon"] = 'fas fa-box-archive',
["Label"] = "Steal plushie",
["Animation"] = {Dict = "mini@repair", Anim = "fixing_a_player"},
},
["2"] = {
["Reward"] = "x_toaster",
["Exp"] = 5,
["Prop"] = "prop_toaster_02",
["Coords"] = vector3(-779.56, 327.62, 196.04),
["Rotation"] = vector3(0.0, 0.0, 92.274),
["Icon"] = 'fas fa-box-archive',
["Label"] = "Steal toaster",
["Animation"] = {Dict = "random@train_tracks", Anim = "idle_e"},
},
["3"] = {
["Reward"] = "laptop",
["Exp"] = 5,
["Prop"] = "reh_prop_reh_laptop_01a",
["Coords"] = vector3(-772.97, 328.25, 195.91),
["Rotation"] = vector3(0.0, 0.0, 227.85),
["Icon"] = 'fas fa-box-archive',
["Label"] = "Steal laptop",
["Animation"] = {Dict = "random@train_tracks", Anim = "idle_e"},
},
["4"] = {
["Reward"] = "x_printer",
["Exp"] = 5,
["Prop"] = "v_res_printer",
["Coords"] = vector3(-762.69, 329.43, 195.81),
["Rotation"] = vector3(0.0, 0.0, 179.527),
["Icon"] = 'fas fa-box-archive',
["Label"] = "Steal printer",
["Animation"] = {Dict = "mini@repair", Anim = "fixing_a_player"},
},
},
["Cash"] = {
["1"] = {
['Cash'] = true,
['CashItem'] = "markedbills",
['Amount'] = {min = 25, max = 100},
['MetaData'] = false,
["Exp"] = 5,
["Prop"] = "prop_ld_purse_01",
["Coords"] = vector3(-761.16, 327.84, 199.30),
["Rotation"] = vector3(86.389, -4.940, 35.907),
["Icon"] = 'fas fa-money-bill-wave',
["Label"] = "Steal Cash",
["Animation"] = {Dict = "mini@repair", Anim = "fixing_a_player"},
},
["2"] = {
['Cash'] = true,
['CashItem'] = "markedbills",
['Amount'] = {min = 25, max = 100},
['MetaData'] = false,
["Exp"] = 5,
["Prop"] = "prop_ld_wallet_pickup",
["Coords"] = vector3(-771.40, 336.41, 196.15),
["Rotation"] = vector3(-91.413, -0.000, -107.493),
["Icon"] = 'fas fa-money-bill-wave',
["Label"] = "Steal Cash",
["Animation"] = {Dict = "mini@repair", Anim = "fixing_a_player"},
},
},
["Safe"] = {
["1"] = {
["Exp"] = 10,
["Coords"] = vector3(-763.27, 331.14, 199.49),
["Rotation"] = vector3(0.0, 0.0, -0.67),
["Icon"] = 'fab fa-keycdn',
["Label"] = "Unlock Safe"
},
},
["Painting"] = {
["1"] = {
["Reward"] = "x_painting",
["Exp"] = 10,
["Coords"] = vector3(-769.91, 324.92, 199.63),
["Rotation"] = vec3(0.00, -0.00, 88.01),
["AnimRotation"] = vec3(0.00, -0.00, 90.10),
["AnimPosition"] = vector3(-769.48, 324.99, 199.49),
["Prop"] = "ch_prop_vault_painting_01g",
["Icon"] = 'fas fa-paintbrush',
["Label"] = "Steal Painting"
},
["2"] = {
["Reward"] = "x_painting",
["Exp"] = 10,
["Coords"] = vector3(-766.74, 315.87, 196.0),
["Rotation"] = vec3(0.00, -0.00, 268.63),
["AnimRotation"] = vec3(0.00, -0.00, -90.87),
["AnimPosition"] = vector3(-767.25, 316.22, 195.79),
["Prop"] = "h4_prop_h4_painting_01c",
["Icon"] = 'fas fa-paintbrush',
["Label"] = "Steal Painting"
},
},
["Display"] = {
["1"] = {
["Reward"] = "x_goldenknife",
["Exp"] = 10,
["DisplayCoords"] = vector3(-761.311, 332.210, 196.090),
["DisplayHeading"] = 269.22,
["Prop"] = "w_me_knife_xm3_08",
["PropCoords"] = vector3(-761.311, 332.210, 196.090),
["PropHeading"] = 269.22,
["RemoveStand"] = true,
["Icon"] = 'fas fa-gem',
["Label"] = "Break Glass"
},
},
["HighValueItems"] = {
["1"] = {
["Reward"] = "emerald_necklace",
["Exp"] = 5,
["Prop"] = "sf_prop_sf_necklace_01a",
["Coords"] = vector3(-765.17, 328.56, 199.35),
["Rotation"] = vector3(0.0, 0.0, 43.255),
["Icon"] = 'fas fa-box-archive',
["Label"] = "Steal necklace",
["Animation"] = {Dict = "anim@amb@carmeet@checkout_car@female_d@base", Anim = "base"},
},
},
["Tenants"] = {
{
["Coords"] = vector4(-774.9, 318.97, 195.89, 91.18),
["Model"] = "s_m_m_strpreach_01",
["Animation"] = {Dict = "timetable@ron@ig_3_couch", Anim = "base"},
["Detection"] = {
["Enable"] = true,
["ZoneCoords"] = {vec(-773.58, 313.86, 195.89), vec(-773.48, 323.12, 195.89), vec(-780.63, 322.83, 195.89), vec(-780.67, 313.86, 195.89)},
["ZoneHeight"] = 4.0,
},
},
{
["Coords"] = vector4(-762.72, 321.76, 200.06, 269.09),
["Model"] = "s_f_y_hooker_01",
["Animation"] = {Dict = "timetable@tracy@sleep@", Anim = "idle_c"},
["Detection"] = {
["Enable"] = false,
["ZoneCoords"] = {},
["ZoneHeight"] = 0.0,
},
},
},
["Pets"] = {
{["Coords"] = vector4(-777.54, 321.39, 195.89, 280.85), ["Model"] = "a_c_chop", ["Animation"] = {Dict = "creatures@rottweiler@amb@sleep_in_kennel@", Anim = "sleep_in_kennel"}},
},
["Laser"] = {
["LasersProp"] = {["Model"] = "ch_prop_fingerprint_scanner_01e", ["Coords"] = vector4(-767.87, 332.73, 196.30, 178.250), ["Label"] = "Turn off the lasers", ["Icon"] = "fas fa-barcode"},
["RequiredLaserItem"] = "x_device",
["LaserCoords"] = {
{["Coords1"] = vector3(-766.6, 334.14, 195.09), ["Coords2"] = vector3(-766.6, 334.14, 197.09), ["Range"] = 5.0},
{["Coords1"] = vector3(-766.67, 333.47, 195.09), ["Coords2"] = vector3(-766.67, 333.47, 197.09), ["Range"] = 5.0},
},
},
["Alarms"] = {
["AlarmProp"] = {Model = "v_res_tre_alarmbox", Coords = vector4(-767.25, 326.49, 199.69, 0.0), Label = "Disable Alarm", Icon = "fas fa-bell-slash"},
["RequiredItem"] = "x_device",
},
["Contracts"] = {
["ChanceOfSpawning"] = 100,
["PossibleContracts"] = {
["1"] = {
["Contract"] = "Trashcan",
["Type"] = "Littering",
["PickupCoords"] = vector3(-764.00, 321.12, 199.17),
["PickupRotation"] = vector3(0.0, 0.0, 343.53),
["LitteredCoords"] = vector3(-764.00, 321.12, 199.17),
["LitteredRotation"] = vector3(0.0, 0.0, 343.53),
},
},
}
})
```
# Configuring Tiers
Source: https://docs.projectx.gg/resources/house-robbery-v2/guides/tiers
Learn how to configure robbery tiers in the config/tiers.lua file
## What Are Tiers?
Tiers are difficulty levels in the House Robbery V2 system. Each tier has different requirements, interiors, approaches, loot tables, and difficulty settings. Players progress through tiers by gaining experience and leveling up.
## Adding a New Tier
To add a new tier, create a new entry in the `Config.Tiers` table with a unique tier number as the key.
### Basic Structure
```lua theme={null}
Config.Tiers = {
[1] = {
["Level"] = 1,
["Interior"] = "shell_name",
["Approach"] = {"approach1", "approach2"},
["RequiredItemForLockpicking"] = "item_name",
["ExpOnDone"] = 10,
["ExpForAllGroupMembers"] = false,
["LootableSpots"] = {},
["LootableProps"] = {},
["LootableCash"] = {},
["LootableSafes"] = {},
["LootableDisplays"] = {},
["LootablePaintings"] = {},
["LootableHighValueItems"] = {},
["Spots"] = {},
["Props"] = {},
["Cash"] = {},
["Display"] = {},
["Painting"] = {},
["Safe"] = {},
["HighValueItems"] = {},
["Tenants"] = {},
["Pets"] = {},
["LootTable"] = {}
}
}
```
## Tier Configuration Options
### Basic Settings
Minimum level required to access this tier
Interior name (Shell or IPL) from the presets file. Must match exactly with a preset name
Available approaches for this tier. Can be a table of multiple approaches or a single string
* `"gangster"` - Break in aggressively
* `"door"` - Lockpick the door
* `"locksmith"` - Pose as locksmith
* `"maid"` - Pose as cleaning service
* `"hacking"` - Hack security systems
* `"payphone"` - Use payphone approach
* `"valet"` - Valet service approach
Item required to break into houses. Set to `false` for no requirement
Experience points awarded when completing the robbery
If `true`, all group members receive XP. Requires a group system implementation
### Lootable Arrays
These arrays reference the spot numbers from your preset file. The numbers correspond to the keys in your preset's loot sections.
Array of spot IDs that can spawn (e.g., `{1, 2, 3, 4}`)
Array of prop IDs that can spawn
Array of cash spot IDs that can spawn
Array of safe IDs that can spawn
Array of display case IDs that can spawn
Array of painting IDs that can spawn
Array of high value item IDs that can spawn
The IDs in these arrays must match the keys defined in your preset file. For example, if your preset has `["Props"]["1"]` and `["Props"]["2"]`, use `["LootableProps"] = {1, 2}`
### Spots Configuration
Enable or disable searchable spots in this tier
Percentage chance (0-100) that spots will spawn
Range of spots that can spawn with `min` and `max` values. Must not exceed the number of `LootableSpots` configured
### Props Configuration
Enable or disable props in this tier
Enable visual outline on stealable props
Percentage chance (0-100) that props will spawn
Range of props that can spawn with `min` and `max` values
### Cash Configuration
Enable or disable cash spawns in this tier
Enable visual outline on cash props
Percentage chance (0-100) that cash will spawn
Range of cash spots that can spawn with `min` and `max` values
### Display Configuration
Enable or disable display cases in this tier
Percentage chance (0-100) that displays will spawn
Range of displays that can spawn with `min` and `max` values
### Painting Configuration
Enable or disable paintings in this tier
Percentage chance (0-100) that paintings will spawn
Range of paintings that can spawn with `min` and `max` values
### Safe Configuration
Enable or disable safes in this tier
Percentage chance (0-100) that safes will spawn
Range of safes that can spawn with `min` and `max` values
Experience points awarded for cracking a safe
How many times the reward table is rolled with `min` and `max` values
Array of possible rewards with each entry containing:
* `Name` - Item name
* `Chance` - Percentage chance (total should equal 100)
* `Amount` - Table with `min` and `max` item quantities
### High Value Items Configuration
Enable or disable high value items in this tier
Enable visual outline on high value items
Percentage chance (0-100) that high value items will spawn
### Tenants Configuration
Enable or disable NPCs in this tier
Percentage chance (0-100) that tenants will spawn
Percentage chance (0-100) that a tenant will be armed
Array of weapon hashes that can be given to armed tenants
Range of tenants that can spawn with `min` and `max` values. Maximum is 4 by default (increase in preset file if needed)
### Pets Configuration
Enable or disable pets in this tier
Percentage chance (0-100) that pets will spawn
Range of pets that can spawn with `min` and `max` values. Maximum is 2 by default (increase in preset file if needed)
### Loot Table Configuration
The loot table defines what items can be found when searching different spot types.
How many different items can be obtained per search with `min` and `max` values
Percentage chance (0-100) of finding loot when searching under normal conditions
Percentage chance (0-100) of finding loot after the alarm has been triggered
Experience points range awarded per search with `min` and `max` values
Each spot type (drawer, cabinet, closet, kitchen, etc.) has its own loot table with entries containing:
* `Name` - Item name
* `Chance` - Percentage chance (total for each spot type should equal 100)
* `Amount` - Table with `min` and `max` item quantities
The total chance values for each spot type in the loot table must equal 100. For example, if you have 4 items in the `drawer` table, their chances could be 25, 25, 25, 25 or any combination that totals 100.
## Complete Example
Here's a complete tier configuration with all options:
```lua theme={null}
Config.Tiers = {
[5] = {
["Level"] = 20,
["Interior"] = "EclipseTowersPenthouse2",
["Approach"] = {"valet", "maid", "hacking"},
["RequiredItemForLockpicking"] = "advancedlockpick",
["ExpOnDone"] = 10,
["ExpForAllGroupMembers"] = false,
["LootableSpots"] = {1, 2, 3, 4, 5},
["LootableProps"] = {1, 2, 3, 4, 5},
["LootableCash"] = {1, 2},
["LootableSafes"] = {1},
["LootableDisplays"] = {1},
["LootablePaintings"] = {1, 2},
["LootableHighValueItems"] = {1},
["Spots"] = {
["Enable"] = true,
["SpawnChance"] = 100,
["SpotCount"] = {min = 4, max = 5},
},
["Props"] = {
["Enable"] = true,
["Outline"] = false,
["SpawnChance"] = 100,
["PropCount"] = {min = 5, max = 5},
},
["Cash"] = {
["Enable"] = true,
["Outline"] = false,
["SpawnChance"] = 100,
["CashCount"] = {min = 2, max = 2},
},
["Display"] = {
["Enable"] = true,
["SpawnChance"] = 100,
["DisplayCount"] = {min = 1, max = 1},
},
["Painting"] = {
["Enable"] = true,
["SpawnChance"] = 100,
["PaintingCount"] = {min = 2, max = 2},
},
["Safe"] = {
["Enable"] = true,
["SpawnChance"] = 100,
["SafeCount"] = {min = 1, max = 1},
["Exp"] = 10,
["RewardCount"] = {min = 1, max = 1},
["Reward"] = {
{Name = "fitbit", Chance = 25, Amount = {min = 1, max = 1}},
{Name = "screwdriverset", Chance = 25, Amount = {min = 1, max = 2}},
{Name = "bandage", Chance = 25, Amount = {min = 1, max = 2}},
{Name = "plastic", Chance = 25, Amount = {min = 1, max = 1}},
},
},
["HighValueItems"] = {
["Enable"] = true,
["Outline"] = false,
["SpawnChance"] = 100,
},
["Tenants"] = {
["Enable"] = true,
["SpawnChance"] = 100,
["WeaponChance"] = 100,
["RandomWeapons"] = {"WEAPON_BAT", "WEAPON_KNIFE", "WEAPON_PISTOL"},
["Count"] = {min = 2, max = 2},
},
["Pets"] = {
["Enable"] = true,
["SpawnChance"] = 100,
["Count"] = {min = 1, max = 1},
},
["LootTable"] = {
LootPerSearch = {min = 1, max = 1},
FindingLootChance = 70,
LootChanceAfterAlarmTriggered = 40,
Exp = {min = 3, max = 4},
["drawer"] = {
{Name = "screwdriverset", Chance = 25, Amount = {min = 1, max = 2}},
{Name = "fitbit", Chance = 25, Amount = {min = 1, max = 1}},
{Name = "lockpick", Chance = 25, Amount = {min = 1, max = 1}},
{Name = "samsungphone", Chance = 25, Amount = {min = 1, max = 1}},
},
["cabinet"] = {
{Name = "bandage", Chance = 25, Amount = {min = 1, max = 2}},
{Name = "painkillers", Chance = 25, Amount = {min = 1, max = 1}},
{Name = "water_bottle", Chance = 25, Amount = {min = 1, max = 2}},
{Name = "joint", Chance = 25, Amount = {min = 1, max = 1}},
},
["closet"] = {
{Name = "diamond", Chance = 25, Amount = {min = 1, max = 1}},
{Name = "rolex", Chance = 25, Amount = {min = 1, max = 1}},
{Name = "iphone", Chance = 25, Amount = {min = 1, max = 1}},
{Name = "samsungphone", Chance = 25, Amount = {min = 1, max = 1}},
},
["kitchen"] = {
{Name = "fitbit", Chance = 25, Amount = {min = 1, max = 1}},
{Name = "screwdriverset", Chance = 25, Amount = {min = 1, max = 2}},
{Name = "bandage", Chance = 25, Amount = {min = 1, max = 2}},
{Name = "plastic", Chance = 25, Amount = {min = 1, max = 1}},
},
},
},
}
```
## Tips for Balancing Tiers
1. **Progressive Difficulty**: Higher tiers should have:
* Higher level requirements
* More armed tenants (`WeaponChance`)
* Lower loot finding chances (`FindingLootChance`)
* More valuable loot in safe rewards
2. **Spawn Chances**: Use spawn chances to create variety:
* Not every robbery needs to have all features
* Lower spawn chances for high-value items create rarity
* Balance risk vs reward with tenant/pet spawn chances
3. **Loot Distribution**: Ensure the count ranges match your configured lootable arrays:
* If `LootableSpots = {1, 2, 3}`, then `SpotCount` max should not exceed 3
* Use empty arrays `{}` for features you want to disable
4. **Experience Points**: Balance XP rewards with difficulty:
* Higher tiers should give more XP
* Consider XP for individual actions (spots, safes) vs completion bonus
5. **Approaches**: Offer multiple approaches for higher tiers to give players options while lower tiers might have limited entry methods
# Installation
Source: https://docs.projectx.gg/resources/house-robbery-v2/installation
Step by step instructions to install the House Robbery V2 resource
## Installation Steps
Verify all dependencies below are started **before** this script in your `server.cfg`.
Download ox\_lib
The following dependencies are required if you want to use the script as is:
Free resource by K4MBI for default shells
Additional shell resources
Free resource by Project X
Free resource by Project X
Download and place in standalone or minigames folder
**bl\_dialog** is included in the minigames zip with modifications for the contracts system.
Make sure they are **not** in the same folder as the robbery script.
Extract the script from the zip file and place it into your scripts folder.
Open `config.lua` and adjust the settings to your liking. Make sure to change the Framework, Inventory, Dispatch, and Target name to match your server setup.
Make sure that the Framework, ox\_lib, Target, Dispatch, Inventory, and Minigames are started before the robbery script.
```cfg theme={null}
ensure ox_lib
ensure projectx-houserobbery
```
## Items Required
### Items Required from Shop/Black Market
* `advancedlockpick`
* `x_burner` (if enabled in config)
* `x_tablet` (if enabled in config)
* `x_device`
* `x_stethoscope`
* `glass_cutter`
* `bag`
The rest of the items are obtained within the robbery. Item images done by [Artwork Inventory](https://discord.gg/Z2awpnXKdw) - Use code **ProjectX** for 10% off!
### Item Configuration
```lua theme={null}
["house_key"] = {
label = "House Key",
weight = 100,
stack = false,
close = false,
description = "To unlock the front door",
},
["x_burner"] = {
label = "Burner Phone",
weight = 100,
stack = false,
close = false,
description = "Nothing suspicious about this phone..",
},
["x_tablet"] = {
label = "X Tablet",
weight = 100,
stack = false,
close = false,
description = "Nothing suspicious about this tablet..",
},
["bag"] = {
label = "Bag",
weight = 400,
stack = false,
close = false,
description = "Duffel bag",
},
["x_stethoscope"] = {
label = "X Stethoscope",
weight = 200,
stack = false,
close = false,
description = "click click",
},
["x_device"] = {
label = "X Device",
weight = 50,
stack = false,
close = false,
description = "?????????",
},
["glass_cutter"] = {
label = "Glass Cutter",
weight = 1000,
stack = false,
close = false,
description = "",
},
["advancedlockpick"] = {
label = "Advanced Lockpick",
weight = 500,
stack = true,
close = true,
description = "If you lose your keys a lot this is very useful... Also useful to open your beers",
},
["x_coffeemaker"] = {
label = "Coffee Maker",
weight = 5000,
stack = true,
close = false,
description = "To make that perfect cup of Joe!",
},
["x_microwave"] = {
label = "Microwave",
weight = 5000,
stack = true,
close = false,
description = "A microwave - for heating things up!",
},
["x_painting"] = {
label = "Painting",
weight = 3000,
stack = true,
close = false,
description = "A beautiful painting - worth a lot!",
},
["x_plush"] = {
label = "Plush Toy",
weight = 100,
stack = true,
close = false,
description = "A cute plush toy",
},
["x_toaster"] = {
label = "Toaster",
weight = 1000,
stack = true,
close = false,
description = "A kitchen toaster",
},
["laptop"] = {
label = "Laptop",
weight = 500,
stack = true,
close = false,
description = "A high-end laptop",
},
["x_printer"] = {
label = "Printer",
weight = 5000,
stack = true,
close = false,
description = "A color printer",
},
["emerald_necklace"] = {
label = "Emerald Necklace",
weight = 200,
stack = true,
close = false,
description = "",
},
['x_goldenknife'] = {
label = "X Golden Knife",
weight = 300,
stack = false,
close = false,
description = "?????????",
},
['x_television'] = {
label = "X Television",
weight = 10000,
stack = false,
close = false,
description = "A high-definition television",
},
["x_watch"] = {
label = "Watch",
weight = 100,
stack = true,
close = false,
description = "Wrist watch",
},
["x_bananatrophy"] = {
label = "Banana Trophy",
weight = 1000,
stack = false,
close = false,
description = "Don't ask..",
},
["x_electricguitar"] = {
label = "Electric Guitar",
weight = 1000,
stack = false,
close = false,
description = "Rock on!",
},
["giant_gem"] = {
label = "Giant Gem",
weight = 500,
stack = false,
close = false,
description = "A huge sparkling gem",
},
```
```lua theme={null}
["house_key"] = {["name"] = "house_key", ["label"] = "House Key", ["weight"] = 100, ["type"] = "item", ["image"] = "house_key.png", ["unique"] = true, ["useable"] = false, ["shouldClose"] = true, ["combinable"] = nil, ["description"] = "To unlock the front door"},
["x_burner"] = {["name"] = "x_burner", ["label"] = "Burner Phone", ["weight"] = 100, ["type"] = "item", ["image"] = "x_burner.png", ["unique"] = true, ["useable"] = false, ["shouldClose"] = true, ["combinable"] = nil, ["description"] = "To receive anonymous calls"},
['x_tablet'] = {['name'] = 'x_tablet', ['label'] = 'X Tablet', ['weight'] = 100, ['type'] = 'item', ['image'] = 'x_tablet.png', ['unique'] = true, ['useable'] = true, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'Nothing suspicious about this tablet..'},
['bag'] = {['name'] = 'bag', ['label'] = 'Bag', ['weight'] = 400, ['type'] = 'item', ['image'] = 'bag.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'Duffel bag'},
['x_stethoscope'] = {['name'] = 'x_stethoscope', ['label'] = 'X Stethoscope', ['weight'] = 200, ['type'] = 'item', ['image'] = 'x_stethoscope.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = "click click"},
['x_device'] = {['name'] = 'x_device', ['label'] = 'X Device', ['weight'] = 50, ['type'] = 'item', ['image'] = 'x_device.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '?????????'},
['glass_cutter'] = {['name'] = 'glass_cutter', ['label'] = 'Glass Cutter', ['weight'] = 1000, ['type'] = 'item', ['image'] = 'glass_cutter.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = ""},
['advancedlockpick'] = {['name'] = 'advancedlockpick', ['label'] = 'Advanced Lockpick', ['weight'] = 500, ['type'] = 'item', ['image'] = 'advancedlockpick.png', ['unique'] = false, ['useable'] = true, ['shouldClose'] = true, ['combinable'] = nil, ['description'] = 'If you lose your keys a lot this is very useful... Also useful to open your beers'},
["x_microwave"] = {["name"] = "microwave", ["label"] = "Microwave", ["weight"] = 5000, ["type"] = "item", ["image"] = "x_microwave.png", ["unique"] = true, ["useable"] = false, ["shouldClose"] = true, ["combinable"] = nil, ["description"] = "Heats things up"},
["x_coffeemaker"] = {["name"] = "x_coffeemaker", ["label"] = "Coffee Machine", ["weight"] = 5000, ["type"] = "item", ["image"] = "x_coffeemaker.png", ["unique"] = true, ["useable"] = false, ["shouldClose"] = true, ["combinable"] = nil, ["description"] = "Makes a delicious expresso"},
["x_painting"] = {["name"] = "x_painting", ["label"] = "Painting", ["weight"] = 3000, ["type"] = "item", ["image"] = "x_painting.png", ["unique"] = true, ["useable"] = false, ["shouldClose"] = true, ["combinable"] = nil, ["description"] = "Just a work of art,"},
["x_plush"] = {["name"] = "x_plush", ["label"] = "Plush Toy", ["weight"] = 100, ["type"] = "item", ["image"] = "x_plush.png", ["unique"] = true, ["useable"] = false, ["shouldClose"] = true, ["combinable"] = nil, ["description"] = "So cute!"},
["x_toaster"] = {["name"] = "x_toaster", ["label"] = "Toaster", ["weight"] = 1000, ["type"] = "item", ["image"] = "x_toaster.png", ["unique"] = true, ["useable"] = false, ["shouldClose"] = true, ["combinable"] = nil, ["description"] = "Toasts bread"},
["laptop"] = {["name"] = "laptop", ["label"] = "Laptop", ["weight"] = 500, ["type"] = "item", ["image"] = "laptop.png", ["unique"] = true, ["useable"] = false, ["shouldClose"] = true, ["combinable"] = nil, ["description"] = "A high-end laptop"},
["x_printer"] = {["name"] = "x_printer", ["label"] = "Printer", ["weight"] = 5000, ["type"] = "item", ["image"] = "x_printer.png", ["unique"] = true, ["useable"] = false, ["shouldClose"] = true, ["combinable"] = nil, ["description"] = "A color printer"},
["emerald_necklace"] = {["name"] = "emerald_necklace", ["label"] = "Emerald Necklace", ["weight"] = 200, ["type"] = "item", ["image"] = "emerald_necklace.png", ["unique"] = true, ["useable"] = false, ["shouldClose"] = true, ["combinable"] = nil, ["description"] = ""},
['x_goldenknife'] = {['name'] = 'x_goldenknife', ['label'] = 'X Golden Knife', ['weight'] = 50, ['type'] = 'item', ['image'] = 'x_goldenknife.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '?????????'},
["x_television"] = {["name"] = "x_television", ["label"] = "X Television", ["weight"] = 10000, ["type"] = "item", ["image"] = "x_television.png", ["unique"] = true, ["useable"] = false, ["shouldClose"] = true, ["combinable"] = nil, ["description"] = "A high-definition television"},
["x_watch"] = {["name"] = "x_watch", ["label"] = "Watch", ["weight"] = 100, ["type"] = "item", ["image"] = "x_watch.png", ["unique"] = true, ["useable"] = false, ["shouldClose"] = true, ["combinable"] = nil, ["description"] = "Wrist watch"},
["x_bananatrophy"] = {["name"] = "x_bananatrophy", ["label"] = "Banana Trophy", ["weight"] = 1000, ["type"] = "item", ["image"] = "x_bananatrophy.png", ["unique"] = true, ["useable"] = false, ["shouldClose"] = true, ["combinable"] = nil, ["description"] = "Don't ask.."},
["x_electricguitar"] = {["name"] = "x_electricguitar", ["label"] = "Electric Guitar", ["weight"] = 1000, ["type"] = "item", ["image"] = "x_electricguitar.png", ["unique"] = true, ["useable"] = false, ["shouldClose"] = true, ["combinable"] = nil, ["description"] = "Rock on!"},
["giant_gem"] = {["name"] = "giant_gem", ["label"] = "Giant Gem", ["weight"] = 500, ["type"] = "item", ["image"] = "giant_gem.png", ["unique"] = true, ["useable"] = false, ["shouldClose"] = true, ["combinable"] = nil, ["description"] = "A huge sparkling gem"},
```
# Commands
Source: https://docs.projectx.gg/resources/laundromat-robbery-k4mb1/commands
Admin commands for the K4MB1 Laundromat Robbery resource
## Admin Commands
**Usage**: `/projectxk4mb1laundromat`
**Permission**: Admin (configurable via `CheckPerms` in the bridge)
**Description**: Forces a full heist reset, unlocking the laundromat and clearing any active robbery state.
**Example**:
```
/projectxk4mb1laundromat
```
This command internally calls the `Reset()` export. See the [Exports](/resources/laundromat-robbery-k4mb1/exports) page for details.
# Configuration
Source: https://docs.projectx.gg/resources/laundromat-robbery-k4mb1/configuration
Full reference for all configuration options in the K4MB1 Laundromat Robbery resource
## config/config.lua
### Main Settings
Shows polyzones created inside the game.
Disables all minigames for flow testing.
Minutes before the heist resets after a completed robbery.
Disables the loud approach path entirely.
Disables the silent approach path entirely.
Requires a `bag` item to collect loot.
Minimum police required online. Set to `0` to disable.
***
### Strike System
Number of strikes players can accumulate before rewards are reduced during the silent approach.
***
### Dispatch
```lua theme={null}
DispatchLocation = {
["Loud"] = true,
["Silent"] = false,
["Key"] = true,
["Button"] = false,
}
```
***
### Keypad Code
Random code range for the keypad password prompt.
***
### Items
```lua theme={null}
Config.Items = {
["Jammer"] = "x_cratejammer",
["Device"] = "x_device",
["Key"] = "laundromatkey",
["Bag"] = "bag",
}
```
Percentage chance the device breaks on use.
***
### Rewards
Cash reward from top-row washing machines (`Cash`, `Item`, `StackAmount`).
Cash reward from bottom-row washing machines.
Large cash pile reward in the back room.
Item rewards per clothing prop (`Clothing1` through `Clothing10`).
***
### Evidence, Stress & Logs
Enables fingerprint evidence drops.
Enables stress on minigame failure.
Logging is configured in `config/logs.lua` (`Enable`, `APIKey`, `FivemanageDataset`).
# Exports
Source: https://docs.projectx.gg/resources/laundromat-robbery-k4mb1/exports
Server-side exports available for the K4MB1 Laundromat Robbery resource
## Server Exports
### Reset
Resets the heist, unlocking the laundromat and clearing any active robbery state.
```lua theme={null}
exports['projectx-laundromatrobbery-k4mb1']:Reset()
```
### IsRobberyInitiated
Returns whether a robbery is currently active.
```lua theme={null}
local active = exports['projectx-laundromatrobbery-k4mb1']:IsRobberyInitiated()
```
**Returns**
* `active` (boolean) - `true` if a robbery is in progress, `false` otherwise
**Example**
```lua theme={null}
local active = exports['projectx-laundromatrobbery-k4mb1']:IsRobberyInitiated()
if active then
print("A robbery is currently in progress")
end
```
# FAQs
Source: https://docs.projectx.gg/resources/laundromat-robbery-k4mb1/faqs
Frequently asked questions about the K4MB1 Laundromat Robbery resource
## General Questions
Yes. See the [Bridge Installation](/resources/bridge/installation) page for setup instructions.
The `laundromatkey` is a progression item obtained outside this robbery — configure it as a bonus from another heist, shop, or custom script.
Only `bl_ui` is required. Install it from [Byte-Labs-Studio/bl\_ui](https://github.com/Byte-Labs-Studio/bl_ui).
Use `/projectxk4mb1laundromat` or call:
```lua theme={null}
exports['projectx-laundromatrobbery-k4mb1']:Reset()
```
Edit `opensource/client/client.lua` — see the [Open Source](/resources/laundromat-robbery-k4mb1/opensource) page for the step-to-minigame table.
## Troubleshooting
Ensure `projectx-bridge`, `ox_lib`, `mka-lasers`, and `bl_ui` are started before `projectx-laundromatrobbery-k4mb1`.
# Installation
Source: https://docs.projectx.gg/resources/laundromat-robbery-k4mb1/installation
Step by step instructions to install the K4MB1 Laundromat Robbery resource
## Installation Steps
Verify all dependencies below are started **before** this script in your `server.cfg`.
Download ox\_lib
Required map by K4MB1
Required minigame resource
Required Project X Bridge
Install `bl_ui` into your standalone or dependencies folder.
Download and place in your standalone or minigames folder
Make sure minigames are **not** in the same folder as the robbery script.
Extract the script from the zip file and place it into your scripts folder.
Add the required items and their images to your inventory resource. See the [items section](#items-required) below for the full list.
Item images done by [Artwork Inventory](https://discord.gg/Z2awpnXKdw) - Use code **ProjectX** for 10% off!
Open `config/config.lua` and adjust the settings to match your server. The bridge handles framework, inventory, dispatch, and interaction automatically if set to `'auto'`.
Make sure the bridge, ox\_lib, your target, dispatch, inventory, minigames, and `mka-lasers` are all started before the robbery script.
```cfg theme={null}
ensure ox_lib
ensure projectx-bridge
ensure mka-lasers
ensure bl_ui
ensure projectx-laundromatrobbery-k4mb1
```
## Items Required
### Items Required from Outside the Robbery
The `laundromatkey` must be obtained externally before the robbery can be started.
* `laundromatkey`
### Items Required from Shop/Black Market
* `x_cratejammer`
* `x_device`
* `bag`
Clothing loot items (`x_shirt`, `x_shirt_pile`, `x_overalls`, `x_towel`, `x_hat`) are obtained within the robbery itself.
### Item Configuration
```lua theme={null}
["x_cratejammer"] = {
label = "X Crate Jammer",
weight = 300,
stack = false,
close = false,
description = "?????????",
},
['x_device'] = {
label = "X Device",
weight = 50,
stack = false,
close = false,
description = "?????????",
},
['bag'] = {
label = "Bag",
weight = 400,
stack = false,
close = false,
description = "Duffel bag",
},
['laundromatkey'] = {
label = "Laundromat Key",
weight = 400,
stack = false,
close = false,
description = "Laundromat Key",
},
['x_shirt'] = {
label = "Shirt",
weight = 200,
stack = false,
close = false,
description = "A Shirt",
},
['x_shirt_pile'] = {
label = "Pile of shirts",
weight = 800,
stack = false,
close = false,
description = "Pile of shirts",
},
['x_overalls'] = {
label = "Overalls",
weight = 200,
stack = false,
close = false,
description = "Overalls",
},
['x_towel'] = {
label = "A Towel",
weight = 200,
stack = false,
close = false,
description = "A Towel",
},
['x_hat'] = {
label = "A Hat",
weight = 200,
stack = false,
close = false,
description = "A Hat",
},
```
```lua theme={null}
['x_cratejammer'] = {['name'] = 'x_cratejammer', ['label'] = 'X Crate Jammer', ['weight'] = 200, ['type'] = 'item', ['image'] = 'x_cratejammer.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'boop beep'},
['x_device'] = {['name'] = 'x_device', ['label'] = 'X Device', ['weight'] = 50, ['type'] = 'item', ['image'] = 'x_device.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '?????????'},
['bag'] = {['name'] = 'bag', ['label'] = 'Bag', ['weight'] = 400, ['type'] = 'item', ['image'] = 'bag.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'Duffel bag'},
['laundromatkey'] = {['name'] = 'laundromatkey', ['label'] = 'Laundromat Key', ['weight'] = 400, ['type'] = 'item', ['image'] = 'laundromatkey.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'Laundromat key'},
['x_shirt'] = {['name'] = 'x_shirt', ['label'] = 'Shirt', ['weight'] = 200, ['type'] = 'item', ['image'] = 'x_shirt.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'A Shirt'},
['x_shirt_pile'] = {['name'] = 'x_shirt_pile', ['label'] = 'Pile of Shirts', ['weight'] = 800, ['type'] = 'item', ['image'] = 'x_shirt_pile.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'Pile of shirts'},
['x_overalls'] = {['name'] = 'x_overalls', ['label'] = 'Overalls', ['weight'] = 200, ['type'] = 'item', ['image'] = 'x_overalls.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'Overalls'},
['x_towel'] = {['name'] = 'x_towel', ['label'] = 'Towel', ['weight'] = 200, ['type'] = 'item', ['image'] = 'x_towel.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'A Towel'},
['x_hat'] = {['name'] = 'x_hat', ['label'] = 'Hat', ['weight'] = 200, ['type'] = 'item', ['image'] = 'x_hat.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'A Hat'},
```
# Open Source
Source: https://docs.projectx.gg/resources/laundromat-robbery-k4mb1/opensource
Open source files available for customization in the K4MB1 Laundromat Robbery resource
## opensource/client/client.lua
Each robbery step triggers the `projectx-laundromatrobbery-k4mb1:client:Minigames` callback with the step name. All default minigames use `bl_ui`.
```lua theme={null}
lib.callback.register('projectx-laundromatrobbery-k4mb1:client:Minigames', function(Step)
local p = promise.new()
if Step == "PlantEMP" then
if not MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:WaveMatch(1, {duration = 30000})
p:resolve(success)
elseif Step == "Keypad" then
if not MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:DigitDazzle(1, {length = 4, duration = 20000})
p:resolve(success)
end
return Citizen.Await(p)
end)
```
You can return `true` unconditionally inside any step block to skip that minigame entirely.
The default minigames per step are:
| Step | Minigame Resource | Function |
| ---------------- | ----------------- | ---------------- |
| `PlantEMP` | `bl_ui` | `WaveMatch` |
| `Clothing` | `bl_ui` | `KeyCircle` |
| `Key` | `bl_ui` | `CircleShake` |
| `WashingMachine` | `bl_ui` | `KeySpam` |
| `Button` | `bl_ui` | `CircleProgress` |
| `Keypad` | `bl_ui` | `DigitDazzle` |
***
## opensource/server/server.lua
### Hooks
Step names are listed in `Config.LaundromatSteps` inside `config/config.lua`.
Called whenever a player fails a robbery step.
Return `false` to block a player from starting the robbery.
Called whenever the heist resets.
# Commands
Source: https://docs.projectx.gg/resources/masks/commands
Player commands for the Masks resource
## Commands
**Usage**: `/removegasmask`
**Description**: Removes the equipped gas mask and returns the item to the player.
**Example**:
```
/removegasmask
```
**Usage**: `/removenightvision`
**Description**: Removes the equipped night vision goggles and returns the item. You must turn night vision and thermal vision off first (using `/togglenightvision` or `/togglethermalvision`).
**Example**:
```
/removenightvision
```
If night vision or thermal vision is still active, the command will fail and show a turn-off message.
**Usage**: `/togglenightvision`
**Description**: Toggles night vision while the goggles are worn. Night vision and thermal vision are mutually exclusive.
**Example**:
```
/togglenightvision
```
**Usage**: `/togglethermalvision`
**Description**: Toggles thermal vision (`SetSeethrough`) while the goggles are worn. Night vision and thermal vision are mutually exclusive.
**Example**:
```
/togglethermalvision
```
# FAQs
Source: https://docs.projectx.gg/resources/masks/faqs
Frequently asked questions about the Masks resource
It provides secure usable items for a **gas mask** (toxic/smoke entity proofs plus mask clothing) and **night vision goggles** (prop plus night vision / thermal toggle). These items are used by Project X crime scripts and can be used standalone.
**Frameworks:** qb-core, qbox, ESX, or custom.
**Inventories:** ox, qs, qb, codem, esx, lj, or ps.
**Notifications:** ox, qb, or esx.
You also need [ox\_lib](https://github.com/CommunityOx/ox_lib/releases/latest) as a dependency.
Using the item again shows the already-wearing message (`WearingMaskMessage` in config). Remove the current mask or goggles with `/removegasmask` or `/removenightvision` first.
You must turn night vision and thermal vision off first with `/togglenightvision` or `/togglethermalvision`, then run `/removenightvision`.
Drawable IDs differ between clothing packs. Update `GasMask.Clothing`, `GasMask.Variation`, and `NightVisionGoggles.Clothing` in `config.lua` to match your pack.
No. Masks uses its own `config.lua` for framework, inventory, and notifications. Bridge is not required.
Join the [Project X Discord](https://discord.gg/projectxdev) and ask in the **#Free-Support** channel.
# Installation
Source: https://docs.projectx.gg/resources/masks/installation
Step by step instructions to install the Masks resource
## Installation Steps
Verify all dependencies below are started **before** this script in your `server.cfg`.
Download ox\_lib
Extract the script from the zip file and place it into your standalone folder or a folder that starts before your scripts.
Add the items below and the images from the `images` folder (`gasmask.png`, `nightvision.png`) to your inventory.
```lua theme={null}
['gasmask'] = {
label = 'Gas Mask',
weight = 450,
stack = false,
close = true,
description = "Phewww..",
client = {
event = 'projectx-masks:client:UseGasMask',
},
},
['nightvision'] = {
label = 'Nightvision Goggles',
weight = 450,
stack = false,
close = true,
description = "Phewww..",
client = {
event = 'projectx-masks:client:UseNightVision',
},
},
```
```lua theme={null}
['gasmask'] = {['name'] = 'gasmask', ['label'] = 'Gas Mask', ['weight'] = 450, ['type'] = 'item', ['image'] = 'gasmask.png', ['unique'] = false, ['useable'] = true, ['shouldClose'] = true, ['combinable'] = nil, ['description'] = "Phewww.."},
['nightvision'] = {['name'] = 'nightvision', ['label'] = 'Nightvision Goggles', ['weight'] = 450, ['type'] = 'item', ['image'] = 'nightvision.png', ['unique'] = true, ['useable'] = true, ['shouldClose'] = true, ['combinable'] = nil, ['description'] = "Phewww.."},
```
The images are provided in the `images` folder that you downloaded. For ox\_inventory, the `client.event` fields are required so using the item triggers the mask/goggles logic.
Open `config.lua` and set your Framework, Inventory, and Notification. See the configuration section below for details.
Make sure ox\_lib is started before the script.
```cfg theme={null}
ensure ox_lib
ensure projectx-masks
```
## Configuration
Below is the configuration file with explanations for each option.
```lua theme={null}
Config = Config or {}
Config = {
Framework = "qb-core", -- "qb-core", "qbox", "esx" or "custom"
Inventory = "ox", -- "ox" or "qs" or "qb" or "codem" or "esx" or "lj" or "ps"
Notification = "ox", -- "ox" or "qb" or "esx"
["GasMask"] = {
["Item"] = "gasmask",
["Clothing"] = 129,
["Variation"] = 1,
},
["NightVisionGoggles"] = {
["Item"] = "nightvision",
["Clothing"] = 119,
},
["NotificationDuration"] = 5000,
}
```
### General Settings
Framework adapter. Options: `"qb-core"`, `"qbox"`, `"esx"`, or `"custom"`.
Inventory adapter. Options: `"ox"`, `"qs"`, `"qb"`, `"codem"`, `"esx"`, `"lj"`, or `"ps"`.
Notification system. Options: `"ox"`, `"qb"`, or `"esx"`.
Duration in milliseconds for notifications.
### Gas Mask
Usable item name for the gas mask.
Ped mask component drawable ID (component slot 1). Adjust if your clothing pack uses different drawables.
Texture variation for the gas mask clothing drawable.
### Night Vision Goggles
Usable item name for the night vision goggles.
Hat/prop index (prop slot 0). When night vision or thermal is active, the script uses `Clothing - 1` for the on state.
Clothing drawable IDs may need adjusting per clothing pack. Equipping the gas mask also applies toxic/smoke entity proofs so the player is protected from gas and smoke effects.
# Commands
Source: https://docs.projectx.gg/resources/sandy-bank-robbery/commands
Admin commands for the Sandy Bank Robbery resource
## Admin Commands
**Usage**: `/projectxsandybank`
**Permission**: Admin (configurable via `CheckPerms` in the bridge)
**Description**: Forces a full heist reset, unlocking the bank and clearing any active robbery state. Useful for testing or recovering from a stuck robbery.
**Example**:
```
/projectxsandybank
```
This command internally calls the `Reset()` export. You can also trigger a reset programmatically from another resource using that export. See the [Exports](/resources/sandy-bank-robbery/exports) page for details.
# Configuration
Source: https://docs.projectx.gg/resources/sandy-bank-robbery/configuration
Full reference for all configuration options in the Sandy Bank Robbery resource
## config/config.lua
### Main Settings
Shows polyzones created inside the game. Useful for testing zone placement.
Disables all minigames. Useful for testing the full robbery flow without completing minigame challenges.
Time in minutes before the bank resets and becomes available to rob again after a completed robbery.
The key code used to trigger drawtext interactions. `38` is `[E]` by default.
The size of the drawtext interaction zone.
The rotation of the drawtext interaction zone.
Disables puzzles that require two players. Enable this to test the script solo.
Disables the loud approach path entirely.
Disables the silent approach path entirely.
Disables all particle effects during the robbery.
Disables damage dealt by lasers in the vault area.
Disables weapon removal during the robbery. Only enable this if you use a weapon wheel resource.
Spawns networked props server side. Set to `false` to spawn them client side instead.
Spawns networked peds server side. Set to `false` to spawn them client side instead.
Requires players to have a `bag` item in order to loot the trolleys.
Minimum number of police required online before the robbery can be started. Set to `0` to disable.
The jobs that count as police for the `MinimumPolice` check and dispatch alerts.
```lua theme={null}
PoliceJobs = {"police", "fbi"}
```
Requires a minimum number of players nearby to start the robbery.
```lua theme={null}
RequiredPlayersNearby = {amount = 0, radius = 20.0}
```
Set `amount` to `0` or `false` to disable.
***
### Cooldowns & Limits
Per-player cooldown in minutes after completing a robbery. Set to `0` to disable.
Maximum number of total robberies allowed per server restart. Set to `0` to disable.
Maximum number of robberies a single player can complete per server restart. Set to `0` to disable.
***
### Strike System
Maximum number of trolleys that can spawn. Actual count depends on the strike system and approach used.
Number of strikes players can accumulate before their reward is cut.
(Silent Approach only) Number of trolleys removed from the reward when the strike limit is reached.
(Loud Approach only) Number of trolleys that spawn during a loud approach.
***
### Skill System
Requires players to meet a minimum level from an integrated XP/skill system before starting the heist. Must have an XP system configured in the bridge.
Minimum level required to initiate the heist. Only applies when `SkillSystem` is `true`.
***
### Dispatch
Title shown in the dispatch alert.
Message body shown in the dispatch alert.
Radio code shown in the dispatch alert.
Time in seconds the dispatch alert remains visible. Not all dispatch systems support this.
Blip settings for the dispatch map marker.
```lua theme={null}
Blip = {
Text = 'Sandy Bank Robbery',
Color = 1,
Sprite = 41,
Scale = 0.8
}
```
Controls which step triggers the dispatch alert. Only one should be enabled at a time.
```lua theme={null}
DispatchLocation = {
["Loud"] = true,
["Silent"] = false,
["ManagerKeypad"] = true,
["Manager"] = false,
["SecurityDoor"] = false,
["SecurityPC"] = false,
["LaptopLasers"] = false,
}
```
***
### Bonus Items
Enables or disables bonus item drops at the end of the heist.
Percentage chance that any bonus item is given at all.
Number of items that can be given from the bonus items table.
Table of possible bonus items. Each entry has a `Name`, `Chance` (%), and `Amount` range.
The total chance across all items needs to add up to 100%.
```lua theme={null}
Items = {
{Name = "x_device", Chance = 30, Amount = {min = 1, max = 1}},
{Name = "x_phone", Chance = 50, Amount = {min = 1, max = 1}},
{Name = "x_stethoscope", Chance = 20, Amount = {min = 1, max = 1}},
}
```
***
### Evidence & Stress
Enables fingerprint evidence drops at the crime scene.
Percentage chance that fingerprint evidence is left behind.
Enables the stress system. Stress is only applied when a minigame is failed.
Percentage chance that stress is applied on a minigame fail.
The minimum and maximum amount of stress applied per failure.
***
### Rewards
Rewards are split into three types: **cash**, **gold**, and **diamond**, each with their own config table. Trolley reward settings (`Config.Rewardcash`, `Config.Rewardgold`, `Config.Rewarddiamond`) and table reward settings (`Config.TableRewardcash`, `Config.TableRewardgold`) follow the same format.
If `true`, items are given per individual cash stack pickup from the trolley. If `false`, the reward is given at the end of the full trolley animation.
Set to `true` to give money directly. Set to `false` to give a cash item instead.
The item name used when `Cash` is `false`.
The minimum and maximum cash or item amount per pickup or per trolley completion.
Optional item metadata. Used if `markedbills` or similar items carry random value data in their info table.
**Drill Reward** (`Config.DrillReward`) uses the same format but controls the reward given when drilling lockboxes.
***
### Logs
Configured in `config/logs.lua`.
Enables or disables the logging system.
Your Discord webhook URL, or your Fivemerr/Fivemanage API key.
The Fivemanage dataset to log activity to. Leave as `"default"` unless you have a specific dataset configured.
# Exports
Source: https://docs.projectx.gg/resources/sandy-bank-robbery/exports
Server-side exports available for the Sandy Bank Robbery resource
## Server Exports
### Reset
Resets the heist, unlocking the bank and clearing any active robbery state. Useful for admin commands or external integrations.
```lua theme={null}
exports['projectx-sandybankrobbery-prompt']:Reset()
```
### IsRobberyInitiated
Returns whether a robbery is currently active.
```lua theme={null}
local active = exports['projectx-sandybankrobbery-prompt']:IsRobberyInitiated()
```
**Returns**
* `active` (boolean) - `true` if a robbery is in progress, `false` otherwise
**Example**
```lua theme={null}
local active = exports['projectx-sandybankrobbery-prompt']:IsRobberyInitiated()
if active then
print("A robbery is currently in progress")
end
```
# FAQs
Source: https://docs.projectx.gg/resources/sandy-bank-robbery/faqs
Frequently asked questions about the Sandy Bank Robbery resource
## General Questions
The script supports QBCore, Qbox, and ESX through the Project X Bridge. Set `Framework` to `'auto'` in the bridge config and it will detect your framework automatically.
Yes. The bridge is required for this script to function. It handles framework detection, inventory, dispatch, notifications, progressbars, XP, evidence, logs, and global cooldowns. See the [Bridge Installation](/resources/bridge/installation) page for setup instructions.
When you purchase Sandy Bank Robbery, the `projectx-bridge` asset is automatically delivered to your CFX portal.
Inventory is handled through the Project X Bridge. Set `Inventory` to `'auto'` in the bridge config for automatic detection. Supported values include ox\_inventory, qb-inventory, ps/lj-inventory, codem-inventory, origen\_inventory, tgiann-inventory, ak47\_inventory, jpr-inventory, one\_inventory, and ESX default inventory. See the [FAQs](/faqs) for the full list with config values and links.
The bridge supports 30+ dispatch systems including PS Dispatch, CodeSign, CodeSign 3D, LB Tablet, FD Dispatch, Wasabi MDT, Oxide Dispatch, VX MDT, Sonoran CAD, and many more. Set `Dispatch` to `'auto'` in the bridge config for automatic detection. See the [FAQs](/faqs) for the full list with config values and links.
Yes. Set `Disable2PlayerPuzzles` to `true` in `config/config.lua` to disable all two-player puzzles. You can then complete the entire robbery alone.
The silent approach is higher risk but offers a higher potential reward. Failing minigames during silent accumulates strikes, which reduce the number of trolleys available at the end. The loud approach is lower risk with a fixed trolley count controlled by `StrikeLoud`, but may trigger dispatch immediately.
Open `opensource/client/client.lua` and find the `projectx-sandybankrobbery-prompt:client:Minigames` callback. Each robbery step has its own `elseif` block where you can swap the minigame export for any resource you prefer. You can also return `true` inside any block to skip that minigame entirely.
```lua theme={null}
elseif step == 'hackserver' then
return true -- Skip this minigame
elseif step == 'drillvault' then
return true -- Skip this minigame
```
See the [Open Source](/resources/sandy-bank-robbery/opensource) page for the full callback code and a table of the default minigame assignments.
Use the `/projectxsandybank` in-game command (requires admin permissions), or call the `Reset()` server export from another resource:
```lua theme={null}
exports['projectx-sandybankrobbery-prompt']:Reset()
```
See the [Commands](/resources/sandy-bank-robbery/commands) and [Exports](/resources/sandy-bank-robbery/exports) pages for more details.
## Configuration Questions
Set `MinimumPolice` to the number you want in `config/config.lua`, and make sure the correct jobs are listed in `PoliceJobs`.
```lua theme={null}
MinimumPolice = 2,
PoliceJobs = {"police", "fbi"},
```
Set `SkillSystem` to `true` and configure `MinimumLevel` in `config/config.lua`. You also need a compatible XP system integrated in the bridge config (`XPSystem`).
Supported systems include `projectx-xp`, `pickle_xp`, `sd-levels`, `cw-rep`, and `OT_skills`. See the [FAQs](/faqs) for bridge XP config values.
Enable `Bonus.Status` and configure the `Bonus.Items` table in `config/config.lua`. Each item has a `Chance` percentage and an `Amount` range.
```lua theme={null}
Bonus = {
Status = true,
BonusChance = 15,
ItemCount = 1,
Items = {
{Name = "x_device", Chance = 30, Amount = {min = 1, max = 1}},
}
}
```
## Troubleshooting
Make sure you have all required dependencies started before the script in your `server.cfg` (`projectx-bridge`, `ox_lib`, minigames).
# Installation
Source: https://docs.projectx.gg/resources/sandy-bank-robbery/installation
Step by step instructions to install the Sandy Bank Robbery resource
## Installation Steps
Verify all dependencies below are started **before** this script in your `server.cfg`.
Download ox\_lib
Required map by Prompt Mods
Required Project X Bridge
Download the minigames zip and place each resource into your standalone or dependencies folder.
Download and place in your standalone or minigames folder
Make sure the minigames are **not** in the same folder as the robbery script.
Extract the script from the zip file and place it into your scripts folder.
Add the required items and their images to your inventory resource. See the [items section](#items-required) below for the full list.
Item images done by [Artwork Inventory](https://discord.gg/Z2awpnXKdw) - Use code **ProjectX** for 10% off!
Open `config/config.lua` and adjust the settings to match your server. The bridge handles framework, inventory, dispatch, and interaction automatically if set to `'auto'`.
Make sure the bridge, ox\_lib, your target, dispatch, inventory, and minigames are all started before the robbery script.
```cfg theme={null}
ensure ox_lib
ensure projectx-bridge
ensure bl_ui
ensure pure-minigames
ensure xdecrypto
ensure projectx-sandybankrobbery-prompt
```
## Items Required
### Items Required from Outside the Robbery
The `sandybank_key` must be obtained externally (e.g. from another robbery or side mission) before the robbery can be started.
* `sandybank_key`
### Items Required from Shop/Black Market
* `x_device`
* `x_phone`
* `x_circuittester`
* `x_breachcharge`
* `x_cyberdeck`
* `hackcard`
* `decryptor`
* `laserdrill`
* `bag`
The rest of the items (`sandybank_security_key`, `managerlaptop`) are obtained within the robbery itself.
### Item Configuration
```lua theme={null}
["sandybank_key"] = {
label = "Sandy Bank Key",
weight = 125,
stack = false,
close = false,
description = "Key!",
},
["sandybank_security_key"] = {
label = "Sandy Bank Security Key",
weight = 125,
stack = false,
close = false,
description = "Key!",
},
["x_device"] = {
label = "X Device",
weight = 125,
stack = false,
close = false,
description = "?????????",
},
["x_phone"] = {
label = "x Phone",
weight = 300,
stack = false,
close = false,
description = "?????????",
},
["x_circuittester"] = {
label = "X Circuit Tester",
weight = 125,
stack = false,
close = false,
description = "?????????",
},
["x_breachcharge"] = {
label = "X Breach Charge",
weight = 125,
stack = false,
close = false,
description = "?????????",
},
["x_cyberdeck"] = {
label = "X Cyberdeck",
weight = 100,
stack = false,
close = false,
description = "Nothing suspicious about this cyberdeck..",
},
["hackcard"] = {
label = "Hackcard",
weight = 50,
stack = false,
close = false,
description = "Hack card",
},
["decryptor"] = {
label = "Decrypt-o-matic",
weight = 300,
stack = false,
close = false,
description = "Decrypt PIN based encryptions",
},
["laserdrill"] = {
label = "Laser Drill",
weight = 1000,
stack = false,
close = false,
description = "",
},
["bag"] = {
label = "Duffel Bag",
weight = 250,
stack = false,
close = false,
description = "Duffel bag",
},
["managerlaptop"] = {
label = "Manager Laptop",
weight = 250,
stack = false,
close = false,
description = "Manager's Laptop",
},
```
```lua theme={null}
['sandybank_key'] = {['name'] = 'sandybank_key', ['label'] = 'Sandy Bank Key', ['weight'] = 50, ['type'] = 'item', ['image'] = 'sandybank_key.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'Key!'},
['sandybank_security_key'] = {['name'] = 'sandybank_security_key', ['label'] = 'Sandy Bank Security Key', ['weight'] = 50, ['type'] = 'item', ['image'] = 'sandybank_security_key.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'Key!'},
['x_device'] = {['name'] = 'x_device', ['label'] = 'X Device', ['weight'] = 50, ['type'] = 'item', ['image'] = 'x_device.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '?????????'},
['x_phone'] = {['name'] = 'x_phone', ['label'] = 'X Phone', ['weight'] = 50, ['type'] = 'item', ['image'] = 'x_phone.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '?????????'},
['x_circuittester'] = {['name'] = 'x_circuittester', ['label'] = 'X Circuit Tester', ['weight'] = 200, ['type'] = 'item', ['image'] = 'x_circuittester.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '????'},
['x_breachcharge'] = {['name'] = 'x_breachcharge', ['label'] = 'X Breach Charge', ['weight'] = 200, ['type'] = 'item', ['image'] = 'x_breachcharge.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '????'},
['x_cyberdeck'] = {['name'] = 'x_cyberdeck', ['label'] = 'X Cyberdeck', ['weight'] = 100, ['type'] = 'item', ['image'] = 'x_cyberdeck.png', ['unique'] = true, ['useable'] = true, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'Nothing suspicious about this cyberdeck..'},
['hackcard'] = {['name'] = 'hackcard', ['label'] = 'hackcard', ['weight'] = 50, ['type'] = 'item', ['image'] = 'hackcard.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'Hack card'},
['decryptor'] = {['name'] = 'decryptor', ['label'] = 'decryptor', ['weight'] = 750, ['type'] = 'item', ['image'] = 'decryptomatic.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'Decyrptomatic'},
['laserdrill'] = {['name'] = 'laserdrill', ['label'] = 'Laser Drill', ['weight'] = 7500, ['type'] = 'item', ['image'] = 'laserdrill.png', ['unique'] = true, ['useable'] = true, ['shouldClose'] = true, ['combinable'] = nil, ['description'] = 'Laser Drill'},
['bag'] = {['name'] = 'bag', ['label'] = 'Bag', ['weight'] = 400, ['type'] = 'item', ['image'] = 'bag.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'Duffel bag'},
['managerlaptop'] = {['name'] = 'managerlaptop', ['label'] = 'Manager Laptop', ['weight'] = 750, ['type'] = 'item', ['image'] = 'managerlaptop.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = "Manager's Laptop"},
```
# Open Source
Source: https://docs.projectx.gg/resources/sandy-bank-robbery/opensource
Open source files available for customization in the Sandy Bank Robbery resource
Most of the core logic in this resource is handled by the bridge. The open source files are provided so you can customize minigames, add hooks for custom systems, and extend the script without touching escrow.
## opensource/client/client.lua
This file handles zone creation, drawtext, evidence, stress, and most importantly, the minigame callback. If you want to change the minigames used for each step, this is the only file you need to edit.
### Minigame Callback
Each robbery step triggers the `projectx-sandybankrobbery-prompt:client:Minigames` callback with the step name. You can swap any minigame by replacing the export call inside the matching `elseif` block.
```lua theme={null}
lib.callback.register('projectx-sandybankrobbery-prompt:client:Minigames', function(Step)
local p = promise.new()
if Step == "BackdoorKeypad" then
local success = exports["bl_ui"]:PrintLock(1, {grid = 5, duration = 15000, target = 5})
p:resolve(success)
elseif Step == "PlantBreachFuse" then
local success = exports["bl_ui"]:CircleProgress(3, 50)
p:resolve(success)
elseif Step == "ManagerKeypad" then
local gameData = {totalNumbers = 20, seconds = 20, timesToChangeNumbers = 4, amountOfGames = 1, incrementByAmount = 5}
local success = exports['pure-minigames']:numberCounter(gameData)
p:resolve(success)
elseif Step == "OfficeComputer" then
local success = exports["bl_ui"]:RapidLines(3, 50, 5)
p:resolve(success)
elseif Step == "GeneralComputer" then
local success = exports["bl_ui"]:MineSweeper(3, {grid = 7, duration = 10000, target = 10, previewDuration = 2000})
p:resolve(success)
elseif Step == "CodeComputer" then
local success = exports["bl_ui"]:Untangle(1, {numberOfNodes = 10, duration = 15000})
p:resolve(success)
elseif Step == "SecurityDoor" then
local success = exports["bl_ui"]:KeySpam(2, 50)
p:resolve(success)
elseif Step == "BreachServer" then
local success = exports["bl_ui"]:WaveMatch(1, {duration = 30000})
p:resolve(success)
elseif Step == "JamServers" then
local success = exports["bl_ui"]:KeySpam(2, 50)
p:resolve(success)
elseif Step == "LaptopVault" then
local success = exports["bl_ui"]:RapidLines(3, 50, 5)
p:resolve(success)
elseif Step == "SecurityPC" then
exports['xdecrypto']:StartHack(function(success)
p:resolve(success)
end)
elseif Step == "PickupLaptop" then
local success = exports["bl_ui"]:CircleProgress(4, 50)
p:resolve(success)
elseif Step == "LaptopPutDown" then
p:resolve(true)
elseif Step == "LaptopLasers" then
local success = exports["bl_ui"]:PathFind(1, {numberOfNodes = 10, duration = 7500})
p:resolve(success)
elseif Step == "Drill" then
local success = exports["bl_ui"]:CircleShake(1, 50, 2)
p:resolve(success)
end
return Citizen.Await(p)
end)
```
You can return `true` unconditionally inside any step block to skip that minigame entirely. This can be useful for testing or for steps you want to make automatic.
The default minigames per step are:
| Step | Minigame Resource | Function |
| ----------------- | ----------------- | ---------------- |
| `BackdoorKeypad` | `bl_ui` | `PrintLock` |
| `PlantBreachFuse` | `bl_ui` | `CircleProgress` |
| `ManagerKeypad` | `pure-minigames` | `numberCounter` |
| `OfficeComputer` | `bl_ui` | `RapidLines` |
| `GeneralComputer` | `bl_ui` | `MineSweeper` |
| `CodeComputer` | `bl_ui` | `Untangle` |
| `SecurityDoor` | `bl_ui` | `KeySpam` |
| `BreachServer` | `bl_ui` | `WaveMatch` |
| `JamServers` | `bl_ui` | `KeySpam` |
| `LaptopVault` | `bl_ui` | `RapidLines` |
| `SecurityPC` | `xdecrypto` | `StartHack` |
| `PickupLaptop` | `bl_ui` | `CircleProgress` |
| `LaptopLasers` | `bl_ui` | `PathFind` |
| `Drill` | `bl_ui` | `CircleShake` |
***
## opensource/server/server.lua
This file handles dispatch, item/money functions, logging, and exposes several hooks you can use to run custom logic at specific points in the robbery.
### Hooks
Called whenever a player successfully completes a robbery step. Use this to award XP, trigger events, or log individual step completions.
```lua theme={null}
function SuccessfulStep(source, step)
if step == "BackdoorKeypad" then
-- exports['projectx-bridge']:AddExperience(source, 'criminal', 10)
elseif step == "ManagerKeypad" then
-- exports['projectx-bridge']:AddExperience(source, 'criminal', 10)
end
end
```
All available step names can be found in `Config.SandyBankSteps` inside `config/config.lua`.
Called whenever a player fails a robbery step. Use this to remove XP, items, or apply penalties.
```lua theme={null}
function FailedStep(source, step)
if step == "BackdoorKeypad" then
-- RemoveItem(source, 'hackcard', 1)
end
end
```
Called before a player can start the robbery. Return `false` to block them.
```lua theme={null}
function InitialCheck(Interaction)
return true
-- Add a group check, tablet requirement, or any other gate here
end
```
Called whenever the heist resets. Use this to update a scoreboard, trigger an external event, or notify players.
```lua theme={null}
function RobberyResetHook()
-- TriggerEvent('my-scoreboard:update')
end
```
# Configuration
Source: https://docs.projectx.gg/resources/sellshop/configuration
Full reference for configuration options in the Sellshop resource
## config/config.lua
### Global Settings
Shows polyzones created in-game. Useful when testing shop interaction zones.
Locale file to use (e.g. `'en'`). Matching locale files live under `locales/`.
Framework adapter. Options: `'auto'`, `'qb'`, `'qbox'`, `'esx'`, or `'custom'`. Custom requires editing stubs in `opensource/client` and `opensource/server`.
ESX version when using ESX. Options: `"new"` or `"old"`.
Inventory adapter. Options: `"auto"`, `"ox"`, `"qb"`, `"origen"`, `"tgiann"`, `"esx"`, `"lj"`, `"ps"`, `"codem"`, or `"custom"`.
Notification system. Options: `"ox"`, `"qb"`, `"esx"`, or `"custom"`.
Progress bar system. Options: `"ox"`, `"qb"`, or `"custom"`.
Ox progress bar style only. Options: `"circle"` or `"bar"`.
Dispatch settings for suspicious sales. `Resource` can be `'auto'` or a supported dispatch name; set to `"other"` / custom and edit opensource if unsupported.
```lua theme={null}
Dispatch = {
Resource = 'auto',
Title = 'Suspicious Sale',
Message = 'A Suspicious sale was made',
Code = '10-69',
Blip = {
Text = 'Suspicious Sale',
Color = 1,
Sprite = 69,
Scale = 0.8
}
}
```
Interaction system. Options: `'auto'`, `'ox_target'`, `'qb-target'`, `'drawtext'`, or `'worldinteract'` ([interact](https://github.com/darktrovx/interact)).
Key code for drawtext interactions. `38` is `[E]` by default.
Drawtext UI style. Options: `"OLDQB"`, `"QB"`, or `"OX"`.
Currency symbol shown in the sell menu UI.
Path to inventory item images. `"auto"` detects common inventory image folders.
Jobs counted for `PoliceCount` checks and dispatch alerts.
```lua theme={null}
PoliceJobs = {["police"] = true, ["fbi"] = true}
```
Enable XP awards on sell when items define an `Exp` field.
When `true`, XP is granted via the client `AddExp` event. When `false`, the server `AddExp` opensource hook runs (default pickle\_xp).
Optional sell progress bar and animation.
```lua theme={null}
ProgressbarConfig = {
Enable = false,
Duration = 2000,
Text = 'Selling...',
Animation = {
Enable = true,
NPCSync = true,
Dict = 'mp_common',
Anim = 'givetake1_b',
}
}
```
When `true`, shop coordinates are read from `config/sv_config.lua` (`Locations`) instead of client config — useful to protect coords from dumpers.
Table of shop definitions keyed by shop id (e.g. `'pawnshop'`, `'suspiciousbuyer'`). See structure below.
***
## Shop Structure
Each entry in `Config.Shops` is a full shop. Concise example:
```lua theme={null}
['myshop'] = {
["MenuTitle"] = 'My Shop',
["TargetIcon"] = 'fas fa-dollar-sign',
["TargetText"] = 'Sell Products',
["TargetSize"] = 1.5,
["TargetDistance"] = 1.0,
["OnlyShowItemsInInventory"] = false,
["Coords"] = vec4(412.15, 315.22, 102.13, 210.65),
-- Or an array of vec4 for a random spawn location:
-- ["Coords"] = { vec4(...), vec4(...) },
["Ped"] = {
Enable = false,
Model = `a_m_m_business_01`,
-- IdleAnimation, SuccessfulAnimation, PedSuccessfulAnimation...
},
["TimeFrame"] = {
Enable = true,
Time = {open = 9, close = 22},
},
["PoliceCount"] = 0,
["Blip"] = {
Enable = true,
Text = "My Shop",
Sprite = 605,
Color = 0,
Scale = 0.8,
},
["Items"] = {
['goldbar'] = {
Label = "Gold Bar",
Price = 100,
-- DispatchChance = 60,
-- ["DisableMoney"] = false,
-- ["DirtyMoney"] = { Enable = true, Item = "black_money", MetaData = false },
-- ["ItemReward"] = { Enable = true, Item = "pawnshopcoin", Amount = 1 },
-- ["Volume"] = { Enable = true, AmountUntilDropInPrice = 10, DropInPrice = 10 },
-- ["Exp"] = 5,
},
},
["BulkSale"] = {
Enable = false,
BulkAmount = 10,
ExtraCash = 10, -- % bonus cash when selling BulkAmount or more
},
}
```
| Field | Purpose |
| --------------------------- | ---------------------------------------------------------------------------------------------------------- |
| `MenuTitle` / target fields | Menu title, icon, text, size, distance; `OnlyShowItemsInInventory` filters the menu |
| `Coords` | Single `vec4` or array of `vec4` (one random location) |
| `Ped` | Optional NPC: model, idle/success animations (`AdvancedAnimation` uses a fixed give/take when enabled) |
| `TimeFrame` | Open/close hours; closed shops notify on interact |
| `PoliceCount` | Minimum police online to use the shop |
| `Blip` | Map blip settings |
| `Items` | Sellables: `Price`, optional `DirtyMoney`, `ItemReward`, `Volume`, `Exp`, `DispatchChance`, `DisableMoney` |
| `BulkSale` | Extra cash % when selling at least `BulkAmount` of an item |
***
## presets/
Use `LoadPreset(name, data)` in files under `presets/` to add or overwrite shops in `Config.Shops`. The built-in `"example"` preset name is skipped by design — rename your preset when copying it.
***
## config/sv\_config.lua
When `ServerCoords = true`, define locations here:
```lua theme={null}
Locations = {
['pawnshop'] = vec4(412.15, 315.22, 102.13, 210.65),
['suspiciousbuyer'] = {
vec4(259.51, 2584.91, 43.95, 9.83),
vec4(1915.52, 3735.22, 31.64, 206.85),
},
}
```
***
## config/logs.lua
Optional sale logging:
Enable or disable logging.
Logging service: `"discord"`, `"fivemerr"`, `"fivemanage"`, or `"custom"` (edit opensource server hooks).
Discord webhook URL or Fivemerr/Fivemanage API key.
# FAQs
Source: https://docs.projectx.gg/resources/sellshop/faqs
Frequently asked questions about the Sellshop resource
A configurable multi-shop sell system. Players sell items at NPC/target/drawtext shops for cash, dirty money, and/or item rewards. Supports time windows, police requirements, dispatch on suspicious sales, volume price drops, bulk bonuses, and optional XP.
Framework: `'auto'`, `'qb'`, `'qbox'`, `'esx'`, or `'custom'`.
Inventory, notification, progress bar, interaction, and dispatch are also configurable (including `'auto'` where available). Custom adapters use the stubs in `opensource/client` and `opensource/server`.
No. Sellshop uses its own `config/config.lua` for framework, inventory, dispatch, and interaction. Bridge is not required.
Check `TimeFrame` (open/close hours) and `PoliceCount` on that shop. Closed hours and too few online police each block access and show a notification.
Set `UseXP = true`. Items can define `["Exp"] = 5` (XP per unit sold). By default, server `AddExp` in `opensource/server/server.lua` calls pickle\_xp when started.
To use **projectx-xp**, change `AddExp` to something like:
```lua theme={null}
exports['projectx-xp']:AddXP(source, 'criminal', exp)
-- or via bridge:
-- exports['projectx-bridge']:AddExperience(source, 'criminal', exp)
```
Set `ClientSideXP = true` only if you intentionally grant XP from the client event hook instead.
Per item, enable `DirtyMoney` (e.g. `black_money`) to pay in dirty money instead of cash. Use `ItemReward` to give an extra item (or set `DisableMoney = true` for item-only payouts).
Enable `Volume` on an item: after `AmountUntilDropInPrice` units are sold, the price drops by `DropInPrice` percent.
Yes. Set `Coords` to an array of `vec4` values — one location is chosen (especially useful with suspicious buyers). With `ServerCoords = true`, put the same array under that shop id in `config/sv_config.lua`.
Join the [Project X Discord](https://discord.gg/projectxdev) and ask in the **#Free-Support** channel.
# Installation
Source: https://docs.projectx.gg/resources/sellshop/installation
Step by step instructions to install the Sellshop resource
## Installation Steps
Verify all dependencies below are started **before** this script in your `server.cfg`.
Download ox\_lib
You also need a framework, inventory, interaction system (target/drawtext/interact), and optionally a dispatch resource. Free dispatch suggestions: [ps-dispatch](https://github.com/Project-Sloth/ps-dispatch) (QB/QBOX) or [linden\_outlawalert](https://github.com/thelindat/linden_outlawalert) (ESX).
Extract the script from the zip file and place it into your scripts folder.
Open `config/config.lua` and set **Framework**, **Inventory**, **Dispatch**, and **Interaction** for your server. Full option reference is on the [Configuration](/resources/sellshop/configuration) page.
Start order matters: Framework → ox\_lib → Interaction → Dispatch → Inventory → then sellshop.
```cfg theme={null}
ensure ox_lib
ensure projectx-sellshop
```
## Notes
* There are **no mandatory items** to install. Add sellable items (and any reward items like dirty money or shop coins) to your inventory as needed for the shops you enable.
* Shop presets live in `presets/*.lua` and are loaded via `LoadPreset`. See [Configuration](/resources/sellshop/configuration).
* Optional: set `ServerCoords = true` and define shop locations in `config/sv_config.lua` to keep coords server-side (anti-dump).
* Optional XP: set `UseXP = true` and wire `AddExp` in `opensource/server/server.lua` (defaults to pickle\_xp; can call `projectx-xp` or bridge `AddExperience`).
# Commands
Source: https://docs.projectx.gg/resources/store-robbery-default/commands
Admin commands for the Default Store Robbery resource
## Admin Commands
**Usage**: `/projectxstore`
**Permission**: Admin (configurable via `CheckPerms` in the bridge)
**Description**: Resets the nearest store within 50 units of your position. Useful for testing or recovering from a stuck robbery.
**Example**:
```
/projectxstore
```
This command resets the closest store location automatically. To reset a specific store programmatically, use the `Reset(location)` export instead. See the [Exports](/resources/store-robbery-default/exports) page for details.
# Configuration
Source: https://docs.projectx.gg/resources/store-robbery-default/configuration
Full reference for all configuration options in the Default Store Robbery resource
## config/config.lua
### Main Settings
Shows polyzones created inside the game. Useful for testing zone placement.
Disables all minigames. Useful for testing the full robbery flow without completing minigame challenges.
The key code used to trigger drawtext interactions. `38` is `[E]` by default.
The size of the drawtext interaction zone.
The default rotation of the drawtext interaction zone. Individual stores can override this in `Config.Stores`.
Spawns networked props server side. Set to `false` to spawn them client side instead.
Spawns networked peds server side. Set to `false` to spawn them client side instead.
Minimum number of police required online before a robbery can be started. Set to `0` to disable.
The jobs that count as police for the `MinimumPolice` check and dispatch alerts.
```lua theme={null}
PoliceJobs = {"police", "fbi"}
```
Requires a minimum number of players nearby to start a robbery.
```lua theme={null}
RequiredPlayersNearby = {amount = 0, radius = 20.0}
```
Set `amount` to `0` or `false` to disable.
Maximum number of store robberies that can be active at the same time. Set to `0` to disable.
Disables the loud approach path entirely.
Disables the silent approach path entirely.
Disables all particle effects during robberies.
Disables weapon removal during robberies. Only enable this if you use a weapon wheel resource.
***
### Cooldowns & Limits
When `true`, robbing one store puts all stores on cooldown. When `false`, each store has its own cooldown.
Cooldown duration in minutes.
Per-player cooldown in minutes after completing a robbery. Set to `0` to disable.
Maximum robberies per server restart, split by store type. Set each value to `0` to disable.
```lua theme={null}
TotalRobberiesPerRestart = {
['Stores247'] = 0,
['GasStations'] = 0,
['LiquorStores'] = 0,
}
```
Maximum robberies a single player can complete per restart, split by store type. Set each value to `0` to disable.
```lua theme={null}
RobberiesPerPlayer = {
['Stores247'] = 0,
['GasStations'] = 0,
['LiquorStores'] = 0,
}
```
***
### Skill System
Requires players to meet a minimum level from an integrated XP/skill system before starting a robbery. Must have an XP system configured in the bridge.
Minimum level required to initiate a robbery. Only applies when `SkillSystem` is `true`.
***
### Dispatch
Title shown in the dispatch alert.
Message body shown in the dispatch alert.
Radio code shown in the dispatch alert.
Time in seconds the dispatch alert remains visible. Not all dispatch systems support this.
Blip settings for the dispatch map marker.
```lua theme={null}
Blip = {
Text = 'Store Robbery',
Color = 1,
Sprite = 41,
Scale = 0.8
}
```
Controls which steps trigger dispatch alerts. `Loud` and `Silent` can be enabled independently.
```lua theme={null}
DispatchLocation = {
["Loud"] = true,
["Silent"] = false,
["Register"] = false,
["Atm"] = true,
}
```
***
### Bonus Items
Enables or disables bonus item drops at the end of a robbery.
Percentage chance that any bonus item is given at all.
Number of items that can be given from the bonus items table.
Table of possible bonus items. Each entry has a `Name`, `Chance` (%), and `Amount` range.
The total chance across all items needs to add up to 100%.
```lua theme={null}
Items = {
{Name = "x_device", Chance = 30, Amount = {min = 1, max = 1}},
{Name = "x_phone", Chance = 50, Amount = {min = 1, max = 1}},
{Name = "x_stethoscope", Chance = 20, Amount = {min = 1, max = 1}},
}
```
***
### Evidence & Stress
Enables fingerprint evidence drops at the crime scene.
Percentage chance that fingerprint evidence is left behind.
Enables the stress system. Stress is only applied when a minigame is failed.
Percentage chance that stress is applied on a minigame fail.
The minimum and maximum amount of stress applied per failure.
***
### Required Items
Maps logical item names to your inventory item names.
```lua theme={null}
Items = {
["Circuit"] = "x_circuittester",
["Lockpick"] = "advancedlockpick",
["Harddrive"] = "x_harddrive",
["Device"] = "x_device",
["Key"] = "storekey",
}
```
Break chance (%) for each item when used during a robbery.
```lua theme={null}
ItemsBreak = {
["Circuit"] = 0,
["Lockpick"] = 0,
["Device"] = 0,
}
```
***
### Rewards
Register, ATM, and safe rewards are configured per store type. Each table follows the same format.
Set to `true` to give money directly. Set to `false` to give a cash item instead.
The item name used when `Cash` is `false`.
The minimum and maximum cash or item amount per reward.
```lua theme={null}
StackAmount = {min = 3000, max = 6000}
```
Optional item metadata. Used if `markedbills` or similar items carry random value data in their info table.
**Reward tables by store type:**
| Table | Description |
| ----------------------------- | --------------------------------------------- |
| `Config.RegisterStores247` | Register loot from 24/7 stores |
| `Config.RegisterGasStations` | Register loot from gas stations |
| `Config.RegisterLiquorStores` | Register loot from liquor stores |
| `Config.AtmStores247` | ATM loot from 24/7 stores |
| `Config.AtmGasStations` | ATM loot from gas stations |
| `Config.SafeStores247` | Safe loot from 24/7 stores (uncorrupted data) |
| `Config.SafeCorruptStores247` | Safe loot from 24/7 stores (corrupted data) |
| `Config.SafeGasStations` | Safe loot from gas stations |
| `Config.SafeLiquorStores` | Safe loot from liquor stores |
**Shelf loot** is configured in `Config.RewardShelf`. `Config.MaxItems` controls how many items can be taken from each shelf.
***
### Store Locations
Enable or disable store types and individual locations using these tables:
* `Config.Stores247` — 24/7 supermarkets (9 locations, default GTA interiors)
* `Config.GasStations` — Gas stations (5 locations)
* `Config.LiquorStores` — Liquor stores (5 locations)
Each enabled location has a full entry in `Config.Stores` with coordinates, interactions, NPC settings, reset timers, and per-store overrides. Use the store key (e.g. `"Strawberry"`, `"Davis"`) when calling exports.
No custom map is required. This variant uses default GTA store interiors. You can add custom store locations by copying an existing entry in `Config.Stores` and adjusting the coordinates and interaction zones.
***
### Other Settings
Controls the safe code range and UI text for the office computer step.
How long the alarm lasts in minutes.
Weapons allowed for threatening the clerk during the loud approach. Add or remove weapon hashes as needed.
**Step durations** (`FuseboxDuration`, `RegisterDuration`, `ServerDuration`, etc.) control how long progress bars run for each interaction step.
***
### Logs
Configured in `config/logs.lua`.
Enables or disables the logging system.
Your Discord webhook URL, or your Fivemerr/Fivemanage API key.
The Fivemanage dataset to log activity to. Leave as `"default"` unless you have a specific dataset configured.
# Exports
Source: https://docs.projectx.gg/resources/store-robbery-default/exports
Server-side exports available for the Default Store Robbery resource
## Server Exports
All exports require a valid store location key from `Config.Stores` (e.g. `"Strawberry"`, `"Davis"`, `"VespucciCanals"`).
### Reset
Resets the robbery at the given location, clearing active state and restoring the store.
```lua theme={null}
exports['projectx-storerobbery-default']:Reset('Strawberry')
```
**Returns**
* `true` if the location exists and was reset successfully
***
### IsRobberyInProgress
Returns whether a robbery is currently active at the given location.
```lua theme={null}
local active = exports['projectx-storerobbery-default']:IsRobberyInProgress('Strawberry')
```
**Returns**
* `true` if a robbery is in progress at that location, `false` otherwise
**Example**
```lua theme={null}
local active = exports['projectx-storerobbery-default']:IsRobberyInProgress('Davis')
if active then
print("Davis gas station is being robbed")
end
```
***
### GetActiveRobberyCount
Returns the total number of active store robberies across all locations.
```lua theme={null}
local count = exports['projectx-storerobbery-default']:GetActiveRobberyCount()
```
**Returns**
* `count` (number) — total active robberies
**Example**
```lua theme={null}
local count = exports['projectx-storerobbery-default']:GetActiveRobberyCount()
print("Active store robberies: " .. count)
```
# FAQs
Source: https://docs.projectx.gg/resources/store-robbery-default/faqs
Frequently asked questions about the Default Store Robbery resource
## General Questions
The script supports QBCore, Qbox, and ESX through the Project X Bridge. Set `Framework` to `'auto'` in the bridge config and it will detect your framework automatically.
Yes. The bridge is required for this script to function. It handles framework detection, inventory, dispatch, notifications, progressbars, XP, evidence, logs, and global cooldowns. See the [Bridge Installation](/resources/bridge/installation) page for setup instructions.
When you purchase Default Store Robbery, the `projectx-bridge` asset is automatically delivered to your CFX portal.
No. This variant uses default GTA store interiors and does not require a paid map pack. Install only `ox_lib`, `projectx-bridge`, and the minigame resources listed on the [Installation](/resources/store-robbery-default/installation) page.
The bridge supports 25+ dispatch systems including PS Dispatch, CodeSign, LB Tablet, FD Dispatch, Wasabi MDT, Sonoran CAD, and many more. Set `Dispatch` to `'auto'` in the bridge config for automatic detection. See the [Bridge Overview](/resources/bridge/overview) for the full list.
The script supports three store types with tier-based loot:
* **24/7 Supermarkets** — 9 locations (default GTA interiors)
* **Gas Stations** — 5 locations
* **Liquor Stores** — 5 locations
Enable or disable individual locations in `Config.Stores247`, `Config.GasStations`, and `Config.LiquorStores`.
The **loud approach** involves threatening the clerk with an allowed weapon. Dispatch can trigger immediately when the loud approach begins.
The **silent approach** bypasses the clerk and focuses on hacking, lockpicking, and stealth interactions. Dispatch timing is controlled by `DispatchLocation` in `config/config.lua`.
Open `opensource/client/client.lua` and find the `projectx-storerobbery-default:client:Minigames` callback. Each robbery step has its own `elseif` block where you can swap the minigame export for any resource you prefer. You can also return `true` inside any block to skip that minigame entirely.
See the [Open Source](/resources/store-robbery-default/opensource) page for the full callback code and a table of the default minigame assignments.
Use the `/projectxstore` in-game command (requires admin permissions) to reset the nearest store, or call the `Reset(location)` server export from another resource:
```lua theme={null}
exports['projectx-storerobbery-default']:Reset('Strawberry')
```
See the [Commands](/resources/store-robbery-default/commands) and [Exports](/resources/store-robbery-default/exports) pages for more details.
## Configuration Questions
Set `MinimumPolice` to the number you want in `config/config.lua`, and make sure the correct jobs are listed in `PoliceJobs`.
```lua theme={null}
MinimumPolice = 2,
PoliceJobs = {"police", "fbi"},
```
Set `SkillSystem` to `true` and configure `MinimumLevel` in `config/config.lua`. You also need a compatible XP system integrated in the bridge config (`XPSystem`).
Supported systems include `pickle_xp`, `sd-levels`, `cw-rep`, and `OT_skills`.
Enable `Bonus.Status` and configure the `Bonus.Items` table in `config/config.lua`. Each item has a `Chance` percentage and an `Amount` range.
```lua theme={null}
Bonus = {
Status = true,
BonusChance = 15,
ItemCount = 1,
Items = {
{Name = "x_device", Chance = 30, Amount = {min = 1, max = 1}},
}
}
```
Set `Cooldown.Global` to `true` to lock all stores when one is robbed. Set it to `false` for individual per-store cooldowns. Adjust the duration with `Cooldown.Timer` (in minutes).
Copy an existing entry in `Config.Stores`, rename the key, and update the coordinates and interaction zones. Enable it in the matching store type table (`Config.Stores247`, `Config.GasStations`, or `Config.LiquorStores`).
## Troubleshooting
Make sure you have all required dependencies started before the script in your `server.cfg` (`projectx-bridge`, `ox_lib`, and minigames).
Verify all minigame resources (`bl_ui`, `pure-minigames`, `SN-Hacking`, `pd-safe`) are started and placed outside the robbery script folder. The bridge's `MinigameCheck` will return `false` if a minigame resource is missing.
This variant is configured for default GTA store interiors. If you use a custom map MLO at a store location, copy the matching `Config.Stores` entry and adjust the coordinates and interaction zones for your map.
# Installation
Source: https://docs.projectx.gg/resources/store-robbery-default/installation
Step by step instructions to install the Default Store Robbery resource
## Installation Steps
Verify all dependencies below are started **before** this script in your `server.cfg`.
Download ox\_lib
Required Project X Bridge
No custom map is required. This variant uses default GTA store interiors.
Download the minigames zip and place each resource into your standalone or dependencies folder.
Download and place in your standalone or minigames folder
Make sure the minigames are **not** in the same folder as the robbery script.
Extract the script from the zip file and place it into your scripts folder.
Add the required items and their images to your inventory resource. See the [items section](#items-required) below for the full list.
Item images done by [Artwork Inventory](https://discord.gg/Z2awpnXKdw) - Use code **ProjectX** for 10% off!
Open `config/config.lua` and adjust the settings to match your server. The bridge handles framework, inventory, dispatch, and interaction automatically if set to `'auto'`.
Make sure the bridge, ox\_lib, your target, dispatch, inventory, and minigames are all started before the robbery script.
```cfg theme={null}
ensure ox_lib
ensure projectx-bridge
ensure bl_ui
ensure pure-minigames
ensure SN-Hacking
ensure pd-safe
ensure projectx-storerobbery-default
```
## Items Required
### Items Required from Outside the Robbery
The `x_harddrive` must be obtained externally (e.g. from another robbery or side mission) before a store robbery can be started.
* `x_harddrive`
### Items Required from Shop/Black Market
* `x_device`
* `x_circuittester`
* `storekey`
* `advancedlockpick`
The rest of the items are obtained within the robbery itself.
### Item Configuration
```lua theme={null}
["x_device"] = {
label = "X Device",
weight = 125,
stack = false,
close = false,
description = "?????????",
},
["x_circuittester"] = {
label = "X Circuit Tester",
weight = 125,
stack = false,
close = false,
description = "?????????",
},
["x_harddrive"] = {
label = "X Harddrive",
weight = 125,
stack = false,
close = false,
description = "?????????",
},
["storekey"] = {
label = "Store Key",
weight = 125,
stack = false,
close = false,
description = "?????????",
},
["advancedlockpick"] = {
label = "Advanced Lockpick",
weight = 500,
stack = true,
close = true,
description = "If you lose your keys a lot this is very useful... Also useful to open your beers",
},
```
```lua theme={null}
['x_device'] = {['name'] = 'x_device', ['label'] = 'X Device', ['weight'] = 50, ['type'] = 'item', ['image'] = 'x_device.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '?????????'},
['x_circuittester'] = {['name'] = 'x_circuittester', ['label'] = 'X Circuit Tester', ['weight'] = 200, ['type'] = 'item', ['image'] = 'x_circuittester.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '????'},
['x_harddrive'] = {['name'] = 'x_harddrive', ['label'] = 'X Hard Drive', ['weight'] = 200, ['type'] = 'item', ['image'] = 'x_harddrive.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '????'},
['storekey'] = {['name'] = 'storekey', ['label'] = 'Store Key', ['weight'] = 200, ['type'] = 'item', ['image'] = 'storekey.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '????'},
['advancedlockpick'] = {['name'] = 'advancedlockpick', ['label'] = 'Advanced Lockpick', ['weight'] = 500, ['type'] = 'item', ['image'] = 'advancedlockpick.png', ['unique'] = false, ['useable'] = true, ['shouldClose'] = true, ['combinable'] = nil, ['description'] = 'If you lose your keys a lot this is very useful... Also useful to open your beers'},
```
# Open Source
Source: https://docs.projectx.gg/resources/store-robbery-default/opensource
Open source files available for customization in the Default Store Robbery resource
Most of the core logic in this resource is handled by the bridge. The open source files are provided so you can customize minigames, add hooks for custom systems, and extend the script without touching escrow.
## opensource/client/client.lua
This file handles zone creation, drawtext, evidence, stress, and most importantly, the minigame callback. If you want to change the minigames used for each step, this is the only file you need to edit.
### Minigame Callback
Each robbery step triggers the `projectx-storerobbery-default:client:Minigames` callback with the step name. You can swap any minigame by replacing the export call inside the matching `elseif` block.
```lua theme={null}
lib.callback.register('projectx-storerobbery-default:client:Minigames', function(Step)
local p = promise.new()
if Step == "Fusebox" then
if not exports['projectx-bridge']:MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:NumberSlide(4, 50, 4)
p:resolve(success)
elseif Step == "Register" then
if not exports['projectx-bridge']:MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:CircleShake(1, 50, 2)
p:resolve(success)
elseif Step == "Atm" then
if not exports['projectx-bridge']:MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:Progress(4, 50)
p:resolve(success)
elseif Step == "Door" then
if not exports['projectx-bridge']:MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:CircleProgress(3, 50)
p:resolve(success)
elseif Step == "Server" then
if not exports['projectx-bridge']:MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:PathFind(1, { numberOfNodes = 10, duration = 7500, })
p:resolve(success)
elseif Step == "Npc" then
if not exports['projectx-bridge']:MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:KeySpam(1, 50)
p:resolve(success)
elseif Step == "Computer1" then
if not exports['projectx-bridge']:MinigameCheck("SN-Hacking") then p:resolve(false) return Citizen.Await(p) end
local success = exports['SN-Hacking']:MemoryCards('hard')
p:resolve(success)
elseif Step == "Computer2" then
if not exports['projectx-bridge']:MinigameCheck("SN-Hacking") then p:resolve(false) return Citizen.Await(p) end
local success = exports['SN-Hacking']:Thermite(7, 5, 10000, 2, 2, 3000)
p:resolve(success)
elseif Step == "Safe" then
local gameData = {totalNumbers = 20, seconds = 20, timesToChangeNumbers = 4, amountOfGames = 1, incrementByAmount = 5}
if not exports['projectx-bridge']:MinigameCheck("pure-minigames") then p:resolve(false) return Citizen.Await(p) end
local success = exports['pure-minigames']:numberCounter(gameData)
p:resolve(success)
elseif Step == "GangSafe" then
if not exports['projectx-bridge']:MinigameCheck("pd-safe") then p:resolve(false) return Citizen.Await(p) end
local success = exports["pd-safe"]:createSafe({math.random(0,99)})
p:resolve(success)
elseif Step == "Shelf" then
if not exports['projectx-bridge']:MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:CircleProgress(1, 50)
p:resolve(success)
end
return Citizen.Await(p)
end)
```
You can return `true` unconditionally inside any step block to skip that minigame entirely. This can be useful for testing or for steps you want to make automatic.
The default minigames per step are:
| Step | Minigame Resource | Function |
| ----------- | ----------------- | ---------------- |
| `Fusebox` | `bl_ui` | `NumberSlide` |
| `Register` | `bl_ui` | `CircleShake` |
| `Atm` | `bl_ui` | `Progress` |
| `Door` | `bl_ui` | `CircleProgress` |
| `Server` | `bl_ui` | `PathFind` |
| `Npc` | `bl_ui` | `KeySpam` |
| `Computer1` | `SN-Hacking` | `MemoryCards` |
| `Computer2` | `SN-Hacking` | `Thermite` |
| `Safe` | `pure-minigames` | `numberCounter` |
| `GangSafe` | `pd-safe` | `createSafe` |
| `Shelf` | `bl_ui` | `CircleProgress` |
***
## opensource/server/server.lua
This file handles dispatch, item/money functions, logging, and exposes several hooks you can use to run custom logic at specific points in the robbery.
### Hooks
Called whenever a player successfully completes a robbery step. Use this to award XP, trigger events, or log individual step completions.
```lua theme={null}
function SuccessfulStep(source, location, step)
if step == "Fusebox" then
-- exports['projectx-bridge']:AddExperience(source, 'criminal', 10)
elseif step == "Register" then
-- exports['projectx-bridge']:AddExperience(source, 'criminal', 10)
end
end
```
Step names match the minigame callback steps and interaction keys defined in `Config.Stores`.
Called whenever a player fails a robbery step. Use this to remove XP, items, or apply penalties.
```lua theme={null}
function FailedStep(source, location, step)
if step == "Fusebox" then
-- RemoveItem(source, 'x_circuittester', 1)
elseif step == "Register" then
-- Apply custom penalty
end
end
```
Called before a player can start a robbery at a location. Return `false` to block them.
```lua theme={null}
function InitialCheck(src, Location, Interaction)
return true
-- Add a group check, tablet requirement, or any other gate here
end
```
Called whenever a store location resets. Use this to update a scoreboard, trigger an external event, or notify players.
```lua theme={null}
function RobberyResetHook(location)
-- TriggerEvent('my-scoreboard:update', location)
end
```
# Commands
Source: https://docs.projectx.gg/resources/store-robbery-fm/commands
Admin commands for the FM Store Robbery resource
## Admin Commands
**Usage**: `/projectxstore`
**Permission**: Admin (configurable via `CheckPerms` in the bridge)
**Description**: Resets the nearest store within 50 units of your position. Useful for testing or recovering from a stuck robbery.
**Example**:
```
/projectxstore
```
This command resets the closest store location automatically. To reset a specific store programmatically, use the `Reset(location)` export instead. See the [Exports](/resources/store-robbery-fm/exports) page for details.
# Configuration
Source: https://docs.projectx.gg/resources/store-robbery-fm/configuration
Full reference for all configuration options in the FM Store Robbery resource
## config/config.lua
### Main Settings
Shows polyzones created inside the game. Useful for testing zone placement.
Disables all minigames. Useful for testing the full robbery flow without completing minigame challenges.
The key code used to trigger drawtext interactions. `38` is `[E]` by default.
The size of the drawtext interaction zone.
The default rotation of the drawtext interaction zone. Individual stores can override this in `Config.Stores`.
Spawns networked props server side. Set to `false` to spawn them client side instead.
Spawns networked peds server side. Set to `false` to spawn them client side instead.
Minimum number of police required online before a robbery can be started. Set to `0` to disable.
The jobs that count as police for the `MinimumPolice` check and dispatch alerts.
```lua theme={null}
PoliceJobs = {"police", "fbi"}
```
Requires a minimum number of players nearby to start a robbery.
```lua theme={null}
RequiredPlayersNearby = {amount = 0, radius = 20.0}
```
Set `amount` to `0` or `false` to disable.
Maximum number of store robberies that can be active at the same time. Set to `0` to disable.
Disables the loud approach path entirely.
Disables the silent approach path entirely.
Disables all particle effects during robberies.
Disables weapon removal during robberies. Only enable this if you use a weapon wheel resource.
Enables compatibility with the GruppeSechs job by 17mov.
***
### Cooldowns & Limits
When `true`, robbing one store puts all stores on cooldown. When `false`, each store has its own cooldown.
Cooldown duration in minutes.
Per-player cooldown in minutes after completing a robbery. Set to `0` to disable.
Maximum robberies per server restart, split by store type. Set each value to `0` to disable.
```lua theme={null}
TotalRobberiesPerRestart = {
['Stores247'] = 0,
['GasStations'] = 0,
['LiquorStores'] = 0,
}
```
Maximum robberies a single player can complete per restart, split by store type. Set each value to `0` to disable.
```lua theme={null}
RobberiesPerPlayer = {
['Stores247'] = 0,
['GasStations'] = 0,
['LiquorStores'] = 0,
}
```
***
### Skill System
Requires players to meet a minimum level from an integrated XP/skill system before starting a robbery. Must have an XP system configured in the bridge.
Minimum level required to initiate a robbery. Only applies when `SkillSystem` is `true`.
***
### Dispatch
Title shown in the dispatch alert.
Message body shown in the dispatch alert.
Radio code shown in the dispatch alert.
Time in seconds the dispatch alert remains visible. Not all dispatch systems support this.
Blip settings for the dispatch map marker.
```lua theme={null}
Blip = {
Text = 'Store Robbery',
Color = 1,
Sprite = 41,
Scale = 0.8
}
```
Controls which steps trigger dispatch alerts. `Loud` and `Silent` can be enabled independently.
```lua theme={null}
DispatchLocation = {
["Loud"] = true,
["Silent"] = false,
["Register"] = false,
["Atm"] = true,
}
```
***
### Bonus Items
Enables or disables bonus item drops at the end of a robbery.
Percentage chance that any bonus item is given at all.
Number of items that can be given from the bonus items table.
Table of possible bonus items. Each entry has a `Name`, `Chance` (%), and `Amount` range.
The total chance across all items needs to add up to 100%.
```lua theme={null}
Items = {
{Name = "x_device", Chance = 30, Amount = {min = 1, max = 1}},
{Name = "x_phone", Chance = 50, Amount = {min = 1, max = 1}},
{Name = "x_stethoscope", Chance = 20, Amount = {min = 1, max = 1}},
}
```
***
### Evidence & Stress
Enables fingerprint evidence drops at the crime scene.
Percentage chance that fingerprint evidence is left behind.
Enables the stress system. Stress is only applied when a minigame is failed.
Percentage chance that stress is applied on a minigame fail.
The minimum and maximum amount of stress applied per failure.
***
### Required Items
Maps logical item names to your inventory item names.
```lua theme={null}
Items = {
["Circuit"] = "x_circuittester",
["Lockpick"] = "advancedlockpick",
["Harddrive"] = "x_harddrive",
["Device"] = "x_device",
["Key"] = "storekey",
}
```
Break chance (%) for each item when used during a robbery.
```lua theme={null}
ItemsBreak = {
["Circuit"] = 0,
["Lockpick"] = 0,
["Device"] = 0,
}
```
***
### Rewards
Register, ATM, and safe rewards are configured per store type. Each table follows the same format.
Set to `true` to give money directly. Set to `false` to give a cash item instead.
The item name used when `Cash` is `false`.
The minimum and maximum cash or item amount per reward.
```lua theme={null}
StackAmount = {min = 3000, max = 6000}
```
Optional item metadata. Used if `markedbills` or similar items carry random value data in their info table.
**Reward tables by store type:**
| Table | Description |
| ----------------------------- | --------------------------------------------- |
| `Config.RegisterStores247` | Register loot from 24/7 stores |
| `Config.RegisterGasStations` | Register loot from gas stations |
| `Config.RegisterLiquorStores` | Register loot from liquor stores |
| `Config.AtmStores247` | ATM loot from 24/7 stores |
| `Config.AtmGasStations` | ATM loot from gas stations |
| `Config.SafeStores247` | Safe loot from 24/7 stores (uncorrupted data) |
| `Config.SafeCorruptStores247` | Safe loot from 24/7 stores (corrupted data) |
| `Config.SafeGasStations` | Safe loot from gas stations |
| `Config.SafeLiquorStores` | Safe loot from liquor stores |
**Shelf loot** is configured in `Config.RewardShelf`. `Config.MaxItems` controls how many items can be taken from each shelf.
***
### Store Locations
Enable or disable store types and individual locations using these tables:
* `Config.Stores247` — 24/7 supermarkets (9 locations, FM Supermarket map)
* `Config.GasStations` — Gas stations (5 locations)
* `Config.LiquorStores` — Liquor stores (5 locations)
Each enabled location has a full entry in `Config.Stores` with coordinates, interactions, NPC settings, reset timers, and per-store overrides. Use the store key (e.g. `"Strawberry"`, `"Davis"`) when calling exports.
You can add custom store locations by copying an existing entry in `Config.Stores` and adjusting the coordinates and interaction zones.
***
### Other Settings
Controls the safe code range and UI text for the office computer step.
How long the alarm lasts in minutes.
Weapons allowed for threatening the clerk during the loud approach. Add or remove weapon hashes as needed.
**Step durations** (`FuseboxDuration`, `RegisterDuration`, `ServerDuration`, etc.) control how long progress bars run for each interaction step.
***
### Logs
Configured in `config/logs.lua`.
Enables or disables the logging system.
Your Discord webhook URL, or your Fivemerr/Fivemanage API key.
The Fivemanage dataset to log activity to. Leave as `"default"` unless you have a specific dataset configured.
# Exports
Source: https://docs.projectx.gg/resources/store-robbery-fm/exports
Server-side exports available for the FM Store Robbery resource
## Server Exports
All exports require a valid store location key from `Config.Stores` (e.g. `"Strawberry"`, `"Davis"`, `"VespucciCanals"`).
### Reset
Resets the robbery at the given location, clearing active state and restoring the store.
```lua theme={null}
exports['projectx-storerobbery-fm']:Reset('Strawberry')
```
**Returns**
* `true` if the location exists and was reset successfully
***
### IsRobberyInProgress
Returns whether a robbery is currently active at the given location.
```lua theme={null}
local active = exports['projectx-storerobbery-fm']:IsRobberyInProgress('Strawberry')
```
**Returns**
* `true` if a robbery is in progress at that location, `false` otherwise
**Example**
```lua theme={null}
local active = exports['projectx-storerobbery-fm']:IsRobberyInProgress('Davis')
if active then
print("Davis gas station is being robbed")
end
```
***
### GetActiveRobberyCount
Returns the total number of active store robberies across all locations.
```lua theme={null}
local count = exports['projectx-storerobbery-fm']:GetActiveRobberyCount()
```
**Returns**
* `count` (number) — total active robberies
**Example**
```lua theme={null}
local count = exports['projectx-storerobbery-fm']:GetActiveRobberyCount()
print("Active store robberies: " .. count)
```
# FAQs
Source: https://docs.projectx.gg/resources/store-robbery-fm/faqs
Frequently asked questions about the FM Store Robbery resource
## General Questions
The script supports QBCore, Qbox, and ESX through the Project X Bridge. Set `Framework` to `'auto'` in the bridge config and it will detect your framework automatically.
Yes. The bridge is required for this script to function. It handles framework detection, inventory, dispatch, notifications, progressbars, XP, evidence, logs, and global cooldowns. See the [Bridge Installation](/resources/bridge/installation) page for setup instructions.
When you purchase FM Store Robbery, the `projectx-bridge` asset is automatically delivered to your CFX portal.
The bridge supports 25+ dispatch systems including PS Dispatch, CodeSign, LB Tablet, FD Dispatch, Wasabi MDT, Sonoran CAD, and many more. Set `Dispatch` to `'auto'` in the bridge config for automatic detection. See the [Bridge Overview](/resources/bridge/overview) for the full list.
The script supports three store types with tier-based loot:
* **24/7 Supermarkets** — 9 locations (FM Supermarket map)
* **Gas Stations** — 5 locations
* **Liquor Stores** — 5 locations
Enable or disable individual locations in `Config.Stores247`, `Config.GasStations`, and `Config.LiquorStores`.
The **loud approach** involves threatening the clerk with an allowed weapon. Dispatch can trigger immediately when the loud approach begins.
The **silent approach** bypasses the clerk and focuses on hacking, lockpicking, and stealth interactions. Dispatch timing is controlled by `DispatchLocation` in `config/config.lua`.
Open `opensource/client/client.lua` and find the `projectx-storerobbery-fm:client:Minigames` callback. Each robbery step has its own `elseif` block where you can swap the minigame export for any resource you prefer. You can also return `true` inside any block to skip that minigame entirely.
See the [Open Source](/resources/store-robbery-fm/opensource) page for the full callback code and a table of the default minigame assignments.
Use the `/projectxstore` in-game command (requires admin permissions) to reset the nearest store, or call the `Reset(location)` server export from another resource:
```lua theme={null}
exports['projectx-storerobbery-fm']:Reset('Strawberry')
```
See the [Commands](/resources/store-robbery-fm/commands) and [Exports](/resources/store-robbery-fm/exports) pages for more details.
## Configuration Questions
Set `MinimumPolice` to the number you want in `config/config.lua`, and make sure the correct jobs are listed in `PoliceJobs`.
```lua theme={null}
MinimumPolice = 2,
PoliceJobs = {"police", "fbi"},
```
Set `SkillSystem` to `true` and configure `MinimumLevel` in `config/config.lua`. You also need a compatible XP system integrated in the bridge config (`XPSystem`).
Supported systems include `pickle_xp`, `sd-levels`, `cw-rep`, and `OT_skills`.
Enable `Bonus.Status` and configure the `Bonus.Items` table in `config/config.lua`. Each item has a `Chance` percentage and an `Amount` range.
```lua theme={null}
Bonus = {
Status = true,
BonusChance = 15,
ItemCount = 1,
Items = {
{Name = "x_device", Chance = 30, Amount = {min = 1, max = 1}},
}
}
```
Set `Cooldown.Global` to `true` to lock all stores when one is robbed. Set it to `false` for individual per-store cooldowns. Adjust the duration with `Cooldown.Timer` (in minutes).
Copy an existing entry in `Config.Stores`, rename the key, and update the coordinates and interaction zones. Enable it in the matching store type table (`Config.Stores247`, `Config.GasStations`, or `Config.LiquorStores`).
## Troubleshooting
Make sure you have all required dependencies started before the script in your `server.cfg` (`projectx-bridge`, `ox_lib`, the FM Supermarket map, and minigames).
Verify all minigame resources (`bl_ui`, `pure-minigames`, `SN-Hacking`, `pd-safe`) are started and placed outside the robbery script folder. The bridge's `MinigameCheck` will return `false` if a minigame resource is missing.
Confirm the FM Supermarket map is installed and started before the robbery script. Interaction zones are configured for the FM map layout in `Config.Stores`.
# Installation
Source: https://docs.projectx.gg/resources/store-robbery-fm/installation
Step by step instructions to install the FM Store Robbery resource
## Installation Steps
Verify all dependencies below are started **before** this script in your `server.cfg`.
Download ox\_lib
Required map by FM Shop
Required Project X Bridge
Download the minigames zip and place each resource into your standalone or dependencies folder.
Download and place in your standalone or minigames folder
Make sure the minigames are **not** in the same folder as the robbery script.
Extract the script from the zip file and place it into your scripts folder.
Add the required items and their images to your inventory resource. See the [items section](#items-required) below for the full list.
Item images done by [Artwork Inventory](https://discord.gg/Z2awpnXKdw) - Use code **ProjectX** for 10% off!
Open `config/config.lua` and adjust the settings to match your server. The bridge handles framework, inventory, dispatch, and interaction automatically if set to `'auto'`.
Make sure the bridge, ox\_lib, your target, dispatch, inventory, and minigames are all started before the robbery script.
```cfg theme={null}
ensure ox_lib
ensure projectx-bridge
ensure bl_ui
ensure pure-minigames
ensure SN-Hacking
ensure pd-safe
ensure projectx-storerobbery-fm
```
## Items Required
### Items Required from Outside the Robbery
The `x_harddrive` must be obtained externally (e.g. from another robbery or side mission) before a store robbery can be started.
* `x_harddrive`
### Items Required from Shop/Black Market
* `x_device`
* `x_circuittester`
* `storekey`
* `advancedlockpick`
The rest of the items are obtained within the robbery itself.
### Item Configuration
```lua theme={null}
["x_device"] = {
label = "X Device",
weight = 125,
stack = false,
close = false,
description = "?????????",
},
["x_circuittester"] = {
label = "X Circuit Tester",
weight = 125,
stack = false,
close = false,
description = "?????????",
},
["x_harddrive"] = {
label = "X Harddrive",
weight = 125,
stack = false,
close = false,
description = "?????????",
},
["storekey"] = {
label = "Store Key",
weight = 125,
stack = false,
close = false,
description = "?????????",
},
["advancedlockpick"] = {
label = "Advanced Lockpick",
weight = 500,
stack = true,
close = true,
description = "If you lose your keys a lot this is very useful... Also useful to open your beers",
},
```
```lua theme={null}
['x_device'] = {['name'] = 'x_device', ['label'] = 'X Device', ['weight'] = 50, ['type'] = 'item', ['image'] = 'x_device.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '?????????'},
['x_circuittester'] = {['name'] = 'x_circuittester', ['label'] = 'X Circuit Tester', ['weight'] = 200, ['type'] = 'item', ['image'] = 'x_circuittester.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '????'},
['x_harddrive'] = {['name'] = 'x_harddrive', ['label'] = 'X Hard Drive', ['weight'] = 200, ['type'] = 'item', ['image'] = 'x_harddrive.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '????'},
['storekey'] = {['name'] = 'storekey', ['label'] = 'Store Key', ['weight'] = 200, ['type'] = 'item', ['image'] = 'storekey.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '????'},
['advancedlockpick'] = {['name'] = 'advancedlockpick', ['label'] = 'Advanced Lockpick', ['weight'] = 500, ['type'] = 'item', ['image'] = 'advancedlockpick.png', ['unique'] = false, ['useable'] = true, ['shouldClose'] = true, ['combinable'] = nil, ['description'] = 'If you lose your keys a lot this is very useful... Also useful to open your beers'},
```
# Open Source
Source: https://docs.projectx.gg/resources/store-robbery-fm/opensource
Open source files available for customization in the FM Store Robbery resource
Most of the core logic in this resource is handled by the bridge. The open source files are provided so you can customize minigames, add hooks for custom systems, and extend the script without touching escrow.
## opensource/client/client.lua
This file handles zone creation, drawtext, evidence, stress, and most importantly, the minigame callback. If you want to change the minigames used for each step, this is the only file you need to edit.
### Minigame Callback
Each robbery step triggers the `projectx-storerobbery-fm:client:Minigames` callback with the step name. You can swap any minigame by replacing the export call inside the matching `elseif` block.
```lua theme={null}
lib.callback.register('projectx-storerobbery-fm:client:Minigames', function(Step)
local p = promise.new()
if Step == "Fusebox" then
if not exports['projectx-bridge']:MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:NumberSlide(4, 50, 4)
p:resolve(success)
elseif Step == "Register" then
if not exports['projectx-bridge']:MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:CircleShake(1, 50, 2)
p:resolve(success)
elseif Step == "Atm" then
if not exports['projectx-bridge']:MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:Progress(4, 50)
p:resolve(success)
elseif Step == "Door" then
if not exports['projectx-bridge']:MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:CircleProgress(3, 50)
p:resolve(success)
elseif Step == "Server" then
if not exports['projectx-bridge']:MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:PathFind(1, { numberOfNodes = 10, duration = 7500, })
p:resolve(success)
elseif Step == "Npc" then
if not exports['projectx-bridge']:MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:KeySpam(1, 50)
p:resolve(success)
elseif Step == "Computer1" then
if not exports['projectx-bridge']:MinigameCheck("SN-Hacking") then p:resolve(false) return Citizen.Await(p) end
local success = exports['SN-Hacking']:MemoryCards('hard')
p:resolve(success)
elseif Step == "Computer2" then
if not exports['projectx-bridge']:MinigameCheck("SN-Hacking") then p:resolve(false) return Citizen.Await(p) end
local success = exports['SN-Hacking']:Thermite(7, 5, 10000, 2, 2, 3000)
p:resolve(success)
elseif Step == "Safe" then
local gameData = {totalNumbers = 20, seconds = 20, timesToChangeNumbers = 4, amountOfGames = 1, incrementByAmount = 5}
if not exports['projectx-bridge']:MinigameCheck("pure-minigames") then p:resolve(false) return Citizen.Await(p) end
local success = exports['pure-minigames']:numberCounter(gameData)
p:resolve(success)
elseif Step == "GangSafe" then
if not exports['projectx-bridge']:MinigameCheck("pd-safe") then p:resolve(false) return Citizen.Await(p) end
local success = exports["pd-safe"]:createSafe({math.random(0,99)})
p:resolve(success)
elseif Step == "Shelf" then
if not exports['projectx-bridge']:MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:CircleProgress(1, 50)
p:resolve(success)
end
return Citizen.Await(p)
end)
```
You can return `true` unconditionally inside any step block to skip that minigame entirely. This can be useful for testing or for steps you want to make automatic.
The default minigames per step are:
| Step | Minigame Resource | Function |
| ----------- | ----------------- | ---------------- |
| `Fusebox` | `bl_ui` | `NumberSlide` |
| `Register` | `bl_ui` | `CircleShake` |
| `Atm` | `bl_ui` | `Progress` |
| `Door` | `bl_ui` | `CircleProgress` |
| `Server` | `bl_ui` | `PathFind` |
| `Npc` | `bl_ui` | `KeySpam` |
| `Computer1` | `SN-Hacking` | `MemoryCards` |
| `Computer2` | `SN-Hacking` | `Thermite` |
| `Safe` | `pure-minigames` | `numberCounter` |
| `GangSafe` | `pd-safe` | `createSafe` |
| `Shelf` | `bl_ui` | `CircleProgress` |
***
## opensource/server/server.lua
This file handles dispatch, item/money functions, logging, and exposes several hooks you can use to run custom logic at specific points in the robbery.
### Hooks
Called whenever a player successfully completes a robbery step. Use this to award XP, trigger events, or log individual step completions.
```lua theme={null}
function SuccessfulStep(source, location, step)
if step == "Fusebox" then
-- exports['projectx-bridge']:AddExperience(source, 'criminal', 10)
elseif step == "Register" then
-- exports['projectx-bridge']:AddExperience(source, 'criminal', 10)
end
end
```
Step names match the minigame callback steps and interaction keys defined in `Config.Stores`.
Called whenever a player fails a robbery step. Use this to remove XP, items, or apply penalties.
```lua theme={null}
function FailedStep(source, location, step)
if step == "Fusebox" then
-- RemoveItem(source, 'x_circuittester', 1)
elseif step == "Register" then
-- Apply custom penalty
end
end
```
Called before a player can start a robbery at a location. Return `false` to block them.
```lua theme={null}
function InitialCheck(src, Location, Interaction)
return true
-- Add a group check, tablet requirement, or any other gate here
end
```
Called whenever a store location resets. Use this to update a scoreboard, trigger an external event, or notify players.
```lua theme={null}
function RobberyResetHook(location)
-- TriggerEvent('my-scoreboard:update', location)
end
```
# Commands
Source: https://docs.projectx.gg/resources/store-robbery-fmv2/commands
Admin commands for the FM V2 Store Robbery resource
## Admin Commands
**Usage**: `/projectxstore`
**Permission**: Admin (configurable via `CheckPerms` in the bridge)
**Description**: Resets the nearest store within 50 units of your position. Useful for testing or recovering from a stuck robbery.
**Example**:
```
/projectxstore
```
This command resets the closest store location automatically. To reset a specific store programmatically, use the `Reset(location)` export instead. See the [Exports](/resources/store-robbery-fmv2/exports) page for details.
# Configuration
Source: https://docs.projectx.gg/resources/store-robbery-fmv2/configuration
Full reference for all configuration options in the FM V2 Store Robbery resource
## config/config.lua
### Main Settings
Shows polyzones created inside the game. Useful for testing zone placement.
Disables all minigames. Useful for testing the full robbery flow without completing minigame challenges.
The key code used to trigger drawtext interactions. `38` is `[E]` by default.
The size of the drawtext interaction zone.
The default rotation of the drawtext interaction zone. Individual stores can override this in `Config.Stores`.
Spawns networked props server side. Set to `false` to spawn them client side instead.
Spawns networked peds server side. Set to `false` to spawn them client side instead.
Minimum number of police required online before a robbery can be started. Set to `0` to disable.
The jobs that count as police for the `MinimumPolice` check and dispatch alerts.
```lua theme={null}
PoliceJobs = {"police", "fbi"}
```
Requires a minimum number of players nearby to start a robbery.
```lua theme={null}
RequiredPlayersNearby = {amount = 0, radius = 20.0}
```
Set `amount` to `0` or `false` to disable.
Maximum number of store robberies that can be active at the same time. Set to `0` to disable.
Disables the loud approach path entirely.
Disables the silent approach path entirely.
Disables the clerk NPC in supermarkets. This also removes the loud approach that uses the NPC and replaces it with register breaking, similar to the older script.
Disables all particle effects during robberies.
Disables weapon removal during robberies. Only enable this if you use a weapon wheel resource.
Shows a timer for the shutter lockdown. Useful when shutters fully close after a short time.
Jobs that can open shutters after lockdown is active.
Minutes until shutters begin shutting down, depending on approach.
```lua theme={null}
Timers = {
["Silent"] = 5,
["Loud"] = 6,
}
```
***
### Cooldowns & Limits
When `true`, robbing one store puts all stores on cooldown. When `false`, each store has its own cooldown.
Cooldown duration in minutes.
Per-player cooldown in minutes after completing a robbery. Set to `0` to disable.
Maximum robberies per server restart, split by store type. Set each value to `0` to disable.
```lua theme={null}
TotalRobberiesPerRestart = {
['Stores247'] = 0,
['GasStations'] = 0,
['LiquorStores'] = 0,
}
```
Maximum robberies a single player can complete per restart, split by store type. Set each value to `0` to disable.
```lua theme={null}
RobberiesPerPlayer = {
['Stores247'] = 0,
['GasStations'] = 0,
['LiquorStores'] = 0,
}
```
***
### Skill System
Requires players to meet a minimum level from an integrated XP/skill system before starting a robbery. Must have an XP system configured in the bridge.
Minimum level required to initiate a robbery. Only applies when `SkillSystem` is `true`.
***
### Dispatch
Title shown in the dispatch alert.
Message body shown in the dispatch alert.
Radio code shown in the dispatch alert.
Time in seconds the dispatch alert remains visible. Not all dispatch systems support this.
Blip settings for the dispatch map marker.
```lua theme={null}
Blip = {
Text = 'Store Robbery',
Color = 1,
Sprite = 41,
Scale = 0.8
}
```
Controls which steps trigger dispatch alerts. `Loud` and `Silent` can be enabled independently. Only one of the step-based options should be enabled at a time.
```lua theme={null}
DispatchLocation = {
["Loud"] = true,
["Silent"] = false,
["Register"] = false,
["Atm"] = true,
}
```
***
### Bonus Items
Enables or disables bonus item drops at the end of a robbery.
Percentage chance that any bonus item is given at all.
Number of items that can be given from the bonus items table.
Table of possible bonus items. Each entry has a `Name`, `Chance` (%), and `Amount` range.
The total chance across all items needs to add up to 100%.
```lua theme={null}
Items = {
{Name = "x_device", Chance = 30, Amount = {min = 1, max = 1}},
{Name = "x_phone", Chance = 50, Amount = {min = 1, max = 1}},
{Name = "x_stethoscope", Chance = 20, Amount = {min = 1, max = 1}},
}
```
***
### Evidence & Stress
Enables fingerprint evidence drops at the crime scene.
Percentage chance that fingerprint evidence is left behind.
Enables the stress system. Stress is only applied when a minigame is failed.
Percentage chance that stress is applied on a minigame fail.
The minimum and maximum amount of stress applied per failure.
***
### Required Items
Maps logical item names to your inventory item names.
```lua theme={null}
Items = {
["Circuit"] = "x_circuittester",
["Stethoscope"] = "x_stethoscope",
["Lockpick"] = "advancedlockpick",
["Harddrive"] = "x_harddrive",
["Device"] = "x_device",
["Key"] = "storekey",
}
```
Break chance (%) for each item when used during a robbery.
```lua theme={null}
ItemsBreak = {
["Circuit"] = 0,
["Lockpick"] = 0,
["Stethoscope"] = 0,
["Device"] = 0,
}
```
***
### Rewards
Register, ATM, and safe rewards are configured per store type. Each table follows the same format.
Set to `true` to give money directly. Set to `false` to give a cash item instead.
The item name used when `Cash` is `false`.
The minimum and maximum cash or item amount per reward.
```lua theme={null}
StackAmount = {min = 3000, max = 6000}
```
Optional item metadata. Used if `markedbills` or similar items carry random value data in their info table.
**Reward tables by store type:**
| Table | Description |
| ----------------------------- | --------------------------------------------- |
| `Config.RegisterStores247` | Register loot from 24/7 stores |
| `Config.RegisterGasStations` | Register loot from gas stations |
| `Config.RegisterLiquorStores` | Register loot from liquor stores |
| `Config.AtmStores247` | ATM loot from 24/7 stores |
| `Config.AtmGasStations` | ATM loot from gas stations |
| `Config.SafeStores247` | Safe loot from 24/7 stores (uncorrupted data) |
| `Config.SafeCorruptStores247` | Safe loot from 24/7 stores (corrupted data) |
| `Config.SafeGasStations` | Safe loot from gas stations |
| `Config.SafeLiquorStores` | Safe loot from liquor stores |
**Shelf loot** is configured in `Config.RewardShelf`. `Config.MaxItems` controls how many items can be taken from each shelf.
***
### Store Locations
Enable or disable store types and individual locations using these tables:
* `Config.Stores247` — 24/7 supermarkets (10 locations)
* `Config.GasStations` — FM gas stations (5 locations)
* `Config.LiquorStores` — MXC liquor stores (5 locations)
Each enabled location has a full entry in `Config.Stores` with coordinates, interactions, NPC settings, reset timers, and per-store overrides. Use the store key (e.g. `"Strawberry"`, `"Davis"`) when calling exports.
You can add custom store locations by copying an existing entry in `Config.Stores` and adjusting the coordinates and interaction zones.
***
### Other Settings
Controls the safe code range and UI text for the office computer step.
How long the alarm lasts in minutes.
Weapons allowed for threatening the clerk during the loud approach. Add or remove weapon hashes as needed.
**Step durations** (`FuseboxDuration`, `RegisterDuration`, `ServerDuration`, etc.) control how long progress bars run for each interaction step.
***
### Logs
Configured in `config/logs.lua`.
Enables or disables the logging system.
Your Discord webhook URL, or your Fivemerr/Fivemanage API key.
The Fivemanage dataset to log activity to. Leave as `"default"` unless you have a specific dataset configured.
# Exports
Source: https://docs.projectx.gg/resources/store-robbery-fmv2/exports
Server-side exports available for the FM V2 Store Robbery resource
## Server Exports
All exports require a valid store location key from `Config.Stores` (e.g. `"Strawberry"`, `"Davis"`, `"VespucciCanals"`).
### Reset
Resets the robbery at the given location, clearing active state and restoring the store.
```lua theme={null}
exports['projectx-storerobbery-fmv2']:Reset('Strawberry')
```
**Returns**
* `true` if the location exists and was reset successfully
***
### IsRobberyInProgress
Returns whether a robbery is currently active at the given location.
```lua theme={null}
local active = exports['projectx-storerobbery-fmv2']:IsRobberyInProgress('Strawberry')
```
**Returns**
* `true` if a robbery is in progress at that location, `false` otherwise
**Example**
```lua theme={null}
local active = exports['projectx-storerobbery-fmv2']:IsRobberyInProgress('Davis')
if active then
print("Davis gas station is being robbed")
end
```
***
### GetActiveRobberyCount
Returns the total number of active store robberies across all locations.
```lua theme={null}
local count = exports['projectx-storerobbery-fmv2']:GetActiveRobberyCount()
```
**Returns**
* `count` (number) — total active robberies
**Example**
```lua theme={null}
local count = exports['projectx-storerobbery-fmv2']:GetActiveRobberyCount()
print("Active store robberies: " .. count)
```
# FAQs
Source: https://docs.projectx.gg/resources/store-robbery-fmv2/faqs
Frequently asked questions about the FM V2 Store Robbery resource
## General Questions
The script supports QBCore, Qbox, and ESX through the Project X Bridge. Set `Framework` to `'auto'` in the bridge config and it will detect your framework automatically.
Yes. The bridge is required for this script to function. It handles framework detection, inventory, dispatch, notifications, progressbars, XP, evidence, logs, and global cooldowns. See the [Bridge Installation](/resources/bridge/installation) page for setup instructions.
When you purchase FM V2 Store Robbery, the `projectx-bridge` asset is automatically delivered to your CFX portal.
The bridge supports 25+ dispatch systems including PS Dispatch, CodeSign, LB Tablet, FD Dispatch, Wasabi MDT, Sonoran CAD, and many more. Set `Dispatch` to `'auto'` in the bridge config for automatic detection. See the [Bridge Overview](/resources/bridge/overview) for the full list.
The script supports three store types with tier-based loot:
* **24/7 Supermarkets** — 10 locations (FM V2 map)
* **Gas Stations** — 5 locations
* **Liquor Stores** — 5 locations
Enable or disable individual locations in `Config.Stores247`, `Config.GasStations`, and `Config.LiquorStores`.
The **loud approach** involves threatening the clerk with an allowed weapon. Dispatch can trigger immediately, and shutter lockdown starts on a timer controlled by `Timers.Loud`.
The **silent approach** bypasses the clerk and focuses on hacking, lockpicking, and stealth interactions. Shutter lockdown starts after successfully hacking the keypad, controlled by `Timers.Silent`.
Open `opensource/client/client.lua` and find the `projectx-storerobbery-fmv2:client:Minigames` callback. Each robbery step has its own `elseif` block where you can swap the minigame export for any resource you prefer. You can also return `true` inside any block to skip that minigame entirely.
See the [Open Source](/resources/store-robbery-fmv2/opensource) page for the full callback code and a table of the default minigame assignments.
Use the `/projectxstore` in-game command (requires admin permissions) to reset the nearest store, or call the `Reset(location)` server export from another resource:
```lua theme={null}
exports['projectx-storerobbery-fmv2']:Reset('Strawberry')
```
See the [Commands](/resources/store-robbery-fmv2/commands) and [Exports](/resources/store-robbery-fmv2/exports) pages for more details.
## Configuration Questions
Set `MinimumPolice` to the number you want in `config/config.lua`, and make sure the correct jobs are listed in `PoliceJobs`.
```lua theme={null}
MinimumPolice = 2,
PoliceJobs = {"police", "fbi"},
```
Set `SkillSystem` to `true` and configure `MinimumLevel` in `config/config.lua`. You also need a compatible XP system integrated in the bridge config (`XPSystem`).
Supported systems include `pickle_xp`, `sd-levels`, `cw-rep`, and `OT_skills`.
Enable `Bonus.Status` and configure the `Bonus.Items` table in `config/config.lua`. Each item has a `Chance` percentage and an `Amount` range.
```lua theme={null}
Bonus = {
Status = true,
BonusChance = 15,
ItemCount = 1,
Items = {
{Name = "x_device", Chance = 30, Amount = {min = 1, max = 1}},
}
}
```
Set `Cooldown.Global` to `true` to lock all stores when one is robbed. Set it to `false` for individual per-store cooldowns. Adjust the duration with `Cooldown.Timer` (in minutes).
Copy an existing entry in `Config.Stores`, rename the key, and update the coordinates and interaction zones. Enable it in the matching store type table (`Config.Stores247`, `Config.GasStations`, or `Config.LiquorStores`).
## Troubleshooting
Make sure you have all required dependencies started before the script in your `server.cfg` (`projectx-bridge`, `ox_lib`, minigames).
Verify all minigame resources (`bl_ui`, `pure-minigames`, `SN-Hacking`, `pd-safe`) are started and placed outside the robbery script folder. The bridge's `MinigameCheck` will return `false` if a minigame resource is missing.
Set `DisableShutters` to `true` on the affected store entry in `Config.Stores`. This disables shutter and red interior effects for that location.
# Installation
Source: https://docs.projectx.gg/resources/store-robbery-fmv2/installation
Step by step instructions to install the FM V2 Store Robbery resource
## Installation Steps
Verify all dependencies below are started **before** this script in your `server.cfg`.
Download ox\_lib
Required map by FM Shop
Required Project X Bridge
Download the minigames zip and place each resource into your standalone or dependencies folder.
Download and place in your standalone or minigames folder
Make sure the minigames are **not** in the same folder as the robbery script.
Extract the script from the zip file and place it into your scripts folder.
Add the required items and their images to your inventory resource. See the [items section](#items-required) below for the full list.
Item images done by [Artwork Inventory](https://discord.gg/Z2awpnXKdw) - Use code **ProjectX** for 10% off!
Open `config/config.lua` and adjust the settings to match your server. The bridge handles framework, inventory, dispatch, and interaction automatically if set to `'auto'`.
Make sure the bridge, ox\_lib, your target, dispatch, inventory, and minigames are all started before the robbery script.
```cfg theme={null}
ensure ox_lib
ensure projectx-bridge
ensure bl_ui
ensure pure-minigames
ensure SN-Hacking
ensure pd-safe
ensure projectx-storerobbery-fmv2
```
## Items Required
### Items Required from Outside the Robbery
The `x_harddrive` must be obtained externally (e.g. from another robbery or side mission) before a store robbery can be started.
* `x_harddrive`
### Items Required from Shop/Black Market
* `x_device`
* `x_circuittester`
* `storekey`
* `advancedlockpick`
* `x_stethoscope`
The rest of the items are obtained within the robbery itself.
### Item Configuration
```lua theme={null}
["x_device"] = {
label = "X Device",
weight = 125,
stack = false,
close = false,
description = "?????????",
},
["x_circuittester"] = {
label = "X Circuit Tester",
weight = 125,
stack = false,
close = false,
description = "?????????",
},
["x_harddrive"] = {
label = "X Harddrive",
weight = 125,
stack = false,
close = false,
description = "?????????",
},
["storekey"] = {
label = "Store Key",
weight = 125,
stack = false,
close = false,
description = "?????????",
},
["advancedlockpick"] = {
label = "Advanced Lockpick",
weight = 500,
stack = true,
close = true,
description = "If you lose your keys a lot this is very useful... Also useful to open your beers",
},
["x_stethoscope"] = {
label = "X Stethoscope",
weight = 200,
stack = false,
close = false,
description = "click click",
},
```
```lua theme={null}
['x_device'] = {['name'] = 'x_device', ['label'] = 'X Device', ['weight'] = 50, ['type'] = 'item', ['image'] = 'x_device.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '?????????'},
['x_circuittester'] = {['name'] = 'x_circuittester', ['label'] = 'X Circuit Tester', ['weight'] = 200, ['type'] = 'item', ['image'] = 'x_circuittester.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '????'},
['x_harddrive'] = {['name'] = 'x_harddrive', ['label'] = 'X Hard Drive', ['weight'] = 200, ['type'] = 'item', ['image'] = 'x_harddrive.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '????'},
['storekey'] = {['name'] = 'storekey', ['label'] = 'Store Key', ['weight'] = 200, ['type'] = 'item', ['image'] = 'storekey.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '????'},
['advancedlockpick'] = {['name'] = 'advancedlockpick', ['label'] = 'Advanced Lockpick', ['weight'] = 500, ['type'] = 'item', ['image'] = 'advancedlockpick.png', ['unique'] = false, ['useable'] = true, ['shouldClose'] = true, ['combinable'] = nil, ['description'] = 'If you lose your keys a lot this is very useful... Also useful to open your beers'},
['x_stethoscope'] = {['name'] = 'x_stethoscope', ['label'] = 'X Stethoscope', ['weight'] = 200, ['type'] = 'item', ['image'] = 'x_stethoscope.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = 'click click'},
```
# Open Source
Source: https://docs.projectx.gg/resources/store-robbery-fmv2/opensource
Open source files available for customization in the FM V2 Store Robbery resource
Most of the core logic in this resource is handled by the bridge. The open source files are provided so you can customize minigames, add hooks for custom systems, and extend the script without touching escrow.
## opensource/client/client.lua
This file handles zone creation, drawtext, evidence, stress, and most importantly, the minigame callback. If you want to change the minigames used for each step, this is the only file you need to edit.
### Minigame Callback
Each robbery step triggers the `projectx-storerobbery-fmv2:client:Minigames` callback with the step name. You can swap any minigame by replacing the export call inside the matching `elseif` block.
```lua theme={null}
lib.callback.register('projectx-storerobbery-fmv2:client:Minigames', function(Step)
local p = promise.new()
if Step == "Fusebox" then
if not exports['projectx-bridge']:MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:NumberSlide(4, 50, 4)
p:resolve(success)
elseif Step == "Register" then
if not exports['projectx-bridge']:MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:CircleShake(1, 50, 2)
p:resolve(success)
elseif Step == "Atm" then
if not exports['projectx-bridge']:MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:Progress(4, 50)
p:resolve(success)
elseif Step == "Door" then
if not exports['projectx-bridge']:MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:CircleProgress(3, 50)
p:resolve(success)
elseif Step == "Server" then
if not exports['projectx-bridge']:MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:PathFind(1, { numberOfNodes = 10, duration = 7500, })
p:resolve(success)
elseif Step == "Keypad" then
if not exports['projectx-bridge']:MinigameCheck("pure-minigames") then p:resolve(false) return Citizen.Await(p) end
local gameData = {totalNumbers = 20, seconds = 20, timesToChangeNumbers = 4, amountOfGames = 1, incrementByAmount = 5}
local success = exports['pure-minigames']:numberCounter(gameData)
p:resolve(success)
elseif Step == "Npc" then
if not exports['projectx-bridge']:MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:KeySpam(1, 50)
p:resolve(success)
elseif Step == "Computer1" then
if not exports['projectx-bridge']:MinigameCheck("SN-Hacking") then p:resolve(false) return Citizen.Await(p) end
local success = exports['SN-Hacking']:MemoryCards('hard')
p:resolve(success)
elseif Step == "Computer2" then
if not exports['projectx-bridge']:MinigameCheck("SN-Hacking") then p:resolve(false) return Citizen.Await(p) end
local success = exports['SN-Hacking']:Thermite(7, 5, 10000, 2, 2, 3000)
p:resolve(success)
elseif Step == "Safe" then
local gameData = {totalNumbers = 20, seconds = 20, timesToChangeNumbers = 4, amountOfGames = 1, incrementByAmount = 5}
if not exports['projectx-bridge']:MinigameCheck("pure-minigames") then p:resolve(false) return Citizen.Await(p) end
local success = exports['pure-minigames']:numberCounter(gameData)
p:resolve(success)
elseif Step == "Stores247Safe" then
if not exports['projectx-bridge']:MinigameCheck("pd-safe") then p:resolve(false) return Citizen.Await(p) end
local success = exports["pd-safe"]:createSafe({math.random(0,99)})
p:resolve(success)
elseif Step == "GangSafe" then
if not exports['projectx-bridge']:MinigameCheck("pd-safe") then p:resolve(false) return Citizen.Await(p) end
local success = exports["pd-safe"]:createSafe({math.random(0,99)})
p:resolve(success)
elseif Step == "Shelf" then
if not exports['projectx-bridge']:MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:CircleProgress(1, 50)
p:resolve(success)
end
return Citizen.Await(p)
end)
```
You can return `true` unconditionally inside any step block to skip that minigame entirely. This can be useful for testing or for steps you want to make automatic.
The default minigames per step are:
| Step | Minigame Resource | Function |
| --------------- | ----------------- | ---------------- |
| `Fusebox` | `bl_ui` | `NumberSlide` |
| `Register` | `bl_ui` | `CircleShake` |
| `Atm` | `bl_ui` | `Progress` |
| `Door` | `bl_ui` | `CircleProgress` |
| `Server` | `bl_ui` | `PathFind` |
| `Keypad` | `pure-minigames` | `numberCounter` |
| `Npc` | `bl_ui` | `KeySpam` |
| `Computer1` | `SN-Hacking` | `MemoryCards` |
| `Computer2` | `SN-Hacking` | `Thermite` |
| `Safe` | `pure-minigames` | `numberCounter` |
| `Stores247Safe` | `pd-safe` | `createSafe` |
| `GangSafe` | `pd-safe` | `createSafe` |
| `Shelf` | `bl_ui` | `CircleProgress` |
***
## opensource/server/server.lua
This file handles dispatch, item/money functions, logging, and exposes several hooks you can use to run custom logic at specific points in the robbery.
### Hooks
Called whenever a player successfully completes a robbery step. Use this to award XP, trigger events, or log individual step completions.
```lua theme={null}
function SuccessfulStep(source, location, step)
if step == "Fusebox" then
-- exports['projectx-bridge']:AddExperience(source, 'criminal', 10)
elseif step == "Register" then
-- exports['projectx-bridge']:AddExperience(source, 'criminal', 10)
end
end
```
Step names match the minigame callback steps and interaction keys defined in `Config.Stores`.
Called whenever a player fails a robbery step. Use this to remove XP, items, or apply penalties.
```lua theme={null}
function FailedStep(source, location, step)
if step == "Fusebox" then
-- RemoveItem(source, 'x_circuittester', 1)
elseif step == "Register" then
-- Apply custom penalty
end
end
```
Called before a player can start a robbery at a location. Return `false` to block them.
```lua theme={null}
function InitialCheck(src, Location, Interaction)
return true
-- Add a group check, tablet requirement, or any other gate here
end
```
Called whenever a store location resets. Use this to update a scoreboard, trigger an external event, or notify players.
```lua theme={null}
function RobberyResetHook(location)
-- TriggerEvent('my-scoreboard:update', location)
end
```
# Commands
Source: https://docs.projectx.gg/resources/store-robbery-gabz/commands
Admin commands for the Gabz Store Robbery resource
## Admin Commands
**Usage**: `/projectxstore`
**Permission**: Admin (configurable via `CheckPerms` in the bridge)
**Description**: Resets the nearest store within 50 units of your position. Useful for testing or recovering from a stuck robbery.
**Example**:
```
/projectxstore
```
This command resets the closest store location automatically. To reset a specific store programmatically, use the `Reset(location)` export instead. See the [Exports](/resources/store-robbery-gabz/exports) page for details.
# Configuration
Source: https://docs.projectx.gg/resources/store-robbery-gabz/configuration
Full reference for all configuration options in the Gabz Store Robbery resource
## config/config.lua
### Main Settings
Shows polyzones created inside the game. Useful for testing zone placement.
Disables all minigames. Useful for testing the full robbery flow without completing minigame challenges.
The key code used to trigger drawtext interactions. `38` is `[E]` by default.
The size of the drawtext interaction zone.
The default rotation of the drawtext interaction zone. Individual stores can override this in `Config.Stores`.
Spawns networked props server side. Set to `false` to spawn them client side instead.
Spawns networked peds server side. Set to `false` to spawn them client side instead.
Minimum number of police required online before a robbery can be started. Set to `0` to disable.
The jobs that count as police for the `MinimumPolice` check and dispatch alerts.
```lua theme={null}
PoliceJobs = {"police", "fbi"}
```
Requires a minimum number of players nearby to start a robbery.
```lua theme={null}
RequiredPlayersNearby = {amount = 0, radius = 20.0}
```
Set `amount` to `0` or `false` to disable.
Maximum number of store robberies that can be active at the same time. Set to `0` to disable.
Disables the loud approach path entirely.
Disables the silent approach path entirely.
Disables all particle effects during robberies.
Disables weapon removal during robberies. Only enable this if you use a weapon wheel resource.
Enables compatibility with the GruppeSechs job by 17mov.
***
### Cooldowns & Limits
When `true`, robbing one store puts all stores on cooldown. When `false`, each store has its own cooldown.
Cooldown duration in minutes.
Per-player cooldown in minutes after completing a robbery. Set to `0` to disable.
Maximum robberies per server restart, split by store type. Set each value to `0` to disable.
```lua theme={null}
TotalRobberiesPerRestart = {
['Stores247'] = 0,
['GasStations'] = 0,
['LiquorStores'] = 0,
}
```
Maximum robberies a single player can complete per restart, split by store type. Set each value to `0` to disable.
```lua theme={null}
RobberiesPerPlayer = {
['Stores247'] = 0,
['GasStations'] = 0,
['LiquorStores'] = 0,
}
```
***
### Skill System
Requires players to meet a minimum level from an integrated XP/skill system before starting a robbery. Must have an XP system configured in the bridge.
Minimum level required to initiate a robbery. Only applies when `SkillSystem` is `true`.
***
### Dispatch
Title shown in the dispatch alert.
Message body shown in the dispatch alert.
Radio code shown in the dispatch alert.
Time in seconds the dispatch alert remains visible. Not all dispatch systems support this.
Blip settings for the dispatch map marker.
```lua theme={null}
Blip = {
Text = 'Store Robbery',
Color = 1,
Sprite = 41,
Scale = 0.8
}
```
Controls which steps trigger dispatch alerts. `Loud` and `Silent` can be enabled independently.
```lua theme={null}
DispatchLocation = {
["Loud"] = true,
["Silent"] = false,
["Register"] = false,
["Atm"] = true,
}
```
***
### Bonus Items
Enables or disables bonus item drops at the end of a robbery.
Percentage chance that any bonus item is given at all.
Number of items that can be given from the bonus items table.
Table of possible bonus items. Each entry has a `Name`, `Chance` (%), and `Amount` range.
The total chance across all items needs to add up to 100%.
```lua theme={null}
Items = {
{Name = "x_device", Chance = 30, Amount = {min = 1, max = 1}},
{Name = "x_phone", Chance = 50, Amount = {min = 1, max = 1}},
{Name = "x_stethoscope", Chance = 20, Amount = {min = 1, max = 1}},
}
```
***
### Evidence & Stress
Enables fingerprint evidence drops at the crime scene.
Percentage chance that fingerprint evidence is left behind.
Enables the stress system. Stress is only applied when a minigame is failed.
Percentage chance that stress is applied on a minigame fail.
The minimum and maximum amount of stress applied per failure.
***
### Required Items
Maps logical item names to your inventory item names.
```lua theme={null}
Items = {
["Circuit"] = "x_circuittester",
["Lockpick"] = "advancedlockpick",
["Harddrive"] = "x_harddrive",
["Device"] = "x_device",
["Key"] = "storekey",
}
```
Break chance (%) for each item when used during a robbery.
```lua theme={null}
ItemsBreak = {
["Circuit"] = 0,
["Lockpick"] = 0,
["Device"] = 0,
}
```
***
### Rewards
Register, ATM, and safe rewards are configured per store type. Each table follows the same format.
Set to `true` to give money directly. Set to `false` to give a cash item instead.
The item name used when `Cash` is `false`.
The minimum and maximum cash or item amount per reward.
```lua theme={null}
StackAmount = {min = 3000, max = 6000}
```
Optional item metadata. Used if `markedbills` or similar items carry random value data in their info table.
**Reward tables by store type:**
| Table | Description |
| ----------------------------- | --------------------------------------------- |
| `Config.RegisterStores247` | Register loot from 24/7 stores |
| `Config.RegisterGasStations` | Register loot from gas stations |
| `Config.RegisterLiquorStores` | Register loot from liquor stores |
| `Config.AtmStores247` | ATM loot from 24/7 stores |
| `Config.AtmGasStations` | ATM loot from gas stations |
| `Config.SafeStores247` | Safe loot from 24/7 stores (uncorrupted data) |
| `Config.SafeCorruptStores247` | Safe loot from 24/7 stores (corrupted data) |
| `Config.SafeGasStations` | Safe loot from gas stations |
| `Config.SafeLiquorStores` | Safe loot from liquor stores |
**Shelf loot** is configured in `Config.RewardShelf`. `Config.MaxItems` controls how many items can be taken from each shelf.
***
### Store Locations
Enable or disable store types and individual locations using these tables:
* `Config.Stores247` — 24/7 supermarkets (9 locations, Gabz store map)
* `Config.GasStations` — Gas stations (5 locations)
* `Config.LiquorStores` — Liquor stores (5 locations)
Each enabled location has a full entry in `Config.Stores` with coordinates, interactions, NPC settings, reset timers, and per-store overrides. Use the store key (e.g. `"Strawberry"`, `"Davis"`) when calling exports.
You can add custom store locations by copying an existing entry in `Config.Stores` and adjusting the coordinates and interaction zones.
***
### Other Settings
Controls the safe code range and UI text for the office computer step.
How long the alarm lasts in minutes.
Weapons allowed for threatening the clerk during the loud approach. Add or remove weapon hashes as needed.
**Step durations** (`FuseboxDuration`, `RegisterDuration`, `ServerDuration`, etc.) control how long progress bars run for each interaction step.
***
### Logs
Configured in `config/logs.lua`.
Enables or disables the logging system.
Your Discord webhook URL, or your Fivemerr/Fivemanage API key.
The Fivemanage dataset to log activity to. Leave as `"default"` unless you have a specific dataset configured.
# Exports
Source: https://docs.projectx.gg/resources/store-robbery-gabz/exports
Server-side exports available for the Gabz Store Robbery resource
## Server Exports
All exports require a valid store location key from `Config.Stores` (e.g. `"Strawberry"`, `"Davis"`, `"VespucciCanals"`).
### Reset
Resets the robbery at the given location, clearing active state and restoring the store.
```lua theme={null}
exports['projectx-storerobbery-gabz']:Reset('Strawberry')
```
**Returns**
* `true` if the location exists and was reset successfully
***
### IsRobberyInProgress
Returns whether a robbery is currently active at the given location.
```lua theme={null}
local active = exports['projectx-storerobbery-gabz']:IsRobberyInProgress('Strawberry')
```
**Returns**
* `true` if a robbery is in progress at that location, `false` otherwise
**Example**
```lua theme={null}
local active = exports['projectx-storerobbery-gabz']:IsRobberyInProgress('Davis')
if active then
print("Davis gas station is being robbed")
end
```
***
### GetActiveRobberyCount
Returns the total number of active store robberies across all locations.
```lua theme={null}
local count = exports['projectx-storerobbery-gabz']:GetActiveRobberyCount()
```
**Returns**
* `count` (number) — total active robberies
**Example**
```lua theme={null}
local count = exports['projectx-storerobbery-gabz']:GetActiveRobberyCount()
print("Active store robberies: " .. count)
```
# FAQs
Source: https://docs.projectx.gg/resources/store-robbery-gabz/faqs
Frequently asked questions about the Gabz Store Robbery resource
## General Questions
The script supports QBCore, Qbox, and ESX through the Project X Bridge. Set `Framework` to `'auto'` in the bridge config and it will detect your framework automatically.
Yes. The bridge is required for this script to function. It handles framework detection, inventory, dispatch, notifications, progressbars, XP, evidence, logs, and global cooldowns. See the [Bridge Installation](/resources/bridge/installation) page for setup instructions.
When you purchase Gabz Store Robbery, the `projectx-bridge` asset is automatically delivered to your CFX portal.
The bridge supports 25+ dispatch systems including PS Dispatch, CodeSign, LB Tablet, FD Dispatch, Wasabi MDT, Sonoran CAD, and many more. Set `Dispatch` to `'auto'` in the bridge config for automatic detection. See the [Bridge Overview](/resources/bridge/overview) for the full list.
The script supports three store types with tier-based loot:
* **24/7 Supermarkets** — 9 locations (Gabz store map)
* **Gas Stations** — 5 locations
* **Liquor Stores** — 5 locations
Enable or disable individual locations in `Config.Stores247`, `Config.GasStations`, and `Config.LiquorStores`.
The **loud approach** involves threatening the clerk with an allowed weapon. Dispatch can trigger immediately when the loud approach begins.
The **silent approach** bypasses the clerk and focuses on hacking, lockpicking, and stealth interactions. Dispatch timing is controlled by `DispatchLocation` in `config/config.lua`.
Open `opensource/client/client.lua` and find the `projectx-storerobbery-gabz:client:Minigames` callback. Each robbery step has its own `elseif` block where you can swap the minigame export for any resource you prefer. You can also return `true` inside any block to skip that minigame entirely.
See the [Open Source](/resources/store-robbery-gabz/opensource) page for the full callback code and a table of the default minigame assignments.
Use the `/projectxstore` in-game command (requires admin permissions) to reset the nearest store, or call the `Reset(location)` server export from another resource:
```lua theme={null}
exports['projectx-storerobbery-gabz']:Reset('Strawberry')
```
See the [Commands](/resources/store-robbery-gabz/commands) and [Exports](/resources/store-robbery-gabz/exports) pages for more details.
## Configuration Questions
Set `MinimumPolice` to the number you want in `config/config.lua`, and make sure the correct jobs are listed in `PoliceJobs`.
```lua theme={null}
MinimumPolice = 2,
PoliceJobs = {"police", "fbi"},
```
Set `SkillSystem` to `true` and configure `MinimumLevel` in `config/config.lua`. You also need a compatible XP system integrated in the bridge config (`XPSystem`).
Supported systems include `pickle_xp`, `sd-levels`, `cw-rep`, and `OT_skills`.
Enable `Bonus.Status` and configure the `Bonus.Items` table in `config/config.lua`. Each item has a `Chance` percentage and an `Amount` range.
```lua theme={null}
Bonus = {
Status = true,
BonusChance = 15,
ItemCount = 1,
Items = {
{Name = "x_device", Chance = 30, Amount = {min = 1, max = 1}},
}
}
```
Set `Cooldown.Global` to `true` to lock all stores when one is robbed. Set it to `false` for individual per-store cooldowns. Adjust the duration with `Cooldown.Timer` (in minutes).
Copy an existing entry in `Config.Stores`, rename the key, and update the coordinates and interaction zones. Enable it in the matching store type table (`Config.Stores247`, `Config.GasStations`, or `Config.LiquorStores`).
## Troubleshooting
Make sure you have all required dependencies started before the script in your `server.cfg` (`projectx-bridge`, `ox_lib`, the Gabz store map, and minigames).
Verify all minigame resources (`bl_ui`, `pure-minigames`, `SN-Hacking`, `pd-safe`) are started and placed outside the robbery script folder. The bridge's `MinigameCheck` will return `false` if a minigame resource is missing.
Confirm the Gabz store map is installed and started before the robbery script. Interaction zones are configured for the Gabz map layout in `Config.Stores`.
# Installation
Source: https://docs.projectx.gg/resources/store-robbery-gabz/installation
Step by step instructions to install the Gabz Store Robbery resource
## Installation Steps
Verify all dependencies below are started **before** this script in your `server.cfg`.
Download ox\_lib
Required map by Gabz
Required Project X Bridge
Download the minigames zip and place each resource into your standalone or dependencies folder.
Download and place in your standalone or minigames folder
Make sure the minigames are **not** in the same folder as the robbery script.
Extract the script from the zip file and place it into your scripts folder.
Add the required items and their images to your inventory resource. See the [items section](#items-required) below for the full list.
Item images done by [Artwork Inventory](https://discord.gg/Z2awpnXKdw) - Use code **ProjectX** for 10% off!
Open `config/config.lua` and adjust the settings to match your server. The bridge handles framework, inventory, dispatch, and interaction automatically if set to `'auto'`.
Make sure the bridge, ox\_lib, your target, dispatch, inventory, and minigames are all started before the robbery script.
```cfg theme={null}
ensure ox_lib
ensure projectx-bridge
ensure bl_ui
ensure pure-minigames
ensure SN-Hacking
ensure pd-safe
ensure projectx-storerobbery-gabz
```
## Items Required
### Items Required from Outside the Robbery
The `x_harddrive` must be obtained externally (e.g. from another robbery or side mission) before a store robbery can be started.
* `x_harddrive`
### Items Required from Shop/Black Market
* `x_device`
* `x_circuittester`
* `storekey`
* `advancedlockpick`
The rest of the items are obtained within the robbery itself.
### Item Configuration
```lua theme={null}
["x_device"] = {
label = "X Device",
weight = 125,
stack = false,
close = false,
description = "?????????",
},
["x_circuittester"] = {
label = "X Circuit Tester",
weight = 125,
stack = false,
close = false,
description = "?????????",
},
["x_harddrive"] = {
label = "X Harddrive",
weight = 125,
stack = false,
close = false,
description = "?????????",
},
["storekey"] = {
label = "Store Key",
weight = 125,
stack = false,
close = false,
description = "?????????",
},
["advancedlockpick"] = {
label = "Advanced Lockpick",
weight = 500,
stack = true,
close = true,
description = "If you lose your keys a lot this is very useful... Also useful to open your beers",
},
```
```lua theme={null}
['x_device'] = {['name'] = 'x_device', ['label'] = 'X Device', ['weight'] = 50, ['type'] = 'item', ['image'] = 'x_device.png', ['unique'] = true, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '?????????'},
['x_circuittester'] = {['name'] = 'x_circuittester', ['label'] = 'X Circuit Tester', ['weight'] = 200, ['type'] = 'item', ['image'] = 'x_circuittester.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '????'},
['x_harddrive'] = {['name'] = 'x_harddrive', ['label'] = 'X Hard Drive', ['weight'] = 200, ['type'] = 'item', ['image'] = 'x_harddrive.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '????'},
['storekey'] = {['name'] = 'storekey', ['label'] = 'Store Key', ['weight'] = 200, ['type'] = 'item', ['image'] = 'storekey.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = false, ['combinable'] = nil, ['description'] = '????'},
['advancedlockpick'] = {['name'] = 'advancedlockpick', ['label'] = 'Advanced Lockpick', ['weight'] = 500, ['type'] = 'item', ['image'] = 'advancedlockpick.png', ['unique'] = false, ['useable'] = true, ['shouldClose'] = true, ['combinable'] = nil, ['description'] = 'If you lose your keys a lot this is very useful... Also useful to open your beers'},
```
# Open Source
Source: https://docs.projectx.gg/resources/store-robbery-gabz/opensource
Open source files available for customization in the Gabz Store Robbery resource
Most of the core logic in this resource is handled by the bridge. The open source files are provided so you can customize minigames, add hooks for custom systems, and extend the script without touching escrow.
## opensource/client/client.lua
This file handles zone creation, drawtext, evidence, stress, and most importantly, the minigame callback. If you want to change the minigames used for each step, this is the only file you need to edit.
### Minigame Callback
Each robbery step triggers the `projectx-storerobbery-gabz:client:Minigames` callback with the step name. You can swap any minigame by replacing the export call inside the matching `elseif` block.
```lua theme={null}
lib.callback.register('projectx-storerobbery-gabz:client:Minigames', function(Step)
local p = promise.new()
if Step == "Fusebox" then
if not exports['projectx-bridge']:MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:NumberSlide(4, 50, 4)
p:resolve(success)
elseif Step == "Register" then
if not exports['projectx-bridge']:MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:CircleShake(1, 50, 2)
p:resolve(success)
elseif Step == "Atm" then
if not exports['projectx-bridge']:MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:Progress(4, 50)
p:resolve(success)
elseif Step == "Door" then
if not exports['projectx-bridge']:MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:CircleProgress(3, 50)
p:resolve(success)
elseif Step == "Server" then
if not exports['projectx-bridge']:MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:PathFind(1, { numberOfNodes = 10, duration = 7500, })
p:resolve(success)
elseif Step == "Npc" then
if not exports['projectx-bridge']:MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:KeySpam(1, 50)
p:resolve(success)
elseif Step == "Computer1" then
if not exports['projectx-bridge']:MinigameCheck("SN-Hacking") then p:resolve(false) return Citizen.Await(p) end
local success = exports['SN-Hacking']:MemoryCards('hard')
p:resolve(success)
elseif Step == "Computer2" then
if not exports['projectx-bridge']:MinigameCheck("SN-Hacking") then p:resolve(false) return Citizen.Await(p) end
local success = exports['SN-Hacking']:Thermite(7, 5, 10000, 2, 2, 3000)
p:resolve(success)
elseif Step == "Safe" then
local gameData = {totalNumbers = 20, seconds = 20, timesToChangeNumbers = 4, amountOfGames = 1, incrementByAmount = 5}
if not exports['projectx-bridge']:MinigameCheck("pure-minigames") then p:resolve(false) return Citizen.Await(p) end
local success = exports['pure-minigames']:numberCounter(gameData)
p:resolve(success)
elseif Step == "GangSafe" then
if not exports['projectx-bridge']:MinigameCheck("pd-safe") then p:resolve(false) return Citizen.Await(p) end
local success = exports["pd-safe"]:createSafe({math.random(0,99)})
p:resolve(success)
elseif Step == "Shelf" then
if not exports['projectx-bridge']:MinigameCheck("bl_ui") then p:resolve(false) return Citizen.Await(p) end
local success = exports["bl_ui"]:CircleProgress(1, 50)
p:resolve(success)
end
return Citizen.Await(p)
end)
```
You can return `true` unconditionally inside any step block to skip that minigame entirely. This can be useful for testing or for steps you want to make automatic.
The default minigames per step are:
| Step | Minigame Resource | Function |
| ----------- | ----------------- | ---------------- |
| `Fusebox` | `bl_ui` | `NumberSlide` |
| `Register` | `bl_ui` | `CircleShake` |
| `Atm` | `bl_ui` | `Progress` |
| `Door` | `bl_ui` | `CircleProgress` |
| `Server` | `bl_ui` | `PathFind` |
| `Npc` | `bl_ui` | `KeySpam` |
| `Computer1` | `SN-Hacking` | `MemoryCards` |
| `Computer2` | `SN-Hacking` | `Thermite` |
| `Safe` | `pure-minigames` | `numberCounter` |
| `GangSafe` | `pd-safe` | `createSafe` |
| `Shelf` | `bl_ui` | `CircleProgress` |
***
## opensource/server/server.lua
This file handles dispatch, item/money functions, logging, and exposes several hooks you can use to run custom logic at specific points in the robbery.
### Hooks
Called whenever a player successfully completes a robbery step. Use this to award XP, trigger events, or log individual step completions.
```lua theme={null}
function SuccessfulStep(source, location, step)
if step == "Fusebox" then
-- exports['projectx-bridge']:AddExperience(source, 'criminal', 10)
elseif step == "Register" then
-- exports['projectx-bridge']:AddExperience(source, 'criminal', 10)
end
end
```
Step names match the minigame callback steps and interaction keys defined in `Config.Stores`.
Called whenever a player fails a robbery step. Use this to remove XP, items, or apply penalties.
```lua theme={null}
function FailedStep(source, location, step)
if step == "Fusebox" then
-- RemoveItem(source, 'x_circuittester', 1)
elseif step == "Register" then
-- Apply custom penalty
end
end
```
Called before a player can start a robbery at a location. Return `false` to block them.
```lua theme={null}
function InitialCheck(src, Location, Interaction)
return true
-- Add a group check, tablet requirement, or any other gate here
end
```
Called whenever a store location resets. Use this to update a scoreboard, trigger an external event, or notify players.
```lua theme={null}
function RobberyResetHook(location)
-- TriggerEvent('my-scoreboard:update', location)
end
```
# Exports
Source: https://docs.projectx.gg/resources/tasks/exports
Available exports for the Tasks resource
## Server Exports
### CreateTasks
Creates a new task list and returns a unique task list ID. Duplicate task names are automatically grouped and tracked using counters.
```lua theme={null}
local uid = exports['projectx-tasks']:CreateTasks(title, tasks)
```
Title shown in the task UI
List of task names (strings)
**Returns**
* `uid` (string) - Unique task list identifier
**Examples**
```lua theme={null}
local uid = exports['projectx-tasks']:CreateTasks('Mission Tasks', { 'Hack Panel', 'Hack Panel', 'Escape Area' })
```
```lua theme={null}
local uid = exports['projectx-tasks']:CreateTasks('Heist Objectives', { 'Collect Supplies', 'Disable Security', 'Crack Vault', 'Escape' })
```
***
### DeleteTasks
Deletes a task list and force closes it for all viewers.
```lua theme={null}
exports['projectx-tasks']:DeleteTasks(uid)
```
Task list ID
**Returns**
* `boolean` - true if deleted, false if not found
***
### OpenTasks
Opens a task list UI for a specific player and registers them as a viewer.
```lua theme={null}
exports['projectx-tasks']:OpenTasks(player, uid, position)
```
Player server ID
Task list ID
UI position (`"left"` or `"right"`)
**Returns**
* `boolean` - true if opened successfully
**Example**
```lua theme={null}
exports['projectx-tasks']:OpenTasks(source, uid, 'left')
```
***
### CloseTasks
Closes a task list UI for a specific player and removes them from the viewer list.
```lua theme={null}
exports['projectx-tasks']:CloseTasks(player, uid)
```
Player server ID
Task list ID
**Returns**
* `boolean` - true if closed successfully
***
### UpdateTask
Updates the state of a task. Supports multiple instances of the same task name and tracks progress automatically. When all tasks are completed or failed, the task list closes and is removed.
```lua theme={null}
exports['projectx-tasks']:UpdateTask(uid, taskName, state)
```
Task list ID
Task label
`true` = task completed, `false` = task failed
**Returns**
* `boolean` - true if the update was successful
**Example**
```lua theme={null}
exports['projectx-tasks']:UpdateTask(uid, 'Hack Panel', true)
```
***
### GetStatus
Returns the current status of a specific task within a task list.
```lua theme={null}
local status = exports['projectx-tasks']:GetStatus(uid, taskName)
```
Task list ID
Task label
**Returns**
* `table` or `nil`
* `Done` (boolean)
* `Failed` (boolean)
* `DoneCount` (number)
* `Count` (number)
***
### GetIsListCompleted
Checks whether a task list has already been fully completed and cleaned up.
```lua theme={null}
local completed = exports['projectx-tasks']:GetIsListCompleted(uid)
```
Task list ID
**Returns**
* `boolean` or `nil`
# FAQs
Source: https://docs.projectx.gg/resources/tasks/faqs
Frequently asked questions about the Tasks resource
Tasks with identical names are automatically grouped and tracked using counters. For example, if you create a task list with two "Hack Panel" tasks, they will be grouped together and you can complete them individually.
Yes, multiple players can view the same task list simultaneously. All viewers will see real-time updates when tasks are completed or failed.
When all tasks in a list are completed or failed, the task list automatically closes for all viewers and is cleaned up from memory.
Player disconnects are handled safely to prevent stale viewers. The player will be automatically removed from the viewer list.
# Installation
Source: https://docs.projectx.gg/resources/tasks/installation
Step by step instructions to install the Tasks resource
## Installation Steps
Extract the script from the zip file and place it into your standalone folder or a folder that starts before your scripts.
Open `config.lua` and adjust the settings to your liking. See the configuration section below for details.
Add the following to your `server.cfg`:
```cfg theme={null}
ensure projectx-tasks
```
## Configuration
Below is the full configuration file with explanations for each option.
```lua theme={null}
Config = Config or {}
Config = {
ToggleCommand = {
Enabled = true,
Command = "toggletasks",
Keybind = 'J',
KeybindDescription = 'Toggle Task List'
}
}
```
### Toggle Command Settings
Enable or disable the command and keybind to toggle the task list visibility. Set to `false` to completely disable the toggle feature.
The command players can use to toggle the task list on/off (e.g., `/toggletasks` in chat)
The keybind to toggle the task list. Set to `''` (empty string) or comment out to disable keybind functionality while keeping the command active.
Description text shown in the FiveM keybinds menu to help players identify what the keybind does
# Exports
Source: https://docs.projectx.gg/resources/xp/exports
Available exports for the Project X XP skill system
## Server Exports
### AddXP
Awards XP to a player for a skill. Active XP buffs are applied using:
```text theme={null}
floor((baseXp + flatBonusTotal) * multiplierTotal)
```
```lua theme={null}
local ok, result = exports['projectx-xp']:AddXP(source, skillId, amount)
```
Player server ID
Skill ID from `Config.Skills` (e.g. `'criminal'`)
Base XP to award before buffs
**Returns**
* `ok` (boolean) — `true` on success, `false` on failure
* `result` (table | string)
* On success (table):
* `skill` (string) — skill ID
* `amount` (number) — XP awarded after buffs
* `xp` (number) — current XP toward the next level
* `totalXp` (number) — lifetime XP for the skill
* `level` (number) — current level
* `previousLevel` (number) — level before this award
* `leveledUp` (boolean) — whether the player leveled up
* `milestones` (table) — milestones reached from this award (if any)
* On failure (string), common values include:
* `'invalid_player'`
* `'invalid_skill'`
* `'invalid_amount'`
* `'max_level'`
**Example**
```lua theme={null}
local ok, result = exports['projectx-xp']:AddXP(source, 'criminal', 50)
if ok then
print(('Awarded %s XP — now level %s'):format(result.amount, result.level))
else
print('AddXP failed:', result)
end
```
***
### AddXPRaw
Awards XP while **ignoring** active XP buffs (no multiplier or flat bonus applied).
```lua theme={null}
local ok, result = exports['projectx-xp']:AddXPRaw(source, skillId, amount)
```
Player server ID
Skill ID from `Config.Skills`
Exact XP to award
**Returns**
Same shape as [`AddXP`](#addxp).
***
### RemoveXP
Removes XP from a player for a skill.
```lua theme={null}
local ok, result = exports['projectx-xp']:RemoveXP(source, skillId, amount)
```
Player server ID
Skill ID from `Config.Skills`
XP to remove
**Returns**
* `ok` (boolean)
* `result` (table | string) — updated skill state on success, or an error string on failure
***
### SetLevel
Sets a player's level for a skill directly.
`SetLevel` does **not** re-grant milestone rewards for levels the player skips or is set to.
```lua theme={null}
local ok, result = exports['projectx-xp']:SetLevel(source, skillId, level)
```
Player server ID
Skill ID from `Config.Skills`
Target level (clamped to the skill's `MaxLevel`)
**Returns**
* `ok` (boolean)
* `result` (table | string) — updated skill state on success, or an error string on failure
***
### GetSkill
Returns a single skill record for a player.
```lua theme={null}
local skill = exports['projectx-xp']:GetSkill(source, skillId)
```
Player server ID
Skill ID from `Config.Skills`
**Returns**
* `table` or `nil` — skill data (`level`, `xp`, `totalXp`, etc.)
***
### GetSkills
Returns all skill records for a player.
```lua theme={null}
local skills = exports['projectx-xp']:GetSkills(source)
```
Player server ID
**Returns**
* `table` — map of skill ID → skill data
***
### GetLevel
Returns the player's current level for a skill.
```lua theme={null}
local level = exports['projectx-xp']:GetLevel(source, skillId)
```
Player server ID
Skill ID from `Config.Skills`
**Returns**
* `number` — current level (typically `0` if missing)
***
### GetTotalXp
Returns the player's total (lifetime) XP for a skill.
```lua theme={null}
local totalXp = exports['projectx-xp']:GetTotalXp(source, skillId)
```
Player server ID
Skill ID from `Config.Skills`
**Returns**
* `number` — total XP
***
### GetSkillIds
Returns the configured skill IDs.
```lua theme={null}
local skillIds = exports['projectx-xp']:GetSkillIds()
```
**Returns**
* `table` — list of skill ID strings
***
### OpenMenu
Opens the XP menu for a player from the server.
```lua theme={null}
exports['projectx-xp']:OpenMenu(source)
```
Player server ID
***
### SyncClient
Forces a client sync of the player's XP data.
```lua theme={null}
exports['projectx-xp']:SyncClient(source)
```
Player server ID
***
### AddXpBuff
Adds a temporary XP buff. Multiple buffs stack.
Award formula while buffs are active:
```text theme={null}
floor((baseXp + flatBonusTotal) * multiplierTotal)
```
```lua theme={null}
local ok, result = exports['projectx-xp']:AddXpBuff(source, options)
```
Player server ID
Buff options table
Skill ID to apply the buff to, or a value that targets all skills depending on your config
Multiplier contribution (e.g. `1.5` for +50%)
Flat XP added before the multiplier is applied
Buff duration in seconds
Display label shown in notifications / UI
Optional unique buff ID (useful for targeted removal)
Whether to notify the player when the buff is applied
**Example**
```lua theme={null}
exports['projectx-xp']:AddXpBuff(source, {
skill = 'criminal',
multiplier = 1.5,
flatBonus = 10,
duration = 300,
label = 'Heist Boost',
id = 'heist_boost',
notify = true,
})
```
***
### RemoveXpBuff
Removes an active XP buff by ID (or matching options, depending on usage).
```lua theme={null}
local ok = exports['projectx-xp']:RemoveXpBuff(source, buffId)
```
Player server ID
Buff ID previously passed to `AddXpBuff`
**Returns**
* `boolean` — whether a buff was removed
***
### GetXpBuffs
Returns active XP buffs for a player.
```lua theme={null}
local buffs = exports['projectx-xp']:GetXpBuffs(source, skillId)
```
Player server ID
Optional skill filter
**Returns**
* `table` — list of active buffs
***
### GetXpMultiplier
Returns the combined XP multiplier (and related totals) currently applied for a skill.
```lua theme={null}
local multiplier = exports['projectx-xp']:GetXpMultiplier(source, skillId)
```
Player server ID
Skill ID from `Config.Skills`
**Returns**
* `number` — combined multiplier total used by `AddXP`
***
## Client Exports
### OpenMenu
Opens the XP menu on the local client.
```lua theme={null}
exports['projectx-xp']:OpenMenu()
```
***
### IsMenuOpen
Returns whether the XP menu is currently open.
```lua theme={null}
local open = exports['projectx-xp']:IsMenuOpen()
```
**Returns**
* `boolean`
***
### RefreshMenu
Refreshes the XP menu UI if it is open.
```lua theme={null}
exports['projectx-xp']:RefreshMenu()
```
***
### GetXpBuffs
Returns active XP buffs known to the client.
```lua theme={null}
local buffs = exports['projectx-xp']:GetXpBuffs(skillId)
```
Optional skill filter
**Returns**
* `table` — list of active buffs
***
## Bridge Integration
When `XPSystem` is set to `'projectx'` (or `'auto'` and projectx-xp is running), Project X scripts can award and read XP through the bridge:
```lua theme={null}
exports['projectx-bridge']:AddExperience(source, 'criminal', 25)
exports['projectx-bridge']:GetLevel(source, 'criminal')
```
See [Bridge Installation](/resources/bridge/installation) for `XPSystem` options.
## Example: Robbery / Job Award
```lua theme={null}
-- Server-side only
local ok, result = exports['projectx-xp']:AddXP(source, 'criminal', 50)
if ok and result.leveledUp then
print(('Player reached criminal level %s'):format(result.level))
end
```
Do not call `AddXP` (or any XP-mutating export) from client scripts. Award XP on the server only.
# FAQs
Source: https://docs.projectx.gg/resources/xp/faqs
Frequently asked questions about the Project X XP skill system
Project X XP (`projectx-xp`) is a multi-skill XP system with levels, milestones, rewards, buffs, a leaderboard, and a built-in UI. Other resources award XP through server exports, or through [projectx-bridge](/resources/bridge/installation) when `XPSystem` is set to `'projectx'` / `'auto'`.
Configure `Framework` and `Inventory` in `config/config.lua` to match your server. Common setups include QBCore, Qbox, and ESX, with inventories such as ox\_inventory and qb-inventory. Inventory is mainly needed if you enable `UseItem` with `x_device`.
No — the bridge is optional for projectx-xp itself. It is recommended if you run Project X robberies or other Project X scripts that award XP through the bridge. In that case, set `XPSystem` to `'projectx'` or `'auto'` in the bridge config. See [Bridge Installation](/resources/bridge/installation).
Check start order in `server.cfg`. `projectx-xp` must start **after** your framework, ox\_lib, and oxmysql, and **before** scripts that call XP exports. Example:
```cfg theme={null}
ensure ox_lib
ensure oxmysql
ensure projectx-xp
```
Import/run with the `player_xp` table in place. Legacy Pickle XP JSON can migrate automatically when the skill keys match entries defined in `Config.Skills`. Align your skill IDs with the old Pickle keys before going live.
Add a new entry under `Config.Skills` in `config/config.lua` with `Label`, `Description`, `Icon`, `BaseXp`, `Multiplier`, `MaxLevel`, optional `LevelTitles`, and optional `Milestones`. Include the new skill ID in `SkillOrder` if you want it shown in a specific position in the UI.
Milestones grant configured rewards (`money`, `item`, `export`, etc.) when a player reaches that level through normal XP gain. `SetLevel` does **not** re-grant milestones for levels you set or skip.
Multiple buffs can be active at once. Awards use:
```text theme={null}
floor((baseXp + flatBonusTotal) * multiplierTotal)
```
Use `AddXPRaw` when you need to award XP without applying buffs.
Players can open the menu with `/xp` (or your configured `OpenCommand`) and the `F7` keybind (or your configured `OpenKey`). Testbuff-related commands are for testing buffs only — do not rely on them in production gameplay.
No. Never grant XP from client scripts. Always use server exports such as `AddXP`, or the bridge's server-side `AddExperience` when integrated.
Join the Project X Discord and use the **Free-Support** channel: [https://discord.gg/projectxdev](https://discord.gg/projectxdev)
# Installation
Source: https://docs.projectx.gg/resources/xp/installation
Install and configure the Project X XP skill system
## Installation Steps
Verify all dependencies below are started **before** this script in your `server.cfg`.
Download ox\_lib (CommunityOx)
Download oxmysql (overextended)
Extract the script from the zip file and place it into your resources folder (for example `standalone` or `[projectx]`).
Import `sql/install.sql` into your database. This creates the `player_xp` table.
The script can also auto-add missing columns at runtime if the table already exists.
Legacy Pickle XP JSON data can migrate automatically when skill keys match entries in `Config.Skills`.
Open `config/config.lua` and adjust the settings to your liking. See the [configuration](#configuration) section below for details.
Start `projectx-xp` **after** your framework, ox\_lib, and oxmysql, and **before** any scripts that award XP:
```cfg theme={null}
ensure ox_lib
ensure oxmysql
ensure projectx-xp
```
If you use [projectx-bridge](/resources/bridge/installation), set `XPSystem` to `'projectx'` or `'auto'`.
* `'projectx'` — always use projectx-xp
* `'auto'` — detects projectx-xp when the resource is started
See the [Bridge Installation](/resources/bridge/installation) page for full setup.
If you enable `UseItem`, add the `x_device` item to your inventory so players can open the XP menu from an item.
Never grant XP from the client. All XP changes must go through server exports only.
## Configuration
Key options in `config/config.lua`:
### General Settings
Language locale used by the resource.
Your server framework (for example QBCore, Qbox, or ESX). Match this to your server setup.
Your inventory system. Required if you use `UseItem` with `x_device`.
Chat command to open the XP menu (e.g. `/xp`).
Keybind to open the XP menu.
When enabled, using the `x_device` item opens the XP menu. Add the item to your inventory if you enable this.
### Notifications
Notification system: `'customui'`, `'ox'`, `'qb'`, or `'esx'`.
Default notification display duration.
Display duration for XP buff notifications.
Notify the player when they gain XP.
Notify the player when they level up.
Notify the player when they reach a milestone.
Notify the player when an XP buff is applied or removed.
### UI & Leaderboard
Maximum number of entries shown on the leaderboard.
Primary accent color for the XP UI.
Overall UI scale multiplier.
Scale multiplier for XP-related notifications.
Show milestone reward details in the UI.
Display level titles from each skill's `LevelTitles` table.
Ordered list of skill IDs that controls how skills appear in the UI.
### Skills (`Config.Skills`)
Each entry in `Config.Skills` is keyed by a skill ID (for example `criminal`) and supports:
| Field | Description |
| ------------- | --------------------------------- |
| `Label` | Display name shown in the UI |
| `Description` | Short description of the skill |
| `Icon` | Icon used in the UI |
| `BaseXp` | Base XP required for early levels |
| `Multiplier` | XP curve multiplier per level |
| `MaxLevel` | Maximum level for the skill |
| `LevelTitles` | Optional titles keyed by level |
| `Milestones` | Level thresholds with `Rewards` |
Milestone `Rewards` support types such as:
* `money` — cash/bank reward
* `item` — inventory item reward
* `export` — custom export callback
**Default skills:** `criminal`, `fishing`, `crafting`, `mechanic`, `delivery`, `farming`, `diving`, `mining`
```lua theme={null}
Config.Skills = {
criminal = {
Label = 'Criminal',
Description = 'Crime and heists',
Icon = 'skull',
BaseXp = 100,
Multiplier = 1.15,
MaxLevel = 100,
LevelTitles = {
[1] = 'Rookie',
[25] = 'Career Criminal',
},
Milestones = {
[10] = {
Rewards = {
{ type = 'money', amount = 500 },
{ type = 'item', name = 'lockpick', amount = 2 },
}
},
},
},
}
```
## UI Build
The shipped UI lives in `web/build`. Only rebuild `web/` if you edit the UI source:
```bash theme={null}
cd web
npm install
npm run build
```