X-SOLUTION
Dokumentation

X-Fuel einrichten

Tanksystem für ESX Legacy mit sieben Kraftstoffsorten, kaufbaren Tankstellen, einem Spritmarkt mit schwankenden Preisen, Tankkarten mit Treueprogramm, Rabattaktionen, einem Nachschub-Auftrag für LKW-Fahrer und Kriminalität rund um die Tankstelle. An jeder Zapfsäule hängt ein Display mit 7-Segment-Ziffern als echte 3D-Fläche in der Welt. Diese Anleitung führt dich vom Download bis zum fertig eingerichteten Server.

Die Oberfläche und die Zapfsäulen-Displays kannst du vorher in der Live-Demo im Browser durchklicken.

Voraussetzungen

  • FiveM Server mit aktuellem Artifact und OneSync
  • es_extended (ESX Legacy)
  • ox_inventory
  • oxmysql
  • MySQL oder MariaDB

Optional:

  • x-hud oder ein anderes Script mit einem notify-Export für Benachrichtigungen. Fehlt es, zeigt X-Fuel eigene Meldungen im gleichen Design.
  • x-dispatch für Polizeialarme bei Spritdiebstahl und Kassenraub. Fehlt es, bekommen Polizisten eine Meldung und einen Blip direkt von X-Fuel.
  • skinchanger, illenium-appearance oder fivem-appearance für die Arbeitskleidung beim Nachschub-Auftrag.

X-Fuel ersetzt andere Tanksysteme. Entferne LegacyFuel, ox_fuel, cdn-fuel, ps-fuel oder rcore_fuel aus deiner server.cfg, bevor du X-Fuel startest. Zwei Tanksysteme gleichzeitig ziehen sich gegenseitig den Tank leer.

Installation

  1. Lade x-fuel aus dem Cfx.re Portal herunter.
  2. Entpacke den Ordner nach resources/[x-solution]/x-fuel. Der Ordnername muss genau x-fuel lauten.
  3. Importiere sql/install.sql in deine Datenbank. Die Datei legt alle Tabellen an und ist wiederholbar ausführbar. X-Fuel prüft die Tabellen beim Start zusätzlich selbst und ergänzt fehlende Spalten automatisch.
  4. Trag die Items in ox_inventory ein (siehe unten).
  5. Trag die Resource in deine server.cfg ein, nach ESX, ox_inventory und oxmysql:
ensure oxmysql
ensure es_extended
ensure ox_inventory
ensure x-fuel
  1. Server neu starten. In der Konsole erscheinen danach unter anderem diese Zeilen, jeweils mit der Uhrzeit davor:
[x-fuel] framework: esx
[x-fuel] inventory: ox_inventory
[x-fuel] Datenbank bereit.
[x-fuel] 28 Tankstellen geladen.
[x-fuel] Spritmarkt aktiv, naechste Berechnung in 15 Minuten.
[x-fuel] Selbsttest SERVER: 8 von 8 Pruefungen bestanden.

Steht beim Selbsttest ein Fehler, sagt die Zeile darunter genau, welche Einstellung nicht passt.

Items in ox_inventory

Öffne ox_inventory/data/items.lua und füge die Einträge aus install/ox_inventory_items.lua ein:

['fuel_pump'] = {
    label = 'Absaugpumpe',
    weight = 4500,
    stack = false,
    close = true,
    description = 'Pumpt Kraftstoff aus einem Fahrzeug in einen Kanister.'
},

['vehicle_manual'] = {
    label = 'Fahrzeughandbuch',
    weight = 400,
    stack = true,
    close = true,
    description = 'Verraet Kraftstoffart und Tankgroesse eines Fahrzeugs.'
},

['fuel_card'] = {
    label = 'Tankkarte',
    weight = 10,
    stack = false,
    close = true,
    description = 'Tanken auf Rechnung, abgerechnet wird am Ende der Periode.'
},

Der Kanister ist die normale GTA-Waffe WEAPON_PETROLCAN, die ox_inventory bereits kennt. Die Bilder für die drei Items legst du wie gewohnt unter ox_inventory/web/images/ ab.

Update auf eine neue Version

Sichere vor dem Update den Ordner config/ und locales/. Ersetze danach den kompletten Resource-Ordner und spiel deine beiden Ordner zurück. Die Datenbank musst du nicht anfassen, fehlende Tabellen und Spalten legt X-Fuel beim Start selbst an.

Kommst du von einer älteren X-Fuel-Version, vergleiche deine alte config/config.lua mit der neuen. Config.Debug ist seit 1.0 eine Tabelle mit Unterbereichen. Ein altes Config.Debug = false funktioniert weiterhin, die neuen Schalter nutzt du aber nur mit der neuen Schreibweise.

Bedienung

Tanken an der Zapfsäule

  1. Stell den Motor ab und geh zur Zapfsäule. Über der Säule erscheint das Display mit allen Sorten, Preisen und dem Lagerbestand der Tankstelle.
  2. Q wechselt die Kraftstoffsorte, E nimmt die Zapfpistole. Ein Schlauch verbindet Pistole und Säule.
  3. Geh zur Tankklappe des Fahrzeugs und drück E. Das Display schaltet auf Menge und Betrag um und zählt live mit.
  4. E beendet den Vorgang, X hängt die Pistole zurück. Entfernst du dich weiter als die Schlauchlänge, reißt der Schlauch.
  5. Nach dem Tanken öffnet sich die Bezahlung mit Karte, Bargeld oder Tankkarte. Rabatte aus Aktionen und deiner Treuestufe sind bereits abgezogen, Treuepunkte lassen sich direkt einlösen.

