1
0
Fork 0
forked from Simnation/Main
This commit is contained in:
Nordi98 2025-07-30 09:14:44 +02:00
parent be80d40d6d
commit 9a0756773b
2 changed files with 448 additions and 218 deletions

View file

@ -86,9 +86,6 @@ function CallTaxi()
-- Blip für Taxi erstellen (Entity-Blip) -- Blip für Taxi erstellen (Entity-Blip)
CreateTaxiBlips(taxi) CreateTaxiBlips(taxi)
-- Überwachung des Taxi-Fortschritts
MonitorTaxiProgress(taxi, driver, playerCoords)
-- Überwachung der Ankunft -- Überwachung der Ankunft
MonitorTaxiArrival(taxi, driver, playerCoords) MonitorTaxiArrival(taxi, driver, playerCoords)
@ -260,7 +257,6 @@ function GetImprovedTaxiSpawnPosition(playerCoords)
return {x = x, y = y, z = z, w = 0.0} return {x = x, y = y, z = z, w = 0.0}
end end
function SpawnTaxi(coords) function SpawnTaxi(coords)
print("^2[TAXI DEBUG]^7 Spawning taxi at: " .. tostring(coords.x) .. ", " .. tostring(coords.y) .. ", " .. tostring(coords.z)) print("^2[TAXI DEBUG]^7 Spawning taxi at: " .. tostring(coords.x) .. ", " .. tostring(coords.y) .. ", " .. tostring(coords.z))
@ -324,6 +320,14 @@ function SpawnTaxi(coords)
SetVehicleEngineOn(taxi, true, true, false) SetVehicleEngineOn(taxi, true, true, false)
SetVehicleDoorsLocked(taxi, 2) -- Locked initially SetVehicleDoorsLocked(taxi, 2) -- Locked initially
-- Verbesserte Persistenz
SetEntityInvincible(taxi, true)
SetVehicleCanBeVisiblyDamaged(taxi, false)
SetEntityProofs(taxi, true, true, true, true, true, true, true, true)
SetVehicleExplodesOnHighExplosionDamage(taxi, false)
SetVehicleHasBeenOwnedByPlayer(taxi, true)
SetVehicleIsConsideredByPlayer(taxi, true)
-- Taxi-Livery setzen falls verfügbar -- Taxi-Livery setzen falls verfügbar
local liveryCount = GetVehicleLiveryCount(taxi) local liveryCount = GetVehicleLiveryCount(taxi)
if liveryCount > 0 then if liveryCount > 0 then
@ -345,12 +349,347 @@ function SpawnTaxi(coords)
return taxi return taxi
end end
-- Fortgeschrittenes Taxi-Fahrer-Verhaltenssystem
function InitializeTaxiDriverAI(driver, vehicle)
if not driver or not DoesEntityExist(driver) then return end
print("^2[TAXI 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 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 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 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 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 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 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 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 DEBUG]^7 Recovery: Path clear, continuing")
TaxiDriverContinueRoute(driver, vehicle)
else
-- Sonst versuchen zu wenden
print("^3[TAXI 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 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 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
local destination = Entity(vehicle).state.currentDestination
if destination then
-- Versuche einen alternativen Weg zu finden
print("^3[TAXI 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 zur Normalisierung eines Vektors
function norm(vector)
local length = math.sqrt(vector.x * vector.x + vector.y * vector.y + vector.z * vector.z)
if length == 0 then
return vector3(0.0, 0.0, 0.0)
end
return vector3(vector.x / length, vector.y / length, vector.z / length)
end
function SpawnTaxiDriver(vehicle) function SpawnTaxiDriver(vehicle)
print("^2[TAXI DEBUG]^7 Spawning taxi driver...") print("^2[TAXI DEBUG]^7 Spawning taxi driver...")
-- Bessere Fahrer-Models mit Fallbacks -- Bessere Fahrer-Models mit Fallbacks
local driverModels = { local driverModels = {
"A_C_Chimp", -- Affe (erste Wahl) "s_m_y_taxidriver_01", -- Taxi Driver (erste Wahl)
"a_m_y_business_01", -- Business Male "a_m_y_business_01", -- Business Male
"a_m_m_business_01", -- Business Male 2 "a_m_m_business_01", -- Business Male 2
"mp_m_freemode_01", -- Male Freemode "mp_m_freemode_01", -- Male Freemode
@ -411,8 +750,6 @@ function SpawnTaxiDriver(vehicle)
SetEntityAsMissionEntity(driver, true, true) SetEntityAsMissionEntity(driver, true, true)
SetBlockingOfNonTemporaryEvents(driver, true) SetBlockingOfNonTemporaryEvents(driver, true)
SetDriverAbility(driver, 1.0) -- Maximale Fahrfähigkeit
SetDriverAggressiveness(driver, 0.0) -- Minimale Aggressivität
SetPedFleeAttributes(driver, 0, 0) SetPedFleeAttributes(driver, 0, 0)
SetPedCombatAttributes(driver, 17, 1) SetPedCombatAttributes(driver, 17, 1)
SetPedSeeingRange(driver, 0.0) SetPedSeeingRange(driver, 0.0)
@ -420,6 +757,17 @@ function SpawnTaxiDriver(vehicle)
SetPedAlertness(driver, 0) SetPedAlertness(driver, 0)
SetPedKeepTask(driver, true) SetPedKeepTask(driver, true)
-- 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
-- Fahrer-Outfit (nur wenn es ein anpassbarer Ped ist) -- Fahrer-Outfit (nur wenn es ein anpassbarer Ped ist)
if driverHash == GetHashKey("mp_m_freemode_01") then if driverHash == GetHashKey("mp_m_freemode_01") then
print("^2[TAXI DEBUG]^7 Setting driver outfit...") print("^2[TAXI DEBUG]^7 Setting driver outfit...")
@ -494,138 +842,23 @@ end
function NavigateToPlayer(driver, taxi, playerCoords) function NavigateToPlayer(driver, taxi, playerCoords)
print("^2[TAXI DEBUG]^7 Navigating taxi to player...") print("^2[TAXI DEBUG]^7 Navigating taxi to player...")
-- Ziel im Fahrzeug-State speichern für die KI-Logik
Entity(taxi).state.currentDestination = playerCoords
-- Versuche einen guten Wegpunkt in der Nähe des Spielers zu finden -- Versuche einen guten Wegpunkt in der Nähe des Spielers zu finden
local success, nodePos = GetClosestVehicleNodeWithHeading(playerCoords.x, playerCoords.y, playerCoords.z, 1, 3.0, 0) local success, nodePos = GetClosestVehicleNodeWithHeading(playerCoords.x, playerCoords.y, playerCoords.z, 1, 3.0, 0)
if success then if success then
print("^2[TAXI DEBUG]^7 Found good vehicle node near player") print("^2[TAXI DEBUG]^7 Found good vehicle node near player")
-- Zum Wegpunkt fahren -- Zum Wegpunkt fahren
TaskVehicleDriveToCoordLongrange(driver, taxi, nodePos.x, nodePos.y, nodePos.z, 25.0, 786603, 5.0) TaskVehicleDriveToCoordLongrange(driver, taxi, nodePos.x, nodePos.y, nodePos.z, 20.0, 786603, 10.0)
else else
print("^3[TAXI DEBUG]^7 No good vehicle node found, driving directly to player") print("^3[TAXI DEBUG]^7 No good vehicle node found, driving directly to player")
-- Direkt zum Spieler fahren -- Direkt zum Spieler fahren
TaskVehicleDriveToCoordLongrange(driver, taxi, playerCoords.x, playerCoords.y, playerCoords.z, 25.0, 786603, 5.0) TaskVehicleDriveToCoordLongrange(driver, taxi, playerCoords.x, playerCoords.y, playerCoords.z, 20.0, 786603, 10.0)
end
-- Fahrer-Verhalten verbessern
SetDriverAggressiveness(driver, 0.0)
SetDriverAbility(driver, 1.0)
end
function MonitorTaxiProgress(taxi, driver, playerCoords)
print("^2[TAXI DEBUG]^7 Monitoring taxi progress...")
local lastPos = GetEntityCoords(taxi)
local stuckCounter = 0
local maxStuckCount = 20
local totalStuckEvents = 3
local maxTotalStuckEvents = 6
CreateThread(function()
while DoesEntityExist(taxi) and DoesEntityExist(driver) do
Wait(3000)
if not DoesEntityExist(taxi) then
print("^1[TAXI DEBUG]^7 Taxi no longer exists! Taxi ID: " .. tostring(taxi))
if currentTaxi == taxi then
print("^1[TAXI DEBUG]^7 This was the current active taxi")
else
print("^1[TAXI DEBUG]^7 This was NOT the current active taxi. Current taxi: " .. tostring(currentTaxi))
end
return
end
if not DoesEntityExist(driver) then
print("^1[TAXI DEBUG]^7 Driver no longer exists! Driver ID: " .. tostring(driver))
if currentDriver == driver then
print("^1[TAXI DEBUG]^7 This was the current active driver")
else
print("^1[TAXI DEBUG]^7 This was NOT the current active driver. Current driver: " .. tostring(currentDriver))
end
return
end
local currentPos = GetEntityCoords(taxi)
local distanceMoved = #(lastPos - currentPos)
local currentPlayerCoords = GetEntityCoords(PlayerPedId())
local distanceToPlayer = #(currentPos - currentPlayerCoords)
-- If taxi is close to player, we're done monitoring progress
if distanceToPlayer < 15.0 then
print("^2[TAXI DEBUG]^7 Taxi arrived near player, stopping progress monitoring")
return
end
-- Check if taxi is stuck (not moving much)
if distanceMoved < 1.0 then
stuckCounter = stuckCounter + 1
print("^3[TAXI DEBUG]^7 Taxi might be stuck: " .. stuckCounter .. "/" .. maxStuckCount)
-- If stuck for too long, try recovery
if stuckCounter >= maxStuckCount then
totalStuckEvents = totalStuckEvents + 1
print("^1[TAXI DEBUG]^7 Taxi is stuck, attempting recovery #" .. totalStuckEvents)
if totalStuckEvents >= maxTotalStuckEvents then
print("^1[TAXI DEBUG]^7 Too many stuck events, respawning taxi")
lib.notify({
title = 'Taxi Service',
description = 'Dein Taxi steckt fest. Ein neues wird gerufen!',
type = 'warning'
})
-- Despawn current taxi and call a new one
DespawnTaxi()
Wait(1000)
CallTaxi()
return
else
-- Try to recover
RecoverStuckTaxi(taxi, driver, currentPlayerCoords)
stuckCounter = 0
end
end
else
stuckCounter = math.max(0, stuckCounter - 1) -- Gradually reduce counter if moving
end
lastPos = currentPos
end
end)
end
function RecoverStuckTaxi(taxi, driver, playerCoords)
print("^2[TAXI DEBUG]^7 Attempting to recover stuck taxi")
-- Clear current task
ClearPedTasks(driver)
-- Try to back up a bit first
TaskVehicleTempAction(driver, taxi, 8, 2000) -- Reverse
Wait(2000)
-- Try to turn around
TaskVehicleTempAction(driver, taxi, 7, 2000) -- Turn left
Wait(1000)
TaskVehicleTempAction(driver, taxi, 8, 1000) -- Reverse
Wait(1000)
TaskVehicleTempAction(driver, taxi, 6, 2000) -- Turn right
Wait(1000)
-- Try to find a new path
local found, nodePos = GetClosestVehicleNode(playerCoords.x, playerCoords.y, playerCoords.z, 1, 3.0, 0)
if found then
print("^2[TAXI DEBUG]^7 Found new path for recovery")
TaskVehicleDriveToCoordLongrange(driver, taxi, nodePos.x, nodePos.y, nodePos.z, 25.0, 786603, 5.0)
else
-- Direct approach as fallback
print("^3[TAXI DEBUG]^7 Using direct approach for recovery")
TaskVehicleDriveToCoordLongrange(driver, taxi, playerCoords.x, playerCoords.y, playerCoords.z, 25.0, 786603, 5.0)
end end
end end
function MonitorTaxiArrival(taxi, driver, playerCoords) function MonitorTaxiArrival(taxi, driver, playerCoords)
print("^2[TAXI DEBUG]^7 Monitoring taxi arrival...") print("^2[TAXI DEBUG]^7 Monitoring taxi arrival...")
@ -691,8 +924,6 @@ function MonitorTaxiArrival(taxi, driver, playerCoords)
end) end)
end end
-- Event für Einsteigen ins Taxi -- Event für Einsteigen ins Taxi
RegisterNetEvent('taxi:enterTaxi', function() RegisterNetEvent('taxi:enterTaxi', function()
print("^2[TAXI DEBUG]^7 Player entering taxi") print("^2[TAXI DEBUG]^7 Player entering taxi")
@ -870,48 +1101,48 @@ function StartTaxiRide(destination, price)
taxiMeter.currentFare = 0 taxiMeter.currentFare = 0
taxiMeter.pricePerKm = Config.PricePerKm taxiMeter.pricePerKm = Config.PricePerKm
-- Ziel im Fahrzeug-State speichern für die KI-Logik
Entity(currentTaxi).state.currentDestination = destination
-- Zum Ziel fahren mit verbesserter Navigation -- Zum Ziel fahren mit verbesserter Navigation
NavigateToDestination(currentDriver, currentTaxi, destination) local drivingStyle = 786603 -- Normal/Vorsichtig
TaskVehicleDriveToCoordLongrange(currentDriver, currentTaxi, destination.x, destination.y, destination.z, 20.0, drivingStyle, 10.0)
-- Fahrer-Dialog anzeigen
local driverName = Entity(currentTaxi).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
})
-- Fahrt überwachen -- Fahrt überwachen
MonitorTaxiRide(destination, price) MonitorTaxiRide(destination, price)
end end
function NavigateToDestination(driver, taxi, destination)
print("^2[TAXI DEBUG]^7 Navigating to destination...")
-- Versuche einen guten Wegpunkt in der Nähe des Ziels zu finden
local success, nodePos = GetClosestVehicleNodeWithHeading(destination.x, destination.y, destination.z, 1, 3.0, 0)
if success then
print("^2[TAXI DEBUG]^7 Found good vehicle node near destination")
-- Zum Wegpunkt fahren mit verbesserter Fahrweise
TaskVehicleDriveToCoordLongrange(driver, taxi, nodePos.x, nodePos.y, nodePos.z, 25.0, 786603, 5.0)
else
print("^3[TAXI DEBUG]^7 No good vehicle node found, driving directly to destination")
-- Direkt zum Ziel fahren
TaskVehicleDriveToCoordLongrange(driver, taxi, destination.x, destination.y, destination.z, 25.0, 786603, 5.0)
end
-- Fahrer-Verhalten verbessern
SetDriverAggressiveness(driver, 0.0)
SetDriverAbility(driver, 1.0)
end
function MonitorTaxiRide(destination, price) function MonitorTaxiRide(destination, price)
print("^2[TAXI DEBUG]^7 Monitoring taxi ride...") print("^2[TAXI DEBUG]^7 Monitoring taxi ride...")
local lastPos = GetEntityCoords(currentTaxi) local rideTimeout = GetGameTimer() + (10 * 60 * 1000) -- 10 Minuten Timeout
local stuckCounter = 0
local maxStuckCount = 10
local rideTimeout = GetGameTimer() + (10 * 60 * 1000) -- 5 Minuten Timeout
CreateThread(function() CreateThread(function()
while DoesEntityExist(currentTaxi) and DoesEntityExist(currentDriver) do while DoesEntityExist(currentTaxi) and DoesEntityExist(currentDriver) do
local taxiCoords = GetEntityCoords(currentTaxi) local taxiCoords = GetEntityCoords(currentTaxi)
local distance = #(vector3(destination.x, destination.y, destination.z) - taxiCoords) local distance = #(vector3(destination.x, destination.y, destination.z) - taxiCoords)
local distanceMoved = #(lastPos - taxiCoords)
-- Überprüfen ob wir angekommen sind -- Überprüfen ob wir angekommen sind
if distance < 10.0 then if distance < 10.0 then
@ -934,6 +1165,24 @@ function MonitorTaxiRide(destination, price)
destinationBlip = nil destinationBlip = nil
end end
-- Fahrer-Dialog anzeigen
local driverName = Entity(currentTaxi).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 despawnen -- Nach 10 Sekunden Taxi despawnen
SetTimeout(10000, function() SetTimeout(10000, function()
DespawnTaxi() DespawnTaxi()
@ -942,70 +1191,53 @@ function MonitorTaxiRide(destination, price)
break break
end end
-- Überprüfen ob das Taxi stecken geblieben ist -- Überprüfen ob die Fahrt zu lange dauert
if distanceMoved < 1.0 then if GetGameTimer() > rideTimeout then
stuckCounter = stuckCounter + 1 print("^1[TAXI DEBUG]^7 Taxi ride timed out!")
if stuckCounter >= maxStuckCount then -- Berechne verbleibende Distanz
print("^1[TAXI DEBUG]^7 Taxi stuck during ride, attempting recovery") local taxiCoords = GetEntityCoords(currentTaxi)
RecoverStuckTaxi(currentTaxi, currentDriver, vector3(destination.x, destination.y, destination.z)) local remainingDistance = #(vector3(destination.x, destination.y, destination.z) - taxiCoords)
stuckCounter = 0
lib.notify({
title = 'Taxi Service',
description = 'Die Fahrt dauert zu lange. Noch ' .. math.ceil(remainingDistance) .. 'm bis zum Ziel!',
type = 'warning'
})
-- Teleportiere Taxi näher ans Ziel (75% des Weges)
local direction = vector3(
destination.x - taxiCoords.x,
destination.y - taxiCoords.y,
destination.z - taxiCoords.z
)
local normalizedDir = norm(direction)
local teleportDistance = remainingDistance * 0.75
local newPos = vector3(
taxiCoords.x + normalizedDir.x * teleportDistance,
taxiCoords.y + normalizedDir.y * teleportDistance,
taxiCoords.z
)
-- Finde gültige Z-Koordinate
local success, groundZ = GetGroundZFor_3dCoord(newPos.x, newPos.y, newPos.z, true)
if success then
newPos = vector3(newPos.x, newPos.y, groundZ)
end end
else
stuckCounter = math.max(0, stuckCounter - 1) -- Teleportiere Taxi
SetEntityCoords(currentTaxi, newPos.x, newPos.y, newPos.z, false, false, false, false)
-- Neues Timeout setzen (2 Minuten)
rideTimeout = GetGameTimer() + (2 * 60 * 1000)
end end
-- Überprüfen ob die Fahrt zu lange dauert
if GetGameTimer() > rideTimeout then
print("^1[TAXI DEBUG]^7 Taxi ride timed out!")
-- Berechne verbleibende Distanz
local taxiCoords = GetEntityCoords(currentTaxi)
local remainingDistance = #(vector3(destination.x, destination.y, destination.z) - taxiCoords)
lib.notify({
title = 'Taxi Service',
description = 'Die Fahrt dauert zu lange. Noch ' .. math.ceil(remainingDistance) .. 'm bis zum Ziel!',
type = 'warning'
})
-- Teleportiere Taxi näher ans Ziel (75% des Weges)
local direction = vector3(
destination.x - taxiCoords.x,
destination.y - taxiCoords.y,
destination.z - taxiCoords.z
)
local normalizedDir = norm(direction)
local teleportDistance = remainingDistance * 0.75
local newPos = vector3(
taxiCoords.x + normalizedDir.x * teleportDistance,
taxiCoords.y + normalizedDir.y * teleportDistance,
taxiCoords.z
)
-- Finde gültige Z-Koordinate
local success, groundZ = GetGroundZFor_3dCoord(newPos.x, newPos.y, newPos.z, true)
if success then
newPos = vector3(newPos.x, newPos.y, groundZ)
end
-- Teleportiere Taxi
SetEntityCoords(currentTaxi, newPos.x, newPos.y, newPos.z, false, false, false, false)
-- Neues Timeout setzen (2 Minuten)
rideTimeout = GetGameTimer() + (2 * 60 * 1000)
end
lastPos = taxiCoords
Wait(2000) Wait(2000)
end end
end) end)
end end
function SelfDriveTaxi() function SelfDriveTaxi()
print("^2[TAXI DEBUG]^7 Player driving taxi themselves") print("^2[TAXI DEBUG]^7 Player driving taxi themselves")
@ -1031,7 +1263,6 @@ function SelfDriveTaxi()
}) })
end end
function ExitTaxi() function ExitTaxi()
print("^2[TAXI DEBUG]^7 Player exiting taxi") print("^2[TAXI DEBUG]^7 Player exiting taxi")
@ -1054,7 +1285,6 @@ function ExitTaxi()
end) end)
end end
function DespawnTaxi() function DespawnTaxi()
print("^2[TAXI DEBUG]^7 Despawning taxi") print("^2[TAXI DEBUG]^7 Despawning taxi")
@ -1144,7 +1374,6 @@ function CalculateDistanceToCoords(coords)
return #(playerCoords - coords) return #(playerCoords - coords)
end end
-- Command um Taxi zu stoppen -- Command um Taxi zu stoppen
RegisterCommand('stoptaxi', function() RegisterCommand('stoptaxi', function()
if currentTaxi and DoesEntityExist(currentTaxi) then if currentTaxi and DoesEntityExist(currentTaxi) then
@ -1242,7 +1471,6 @@ function EndTaxiRide()
end) end)
end end
-- Thread zum Überwachen des Einsteigens ins Taxi (ohne qb-target) -- Thread zum Überwachen des Einsteigens ins Taxi (ohne qb-target)
CreateThread(function() CreateThread(function()
while true do while true do
@ -1270,7 +1498,6 @@ CreateThread(function()
if IsControlJustReleased(0, 38) then -- E Taste if IsControlJustReleased(0, 38) then -- E Taste
-- Spieler will einsteigen -- Spieler will einsteigen
lib.hideTextUI() lib.hideTextUI()
-- Spieler hinten einsteigen lassen -- Spieler hinten einsteigen lassen
local seatIndex = 1 -- Hinten links local seatIndex = 1 -- Hinten links
if not IsVehicleSeatFree(currentTaxi, 1) then if not IsVehicleSeatFree(currentTaxi, 1) then
@ -1317,3 +1544,6 @@ AddEventHandler('onResourceStop', function(resourceName)
print("^2[TAXI DEBUG]^7 Main cleanup completed") print("^2[TAXI DEBUG]^7 Main cleanup completed")
end end
end) end)

View file

@ -139,7 +139,7 @@ Config.KnownDestinations = {
}, },
{ {
name = "Paleto Bay", name = "Paleto Bay",
coords = vector3(-276.0, 6635.0, 7.5), coords = vector3(-296.31, 6056.98, 31.36),
price = 100 price = 100
}, },
{ {