FiveM drug system design: gathering, processing and selling safely
How to design a FiveM drug system: gathering and processing with server-side item checks, rate limits, selling to NPCs safely, police alerts and balancing payouts.
The symptom: players have thousands of drugs in minutes, sell the same item to the same NPC forever, or earn ten times what a job pays with no police alert at all.
A drug system has three stages: gather, process and sell. All three follow the same rule: the client asks, the server checks and decides. This article shows the checks and the balance questions that matter.
The three stages
| Stage | What happens | What the server must check |
|---|---|---|
| Gather | Player picks a plant, mines a resource | Location, cooldown, a rate limit |
| Process | Raw items become a finished product | The player has the items, is at the process spot |
| Sell | Product turns into money or dirty money | The item, the buyer, the price, the cooldown |
Each stage consumes or creates items, so the safe design uses your inventory's server functions. The item creation side is in adding items to ox_inventory.
Server-side item checks
Never trust a client that says "I have 10 of this". Ask the inventory on the server, remove the inputs, then add the outputs, in one place:
-- server
RegisterNetEvent('drugs:process', function()
local src = source
if not isNearProcessor(src) then return end -- distance check on the server
local count = exports.ox_inventory:GetItemCount(src, 'weed_leaf')
if count < 3 then return end
if exports.ox_inventory:RemoveItem(src, 'weed_leaf', 3) then
exports.ox_inventory:AddItem(src, 'weed_bag', 1)
end
end)Remove first, add second, and only add when the removal succeeded. If you add first, a player who spams the event can keep the output and lose nothing. Check for canCarryItem before adding if players can be full.
Rate limits
Even a legitimate event can be abused by firing it from a loop. Give each action a minimum delay per player, kept on the server:
local lastAction = {}
local function rateLimited(src, key, ms)
local now = GetGameTimer()
lastAction[src] = lastAction[src] or {}
if lastAction[src][key] and now - lastAction[src][key] < ms then
return true
end
lastAction[src][key] = now
return false
endSet the delay a bit under what the real action takes, so honest players are never blocked. Remember to clear lastAction[src] on playerDropped so the table does not grow forever. Gathering should also be limited by location: a plant that exists in one field must not be pickable from anywhere.
Selling to NPCs safely
Selling to pedestrians is the most abused part, because the client picks the ped. Add the option with your target library on the client, for example on all peds:
-- client (ox_target)
exports.ox_target:addGlobalPed({
{
label = 'Offer drugs',
icon = 'fa-solid fa-cannabis',
distance = 2.0,
canInteract = function(entity)
return not IsPedAPlayer(entity) and not IsEntityDead(entity)
end,
onSelect = function(data)
TriggerServerEvent('drugs:sell', 'weed_bag')
end,
},
})Targeting basics are in adding ox_target zones. Notice that the client sends only the item name. Everything else is decided on the server:
RegisterNetEvent('drugs:sell', function(item)
local src = source
local price = Config.Prices[item]
if not price then return end -- only allowed items
if rateLimited(src, 'sell', 4000) then return end -- cooldown between deals
if exports.ox_inventory:RemoveItem(src, item, 1) then
local payout = math.random(price.min, price.max)
exports.ox_inventory:AddItem(src, 'black_money', payout)
end
end)The price comes from the server config, never from the client. The item name should be checked against an allowed list, because a client could send any name. Add a random chance that the NPC refuses or reports you. If the sale needs the player to be in a zone or at night only, check that on the server too. The black_money item name depends on your setup; see money types.
Police alerts
Risk is what makes drugs interesting. Alert the police on a chance, from the server, with the location of the deal:
- A percentage chance on every sale (for example a small chance that the NPC calls the police).
- A larger chance when fewer deals have been made in a quiet area, or when many deals happen in the same spot.
- A required minimum of on-duty officers for selling and processing, counted on the server, as in setting up a police job.
If you use a phone app for deals, orders and meeting points should still be created and checked on the server.
Drug Dealer AppStreet sales as an lb-phone app: zones, NPC buyers, levels and police alerts.from β¬18.15View script β
Balancing payouts
Balance in numbers, not in feeling:
- Time one full loop (gather, process, sell) and count how many minutes it takes.
- Compute money per hour: payout times loops per hour.
- Compare it with your best legal job's paycheck. Drugs may pay more, because of the risk, but a factor of two or three is plenty.
- Add friction: processing time, item weight, a limited number of sales per NPC, a cooldown per location.
Then watch the money in your database after a week and adjust. The method is in balancing your server economy.
Checklist
| Symptom | Fix |
|---|---|
| Infinite items | Check location, remove inputs first and rate limit on the server |
| Client sets the price | Take prices from the server config only |
| Sells any item as drugs | Check the item name against an allowed list |
| Same NPC buys forever | Add a cooldown per player and per ped or location |
| Drugs pay too much | Compare money per hour with a normal job |
| No police reaction | Alert on a chance, from the server |
Quick answers
Why do players get unlimited drugs?
The gather or process event runs on the server without checking location, time or limits, so a modified client can fire it in a loop. Add the checks and a rate limit on the server.
How do I let players sell drugs to NPCs?
Add a target option to pedestrians on the client, then let the server check the item, the distance, a cooldown and the price before it pays. The client only asks.
How do I balance drug payouts?
Work out the money per hour a player can earn and compare it with a normal job. Drugs can pay more because of the risk, but not so much that nobody does anything else.

