2025-07-30 02:17:38 +02:00
local QBCore = exports [ ' qb-core ' ] : GetCoreObject ( )
local currentTaxi = nil
2025-07-30 03:21:38 +02:00
local currentDriver = nil
2025-07-30 02:17:38 +02:00
local taxiBlip = nil
2025-07-30 04:08:22 +02:00
local mapBlip = nil
2025-07-30 02:17:38 +02:00
local destinationBlip = nil
2025-07-30 03:21:38 +02:00
local taxiMeter = {
isRunning = false ,
startCoords = nil ,
currentFare = 0 ,
pricePerKm = 0
}
2025-07-30 02:17:38 +02:00
2025-07-30 03:21:38 +02:00
print ( " ^2[TAXI DEBUG]^7 Main script loaded " )
2025-07-30 02:46:15 +02:00
2025-07-30 03:21:38 +02:00
-- Taxi rufen Command
2025-07-30 02:17:38 +02:00
RegisterCommand ( ' taxi ' , function ( )
2025-07-30 03:21:38 +02:00
print ( " ^2[TAXI DEBUG]^7 Taxi command executed " )
2025-07-30 02:46:15 +02:00
2025-07-30 03:21:38 +02:00
if currentTaxi and DoesEntityExist ( currentTaxi ) then
2025-07-30 02:46:15 +02:00
print ( " ^1[TAXI DEBUG]^7 Taxi already exists " )
2025-07-30 02:17:38 +02:00
lib.notify ( {
title = ' Taxi Service ' ,
description = ' Du hast bereits ein Taxi gerufen ' ,
type = ' error '
} )
return
end
2025-07-30 03:21:38 +02:00
CallTaxi ( )
2025-07-30 02:17:38 +02:00
end )
2025-07-30 03:21:38 +02:00
function CallTaxi ( )
print ( " ^2[TAXI DEBUG]^7 CallTaxi function started " )
2025-07-30 02:17:38 +02:00
lib.notify ( {
title = ' Taxi Service ' ,
2025-07-30 03:21:38 +02:00
description = ' Taxi wird gerufen... ' ,
type = ' info '
2025-07-30 02:17:38 +02:00
} )
2025-07-30 03:21:38 +02:00
2025-07-30 02:17:38 +02:00
CreateThread ( function ( )
local playerPed = PlayerPedId ( )
local playerCoords = GetEntityCoords ( playerPed )
2025-07-30 03:21:38 +02:00
2025-07-30 02:46:15 +02:00
print ( " ^2[TAXI DEBUG]^7 Player coords: " .. tostring ( playerCoords ) )
2025-07-30 05:48:24 +02:00
-- Verbesserte Spawn-Position für Taxi finden
local spawnCoords = GetImprovedTaxiSpawnPosition ( playerCoords )
2025-07-30 03:21:38 +02:00
if not spawnCoords then
print ( " ^1[TAXI DEBUG]^7 No spawn position found " )
lib.notify ( {
title = ' Taxi Service ' ,
description = ' Kein geeigneter Spawn-Punkt gefunden ' ,
type = ' error '
} )
2025-07-30 02:46:15 +02:00
return
end
2025-07-30 02:17:38 +02:00
2025-07-30 05:48:24 +02:00
print ( " ^2[TAXI DEBUG]^7 Spawn coords found: " .. tostring ( spawnCoords.x ) .. " , " .. tostring ( spawnCoords.y ) .. " , " .. tostring ( spawnCoords.z ) )
2025-07-30 02:17:38 +02:00
2025-07-30 03:21:38 +02:00
-- Taxi spawnen
local taxi = SpawnTaxi ( spawnCoords )
if not taxi then
print ( " ^1[TAXI DEBUG]^7 Failed to spawn taxi " )
lib.notify ( {
title = ' Taxi Service ' ,
description = ' Taxi konnte nicht gespawnt werden ' ,
type = ' error '
} )
return
2025-07-30 02:17:38 +02:00
end
2025-07-30 02:46:15 +02:00
2025-07-30 03:21:38 +02:00
print ( " ^2[TAXI DEBUG]^7 Taxi spawned: " .. taxi )
currentTaxi = taxi
-- Fahrer spawnen
local driver = SpawnTaxiDriver ( taxi )
if driver then
currentDriver = driver
print ( " ^2[TAXI DEBUG]^7 Driver spawned: " .. driver )
2025-07-30 05:48:24 +02:00
-- Verbesserte Navigation zum Spieler
NavigateToPlayer ( driver , taxi , playerCoords )
2025-07-30 03:21:38 +02:00
2025-07-30 04:08:22 +02:00
-- Blip für Taxi erstellen (Entity-Blip)
2025-07-30 05:48:24 +02:00
CreateTaxiBlips ( taxi )
2025-07-30 03:21:38 +02:00
2025-07-30 05:48:24 +02:00
-- Überwachung der Ankunft
MonitorTaxiArrival ( taxi , driver , playerCoords )
2025-07-30 04:08:22 +02:00
2025-07-30 03:21:38 +02:00
lib.notify ( {
title = ' Taxi Service ' ,
2025-07-30 04:08:22 +02:00
description = ' Taxi ist unterwegs zu dir! Verfolge es auf der Karte. ' ,
2025-07-30 03:21:38 +02:00
type = ' success '
} )
else
print ( " ^1[TAXI DEBUG]^7 Failed to spawn driver " )
lib.notify ( {
title = ' Taxi Service ' ,
description = ' Taxi ohne Fahrer gespawnt - Du kannst es selbst fahren ' ,
type = ' warning '
} )
2025-07-30 02:46:15 +02:00
end
2025-07-30 03:21:38 +02:00
end )
end
2025-07-30 02:17:38 +02:00
2025-07-30 05:48:24 +02:00
function GetImprovedTaxiSpawnPosition ( playerCoords )
2025-07-30 06:50:33 +02:00
print ( " ^2[TAXI DEBUG]^7 Finding improved spawn position... " )
2025-07-30 09:27:31 +02:00
-- Minimale und maximale Entfernung zum Spieler
local minAcceptableDistance = 50.0 -- Mindestens 50 Meter entfernt
local maxAcceptableDistance = 150.0 -- Maximal 150 Meter entfernt
2025-07-30 06:50:33 +02:00
local bestPosition = nil
local bestDistance = 999999.0
-- Versuche zuerst einen Straßenknotenpunkt zu finden
local roadPosition = nil
local foundNode = false
local nodePos = vector3 ( 0.0 , 0.0 , 0.0 )
-- Versuche einen Straßenknotenpunkt in optimaler Entfernung zu finden
2025-07-30 09:27:31 +02:00
-- Suche in einem größeren Radius, um mehr Optionen zu haben
2025-07-30 06:50:33 +02:00
foundNode , nodePos = GetClosestVehicleNode ( playerCoords.x , playerCoords.y , playerCoords.z , 1 , 3.0 , 0 )
if foundNode then
local nodeDistance = # ( playerCoords - nodePos )
2025-07-30 09:27:31 +02:00
if nodeDistance >= minAcceptableDistance and nodeDistance <= maxAcceptableDistance then
2025-07-30 06:50:33 +02:00
roadPosition = nodePos
print ( " ^2[TAXI DEBUG]^7 Found road node for spawn at distance: " .. nodeDistance )
return { x = roadPosition.x , y = roadPosition.y , z = roadPosition.z , w = 0.0 }
else
-- Speichern für später, falls wir nichts Besseres finden
2025-07-30 09:27:31 +02:00
if nodeDistance < bestDistance and nodeDistance >= minAcceptableDistance then
2025-07-30 06:50:33 +02:00
bestDistance = nodeDistance
bestPosition = { x = nodePos.x , y = nodePos.y , z = nodePos.z , w = 0.0 }
end
end
end
2025-07-30 09:27:31 +02:00
-- Versuche mehrere Knotenpunkte in verschiedenen Richtungen zu finden
for i = 1 , 8 do
local angle = ( i - 1 ) * 45.0 -- 8 Richtungen (0, 45, 90, 135, 180, 225, 270, 315 Grad)
local searchDistance = ( minAcceptableDistance + maxAcceptableDistance ) / 2
local searchX = playerCoords.x + math.cos ( math.rad ( angle ) ) * searchDistance
local searchY = playerCoords.y + math.sin ( math.rad ( angle ) ) * searchDistance
foundNode , nodePos = GetClosestVehicleNodeWithHeading ( searchX , searchY , playerCoords.z , 1 , 3.0 , 0 )
if foundNode then
local nodeDistance = # ( playerCoords - nodePos )
if nodeDistance >= minAcceptableDistance and nodeDistance <= maxAcceptableDistance then
print ( " ^2[TAXI DEBUG]^7 Found directional node for spawn at distance: " .. nodeDistance .. " in direction " .. angle )
return { x = nodePos.x , y = nodePos.y , z = nodePos.z , w = 0.0 }
else
-- Speichern für später, falls wir nichts Besseres finden
if nodeDistance < bestDistance and nodeDistance >= minAcceptableDistance then
bestDistance = nodeDistance
bestPosition = { x = nodePos.x , y = nodePos.y , z = nodePos.z , w = 0.0 }
end
end
end
end
2025-07-30 06:50:33 +02:00
-- Versuche einen weiteren Knotenpunkt mit größerem Radius
foundNode , nodePos = GetClosestMajorVehicleNode ( playerCoords.x , playerCoords.y , playerCoords.z , 100.0 , 0 )
if foundNode then
local nodeDistance = # ( playerCoords - nodePos )
2025-07-30 09:27:31 +02:00
if nodeDistance >= minAcceptableDistance and nodeDistance <= maxAcceptableDistance then
2025-07-30 06:50:33 +02:00
roadPosition = nodePos
print ( " ^2[TAXI DEBUG]^7 Found major road node for spawn at distance: " .. nodeDistance )
return { x = roadPosition.x , y = roadPosition.y , z = roadPosition.z , w = 0.0 }
else
-- Speichern für später, falls wir nichts Besseres finden
2025-07-30 09:27:31 +02:00
if nodeDistance < bestDistance and nodeDistance >= minAcceptableDistance then
2025-07-30 06:50:33 +02:00
bestDistance = nodeDistance
bestPosition = { x = nodePos.x , y = nodePos.y , z = nodePos.z , w = 0.0 }
end
end
2025-07-30 09:51:29 +02:00
end
2025-07-30 06:17:38 +02:00
2025-07-30 06:50:33 +02:00
-- Fallback auf Config-Positionen
2025-07-30 05:48:24 +02:00
if Config.MobileTaxiSpawns and # Config.MobileTaxiSpawns > 0 then
-- Alle Spawn-Positionen nach Entfernung sortieren
local sortedSpawns = { }
for i , spawnPos in ipairs ( Config.MobileTaxiSpawns ) do
local distance = # ( playerCoords - vector3 ( spawnPos.x , spawnPos.y , spawnPos.z ) )
2025-07-30 09:27:31 +02:00
if distance >= minAcceptableDistance then
table.insert ( sortedSpawns , {
coords = spawnPos ,
distance = distance
} )
end
2025-07-30 05:48:24 +02:00
end
2025-07-30 02:46:15 +02:00
2025-07-30 09:27:31 +02:00
-- Nach Entfernung sortieren (nächste zuerst, aber mindestens minAcceptableDistance entfernt)
2025-07-30 05:48:24 +02:00
table.sort ( sortedSpawns , function ( a , b )
return a.distance < b.distance
end )
2025-07-30 03:21:38 +02:00
2025-07-30 06:50:33 +02:00
-- Prüfen ob die nächsten Positionen frei und nah genug sind
2025-07-30 05:48:24 +02:00
for i , spawn in ipairs ( sortedSpawns ) do
local spawnCoords = spawn.coords
2025-07-30 06:50:33 +02:00
-- Wenn Position zu weit weg ist, überspringen
if spawn.distance > maxAcceptableDistance then
-- Speichern für später, falls wir nichts Besseres finden
if spawn.distance < bestDistance then
bestDistance = spawn.distance
bestPosition = spawnCoords
end
goto continue
end
2025-07-30 05:48:24 +02:00
-- Prüfen ob Position frei ist
local clearArea = true
local vehicles = GetGamePool ( ' CVehicle ' )
-- Prüfen ob andere Fahrzeuge in der Nähe sind
for _ , vehicle in ipairs ( vehicles ) do
local vehCoords = GetEntityCoords ( vehicle )
if # ( vector3 ( spawnCoords.x , spawnCoords.y , spawnCoords.z ) - vehCoords ) < 5.0 then
clearArea = false
break
end
end
-- Wenn Position frei ist, verwenden
if clearArea then
print ( " ^2[TAXI DEBUG]^7 Using spawn position from config: " .. tostring ( spawnCoords.x ) .. " , " .. tostring ( spawnCoords.y ) .. " , " .. tostring ( spawnCoords.z ) .. " (Distance: " .. spawn.distance .. " m) " )
return spawnCoords
2025-07-30 03:21:38 +02:00
end
2025-07-30 06:50:33 +02:00
:: continue ::
2025-07-30 06:32:52 +02:00
end
end
2025-07-30 09:27:31 +02:00
-- Wenn wir hier sind, haben wir keine ideale Position gefunden
-- Wenn wir eine "beste" Position haben, die den Mindestabstand einhält, verwenden wir diese
if bestPosition and bestDistance >= minAcceptableDistance then
print ( " ^3[TAXI DEBUG]^7 Using best available position at " .. bestDistance .. " m " )
2025-07-30 06:50:33 +02:00
return bestPosition
2025-07-30 06:17:38 +02:00
end
2025-07-30 06:50:33 +02:00
-- Wenn alles fehlschlägt: Generiere eine zufällige Position in der Nähe des Spielers
2025-07-30 09:27:31 +02:00
print ( " ^3[TAXI DEBUG]^7 Generating random position between " .. minAcceptableDistance .. " m and " .. maxAcceptableDistance .. " m of player " )
2025-07-30 06:17:38 +02:00
2025-07-30 09:27:31 +02:00
-- Versuche bis zu 15 Mal, eine gültige Position zu finden
for attempt = 1 , 15 do
-- Zufällige Position im Umkreis, aber mindestens minAcceptableDistance entfernt
2025-07-30 06:17:38 +02:00
local angle = math.random ( ) * 2 * math.pi
2025-07-30 09:27:31 +02:00
local distance = math.random ( minAcceptableDistance , maxAcceptableDistance )
2025-07-30 06:17:38 +02:00
local x = playerCoords.x + math.cos ( angle ) * distance
local y = playerCoords.y + math.sin ( angle ) * distance
local z = playerCoords.z
2025-07-30 02:46:15 +02:00
2025-07-30 06:17:38 +02:00
-- Versuche eine gültige Z-Koordinate zu bekommen
local success , groundZ = GetGroundZFor_3dCoord ( x , y , z , true )
if success then
-- Prüfe ob die Position auf einer Straße ist
local isOnRoad = IsPointOnRoad ( x , y , groundZ )
if isOnRoad then
2025-07-30 06:50:33 +02:00
print ( " ^2[TAXI DEBUG]^7 Found random position on road at distance: " .. distance )
2025-07-30 06:17:38 +02:00
return { x = x , y = y , z = groundZ , w = 0.0 }
end
end
2025-07-30 03:21:38 +02:00
end
2025-07-30 09:27:31 +02:00
-- Absolute Notfall-Fallback: Einfach irgendwo in der Nähe, aber mindestens minAcceptableDistance entfernt
2025-07-30 05:48:24 +02:00
local angle = math.random ( ) * 2 * math.pi
2025-07-30 09:27:31 +02:00
local distance = math.random ( minAcceptableDistance , maxAcceptableDistance )
2025-07-30 05:48:24 +02:00
local x = playerCoords.x + math.cos ( angle ) * distance
local y = playerCoords.y + math.sin ( angle ) * distance
local z = playerCoords.z
-- Versuche eine gültige Z-Koordinate zu bekommen
local success , groundZ = GetGroundZFor_3dCoord ( x , y , z , true )
if success then
z = groundZ
end
2025-07-30 06:50:33 +02:00
print ( " ^3[TAXI DEBUG]^7 Using emergency random spawn position at distance: " .. distance )
2025-07-30 05:48:24 +02:00
return { x = x , y = y , z = z , w = 0.0 }
2025-07-30 03:21:38 +02:00
end
2025-07-30 09:27:31 +02:00
2025-07-30 03:50:38 +02:00
function SpawnTaxi ( coords )
2025-07-30 05:48:24 +02:00
print ( " ^2[TAXI DEBUG]^7 Spawning taxi at: " .. tostring ( coords.x ) .. " , " .. tostring ( coords.y ) .. " , " .. tostring ( coords.z ) )
2025-07-30 03:50:38 +02:00
2025-07-30 04:08:22 +02:00
-- Sicherstellen dass wir ein gültiges Taxi-Model haben
local taxiModel = nil
if Config.TaxiVehicles and # Config.TaxiVehicles > 0 then
2025-07-30 05:48:24 +02:00
-- Zufälliges Taxi-Model aus Config wählen
local randomIndex = math.random ( 1 , # Config.TaxiVehicles )
taxiModel = GetHashKey ( Config.TaxiVehicles [ randomIndex ] . model )
2025-07-30 04:08:22 +02:00
else
taxiModel = GetHashKey ( " taxi " ) -- Fallback
end
2025-07-30 03:50:38 +02:00
print ( " ^2[TAXI DEBUG]^7 Taxi model hash: " .. taxiModel )
2025-07-30 05:48:24 +02:00
-- Model laden mit Timeout
2025-07-30 03:50:38 +02:00
RequestModel ( taxiModel )
2025-07-30 05:48:24 +02:00
local modelLoaded = false
2025-07-30 03:50:38 +02:00
local timeout = GetGameTimer ( ) + 10000
2025-07-30 05:48:24 +02:00
while not modelLoaded and GetGameTimer ( ) < timeout do
modelLoaded = HasModelLoaded ( taxiModel )
if not modelLoaded then
print ( " ^3[TAXI DEBUG]^7 Waiting for taxi model to load... " )
Wait ( 100 )
end
2025-07-30 03:50:38 +02:00
end
2025-07-30 05:48:24 +02:00
if not modelLoaded then
print ( " ^1[TAXI DEBUG]^7 Failed to load taxi model! Trying default model. " )
SetModelAsNoLongerNeeded ( taxiModel )
-- Versuche Standard-Taxi als Fallback
taxiModel = GetHashKey ( " taxi " )
RequestModel ( taxiModel )
timeout = GetGameTimer ( ) + 5000
while not HasModelLoaded ( taxiModel ) and GetGameTimer ( ) < timeout do
Wait ( 100 )
end
if not HasModelLoaded ( taxiModel ) then
print ( " ^1[TAXI DEBUG]^7 Failed to load default taxi model! " )
return nil
end
2025-07-30 03:50:38 +02:00
end
2025-07-30 05:48:24 +02:00
-- Fahrzeug erstellen
local taxi = CreateVehicle ( taxiModel , coords.x , coords.y , coords.z , coords.w or 0.0 , true , false )
2025-07-30 03:50:38 +02:00
if not DoesEntityExist ( taxi ) then
print ( " ^1[TAXI DEBUG]^7 Failed to create taxi vehicle! " )
return nil
end
print ( " ^2[TAXI DEBUG]^7 Taxi created successfully: " .. taxi )
2025-07-30 05:48:24 +02:00
-- Fahrzeug konfigurieren
2025-07-30 03:50:38 +02:00
SetEntityAsMissionEntity ( taxi , true , true )
SetVehicleOnGroundProperly ( taxi )
SetVehicleEngineOn ( taxi , true , true , false )
SetVehicleDoorsLocked ( taxi , 2 ) -- Locked initially
2025-07-30 09:14:44 +02:00
-- 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 )
2025-07-30 03:50:38 +02:00
-- Taxi-Livery setzen falls verfügbar
local liveryCount = GetVehicleLiveryCount ( taxi )
if liveryCount > 0 then
SetVehicleLivery ( taxi , 0 ) -- Erste Livery verwenden
print ( " ^2[TAXI DEBUG]^7 Taxi livery set " )
end
2025-07-30 05:48:24 +02:00
-- Fahrzeug-Extras aktivieren falls vorhanden
for i = 1 , 14 do
if DoesExtraExist ( taxi , i ) then
SetVehicleExtra ( taxi , i , false ) -- Extra aktivieren
end
end
-- Fahrzeug-Farbe setzen (Gelb für Taxis)
SetVehicleColours ( taxi , 88 , 88 ) -- Taxi Yellow
2025-07-30 03:50:38 +02:00
SetModelAsNoLongerNeeded ( taxiModel )
return taxi
end
2025-07-30 03:38:41 +02:00
2025-07-30 09:14:44 +02:00
-- 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
2025-07-30 03:21:38 +02:00
function SpawnTaxiDriver ( vehicle )
print ( " ^2[TAXI DEBUG]^7 Spawning taxi driver... " )
-- Bessere Fahrer-Models mit Fallbacks
local driverModels = {
2025-07-30 09:19:32 +02:00
" A_C_Chimp " , -- Taxi Driver (erste Wahl)
2025-07-30 05:48:24 +02:00
" a_m_y_business_01 " , -- Business Male
" a_m_m_business_01 " , -- Business Male 2
" mp_m_freemode_01 " , -- Male Freemode
" a_m_y_downtown_01 " , -- Downtown Male
" a_m_m_farmer_01 " , -- Farmer
" a_m_y_hipster_01 " , -- Hipster
" a_m_y_beach_01 " -- Beach Guy
2025-07-30 03:21:38 +02:00
}
local driver = nil
local driverHash = nil
-- Versuche verschiedene Models
2025-07-30 05:48:24 +02:00
for i , modelName in ipairs ( driverModels ) do
2025-07-30 03:21:38 +02:00
print ( " ^2[TAXI DEBUG]^7 Trying driver model " .. i .. " : " .. modelName )
driverHash = GetHashKey ( modelName )
2025-07-30 02:17:38 +02:00
2025-07-30 03:21:38 +02:00
-- Model laden
2025-07-30 02:17:38 +02:00
RequestModel ( driverHash )
2025-07-30 03:21:38 +02:00
local timeout = GetGameTimer ( ) + 8000 -- Längere Wartezeit
local attempts = 0
2025-07-30 02:46:15 +02:00
while not HasModelLoaded ( driverHash ) and GetGameTimer ( ) < timeout do
2025-07-30 03:21:38 +02:00
attempts = attempts + 1
if attempts % 10 == 0 then -- Alle 1 Sekunde loggen
print ( " ^3[TAXI DEBUG]^7 Still waiting for model " .. modelName .. " (attempt " .. attempts .. " ) " )
end
2025-07-30 02:17:38 +02:00
Wait ( 100 )
end
2025-07-30 02:46:15 +02:00
2025-07-30 03:21:38 +02:00
if HasModelLoaded ( driverHash ) then
print ( " ^2[TAXI DEBUG]^7 Model " .. modelName .. " loaded successfully after " .. attempts .. " attempts " )
-- Fahrer erstellen
driver = CreatePedInsideVehicle ( vehicle , 26 , driverHash , - 1 , true , false )
if DoesEntityExist ( driver ) then
print ( " ^2[TAXI DEBUG]^7 Driver created successfully with model: " .. modelName .. " (ID: " .. driver .. " ) " )
break
else
print ( " ^1[TAXI DEBUG]^7 Failed to create driver with loaded model: " .. modelName )
SetModelAsNoLongerNeeded ( driverHash )
end
else
print ( " ^1[TAXI DEBUG]^7 Failed to load driver model: " .. modelName )
SetModelAsNoLongerNeeded ( driverHash )
2025-07-30 02:46:15 +02:00
end
2025-07-30 03:21:38 +02:00
end
-- Wenn immer noch kein Fahrer erstellt wurde
if not driver or not DoesEntityExist ( driver ) then
print ( " ^1[TAXI DEBUG]^7 Could not create any driver! Continuing without driver... " )
return nil
end
-- Fahrer konfigurieren
print ( " ^2[TAXI DEBUG]^7 Configuring driver... " )
SetEntityAsMissionEntity ( driver , true , true )
2025-07-30 05:48:24 +02:00
SetBlockingOfNonTemporaryEvents ( driver , true )
2025-07-30 03:21:38 +02:00
SetPedFleeAttributes ( driver , 0 , 0 )
SetPedCombatAttributes ( driver , 17 , 1 )
SetPedSeeingRange ( driver , 0.0 )
SetPedHearingRange ( driver , 0.0 )
SetPedAlertness ( driver , 0 )
SetPedKeepTask ( driver , true )
2025-07-30 09:14:44 +02:00
-- 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
2025-07-30 03:21:38 +02:00
-- Fahrer-Outfit (nur wenn es ein anpassbarer Ped ist)
2025-07-30 05:48:24 +02:00
if driverHash == GetHashKey ( " mp_m_freemode_01 " ) then
2025-07-30 03:21:38 +02:00
print ( " ^2[TAXI DEBUG]^7 Setting driver outfit... " )
-- Basis-Outfit für Taxi-Fahrer
2025-07-30 05:48:24 +02:00
SetPedComponentVariation ( driver , 0 , 0 , 0 , 0 ) -- Face
SetPedComponentVariation ( driver , 2 , 1 , 0 , 0 ) -- Hair
SetPedComponentVariation ( driver , 8 , 15 , 0 , 0 ) -- Undershirt
SetPedComponentVariation ( driver , 11 , 91 , 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
2025-07-30 03:21:38 +02:00
-- 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
-- Model nicht mehr benötigt
if driverHash then
SetModelAsNoLongerNeeded ( driverHash )
end
print ( " ^2[TAXI DEBUG]^7 Driver spawn completed successfully " )
return driver
end
2025-07-30 05:48:24 +02:00
function CreateTaxiBlips ( taxi )
-- Blip für Taxi erstellen (Entity-Blip)
taxiBlip = AddBlipForEntity ( taxi )
SetBlipSprite ( taxiBlip , 198 )
SetBlipColour ( taxiBlip , 5 )
SetBlipScale ( taxiBlip , 0.8 )
SetBlipDisplay ( taxiBlip , 2 ) -- Zeigt auf Minimap und großer Karte
SetBlipShowCone ( taxiBlip , true ) -- Zeigt Sichtkegel
SetBlipAsShortRange ( taxiBlip , false ) -- Immer sichtbar, egal wie weit entfernt
BeginTextCommandSetBlipName ( " STRING " )
AddTextComponentString ( " Dein Taxi " )
EndTextCommandSetBlipName ( taxiBlip )
-- Zusätzlicher Blip auf der Karte für bessere Sichtbarkeit
local taxiCoords = GetEntityCoords ( taxi )
mapBlip = AddBlipForCoord ( taxiCoords.x , taxiCoords.y , taxiCoords.z )
SetBlipSprite ( mapBlip , 198 )
SetBlipColour ( mapBlip , 5 )
SetBlipScale ( mapBlip , 1.0 )
SetBlipDisplay ( mapBlip , 4 ) -- Nur auf großer Karte
BeginTextCommandSetBlipName ( " STRING " )
AddTextComponentString ( " Dein Taxi " )
EndTextCommandSetBlipName ( mapBlip )
-- Blip aktualisieren während Taxi unterwegs ist
CreateThread ( function ( )
while DoesEntityExist ( taxi ) and mapBlip do
local taxiCoords = GetEntityCoords ( taxi )
SetBlipCoords ( mapBlip , taxiCoords.x , taxiCoords.y , taxiCoords.z )
Wait ( 1000 )
end
-- Blip entfernen wenn Thread beendet
if mapBlip then
RemoveBlip ( mapBlip )
mapBlip = nil
end
end )
end
function NavigateToPlayer ( driver , taxi , playerCoords )
print ( " ^2[TAXI DEBUG]^7 Navigating taxi to player... " )
2025-07-30 09:14:44 +02:00
-- Ziel im Fahrzeug-State speichern für die KI-Logik
Entity ( taxi ) . state.currentDestination = playerCoords
2025-07-30 05:48:24 +02:00
-- 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 )
if success then
print ( " ^2[TAXI DEBUG]^7 Found good vehicle node near player " )
-- Zum Wegpunkt fahren
2025-07-30 09:14:44 +02:00
TaskVehicleDriveToCoordLongrange ( driver , taxi , nodePos.x , nodePos.y , nodePos.z , 20.0 , 786603 , 10.0 )
2025-07-30 05:48:24 +02:00
else
print ( " ^3[TAXI DEBUG]^7 No good vehicle node found, driving directly to player " )
-- Direkt zum Spieler fahren
2025-07-30 09:14:44 +02:00
TaskVehicleDriveToCoordLongrange ( driver , taxi , playerCoords.x , playerCoords.y , playerCoords.z , 20.0 , 786603 , 10.0 )
2025-07-30 05:48:24 +02:00
end
2025-07-30 06:03:41 +02:00
end
2025-07-30 05:48:24 +02:00
2025-07-30 03:21:38 +02:00
function MonitorTaxiArrival ( taxi , driver , playerCoords )
print ( " ^2[TAXI DEBUG]^7 Monitoring taxi arrival... " )
2025-07-30 05:48:24 +02:00
local arrivalTimeout = GetGameTimer ( ) + ( 120 * 1000 ) -- 2 minute timeout
2025-07-30 03:21:38 +02:00
CreateThread ( function ( )
while DoesEntityExist ( taxi ) and ( not driver or DoesEntityExist ( driver ) ) do
local taxiCoords = GetEntityCoords ( taxi )
2025-07-30 05:48:24 +02:00
local currentPlayerCoords = GetEntityCoords ( PlayerPedId ( ) )
local distance = # ( currentPlayerCoords - taxiCoords )
2025-07-30 02:17:38 +02:00
2025-07-30 05:48:24 +02:00
-- Check if taxi is close to player
2025-07-30 05:39:51 +02:00
if distance < 15.0 then
2025-07-30 02:46:15 +02:00
print ( " ^2[TAXI DEBUG]^7 Taxi arrived! " )
2025-07-30 03:21:38 +02:00
-- Taxi stoppen
if driver and DoesEntityExist ( driver ) then
TaskVehicleTempAction ( driver , taxi , 27 , 3000 ) -- Brake
Wait ( 2000 )
SetVehicleDoorsLocked ( taxi , 1 ) -- Unlock doors
end
2025-07-30 02:17:38 +02:00
lib.notify ( {
title = ' Taxi Service ' ,
description = ' Dein Taxi ist angekommen! Steige ein. ' ,
type = ' success '
} )
2025-07-30 03:21:38 +02:00
-- qb-target für Einsteigen hinzufügen
exports [ ' qb-target ' ] : AddTargetEntity ( taxi , {
options = {
{
type = " client " ,
event = " taxi:enterTaxi " ,
icon = " fas fa-car-side " ,
label = " Ins Taxi einsteigen "
}
} ,
distance = 3.0
} )
break
2025-07-30 02:17:38 +02:00
end
2025-07-30 03:21:38 +02:00
2025-07-30 05:48:24 +02:00
-- Check for timeout
if GetGameTimer ( ) > arrivalTimeout then
print ( " ^1[TAXI DEBUG]^7 Taxi arrival timed out! " )
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 ( )
break
end
2025-07-30 03:21:38 +02:00
Wait ( 2000 )
2025-07-30 02:17:38 +02:00
end
end )
2025-07-30 05:51:20 +02:00
end
2025-07-30 03:21:38 +02:00
-- Event für Einsteigen ins Taxi
RegisterNetEvent ( ' taxi:enterTaxi ' , function ( )
print ( " ^2[TAXI DEBUG]^7 Player entering taxi " )
2025-07-30 02:46:15 +02:00
2025-07-30 03:21:38 +02:00
if not currentTaxi or not DoesEntityExist ( currentTaxi ) then
print ( " ^1[TAXI DEBUG]^7 No taxi exists " )
return
2025-07-30 02:17:38 +02:00
end
2025-07-30 03:21:38 +02:00
local playerPed = PlayerPedId ( )
2025-07-30 02:17:38 +02:00
2025-07-30 03:21:38 +02:00
-- Spieler hinten einsteigen lassen
local seatIndex = 1 -- Hinten links
if not IsVehicleSeatFree ( currentTaxi , 1 ) then
seatIndex = 2 -- Hinten rechts
end
if not IsVehicleSeatFree ( currentTaxi , seatIndex ) then
seatIndex = 0 -- Beifahrer als Fallback
2025-07-30 02:17:38 +02:00
end
2025-07-30 03:21:38 +02:00
TaskEnterVehicle ( playerPed , currentTaxi , 10000 , seatIndex , 1.0 , 1 , 0 )
-- Warten bis eingestiegen
2025-07-30 02:17:38 +02:00
CreateThread ( function ( )
2025-07-30 03:21:38 +02:00
local timeout = GetGameTimer ( ) + 10000
2025-07-30 04:46:12 +02:00
local entered = false
while GetGameTimer ( ) < timeout and not entered do
2025-07-30 02:17:38 +02:00
if IsPedInVehicle ( playerPed , currentTaxi , false ) then
2025-07-30 04:46:12 +02:00
entered = true
2025-07-30 03:21:38 +02:00
print ( " ^2[TAXI DEBUG]^7 Player entered taxi successfully " )
-- qb-target entfernen
exports [ ' qb-target ' ] : RemoveTargetEntity ( currentTaxi )
lib.notify ( {
title = ' Taxi Service ' ,
description = ' Willkommen im Taxi! Wähle dein Ziel. ' ,
type = ' success '
} )
-- Ziel-Menu öffnen
Wait ( 1000 )
OpenDestinationMenu ( )
2025-07-30 02:17:38 +02:00
end
2025-07-30 03:21:38 +02:00
Wait ( 100 )
2025-07-30 02:17:38 +02:00
end
2025-07-30 04:46:12 +02:00
if not entered then
print ( " ^1[TAXI DEBUG]^7 Player failed to enter taxi " )
lib.notify ( {
title = ' Taxi Service ' ,
description = ' Einsteigen fehlgeschlagen ' ,
type = ' error '
} )
end
2025-07-30 02:17:38 +02:00
end )
2025-07-30 03:21:38 +02:00
end )
2025-07-30 02:17:38 +02:00
2025-07-30 03:21:38 +02:00
function OpenDestinationMenu ( )
print ( " ^2[TAXI DEBUG]^7 Opening destination menu " )
2025-07-30 02:17:38 +02:00
local options = { }
-- Bekannte Ziele hinzufügen
for _ , destination in pairs ( Config.KnownDestinations ) do
2025-07-30 03:21:38 +02:00
local distance = CalculateDistanceToCoords ( destination.coords ) / 1000 -- in km
local price = math.max ( Config.MinFare , math.ceil ( distance * Config.PricePerKm ) )
2025-07-30 02:17:38 +02:00
table.insert ( options , {
title = destination.name ,
2025-07-30 03:21:38 +02:00
description = ' Preis: $ ' .. price .. ' | Entfernung: ' .. math.ceil ( distance * 100 ) / 100 .. ' km ' ,
2025-07-30 02:17:38 +02:00
icon = ' map-marker ' ,
onSelect = function ( )
2025-07-30 03:21:38 +02:00
StartTaxiRide ( destination.coords , price )
2025-07-30 02:17:38 +02:00
end
} )
end
-- Waypoint Option
table.insert ( options , {
title = ' Zu meinem Waypoint ' ,
description = ' Fahre zu deinem gesetzten Waypoint ' ,
icon = ' location-dot ' ,
onSelect = function ( )
local waypoint = GetFirstBlipInfoId ( 8 )
if DoesBlipExist ( waypoint ) then
local coords = GetBlipInfoIdCoord ( waypoint )
2025-07-30 03:21:38 +02:00
local distance = CalculateDistanceToCoords ( coords ) / 1000
local price = math.max ( Config.MinFare , math.ceil ( distance * Config.PricePerKm ) )
StartTaxiRide ( coords , price )
2025-07-30 02:17:38 +02:00
else
lib.notify ( {
title = ' Taxi Service ' ,
description = ' Du hast keinen Waypoint gesetzt ' ,
type = ' error '
} )
2025-07-30 03:21:38 +02:00
OpenDestinationMenu ( )
2025-07-30 02:17:38 +02:00
end
end
} )
2025-07-30 03:21:38 +02:00
-- Selbst fahren Option (wenn kein Fahrer)
if not currentDriver or not DoesEntityExist ( currentDriver ) then
table.insert ( options , {
title = ' 🚗 Selbst fahren ' ,
description = ' Du fährst das Taxi selbst ' ,
icon = ' car ' ,
onSelect = function ( )
SelfDriveTaxi ( )
end
} )
end
2025-07-30 02:17:38 +02:00
-- Aussteigen Option
table.insert ( options , {
title = ' Aussteigen ' ,
description = ' Das Taxi verlassen ' ,
icon = ' door-open ' ,
onSelect = function ( )
2025-07-30 03:21:38 +02:00
ExitTaxi ( )
2025-07-30 02:17:38 +02:00
end
} )
lib.registerContext ( {
2025-07-30 03:21:38 +02:00
id = ' taxi_destination_menu ' ,
2025-07-30 02:17:38 +02:00
title = ' Taxi - Ziel wählen ' ,
options = options
} )
2025-07-30 03:21:38 +02:00
lib.showContext ( ' taxi_destination_menu ' )
2025-07-30 02:17:38 +02:00
end
2025-07-30 03:21:38 +02:00
function StartTaxiRide ( destination , price )
2025-07-30 05:48:24 +02:00
print ( " ^2[TAXI DEBUG]^7 Starting taxi ride to: " .. tostring ( destination.x ) .. " , " .. tostring ( destination.y ) .. " , " .. tostring ( destination.z ) )
2025-07-30 03:21:38 +02:00
if not currentTaxi or not DoesEntityExist ( currentTaxi ) then
print ( " ^1[TAXI DEBUG]^7 No taxi exists for ride " )
return
2025-07-30 02:46:15 +02:00
end
2025-07-30 02:17:38 +02:00
2025-07-30 03:21:38 +02:00
-- Wenn kein Fahrer, Spieler selbst fahren lassen
if not currentDriver or not DoesEntityExist ( currentDriver ) then
lib.notify ( {
title = ' Taxi Service ' ,
description = ' Kein Fahrer verfügbar. Du musst selbst fahren! ' ,
type = ' warning '
} )
return
end
lib.notify ( {
title = ' Taxi Service ' ,
description = ' Fahrt gestartet - Preis: $ ' .. price ,
type = ' success '
} )
2025-07-30 02:17:38 +02:00
-- Destination Blip erstellen
2025-07-30 05:48:24 +02:00
if destinationBlip then
RemoveBlip ( destinationBlip )
end
2025-07-30 02:17:38 +02:00
destinationBlip = AddBlipForCoord ( destination.x , destination.y , destination.z )
SetBlipSprite ( destinationBlip , 1 )
SetBlipColour ( destinationBlip , 2 )
SetBlipScale ( destinationBlip , 0.8 )
2025-07-30 05:48:24 +02:00
SetBlipRoute ( destinationBlip , true )
2025-07-30 02:17:38 +02:00
BeginTextCommandSetBlipName ( " STRING " )
AddTextComponentString ( " Taxi Ziel " )
EndTextCommandSetBlipName ( destinationBlip )
2025-07-30 05:48:24 +02:00
-- Taximeter starten
taxiMeter.isRunning = true
taxiMeter.startCoords = GetEntityCoords ( currentTaxi )
taxiMeter.currentFare = 0
taxiMeter.pricePerKm = Config.PricePerKm
2025-07-30 09:14:44 +02:00
-- Ziel im Fahrzeug-State speichern für die KI-Logik
Entity ( currentTaxi ) . state.currentDestination = destination
2025-07-30 05:48:24 +02:00
-- Zum Ziel fahren mit verbesserter Navigation
2025-07-30 09:14:44 +02:00
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
} )
2025-07-30 03:21:38 +02:00
-- Fahrt überwachen
MonitorTaxiRide ( destination , price )
end
function MonitorTaxiRide ( destination , price )
print ( " ^2[TAXI DEBUG]^7 Monitoring taxi ride... " )
2025-07-30 02:17:38 +02:00
2025-07-30 09:14:44 +02:00
local rideTimeout = GetGameTimer ( ) + ( 10 * 60 * 1000 ) -- 10 Minuten Timeout
2025-07-30 05:48:24 +02:00
2025-07-30 02:17:38 +02:00
CreateThread ( function ( )
2025-07-30 03:21:38 +02:00
while DoesEntityExist ( currentTaxi ) and DoesEntityExist ( currentDriver ) do
2025-07-30 02:17:38 +02:00
local taxiCoords = GetEntityCoords ( currentTaxi )
local distance = # ( vector3 ( destination.x , destination.y , destination.z ) - taxiCoords )
2025-07-30 05:48:24 +02:00
-- Überprüfen ob wir angekommen sind
2025-07-30 02:17:38 +02:00
if distance < 10.0 then
2025-07-30 03:21:38 +02:00
-- Angekommen
TaskVehicleTempAction ( currentDriver , currentTaxi , 27 , 3000 )
2025-07-30 02:17:38 +02:00
2025-07-30 02:46:15 +02:00
print ( " ^2[TAXI DEBUG]^7 Arrived at destination " )
2025-07-30 02:17:38 +02:00
lib.notify ( {
title = ' Taxi Service ' ,
2025-07-30 03:21:38 +02:00
description = ' Du bist angekommen! Preis: $ ' .. price ,
2025-07-30 02:17:38 +02:00
type = ' success '
} )
2025-07-30 03:21:38 +02:00
-- Bezahlung
TriggerServerEvent ( ' taxi:payFare ' , price )
2025-07-30 02:17:38 +02:00
2025-07-30 03:21:38 +02:00
-- Blips entfernen
if destinationBlip then
RemoveBlip ( destinationBlip )
destinationBlip = nil
end
2025-07-30 09:14:44 +02:00
-- 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
} )
2025-07-30 03:21:38 +02:00
-- Nach 10 Sekunden Taxi despawnen
2025-07-30 02:17:38 +02:00
SetTimeout ( 10000 , function ( )
2025-07-30 03:21:38 +02:00
DespawnTaxi ( )
2025-07-30 02:17:38 +02:00
end )
break
end
2025-07-30 09:14:44 +02:00
-- Ü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 )
2025-07-30 05:48:24 +02:00
2025-07-30 09:14:44 +02:00
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 )
2025-07-30 05:48:24 +02:00
end
2025-07-30 09:14:44 +02:00
-- Teleportiere Taxi
SetEntityCoords ( currentTaxi , newPos.x , newPos.y , newPos.z , false , false , false , false )
-- Neues Timeout setzen (2 Minuten)
rideTimeout = GetGameTimer ( ) + ( 2 * 60 * 1000 )
2025-07-30 05:48:24 +02:00
end
2025-07-30 02:17:38 +02:00
Wait ( 2000 )
end
end )
2025-07-30 06:03:41 +02:00
end
2025-07-30 03:21:38 +02:00
function SelfDriveTaxi ( )
print ( " ^2[TAXI DEBUG]^7 Player driving taxi themselves " )
if not currentTaxi or not DoesEntityExist ( currentTaxi ) then
return
end
local playerPed = PlayerPedId ( )
-- Fahrer entfernen falls vorhanden
if currentDriver and DoesEntityExist ( currentDriver ) then
DeleteEntity ( currentDriver )
currentDriver = nil
end
-- Spieler zum Fahrersitz bewegen
TaskShuffleToNextVehicleSeat ( playerPed , currentTaxi )
lib.notify ( {
title = ' Taxi Service ' ,
description = ' Du fährst das Taxi jetzt selbst. Nutze /stoptaxi um es zu beenden. ' ,
type = ' info '
} )
2025-07-30 06:03:41 +02:00
end
2025-07-30 03:21:38 +02:00
function ExitTaxi ( )
2025-07-30 02:46:15 +02:00
print ( " ^2[TAXI DEBUG]^7 Player exiting taxi " )
2025-07-30 03:21:38 +02:00
if not currentTaxi or not DoesEntityExist ( currentTaxi ) then
return
end
2025-07-30 02:17:38 +02:00
local playerPed = PlayerPedId ( )
TaskLeaveVehicle ( playerPed , currentTaxi , 0 )
lib.notify ( {
title = ' Taxi Service ' ,
description = ' Du bist ausgestiegen ' ,
type = ' info '
} )
2025-07-30 03:21:38 +02:00
-- Taxi nach 5 Sekunden despawnen
2025-07-30 02:17:38 +02:00
SetTimeout ( 5000 , function ( )
2025-07-30 03:21:38 +02:00
DespawnTaxi ( )
2025-07-30 02:17:38 +02:00
end )
2025-07-30 06:03:41 +02:00
end
2025-07-30 03:21:38 +02:00
function DespawnTaxi ( )
print ( " ^2[TAXI DEBUG]^7 Despawning taxi " )
2025-07-30 02:17:38 +02:00
2025-07-30 03:50:38 +02:00
if not currentTaxi or not DoesEntityExist ( currentTaxi ) then
return
2025-07-30 02:17:38 +02:00
end
2025-07-30 03:50:38 +02:00
-- Taxi wegfahren lassen, wenn ein Fahrer existiert
if currentDriver and DoesEntityExist ( currentDriver ) then
print ( " ^2[TAXI DEBUG]^7 Making taxi drive away before despawn " )
-- Zufällige Position in der Nähe finden
local taxiCoords = GetEntityCoords ( currentTaxi )
local angle = math.random ( ) * 2 * math.pi
local distance = 150.0
local driveToX = taxiCoords.x + math.cos ( angle ) * distance
local driveToY = taxiCoords.y + math.sin ( angle ) * distance
-- Taxi wegfahren lassen
2025-07-30 05:48:24 +02:00
TaskVehicleDriveToCoordLongrange ( currentDriver , currentTaxi , driveToX , driveToY , taxiCoords.z , 25.0 , 786603 , 5.0 )
2025-07-30 03:50:38 +02:00
-- Blips entfernen
if taxiBlip then
RemoveBlip ( taxiBlip )
taxiBlip = nil
end
2025-07-30 04:08:22 +02:00
if mapBlip then
RemoveBlip ( mapBlip )
mapBlip = nil
end
2025-07-30 03:50:38 +02:00
if destinationBlip then
RemoveBlip ( destinationBlip )
destinationBlip = nil
2025-07-30 03:54:22 +02:00
end
2025-07-30 03:50:38 +02:00
-- Nach 10 Sekunden tatsächlich löschen
SetTimeout ( 10000 , function ( )
-- Fahrer löschen
if currentDriver and DoesEntityExist ( currentDriver ) then
DeleteEntity ( currentDriver )
currentDriver = nil
print ( " ^2[TAXI DEBUG]^7 Driver deleted " )
end
-- Taxi löschen
if currentTaxi and DoesEntityExist ( currentTaxi ) then
exports [ ' qb-target ' ] : RemoveTargetEntity ( currentTaxi )
DeleteEntity ( currentTaxi )
currentTaxi = nil
print ( " ^2[TAXI DEBUG]^7 Taxi deleted " )
end
print ( " ^2[TAXI DEBUG]^7 Taxi despawn completed " )
end )
else
-- Sofort löschen wenn kein Fahrer da ist
if taxiBlip then
RemoveBlip ( taxiBlip )
taxiBlip = nil
end
2025-07-30 04:08:22 +02:00
if mapBlip then
RemoveBlip ( mapBlip )
mapBlip = nil
end
2025-07-30 03:50:38 +02:00
if destinationBlip then
RemoveBlip ( destinationBlip )
destinationBlip = nil
2025-07-30 03:54:22 +02:00
end
2025-07-30 03:50:38 +02:00
-- Taxi löschen
if currentTaxi and DoesEntityExist ( currentTaxi ) then
exports [ ' qb-target ' ] : RemoveTargetEntity ( currentTaxi )
DeleteEntity ( currentTaxi )
currentTaxi = nil
print ( " ^2[TAXI DEBUG]^7 Taxi deleted " )
end
print ( " ^2[TAXI DEBUG]^7 Taxi despawn completed (no driver) " )
2025-07-30 02:17:38 +02:00
end
2025-07-30 06:03:41 +02:00
end
2025-07-30 03:54:22 +02:00
2025-07-30 03:21:38 +02:00
function CalculateDistanceToCoords ( coords )
local playerCoords = GetEntityCoords ( PlayerPedId ( ) )
return # ( playerCoords - coords )
2025-07-30 06:03:41 +02:00
end
2025-07-30 03:21:38 +02:00
-- Command um Taxi zu stoppen
RegisterCommand ( ' stoptaxi ' , function ( )
if currentTaxi and DoesEntityExist ( currentTaxi ) then
DespawnTaxi ( )
lib.notify ( {
title = ' Taxi Service ' ,
description = ' Taxi-Service beendet ' ,
type = ' info '
} )
else
lib.notify ( {
title = ' Taxi Service ' ,
description = ' Du hast kein aktives Taxi ' ,
type = ' error '
} )
2025-07-30 02:17:38 +02:00
end
end )
2025-07-30 04:47:41 +02:00
-- Thread zum Überwachen der Tasten im Taxi
2025-07-30 04:46:12 +02:00
CreateThread ( function ( )
while true do
Wait ( 0 )
if currentTaxi and DoesEntityExist ( currentTaxi ) then
local playerPed = PlayerPedId ( )
if IsPedInVehicle ( playerPed , currentTaxi , false ) then
2025-07-30 04:47:41 +02:00
-- Zeige Hinweise an
local helpText = ' [E] - Ziel wählen [F] - Fahrt beenden '
lib.showTextUI ( helpText , {
2025-07-30 04:46:12 +02:00
position = " top-center " ,
2025-07-30 04:47:41 +02:00
icon = ' taxi ' ,
2025-07-30 04:46:12 +02:00
style = {
borderRadius = 10 ,
backgroundColor = ' #48BB78 ' ,
color = ' white '
}
} )
-- Wenn E gedrückt wird, öffne Menü
if IsControlJustReleased ( 0 , 38 ) then -- E Taste
OpenDestinationMenu ( )
end
2025-07-30 04:47:41 +02:00
-- Wenn F gedrückt wird, beende Fahrt
if IsControlJustReleased ( 0 , 23 ) then -- F Taste
lib.hideTextUI ( )
EndTaxiRide ( )
end
2025-07-30 04:46:12 +02:00
else
lib.hideTextUI ( )
end
else
lib.hideTextUI ( )
Wait ( 1000 ) -- Längere Wartezeit wenn kein Taxi existiert
end
end
end )
2025-07-30 04:47:41 +02:00
-- Funktion zum Beenden der Fahrt
function EndTaxiRide ( )
print ( " ^2[TAXI DEBUG]^7 Ending taxi ride " )
if not currentTaxi or not DoesEntityExist ( currentTaxi ) then
return
end
local playerPed = PlayerPedId ( )
-- Fahrt beenden Benachrichtigung
lib.notify ( {
title = ' Taxi Service ' ,
description = ' Fahrt beendet. Du steigst aus. ' ,
type = ' info '
} )
-- Spieler aussteigen lassen
TaskLeaveVehicle ( playerPed , currentTaxi , 0 )
-- Warten bis ausgestiegen
CreateThread ( function ( )
local timeout = GetGameTimer ( ) + 5000
while GetGameTimer ( ) < timeout do
if not IsPedInVehicle ( playerPed , currentTaxi , false ) then
-- Spieler ist ausgestiegen
break
end
Wait ( 100 )
end
-- Taxi nach 5 Sekunden despawnen
SetTimeout ( 5000 , function ( )
DespawnTaxi ( )
end )
end )
2025-07-30 06:03:41 +02:00
end
2025-07-30 04:46:12 +02:00
-- Thread zum Überwachen des Einsteigens ins Taxi (ohne qb-target)
CreateThread ( function ( )
while true do
Wait ( 1000 )
if currentTaxi and DoesEntityExist ( currentTaxi ) and not IsPedInVehicle ( PlayerPedId ( ) , currentTaxi , false ) then
-- Spieler ist nicht im Taxi, aber Taxi existiert
local playerPed = PlayerPedId ( )
local playerCoords = GetEntityCoords ( playerPed )
local taxiCoords = GetEntityCoords ( currentTaxi )
if # ( playerCoords - taxiCoords ) < 5.0 then
-- Spieler ist in der Nähe des Taxis
lib.showTextUI ( ' [E] - Ins Taxi einsteigen ' , {
position = " top-center " ,
icon = ' car-side ' ,
style = {
borderRadius = 10 ,
backgroundColor = ' #4299E1 ' ,
color = ' white '
}
} )
2025-07-30 05:48:24 +02:00
-- Prüfen ob E gedrückt wird
2025-07-30 04:46:12 +02:00
if IsControlJustReleased ( 0 , 38 ) then -- E Taste
-- Spieler will einsteigen
lib.hideTextUI ( )
-- Spieler hinten einsteigen lassen
local seatIndex = 1 -- Hinten links
if not IsVehicleSeatFree ( currentTaxi , 1 ) then
seatIndex = 2 -- Hinten rechts
end
if not IsVehicleSeatFree ( currentTaxi , seatIndex ) then
seatIndex = 0 -- Beifahrer als Fallback
end
TaskEnterVehicle ( playerPed , currentTaxi , 10000 , seatIndex , 1.0 , 1 , 0 )
-- Warten bis eingestiegen
local entryTimeout = GetGameTimer ( ) + 10000
2025-07-30 05:48:24 +02:00
CreateThread ( function ( )
while GetGameTimer ( ) < entryTimeout do
if IsPedInVehicle ( playerPed , currentTaxi , false ) then
-- Spieler ist eingestiegen
Wait ( 1000 )
OpenDestinationMenu ( )
break
end
Wait ( 100 )
2025-07-30 04:46:12 +02:00
end
2025-07-30 05:48:24 +02:00
end )
2025-07-30 04:46:12 +02:00
end
else
lib.hideTextUI ( )
end
end
end
end )
2025-07-30 03:21:38 +02:00
-- Cleanup beim Resource Stop
2025-07-30 02:17:38 +02:00
AddEventHandler ( ' onResourceStop ' , function ( resourceName )
if GetCurrentResourceName ( ) == resourceName then
2025-07-30 03:21:38 +02:00
print ( " ^2[TAXI DEBUG]^7 Cleaning up main script... " )
2025-07-30 05:48:24 +02:00
-- UI ausblenden
lib.hideTextUI ( )
-- Taxi despawnen
2025-07-30 03:21:38 +02:00
DespawnTaxi ( )
2025-07-30 05:48:24 +02:00
2025-07-30 03:21:38 +02:00
print ( " ^2[TAXI DEBUG]^7 Main cleanup completed " )
2025-07-30 02:17:38 +02:00
end
end )
2025-07-30 09:14:44 +02:00