FiveM & QBCore · Practical guide

FiveM Bank Robbery Script — Complete QBCore Guide

A complete bank robbery system for your FiveM server covering store robberies, bank vaults and escape routes on QBCore.

Stellar AI · Updated 8 September 2026 · 6 min read

A practical guide to fivem bank robbery script — complete qbcore guide, with implementation decisions, validation steps, and security considerations for a production-minded project.

Overview: Purpose and Scope

This guide walks through building a secure, maintainable bank robbery script for FiveM using QBCore, with notes on ESX compatibility, ox_lib integration, and a short section covering Roblox porting considerations. It focuses on architecture, server-side validation, implementation choices, testing, deployment, and maintenance. It does not rely on client input for security-sensitive checks and follows best practices for data integrity and anti-cheat resilience.

Architecture and Data Flow

Design the robbery flow as a set of authoritative server processes with minimal client authority. Typical components:

  • Server controller: single source of truth for robbery state, cooldowns, police counts, and payouts.
  • Client UI & effects: animations, progress bars, target selection, sound—purely cosmetic and driven by server state.
  • Database/logging layer: persistent logs for audits and rollback, optionally using MySQL or your preferred DB via an async query layer.
  • Anti-cheat integration: rate limiting, event throttling, and anomaly detection on the server.

Sequence (high-level): Player requests to start → server validates permissions and world state → server begins robbery, pushes events to clients (police alert, UI triggers) → client reports progress ticks only as confirmations to server → server awards payout and updates persistent logs when the robbery completes.

State model

Keep a small in-memory state for active robberies keyed by bankId or instanceId. Persist only final outcomes or significant checkpoints to DB. Never persist transient client-sent progress without server verification.

Implementation Choices (QBCore-focused)

Use the server-side QBCore API for player lookups, inventory checks, and item consumption. For QBCore v2+ common idioms:

local QBCore = exports['qb-core']:GetCoreObject()

RegisterNetEvent('bank:server:StartRobbery', function(bankId)
  local src = source
  local Player = QBCore.Functions.GetPlayer(src)
  if not Player then return end

  -- server-side validations
  if not validBank(bankId) then
    TriggerClientEvent('bank:client:RobberyDenied', src, 'invalid_bank')
    return
  end

  if not Player.Functions.GetItemByName('thermal_charge') then
    TriggerClientEvent('bank:client:RobberyDenied', src, 'missing_item')
    return
  end

  -- start robbery in server state and notify police
  startRobberyForPlayer(src, bankId)
end)

Validate inventory and permissions on server, consume required items on server, and use QBCore.Functions.CreateCallback for synchronous server-client queries when necessary.

ox_lib and effect integration

Use ox_lib for standardized UI and progressbars on the client, but drive the progress state from server heartbeats or validated ticks. Never let the client unilaterally trigger completion; client sends "progress tick" events that server verifies against timeouts and expected intervals.

Security and Server Validation

Security is the single most important area. Never trust client input. Key server-side checks:

  • Player identity: use QBCore functions to retrieve player metadata, identifiers, and job.
  • Inventory and items: check for required items server-side and remove them atomically when starting.
  • Proximity / line-of-sight: validate player coordinates server-side if the world position matters.
  • Weapon check: verify weapon type on server by checking the player state or an equip flag sent in a short-lived, validated event.
  • Police count and presence: count active police jobs on the server—not client-supplied numbers.
  • Timing & anti-rapid-fire: implement minimum intervals between progress ticks, and reject impossible sequences.

Store a server-side anti-cheat score and incremental penalties for suspicious behavior (e.g., impossible location changes, too-fast completion). Log suspicious events for offline review rather than immediate punishment in ambiguous cases.

Database and Logging

Persist outcomes and important state transitions:

  • Robbery start and end timestamps
  • Payout amounts, player identifiers, and item consumption
  • Police notifications and response IDs
  • Suspicious activity flags

Use asynchronous DB calls and ensure errors are handled—retry transient failures and fail-safe by placing the robbery in a "pending" state until persistence succeeds or manual reconciliation occurs.

Practical Checklist: Server vs Client Responsibilities

