esx_drugs
esx_drugs lets players harvest cannabis, process it into marijuana and sell it for black money in ESX Legacy. Config, items, events and anti-exploit checks.
esx_drugs is a small weed economy for ESX Legacy: players pick cannabis plants in a field, process them into marijuana and sell it to a dealer for black money. The server validates every step by position and rate limits, so it is a reasonable base for your own drug scripts.
Overview
| Fact | Value |
|---|---|
| Resource | esx_drugs |
| Side | Client + server |
| Dependencies | esx_lib, es_extended (plus oxmysql) |
| Optional | esx_license when Config.LicenseEnable = true |
| Items | cannabis (weight 3), marijuana (weight 2) |
| License | weed_processing |
In-game flow
- Harvest: near the weed field the client spawns 25 local
prop_weed_02plants within 50 m of the field center. Press E next to a plant to pick it. After about 3 seconds the server gives 1 to 3cannabis. - Process: stand on the processing spot and press E. Every
Config.Delays.WeedProcessingms the server converts 3cannabisinto 1marijuanauntil you run out, walk away or your inventory is full. - Sell: at the dealer marker press E, choose an item and an amount between
Config.SellMenu.MinandConfig.SellMenu.Max.
Installation
Database
The resource uses the esx_lib SQL catalog and inserts the items and the license automatically in your esx:locale. The manual equivalent is esx_drugs.sql:
INSERT INTO `items` (`name`, `label`, `weight`, `rare`, `can_remove`) VALUES
('cannabis', 'Cannabis', 3, 0, 1),
('marijuana', 'Marijuana', 2, 0, 1);
INSERT INTO `licenses` (`type`, `label`) VALUES
('weed_processing', 'Weed Processing License');If you use ox_inventory, add the two items to ox_inventory/data/items.lua instead. See ox_inventory.
server.cfg
ensure esx_license # only needed with Config.LicenseEnable = true
ensure esx_drugsConfiguration
| Key | Default | Description |
|---|---|---|
Config.Locale | GetConvar('esx:locale', 'en') | Locale used for texts. |
Config.Delays.WeedProcessing | 1000 * 7 | Time in ms per processing step (3 cannabis → 1 marijuana). |
Config.DrugDealerItems | { marijuana = 91 } | Items the dealer buys and the price per unit. |
Config.LicenseEnable | false | Ask for the weed_processing license before processing. Needs esx_license. |
Config.LicensePrices | { weed_processing = { label = TranslateCap('license_weed'), price = 15000 } } | License label and cash price. |
Config.GiveBlack | true | Pay sales into black_money. false pays cash. |
Config.CircleZones.WeedField | vector3(2220.72, 5582.52, 53.81), radius 100.0 | Field center. Blip color 25, sprite 496, plus a radius blip. |
Config.CircleZones.WeedProcessing | vector3(2329.02, 2571.29, 46.68) | Processing spot. Blip color 25, sprite 496. |
Config.CircleZones.DrugDealer | vector3(-1172.02, -1571.98, 4.66) | Dealer spot. Blip color 6, sprite 378. |
Config.Marker.Distance | 100.0 | Distance at which the dealer marker is drawn. |
Config.Marker.Color | { r = 60, g = 230, b = 60, a = 255 } | Dealer marker color. |
Config.Marker.Size | vector3(1.5, 1.5, 1.0) | Dealer marker size. |
Config.Marker.Type | 1 | Dealer marker type. |
Config.SellMenu.Min | 1 | Minimum amount per sale. |
Config.SellMenu.Max | 50 | Maximum amount per sale. The server rejects (and kicks for) amounts outside this range. |
Hard-coded server values
These are local constants at the top of server/main.lua, not config keys:
| Constant | Value | Meaning |
|---|---|---|
PickupCooldown | 3500 | Min ms between pickups (rate limiter). |
PickupDuration | 3000 | Delay before cannabis is added. |
PickupDistance / PickupFieldDistance | 3.0 / 55.0 | Max distance to the plant / to the field center. |
ProcessDistance | 5.0 | Max distance to the processing spot. |
SellDistance / SellCooldown | 3.0 / 1500 | Max distance to the dealer / min ms between sales. |
MinCannabisPickup / MaxCannabisPickup | 1 / 3 | Cannabis per plant. |
Config.CircleZones.WeedField.radius only affects the map blip. Plants spawn within 50 m and the server accepts pickups within 55 m of the field center, so a larger radius does not make the field bigger.
Server events and callbacks
All net events below can be triggered by clients. The server validates them as follows.
| Name | Type | Arguments | Server checks |
|---|---|---|---|
esx_drugs:pickedUpCannabis | net event | plantCoords | Rate limited. Plant and player must be inside the field and within 3 m of each other; re-checked after 3 s. Fails → player is dropped. |
esx_drugs:processCannabis | net event | none | Within 5 m of WeedProcessing, at least 3 cannabis, one loop per player. Fails position check → player is dropped. |
esx_drugs:sellDrug | net event | itemName, amount | Rate limited, within 3 m of the dealer, integer amount within SellMenu, item listed in DrugDealerItems, enough items. Wrong types, position or amount → player is dropped. |
esx_drugs:cancelProcessing / esx_drugs:outofbound | net event | none | Stops the player's processing loop. |
esx_drugs:buyLicense | callback | licenseName | License must exist in Config.LicensePrices and the player must have the cash. |
esx_drugs:canPickUp | callback | item | Returns whether the player can carry 1 cannabis. |
esx_drugs:cannabis_count | callback | none | Returns the player's cannabis count. |
License is client-side only
With Config.LicenseEnable = true the license is only checked on the client before processing starts. esx_drugs:processCannabis does not check weed_processing on the server, and esx_drugs:buyLicense has no distance check. Add an esx_license:checkLicense check in the server event if the license must be enforced.
The kick function is FoundExploiter(src, reason) in server/main.lua. Replace DropPlayer there with your ban system if you want stricter handling.
Integration tips
- To sell more drugs at the dealer, add items to
Config.DrugDealerItems(for example{ marijuana = 91, cocaine = 150 }) and create the items. The menu lists every item from that table that the player carries. - Sales use
xPlayer.addAccountMoney('black_money', ...)with the reason"Drugs Sold", which shows up in ESX money logs. - esx_drugs stops processing for a player on
esx:onPlayerDeathand on disconnect.
Common issues
- Plants spawn in the air or underground: plant height is searched between Z 48 and 58. If you move the field, adjust
GetCoordZinclient/weed.lua. - Dealer menu is empty: the dealer menu lists items from
ESX.GetPlayerData().inventoryon the client. With a custom inventory, make sure it keeps ESX player data in sync. - Processing stops after one step: the player cannot carry the marijuana (
canSwapItemfailed) or has fewer than 3 cannabis.
Related
Frequently asked questions
Independent documentation
Last updated on
esx_dmvschool
esx_dmvschool adds a theory test and car, motorcycle and truck driving tests to ESX Legacy. Covers licenses, config keys, checkpoints, events and common issues.
esx_garage
Configure esx_garage 2.0 for ESX Legacy: garages, impound lots, job access, settings, server exports like registerGarage and impoundVehicle, and fixes.