Flugzeuge, Hubschrauber und Boote betankst du an jeder Stelle ihrer Außenhülle, nicht nur an einem festen Punkt.

Falscher Kraftstoff

Passt der Stecker nicht, zum Beispiel Strom in einen Benziner, blockt die Säule sofort. Bei verwandten Sorten wie Diesel in einen Benziner lässt sich tanken, der Motor läuft danach aber unrund, qualmt und geht nach der eingestellten Strecke kaputt. Im Adminmenü lässt sich falscher Sprit wieder entfernen.

Kanister, Absaugpumpe und Handbuch

  • Kanister: Mit gezogenem Kanister an der Zapfsäule E drücken füllt ihn zum aktuellen Preis. Mit gezogenem Kanister am Fahrzeug E drücken füllt den Tank.
  • Absaugpumpe: Benutzen am eigenen Fahrzeug pumpt Sprit in deinen Kanister. An fremden Fahrzeugen wird daraus ein Diebstahl (siehe unten).
  • Fahrzeughandbuch: Benutzen neben einem Fahrzeug blendet für zwölf Sekunden ein Display mit Sorte, Tankgröße, Inhalt und Reichweite über dem Auto ein.

Tankkarten und Treuepunkte

Mit /tankkarte oder durch Benutzen des Items fuel_card öffnest du die Kartenverwaltung. Dort stellst du Karten aus, setzt Limits, sperrst verlorene Karten und begleichst offene Beträge. Als Chef einer Firma kannst du beim Ausstellen „Über meine Firma abrechnen" wählen. Dann zahlt das Firmenkonto am Ende der Abrechnungsperiode.

Jeder Tankvorgang bringt Treuepunkte. Ab bestimmten Punkteständen steigst du in eine höhere Stufe auf und bekommst dauerhaft Rabatt auf jeden Liter. Punkte lassen sich beim Bezahlen gegen Geld einlösen.

Tankstelle kaufen und verwalten

Tankstellen, die zum Verkauf stehen, haben einen grünen Marker. E öffnet das Kaufangebot mit Preis, passivem Einkommen und aktuellem Lagerbestand. Nach dem Kauf wird der Marker blau und öffnet die Verwaltung mit fünf Reitern:

Reiter Inhalt
Übersicht Kasse, Einkommen, Umsatz und Gewinn der letzten sieben Tage, Öffnen und Schließen, Nur-Mitarbeiter-Modus, Geld abheben und einzahlen
Preise Preis je Sorte mit Marktpreis, Trend und deiner Marge. Optional folgen die Preise automatisch dem Markt
Lager Füllstand je Sorte und Nachschub-Einkauf aus der Kasse
Aktionen Rabattaktionen wie Happy Hour starten und beenden
Statistik Umsatz je Tag als Diagramm, Umsatz je Sorte, Einkaufskosten, Kundschaft und die letzten Buchungen

Jeder Verkauf landet in der Kasse der Tankstelle. Verkaufst du die Tankstelle, bekommst du einen Teil des Kaufpreises zurück.

Tankstellen-Shop

Der weiße Marker im Verkaufsraum öffnet den Shop mit Kanister, Absaugpumpe, Handbuch und Reparaturkit. Ein Teil jedes Shop-Verkaufs geht an den Besitzer.

Nachschub-Auftrag

