From 0be79cdd60053c494359f75a2cd4fc919812ed3e Mon Sep 17 00:00:00 2001 From: Nordi98 Date: Wed, 6 Aug 2025 18:50:02 +0200 Subject: [PATCH] ed --- .../nordi_antidespawn/client/main.lua | 351 +++++++++++++++--- .../nordi_antidespawn/server/main.lua | 36 +- 2 files changed, 321 insertions(+), 66 deletions(-) diff --git a/resources/[carscripts]/nordi_antidespawn/client/main.lua b/resources/[carscripts]/nordi_antidespawn/client/main.lua index 2725a0380..e51898065 100644 --- a/resources/[carscripts]/nordi_antidespawn/client/main.lua +++ b/resources/[carscripts]/nordi_antidespawn/client/main.lua @@ -1,6 +1,7 @@ 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) @@ -30,6 +31,184 @@ local function IsVehicleClassAllowed(vehicle) 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 @@ -79,22 +258,31 @@ CreateThread(function() -- Nur wenn Spieler der Fahrer ist (Seat -1) if driver == playerPed and IsVehicleClassAllowed(currentVehicle) then local plate = QBCore.Functions.GetPlate(currentVehicle) - trackedVehicles[plate] = currentVehicle - -- Speichere letzte bekannte Position - lastKnownCoords[plate] = GetEntityCoords(currentVehicle) - - -- Sofort starke Despawn-Verhinderung - PreventDespawn(currentVehicle) - - Debug("Fahrzeug wird nun getrackt: " .. plate) - - -- Registriere Fahrzeug beim Server - local vehicleCoords = GetEntityCoords(currentVehicle) - local vehicleHeading = GetEntityHeading(currentVehicle) - local vehicleModel = GetEntityModel(currentVehicle) - - TriggerServerEvent('antidespawn:server:registerVehicle', plate, vehicleModel, vehicleCoords, vehicleHeading) + -- 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 @@ -108,29 +296,43 @@ CreateThread(function() Wait(5000) -- Alle 5 Sekunden for plate, vehicle in pairs(trackedVehicles) do - if DoesEntityExist(vehicle) then + -- 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) + TriggerServerEvent('antidespawn:server:updateVehicle', plate, vehicleCoords, vehicleHeading, vehicleMods) Debug("Aktualisiere Fahrzeug: " .. plate) else Debug("Fahrzeug existiert nicht mehr: " .. plate) - -- Versuche Fahrzeug wiederherzustellen - if lastKnownCoords[plate] then + -- 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 @@ -144,6 +346,17 @@ RegisterNetEvent('QBCore:Client:OnPlayerLoaded', function() 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) @@ -158,6 +371,12 @@ RegisterNetEvent('antidespawn:client:spawnVehicle', function(data) 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 @@ -187,6 +406,11 @@ RegisterNetEvent('antidespawn:client:spawnVehicle', function(data) -- 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) @@ -200,10 +424,7 @@ RegisterNetEvent('antidespawn:client:spawnVehicle', function(data) lastKnownCoords[data.plate] = GetEntityCoords(vehicle) -- Registriere beim Server - TriggerServerEvent('antidespawn:server:registerVehicle', data.plate, modelHash, GetEntityCoords(vehicle), GetEntityHeading(vehicle)) - - -- Registriere bei jg-advancedgarages als "draußen" - TriggerEvent("jg-advancedgarages:server:register-vehicle-outside", data.plate, NetworkGetNetworkIdFromEntity(vehicle)) + TriggerServerEvent('antidespawn:server:registerVehicle', data.plate, modelHash, GetEntityCoords(vehicle), GetEntityHeading(vehicle), GetVehicleMods(vehicle)) Debug("Fahrzeug erfolgreich gespawnt: " .. data.plate) else @@ -227,18 +448,49 @@ function GetVehicleByPlate(plate) 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 and trackedVehicles[data.plate] then - trackedVehicles[data.plate] = nil - lastKnownCoords[data.plate] = nil - TriggerServerEvent('antidespawn:server:removeVehicle', data.plate) - Debug("Fahrzeug in Garage gespeichert, entferne aus Tracking: " .. data.plate) + 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 @@ -260,8 +512,8 @@ RegisterNetEvent('jg-advancedgarages:client:vehicle-spawned', function(data) end) -- Öffnen der Garage - entferne Tracking für Fahrzeuge in der Nähe -RegisterNetEvent('jg-advancedgarages:client:open-garage', function() - Debug("Garage geöffnet, prüfe Fahrzeuge in der Nähe") +RegisterNetEvent('jg-advancedgarages:client:open-garage', function(garageId, vehicleType, spawnCoords) + Debug("Garage geöffnet: " .. garageId) local playerPos = GetEntityCoords(PlayerPedId()) @@ -271,12 +523,11 @@ RegisterNetEvent('jg-advancedgarages:client:open-garage', function() local vehiclePos = GetEntityCoords(vehicle) local distance = #(playerPos - vehiclePos) - -- Wenn Fahrzeug in der Nähe ist (50m), entferne aus Tracking - -- da es wahrscheinlich in die Garage gestellt wird + -- 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, entferne temporär aus Tracking: " .. plate) - -- Nicht komplett entfernen, nur temporär ignorieren - -- Das Event jg-advancedgarages:client:vehicle-stored wird ausgelöst wenn es eingelagert wird + 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 @@ -289,18 +540,25 @@ RegisterCommand('fixvehicle', function() if vehicle ~= 0 then local plate = QBCore.Functions.GetPlate(vehicle) - 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) - - TriggerServerEvent('antidespawn:server:registerVehicle', plate, vehicleModel, vehicleCoords, vehicleHeading) - - Debug("Anti-Despawn für Fahrzeug aktiviert: " .. plate) + -- 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 @@ -311,5 +569,6 @@ AddEventHandler('onResourceStop', function(resourceName) if resourceName == GetCurrentResourceName() then trackedVehicles = {} lastKnownCoords = {} + garagePending = {} end end) diff --git a/resources/[carscripts]/nordi_antidespawn/server/main.lua b/resources/[carscripts]/nordi_antidespawn/server/main.lua index 160627045..846f96d38 100644 --- a/resources/[carscripts]/nordi_antidespawn/server/main.lua +++ b/resources/[carscripts]/nordi_antidespawn/server/main.lua @@ -18,6 +18,7 @@ CreateThread(function() `coords` longtext NOT NULL, `heading` float NOT NULL, `fuel` int(11) DEFAULT 100, + `mods` longtext DEFAULT NULL, `last_updated` timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `plate` (`plate`) @@ -37,6 +38,7 @@ CreateThread(function() coords = json.decode(vehicle.coords), heading = vehicle.heading, fuel = vehicle.fuel, + mods = json.decode(vehicle.mods), last_updated = vehicle.last_updated } end @@ -45,7 +47,7 @@ CreateThread(function() end) -- Registriere ein Fahrzeug -RegisterNetEvent('antidespawn:server:registerVehicle', function(plate, model, coords, heading) +RegisterNetEvent('antidespawn:server:registerVehicle', function(plate, model, coords, heading, mods) local src = source if not plate or not model or not coords then @@ -65,15 +67,17 @@ RegisterNetEvent('antidespawn:server:registerVehicle', function(plate, model, co coords = coords, heading = heading, fuel = 100, + mods = mods, last_updated = os.time() } - MySQL.query("INSERT INTO vehicle_antidespawn (plate, model, coords, heading, fuel) VALUES (?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE coords = VALUES(coords), heading = VALUES(heading), last_updated = CURRENT_TIMESTAMP", { + MySQL.query("INSERT INTO vehicle_antidespawn (plate, model, coords, heading, fuel, mods) VALUES (?, ?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE coords = VALUES(coords), heading = VALUES(heading), mods = VALUES(mods), last_updated = CURRENT_TIMESTAMP", { plate, model, json.encode(coords), heading, - 100 + 100, + json.encode(mods) }) Debug("Fahrzeug registriert: " .. plate) @@ -81,7 +85,7 @@ RegisterNetEvent('antidespawn:server:registerVehicle', function(plate, model, co end) -- Aktualisiere ein Fahrzeug -RegisterNetEvent('antidespawn:server:updateVehicle', function(plate, coords, heading) +RegisterNetEvent('antidespawn:server:updateVehicle', function(plate, coords, heading, mods) if not vehicles[plate] then return end -- Prüfe ob Fahrzeug in der Garage ist @@ -98,11 +102,13 @@ RegisterNetEvent('antidespawn:server:updateVehicle', function(plate, coords, hea vehicles[plate].coords = coords vehicles[plate].heading = heading + vehicles[plate].mods = mods vehicles[plate].last_updated = os.time() - MySQL.query("UPDATE vehicle_antidespawn SET coords = ?, heading = ?, last_updated = CURRENT_TIMESTAMP WHERE plate = ?", { + MySQL.query("UPDATE vehicle_antidespawn SET coords = ?, heading = ?, mods = ?, last_updated = CURRENT_TIMESTAMP WHERE plate = ?", { json.encode(coords), heading, + json.encode(mods), plate }) @@ -110,19 +116,6 @@ RegisterNetEvent('antidespawn:server:updateVehicle', function(plate, coords, hea end) end) --- Entferne ein Fahrzeug -RegisterNetEvent('antidespawn:server:removeVehicle', function(plate) - if not vehicles[plate] then return end - - vehicles[plate] = nil - - MySQL.query("DELETE FROM vehicle_antidespawn WHERE plate = ?", { - plate - }) - - Debug("Fahrzeug entfernt: " .. plate) -end) - -- Respawn ein Fahrzeug RegisterNetEvent('antidespawn:server:respawnVehicle', function(plate) local src = source @@ -152,7 +145,8 @@ RegisterNetEvent('antidespawn:server:respawnVehicle', function(plate) model = vehicles[plate].model, coords = vehicles[plate].coords, heading = vehicles[plate].heading, - fuel = vehicles[plate].fuel + fuel = vehicles[plate].fuel, + mods = vehicles[plate].mods }) Debug("Fahrzeug Respawn angefordert: " .. plate) @@ -192,7 +186,8 @@ RegisterNetEvent('antidespawn:server:loadVehicles', function() model = vehicle.model, coords = vehicle.coords, heading = vehicle.heading, - fuel = vehicle.fuel + fuel = vehicle.fuel, + mods = vehicle.mods }) Debug("Fahrzeug für Spieler geladen: " .. plate) @@ -201,6 +196,7 @@ RegisterNetEvent('antidespawn:server:loadVehicles', function() end end) + -- Cleanup alte Einträge (älter als 24 Stunden) CreateThread(function() while true do