X-SOLUTION
Dokumentation

X-Banking einrichten

Vollständiges Bankensystem für ESX Legacy: Konto mit IBAN, Sparkonto mit Zinsen, Festgeld und Sparzielen, Kredite mit Bonitätsprüfung, Aktienmarkt, Rechnungen, Firmenkonten, Justiz-Zugriff und ein nachgebauter Geldautomat. Diese Anleitung führt dich vom Download bis zum eingerichteten Server.

Die Oberfläche kannst du vorher in der Live-Demo im Browser durchklicken.

Voraussetzungen

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

Optional, jeweils über die Config zuschaltbar:

  • ox_inventory für die Bankkarte als Item
  • ox_target oder qtarget statt der Taste am NPC und am Automaten
  • okokBilling als Rechnungssystem anstelle des eingebauten
  • lb-phone oder qs-smartphone für die Handy-App (eigene Resource, siehe unten)
  • esx_addonaccount für Job-Konten. Fehlt es, greift X-Banking direkt auf addon_account_data zu.

Installation

  1. Lade x-banking aus dem Cfx.re Portal herunter.
  2. Entpacke den Ordner nach resources/[x-solution]/x-banking.
  3. Importiere sql/install.sql in deine Datenbank. Die Datei legt alle benötigten Tabellen an und ist wiederholbar ausführbar (CREATE TABLE IF NOT EXISTS).
  4. Trage die Resource in deiner server.cfg ein, nach ESX und oxmysql:
ensure oxmysql
ensure es_extended
ensure x-banking
  1. Server neu starten.

Bankkarte als Item

Nur nötig, wenn du Config.Card.enabled nutzt. Öffne ox_inventory/data/items.lua und füge den Eintrag aus install/ox_inventory_items.lua ein:

['bankcard'] = {
    label = 'Bankkarte',
    weight = 10,
    stack = false,
    close = true,
    description = 'Deine persönliche Bankkarte',
},

Optional legst du ein Bild bankcard.png nach ox_inventory/web/images/. Steht Config.Card.required auf true, kommt ohne Karte im Inventar weder der Schalter noch der Automat auf.

Update auf eine neue Version

Führe sql/install.sql nach jedem Update erneut aus. Neue Funktionen bringen regelmäßig neue Tabellen mit, und ohne sie startet das jeweilige Modul nicht.

Bedienung

Ort Bedienung Was passiert
Bankschalter Taste E am NPC Volle Bank-Oberfläche
Geldautomat Taste E am Prop Automaten-Terminal
Geldautomat Taste G am Prop ATM-Hacking, sofern freigeschaltet
Bankkarte Item benutzen Öffnet die Bank
Nummernkonto Taste E am versteckten Kontakt Schweizer Konto

Die Taste am Schalter und Automaten stellst du über Config.OpenKey ein (Standard 38, also E). Es gibt keinen /bank-Befehl — der Zugang läuft bewusst nur über NPC, Automat und Karte.

Befehl Rechte Wirkung
/xbank Admin Verwaltung und Wirtschafts-Statistik
/doj Justiz Konten suchen, sperren, beschlagnahmen

Beide Namen änderst du in Config.AdminCommand und Config.DOJ.command.

Wichtige Einstellungen

Alles liegt in shared/config.lua. Diese Dateien sind bewusst nicht verschlüsselt und bleiben deine:

Datei Wofür
shared/config.lua Alle Einstellungen
shared/locales.lua Sämtliche Texte, Deutsch und Englisch
sql/install.sql Datenbankschema zum Nachlesen
install/ox_inventory_items.lua Vorlage für die Bankkarte

Der restliche Code ist über den Cfx.re-Escrow geschützt. Sicher deine angepassten Dateien vor einem Update trotzdem — ein überschriebener Ordner ist schnell passiert.

Sprache und Texte

Config.Locale = 'de'
Config.Debug  = false

shared/locales.lua bringt de und en mit. Jeder Text steht dort als Schlüssel, du kannst also einzelne Sätze ändern, ohne etwas anderes anzufassen. Platzhalter wie %s müssen erhalten bleiben, sonst fehlt im Text der Betrag oder der Name. Eine eigene Sprache legst du als weiteren Block Locales['fr'] = { ... } an und trägst das Kürzel in Config.Locale ein.

Config.Debug = true schreibt zusätzliche Meldungen in die Serverkonsole. Für den Livebetrieb aus lassen.

Grundlagen

Config.BankAccount = 'bank'
Config.CashAccount = 'money'
Config.Currency    = '$'
Config.IBANPrefix  = 'XB'

Config.BankAccount ist der entscheidende Wert: X-Banking rechnet direkt auf dem ESX-Konto bank. Damit bleibt jedes andere Script, das dieses Konto liest oder schreibt, automatisch synchron. Spar-, Kredit- und Depotdaten liegen in eigenen Tabellen.

Standorte und Zugang

Config.TargetSystem = 'none'
Config.OpenKey      = 38

Config.TargetSystem akzeptiert 'none', 'ox_target' oder 'qtarget'. Bei 'none' erscheint ein Hinweis mit Tastendruck, sonst wird der NPC beziehungsweise das ATM-Prop als Ziel registriert.

Config.Banks enthält die acht Standorte mit Koordinaten und Blip-Einstellungen, Config.NPC das Modell und Szenario des Bankangestellten, Config.Blip das Kartensymbol. Config.ATM.models listet die Props, an denen der Automat aufgeht.

Ein- und Auszahlungen

Config.Deposit = {
    enabled = true,
    min     = 1,
    max     = 10000000,
}
Config.Withdraw = {
    enabled = true,
    min     = 1,
    max     = 10000000,
}

min und max gelten pro Vorgang. Mit enabled = false blendet der Automat den jeweiligen Menüpunkt aus; am Bankschalter bleibt der Knopf sichtbar, der Server lehnt den Vorgang aber ab und meldet es dem Spieler. Nützlich, wenn Bargeld auf deinem Server nur über bestimmte Wege ins Konto soll.

Überweisungen

Config.Transfer = {
    enabled      = true,
    min          = 1,
    max          = 5000000,
    fee          = 0.0,
    feeMin       = 0,
    byIBAN       = true,
    byId         = true,
    confirmAbove = 100000,
}

fee ist ein Prozentwert, feeMin eine Mindestgebühr in bar. Ab confirmAbove fragt die Oberfläche vor dem Absenden nach. Überweisungen per IBAN erreichen auch Offline-Spieler sowie Job-Konten (XJ) und Gemeinschaftskonten (XC).

Sparkonto

Config.Savings = {
    enabled            = true,
    interestRate       = 0.3,
    intervalHours      = 24,
    maxBalance         = 50000000,
    maxInterestBalance = 1000000,
    minDeposit         = 100,
    withdrawFee        = 0.0,
}

interestRate ist der Zinssatz pro Intervall in Prozent. Zinsen laufen offline weiter und werden beim nächsten Login nachberechnet.

maxInterestBalance ist eine Sicherung, keine Schikane: nur bis zu diesem Guthaben wird verzinst. Ohne die Grenze können Spieler einen Großkredit aufnehmen, ihn aufs Sparkonto legen und mehr Zinsen kassieren als der Kredit kostet.

Der Sparplan unter Config.Savings.plan bucht automatisch in festen Intervallen vom Konto aufs Sparkonto. intervals sind die auswählbaren Abstände in Stunden (24 = täglich, 168 = wöchentlich, 720 = monatlich), maxPlans begrenzt, wie viele Pläne ein Spieler gleichzeitig laufen lassen darf.

Festgeld und Sparziele

Config.FixedDeposit = {
    enabled    = true,
    dayHours   = 24,
    minAmount  = 1000,
    allowEarly = true,
    options = {
        { days = 7,  rate = 3.0 },
        { days = 14, rate = 7.0 },
        { days = 30, rate = 18.0 },
    },
}

Config.SavingsGoals = {
    enabled  = true,
    maxGoals = 6,
}

Festgeld ist fest angelegtes Geld: Der Spieler wählt eine Laufzeit aus options und bekommt am Ende rate Prozent Zinsen auf den gesamten Betrag — deutlich mehr als das normale Sparkonto, dafür ist das Geld bis zur Fälligkeit weg. dayHours legt fest, wie lang ein „Tag" in Stunden ist; damit stellst du die Laufzeiten auf deinen Servertakt ein. Steht allowEarly auf true, darf vorzeitig aufgelöst werden — dann gibt es die Einlage zurück, aber keine Zinsen.

Achte darauf, dass die Festgeld-Sätze zu deinen Kreditzinsen passen. Liegt die 30-Tage-Rendite über den Kosten eines Großkredits, ist die Kombination aus Kredit und Festgeld wieder ein Selbstläufer.

Sparziele sind reine Spardosen ohne Zinsen: Name, Zielbetrag, Fortschrittsbalken. maxGoals begrenzt die Anzahl pro Spieler. Beim Löschen eines Ziels geht das Guthaben zurück aufs Bankkonto, es kann also nichts verloren gehen.

Kredite

Config.Loans = {
    offers = {
        { id = 'mikro',    label = 'Mikrokredit',    min = 1000,   max = 50000,   rate = 5.0,  term = 7 },
        { id = 'standard', label = 'Standardkredit', min = 50000,  max = 250000,  rate = 8.0,  term = 14 },
        { id = 'premium',  label = 'Großkredit',     min = 250000, max = 1000000, rate = 12.0, term = 30 },
    },
    installmentIntervalHours = 24,
    maxActiveLoans = 1,
    maxMissed      = 3,
    penaltyPerMiss = 5.0,
    seizeOrder     = { 'bank', 'savings' },
    blockOnDefault = true,
}

term ist die Anzahl der Raten, installmentIntervalHours der Abstand dazwischen. Raten werden auch bei Offline-Spielern abgebucht.

Reicht das Geld nicht, zählt X-Banking eine Mahnstufe hoch und pfändet in der Reihenfolge aus seizeOrder. Nach maxMissed gilt der Kredit als geplatzt. Er wird weiter eingezogen, zählt weiter aufs Limit und sperrt neue Kredite, solange blockOnDefault aktiv ist. Ohne diese drei Punkte lohnt es sich, einen Kredit einfach nicht zu bezahlen.

Der Kreditrahmen ergibt sich aus Config.Loans.credit: flat plus factor mal Vermögen, abzüglich offener Schulden. Die Bonität samt Faktoren sieht der Spieler im Kredite-Tab.

Aktienmarkt

Config.Stocks = {
    tickSeconds        = 90,
    persistSeconds     = 600,
    tradeFee           = 0.5,
    maxPriceFactor     = 25,
    symbols = { ... },
}

Die Kurse berechnet der Server (Random Walk je Symbol nach volatility) und schickt sie nur an offene Oberflächen. maxPriceFactor deckelt, wie weit ein Kurs vom Startwert weglaufen darf.

Dazu kommen Dividenden (Config.Stocks.dividends), Limit- und Stop-Orders (Config.Stocks.orders) sowie Marktnachrichten (Config.Stocks.news), die den Kurs tatsächlich bewegen — chance ist die Wahrscheinlichkeit pro Tick, impact die Kursänderung in Prozent.

Neue Werte trägst du einfach in symbols ein:

{ symbol = 'MEIN', name = 'Meine Firma AG', start = 100.00, volatility = 4.0, dividend = 0.3 },

Rechnungen, Anfragen und Daueraufträge

Config.Invoices = {
    enabled      = true,
    maxOpen      = 20,
    okokBilling  = true,
    okokResource = 'okokBilling',
}

