Wiki im Aufbau. Viele Konzepte hier stammen aus Alpha 0.2 und können sich noch ändern. Das Wiki wird zur Version 1.0 finalisiert — vorerst hilft es Closed-Testern und später Early-Access-Spielern bei der Orientierung. Für die aktuellsten und verlässlichsten Infos tritt dem Discord bei — dort werden Änderungen zuerst angekündigt und du kannst direkt nachfragen.

Für die neuesten Infos dem Discord beitreten

Ein Pack in SQL bearbeiten

Das vollständige Schema eines Mod-Packs, Tabelle für Tabelle, die Werkzeuge zum Öffnen — sqlite3, DB Browser, ein Python-Skript — und die Regeln, nach denen der Lader arbeitet.

Auf dieser Seite

Ein Mod-Pack ist eine ganz normale SQLite-Datenbank. Der Mod-Editor ist der bequeme Weg, eines zu schreiben, aber nichts hindert Sie daran, die Datei selbst zu öffnen — und für manche Arbeiten ist das mit Abstand der schnellere Weg:

  • eine reale Saison aus einer Tabelle oder CSV importieren;
  • vierzig Sponsoren umbenennen oder jedes Fahrergehalt um 10 % anheben;
  • ein Pack aus einem Skript erzeugen, um es neu zu bauen, sobald sich die Quelldaten ändern;
  • das Pack eines anderen lesen, um zu sehen, wie er es gemacht hat.

Diese Seite ist die Referenz dafür. Sie dokumentiert, was das Spiel tatsächlich liest — Spalte für Spalte — und nach welchen Regeln. Nichts davon ist ein internes Detail: Der Lader ist bewusst nachsichtig, und zu wissen, wie nachsichtig, ist genau das, was einem erlaubt, ein Pack von Hand zu schreiben.

Sie brauchen diese Seite nie, um zu modden. Der Mod-Editor schreibt jede hier beschriebene Tabelle, prüft Ihre Arbeit und hebt ältere Packs an. Greifen Sie zu SQL, wenn Sie Massenänderungen oder Skripte wollen.


Ein Pack öffnen

Jedes SQLite-Werkzeug funktioniert — die Datei hat keinen eigenen Header, keine Kompression, keine Verschlüsselung.

Mod-Editor im Spiel · geprüft · sicher DB Browser wie eine Tabelle sqlite3 · Python Massen · Erzeugung my_pack.db eine SQLite-Datei Das Spiel liest beim Start

Grafisch — DB Browser for SQLite ist kostenlos, läuft unter Windows, macOS und Linux und bearbeitet Tabellen wie eine Tabellenkalkulation. Das ist der sanfteste Einstieg, wenn Sie nie SQL geschrieben haben: Datei öffnen, Daten durchsuchen, Tabelle wählen, tippen. Denken Sie an Änderungen schreiben, bevor Sie schließen.

Kommandozeile — sqlite3 liegt macOS und den meisten Linux-Distributionen bei und ist unter Windows ein kleiner Download:

sqlite3 my_pack.db
sqlite> .tables
sqlite> .schema teams
sqlite> SELECT name, country FROM teams ORDER BY sort;
sqlite> .quit

Aus einem Skript — Python bringt SQLite mit, was ein Pack zu einer natürlichen Build-Ausgabe macht:

import sqlite3
db = sqlite3.connect("my_pack.db")
db.execute("UPDATE drivers SET salary = CAST(salary * 1.1 AS INTEGER)")
db.commit()
db.close()

Arbeiten Sie immer an einer Kopie. Ein Pack ist eine einzige Datei — die Sicherung ist ein Ziehen mit der Maus.


Die Regeln des Laders

Diese sechs Regeln machen das Bearbeiten von Hand sicher. Sie lohnen sich vor dem Schema selbst.

1 — Jede Tabelle ist optional. Ein Pack mit nur einer drivers-Tabelle ist gültig. Eine fehlende Tabelle heißt „dieser Bereich bleibt prozedural”, nie ein Fehler.

2 — Jede Spalte ist optional. Der Lader fragt SQLite, welche Spalten Ihre Tabelle wirklich hat, und liefert den Rest als NULL. CREATE TABLE teams(name TEXT) funktioniert also. Das heißt auch: Ein für eine ältere Version geschriebenes Pack lädt weiter — und ein Tippfehler in einem Spaltennamen ist kein Fehler, die Spalte wird schlicht nie gelesen. Das ist der eine Fehlerfall, auf den man achten muss.

3 — Typen sind nachsichtig. Jeder Wert wird als Text gelesen, egal wie gespeichert. 12, "12" und sogar 12.0 kommen alle als Zahl 12 an, wo eine Zahl erwartet wird. Speichern Sie, was bequem ist.

