> For the complete documentation index, see [llms.txt](https://pepper-scripts.gitbook.io/pepper-scripts-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://pepper-scripts.gitbook.io/pepper-scripts-docs/jobs/pepper-dealership.md).

# Pepper Dealership

Dealerships for every vehicle type – 3D showroom, test drives, financing, trade-ins, used cars and player dealerships with stock, commission and levels 1–50 for ESX, QBCore and Qbox.

{% hint style="success" %}
✅ **Get Pepper Dealership:** <https://pepperscripts.de/package/7809142>
{% endhint %}

{% hint style="info" %}
🧪 **Tested on our dev server:** Of course we test all scripts continuously on our own dev server “Pepper Scripts”.
{% endhint %}

## Overview

Pepper Dealership brings **dealerships for every vehicle type** to your server – cars, motorcycles, commercial vehicles, boats and aircraft. Each dealership is set up individually as an **NPC dealership** (sells around the clock), a **job dealership** (staff via the framework job) or a **purchasable player dealership** with its own owner.

Customers get a **3D showroom**: the vehicle stands on the preview spot, the camera orbits it, in-game stats, comparison, **paint**, **custom plates**, **test drive**, **financing** with real-time payments and **trade-in** of the old vehicle. Pay cash or by bank, then pick the vehicle up at the pickup spot or find it in the **framework garage**. A **used car lot** lets players sell vehicles to each other – the money arrives even if the seller is offline.

Player dealerships keep **stock** and buy from the manufacturer (delivery or **transfer** it yourself), set their own prices, hire staff with **ranks**, **wages** and **commission**, make customers **offers** and grow through **levels 1–50** with upgrades, a **deal of the week**, **coupons** and a **loyalty discount**. A **catalog tablet** (also as an lb-phone app) shows every player all dealerships, deals and a leaderboard.

🧪 **Tested on our dev server:** Of course we test all scripts continuously on our own dev server “Pepper Scripts”.

## Features

* **6 dealer types** (cars, motorcycles, commercial, boats, aviation, mixed), unlimited dealerships, each **NPC, job or purchasable**
* **Admin menu** `/dealeradmin` with **placement mode** (aim ray, transparent preview vehicle for parking spots, own position with **G**), 6 templates, assortment per dealership, set owner
* **Vehicle catalog** with 454 vanilla vehicles in 19 categories, image URL, “from level”, **import from the framework** (qbx\_core, QBCore, ESX) with preview
* **3D showroom**: preview vehicle, camera with orbit + views (front, side, rear, top, interior), doors, lights, **in-game stats**, **compare** up to 3 vehicles
* **Paint** (31 colors, primary + secondary, surcharge per paint type) and **custom plates** with blocked words and reservation
* **Purchase** by cash or bank, handover **at the pickup spot** (keys, full tank, waypoint) or **into the garage**, optional contract item (ox\_inventory)
* **Test drive** with time limit, distance and exit limit, `/teststop`, return to the salesperson, optional fee and own instance
* **Display vehicles** inside the dealership with “View”
* **Financing**: 3 plans (6/12/24 payments), 20–90 % down payment, real-time payments from the bank account, late fees, **repossession** after 3 missed payments, pay off anytime, no penalty while offline
* **Trade-in** of the old vehicle (condition + age set the value) and **buy-in** at the salesperson
* **Used car lot** player → player with price, description, duration and payout even to offline sellers
* **“My financing & listings”** (`/myfinance`)
* **Player dealership**: 5 ranks with permissions, **time clock**, wages from the business account, **commission**, invite/promote/fire
* **Business account** with ledger, optionally mirrored into the framework society account
* **Office tablet**: stock, own prices (90–130 %), buying via **delivery** or **transfer** from the factory, used cars, display, team, account, promotions, settings
* **Offers to customers** with a price down to the rank limit and one counter-offer; **self-service** when nobody is on duty (can be turned off), “call a salesperson”
* **Used stock** from trade-ins, buy-ins and repossessions; **dealer financing** paid into the business account
* **Buy** a dealership, **hand it over** to a player, **sell it back** to the state; reverts after inactivity
* **Levels 1–50** with 10 titles: vehicle classes and features by level, **upgrades** (stock, display, staff, buying discount, delivery time)
* **Deal of the week**, **coupons** (percent/amount, uses, expiry) and **loyalty discount** – capped, never below the buying price
* **Catalog tablet** (`/dealer`, key, optional item) and **lb-phone app**: all dealerships, assortment, waypoint, **test drive appointment/purchase request**, leaderboard, own purchases
* **Admin overview**: revenue, staff on duty, open payments, forgive/repossess financing, remove listings, correct accounts, plate search
* **Garage script selectable in the config** (esx\_garage, qb-garages, qbx\_garages, jg-advancedgarages, cd\_garage, qs-advancedgarages, okokGarage, loaf\_garage, framework only or own functions) with garage names per vehicle type, **11 key systems**, 7 fuel scripts (ox\_fuel, LegacyFuel, cdn-fuel, ps-fuel, qb-fuel, lj-fuel, lc\_fuel)
* **Showroom stage** with turntable, engine start, light moods, rarity of the day and visitor NPCs
* **Big handover** on its own stage: reveal, tour, key handover, photo moment, skippable
* **Price negotiation** with a hidden limit, patience and four arguments; one counter-offer on salesperson offers
* **Limited series** with serial numbers, special equipment, plate patterns, drops with countdown, reminders and presale
* **Vehicle pass** for every car, **collector rank** with 5 tiers and a tablet collection
* **Live auctions**: auction house, weekly schedule, bidding in the hall or by tablet, anti-sniping, player consignments
* **NPC customers** for player dealerships with wishes from real stock, passenger on test drives, negotiation, ratings and **reputation**, with hourly limits for the server economy
* **Dealership events**: car launch, open day, sale week, extras and a no-show rule
* **“Today” office page** with reputation, revenue, live feed, shortages and a tip
* 3 Discord webhooks, 15 server exports, German & English, config, locales, bridges and install files open
* No idle loops (built for **0.00 ms** idle)

## Requirements

| Requirement        | Version                   |
| ------------------ | ------------------------- |
| FiveM server build | ≥ 7290                    |
| OneSync            | required                  |
| Framework          | ESX, QBCore or Qbox       |
| Database           | MySQL 8 or MariaDB ≥ 10.6 |

## Dependencies

* [ox\_lib](https://github.com/overextended/ox_lib)
* [oxmysql](https://github.com/overextended/oxmysql)
* optional [ox\_target](https://github.com/overextended/ox_target) or qb-target – otherwise a “\[E] …” prompt
* a garage script (choose it in the config) – optionally a key and a fuel script (detected automatically)
* optional [ox\_inventory](https://github.com/overextended/ox_inventory) – contract and tablet item
* optional [lb-phone](https://lbscripts.com) – own app “Pepper Dealership”

## Installation

1. Copy the folder to `resources/[pepper]/pepper_dealership` – **do not rename it**.
2. Add to your `server.cfg` after the framework, oxmysql and ox\_lib:

```
ensure pepper_dealership
```

3. Admin permission: `add_ace group.admin pepper_dealership.admin allow` (or a group from `Config.AdminGroups`).
4. The resource creates its tables on start. You only need `install/pepper_dealership.sql` if your database user may not create tables.
5. Adjust `config/config.lua` (language, garage, purchase, financing …), webhooks in `config/server.lua`.
6. Start the server, open `/dealeradmin` in game, take a **template** (e.g. Premium Deluxe Motorsport) or create your own dealership and set the points in placement mode.
7. **Choose your garage:** in `config/config.lua` set `Config.Garage.System` to your garage script and put the names of your garages (car, boat, aircraft) from your garage script's config into `Config.Garage.Garages`. On start the server console shows system, table and garages (“Garage: …”) and warns if the script is not running or its columns are missing.

| `Config.Garage.System` | Garage script                                             |
| ---------------------- | --------------------------------------------------------- |
| `esx_garage`           | ESX Legacy garage                                         |
| `qb-garages`           | QBCore garages                                            |
| `qbx_garages`          | Qbox garages                                              |
| `jg-advancedgarages`   | JG Advanced Garages                                       |
| `cd_garage`            | Codesign Garage                                           |
| `qs-advancedgarages`   | Quasar Advanced Garages                                   |
| `okokGarage`           | okokGarage                                                |
| `loaf_garage`          | Loaf Garage                                               |
| `framework`            | no garage script (framework table only)                   |
| `custom`               | own functions `Config.Garage.Add/Remove/Transfer/OwnerOf` |
| `auto`                 | detects the running script itself                         |

Optional:

* **Tablet item:** `Config.Tablet.Item = 'dealer_tablet'` and an ox\_inventory item with `server = { export = 'pepper_dealership.dealer_tablet' }`.
* **lb-phone:** if lb-phone runs, the app appears automatically (`Config.Tablet.LbPhone`).

## Configuration

| File                     | Content                                                                                                                                                        |
| ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `config/config.lua`      | The essentials: language, framework, commands, garage, keys, showroom, purchase, plates, test drive, licence, police, financing, trade-in, used cars, auctions |
| `config/advanced.lua`    | Fine-tuning: dealer types, categories, blips, keys, camera, distances, timings, models, events. Values from `config.lua` take priority                         |
| `config/ranks.lua`       | Ranks with permissions, wage, commission, discount; player dealership (price range, stock, offers), wholesale, ownership                                       |
| `config/progression.lua` | Level curve, XP, unlocks, upgrades, discount cap, promotions, loyalty, requests, tablet                                                                        |
| `config/dealers.lua`     | Templates (check coordinates in game)                                                                                                                          |
| `config/vehicles.lua`    | Catalog for the first fill (maintained in game afterwards)                                                                                                     |
| `config/colors.lua`      | Paint colors                                                                                                                                                   |
| `config/server.lua`      | Webhooks, admin ACE, allowed image hosts (never sent to clients)                                                                                               |

Dealerships, catalog, assortments, stock, prices and promotions live in the database and are maintained in game.

## Permissions

| Who                     | Permission                                                                                                                       |
| ----------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| Admin                   | ACE `pepper_dealership.admin` or `Config.AdminGroups` – admin menu, all dealerships, promotions for NPC dealerships too          |
| Staff (job/purchasable) | Ranks from `config/ranks.lua`: `sell`, `display`, `used`, `stock`, `prices`, `staff`, `account`, `promo`, `upgrades`, `settings` |
| Job dealership          | Rank from the job grade (mapping per dealership in the admin menu)                                                               |

## Creating a dealership

1. `/dealeradmin` → take a **template** or **New dealership**: name, dealer type, operating mode (NPC/job/purchasable), job or price.
2. Tab **Points** → **Set points one by one**: salesperson, preview spot, pickup spots, test drive start; optionally trade-in zone, display and used car spots; for job/purchasable also office, time clock and delivery point. In placement mode: aim, **E** set, **G** own position or own vehicle, **mouse wheel** rotate, **Page up/down** height, **X** skip, **Z** back, **ESC** finish.
3. Tab **Assortment**: choose categories, hide single models.
4. **Save** – blip, salesperson and display vehicles appear for everyone right away.

## Buying, test drive, financing

At the salesperson **open the showroom**: pick a vehicle, paint and plate, handover and payment. **Test drive** starts right away; `/teststop` ends it. With **Finance** you choose plan and down payment – payments are taken from the bank account automatically, the overview is at `/myfinance`. For a **trade-in** park the old vehicle in the trade-in zone and select it in the showroom.

## Licence, deposit and police

**Driving licence:** Test drives and purchases need the matching licence. Set your licence script in `Config.License.System`:

| Setting                | For                                                                                                |
| ---------------------- | -------------------------------------------------------------------------------------------------- |
| `'esx_license'`        | ESX with esx\_license – also esx\_dmvschool, okokDrivingSchool (ESX) and most ESX driving schools  |
| `'qb'`                 | QBCore/Qbox licences (`metadata.licences`) – qb-drivingschool, qb-cityhall, okokDrivingSchool (QB) |
| `'bcs_licensemanager'` | BCS License Manager                                                                                |
| `'item'`               | Licence as an inventory item – bl\_idcard, um-idcard, qbx\_idcard, ox\_inventory cards             |
| `'custom'`             | your own check via `Config.License.Check`                                                          |
| `'auto'`               | detects BCS → esx\_license (ESX) → QBCore/Qbox                                                     |
| `false`                | no check                                                                                           |

`Config.License.Classes` sets which class a vehicle needs (car, motorcycle, truck, boat, air), `Config.License.Names` how the licence is called in your script. Boats and aircraft are unchecked by default. `TestDrive`/`Purchase` turn the check off separately, `OnError` decides what happens when the lookup fails.

**Deposit:** A test drive takes a deposit (`Config.TestDrive.Deposit`, share of the vehicle price with minimum and maximum). It is returned when the vehicle comes back, minus any damage.

**Theft:** Driving further than `MaxDistance` triggers a warning. Without turning back within `Theft.WarnSeconds` the vehicle counts as stolen: the dealership keeps the deposit (player dealership: into the account), the police get an alert with the position (renewed every `AlertEverySeconds`), and after `TrackMinutes` the dealership recovers the vehicle. No test drive for `Theft.CooldownMinutes` afterwards. Alerts go through `Config.Police.Dispatch` (Pepper Emergency pepper\_dispatch, ps-dispatch, cd\_dispatch, qs-dispatch, rcore\_dispatch, core\_dispatch) or, without a dispatch script, built in as a notification with blip to every player with a job from `Config.Police.Jobs`. With `Theft.Enabled = false` the drive simply ends at the limit as before.

## Selling a vehicle to a player

With `/sellcar` a player sells their own vehicle directly to another player. Both stand at the vehicle, the seller picks vehicle, buyer (player ID) and price, the buyer sees condition, price and registration fee and accepts or declines. Afterwards the vehicle is in the buyer's garage, the keys change and the vehicle passport counts one more previous owner. Financed, listed, rented and occupied vehicles cannot be sold. Settings in `Config.Handover` (distance, price limits, fee, payment methods, offer time).

## Player dealership

* **Buy** at the salesperson of a purchasable dealership (one per character). The owner finds the **office** inside.
* **Time clock**: only staff who are clocked in sell and earn wages and commission.
* **Stock**: new cars only come from stock. Buy at 70 % (delivery) or cheaper via **transfer** from the factory – waypoint, hand it in at the delivery point with **E**, damage is repaired from the account.
* **Offer to customers**: in the showroom “Make an offer” → choose a nearby customer, set the discount, send. The customer sees it with payment, financing, trade-in and coupon and accepts.
* **Self-service**: when nobody is on duty, customers buy themselves (can be turned off in the office, as can financing and trade-in in self-service).

## Levels, upgrades and promotions

Player dealerships earn **XP** for sales, transfers, purchases after a test drive and paid-off dealer financing. **Levels 1–50** (about 80–100 hours of business) unlock vehicle classes (e.g. sports from 15, super from 30) and features: coupons from 5, deal of the week from 8, dealer financing from 10, long terms from 20, “featured” in the catalog from 25. With money from the business account the owner upgrades stock, display, staff, buying discount and delivery time. All discounts together are capped at 25 % (`Config.Pricing`) and a player dealership never sells below the buying price. NPC dealerships have no level limits.

## Showroom stage and handover

The optional **Handover stage** point in the admin menu enables the big handover. Without it pickup works as usual. Timing, keys and cover are in `Config.Reveal`, the stage in `Config.Showroom`.

## Negotiation

In NPC dealerships and self-service, players can negotiate for up to 3 rounds. Owners can turn this off in the office. Staff cannot negotiate at their own dealership. Values are in `Config.Negotiation`. A negotiated price is valid for 5 minutes and one purchase; the discount cap and purchase cost remain limits.

## Limited series

Admins create series in the admin menu under **Series**. The price is fixed. Player dealerships only sell series that list them; the price minus the series cost goes to the account and stock stays untouched. Equipment values are GTA numbers. `Config.Series` and `Config.Collectors` control presale, limits, points and ranks.

## Auctions

Under **Auction house** admins set the lot spot and auctioneer at their position, plan dates and add lots. `Config.Auction.Schedule` creates weekly dates; a date without lots is dropped. Money is only taken when the lot is sold, plus the buyer premium. If the top bidder is offline or cannot pay, the next bid wins and they are blocked for that auction. With `Remote = false` bidding only works in the hall.

## NPC customers and reputation

Customers only come to player dealerships with a salesperson on duty and the **Customer area** point set. Serve them in the office under **Customers**. A sale creates real money, so `MaxRevenuePerHour` and `MaxPerPlayerHour` in `config/customers.lua` apply. Customer types, names and the reputation window are there too.

## Events

Staff with the promotions right plan events in the office, between 15 minutes and 3 days ahead. If nobody is on duty at the start, the event fails: cost lost, reputation −0.5. Types and extras are in `Config.Events`.

## Catalog tablet and phone

`/dealer` (bindable key) shows every player all dealerships with status (open, staff on duty, self-service, closed), assortment, stock, deal of the week, waypoint, **test drive appointment** and **purchase request**, the **leaderboard** and own purchases. Staff also see their dealership’s requests. With lb-phone the same view is an app.

## Commands

| Command        | Who      | Purpose                                       |
| -------------- | -------- | --------------------------------------------- |
| `/dealeradmin` | Admin    | Admin menu                                    |
| `/dealer`      | everyone | Catalog tablet                                |
| `/myfinance`   | everyone | My financing & listings                       |
| `/teststop`    | everyone | End test drive or transfer                    |
| `/sellcar`     | everyone | Sell your own vehicle to a player next to you |

All commands can be renamed or disabled in the config.

## Webhooks

In `config/server.lua`:

| Webhook    | Content                                                                                                       |
| ---------- | ------------------------------------------------------------------------------------------------------------- |
| `admin`    | Dealerships created/changed/deleted, owner, catalog, actions from the admin overview                          |
| `business` | Purchases, ownership changes, player-to-player sales, stolen test drives, repossessions, used cars, level-ups |
| `security` | Suspicious activity                                                                                           |

## Exports

**Server**

```lua
exports.pepper_dealership:getDealers()                 -- all dealerships (public view)
exports.pepper_dealership:getDealer(id)
exports.pepper_dealership:getVehicle(model)            -- catalog entry
exports.pepper_dealership:getVehiclePrice(model)
exports.pepper_dealership:getCatalog()
exports.pepper_dealership:isFinanced(plate)            -- for garage/trade scripts: do not sell/transfer
exports.pepper_dealership:getFinance(plate)
exports.pepper_dealership:isListed(plate)              -- listed on the used car lot
exports.pepper_dealership:getRank(src, dealerId)       -- rank in a player dealership or nil
exports.pepper_dealership:getDuty(src)                 -- dealership ID on duty or nil
exports.pepper_dealership:getBalance(dealerId)
exports.pepper_dealership:addBalance(dealerId, amount, note)
exports.pepper_dealership:getStock(dealerId, model)
exports.pepper_dealership:getLevel(dealerId)
exports.pepper_dealership:addXp(dealerId, amount)
```

**Server events** – for police computers, insurance, logs. Server side only, receive them with `AddEventHandler` (not `RegisterNetEvent`):

```lua
AddEventHandler('pepper_dealership:vehiclePurchased', function(e) end)    -- source, identifier, dealerId, model, plate, price, financed, delivery, used
AddEventHandler('pepper_dealership:ownerChanged', function(e) end)        -- plate, model, from, to, source, price, via ('handover' | 'listing' | 'auction')
AddEventHandler('pepper_dealership:vehicleSoldToDealer', function(e) end) -- source, identifier, dealerId, model, plate, price
AddEventHandler('pepper_dealership:vehicleRepossessed', function(e) end)  -- plate, model, identifier, dealerId
AddEventHandler('pepper_dealership:testDriveStolen', function(e) end)     -- source, identifier, dealerId, model, plate, coords
```

## Framework integration

The bridges in `bridge/` (open) detect ESX, QBCore and Qbox automatically (`Config.Framework = 'auto'`). Money runs through the framework, bought vehicles through the garage bridge (`bridge/server/garage.lua`, own functions with `Config.Garage.System = 'custom'`), keys through `bridge/*/keys.lua`, fuel through `bridge/client/fuel.lua`.

## Troubleshooting

| Problem                                      | Solution                                                                                                                                    |
| -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| Bought vehicle missing in the garage         | `Config.Garage.System` = your garage script? Garage names in `Config.Garage.Garages` correct? The console on start (“Garage: …”) shows both |
| No keys after buying                         | Key script running? Otherwise `Config.Keys.Mode = 'custom'` with your own functions                                                         |
| Preview vehicle missing in the showroom      | Set the preview spot again in the admin menu; check the model in the catalog (“Check model”)                                                |
| Customer cannot buy at a player dealership   | A salesperson is on duty (buy via offer) or self-service is off                                                                             |
| Vehicle class missing at a player dealership | Level too low – see office → Level or `config/progression.lua`                                                                              |
| App missing in lb-phone                      | `Config.Tablet.LbPhone = true`? The app registers again after an lb-phone restart; F8 with `Config.Debug = true` shows the reason           |

## Changelog

**Current version: 1.0.0.** All changes are listed in `CHANGELOG.md` inside the resource.

## Support

Open a ticket in our [Discord](https://discord.gg/6NaFJWKDYu) (category “Script Support”) and link your purchase with `/verify` first.