Steht okokBilling auf true und läuft die Resource, gehen erstellte Rechnungen dorthin, und der Rechnungen-Tab zeigt einen Knopf, der okokBilling öffnet. Läuft sie nicht, fällt X-Banking automatisch auf das eigene System zurück. Achtung: Für okokBilling muss der Empfänger online sein.

Config.Requests regelt Zahlungsanfragen zwischen Spielern, Config.StandingOrders wiederkehrende Überweisungen. checkMinutes bestimmt, wie oft der Server fällige Aufträge prüft.

Job- und Gemeinschaftskonten

Config.Society = {
    ibanPrefix       = 'XJ',
    bossGrades       = { 'boss' },
    depositAnyMember = true,
    withdrawBossOnly = true,
    allowTransferIn  = true,
    payroll = { enabled = true, maxPerPay = 1000000 },
}

Config.Company = {
    maxAccounts    = 2,
    maxMembers     = 10,
    createCost     = 50000,
    membersDeposit = true,
    ibanPrefix     = 'XC',
}

Job-Konten spiegeln die ESX-Society deines Jobs und bekommen eine eigene IBAN, damit man ihnen Geld überweisen kann. Heißt euer Chef-Grade anders als boss, trag ihn in bossGrades ein — sonst kommt niemand ans Geld.

Gemeinschaftskonten gründen Spieler selbst gegen createCost, mit den Rollen Inhaber, Manager und Mitglied.

Justiz und Kontosperre

Config.DOJ = {
    enabled = true,
    mode    = 'group',
    ace     = 'x-banking.doj',
    group   = 'admin',
    command = 'doj',
    seizeTo = 'society_government',
}

mode ist entweder 'group' (prüft die ESX-Gruppe aus group) oder 'ace' (prüft die Berechtigung aus ace). Eine Sperre blockiert jeden Geldabfluss: Auszahlung, Überweisung, Sparen, Kreditrückzahlung, Aktienkauf, Rechnungen, Firmeneinzahlungen. Beschlagnahmtes Geld landet auf dem Konto aus seizeTo.

Schweizer Nummernkonto

Config.Swiss = {
    enabled    = true,
    fee        = 10.0,
    minDeposit = 1000,
    maxBalance = 100000000,
    npc = { model = 's_m_m_highsec_01', coords = vec4(...), label = 'Kontakt', blip = false },
}

Ein bewusst verstecktes Konto ohne Blip. Es taucht in der Justiz-Suche nicht auf und lässt sich weder sperren noch beschlagnahmen — dafür kostet jede Einzahlung fee Prozent. Wenn du kein Schlupfloch für Schwarzgeld willst, setz enabled = false.

Kontoauszug, Verlauf und Vermögen

Config.Statement = {
    enabled = true,
    webhook = '',
    last    = 15,
    cooldownSeconds = 30,
}

Config.History = {
    showLast = 25,
}

Config.Networth = {
    enabled       = true,
    snapshotHours = 6,
    keep          = 30,
}

Config.UI = {
    sounds = true,
}

Config.Statement ist der Kontoauszug, den ein Spieler selbst exportiert: last ist die Zahl der Buchungen darauf, cooldownSeconds verhindert Spam, webhook schickt eine Kopie in einen Discord-Kanal. Lässt du webhook leer, bleibt der Auszug im Spiel.

Config.History.showLast bestimmt, wie viele Buchungen die Oberfläche lädt, Config.Requests.showLast dasselbe für Zahlungsanfragen. Beides sind Anzeigegrenzen — in der Datenbank bleibt alles stehen.

Config.Networth zeichnet in Abständen von snapshotHours das Gesamtvermögen auf und hebt keep Messpunkte auf. Daraus entsteht die Kurve auf der Startseite der Bank. Mit enabled = false verschwindet die Kurve, gespart wird dann nichts mehr.

