forked from Simnation/Main
ed
This commit is contained in:
parent
7592bef869
commit
dad50e73dd
5 changed files with 443 additions and 0 deletions
260
resources/[carscripts]/nordi_antidespawn/client/main.lua
Normal file
260
resources/[carscripts]/nordi_antidespawn/client/main.lua
Normal file
|
@ -0,0 +1,260 @@
|
||||||
|
local QBCore = exports['qb-core']:GetCoreObject()
|
||||||
|
local trackedVehicles = {}
|
||||||
|
local playerVehicles = {}
|
||||||
|
|
||||||
|
-- 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
|
||||||
|
|
||||||
|
-- Prüfe ob Fahrzeug einem Spieler gehört
|
||||||
|
local function DoesVehicleBelongToPlayer(plate)
|
||||||
|
-- Verwende jg-advanced-garage Export
|
||||||
|
local vehicleData = exports['jg-advancedgarages']:GetVehicleByPlate(plate)
|
||||||
|
return vehicleData ~= nil
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Hauptloop für Fahrzeugtracking
|
||||||
|
CreateThread(function()
|
||||||
|
while true do
|
||||||
|
Wait(Config.SaveInterval)
|
||||||
|
|
||||||
|
local playerPed = PlayerPedId()
|
||||||
|
local playerCoords = GetEntityCoords(playerPed)
|
||||||
|
|
||||||
|
-- Finde alle Fahrzeuge in der Nähe
|
||||||
|
local vehicles = GetGamePool('CVehicle')
|
||||||
|
|
||||||
|
for _, vehicle in pairs(vehicles) do
|
||||||
|
if DoesEntityExist(vehicle) and IsVehicleClassAllowed(vehicle) then
|
||||||
|
local plate = QBCore.Functions.GetPlate(vehicle)
|
||||||
|
local vehicleCoords = GetEntityCoords(vehicle)
|
||||||
|
local distance = #(playerCoords - vehicleCoords)
|
||||||
|
|
||||||
|
-- Prüfe ob Fahrzeug einem Spieler gehört
|
||||||
|
if DoesVehicleBelongToPlayer(plate) then
|
||||||
|
-- Prüfe ob Fahrzeug nicht zu nah an einer Garage ist
|
||||||
|
local nearGarage = exports['jg-advancedgarages']:IsNearGarage(vehicleCoords, Config.MinGarageDistance)
|
||||||
|
|
||||||
|
if not nearGarage then
|
||||||
|
-- Speichere Fahrzeugdaten
|
||||||
|
local vehicleData = {
|
||||||
|
plate = plate,
|
||||||
|
model = GetDisplayNameFromVehicleModel(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 = exports['LegacyFuel']:GetFuel(vehicle) or 100, -- Anpassen je nach Fuel System
|
||||||
|
mods = GetVehicleMods(vehicle)
|
||||||
|
}
|
||||||
|
|
||||||
|
TriggerServerEvent('vehicle-persistence:server:saveVehiclePosition', vehicleData)
|
||||||
|
trackedVehicles[plate] = vehicle
|
||||||
|
|
||||||
|
-- Verhindere Despawn
|
||||||
|
SetEntityAsMissionEntity(vehicle, true, true)
|
||||||
|
SetVehicleHasBeenOwnedByPlayer(vehicle, true)
|
||||||
|
|
||||||
|
if Config.Debug then
|
||||||
|
print(string.format("Tracking vehicle: %s at distance: %.2f", plate, distance))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- Spawne gespeicherte Fahrzeuge
|
||||||
|
RegisterNetEvent('vehicle-persistence:client:spawnSavedVehicles', function(vehicles)
|
||||||
|
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
|
||||||
|
-- Prüfe ob Position nicht in einer Garage ist
|
||||||
|
local nearGarage = exports['jg-advancedgarages']:IsNearGarage(vector3(position.x, position.y, position.z), Config.MinGarageDistance)
|
||||||
|
|
||||||
|
if not nearGarage then
|
||||||
|
-- Spawne Fahrzeug
|
||||||
|
local modelHash = GetHashKey(vehicleData.model)
|
||||||
|
|
||||||
|
RequestModel(modelHash)
|
||||||
|
while not HasModelLoaded(modelHash) do
|
||||||
|
Wait(100)
|
||||||
|
end
|
||||||
|
|
||||||
|
local vehicle = CreateVehicle(modelHash, position.x, position.y, position.z, rotation.z, true, false)
|
||||||
|
|
||||||
|
if DoesEntityExist(vehicle) then
|
||||||
|
-- Setze Fahrzeugdaten
|
||||||
|
SetVehicleNumberPlateText(vehicle, vehicleData.plate)
|
||||||
|
SetVehicleEngineHealth(vehicle, vehicleData.engine_health)
|
||||||
|
SetVehicleBodyHealth(vehicle, vehicleData.body_health)
|
||||||
|
|
||||||
|
-- Setze Fuel (anpassen je nach System)
|
||||||
|
if exports['LegacyFuel'] then
|
||||||
|
exports['LegacyFuel']:SetFuel(vehicle, vehicleData.fuel)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Setze Mods
|
||||||
|
if vehicleData.mods then
|
||||||
|
local mods = json.decode(vehicleData.mods)
|
||||||
|
SetVehicleMods(vehicle, mods)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Verhindere Despawn
|
||||||
|
SetEntityAsMissionEntity(vehicle, true, true)
|
||||||
|
SetVehicleHasBeenOwnedByPlayer(vehicle, true)
|
||||||
|
|
||||||
|
trackedVehicles[vehicleData.plate] = vehicle
|
||||||
|
|
||||||
|
if Config.Debug then
|
||||||
|
print(string.format("Spawned saved vehicle: %s", vehicleData.plate))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
SetModelAsNoLongerNeeded(modelHash)
|
||||||
|
else
|
||||||
|
-- Entferne aus Datenbank da es zu nah an einer Garage ist
|
||||||
|
TriggerServerEvent('vehicle-persistence:server:removeVehicle', 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(5000) -- Warte bis alles geladen ist
|
||||||
|
TriggerServerEvent('vehicle-persistence:server:loadVehicles')
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- jg-advanced-garage Events
|
||||||
|
RegisterNetEvent('jg-advancedgarages:client:vehicle-stored', function(data)
|
||||||
|
-- Entferne aus Tracking wenn Fahrzeug gespeichert wird
|
||||||
|
if data and data.plate and trackedVehicles[data.plate] then
|
||||||
|
trackedVehicles[data.plate] = nil
|
||||||
|
if Config.Debug then
|
||||||
|
print(string.format("Vehicle stored, removed from tracking: %s", data.plate))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
RegisterNetEvent('jg-advancedgarages:client:vehicle-spawned', function(data)
|
||||||
|
-- Entferne aus Tracking da Fahrzeug jetzt über Garage gespawnt wurde
|
||||||
|
if data and data.plate and trackedVehicles[data.plate] then
|
||||||
|
trackedVehicles[data.plate] = nil
|
||||||
|
if Config.Debug then
|
||||||
|
print(string.format("Vehicle spawned from garage, removed from tracking: %s", data.plate))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- Cleanup beim Disconnect
|
||||||
|
AddEventHandler('onResourceStop', function(resourceName)
|
||||||
|
if resourceName == GetCurrentResourceName() then
|
||||||
|
-- Cleanup Code hier falls nötig
|
||||||
|
trackedVehicles = {}
|
||||||
|
end
|
||||||
|
end)
|
40
resources/[carscripts]/nordi_antidespawn/config.lua
Normal file
40
resources/[carscripts]/nordi_antidespawn/config.lua
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
Config = {}
|
||||||
|
|
||||||
|
-- Speicherintervall in Millisekunden (5000 = 5 Sekunden)
|
||||||
|
Config.SaveInterval = 5000
|
||||||
|
|
||||||
|
-- Maximale Distanz zum Fahrzeug bevor es als "verlassen" gilt
|
||||||
|
Config.MaxDistance = 100.0
|
||||||
|
|
||||||
|
-- Debug Modus
|
||||||
|
Config.Debug = false
|
||||||
|
|
||||||
|
-- Fahrzeugklassen die gespeichert werden sollen
|
||||||
|
Config.AllowedVehicleClasses = {
|
||||||
|
0, -- Compacts
|
||||||
|
1, -- Sedans
|
||||||
|
2, -- SUVs
|
||||||
|
3, -- Coupes
|
||||||
|
4, -- Muscle
|
||||||
|
5, -- Sports Classics
|
||||||
|
6, -- Sports
|
||||||
|
7, -- Super
|
||||||
|
8, -- Motorcycles
|
||||||
|
9, -- Off-road
|
||||||
|
10, -- Industrial
|
||||||
|
11, -- Utility
|
||||||
|
12, -- Vans
|
||||||
|
13, -- Cycles
|
||||||
|
14, -- Boats
|
||||||
|
15, -- Helicopters
|
||||||
|
16, -- Planes
|
||||||
|
17, -- Service
|
||||||
|
18, -- Emergency
|
||||||
|
19, -- Military
|
||||||
|
20, -- Commercial
|
||||||
|
21, -- Trains
|
||||||
|
22, -- Open Wheel
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Mindestdistanz zu Garagen um Fahrzeuge zu tracken
|
||||||
|
Config.MinGarageDistance = 50.0
|
25
resources/[carscripts]/nordi_antidespawn/fxmanifest.lua
Normal file
25
resources/[carscripts]/nordi_antidespawn/fxmanifest.lua
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
fx_version 'cerulean'
|
||||||
|
game 'gta5'
|
||||||
|
|
||||||
|
author 'YourName'
|
||||||
|
description 'Vehicle Persistence System for jg-advanced-garage'
|
||||||
|
version '1.0.0'
|
||||||
|
|
||||||
|
shared_scripts {
|
||||||
|
'config.lua'
|
||||||
|
}
|
||||||
|
|
||||||
|
server_scripts {
|
||||||
|
'@oxmysql/lib/MySQL.lua',
|
||||||
|
'server/main.lua'
|
||||||
|
}
|
||||||
|
|
||||||
|
client_scripts {
|
||||||
|
'client/main.lua'
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
'qb-core',
|
||||||
|
'jg-advancedgarages',
|
||||||
|
'oxmysql'
|
||||||
|
}
|
116
resources/[carscripts]/nordi_antidespawn/server/main.lua
Normal file
116
resources/[carscripts]/nordi_antidespawn/server/main.lua
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
local QBCore = exports['qb-core']:GetCoreObject()
|
||||||
|
|
||||||
|
-- Erstelle Tabelle bei Serverstart
|
||||||
|
CreateThread(function()
|
||||||
|
MySQL.query([[
|
||||||
|
CREATE TABLE IF NOT EXISTS `vehicle_positions` (
|
||||||
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`plate` varchar(50) NOT NULL,
|
||||||
|
`citizenid` varchar(50) NOT NULL,
|
||||||
|
`model` varchar(50) NOT NULL,
|
||||||
|
`position` longtext NOT NULL,
|
||||||
|
`rotation` longtext NOT NULL,
|
||||||
|
`engine_health` float DEFAULT 1000.0,
|
||||||
|
`body_health` float DEFAULT 1000.0,
|
||||||
|
`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`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||||
|
]])
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- Speichere Fahrzeugposition
|
||||||
|
RegisterNetEvent('vehicle-persistence:server:saveVehiclePosition', function(vehicleData)
|
||||||
|
local src = source
|
||||||
|
local Player = QBCore.Functions.GetPlayer(src)
|
||||||
|
|
||||||
|
if not Player then return end
|
||||||
|
|
||||||
|
local query = [[
|
||||||
|
INSERT INTO vehicle_positions (plate, citizenid, model, position, rotation, engine_health, body_health, fuel, mods)
|
||||||
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
|
ON DUPLICATE KEY UPDATE
|
||||||
|
position = VALUES(position),
|
||||||
|
rotation = VALUES(rotation),
|
||||||
|
engine_health = VALUES(engine_health),
|
||||||
|
body_health = VALUES(body_health),
|
||||||
|
fuel = VALUES(fuel),
|
||||||
|
mods = VALUES(mods),
|
||||||
|
last_updated = CURRENT_TIMESTAMP
|
||||||
|
]]
|
||||||
|
|
||||||
|
MySQL.insert(query, {
|
||||||
|
vehicleData.plate,
|
||||||
|
Player.PlayerData.citizenid,
|
||||||
|
vehicleData.model,
|
||||||
|
json.encode(vehicleData.position),
|
||||||
|
json.encode(vehicleData.rotation),
|
||||||
|
vehicleData.engineHealth,
|
||||||
|
vehicleData.bodyHealth,
|
||||||
|
vehicleData.fuel,
|
||||||
|
json.encode(vehicleData.mods)
|
||||||
|
})
|
||||||
|
|
||||||
|
if Config.Debug then
|
||||||
|
print(string.format("Saved vehicle position for plate: %s", vehicleData.plate))
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- Lade gespeicherte Fahrzeuge beim Serverstart
|
||||||
|
RegisterNetEvent('vehicle-persistence:server:loadVehicles', function()
|
||||||
|
local src = source
|
||||||
|
local Player = QBCore.Functions.GetPlayer(src)
|
||||||
|
|
||||||
|
if not Player then return end
|
||||||
|
|
||||||
|
MySQL.query('SELECT * FROM vehicle_positions WHERE citizenid = ?', {
|
||||||
|
Player.PlayerData.citizenid
|
||||||
|
}, function(result)
|
||||||
|
if result and #result > 0 then
|
||||||
|
TriggerClientEvent('vehicle-persistence:client:spawnSavedVehicles', src, result)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- Entferne Fahrzeug aus Datenbank
|
||||||
|
RegisterNetEvent('vehicle-persistence:server:removeVehicle', function(plate)
|
||||||
|
MySQL.execute('DELETE FROM vehicle_positions WHERE plate = ?', {plate})
|
||||||
|
|
||||||
|
if Config.Debug then
|
||||||
|
print(string.format("Removed vehicle from persistence: %s", plate))
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- Cleanup alte Einträge (älter als 24 Stunden)
|
||||||
|
CreateThread(function()
|
||||||
|
while true do
|
||||||
|
Wait(3600000) -- 1 Stunde
|
||||||
|
MySQL.execute('DELETE FROM vehicle_positions WHERE last_updated < DATE_SUB(NOW(), INTERVAL 24 HOUR)')
|
||||||
|
if Config.Debug then
|
||||||
|
print("Cleaned up old vehicle positions")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- jg-advanced-garage Events
|
||||||
|
RegisterNetEvent('jg-advancedgarages:server:vehicle-stored', function(data)
|
||||||
|
-- Entferne Fahrzeug aus Persistence wenn es in Garage gespeichert wird
|
||||||
|
if data and data.plate then
|
||||||
|
TriggerEvent('vehicle-persistence:server:removeVehicle', data.plate)
|
||||||
|
if Config.Debug then
|
||||||
|
print(string.format("Vehicle stored in garage, removed from persistence: %s", data.plate))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
RegisterNetEvent('jg-advancedgarages:server:vehicle-spawned', function(data)
|
||||||
|
-- Entferne aus Persistence da Fahrzeug jetzt über Garage gespawnt wurde
|
||||||
|
if data and data.plate then
|
||||||
|
TriggerEvent('vehicle-persistence:server:removeVehicle', data.plate)
|
||||||
|
if Config.Debug then
|
||||||
|
print(string.format("Vehicle spawned from garage, removed from persistence: %s", data.plate))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
|
@ -19,6 +19,8 @@ config.maxStacks = {
|
||||||
weapon_petrolcan = 1,
|
weapon_petrolcan = 1,
|
||||||
printerdocument = 1,
|
printerdocument = 1,
|
||||||
plastic_box = 1,
|
plastic_box = 1,
|
||||||
|
vehiclekeys = 1,
|
||||||
|
keyring = 1,
|
||||||
|
|
||||||
c_necklace = 1,
|
c_necklace = 1,
|
||||||
c_bproof = 1,
|
c_bproof = 1,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue