Zum Inhalt

Fahrzeuge

Besondere Fahrzeuge

Model Name
nkguardian Abschlepper
onebeast DOJ Limo

FIB Fahrzeuge

Model Name
nkjugularum FIB Jugular
nkpantoum FIB Panto
nktailgatersum FIB Tailgater

MD Fahrzeuge (Medizin)

Model Name
nkambulance MD Ambulance
nkballer7ems MD Baller
nkstxems MD Buffelo
nksvolitoems MD Supervolito

PD Fahrzeuge (Polizei)

Model Name
nkbuzzard PD buzzard
nkcomet6 PD Comet 6
nkjugular PD Jugular
nkpanto PD Panto
nkscout PD Scout
nkshinobi PD Shinobi
nksvolito PD Volito
nktailgaters PD Tailgater
nkvigero2 PD Vigero2
insurgentpd Metro Insurgent

Luxusfahrzeuge

Model Name
LUMMA750 Lumma 750
bmm Bentley Mulstenne
amggt63s AMG GT63
maybach Maybach S650
techart17 Porsche Panamera Techart
rs6abt20 Audi RS6
rs318 Audi RS3
agerars Agera RS
amggtbs Balck Series
69charger Charger69
corvetteZR1 Corvette ZR1
demon Demon
eleanor Eleanor
rmodm4gts BMW M4 GTS
911turbos Porsche 911 Turbo
r6 YamahaR6
x6m BMW X6
urus Lambo Urus
RSQ8M Audi RS Q8

Kart Fahrzeuge

Model Name
PV_urus Kart Urus
PV_sianr Kart Sianr
PV_rover Kart Rover
PV_dawn Kart Rolls
PV_jeep Kart Jeep
PV_gtr Kart GTR
PV_lgss Kart Gallardo
PV_bugvr Kart Bugatti
---

Persistente Fahrzeug System

Ein robustes System zum Speichern und Laden von Fahrzeugen über Server-Restarts hinweg. Fahrzeuge können Charakteren, Unternehmen oder Fraktionen gehören.


Übersicht

Features

  • Automatische Persistierung - Fahrzeuge werden auf dem Shutdown gespeichert und beim Start wiederhergestellt
  • Multi-Owner Support - Charakter-, Unternehmens- und Faktionsfahrzeuge
  • Vollständiger Zustand - Motor-, Karosserie- und Tankgesundheit bleiben erhalten
  • Schadensmodellierung - Reifen, Türen, Fenster, Kratzer und Beulen
  • Statebag Integration - Fahrzeug-IDs in FiveM Statebags gespeichert
  • Benutzerdefinierte IDs - Eindeutige Fahrzeug-IDs für die Verwaltung
  • Admin Commands - Debug- und Test-Commands für Administratoren

Datenbank-Schema

persistent_vehicles Tabelle

Spalte Typ Beschreibung
id INT Primary Key
veh_id VARCHAR(50) Eindeutige persistente Fahrzeug-ID (Crypto, Format: veh_HEXSTRING)
model VARCHAR(50) Fahrzeugmodell (z.B. "blista", "rumpo")
custom_id VARCHAR(50) Optionale benutzerdefinierte Kennung
owner_type ENUM 'character', 'business', oder 'faction'
owner_id INT Charakter-/Unternehmens-/Fraktions-ID
numplate VARCHAR(8) Nummernschild (Auto-generiert, Format: AB 12345)
location_x/y/z FLOAT Aktueller Standort
rotation_x/y/z FLOAT Aktuelle Ausrichtung
engine_health FLOAT Motorgesundheit (0-1000)
body_health FLOAT Karosseriegesundheit (0-1000)
tank_health FLOAT Tankgesundheit (0-1000)
fuel FLOAT Kraftstoffmenge (0-100)
tyres JSON Reifenschaden pro Rad (0-7)
doors JSON Türschaden pro Tür (0-5)
windows JSON Fensterschaden pro Fenster (0-7)
properties JSON Zusätzliche Eigenschaften/Modifikationen

Server-Funktionen

Fahrzeuge erstellen

Charakter-Fahrzeug erstellen

cv.createCharacterVehicle(
    charId,      -- number: Charakter-ID
    model,       -- string: Fahrzeugmodell
    coords,      -- vector3/table: {x, y, z}
    heading,     -- number: Ausrichtung
    customId,    -- string (optional): Benutzerdefinierte ID
    callback     -- function (optional): Callback bei Erfolg
)

