> 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-carwash.md).

# Pepper Carwash

On most servers a car wash is a marker: drive in, pay, clean. With **Pepper Carwash** admins build car washes right in the game – with a **guided setup**, from a **blueprint**, freely in **build mode** or as **zones** inside an existing building – and players own and run them. Everything is built from props that ship with the game: no MLO, no addon models.

Customers drive to the entrance, pick one of **6 wash programs** and get washed: in a tunnel wash the vehicle is guided through the stations, in a gantry wash the vehicle stands still and the gantry moves over it. A car wash without an owner works as a state-run car wash for everyone. Put up for sale, a player buys it and runs it from the **business tablet**: business account, own prices, storage, stations, staff, levels 1–100 with upgrades, and NPC customers while staff is on duty.

{% embed url="<https://youtu.be/qz0wMCKWzQ8>" %}
Pepper Carwash – trailer
{% endembed %}

{% hint style="success" %}
**Get Pepper Carwash:** [pepper-scripts.tebex.store](https://pepper-scripts.tebex.store)
{% endhint %}

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

{% hint style="warning" %}
**Check the coordinates:** The tab **Default car washes** in `/carwashadmin` can create five well-known locations (`config/presets.lua`). Their coordinates are approximations – check every car wash on site and correct it with *Redo zones*.
{% endhint %}

### Features

* **Four ways to create a car wash**, all in game and without a restart: guided setup, blueprint, build mode (catalog with 49 parts), zones inside existing buildings
* **Quick setup** (since 1.1.0): place only the lane – the script sets up stations, gate, terminal, walls, equipment and signs wherever there is room
* **Self-measurement** (since 1.1.0): the script reads the model dimensions from the game once and places every part centred and on the ground – custom props too
* **Your own logo on the large billboard** (since 1.1.0): drop an image into the folder, enter it in the config, selectable or switched off per car wash
* **3 types:** self-service bay, gantry wash, tunnel wash – built from stock GTA props only
* **6 wash programs** (Basic, Foam, Underbody, Wax, Premium, Showroom finish) and **6 extras** (Wheel cleaning, Bug remover, Glass sealant, Hot wax, Nano sealant, Engine bay wash) with particles, sound and a progress display
* **Wax protection** keeps a vehicle clean for the time that was bought – stored in the database, survives the garage and a restart
* **Self-service bay:** buy 1 to 5 minutes, take the spray gun, wash the vehicle yourself
* **Vacuum spot** with self-service vacuuming and the services interior cleaning and hand polish
* **Ownable business:** bought at the sale sign, one car wash per player (per character or per license), sell it back or transfer it to another player
* **Business tablet** with 14 pages: Overview, Tasks, Level & upgrades, Exam, Finances, Prices, Storage, Stations, Staff, Loyalty cards, Fleets, Statistics, Settings, Help
* **Stock and wear:** water, shampoo and wax are used up, stations wear down, faults stop the lane, a technician can be called
* **Staff:** hire players on site, 5 ranks with rights, duty, commission, task pay and shift pay from the business account – no framework job needed
* **8 tasks**, 7 of them as mini-games: fix fault, manual pre-wash, hand drying, interior cleaning, hand polish, refill chemicals, service the brushes, pick up delivery – with a performance rating from 80 to 120 % for pay and XP
* **Business levels 1–100** with 90 upgrades (stations, lanes, tanks, speed, advertising and more), a build mode for owners and **business exams** at level 30, 60 and 90
* **NPC customers** while staff is on duty, **loyalty cards**, **company cards** and **fleet contracts**
* **Inactivity rule:** an owner who was offline for 30 days loses the car wash (warnings, admin protection, restore within 14 days – all in the config)
* **Admin tools in game:** create, change, move and remove car washes, ownership, log, diagnostics
* **Built-in UI** for prompts, progress bar, notifications, dialogs and menus – the only dependency is oxmysql
* **Optional inventory items** (canisters, spare parts, tablet, loyalty card) with 5 ready-made images
* In-game help for staff, owners and customers, plus a player guide in English and German to copy into your wiki
* 6 Discord webhooks, server and client exports
* German & English, open config, locales, bridges and install files

### At a glance

|                             |                                                                                                                          |
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
| **Version**                 | 1.0.0                                                                                                                    |
| **Framework**               | ESX Legacy (`es_extended`), QBCore (`qb-core`) or Qbox (`qbx_core`) – detected automatically                             |
| **FiveM server**            | build 7290 or newer, **OneSync** required                                                                                |
| **Dependencies (required)** | [oxmysql](https://github.com/overextended/oxmysql) – nothing else. **No ox\_lib**, no target script, no inventory needed |
| **Interaction**             | built-in help text + key · ox\_target or qb-target optional for the self-service bay on foot (`Config.Interact.Mode`)    |
| **Optional**                | inventory items for ox\_inventory, qb-inventory, ps-inventory, qs-inventory or the ESX inventory                         |
| **Database**                | MySQL 8 or MariaDB 10.x – tables are created automatically                                                               |
| **Models**                  | stock GTA props only – no MLO, no addon models                                                                           |
| **Tested in game**          | ESX Legacy with ox\_inventory                                                                                            |
| **Languages**               | German, English                                                                                                          |
| **Delivery**                | Cfx.re Asset Escrow (`config/`, `locales/`, `bridge/`, `install/` open)                                                  |

### Installation

Work through the steps in order – every step ends with a **checkpoint**.

{% hint style="warning" %}
**Always open files with a text editor**, for example [Visual Studio Code](https://code.visualstudio.com/) or [Notepad++](https://notepad-plus-plus.org/) – never with Word or WordPad.
{% endhint %}

#### Step 1 – Check the requirements

In short: a FiveM server with OneSync and oxmysql. Prompts, progress bar, notifications, dialogs, menus and key bindings are built into the resource.

| What                                                                                    | Why                                                                                                   | Required?   |
| --------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | ----------- |
| FiveM server **build 7290 or newer**                                                    | older servers will not start the script                                                               | yes         |
| **OneSync** enabled                                                                     | the server verifies positions, vehicles and seats itself                                              | yes         |
| **MySQL 8 / MariaDB 10.x** + **oxmysql**                                                | car washes, business account, stock, levels, wax protection                                           | yes         |
| **ESX Legacy**, **QBCore** or **Qbox**                                                  | characters, money, groups – detected automatically                                                    | exactly one |
| ox\_lib                                                                                 | not used and not loaded – if it runs for other scripts, that does no harm                             | no          |
| **ox\_target** or **qb-target**                                                         | only for the self-service bay on foot – without a target a help text with a key is shown              | no          |
| Inventory: ox\_inventory, qb-inventory, ps-inventory, qs-inventory or the ESX inventory | only for the optional items (step 8) – without one, canisters and spare parts are counters in storage | no          |

**OneSync:** in txAdmin set **Settings → FXServer** to **On** – without txAdmin put `set onesync on` at the very top of your `server.cfg`.

{% hint style="info" %}
**Tested in game on ESX Legacy with ox\_inventory.** The integrations for QBCore, Qbox and the other inventories are built against their source code or documentation.
{% endhint %}

{% hint style="success" %}
**Checkpoint:** On server start the console shows `Started resource <name>` for `oxmysql` and your framework.
{% endhint %}

#### Step 2 – Download and extract

1. Open [Cfx.re Portal → Granted Assets](https://portal.cfx.re/assets/granted-assets) and download **pepper\_carwash**.
2. Copy the `pepper_carwash` folder to `resources/[pepper]/` (the `[pepper]` subfolder is up to you).

```
resources/
└── [pepper]/
    └── pepper_carwash/
        ├── bridge/
        ├── client/
        ├── config/
        │   ├── blueprints.lua
        │   ├── config.lua
        │   ├── exams.lua
        │   ├── levels.lua
        │   ├── parts.lua
        │   ├── presets.lua
        │   ├── programs.lua
        │   ├── server.lua
        │   └── staff.lua
        ├── html/
        ├── install/
        │   ├── items/
        │   └── pepper_carwash.sql
        ├── locales/
        ├── server/
        ├── shared/
        ├── INSTALL.md
        ├── PLAYER-GUIDE.md
        ├── SPIELER-ANLEITUNG.md
        └── fxmanifest.lua
```

{% hint style="danger" %}
**Never rename the `pepper_carwash` folder.** Events and the UI use the resource name.
{% endhint %}

{% hint style="warning" %}
**Asset Escrow:** The script only starts on a server whose license key (`sv_licenseKey`) belongs to the same Cfx.re account you bought it with. More: **Asset Escrow**.
{% endhint %}

#### Step 3 – server.cfg

Add Pepper Carwash **after** oxmysql and your framework:

```cfg
ensure oxmysql
ensure es_extended        # or qb-core / qbx_core
# ensure ox_inventory     # optional (items) – or qb-inventory / ps-inventory / qs-inventory
# ensure ox_target        # optional (self-service bay on foot) – or qb-target
ensure pepper_carwash
```

You do not need an ox\_lib line for Pepper Carwash. Inventory and target should come before it; if they start later, Pepper Carwash detects the inventory afterwards.

{% hint style="warning" %}
**Mind the order:** If no framework is running when `pepper_carwash` starts, the resource falls back to standalone mode and says so in a red box in the console. Identity is then the Rockstar license and money is the ox\_inventory item `money`. Your framework therefore has to come **before** `pepper_carwash`.
{% endhint %}

{% hint style="warning" %}
**Other car wash scripts:** Scripts such as `esx_carwash` or `qbx_carwash` also use `/carwash` and the same locations. Stop the other script (recommended) or rename the command with `Config.Commands.Main`.
{% endhint %}

#### Step 4 – Admin permission

A player is an admin if **one** of these is true – checked on the server for every single call:

* **ACE permission `pepper_carwash.admin`** – the reliable way on every framework
* **a group from `Config.AdminGroups`** (default `admin`, `superadmin`, `god`)

```cfg
add_ace group.admin pepper_carwash.admin allow                        # everyone in group.admin
add_ace identifier.license:YOUR_LICENSE pepper_carwash.admin allow    # or a single player
```

How the group is checked depends on the framework:

| Framework        | Check                                                       |
| ---------------- | ----------------------------------------------------------- |
| ESX Legacy       | `xPlayer.getGroup()` equals one of the names                |
| QBCore           | `QBCore.Functions.HasPermission(src, name)`                 |
| Qbox, standalone | ACE permission `group.<name>` – use the ACE line above here |

{% hint style="success" %}
**Checkpoint:** After a server restart `/carwashadmin` opens the admin UI instead of “You do not have permission to do that”.
{% endhint %}

#### Step 5 – Database

Nothing to do: on first start the resource creates eleven tables (`pepper_carwash_*`). The database user needs the CREATE and ALTER privileges for that. If your user has **no CREATE permission**, import `install/pepper_carwash.sql` first.

#### Step 6 – Check the config

Open `config/config.lua` and check at least:

* `Config.Locale = 'en'` (or `'de'`) – applies to all players
* `Config.Framework = 'auto'` – detects ESX, QBCore and Qbox
* `Config.Currency` and the prices
* `Config.Economy.IncomeMultiplier` – the main dial for all money from NPC customers
* `Config.Ownership.Scope` – one car wash per character (`'character'`) or per player (`'license'`)
* `Config.Commands` – rename `/carwash` if another script uses it

Webhooks are in `config/server.lua`. Every key with its default: **Configuration**.

#### Step 7 – First start and first car wash

1. Start the server. The console shows a green line `Pepper Carwash 1.1.0 started (…)` with framework, car washes, parts and vehicles with wax protection.
2. In game, open `/carwashadmin` → tab **New** and create the first car wash – the **guided setup** is recommended.
3. Set the status: *For sale* (a sale sign appears, a player buys the car wash there), *State-run* (usable by everyone) or *Locked*.
4. Drive to the entrance, press `E`, pick a program and start the wash.

The four ways to create a car wash are described under **Gameplay**.

{% hint style="success" %}
**Checkpoint:** The console shows the green start line with the right framework, `/carwashadmin` opens, and a wash runs through at your first car wash.
{% endhint %}

#### Step 8 – Items (optional)

Everything works without this step: canisters and spare parts are then counters in the car wash's storage. **With** items the wholesaler hands the goods into the inventory on pick-up, and an employee stocks them at the storage point.

| Item                                                        | Purpose                                     | Switch                                  |
| ----------------------------------------------------------- | ------------------------------------------- | --------------------------------------- |
| `carwash_cans_shampoo`, `carwash_cans_wax`, `carwash_parts` | canisters of shampoo / wax, spare parts     | `Config.Supply.UseItems` (`'auto'`)     |
| `carwash_tablet`                                            | use = opens the tablet of your own car wash | `Config.Items.Tablet.Enabled` (`false`) |
| `carwash_card`                                              | loyalty card: use = shows your stamps       | `Config.Items.Card.Enabled` (`false`)   |

Templates and the 5 images are in `install/items/`. Always: add the items → copy the images → restart the server.

{% tabs %}
{% tab title="ox\_inventory" %}
For ESX, QBCore and Qbox.

1. Open `install/items/ox_inventory_en.lua` (English labels) or `ox_inventory.lua` (German labels).
2. Copy **only the entries** between `return {` and the final `}`.
3. Paste them into `ox_inventory/data/items.lua` **inside** the `return { … }` table (before the final `}`).
4. Copy all files from `install/items/images/*.png` to `ox_inventory/web/images/`.

Tablet and loyalty card contain the line `client = { export = 'pepper_carwash.useTablet' }` or `'pepper_carwash.useCard'` – it makes the item usable and has to stay.
{% endtab %}

{% tab title="qb-inventory / ps-inventory" %}
For QBCore.

1. Open `qb-core/shared/items.lua` and check which style it uses: `name = '…'` = new format, `['name'] = '…'` = old format.
2. Open the matching template – new format `install/items/qb-core_items_en.lua`, old format `qb-core_items_old_en.lua` (German labels: `qb-core_items.lua` and `qb-core_items_old.lua`) – and paste its five entries into the items table.
3. Copy the images from `install/items/images/*.png` to `qb-inventory/html/images/` or `ps-inventory/html/images/`.
4. ps-inventory with decay only: add the `decay` value the same way your existing items have it.

Pepper Carwash registers the use of tablet and loyalty card itself.
{% endtab %}

{% tab title="qs-inventory" %}

1. **ESX:** paste the entries from `install/items/qs-inventory_en.lua` (German labels: `qs-inventory.lua`) into `qs-inventory/shared/items.lua`. **QBCore:** use the qb-core templates in `qb-core/shared/items.lua` instead.
2. Copy the images from `install/items/images/*.png` to `qs-inventory/html/images/`.

Pepper Carwash registers the use of tablet and loyalty card itself.
{% endtab %}

{% tab title="ESX inventory" %}

1. Run `install/items/esx_items.sql` on the server database (`INSERT IGNORE` only – existing rows are kept).
2. Weight there is in ESX units, not grams – adjust if needed.
3. Copy the images to your inventory's image folder.

Pepper Carwash registers the use of tablet and loyalty card itself.
{% endtab %}
{% endtabs %}

{% hint style="danger" %}
**Check your inventory after pasting:** an error in your inventory's item file (for example a missing brace) takes the whole inventory down – then cash payments fail as well. Make sure your inventory starts without an error in the console.
{% endhint %}

{% hint style="success" %}
**Checkpoint:** After the restart the console prints a line starting with `[pepper_carwash] Items:` that names the inventory in use. If an item is missing, the line names it and the business keeps running without items – this never causes an error.
{% endhint %}

How it works with items:

1. Order canisters or spare parts on the tablet (**Storage**) with "pick up yourself" – paid at once from the business account.
2. An employee with the "pick up deliveries" right loads at the wholesaler (blip): as many as they can carry, at most 10 per trip (`Config.Supply.Items.MaxCarry`).
3. At the storage point of the car wash: `E` stocks the goods – item gone, stock up.
4. Pay and XP are granted once, as soon as a paid order of **this** car wash is completely in storage.

Detection order is ox\_inventory → qs-inventory → ps-inventory → qb-inventory → ESX; pin one with `Config.Inventory`.

#### Updating

1. Back up your own changes in `config/`, `locales/` and `bridge/`.
2. Stop the server (or `stop pepper_carwash`).
3. **Delete** the old `pepper_carwash` folder and copy the new one to the same place – do not copy into the old folder.
4. Carry your own values over into the **new** files – do not copy the old files back, new versions bring new switches and texts.
5. Restart the server and look for the green start line in the console.

Running washes are ended on stop and refunded according to the car wash's rule. Players' key bindings are kept.

**From 1.0.0 to 1.1.0**

* No database change. Your `config.lua` from 1.0.0 keeps working unchanged – all new switches (`Config.Signs`, `Config.Measure`, `Config.Guide`, `Config.World.AutoRebuild`) have defaults.
* After the first start the script measures its models once in the background as soon as an admin is online (console: `Vermessung gestartet …` / `Vermessung abgeschlossen …`).
* The blueprints changed in two places (vacuum post, entrance sign). For existing blueprint car washes `/carwashadmin` shows the yellow notice at the top – press **"Reset all affected car washes"** once. Nothing is rebuilt by itself (`Config.World.AutoRebuild = 'ask'`). The reset puts blueprint parts you moved in build mode back in their place; parts you added stay.
* The large billboard now shows the Pepper Scripts logo by default. Your own image or switching it off: **Configuration**.
* Use the new `config/parts.lua` and `config/blueprints.lua` and carry only your own changes over. With the files from 1.0.0 everything keeps running as before, but without an image on the billboard and without the corrections to dryer fan, plant pot, vacuum post and entrance sign.

{% hint style="info" %}
Problems? See the **FAQ**. The complete guide in English and German is `INSTALL.md` in the resource.
{% endhint %}

### Configuration

| File                       | Contents                                                                                                                                                                                                                     |
| -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `config/config.lua`        | language, currency, commands, admin groups, keys, blips, washing, self-service bay, wax, ownership, economy, levels, NPC customers, tips, loyalty cards, fleets, tablet, inactivity, stock, supply, wear, build mode, limits |
| `config/programs.lua`      | programs, extras, stations with effect and sound candidates, spray gun (`Config.LanceSpray`)                                                                                                                                 |
| `config/parts.lua`         | parts catalog with model candidates and dimensions, swing of the gate                                                                                                                                                        |
| `config/blueprints.lua`    | the three blueprints (self-service bay, gantry wash, tunnel wash)                                                                                                                                                            |
| `config/presets.lua`       | five well-known locations for the tab **Default car washes**                                                                                                                                                                 |
| `config/staff.lua`         | ranks and rights, wages, duty, tasks, performance rating and mini-game rules                                                                                                                                                 |
| `config/levels.lua`        | unlock list level 1–100 with upgrade prices                                                                                                                                                                                  |
| `config/exams.lua`         | business exams                                                                                                                                                                                                               |
| `config/server.lua`        | webhooks, admin ACE – **never** sent to clients                                                                                                                                                                              |
| `locales/de`, `locales/en` | all texts                                                                                                                                                                                                                    |

Restart the resource after every change (`restart pepper_carwash`).

{% hint style="warning" %}
The coordinates in `config/presets.lua` are **approximations**. Check every default car wash on site and correct it with *Redo zones*.
{% endhint %}

{% hint style="danger" %}
Do not change the `key` of an upgrade in `config/levels.lua` after the first start – the purchase is stored in the database under that name.
{% endhint %}

#### Basics

| Option                  | Default                                           | Meaning                                                                                     |
| ----------------------- | ------------------------------------------------- | ------------------------------------------------------------------------------------------- |
| `Config.Locale`         | `'de'`                                            | language (`de` / `en`) – applies to all players, there is no per-player choice              |
| `Config.Framework`      | `'auto'`                                          | `auto`, `esx`, `qbcore`, `qbox`, `standalone` – set it explicitly if detection does not fit |
| `Config.Commands`       | `carwash`, `carwashduty`, `carwashadmin`, `cwdev` | command names – see **Commands & Exports**; an empty string disables a command              |
| `Config.AdminGroups`    | `admin`, `superadmin`, `god`                      | framework groups with admin permission (in addition to the ACE)                             |
| `Config.Notify.Mode`    | `'pepper'`                                        | built-in notifications · `'framework'` = notification of ESX / QBCore / Qbox                |
| `Config.Effects.Sounds` | `'auto'`                                          | `'nui'` forces the UI sounds, `'off'` disables sound                                        |
| `Config.Dirt.Mode`      | `'native'`                                        | `'custom'` = your own dirt system via `bridge/client/dirt.lua`                              |
| `Config.Debug`          | `false`                                           | extra output in the server console and F8 – switch it off again afterwards                  |

Your own language: copy the folder `locales/en` (for example to `locales/fr`), translate the four files and put the folder name into `Config.Locale`. A missing text falls back to English.

#### Economy and ownership

| Option                             | Default                   | Meaning                                                                                       |
| ---------------------------------- | ------------------------- | --------------------------------------------------------------------------------------------- |
| `Config.Economy.IncomeMultiplier`  | `1.0`                     | **the main dial**: scales all money from NPC customers. It does not change prices for players |
| `Config.Economy.UpgradeMultiplier` | `1.0`                     | scales all upgrade and decoration prices                                                      |
| `Config.Ownership.Scope`           | `'character'`             | one car wash per character or (`'license'`) per player                                        |
| `Config.Ownership.DefaultPrice`    | 40,000 / 80,000 / 150,000 | suggested purchase price for self-service bay / gantry wash / tunnel wash                     |
| `Config.Inactivity.Enabled`        | `true`                    | owners who were offline too long lose the car wash; the business account is forfeited         |
| `Config.Inactivity.Days`           | `30`                      | days offline until the car wash is released – with warnings 7, 3 and 1 day before             |

Inside a business the owner sets every price between 50 % and 130 % of the base price (upgrades raise the upper limit), the commission between 0 and 30 % and the pay per task between 50 and 150 % of the default.

#### Washing and self-service bay

| Option                              | Default  | Meaning                                                                           |
| ----------------------------------- | -------- | --------------------------------------------------------------------------------- |
| `Config.Wash.StaffRequired`         | `false`  | `true`: players can only wash at owned car washes while staff is on duty          |
| `Config.Wash.Guide`                 | `'auto'` | how the vehicle is guided through the tunnel: `'task'`, `'speed'`, `'conveyor'`   |
| `Config.Wash.MaxVehicle`            | –        | largest vehicle that is accepted – adjust if a vehicle is rejected as "too large" |
| `Config.Wash.AbortDefaultKey`       | `'X'`    | default of the key binding "Cancel wash"                                          |
| `Config.SelfService.PricePerMinute` | `15`     | price of one minute in the self-service bay                                       |
| `Config.SelfService.MaxMinutes`     | `5`      | most minutes that can be bought at once                                           |

Programs and extras are in `config/programs.lua` (`Config.Programs`, `Config.Extras`):

| Program         | From level | Base price | Duration | Wax protection |
| --------------- | ---------- | ---------- | -------- | -------------- |
| Basic           | 1          | $40        | 40 s     | –              |
| Foam            | 3          | $70        | 55 s     | –              |
| Underbody       | 8          | $90        | 60 s     | –              |
| Wax             | 15         | $110       | 75 s     | 60 min         |
| Premium         | 25         | $180       | 100 s    | 120 min        |
| Showroom finish | 75         | $260       | 120 s    | 180 min        |

| Extra           | From level | Base price | Note                                                   |
| --------------- | ---------- | ---------- | ------------------------------------------------------ |
| Wheel cleaning  | 12         | $15        |                                                        |
| Bug remover     | 18         | $10        |                                                        |
| Glass sealant   | 33         | $20        |                                                        |
| Hot wax         | 35         | $25        | wax programs only – extends the wax protection by 50 % |
| Nano sealant    | 50         | $60        | wax protection of at least 240 min                     |
| Engine bay wash | 87         | $30        |                                                        |

{% hint style="info" %}
The level is the **business level** of the car wash. A program also needs its stations to be built and enough water, shampoo and wax in stock – locked programs state the reason in the program selection.
{% endhint %}

#### Interaction and keys

| Option                          | Default  | Meaning                                                                                                        |
| ------------------------------- | -------- | -------------------------------------------------------------------------------------------------------------- |
| `Config.Interact.Mode`          | `'auto'` | self-service bay: ox\_target, otherwise qb-target, otherwise help text + key · `'textui'` = never use a target |
| `Config.Interact.KeyWithTarget` | `true`   | help text + key stays active at the self-service bay even with a target · `false` = target only there          |
| `Config.Interact.KeyMapping`    | `true`   | keys via FiveM key bindings (players can rebind them) instead of fixed keys                                    |
| `Config.Interact.DefaultKey`    | `'E'`    | default of the key binding "Interact"                                                                          |

All other points (entrance, office, duty, storage, tasks) always use help text + key.

{% hint style="info" %}
`DefaultKey` and `AbortDefaultKey` are only the default for players who have **never loaded the resource before** – FiveM remembers the binding per player. Anyone who has connected once keeps their key and rebinds it themselves.
{% endhint %}

#### Items

| Option                         | Default  | Meaning                                                                                                |
| ------------------------------ | -------- | ------------------------------------------------------------------------------------------------------ |
| `Config.Inventory`             | `'auto'` | detect the inventory for the optional items or set it explicitly · `'none'` = never use one            |
| `Config.Supply.UseItems`       | `'auto'` | canisters / spare parts as items once inventory and items exist · `false` = always counters in storage |
| `Config.Supply.Items.MaxCarry` | `10`     | most pieces the wholesaler hands out per load                                                          |
| `Config.Supply.PickupMinCost`  | `200`    | pick-up orders below this list value earn the collector no pay                                         |
| `Config.Items.Tablet.Enabled`  | `false`  | tablet item `carwash_tablet` – use opens the tablet of your own car wash                               |
| `Config.Items.Tablet.Give`     | `true`   | owners and newly hired employees receive a tablet item if they have none                               |
| `Config.Items.Card.Enabled`    | `false`  | loyalty card item `carwash_card` – handed out with the first stamp                                     |

Setting up the items: **Installation**.

#### Staff and tasks

Ranks, rights, wages and tasks are in `config/staff.lua`.

| Option                     | Default                                    | Meaning                                                                                                                                                       |
| -------------------------- | ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Config.Tasks.Performance` | `{ Min = 0.8, Max = 1.2, Enabled = true }` | performance rating: pay and XP of every task with a mini-game range from 80 % to 120 %. `Enabled = false`: always exactly the configured pay and the fixed XP |
| `Config.Tasks.Games`       | one line per mini-game                     | the mini-game rules in one place (zones, seconds, green zone, hits) – applies to server and UI alike                                                          |
| `Config.Tasks.DryWindow`   | `120`                                      | "Hand drying" is offered for that many seconds after a wash without dryer – an NPC customer waits at the exit exactly that long                               |
| `Config.Tasks.DryEffect`   | `{ Reduce = 1.0, Fresh = true }`           | visible result of drying: how much remaining dirt disappears (scale 0–15) · paint "fresh"                                                                     |

The default ranks, pay and limits of every task are listed under **Gameplay**.

#### Levels and business exams

| Option                       | Default | Meaning                               |
| ---------------------------- | ------- | ------------------------------------- |
| `Config.Level.XpMultiplier`  | `1.0`   | levelling speed (2.0 ≈ half the time) |
| `Config.Level.Exams.Enabled` | `true`  | business exams at level 30 / 60 / 90  |

The unlock list with all 90 upgrades and their prices is in `config/levels.lua`, the exam tasks in `config/exams.lua`.

#### NPC customers

| Option               | Default | Meaning                                                                                                   |
| -------------------- | ------- | --------------------------------------------------------------------------------------------------------- |
| `Config.Npc.Enabled` | `true`  | NPC customers on or off                                                                                   |
| `Config.Npc.Visible` | `true`  | `false`: customers as bookings only, no vehicles – the business then runs completely without NPC vehicles |

NPC customers only come while someone is on duty (default). The server calculates money and XP; the visible vehicle is presentation only.

#### Billboard, measurement and quick setup (since 1.1.0)

| Field                                                               | Default                                           | Meaning                                                                                                                                                                    |
| ------------------------------------------------------------------- | ------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Config.Signs.Enabled`                                              | `true`                                            | image on the large billboard. `false` = the sign stays empty as in 1.0.0                                                                                                   |
| `Config.Signs.Image`                                                | `'pepper'`                                        | default for all car washes: a key from `Images`. `false` = empty until an admin picks an image per car wash                                                                |
| `Config.Signs.Images`                                               | `pepper = { file = 'html/img/sign-logo.png', … }` | list of images. Put your own images into `html/img/` and enter them here                                                                                                   |
| `Config.Signs.PerWash`                                              | `true`                                            | a different image from the list (or "no image") can be picked per car wash in the admin menu                                                                               |
| `Config.Signs.Backplate` · `Margin` · `DrawDistance` · `Brightness` | dark, opaque · `0.15` · `120.0` · `255`           | dark plate behind the image · margin in metres · view distance · brightness                                                                                                |
| `Config.Measure.Enabled`                                            | `true`                                            | self-measurement of the models. `false` = never measure, only the shipped dimensions apply                                                                                 |
| `Config.Measure.WaitAdminMinutes`                                   | `5`                                               | how long the server waits for an admin before it asks any player                                                                                                           |
| `Config.World.AutoRebuild`                                          | `'ask'`                                           | after an update with a changed blueprint: `'ask'` = report it, an admin resets all affected car washes with one button · `'auto'` = by itself on start · `'off'` = nothing |
| `Config.Guide.MaxStep`                                              | `0.6`                                             | quick setup: how many metres the ground under a slot may be uneven, otherwise it counts as "no room"                                                                       |
| `Config.Guide.AvoidRoads`                                           | `true`                                            | quick setup: never put anything beside the lane on a road                                                                                                                  |

**Your own logo on the billboard**

The large billboard (from level 70) is an empty frame in the game. The script draws an image into it, readable from both sides. The default is the Pepper Scripts logo.

1. Prepare the image: PNG (with transparency) or JPG, ideally square, 512 to 1024 pixels.
2. Put the file into the folder `pepper_carwash/html/img/`, e.g. `my-logo.png`.
3. Enter it in `config/config.lua` under `Config.Signs`:

```lua
Image = 'mylogo',
Images = {
    pepper = { file = 'html/img/sign-logo.png', label = 'Pepper Scripts' },
    mylogo = { file = 'html/img/my-logo.png', label = 'My server' },
},
```

4. Restart with `ensure pepper_carwash`.

**Switching it off:** `Config.Signs.Enabled = false` (no image anywhere) or `Image = false` (no default). For a single car wash: `/carwashadmin` → car wash → *General* → **Image on the billboard** → "no image (empty)".

Only files inside the resource work – no links. More hints (aspect ratio, brightness, mirrored image): `INSTALL.md` section 8.

**Self-measurement**

The script reads the dimensions of all models from the game once – in the background, as soon as an admin is online – and uses them to place every part centred and on the ground. Shipped models always use the shipped dimensions (`config/model-dims.lua`); a differing measurement is listed under `/carwashadmin` → **Diagnostics** and only applies once you click **Adopt measurement** there (only useful if you replaced a prop). Custom models are simply entered as a candidate in `config/parts.lua` – they are measured on the next start.

#### Fine tuning

Every field has a default – only touch it if something does not fit in game.

| Field                                               | Default                                      | When to touch it                                                                                                                                                                     |
| --------------------------------------------------- | -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `Config.LanceSpray.FromNozzle` / `.Nozzle`          | `true` / `{ x = 0.0, y = 0.16, z = 0.02 }`   | spray gun: the jet starts at the nozzle of the prop. If it starts beside the gun, adjust `Nozzle`                                                                                    |
| `Config.LanceSpray.Hand`                            | `bone = 28422`, offset and rotation          | position of the spray gun in the hand – if it sits crooked: `/cwdev` → *Align spray gun*                                                                                             |
| `Config.LanceSpray.TurnToCamera` / `.TurnSpeed`     | `true` / `420.0`                             | while spraying the character turns to where the camera looks, at that many degrees per second                                                                                        |
| `Config.LanceSpray.Pitch`                           | `{ Follow = true, Min = -35.0, Max = 25.0 }` | the jet follows the camera pitch within these limits (degrees)                                                                                                                       |
| `Config.Effects.Anchor`                             | `'prop_ld_test_01'`                          | invisible prop on the lane axis that a station's nozzles are attached to – change it if the prop is visible on your server                                                           |
| `Config.Effects.GantryTurn`                         | `0.85`                                       | gantry wash: rear turning point of the gantry on the lane (0 = start, 1 = end)                                                                                                       |
| `config/programs.lua` – effect candidate `rot`      | `{ x = 0.0, y = 0.0, z = 0.0 }`              | this one effect's own rotation – if an effect sprays the wrong way: `/cwdev` → *Adjust effect direction*                                                                             |
| `config/parts.lua` – `openTurn` / `openSeconds`     | gate `90.0` / `1.0`                          | the gate swings that many degrees around its post, within that many seconds. If it swings to the wrong side: `openTurn = -90.0`                                                      |
| `config/parts.lua` – `offset`, `hOffset`, `zOffset` | per model                                    | optional fine correction: sideways shift, rotation and height of a model. Since 1.1.0 the script calculates the position from the model dimensions – a stated value takes precedence |

Every part has a list of model candidates in `config/parts.lua`: the client uses the first model your game knows. If none loads, the station still works with effects, sound and light. `/carwashadmin` → **Diagnostics** shows which models were chosen.

#### Server-only (`config/server.lua`)

| Option                         | Default                        | Meaning                                                                                                                                      |
| ------------------------------ | ------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------- |
| `ServerConfig.Webhooks`        | all `''`                       | `admin`, `ownership`, `inactivity`, `milestones`, `washes`, `security` – see **Commands & Exports**                                          |
| `ServerConfig.WebhookName`     | `'Pepper Carwash'`             | sender name of the webhook messages                                                                                                          |
| `ServerConfig.AdminAce`        | `'pepper_carwash.admin'`       | ACE permission for admins                                                                                                                    |
| `ServerConfig.VersionCheck`    | `true`                         | update notice in the console (loads no code)                                                                                                 |
| `ServerConfig.PidSalt`         | `true`                         | public short ID of players in lists: `true` = random server secret, `'text'` = your own secret, `false` = without a secret (not recommended) |
| `ServerConfig.SavePlayerAbove` | `5000`                         | after bookings of this amount or more the player is saved in the framework · `-1` = never                                                    |
| `ServerConfig.LongCallSeconds` | `30`                           | time limit for admin calls that write a lot (create, rebuild, move, delete) – only raise it if the database is slow                          |
| `ServerConfig.Paging`          | `{ Washes = 10, Parts = 120 }` | large lists are sent to players in pages – lower it if the console warns about oversized events                                              |

### Gameplay

#### Creating a car wash

`/carwashadmin` → tab **New**. Each way first asks for name, purchase price and status; then the UI hides until you have placed or cancelled.

{% tabs %}
{% tab title="Guided setup" %}
**For any plot** – open ground, a backyard, a drive-through inside a building. Recommended.

Choose the kind (self-service bay, gantry wash, tunnel wash) and a build level → *Place in game*.

**Quick setup (default, since 1.1.0):** you only place the lane – for a tunnel wash the entrance (with driving direction), start and end of the wash lane and the exit, for a gantry wash the entrance and the start of the bay, for a self-service bay just its position. The script sets up everything else: stations, gate, terminal, walls, equipment, office, duty, storage, signs and further lanes – at ground level and only where there is room. Whatever does not fit moves to the other side of the lane or is left out. Before saving, a summary shows everything as a preview and lists what was placed and what was left out.

**Place everything myself:** an assistant at the top of the screen asks for every slot step by step: entrance, start and end of the wash lane, exit, waiting spots, gate and terminal, every station, office, duty, storage, sale sign, name sign, outdoor extras, further lanes.

Each step shows a preview at the suggested spot: **Enter** confirm · `H` aim yourself · `Q`/`E` or mouse wheel rotate (Shift = fine) · Page Up/Down height · `G` step back · `X` skip · **Backspace twice** = discard everything.

Nothing is built until you save at the end.
{% endtab %}

{% tab title="Blueprint" %}
**For open ground.**

Choose a blueprint (self-service bay, gantry wash, tunnel wash) and a build level, set under **Site** where further lanes grow (**automatic** = checked in game after placing: right, otherwise left, otherwise none · or fixed right / left / none) and which slots beside the first lane are never built here → *Place in game*.

The preview follows the crosshair: `Q`/`E` or mouse wheel to rotate (Shift 1°, Alt 45°), Page Up/Down to raise, **Enter** to place, **Backspace or ESC** to cancel. Blue frame = built right away, orange frame = full build-out.
{% endtab %}

{% tab title="Zones" %}
**For an existing building** – the car washes of the game or your MLO. No props are placed.

Walk or drive to the entrance, the start and the end of the wash line and the exit and press `E` at each – the direction you face is the driving direction. Mouse wheel = lane width, `Q` = waiting spot, `G` = self-service spot, `H` = sign, Backspace = one step back, Enter = done.
{% endtab %}

{% tab title="Build mode" %}
**Built from single parts.**

Place the origin first, then build mode opens: `TAB` catalog (49 parts), pick a part, place it; `F` pick up, `Del` remove, Backspace to leave. Set the lane afterwards in the details with *Redo zones*.
{% endtab %}
{% endtabs %}

| Status      | Meaning                                                      |
| ----------- | ------------------------------------------------------------ |
| *For sale*  | a sale sign appears at the car wash – a player buys it there |
| *State-run* | usable by everyone, not for sale, the money disappears       |
| *Locked*    | closed                                                       |

The car wash name is also the map blip name. Allowed: letters, digits, spaces and `- ' & . ! +`.

**Business points:** office (tablet), duty, storage and sale sign come with a blueprint. For zone and build-mode car washes they start out to the left of the entrance; use *Set points* in the details to put them – and vacuum spots – where they belong.

**Adjusting later:** the details of a blueprint or guided car wash have three sections. *Build level* builds every slot up to a level. *Site* defines what is never built at this car wash; *Reset parts* puts all parts back the way the blueprint has them. *Move slots* repositions a single slot in game.

{% hint style="warning" %}
The tab **Default car washes** can create five well-known locations. The coordinates are approximations – check every car wash on site and correct it with *Redo zones*.
{% endhint %}

#### A wash in five steps

{% stepper %}
{% step %}
**Drive up**

Stop at the entrance, press `E` and choose a program and extras. Each card shows price, duration, stations and the wax protection. Locked programs state the reason (level, missing station, empty stock).
{% endstep %}

{% step %}
**Pay**

With *Start wash* the money is taken at once. Stay in the vehicle – if you get out, the wash is cancelled.
{% endstep %}

{% step %}
**Wash**

In a tunnel wash the vehicle is guided through the stations, in a gantry wash the gantry moves over the standing vehicle. The display shows program, station and time left.
{% endstep %}

{% step %}
**Done**

The dirt is gone; a wax program keeps the vehicle clean for the time shown – in real time, even in the garage and after a server restart.
{% endstep %}

{% step %}
**Cancel**

Press `X` twice – no refund. If the car wash itself stops because of a fault, the customer gets money back: all of it if less than half had run, otherwise half.
{% endstep %}
{% endstepper %}

The server decides prices, duration, completion, wax and permissions and checks every call (place, state, time, rate limit).

| Program         | From business level | Base price | Wax protection |
| --------------- | ------------------- | ---------- | -------------- |
| Basic           | 1                   | $40        | –              |
| Foam            | 3                   | $70        | –              |
| Underbody       | 8                   | $90        | –              |
| Wax             | 15                  | $110       | 60 min         |
| Premium         | 25                  | $180       | 120 min        |
| Showroom finish | 75                  | $260       | 180 min        |

**Extras** are booked on top of the program: Wheel cleaning, Bug remover, Glass sealant, Hot wax (wax programs only), Nano sealant and Engine bay wash.

**Loyalty card:** if the business runs loyalty cards, every paid wash from $20 earns a stamp. When the card is full the customer redeems a free wash in the program selection – free up to the average price of the stamped washes.

#### Self-service bay and vacuum spot

**Self-service bay**

* Choose 1 to 5 minutes and pay ($15 per minute). The clock starts at once – you have to be on foot.
* You then hold the spray gun: holding the left mouse button sprays. Your character turns towards the camera and the jet goes where you aim.
* The vehicle only gets cleaner while the jet hits it – the jet reaches 6 metres. A completely filthy vehicle takes about 40 seconds.
* `X` hangs the spray gun back. Remaining time is not refunded. If you walk more than 14 metres away, your time ends.

**Vacuum spot**

* Park your vehicle at the spot, get out and press `E`.
* Vacuuming yourself costs $10 and takes 20 seconds.
* Interior cleaning ($60) and hand polish ($120) are done by an employee. You pay at once; if nobody takes the job in time, you get the money back automatically.

#### Buying and running a business

A player buys a car wash at its **sale sign** – one car wash per player (`Config.Ownership.Scope`: per character or per license). The owner can sell it back, transfer it to another player or rename it.

The **business tablet** opens with `/carwash` or `E` at the office point. Reading works from anywhere, changing things only on site.

| Page                 | Contents                                                                                          |
| -------------------- | ------------------------------------------------------------------------------------------------- |
| **Overview**         | state of the business, warnings (for example a tank below 20 %), countdown of the inactivity rule |
| **Tasks**            | open tasks with waypoint pin, your standing against the daily limit                               |
| **Level & upgrades** | XP bar, next unlocks, buy upgrades, foam colour                                                   |
| **Exam**             | progress of the business exam with a bar per exam task                                            |
| **Finances**         | business account, daily report, ledger                                                            |
| **Prices**           | every price between 50 % and 130 % of the base price                                              |
| **Storage**          | stock, order water, canisters and spare parts                                                     |
| **Stations**         | condition of every station, call the technician                                                   |
| **Staff**            | staff, ranks, shift pay per person                                                                |
| **Loyalty cards**    | loyalty cards of the business                                                                     |
| **Fleets**           | company cards and fleet contracts                                                                 |
| **Statistics**       | statistics of the last 30 days                                                                    |
| **Settings**         | wages (commission, pay per task) and settings of the business                                     |
| **Help**             | the player guide with the values of your server                                                   |

* **Business account:** every wash, self-service minute, vacuum use and service is booked to it; wages, supplies and the technician are paid from it.
* **Prices:** NPC customers react to them – the more expensive, the fewer come.
* **NPC customers** only come while someone is on duty. More people on duty bring more customers (up to +15 %).
* **Inactivity:** an owner who is not online for 30 days loses the car wash, and the business account is forfeited. Warnings come 7, 3 and 1 day before.

#### Staff

The owner hires players on site – no framework job needed. At the start a business has 2 staff slots, up to 12 with upgrades.

| Rank       | From business level | Adds                                                  |
| ---------- | ------------------- | ----------------------------------------------------- |
| Helper     | 1                   | duty and tasks                                        |
| Employee   | 1                   | pick up deliveries, refill                            |
| Shift lead | 10                  | order supplies, call the technician, place decoration |
| Manager    | 25                  | prices, hiring, upgrades, build mode, finances        |
| Deputy     | 60                  | manage staff, deposit and withdraw, ledger, settings  |

The rank names are defaults and can be renamed per car wash. Only the owner can sell, transfer or rename the car wash.

**Start your shift:** go to the duty point of your car wash and press `E` – `/carwashduty` works there too. Tasks only exist while you are on duty. If you leave the premises (60 m around the car wash) for more than 90 seconds, your shift ends by itself.

| What you earn | When                                                                   | Default                                     |
| ------------- | ---------------------------------------------------------------------- | ------------------------------------------- |
| Task pay      | per finished task, 80–120 % depending on performance                   | see the table below, $6,000 per day at most |
| Commission    | on every finished customer wash, split between everyone on duty        | 15 % (the owner sets 0–30 %)                |
| Shift pay     | every 15 minutes on duty – only if you got something done in that time | set by the owner per person, $150 at most   |
| Tips          | sometimes after hand work on a customer vehicle                        | $5–25, $1,500 per day at most               |

All wages are paid from the business account. If it runs short, the pay for that task is dropped. Only tips come straight from the customer.

#### Tasks

Open tasks are listed on the tablet under **Tasks** and float as a coloured marker above their spot. Walk there and press `E`. The first time, every task shows a briefing – the clock only starts after **Go**. `ESC` cancels a mini-game; the task then stays open.

| Task                | From level | Who      | Where                                   | Mini-game                           | Pay                       | XP |
| ------------------- | ---------- | -------- | --------------------------------------- | ----------------------------------- | ------------------------- | -- |
| Fix fault           | 1          | Helper   | control cabinet (red)                   | memorise the fuses and repeat them  | $50                       | 50 |
| Manual pre-wash     | 1          | Helper   | customer vehicle at the entrance (blue) | follow the circle, 5 zones          | $30                       | 30 |
| Hand drying         | 2          | Helper   | customer vehicle at the exit (blue)     | follow the circle, 4 strokes        | $25                       | 25 |
| Interior cleaning   | 10         | Helper   | vehicle at the vacuum spot (yellow)     | vacuum the spots, wipe the window   | $40 + 50 % of the service | 60 |
| Hand polish         | 55         | Helper   | vehicle at the vacuum spot (yellow)     | follow the circle, 4 panels         | $60 + 50 % of the service | 60 |
| Refill chemicals    | 1          | Employee | storage point (green)                   | release the valve in the green zone | $20                       | 25 |
| Service the brushes | 4          | Helper   | next to the station (green)             | keys, slider, timing                | $45                       | 45 |
| Pick up delivery    | 1          | Employee | wholesaler → storage point              | none (load, drive, unload)          | $80                       | 80 |

Pay and XP are the values at 100 %. In every task with a mini-game it counts how swiftly and cleanly you work: pay **and** XP range from **80 %** to **120 %**. "Pick up delivery" always pays the full value.

{% hint style="info" %}
All numbers on this page are **default values** from the config. The tablet page **Help** and the files `PLAYER-GUIDE.md` (English) and `SPIELER-ANLEITUNG.md` (German) in the resource explain every task in detail – copy them into your wiki or Discord and adapt them.
{% endhint %}

#### Stock, wear and faults

* **Tanks:** the water tank and the machine tanks (shampoo, wax) drain with every wash. If one is empty, the programs that need it are unavailable.
* **Water** always comes by tanker: at least 500 litres, waiting time 5 minutes.
* **Canisters and spare parts:** pick them up at the wholesaler yourself (a paid task) – or from level 7 have them delivered: 20 % more expensive, waiting time 10 minutes.
* **Automatic reordering** is an upgrade from level 36.

| Condition of the station | What happens                                                                                         |
| ------------------------ | ---------------------------------------------------------------------------------------------------- |
| 60 % or less             | the task "Service the brushes" appears (+40 points, one spare part)                                  |
| below 50 %               | a wash can stop with a fault – the lane is down until someone fixes the fault at the control cabinet |
| below 5 %                | the station is out of order – programs that need it can no longer be chosen                          |

The **technician** (Shift lead or higher, page **Stations**) costs $400 from the business account. The lane is down for 3 minutes, afterwards the station is like new and any fault is fixed.

#### Levels, upgrades and business exams

Every wash and every task earns the **business** XP – not the player. Some levels apply at once, others are upgrades bought from the business account; stations, spots and lanes then still have to be **built** on site.

At **level 30, 60 and 90** a full XP bar is not enough: the business must also pass a **business exam**. It starts by itself, and the whole team fills the same counters.

|                                | Business exam I (level 30)                    | Business exam II (level 60)              | Master exam (level 90)                                 |
| ------------------------------ | --------------------------------------------- | ---------------------------------------- | ------------------------------------------------------ |
| Counted customer washes        | 120                                           | 600                                      | 1,200                                                  |
| Better programs                | 30 × "Wax" or higher                          | 100 × "Premium" or higher                | 100 × "Showroom finish"                                |
| Hand work on customer vehicles | 40                                            | 80, of which 20 interior cleaning/polish | –                                                      |
| Storage                        | 12 × refill, 2 × pick up delivery             | –                                        | –                                                      |
| Fleet vehicles                 | –                                             | 80                                       | 280                                                    |
| Faults fixed by the team       | 2, each in under 6 min                        | 4, each in under 4 min                   | 6, each in under 3 min                                 |
| Business days                  | 3 days with 45 min of duty and 10 washes each | –                                        | 7 days in a row with 90 min of duty and 40 washes each |
| Satisfaction                   | –                                             | 90 % over the last 300 customers         | 95 % over the last 500 customers                       |

Only real customers count: no vehicles of your own team, the same number plate once per hour at most, the same player customer three times per day at most.

### Commands & Exports

#### Commands

| Command         | Who      | Function                                                                                                           |
| --------------- | -------- | ------------------------------------------------------------------------------------------------------------------ |
| `/carwash`      | everyone | owners and staff: tablet of their own car wash · everyone else: waypoint to the nearest open car wash              |
| `/carwashduty`  | staff    | start or end duty (only at the duty point of your own car wash)                                                    |
| `/carwashadmin` | admin    | create, change, move and remove car washes; build mode; zone editor; ownership and inactivity; log; diagnostics    |
| `/cwdev`        | admin    | test tool: inspect single parts, effects and sounds, print model dimensions, adjust effect direction and spray gun |

All names can be changed in `Config.Commands` (`Main`, `Duty`, `Admin`, `Dev`) – an empty string disables a command. There are no console commands.

{% hint style="warning" %}
Scripts such as `esx_carwash` or `qbx_carwash` also use `/carwash`. Stop the other script or rename the command, for example `Config.Commands.Main = 'washpark'`.
{% endhint %}

The tools in `/cwdev` are local and change nothing at any car wash: *Inspect a part*, *Test an effect*, *Test a sound*, *Diagnostics*, *Print model dimensions*, *Adjust effect direction* and *Align spray gun*. The last two note their values with **Enter** in the F8 console and in `fx-values.txt` in the resource folder.

#### Keys

| Key                    | Function                                                                           |
| ---------------------- | ---------------------------------------------------------------------------------- |
| `E`                    | interact: choose a program, self-service bay, points of the business, start a task |
| `X`                    | cancel a wash (press twice), cancel a progress bar, hang the spray gun back        |
| Left mouse button      | spray (self-service bay), hold in the mini-games                                   |
| `W` `A` `S` `D`, space | mini-games "Service the brushes" and "Refill chemicals"                            |
| `ESC`                  | cancel a mini-game – the task stays open                                           |

"Interact" and "Cancel wash" are FiveM key bindings: every player can rebind them in the GTA settings under **Key Bindings → FiveM**, and the prompts show the player's key. `Config.Interact.DefaultKey` and `Config.Wash.AbortDefaultKey` are only the default for players who never loaded the resource before.

#### Permissions (ACE)

```cfg
add_ace group.admin pepper_carwash.admin allow                        # /carwashadmin and /cwdev
add_ace identifier.license:YOUR_LICENSE pepper_carwash.admin allow    # or a single player
```

Alternatively via a group from `Config.AdminGroups` (default `admin`, `superadmin`, `god`). The name of the ACE permission is in `config/server.lua` (`ServerConfig.AdminAce`). Every permission is checked on the server for every single call.

Inside a business the owner assigns 5 ranks with rights – see **Gameplay**.

#### Exports (server)

| Export                                                    | Returns / does                                                                                                                         |
| --------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| `exports.pepper_carwash:getWashes()`                      | all car washes in their public form                                                                                                    |
| `exports.pepper_carwash:getWash(id)`                      | one car wash or `nil`                                                                                                                  |
| `exports.pepper_carwash:getWashOf(src)`                   | car wash the player owns or works at: `{ id, label, owner, grade }` or `nil`                                                           |
| `exports.pepper_carwash:isOnDuty(src)`                    | `true` while the player is on duty at their car wash                                                                                   |
| `exports.pepper_carwash:addBalance(washId, amount, info)` | changes the business account of an owned car wash (plus or minus, e.g. invoices or taxes, never below 0) – returns `true` / `false`    |
| `exports.pepper_carwash:addXp(washId, amount, reason)`    | credits business XP (with `Config.Level.XpMultiplier`) – returns the XP credited. Such XP never count for the tasks of a business exam |
| `exports.pepper_carwash:hasWax(plate)`                    | expiry time of the wax protection (Unix seconds) or `false`                                                                            |
| `exports.pepper_carwash:setWax(plate, minutes)`           | sets wax protection for a number plate – returns the expiry time or `nil`                                                              |
| `exports.pepper_carwash:removeWax(plate)`                 | removes the wax protection – returns `true` / `false`                                                                                  |

#### Exports (client)

| Export                                 | Returns / does                                    |
| -------------------------------------- | ------------------------------------------------- |
| `exports.pepper_carwash:isWashing()`   | `true` while a wash is running for the player     |
| `exports.pepper_carwash:nearestWash()` | ID of the nearest car wash and the distance to it |
| `exports.pepper_carwash:openTablet()`  | opens the tablet of the player's own car wash     |

Example – give a vehicle two hours of wax protection from another script:

```lua
exports.pepper_carwash:setWax(plate, 120)
```

#### Server events

Listen with `AddEventHandler` – **not** `RegisterNetEvent`:

| Event                         | Arguments                            | When                                                                           |
| ----------------------------- | ------------------------------------ | ------------------------------------------------------------------------------ |
| `pepper_carwash:washed`       | `src, washId, program, plate, price` | a wash was finished (NPC customer: `src = nil`)                                |
| `pepper_carwash:renamed`      | `washId, label`                      | a car wash was renamed                                                         |
| `pepper_carwash:ownerChanged` | `washId, reason`                     | `reason` is `bought`, `sold`, `transferred`, `inactive`, `admin` or `restored` |
| `pepper_carwash:levelUp`      | `washId, level`                      | once per level reached                                                         |
| `pepper_carwash:examPassed`   | `washId, stage`                      | business exam passed (`stage` = 30, 60 or 90)                                  |

#### Webhooks

In `config/server.lua` (`''` = off):

```lua
ServerConfig.Webhooks = {
    admin = '',      -- car washes created, changed, moved, removed; changes to ownership and business account
    ownership = '',  -- purchase, sale, transfer, renaming by the owner
    inactivity = '', -- warnings and releases because of inactivity
    milestones = '', -- level 10, 20, … 100 and passed business exams
    washes = '',     -- finished washes (optional, can be a lot)
    security = '',   -- suspicious cases from the plausibility check
}
ServerConfig.WebhookName = 'Pepper Carwash'
```

Never share webhook URLs publicly.

#### Bridges (open)

| File                                              | Purpose                                                                                                                          |
| ------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `bridge/detect.lua`                               | framework detection                                                                                                              |
| `bridge/server/esx.lua`, `qbcore.lua`, `qbox.lua` | money, name and groups per framework                                                                                             |
| `bridge/server/standalone.lua`                    | standalone mode without a framework (identity = license, money = ox\_inventory item `money`) – only when no framework is running |
| `bridge/server/inventory.lua`                     | inventories for the optional items: ox\_inventory, qb-inventory, ps-inventory, qs-inventory, ESX                                 |
| `bridge/client/target.lua`                        | ox\_target / qb-target for the self-service bay                                                                                  |
| `bridge/client/frameworks.lua`                    | framework notification on the client (`Config.Notify.Mode = 'framework'`)                                                        |
| `bridge/client/dirt.lua`                          | your own dirt system (`Config.Dirt.Mode = 'custom'`)                                                                             |

### FAQ

#### Troubleshooting

| Problem                                                                                  | Solution                                                                                                                                                                                                                                                                |
| ---------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Resource does not start, the console names a missing dependency                          | `oxmysql` must start before `pepper_carwash`, OneSync must be on, server build 7290 or newer.                                                                                                                                                                           |
| Red box "standalone mode" in the console                                                 | No framework detected – start `es_extended`, `qb-core` or `qbx_core` **before** `pepper_carwash` or set `Config.Framework` explicitly.                                                                                                                                  |
| No green line `Pepper Carwash 1.1.0 started (…)`                                         | Search the console for red lines containing `pepper_carwash`.                                                                                                                                                                                                           |
| "Pepper Carwash is still starting" does not go away                                      | The server start did not finish – database not reachable (check `mysql_connection_string`) or the user may not create tables: import `install/pepper_carwash.sql`.                                                                                                      |
| Right after a restart: "Pepper Carwash is not ready yet."                                | The UI is still loading – wait a few seconds and try again. If it stays, check F8 for errors containing `pepper_carwash`.                                                                                                                                               |
| `/carwashadmin`: "You do not have permission to do that"                                 | Add `add_ace group.admin pepper_carwash.admin allow` to your `server.cfg` and restart the server.                                                                                                                                                                       |
| `/carwash` does something unexpected                                                     | A second script uses the command – stop it or change `Config.Commands.Main`.                                                                                                                                                                                            |
| No help text at a point, no progress bar                                                 | The UI of the resource did not load – check F8 for errors containing `pepper_carwash`.                                                                                                                                                                                  |
| A part looks wrong, faces the wrong way, floats or sinks                                 | First `/carwashadmin` → **Diagnostics** → model measurement: does it say "measured"? If not, press **Measure again**. Then swap the model or `zOffset` in `config/parts.lua`, or rotate the part in build mode. `/cwdev` → *Inspect a part* shows model and dimensions. |
| The gate swings to the wrong side                                                        | Set `openTurn = -90.0` for `entry_gate` in `config/parts.lua`.                                                                                                                                                                                                          |
| An effect is not visible                                                                 | `/cwdev` → *Test an effect*; change the order of the candidates in `config/programs.lua`.                                                                                                                                                                               |
| An effect sprays in the wrong direction                                                  | `/cwdev` → *Adjust effect direction*, then enter the noted values at the candidate in `config/programs.lua` as `rot = { x, y, z }`.                                                                                                                                     |
| The spray gun sits crooked in the hand                                                   | `/cwdev` → *Align spray gun*, then enter the noted values at `Config.LanceSpray.Hand` or `.Nozzle`.                                                                                                                                                                     |
| No sound                                                                                 | `Config.Effects.Sounds = 'nui'`                                                                                                                                                                                                                                         |
| The vehicle drives through the tunnel unevenly                                           | Set `Config.Wash.Guide` to `'speed'` or `'conveyor'`.                                                                                                                                                                                                                   |
| A vehicle is rejected as "too large"                                                     | Adjust `Config.Wash.MaxVehicle` (with `Config.Debug = true` the measurement is printed to F8).                                                                                                                                                                          |
| NPC vehicles get stuck                                                                   | `Config.Npc.Visible = false` – the business then runs completely without vehicles.                                                                                                                                                                                      |
| Office, duty or storage point is inside a wall                                           | `/carwashadmin` → car wash → *Set points*.                                                                                                                                                                                                                              |
| An admin call reports "The server is not responding", but the change is there afterwards | The database is slow – raise `ServerConfig.LongCallSeconds` in `config/server.lua`.                                                                                                                                                                                     |
| The console warns about oversized network events                                         | Lower `ServerConfig.Paging` in `config/server.lua`.                                                                                                                                                                                                                     |
| Console: `Items: …` without items                                                        | Not an error: no supported inventory is running or the items are not set up – the business runs with counters in storage.                                                                                                                                               |
| Staff got no pay for a task                                                              | The message names the reason: daily limit reached or business account too low.                                                                                                                                                                                          |
| A program cannot be chosen                                                               | The card states the reason: business level, a missing or worn-out station or an empty tank.                                                                                                                                                                             |

{% hint style="info" %}
`/carwashadmin` → tab **Diagnostics** shows version, framework and which model was chosen per part. For more output set `Config.Debug = true` and switch it off again afterwards.
{% endhint %}

#### Questions

<details>

<summary>Do I need an MLO or addon models?</summary>

No. Every part is a prop that ships with the game. You can swap any model in `config/parts.lua`, for example for props of a map pack running on your server.

</details>

<details>

<summary>Does it need ox_lib, a target script or an inventory?</summary>

No. The only dependency is oxmysql. ox\_target / qb-target and an inventory are optional and detected automatically.

</details>

<details>

<summary>Which frameworks and inventories are supported?</summary>

ESX Legacy, QBCore and Qbox. The optional items work with ox\_inventory, qb-inventory, ps-inventory, qs-inventory and the ESX inventory. Tested in game on ESX Legacy with ox\_inventory.

</details>

<details>

<summary>Does it work with the car washes of the game or with my MLO?</summary>

Yes – use *Zones*: you mark entrance, wash line and exit, and no props are placed.

</details>

<details>

<summary>Is it a framework job?</summary>

No. The owner hires players at the car wash; ranks, duty and wages are part of the script.

</details>

<details>

<summary>Is there passive income?</summary>

Not by default: NPC customers only come while someone is on duty.

</details>

<details>

<summary>Can I adapt the money to my server economy?</summary>

Yes. `Config.Economy.IncomeMultiplier` scales all money from NPC customers, `Config.Economy.UpgradeMultiplier` all upgrade and decoration prices. Program prices are in `config/programs.lua`, wages in `config/staff.lua`.

</details>

<details>

<summary>How do I change how fast a business levels?</summary>

With `Config.Level.XpMultiplier`: `2.0` is about half the time. `Config.Level.Exams.Enabled = false` turns the business exams at level 30, 60 and 90 off.

</details>

<details>

<summary>Can a player own several car washes?</summary>

No, one per player. `Config.Ownership.Scope` decides whether that is per character (`'character'`) or per license (`'license'`).

</details>

<details>

<summary>What happens to car washes of inactive owners?</summary>

An owner who was offline for 30 days loses the car wash, and the business account is forfeited. There are warnings 7, 3 and 1 day before, admins can protect a car wash and restore it afterwards. Turn the rule off with `Config.Inactivity.Enabled = false`.

</details>

<details>

<summary>Can I run car washes without owners?</summary>

Yes. Set the status to *State-run*: the car wash is usable by everyone and not for sale.

</details>

<details>

<summary>What happens on a server restart?</summary>

Running washes end and are refunded according to the rule of the car wash. Car washes, business account, stock, levels and wax protection are stored in the database.

</details>

<details>

<summary>Can I put my own logo on the billboard – or switch it off?</summary>

Yes, since 1.1.0. The default is the Pepper Scripts logo. Put your own image into `html/img/` and enter it in `Config.Signs`; `Config.Signs.Enabled = false` switches the image off. Step by step: **Configuration**.

</details>

<details>

<summary>After the update /carwashadmin says "Blueprint was updated" – what now?</summary>

An update changed a blueprint and the parts of your blueprint car washes still stand in the old place. Press **"Reset all affected car washes"** once. The script rebuilds nothing by itself. Blueprint parts you moved in build mode go back to their place; parts you added stay.

</details>

<details>

<summary>How do I switch to German?</summary>

`Config.Locale = 'de'` in `config/config.lua` (that is the default). The language applies to all players.

</details>

#### Support

Open a ticket on our [Discord](https://discord.gg/6NaFJWKDYu) and link your purchase with `/verify` first. More: **Support**.

### Changelog

#### 1.1.0 – 2026-10-11

{% hint style="info" %}
**Updating from 1.0.0:** swap the folder, start the server – no database change, your `config.lua` keeps working. Then press **"Reset all affected car washes"** once in `/carwashadmin`. All steps are listed under **Installation → Updating**.
{% endhint %}

**New**

* Quick setup as the default of the guided setup: place only the lane – stations, gate, terminal, walls, equipment, signs and further lanes are set up by the script, only where there is room; summary before building
* Self-measurement: the script reads the dimensions of all models from the game once and places every part centred and on the ground – custom props too (`Config.Measure`)
* Image on the large billboard, readable from both sides – default is the Pepper Scripts logo, your own image or off via `Config.Signs`
* Button "Reset all affected car washes" after blueprint changes (`Config.World.AutoRebuild`)
* Blueprint: "Further lanes: automatic"
* Vacuum spot: the preview shows the vehicle's parking spot as an outline
* Diagnostics: adopt or drop differing measurements one by one

**Changed**

* The parking spot at the vacuum is on the operating side of the post; the entrance sign in the blueprints is turned
* `config/parts.lua`: `zOffset` / `offset` only as a fine correction – a stated value takes precedence over the calculation
* More restrained defaults for fallback effects in `config/programs.lua`

**Fixed**

* Dryer fan and plant pot floated 26 and 14 cm above the ground
* The entrance sign of the blueprints stood the wrong way round
* The parking spot at the vacuum could lie behind the post or inside a building

#### 1.0.0 – 2026-10-11

**Initial release**

* Create car washes in game with `/carwashadmin`: guided setup, blueprint, build mode with 49 parts or zones inside existing buildings
* 3 types (self-service bay, gantry wash, tunnel wash) built from stock GTA props – no MLO, no addon models
* 6 wash programs and 6 extras with particles, sound and a progress display; wax protection that survives the garage and a restart
* Self-service bay with spray gun, vacuum spot with interior cleaning and hand polish as services
* Ownable businesses (one car wash per player at most), sale and transfer, state-run car washes without an owner
* Tablet with business account, daily report, own prices, storage, stations, staff, statistics and help
* Stock and wear: water, shampoo, wax and spare parts, faults, technician
* Staff with 5 ranks, duty, commission, task pay and shift pay; 8 tasks, 7 of them as mini-games
* Business levels 1–100 with 90 upgrades, a build mode for owners and business exams at level 30, 60 and 90
* NPC customers, loyalty cards, company cards and fleet contracts
* Inactivity rule (30 days by default) with warnings, admin protection and restore
* Admin tools with log and diagnostics, 6 Discord webhooks, server and client exports
* Built-in UI for prompts, progress bar, notifications, dialogs and menus – the only dependency is oxmysql
* Optional items for ox\_inventory, qb-inventory, ps-inventory, qs-inventory and the ESX inventory with 5 item images
* ESX Legacy, QBCore and Qbox · German and English, player guide in both languages (`PLAYER-GUIDE.md`, `SPIELER-ANLEITUNG.md`)
