esx_weaponshop
esx_weaponshop adds Ammu-Nation and a black market dealer with a NUI, weapon license, ammo, attachments and tints to ESX Legacy. Setup, config and API.
esx_weaponshop is the official weapon store for ESX Legacy. It adds Ammu-Nation locations and a hidden black market dealer, opens a NUI catalog, and lets players buy weapons, a weapon license, ammo, attachments and tints. All purchases are validated and charged on the server.
Overview
| Resource | esx_weaponshop (version 1.0) |
| Side | Client + server, NUI (web/dist) |
| Dependencies | esx_lib, es_extended, esx_license, OneSync (/onesync) |
| Optional | ox_inventory (detected from ESX.GetConfig().OxInventory) |
| SQL file | esx_weaponshop.sql (adds the weapon license) |
| Config files | shared/config/main.lua, shops.lua, upgrades.lua, weapon_images.lua |
In-game flow:
- Legal shops (
Legal = true, defaultGunShop) charge cash. WithConfig.LicenseEnable, players without theweaponlicense get a menu to buy it forConfig.LicensePricefirst. - Illegal shops (
Legal = false, defaultBlackWeashop) charge black_money, never need a license and have their blip disabled by default. - Players can buy ammo, components and tints for a weapon they own and that the zone sells (when
Config.WeaponShopUpgrades.Enabledis on).
Installation
Import the SQL
Run esx_weaponshop.sql. It only inserts the weapon license into the licenses table (from esx_license).
INSERT IGNORE INTO `licenses` (`type`, `label`) VALUES ('weapon', "Weapon licence");The files in localization/ still create a legacy weashops table. The current version does not read it, prices come from the Lua config.
Ensure the resource
ensure oxmysql
ensure esx_lib
ensure es_extended
ensure esx_license
ensure esx_weaponshopOneSync must be enabled, the manifest declares /onesync as a dependency.
Configuration
Main config (shared/config/main.lua)
| Key | Default | Description |
|---|---|---|
Config.Locale | GetConvar('esx:locale', 'en') | Locale. |
Config.OxInventory | ESX.GetConfig().OxInventory | Uses ox_inventory for weapons and attachments when true. |
Config.FallbackWeaponImage | '' | Image shown when a weapon image cannot be loaded. |
Config.WeaponImages | per-weapon map | Image overrides. weapon_images.lua fills this with bundled images. |
Config.InitialWeaponAmmo | 42 | Ammo given with a weapon bought through the ESX loadout. |
Config.LicenseEnable | true | Require the weapon license in legal shops. |
Config.LicensePrice | 5000 | Price of the weapon license (cash). |
Config.ServerDistanceBuffer | 3.0 | Extra meters added to InteractionDistance for the server distance check. |
Config.PurchaseCooldown | 1500 | Minimum ms between purchases of the same type per player. |
Config.LicenseCallbackTimeout | 5000 | Timeout for esx_license calls in ms. |
Config.ClientCallbackTimeout | 5000 | Timeout when asking the client for its ammo state. |
Config.DrawDistance | 10.0 | Marker draw distance. |
Config.Size | { x = 1.5, y = 1.5, z = 0.5 } | Marker size. |
Config.Color | { r = 0, g = 128, b = 255 } | Marker color. |
Config.Type | 1 | Marker type. |
Config.InteractionDistance | 2.0 | Distance to open the shop. |
Config.InteractionKeyLabel | 'E' | Key label shown in the UI. |
Shop zones (shared/config/shops.lua)
Config.Zones = {
GunShop = {
Legal = true,
Blip = { Enabled = true, Sprite = 110, Color = 81, Display = 4, Scale = 0.7, ShortRange = true },
Items = {
{ name = 'WEAPON_PISTOL', price = 500 },
{ name = 'WEAPON_BAT', price = 50 },
},
Locations = {
vector3(-662.1, -935.3, 20.8),
},
},
}| Field | Description |
|---|---|
Legal | true = cash + license check, false = black money, no license. |
Blip | Enabled, Sprite, Color, Display, Scale, ShortRange. |
Items | { name, price } per weapon. Only weapons listed here can be bought or upgraded in this zone. |
Locations | vector3 list of counters. |
Upgrades (shared/config/upgrades.lua)
| Key | Default | Description |
|---|---|---|
Config.WeaponShopUpgrades.Enabled | true | Master switch. With ox_inventory enabled, upgrades also require ox_inventory to be started. |
Ammo.Enabled | true | Sell ammo. |
Ammo.PricePerRound | 5 | Price per round. |
Ammo.DefaultAmount / MinAmount / MaxAmount | 30 / 1 / 250 | Amount limits per purchase. |
Ammo.MaxTotal | 250 | Maximum ammo a weapon may hold after buying. |
Ammo.QuickAmounts | { 30, 60, 120, 250 } | Buttons in the UI. |
Components.Enabled | true | Sell attachments. |
Components.DefaultPrice | 750 | Price when a component has no entry in Prices. |
Components.Blacklisted | { clip_default = true } | Components that are never sold. |
Components.Prices | e.g. suppressor = 1250, scope = 1500 | Per-component prices. |
Components.OxItemsByName / OxItemsByHash | mapping | ESX component name or hash to ox_inventory attachment item. |
Tints.Enabled | true | Sell weapon tints. |
Tints.DefaultPrice | 350 | Price when a tint index has no entry. |
Tints.Prices | [0] = 0 ... [7] = 900 | Price per tint index. |
Tints.Swatches | hex colors | Colors shown in the UI. |
Developer API
The resource has no exports. Its server callbacks are used by the NUI:
| Callback | Arguments | Description |
|---|---|---|
esx_weaponshop:buyWeapon | weaponName, zone | Buys a weapon from a zone. |
esx_weaponshop:buyLicense | none | Buys the weapon license near a legal shop. |
esx_weaponshop:buyUpgrade | data ({ weaponName, action, ... }), zone | action is 'ammo', 'component' or 'tint'. |
The server also sends esx_weaponshop:requestWeaponAmmoState to the client and accepts the answer through the net event esx_weaponshop:receiveWeaponAmmoState (only from the same player, matched by request id).
Client-triggerable
All three callbacks are client-callable. The server validates the zone, the weapon name, the distance to a zone location (InteractionDistance + ServerDistanceBuffer), the license, the price from config, the payment and the inventory, and refunds when adding the weapon fails. Requests are rate-limited per player and action. Never move prices to the client.
To check the weapon license from your own scripts, use esx_license:
TriggerEvent('esx_license:checkLicense', playerId, 'weapon', function(hasLicense)
if not hasLicense then
TriggerClientEvent('esx:showNotification', playerId, 'You need a weapon license.')
end
end)Common issues
- Resource does not start.
esx_licenseis a hard dependency and OneSync must be on. - License menu never appears.
Config.LicenseEnableisfalse, or the zone hasLegal = false. - Purchase fails silently. The player is too far from a
Locationsentry, is spamming (cooldown), lacks cash / black money, or cannot carry the weapon. - Upgrades unavailable.
Config.WeaponShopUpgrades.Enabledis off, orConfig.OxInventoryis true and ox_inventory is not started. The player must own the weapon. - Changed prices in
weashopshave no effect. EditConfig.Zonesinstead.
Related
Frequently asked questions
Independent documentation
Last updated on
esx_vehicleshop
esx_vehicleshop adds the Premium Deluxe Motorsport dealership to ESX Legacy, with direct sales or a car dealer job, rentals and reselling. Setup and API.
esx_weather
esx_weather syncs weather and time per zone (Los Santos, Sandy Shores, Paleto Bay) on ESX Legacy, with an admin panel, persistence and sync toggle exports.