4 — Zeilen werden nach sort sortiert. Fügen Sie eine ganzzahlige Spalte sort hinzu, und die Zeilen werden in dieser Reihenfolge gelesen; ohne sie in Einfügereihenfolge. Die Reihenfolge zählt bei Teams (das Feld wird darin aufgebaut) und bei Kalenderläufen.

5 — Leer heißt „das Generierte behalten”. Das ist die nützlichste Regel überhaupt. Eine leere Farbe behält das generierte Design, ein leerer car_index das generierte Modell, ein Potenzial von 0 überlässt dem Generator die Obergrenze. Sie überschreiben, was Ihnen wichtig ist, und lassen den Rest in Ruhe.

6 — Fehlerhafte Zeilen werden übersprungen, nicht fatal. Ein Team ohne Namen, eine Strecke mit weniger als drei Punkten, ein kaputter Historieneintrag — jedes fällt für sich heraus. Der Rest des Packs lädt trotzdem.


meta — die Einstellungen des Packs

Zwei Spalten, key und value, eine Zeile je Einstellung. Schlüssel sind nicht case-sensitiv.

SchlüsselWertStandard
nameAnzeigename in der Auswahlder Dateiname
authorIhr Name — wird mit dem Pack angezeigt—
schema_versionFormatversion dieses Packs (aktuell: 2)1
min_game_versionÄltester Build, der es versteht, z. B. 0.5.4-6keiner
scenarionew_series (Sie kommen als neues Team) oder imposed (Sie übernehmen ein gesetztes Feld)new_series
start_yearKalenderjahr der ersten Saisondas des Spiels
teams_mode · drivers_mode · sponsors_mode · suppliers_mode · circuits_modeextend (ergänzt die generierte Welt) oder replace (nur Ihre)extend
active_seriesCSV der Meisterschaften, die laufen sollen, z. B. PFS,PF2alle aktiven
rulesCSV von Regelsatz-Ids, z. B. points_classic_top6,quali_107die der Serie

replace akzeptiert auch only; imposed auch takeover oder existing. Ein unbekannter Wert fällt auf den Standard zurück, statt zu scheitern.

Zwei Schlüssel sind ein Handschlag mit dem Spiel, und deshalb scheitert ein Pack nie stillschweigend:

  • ist schema_version höher, als der Build versteht, sagt die Zeile des Packs in der Auswahl genau das — „für ein neueres Format geschrieben” — und die unlesbaren Teile werden ignoriert;
  • ist min_game_version neuer als der Build, steht dort „benötigt Spiel X oder neuer”.

Setzen Sie beide. Sie kosten zwei Zeilen und machen aus einem rätselhaft halb funktionierenden Pack eine klare Meldung.

CREATE TABLE meta(key TEXT, value TEXT);
INSERT INTO meta VALUES
  ('name', 'Saison 1994'),
  ('author', 'Ihr Name'),
  ('schema_version', '2'),
  ('min_game_version', '0.5.4-6'),
  ('scenario', 'imposed'),
  ('start_year', '1994'),
  ('teams_mode', 'replace'),
  ('drivers_mode', 'replace');

teams

SpalteBedeutung
idStabiler Schlüssel. Worauf Fahrer, Sponsoren und Lieferanten zeigen. Beliebige eindeutige Zeichenkette.
nameAnzeigename. Eine Zeile ohne Namen wird übersprungen.
countryLändername (Germany) oder ISO-Code (de) — beides geht
budget_tiersmall · medium · large — das Verhalten des Teams, nicht nur seine Kasse
budget_musdStartbudget in Millionen. Setzt auch die Stufe, sofern budget_tier nichts anderes sagt
reputation0-100
color1 · color2 · color3Hex, z. B. #1A5FB4. Alle drei leer = generiertes Design behalten
car_indexFahrzeugmodell 0-11. Leer = generiertes behalten (0 ist ein echtes Auto, kein „nicht gesetzt”)
livery · suitVariantenindizes; 255 = generiert
logoEin Name aus images, ein Pfad relativ zum Mods-Ordner, oder eine reine Zahl für ein eingebautes Logo
car_imageEin Name aus images für ein eigenes Fahrzeug-Sprite
infra_engineering · _rnd · _chassis · _handling · _aero · _engine · _marketing · _scoutingAbteilungsstufen 0-10. 0 = generiertes behalten
infra_academyDasselbe, gedeckelt bei 3
career_wins · career_titles · best_championship · founding_yearPalmarès für eine geschriebene Historie
historyVergangene Saisons als saison:platz:siege, getrennt durch ; oder Zeilenumbrüche

Infrastruktur und Palmarès zählen wirklich nur im Szenario imposed, wo das Feld ab dem ersten Rennen ein laufender Betrieb sein soll.


drivers

