FiveM & QBCore · Practical guide

QBCore Hunting Job — Build a secure, server-authoritative hunting resource

Step-by-step guide to implement a QBCore hunting job for FiveM: plan, files, server validation, client interactions, installation checklist, and security notes for a production-ready.

Stellar AI · Updated 8 September 2026 · 4 min read

This guide walks a FiveM builder through creating a server-authoritative QBCore hunting job. It includes a short implementation plan, assumptions, complete destination-labelled files, installation steps, validation and anti-cheat notes, and quick next steps so you can ship a safe hunting script.

Implementation plan

Short plan (do these in order):

  1. Decide scope: free-for-all hunting or job-locked. Configure animal spawn points and sell/pelt items in config.lua.
  2. Create resource manifest and server/client scripts. Use server events for all state changes: giving/removing items, paying money.
  3. Integrate interaction (qb-target or keybind) on client; call server events for authoritative actions.
  4. Test with multiple players, check item integrity, and apply anti-spam/cooldowns on server.

Assumptions & framework dependencies

Assumptions: you use QBCore v1/v2 style exports (exports['qb-core']:GetCoreObject()). The guide avoids inventory API specifics beyond common functions: QBCore.Functions.GetPlayer, Player.Functions.AddItem, Player.Functions.RemoveItem, and Player.Functions.AddMoney. If you use ox_inventory or a different core, adapt those calls accordingly. Optional: qb-target for interaction targets.

Destination-labelled files

Place these files inside a resource folder named qb-hunting. The list below is complete for a minimal, secure hunting job.

fxmanifest.lua

fx_version 'cerulean'
games {'gta5'}

author 'Your Name'
description 'QBCore Hunting Job'
version '1.0.0'

shared_scripts {
  'config.lua'
}

client_scripts {
  'client/main.lua'
}

server_scripts {
  'server/main.lua'
}

dependencies {
  'qb-core'
}

config.lua

Config = {}

-- Toggle whether only players with a specific job can sell pelts
Config.RequireJob = false
Config.AllowedJob = 'hunter' -- only used if RequireJob = true

-- Prices per pelt item
Config.Prices = {
  ['pelt_rabbit'] = 50,
  ['pelt_deer'] = 250,
  ['pelt_bear'] = 800
}

-- Sell ped/coords -- simple single location example
Config.SellLocation = { x = 2442.0, y = 4969.0, z = 41.35 }

-- Server-side cooldown (ms) per player to prevent spam
Config.SellCooldown = 1500

server/main.lua

local QBCore = exports['qb-core']:GetCoreObject()
local lastSell = {} -- source -> timestamp

RegisterNetEvent('qb-hunting:server:SellPelt', function(peltItem)
  local src = source
  local now = os.time() * 1000
  if lastSell[src] and (now - lastSell[src]) < Config.SellCooldown then
    TriggerClientEvent('QBCore:Notify', src, 'Please wait before selling again', 'error')
    return
  end

  local Player = QBCore.Functions.GetPlayer(src)
  if not Player then return end

  if Config.RequireJob and Player.PlayerData.job.name ~= Config.AllowedJob then
    TriggerClientEvent('QBCore:Notify', src, 'Your job cannot sell these pelts', 'error')
    return
  end

  local item = Player.Functions.GetItemByName(peltItem)
  if not item then
    TriggerClientEvent('QBCore:Notify', src, 'You have no pelts to sell', 'error')
    return
  end

  local price = Config.Prices[peltItem] or 0
  if price <= 0 then
    TriggerClientEvent('QBCore:Notify', src, 'This pelt cannot be sold', 'error')
    return
  end

  -- Remove exactly one pelt, server-side authoritative
  local removed = Player.Functions.RemoveItem(peltItem, 1, false)
  if removed then
    Player.Functions.AddMoney('cash', price, 'hunting-pelt-sell')
    TriggerClientEvent('QBCore:Notify', src, 'Sold pelt for $' .. price, 'success')
    lastSell[src] = now
  else
    TriggerClientEvent('QBCore:Notify', src, 'Failed to remove pelt', 'error')
  end
end)

client/main.lua

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

-- Example: direct sell interaction at a fixed coord (also support qb-target externally)
Citizen.CreateThread(function()
  while true do
    local sleep = 2000
    local ped = PlayerPedId()
    local pCoords = GetEntityCoords(ped)
    local dist = #(pCoords - vector3(Config.SellLocation.x, Config.SellLocation.y, Config.SellLocation.z))
    if dist < 3.0 then
      sleep = 5
      -- show prompt (use your notification/UI) and listen for keypress
      -- For brevity we use a simple key check
      if IsControlJustReleased(0, 38) then -- E
        -- open a sell menu or attempt to sell a default item
        -- In real use, show player's pelts and select item to sell
        TriggerServerEvent('qb-hunting:server:SellPelt', 'pelt_deer')
      end
    end
    Citizen.Wait(sleep)
  end
end)

Installation & where files belong

  • Create folder resources/[local]/qb-hunting
  • Drop the files above into that folder with the same filenames.
  • Start the resource in server.cfg: ensure qb-hunting
  • If you use qb-target, add target models or add an export in client/main.lua to register the sell spot.

Validation, security and anti-cheat notes

  • Never give money or remove items on the client. All state changes happen in server/main.lua.
  • Validate Player existence with QBCore.Functions.GetPlayer and check the real inventory with Player.Functions.GetItemByName.
  • Use cooldowns (Config.SellCooldown) and optionally server-side rate limits to stop automated farming.
  • Do not trust client-sent prices or counts; derive prices from server-side Config.Prices and remove items server-side.
  • If you integrate with a police or economy system, add logs and export events for auditing.
ChecklistWhy it matters
Server-only money/item changesPrevents spoofing and duping
Cooldown per playerMitigates rapid automated sells
Job checks (optional)Supports roleplay rules and monetization
qb-target integrationBetter UX than a keybind loop
Test with multiple playersFind race conditions and concurrency issues

Testing and validation steps

  1. Start the server and join as two players to test concurrency.
  2. Try selling without a pelt (should be denied).
  3. Give a pelt via your server admin tools or a spawn command, then sell and confirm money arrival in server logs.
  4. Attempt to spam sell to ensure cooldown and removal logic hold.
  5. Check resource logs for unexpected errors and tighten error handling.

Next practical steps

Improve realism by spawning animal entities client-side and dropping progressive pelt types. Add a butcher minigame client-side (only triggers a server event when completed), track pelt quality in item metadata, and provide NPC buyers with dynamic prices. For workflow acceleration, consider generating plan files and tests using a scripting workspace like Stellar AI — start at https://trystellarai.com/app to prototype resource structure and tests. When you publish or iterate, keep the spec and tests with the resource; Stellar AI can help with iteration at https://trystellarai.com/app. For articles and deeper design patterns see the engineering posts on the Stellar blog: https://trystellarai.com/blog.

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 →