Config.UI.sounds schaltet die Klicks und Bestätigungstöne der Oberfläche ab.

Verwaltung und Protokolle

Config.AdminMode    = 'group'
Config.AdminGroup   = 'admin'
Config.AdminAce     = 'x-banking.admin'
Config.AdminCommand = 'xbank'

Wie beim DOJ entscheidet AdminMode zwischen ESX-Gruppe und ACE-Berechtigung.

Config.Webhooks schickt Überweisungen, Ein- und Auszahlungen, Kredite, Aktiengeschäfte und Admin-Eingriffe an Discord. Trag pro Bereich eine Webhook-URL ein und setz enabled = true. Config.Statement.webhook ist davon getrennt und bekommt die Kontoauszüge, die Spieler selbst exportieren.

Der Geldautomat

Am Automaten öffnet sich standardmäßig kein Bankfenster, sondern ein nachgebautes Terminal mit Gehäuse, Tastatur, Geldschacht und Quittungsdrucker.

Config.ATM.machine = {
    enabled      = true,
    brand        = 'FLEECA BANK',
    headline     = 'Auszahlungen',
    provider     = 'SIX',
    providerSub  = 'Payment Services',
    notes        = { 20, 50, 100, 200, 500, 1000 },
    transfer     = true,
    deposit      = true,
    history      = true,
    receiptCount = 6,
}

notes sind die Schnellbeträge auf dem Auszahlungs-Bildschirm, receiptCount die Zeilenzahl auf der Quittung. Mit transfer, deposit und history schaltest du einzelne Menüpunkte ab. Setzt du enabled = false, öffnet am Automaten wieder die normale Bank-Oberfläche.

PIN

Config.ATM.pin = {
    enabled     = true,
    length      = 4,
    maxFails    = 3,
    lockSeconds = 300,
}

Beim ersten Automatenbesuch legt der Spieler eine PIN fest. Nach maxFails Fehlversuchen ist der Zugang für lockSeconds gesperrt. Am Bankschalter wird nie nach der PIN gefragt.

ATM-Hacking

Config.ATM.robbery = {
    enabled               = true,
    hackControl           = 47,
    atmCooldownMinutes    = 30,
    playerCooldownMinutes = 15,
    minReward             = 500,
    maxReward             = 5000,
    rounds                = 4,
    requiredHits          = 3,
    minCops               = 0,
    copJobs               = { 'police', 'sheriff', 'lspd', 'bcso' },
    alertChance           = 100,
}

hackControl ist die Taste (Standard 47, also G). Das Minispiel läuft über rounds Runden, von denen requiredHits sitzen müssen. Die Cooldowns gelten getrennt pro Automat und pro Spieler. Mit minCops verlangst du eine Mindestzahl an Polizisten im Dienst, alertChance ist die Wahrscheinlichkeit in Prozent, dass ein Blip bei den Jobs aus copJobs gesetzt wird.

Handy-App

Die App ist eine eigene Resource: x-banking-phone. Sie unterstützt lb-phone und qs-smartphone und registriert sich bei dem Telefon, das auf deinem Server läuft.

ensure x-banking
ensure lb-phone
ensure x-banking-phone

Die App muss nach x-banking und nach dem Telefon geladen werden. In shared/config.lua der App schaltest du einzelne Telefone ab:

Config.Phones = {
    ['lb-phone']      = true,
    ['qs-smartphone'] = true,
}

Im Handy gibt es Kontostand, Überweisen, offene Rechnungen und Zahlungsanfragen sowie den Verlauf. Alles andere bleibt bewusst der Bank und dem Automaten vorbehalten.

Bei qs-smartphone unterscheiden sich die Export-Namen je nach Version. Die App probiert der Reihe nach die Namen aus Config.QsExports durch und schreibt beim Start in die Serverkonsole, welcher funktioniert hat. Steht dort, dass keiner gepasst hat, trag den Namen deiner Version vorne in die Liste ein.

