forked from Simnation/Main
278 lines
9.2 KiB
Lua
278 lines
9.2 KiB
Lua
![]() |
-- client.lua
|
||
|
local QBCore = exports['qb-core']:GetCoreObject()
|
||
|
local activeZones = {}
|
||
|
local spawnedProps = {}
|
||
|
local processedVehicles = {}
|
||
|
local menu = false
|
||
|
|
||
|
-- Debug Funktion
|
||
|
function DebugPrint(text)
|
||
|
if Config.Debug then
|
||
|
print('[Traffic Control] ' .. tostring(text))
|
||
|
end
|
||
|
end
|
||
|
|
||
|
-- Hotkey Registration
|
||
|
RegisterKeyMapping('trafficmenu', 'Öffne Verkehrssteuerung', 'keyboard', Config.Hotkey)
|
||
|
|
||
|
RegisterCommand('trafficmenu', function()
|
||
|
local job = QBCore.Functions.GetPlayerData().job
|
||
|
if Config.AllowedJobs[job.name] then
|
||
|
ToggleMenu()
|
||
|
end
|
||
|
end)
|
||
|
|
||
|
function ToggleMenu()
|
||
|
if menu then
|
||
|
CloseMenu()
|
||
|
else
|
||
|
OpenMenu()
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function OpenMenu()
|
||
|
if menu then return end
|
||
|
|
||
|
local job = QBCore.Functions.GetPlayerData().job
|
||
|
if not Config.AllowedJobs[job.name] then
|
||
|
DebugPrint('Keine Berechtigung für Job: ' .. job.name)
|
||
|
return
|
||
|
end
|
||
|
|
||
|
menu = true
|
||
|
SendNUIMessage({
|
||
|
action = "open",
|
||
|
items = Config.Items
|
||
|
})
|
||
|
SetNuiFocus(true, true)
|
||
|
DebugPrint('Menü geöffnet')
|
||
|
end
|
||
|
|
||
|
function CloseMenu()
|
||
|
menu = false
|
||
|
SetNuiFocus(false, false)
|
||
|
SendNUIMessage({
|
||
|
action = "close"
|
||
|
})
|
||
|
DebugPrint('Menü geschlossen')
|
||
|
end
|
||
|
|
||
|
RegisterNUICallback('closeMenu', function(data, cb)
|
||
|
CloseMenu()
|
||
|
cb('ok')
|
||
|
end)
|
||
|
|
||
|
RegisterNUICallback('setPoint', function(data, cb)
|
||
|
local coords = GetEntityCoords(PlayerPedId())
|
||
|
local radius = tonumber(data.radius) or 30.0
|
||
|
|
||
|
local zone = {
|
||
|
coords = coords,
|
||
|
radius = radius
|
||
|
}
|
||
|
|
||
|
table.insert(activeZones, zone)
|
||
|
spawnBarrier(coords, data.item)
|
||
|
|
||
|
CloseMenu()
|
||
|
DebugPrint('Punkt gesetzt bei ' .. vec3(coords.x, coords.y, coords.z))
|
||
|
cb('ok')
|
||
|
end)
|
||
|
|
||
|
function spawnBarrier(coords, itemModel)
|
||
|
DebugPrint('Versuche Barriere zu spawnen: ' .. itemModel)
|
||
|
local prop = CreateObject(GetHashKey(itemModel), coords.x, coords.y, coords.z - 1.0, true, false, false)
|
||
|
if prop and DoesEntityExist(prop) then
|
||
|
PlaceObjectOnGroundProperly(prop)
|
||
|
FreezeEntityPosition(prop, true)
|
||
|
table.insert(spawnedProps, prop)
|
||
|
DebugPrint('Barriere erfolgreich gespawnt')
|
||
|
else
|
||
|
DebugPrint('Fehler beim Spawnen der Barriere')
|
||
|
end
|
||
|
end
|
||
|
|
||
|
-- NPC Steuerung
|
||
|
Citizen.CreateThread(function()
|
||
|
while true do
|
||
|
Citizen.Wait(100)
|
||
|
|
||
|
if #activeZones == 0 then
|
||
|
Citizen.Wait(1000)
|
||
|
goto continue
|
||
|
end
|
||
|
|
||
|
for _, zone in pairs(activeZones) do
|
||
|
local vehicles = GetGamePool('CVehicle')
|
||
|
|
||
|
for _, vehicle in pairs(vehicles) do
|
||
|
if DoesEntityExist(vehicle) then
|
||
|
local vehicleCoords = GetEntityCoords(vehicle)
|
||
|
local distance = #(vehicleCoords - zone.coords)
|
||
|
local detectionRange = zone.radius + 30.0 -- Erkennung 30 Meter vor der Zone
|
||
|
|
||
|
if distance <= detectionRange and not processedVehicles[vehicle] then
|
||
|
local driver = GetPedInVehicleSeat(vehicle, -1)
|
||
|
|
||
|
if DoesEntityExist(driver) and not IsPedAPlayer(driver) then
|
||
|
processedVehicles[vehicle] = true
|
||
|
|
||
|
-- Bremse das Fahrzeug
|
||
|
SetVehicleForwardSpeed(vehicle, 0.0)
|
||
|
TaskVehicleTempAction(driver, vehicle, 27, 1000) -- Bremsaktion
|
||
|
|
||
|
-- Warte kurz
|
||
|
Citizen.Wait(1000)
|
||
|
|
||
|
-- Hole aktuelle Position und Heading
|
||
|
local currentHeading = GetEntityHeading(vehicle)
|
||
|
|
||
|
-- Drehe um 180 Grad
|
||
|
local newHeading = currentHeading + 180.0
|
||
|
if newHeading > 360.0 then
|
||
|
newHeading = newHeading - 360.0
|
||
|
end
|
||
|
|
||
|
-- Führe die Drehung aus
|
||
|
TaskVehicleTempAction(driver, vehicle, 6, 2000) -- Drehe nach links
|
||
|
|
||
|
-- Warte auf Drehung
|
||
|
Citizen.Wait(2000)
|
||
|
|
||
|
-- Fahre weg
|
||
|
local escapePoint = vector3(
|
||
|
vehicleCoords.x - (math.cos(math.rad(currentHeading)) * 100.0),
|
||
|
vehicleCoords.y - (math.sin(math.rad(currentHeading)) * 100.0),
|
||
|
vehicleCoords.z
|
||
|
)
|
||
|
|
||
|
TaskVehicleDriveToCoordLongrange(
|
||
|
driver,
|
||
|
vehicle,
|
||
|
escapePoint.x,
|
||
|
escapePoint.y,
|
||
|
escapePoint.z,
|
||
|
20.0, -- Geschwindigkeit
|
||
|
786603, -- Driving Style
|
||
|
20.0 -- Stopping Range
|
||
|
)
|
||
|
|
||
|
-- Lösche Fahrzeug nach Entfernung
|
||
|
Citizen.SetTimeout(8000, function()
|
||
|
if DoesEntityExist(vehicle) then
|
||
|
local newDist = #(GetEntityCoords(vehicle) - zone.coords)
|
||
|
if newDist > detectionRange * 2 then
|
||
|
DeleteEntity(vehicle)
|
||
|
processedVehicles[vehicle] = nil
|
||
|
end
|
||
|
end
|
||
|
end)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
::continue::
|
||
|
end
|
||
|
end)
|
||
|
|
||
|
-- Cleanup Thread für processedVehicles
|
||
|
Citizen.CreateThread(function()
|
||
|
while true do
|
||
|
Citizen.Wait(30000)
|
||
|
for vehicle, _ in pairs(processedVehicles) do
|
||
|
if not DoesEntityExist(vehicle) then
|
||
|
processedVehicles[vehicle] = nil
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end)
|
||
|
|
||
|
|
||
|
-- Zusätzlicher Thread für Fußgänger
|
||
|
Citizen.CreateThread(function()
|
||
|
while true do
|
||
|
Citizen.Wait(500)
|
||
|
|
||
|
if #activeZones == 0 then
|
||
|
Citizen.Wait(1000)
|
||
|
goto continue
|
||
|
end
|
||
|
|
||
|
for _, zone in pairs(activeZones) do
|
||
|
local peds = GetGamePool('CPed')
|
||
|
|
||
|
for _, ped in pairs(peds) do
|
||
|
if DoesEntityExist(ped) and not IsPedAPlayer(ped) and not IsPedInAnyVehicle(ped, false) then
|
||
|
local pedCoords = GetEntityCoords(ped)
|
||
|
local distance = #(pedCoords - zone.coords)
|
||
|
|
||
|
if distance <= (zone.radius + 10.0) then
|
||
|
-- Berechne Fluchtrichtung
|
||
|
local awayVector = vector3(
|
||
|
pedCoords.x - zone.coords.x,
|
||
|
pedCoords.y - zone.coords.y,
|
||
|
0.0
|
||
|
)
|
||
|
local escapePoint = vector3(
|
||
|
pedCoords.x + (awayVector.x * 2),
|
||
|
pedCoords.y + (awayVector.y * 2),
|
||
|
pedCoords.z
|
||
|
)
|
||
|
|
||
|
-- Lasse Ped weglaufen
|
||
|
ClearPedTasks(ped)
|
||
|
TaskGoStraightToCoord(ped, escapePoint.x, escapePoint.y, escapePoint.z, 2.0, -1, 0.0, 0.0)
|
||
|
|
||
|
-- Lösche Ped nach einer Weile
|
||
|
Citizen.SetTimeout(8000, function()
|
||
|
if DoesEntityExist(ped) then
|
||
|
DeleteEntity(ped)
|
||
|
end
|
||
|
end)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
::continue::
|
||
|
end
|
||
|
end)
|
||
|
|
||
|
-- Cleanup Thread
|
||
|
Citizen.CreateThread(function()
|
||
|
while true do
|
||
|
Citizen.Wait(30000)
|
||
|
for vehicle, _ in pairs(processedVehicles) do
|
||
|
if not DoesEntityExist(vehicle) then
|
||
|
processedVehicles[vehicle] = nil
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end)
|
||
|
|
||
|
-- Cleanup Command und Event
|
||
|
RegisterCommand('trafficclean', function()
|
||
|
local job = QBCore.Functions.GetPlayerData().job
|
||
|
if Config.AllowedJobs[job.name] then
|
||
|
TriggerEvent('traffic:cleanup')
|
||
|
QBCore.Functions.Notify('Verkehrssteuerung zurückgesetzt', 'success')
|
||
|
end
|
||
|
end)
|
||
|
|
||
|
RegisterNetEvent('traffic:cleanup')
|
||
|
AddEventHandler('traffic:cleanup', function()
|
||
|
for _, prop in pairs(spawnedProps) do
|
||
|
if DoesEntityExist(prop) then
|
||
|
DeleteEntity(prop)
|
||
|
end
|
||
|
end
|
||
|
spawnedProps = {}
|
||
|
activeZones = {}
|
||
|
processedVehicles = {}
|
||
|
DebugPrint('Aufräumen abgeschlossen')
|
||
|
end)
|
||
|
|
||
|
|