From be80d40d6d635024263c8bd5ff70516209e7b070 Mon Sep 17 00:00:00 2001 From: Nordi98 Date: Wed, 30 Jul 2025 08:49:39 +0200 Subject: [PATCH] Update stations.lua --- .../[tools]/nordi_taxi/client/stations.lua | 613 +++++++++++++----- 1 file changed, 452 insertions(+), 161 deletions(-) diff --git a/resources/[tools]/nordi_taxi/client/stations.lua b/resources/[tools]/nordi_taxi/client/stations.lua index e61ee24ad..54152ef14 100644 --- a/resources/[tools]/nordi_taxi/client/stations.lua +++ b/resources/[tools]/nordi_taxi/client/stations.lua @@ -257,6 +257,333 @@ function CheckAndRestoreStationVehicles() end end +-- Fortgeschrittenes Taxi-Fahrer-Verhaltenssystem +function InitializeTaxiDriverAI(driver, vehicle) + if not driver or not DoesEntityExist(driver) then return end + + print("^2[TAXI STATIONS DEBUG]^7 Initializing advanced taxi driver AI") + + -- Fahrer-Persönlichkeit und Fähigkeiten zufällig festlegen + local driverData = { + personality = { + patience = math.random(7, 10) / 10, -- 0.7-1.0: Wie geduldig ist der Fahrer + caution = math.random(6, 10) / 10, -- 0.6-1.0: Wie vorsichtig fährt er + speedPreference = math.random(15, 25), -- 15-25: Bevorzugte Geschwindigkeit + trafficRuleCompliance = math.random(8, 10)/10 -- 0.8-1.0: Wie genau hält er Verkehrsregeln ein + }, + state = { + stuckCounter = 0, + lastStuckRecovery = 0, + lastRouteRecalculation = 0, + currentBehavior = "normal", -- normal, cautious, stuck, recovery + lastSpeedCheck = 0, + speedHistory = {}, + lastPositions = {}, + trafficLightWaitStart = 0, + isWaitingAtTrafficLight = false + }, + settings = { + maxStuckCounter = math.random(15, 25), -- Wie lange warten bis Befreiungsversuch + stuckThreshold = 0.5, -- Bewegungsschwelle für Steckenbleiben + checkInterval = 2000, -- Überprüfungsintervall in ms + positionHistorySize = 5, -- Anzahl der zu speichernden Positionen + minRecoveryInterval = 25000, -- Min. Zeit zwischen Befreiungsversuchen + minRouteRecalcInterval = 30000, -- Min. Zeit zwischen Routenneuberechnungen + trafficLightMaxWait = 45000 -- Max. Wartezeit an Ampeln + } + } + + -- Fahrer-Verhalten basierend auf Persönlichkeit einstellen + SetDriverAbility(driver, driverData.personality.caution) + SetDriverAggressiveness(driver, 1.0 - driverData.personality.caution) + + -- Fahrer-Daten im Entity speichern + Entity(vehicle).state.driverData = driverData + + -- Fahrer-Verhalten-Thread starten + CreateThread(function() + local lastPos = GetEntityCoords(vehicle) + local lastCheck = GetGameTimer() + + while DoesEntityExist(vehicle) and DoesEntityExist(driver) do + Wait(driverData.settings.checkInterval) + + local currentTime = GetGameTimer() + local timeDelta = currentTime - lastCheck + lastCheck = currentTime + + -- Aktuelle Position und Geschwindigkeit + local currentPos = GetEntityCoords(vehicle) + local speed = GetEntitySpeed(vehicle) + local distanceMoved = #(lastPos - currentPos) + + -- Position für Historie speichern + table.insert(driverData.state.lastPositions, 1, currentPos) + if #driverData.state.lastPositions > driverData.settings.positionHistorySize then + table.remove(driverData.state.lastPositions) + end + + -- Geschwindigkeit für Historie speichern + table.insert(driverData.state.speedHistory, 1, speed) + if #driverData.state.speedHistory > 5 then + table.remove(driverData.state.speedHistory) + end + + -- Durchschnittsgeschwindigkeit berechnen + local avgSpeed = 0 + for _, s in ipairs(driverData.state.speedHistory) do + avgSpeed = avgSpeed + s + end + avgSpeed = avgSpeed / #driverData.state.speedHistory + + -- Ampel-Erkennung + local isAtTrafficLight = IsVehicleStoppedAtTrafficLights(vehicle) + + -- Ampel-Wartezustand aktualisieren + if isAtTrafficLight and not driverData.state.isWaitingAtTrafficLight then + -- Gerade an Ampel angekommen + driverData.state.isWaitingAtTrafficLight = true + driverData.state.trafficLightWaitStart = currentTime + print("^3[TAXI STATIONS DEBUG]^7 Taxi waiting at traffic light") + elseif isAtTrafficLight and driverData.state.isWaitingAtTrafficLight then + -- Immer noch an Ampel + local waitTime = currentTime - driverData.state.trafficLightWaitStart + + -- Wenn zu lange an Ampel, versuche weiterzufahren (Ampel könnte hängen) + if waitTime > driverData.settings.trafficLightMaxWait then + print("^3[TAXI STATIONS DEBUG]^7 Taxi waited too long at traffic light, trying to continue") + -- Kurz vorwärts fahren um Ampel zu überwinden + TaskVehicleTempAction(driver, vehicle, 1, 2000) -- Forward + Wait(2000) + -- Dann normale Fahrt fortsetzen + TaxiDriverContinueRoute(driver, vehicle) + driverData.state.isWaitingAtTrafficLight = false + end + elseif not isAtTrafficLight and driverData.state.isWaitingAtTrafficLight then + -- Ampel verlassen + driverData.state.isWaitingAtTrafficLight = false + print("^2[TAXI STATIONS DEBUG]^7 Taxi continued after traffic light") + end + + -- Steckenbleiben-Erkennung (nicht an Ampel und kaum Bewegung) + if not isAtTrafficLight and distanceMoved < driverData.settings.stuckThreshold and speed < 0.5 then + driverData.state.stuckCounter = driverData.state.stuckCounter + 1 + + -- Nur alle 5 Zähler-Erhöhungen loggen + if driverData.state.stuckCounter % 5 == 0 then + print("^3[TAXI STATIONS DEBUG]^7 Taxi might be stuck: " .. driverData.state.stuckCounter .. "/" .. driverData.settings.maxStuckCounter) + end + + -- Wenn lange genug steckengeblieben und genug Zeit seit letztem Versuch + if driverData.state.stuckCounter >= driverData.settings.maxStuckCounter and + (currentTime - driverData.state.lastStuckRecovery) > driverData.settings.minRecoveryInterval then + + print("^1[TAXI STATIONS DEBUG]^7 Taxi is stuck, attempting intelligent recovery") + driverData.state.lastStuckRecovery = currentTime + driverData.state.currentBehavior = "recovery" + + -- Intelligente Befreiung basierend auf Umgebung + TaxiDriverIntelligentRecovery(driver, vehicle) + + -- Steckenbleiben-Zähler teilweise zurücksetzen + driverData.state.stuckCounter = math.floor(driverData.settings.maxStuckCounter * 0.4) + end + else + -- Wenn sich das Fahrzeug bewegt oder an einer Ampel steht + if isAtTrafficLight then + -- An Ampel: Zähler langsamer reduzieren + driverData.state.stuckCounter = math.max(0, driverData.state.stuckCounter - 0.2) + else + -- In Bewegung: Zähler reduzieren + driverData.state.stuckCounter = math.max(0, driverData.state.stuckCounter - 1) + + -- Wenn Fahrzeug sich bewegt, aber sehr langsam über längere Zeit + if avgSpeed < 2.0 and driverData.state.stuckCounter > driverData.settings.maxStuckCounter * 0.5 and + (currentTime - driverData.state.lastRouteRecalculation) > driverData.settings.minRouteRecalcInterval then + + print("^3[TAXI STATIONS DEBUG]^7 Taxi moving too slow, recalculating route") + driverData.state.lastRouteRecalculation = currentTime + + -- Route neu berechnen + TaxiDriverRecalculateRoute(driver, vehicle) + end + end + end + + -- Verhalten basierend auf Umgebung anpassen + TaxiDriverAdaptBehavior(driver, vehicle, driverData) + + lastPos = currentPos + end + end) + + return driverData +end + +-- Intelligente Befreiung bei Steckenbleiben +function TaxiDriverIntelligentRecovery(driver, vehicle) + if not DoesEntityExist(vehicle) or not DoesEntityExist(driver) then return end + + -- Aktuelle Position und Umgebung analysieren + local vehicleCoords = GetEntityCoords(vehicle) + local vehicleHeading = GetEntityHeading(vehicle) + local vehicleForwardVector = GetEntityForwardVector(vehicle) + + -- Prüfen ob Hindernisse vorne, hinten, links, rechts + local forwardClear = not IsPositionOccupied( + vehicleCoords.x + vehicleForwardVector.x * 4.0, + vehicleCoords.y + vehicleForwardVector.y * 4.0, + vehicleCoords.z, + 1.0, false, true, false, false, false, 0, false + ) + + local backwardClear = not IsPositionOccupied( + vehicleCoords.x - vehicleForwardVector.x * 4.0, + vehicleCoords.y - vehicleForwardVector.y * 4.0, + vehicleCoords.z, + 1.0, false, true, false, false, false, 0, false + ) + + -- Befreiungsstrategie basierend auf Umgebung + ClearPedTasks(driver) + + if backwardClear then + -- Rückwärts fahren wenn hinten frei + print("^3[TAXI STATIONS DEBUG]^7 Recovery: Backing up") + TaskVehicleTempAction(driver, vehicle, 8, 2000) -- Reverse + Wait(2000) + + if forwardClear then + -- Wenn vorne auch frei, einfach weiterfahren + print("^3[TAXI STATIONS DEBUG]^7 Recovery: Path clear, continuing") + TaxiDriverContinueRoute(driver, vehicle) + else + -- Sonst versuchen zu wenden + print("^3[TAXI STATIONS DEBUG]^7 Recovery: Turning around") + TaskVehicleTempAction(driver, vehicle, 7, 2000) -- Turn left + Wait(1000) + TaskVehicleTempAction(driver, vehicle, 8, 1000) -- Reverse + Wait(1000) + TaskVehicleTempAction(driver, vehicle, 6, 2000) -- Turn right + Wait(1000) + TaxiDriverContinueRoute(driver, vehicle) + end + elseif forwardClear then + -- Wenn nur vorne frei, vorwärts fahren + print("^3[TAXI STATIONS DEBUG]^7 Recovery: Moving forward") + TaskVehicleTempAction(driver, vehicle, 1, 2000) -- Forward + Wait(2000) + TaxiDriverContinueRoute(driver, vehicle) + else + -- Wenn komplett eingeklemmt, versuche zu rütteln + print("^3[TAXI STATIONS DEBUG]^7 Recovery: Trying to wiggle free") + TaskVehicleTempAction(driver, vehicle, 7, 1000) -- Turn left + Wait(1000) + TaskVehicleTempAction(driver, vehicle, 8, 800) -- Reverse + Wait(800) + TaskVehicleTempAction(driver, vehicle, 6, 1000) -- Turn right + Wait(1000) + TaskVehicleTempAction(driver, vehicle, 1, 800) -- Forward + Wait(800) + TaxiDriverContinueRoute(driver, vehicle) + end +end + +-- Route neu berechnen +function TaxiDriverRecalculateRoute(driver, vehicle) + if not DoesEntityExist(vehicle) or not DoesEntityExist(driver) then return end + + -- Aktuelle Zielposition aus dem Fahrzeug-State ermitteln + -- Da wir die nicht direkt auslesen können, nehmen wir an, dass es das aktuelle Ziel ist + local destination = Entity(vehicle).state.currentDestination + + if destination then + -- Versuche einen alternativen Weg zu finden + print("^3[TAXI STATIONS DEBUG]^7 Recalculating route to destination") + + -- Kurz anhalten + TaskVehicleTempAction(driver, vehicle, 27, 1000) -- Stop + Wait(1000) + + -- Neue Route mit leicht geändertem Fahrstil + local drivingStyle = 786603 -- Normal/Vorsichtig + TaskVehicleDriveToCoordLongrange(driver, vehicle, destination.x, destination.y, destination.z, 20.0, drivingStyle, 10.0) + else + -- Wenn kein Ziel bekannt, einfach weiterfahren + TaxiDriverContinueRoute(driver, vehicle) + end +end + +-- Normale Fahrt fortsetzen +function TaxiDriverContinueRoute(driver, vehicle) + if not DoesEntityExist(vehicle) or not DoesEntityExist(driver) then return end + + -- Ziel aus dem Fahrzeug-State holen + local destination = Entity(vehicle).state.currentDestination + + if destination then + -- Zum Ziel fahren mit angepasster Fahrweise + local drivingStyle = 786603 -- Normal/Vorsichtig + TaskVehicleDriveToCoordLongrange(driver, vehicle, destination.x, destination.y, destination.z, 20.0, drivingStyle, 10.0) + else + -- Wenn kein Ziel bekannt, einfach geradeaus fahren + TaskVehicleDriveWander(driver, vehicle, 15.0, 786603) + end +end + +-- Fahrverhalten an Umgebung anpassen +function TaxiDriverAdaptBehavior(driver, vehicle, driverData) + if not DoesEntityExist(vehicle) or not DoesEntityExist(driver) then return end + + -- Aktuelle Geschwindigkeit und Position + local speed = GetEntitySpeed(vehicle) + local vehicleCoords = GetEntityCoords(vehicle) + + -- Verkehrsdichte in der Umgebung prüfen + local vehiclesNearby = 0 + local vehicles = GetGamePool('CVehicle') + for _, otherVehicle in ipairs(vehicles) do + if otherVehicle ~= vehicle then + local otherCoords = GetEntityCoords(otherVehicle) + local distance = #(vehicleCoords - otherCoords) + if distance < 15.0 then + vehiclesNearby = vehiclesNearby + 1 + end + end + end + + -- Verhalten basierend auf Verkehrsdichte anpassen + local targetSpeed = driverData.personality.speedPreference + + if vehiclesNearby > 5 then + -- Viel Verkehr: langsamer und vorsichtiger + targetSpeed = targetSpeed * 0.7 + SetDriverAggressiveness(driver, 0.0) + elseif vehiclesNearby > 2 then + -- Moderater Verkehr: etwas langsamer + targetSpeed = targetSpeed * 0.85 + SetDriverAggressiveness(driver, 0.1) + else + -- Wenig Verkehr: normale Geschwindigkeit + SetDriverAggressiveness(driver, 0.2) + end + + -- Geschwindigkeit anpassen wenn nötig + if math.abs(speed - targetSpeed) > 5.0 then + if speed < targetSpeed then + -- Beschleunigen + TaskVehicleTempAction(driver, vehicle, 23, 500) -- Gentle forward + else + -- Abbremsen + TaskVehicleTempAction(driver, vehicle, 24, 500) -- Gentle brake + end + + -- Nach der Anpassung normale Fahrt fortsetzen + Wait(500) + TaxiDriverContinueRoute(driver, vehicle) + end +end + -- Hilfsfunktion um Spieler-Sitz zu ermitteln function GetPlayerVehicleSeat(ped, vehicle) if not IsPedInVehicle(ped, vehicle, false) then @@ -311,7 +638,6 @@ RegisterNetEvent('taxi:enterStationVehicle', function(data) -- Türen entsperren SetVehicleDoorsLocked(vehicle, 1) - -- Info-Text anzeigen während Fahrer geladen wird print("^2[TAXI STATIONS DEBUG]^7 Showing driver loading text...") lib.showTextUI('🚕 Warte an der Station - Fahrer wird geladen...', { @@ -329,7 +655,7 @@ RegisterNetEvent('taxi:enterStationVehicle', function(data) -- Verschiedene Fahrer-Models versuchen local driverModels = { - "A_C_Chimp", -- Taxi Driver (erste Wahl) + "s_m_y_taxidriver_01", -- Taxi Driver (erste Wahl) "a_m_y_business_01", -- Business Male "a_m_m_business_01", -- Business Male 2 "mp_m_freemode_01", -- Male Freemode @@ -491,34 +817,20 @@ RegisterNetEvent('taxi:enterStationVehicle', function(data) SetPedKeepTask(driver, true) SetBlockingOfNonTemporaryEvents(driver, true) - -- Verbesserte Fahrer-Einstellungen - SetDriverAbility(driver, 1.0) -- Maximale Fahrfähigkeit - SetDriverAggressiveness(driver, 0.0) -- Minimale Aggressivität - SetPedDriveByClipsetHash(driver, GetHashKey("DRIVE_SLOW")) - - -- Fahrer-Outfit (nur wenn es ein anpassbarer Ped ist) - if driverHash == GetHashKey("mp_m_freemode_01") or driverHash == GetHashKey("mp_f_freemode_01") then - print("^2[TAXI STATIONS DEBUG]^7 Setting driver outfit...") - - -- Basis-Outfit für Taxi-Fahrer - SetPedComponentVariation(driver, 8, 15, 0, 0) -- Undershirt - SetPedComponentVariation(driver, 11, 28, 0, 0) -- Jacket - SetPedComponentVariation(driver, 4, 10, 0, 0) -- Pants - SetPedComponentVariation(driver, 6, 10, 0, 0) -- Shoes - SetPedComponentVariation(driver, 1, 0, 0, 0) -- Mask - SetPedComponentVariation(driver, 3, 0, 0, 0) -- Arms - SetPedComponentVariation(driver, 5, 0, 0, 0) -- Bag - SetPedComponentVariation(driver, 7, 0, 0, 0) -- Tie - SetPedComponentVariation(driver, 9, 0, 0, 0) -- Body Armor - SetPedComponentVariation(driver, 10, 0, 0, 0) -- Decals - - -- Zufällige Gesichtsmerkmale - SetPedHeadBlendData(driver, math.random(0, 20), math.random(0, 20), 0, math.random(0, 20), math.random(0, 20), 0, 0.5, 0.5, 0.0, false) - end - + -- Fortgeschrittene KI-ähnliche Fahrer-Logik initialisieren + local driverData = InitializeTaxiDriverAI(driver, vehicle) + + -- Zufälligen Fahrer-Namen generieren + local firstNames = {"Max", "Thomas", "Ali", "Mehmet", "Hans", "Peter", "Klaus", "Michael", "Stefan", "Frank"} + local lastNames = {"Müller", "Schmidt", "Schneider", "Fischer", "Weber", "Meyer", "Wagner", "Becker", "Schulz", "Hoffmann"} + local driverName = firstNames[math.random(#firstNames)] .. " " .. lastNames[math.random(#lastNames)] + + -- Fahrer-Name im Fahrzeug-State speichern + Entity(vehicle).state.driverName = driverName + lib.notify({ title = 'Taxi Service', - description = 'Fahrer bereit - Steige hinten ein', + description = 'Dein Fahrer ' .. driverName .. ' ist bereit - Steige hinten ein', type = 'success' }) end @@ -825,146 +1137,121 @@ function StartStationTaxiRide(stationId, vehicleId, vehicle, driver, destination AddTextComponentString("Taxi Ziel") EndTextCommandSetBlipName(destinationBlip) - -- Zum Ziel fahren mit verbesserter Navigation und geduldiger Fahrweise --- Niedrigere Geschwindigkeit und angepasste Fahrweise -local drivingStyle = 786603 -- Normal/Vorsichtig -TaskVehicleDriveToCoordLongrange(driver, vehicle, destination.x, destination.y, destination.z, 20.0, drivingStyle, 10.0) + -- Ziel im Fahrzeug-State speichern für die KI-Logik + Entity(vehicle).state.currentDestination = destination - -- Fahrt überwachen -CreateThread(function() - local lastPos = GetEntityCoords(vehicle) - local stuckCounter = 0 - local maxStuckCount = 20 -- Erhöht von 5 auf 20 für viel mehr Geduld - local stuckThreshold = 0.5 -- Reduziert von 1.0 auf 0.5 für genauere Erkennung - local checkInterval = 3000 -- Erhöht von 2000 auf 3000 ms für längere Prüfintervalle - local rideTimeout = GetGameTimer() + (8 * 60 * 1000) -- 8 Minuten Timeout (erhöht von 5) - local lastStuckWarning = 0 -- Zeitpunkt der letzten Steckenbleiben-Warnung + -- Zum Ziel fahren mit verbesserter Navigation + local drivingStyle = 786603 -- Normal/Vorsichtig + TaskVehicleDriveToCoordLongrange(driver, vehicle, destination.x, destination.y, destination.z, 20.0, drivingStyle, 10.0) + + -- Fahrer-Dialog anzeigen + local driverName = Entity(vehicle).state.driverName or "Taxi-Fahrer" + local dialogOptions = { + "Ich bringe dich sicher ans Ziel.", + "Schönes Wetter heute, oder?", + "Ich kenne eine Abkürzung.", + "Bist du aus der Gegend?", + "Ich fahre schon seit 15 Jahren Taxi.", + "Entspann dich und genieße die Fahrt." + } + + -- Zufälligen Dialog auswählen und anzeigen + Wait(3000) -- Kurz warten bevor der Fahrer spricht + lib.notify({ + title = driverName, + description = dialogOptions[math.random(#dialogOptions)], + type = 'info', + icon = 'comment', + position = 'top-center', + duration = 5000 + }) - while DoesEntityExist(vehicle) and DoesEntityExist(driver) do - local vehicleCoords = GetEntityCoords(vehicle) - local distance = #(vector3(destination.x, destination.y, destination.z) - vehicleCoords) - local distanceMoved = #(lastPos - vehicleCoords) + -- Fahrt überwachen (vereinfacht, da KI-Logik die meiste Arbeit übernimmt) + CreateThread(function() + local rideTimeout = GetGameTimer() + (8 * 60 * 1000) -- 8 Minuten Timeout - -- Überprüfen ob wir angekommen sind - if distance < 10.0 then - -- Angekommen - TaskVehicleTempAction(driver, vehicle, 27, 3000) + while DoesEntityExist(vehicle) and DoesEntityExist(driver) do + local vehicleCoords = GetEntityCoords(vehicle) + local distance = #(vector3(destination.x, destination.y, destination.z) - vehicleCoords) - print("^2[TAXI STATIONS DEBUG]^7 Arrived at destination") - lib.notify({ - title = 'Taxi Service', - description = 'Du bist angekommen! Preis: $' .. price, - type = 'success' - }) - - -- Bezahlung - TriggerServerEvent('taxi:payFare', price) - - -- Blip entfernen - RemoveBlip(destinationBlip) - - -- Nach 10 Sekunden Taxi zurück zur Station - SetTimeout(10000, function() - ReturnTaxiToStation(stationId, vehicleId, vehicle, driver) - end) - - break - end - - -- Überprüfen ob das Taxi stecken geblieben ist - -- Prüfe auch ob das Fahrzeug steht (Geschwindigkeit nahe 0) - local speed = GetEntitySpeed(vehicle) - local isAtRedLight = IsVehicleStoppedAtTrafficLights(vehicle) - - -- Wenn das Fahrzeug an einer Ampel steht, nicht als steckengeblieben betrachten - if distanceMoved < stuckThreshold and speed < 0.5 and not isAtRedLight then - stuckCounter = stuckCounter + 1 - - -- Nur alle 5 Zähler-Erhöhungen loggen, um Spam zu vermeiden - if stuckCounter % 5 == 0 then - print("^3[TAXI STATIONS DEBUG]^7 Taxi might be stuck: " .. stuckCounter .. "/" .. maxStuckCount) + -- Überprüfen ob wir angekommen sind + if distance < 10.0 then + -- Angekommen + TaskVehicleTempAction(driver, vehicle, 27, 3000) + + print("^2[TAXI STATIONS DEBUG]^7 Arrived at destination") + lib.notify({ + title = 'Taxi Service', + description = 'Du bist angekommen! Preis: $' .. price, + type = 'success' + }) + + -- Bezahlung + TriggerServerEvent('taxi:payFare', price) + + -- Blip entfernen + RemoveBlip(destinationBlip) + + -- Fahrer-Dialog anzeigen + local driverName = Entity(vehicle).state.driverName or "Taxi-Fahrer" + local arrivalDialogs = { + "Wir sind da! Das macht dann $" .. price .. ".", + "Angekommen! $" .. price .. " bitte.", + "Hier sind wir. $" .. price .. ", bargeldlos ist auch möglich.", + "Ziel erreicht! Das macht $" .. price .. "." + } + + lib.notify({ + title = driverName, + description = arrivalDialogs[math.random(#arrivalDialogs)], + type = 'info', + icon = 'comment', + position = 'top-center', + duration = 5000 + }) + + -- Nach 10 Sekunden Taxi zurück zur Station + SetTimeout(10000, function() + ReturnTaxiToStation(stationId, vehicleId, vehicle, driver) + end) + + break end - -- Nur versuchen zu befreien, wenn wirklich lange steckengeblieben - if stuckCounter >= maxStuckCount then - -- Mindestens 30 Sekunden zwischen Befreiungsversuchen warten - local currentTime = GetGameTimer() - if currentTime - lastStuckWarning > 30000 then - lastStuckWarning = currentTime - - print("^1[TAXI STATIONS DEBUG]^7 Taxi stuck during ride, attempting recovery") - - -- Versuche, das Taxi zu befreien - ClearPedTasks(driver) - - -- Rückwärts fahren - TaskVehicleTempAction(driver, vehicle, 8, 2000) -- Reverse - Wait(2000) - - -- Drehen - TaskVehicleTempAction(driver, vehicle, 7, 2000) -- Turn left - Wait(1000) - TaskVehicleTempAction(driver, vehicle, 8, 1000) -- Reverse - Wait(1000) - TaskVehicleTempAction(driver, vehicle, 6, 2000) -- Turn right - Wait(1000) - - -- Neue Route zum Ziel mit geduldiger Fahrweise - local drivingStyle = 786603 -- Normal/Vorsichtig - TaskVehicleDriveToCoordLongrange(driver, vehicle, destination.x, destination.y, destination.z, 20.0, drivingStyle, 10.0) - - -- Steckenbleiben-Zähler zurücksetzen, aber nicht ganz auf 0 - -- So kann ein wirklich festgefahrenes Taxi nach einiger Zeit einen neuen Versuch starten - stuckCounter = maxStuckCount / 2 + -- Überprüfen ob die Fahrt zu lange dauert + if GetGameTimer() > rideTimeout then + print("^1[TAXI STATIONS DEBUG]^7 Taxi ride timed out!") + lib.notify({ + title = 'Taxi Service', + description = 'Die Fahrt dauert zu lange. Wir sind fast da!', + type = 'warning' + }) + + -- Teleportiere Taxi in die Nähe des Ziels + local offset = vector3( + math.random(-20, 20), + math.random(-20, 20), + 0 + ) + local nearDestination = vector3(destination.x, destination.y, destination.z) + offset + + -- Finde gültige Z-Koordinate + local success, groundZ = GetGroundZFor_3dCoord(nearDestination.x, nearDestination.y, nearDestination.z, true) + if success then + nearDestination = vector3(nearDestination.x, nearDestination.y, groundZ) end + + -- Teleportiere Taxi + SetEntityCoords(vehicle, nearDestination.x, nearDestination.y, nearDestination.z, false, false, false, false) + + -- Neues Timeout setzen (1 Minute) + rideTimeout = GetGameTimer() + (60 * 1000) end - else - -- Wenn sich das Fahrzeug bewegt oder an einer Ampel steht, Zähler langsamer reduzieren - if isAtRedLight then - -- An Ampel: Zähler nicht erhöhen, aber auch nicht stark reduzieren - stuckCounter = math.max(0, stuckCounter - 0.2) - else - -- In Bewegung: Zähler reduzieren - stuckCounter = math.max(0, stuckCounter - 1) - end + + Wait(2000) end - - -- Überprüfen ob die Fahrt zu lange dauert - if GetGameTimer() > rideTimeout then - print("^1[TAXI STATIONS DEBUG]^7 Taxi ride timed out!") - lib.notify({ - title = 'Taxi Service', - description = 'Die Fahrt dauert zu lange. Wir sind fast da!', - type = 'warning' - }) - - -- Teleportiere Taxi in die Nähe des Ziels - local offset = vector3( - math.random(-20, 20), - math.random(-20, 20), - 0 - ) - local nearDestination = vector3(destination.x, destination.y, destination.z) + offset - - -- Finde gültige Z-Koordinate - local success, groundZ = GetGroundZFor_3dCoord(nearDestination.x, nearDestination.y, nearDestination.z, true) - if success then - nearDestination = vector3(nearDestination.x, nearDestination.y, groundZ) - end - - -- Teleportiere Taxi - SetEntityCoords(vehicle, nearDestination.x, nearDestination.y, nearDestination.z, false, false, false, false) - - -- Neues Timeout setzen (1 Minute) - rideTimeout = GetGameTimer() + (60 * 1000) - end - - lastPos = vehicleCoords - Wait(checkInterval) - end -end) - - + end) +end function ExitStationTaxi(stationId, vehicleId, vehicle, driver) print("^2[TAXI STATIONS DEBUG]^7 Player exiting station taxi") @@ -1018,8 +1305,9 @@ function ReturnTaxiToStation(stationId, vehicleId, vehicle, driver) -- Zufällige Position in der Nähe der Station finden local stationCoords = Config.TaxiStations[stationId].coords - -- Taxi zur Station zurückfahren lassen - TaskVehicleDriveToCoordLongrange(driver, vehicle, stationCoords.x, stationCoords.y, stationCoords.z, 25.0, 786603, 5.0) + -- Taxi zur Station zurückfahren lassen mit geduldiger Fahrweise + local drivingStyle = 786603 -- Normal/Vorsichtig + TaskVehicleDriveToCoordLongrange(driver, vehicle, stationCoords.x, stationCoords.y, stationCoords.z, 20.0, drivingStyle, 10.0) -- qb-target entfernen während der Fahrt exports['qb-target']:RemoveTargetEntity(vehicle) @@ -1283,3 +1571,6 @@ AddEventHandler('onResourceStop', function(resourceName) end end) + + +