You can access the setup information you need about this product
🚀 Installation
Welcome to the Wert Drug Selling System documentation. Follow these steps to install and configure the script on your server.
Note: This script is encrypted using FiveM Asset Escrow system. Ensure your server license key is linked to the same CFX account used for the purchase.
📋 Requirements
Before installing, ensure you have the following dependencies installed and started:
Download the wert_drugsell package from your Keymaster assets. Extract the folder into your server's resources directory.
2. Configure Framework
Open shared/config.lua and ensure the framework settings match your server.
Lua
3. Database Setup (Auto-Install) ✨
You do not need to run any SQL files manually.
The script includes an Auto-Migration system. When you start the script for the first time, it will automatically create the necessary database tables (wert_drugsell_users, transactions, etc.) and load the dealers.
4. Add Items to Inventory
Since this script works seamlessly with ox_inventory, you need to register the drug items and the tablet.
Open ox_inventory/data/items.lua and paste the following codes:
Lua
{% hint style="warning" %}
Important: Ensure the item names match exactly what is in your Config.Drugs inside shared/config.lua. If you change item names there, change them here too.
{% endhint %}
5. Item Images
Copy the images provided in the assets/images folder of the script and paste them into:
ox_inventory/web/images/
6. Server Config
Add the script to your server.cfg file. Ensure it is started after the dependencies.
Kod snippet'i
7. Restart Server
Restart your server. Watch the server console; you should see a message confirming that the database tables have been checked and dealers have been initialized.
🌍 Localization (Translation)
You can easily translate the entire interface without editing the source code.
Navigate to wert_drugsell/web/build/locales.json.
Open the file with any text editor (VS Code, Notepad++).
Edit the values on the right side to your desired language.
Restart the script.
Example:
JSON
OPEN FILES
SHARED/CONFIG.LUA
CLIENT/EDITABLE_CLIENT.LUA
SERVER/EDITABLE_SERVER.LUA
🆘 Support
If you encounter any issues during installation, please check the server console for errors first. For further assistance, join our Discord Server and open a ticket.
Config = {}
Config.Debug = false
Config.Framework = 'qb' -- 'qb' or 'esx' or 'qbox'
Config.TabletItem = 'drugtablet'
Config.TabletStream = {
dict = "amb@code_human_in_bus_passenger_idles@female@tablet@idle_a",
clip = "idle_a",
flag = 49,
model = `prop_cs_tablet`,
bone = 28422,
pos = vector3(-0.05, 0.0, 0.0),
rot = vector3(0.0, 0.0, 0.0)
}
Config.MoneyIcon = "nui://ox_inventory/web/images/money.png"
Config.PoliceAlertChance = {
active = false,
param = 10
}
Config.GangControl = { -- Do you want only the gangs to have access?
active = false, -- active state?
perms = { -- allowed gangs for system?
ballas = true,
vagos = true,
families = true,
-- If u want add more
}
}
Config.CornerSellChance = 50
Config.CornerSellCooldown = 0
Config.Levels = {
[1] = { requiredXP = 0, label = "Street Rat" },
[2] = { requiredXP = 500, label = "Runner" },
[3] = { requiredXP = 1500, label = "Hustler" },
[4] = { requiredXP = 3500, label = "Supplier" },
[5] = { requiredXP = 7000, label = "Kingpin" },
}
Config.Drugs = {
['weed_ak47'] = {
label = "Weed Baggy",
price = { min = 150, max = 220 },
xp = 10,
risk = false,
image = "nui://ox_inventory/web/images/weed_ak47.png"
},
['cokebaggy'] = {
label = "Bag of Coke",
price = { min = 300, max = 450 },
xp = 25,
risk = true,
image = "nui://ox_inventory/web/images/cokebaggy.png"
},
['meth'] = {
label = "Meth Crystal",
price = { min = 400, max = 600 },
xp = 35,
risk = true,
image = "nui://ox_inventory/web/images/meth_baggy.png"
}
}
Config.Dealers = {
['gustavo'] = {
name = "Gustavo",
region = "South Side",
coords = vector4(-92.3008, -2205.0381, 7.8117, 0.4437), -- Koordinatları ayarla
model = 'g_m_y_mexgoon_01',
image = "nui://wert_drugsell/web/images/dealers/gustavo.png"
},
['vlad'] = {
name = "Little Vlad",
region = "Downtown",
coords = vector4(-98.6998, -2205.0425, 7.8117, 2.4237),
model = 'a_m_y_business_02',
image = "nui://wert_drugsell/web/images/dealers/littlevlad.png"
}
}
Config.MessageItemControl = true -- # For the get messages from buyer, player must be a drug tablet in inventory.
Config.MessageChance = { -- Do you want an extra chance check so that the message can be sent to the player?
active = false,
param = 10, -- Max 100
}
Config.MessageSettings = {
minTime = 2, -- Min Time For Get Message 2
maxTime = 5, -- Max Time For Get Message 5
npcNames = { "Unknown", "Customer", "Junkie", "Blue", "Ghost", "T-Bone" },
maxPendingLimit = 3, -- How many unread messages can a player have?
expirationTime = 30, -- How many minutes should the message be deleted after?
allowExpire = true, -- expirationTime? can work ?
locations = {
{ label = "Grove St. Gas Station", coords = vector3(-62.8336, -1784.8881, 26.9940), heading = 141.2766 },
{ label = "Mirror Park", coords = vector3(1113.1360, -636.4269, 55.8128), heading = 99.8651 },
{ label = "Vespucci Canals", coords = vector3(-1100.9879, -1196.3208, 1.3549), heading = 303.2260 },
-- Buraya daha fazla koordinat ekle
}
}
Config.BuyerPeds = {
'a_m_y_beach_01', 'a_m_y_genstreet_01', 'g_m_y_ballaeast_01',
'a_f_y_hipster_01',
}
Config.CornerPositions = {
{ pos = vector4(-1179.1772, -1509.5145, 4.3453, 205.0501), distance = 150.0 },
{ pos = vector4(14.3249, -1663.2289, 29.2768, 318.2131), distance = 150.0 },
{ pos = vector4(209.6659, -71.7806, 69.0762, 40.8674), distance = 150.0 }
}
Config.SomeLangs = {
locationSet = "Buyer location set. Go meet them.",
permission = 'You are not have permission for that!',
goDealer = "Go to %s to collect cash.",
itemError = "You don't have the items!",
noFunds = "No funds to collect.",
soldMessage = "Sold %sx %s for $%s",
collectedMessage = "Collected $%s from %s",
noNeedItem = 'You are not have enough item!',
}
Framework = nil
local oxInventoryActive = GetResourceState('ox_inventory') == 'started'
if Config.Framework == 'qb' or Config.Framework == 'qbox' then
Framework = exports['qb-core']:GetCoreObject()
elseif Config.Framework == 'esx' then
Framework = exports["es_extended"]:getSharedObject()
end
-- # Global Variables
drugSellDuty = false
MyGang = 'nil'
drugSelectedItems = {}
local function LoadPlayerMetas()
Wait(1000)
local myPlayerData = lib.callback.await('wert_drugsell:server:load-player-meta', false)
drugSellDuty = myPlayerData.drugSellDuty
drugSelectedItems = myPlayerData.drugSelectedItems
MyGang = myPlayerData.MyGang
end
function SelectCustomNotify(text, style, duration)
lib.notify({ title = 'Drug Sell', description = text, type = style, duration = duration })
end
function CheckPoliceAlert(data)
if not data then return end
-- data table inners if u want use in police call
--[[ data.label -> Label
data.image -> Image
data.amount -> Amount
data.price -> Price ]]
-- data.type -> 'mission_sell' or 'dealer_collect' or 'corner_sell'
local pos = GetEntityCoords(cache.ped) -- # Alert Position
-- Add ur police alert export
end
function CheckHasItem(key)
if oxInventoryActive then
local itemCount = exports.ox_inventory:GetItemCount(key)
if itemCount and itemCount > 0 then
return true
end
return false
end
if Config.Framework == 'qb' or Config.Framework == 'qbox' then
return QBCore.Functions.HasItem(key)
end
return false
end
function WertGetPeds(ignoreList)
ignoreList = ignoreList or {}
local ents = GetGamePool('CPed')
local entities = {}
local ignoreMap = {}
for i = 1, #ignoreList do
ignoreMap[ignoreList[i]] = true
end
for i = 1, #ents do
local entity = ents[i]
if not ignoreMap[entity] then
entities[#entities + 1] = entity
end
end
return entities
end
RegisterNetEvent('wert_drugsell:client:custom-select-notify', SelectCustomNotify)
AddEventHandler('onResourceStart', function(resource)
if resource ~= GetCurrentResourceName() then return end
LoadPlayerMetas()
end)
RegisterNetEvent('QBCore:Client:OnPlayerLoaded', function()
LoadPlayerMetas()
end)
RegisterNetEvent('esx:playerLoaded', function()
LoadPlayerMetas()
end)
Framework = nil
Bridge = {}
if Config.Framework == 'qb' or Config.Framework == 'qbox' then
Framework = exports['qb-core']:GetCoreObject()
elseif Config.Framework == 'esx' then
Framework = exports["es_extended"]:getSharedObject()
end
local function SaveMetadataToSQL(citizenid, data)
if not citizenid then return end
MySQL.update('UPDATE wert_drugsell_users SET metadata = ? WHERE citizenid = ?', { json.encode(data or {}), citizenid })
end
local function GetMetadaFromSQL(citizenid, includeUserData)
local defaultMeta = { drug_duty = false, drug_selecteditems = {} }
local userData = MySQL.single.await('SELECT * FROM wert_drugsell_users WHERE citizenid = ?', {citizenid})
if not userData then
MySQL.insert.await('INSERT INTO wert_drugsell_users (citizenid, metadata) VALUES (?, ?)', { citizenid, json.encode(defaultMeta) })
if includeUserData then
userData = { xp = 0, level = 1, settings = nil, metadata = defaultMeta }
return userData
end
return defaultMeta
end
userData.metadata = userData.metadata and json.decode(userData.metadata) or defaultMeta
if includeUserData then
userData.settings = userData.settings and json.decode(userData.settings) or nil
return userData
end
return userData.metadata
end
function Bridge.GetPlayer(src)
if not src then return nil end
if Config.Framework == 'qb' or Config.Framework == 'qbox' then
return Framework.Functions.GetPlayer(src)
else
return Framework.GetPlayerFromId(src)
end
end
function Bridge.GetPlayerByIdentifier(identifier)
if not identifier then return nil end
if Config.Framework == 'qb' or Config.Framework == 'qbox' then
return Framework.Functions.GetPlayerByCitizenId(identifier)
else
return Framework.GetPlayerFromIdentifier(identifier)
end
end
function Bridge.GetPlayerIdentifier(ply)
if not ply then return nil end
if Config.Framework == 'qb' or Config.Framework == 'qbox' then
return ply.PlayerData.citizenid
end
return ply.getIdentifier()
end
function Bridge.AddMoney(src, account, amount)
local ply = Bridge.GetPlayer(src)
if not ply then return end
amount = tonumber(amount)
if Config.Framework == 'qb' or Config.Framework == 'qbox' then
ply.Functions.AddMoney(account, amount)
else
if account == 'cash' then
ply.addMoney(amount, "Drug Sell System")
else
ply.addAccountMoney(account, amount, "Drug Sell System")
end
end
end
function Bridge.RemoveItem(src, item, amount)
local ply = Bridge.GetPlayer(src)
if not ply then return end
amount = tonumber(amount)
if GetResourceState('ox_inventory') == 'started' then
local success = exports.ox_inventory:RemoveItem(src, item, amount)
return success
end
if Config.Framework == 'qb' or Config.Framework == 'qbox' then
local item = ply.Functions.GetItemByName(item)
if item and item.amount >= amount then
ply.Functions.RemoveItem(item, amount)
return true
end
else
local item = ply.getInventoryItem(item)
if item and item.count >= amount then
ply.removeInventoryItem(item, amount)
return true
end
end
return false
end
function Bridge.CanRemoveItem(src, item, amount)
local ply = Bridge.GetPlayer(src)
if not ply then return end
amount = tonumber(amount)
if GetResourceState('ox_inventory') == 'started' then
local itemCountt = exports.ox_inventory:GetItemCount(src, item)
if not itemCountt then itemCountt = 0 end
if itemCountt >= amount then
return true
end
return false
end
if Config.Framework == 'qb' or Config.Framework == 'qbox' then
local item = ply.Functions.GetItemByName(item)
if item and item.amount >= amount then
return true
end
else
local item = ply.getInventoryItem(item)
if item and item.count >= amount then
return true
end
end
return false
end
function Bridge.SetDuty(src, state)
local ply = Bridge.GetPlayer(src)
if not ply then return end
local citizenid = Bridge.GetPlayerIdentifier(ply)
local metadata = GetMetadaFromSQL(citizenid)
metadata.drug_duty = state
SaveMetadataToSQL(citizenid, metadata)
end
function Bridge.SetSelectedItems(src, data)
local ply = Bridge.GetPlayer(src)
if not ply then return end
local citizenid = Bridge.GetPlayerIdentifier(ply)
local metadata = GetMetadaFromSQL(citizenid)
metadata.drug_selecteditems = data
SaveMetadataToSQL(citizenid, metadata)
end
function Bridge.GetUIComponents(ply, includeUserData)
if not ply then return nil end
local citizenid = Bridge.GetPlayerIdentifier(ply)
local userData = GetMetadaFromSQL(citizenid, includeUserData)
local metadata = includeUserData and userData.metadata or userData
if Config.Framework == 'qb' or Config.Framework == 'qbox' then
return {
name = ply.PlayerData.charinfo.firstname .. " " .. ply.PlayerData.charinfo.lastname,
cash = ply.PlayerData.money['cash'],
isDuty = metadata.drug_duty,
selectedItems = metadata.drug_selecteditems or {},
gang = ply.PlayerData.gang.name,
userData = includeUserData and userData or nil
}
else
return {
name = ply.getName(),
cash = ply.getMoney(),
isDuty = metadata.drug_duty,
selectedItems = metadata.drug_selecteditems or {},
gang = 'none', -- If u use any gang system please provide export !IMPORTANT FOR ESX USERS
userData = includeUserData and userData or nil
}
end
end
function Bridge.FramePlayers()
if Config.Framework == 'qb' or Config.Framework == 'qbox' then
return Framework.Functions.GetPlayers()
else
return Framework.GetPlayers()
end
end
function Bridge.Source(ply)
if not ply then return 0 end
if Config.Framework == 'qb' or Config.Framework == 'qbox' then
return ply.PlayerData.source
else
return ply.source
end
end
function Bridge.CheckTablet(ply, src)
if not ply then return false end
if GetResourceState('ox_inventory') == 'started' then
local tabletCount = exports.ox_inventory:GetItemCount(src, Config.TabletItem)
if not tabletCount then tabletCount = 0 end
if tabletCount > 0 then return true end
return false
end
if Config.Framework == 'qb' or Config.Framework == 'qbox' then
local item = ply.Functions.GetItemByName(Config.TabletItem)
if item and item.amount > 0 then
return true
end
else
local item = ply.getInventoryItem(Config.TabletItem)
if item and item.count > 0 then
return true
end
end
return false
end
-- # Item Use
if Config.Framework == 'qb' or Config.Framework == 'qbox' then
Framework.Functions.CreateUseableItem(Config.TabletItem, function(source)
TriggerClientEvent('wert_drugsell:client:openTablet', source)
end)
else
Framework.RegisterUsableItem(Config.TabletItem, function(playerId)
TriggerClientEvent('wert_drugsell:client:openTablet', tonumber(playerId))
end)
end