TaskServerClientNotes
Start requestValidate player, items, cooldowns, police countSend request, show pending UIServer decides accept/deny
Progress trackingValidate ticks, enforce timing, store stateShow progressbar/animationClient-only visuals; server owns correctness
PayoutCalculate and distribute money/items, log to DBShow reward UI/animationServer should be authoritative
Police alertDetermine and broadcast geofence alertsPlay sounds/markersUse server to prevent false alarms
Anti-cheatScore based on anomalies; block/flagNoneKeep lists of violators

Sample Server Event Patterns and Fail-Safes

Use guarded RegisterNetEvent handlers with local source checking and state locks. Example patterns to protect critical sections:

local activeRobberies = {}

local function startRobberyForPlayer(src, bankId)
  if activeRobberies[bankId] then return end
  activeRobberies[bankId] = {player = src, start = os.time()}
  -- schedule end or timeout
  SetTimeout(60 * 1000, function()
    if activeRobberies[bankId] and activeRobberies[bankId].player == src then
      finishRobbery(src, bankId)
    end
  end)
end

RegisterNetEvent('bank:server:ProgressTick', function(bankId, tickId)
  local src = source
  if not activeRobberies[bankId] or activeRobberies[bankId].player ~= src then
    return -- invalid or stale tick
  end
  -- validate tick timing and update server state
end)

Testing: Unit, Integration, and Abuse Scenarios

Testing phases:

  1. Unit tests for server-side validation logic (cooldowns, item checks).
  2. Integration tests with QBCore player objects and DB layer (simulate multiple concurrent players).
  3. Manual gameplay testing with QA players: police responses, UI flow, edge cases like disconnect mid-robbery.
  4. Abuse testing: simulate forged client events, rapid tick submissions, and improbable position reports.

Use verbose server logs during testing but disable expensive logging in production. Record player identifiers with tests so you can reproduce sequences later.

Deployment and Runtime Considerations

When releasing:

  • Feature toggle: release behind a config flag so you can quickly disable if issues arise.
  • DB migrations: apply schema changes in a transactional way and verify backups before schema-altering updates.
  • Monitoring: expose metrics (robberies/attempts/success rate/flags) to your monitoring system. Keep logs for reconciliation.
  • Auto-reload safety: avoid hot-reloading scripts that reset in-memory robbery state without persisting; gracefully drain active robberies before a restart.

For on-going analytics and admin control, integrate an admin panel to list active robberies, cancel, or force-complete for recovery operations. You can use a lightweight internal UI or a web dashboard linked to the same DB and protected by admin auth.

Stellar AI can help generate and revise the project files for this workflow. Describe your framework, existing dependencies, and one testable feature, then bring back errors for a focused revision. You remain responsible for running the tests and managing deployment in your own development environment.

Maintenance, Updates, and Versioning

Maintain a changelog and semantic versioning. When updating the script:

  • Document breaking changes (state model changes, DB schema updates).
  • Provide compatibility shims for older client assets if immediate client updates are impossible.
  • Schedule maintenance windows for schema migrations and major updates that require player downtime.
  • Rotate any secrets (API keys, webhook tokens) used by your logging or alerting systems periodically and after suspected leaks.

Roblox Porting Considerations (Luau)

If you plan to port the core ideas to Roblox, follow these server-authoritative patterns:

  • All security checks and payouts are executed on the Roblox server (Script), never on client LocalScripts.
  • Use RemoteEvents and RemoteFunctions only to request actions; validate all data and refusal reasons on the server. Never accept positional data without server-side verification.
  • Handle DataStore errors robustly using pcall, retries, and backoff. Design for rate limits and expired writes.
  • Use server-side locking patterns (e.g., ordered state tables or BindableEvents) to prevent double-completion.
  • Log server-side events and provide an admin UI for investigation. Protect admin endpoints by group/role checks.

Common Pitfalls and How to Avoid Them

  • Trusting client timestamps: Reject or re-derive time deltas server-side.
  • Not accounting for disconnects: persist mid-state when appropriate and support resume or safe cancellation.
  • Race conditions on DB writes: use transactions or atomic updates when crediting money or items.
  • Insufficient police verification: count only active police jobs from the server job registry, not client claims.

Build your next system with Stellar AI

Describe one feature, get organized project files, then bring back your errors to keep improving. Start free with no card required. Test generated code in a private development environment before release.

Create your first script free →