> 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/docs/de/activities/pepper-racing.md).

# Pepper Racing

Racing-Tablet mit legalem Club und Underground-Szene – Startaufstellung mit Startampel, Rennleitung, Protestverfahren, Ghosts, Crews, Saisons und Strecken-Editor für ESX, QBCore und Qbox.

Rennen waren auf den meisten Servern: Checkpoints abfahren, Zeit ablesen, fertig. Mit **Pepper Racing** stellen sich deine Spieler auf ihren Grid-Platz, warten auf fünf rote Lichter, und eine Rennleitung wacht über jede Kurve – oder sie fahren nachts im Underground, wo der Treffpunkt erst kurz vor dem Start aufs GPS kommt.

Alles läuft über das **Racing-Tablet** (Item `racing_tablet`) mit zwei Welten: dem hellen **Pepper Racing Club** im Zeitnahme-Look und dem dunklen **Underground** in Neon.

{% hint style="success" %}
**Pepper Racing holen:** [shop.pepperscripts.de](https://shop.pepperscripts.de)
{% endhint %}

{% hint style="info" %}
🧪 **Getestet auf unserem Dev-Server:** Wir testen alle Skripte selbstverständlich permanent auf unserem eigenen Dev-Server „Pepper Scripts“.
{% endhint %}

### Funktionen

* **6 Modi** – Sprint, Rundstrecke (1–50 Runden), Ausscheidung, Drag, Drift, Zeitfahren mit Bestenliste
* **Startaufstellung** mit bis zu 16 Grid-Plätzen (nach Rating, Anmeldung oder ausgelost), Marker + GPS, 90 s Frist
* **Startampel** – 5 rote Lichter mit zufälliger Haltezeit; bei Drag ein Christmas Tree mit Frühstart-Erkennung
* **Rennkommissar** – erkennt Abkürzungen (Warnung, dann 5 s Zeitstrafe), prüft Checkpoint-Reihenfolge und Zeiten am Server
* **Rennleitung als RP-Rolle** – Live-Karte, Zeitnahme, Zeitstrafen, Disqualifikation, rote Flagge, Durchsagen, Vorfall-Protokoll
* **Protestverfahren** im Club – 120 s Frist, vorläufiges → offizielles Ergebnis, Preisgeld und Rating erst danach
* **Live-HUD** – Zeitnahme-Turm, Delta zur Bestzeit, Sektorzeiten lila/grün/gelb, Mini-Karte, Reifen, Drift-Meter, frei verschiebbar
* **Ghost & Ideallinie** – eigene Bestzeit oder Streckenrekord fährt halbtransparent mit
* **Reifenverschleiß & Boxenstopp** auf Rundkursen ab 3 Runden, **Fotofinish** unter 0,1 s
* **Leistungsklassen D–X** automatisch aus den Fahrzeugwerten inkl. Tuning (PI 100–999)
* **Underground** – Bezirk + Uhrzeit statt Ort, geheimer Treffpunkt, Szene-Heat je Bezirk, Polizei-Alarm, Szene-Ruf
* **Underground-Karriere** – 5 Auftragsarten (Kurierfahrt, Blitzer-Jagd, Drift-Spur, Abhängen, Rivalen-Duell) und 6 Szene-Stufen mit Freischaltungen; Schwarzgeld auf Wunsch als Item
* **Wetten** als Totalisator mit Live-Quoten, **Pink Slips** (vom Server-Betreiber einschaltbar, Standard aus)
* **Racer-Rating** (Elo) mit 6 Rängen, **Crews/Teams**, **Saisons** mit Belohnungen, **K.-o.-Turniere** und **Meisterschaften**
* **Strecken-Editor** im Spiel mit Aufnahme-Modus, Boxengasse und Vorschau-Kamerafahrt – plus **Streckenabnahme**
* **Broadcast-Overlay** für Streamer und Kommentatoren, Discord-Webhooks, Server-Exports
* Deutsch & Englisch mit deutschen Motorsport-Begriffen, Config, Sprachdateien und Bridges offen

{% hint style="info" %}
**4 Standardstrecken inklusive:** Sandy Shores Short Loop, Grand Senora Loop, Sandy Shores Airfield Drag und LSIA Runway Drag werden beim ersten Start eingespielt (`install/default_tracks.json`, abschaltbar mit `Config.Tracks.InstallDefaults`). Weitere Strecken baust du selbst im Editor – an jedem Ort der Karte. Strecken von Admins sind sofort freigegeben, Strecken von anderen Spielern gehen in die Streckenabnahme.
{% endhint %}

### Auf einen Blick

|                              |                                                                                                       |
| ---------------------------- | ----------------------------------------------------------------------------------------------------- |
| **Version**                  | 1.0.0                                                                                                 |
| **Framework**                | ESX Legacy (`es_extended`), QBCore (`qb-core`) oder Qbox (`qbx_core`) – automatische Erkennung        |
| **FiveM-Server**             | Build 7290 oder neuer, **OneSync** erforderlich                                                       |
| **Abhängigkeiten (Pflicht)** | [oxmysql](https://github.com/overextended/oxmysql), [ox\_lib](https://github.com/overextended/ox_lib) |
| **Inventar**                 | ox\_inventory, qb-inventory (auch ps-/lj-inventory) oder ESX-Standardinventar                         |
| **Optional**                 | ps-dispatch, cd\_dispatch, qs-dispatch, rcore\_dispatch oder core\_dispatch                           |
| **Datenbank**                | MySQL oder MariaDB – Tabellen werden automatisch angelegt                                             |
| **Sprachen**                 | Deutsch, Englisch                                                                                     |
| **Auslieferung**             | Cfx.re Asset Escrow (`config/`, `locales/`, `bridge/`, `install/` offen)                              |

### Installation

Rechne mit etwa **15–20 Minuten**. Arbeite die Schritte in der angegebenen Reihenfolge ab – nach jedem Schritt gibt es einen **Kontrollpunkt**.

{% hint style="warning" %}
**Dateien immer mit einem Text-Editor öffnen**, zum Beispiel [Visual Studio Code](https://code.visualstudio.com/) oder [Notepad++](https://notepad-plus-plus.org/) – niemals mit Word oder WordPad.
{% endhint %}

#### Schritt 1 – Voraussetzungen prüfen

| Was                                                                               | Wozu                                                           | Pflicht?   |
| --------------------------------------------------------------------------------- | -------------------------------------------------------------- | ---------- |
| FiveM-Server **Build 7290 oder neuer**                                            | ältere Server starten das Script nicht                         | ja         |
| **OneSync** eingeschaltet                                                         | Startplätze, Positionen und Fahrzeuge werden am Server geprüft | ja         |
| **MySQL/MariaDB** + **oxmysql**                                                   | Profile, Strecken, Bestzeiten, Ghosts, Crews, Saisons          | ja         |
| **ox\_lib**                                                                       | Server-Aufrufe und Hinweise                                    | ja         |
| **ESX Legacy**, **QBCore** oder **Qbox**                                          | Charaktere, Geld, Jobs                                         | genau eins |
| Inventar: **ox\_inventory**, **qb-inventory** (ps-/lj-) oder ESX-Inventar         | Items `racing_tablet` usw.                                     | eins davon |
| Dispatch: ps-dispatch, cd\_dispatch, qs-dispatch, rcore\_dispatch, core\_dispatch | Polizei-Alarm im Underground                                   | nein       |

**OneSync:** in txAdmin unter **Settings → FXServer** auf **On** – ohne txAdmin `set onesync on` ganz oben in die `server.cfg`.

{% hint style="success" %}
**Kontrollpunkt:** Beim Serverstart steht für `oxmysql`, `ox_lib`, dein Framework und dein Inventar jeweils `Started resource <name>` in der Konsole.
{% endhint %}

#### Schritt 2 – Herunterladen und entpacken

1. [Cfx.re-Portal → Granted Assets](https://portal.cfx.re/assets/granted-assets) öffnen und **pepper\_racing** herunterladen.
2. Den Ordner `pepper_racing` nach `resources/[pepper]/` kopieren.

```
resources/
└── [pepper]/
    └── pepper_racing/
        ├── bridge/
        ├── client/
        ├── config/
        │   ├── config.lua
        │   ├── server.lua
        │   └── vehicles.lua
        ├── html/
        ├── install/
        │   ├── esx_items.sql
        │   ├── ox_items.lua
        │   ├── ox_items_en.lua
        │   ├── pepper_racing.sql
        │   └── qb_items.lua
        ├── locales/
        ├── server/
        ├── shared/
        └── fxmanifest.lua
```

{% hint style="danger" %}
**Den Ordnernamen `pepper_racing` nie ändern.** Tablet und ox\_inventory-Export nutzen den Ressourcennamen.
{% endhint %}

{% hint style="warning" %}
**Asset Escrow:** Das Script startet nur auf einem Server, dessen Lizenzschlüssel (`sv_licenseKey`) zum selben Cfx.re-Konto gehört, mit dem du gekauft hast. Mehr dazu: **Asset Escrow**.
{% endhint %}

#### Schritt 3 – Items eintragen

Pepper Racing nutzt drei Items:

| Item            | Name              | Zweck                                                                             |
| --------------- | ----------------- | --------------------------------------------------------------------------------- |
| `racing_tablet` | Racing-Tablet     | öffnet das Tablet (benutzbar)                                                     |
| `race_license`  | Rennleiter-Lizenz | Standard-Recht zum Ausschreiben von Rennen                                        |
| `race_usb`      | Underground-Stick | optionaler Underground-Zugang (nur wenn `Config.Illegal.AccessItem = 'race_usb'`) |

{% tabs %}
{% tab title="ox\_inventory (ESX, QBCore, Qbox)" %}

1. Öffne `install/ox_items.lua` (deutsche Namen) bzw. `install/ox_items_en.lua` (englische Namen).
2. Kopiere **nur die Einträge** zwischen `return {` und der letzten `}`.
3. Füge sie in `ox_inventory/data/items.lua` **vor der allerletzten schließenden Klammer `}`** ein.

Das Tablet enthält die Zeile `server = { export = 'pepper_racing.racing_tablet' }` – sie macht das Item benutzbar und muss drinbleiben.
{% endtab %}

{% tab title="qb-inventory (QBCore)" %}

1. Öffne `install/qb_items.lua`.
2. Kopiere die Einträge zwischen `return {` und der letzten `}`.
3. Füge sie in `qb-core/shared/items.lua` in die Tabelle `QBShared.Items` ein (vor deren schließender Klammer).

Gilt auch für ps-inventory und lj-inventory.
{% endtab %}

{% tab title="ESX-Standardinventar" %}
Importiere `install/esx_items.sql` in deine Datenbank (z. B. mit HeidiSQL oder phpMyAdmin). Die Datei fügt die drei Items in die Tabelle `items` ein.
{% endtab %}
{% endtabs %}

**Itembilder:** Kopiere die mitgelieferten Bilder aus `install/images/` (`racing_tablet.png`, `race_license.png`, `race_usb.png`) in den Bilderordner deines Inventars (ox\_inventory: `web/images/`, qb-inventory: `html/images/`).

{% hint style="success" %}
**Kontrollpunkt:** Nach einem Neustart kannst du dir das Tablet geben (z. B. `/giveitem <id> racing_tablet 1`) und es erscheint mit Namen im Inventar.
{% endhint %}

#### Schritt 4 – Datenbank

Nichts zu tun: Die Ressource legt beim ersten Start alle Tabellen (`pepper_racing_*`) selbst an. Hat dein Datenbank-Benutzer **kein CREATE-Recht**, importiere vorher `install/pepper_racing.sql`.

#### Schritt 5 – Config prüfen

Öffne `config/config.lua` und prüfe mindestens:

* `Config.Locale = 'de'` (oder `'en'`)
* `Config.Framework = 'auto'` – erkennt Qbox, ESX und QBCore selbst
* `Config.Permissions` – wer Rennen ausschreiben, Strecken bauen, abnehmen und die Rennleitung übernehmen darf (siehe **Konfiguration**)
* `Config.Economy` und `Config.DirtyMoney` – Konten für Club (Bank) und Underground

Webhooks, Pink Slips und Sponsor-Bonus stehen in `config/server.lua`.

#### Schritt 6 – server.cfg

Trag Pepper Racing **nach** allen Abhängigkeiten ein:

```cfg
ensure oxmysql
ensure ox_lib
ensure es_extended      # bzw. qb-core oder qbx_core
ensure ox_inventory     # bzw. qb-inventory
# optional: dein Dispatch-System
ensure pepper_racing
```

Admin-Recht vergeben (empfohlen):

```cfg
add_ace group.admin pepper_racing.admin allow
```

#### Schritt 7 – Erster Start

1. Server starten. In der Konsole erscheinen `4 Standardstrecken eingespielt` und `Pepper Racing … gestartet (Framework: esx, Strecken: 4, Saison: …)`.
2. Im Spiel das Tablet benutzen.
3. **Strecken** – die 4 mitgelieferten Strecken sind schon freigegeben. Eigene Strecken: **Neue Strecke** – Name, Typ und Bereich wählen, Editor öffnen (siehe **Rennleitung & Editor**).
4. **Erstellen** – ein Testrennen ausschreiben.

{% hint style="success" %}
**Kontrollpunkt:** Die Konsole zeigt das richtige Framework, das Tablet öffnet sich, und unter **Strecken** stehen die 4 Standardstrecken mit Status „Freigegeben“.
{% endhint %}

{% hint style="info" %}
Probleme? Siehe **FAQ**.
{% endhint %}

### Konfiguration

| Datei                 | Inhalt                                                                            |
| --------------------- | --------------------------------------------------------------------------------- |
| `config/config.lua`   | alle Einstellungen für Client und Server                                          |
| `config/vehicles.lua` | feste Klassen pro Modell, gesperrte Modelle und Fahrzeugklassen                   |
| `config/server.lua`   | Webhooks, Pink Slips, Sponsor-Bonus, Admin-ACE – wird **nie** an Clients gesendet |

Zeiten ohne Einheit im Namen sind Sekunden, Geld ist immer ganzzahlig.

#### Grundlagen

| Option             | Standard          | Bedeutung                                                                                       |
| ------------------ | ----------------- | ----------------------------------------------------------------------------------------------- |
| `Config.Locale`    | `'de'`            | Sprache (`de` / `en`) – Ordner in `locales/`                                                    |
| `Config.Framework` | `'auto'`          | `auto`, `esx`, `qbcore`, `qbox`, `standalone` (`auto` prüft qbx\_core → es\_extended → qb-core) |
| `Config.Item`      | `'racing_tablet'` | Item, das das Tablet öffnet                                                                     |
| `Config.Command`   | `false`           | optionaler Chat-Befehl (z. B. `'racing'`) – öffnet das Tablet **ohne** Item                     |
| `Config.Tablet`    | `prop_cs_tablet`  | Prop und Animation beim Öffnen                                                                  |

#### Rechte

Admin = ACE `pepper_racing.admin` **oder** eine Gruppe aus `Config.AdminGroups` (`admin`, `superadmin`, `god`). Admins haben automatisch alle Rechte. Alle Rechte werden bei **jedem** Server-Aufruf neu geprüft.

| Recht          | Wofür                                                     | Standard                                |
| -------------- | --------------------------------------------------------- | --------------------------------------- |
| `createRace`   | Rennen und Events ausschreiben (Club + Underground)       | Gruppe `admin` oder Item `race_license` |
| `createTrack`  | Strecken im Editor bauen (Nicht-Admins → Streckenabnahme) | Gruppe `admin`                          |
| `approveTrack` | eingereichte Strecken freigeben oder ablehnen             | Gruppe `admin`                          |
| `control`      | Rennleitung für **alle** Rennen                           | Gruppe `admin`                          |

Der **Organisator** eines Rennens hat die Rennleitung für sein eigenes Rennen immer. Jede erfüllte Bedingung reicht:

```lua
Config.Permissions = {
    createTrack = {
        ace = 'pepper_racing.createTrack',  -- add_ace group.mod pepper_racing.createTrack allow
        groups = { 'admin' },               -- Framework-Gruppen
        jobs = { mechanic = 2 },            -- Job ab Dienstgrad 2
        items = {},                         -- Item im Inventar
        everyone = false,                   -- true = jeder Spieler
    },
}
```

{% hint style="info" %}
**RP-Idee:** Gib einem Job (z. B. einem Rennclub-Job) das Recht `control` – dann ist die Rennleitung eine echte Rolle auf deinem Server, nicht nur ein Admin-Werkzeug.
{% endhint %}

#### Rennen

| Option                         | Standard              | Bedeutung                                            |
| ------------------------------ | --------------------- | ---------------------------------------------------- |
| `Config.Races.MaxActive`       | `10`                  | offene Rennen gleichzeitig (pro Organisator 1)       |
| `Config.Races.MinRacers`       | `2`                   | Mindestfahrer für einen Start                        |
| `Config.Races.MaxRacers`       | `16`                  | Obergrenze Fahrer (2–16)                             |
| `Config.Races.MaxLaps`         | `50`                  | höchste Rundenzahl                                   |
| `Config.Races.LobbyTimeout`    | `1800`                | offene Lobby ohne Start wird nach 30 min geschlossen |
| `Config.Races.LeaveVehicleDnf` | `15`                  | Fahrzeug so lange verlassen → Ausfall (DNF)          |
| `Config.Races.StartDelays`     | `0, 2, 5, 10, 15, 30` | wählbare Startzeiten in Minuten                      |
| `Config.Grid.Time`             | `90`                  | Sekunden, um auf den Startplatz zu fahren            |
| `Config.Grid.Radius`           | `4.0`                 | so nah (m) muss das Fahrzeug am Platz stehen         |
| `Config.Grid.Teleport`         | `false`               | Fahrer direkt auf den Platz setzen                   |
| `Config.Grid.Order`            | `'rating'`            | `rating` (beste vorne), `signup`, `random`           |
| `Config.Lights`                | `200`–`3000` ms       | zufällige Haltezeit nach dem 5. roten Licht          |
| `Config.FinishTimeout`         | `120`                 | Zeit für alle anderen nach dem ersten Fahrer im Ziel |
| `Config.PhotoFinish`           | `100`                 | Fotofinish-Markierung unter so vielen Millisekunden  |

#### Rennkommissar, Anti-Cheat und Protest

| Option                           | Standard | Bedeutung                                                   |
| -------------------------------- | -------- | ----------------------------------------------------------- |
| `Config.Steward.Corridor`        | `2.5`    | Korridor = Checkpoint-Breite × Faktor (mind. 35 m)          |
| `Config.Steward.CutWarnAfter`    | `1.5`    | Sekunden außerhalb → Warnung                                |
| `Config.Steward.CutPenaltyAfter` | `3.0`    | Sekunden außerhalb → Zeitstrafe                             |
| `Config.Steward.CutPenalty`      | `5`      | Zeitstrafe (s), höchstens 1 je Streckenabschnitt            |
| `Config.AntiCheat.MaxSpeed`      | `110.0`  | m/s – schneller kann niemand zwischen zwei Checkpoints sein |
| `Config.AntiCheat.MaxViolations` | `2`      | ab so vielen Verstößen → Disqualifikation                   |
| `Config.Protest.Enabled`         | `true`   | Protestverfahren (nur Club)                                 |
| `Config.Protest.Window`          | `120`    | Frist nach Rennende, danach ist das Ergebnis offiziell      |
| `Config.Protest.Reasons`         | 4 Gründe | Kontakt, Abkürzung, Blockieren, unsportliches Verhalten     |

#### Geld und Wetten

| Option                           | Standard                                           | Bedeutung                                                 |
| -------------------------------- | -------------------------------------------------- | --------------------------------------------------------- |
| `Config.Economy.LegalAccount`    | `'bank'`                                           | Startgeld/Preisgeld im Club                               |
| `Config.Economy.IllegalAccount`  | `'black_money'`                                    | Underground (Konto je Framework über `Config.DirtyMoney`) |
| `Config.Economy.MaxEntryFee`     | `50000`                                            | höchstes Startgeld                                        |
| `Config.Economy.HouseCut`        | `0.05`                                             | 5 % des Topfs werden einbehalten                          |
| `Config.Economy.PrizeSplits`     | Sieger 100 · Podium 60/30/10 · Top 5 40/25/15/12/8 | Preisverteilung in Prozent                                |
| `Config.DirtyMoney`              | ESX `black_money`, QBCore/Qbox `cash`              | QBCore/Qbox haben standardmäßig kein Schwarzgeld-Konto    |
| `Config.Bets.Enabled`            | `true`                                             | Wetten (Totalisator)                                      |
| `Config.Bets.Min` / `Max`        | `100` / `25000`                                    | Einsatzgrenzen                                            |
| `Config.Bets.HouseCut`           | `0.05`                                             | Anteil der Hauskasse                                      |
| `Config.Bets.RacersMayBetOnSelf` | `true`                                             | Fahrer dürfen auf sich setzen – auf Gegner nie            |
| `Config.Bets.Legal` / `Illegal`  | `true` / `true`                                    | Wetten im Club / im Underground erlauben                  |

**Sponsor-Bonus** (`config/server.lua`): `ServerConfig.Sponsor = { Enabled = false, PerRacer = 500, Max = 10000 }` – der Server legt pro gestartetem Fahrer Geld in den Preistopf legaler Rennen (neues Geld, nicht von Spielern).

#### Underground und Polizei

| Option                                   | Standard                     | Bedeutung                                                                                                      |
| ---------------------------------------- | ---------------------------- | -------------------------------------------------------------------------------------------------------------- |
| `Config.Illegal.HiddenForJobs`           | `police`, `sheriff`, `state` | diese Jobs sehen den Underground nicht                                                                         |
| `Config.Illegal.AccessItem`              | `nil`                        | z. B. `'race_usb'` – dann nur mit Item                                                                         |
| `Config.Illegal.RevealBefore`            | `120`                        | Treffpunkt so viele Sekunden vor dem Start per GPS                                                             |
| `Config.Illegal.MeetupRadius`            | `60.0`                       | Radius des Treffpunkts (m)                                                                                     |
| `Config.Illegal.Heat`                    | `18` / `1.0` / `60`          | Heat pro Rennen / Abbau pro Minute / Warnschwelle                                                              |
| `Config.Illegal.StreetRepWin` / `Podium` | `25` / `10`                  | Szene-Ruf für Sieg / Platz 2–3                                                                                 |
| `Config.Police.Jobs`                     | `police`, `sheriff`          | wer den Alarm bekommt                                                                                          |
| `Config.Police.BaseChance`               | `0.15`                       | Grundwahrscheinlichkeit eines Alarms                                                                           |
| `Config.Police.HeatFactor`               | `0.006`                      | + Heat × Faktor (Heat 100 → +60 %)                                                                             |
| `Config.Police.MaxChance`                | `0.85`                       | höchstens 85 %                                                                                                 |
| `Config.Police.BlipTime`                 | `90`                         | Sekunden, die der Einsatz-Blip sichtbar ist                                                                    |
| `Config.Police.Dispatch`                 | `'auto'`                     | `auto`, `builtin`, `ps-dispatch`, `cd_dispatch`, `qs-dispatch`, `rcore_dispatch`, `core_dispatch` oder `false` |

**Pink Slips**

{% hint style="danger" %}
**Standard: aus.** Bei Pink Slips setzen beide Fahrer ihr eigenes Fahrzeug, der Sieger bekommt das Fahrzeug des Verlierers **endgültig** – der Besitz wird in der Datenbank umgeschrieben. Schalte das nur ein, wenn es zu deinen Server-Regeln passt, und weise deine Spieler darauf hin.
{% endhint %}

```lua
-- config/server.lua
ServerConfig.PinkSlips = { Enabled = true, Table = 'auto' } -- 'auto' | 'owned_vehicles' | 'player_vehicles'
```

`auto` nimmt `owned_vehicles` (ESX) bzw. `player_vehicles` (QBCore/Qbox). Fehlt die Tabelle oder Spalte, meldet die Konsole das beim Start und Pink Slips bleiben aus. Schlüssel: qbx\_vehiclekeys, qb-vehiclekeys, wasabi\_carlock, MrNewbVehicleKeys – eigene Systeme in `bridge/server/vehicles.lua`.

#### Street Rep und Aufträge (seit 1.2.0)

**Stufen** (`config/config.lua` → `Config.StreetRep`):

| Option                 | Standard                          | Bedeutung                                                                                                |
| ---------------------- | --------------------------------- | -------------------------------------------------------------------------------------------------------- |
| `Tiers`                | 0 / 150 / 400 / 900 / 1800 / 3000 | Rep ab dem eine Stufe gilt (Namen in `locales/*/core.json` → `core.tier_<key>`)                          |
| `Unlocks.createRace`   | `1`                               | ab welcher Stufe Spieler eigene Underground-Rennen ausschreiben (das Recht `createRace` gilt zusätzlich) |
| `Unlocks.pinkSlips`    | `3`                               | Pink-Slip-Rennen ausschreiben und mitfahren                                                              |
| `Unlocks.minTierRaces` | `4`                               | Rennen „nur ab Stufe X“ ausschreiben                                                                     |
| `BetLimit`             | 2.500 / 5.000 / 10.000 / 25.000 … | Höchsteinsatz je Underground-Rennen nach Stufe (nie über `Config.Bets.Max`)                              |
| `MissionBonus`         | 0 / 5 / 10 / 15 / 20 / 25         | % Aufschlag auf Auftragsprämien nach Stufe                                                               |

Admins sind von allen Stufen-Sperren ausgenommen.

**Aufträge** (`config/missions.lua`, wird nie an Clients gesendet):

| Option                    | Standard                                                        | Bedeutung                                                                                                                       |
| ------------------------- | --------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| `Enabled`                 | `true`                                                          | Reiter „Aufträge“ an/aus                                                                                                        |
| `Offers` / `SlotCooldown` | `3` / `240`                                                     | Angebote auf dem Brett / Sekunden bis ein Platz neu belegt wird                                                                 |
| `DailyLimit`              | `20`                                                            | Aufträge je Charakter und Tag (0 = unbegrenzt)                                                                                  |
| `TravelMinutes`           | `10`                                                            | Zeit bis zum Treffpunkt                                                                                                         |
| `Reroll`                  | `250` $ / `60` s                                                | Preis und Wartezeit für „Neu würfeln“                                                                                           |
| `FailRep` / `AbortRep`    | `2` / `4`                                                       | Rep-Verlust bei Fehlschlag / Abbruch nach dem Start                                                                             |
| `Difficulty`              | leicht ×1 · mittel ×1,6 (ab Stufe 2) · schwer ×2,6 (ab Stufe 5) | Prämien-, Rep- und Zeitfaktor                                                                                                   |
| `Types.<art>`             | siehe Datei                                                     | `Enabled`, `tier`, `Money = { min, max }`, `Rep` und die Werte jeder Art (Zeitlimit, Mindesttempo, Punkteziel, Suchgebiet …)    |
| `Items`                   | leer                                                            | Zufalls-Items als Bonus, z. B. `{ name = 'race_usb', count = 1, chance = 0.05, types = { 'rival' }, minDifficulty = 'normal' }` |
| `Locations`               | 20 Orte                                                         | Abhol-, Abgabe- und Treffpunkte – eigene Koordinaten einfach ergänzen                                                           |
| `DriftZones`              | 4 Bereiche                                                      | große freie Flächen mit Radius                                                                                                  |
| `SpeedTraps`              | leer                                                            | eigene Blitzer-Routen; zusätzlich sucht das Script lange Geraden auf euren freigegebenen Sprint-/Rundstrecken                   |

{% hint style="info" %}
**Rivalen-Duelle** brauchen Bestzeiten anderer Fahrer (Zeitfahren oder Sprint) auf freigegebenen Strecken. Auf einem neuen Server erscheinen sie erst, wenn jemand Zeitfahren gefahren ist.
{% endhint %}

**Schwarzgeld als Item:** Soll das Underground-Geld ein Item sein (z. B. `markedbills` bei QBCore/Qbox), trage es in `Config.DirtyMoney.Item` ein:

```lua
Config.DirtyMoney = {
    esx = 'black_money', qbcore = 'cash', qbox = 'cash', standalone = 'black_money',
    Item = { name = 'markedbills', worth = true }, -- worth = Wert steht in den Metadaten (sonst 1 Item = 1 $)
}
```

Startgeld, Wetten, Preisgeld und Auftragsprämien laufen dann über das Item (ox\_inventory, qb-/ps-/lj-inventory). Abgebucht werden ganze Bündel, das Wechselgeld kommt als neues Bündel zurück.

#### Rating, Ränge und Saison

| Option                              | Standard                               | Bedeutung                                                                              |
| ----------------------------------- | -------------------------------------- | -------------------------------------------------------------------------------------- |
| `Config.Elo`                        | Start `1000`, K `32`, SoftReset `0.5`  | Racer-Rating; Soft-Reset halbiert den Abstand zu 1000 am Saisonende                    |
| `Config.Ranks`                      | 6 Ränge                                | Rookie < 1000 ≤ Amateur < 1200 ≤ Semi-Pro < 1400 ≤ Pro < 1600 ≤ Elite < 1800 ≤ Legende |
| `Config.Points`                     | 25, 18, 15, 12, 10, 8, 6, 4, 2, 1      | Saison- und Meisterschaftspunkte je Platz                                              |
| `Config.Season.Days`                | `30`                                   | Länge einer Saison (neue Saison startet automatisch)                                   |
| `Config.Season.Factor`              | Club `1.0`, Underground `1.0`          | Saisonpunkte-Faktor (Zeitfahren zählt nie)                                             |
| `Config.Season.Rewards`             | P1 50.000 · P2–3 25.000 · P4–10 10.000 | Belohnungen (Geld und/oder Items), auch offline abholbar                               |
| `Config.Profile.AliasCooldownHours` | `24`                                   | so oft darf der Alias geändert werden                                                  |

#### Crews und Events

| Option                                | Standard       | Bedeutung                                                   |
| ------------------------------------- | -------------- | ----------------------------------------------------------- |
| `Config.Crews.Cost`                   | `25000` (Bank) | Gründungskosten                                             |
| `Config.Crews.MaxMembers`             | `20`           | Mitglieder pro Crew                                         |
| `Config.Crews.InviteDistance`         | `10.0`         | Einladung per Server-ID nur in der Nähe (per Alias überall) |
| `Config.Crews.Emblems` / `Colors`     | 12 / 12        | Embleme und Farben zur Auswahl                              |
| `Config.Events.MaxOpen`               | `5`            | gleichzeitig offene Events                                  |
| `Config.Events.KnockoutSizes`         | `4, 8, 16`     | Feldgrößen für K.-o.-Turniere                               |
| `Config.Events.MinRaces` / `MaxRaces` | `2` / `10`     | Rennen pro Meisterschaft                                    |

#### Ghost, Reifen, Drift, Drag

| Option                                       | Standard                                   | Bedeutung                                                                |
| -------------------------------------------- | ------------------------------------------ | ------------------------------------------------------------------------ |
| `Config.Ghost`                               | Intervall `100` ms, max. 15 min            | Ghost-Aufnahme, Transparenz `Alpha = 120`                                |
| `Config.IdealLine`                           | `Ahead = 120.0`                            | Meter Ideallinie vor dem Fahrzeug                                        |
| `Config.Tires.WearPerKm`                     | `4.0`                                      | % Verschleiß je km (× `SlipFactor 3.0` bei Schlupf, Drift, Vollbremsung) |
| `Config.Tires.GripLossStart` / `MaxGripLoss` | `40` / `0.18`                              | ab 40 % Verschleiß weniger Grip, höchstens −18 %                         |
| `Config.Tires.PitTime`                       | `6`                                        | Sekunden Reifenwechsel in der Box                                        |
| `Config.Drift`                               | Winkel `12°`, Tempo `8 m/s`, Kombo `2.5 s` | Driftwertung                                                             |
| `Config.Drag.Distances`                      | `201, 402`                                 | übliche Drag-Distanzen (m)                                               |

#### Strecken, Editor, Blips, HUD

| Option                               | Standard                           | Bedeutung                                                                               |
| ------------------------------------ | ---------------------------------- | --------------------------------------------------------------------------------------- |
| `Config.Tracks.InstallDefaults`      | `true`                             | 4 Standardstrecken beim ersten Start einspielen (nur wenn noch keine Strecke existiert) |
| `Config.Tracks.AdminAutoApprove`     | `true`                             | Admin-Strecken sofort freigegeben                                                       |
| `Config.Tracks.MaxCheckpoints`       | `120`                              | Checkpoints pro Strecke                                                                 |
| `Config.Tracks.MaxPerCreator`        | `10`                               | Strecken pro Ersteller (Admins unbegrenzt)                                              |
| `Config.Tracks.SnapToRoad`           | `true`                             | Checkpoints auf die Straße einrasten                                                    |
| `Config.Tracks.RecordSpacing`        | `60.0`                             | Aufnahme-Modus: alle N Meter ein Checkpoint                                             |
| `Config.Tracks.DefaultWidth`         | `14.0`                             | Standardbreite neuer Checkpoints (m)                                                    |
| `Config.Keys`                        | E, Backspace, G, H, R, F, Enter, X | Editor-Tasten (GTA-Control-IDs)                                                         |
| `Config.Blips` / `Config.Checkpoint` | –                                  | Blips, Checkpoint-Typen und -Farben (Club rot, Underground magenta)                     |
| `Config.Hud.Units`                   | `'kmh'`                            | `kmh` oder `mph`                                                                        |
| `Config.Hud.Draggable`               | `true`                             | Spieler dürfen das Renn-HUD verschieben                                                 |

#### Fahrzeuge (`config/vehicles.lua`)

Die Klasse berechnet das Script aus Höchstgeschwindigkeit, Beschleunigung, Bremse und Traktion **inkl. Tuning** (Leistungsindex PI 100–999: D < 400 ≤ C < 500 ≤ B < 600 ≤ A < 700 ≤ S < 800 ≤ X).

```lua
Config.VehicleClasses = { ['zentorno'] = 'S', ['bmx'] = 'D' }        -- feste Klasse pro Modell
Config.BlockedModels = { 'oppressor2', 'deluxo', 'rhino' }            -- nie zugelassen
Config.BlockedVehicleClasses = { 14, 15, 16, 21 }                     -- Boote, Helis, Flugzeuge, Züge
```

#### Webhooks (`config/server.lua`)

| Schlüssel  | Inhalt                                                          |
| ---------- | --------------------------------------------------------------- |
| `results`  | offizielle Club-Ergebnisse, Streckenrekorde, Events, Saisonende |
| `tracks`   | eingereichte und abgenommene Strecken                           |
| `illegal`  | Underground-Ergebnisse und -Events, Polizei-Alarme, Pink Slips  |
| `security` | Verdachtsfälle des Rennkommissars                               |

Leere URL = aus. Webhooks enthalten nur Alias-Namen, keine Spieler-Identifier.

#### Texte anpassen

Alle Texte stehen in `locales/de/*.json` und `locales/en/*.json` (`core`, `race`, `ui`, `admin`). Für eine neue Sprache den Ordner `en` kopieren, übersetzen und `Config.Locale` setzen.

### Spielablauf

#### Das Racing-Tablet

Das Item **Racing-Tablet** öffnet das Tablet (mit Prop und Animation). Oben schaltest du zwischen den zwei Welten um:

|           | 🏁 Club (legal)                      | 🌃 Underground                                         |
| --------- | ------------------------------------ | ------------------------------------------------------ |
| Look      | hell, Zeitnahme-Monitor, Signalrot   | dunkel, Neon-Magenta und Cyan                          |
| Name      | Spielername bzw. Fahrerlizenz        | Racer-Alias                                            |
| Geld      | Bankkonto                            | Schwarzgeld (QBCore/Qbox: Bargeld)                     |
| Rennliste | Strecke, Startzeit, Teilnehmer       | nur Bezirk und Uhrzeit                                 |
| Ergebnis  | vorläufig → Protestfrist → offiziell | sofort offiziell                                       |
| Extras    | Rennleitung, Protest, Sponsor-Bonus  | Treffpunkt, Szene-Heat, Polizei, Szene-Ruf, Pink Slips |

Bereiche: **Start** (Profilkarte, nächste Rennen, Saison-Countdown, Crew, Belohnungen), **Rennen**, **Erstellen**, **Strecken**, **Ranglisten**, **Events**, **Crew**, **Profil** – mit Rechten zusätzlich **Rennleitung** und **Admin**.

Polizei-Jobs (`Config.Illegal.HiddenForJobs`) sehen den Underground gar nicht. Ist `Config.Illegal.AccessItem` gesetzt, braucht man zusätzlich den **Underground-Stick**.

#### Die 6 Modi

| Modus            | Strecke               | Wertung                                                      |
| ---------------- | --------------------- | ------------------------------------------------------------ |
| **Sprint**       | A → B                 | Zeit                                                         |
| **Rundstrecke**  | Rundkurs, 1–50 Runden | Zeit, beste Runde                                            |
| **Ausscheidung** | Rundkurs, ab 2 Runden | der Letzte jeder Runde scheidet aus                          |
| **Drag**         | Gerade, 2 Spuren      | Reaktionszeit, ET, Endgeschwindigkeit – Frühstart = Rotlicht |
| **Drift**        | beliebige Strecke     | Driftpunkte aus Winkel × Tempo × Kombo                       |
| **Zeitfahren**   | jede Strecke, solo    | Zeit gegen den Ghost, Bestenliste (zählt nicht fürs Rating)  |

#### Ein Rennen ausschreiben

Recht `createRace` (Standard: Admins oder Item **Rennleiter-Lizenz**). Tablet → **Erstellen**:

1. **Modus & Strecke** – nur freigegebene Strecken, die zum Modus und zur Welt passen
2. **Regeln** – Runden, Klassen-Limit (D/C/B/A/S/X/offen), max. Fahrer (2–16), Kollisionen oder Phasing, Ghost, Ideallinie, Reifen & Boxenstopp (Rundstrecke ab 3 Runden)
3. **Einsatz** – Startgeld (bis 50.000), Preisverteilung Sieger / Podium / Top 5, Wetten an/aus, im Underground optional Pink Slip
4. **Start** – sofort (Start durch den Organisator) oder in 2, 5, 10, 15 oder 30 Minuten, optional privat mit Code

#### Ablauf eines Rennens

{% stepper %}
{% step %}
**Anmelden**

Spieler setzen sich ans Steuer und melden sich im Tablet an. Der Server prüft Klasse, gesperrte Modelle und das Startgeld. Zuschauer können bis zur Startampel auf Fahrer wetten (wenn Wetten an sind).
{% endstep %}

{% step %}
**Treffpunkt (nur Underground)**

120 s vor dem Start wird der Treffpunkt per GPS enthüllt – vorher kennen alle nur Bezirk und Uhrzeit.
{% endstep %}

{% step %}
**Startaufstellung**

Das Startgeld wird abgebucht, jeder Fahrer bekommt seinen **Grid-Platz** (nach Rating, Anmeldung oder ausgelost) mit Marker und GPS. 90 s Zeit, um auf den Platz zu fahren – wer nicht da ist, ist **nicht gestartet (DNS)** und bekommt sein Startgeld zurück.
{% endstep %}

{% step %}
**Startampel**

Rundstrecke, Sprint & Co.: **5 rote Lichter**, dann eine zufällige Pause bis „Lichter aus“ – die Fahrzeuge sind bis dahin eingefroren. Drag: **Christmas Tree** (Gelb – Gelb – Gelb – Grün), nicht eingefroren – wer vor Grün mehr als 0,5 m rollt, sieht Rot.
{% endstep %}

{% step %}
**Rennen**

Checkpoints müssen in Reihenfolge durchfahren werden. Der **Rennkommissar** warnt nach 1,5 s neben der Strecke und verhängt nach 3 s eine Zeitstrafe von 5 s. Fahrzeug länger als 15 s verlassen = **Ausfall (DNF)**.
{% endstep %}

{% step %}
**Ziel & Ergebnis**

Nach dem ersten Fahrer im Ziel haben alle anderen 120 s. Liegen zwei Fahrer weniger als 0,1 s auseinander, gibt es eine **Fotofinish**-Markierung. Der Ergebnis-Bildschirm zeigt Podium, Zeiten, Strafen, Rating-Änderung und Preisgeld.
{% endstep %}

{% step %}
**Protest & offizielles Ergebnis (Club)**

Das Ergebnis ist zuerst **vorläufig**. 120 s lang kann jeder Fahrer **Protest** gegen einen anderen einlegen (Kontakt, Abkürzung, Blockieren, unsportliches Verhalten). Die Rennleitung entscheidet – danach oder nach Ablauf der Frist wird das Ergebnis **offiziell**. Erst dann gibt es Preisgeld, Wettgewinne, Rating und Saisonpunkte.
{% endstep %}
{% endstepper %}

{% hint style="info" %}
**Geld ist sicher:** Bei roter Flagge, zu wenigen Fahrern in der Startaufstellung oder einem Neustart der Ressource werden Startgelder und Wetteinsätze sofort erstattet.
{% endhint %}

#### Das Renn-HUD

| Element            | Inhalt                                                                                                                                               |
| ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Zeitnahme**      | Positionen, Abstände, Crew-Farben, Strafen                                                                                                           |
| **Zeit & Delta**   | Runde, Gesamt- und Rundenzeit, beste Runde, **Delta zur Bestzeit live**, Sektorzeiten **lila** (Rekord) / **grün** (persönliche Bestzeit) / **gelb** |
| **Mini-Karte**     | Streckenverlauf mit allen Fahrern                                                                                                                    |
| **Tempo & Reifen** | Geschwindigkeit (km/h oder mph), Reifenverschleiß und Grip                                                                                           |
| **Drift-Meter**    | Driftpunkte und Kombo (Drift-Modus)                                                                                                                  |

Dazu Banner (Rennleitung, Abkürzung, Strafe, Polizei), die große Startampel und Checkpoint-Pfeile. **HUD anpassen** (Tablet → Profil): Elemente ziehen, sie rasten im Raster ein – gespeichert pro Spieler.

#### Ghost, Ideallinie, Reifen

* **Ghost:** Deine Bestzeit oder der Streckenrekord fährt als halbtransparentes Fahrzeug ohne Kollision mit. Im Zeitfahren wählst du in der Streckenansicht: ohne, meine PB oder Rekord.
* **Ideallinie:** Die Linie der Rekordrunde läuft 120 m als Spur vor deinem Fahrzeug.
* **Reifen & Boxenstopp:** Ab 3 Runden auf Rundkursen nutzen sich die Reifen ab (schneller bei Drift, Schlupf und Vollbremsungen). Ab 40 % Verschleiß sinkt der Grip. In der Box anhalten → 6 s Reifenwechsel.

#### Leistungsklassen

Jedes Fahrzeug bekommt einen Leistungsindex (PI 100–999) aus Höchstgeschwindigkeit, Beschleunigung, Bremse und Traktion – **inkl. Tuning**. Daraus folgt die Klasse D, C, B, A, S oder X. Das Tablet zeigt deine Klasse an, bevor du dich anmeldest.

#### Underground

* **Szene-Heat:** Jeder Bezirk hat einen Heat-Wert von 0 bis 100. Jedes Rennen erhöht ihn um 18, pro Minute sinkt er um 1. Ab 60 warnt das Tablet: „Szene wird beobachtet“.
* **Polizei-Alarm:** Beim Start wird gewürfelt – 15 % plus Heat × 0,6 %, höchstens 85 %. Die Polizei bekommt eine Meldung mit Blip (über dein Dispatch-System oder eingebaut).
* **Szene-Ruf:** +25 für einen Sieg, +10 für Platz 2–3, dazu Rep aus Aufträgen – eigene Rangliste „Street“ und 6 Stufen mit Freischaltungen (siehe unten).
* **Pink Slips** (nur wenn der Server sie eingeschaltet hat): 1 gegen 1, beide setzen ihr aktuelles eigenes Fahrzeug, doppelte Bestätigung – der Sieger bekommt das Fahrzeug des Verlierers.

#### Underground-Karriere: Aufträge & Szene-Stufen

Im Underground-Tablet gibt es den Reiter **Aufträge**. Dort liegen 3 Angebote mit Schwierigkeit, Zeitlimit und Prämie (Schwarzgeld + Szene-Ruf). Annehmen → Ziel und GPS erscheinen auf der Karte, rechts oben zeigt eine Anzeige Ziel, Zeitlimit und Fortschritt. Ein angenommener Platz wird nach ein paar Minuten neu belegt, **Neu würfeln** tauscht alle Angebote gegen Schwarzgeld.

| Auftrag           | Ab Stufe    | Was zu tun ist                                                                                                                          |
| ----------------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| **Kurierfahrt**   | Neuling     | Paket beim Kontakt abholen (im Kreis anhalten) und unter Zeitdruck abliefern. Schäden am Auto kosten Prämie.                            |
| **Blitzer-Jagd**  | Bekannt     | 4 Blitzer mit Mindesttempo durchfahren, Reihenfolge egal. Die Blitzer liegen auf den Geraden eurer Strecken.                            |
| **Drift-Spur**    | Bekannt     | In einem freien Bereich (Flugfeld, Rollbahn, Steinbruch …) ein Punkteziel erdriften.                                                    |
| **Abhängen**      | Respektiert | Ab dem Treffpunkt folgt dir ein Suchgebiet. Raus aus dem Kreis und lange genug draußen bleiben. Oft wird dabei echte Polizei alarmiert. |
| **Rivalen-Duell** | Gefürchtet  | Zeitfahren gegen die Bestzeit **und den Ghost** eines echten Fahrers. Gewinnst du, verliert der Rivale Szene-Ruf.                       |

Schwere Aufträge gibt es ab **Szene-Größe** – mit deutlich mehr Prämie. Wer scheitert oder einen gestarteten Auftrag abbricht, verliert ein paar Punkte Szene-Ruf (vor dem Treffpunkt abbrechen kostet nichts).

**Szene-Stufen:** Szene-Ruf gibt es für Underground-Siege, Podien und Aufträge. Er steigt durch 6 Stufen – Neuling, Bekannt, Respektiert, Gefürchtet, Szene-Größe, Legende. Jede Stufe schaltet etwas frei: neue Auftragsarten, höhere Wetten, Pink Slips, Rennen nur für Fahrer ab einer bestimmten Stufe und einen Prämien-Bonus. Das Tablet zeigt die Leiter mit allen Freischaltungen.

#### Wetten

Zuschauer (und Fahrer auf sich selbst) setzen bis zum Start auf einen Fahrer. Alle Einsätze landen in einem Topf (**Totalisator**), die Quoten ändern sich live. Ausgezahlt wird mit dem offiziellen Ergebnis – hat niemand auf den Sieger gesetzt, gibt es alle Einsätze zurück.

#### Rating, Ränge und Abzeichen

* **Racer-Rating** (Elo, Start 1000): Wer stärkere Gegner schlägt, gewinnt mehr. Zeitfahren zählt nicht.
* **6 Ränge:** Rookie, Amateur, Semi-Pro, Pro, Elite, Legende.
* **Profil:** Statistiken, Rating-Verlauf, letzte Rennen, Bestzeiten und **11 Abzeichen** (z. B. Erster Sieg, Saubere Weste, Marathon, Pink-Slip-König, Legende).
* **Ranglisten:** Saison, Allzeit, Street (Szene-Ruf) und Crews.

#### Crews

Im Club heißen sie **Team**, im Underground **Crew**. Gründen kostet 25.000: Name, Kürzel (2–4 Zeichen), eine von 12 Farben, eines von 12 Emblemen, Motto. Rollen Chef, Vize, Mitglied – bis zu 20 Mitglieder, Einladung per Alias oder Server-ID in der Nähe. Das **Crew-Rating** ist der Schnitt der 5 besten Fahrer, dazu eine eigene Crew-Saisonwertung.

#### Saison

Eine Saison dauert 30 Tage. Jedes gewertete Rennen bringt Saisonpunkte (25-18-15-12-10-8-6-4-2-1). Am Saisonende bekommen die Top 10 Belohnungen – abholbar im Tablet, auch wer beim Saisonende offline war. Das Rating wird weich zurückgesetzt, die nächste Saison startet automatisch.

#### Events

Recht `createRace`. Tablet → **Events**:

* **K.-o.-Turnier:** 4, 8 oder 16 Fahrer, 1-gegen-1-Läufe (Sprint, Rundstrecke oder Drag), Turnierbaum als Grafik.
* **Meisterschaft:** 2–10 Rennen (Sprint, Rundstrecke, Ausscheidung oder Drift), Punktetabelle 25-18-15-…

Der Organisator legt mit **Nächstes Duell / Nächstes Rennen** jeweils das nächste Rennen an – die Teilnehmer werden benachrichtigt.

#### Broadcast-Overlay

Sobald ein Rennen läuft, in der Rennansicht **Zuschauen** wählen: Das Tablet schließt sich, und ein großer Zeitnahme-Turm mit Rundenanzeige liegt über dem Bild – ideal für Streamer und Kommentatoren. Ausschalten im Tablet.

### Befehle & Exports

#### Befehle

Pepper Racing braucht **keinen** Chat-Befehl – das Tablet öffnet sich über das Item `racing_tablet`.

| Befehl                                                      | Standard                             | Funktion                                                                     |
| ----------------------------------------------------------- | ------------------------------------ | ---------------------------------------------------------------------------- |
| `Config.Command`                                            | aus (`false`)                        | z. B. `'racing'` → `/racing` öffnet das Tablet **ohne** Item                 |
| `/racingrep <ID> <+/-Menge>` · `/racingrep <ID> set <Wert>` | an (`Config.StreetRep.AdminCommand`) | nur Admins/Konsole: Szene-Ruf eines Spielers ändern oder setzen (seit 1.2.0) |

Admin-Aufgaben (Streckenabnahme, Saison, Strecken sperren) laufen im Admin-Bereich des Tablets, nicht über Befehle.

#### Tasten

| Wo     | Taste             | Funktion                               |
| ------ | ----------------- | -------------------------------------- |
| Editor | `E`               | Checkpoint setzen                      |
| Editor | `Backspace`       | letzten Checkpoint löschen             |
| Editor | Mausrad / `←` `→` | Breite ändern                          |
| Editor | `G`               | Startplatz                             |
| Editor | `H`               | Boxengasse (Einfahrt → Box → Ausfahrt) |
| Editor | `R`               | Aufnahme-Modus                         |
| Editor | `F`               | Vorschau-Kamerafahrt                   |
| Editor | `Enter`           | Speichern                              |
| Editor | `X`               | Abbrechen                              |

Ändern in `Config.Keys` (GTA-Control-IDs: `Place = 38, Remove = 177, Grid = 47, Pit = 74, Record = 45, Preview = 23, Save = 191, Exit = 73`).

#### Rechte (ACE)

```cfg
add_ace group.admin pepper_racing.admin allow          # alle Rechte
add_ace group.mod pepper_racing.createRace allow       # Rennen und Events ausschreiben
add_ace group.mod pepper_racing.createTrack allow      # Strecken bauen
add_ace group.mod pepper_racing.approveTrack allow     # Streckenabnahme
add_ace group.mod pepper_racing.control allow          # Rennleitung für alle Rennen
```

Alternativ über Gruppen, Jobs mit Mindest-Dienstgrad, Items oder `everyone = true` – siehe **Konfiguration**.

#### Exports (Server)

Alle Exports sind **nur lesend** – es gibt bewusst keinen Export, mit dem andere Ressourcen Geld, Rating oder Ergebnisse ändern.

| Export                                   | Rückgabe                                                                            |
| ---------------------------------------- | ----------------------------------------------------------------------------------- |
| `exports.pepper_racing:getProfile(src)`  | öffentliches Fahrerprofil (pid, Alias, Rating, Rang, Statistiken, Crew) oder `nil`  |
| `exports.pepper_racing:isRacing(src)`    | `true`, wenn der Spieler in Startaufstellung, Ampelphase oder Rennen ist            |
| `exports.pepper_racing:getActiveRaces()` | Liste aktiver Rennen (id, Bereich, Modus, Strecke, Status, Fahrer, Startgeld, Topf) |

Beispiel – Handy oder Notruf im Rennen sperren:

```lua
if exports.pepper_racing:isRacing(source) then
    return -- Spieler fährt gerade ein Rennen
end
```

#### Webhooks

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

```lua
ServerConfig.Webhooks = {
    results = '',  -- offizielle Ergebnisse (Podium, Rekorde), Events, Saisonende
    tracks = '',   -- eingereichte/abgenommene Strecken
    illegal = '',  -- Underground: Ergebnisse, Polizei-Alarme, Pink Slips
    security = '', -- Verdachtsfälle des Rennkommissars
}
ServerConfig.WebhookName = 'Pepper Racing'
```

Webhooks enthalten nur Alias-Namen, nie Spieler-Identifier. Webhook-URLs nie öffentlich teilen.

#### Dispatch

`Config.Police.Dispatch` in `config/config.lua`:

| Wert                                                                                     | Verhalten                                                                                                                                   |
| ---------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| `'auto'` (Standard)                                                                      | erste laufende Integration in dieser Reihenfolge: ps-dispatch, cd\_dispatch, qs-dispatch, rcore\_dispatch, core\_dispatch – sonst eingebaut |
| `'ps-dispatch'`, `'cd_dispatch'`, `'qs-dispatch'`, `'rcore_dispatch'`, `'core_dispatch'` | genau diese Integration (läuft sie nicht → eingebaut)                                                                                       |
| `'builtin'`                                                                              | eingebauter Alarm: Meldung + Blip für alle Spieler mit Job aus `Config.Police.Jobs`                                                         |
| `false`                                                                                  | kein Polizei-Alarm                                                                                                                          |

Der Alarm nutzt den Code `10-94` und bleibt `Config.Police.BlipTime` Sekunden sichtbar. Eigene Systeme bindest du in `bridge/server/dispatch.lua` an (offen).

#### Bridges (offen)

| Datei                                                               | Aufgabe                                                                                 |
| ------------------------------------------------------------------- | --------------------------------------------------------------------------------------- |
| `bridge/detect.lua`                                                 | Framework-Erkennung                                                                     |
| `bridge/server/esx.lua`, `qbcore.lua`, `qbox.lua`, `standalone.lua` | Geld, Job, Identifier, Charakterwechsel                                                 |
| `bridge/server/inventory.lua`                                       | Item benutzbar machen, prüfen, geben, nehmen (ox\_inventory, qb-/ps-/lj-inventory, ESX) |
| `bridge/server/vehicles.lua`                                        | Fahrzeugbesitz prüfen/übertragen (Pink Slips), Schlüssel-Hook                           |
| `bridge/server/dispatch.lua`                                        | Polizei-Alarm                                                                           |
| `bridge/client/frameworks.lua`                                      | Job und Benachrichtigungen im Client                                                    |

### Rennleitung & Editor

#### Rennleitung

Die Rennleitung ist eine **RP-Rolle**: Wer das Recht `control` hat, leitet alle Rennen – der Organisator eines Rennens leitet sein eigenes Rennen immer. Tablet → **Rennleitung**.

| Bereich               | Inhalt                                                                                                                          |
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| **Live-Karte**        | Strecke mit allen Fahrern in Echtzeit                                                                                           |
| **Live-Zeitnahme**    | Positionen, Abstände, Runden, Strafen – Fahrer anklicken, um zu handeln                                                         |
| **Vorfall-Protokoll** | alles, was passiert: Abkürzungen, Frühstarts, Strafen, Ausfälle – markiert als „Rennkommissar“ (automatisch) oder „Rennleitung“ |
| **Proteste**          | eingegangene Proteste mit Grund, Beschreibung und Frist                                                                         |

**Werkzeuge**

| Aktion                          | Wirkung                                                                                                                                                                 |
| ------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Zeitstrafe**                  | +5 s, +10 s oder +30 s für einen Fahrer, mit Begründung                                                                                                                 |
| **Disqualifizieren**            | Fahrer wird gewertet als DSQ                                                                                                                                            |
| **Durchsage**                   | Text (max. 120 Zeichen) als Banner an alle Fahrer – Vorlagen: „Gelbe Flagge – nicht überholen!“, „Fahrzeug auf der Strecke – Vorsicht!“, „Strecke frei – Rennen läuft!“ |
| **Rote Flagge**                 | Rennen sofort abbrechen – Startgelder und Wetten werden erstattet (gedrückt halten)                                                                                     |
| **Ergebnis offiziell erklären** | offene Proteste verfallen, Preisgeld, Wetten und Rating werden ausgezahlt                                                                                               |

Alle Eingriffe landen im Vorfall-Protokoll und sind für die Fahrer als Banner sichtbar.

#### Rennkommissar (automatisch)

Der Rennkommissar arbeitet in jedem Rennen, auch ohne Rennleitung:

* **Korridor:** Um die Strecke liegt ein Korridor (Checkpoint-Breite × 2,5, mindestens 35 m). Wer ihn verlässt, bekommt nach 1,5 s eine Warnung und nach 3 s eine **Zeitstrafe von 5 s** – höchstens eine je Streckenabschnitt.
* **Reihenfolge:** Checkpoints zählen nur in der richtigen Reihenfolge.
* **Plausibilität am Server:** Position am Checkpoint, Mindestzeit zwischen zwei Checkpoints, abweichende Client-Uhr, unrealistische Drag-Zeiten und Driftpunkte. Ab 2 Verstößen: Disqualifikation. Verdachtsfälle stehen im Admin-Bereich („Rennkommissar-Protokoll“) und optional im Webhook `security`.
* **Frühstart (Drag):** Wer vor Grün mehr als 0,5 m rollt, sieht Rot und verliert den Lauf.

#### Protestverfahren (nur Club)

1. Nach dem Rennen ist das Ergebnis **vorläufig**.
2. 120 s lang (`Config.Protest.Window`) kann jeder Fahrer im Ergebnis-Bildschirm **Protest einlegen**: gegen wen, Grund (Kontakt, Abkürzung, Blockieren, unsportliches Verhalten) und eine kurze Beschreibung.
3. Rennleitung und Organisator werden benachrichtigt und entscheiden: **abweisen**, **Zeitstrafe** oder **Disqualifikation**.
4. Nach der Entscheidung (oder nach Ablauf der Frist) wird das Ergebnis **offiziell** – erst dann gibt es Preisgeld, Wettgewinne, Rating und Saisonpunkte.

Ist keine Rennleitung online, wird das Ergebnis nach der Frist automatisch offiziell. Underground-Rennen sind immer sofort offiziell.

#### Strecken-Editor

Recht `createTrack`. Tablet → **Strecken → Neue Strecke**: Name, Typ und Bereich wählen, dann **Editor öffnen**. Der Editor startet an deiner Position.

| Taste             | Funktion                                                                       |
| ----------------- | ------------------------------------------------------------------------------ |
| `E`               | Checkpoint setzen                                                              |
| `Backspace`       | letzten Checkpoint löschen                                                     |
| Mausrad / `←` `→` | Breite des nächsten Checkpoints (6–40 m)                                       |
| `G`               | Startplatz an der aktuellen Fahrzeugposition (max. 16)                         |
| `H`               | Boxengasse: 1× Einfahrt, 2× Box, 3× Ausfahrt (nur Rundkurse)                   |
| `R`               | Aufnahme-Modus an/aus – fahr die Strecke ab, alle 60 m entsteht ein Checkpoint |
| `F`               | Vorschau-Kamerafahrt                                                           |
| `Enter`           | Speichern (mit Bestätigung)                                                    |
| `X`               | Abbrechen                                                                      |

Die Tasten lassen sich in `Config.Keys` ändern. Checkpoints rasten auf Wunsch auf der Straßenmitte ein (`Config.Tracks.SnapToRoad`). Ein Info-Panel zeigt Anzahl Checkpoints, Länge, Breite und Modus.

**Streckentypen**

| Typ               | Regeln                                                                               |
| ----------------- | ------------------------------------------------------------------------------------ |
| **Rundkurs**      | Checkpoint 1 ist Start und Ziel, mind. 3 Checkpoints, optional Boxengasse            |
| **Sprintstrecke** | der letzte Checkpoint ist das Ziel                                                   |
| **Drag-Strecke**  | genau 2 Checkpoints (Start- und Ziellinie), 2 Startplätze nebeneinander, max. 1000 m |
| **Driftstrecke**  | beliebiger Verlauf, gewertet werden Driftpunkte                                      |

Jede Strecke braucht mindestens einen Startplatz, mindestens 100 m Länge und höchstens 120 Checkpoints. Bereich: **Club**, **Underground** oder **beide**. Ersteller ohne Admin-Rechte können bis zu 10 Strecken haben.

**Tipps**

* Startplätze in Zweierreihen versetzt hintereinander setzen – wie eine echte Startaufstellung.
* Für lange Strecken den **Aufnahme-Modus** nutzen und danach einzelne Checkpoints korrigieren.
* Vor dem Speichern die **Vorschau** ansehen – genau diese Kamerafahrt sieht später auch die Streckenabnahme.

#### Streckenabnahme

Strecken von Spielern ohne Admin-Rechte haben nach dem Speichern den Status **„Wartet auf Abnahme“**. Wer das Recht `approveTrack` hat, sieht sie im Tablet unter **Admin → Streckenabnahme**:

* **Vorschau-Kamerafahrt** abspielen oder den Start als **Wegpunkt** setzen und selbst abfahren
* **Freigeben** (optional mit Kommentar) oder **Ablehnen** (Begründung Pflicht)
* Der Ersteller wird benachrichtigt, optional geht eine Meldung an den Webhook `tracks`

Admin-Strecken sind sofort freigegeben (`Config.Tracks.AdminAutoApprove`). Unter **Admin → Strecken verwalten** lassen sich Strecken sperren, entsperren und löschen.

#### Admin-Bereich

| Bereich                 | Inhalt                                                                                                      |
| ----------------------- | ----------------------------------------------------------------------------------------------------------- |
| Übersicht               | Fahrerprofile, Strecken, offene Abnahmen, aktive Rennen, Crews, Fahrer online                               |
| Streckenabnahme         | siehe oben                                                                                                  |
| Saison                  | laufende Saison, **Saison jetzt beenden** (Belohnungen + Soft-Reset), **neue Saison starten** (Name, Dauer) |
| Strecken                | Status aller Strecken ändern                                                                                |
| Rennkommissar-Protokoll | Verdachtsfälle                                                                                              |

### FAQ

#### Fehlerbehebung

| Problem                                      | Lösung                                                                                                                                                                                      |
| -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Tablet öffnet sich nicht                     | Item eingetragen? Bei ox\_inventory muss `server = { export = 'pepper_racing.racing_tablet' }` drinstehen. Ordner nicht umbenennen. Framework und Inventar **vor** `pepper_racing` starten. |
| Item zeigt nur den internen Namen            | Item-Datei aus `install/` in dein Inventar eintragen (siehe **Installation**).                                                                                                              |
| „Die Zeitnahme startet noch“                 | Datenbank nicht erreichbar – `oxmysql` vor `pepper_racing` starten, Konsole prüfen. Ohne CREATE-Recht `install/pepper_racing.sql` importieren.                                              |
| „Dafür fehlt dir die Berechtigung“           | Recht in `Config.Permissions` vergeben oder `add_ace group.admin pepper_racing.admin allow`.                                                                                                |
| „Keine passende Strecke“                     | Für diesen Modus und diese Welt gibt es noch keine freigegebene Strecke – im Editor bauen oder abnehmen. Drag braucht eine Drag-Strecke.                                                    |
| Underground fehlt im Tablet                  | Dein Job steht in `Config.Illegal.HiddenForJobs`, oder `AccessItem` ist gesetzt und das Item fehlt.                                                                                         |
| „Nicht gestartet (DNS)“                      | Nicht innerhalb von 90 s auf dem Startplatz. `Config.Grid.Time` erhöhen oder `Config.Grid.Teleport = true`.                                                                                 |
| „Dieses Fahrzeug ist für Rennen gesperrt“    | Modell steht in `Config.BlockedModels` oder die GTA-Klasse in `Config.BlockedVehicleClasses`.                                                                                               |
| Fahrzeug landet in der falschen Klasse       | In `Config.VehicleClasses` eine feste Klasse für das Modell eintragen.                                                                                                                      |
| Startgeld im Underground fehlt (QBCore/Qbox) | `Config.DirtyMoney` nutzt dort Bargeld (`cash`) – oder ein eigenes Konto eintragen.                                                                                                         |
| Pink Slip lässt sich nicht wählen            | `ServerConfig.PinkSlips.Enabled = true` setzen. Meldet die Konsole „Tabelle … nicht gefunden“, `Table` passend setzen.                                                                      |
| Polizei bekommt keinen Alarm                 | `Config.Police.Jobs` und `Config.Police.Dispatch` prüfen – der Alarm kommt nur mit einer Wahrscheinlichkeit (15 % + Heat).                                                                  |
| Ergebnis bleibt „vorläufig“                  | Normal im Club: 120 s Protestfrist. Die Rennleitung kann es sofort offiziell erklären.                                                                                                      |

#### Fragen

<details>

<summary>Sind Strecken dabei?</summary>

Ja, 4 Strecken sind dabei: Sandy Shores Short Loop, Grand Senora Loop (Rundkurse), Sandy Shores Airfield Drag und LSIA Runway Drag (Drag). Sie werden beim ersten Start eingespielt, solange noch keine Strecke existiert (`install/default_tracks.json`, abschaltbar mit `Config.Tracks.InstallDefaults = false`). Weitere Strecken baust du selbst im Editor – an jedem Ort der Karte, mit Aufnahme-Modus in wenigen Minuten. Strecken von Admins sind sofort freigegeben.

</details>

<details>

<summary>Brauche ich Addon-Fahrzeuge?</summary>

Nein. Jedes Fahrzeug – auch Addon-Fahrzeuge – bekommt seine Klasse automatisch aus den eigenen Werten inkl. Tuning.

</details>

<details>

<summary>Wer darf Rennen ausschreiben?</summary>

Standardmäßig Admins und alle mit dem Item **Rennleiter-Lizenz** (`race_license`). Das änderst du in `Config.Permissions.createRace` – z. B. für einen Job oder mit `everyone = true` für alle.

</details>

<details>

<summary>Muss eine Rennleitung online sein?</summary>

Nein. Der Rennkommissar arbeitet automatisch, und ohne Entscheidung wird das Ergebnis nach der Protestfrist offiziell. Die Rennleitung ist ein RP-Plus.

</details>

<details>

<summary>Was passiert bei einem Server-Neustart mitten im Rennen?</summary>

Laufende Rennen werden abgebrochen, Startgelder und Wetteinsätze sofort erstattet. Profile, Strecken, Bestzeiten, Ghosts, Crews und Saisons liegen in der Datenbank.

</details>

<details>

<summary>Sind Pink Slips gefährlich für meine Server-Wirtschaft?</summary>

Pink Slips sind **standardmäßig aus**. Wenn du sie einschaltest, wechseln Fahrzeuge endgültig den Besitzer – der Server prüft vorher Besitz und Kennzeichen, beide Fahrer bestätigen doppelt, und es gibt sie nur im Underground 1 gegen 1. Schalte sie nur ein, wenn das zu deinen Regeln passt.

</details>

<details>

<summary>Kann die Polizei den Underground sehen?</summary>

Nein. Jobs aus `Config.Illegal.HiddenForJobs` sehen den Underground gar nicht. Die Polizei erfährt von Rennen nur über den Polizei-Alarm.

</details>

<details>

<summary>Wie funktioniert das Rating?</summary>

Elo-Rating mit Startwert 1000: Wer stärkere Gegner schlägt, gewinnt mehr Punkte. Gewertet werden Rennen mit mindestens 2 Fahrern, Zeitfahren zählt nicht. Am Saisonende wird der Abstand zu 1000 halbiert.

</details>

<details>

<summary>Kann ich mph statt km/h anzeigen?</summary>

Ja: `Config.Hud.Units = 'mph'`.

</details>

<details>

<summary>Wie stelle ich auf Englisch um?</summary>

`Config.Locale = 'en'` in `config/config.lua`. Für die Items `install/ox_items_en.lua` verwenden.

</details>

<details>

<summary>Wie zeige ich ein Rennen im Stream?</summary>

Während ein Rennen läuft, in der Rennansicht **Zuschauen** wählen – das Broadcast-Overlay zeigt einen großen Zeitnahme-Turm und die Rundenanzeige, ohne Tablet.

</details>

### Changelog

#### 1.2.0 – 2026-10-25

**Underground-Karriere**

* Neuer Reiter **Aufträge** im Underground-Tablet: Kurierfahrt, Blitzer-Jagd, Drift-Spur, Abhängen und Rivalen-Duell – Prämie in Schwarzgeld + Szene-Ruf
* **6 Szene-Stufen** (Neuling bis Legende) schalten Aufträge, schwere Aufträge, höhere Wetten, Pink Slips und einen Prämien-Bonus frei
* Underground-Rennen nur ab einer bestimmten Stufe ausschreiben
* **Schwarzgeld als Item** (`Config.DirtyMoney.Item`, z. B. `markedbills`)
* Admin-Befehl `/racingrep`, Webhooks für Stufenaufstiege und gewonnene Rivalen-Duelle
* Neue Datei `config/missions.lua`; Wetten im Underground nach Stufe begrenzt, Pink Slips ab Stufe 3

#### 1.1.0 – 2026-10-02

**Strecken-Update**

* 4 Strecken inklusive: Sandy Shores Short Loop, Grand Senora Loop, Sandy Shores Airfield Drag, LSIA Runway Drag
* Werden beim ersten Start automatisch eingespielt (nur wenn noch keine Strecke existiert), abschaltbar mit `Config.Tracks.InstallDefaults`

#### 1.0.1 – 2026-10-02

**Bugfixes**

* Diverse Fehler behoben, Stabilität verbessert

#### 1.0.0 – 2026-10-01

**Erste Version**

* Racing-Tablet mit zwei Welten: heller Pepper Racing Club und dunkles Underground
* 6 Modi: Sprint, Rundstrecke, Ausscheidung, Drag, Drift, Zeitfahren
* Startaufstellung mit bis zu 16 Grid-Plätzen, F1-Startampel, Drag-Christmas-Tree mit Frühstart-Erkennung
* Rennkommissar mit Abkürzungs-Erkennung und Zeitstrafen, Plausibilitätsprüfung am Server
* Rennleitung als RP-Rolle: Live-Karte, Zeitstrafen, Disqualifikation, rote Flagge, Durchsagen
* Protestverfahren mit vorläufigem und offiziellem Ergebnis
* Live-HUD mit Delta, Sektorfarben, Mini-Karte – frei verschiebbar
* Ghost, Ideallinie, Reifenverschleiß mit Boxenstopp, Fotofinish
* Leistungsklassen D–X aus den Fahrzeugwerten inkl. Tuning
* Underground mit geheimem Treffpunkt, Szene-Heat, Polizei-Alarm (5 Dispatch-Integrationen + eingebaut), Szene-Ruf
* Wetten (Totalisator), Pink Slips (Standard aus)
* Racer-Rating mit 6 Rängen, 11 Abzeichen, Crews/Teams, Saisons mit Belohnungen
* K.-o.-Turniere mit Turnierbaum und Meisterschaften
* Strecken-Editor mit Aufnahme-Modus, Boxengasse und Vorschau, Streckenabnahme
* Broadcast-Overlay, Discord-Webhooks, Server-Exports
* ESX Legacy, QBCore und Qbox · Deutsch und Englisch
