local QBCore = exports['qb-core']:GetCoreObject() local trackedVehicles = {} local lastKnownCoords = {} local garagePending = {} -- Fahrzeuge, die gerade in die Garage gestellt werden -- Debug Funktion local function Debug(msg) if Config.Debug then print("[AntiDespawn] " .. msg) end end -- Funktion um zu prüfen ob Fahrzeugklasse erlaubt ist local function IsVehicleClassAllowed(vehicle) local vehicleClass = GetVehicleClass(vehicle) -- Prüfe Blacklist for _, blacklistedClass in pairs(Config.BlacklistedVehicleClasses) do if vehicleClass == blacklistedClass then return false end end -- Prüfe Whitelist 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 } -- Custom Farben local hasCustomPrimaryColor = GetIsVehiclePrimaryColourCustom(vehicle) if hasCustomPrimaryColor then local r, g, b = GetVehicleCustomPrimaryColour(vehicle) mods.customPrimaryColor = {r = r, g = g, b = b} end local hasCustomSecondaryColor = GetIsVehicleSecondaryColourCustom(vehicle) if hasCustomSecondaryColor then local r, g, b = GetVehicleCustomSecondaryColour(vehicle) mods.customSecondaryColor = {r = r, g = g, b = b} end -- 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} -- Xenon mods.xenonColor = GetVehicleXenonLightsColour(vehicle) mods.xenonEnabled = IsToggleModOn(vehicle, 22) -- Livery mods.livery = GetVehicleLivery(vehicle) -- Fenster Tint mods.windowTint = GetVehicleWindowTint(vehicle) -- Rad Typ mods.wheelType = GetVehicleWheelType(vehicle) -- Rauch Farbe local r, g, b = GetVehicleTyreSmokeColor(vehicle) mods.tyreSmokeColor = {r = r, g = g, b = b} -- Dashboard & Interior Farbe mods.dashboardColor = GetVehicleDashboardColour(vehicle) mods.interiorColor = GetVehicleInteriorColour(vehicle) -- Toggles mods.bulletProofTires = not GetVehicleTyresCanBurst(vehicle) mods.turbo = IsToggleModOn(vehicle, 18) mods.xeonHeadlights = IsToggleModOn(vehicle, 22) return mods end -- Funktion um Fahrzeugmods zu setzen local function SetVehicleMods(vehicle, mods) if not mods then return end -- Setze Modkit SetVehicleModKit(vehicle, 0) -- Rad Typ zuerst setzen if mods.wheelType then SetVehicleWheelType(vehicle, mods.wheelType) end -- Basis Mods for i = 0, 49 do if mods[tostring(i)] ~= nil 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 -- Custom Farben if mods.customPrimaryColor then SetVehicleCustomPrimaryColour(vehicle, mods.customPrimaryColor.r, mods.customPrimaryColor.g, mods.customPrimaryColor.b) end if mods.customSecondaryColor then SetVehicleCustomSecondaryColour(vehicle, mods.customSecondaryColor.r, mods.customSecondaryColor.g, mods.customSecondaryColor.b) 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 -- Xenon if mods.xenonEnabled then ToggleVehicleMod(vehicle, 22, true) if mods.xenonColor then SetVehicleXenonLightsColour(vehicle, mods.xenonColor) end end -- Livery if mods.livery then SetVehicleLivery(vehicle, mods.livery) end -- Fenster Tint if mods.windowTint then SetVehicleWindowTint(vehicle, mods.windowTint) end -- Rauch Farbe if mods.tyreSmokeColor then ToggleVehicleMod(vehicle, 20, true) -- Aktiviere Rauch SetVehicleTyreSmokeColor(vehicle, mods.tyreSmokeColor.r, mods.tyreSmokeColor.g, mods.tyreSmokeColor.b) end -- Dashboard & Interior Farbe if mods.dashboardColor then SetVehicleDashboardColour(vehicle, mods.dashboardColor) end if mods.interiorColor then SetVehicleInteriorColour(vehicle, mods.interiorColor) end -- Toggles if mods.bulletProofTires ~= nil then SetVehicleTyresCanBurst(vehicle, not mods.bulletProofTires) end if mods.turbo ~= nil then ToggleVehicleMod(vehicle, 18, mods.turbo) end -- Setze Felgen nochmal explizit if mods["23"] ~= nil then -- Vorderräder SetVehicleMod(vehicle, 23, mods["23"], false) end if mods["24"] ~= nil then -- Hinterräder SetVehicleMod(vehicle, 24, mods["24"], false) end end -- Extrem starke Anti-Despawn Funktion local function PreventDespawn(vehicle) if not DoesEntityExist(vehicle) then return false end -- Grundlegende Persistenz SetEntityAsMissionEntity(vehicle, true, true) SetVehicleHasBeenOwnedByPlayer(vehicle, true) SetVehicleNeedsToBeHotwired(vehicle, false) -- Zusätzliche Flags SetEntityLoadCollisionFlag(vehicle, true) SetVehicleIsStolen(vehicle, false) SetVehicleIsWanted(vehicle, false) -- Verhindere dass das Fahrzeug als "abandoned" markiert wird if DecorIsRegisteredAsType("IgnoredByQuickSave", 2) then DecorSetBool(vehicle, "IgnoredByQuickSave", false) end -- Setze Fahrzeug auf Boden SetVehicleOnGroundProperly(vehicle) -- Verhindere dass das Fahrzeug gelöscht wird NetworkRegisterEntityAsNetworked(vehicle) local netID = NetworkGetNetworkIdFromEntity(vehicle) SetNetworkIdExistsOnAllMachines(netID, true) SetNetworkIdCanMigrate(netID, true) return true end -- Event Handler für Fahrzeug betreten (nur Fahrersitz) CreateThread(function() local lastVehicle = 0 while true do Wait(1000) local playerPed = PlayerPedId() local currentVehicle = GetVehiclePedIsIn(playerPed, false) -- Spieler ist als Fahrer in ein Fahrzeug eingestiegen if currentVehicle ~= 0 and currentVehicle ~= lastVehicle then -- Prüfe ob Spieler auf Fahrersitz ist local driver = GetPedInVehicleSeat(currentVehicle, -1) -- Nur wenn Spieler der Fahrer ist (Seat -1) if driver == playerPed and IsVehicleClassAllowed(currentVehicle) then local plate = QBCore.Functions.GetPlate(currentVehicle) -- Prüfe ob Fahrzeug gerade in die Garage gestellt wird if not garagePending[plate] then trackedVehicles[plate] = currentVehicle -- Speichere letzte bekannte Position lastKnownCoords[plate] = GetEntityCoords(currentVehicle) -- Sofort starke Despawn-Verhinderung PreventDespawn(currentVehicle) Debug("Fahrzeug wird nun getrackt: " .. plate) -- Hole Fahrzeugmods local vehicleMods = GetVehicleMods(currentVehicle) -- Registriere Fahrzeug beim Server local vehicleCoords = GetEntityCoords(currentVehicle) local vehicleHeading = GetEntityHeading(currentVehicle) local vehicleModel = GetEntityModel(currentVehicle) TriggerServerEvent('antidespawn:server:registerVehicle', plate, vehicleModel, vehicleCoords, vehicleHeading, vehicleMods) else Debug("Fahrzeug wird gerade in Garage gestellt, nicht tracken: " .. plate) end end end lastVehicle = currentVehicle end end) -- Kontinuierliche Despawn-Verhinderung für alle getrackten Fahrzeuge CreateThread(function() while true do Wait(5000) -- Alle 5 Sekunden for plate, vehicle in pairs(trackedVehicles) do -- Prüfe ob Fahrzeug gerade in die Garage gestellt wird if garagePending[plate] then Debug("Fahrzeug wird gerade in Garage gestellt, entferne aus Tracking: " .. plate) trackedVehicles[plate] = nil lastKnownCoords[plate] = nil TriggerServerEvent('antidespawn:server:removeVehicle', plate) elseif DoesEntityExist(vehicle) then PreventDespawn(vehicle) -- Aktualisiere letzte bekannte Position lastKnownCoords[plate] = GetEntityCoords(vehicle) -- Hole Fahrzeugmods local vehicleMods = GetVehicleMods(vehicle) -- Aktualisiere Position local vehicleCoords = GetEntityCoords(vehicle) local vehicleHeading = GetEntityHeading(vehicle) TriggerServerEvent('antidespawn:server:updateVehicle', plate, vehicleCoords, vehicleHeading, vehicleMods) Debug("Aktualisiere Fahrzeug: " .. plate) else Debug("Fahrzeug existiert nicht mehr: " .. plate) -- Versuche Fahrzeug wiederherzustellen, aber nur wenn es nicht in die Garage gestellt wird if lastKnownCoords[plate] and not garagePending[plate] then Debug("Versuche Fahrzeug wiederherzustellen: " .. plate) TriggerServerEvent('antidespawn:server:respawnVehicle', plate) -- Entferne aus lokaler Tracking-Liste, wird nach Respawn wieder hinzugefügt trackedVehicles[plate] = nil lastKnownCoords[plate] = nil else -- Entferne aus Tracking trackedVehicles[plate] = nil lastKnownCoords[plate] = nil end end end end end) -- Lade Fahrzeuge beim Spawn RegisterNetEvent('QBCore:Client:OnPlayerLoaded', function() Debug("Spieler geladen, warte vor dem Laden der Fahrzeuge...") -- Längere Wartezeit, um sicherzustellen, dass alles geladen ist Wait(15000) TriggerServerEvent('antidespawn:server:loadVehicles') end) -- Automatisches Laden beim Resource Start CreateThread(function() -- Längere Wartezeit beim Serverstart Wait(20000) -- Prüfe ob Spieler eingeloggt ist local playerData = QBCore.Functions.GetPlayerData() if playerData and playerData.citizenid then Debug("Resource gestartet, lade Fahrzeuge...") TriggerServerEvent('antidespawn:server:loadVehicles') else -- Warte auf Login, wenn Spieler noch nicht eingeloggt ist Debug("Warte auf Spieler-Login...") while true do Wait(5000) playerData = QBCore.Functions.GetPlayerData() if playerData and playerData.citizenid then Debug("Spieler jetzt eingeloggt, lade Fahrzeuge...") TriggerServerEvent('antidespawn:server:loadVehicles') break end end end end) -- Spawne ein Fahrzeug RegisterNetEvent('antidespawn:client:spawnVehicle', function(data) Debug("Spawne Fahrzeug: " .. data.plate) -- Prüfe ob Fahrzeug bereits existiert local existingVehicle = GetVehicleByPlate(data.plate) if existingVehicle then Debug("Fahrzeug existiert bereits: " .. data.plate) trackedVehicles[data.plate] = existingVehicle lastKnownCoords[data.plate] = GetEntityCoords(existingVehicle) PreventDespawn(existingVehicle) return end -- Prüfe ob Fahrzeug gerade in die Garage gestellt wird if garagePending[data.plate] then Debug("Fahrzeug wird gerade in Garage gestellt, nicht spawnen: " .. data.plate) return end -- Konvertiere Modell zu Hash wenn nötig local modelHash = data.model if type(modelHash) == "string" then -- Versuche den String als Hash zu interpretieren if tonumber(modelHash) then modelHash = tonumber(modelHash) else -- Versuche den String als Modellnamen zu interpretieren modelHash = GetHashKey(modelHash) end end Debug("Versuche Modell zu laden: " .. tostring(modelHash)) -- Prüfe ob Modell existiert if not IsModelInCdimage(modelHash) then Debug("Modell existiert nicht in CD Image: " .. tostring(modelHash)) return end RequestModel(modelHash) local timeout = 0 while not HasModelLoaded(modelHash) and timeout < 100 do Wait(100) timeout = timeout + 1 Debug("Warte auf Modell: " .. tostring(timeout) .. "/100") end if HasModelLoaded(modelHash) then Debug("Modell geladen, erstelle Fahrzeug...") -- Verwende CREATE_AUTOMOBILE für bessere Persistenz local vehicle if Citizen and Citizen.InvokeNative then -- OneSync Methode Debug("Verwende OneSync Methode") vehicle = Citizen.InvokeNative(0xAF35D0D2583051B0, modelHash, data.coords.x, data.coords.y, data.coords.z, data.heading, true, true) else -- Fallback Debug("Verwende Fallback Methode") vehicle = CreateVehicle(modelHash, data.coords.x, data.coords.y, data.coords.z, data.heading, true, false) end if DoesEntityExist(vehicle) then -- Warte bis Fahrzeug vollständig geladen ist Wait(500) -- Setze Kennzeichen SetVehicleNumberPlateText(vehicle, data.plate) -- Setze Mods if data.mods then Debug("Setze Fahrzeugmods...") SetVehicleMods(vehicle, data.mods) end -- Setze Fuel if GetResourceState(Config.FuelSystem) == 'started' then exports[Config.FuelSystem]:SetFuel(vehicle, data.fuel or 100) end -- Verhindere Despawn PreventDespawn(vehicle) -- Füge zu getrackten Fahrzeugen hinzu trackedVehicles[data.plate] = vehicle lastKnownCoords[data.plate] = GetEntityCoords(vehicle) -- Registriere beim Server TriggerServerEvent('antidespawn:server:registerVehicle', data.plate, modelHash, GetEntityCoords(vehicle), GetEntityHeading(vehicle), GetVehicleMods(vehicle)) Debug("Fahrzeug erfolgreich gespawnt: " .. data.plate) else Debug("Fehler beim Spawnen des Fahrzeugs: " .. data.plate) end SetModelAsNoLongerNeeded(modelHash) else Debug("Modell konnte nicht geladen werden: " .. data.plate .. " (Hash: " .. tostring(modelHash) .. ")") 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 -- Event für Garage Store (wird ausgelöst, wenn der Spieler ein Fahrzeug in die Garage stellen will) RegisterNetEvent('jg-advancedgarages:client:store-vehicle', function(garageId, garageVehicleType) local playerPed = PlayerPedId() local vehicle = GetVehiclePedIsIn(playerPed, false) if vehicle ~= 0 then local plate = QBCore.Functions.GetPlate(vehicle) -- Markiere Fahrzeug als "wird in Garage gestellt" garagePending[plate] = true -- Entferne aus Tracking if trackedVehicles[plate] then Debug("Fahrzeug wird in Garage gestellt, entferne aus Tracking: " .. plate) trackedVehicles[plate] = nil lastKnownCoords[plate] = nil TriggerServerEvent('antidespawn:server:removeVehicle', plate) end end end) -- jg-advanced-garage Events RegisterNetEvent('jg-advancedgarages:client:vehicle-stored', function(data) if data and data.plate then -- Markiere Fahrzeug als "in Garage" garagePending[data.plate] = nil -- Entferne aus Tracking if trackedVehicles[data.plate] then trackedVehicles[data.plate] = nil lastKnownCoords[data.plate] = nil end -- Entferne aus Datenbank TriggerServerEvent('antidespawn:server:removeVehicle', data.plate) Debug("Fahrzeug in Garage gespeichert, aus DB entfernt: " .. data.plate) end end) RegisterNetEvent('jg-advancedgarages:client:vehicle-spawned', function(data) if data and data.plate then -- Entferne Markierung "in Garage" garagePending[data.plate] = nil Debug("Fahrzeug aus Garage gespawnt: " .. data.plate) -- Warte kurz bis das Fahrzeug vollständig gespawnt ist Wait(1000) -- Finde das Fahrzeug local vehicle = GetVehicleByPlate(data.plate) if vehicle then -- Füge zu getrackten Fahrzeugen hinzu trackedVehicles[data.plate] = vehicle lastKnownCoords[data.plate] = GetEntityCoords(vehicle) -- Verhindere Despawn PreventDespawn(vehicle) Debug("Fahrzeug aus Garage zum Tracking hinzugefügt: " .. data.plate) end end end) -- Öffnen der Garage - entferne Tracking für Fahrzeuge in der Nähe RegisterNetEvent('jg-advancedgarages:client:open-garage', function(garageId, vehicleType, spawnCoords) Debug("Garage geöffnet: " .. garageId) local playerPos = GetEntityCoords(PlayerPedId()) -- Prüfe alle getrackten Fahrzeuge for plate, vehicle in pairs(trackedVehicles) do if DoesEntityExist(vehicle) then local vehiclePos = GetEntityCoords(vehicle) local distance = #(playerPos - vehiclePos) -- Wenn Fahrzeug in der Nähe ist (50m), markiere als "wird möglicherweise in Garage gestellt" if distance < 50.0 then Debug("Fahrzeug in Garagennähe: " .. plate) -- Nicht komplett entfernen, nur markieren -- Das Event jg-advancedgarages:client:store-vehicle wird ausgelöst wenn es eingelagert wird end end end end) -- Manuelle Lade-Funktion RegisterCommand('loadvehicles', function() Debug("Manuelles Laden der Fahrzeuge...") TriggerServerEvent('antidespawn:server:loadVehicles') end, false) -- Debug Command RegisterCommand('fixvehicle', function() local playerPed = PlayerPedId() local vehicle = GetVehiclePedIsIn(playerPed, false) if vehicle ~= 0 then local plate = QBCore.Functions.GetPlate(vehicle) -- Prüfe ob Fahrzeug gerade in die Garage gestellt wird if not garagePending[plate] then PreventDespawn(vehicle) trackedVehicles[plate] = vehicle lastKnownCoords[plate] = GetEntityCoords(vehicle) -- Registriere Fahrzeug beim Server local vehicleCoords = GetEntityCoords(vehicle) local vehicleHeading = GetEntityHeading(vehicle) local vehicleModel = GetEntityModel(vehicle) local vehicleMods = GetVehicleMods(vehicle) TriggerServerEvent('antidespawn:server:registerVehicle', plate, vehicleModel, vehicleCoords, vehicleHeading, vehicleMods) Debug("Anti-Despawn für Fahrzeug aktiviert: " .. plate) else Debug("Fahrzeug wird gerade in Garage gestellt, kann nicht fixiert werden: " .. plate) end else Debug("Du musst in einem Fahrzeug sitzen!") end end, false) -- Cleanup beim Disconnect AddEventHandler('onResourceStop', function(resourceName) if resourceName == GetCurrentResourceName() then trackedVehicles = {} lastKnownCoords = {} garagePending = {} end end)