1
0
Fork 0
forked from Simnation/Main
Main/resources/[carscripts]/nordi_antidespawn/client/main.lua
2025-08-06 18:50:02 +02:00

574 lines
20 KiB
Lua

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)
-- 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
-- Rad Typ
if mods.wheelType then
SetVehicleWheelType(vehicle, mods.wheelType)
end
-- Rauch Farbe
if mods.tyreSmokeColor then
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
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, lade Fahrzeuge...")
Wait(10000) -- Warte bis alles geladen ist
TriggerServerEvent('antidespawn:server:loadVehicles')
end)
-- Lade Fahrzeuge auch beim Resource Start
CreateThread(function()
Wait(15000) -- Warte bis alles geladen ist
local playerData = QBCore.Functions.GetPlayerData()
if playerData and playerData.citizenid then
Debug("Resource gestartet, lade Fahrzeuge...")
TriggerServerEvent('antidespawn:server:loadVehicles')
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
-- Spawne Fahrzeug
local modelHash = data.model
RequestModel(modelHash)
local timeout = 0
while not HasModelLoaded(modelHash) and timeout < 100 do
Wait(100)
timeout = timeout + 1
end
if HasModelLoaded(modelHash) then
-- Verwende CREATE_AUTOMOBILE für bessere Persistenz
local vehicle
if Citizen and Citizen.InvokeNative then
-- OneSync Methode
vehicle = Citizen.InvokeNative(0xAF35D0D2583051B0, modelHash, data.coords.x, data.coords.y, data.coords.z, data.heading, true, true)
else
-- Fallback
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
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)
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
TriggerServerEvent('antidespawn:server:removeVehicle', data.plate)
end
Debug("Fahrzeug in Garage gespeichert: " .. 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)
-- 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)