Beispiel:

cv.createCharacterVehicle(1, "blista", vector3(425.5, -982.3, 29.4), 180.0, "my_car", function(veh)
    if veh then
        print("Charakter-Fahrzeug erstellt!")
    end
end)

Unternehmens-Fahrzeug erstellen

cv.createBusinessVehicle(
    businessId,  -- number: Unternehmens-ID
    model,       -- string: Fahrzeugmodell
    coords,      -- vector3/table: Koordinaten
    heading,     -- number: Ausrichtung
    customId,    -- string (optional)
    callback     -- function (optional)
)

Beispiel:

cv.createBusinessVehicle(5, "rumpo", vector3(100, 200, 30), 90.0, "delivery_01")

Fraktions-Fahrzeug erstellen

cv.createFactionVehicle(
    factionId,   -- number: Fraktions-ID
    model,       -- string: Fahrzeugmodell
    coords,      -- vector3/table: Koordinaten
    heading,     -- number: Ausrichtung
    customId,    -- string (optional)
    callback     -- function (optional)
)

Beispiel:

cv.createFactionVehicle(2, "police", vector3(450, -500, 25), 0.0, "patrol_01")


Fahrzeuge abrufen

Einzelnes Fahrzeug abrufen

local veh = cv.getPersistentVehicle(veh_id)

Alle Fahrzeuge eines Charakters

local vehicles = cv.getCharacterVehicles(charId)
for _, veh in ipairs(vehicles) do
    print(veh.model .. " - " .. veh.numplate)
end

Alle Fahrzeuge eines Unternehmens

local vehicles = cv.getBusinessVehicles(businessId)

Alle Fahrzeuge einer Fraktion

local vehicles = cv.getFactionVehicles(factionId)

Fahrzeuge verwalten

Fahrzeug-Zustand aktualisieren

cv.updatePersistentVehicleHealth(
    veh_id,          -- string: Fahrzeug-ID
    engineHealth,    -- number: Motor (0-1000)
    bodyHealth,      -- number: Karosserie (0-1000)
    tankHealth,      -- number: Tank (0-1000)
    fuel,            -- number: Kraftstoff (0-100)
    properties       -- table (optional): Zusätz. Eigenschaften
)

Beispiel:

-- Fahrzeug nach Unfall aktualisieren
cv.updatePersistentVehicleHealth(veh_id, 800, 900, 950, 45)

Fahrzeug löschen

cv.deletePersistentVehicle(
    veh_id,          -- string: Fahrzeug-ID
    deleteFromDB     -- boolean (optional, default: true)
)

Beispiel:

cv.deletePersistentVehicle(veh_id)  -- Löscht auch aus DB


Nummernschild-Verwaltung

Nummernschild-Format

Nummerschilder folgen strikten Regeln: - Erlaubte Zeichen: A-Z, 0-9, Leerzeichen - Länge: Max. 8 Zeichen - Format: Nur Leerzeichen zwischen Zeichen erlaubt (nicht am Anfang/Ende) - Mehrfach-Leerzeichen: Nicht erlaubt

Gültige Beispiele: - ABC 1234 - AB 12345 - ABCD 123

Ungültige Beispiele: - ABC1234 (Leerzeichen am Anfang) - ABC1234 (Leerzeichen am Ende) - AB 1234 (Doppel-Leerzeichen) - abc1234 (Kleinbuchstaben)

Nummernschild-Verfügbarkeit prüfen

local available = cv.isPlateAvailable(plate)
if available then
    print("Nummernschild verfügbar!")
else
    print("Nummernschild bereits registriert")
end

Beispiel:

if cv.isPlateAvailable("ABC 1234") then
    -- Nummernschild ist frei
else
    -- Nummernschild vergeben
end

Nummernschild registrieren/ändern

local success = cv.registerVehiclePlate(
    veh_id,   -- string: Fahrzeug-ID
    plate     -- string: Neues Nummernschild
)

Rückgabewert: - true - Erfolgreich registriert - false - Ungültiges Format oder bereits vergeben

Beispiel:

if cv.registerVehiclePlate(veh_id, "ABC 1234") then
    print("Nummernschild geändert!")
else
    print("Nummernschild-Änderung fehlgeschlagen!")
end

In Fahrzeugerstellung:

cv.createCharacterVehicle(charId, "blista", coords, heading, nil, bucketId, function(veh)
    if veh then
        -- Fahrzeug wurde mit Auto-Nummernschild erstellt
        local vehData = cv.getPersistentVehicle(veh_id)
        print("Nummernschild: " .. vehData.numplate)
    end
end)


Client-Funktionen

Prüfe ob Fahrzeug persistiert

local vehicle = GetVehiclePedIsIn(PlayerPedId(), false)
if cv.isPersistentVehicle(vehicle) then
    print("Das ist ein persistentes Fahrzeug!")
end

Hole Fahrzeug-ID

local veh_id = cv.getPersistentVehicleId(vehicle)
print("Fahrzeug-ID: " .. veh_id)

Hole Besitzer-Info

local ownerInfo = cv.getVehicleOwnerInfo(vehicle)
if ownerInfo then
    print("Besitzer-Typ: " .. ownerInfo.owner_type)
    print("Besitzer-ID: " .. ownerInfo.owner_id)
end

Gecachte Health-Werte

local engineHealth = cv.getVehicleEngineHealthCached(vehicle)
local bodyHealth = cv.getVehicleBodyHealthCached(vehicle)

Statebag-Eigenschaften

Jedes persistente Fahrzeug speichert automatisch folgende Werte im Statebag:

Entity(vehicle).state['persistentVehId']   -- Eindeutige Fahrzeug-ID
Entity(vehicle).state['ownerType']         -- 'character', 'business', 'faction'
Entity(vehicle).state['ownerId']           -- Besitzer-ID
Entity(vehicle).state['engineHealth']      -- Motorgesundheit (0-1000)
Entity(vehicle).state['bodyHealth']        -- Karosseriegesundheit (0-1000)

Diese Werte werden mit allen Clients synchronisiert.


Admin-Commands

/spawntest

Spawnt ein Test-Fahrzeug für den Charakter

/spawntest [model]
Beispiele:
/spawntest blista
/spawntest adder

/spawncompanycar

Spawnt ein Unternehmensfahrzeug (nur für Tests)

/spawncompanycar [model] [businessId]
Beispiele:
/spawncompanycar rumpo 1
/spawncompanycar police 5

/pvdebug

Debug-Commands für das Fahrzeug-System

/pvdebug [count|check]
- count - Zeigt Anzahl der Fahrzeuge in der DB - check - Zeigt Verteilung nach Besitzer-Typ


Praktische Beispiele

Beispiel 1: Fahrzeug-Flotte für Unternehmen

-- Erstelle 5 Lieferfahrzeuge für ein Unternehmen
for i = 1, 5 do
    cv.createBusinessVehicle(1, "rumpo",
        vector3(100 + i*10, 200, 30), 0.0,
        "delivery_"..i
    )
end

-- Rufe später alle Fahrzeuge ab
local vehicles = cv.getBusinessVehicles(1)

Beispiel 2: Persönliche Fahrzeuggarage

-- Charakter parkt sein Fahrzeug
cv.createCharacterVehicle(charId, "adder", coords, heading, "primary_vehicle")

-- Später im Garagen-Command
local vehicles = cv.getCharacterVehicles(charId)
for _, veh in ipairs(vehicles) do
    if veh.custom_id == "primary_vehicle" then
        -- Dieses Fahrzeug spawnen
    end
end

Beispiel 3: Fraktions-Fahrzeuge

-- Polizei-Streifenwagen
cv.createFactionVehicle(1, "police", coords1, 0.0, "patrol_01")
cv.createFactionVehicle(1, "police", coords2, 90.0, "patrol_02")

-- Nach Neustart werden alle Fahrzeuge automatisch geladen

Beispiel 4: Fahrzeug-Health nach Unfall speichern

-- Nach Fahrzeug-Unfall
local vehicle = GetVehiclePedIsIn(PlayerPedId(), false)
if cv.isPersistentVehicle(vehicle) then
    local veh_id = cv.getPersistentVehicleId(vehicle)
    local engineHealth = GetVehicleEngineHealth(vehicle)
    local bodyHealth = GetVehicleBodyHealth(vehicle)

    -- Speichere den Schaden
    cv.updatePersistentVehicleHealth(veh_id, engineHealth, bodyHealth, 1000, 65)
end

Automatisches Speichern/Laden

