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 des Taxi-Fortschritts
MonitorTaxiProgress ( taxi , driver , playerCoords )
2025-07-30 04:08:22 +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... " )
-- Maximale Entfernung, die wir akzeptieren
local maxAcceptableDistance = 100.0
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
foundNode , nodePos = GetClosestVehicleNode ( playerCoords.x , playerCoords.y , playerCoords.z , 1 , 3.0 , 0 )
if foundNode then
local nodeDistance = # ( playerCoords - nodePos )
if nodeDistance < maxAcceptableDistance then
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
if nodeDistance < bestDistance then
bestDistance = nodeDistance
bestPosition = { x = nodePos.x , y = nodePos.y , z = nodePos.z , w = 0.0 }
end
end
end
-- 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 )
if nodeDistance < maxAcceptableDistance then
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
if nodeDistance < bestDistance then
bestDistance = nodeDistance
bestPosition = { x = nodePos.x , y = nodePos.y , z = nodePos.z , w = 0.0 }
end
end
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 06:37:34 +02:00
table.insert ( sortedSpawns , {
coords = spawnPos ,
distance = distance
} )
2025-07-30 05:48:24 +02:00
end
2025-07-30 02:46:15 +02:00
2025-07-30 06:37:34 +02:00
-- Nach Entfernung sortieren (nächste zuerst)
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 06:50:33 +02:00
-- Wenn wir hier sind, haben wir keine nahe Position gefunden
-- Wenn wir eine "beste" Position haben, die nur etwas zu weit weg ist, verwenden wir diese
if bestPosition then
print ( " ^3[TAXI DEBUG]^7 No position within " .. maxAcceptableDistance .. " m found, using best available at " .. bestDistance .. " m " )
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
print ( " ^3[TAXI DEBUG]^7 Generating random position within " .. maxAcceptableDistance .. " m of player " )
2025-07-30 06:17:38 +02:00
2025-07-30 06:50:33 +02:00
-- Versuche bis zu 10 Mal, eine gültige Position zu finden
2025-07-30 06:17:38 +02:00
for attempt = 1 , 10 do
2025-07-30 06:37:34 +02:00
-- Zufällige Position im Umkreis
2025-07-30 06:17:38 +02:00
local angle = math.random ( ) * 2 * math.pi
2025-07-30 06:50:33 +02:00
local distance = math.random ( 30 , 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 06:50:33 +02:00
-- Absolute Notfall-Fallback: Einfach irgendwo in der Nähe
2025-07-30 05:48:24 +02:00
local angle = math.random ( ) * 2 * math.pi
2025-07-30 06:50:33 +02:00
local distance = math.random ( 30 , 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 06:17:38 +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
-- 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 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 06:06:17 +02:00
" A_C_Chimp " , -- Affe (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 )
SetDriverAbility ( driver , 1.0 ) -- Maximale Fahrfähigkeit
SetDriverAggressiveness ( driver , 0.0 ) -- Minimale Aggressivität
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 )
-- 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... " )
-- 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
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 player " )
-- Direkt zum Spieler fahren
TaskVehicleDriveToCoordLongrange ( driver , taxi , playerCoords.x , playerCoords.y , playerCoords.z , 25.0 , 786603 , 5.0 )
end
-- Fahrer-Verhalten verbessern
SetDriverAggressiveness ( driver , 0.0 )
SetDriverAbility ( driver , 1.0 )
2025-07-30 06:03:41 +02:00
end
2025-07-30 05:48:24 +02:00
function MonitorTaxiProgress ( taxi , driver , playerCoords )
print ( " ^2[TAXI DEBUG]^7 Monitoring taxi progress... " )
local lastPos = GetEntityCoords ( taxi )
local stuckCounter = 0
2025-07-30 08:23:40 +02:00
local maxStuckCount = 10
2025-07-30 05:48:24 +02:00
local totalStuckEvents = 0
2025-07-30 08:23:40 +02:00
local maxTotalStuckEvents = 6
2025-07-30 05:48:24 +02:00
CreateThread ( function ( )
while DoesEntityExist ( taxi ) and DoesEntityExist ( driver ) do
Wait ( 3000 )
2025-07-30 06:11:59 +02:00
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
2025-07-30 05:48:24 +02:00
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
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 02:17:38 +02:00
2025-07-30 06:03:41 +02:00
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
-- Zum Ziel fahren mit verbesserter Navigation
NavigateToDestination ( currentDriver , currentTaxi , destination )
2025-07-30 03:21:38 +02:00
-- Fahrt überwachen
MonitorTaxiRide ( destination , price )
end
2025-07-30 05:48:24 +02:00
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 )
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 MonitorTaxiRide ( destination , price )
print ( " ^2[TAXI DEBUG]^7 Monitoring taxi ride... " )
2025-07-30 02:17:38 +02:00
2025-07-30 05:48:24 +02:00
local lastPos = GetEntityCoords ( currentTaxi )
local stuckCounter = 0
2025-07-30 07:02:08 +02:00
local maxStuckCount = 10
local rideTimeout = GetGameTimer ( ) + ( 10 * 60 * 1000 ) -- 5 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
local distanceMoved = # ( lastPos - taxiCoords )
2025-07-30 02:17:38 +02:00
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
-- 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 05:48:24 +02:00
-- Überprüfen ob das Taxi stecken geblieben ist
if distanceMoved < 1.0 then
stuckCounter = stuckCounter + 1
if stuckCounter >= maxStuckCount then
print ( " ^1[TAXI DEBUG]^7 Taxi stuck during ride, attempting recovery " )
RecoverStuckTaxi ( currentTaxi , currentDriver , vector3 ( destination.x , destination.y , destination.z ) )
stuckCounter = 0
end
else
stuckCounter = math.max ( 0 , stuckCounter - 1 )
end
2025-07-30 07:02:08 +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 )
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
2025-07-30 05:48:24 +02:00
lastPos = taxiCoords
2025-07-30 02:17:38 +02:00
Wait ( 2000 )
end
end )
2025-07-30 06:03:41 +02:00
end
2025-07-30 02:17:38 +02:00
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 02:17:38 +02:00
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 02:17:38 +02:00
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 )