lation scripts
scriptsmembershipdocs
see the scripts
Skip to Content
lation ui
lation interact
lation banking
lation shops
lation jobs
lation weed
lation chop shop

classics

money laundering
drug sales
SellingConfigurationDevelopersChangelog
coke processing
meth crafting
metal detecting
scuba diving
drug sales

Developers

The drug sales server and client exports, its notification event and state bag, and the open functions for prices, payouts, police counts, dispatch and sale checks.

Every export is called on exports.lation_selling. Server exports that act on a player take their server id as source; client exports work on the local player. A player's identifier is the ESX identifier on ESX and the citizenid on Qbox and QBCore.

Server exports

ExportReturns
GetData(source, type?)A player's record, or one field of it
AddData(source, amount, dataType)Nothing
CheckLevel(source)Nothing
PoliceCount()Police on duty
TotalSales(source, zoneId)Drugs the player sold in a capped zone this session

GetData

Server export

local data = exports.lation_selling:GetData(source, type)

Parameters

sourcenumber
The player's server id
typestringoptionaldefault nil
One field: level, rep, total_sales or total_earned. The whole record when left out.

Returns

table | number | nil
The record (below), or the value of type. nil when the player isn't loaded in your framework.

The first time a player is looked up, their row is read from the lation_selling table, or created at level 1. The record is the cached one, so treat it as read-only and change it with AddData.

{
    level = 2,
    rep = 4120,            -- earned since the last level up; held at levelUp at the top level
    total_sales = 318,     -- drugs sold, all time
    total_earned = 52440,  -- money made, all time
    identifier = 'ABC12345', -- present once the record has come from the table
}
server.lua
local level = exports.lation_selling:GetData(source, 'level')
if level and level >= 3 then
    -- unlock something
end

AddData

Server export

exports.lation_selling:AddData(source, amount, dataType)

Parameters

sourcenumber
The player's server id
amountnumber
How much to add. Negative numbers and anything that isn't a number do nothing.
dataTypestring
rep, level, total_sales or total_earned

Returns

Nothing

Adding rep doesn't level the player up on its own: call CheckLevel after it. At the top level, rep can't be added. Nothing is written straight away: records are saved when the player leaves, when the resource stops and when txAdmin shuts the server down.

server.lua
exports.lation_selling:AddData(source, 500, 'rep')
exports.lation_selling:CheckLevel(source)

CheckLevel

Server export

exports.lation_selling:CheckLevel(source)

Parameters

sourcenumber
The player's server id

Returns

Nothing

If the player's rep has reached Config.Reputation.levelUp, raises their level by as many levels as it covers, keeps the rest as rep, shows "Congratulations, you've leveled up!" and writes the leveled log when it's on. Does nothing at the top level. Every sale calls it.

PoliceCount

Server export

local police = exports.lation_selling:PoliceCount()

Returns

number
Players with a job in Config.Police.jobs; on Qbox and QBCore, only those on duty

This is GetPoliceCount in server/functions.lua, so a change there changes the export too.

TotalSales

Server export

local sold = exports.lation_selling:TotalSales(source, zoneId)

Parameters

sourcenumber
The player's server id
zoneIdnumber
The zone's index in Config.Zones

Returns

number
Drugs the player has sold in that zone since drug sales last started

Sales are only counted in zones with limit on, toward their cap. In any other zone it stays 0.

Client exports

ExportReturns
GetData(type?)The local player's record, or one field of it
PoliceCount()Police on duty
TotalSales(zoneId)Drugs the local player sold in a capped zone this session

All three ask the server, so call them from a thread, not every frame.

GetData (client)

Client export

local data = exports.lation_selling:GetData(type)

Parameters

typestringoptionaldefault nil
One field: level, rep, total_sales or total_earned

Returns

table | number
The record or the field, as the server export returns it. 0 when there is none.
client.lua
local level = exports.lation_selling:GetData('level')

PoliceCount (client)

Client export

local police = exports.lation_selling:PoliceCount()

Returns

number
The same count as the server export

TotalSales (client)

Client export

local sold = exports.lation_selling:TotalSales(zoneId)

Parameters

zoneIdnumber
The zone's index in Config.Zones

Returns

number
The same count as the server export

Events

lation_selling:Notify

Client event

TriggerClientEvent('lation_selling:Notify', source, message, type)

Parameters

messagestring
The text
typestring
success, error, inform and the like, as your notification system reads them

Send it from the server to show a notification through Config.Setup.notify, titled "Drugs".

server.lua
TriggerClientEvent('lation_selling:Notify', source, 'A new buyer is asking around Vespucci', 'inform')

State bag

drugSale

Entity state bag

local state = Entity(ped).state.drugSale

Returns

string | nil
'pending' while a player has that ped's menu open, 'sold' once the ped has dealt, refused or been sent away, nil before

Set by the server and seen by every client. A ped that is pending or sold can't be sold to, by anyone. Your own scripts can read it, for example to skip peds that have already dealt.

Server functions

server/functions.lua ships open. drug sales calls these functions by name, so keep each one defined with the same arguments when you edit it.

DrugSold

Server function

function DrugSold(source, zoneId, item, quantity, value, xpAdded, metadata) end

Parameters

sourcenumber
The seller's server id
zoneIdnumber
The zone's index in Config.Zones
itemstring
The item sold
quantitynumber
How many
valuenumber
What the seller was paid
xpAddednumber
The reputation the sale gave
metadatatable | nil
The item's metadata, such as purity

Called after every completed sale, once the item is taken and the seller is paid. It ships with an example for a gang script that does nothing until you edit it.