Server-Start

  1. Nach 1 Sekunde Verzögerung werden alle Fahrzeuge aus der DB geladen
  2. Standort und Ausrichtung werden wiederhergestellt
  3. Alle Health- und Schadenseigenschaften werden angewendet
  4. Statebag-Werte werden aktualisiert

Server-Shutdown

  1. Beim Herunterfahren (txAdmin oder Resource Stop) werden alle Fahrzeuge gespeichert
  2. Aktueller Standort, Ausrichtung und Health werden aufgezeichnet
  3. Schadenzustände (Reifen, Türen, Fenster) bleiben erhalten
  4. Alle Daten werden in die DB geschrieben

txAdmin-Integration

  • Standard: Nutzt txAdmin serverShuttingDown Event
  • Fallback: Nutzt onResourceStop wenn txAdmin nicht verfügbar
  • Config: setr persistvehicles:useTxAdminEvent 1

Häufig gestellte Fragen

F: Wie lange dauert es, bis Fahrzeuge geladen werden? A: Fahrzeuge werden 1 Sekunde nach Server-Start geladen, um die DB-Verbindung zu initialisieren.

F: Können Fahrzeuge an neue Besitzer übertragen werden? A: Ja, durch direktes DB-Update:

MySQL.update.await(
    'UPDATE persistent_vehicles SET owner_type = ?, owner_id = ? WHERE veh_id = ?',
    {newType, newId, veh_id}
)

F: Bleiben Fahrzeug-Modifikationen erhalten? A: Ja, alle Eigenschaften werden in der properties JSON-Spalte gespeichert.

F: Was passiert, wenn der Besitzer gelöscht wird? A: Derzeit bleiben die Fahrzeuge bestehen. Sie können Cleanup-Logik bei Charakter-Löschung hinzufügen.

F: Gibt es eine Obergrenze für Fahrzeuge? A: Nein, nur die MySQL-DB-Kapazität ist die Grenze.


Best Practices

  1. Verwende immer Callbacks - Fahrzeuge spawen asynchron
  2. Validiere Owner-IDs - Stelle sicher, dass Charakter/Unternehmens-IDs existieren
  3. Aktualisiere Health regelmäßig - Nutze updatePersistentVehicleHealth() nach Änderungen
  4. Verwende benutzerdefinierte IDs - Organisiere Fahrzeuge (z.B. "taxi_01", "police_k9")
  5. Prüfe auf Client - Nutze cv.isPersistentVehicle() um Fahrzeugtyp zu checken
  6. Nutze Statebag-Werte - Statt Entity-Abfragen mehrfach zu machen

Troubleshooting

Fahrzeuge werden nicht gespeichert

  • Prüfe MySQL-Verbindung
  • Verifiziere dass persistent_vehicles Tabelle existiert
  • Schaue Server-Logs für SQL-Fehler

Fahrzeuge laden nicht nach Neustart

  • Warte 1+ Sekunden nach Server-Start
  • Prüfe DB auf Fahrzeug-Records
  • Führe /pvdebug count aus

Fahrzeug am falschen Ort

  • Z-Koordinate müssen auf dem Boden sein
  • Prüfe rotation_z (Ausrichtung) in DB
  • Standort sollte keine Gebäude durchschneiden

Performance-Probleme

  • Fahrzeuge werden mit Verzögerung nach Start geladen
  • DB-Operationen sind synchron (.await())
  • Nur beim Shutdown wird gespeichert
  • Minimaler Memory-Overhead

Integration mit cv_framework

  • Nutzt existierendes cv.spawnVehicle() System
  • Respektiert FiveM Bucket-Systeme
  • Verwendet MySQL.query/insert/update.await() für DB
  • Broadcast Statebag-Updates an alle Clients
  • Integriert mit CVPlayer Character-System

FAQ - Benutzerdefinierte ID-Verwaltung

Fahrzeuge nach Custom-ID filtern

local allVehicles = cv.getCharacterVehicles(charId)
for _, veh in ipairs(allVehicles) do
    if veh.custom_id == "primary_vehicle" then
        print("Primär-Fahrzeug gefunden: " .. veh.model)
    end
end

Nach Besitzer-Typ filtern

local vehicles = cv.getOwnerVehicles('character', charId)
local businessVehs = cv.getOwnerVehicles('business', businessId)
local factionVehs = cv.getOwnerVehicles('faction', factionId)