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.
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.
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.
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.
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.