1
0
Fork 0
forked from Simnation/Main
Main/resources/[carscripts]/nordi_antidespawn/client/main.lua

859 lines
30 KiB
Lua
Raw Normal View History

2025-08-06 17:33:26 +02:00
local QBCore = exports['qb-core']:GetCoreObject()
2025-08-06 18:18:04 +02:00
local trackedVehicles = {}
2025-08-06 18:32:55 +02:00
local lastKnownCoords = {}
2025-08-06 18:50:02 +02:00
local garagePending = {} -- Fahrzeuge, die gerade in die Garage gestellt werden
2025-08-07 13:21:12 +02:00
local spawnedVehicles = {} -- Track recently spawned vehicles to prevent duplication
local vehicleOwnership = {} -- Cache vehicle ownership status
2025-08-06 18:18:04 +02:00
2025-08-07 13:02:53 +02:00
-- Helper function to count table entries
function tableLength(T)
local count = 0
for _ in pairs(T) do count = count + 1 end
return count
end
2025-08-06 18:18:04 +02:00
-- Debug Funktion
local function Debug(msg)
if Config.Debug then
print("[AntiDespawn] " .. msg)
end
end
2025-08-06 17:33:26 +02:00
2025-08-07 13:21:12 +02:00
-- Anti-Duplication: Check if a vehicle with this plate already exists in the world
local function DoesVehicleExistInWorld(plate)
local vehicles = GetGamePool('CVehicle')
local count = 0
2025-08-07 13:07:01 +02:00
2025-08-07 13:21:12 +02:00
for _, vehicle in pairs(vehicles) do
local vehPlate = QBCore.Functions.GetPlate(vehicle)
if vehPlate == plate then
count = count + 1
if count > 1 then
-- More than one vehicle with this plate exists!
Debug("DUPLICATION DETECTED: Multiple vehicles with plate " .. plate .. " exist!")
return true
end
end
2025-08-07 13:07:01 +02:00
end
2025-08-07 13:21:12 +02:00
return false
end
-- Anti-Duplication: Check if vehicle was recently spawned
local function WasVehicleRecentlySpawned(plate)
if spawnedVehicles[plate] then
local timeSinceSpawn = GetGameTimer() - spawnedVehicles[plate]
if timeSinceSpawn < 60000 then -- 60 seconds cooldown
Debug("Anti-Dupe: Vehicle " .. plate .. " was recently spawned (" .. math.floor(timeSinceSpawn/1000) .. " seconds ago)")
return true
else
-- Reset the timer if it's been more than 60 seconds
spawnedVehicles[plate] = nil
end
end
return false
end
-- Anti-Duplication: Mark vehicle as recently spawned
local function MarkVehicleAsSpawned(plate)
spawnedVehicles[plate] = GetGameTimer()
Debug("Anti-Dupe: Marked vehicle " .. plate .. " as recently spawned")
-- Clean up old entries every 5 minutes
SetTimeout(300000, function()
for p, time in pairs(spawnedVehicles) do
if GetGameTimer() - time > 300000 then -- 5 minutes
spawnedVehicles[p] = nil
end
end
end)
2025-08-07 13:07:01 +02:00
end
2025-08-07 13:21:12 +02:00
-- Function to check if player owns the vehicle with caching
2025-08-07 13:02:53 +02:00
local function DoesPlayerOwnVehicle(plate)
2025-08-07 13:21:12 +02:00
-- Check cache first
if vehicleOwnership[plate] ~= nil then
-- Cache expires after 5 minutes
local timeSinceCheck = GetGameTimer() - vehicleOwnership[plate].timestamp
if timeSinceCheck < 300000 then -- 5 minutes
return vehicleOwnership[plate].owned
end
end
2025-08-07 13:02:53 +02:00
local playerData = QBCore.Functions.GetPlayerData()
if not playerData then return false end
-- Trigger server event to check ownership and wait for response
local isOwned = nil
-- Request ownership check from server
TriggerServerEvent('antidespawn:server:checkVehicleOwnership', plate)
-- Register one-time event handler for the response
local eventHandler = AddEventHandler('antidespawn:client:vehicleOwnershipResult', function(result, checkPlate)
if plate == checkPlate then
isOwned = result
2025-08-07 13:21:12 +02:00
-- Cache the result
vehicleOwnership[plate] = {
owned = result,
timestamp = GetGameTimer()
}
2025-08-07 13:02:53 +02:00
end
end)
-- Wait for response with timeout
local timeout = 0
while isOwned == nil and timeout < 50 do
Wait(10)
timeout = timeout + 1
end
-- Remove event handler
RemoveEventHandler(eventHandler)
return isOwned == true
end
2025-08-06 17:33:26 +02:00
-- Funktion um zu prüfen ob Fahrzeugklasse erlaubt ist
local function IsVehicleClassAllowed(vehicle)
local vehicleClass = GetVehicleClass(vehicle)
2025-08-06 18:18:04 +02:00
-- Prüfe Blacklist
for _, blacklistedClass in pairs(Config.BlacklistedVehicleClasses) do
if vehicleClass == blacklistedClass then
return false
end
end
-- Prüfe Whitelist
2025-08-06 17:33:26 +02:00
for _, allowedClass in pairs(Config.AllowedVehicleClasses) do
if vehicleClass == allowedClass then
return true
end
end
2025-08-06 18:18:04 +02:00
2025-08-06 17:33:26 +02:00
return false
end
2025-08-07 13:21:12 +02:00
-- 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
2025-08-07 13:07:01 +02:00
-- 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
-- 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
2025-08-06 17:59:00 +02:00
-- Event Handler für Fahrzeug betreten (nur Fahrersitz)
2025-08-06 17:53:15 +02:00
CreateThread(function()
while true do
Wait(1000)
local playerPed = PlayerPedId()
local currentVehicle = GetVehiclePedIsIn(playerPed, false)
2025-08-06 17:59:00 +02:00
-- Spieler ist als Fahrer in ein Fahrzeug eingestiegen
2025-08-07 12:45:07 +02:00
if currentVehicle ~= 0 then
2025-08-06 18:01:54 +02:00
-- Prüfe ob Spieler auf Fahrersitz ist
local driver = GetPedInVehicleSeat(currentVehicle, -1)
2025-08-06 17:59:00 +02:00
2025-08-06 18:01:54 +02:00
-- Nur wenn Spieler der Fahrer ist (Seat -1)
if driver == playerPed and IsVehicleClassAllowed(currentVehicle) then
2025-08-06 17:53:15 +02:00
local plate = QBCore.Functions.GetPlate(currentVehicle)
2025-08-06 17:59:00 +02:00
2025-08-07 13:21:12 +02:00
-- Anti-Duplication: Check if this plate already exists multiple times
if DoesVehicleExistInWorld(plate) then
Debug("Anti-Dupe: Detected duplicate vehicle with plate " .. plate .. ", not tracking")
-- Optionally, you could delete the duplicate here
-- DeleteEntity(currentVehicle)
goto continue
end
2025-08-07 12:45:07 +02:00
-- Check if this vehicle is already being tracked
if not trackedVehicles[plate] and not garagePending[plate] then
2025-08-07 13:02:53 +02:00
-- Check if player owns this vehicle
if DoesPlayerOwnVehicle(plate) then
-- Check if maximum tracked vehicles limit is reached
local maxTrackedVehicles = 100 -- Adjust as needed
if tableLength(trackedVehicles) >= maxTrackedVehicles then
Debug("Maximum number of tracked vehicles reached")
else
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)
end
else
Debug("Fahrzeug gehört nicht dem Spieler, wird nicht getrackt: " .. plate)
end
2025-08-06 18:50:02 +02:00
end
2025-08-06 17:53:15 +02:00
end
end
2025-08-07 13:21:12 +02:00
::continue::
2025-08-06 17:53:15 +02:00
end
end)
2025-08-06 18:12:40 +02:00
-- Kontinuierliche Despawn-Verhinderung für alle getrackten Fahrzeuge
CreateThread(function()
while true do
2025-08-06 18:32:55 +02:00
Wait(5000) -- Alle 5 Sekunden
2025-08-06 18:12:40 +02:00
2025-08-07 13:02:53 +02:00
local playerPed = PlayerPedId()
local playerPos = GetEntityCoords(playerPed)
2025-08-06 18:18:04 +02:00
for plate, vehicle in pairs(trackedVehicles) do
2025-08-07 13:21:12 +02:00
-- Anti-Duplication: Check if multiple vehicles with this plate exist
if DoesVehicleExistInWorld(plate) then
Debug("Anti-Dupe: Detected duplicate during tracking for plate " .. plate .. ", removing from tracking")
trackedVehicles[plate] = nil
lastKnownCoords[plate] = nil
TriggerServerEvent('antidespawn:server:removeVehicle', plate)
goto continue
end
2025-08-06 18:50:02 +02:00
-- 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
2025-08-07 13:02:53 +02:00
-- Check distance to player
local vehiclePos = GetEntityCoords(vehicle)
local distance = #(playerPos - vehiclePos)
2025-08-06 18:32:55 +02:00
2025-08-07 13:02:53 +02:00
if distance > 500.0 then -- 500 units = about 500 meters
Debug("Fahrzeug zu weit entfernt, entferne aus Tracking: " .. plate)
trackedVehicles[plate] = nil
lastKnownCoords[plate] = nil
TriggerServerEvent('antidespawn:server:removeVehicle', plate)
else
PreventDespawn(vehicle)
-- Aktualisiere letzte bekannte Position
lastKnownCoords[plate] = vehiclePos
-- Hole Fahrzeugmods
local vehicleMods = GetVehicleMods(vehicle)
-- Aktualisiere Position
local vehicleHeading = GetEntityHeading(vehicle)
TriggerServerEvent('antidespawn:server:updateVehicle', plate, vehiclePos, vehicleHeading, vehicleMods)
Debug("Aktualisiere Fahrzeug: " .. plate)
end
2025-08-06 17:53:15 +02:00
else
2025-08-06 18:18:04 +02:00
Debug("Fahrzeug existiert nicht mehr: " .. plate)
2025-08-06 18:32:55 +02:00
2025-08-07 13:21:12 +02:00
-- Anti-Duplication: Check if vehicle was recently spawned before respawning
if WasVehicleRecentlySpawned(plate) then
Debug("Anti-Dupe: Not respawning recently spawned vehicle: " .. plate)
trackedVehicles[plate] = nil
lastKnownCoords[plate] = nil
goto continue
end
2025-08-06 18:50:02 +02:00
-- Versuche Fahrzeug wiederherzustellen, aber nur wenn es nicht in die Garage gestellt wird
if lastKnownCoords[plate] and not garagePending[plate] then
2025-08-06 18:32:55 +02:00
Debug("Versuche Fahrzeug wiederherzustellen: " .. plate)
TriggerServerEvent('antidespawn:server:respawnVehicle', plate)
-- Entferne aus lokaler Tracking-Liste, wird nach Respawn wieder hinzugefügt
trackedVehicles[plate] = nil
2025-08-06 18:50:02 +02:00
lastKnownCoords[plate] = nil
else
-- Entferne aus Tracking
trackedVehicles[plate] = nil
lastKnownCoords[plate] = nil
2025-08-06 18:32:55 +02:00
end
2025-08-06 17:49:33 +02:00
end
2025-08-07 13:21:12 +02:00
::continue::
2025-08-06 17:49:33 +02:00
end
2025-08-06 17:33:26 +02:00
end
end)
2025-08-06 18:18:04 +02:00
-- Lade Fahrzeuge beim Spawn
RegisterNetEvent('QBCore:Client:OnPlayerLoaded', function()
2025-08-06 19:45:59 +02:00
Debug("Spieler geladen, warte vor dem Laden der Fahrzeuge...")
-- Längere Wartezeit, um sicherzustellen, dass alles geladen ist
Wait(15000)
2025-08-06 18:18:04 +02:00
TriggerServerEvent('antidespawn:server:loadVehicles')
end)
2025-08-06 19:45:59 +02:00
-- Automatisches Laden beim Resource Start
2025-08-06 18:50:02 +02:00
CreateThread(function()
2025-08-06 19:45:59 +02:00
-- Längere Wartezeit beim Serverstart
Wait(20000)
2025-08-06 18:50:02 +02:00
2025-08-06 19:45:59 +02:00
-- Prüfe ob Spieler eingeloggt ist
2025-08-06 18:50:02 +02:00
local playerData = QBCore.Functions.GetPlayerData()
if playerData and playerData.citizenid then
Debug("Resource gestartet, lade Fahrzeuge...")
TriggerServerEvent('antidespawn:server:loadVehicles')
2025-08-06 19:45:59 +02:00
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
2025-08-06 18:50:02 +02:00
end
end)
2025-08-06 18:18:04 +02:00
-- Spawne ein Fahrzeug
RegisterNetEvent('antidespawn:client:spawnVehicle', function(data)
Debug("Spawne Fahrzeug: " .. data.plate)
2025-08-07 13:21:12 +02:00
-- Anti-Duplication: Check if vehicle was recently spawned
if WasVehicleRecentlySpawned(data.plate) then
Debug("Anti-Dupe: Blocking respawn of recently spawned vehicle: " .. data.plate)
return
end
2025-08-06 18:18:04 +02:00
-- Prüfe ob Fahrzeug bereits existiert
local existingVehicle = GetVehicleByPlate(data.plate)
if existingVehicle then
Debug("Fahrzeug existiert bereits: " .. data.plate)
trackedVehicles[data.plate] = existingVehicle
2025-08-06 18:32:55 +02:00
lastKnownCoords[data.plate] = GetEntityCoords(existingVehicle)
2025-08-06 18:18:04 +02:00
PreventDespawn(existingVehicle)
return
2025-08-06 17:49:33 +02:00
end
2025-08-06 18:50:02 +02:00
-- 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
2025-08-07 13:21:12 +02:00
-- Anti-Duplication: Check if player owns this vehicle
if not DoesPlayerOwnVehicle(data.plate) then
Debug("Anti-Dupe: Player does not own vehicle, not spawning: " .. data.plate)
return
end
2025-08-06 19:16:18 +02:00
-- Konvertiere Modell zu Hash wenn nötig
2025-08-06 18:18:04 +02:00
local modelHash = data.model
2025-08-06 19:16:18 +02:00
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
2025-08-06 18:18:04 +02:00
RequestModel(modelHash)
local timeout = 0
while not HasModelLoaded(modelHash) and timeout < 100 do
Wait(100)
timeout = timeout + 1
2025-08-06 19:16:18 +02:00
Debug("Warte auf Modell: " .. tostring(timeout) .. "/100")
2025-08-06 18:18:04 +02:00
end
if HasModelLoaded(modelHash) then
2025-08-06 19:16:18 +02:00
Debug("Modell geladen, erstelle Fahrzeug...")
2025-08-07 13:21:12 +02:00
-- Anti-Duplication: Final check before spawning
if GetVehicleByPlate(data.plate) then
Debug("Anti-Dupe: Vehicle with plate " .. data.plate .. " appeared during model loading, aborting spawn")
SetModelAsNoLongerNeeded(modelHash)
return
end
2025-08-06 18:32:55 +02:00
-- Verwende CREATE_AUTOMOBILE für bessere Persistenz
local vehicle
if Citizen and Citizen.InvokeNative then
-- OneSync Methode
2025-08-06 19:16:18 +02:00
Debug("Verwende OneSync Methode")
2025-08-06 18:32:55 +02:00
vehicle = Citizen.InvokeNative(0xAF35D0D2583051B0, modelHash, data.coords.x, data.coords.y, data.coords.z, data.heading, true, true)
else
-- Fallback
2025-08-06 19:16:18 +02:00
Debug("Verwende Fallback Methode")
2025-08-06 18:32:55 +02:00
vehicle = CreateVehicle(modelHash, data.coords.x, data.coords.y, data.coords.z, data.heading, true, false)
end
2025-08-06 17:33:26 +02:00
2025-08-06 18:18:04 +02:00
if DoesEntityExist(vehicle) then
2025-08-07 13:21:12 +02:00
-- Anti-Duplication: Mark as recently spawned
MarkVehicleAsSpawned(data.plate)
2025-08-06 18:32:55 +02:00
-- Warte bis Fahrzeug vollständig geladen ist
Wait(500)
2025-08-06 18:18:04 +02:00
-- Setze Kennzeichen
SetVehicleNumberPlateText(vehicle, data.plate)
2025-08-06 18:07:18 +02:00
2025-08-06 18:50:02 +02:00
-- Setze Mods
if data.mods then
2025-08-06 19:16:18 +02:00
Debug("Setze Fahrzeugmods...")
2025-08-06 18:50:02 +02:00
SetVehicleMods(vehicle, data.mods)
end
2025-08-06 18:18:04 +02:00
-- Setze Fuel
if GetResourceState(Config.FuelSystem) == 'started' then
exports[Config.FuelSystem]:SetFuel(vehicle, data.fuel or 100)
2025-08-06 18:07:18 +02:00
end
2025-08-06 18:18:04 +02:00
-- Verhindere Despawn
PreventDespawn(vehicle)
-- Füge zu getrackten Fahrzeugen hinzu
trackedVehicles[data.plate] = vehicle
2025-08-06 18:32:55 +02:00
lastKnownCoords[data.plate] = GetEntityCoords(vehicle)
-- Registriere beim Server
2025-08-06 18:50:02 +02:00
TriggerServerEvent('antidespawn:server:registerVehicle', data.plate, modelHash, GetEntityCoords(vehicle), GetEntityHeading(vehicle), GetVehicleMods(vehicle))
2025-08-06 18:18:04 +02:00
Debug("Fahrzeug erfolgreich gespawnt: " .. data.plate)
else
Debug("Fehler beim Spawnen des Fahrzeugs: " .. data.plate)
2025-08-06 17:33:26 +02:00
end
2025-08-06 18:18:04 +02:00
SetModelAsNoLongerNeeded(modelHash)
else
2025-08-06 19:16:18 +02:00
Debug("Modell konnte nicht geladen werden: " .. data.plate .. " (Hash: " .. tostring(modelHash) .. ")")
2025-08-06 17:33:26 +02:00
end
end)
2025-08-06 18:50:02 +02:00
-- 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
2025-08-07 13:02:53 +02:00
SetTimeout(10000, function()
if garagePending[plate] then
Debug("Garage storage timeout for vehicle: " .. plate)
garagePending[plate] = nil
end
end)
2025-08-06 18:50:02 +02:00
-- 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)
2025-08-06 17:33:26 +02:00
-- jg-advanced-garage Events
RegisterNetEvent('jg-advancedgarages:client:vehicle-stored', function(data)
2025-08-06 18:50:02 +02:00
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
2025-08-06 19:45:59 +02:00
-- Entferne aus Datenbank
TriggerServerEvent('antidespawn:server:removeVehicle', data.plate)
Debug("Fahrzeug in Garage gespeichert, aus DB entfernt: " .. data.plate)
2025-08-06 17:33:26 +02:00
end
end)
2025-08-06 18:32:55 +02:00
RegisterNetEvent('jg-advancedgarages:client:vehicle-spawned', function(data)
if data and data.plate then
2025-08-06 18:50:02 +02:00
-- Entferne Markierung "in Garage"
garagePending[data.plate] = nil
2025-08-06 18:32:55 +02:00
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)
2025-08-07 08:57:28 +02:00
-- Öffnen der Garage
2025-08-06 18:50:02 +02:00
RegisterNetEvent('jg-advancedgarages:client:open-garage', function(garageId, vehicleType, spawnCoords)
Debug("Garage geöffnet: " .. garageId)
2025-08-06 18:32:55 +02:00
2025-08-07 08:57:28 +02:00
-- No need to mark vehicles as potentially being stored here
-- Let the actual store-vehicle event handle this
2025-08-06 18:32:55 +02:00
end)
2025-08-06 19:45:59 +02:00
-- Manuelle Lade-Funktion
RegisterCommand('loadvehicles', function()
Debug("Manuelles Laden der Fahrzeuge...")
TriggerServerEvent('antidespawn:server:loadVehicles')
end, false)
2025-08-06 18:32:55 +02:00
-- Debug Command
RegisterCommand('fixvehicle', function()
local playerPed = PlayerPedId()
local vehicle = GetVehiclePedIsIn(playerPed, false)
if vehicle ~= 0 then
local plate = QBCore.Functions.GetPlate(vehicle)
2025-08-07 13:21:12 +02:00
-- Anti-Duplication: Check if this plate already exists multiple times
if DoesVehicleExistInWorld(plate) then
Debug("Anti-Dupe: Detected duplicate vehicle with plate " .. plate .. ", not fixing")
return
end
2025-08-06 18:50:02 +02:00
-- Prüfe ob Fahrzeug gerade in die Garage gestellt wird
if not garagePending[plate] then
2025-08-07 13:21:12 +02:00
-- Check if player owns this vehicle
if DoesPlayerOwnVehicle(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 gehört nicht dem Spieler, kann nicht fixiert werden: " .. plate)
end
2025-08-06 18:50:02 +02:00
else
Debug("Fahrzeug wird gerade in Garage gestellt, kann nicht fixiert werden: " .. plate)
end
2025-08-06 18:32:55 +02:00
else
Debug("Du musst in einem Fahrzeug sitzen!")
end
end, false)
2025-08-07 13:21:12 +02:00
-- Server-side event handler for ownership verification
RegisterNetEvent('antidespawn:client:vehicleOwnershipResult', function(result, plate)
-- This event is handled by the DoesPlayerOwnVehicle function
end)
-- Clean up resources when script stops
2025-08-06 17:33:26 +02:00
AddEventHandler('onResourceStop', function(resourceName)
if resourceName == GetCurrentResourceName() then
2025-08-07 08:57:28 +02:00
Debug("Resource stopping, clearing all data")
2025-08-06 18:18:04 +02:00
trackedVehicles = {}
2025-08-06 18:32:55 +02:00
lastKnownCoords = {}
2025-08-06 18:50:02 +02:00
garagePending = {}
2025-08-07 13:21:12 +02:00
spawnedVehicles = {}
vehicleOwnership = {}
2025-08-06 17:33:26 +02:00
end
end)
2025-08-07 13:21:12 +02:00
-- Debug command to check vehicle duplication
RegisterCommand('checkdupes', function()
local vehicles = GetGamePool('CVehicle')
local plates = {}
local dupes = {}
for _, vehicle in pairs(vehicles) do
local plate = QBCore.Functions.GetPlate(vehicle)
if plates[plate] then
if not dupes[plate] then
dupes[plate] = 2
else
dupes[plate] = dupes[plate] + 1
end
else
plates[plate] = true
end
end
local dupeCount = 0
for plate, count in pairs(dupes) do
Debug("Duplicate found: " .. plate .. " (Count: " .. count .. ")")
dupeCount = dupeCount + 1
end
if dupeCount == 0 then
Debug("No duplicate vehicles found")
else
Debug("Found " .. dupeCount .. " duplicate vehicles")
end
end, false)
-- Debug command to clear recently spawned vehicles list
RegisterCommand('clearspawned', function()
spawnedVehicles = {}
Debug("Cleared recently spawned vehicles list")
end, false)
-- Debug command to clear ownership cache
RegisterCommand('clearownership', function()
vehicleOwnership = {}
Debug("Cleared vehicle ownership cache")
end, false)