SpalteBedeutung
idStabiler Schlüssel
first_name · last_nameEine Zeile ohne beides wird übersprungen
codeDrei-Buchstaben-Kürzel. Wird beim Laden großgeschrieben; eine Dopplung wird stillschweigend umbenannt
countryISO-Code — hier IST der Wert der Flaggenschlüssel
age1-55. Unter 16 ist für ein Talent erlaubt: Er altert, bleibt bis 14 vor dem Scouting verborgen und kann nicht gesetzt werden, bevor die Altersregeln der Serie es zulassen
intelligence · pace · consistency · adaptability · stamina · aggressivityDie sechs Fähigkeiten, 1-20
pot_intelligence … pot_aggressivityIhre Obergrenzen, 0-20. 0 = den Generator entscheiden lassen
curve_intelligence … curve_aggressivityIds der Entwicklungskurve; 255 = Standard. Eine unbekannte Id fällt auf den Standard zurück, statt den Wert einzufrieren
salaryPro Saison
traitsPaare art:stufe, kommagetrennt, z. B. 3:1,7:2
face_sheet · face_index · helmet_indexPorträt; 255 = generiert
helmet_hue_0 · _1 · _2Helm-Farbtöne. Alle drei leer = generiert
team · team_idDas Cockpit. team_id gewinnt, wenn beides gesetzt ist
roleprimary · secondary · reserve
contract_years0-5
career_starts · career_wins · career_podiums · career_titles · best_finishPalmarès
fame0-100; 0 behält den berechneten Wert

Zwei Fahrer je Team, einer je Cockpit. Zwei primary-Fahrer in einem Team lassen Auto 2 leer — und ein Auto ohne Fahrer startet nicht.


sponsors

SpalteBedeutung
idStabiler Schlüssel
nameLeer wird übersprungen
sectorBranche — steuert das prozedurale Logo
colorHex
budget · prominence1-10
originLändername oder ISO-Code
logoEin Name aus images oder ein Pfad
team · team_idVorab an ein Team binden. Akzeptiert eine Liste, getrennt durch ; oder ,

Der erste Sponsor eines Teams wird sein Hauptsponsor, die übrigen Nebensponsoren.


suppliers

SpalteBedeutung
idStabiler Schlüssel
nameLeer wird übersprungen
categoryengine · tires · fuel
color · origin · logoWie bei Sponsoren
budget · size1-10
money_per_gpGeld pro Rennen. Positiv = er zahlt Ihnen, negativ = Sie zahlen ihm
contractpartnership (exklusiv) oder client. Gewinnt über das Vorzeichen von money_per_gp
duration0-5 Saisons
team · team_idVorabbindung; eine Liste, wie bei Sponsoren

Die technischen Werte haben zwei Schreibweisen, und die benannten Spalten sind der Grund für diese Seite. Vier generische Felder (stat_a … stat_d) bedeuteten je Kategorie etwas anderes, was kein Fremdwerkzeug erraten konnte. Schreiben Sie stattdessen die benannten Spalten — sie gewinnen, sobald sie gesetzt und ungleich null sind:

KategorieBenannte Spalten (0-10)
enginepower · reliability · endurance · potential
tiresperformance · endurance · reliability · heat
fuelefficiency

circuits

Handgezeichnete Strecken, die das Pack mitbringt. Der Streckeneditor schreibt diese Zeilen, aber die Geometrie ist reiner Text — ein Skript kann es auch.

SpalteBedeutung
idStabiler Schlüssel — worauf ein Kalenderlauf zeigt
nameLeer wird übersprungen
pointsDie Mittellinie. x,y-Paare, verbunden mit ;. Unter drei Punkten fällt die Zeile heraus
country · cityLeer ergibt einen zufälligen, aber stabilen Ort
target_kmRundenlänge; unter 1 fällt auf 5 km zurück
characterStreckencharakter — das liest die Simulation tatsächlich
presetId der Optik-Voreinstellung
start_finish · pit_entry · pit_exitPositionen entlang der Runde; negativ oder fehlend = abgeleitet
year · downforce · tire_wear · overtakingGespeichert und angezeigt, aber nicht simuliert — im Spiel folgen diese drei aus character

calendar

Eine Zeile je Lauf, in sort-Reihenfolge, bis 24.

SpalteBedeutung
kindcircuit = eine Strecke des Packs nutzen; alles andere = generierte Strecke
circuit · circuit_idWelche. circuit_id wird zuerst versucht
character · target_kmFür einen generierten Lauf

Ein Pack mit Kalender ersetzt die Saison. Ein Pack mit Strecken ohne Kalender legt seine Kurse in den Weltpool und lässt sie selbst Läufe gewinnen.


images

name (der Schlüssel, auf den andere Tabellen zeigen) und data, die PNG-Bytes als BLOB. Logos werden mit 195×195 gezeichnet; ein eigenes Fahrzeug-Sprite ist eine Seitenansicht nach rechts auf Transparenz, 256 px hoch.

