FiveM Docs
Addons

esx_lscustom

esx_lscustom adds Los Santos Customs tuning to ESX Legacy with a cart-based NUI, live stats and server-validated prices. Setup, config, pricing and events.

esx_lscustom brings the Los Santos Customs workshop to ESX Legacy. Players drive into one of the workshops, press the interaction key and customize performance, body parts, wheels, colors, lights and more in a NUI with a cart, a camera mode and live vehicle stats. Everything in the cart is priced and checked on the server before money is taken.

Overview

Resourceesx_lscustom (version 1.0)
SideClient + server, NUI in html/ (no build step)
Dependenciesesx_lib, es_extended, oxmysql
Readsvehicles table from esx_vehicleshop for base prices, owned_vehicles for saving
Optionalesx_addonaccount with society_mechanic (mechanic-only mode)
SQL fileNone

How it works:

  1. The player sits in a vehicle within Config.DrawDistance of a zone and presses E.
  2. The client sends esx_lscustom:startModing with the current vehicle properties. The server stores this snapshot as the session's reference.
  3. The player previews parts. Nothing is paid until checkout.
  4. On checkout, the esx_lscustom:buyCart callback recomputes every cart line from Config.Menus and the vehicle price, checks that the vehicle props only differ in paid fields, charges the money and saves the result.
  5. On cancel or disconnect the original props are restored.

Installation

Install the vehicle catalog

Prices depend on the vehicles table. Install esx_vehicleshop or create that table with model and price columns yourself.

Ensure the resource

server.cfg
ensure oxmysql
ensure esx_lib
ensure es_extended
ensure esx_vehicleshop
ensure esx_lscustom

Configuration

KeyDefaultDescription
Config.DrawDistance10.0Distance at which the zone hint appears.
Config.LocaleGetConvar('esx:locale', 'en')Locale.
Config.IsMechanicJobOnlyfalseOnly the mechanic job can use the workshop. Payment comes from society_mechanic.
Config.Currency'$'Currency symbol in messages and UI.
Config.Workshop.UseNuitrueNUI workshop. false uses the ESX default menu flow.
Config.Workshop.EnableCameratrueCamera controls in the NUI.
Config.Workshop.EnableStatstrueLive handling stats.
Config.Workshop.PurchaseCooldown1500ms between checkouts per player.
Config.Workshop.Ownership.RequireOwnedfalseOnly accept vehicles owned by the buyer (or mechanic customer vehicles).
Config.Workshop.Ownership.SaveOwnedVehiclestrueSave paid changes to owned_vehicles.
Config.Workshop.Ownership.AllowMechanicCustomerVehiclesfalseMechanics may tune and save vehicles they do not own.
Config.Workshop.StatGainsper modDisplay-only stat gains, e.g. modEngine = { accel = 12, speed = 8 }.
Config.Zonesls1 ... ls5Workshop locations with Pos, Name (blip) and Hint.
Config.ColorslistPaint color groups shown in the respray menu.
Config.DefaultWheelsPriceMultiplier2Wheel price in percent when a wheel menu has no price.
Config.Menuslarge tableMenu tree and prices.

Prices in Config.Menus

Every purchasable entry has a modType and a price. The price is a percentage of the vehicle price:

config.lua
modEngine = {
    label = TranslateCap('engine'),
    parent = 'upgrades',
    modType = 11,
    price = { 13.95, 32.56, 65.12, 139.53 }, -- one value per level
},
  • Performance mods (engine, brakes, transmission, suspension, armor) take one percentage per level. Removing a mod (level -1) is free.
  • Turbo and xenon toggles use a single percentage.
  • Cosmetic parts, paint and wheels use a single percentage.

To make tuning cheaper or more expensive overall, scale these numbers. The workshop zones themselves look like this:

config.lua
Config.Zones = {
    ls1 = {
        Pos = vector3(-337.38, -136.92, 38.57),
        Name = TranslateCap('blip_name'),
        Hint = TranslateCap('press_custom'),
    },
}

Developer API

The resource has no exports.

NameTypeDescription
esx_lscustom:startModingServer net event(props, netId). Starts a session for the vehicle the player is in. Ignored unless the player is within 12 m of a zone, in that vehicle, and matching model and plate.
esx_lscustom:stopModingServer net event(plate). Ends the player's session for that plate.
esx_lscustom:buyCartServer callback(payload, netId) with payload.cart and payload.vehicleProps. Returns success, message. Max 40 cart lines.
esx_lscustom:getVehiclesPricesServer callbackReturns the cached { model, price } list.
esx_lscustom:setVehiclesPricesClient eventServer pushes the price list (refreshed every 10 minutes when changed).
esx_lscustom:restoreModsClient event(netId, props). Restores a vehicle when its customer disconnects mid-session.
esx_lscustom:cancelInstallModClient eventRestores the original props of the current vehicle.

Client-triggerable

startModing and buyCart are callable by clients. The server ignores the client's prices: it recalculates each line from Config.Menus, rejects props that changed fields nobody paid for, enforces the distance, the session and a cooldown, and locks per player and plate during checkout. If you add custom mods, add them to Config.Menus so they are validated too.

Common issues

  • Everything costs the same for every car. The model is missing in vehicles, so the 50000 fallback is used. Add the model to the table.
  • Changes are lost after restart. The vehicle is not in owned_vehicles, the buyer is not the owner, or SaveOwnedVehicles is false. Your garage script must also apply the stored props.
  • "Not enough money" in mechanic-only mode. Payment comes from society_mechanic, not the mechanic's wallet.
  • Hint does not appear. You must be in a vehicle, and with IsMechanicJobOnly you need the mechanic job.

Frequently asked questions

Independent documentation

esx-fivem.com is a community project and is not affiliated with the ESX Framework team. Facts on this page were checked against the upstream source. Official resources: docs.esx-framework.org and github.com/esx-framework.
Edit on GitHub

Last updated on

On this page