NR_DrugSelling
A street-level drug selling system with a custom React tablet UI, buyer contacts, sell zones, NPC deal outcomes, leveling, leaderboards, street chat, police dispatch integration, and full anti-exploit protection.
Features
- Custom tablet UI - React interface with dashboard, inventory, sell, contacts, history, rank, leaderboard, and street chat tabs
- Config-driven drugs - Define any number of drugs with custom items, labels, base prices, and icons
- Buyer contacts - Configurable NPC buyers at specific locations, each with preferred drugs, price multipliers, risk levels, and level requirements
- Sell zones - Timed selling areas with radius blips, GPS routes, and NPC interaction within the zone
- Dynamic deal outcomes - NPCs can buy, rob you, attack you, call the cops, or ignore you — all with configurable chances
- Robber recovery - Kill an NPC that robbed you and search their body to recover stolen items
- Attack NPCs - Armed NPCs spawn and fight you with configurable weapons and despawn timers
- Leveling system - Earn XP per unit sold, unlock new contacts and higher sell limits as you level up
- Leaderboard - Server-wide rankings by total drugs sold, displayed with player aliases
- Street chat - In-app anonymous messaging system with alias support, persisted to database
- Transaction history - Full database-backed sale history with drug, buyer, price, quantity, and timestamps
- Police dispatch - Auto-detects 9 dispatch resources with manual LEO fallback
- Police requirements - Optional minimum LEO count to allow selling
- Scaled risk - Police alert and dispatch chances scale with player level
- Configurable theme - Set any hex accent color via config
- NR_Tablet integration - Optional app inside NR_Tablet, or standalone with keybind/command
- Multi-framework - ESX, QBCore, and QBX with auto-detection
- Multi-inventory - Supports 12+ inventory systems with auto-detection
- Multi-target - ox_target, qb-target, or E-key fallback
- Anti-exploit - Server-authoritative validation, rate limiting, race condition guards, input sanitization, and cooldown enforcement
- Localization - All UI text configurable via locales.lua
Dependencies
| Resource | Description | Required |
|---|---|---|
| ox_lib | Notifications, progress bars, text UI | Yes |
| oxmysql | MySQL database for leveling, history, and chat | Yes |
| ESX / QBCore / QBX | Any supported framework (auto-detected) | Yes |
| Inventory system | ox_inventory, qb-inventory, ps-inventory, qs-inventory, and 8 more (auto-detected) | Yes |
| ox_target / qb-target | Third-eye interaction (falls back to E-key if not found) | Optional |
| Dispatch resource | ps-dispatch, cd_dispatch, qs-dispatch, rcore_dispatch, and 5 more (auto-detected) | Optional |
| NR_Tablet | Opens as a tablet app instead of standalone | Optional |
| is_ui | Alternative notification/progress bar system | Optional |
Supported Inventories
The script auto-detects the first running inventory from this list:
ox_inventory, qb-inventory, ps-inventory, lj-inventory,
qs-inventory, codem-inventory, ak47_qb_inventory,
ak47_esx_inventory, core_inventory, mf-inventory,
origen_inventory, tgiann-inventory, ESX built-in
Supported Dispatch Resources
ps-dispatch, cd_dispatch, qs-dispatch, core_dispatch,
rcore_dispatch, linden_outlawalert, origen_police,
emergencydispatch, op-dispatch
If no dispatch resource is detected, the script sends blip notifications directly to online LEO players as a fallback.
Installation
Step 1: Download
Download NR_DrugSelling from your Tebex purchase and extract it to your resources folder:
server/
└── resources/
└── [echo]/
└── NR_DrugSelling/
Step 2: server.cfg
Add the resource to your server configuration. ox_lib and oxmysql must start before NR_DrugSelling:
ensure oxmysql
ensure ox_lib
ensure ox_target # or qb-target (optional)
ensure NR_DrugSelling
Step 3: Inventory Items
Add the drug items to your inventory system. The default config expects these items:
| Item | Label | Base Price |
|---|---|---|
weed_bag | Weed | $50 |
coke_brick | Cocaine | $150 |
meth_bag | Meth | $200 |
oxy | Oxy | $80 |
crack_baggy | Crack | $120 |
heroin | Heroin | $250 |
Item names are fully configurable in Config.Drugs. Change them to match your existing drug items.
Step 4: Database
The database tables are created automatically on first start. No manual SQL setup required. Three tables are created:
nr_drugselling— Player profiles (level, XP, alias, earnings)nr_drugselling_history— Transaction lognr_drugselling_chat— Street chat messages
Step 5: Configuration
Edit config.lua to customize drugs, contacts, sell settings, and police configuration.
Step 6: Restart
Restart your server to load the resource.
How It Works
1. Opening the App
Press F5 (default keybind) or type /drugselling in chat. If using NR_Tablet, the app opens from within the tablet interface. The dashboard shows your total earnings, drugs sold, rep level, and active contacts.
2. Checking Inventory
The Inventory tab shows which drugs you're carrying and their quantities, pulled directly from your inventory system in real time.
3. Starting a Sell
From the Sell tab, select a drug to sell. The server picks an eligible buyer contact based on your level and the drug type. A sell zone is created around the contact's location with a GPS route and radius blip.
4. Selling to NPCs
Travel to the sell zone and approach any NPC pedestrian within the radius. Use ox_target / qb-target (or press E) to initiate a deal. A handoff animation plays with a progress bar.
5. Deal Outcomes
Each NPC interaction rolls a random outcome:
| Outcome | Default Chance | What Happens |
|---|---|---|
| Buy | 35% | NPC buys a random quantity at the contact's price multiplier. You get cash and XP. |
| Rob | 35% | NPC takes your drugs and runs. Kill them and search the body to recover items. |
| Attack | 15% | An armed NPC spawns nearby and attacks you. |
| Dispatch | 15% | NPC calls the cops. Police are alerted via dispatch. |
| Ignore | Remaining % | NPC isn't interested. Try another one. |
6. Sell Zone Timer
The sell zone stays active for a configurable duration (default 15 minutes). You can sell to multiple NPCs during this window. When the timer expires, the zone closes and a cooldown begins before you can sell again.
7. Leveling Up
You earn 1 XP per unit sold. Leveling up unlocks new buyer contacts with better price multipliers and increases your max sell quantity per deal. The Rank tab shows your progression and upcoming unlocks.
8. Street Chat
The in-app chat lets players communicate with aliases. Set your alias from the dashboard, toggle anonymous mode, and chat with other drug sellers server-wide. Messages persist in the database.
9. Leaderboard
The leaderboard ranks all players by total drugs sold, displayed with their chosen aliases. It updates in real time as sales are completed.
Configuration
General Settings
Config.Debug = false -- Enable debug mode
Config.Theme = '#00ffff' -- UI accent color
Config.UsingNRTablet = true -- Open as NR_Tablet app
Config.Keybind = 'F5' -- Open keybind (standalone mode)
Leveling
Config.MaxLevel = 25 -- Maximum player level
Config.XPPerLevel = 100 -- XP needed per level
Drug Definitions
Config.Drugs = {
{ item = 'weed_bag', label = 'Weed', basePrice = 50, icon = 'leaf' },
{ item = 'coke_brick', label = 'Cocaine', basePrice = 150, icon = 'snowflake' },
{ item = 'meth_bag', label = 'Meth', basePrice = 200, icon = 'flask' },
{ item = 'oxy', label = 'Oxy', basePrice = 80, icon = 'pills' },
{ item = 'crack_baggy', label = 'Crack', basePrice = 120, icon = 'fire' },
{ item = 'heroin', label = 'Heroin', basePrice = 250, icon = 'syringe' },
}
Add or remove entries to match your server's drug items. Icons use FontAwesome names.
Buyer Contacts
{
id = 1,
name = 'Street Corner Kid', -- Display name
location = 'Grove Street', -- Location label
coords = vec3(-182.47, -1676.87, 33.84),
drugs = { 'weed_bag', 'crack_baggy' }, -- Accepted drugs
multiplier = 0.8, -- Price multiplier
risk = 'Low', -- Risk label
unlockLevel = 1, -- Required level
}
Higher-level contacts have better multipliers but may be in more dangerous locations. The default config includes 7 contacts from level 1 to level 20.
Contact Multipliers
| Contact | Multiplier | Unlock Level | Risk |
|---|---|---|---|
| Street Corner Kid | 0.8x | 1 | Low |
| The Plug | 1.0x | 3 | Medium |
| Backstreet Doc | 1.1x | 5 | Medium |
| Cartel Contact | 1.3x | 8 | High |
| Club Owner | 1.2x | 10 | Medium |
| Biker Gang | 1.5x | 15 | High |
| Kingpin | 1.8x | 20 | High |
Sell Settings
Config.BaseSellMax = 5 -- Max units at level 1
Config.SellMaxPerLevel = 2 -- +2 per level above 1
Config.SellCooldown = 900 -- Seconds cooldown after zone expires
Config.SellZoneRadius = 200.0 -- Radius of the sell zone
Config.SellZoneTimeout = 900 -- Seconds the sell zone is active
Max sell quantity formula: BaseSellMax + SellMaxPerLevel * (level - 1). At level 25, players can sell up to 53 units per NPC interaction.
Deal Outcome Chances
Config.BuyChance = 0.35 -- 35% NPC buys
Config.RobChance = 0.35 -- 35% NPC robs you
Config.AttackChance = 0.15 -- 15% armed NPC attacks
Config.DispatchChance = 0.15 -- 15% NPC calls police
Any remaining probability (if total < 1.0) becomes the ignore chance.
Attack NPC Settings
Config.AttackSpawnDistance = 15.0 -- Min spawn distance
Config.AttackDespawnTime = 120 -- Seconds before cleanup
Config.AttackWeapons = {
'WEAPON_PISTOL', 'WEAPON_SWITCHBLADE',
'WEAPON_KNIFE', 'WEAPON_BAT', 'WEAPON_BOTTLE',
}
Police Settings
Config.RequiredPolice = 0 -- Min LEO online (0 = disabled)
Config.LeoJobs = { 'police', 'sheriff', 'bcso', 'sasp', 'ranger' }
-- Police alert to seller (warning notification)
Config.PoliceAlertChance = 0.10
Config.PoliceAlertChancePerLevel = 0.01
Config.PoliceAlertChanceMax = 0.40
-- Police dispatch (blip/alert to LEO players)
Config.PoliceNotifyChance = 0.25
Config.PoliceNotifyChancePerLevel = 0.015
Config.PoliceNotifyChanceMax = 0.60
Both police chances scale with player level: base + perLevel * (level - 1), capped at max. Higher-level dealers attract more police attention.
NPC Interaction
Config.InteractDistance = 2.0 -- How close to interact
Config.DealDuration = 5000 -- Progress bar duration (ms)
Pricing System
The final sale price per unit is calculated as:
price = basePrice * contactMultiplier * randomVariance
Where randomVariance is between 0.7 and 1.4 (30% below to 40% above base). This means prices fluctuate per deal, adding unpredictability.
Database
NR_DrugSelling uses oxmysql with three auto-created tables:
nr_drugselling (Player Profiles)
| Column | Type | Description |
|---|---|---|
citizenid | VARCHAR(50) | Unique player identifier |
alias | VARCHAR(50) | Player's chosen street name |
level | INT | Current level (1-25) |
xp | INT | Current XP towards next level |
total_earned | INT | Lifetime cash earned |
total_sold | INT | Lifetime units sold |
chat_anonymous | TINYINT | Anonymous chat preference |
nr_drugselling_history (Transaction Log)
| Column | Type | Description |
|---|---|---|
citizenid | VARCHAR(50) | Seller identifier |
drug | VARCHAR(50) | Item name sold |
quantity | INT | Units sold |
price_per_unit | INT | Price per unit at time of sale |
total_price | INT | Total cash received |
buyer | VARCHAR(100) | Contact name |
sold_at | TIMESTAMP | Sale timestamp |
nr_drugselling_chat (Street Chat)
| Column | Type | Description |
|---|---|---|
citizenid | VARCHAR(50) | Sender identifier |
alias | VARCHAR(50) | Display name (or "Anonymous") |
message | VARCHAR(500) | Message content |
sent_at | TIMESTAMP | Message timestamp |
Localization
All UI text is configurable in locales.lua. Override any string to change labels, notifications, and tab names. Example:
Locales.AppTitle = 'Drug Selling Hub'
Locales.TabDashboard = 'Dashboard'
Locales.TabInventory = 'Inventory'
Locales.FindBuyer = 'Find Buyer'
Locales.SellSuccess = 'Deal complete'
Locales.PoliceAlert = 'The cops have been tipped off!'
Troubleshooting
UI not opening
- Check F8 console for errors
- Verify the
web/build/folder exists with built files - If using NR_Tablet, ensure
Config.UsingNRTablet = true - Try the
/drugsellingchat command as a fallback - You cannot open the UI while a sell zone is active
No buyers available
- Your level may be too low for any contact that accepts that drug
- Check
Config.Contacts— ensure at least one contact has the drug and anunlockLevelyou meet - Verify you actually have the drug item in your inventory
Sell zone not appearing
- You may be on cooldown — wait for the cooldown to expire
- Check if
Config.RequiredPoliceis set and not enough police are online - Enable
Config.Debug = truefor detailed server console logs
Can't interact with NPCs in zone
- NPCs must be within the sell zone radius and not in vehicles
- You can only interact with each NPC once per zone session
- If using ox_target/qb-target, ensure it's running
- Without a target resource, press E when the text prompt appears
Database errors
- Verify oxmysql is running and your connection string is correct
- Tables are created automatically — check server console for creation errors
- If upgrading, the script adds missing columns automatically via
ALTER TABLE IF NOT EXISTS
Items not being removed/added
- Ensure your inventory system is detected — check server console for
[NR_DrugSelling] Inventory: NONE - Verify the item names in
Config.Drugsmatch your inventory's item definitions exactly - Ensure the inventory resource starts before NR_DrugSelling
Support
For paid script support, open a ticket in our Discord server for priority assistance.