local QBCore = exports['qb-core']:GetCoreObject() local trackedVehicles = {} local spawnedVehicles = {} local playerEnteredVehicles = {} -- Fahrzeuge in die sich der Spieler gesetzt hat -- Funktion um zu prüfen ob Fahrzeugklasse erlaubt ist local function IsVehicleClassAllowed(vehicle) local vehicleClass = GetVehicleClass(vehicle) for _, allowedClass in pairs(Config.AllowedVehicleClasses) do if vehicleClass == allowedClass then return true end end return false end -- Funktion um Fahrzeugmods zu erhalten local function GetVehicleMods(vehicle) local mods = {} -- Basis Mods for i = 0, 49 do mods[tostring(i)] = GetVehicleMod(vehicle, i) end -- Extras mods.extras = {} for i = 1, 12 do if DoesExtraExist(vehicle, i) then mods.extras[tostring(i)] = IsVehicleExtraTurnedOn(vehicle, i) end end -- Farben local primaryColor, secondaryColor = GetVehicleColours(vehicle) local pearlescentColor, wheelColor = GetVehicleExtraColours(vehicle) mods.colors = { primary = primaryColor, secondary = secondaryColor, pearlescent = pearlescentColor, wheels = wheelColor } -- Neon mods.neon = { left = IsVehicleNeonLightEnabled(vehicle, 0), right = IsVehicleNeonLightEnabled(vehicle, 1), front = IsVehicleNeonLightEnabled(vehicle, 2), back = IsVehicleNeonLightEnabled(vehicle, 3) } local r, g, b = GetVehicleNeonLightsColour(vehicle) mods.neonColor = {r = r, g = g, b = b} return mods end -- Funktion um Fahrzeugmods zu setzen local function SetVehicleMods(vehicle, mods) if not mods then return end -- Basis Mods for i = 0, 49 do if mods[tostring(i)] then SetVehicleMod(vehicle, i, mods[tostring(i)], false) end end -- Extras if mods.extras then for i = 1, 12 do if mods.extras[tostring(i)] ~= nil then SetVehicleExtra(vehicle, i, not mods.extras[tostring(i)]) end end end -- Farben if mods.colors then SetVehicleColours(vehicle, mods.colors.primary or 0, mods.colors.secondary or 0) SetVehicleExtraColours(vehicle, mods.colors.pearlescent or 0, mods.colors.wheels or 0) end -- Neon if mods.neon then SetVehicleNeonLightEnabled(vehicle, 0, mods.neon.left or false) SetVehicleNeonLightEnabled(vehicle, 1, mods.neon.right or false) SetVehicleNeonLightEnabled(vehicle, 2, mods.neon.front or false) SetVehicleNeonLightEnabled(vehicle, 3, mods.neon.back or false) end if mods.neonColor then SetVehicleNeonLightsColour(vehicle, mods.neonColor.r, mods.neonColor.g, mods.neonColor.b) end end -- Verhindere Despawn für alle getrackten Fahrzeuge local function PreventVehicleDespawn(vehicle) if DoesEntityExist(vehicle) then SetEntityAsMissionEntity(vehicle, true, true) SetVehicleHasBeenOwnedByPlayer(vehicle, true) SetVehicleNeedsToBeHotwired(vehicle, false) SetVehicleOnGroundProperly(vehicle) FreezeEntityPosition(vehicle, false) -- Verhindere dass das Fahrzeug als "abandoned" markiert wird DecorSetBool(vehicle, "IgnoredByQuickSave", false) -- Setze Vehicle als persistent SetEntityLoadCollisionFlag(vehicle, true) end end -- Event Handler für Fahrzeug betreten CreateThread(function() local lastVehicle = 0 while true do Wait(1000) local playerPed = PlayerPedId() local currentVehicle = GetVehiclePedIsIn(playerPed, false) -- Spieler ist in ein Fahrzeug eingestiegen if currentVehicle ~= 0 and currentVehicle ~= lastVehicle then if IsVehicleClassAllowed(currentVehicle) then local plate = QBCore.Functions.GetPlate(currentVehicle) playerEnteredVehicles[plate] = currentVehicle if Config.Debug then print(string.format("Player entered vehicle: %s", plate)) end end end lastVehicle = currentVehicle end end) -- Hauptloop für Fahrzeugtracking (nur für Fahrzeuge in die sich Spieler gesetzt haben) CreateThread(function() while true do Wait(Config.SaveInterval) local playerPed = PlayerPedId() local playerCoords = GetEntityCoords(playerPed) -- Tracke nur Fahrzeuge in die sich der Spieler gesetzt hat for plate, vehicle in pairs(playerEnteredVehicles) do if DoesEntityExist(vehicle) then local vehicleCoords = GetEntityCoords(vehicle) -- Verhindere Despawn PreventVehicleDespawn(vehicle) -- Speichere Fahrzeugdaten local vehicleData = { plate = plate, model = GetEntityModel(vehicle), position = {x = vehicleCoords.x, y = vehicleCoords.y, z = vehicleCoords.z}, rotation = {x = 0.0, y = 0.0, z = GetEntityHeading(vehicle)}, engineHealth = GetVehicleEngineHealth(vehicle), bodyHealth = GetVehicleBodyHealth(vehicle), fuel = 100, -- Standardwert, anpassen je nach Fuel System mods = GetVehicleMods(vehicle) } -- Versuche Fuel zu bekommen if GetResourceState('LegacyFuel') == 'started' then vehicleData.fuel = exports['LegacyFuel']:GetFuel(vehicle) or 100 elseif GetResourceState('ps-fuel') == 'started' then vehicleData.fuel = exports['ps-fuel']:GetFuel(vehicle) or 100 end TriggerServerEvent('vehicle-persistence:server:saveVehiclePosition', vehicleData) trackedVehicles[plate] = vehicle if Config.Debug then local distance = #(playerCoords - vehicleCoords) print(string.format("Tracking player vehicle: %s at distance: %.2f", plate, distance)) end else -- Fahrzeug existiert nicht mehr, entferne aus Liste playerEnteredVehicles[plate] = nil if Config.Debug then print(string.format("Player vehicle no longer exists: %s", plate)) end end end -- Prüfe ob getrackte Fahrzeuge noch existieren for plate, vehicle in pairs(trackedVehicles) do if not DoesEntityExist(vehicle) then trackedVehicles[plate] = nil if Config.Debug then print(string.format("Tracked vehicle no longer exists: %s", plate)) end end end end end) -- Spawne gespeicherte Fahrzeuge RegisterNetEvent('vehicle-persistence:client:spawnSavedVehicles', function(vehicles) if Config.Debug then print(string.format("Attempting to spawn %d saved vehicles", #vehicles)) end for _, vehicleData in pairs(vehicles) do local position = json.decode(vehicleData.position) local rotation = json.decode(vehicleData.rotation) -- Prüfe ob Fahrzeug bereits existiert local existingVehicle = GetVehicleByPlate(vehicleData.plate) if not existingVehicle then CreateThread(function() local modelHash = vehicleData.model if type(modelHash) == "string" then modelHash = GetHashKey(modelHash) end RequestModel(modelHash) local timeout = 0 while not HasModelLoaded(modelHash) and timeout < 50 do Wait(100) timeout = timeout + 1 end if HasModelLoaded(modelHash) then local vehicle = CreateVehicle(modelHash, position.x, position.y, position.z, rotation.z, true, false) if DoesEntityExist(vehicle) then -- Warte bis Fahrzeug vollständig geladen ist Wait(500) -- Setze Fahrzeugdaten SetVehicleNumberPlateText(vehicle, vehicleData.plate) SetVehicleEngineHealth(vehicle, vehicleData.engine_health or 1000.0) SetVehicleBodyHealth(vehicle, vehicleData.body_health or 1000.0) -- Setze Fuel if GetResourceState('LegacyFuel') == 'started' then exports['LegacyFuel']:SetFuel(vehicle, vehicleData.fuel or 100) elseif GetResourceState('ps-fuel') == 'started' then exports['ps-fuel']:SetFuel(vehicle, vehicleData.fuel or 100) end -- Setze Mods if vehicleData.mods then local mods = json.decode(vehicleData.mods) SetVehicleMods(vehicle, mods) end -- Verhindere Despawn PreventVehicleDespawn(vehicle) spawnedVehicles[vehicleData.plate] = vehicle trackedVehicles[vehicleData.plate] = vehicle playerEnteredVehicles[vehicleData.plate] = vehicle -- Markiere als Spielerfahrzeug if Config.Debug then print(string.format("Successfully spawned saved vehicle: %s", vehicleData.plate)) end else if Config.Debug then print(string.format("Failed to create vehicle: %s", vehicleData.plate)) end end SetModelAsNoLongerNeeded(modelHash) else if Config.Debug then print(string.format("Failed to load model for vehicle: %s", vehicleData.plate)) end end end) else -- Fahrzeug existiert bereits, füge zu Tracking hinzu trackedVehicles[vehicleData.plate] = existingVehicle playerEnteredVehicles[vehicleData.plate] = existingVehicle PreventVehicleDespawn(existingVehicle) if Config.Debug then print(string.format("Vehicle already exists, added to tracking: %s", vehicleData.plate)) end end end end) -- Hilfsfunktion um Fahrzeug anhand Kennzeichen zu finden function GetVehicleByPlate(plate) local vehicles = GetGamePool('CVehicle') for _, vehicle in pairs(vehicles) do if QBCore.Functions.GetPlate(vehicle) == plate then return vehicle end end return nil end -- Lade Fahrzeuge beim Spawn RegisterNetEvent('QBCore:Client:OnPlayerLoaded', function() Wait(10000) -- Längere Wartezeit bis alles geladen ist TriggerServerEvent('vehicle-persistence:server:loadVehicles') end) -- Lade Fahrzeuge auch beim Resource Start CreateThread(function() Wait(15000) -- Warte bis Server vollständig geladen ist if QBCore.Functions.GetPlayerData().citizenid then TriggerServerEvent('vehicle-persistence:server:loadVehicles') end end) -- jg-advanced-garage Events RegisterNetEvent('jg-advancedgarages:client:vehicle-stored', function(data) if data and data.plate then if trackedVehicles[data.plate] then trackedVehicles[data.plate] = nil end if spawnedVehicles[data.plate] then spawnedVehicles[data.plate] = nil end if playerEnteredVehicles[data.plate] then playerEnteredVehicles[data.plate] = nil end if Config.Debug then print(string.format("Vehicle stored in garage, removed from tracking: %s", data.plate)) end end end) RegisterNetEvent('jg-advancedgarages:client:vehicle-spawned', function(data) if data and data.plate then if trackedVehicles[data.plate] then trackedVehicles[data.plate] = nil end if spawnedVehicles[data.plate] then spawnedVehicles[data.plate] = nil end if playerEnteredVehicles[data.plate] then playerEnteredVehicles[data.plate] = nil end if Config.Debug then print(string.format("Vehicle spawned from garage, removed from tracking: %s", data.plate)) end end end) -- Kontinuierliche Despawn-Verhinderung CreateThread(function() while true do Wait(30000) -- Alle 30 Sekunden for plate, vehicle in pairs(trackedVehicles) do if DoesEntityExist(vehicle) then PreventVehicleDespawn(vehicle) else trackedVehicles[plate] = nil spawnedVehicles[plate] = nil playerEnteredVehicles[plate] = nil end end end end) -- Cleanup beim Disconnect AddEventHandler('onResourceStop', function(resourceName) if resourceName == GetCurrentResourceName() then trackedVehicles = {} spawnedVehicles = {} playerEnteredVehicles = {} end end)