An der Raffinerie (Blip „Raffinerie") startest du mit E einen Auftrag:

  1. Arbeitskleidung anziehen.
  2. Leere Fässer holen und an der Pumpe befüllen.
  3. Fässer auf den Kipper laden, bis zu vier Stück.
  4. Zu einer Tankstelle mit Tankanschluss fahren und den Kraftstoff in den Lagertank pumpen.
  5. Den Kipper zurückbringen und die Bezahlung abholen.

Der Lohn richtet sich nach den gelieferten Litern plus einem Bonus je Fass.

Sprit abzapfen

Wer eine Absaugpumpe und einen Kanister dabei hat, kann an fremden, abgestellten Fahrzeugen Sprit abzapfen. Nach einem kurzen Geschicklichkeitsspiel läuft der Sprit in den Kanister. Mit etwas Pech springt der Autoalarm an, und die Polizei bekommt je nach Zufall einen Hinweis. Fahrzeuge, die du in dieser Sitzung selbst gefahren hast, zählen als eigene.

Gestohlenen Sprit verkaufst du bei einem der Hehler (rote Marker). Verkauft wird höchstens so viel, wie wirklich gestohlen wurde und noch im Kanister ist.

Kassenraub

Mit gezogener Waffe an der Kasse einer Tankstelle erscheint E zum Aufbrechen. Nach zwei Geschicklichkeitsspielen und einer Wartezeit gibt es einen Anteil der Stationskasse als Bargeld. Kurz nach dem Start läutet die Alarmglocke und die Polizei wird alarmiert. Der Besitzer bekommt eine Nachricht über den Verlust. Besitzer können ihre eigene Tankstelle nicht ausrauben.

Befehle

Befehl Wer Wirkung
/fueladmin Admins Öffnet das Adminmenü. Auch als Taste belegbar unter Einstellungen → Tastenbelegung → FiveM
/fuel Admins Öffnet ebenfalls das Adminmenü
/fuel reset <id> Admins, Konsole Setzt eine Tankstelle auf den Stand aus der Config zurück
/fuel restock Admins, Konsole Füllt alle Tankstellen komplett auf
/fuelstations Admins, Konsole Listet alle Tankstellen mit Besitzer und Kasse in der Konsole
/fuelperm Alle Zeigt deine erkannte Gruppe und ob du Adminzugriff hast
/fueldebug Admins Schaltet das Debug-Overlay und alle Debug-Bereiche ein oder aus
/fueldebug <bereich> Admins Schaltet einen einzelnen Debug-Bereich, zum Beispiel /fueldebug pump
/fueldebug aus Admins Schaltet Overlay und alle Bereiche aus
fueldebug test Konsole Führt den Selbsttest erneut aus
/fuelpanel Alle Gibt die Panel-Werte und alle sichtbaren Panels in der F8-Konsole aus
/fuelpanel screen oder world Alle Schaltet lokal zwischen 3D-Panel und Bildschirmanzeige um
/fuelpanel reset Alle Setzt die lokale Panel-Feinjustierung zurück
/tankkarte Alle Öffnet die Tankkarten

Alle Befehlsnamen änderst du unter Config.Commands.

Wichtige Einstellungen

Alle Einstellungen liegen im Ordner config/. Die Dateien sind nicht verschlüsselt und lassen sich frei bearbeiten.

Datei Inhalt
config.lua Debug, Sprache, Tasten, Panels, Bezahlung, Tankstellen-Grundregeln, Befehle, Adminrechte
fuel.lua Kraftstoffsorten, Tankgrößen, Verbrauch, falscher Sprit, Kanister, Absaugpumpe, Handbuch
dispensers.lua Zapfsäulen-Modelle, Schlauch- und Panelpositionen, Tankklappen, E-Ladesäulen
stations.lua Alle Tankstellen mit Positionen und Standardwerten, Marker
market.lua Spritmarkt und Marktereignisse
loyalty.lua Treueprogramm, Tankkarten, Rabattaktionen
crime.lua Sprit abzapfen, Kassenraub, Polizeialarm
mission.lua Nachschub-Auftrag
shop.lua Shop-Sortiment

Sprache und Benachrichtigungen

Config.Locale = 'de'

Config.Notify = {
    export = 'x-hud',
    builtIn = true,
    duration = 4000
}
  • Config.Locale wählt de oder en. Die Texte liegen in locales/de.lua und locales/en.lua. Platzhalter wie %s müssen beim Ändern stehen bleiben.
  • export ist die Resource, deren notify-Export X-Fuel zuerst benutzt. Läuft sie nicht, greift builtIn.
  • builtIn = true zeigt eigene Meldungen im X-Fuel-Design oben rechts. Bei false gehen Meldungen an die ESX-Benachrichtigung.

Debug und Selbsttest

Config.Debug = {
    enabled = false,
    selfTest = true,
    overlay = false,
    timestamps = true,

    pump = false,
    panels = false,
    consumption = false,
    stations = false,
    market = false,
    loyalty = false,
    crime = false,
    mission = false,
    network = false,
    database = false,
    ui = false
}
  • enabled ist der Hauptschalter. Ohne ihn bleibt jeder Bereich stumm.
  • selfTest prüft beim Start auf Server und Client die Config auf Widersprüche: fehlende Kraftstoffsorten, Tankstellen ohne Position, unbekannte Sorten an Zapfsäulen, falsche Markt- und Treuegrenzen, unpassende Panelwerte, fehlende Übersetzungen. Das Ergebnis steht in der Konsole und im Adminmenü.
  • overlay blendet das Debug-Overlay für Admins direkt beim Einloggen ein.
  • timestamps stellt jeder Zeile die Uhrzeit voran.

Jeder Bereich schreibt eigene, mit [bereich] markierte Zeilen in die Konsole:

Bereich Was du siehst
pump Nächste Zapfsäule, Zapfpistole genommen, Tanken gestartet und beendet mit Grund, Menge und Dauer
panels Panels erstellt, entfernt, sichtbar oder versteckt, Instanzlimit erreicht
consumption Alle zehn Sekunden Verbrauch, Geschwindigkeit, Untergrund und Wetterzuschlag des gefahrenen Autos
stations Tankstellen empfangen und aktualisiert, Statistiken berechnet
market Marktberechnung, Ereignisse, empfangene Marktpreise
loyalty Treuepunkte geladen, vergeben und eingelöst, Tankkarten belastet, Aktionen gestartet
crime Abzapfen, Autoalarm, Kassenraub, Alarme an die Polizei
mission Jeder Schritt des Nachschub-Auftrags
network Jeder Callback zwischen Client und Server mit Antwortzeit
database Speichern von Tankstellen, Fahrzeugen und Buchungen
ui Geöffnete und geschlossene Oberflächen, gesendete NUI-Nachrichten. Zusätzlich loggt die Oberfläche jede Nachricht in der F8-Konsole

Unabhängig vom Schalter meldet X-Fuel immer, wenn ein Callback nicht antwortet oder ein unbekannter Callback eintrifft.

Im Spiel schaltest du dasselbe mit /fueldebug oder im Adminmenü unter Debug. Das Overlay oben links zeigt dann live FPS, sichtbare Panels, nächste Tankstelle, Zustand der Zapfpistole, Tank und Sorte des Fahrzeugs, den Marktpreis und die Werte vom Server. Änderungen im Spiel gelten bis zum nächsten Neustart, dauerhaft stellst du sie in der Config ein.

Tasten und Reichweiten

Config.Keys = {
    interact = 38,
    interactLabel = 'E',
    switch = 44,
    switchLabel = 'Q',
    drop = 73,
    dropLabel = 'X',
    cancel = 194,
    cancelLabel = 'BACKSPACE'
}

Die Zahlen sind GTA-Control-IDs, die Label stehen auf den Displays und in den Hinweisen. Änderst du eine Taste, änder das passende Label mit.

Config.Interaction = {
    pumpDistance = 3.2,
    nozzleDistance = 2.4,
    largeVehicleDistance = 4.5,
    largeVehicleTypes = { 'plane', 'heli', 'boat', 'train' },
    ropeLength = 13.0,
    markerDistance = 40.0,
    objectDistance = 140.0
}
  • pumpDistance ist der Abstand, ab dem die Zapfsäule reagiert.
  • nozzleDistance und largeVehicleDistance sind die Reichweiten zum Tank bei normalen und großen Fahrzeugen.
  • ropeLength ist die Schlauchlänge. Weiter weg reißt der Schlauch.
  • markerDistance ist die Sichtweite der Marker für Kauf, Verwaltung und Shop.
  • objectDistance ist die Entfernung, ab der im Adminmenü platzierte Zapfsäulen erscheinen.

Weltpanels

Config.Panels = {
    enabled = true,
    mode = 'world',
    debug = false,
    screenScale = 0.5,
    width = 768,
    height = 384,
    worldWidth = 0.85,
    worldHeight = 0.425,
    drawDistance = 9.0,
    fadeDistance = 12.0,
    doubleSided = true,
    maxInstances = 4
}
  • mode = 'world' zeichnet das Display als 3D-Fläche direkt an der Säule. 'screen' zeigt es stattdessen als Bildschirmanzeige über der Säule.
  • width und height sind die Auflösung des Displays in Pixeln, worldWidth und worldHeight seine Größe in Metern.
  • drawDistance ist die volle Sichtweite, bis fadeDistance blendet es aus.
  • doubleSided macht das Display von beiden Seiten lesbar.
  • maxInstances begrenzt, wie viele Displays gleichzeitig existieren. Jedes Display ist eine eigene Browser-Instanz, höhere Werte kosten Leistung.
  • debug zeichnet einen roten Punkt in die Mitte jedes Displays.

Größe, Drehung und Versatz stellst du bequemer im Adminmenü unter System ein. Die Regler wirken sofort, gespeichert wird erst mit „Einstellungen speichern".

Kraftstoffsorten

In config/fuel.lua stehen sieben Sorten: Benzin, Diesel, Strom, Autogas, Erdgas, Kerosin und Milch.

[FuelType.PETROL] = {
    label = 'Benzin',
    unit = 'L',
    color = '#376ceb',
    icon = 'nozzle',
    liquid = true,
    jerrycan = true,
    basePrice = 32,
    flowRate = 60
},
  • basePrice ist der Grundpreis je Einheit. Der Spritmarkt bewegt den tatsächlichen Preis um diesen Wert herum.
  • flowRate ist die Menge je Minute beim Tanken.
  • color färbt Displays, Diagramme und Menüs. Die mitgelieferten Farben sind so abgestimmt, dass sie sich auch bei Farbsehschwäche unterscheiden.

Welche Sorte ein Fahrzeug braucht, bestimmen der Reihe nach Config.FuelTypeByModel, Config.FuelTypeByVehicleType, Config.FuelTypeByClass und zuletzt Config.DefaultFuelTypes. Einzelne Modelle schaltest du mit Config.DisabledModels ganz aus.

Tankgrößen und Verbrauch

  • Config.TankSizeByModel, Config.TankSizeByFuelType und Config.TankSizeByClass legen die Tankgröße fest, in dieser Reihenfolge.
  • Config.Consumption bestimmt den Verbrauch je 100 km zwischen min und max, abhängig von Geschwindigkeit, Untergrund (terrain), Modell und Sorte. Über speedIncrease steigt der Verbrauch zusätzlich.
  • Config.ClassModifier und Config.ClassModifierPerFuelType multiplizieren den Verbrauch je Fahrzeugklasse.
  • Config.WeatherConsumption addiert bei Regen oder Schnee einen Zuschlag.
  • Config.ReverseConsumptionClasses dreht die Kurve für Supersportwagen um: sie verbrauchen bei hoher Geschwindigkeit mehr statt weniger.
  • Config.EngineStopOnEmpty = true stellt den Motor bei leerem Tank ab. Bei E-Autos greift das schon bei dem Wert aus Config.EngineCutoff.
  • Config.RefuelWithEngineOn = false verlangt, dass der Motor beim Tanken aus ist.

Falscher Kraftstoff

Config.WrongFuel = {
    enabled = true,
    blockAtPump = true,
    failureDistance = 100.0,
    smokeEffect = true,
    engineHealthLoss = 250.0
}
  • blockAtPump verhindert an der Säule alle Kombinationen aus Config.IncompatibleNozzles.
  • failureDistance ist die Strecke in Metern, nach der der Motor ausfällt.
  • engineHealthLoss ist der Schaden am Motor beim Ausfall.

Tankstellen

Config.Stations = {
    enableBuying = true,
    maxPerPlayer = 2,
    minPrice = 100000,
    sellRefund = 0.65,
    passiveIncome = true,
    passiveIncomeMinutes = 60,
    automaticRestock = true,
    automaticRestockTax = 0.1,
    minPricePerUnit = 5,
    maxPricePerUnit = 500
}
  • maxPerPlayer begrenzt, wie viele Tankstellen ein Spieler besitzen darf.
  • sellRefund = 0.65 erstattet beim Verkauf 65 Prozent des Kaufpreises.
  • passiveIncome zahlt alle passiveIncomeMinutes das hourlyIncome der Tankstelle in die Kasse, solange sie geöffnet ist.
  • automaticRestock erlaubt Besitzern den Einkauf von Nachschub aus der Kasse. Der Preis ist der Marktpreis plus automaticRestockTax. Bei false füllt nur der Nachschub-Auftrag das Lager.
  • minPricePerUnit und maxPricePerUnit begrenzen, welche Preise Besitzer setzen dürfen.

Die 28 mitgelieferten Tankstellen stehen in Config.StationList in config/stations.lua. Jede Tankstelle erbt alle Werte aus Config.StationDefaults und überschreibt nur, was sie selbst angibt:

['ls_strawberry'] = {
    label = 'Xero Strawberry',
    position = vec3(265.64, -1261.30, 29.29),
    boss = vec3(273.15, -1258.42, 29.29),
    shopPosition = vec3(287.35, -1270.94, 29.44),
    tanker = { pos = vec3(281.03, -1252.62, 29.14), heading = 90.0 },
    price = 520000,
    fuelTypes = { FuelType.PETROL, FuelType.DIESEL, FuelType.EV }
},
  • position ist die Mitte, radius aus den Defaults der Bereich der Tankstelle.
  • boss ist der Marker für Kauf und Verwaltung, shopPosition der Shop und gleichzeitig die Kasse für Überfälle.
  • tanker ist der Anschluss für den Nachschub-Auftrag. Stationen ohne tanker bekommen keinen Nachschub per Auftrag.
  • society und job aus den Defaults binden eine Tankstelle an eine Firma. Mit society gehen Einnahmen auf das Firmenkonto statt in die Kasse, mit job gilt der Nur-Mitarbeiter-Modus für diesen Job.

Neue Tankstellen legst du ohne Neustart im Adminmenü an. Sie landen in der Datenbank und überschreiben gleichnamige Einträge aus der Config.

Config.Blips steuert Symbol, Größe und Farbe der Kartenmarkierungen, ownedColor ist die Farbe verkaufter Tankstellen. Config.StationMarkers legt Form und Farbe der Bodenmarker fest.

Spritmarkt

Config.Market = {
    enabled = true,
    tickMinutes = 15,
    historyPoints = 48,
    broadcast = true,
    drift = 0.035,
    meanReversion = 0.25,
    stockInfluence = 0.30,
    stockPivot = 0.55,
    ...
}

Alle tickMinutes berechnet der Server für jede Sorte einen Marktfaktor, mit dem der Grundpreis multipliziert wird:

  • drift ist die zufällige Schwankung je Berechnung.
  • meanReversion zieht den Faktor zurück zum Normalwert, damit die Preise nicht davonlaufen.
  • stockInfluence und stockPivot verteuern Sprit, wenn die Lager im Schnitt aller Tankstellen unter stockPivot gefüllt sind, und verbilligen ihn bei vollen Lagern.
  • hourly gibt je Uhrzeit einen Zu- oder Abschlag vor, zum Beispiel teurer im Berufsverkehr und günstiger nachts. Maßgeblich ist die Serverzeit.
  • bounds begrenzt den Faktor je Sorte, zum Beispiel min = 0.72, max = 1.45 für Benzin.
  • historyPoints ist die Länge des Preisverlaufs im Adminmenü.

Unter events stehen Marktereignisse wie Raffineriebrand, Tanker eingetroffen, Netzüberlastung oder Preisdeckel. Bei jeder Berechnung startet mit der Wahrscheinlichkeit chance ein zufälliges Ereignis für minMinutes bis maxMinutes. Es verändert die Preise der angegebenen types um impact und erscheint als Banner auf den Zapfsäulen-Displays. weight macht ein Ereignis häufiger.

stationPricing = {
    autoFollow = true,
    followSpeed = 0.6,
    ownerMargin = { min = -0.15, max = 0.35 }
}
  • autoFollow lässt die Preise aller Tankstellen dem Markt folgen. Besitzer können das je Tankstelle abschalten.
  • followSpeed ist der Anteil, um den sich der Preis je Berechnung dem Ziel nähert.
  • ownerMargin begrenzt den Auf- oder Abschlag, den ein Besitzer beim automatischen Folgen behält.

Im Adminmenü unter Markt siehst du den Verlauf je Sorte, verschiebst Faktoren von Hand, löst Ereignisse aus und rechnest sofort neu.

Treueprogramm

Config.Loyalty = {
    enabled = true,
    pointsPerCurrency = 0.02,
    pointsPerLiter = 0.5,
    roundPoints = true,
    redeemEnabled = true,
    redeemRate = 0.75,
    redeemMinPoints = 250,
    tiers = {
        { id = 'basic', label = 'Basis', points = 0, discount = 0.0, color = '#8b97ad' },
        { id = 'silver', label = 'Silber', points = 2500, discount = 0.02, color = '#c6d0e0' },
        { id = 'gold', label = 'Gold', points = 9000, discount = 0.04, color = '#f2c14e' },
        { id = 'platinum', label = 'Platin', points = 25000, discount = 0.07, color = '#7fe3ff' }
    }
}
  • Je Kauf gibt es pointsPerCurrency Punkte je Dollar plus pointsPerLiter Punkte je Liter. Bei 1.000 $ und 40 Litern sind das 40 Punkte.
  • redeemRate = 0.75 bedeutet: 100 Punkte sind 75 $ wert. Einlösen geht ab redeemMinPoints.
  • tiers sind die Stufen. points muss von oben nach unten steigen, discount ist der Rabatt auf jeden Kauf.

Eingelöste Punkte zahlt das Treueprogramm, die Kasse der Tankstelle bekommt trotzdem den vollen Betrag.

Tankkarten

Config.Cards = {
    enabled = true,
    item = 'fuel_card',
    requireItem = false,
    maxPerPlayer = 3,
    issueCost = 2500,
    defaultLimit = 25000,
    minLimit = 1000,
    maxLimit = 500000,
    periodHours = 168,
    settleAutomatic = true,
    lateFeePercent = 0.05,
    allowCompany = true,
    companyGrades = { 'boss' },
    companyExcludedJobs = { 'unemployed' },
    companySocietyPrefix = 'society_',
    blockOnLimit = true,
    fuelTypes = { ... }
}
  • requireItem = true gibt beim Ausstellen zusätzlich das Item fuel_card ins Inventar.
  • issueCost wird beim Ausstellen vom Bankkonto abgebucht.
  • periodHours ist die Abrechnungsperiode in Echtzeitstunden, 168 sind eine Woche.
  • settleAutomatic bucht bei Firmenkarten am Periodenende vom Firmenkonto ab. Reicht das Geld nicht, oder ist die Karte privat, kommt lateFeePercent als Säumniszuschlag drauf und der Betrag bleibt offen.
  • allowCompany erlaubt Firmenkarten. Ausstellen darf sie nur, wer in seinem Job einen Rang aus companyGrades hat. Abgerechnet wird immer über das Konto companySocietyPrefix plus Jobname der eigenen Firma, zum Beispiel society_mechanic. Jobs aus companyExcludedJobs bekommen keine Firmenkarte. Ist companyGrades leer, darf jeder Mitarbeiter Firmenkarten ausstellen.
  • blockOnLimit lehnt Zahlungen ab, die das Restlimit überschreiten.
  • fuelTypes legt fest, welche Sorten mit Karte bezahlt werden dürfen. Milch ist standardmäßig ausgenommen.

Config.Payment.allowCard blendet die Tankkarte in der Bezahlung ein oder aus.

Rabattaktionen

Config.Promotions = {
    enabled = true,
    maxPerStation = 2,
    maxDiscount = 0.35,
    maxHours = 12,
    presets = {
        { id = 'happy_hour', label = 'Happy Hour', discount = 0.10, hours = 2 },
        { id = 'night_deal', label = 'Nachtrabatt', discount = 0.15, hours = 6 },
        { id = 'weekend', label = 'Wochenendaktion', discount = 0.08, hours = 12 }
    }
}

Besitzer starten die Vorlagen aus presets in der Verwaltung. maxDiscount und maxHours begrenzen jede Aktion zusätzlich, egal was in den Vorlagen steht. Laufende Aktionen überstehen einen Neustart und erscheinen als Banner auf den Displays der Tankstelle. Den Rabatt trägt der Besitzer.

Bezahlung und Steuern

Config.Payment = {
    allowCash = true,
    allowBank = true,
    allowCard = true,
    defaultMethod = 'bank',
    showModal = true
}

Config.Society = {
    enabled = true,
    taxEnabled = false,
    taxPercent = 0.2,
    taxSociety = 'society_government'
}
  • showModal = false überspringt die Bezahlung und bucht direkt mit defaultMethod ab.
  • Mit taxEnabled geht taxPercent jedes Verkaufs an das Firmenkonto taxSociety.

Kanister, Absaugpumpe und Handbuch

In config/fuel.lua:

  • Config.Jerrycan: size ist das Fassungsvermögen in Litern, fillTime die Füllzeit an der Säule, allowedTypes die Sorten, die in einen Kanister dürfen.
  • Config.FuelPumper: maxLiters je Vorgang und duration für das Abpumpen aus dem eigenen Fahrzeug.
  • Config.VehicleManual: Lesedauer und Animation.

Config.Shop in config/shop.lua legt Sortiment und Preise im Tankstellen-Shop fest.

Nachschub-Auftrag

In config/mission.lua:

  • requireJob und job beschränken den Auftrag auf einen Job.
  • start ist der Startpunkt, blip seine Kartenmarkierung.
  • outfitEnabled und outfitSkin legen die Arbeitskleidung fest.
  • truck bestimmt Modell, Spawnpunkt und Rückgabe des Fahrzeugs.
  • barrel enthält Abhol- und Füllpunkt, litersPerBarrel, fillTime und maxBarrels.
  • transfer bestimmt, wie schnell der Sprit in den Lagertank läuft.
  • payPerLiter und bonusPerBarrel ergeben den Lohn.

Sprit abzapfen und Kassenraub

Config.Crime = {
    enabled = true,

    dispatch = {
        resource = 'x-dispatch',
        siphonType = 'vehicle_theft',
        robberyType = 'store_robbery',
        siphonCode = '10-31',
        robberyCode = '10-90',
        jobs = { 'police', 'sheriff' },
        blipTime = 180
    },
    ...
}
  • dispatch.resource ist das Dispatch-Script. Mit x-dispatch legt X-Fuel einen Einsatz vom Typ siphonType oder robberyType an. Diese Typen müssen in der Config von x-dispatch existieren. Läuft kein Dispatch-Script, bekommen alle Spieler aus jobs eine Meldung mit dem Code und einen Blip für blipTime Sekunden.

Beim Abzapfen (siphon):

  • requireItem und item verlangen die Absaugpumpe.
  • minPlayers ist die Mindestzahl an Polizisten im Dienst.
  • cooldownMinutes gilt je Spieler, vehicleCooldownMinutes je Kennzeichen.
  • maxLiters ist die Höchstmenge je Vorgang.
  • skipOwnVehicle behandelt selbst gefahrene Fahrzeuge als eigene.
  • engineMustBeOff verlangt einen abgestellten Motor.
  • alarmChance ist die Chance auf den Autoalarm, alertChance die Chance, dass die Polizei alarmiert wird.
  • minigame legt Runden, Zeit je Runde, Größe der Trefferzone und Geschwindigkeit fest.
  • sellPricePerLiter und sellPositions bestimmen Preis und Standorte der Hehler.

Beim Kassenraub (robbery):

  • requireWeapon verlangt eine gezogene Waffe. Das prüft auch der Server.
  • requireItem und item verlangen zusätzlich ein Werkzeug, removeItemChance ist die Chance, dass es dabei kaputtgeht.
  • minPolice ist die Mindestzahl an Polizisten im Dienst.
  • minBalance ist der Mindestbetrag in der Kasse, damit sich ein Raub lohnt.
  • lootPercent und maxLoot bestimmen die Beute: 65 Prozent der Kasse, höchstens 60.000 $.
  • cooldownMinutes gilt je Tankstelle, globalCooldownMinutes für alle Tankstellen zusammen.
  • duration ist die Dauer nach den Geschicklichkeitsspielen, alertDelay die Zeit bis zum Polizeialarm.
  • alarmSound lässt eine Alarmglocke für alle Spieler im Umkreis läuten.
  • payoutItem zahlt die Beute als Item aus, zum Beispiel black_money. Bei nil gibt es Bargeld.

Adminrechte

Config.AdminGroups = { 'admin', 'superadmin', 'god', 'owner' }
Config.AdminIdentifiers = {}

Zugriff aufs Adminmenü hat, wer eine dieser Bedingungen erfüllt:

  • ESX-Gruppe aus Config.AdminGroups
  • ACE-Recht xfuel.admin oder command.fueladmin
  • Identifier aus Config.AdminIdentifiers, zum Beispiel 'char1:abc123'

Per ACE in der server.cfg:

add_ace group.admin xfuel.admin allow

Adminmenü

/fueladmin öffnet das Menü mit sieben Bereichen:

Bereich Funktion
Fahrzeug Tankstand und Sorte des nächsten Fahrzeugs setzen, falschen Sprit entfernen, reparieren
Tankstellen Tankstellen anlegen, bearbeiten und löschen. Positionen per „Hierher" aus deiner Position übernehmen, per „Hin" teleportieren. Auffüllen, Besitzer zuweisen oder entfernen, zurücksetzen, Preise je Sorte
Grundpreise Grundpreise je Sorte setzen und optional auf alle Tankstellen übertragen
Markt Preisverlauf je Sorte, Marktfaktor von Hand setzen, Ereignis auslösen oder beenden, sofort neu berechnen
Objekte Zusätzliche Zapfsäulen und Ladesäulen platzieren. Pfeiltasten drehen, Mausrad ändert den Abstand, Bild auf und ab die Höhe, Enter setzt, Backspace bricht ab
System Größe, Sichtweite, Drehung und Versatz der Displays sowie die Haltung der Zapfpistole live einstellen
Debug Debug-Bereiche schalten, Selbsttest erneut ausführen, Werte von Client und Server

Für Entwickler

Client-Exports

local fuel = exports['x-fuel']:GetFuel(vehicle)
exports['x-fuel']:SetFuel(vehicle, 75.0)

local fuelType = exports['x-fuel']:GetFuelType(vehicle)
exports['x-fuel']:SetFuelType(vehicle, 'diesel')

local capacity = exports['x-fuel']:GetCapacity(vehicle)
local liters = exports['x-fuel']:GetLiters(vehicle)
local wrong = exports['x-fuel']:IsWrongFuel(vehicle)

GetFuel und SetFuel arbeiten wie bei LegacyFuel in Prozent von 0 bis 100. Garagen-, HUD- und Autohaus-Scripts, die LegacyFuel oder den Fahrzeug-Tankstand nutzen, funktionieren damit ohne Anpassung.

Server-Exports

exports['x-fuel']:GetVehicleFuel(plate)
exports['x-fuel']:SetVehicleFuel(plate, fuel, fuelType)

exports['x-fuel']:GetStationState(stationId)
exports['x-fuel']:GetStationStats(stationId)
exports['x-fuel']:GetStationPromotion(stationId, fuelType)

exports['x-fuel']:GetMarketPrice(fuelType)
exports['x-fuel']:GetMarketFactor(fuelType)

exports['x-fuel']:GetLoyaltyPoints(identifier)
exports['x-fuel']:AddLoyaltyPoints(identifier, amount)

exports['x-fuel']:IsRobberyActive(stationId)
exports['x-fuel']:GetActiveMission(source)

State Bags

Jedes Fahrzeug trägt drei State Bags, die für alle Spieler synchron sind:

Schlüssel Inhalt
fuel Tankstand in Prozent
fuelType Kraftstoffsorte, zum Beispiel petrol
wrongFuel true, wenn falscher Sprit im Tank ist

Der Server speichert Änderungen nach Kennzeichen in x_fuel_vehicles, alle Config.Sync.saveMinutes Minuten und beim Stoppen der Resource.

Datenbank

Tabelle Inhalt
x_fuel_vehicles Tankstand, Sorte und falscher Sprit je Kennzeichen
x_fuel_stations Besitzer, Kasse, Preise, Lager, Öffnungsstatus und Marktfolge je Tankstelle
x_fuel_places Im Adminmenü angelegte oder geänderte Tankstellen
x_fuel_objects Platzierte Zapfsäulen und Ladesäulen
x_fuel_settings Panel- und Pistolen-Einstellungen, Grundpreise, Marktzustand
x_fuel_logs Alle Buchungen, Grundlage der Statistik
x_fuel_cards Tankkarten mit Limit, offenem Betrag und Firma
x_fuel_loyalty Treuepunkte
x_fuel_promotions Laufende Rabattaktionen

Häufige Fragen

Das Display an der Zapfsäule ist nicht zu sehen

Stell dich direkt vor eine Zapfsäule und gib /fuelpanel ein. Die F8-Konsole zeigt, wie viele Panels existieren, ob sie sichtbar sind und wo sie stehen. Steht dort kein einziges Panel, ist das Modell der Säule nicht in Config.Dispensers eingetragen. Steht es dort, liegt es aber unsichtbar, dreh es im Adminmenü unter System oder teste mit /fuelpanel screen, ob die Bildschirmanzeige erscheint.

Beim Start meldet der Selbsttest Fehler

Die Zeile nennt die betroffene Einstellung. Typisch sind eine Tankstelle mit einer Sorte, die es in Config.FuelTypes nicht gibt, oder eine Treuestufe, deren Punkte nicht steigen. Nach der Korrektur reicht restart x-fuel.

Das Adminmenü öffnet sich nicht

Gib /fuelperm ein. Die Meldung zeigt deine erkannte Gruppe. Steht sie nicht in Config.AdminGroups, trag sie ein oder vergib das ACE-Recht xfuel.admin. Die Serverkonsole schreibt bei jedem abgelehnten Versuch zusätzlich eine Warnung mit Name und Gruppe.

Fahrzeuge verlieren beim Ausparken ihren Tankstand

Der Tankstand hängt am Kennzeichen. Prüfe, ob dein Garagen-Script das Kennzeichen beim Spawnen exakt so setzt wie beim Einparken. Läuft außerdem noch ein zweites Tanksystem, setzt es den Tank beim Spawnen zurück.

Der Tank leert sich doppelt so schnell

Ein zweites Tanksystem läuft parallel. Entferne es aus der server.cfg.

Die Preise ändern sich nie

Prüfe Config.Market.enabled. Die erste Berechnung passiert erst nach tickMinutes. Im Adminmenü unter Markt löst „Jetzt neu rechnen" sofort eine aus. Hat ein Besitzer „Preise dem Markt folgen lassen" abgeschaltet, bleiben die Preise dieser Tankstelle fest.

Die Preise schwanken zu stark

Senk drift und erhöh meanReversion. Engere bounds begrenzen die Spanne zusätzlich.

Kassenraub startet nicht

Du brauchst eine gezogene Waffe, es müssen mindestens minPolice Polizisten im Dienst sein, und in der Kasse müssen mindestens minBalance Dollar liegen. Danach greifen die Cooldowns je Tankstelle und für alle Tankstellen zusammen. Die genaue Ablehnung steht jeweils in der Meldung.

Die Polizei bekommt keinen Alarm

Läuft x-dispatch, müssen siphonType und robberyType als Alarmtypen in dessen Config existieren. Ohne Dispatch-Script bekommen nur Spieler mit einem Job aus Config.Crime.dispatch.jobs die Meldung.

Beim Tanken passiert nach „Tanken starten" nichts

Stell den Motor ab, oder setz Config.RefuelWithEngineOn = true. Ist die Tankstelle geschlossen, im Nur-Mitarbeiter-Modus oder ist das Lager der gewählten Sorte leer, steht das in der Meldung.

Ein Callback antwortet nicht

Steht in der F8-Konsole „Callback … hat nach 8 Sekunden nicht geantwortet", läuft der Server-Teil nicht oder ist abgestürzt. Prüf die Serverkonsole auf Fehler von x-fuel und oxmysql.

Ich will genau sehen, was beim Tanken passiert

Aktiviere im Adminmenü unter Debug die Bereiche pump, network und database, oder gib /fueldebug pump ein. Jeder Schritt steht dann mit Uhrzeit in der Konsole.

Ich hätte die Texte gern auf Englisch

Setz Config.Locale = 'en'. Die Oberfläche der Menüs bleibt deutsch, alle Meldungen und Hinweise wechseln auf Englisch.

Nach einem Update sind meine Einstellungen weg

Der Ordner config/ liegt im Resource-Ordner. Wird der Ordner beim Update komplett ersetzt, sind auch deine Anpassungen weg. Sichere config/ und locales/ vorher und spiel sie danach zurück.

Support

Kommst du nicht weiter, melde dich auf Discord. Halte bitte die Serverkonsole vom Start mit der Selbsttest-Zeile, deine X-Fuel-Version und den betroffenen Abschnitt aus dem Ordner config/ bereit. Mit /fueldebug und dem passenden Bereich lässt sich fast jedes Problem direkt eingrenzen.

Etwas unklar geblieben?

Schreib uns auf Discord, wir ergänzen die Anleitung.

Discord
X-Fuel einrichten — Dokumentation · X-Solution