Frameworks
Writing your first QBCore script
Learn QBCore scripting: GetCoreObject, QBCore.Functions.GetPlayer and PlayerData, money types, AddItem/RemoveItem, jobs and grades, CreateUseableItem, QBCore.Commands.Add with permissions, OnPlayerLoaded and OnJobUpdate events, and a complete example resource.
Overview
QBCore is the other big roleplay framework. Where ESX has xPlayer, QBCore has a Player object with PlayerData and Functions. The concepts — money, items, jobs, commands, loaded events — map almost one to one, so moving between the two is mostly vocabulary.
01Getting the core object
local QBCore = exports['qb-core']:GetCoreObject()fx_version 'cerulean'
game 'gta5'
lua54 'yes'
shared_script 'config.lua'
client_script 'client.lua'
server_script 'server.lua'
dependency 'qb-core'The Player object
| Task | Code |
|---|---|
| Get the player | local Player = QBCore.Functions.GetPlayer(source) |
| Character ID | Player.PlayerData.citizenid |
| Money | Player.PlayerData.money.cash, Player.Functions.AddMoney('bank', n, reason), RemoveMoney |
| Items | Player.Functions.AddItem('bread', 1), Player.Functions.RemoveItem('bread', 1), GetItemByName |
| Job | Player.PlayerData.job.name, .job.grade.level, .job.onduty, Player.Functions.SetJob('police', 0) |
| Notify | TriggerClientEvent('QBCore:Notify', source, 'Saved', 'success') |
| Player by citizenid | QBCore.Functions.GetPlayerByCitizenId(cid) |
02A complete example: selling fish
local QBCore = exports['qb-core']:GetCoreObject()
local PRICE = 45
local MARKET = vec3(-1845.0, -1195.0, 14.3)
RegisterNetEvent('fishmarket:sell', function()
local src = source
local Player = QBCore.Functions.GetPlayer(src)
if not Player then return end
if #(GetEntityCoords(GetPlayerPed(src)) - MARKET) > 5.0 then return end
local item = Player.Functions.GetItemByName('fish')
local count = item and item.amount or 0
if count < 1 then
return TriggerClientEvent('QBCore:Notify', src, 'You have no fish', 'error')
end
if Player.Functions.RemoveItem('fish', count) then
Player.Functions.AddMoney('cash', count * PRICE, 'fish-market')
TriggerClientEvent('QBCore:Notify', src, ('Sold %d fish for $%d'):format(count, count * PRICE), 'success')
end
end)local MARKET = vec3(-1845.0, -1195.0, 14.3)
CreateThread(function()
while true do
local sleep = 1000
if #(GetEntityCoords(PlayerPedId()) - MARKET) < 2.0 then
sleep = 0
if IsControlJustReleased(0, 38) then
TriggerServerEvent('fishmarket:sell')
end
end
Wait(sleep)
end
end)Usable items
QBCore.Functions.CreateUseableItem('bandage', function(source, item)
local Player = QBCore.Functions.GetPlayer(source)
if Player.Functions.RemoveItem(item.name, 1, item.slot) then
TriggerClientEvent('medical:useBandage', source)
end
end)Define the item in qb-core/shared/items.lua (or in ox_inventory/data/items.lua if you run ox_inventory). The shared list is available as QBCore.Shared.Items.
Commands
QBCore.Commands.Add('givefish', 'Give fish to a player', {
{ name = 'id', help = 'Player ID' },
{ name = 'amount', help = 'Amount' },
}, true, function(source, args)
local target = QBCore.Functions.GetPlayer(tonumber(args[1]))
if target then target.Functions.AddItem('fish', tonumber(args[2]) or 1) end
end, 'admin')The last argument is the permission level (user, mod, admin, god), which QBCore maps to ACE groups like qbcore.admin — see ACE permissions.
Client-side player data
local PlayerData = {}
RegisterNetEvent('QBCore:Client:OnPlayerLoaded', function()
PlayerData = QBCore.Functions.GetPlayerData()
end)
RegisterNetEvent('QBCore:Client:OnJobUpdate', function(job)
PlayerData.job = job
end)Compare with the ESX tutorial — the same fish market, different vocabulary. Qbox, the QBCore successor, keeps most of this API while moving to ox_lib patterns.
Frequently asked questions
How do I get the QBCore object?
local QBCore = exports['qb-core']:GetCoreObject() in both client and server scripts.
How do I add money in QBCore?
Player.Functions.AddMoney('cash', amount, reason) — or 'bank' / 'crypto'.
Where are QBCore items defined?
In qb-core/shared/items.lua, or in your inventory resource if it keeps its own list (ox_inventory).
How do I restrict a QBCore command to admins?
Pass 'admin' as the last argument of QBCore.Commands.Add and give staff the matching ACE group.
Need this built, not just explained?
Ten years of FiveM work, from Lua to NUI
Custom resources, React NUI, ESX / QBCore / Qbox integration, OneSync performance audits and security reviews — plus the websites and SEO around your server brand.
Related guides
- FrameworksWriting your first ESX Legacy scriptImport ESX with shared_script '@es_extended/imports.lua' (or exports.es_extended:getSharedObject()). On the server, ESX.GetPlayerFromId(source) returns xPlayer, which handles money (addMoney, addAccountMoney('bank', …)), items (addInventoryItem, getInventoryItem), and the job (xPlayer.job.name, .grade). Register usable items with ESX.RegisterUsableItem and commands with ESX.RegisterCommand. On the client use ESX.PlayerData and the esx:playerLoaded and esx:setJob events.
- FrameworksCallbacks: asking the server a question and getting an answerA callback registers a named handler on one side and lets the other side call it and receive its return value. With ox_lib use lib.callback.register on the server and lib.callback.await on the client (it also works server → client). ESX uses ESX.RegisterServerCallback / ESX.TriggerServerCallback, QBCore QBCore.Functions.CreateCallback / QBCore.Functions.TriggerCallback. Validate inside callbacks exactly like events.
- EngineeringWriting server events that cannot be abusedAny client can call any event you registered with RegisterNetEvent, with any arguments. In each handler: copy source into a local, check argument types and ranges, re-derive everything from server state (prices, amounts, rewards), verify the player can do this now (distance, job, item, cooldown), and log refusals. Events only other server scripts should use are registered with AddEventHandler alone, so clients cannot trigger them.
- FrameworksAdding interactions with ox_targetCall ox_target exports from your client script: addModel for every prop of a model, addGlobalVehicle/addGlobalPed/addGlobalPlayer for all of a type, addLocalEntity/addEntity for specific entities, and addBoxZone/addSphereZone for places. Each option has a name, label, icon, optional distance (default 7), groups, items and canInteract, and runs onSelect, an event, a serverEvent or a command.