1
0
Fork 0
forked from Simnation/Main
Main/resources/[test]/nordi_npc_routing/client.lua

278 lines
9.2 KiB
Lua
Raw Permalink Normal View History

2025-06-07 08:51:21 +02:00
-- 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)