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

# Pepper Bus

<figure><img src="https://content.gitbook.com/content/2wrlmY2LsiAJf6u7YGfs/blobs/jodrxOeml8VQ7feXExkm/.gitbook/assets/bus-cover.png" alt="Pepper Bus"><figcaption></figcaption></figure>

Not just "drive from A to B": with **Pepper Bus** your players drive real lines. NPC passengers wait at the stops, get on and off, the schedule keeps running and punctual, smooth driving pays off. Admins build new lines right in-game with the route editor.

{% 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="success" %}
**Get Pepper Bus:** [pepper-scripts.tebex.store](https://pepper-scripts.tebex.store/)
{% endhint %}

### Features

* Real line service with stops, doors, boarding, alighting and minimum dwell time
* **Schedule with punctuality** – leave too early and passengers are left behind
* **In-game route editor** – place stops at your position, reorder, test run, reverse direction
* **14 ready-made lines** and **10 line types**, e.g. city, school bus, airport, night, sightseeing, intercity, event charter
* **9 passenger types** with their own fares and comfort needs, real NPCs on board
* Career with **50 levels**, **6 buses** from shuttle to festival bus, reputation and 1–5 star rating
* Control center with line offers and a bonus for lines nobody drove for a while
* Daily and weekly challenges, bonus for active duty time
* **Bus company** – public or player-run – with employees, ranks, salaries and a company account
* **Admin panel** with offline editing and audit log
* Server-side payouts, protection against double payouts and teleports
* German & English, config and locales open

### At a glance

|                  |                                                                                                               |
| ---------------- | ------------------------------------------------------------------------------------------------------------- |
| **Version**      | 1.0.0                                                                                                         |
| **Framework**    | ESX Legacy 1.9+                                                                                               |
| **OneSync**      | required                                                                                                      |
| **Dependencies** | [es\_extended](https://github.com/esx-framework/esx_core), [oxmysql](https://github.com/overextended/oxmysql) |
| **Not required** | ox\_lib, ox\_target, ox\_inventory                                                                            |
| **Performance**  | approx. 0.02 ms idle / 0.12 ms on duty (guide value)                                                          |
| **Distribution** | Cfx.re Asset Escrow (`config/`, `locales/`, `sql/` open)                                                      |

{% hint style="info" %}
**Open-source variant:** Pepper Bus is also available as **Pepper Bus (Open Source)** with the full, unencrypted source code – see the [shop](https://pepper-scripts.tebex.store/).
{% endhint %}

### Installation

#### Requirements

| Requirement        | Version                                            |
| ------------------ | -------------------------------------------------- |
| FiveM server build | 7290+ with **OneSync**                             |
| Framework          | ESX Legacy 1.9+ (`es_extended`)                    |
| Database           | [oxmysql](https://github.com/overextended/oxmysql) |

ox\_lib, ox\_target and ox\_inventory are **not** required.

#### Steps

{% stepper %}
{% step %}
**Download**

Download `pepper_bus` from the [Cfx.re Portal → Granted Assets](https://portal.cfx.re/assets/granted-assets).
{% endstep %}

{% step %}
**Copy**

Extract it to `resources/[pepper]/pepper_bus`.
{% endstep %}

{% step %}
**Database**

Keep `Config.Database.AutoInstall = true` (default) – missing tables are created on first start. Alternatively, import `sql/install.sql` manually. On first start the **14 default lines** are created (`Config.Database.SeedDefaultRoutes`).
{% endstep %}

{% step %}
**server.cfg**

Add the resource after its dependencies:

```cfg
ensure oxmysql
ensure es_extended
ensure pepper_bus
```

{% endstep %}

{% step %}
**Admin permissions**

Grant admin access (see below).
{% endstep %}

{% step %}
**Check the default lines**

Drive the default lines once and correct stops in the **route editor** if needed.
{% endstep %}

{% step %}
**Start**

Drive to the bus depot (bus icon on the map) and press `E`.
{% endstep %}
{% endstepper %}

#### Admin permissions

ESX group in `Config.Admin.Groups` (default: `superadmin`, `admin`) **or** ACE permission:

```cfg
add_ace group.admin pepper_bus.admin allow
```

#### Database

`sql/install.sql` can be imported safely several times. It contains tables for the career, statistics, challenges, unlocks, **lines and stops**, company, admin logs and route history.

{% hint style="info" %}
Lines are stored in the database – updates of the resource never overwrite your lines. Career data is stored per ESX character (multicharacter compatible).
{% endhint %}

### Configuration

All settings are open in `config/`. Restart the resource after changes.

#### Files

| File                    | Content                                                                                                                                     |
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| `config/config.lua`     | Language, depot, control center, stops, schedule, AFK, security, passengers, payouts, damage, rating, reputation, company, admin, sounds/UI |
| `config/vehicles.lua`   | Vehicle classes and buses (capacity, requirements)                                                                                          |
| `config/levels.lua`     | XP curve, titles, career bonus, level rewards                                                                                               |
| `config/passengers.lua` | Passenger types                                                                                                                             |
| `config/routetypes.lua` | Line types (requirements, allowed buses, passenger mix, payout, times)                                                                      |
| `config/routes.lua`     | Default stops and lines (only for the first start / import)                                                                                 |
| `config/challenges.lua` | Daily and weekly challenge pools                                                                                                            |
| `config/server.lua`     | Server-only: optional Discord webhook                                                                                                       |

#### General

| Option                              | Default  | Description                                              |
| ----------------------------------- | -------- | -------------------------------------------------------- |
| `Config.Locale`                     | `'de'`   | Language: `'de'` or `'en'`                               |
| `Config.Debug`                      | `false`  | Detailed console logs                                    |
| `Config.Currency`                   | `'$'`    | Currency symbol                                          |
| `Config.TimeSource`                 | `'game'` | Time of day for lines/passengers: `'game'` or `'server'` |
| `Config.Database.AutoInstall`       | `true`   | Create missing tables on start                           |
| `Config.Database.SeedDefaultRoutes` | `true`   | Create the default lines if no lines exist yet           |

#### Depot (`Config.Center`)

| Option             | Default                | Description                                       |
| ------------------ | ---------------------- | ------------------------------------------------- |
| `Label`            | `'Los Santos Transit'` | Name of the depot                                 |
| `Terminal`         | depot                  | Interaction point (press `E`)                     |
| `SpawnPoints`      | 4 spots                | Bus spawn points, checked for free space in order |
| `MaxStartDistance` | `70.0`                 | Shifts can only start this close to the depot     |

#### Tablet & control center

| Option                                            | Default       | Description                                                                                                   |
| ------------------------------------------------- | ------------- | ------------------------------------------------------------------------------------------------------------- |
| `Config.Tablet.DefaultKey`                        | `'F7'`        | Key for the tablet (players can rebind it)                                                                    |
| `Config.Tablet.AcceptKey` / `DeclineKey`          | `'Y'` / `'N'` | Accept or decline control center offers                                                                       |
| `Config.Dispatch.Enabled`                         | `false`       | `false`: drivers choose lines themselves in the tablet · `true`: the control center additionally offers lines |
| `Config.Dispatch.MinOfferDelay` / `MaxOfferDelay` | `45` / `240`  | Seconds between offers                                                                                        |
| `Config.Dispatch.OfferTimeout`                    | `30`          | Seconds to accept an offer                                                                                    |
| `Config.Dispatch.DemandBonusMax`                  | `0.25`        | Up to +25 % for lines nobody drove for a while                                                                |

#### Stops & schedule

| Option                            | Default | Description                                      |
| --------------------------------- | ------- | ------------------------------------------------ |
| `Config.Stops.Radius`             | `14.0`  | Default stop radius (changeable per stop)        |
| `Config.Stops.BaseDwell`          | `4`     | Minimum dwell time per stop (seconds) …          |
| `Config.Stops.DwellPerPassenger`  | `1.2`   | … plus seconds per boarding/alighting passenger  |
| `Config.Stops.MaxDwell`           | `25`    | Maximum dwell time                               |
| `Config.Stops.MinStopDistance`    | `40.0`  | Route editor: minimum distance between two stops |
| `Config.Schedule.OnTimeTolerance` | `45`    | ± seconds that still count as punctual           |
| `Config.Schedule.EarlyLimit`      | `60`    | More than 60 s early = departed too early        |

#### Passengers (`Config.Passengers`)

| Option            | Default    | Description                                         |
| ----------------- | ---------- | --------------------------------------------------- |
| `RushHours`       | 7–9, 16–19 | More passengers wait during these hours             |
| `RushFactor`      | `1.6`      | Passenger factor in rush hour                       |
| `NightFactor`     | `0.5`      | Fewer passengers 0–5 h (except night lines)         |
| `MaxBoardPerStop` | `8`        | Maximum boarding passengers per stop                |
| `MaxVisible`      | `12`       | Visible NPCs in the bus (the rest are counted only) |

#### Payouts (`Config.Economy`)

| Option               | Default  | Description                                  |
| -------------------- | -------- | -------------------------------------------- |
| `PayAccount`         | `'bank'` | `'bank'` or `'money'`                        |
| `GlobalMultiplier`   | `1.0`    | Multiplies all payouts                       |
| `FarePerStop`        | `9`      | Per passenger and stop driven …              |
| `FareBase`           | `6`      | … plus base fare per passenger               |
| `StopBonus`          | `12`     | Per correctly served stop                    |
| `PunctualBonus`      | `10`     | Extra per punctual stop                      |
| `AbortPayout`        | `0.4`    | On abort: 40 % of the fares collected so far |
| `MinPayout`          | `50`     | Minimum payout for a completed line          |
| `MaxRepairDeduction` | `0.8`    | Repair deduction max. 80 %                   |

#### Rating, reputation & duty bonus

| Option                                | Default | Description                                      |
| ------------------------------------- | ------- | ------------------------------------------------ |
| `Config.Rating.SpeedLimit`            | `25.0`  | m/s (\~90 km/h) × line type tolerance            |
| `Config.Rating.EarlyDeparturePenalty` | `0.4`   | Star deduction per stop left too early           |
| `Config.Reputation.Tiers`             | 6 tiers | Bronze to Legend, each with a pay bonus (0–15 %) |
| `Config.DutyBonus.DutyBonusXP`        | `150`   | XP per hour of active duty                       |

#### Vehicles, charter & company

| Option                                | Default  | Description                                  |
| ------------------------------------- | -------- | -------------------------------------------- |
| `Config.VehicleRules.PlatePrefix`     | `'LST'`  | License plate prefix                         |
| `Config.VehicleRules.DeleteOnDutyEnd` | `true`   | Remove the bus when the shift ends           |
| `Config.PlayerCharter.Enabled`        | `true`   | Special rides for players (no script payout) |
| `Config.Company.AllowPurchase`        | `true`   | Players can take over the company            |
| `Config.Company.PurchasePrice`        | `900000` | Purchase price                               |
| `Config.Company.VehicleSpawnCost`     | `250`    | Operating cost per bus taken out             |
| `Config.Company.SalaryInterval`       | `1800`   | Seconds of active duty per salary payment    |
| `Config.Company.DefaultRanks`         | 5 ranks  | Salary, share and permissions per rank       |

New buses are added in `config/vehicles.lua` with a unique `key`, spawn `model`, class, `capacity` and requirements. The class decides which line types the bus may drive.

#### Admin & route editor

| Option                          | Default               | Description                                |
| ------------------------------- | --------------------- | ------------------------------------------ |
| `Config.Admin.Groups`           | `superadmin`, `admin` | ESX groups with admin access               |
| `Config.Admin.Ace`              | `'pepper_bus.admin'`  | ACE permission as an alternative           |
| `Config.Admin.RequireReason`    | `true`                | Reason required for player/company changes |
| `Config.Admin.AllowTeleport`    | `true`                | Admins may teleport to stops in the editor |
| `Config.Admin.EditorCommand`    | `'busstop'`           | Command to add your position as a stop     |
| `Config.Admin.MaxRoutes`        | `100`                 | Maximum number of lines                    |
| `Config.Admin.MaxStopsPerRoute` | `40`                  | Maximum stops per line                     |

{% hint style="warning" %}
Don't rename vehicle `key`s or challenge `id`s after going live – they are stored in the database.
{% endhint %}

### Gameplay & Route Editor

#### Starting a shift

1. Drive to the **bus depot** (bus icon on the map) and press `E` at the terminal.
2. Choose an unlocked bus – it spawns on a free parking spot.
3. No ESX job is needed – every player can drive.

#### Choosing a line

* Open the tablet (`F7`) and pick a line yourself. Locked lines show the reason (level, reputation, time, wrong bus).
* If the server enables the control center (`Config.Dispatch.Enabled`), you also receive line offers – accept with `Y`, decline with `N`. Lines that nobody drove for a while pay a bonus.

#### Driving a line

{% stepper %}
{% step %}
**Stop at the stop**

Stop within the stop radius (below approx. 5 km/h). The doors open automatically.
{% endstep %}

{% step %}
**Boarding & alighting**

Passengers get off and on. The HUD shows the dwell time ("doors open") – leave too early and passengers are left behind.
{% endstep %}

{% step %}
**Keep the schedule**

Scheduled times start with the first departure. Punctuality is shown live in the HUD and every punctual stop pays a bonus.
{% endstep %}

{% step %}
**Final stop**

At the last stop you get your result: stars, payout, XP and reputation.
{% endstep %}
{% endstepper %}

#### Line types & passengers

**10 line types:** shuttle, city line, school bus, airport, night line, sightseeing, express, intercity, event shuttle and party charter.

**9 passenger types** (e.g. commuters, students, seniors, tourists, travellers, party guests) with their own fare, pace and comfort needs.

#### Buses

| Bus             | Class       | Seats |
| --------------- | ----------- | ----- |
| Shuttle bus     | Shuttle     | 9     |
| City bus        | City bus    | 16    |
| Airport bus     | Airport bus | 16    |
| Sightseeing bus | Sightseeing | 10    |
| Coach           | Coach       | 16    |
| Festival bus    | Event bus   | 12    |

#### Rating & career

* **Stars (1–5)** from punctuality, smooth driving, speed, collisions and damage – with reasons
* **50 levels** with titles and level rewards, **reputation** Bronze → Legend
* **Challenges** daily and weekly (lines, passengers, stops, punctuality, km, earnings)
* **Charter rides** for players: no line offers and no script payout during the ride

#### Bus company

| Mode                 | Description                                                                                                                             |
| -------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| **Public** (default) | Nobody owns the company – everybody drives and gets the full payout.                                                                    |
| **Player company**   | Only the owner and employees drive. Payouts go to the company, drivers receive their share, salaries are paid from the company account. |

#### Route editor (admins)

Tablet (`F7`) → **Admin → Line editor**.

{% stepper %}
{% step %}
**New line**

Enter number, name, line type and optionally a minimum level.
{% endstep %}

{% step %}
**Add stops**

Drive the route with a bus and press **"Stop at my position"** at every stop – or type `/busstop` without opening the tablet (the open draft is kept).
{% endstep %}

{% step %}
**Fine-tune**

Rename stops (the street name is suggested), reorder them, re-capture the position, insert stops, and set radius, passenger volume (0.2–3.0) and extra dwell time.
{% endstep %}

{% step %}
**Preview & save**

**Preview on map** shows all stops numbered for 5 minutes. **Save** makes the line available to all drivers immediately (if active). **Test run** drives the line without requirements and without rewards. **Copy** / **Reverse direction** create an inactive copy.
{% endstep %}
{% endstepper %}

{% hint style="info" %}
A line needs at least 2 stops and at most `Config.Admin.MaxStopsPerRoute`. Running rides use a copy of the line – changes apply from the next ride. **"Default lines"** re-creates missing lines from `config/routes.lua` without changing existing ones.
{% endhint %}

#### Admin panel

Tablet → **Admin**: search players (also offline), edit XP, level, reputation, statistics, challenges and unlocks, manage the company – every change is recorded in the audit log.

### Commands & Exports

#### Commands & keys

| Command       | Key  | Function                                                                     |
| ------------- | ---- | ---------------------------------------------------------------------------- |
| `/bustablet`  | `F7` | Open the tablet (anywhere while on duty or as admin, otherwise at the depot) |
| `/busaccept`  | `Y`  | Accept a control center offer                                                |
| `/busdecline` | `N`  | Decline a control center offer                                               |
| `/busstop`    | –    | Admin: add your current position as a stop to the open editor draft          |

{% hint style="info" %}
Players can change the keys in the GTA settings → Key Bindings → FiveM.
{% endhint %}

#### Exports (server)

| Export                                     | Returns / description                                                    |
| ------------------------------------------ | ------------------------------------------------------------------------ |
| `GetBusPlayerData(source)`                 | Career and statistics                                                    |
| `IsBusDriverOnDuty(source)`                | `boolean`                                                                |
| `GetBusDriverStatus(source)`               | Status, e.g. `'OFF_DUTY'`, `'AVAILABLE'`, `'AT_STOP'`, `'ON_ROUTE'`      |
| `GetBusDriverLine(source)`                 | Current line (number, label, stage, stops, passengers on board) or `nil` |
| `SetPlayerCharterActive(source, active)`   | Turn a charter ride on/off – returns `ok, reason`                        |
| `GetOnDutyDrivers()`                       | List of drivers on duty with their line                                  |
| `GetBusRoutes()`                           | All lines incl. stops (e.g. for a timetable app)                         |
| `GetBusCompany()`                          | Company info (label, mode, balance, employees, owner)                    |
| `IsBusCompanyEmployee(sourceOrIdentifier)` | Employee check                                                           |

Example:

```lua
local line = exports.pepper_bus:GetBusDriverLine(source)
```

{% hint style="info" %}
There is deliberately **no** export that lets other resources create money, XP or reputation.
{% endhint %}

### FAQ

| Problem                  | Solution                                                                                                  |
| ------------------------ | --------------------------------------------------------------------------------------------------------- |
| Tables missing           | Import `sql/install.sql` or set `Config.Database.AutoInstall = true`.                                     |
| No lines                 | Admin → Line editor → "Default lines", or create your own line and set it active.                         |
| Line locked              | The reason is shown on the card (level, reputation, time of day, wrong bus).                              |
| Stop not detected        | **Stop** inside the radius (below approx. 5 km/h). Enlarge the radius in the editor or re-place the stop. |
| Passengers left behind   | You departed too early – the HUD shows the dwell time ("doors open").                                     |
| "Ride was not plausible" | Teleport or shortcut between stops detected (see server console).                                         |
| Admin area missing       | ESX group in `Config.Admin.Groups` or ACE `pepper_bus.admin`.                                             |

<details>

<summary>Do players need an ESX job?</summary>

No. Everyone can go on duty at the depot.

</details>

<details>

<summary>Will an update overwrite my lines?</summary>

No. Lines are stored in the database and are never overwritten by updates.

</details>

<details>

<summary>Why don't I get line offers from the control center?</summary>

By default drivers choose lines themselves in the tablet (`Config.Dispatch.Enabled = false`). Set it to `true` to receive offers as well.

</details>

<details>

<summary>Does F7 conflict with Pepper Taxi or Pepper Trucking?</summary>

No – Taxi uses F6 and Trucking F9. Every player can also rebind the key.

</details>

### Changelog

#### Upcoming update

**Changed**

* Drivers choose their lines themselves in the tablet – by default the control center no longer assigns lines (`Config.Dispatch.Enabled = false`, can be switched back on)

**Fixed**

* At stops only the passenger doors open – no longer hood, trunk and driver door (configurable per bus via `doors`)
* Crash with the company account and shifted challenge popup
* Line editor: wider stop list, cut-off columns and buttons

#### 1.0.0 – 2026-09-26

**Initial release**

* Bus driver career with 50 levels, reputation and 6 buses from shuttle to festival bus
* Real line service: stops, doors, boarding and alighting, minimum dwell time, schedule with punctuality
* 14 default lines, 10 line types, 9 passenger types, control center offers with demand bonus
* 1–5 star rating, daily and weekly challenges, duty bonus, charter rides for players
* Bus company (public or player-run) with employees, ranks, salaries and company account
* In-game line editor (incl. `/busstop`, preview, test run, copy, reverse direction), admin panel with offline editing and audit log
* Driver tablet, HUD, sounds; German and English
