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_vehicleshop is the official car dealership for ESX Legacy. It turns Premium Deluxe Motorsport into a showroom where players buy vehicles that are saved to owned_vehicles, and optionally into a player-run cardealer job that orders stock, sells or rents cars to other players, and gets paid daily rent.
Overview
| Resource | esx_vehicleshop (version 1.0) |
| Side | Client + server |
| Dependencies | esx_lib, es_extended, oxmysql |
| Optional | esx_society, esx_addonaccount, esx_addoninventory (job mode), esx_license (license check), cron (rent) |
| SQL file | esx_vehicleshop.sql |
| Client export | GeneratePlate |
Two modes, controlled by Config.EnablePlayerManagement:
- Direct sales (
false, default). Anyone can enter the showroom, browsevehiclesby category and buy with cash. The vehicle spawns outside, the player is warped in, and a row is added toowned_vehicleswith a server-generated plate. - Car dealer job (
true). Players with thecardealerjob buy stock with society money intocardealer_vehicles, then sell or rent it to nearby players, return it to the provider for 75 % of the price, and manage the society stash through the boss actions marker. The societycardealeris registered with esx_society.
Reselling at the ResellVehicle marker pays Config.ResellPercentage of the catalog price and deletes the vehicle from owned_vehicles.
Installation
Import the SQL
esx_vehicleshop.sql creates the tables cardealer_vehicles, vehicle_sold, owned_vehicles, rented_vehicles, vehicle_categories and vehicles (with the default catalog), plus the cardealer job, its grades and the society_cardealer addon account and inventory.
If owned_vehicles already exists (for example from another garage script), remove that CREATE TABLE from the file before importing. All of cardealer_vehicles, owned_vehicles, rented_vehicles and vehicle_sold must use InnoDB, otherwise dealer transactions are disabled at startup.
Ensure the resource
ensure oxmysql
ensure esx_lib
ensure es_extended
ensure cron
ensure esx_addonaccount
ensure esx_addoninventory
ensure esx_society
ensure esx_license
ensure esx_vehicleshopOnly the first three are required in direct sales mode.
On first start the resource also creates vehicle_rental_payments (daily rent receipts), converts a legacy varchar vehicle_sold.date to DATETIME when all values are valid, and adds the idx_vehicle_sold_date_plate index.
Configuration
| Key | Default | Description |
|---|---|---|
Config.DrawDistance | 10 | Marker draw distance. |
Config.MarkerColor | {r = 120, g = 120, b = 240} | Marker color. |
Config.EnablePlayerManagement | false | Enables the cardealer job mode. Needs esx_addonaccount, esx_billing and esx_society. |
Config.ResellPercentage | 50 | Percent of the catalog price paid when reselling. |
Config.RentalPriceMultiplier | 0.05 | Daily rent = base price × multiplier. |
Config.MinimumRentalPrice | 1 | Lowest daily rent. |
Config.Locale | GetConvar('esx:locale', 'en') | Locale. |
Config.LicenseEnable | false | Require the drive license before opening the shop menu (direct mode, client-side check). |
Config.PlateLetters | 3 | Letters in generated plates. |
Config.PlateNumbers | 3 | Digits in generated plates. |
Config.PlateUseSpace | true | Space between letters and digits. Letters + numbers + space must not exceed 8. |
Config.OxInventory | ESX.GetConfig().OxInventory | Uses an ox_inventory stash for the society stock. |
Config.Blip | { show = true, Sprite = 326, Display = 4, Scale = 0.8 } | Dealership blip. |
Zones
Config.Zones defines six points. Type = -1 hides the marker.
| Zone | Default position | Purpose |
|---|---|---|
ShopEntering | vector3(-33.7, -1102.0, 25.4) | Opens the shop / dealer menu. |
ShopInside | vector3(-47.5, -1097.2, 25.4) | Preview spot. Server checks for sales use 30 m around it. |
ShopOutside | vector3(-28.6, -1085.6, 25.5) | Spawn point of bought vehicles. |
BossActions | vector3(-32.0, -1114.2, 25.4) | Boss menu and stock (job mode). |
GiveBackVehicle | vector3(-18.2, -1078.5, 25.6) | Return a rented vehicle. |
ResellVehicle | vector3(-44.6, -1080.7, 25.6) | Sell an owned vehicle back. |
Catalog tables
INSERT INTO `vehicle_categories` (`name`, `label`) VALUES ('electric', 'Electric');
INSERT INTO `vehicles` (`name`, `model`, `price`, `category`) VALUES ('Neon', 'neon', 150000, 'electric');Vehicles whose category has no matching row in vehicle_categories are not shown (the query uses an inner join).
Rentals
In job mode a dealer can rent a stock car to a player. The rent is computed on the server (getRentalPrice). Every day at 22:00 the cron resource triggers PayRent(): rent is taken from each renter's bank and added to society_cardealer. If a renter cannot pay, the rental is removed ("evicted"). Each charge is written to vehicle_rental_payments, so a restart does not charge twice on the same day.
Developer API
Client export GeneratePlate
local plate = exports.esx_vehicleshop:GeneratePlate()Returns a random plate in the configured format that is not in owned_vehicles (checked with the esx_vehicleshop:isPlateTaken callback). It yields, so call it from a thread. The shop itself generates plates on the server and ignores client plates.
CreateThread(function()
local plate = exports.esx_vehicleshop:GeneratePlate()
print(('Free plate: %s'):format(plate))
end)Server callbacks
| Callback | Arguments | Who | Notes |
|---|---|---|---|
esx_vehicleshop:buyVehicle | model, plate | Anyone within 30 m of ShopInside | Plate argument is ignored, price comes from vehicles. |
esx_vehicleshop:resellVehicle | plate, model (hash) | Owner near ResellVehicle | Checks ownership, model and plate. |
esx_vehicleshop:giveBackVehicle | plate | Renter near GiveBackVehicle | Vehicle with that plate must be within 8 m. |
esx_vehicleshop:buyCarDealerVehicle | model | cardealer near showroom | Pays from society_cardealer. |
esx_vehicleshop:getCommercialVehicles | none | cardealer | Current stock. |
esx_vehicleshop:getRentedVehicles | none | cardealer near boss marker | Active rentals. |
esx_vehicleshop:getSoldVehicles | page | cardealer | Sales log, 50 per page. |
esx_vehicleshop:getStockItems / getPlayerInventory | none | cardealer / player | Society stash and own inventory. |
esx_vehicleshop:isPlateTaken | plate | Anyone | true if the plate exists in owned_vehicles. |
esx_vehicleshop:retrieveJobVehicles | type | Player | Own vehicles of type for the current job. |
Net events (client to server)
| Event | Arguments | Guard |
|---|---|---|
esx_vehicleshop:setVehicleOwnedPlayerId | playerId, vehicleProps, model, label | cardealer near showroom, model must be in stock. Sells a stock car to playerId. |
esx_vehicleshop:rentVehicle | vehicle, plate, rentPrice, playerId | Same guard. plate and rentPrice are ignored, the server computes both. |
esx_vehicleshop:returnProvider | vehicleModel | cardealer near boss or resell marker. |
esx_vehicleshop:getStockItem / putStockItems | itemName, count | cardealer near boss or resell marker. |
esx_vehicleshop:setJobVehicleState | plate, state | Only sets stored = 0 for the player's own job vehicle near them. |
esx_vehicleshop:getVehiclesAndCategories | none | Sends the catalog to the caller. |
The server broadcasts esx_vehicleshop:updateVehiclesAndCategories(vehicles, categories, vehiclesByModel) to clients.
Security notes
All money-moving events and callbacks are guarded by job, distance and database transactions. Two gaps remain: the drive license check (Config.LicenseEnable) runs only on the client, and isPlateTaken can be called by anyone. If the license must be enforced, add a server-side esx_license:checkLicense call to your fork of buyVehicle.
Common issues
- "Dealer transactions disabled" in the console. One of the dealer tables is MyISAM. Convert it with
ALTER TABLE <name> ENGINE=InnoDB;. - Shop menu is empty. The
vehiclestable is empty or categories do not matchvehicle_categories.name. - Plate length warning.
PlateLetters + PlateNumbers(+1 with space) is above 8. - Rent is never charged. The
cronresource is not started, orsociety_cardealeris missing inaddon_account. - Job menu does not show.
Config.EnablePlayerManagementis off or the player does not have thecardealerjob.
Related
Frequently asked questions
Independent documentation
Last updated on
esx_taxijob
Set up esx_taxijob for ESX Legacy. NPC taxi missions, payout split, billing, config keys with defaults, server events, callbacks and fixes for common issues.
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.