Update stations.lua
This commit is contained in:
		
							parent
							
								
									9f68c1ebde
								
							
						
					
					
						commit
						be80d40d6d
					
				
					 1 changed files with 452 additions and 161 deletions
				
			
		|  | @ -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) | ||||
|  | ||||
|          | ||||
|      | ||||
|  | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Nordi98
						Nordi98