Ein Bild von der Kommandozeile einfügen:

sqlite3 my_pack.db "INSERT INTO images(name, data) VALUES('lotus.png', readfile('lotus.png'))"

…oder aus Python:

db.execute("INSERT INTO images(name, data) VALUES(?, ?)",
           ("lotus.png", open("lotus.png", "rb").read()))

Dann eine Zeile darauf zeigen lassen: UPDATE teams SET logo = 'lotus.png' WHERE name = 'Lotus'.

Zwei Namen, die sich nur in der Zeichensetzung unterscheiden (mein logo.png und mein-logo.png), landen in derselben Datei; der erste behält sie, der zweite bekommt ein nummeriertes Suffix — so wird nichts stillschweigend überschrieben.


Ein minimales Pack, von Anfang bis Ende

CREATE TABLE meta(key TEXT, value TEXT);
INSERT INTO meta VALUES
  ('name','Zwei Teams'), ('schema_version','2'),
  ('min_game_version','0.5.4-6'), ('teams_mode','extend');

CREATE TABLE teams(sort INTEGER, id TEXT, name TEXT, country TEXT,
                   budget_tier TEXT, color1 TEXT, color2 TEXT);
INSERT INTO teams VALUES
  (1,'t_alba','Alba Corse','Italy','large','#B3122C','#F2E8D5'),
  (2,'t_nord','Nordwind GP','Germany','medium','#14304F','#C8D3DC');

CREATE TABLE drivers(sort INTEGER, id TEXT, first_name TEXT, last_name TEXT,
                     code TEXT, country TEXT, age INTEGER,
                     pace INTEGER, consistency INTEGER,
                     team_id TEXT, role TEXT);
INSERT INTO drivers VALUES
  (1,'d_ros','Elio','Rossi','ROS','it',27,17,15,'t_alba','primary'),
  (2,'d_ber','Karl','Berger','BER','de',31,15,17,'t_alba','secondary');

Das ist ein vollständiges, gültiges Pack. Alles Nichtgenannte bleibt prozedural.


Die eigene Arbeit prüfen

Fragen Sie das Spiel, was es sieht. Starten Sie es einmal aus einem Terminal mit --list-mods: Es druckt die Ordner, die es durchsucht, in der Reihenfolge, dann jedes gefundene Pack, jede Strecke und jede Sprache. Das ist das Erste, was man ausführt, wenn ein Pack nicht auftaucht.

mod folders (read in this order):
  /home/sie/.local/share/TheUndercut/mods
  /pfad/zum/spiel/mods   (does not exist)
packs:
  my_pack

Lesen Sie die Zeile des Packs in der Auswahl. Dort sagt das Spiel, was es nur halb verstanden hat — ein neueres Format, eine benötigte Spielversion, oder zwei Teams mit demselben Namen, was Bindungen mehrdeutig macht.

Öffnen Sie es einmal im Mod-Editor. Sein Audit-Reiter fängt, was SQL nicht sehen kann: ein leeres zweites Cockpit, ein Fahrer an einem Team, das es nicht gibt, ein doppeltes Kürzel. Ein von Hand geschriebenes Pack zu öffnen stempelt außerdem stabile Ids auf Zeilen, die keine haben — das Beste, was man einem handgeschriebenen Pack antun kann.


Fallen, die man kennen sollte

  • Eine falsch geschriebene Spalte ist stumm. colour1 ist nicht color1; sie wird schlicht nie gelesen. Wenn eine Änderung nichts zu bewirken scheint, prüfen Sie zuerst die Schreibweise gegen diese Seite — PRAGMA table_info(teams) zeigt, was Ihre Tabelle wirklich hat.
  • Bindungen folgen erst id, dann dem Namen. Geben Sie jeder Zeile eine Id, dann behält ein umbenanntes Team seine Fahrer. Ohne Ids wandern die Fahrer beim Umbenennen in den Pool der freien Fahrer.
  • 0 heißt nicht überall „nicht gesetzt”. Bei Potenzialen, Infrastruktur und Bekanntheit heißt es generiertes behalten — aber car_index 0 ist ein echtes Auto: Lassen Sie diese Spalte leer, um das generierte Modell zu behalten.
  • Ein Pack greift nur bei der Karriere-Erstellung. Es zu bearbeiten ändert nichts an einer laufenden Karriere. Fangen Sie eine neue an.
  • Die Datei muss bleiben, wo sie ist. Logos und Fahrzeug-Sprites werden für die gesamte Karriere daraus gelesen.
  • Schreiben Sie Ihre Änderungen. Ein grafischer Browser hält sie in einer offenen Transaktion — schließen ohne Änderungen schreiben, und nichts wurde gespeichert.

Siehe auch