server/functions.lua
function DrugSold(source, zoneId, item, quantity, value, xpAdded, metadata)
    if metadata and metadata.purity == 100 then
        -- a perfect batch: reward it in your own script
        TriggerEvent('my_gangs:addRespect', source, 10 * quantity)
    end
end

(my_gangs:addRespect stands for your own script's event.)

ItemsClaimed

Server function

function ItemsClaimed(source, item, quantity) end

Parameters

sourcenumber
The player's server id
itemstring
The item taken back
quantitynumber
How many

Called when a player takes back drugs a buyer robbed them of. Empty by default.

CreateSaleQuote

Server function

function CreateSaleQuote(source, zoneId, item, itemCount) end

Parameters

sourcenumber
The seller's server id
zoneIdnumber
The zone's index in Config.Zones
itemstring
The item
itemCountnumber
How many the seller carries

Returns

table | nil
The quote (below), or nil to leave the drug out of the menu

Works out each drug's offer when the menu opens, as described under prices: the purity or the zone's range, the police risk, the level's boost and the quantity. The server keeps the quote and pays its total if the sale goes through.

{
    price = 120,            -- one, before bonuses ("Buyer will buy for")
    difference = 18,        -- what police risk adds to one ("Risk bonus")
    unitPrice = 144,        -- one, with both bonuses
    quantity = 1,           -- "Buyer wants a total of"
    total = 144,            -- "Total sale is worth", what is paid
    missingMetadata = false, -- true when a Config.Metadata item had no value
}

PayPlayer

Server function

function PayPlayer(source, zoneId, item, amount) end

Parameters

sourcenumber
The seller's server id
zoneIdnumber
The zone's index in Config.Zones
itemstring
The item sold
amountnumber
The sale's total

Pays the zone's money, as described under money. Edit it to pay another way, for example into a gang's account.

GetPoliceCount

Server function

function GetPoliceCount() end

Returns

number
Police on duty

Used for police risk, for zones that need police, and by the PoliceCount exports.

GetMetadata

Server function

function GetMetadata(source, item) end

Parameters

sourcenumber
The player's server id
itemstring
The item

Returns

table | nil
The metadata of the first stack of that item the player carries

Reads purity for purity pricing, and keeps a robbed item's metadata so it comes back the same.

PlayerLog

Server function

function PlayerLog(source, title, message) end

Parameters

sourcenumber
The player's server id
titlestring
The log's title from Strings.Logs
messagestring
The filled-in message

Sends a log to the service in Logs.Service. See logs.

Client functions

client/functions.lua ships open too. The ones you're most likely to edit:

CanSell

Client function

function CanSell(zoneId) end

Parameters

zoneIdnumber
The zone's index in Config.Zones

Returns

boolean
false to stop the sale

Asked each time a player starts a sale, before the menu opens. By default it stops a player in a vehicle with "You cannot sell from inside your vehicle".

client/functions.lua
function CanSell(zoneId)
    if IsPedInAnyVehicle(cache.ped, true) then
        ShowNotification(Strings.Notify.noVehicle, 'error')
        return false
    end
    -- Rockford Hills (zone 6) only deals with players carrying a burner phone (ox_inventory)
    if zoneId == 6 and exports.ox_inventory:Search('count', 'burner_phone') < 1 then
        ShowNotification('Nobody here trusts you without a burner', 'error') 
        return false
    end
    return true
end

PoliceDispatch

Client function

function PoliceDispatch(data) end

Parameters

data.coordsvector3
Where the seller stands
data.streetstring
The street's name

Sends the police alert for the dispatch in Config.Setup.dispatch. Add yours under the custom branch; see dispatch.

The rest

FunctionWhat it does
ShowNotification(message, type)Shows a notification through Config.Setup.notify, with a custom slot
ShowTextUI(text, icon), HideTextUI(label)The prompts, through the textui line at the top of the file
RegisterMenu(data), ShowMenu(menuId)The menu, through Config.Setup.menu
AddTargetGlobal, AddTargetEntity, RemoveTargetGlobal, RemoveTargetEntityThe target options, through Config.Setup.target
SetEntityEvents(entity), ClearEntityEvents(entity)Hold a buyer still, facing the seller and unhurt while the menu is open, then let them go

Open files

PathWhat it's for
config.luaEvery option; see configuration
strings.luaEvery line players read
logs.luaLogging, read by the server only
bridge/client.lua, bridge/server.luaFramework and inventory support, with slots for a custom framework or inventory
client/functions.luaNotifications, prompts, menus, targets, dispatch and CanSell
server/functions.luaPrices, payouts, the police count, metadata, logging and the sale hooks

Still stuck? Ask in our Discord: the people who write the scripts answer.

Last updated November 11, 2026

Configuration

Every drug sales option in config.lua, strings.lua and logs.lua with its default, plus the prompt setting in client/functions.lua.

Changelog

Every drug sales release, newest first, with what it added, changed and fixed.

On this page

Server exportsGetDataAddDataCheckLevelPoliceCountTotalSalesClient exportsGetData (client)PoliceCount (client)TotalSales (client)Eventslation_selling:NotifyState bagdrugSaleServer functionsDrugSoldItemsClaimedCreateSaleQuotePayPlayerGetPoliceCountGetMetadataPlayerLogClient functionsCanSellPoliceDispatchThe restOpen files
lation scripts

FiveM scripts for Qbox, QBCore and ESX servers, made to look and work like one product.

store

  • all scripts
  • membership
  • classics

help

  • docs
  • discord
  • email support

legal

  • terms
  • refunds
  • privacy
© 2026 Lation Labslationscripts.com
  • home
  • scripts
  • membership
  • docs