Häufige Fragen

Beim Start kommen SQL-Fehler über fehlende Tabellen

sql/install.sql wurde nicht oder nur teilweise importiert. Führ die Datei komplett aus; sie ist so gebaut, dass ein erneuter Durchlauf nichts kaputt macht.

Der Kontostand weicht von einem anderen Script ab

Prüf, ob das andere Script ebenfalls auf bank arbeitet. X-Banking nutzt ausschließlich das ESX-Konto aus Config.BankAccount und führt keinen eigenen Kontostand.

Am NPC oder Automaten passiert nichts

Steht Config.TargetSystem auf 'ox_target' oder 'qtarget', obwohl die Resource nicht läuft, gibt es weder Ziel noch Tastenhinweis. Setz den Wert auf 'none' zurück.

Das Job-Konto ist leer oder niemand kommt ans Geld

Zwei Ursachen: Entweder heißt der Chef-Grade anders als in Config.Society.bossGrades, oder es existiert kein addon_account für den Job. X-Banking liest die ESX-Society und fällt auf addon_account_data zurück; gibt es beides nicht, bleibt das Konto leer.

Rechnungen kommen beim Empfänger nicht an

Im okokBilling-Modus muss der Empfänger online sein. Für Rechnungen an Offline-Spieler setz Config.Invoices.okokBilling = false, dann übernimmt das eingebaute System.

Spieler verdienen mit Sparzinsen mehr als ein Kredit kostet

Senk Config.Savings.maxInterestBalance oder interestRate. Die verzinste Obergrenze sollte deutlich unter dem größten Kreditbetrag liegen, sonst ist die Kombination aus Kredit und Sparkonto ein Selbstläufer.

Ein Kredit wurde nicht zurückgezahlt und der Spieler behält das Geld

Das darf nicht passieren, solange blockOnDefault = true gesetzt ist und seizeOrder gefüllt bleibt. Geplatzte Kredite werden weiter eingezogen und blockieren neue Aufnahmen.

Der Aktienkurs läuft davon

maxPriceFactor begrenzt den Abstand zum Startwert. Für ruhigere Kurse senkst du zusätzlich volatility am jeweiligen Symbol oder erhöhst tickSeconds.

ATM-Hacking startet nicht

Prüf Config.ATM.robbery.minCops. Steht dort ein Wert über null und sind nicht genug Spieler aus copJobs im Dienst, bricht der Versuch ab. Danach greifen die beiden Cooldowns pro Automat und pro Spieler.

Die Bank-App reagiert nicht mehr

Drück Escape. Die Oberfläche schließt sich damit immer, auch aus Untermenüs und offenen Dialogen heraus.

Ich hätte die Texte gern auf Englisch

Setz Config.Locale = 'en'. Die englischen Texte liegen fertig in shared/locales.lua. Einzelne Sätze änderst du direkt in der Datei, Platzhalter wie %s müssen dabei stehen bleiben.

Nach einem Update sind meine Einstellungen weg

shared/config.lua und shared/locales.lua liegen im Resource-Ordner. Wird der Ordner beim Update komplett ersetzt, sind auch deine Anpassungen weg. Sicher beide Dateien vorher und spiel sie danach zurück — verschlüsselt sind sie nicht, du kannst sie also einfach kopieren.

Festgeld läuft nie ab

Config.FixedDeposit.dayHours rechnet die Laufzeit in Echtzeitstunden. Bei dayHours = 24 dauert ein 30-Tage-Festgeld tatsächlich 30 reale Tage. Für schnellere Server setz den Wert herunter, zum Beispiel auf 4.

Support

Kommst du nicht weiter, melde dich auf Discord. Halte bitte die Serverkonsole vom Start, deine Resource-Version und den betroffenen Abschnitt aus der config.lua bereit.

Etwas unklar geblieben?

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

Discord
X-Banking einrichten — Dokumentation · X-Solution