2025-07-30 04:57:57 +02:00
|
|
|
local QBCore = exports['qb-core']:GetCoreObject()
|
2025-07-30 02:17:38 +02:00
|
|
|
local stationVehicles = {}
|
|
|
|
local stationBlips = {}
|
|
|
|
|
2025-07-30 02:46:15 +02:00
|
|
|
print("^2[TAXI STATIONS DEBUG]^7 Stations script loaded")
|
|
|
|
|
2025-07-30 02:17:38 +02:00
|
|
|
-- Taxi Stationen initialisieren
|
|
|
|
CreateThread(function()
|
2025-07-30 07:32:37 +02:00
|
|
|
Wait(5000) -- Längere Wartezeit, um sicherzustellen, dass alle Ressourcen geladen sind
|
2025-07-30 02:46:15 +02:00
|
|
|
print("^2[TAXI STATIONS DEBUG]^7 Initializing taxi stations...")
|
2025-07-30 02:17:38 +02:00
|
|
|
InitializeTaxiStations()
|
2025-07-30 07:32:37 +02:00
|
|
|
|
|
|
|
-- Regelmäßige Überprüfung und Wiederherstellung der Stationen
|
|
|
|
CreateThread(function()
|
|
|
|
while true do
|
|
|
|
Wait(60000) -- Alle 60 Sekunden prüfen
|
|
|
|
CheckAndRestoreStationVehicles()
|
|
|
|
end
|
|
|
|
end)
|
2025-07-30 02:17:38 +02:00
|
|
|
end)
|
|
|
|
|
|
|
|
function InitializeTaxiStations()
|
2025-07-30 02:46:15 +02:00
|
|
|
print("^2[TAXI STATIONS DEBUG]^7 InitializeTaxiStations started")
|
|
|
|
|
|
|
|
if not Config.TaxiStations then
|
|
|
|
print("^1[TAXI STATIONS DEBUG]^7 Config.TaxiStations not found!")
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
print("^2[TAXI STATIONS DEBUG]^7 Found " .. #Config.TaxiStations .. " stations")
|
|
|
|
|
2025-07-30 07:32:37 +02:00
|
|
|
-- Zuerst alle bestehenden Fahrzeuge und Blips entfernen
|
|
|
|
CleanupExistingStations()
|
|
|
|
|
|
|
|
-- Dann neue erstellen
|
2025-07-30 02:17:38 +02:00
|
|
|
for stationId, station in pairs(Config.TaxiStations) do
|
2025-07-30 02:46:15 +02:00
|
|
|
print("^2[TAXI STATIONS DEBUG]^7 Processing station " .. stationId .. ": " .. station.name)
|
|
|
|
|
2025-07-30 02:17:38 +02:00
|
|
|
-- Blip für Station erstellen
|
|
|
|
local blip = AddBlipForCoord(station.blipCoords.x, station.blipCoords.y, station.blipCoords.z)
|
|
|
|
SetBlipSprite(blip, 198)
|
|
|
|
SetBlipColour(blip, 5)
|
|
|
|
SetBlipScale(blip, 0.8)
|
|
|
|
SetBlipAsShortRange(blip, true)
|
|
|
|
BeginTextCommandSetBlipName("STRING")
|
|
|
|
AddTextComponentString(station.name)
|
|
|
|
EndTextCommandSetBlipName(blip)
|
|
|
|
stationBlips[stationId] = blip
|
2025-07-30 02:46:15 +02:00
|
|
|
print("^2[TAXI STATIONS DEBUG]^7 Blip created for station " .. stationId)
|
2025-07-30 02:17:38 +02:00
|
|
|
|
|
|
|
-- Fahrzeuge an Station spawnen
|
|
|
|
stationVehicles[stationId] = {}
|
2025-07-30 07:32:37 +02:00
|
|
|
|
|
|
|
-- Verzögertes Spawnen der Fahrzeuge, um Ressourcenkonflikte zu vermeiden
|
|
|
|
CreateThread(function()
|
|
|
|
for vehicleId, vehicleData in pairs(station.vehicles) do
|
|
|
|
-- Kleine Verzögerung zwischen jedem Fahrzeug
|
|
|
|
Wait(500)
|
|
|
|
print("^2[TAXI STATIONS DEBUG]^7 Spawning vehicle " .. vehicleId .. " (" .. vehicleData.model .. ") at station " .. stationId)
|
|
|
|
SpawnStationVehicle(stationId, vehicleId, vehicleData)
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
end
|
|
|
|
|
|
|
|
print("^2[TAXI STATIONS DEBUG]^7 All stations initialization started")
|
|
|
|
end
|
|
|
|
|
|
|
|
function CleanupExistingStations()
|
|
|
|
print("^2[TAXI STATIONS DEBUG]^7 Cleaning up existing stations...")
|
|
|
|
|
|
|
|
-- Alle bestehenden Fahrzeuge löschen
|
|
|
|
for stationId, vehicles in pairs(stationVehicles) do
|
|
|
|
for vehicleId, vehicleInfo in pairs(vehicles) do
|
|
|
|
if vehicleInfo.entity and DoesEntityExist(vehicleInfo.entity) then
|
|
|
|
exports['qb-target']:RemoveTargetEntity(vehicleInfo.entity)
|
|
|
|
DeleteEntity(vehicleInfo.entity)
|
|
|
|
end
|
|
|
|
if vehicleInfo.driver and DoesEntityExist(vehicleInfo.driver) then
|
|
|
|
DeleteEntity(vehicleInfo.driver)
|
|
|
|
end
|
2025-07-30 02:17:38 +02:00
|
|
|
end
|
|
|
|
end
|
2025-07-30 02:46:15 +02:00
|
|
|
|
2025-07-30 07:32:37 +02:00
|
|
|
-- Alle Blips entfernen
|
|
|
|
for _, blip in pairs(stationBlips) do
|
|
|
|
RemoveBlip(blip)
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Variablen zurücksetzen
|
|
|
|
stationVehicles = {}
|
|
|
|
stationBlips = {}
|
|
|
|
|
|
|
|
print("^2[TAXI STATIONS DEBUG]^7 Cleanup completed")
|
2025-07-30 02:17:38 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
function SpawnStationVehicle(stationId, vehicleId, vehicleData)
|
2025-07-30 02:46:15 +02:00
|
|
|
print("^2[TAXI STATIONS DEBUG]^7 SpawnStationVehicle: " .. stationId .. "/" .. vehicleId)
|
|
|
|
|
2025-07-30 07:32:37 +02:00
|
|
|
-- Prüfen ob bereits ein Fahrzeug für diese Position existiert
|
|
|
|
if stationVehicles[stationId] and stationVehicles[stationId][vehicleId] and
|
|
|
|
stationVehicles[stationId][vehicleId].entity and
|
|
|
|
DoesEntityExist(stationVehicles[stationId][vehicleId].entity) then
|
|
|
|
print("^3[TAXI STATIONS DEBUG]^7 Vehicle already exists for this position, removing it first")
|
|
|
|
exports['qb-target']:RemoveTargetEntity(stationVehicles[stationId][vehicleId].entity)
|
|
|
|
DeleteEntity(stationVehicles[stationId][vehicleId].entity)
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Prüfen ob die Position frei ist
|
|
|
|
local clearArea = true
|
|
|
|
local vehicles = GetGamePool('CVehicle')
|
|
|
|
for _, vehicle in ipairs(vehicles) do
|
|
|
|
local vehCoords = GetEntityCoords(vehicle)
|
|
|
|
if #(vector3(vehicleData.coords.x, vehicleData.coords.y, vehicleData.coords.z) - vehCoords) < 3.0 then
|
|
|
|
clearArea = false
|
|
|
|
print("^3[TAXI STATIONS DEBUG]^7 Position blocked by another vehicle, will retry later")
|
|
|
|
-- Nach 30 Sekunden erneut versuchen
|
|
|
|
SetTimeout(30000, function()
|
|
|
|
SpawnStationVehicle(stationId, vehicleId, vehicleData)
|
|
|
|
end)
|
|
|
|
return
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2025-07-30 02:17:38 +02:00
|
|
|
CreateThread(function()
|
|
|
|
local vehicleHash = GetHashKey(vehicleData.model)
|
2025-07-30 02:46:15 +02:00
|
|
|
print("^2[TAXI STATIONS DEBUG]^7 Vehicle hash: " .. vehicleHash)
|
|
|
|
|
2025-07-30 02:17:38 +02:00
|
|
|
RequestModel(vehicleHash)
|
2025-07-30 02:46:15 +02:00
|
|
|
local timeout = GetGameTimer() + 10000
|
|
|
|
while not HasModelLoaded(vehicleHash) and GetGameTimer() < timeout do
|
|
|
|
print("^3[TAXI STATIONS DEBUG]^7 Waiting for model " .. vehicleData.model .. " to load...")
|
2025-07-30 02:17:38 +02:00
|
|
|
Wait(100)
|
|
|
|
end
|
2025-07-30 02:46:15 +02:00
|
|
|
|
|
|
|
if not HasModelLoaded(vehicleHash) then
|
|
|
|
print("^1[TAXI STATIONS DEBUG]^7 Failed to load model: " .. vehicleData.model)
|
2025-07-30 07:32:37 +02:00
|
|
|
-- Nach 30 Sekunden erneut versuchen
|
|
|
|
SetTimeout(30000, function()
|
|
|
|
SpawnStationVehicle(stationId, vehicleId, vehicleData)
|
|
|
|
end)
|
2025-07-30 02:46:15 +02:00
|
|
|
return
|
|
|
|
end
|
2025-07-30 02:17:38 +02:00
|
|
|
|
|
|
|
local vehicle = CreateVehicle(
|
|
|
|
vehicleHash,
|
|
|
|
vehicleData.coords.x,
|
|
|
|
vehicleData.coords.y,
|
|
|
|
vehicleData.coords.z,
|
|
|
|
vehicleData.coords.w,
|
|
|
|
false,
|
|
|
|
false
|
|
|
|
)
|
|
|
|
|
2025-07-30 02:46:15 +02:00
|
|
|
if not DoesEntityExist(vehicle) then
|
|
|
|
print("^1[TAXI STATIONS DEBUG]^7 Failed to create vehicle!")
|
2025-07-30 07:32:37 +02:00
|
|
|
-- Nach 30 Sekunden erneut versuchen
|
|
|
|
SetTimeout(30000, function()
|
|
|
|
SpawnStationVehicle(stationId, vehicleId, vehicleData)
|
|
|
|
end)
|
2025-07-30 02:46:15 +02:00
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
print("^2[TAXI STATIONS DEBUG]^7 Vehicle created: " .. vehicle)
|
|
|
|
|
2025-07-30 07:32:37 +02:00
|
|
|
-- Fahrzeug konfigurieren
|
2025-07-30 02:17:38 +02:00
|
|
|
SetEntityAsMissionEntity(vehicle, true, true)
|
|
|
|
SetVehicleOnGroundProperly(vehicle)
|
|
|
|
SetVehicleDoorsLocked(vehicle, 2) -- Locked
|
|
|
|
SetVehicleEngineOn(vehicle, false, true, false)
|
|
|
|
|
2025-07-30 07:32:37 +02:00
|
|
|
-- Verbesserte Persistenz
|
|
|
|
SetEntityInvincible(vehicle, true)
|
|
|
|
SetVehicleCanBeVisiblyDamaged(vehicle, false)
|
|
|
|
SetEntityProofs(vehicle, true, true, true, true, true, true, true, true)
|
|
|
|
SetVehicleExplodesOnHighExplosionDamage(vehicle, false)
|
|
|
|
SetVehicleHasBeenOwnedByPlayer(vehicle, true)
|
|
|
|
SetVehicleIsConsideredByPlayer(vehicle, true)
|
|
|
|
|
2025-07-30 02:17:38 +02:00
|
|
|
-- Fahrzeug-Info speichern
|
2025-07-30 07:32:37 +02:00
|
|
|
if not stationVehicles[stationId] then
|
|
|
|
stationVehicles[stationId] = {}
|
|
|
|
end
|
|
|
|
|
2025-07-30 02:17:38 +02:00
|
|
|
stationVehicles[stationId][vehicleId] = {
|
|
|
|
entity = vehicle,
|
|
|
|
data = vehicleData,
|
|
|
|
occupied = false
|
|
|
|
}
|
|
|
|
|
2025-07-30 02:46:15 +02:00
|
|
|
print("^2[TAXI STATIONS DEBUG]^7 Adding qb-target for vehicle " .. vehicle)
|
|
|
|
|
2025-07-30 02:17:38 +02:00
|
|
|
-- qb-target für Fahrzeug hinzufügen
|
|
|
|
exports['qb-target']:AddTargetEntity(vehicle, {
|
|
|
|
options = {
|
|
|
|
{
|
|
|
|
type = "client",
|
|
|
|
event = "taxi:enterStationVehicle",
|
|
|
|
icon = "fas fa-taxi",
|
|
|
|
label = "Taxi nehmen ($" .. vehicleData.pricePerKm .. "/km)",
|
|
|
|
stationId = stationId,
|
|
|
|
vehicleId = vehicleId
|
|
|
|
}
|
|
|
|
},
|
|
|
|
distance = 3.0
|
|
|
|
})
|
|
|
|
|
2025-07-30 02:46:15 +02:00
|
|
|
print("^2[TAXI STATIONS DEBUG]^7 qb-target added for vehicle " .. vehicle)
|
|
|
|
|
2025-07-30 02:17:38 +02:00
|
|
|
SetModelAsNoLongerNeeded(vehicleHash)
|
|
|
|
end)
|
|
|
|
end
|
|
|
|
|
2025-07-30 07:32:37 +02:00
|
|
|
function CheckAndRestoreStationVehicles()
|
|
|
|
print("^2[TAXI STATIONS DEBUG]^7 Checking station vehicles...")
|
|
|
|
|
|
|
|
local restoredCount = 0
|
|
|
|
|
|
|
|
for stationId, station in pairs(Config.TaxiStations) do
|
|
|
|
if not stationVehicles[stationId] then
|
|
|
|
stationVehicles[stationId] = {}
|
|
|
|
end
|
|
|
|
|
|
|
|
for vehicleId, vehicleData in pairs(station.vehicles) do
|
|
|
|
local shouldSpawn = false
|
|
|
|
|
|
|
|
-- Prüfen ob das Fahrzeug existiert
|
|
|
|
if not stationVehicles[stationId][vehicleId] then
|
|
|
|
print("^3[TAXI STATIONS DEBUG]^7 Vehicle data missing for station " .. stationId .. ", vehicle " .. vehicleId)
|
|
|
|
shouldSpawn = true
|
|
|
|
elseif not stationVehicles[stationId][vehicleId].entity then
|
|
|
|
print("^3[TAXI STATIONS DEBUG]^7 Vehicle entity missing for station " .. stationId .. ", vehicle " .. vehicleId)
|
|
|
|
shouldSpawn = true
|
|
|
|
elseif not DoesEntityExist(stationVehicles[stationId][vehicleId].entity) then
|
|
|
|
print("^3[TAXI STATIONS DEBUG]^7 Vehicle entity doesn't exist for station " .. stationId .. ", vehicle " .. vehicleId)
|
|
|
|
shouldSpawn = true
|
|
|
|
elseif stationVehicles[stationId][vehicleId].occupied then
|
|
|
|
-- Fahrzeug ist besetzt, nicht neu spawnen
|
|
|
|
print("^2[TAXI STATIONS DEBUG]^7 Vehicle at station " .. stationId .. ", vehicle " .. vehicleId .. " is occupied")
|
|
|
|
shouldSpawn = false
|
|
|
|
end
|
|
|
|
|
|
|
|
if shouldSpawn then
|
|
|
|
print("^2[TAXI STATIONS DEBUG]^7 Respawning vehicle at station " .. stationId .. ", vehicle " .. vehicleId)
|
|
|
|
SpawnStationVehicle(stationId, vehicleId, vehicleData)
|
|
|
|
restoredCount = restoredCount + 1
|
|
|
|
|
|
|
|
-- Kleine Verzögerung zwischen Spawns
|
|
|
|
Wait(500)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
if restoredCount > 0 then
|
|
|
|
print("^2[TAXI STATIONS DEBUG]^7 Restored " .. restoredCount .. " station vehicles")
|
|
|
|
else
|
|
|
|
print("^2[TAXI STATIONS DEBUG]^7 All station vehicles are present")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2025-07-30 03:05:27 +02:00
|
|
|
-- Hilfsfunktion um Spieler-Sitz zu ermitteln
|
|
|
|
function GetPlayerVehicleSeat(ped, vehicle)
|
|
|
|
if not IsPedInVehicle(ped, vehicle, false) then
|
|
|
|
return nil
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Alle möglichen Sitze prüfen
|
|
|
|
for seat = -1, 7 do -- -1 = Fahrer, 0 = Beifahrer, 1+ = Hintersitze
|
|
|
|
if GetPedInVehicleSeat(vehicle, seat) == ped then
|
|
|
|
return seat
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
return nil
|
|
|
|
end
|
|
|
|
|
2025-07-30 02:17:38 +02:00
|
|
|
-- Event für Einsteigen in Station-Taxi
|
|
|
|
RegisterNetEvent('taxi:enterStationVehicle', function(data)
|
2025-07-30 02:46:15 +02:00
|
|
|
print("^2[TAXI STATIONS DEBUG]^7 Player trying to enter station vehicle")
|
|
|
|
print("^2[TAXI STATIONS DEBUG]^7 Data: " .. json.encode(data))
|
|
|
|
|
2025-07-30 02:17:38 +02:00
|
|
|
local stationId = data.stationId
|
|
|
|
local vehicleId = data.vehicleId
|
|
|
|
|
|
|
|
if not stationVehicles[stationId] or not stationVehicles[stationId][vehicleId] then
|
2025-07-30 02:46:15 +02:00
|
|
|
print("^1[TAXI STATIONS DEBUG]^7 Vehicle not found in data")
|
2025-07-30 02:17:38 +02:00
|
|
|
lib.notify({
|
|
|
|
title = 'Taxi Service',
|
|
|
|
description = 'Dieses Taxi ist nicht verfügbar',
|
|
|
|
type = 'error'
|
|
|
|
})
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
local vehicleInfo = stationVehicles[stationId][vehicleId]
|
|
|
|
|
|
|
|
if vehicleInfo.occupied then
|
2025-07-30 02:46:15 +02:00
|
|
|
print("^1[TAXI STATIONS DEBUG]^7 Vehicle already occupied")
|
2025-07-30 02:17:38 +02:00
|
|
|
lib.notify({
|
|
|
|
title = 'Taxi Service',
|
|
|
|
description = 'Dieses Taxi ist bereits besetzt',
|
|
|
|
type = 'error'
|
|
|
|
})
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
2025-07-30 02:46:15 +02:00
|
|
|
print("^2[TAXI STATIONS DEBUG]^7 Entering vehicle...")
|
|
|
|
|
2025-07-30 02:17:38 +02:00
|
|
|
-- Spieler ins Fahrzeug setzen
|
|
|
|
local playerPed = PlayerPedId()
|
|
|
|
local vehicle = vehicleInfo.entity
|
|
|
|
|
|
|
|
-- Türen entsperren
|
|
|
|
SetVehicleDoorsLocked(vehicle, 1)
|
|
|
|
|
2025-07-30 02:59:59 +02:00
|
|
|
-- Info-Text anzeigen während Fahrer geladen wird
|
2025-07-30 03:12:57 +02:00
|
|
|
print("^2[TAXI STATIONS DEBUG]^7 Showing driver loading text...")
|
|
|
|
lib.showTextUI('🚕 Warte an der Station - Fahrer wird geladen...', {
|
2025-07-30 02:59:59 +02:00
|
|
|
position = "top-center",
|
|
|
|
icon = 'taxi',
|
|
|
|
style = {
|
|
|
|
borderRadius = 10,
|
|
|
|
backgroundColor = '#48BB78',
|
|
|
|
color = 'white'
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
2025-07-30 03:12:57 +02:00
|
|
|
-- Kurz warten damit der Text sichtbar wird
|
|
|
|
Wait(1000)
|
|
|
|
|
2025-07-30 02:53:21 +02:00
|
|
|
-- Verschiedene Fahrer-Models versuchen
|
|
|
|
local driverModels = {
|
2025-07-30 08:11:37 +02:00
|
|
|
"A_C_Chimp", -- Taxi Driver (erste Wahl)
|
2025-07-30 07:32:37 +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 02:53:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
local driver = nil
|
|
|
|
local driverHash = nil
|
|
|
|
|
2025-07-30 03:21:38 +02:00
|
|
|
for i, modelName in pairs(driverModels) do
|
|
|
|
print("^2[TAXI STATIONS DEBUG]^7 Trying driver model " .. i .. ": " .. modelName)
|
2025-07-30 02:53:21 +02:00
|
|
|
driverHash = GetHashKey(modelName)
|
|
|
|
|
2025-07-30 03:12:57 +02:00
|
|
|
-- Text während Model-Loading aktualisieren
|
2025-07-30 03:21:38 +02:00
|
|
|
lib.showTextUI('🚕 Lade Fahrer-Model (' .. i .. '/' .. #driverModels .. '): ' .. modelName .. '...', {
|
2025-07-30 03:12:57 +02:00
|
|
|
position = "top-center",
|
|
|
|
icon = 'taxi',
|
|
|
|
style = {
|
|
|
|
borderRadius = 10,
|
|
|
|
backgroundColor = '#48BB78',
|
|
|
|
color = 'white'
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
2025-07-30 02:53:21 +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:53:21 +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
|
|
|
|
print("^3[TAXI STATIONS DEBUG]^7 Still waiting for model " .. modelName .. " (attempt " .. attempts .. ")")
|
|
|
|
end
|
2025-07-30 02:53:21 +02:00
|
|
|
Wait(100)
|
|
|
|
end
|
|
|
|
|
|
|
|
if HasModelLoaded(driverHash) then
|
|
|
|
print("^2[TAXI STATIONS DEBUG]^7 Driver model " .. modelName .. " loaded successfully")
|
|
|
|
|
2025-07-30 03:12:57 +02:00
|
|
|
-- Text aktualisieren
|
|
|
|
lib.showTextUI('🚕 Erstelle Fahrer...', {
|
|
|
|
position = "top-center",
|
|
|
|
icon = 'taxi',
|
|
|
|
style = {
|
|
|
|
borderRadius = 10,
|
|
|
|
backgroundColor = '#48BB78',
|
|
|
|
color = 'white'
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
2025-07-30 02:53:21 +02:00
|
|
|
driver = CreatePedInsideVehicle(vehicle, 26, driverHash, -1, true, false)
|
|
|
|
|
|
|
|
if DoesEntityExist(driver) then
|
|
|
|
print("^2[TAXI STATIONS DEBUG]^7 Driver created successfully: " .. driver)
|
|
|
|
break
|
|
|
|
else
|
|
|
|
print("^1[TAXI STATIONS DEBUG]^7 Failed to create driver with model: " .. modelName)
|
|
|
|
SetModelAsNoLongerNeeded(driverHash)
|
|
|
|
end
|
|
|
|
else
|
|
|
|
print("^1[TAXI STATIONS DEBUG]^7 Failed to load driver model: " .. modelName)
|
2025-07-30 03:21:38 +02:00
|
|
|
SetModelAsNoLongerNeeded(driverHash)
|
2025-07-30 02:53:21 +02:00
|
|
|
end
|
2025-07-30 03:12:57 +02:00
|
|
|
|
|
|
|
Wait(500) -- Kurze Pause zwischen Versuchen
|
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
|
|
|
-- Fallback: Notfall-Fahrer erstellen
|
2025-07-30 02:53:21 +02:00
|
|
|
if not driver or not DoesEntityExist(driver) then
|
2025-07-30 03:21:38 +02:00
|
|
|
print("^3[TAXI STATIONS DEBUG]^7 Using emergency fallback driver creation...")
|
2025-07-30 02:53:21 +02:00
|
|
|
|
2025-07-30 03:21:38 +02:00
|
|
|
lib.showTextUI('🚕 Erstelle Notfall-Fahrer...', {
|
2025-07-30 03:12:57 +02:00
|
|
|
position = "top-center",
|
|
|
|
icon = 'taxi',
|
|
|
|
style = {
|
|
|
|
borderRadius = 10,
|
|
|
|
backgroundColor = '#FFA500',
|
|
|
|
color = 'white'
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
2025-07-30 03:21:38 +02:00
|
|
|
-- Notfall-Fallback mit Hash-Werten
|
|
|
|
local emergencyModels = {
|
|
|
|
`mp_m_freemode_01`,
|
|
|
|
`a_m_y_hipster_01`,
|
|
|
|
`a_m_m_farmer_01`,
|
|
|
|
`a_m_y_beach_01`
|
|
|
|
}
|
2025-07-30 02:53:21 +02:00
|
|
|
|
2025-07-30 03:21:38 +02:00
|
|
|
for _, hash in pairs(emergencyModels) do
|
|
|
|
RequestModel(hash)
|
|
|
|
local timeout = GetGameTimer() + 5000
|
|
|
|
while not HasModelLoaded(hash) and GetGameTimer() < timeout do
|
|
|
|
Wait(50)
|
|
|
|
end
|
|
|
|
|
|
|
|
if HasModelLoaded(hash) then
|
|
|
|
driver = CreatePedInsideVehicle(vehicle, 26, hash, -1, true, false)
|
|
|
|
if DoesEntityExist(driver) then
|
|
|
|
print("^2[TAXI STATIONS DEBUG]^7 Emergency driver created")
|
|
|
|
driverHash = hash
|
|
|
|
break
|
|
|
|
end
|
|
|
|
SetModelAsNoLongerNeeded(hash)
|
|
|
|
end
|
2025-07-30 02:53:21 +02:00
|
|
|
end
|
2025-07-30 03:12:57 +02:00
|
|
|
|
2025-07-30 03:21:38 +02:00
|
|
|
Wait(1000)
|
2025-07-30 02:46:15 +02:00
|
|
|
end
|
|
|
|
|
2025-07-30 02:53:21 +02:00
|
|
|
-- Wenn immer noch kein Fahrer, ohne Fahrer fortfahren
|
|
|
|
if not driver or not DoesEntityExist(driver) then
|
|
|
|
print("^1[TAXI STATIONS DEBUG]^7 Could not create any driver, continuing without driver")
|
2025-07-30 03:12:57 +02:00
|
|
|
|
|
|
|
lib.showTextUI('❌ Kein Fahrer verfügbar - Du kannst selbst fahren', {
|
|
|
|
position = "top-center",
|
|
|
|
icon = 'exclamation-triangle',
|
|
|
|
style = {
|
|
|
|
borderRadius = 10,
|
|
|
|
backgroundColor = '#FF6B6B',
|
|
|
|
color = 'white'
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
Wait(3000) -- 3 Sekunden anzeigen
|
|
|
|
lib.hideTextUI()
|
|
|
|
|
2025-07-30 02:53:21 +02:00
|
|
|
driver = nil
|
2025-07-30 02:59:59 +02:00
|
|
|
|
|
|
|
lib.notify({
|
|
|
|
title = 'Taxi Service',
|
|
|
|
description = 'Kein Fahrer verfügbar - Du kannst das Taxi selbst fahren',
|
|
|
|
type = 'warning'
|
|
|
|
})
|
2025-07-30 02:53:21 +02:00
|
|
|
else
|
2025-07-30 03:12:57 +02:00
|
|
|
-- Fahrer erfolgreich erstellt
|
|
|
|
lib.showTextUI('✅ Fahrer bereit - Steige hinten ein!', {
|
|
|
|
position = "top-center",
|
|
|
|
icon = 'check-circle',
|
|
|
|
style = {
|
|
|
|
borderRadius = 10,
|
|
|
|
backgroundColor = '#48BB78',
|
|
|
|
color = 'white'
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
Wait(2000) -- 2 Sekunden anzeigen
|
|
|
|
|
2025-07-30 02:53:21 +02:00
|
|
|
-- Fahrer konfigurieren
|
|
|
|
SetEntityAsMissionEntity(driver, true, true)
|
|
|
|
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 03:21:38 +02:00
|
|
|
SetBlockingOfNonTemporaryEvents(driver, true)
|
2025-07-30 02:53:21 +02:00
|
|
|
|
2025-07-30 07:32:37 +02:00
|
|
|
-- Verbesserte Fahrer-Einstellungen
|
|
|
|
SetDriverAbility(driver, 1.0) -- Maximale Fahrfähigkeit
|
|
|
|
SetDriverAggressiveness(driver, 0.0) -- Minimale Aggressivität
|
2025-07-30 08:20:25 +02:00
|
|
|
SetPedDriveByClipsetHash(driver, GetHashKey("DRIVE_SLOW"))
|
2025-07-30 07:32:37 +02:00
|
|
|
|
2025-07-30 03:21:38 +02:00
|
|
|
-- Fahrer-Outfit (nur wenn es ein anpassbarer Ped ist)
|
|
|
|
if driverHash == GetHashKey("mp_m_freemode_01") or driverHash == GetHashKey("mp_f_freemode_01") then
|
|
|
|
print("^2[TAXI STATIONS DEBUG]^7 Setting driver outfit...")
|
|
|
|
|
|
|
|
-- Basis-Outfit für Taxi-Fahrer
|
|
|
|
SetPedComponentVariation(driver, 8, 15, 0, 0) -- Undershirt
|
|
|
|
SetPedComponentVariation(driver, 11, 28, 0, 0) -- Jacket
|
|
|
|
SetPedComponentVariation(driver, 4, 10, 0, 0) -- Pants
|
|
|
|
SetPedComponentVariation(driver, 6, 10, 0, 0) -- Shoes
|
|
|
|
SetPedComponentVariation(driver, 1, 0, 0, 0) -- Mask
|
|
|
|
SetPedComponentVariation(driver, 3, 0, 0, 0) -- Arms
|
|
|
|
SetPedComponentVariation(driver, 5, 0, 0, 0) -- Bag
|
|
|
|
SetPedComponentVariation(driver, 7, 0, 0, 0) -- Tie
|
|
|
|
SetPedComponentVariation(driver, 9, 0, 0, 0) -- Body Armor
|
|
|
|
SetPedComponentVariation(driver, 10, 0, 0, 0) -- Decals
|
|
|
|
|
|
|
|
-- Zufällige Gesichtsmerkmale
|
|
|
|
SetPedHeadBlendData(driver, math.random(0, 20), math.random(0, 20), 0, math.random(0, 20), math.random(0, 20), 0, 0.5, 0.5, 0.0, false)
|
|
|
|
end
|
2025-07-30 02:59:59 +02:00
|
|
|
|
|
|
|
lib.notify({
|
|
|
|
title = 'Taxi Service',
|
|
|
|
description = 'Fahrer bereit - Steige hinten ein',
|
|
|
|
type = 'success'
|
|
|
|
})
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Spieler HINTEN einsteigen lassen
|
2025-07-30 03:05:27 +02:00
|
|
|
local seatIndex = 1 -- Hinten links als Standard
|
2025-07-30 02:59:59 +02:00
|
|
|
|
|
|
|
-- Prüfen welche Hintersitze verfügbar sind
|
|
|
|
local availableSeats = {}
|
|
|
|
for i = 1, 3 do -- Sitze 1, 2, 3 (hinten links, hinten mitte, hinten rechts)
|
2025-07-30 03:05:27 +02:00
|
|
|
if IsVehicleSeatFree(vehicle, i) then
|
2025-07-30 02:59:59 +02:00
|
|
|
table.insert(availableSeats, i)
|
|
|
|
end
|
2025-07-30 02:46:15 +02:00
|
|
|
end
|
|
|
|
|
2025-07-30 02:59:59 +02:00
|
|
|
-- Ersten verfügbaren Hintersitz wählen
|
|
|
|
if #availableSeats > 0 then
|
|
|
|
seatIndex = availableSeats[1]
|
|
|
|
print("^2[TAXI STATIONS DEBUG]^7 Using rear seat: " .. seatIndex)
|
|
|
|
else
|
|
|
|
-- Fallback: Beifahrersitz
|
|
|
|
seatIndex = 0
|
|
|
|
print("^3[TAXI STATIONS DEBUG]^7 No rear seats available, using passenger seat")
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Spieler in den gewählten Sitz einsteigen lassen
|
|
|
|
TaskEnterVehicle(playerPed, vehicle, 10000, seatIndex, 1.0, 1, 0)
|
|
|
|
|
|
|
|
-- Info-Text während Einsteigen
|
|
|
|
lib.showTextUI('🚕 Steige ins Taxi ein...', {
|
|
|
|
position = "top-center",
|
|
|
|
icon = 'car-side',
|
|
|
|
style = {
|
|
|
|
borderRadius = 10,
|
|
|
|
backgroundColor = '#4299E1',
|
|
|
|
color = 'white'
|
|
|
|
}
|
|
|
|
})
|
2025-07-30 02:17:38 +02:00
|
|
|
|
|
|
|
-- Warten bis Spieler eingestiegen ist
|
|
|
|
CreateThread(function()
|
2025-07-30 02:59:59 +02:00
|
|
|
local enterTimeout = GetGameTimer() + 15000 -- Längere Zeit für Einsteigen
|
|
|
|
local hasEntered = false
|
|
|
|
|
|
|
|
while GetGameTimer() < enterTimeout and not hasEntered do
|
2025-07-30 02:17:38 +02:00
|
|
|
if IsPedInVehicle(playerPed, vehicle, false) then
|
2025-07-30 02:59:59 +02:00
|
|
|
hasEntered = true
|
2025-07-30 02:17:38 +02:00
|
|
|
vehicleInfo.occupied = true
|
|
|
|
vehicleInfo.driver = driver
|
|
|
|
|
2025-07-30 02:59:59 +02:00
|
|
|
-- Info-Text verstecken
|
|
|
|
lib.hideTextUI()
|
|
|
|
|
|
|
|
print("^2[TAXI STATIONS DEBUG]^7 Player entered successfully")
|
|
|
|
|
|
|
|
-- Prüfen ob Spieler wirklich hinten sitzt
|
2025-07-30 03:05:27 +02:00
|
|
|
local playerSeat = GetPlayerVehicleSeat(playerPed, vehicle)
|
|
|
|
print("^2[TAXI STATIONS DEBUG]^7 Player is in seat: " .. tostring(playerSeat))
|
|
|
|
|
2025-07-30 02:59:59 +02:00
|
|
|
if playerSeat == -1 then -- Fahrersitz
|
|
|
|
print("^3[TAXI STATIONS DEBUG]^7 Player is in driver seat, moving to passenger area")
|
|
|
|
|
|
|
|
if driver and DoesEntityExist(driver) then
|
2025-07-30 03:05:27 +02:00
|
|
|
-- Spieler zum nächsten verfügbaren Sitz bewegen
|
|
|
|
Wait(1000)
|
2025-07-30 02:59:59 +02:00
|
|
|
TaskShuffleToNextVehicleSeat(playerPed, vehicle)
|
|
|
|
Wait(2000)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
lib.notify({
|
|
|
|
title = 'Taxi Service',
|
|
|
|
description = 'Willkommen im Taxi! Wähle dein Ziel.',
|
|
|
|
type = 'success'
|
|
|
|
})
|
|
|
|
|
2025-07-30 02:17:38 +02:00
|
|
|
-- Ziel-Menu öffnen
|
2025-07-30 02:59:59 +02:00
|
|
|
Wait(1000) -- Kurz warten damit Einsteigen abgeschlossen ist
|
2025-07-30 02:17:38 +02:00
|
|
|
OpenStationTaxiMenu(stationId, vehicleId, vehicle, driver, vehicleInfo.data.pricePerKm)
|
|
|
|
break
|
|
|
|
end
|
|
|
|
Wait(100)
|
|
|
|
end
|
2025-07-30 02:46:15 +02:00
|
|
|
|
2025-07-30 02:59:59 +02:00
|
|
|
if not hasEntered then
|
2025-07-30 02:46:15 +02:00
|
|
|
print("^1[TAXI STATIONS DEBUG]^7 Player failed to enter vehicle")
|
2025-07-30 02:59:59 +02:00
|
|
|
|
|
|
|
-- Info-Text verstecken
|
|
|
|
lib.hideTextUI()
|
|
|
|
|
|
|
|
lib.notify({
|
|
|
|
title = 'Taxi Service',
|
|
|
|
description = 'Einsteigen fehlgeschlagen',
|
|
|
|
type = 'error'
|
|
|
|
})
|
|
|
|
|
2025-07-30 02:46:15 +02:00
|
|
|
-- Cleanup
|
2025-07-30 02:53:21 +02:00
|
|
|
if driver and DoesEntityExist(driver) then
|
2025-07-30 02:46:15 +02:00
|
|
|
DeleteEntity(driver)
|
|
|
|
end
|
|
|
|
SetVehicleDoorsLocked(vehicle, 2)
|
2025-07-30 02:59:59 +02:00
|
|
|
vehicleInfo.occupied = false
|
2025-07-30 02:46:15 +02:00
|
|
|
end
|
2025-07-30 02:17:38 +02:00
|
|
|
end)
|
|
|
|
end)
|
|
|
|
|
|
|
|
function OpenStationTaxiMenu(stationId, vehicleId, vehicle, driver, pricePerKm)
|
2025-07-30 02:46:15 +02:00
|
|
|
print("^2[TAXI STATIONS DEBUG]^7 Opening station taxi menu")
|
|
|
|
|
2025-07-30 02:17:38 +02:00
|
|
|
local options = {}
|
|
|
|
|
|
|
|
-- Bekannte Ziele hinzufügen
|
|
|
|
for _, destination in pairs(Config.KnownDestinations) do
|
|
|
|
local customPrice = math.max(Config.MinFare, math.ceil((CalculateDistanceToCoords(destination.coords) / 1000) * pricePerKm))
|
|
|
|
table.insert(options, {
|
|
|
|
title = destination.name,
|
2025-07-30 02:46:15 +02:00
|
|
|
description = 'Preis: $' .. customPrice .. ' | Entfernung: ' .. math.ceil(CalculateDistanceToCoords(destination.coords) / 1000 * 100) / 100 .. 'km',
|
2025-07-30 02:17:38 +02:00
|
|
|
icon = 'map-marker',
|
|
|
|
onSelect = function()
|
|
|
|
StartStationTaxiRide(stationId, vehicleId, vehicle, driver, destination.coords, customPrice)
|
|
|
|
end
|
|
|
|
})
|
|
|
|
end
|
|
|
|
|
2025-07-30 02:46:15 +02:00
|
|
|
-- Andere Taxi-Stationen als Ziele
|
|
|
|
table.insert(options, {
|
|
|
|
title = '📍 Andere Taxi-Stationen',
|
|
|
|
description = 'Fahre zu einer anderen Taxi-Station',
|
|
|
|
icon = 'taxi',
|
|
|
|
onSelect = function()
|
|
|
|
OpenStationSelectionMenu(stationId, vehicleId, vehicle, driver, pricePerKm)
|
|
|
|
end
|
|
|
|
})
|
|
|
|
|
2025-07-30 02:17:38 +02:00
|
|
|
-- 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)
|
|
|
|
local distance = CalculateDistanceToCoords(coords) / 1000
|
|
|
|
local price = math.max(Config.MinFare, math.ceil(distance * pricePerKm))
|
|
|
|
StartStationTaxiRide(stationId, vehicleId, vehicle, driver, coords, price)
|
|
|
|
else
|
|
|
|
lib.notify({
|
|
|
|
title = 'Taxi Service',
|
|
|
|
description = 'Du hast keinen Waypoint gesetzt',
|
|
|
|
type = 'error'
|
|
|
|
})
|
|
|
|
OpenStationTaxiMenu(stationId, vehicleId, vehicle, driver, pricePerKm)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
})
|
|
|
|
|
2025-07-30 02:53:21 +02:00
|
|
|
-- Selbst fahren Option (wenn kein Fahrer)
|
|
|
|
if not driver or not DoesEntityExist(driver) then
|
|
|
|
table.insert(options, {
|
|
|
|
title = '🚗 Selbst fahren',
|
|
|
|
description = 'Du fährst das Taxi selbst (kostenlos)',
|
|
|
|
icon = 'car',
|
|
|
|
onSelect = function()
|
|
|
|
SelfDriveStationTaxi(stationId, vehicleId, vehicle)
|
|
|
|
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()
|
|
|
|
ExitStationTaxi(stationId, vehicleId, vehicle, driver)
|
|
|
|
end
|
|
|
|
})
|
|
|
|
|
|
|
|
lib.registerContext({
|
|
|
|
id = 'station_taxi_menu',
|
2025-07-30 02:46:15 +02:00
|
|
|
title = 'Taxi - Ziel wählen (' .. Config.TaxiStations[stationId].name .. ')',
|
2025-07-30 02:17:38 +02:00
|
|
|
options = options
|
|
|
|
})
|
|
|
|
|
|
|
|
lib.showContext('station_taxi_menu')
|
|
|
|
end
|
|
|
|
|
2025-07-30 02:53:21 +02:00
|
|
|
function SelfDriveStationTaxi(stationId, vehicleId, vehicle)
|
|
|
|
print("^2[TAXI STATIONS DEBUG]^7 Player driving taxi themselves")
|
|
|
|
|
|
|
|
local playerPed = PlayerPedId()
|
|
|
|
|
|
|
|
-- Spieler zum Fahrersitz bewegen
|
|
|
|
TaskShuffleToNextVehicleSeat(playerPed, vehicle)
|
|
|
|
|
|
|
|
lib.notify({
|
|
|
|
title = 'Taxi Service',
|
|
|
|
description = 'Du fährst das Taxi jetzt selbst. Bringe es zur Station zurück wenn du fertig bist.',
|
|
|
|
type = 'info'
|
|
|
|
})
|
|
|
|
|
|
|
|
-- Überwachung für Rückgabe
|
|
|
|
CreateThread(function()
|
|
|
|
while DoesEntityExist(vehicle) do
|
|
|
|
local playerPed = PlayerPedId()
|
|
|
|
|
|
|
|
-- Prüfen ob Spieler noch im Fahrzeug ist
|
|
|
|
if not IsPedInVehicle(playerPed, vehicle, false) then
|
|
|
|
print("^2[TAXI STATIONS DEBUG]^7 Player left self-drive taxi")
|
|
|
|
|
|
|
|
-- Nach 30 Sekunden Taxi zurück zur Station
|
|
|
|
SetTimeout(30000, function()
|
|
|
|
ReturnTaxiToStation(stationId, vehicleId, vehicle, nil)
|
|
|
|
end)
|
|
|
|
break
|
|
|
|
end
|
|
|
|
|
|
|
|
Wait(5000)
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
end
|
|
|
|
|
2025-07-30 02:46:15 +02:00
|
|
|
function OpenStationSelectionMenu(stationId, vehicleId, vehicle, driver, pricePerKm)
|
|
|
|
print("^2[TAXI STATIONS DEBUG]^7 Opening station selection menu")
|
|
|
|
|
|
|
|
local options = {}
|
|
|
|
|
|
|
|
for otherStationId, station in pairs(Config.TaxiStations) do
|
|
|
|
if otherStationId ~= stationId then
|
|
|
|
local distance = CalculateDistanceToCoords(station.blipCoords) / 1000
|
|
|
|
local price = math.max(Config.MinFare, math.ceil(distance * pricePerKm))
|
|
|
|
|
|
|
|
table.insert(options, {
|
|
|
|
title = station.name,
|
|
|
|
description = 'Preis: $' .. price .. ' | Entfernung: ' .. math.ceil(distance * 100) / 100 .. 'km',
|
|
|
|
icon = 'building',
|
|
|
|
onSelect = function()
|
|
|
|
StartStationTaxiRide(stationId, vehicleId, vehicle, driver, station.blipCoords, price)
|
|
|
|
end
|
|
|
|
})
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Zurück Option
|
|
|
|
table.insert(options, {
|
|
|
|
title = '← Zurück',
|
|
|
|
description = 'Zurück zum Hauptmenü',
|
|
|
|
icon = 'arrow-left',
|
|
|
|
onSelect = function()
|
|
|
|
OpenStationTaxiMenu(stationId, vehicleId, vehicle, driver, pricePerKm)
|
|
|
|
end
|
|
|
|
})
|
|
|
|
|
|
|
|
lib.registerContext({
|
|
|
|
id = 'station_selection_menu',
|
|
|
|
title = 'Taxi-Stationen',
|
|
|
|
options = options
|
|
|
|
})
|
|
|
|
|
|
|
|
lib.showContext('station_selection_menu')
|
|
|
|
end
|
|
|
|
|
2025-07-30 02:17:38 +02:00
|
|
|
function StartStationTaxiRide(stationId, vehicleId, vehicle, driver, destination, price)
|
2025-07-30 07:32:37 +02:00
|
|
|
print("^2[TAXI STATIONS DEBUG]^7 Starting station taxi ride to: " .. tostring(destination.x) .. ", " .. tostring(destination.y) .. ", " .. tostring(destination.z))
|
2025-07-30 02:46:15 +02:00
|
|
|
|
2025-07-30 02:53:21 +02:00
|
|
|
-- Wenn kein Fahrer, Spieler selbst fahren lassen
|
|
|
|
if not driver or not DoesEntityExist(driver) then
|
|
|
|
lib.notify({
|
|
|
|
title = 'Taxi Service',
|
|
|
|
description = 'Kein Fahrer verfügbar. Fahre selbst zum Ziel! (Kostenlos)',
|
|
|
|
type = 'info'
|
|
|
|
})
|
|
|
|
|
|
|
|
-- Destination Blip erstellen
|
|
|
|
local destinationBlip = AddBlipForCoord(destination.x, destination.y, destination.z)
|
|
|
|
SetBlipSprite(destinationBlip, 1)
|
|
|
|
SetBlipColour(destinationBlip, 2)
|
|
|
|
SetBlipScale(destinationBlip, 0.8)
|
2025-07-30 07:32:37 +02:00
|
|
|
SetBlipRoute(destinationBlip, true) -- Route zum Ziel anzeigen
|
2025-07-30 02:53:21 +02:00
|
|
|
BeginTextCommandSetBlipName("STRING")
|
|
|
|
AddTextComponentString("Taxi Ziel")
|
|
|
|
EndTextCommandSetBlipName(destinationBlip)
|
|
|
|
|
|
|
|
-- Route setzen
|
|
|
|
SetNewWaypoint(destination.x, destination.y)
|
|
|
|
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
2025-07-30 02:17:38 +02:00
|
|
|
lib.notify({
|
|
|
|
title = 'Taxi Service',
|
|
|
|
description = 'Fahrt gestartet - Preis: $' .. price,
|
|
|
|
type = 'success'
|
|
|
|
})
|
|
|
|
|
|
|
|
-- Destination Blip erstellen
|
|
|
|
local destinationBlip = AddBlipForCoord(destination.x, destination.y, destination.z)
|
|
|
|
SetBlipSprite(destinationBlip, 1)
|
|
|
|
SetBlipColour(destinationBlip, 2)
|
|
|
|
SetBlipScale(destinationBlip, 0.8)
|
2025-07-30 07:32:37 +02:00
|
|
|
SetBlipRoute(destinationBlip, true) -- Route zum Ziel anzeigen
|
2025-07-30 02:17:38 +02:00
|
|
|
BeginTextCommandSetBlipName("STRING")
|
|
|
|
AddTextComponentString("Taxi Ziel")
|
|
|
|
EndTextCommandSetBlipName(destinationBlip)
|
|
|
|
|
2025-07-30 08:20:25 +02:00
|
|
|
-- Zum Ziel fahren mit verbesserter Navigation und geduldiger Fahrweise
|
|
|
|
-- Niedrigere Geschwindigkeit und angepasste Fahrweise
|
|
|
|
local drivingStyle = 786603 -- Normal/Vorsichtig
|
|
|
|
TaskVehicleDriveToCoordLongrange(driver, vehicle, destination.x, destination.y, destination.z, 20.0, drivingStyle, 10.0)
|
|
|
|
|
2025-07-30 08:31:19 +02:00
|
|
|
-- Fahrt überwachen
|
|
|
|
CreateThread(function()
|
|
|
|
local lastPos = GetEntityCoords(vehicle)
|
|
|
|
local stuckCounter = 0
|
|
|
|
local maxStuckCount = 20 -- Erhöht von 5 auf 20 für viel mehr Geduld
|
|
|
|
local stuckThreshold = 0.5 -- Reduziert von 1.0 auf 0.5 für genauere Erkennung
|
|
|
|
local checkInterval = 3000 -- Erhöht von 2000 auf 3000 ms für längere Prüfintervalle
|
|
|
|
local rideTimeout = GetGameTimer() + (8 * 60 * 1000) -- 8 Minuten Timeout (erhöht von 5)
|
|
|
|
local lastStuckWarning = 0 -- Zeitpunkt der letzten Steckenbleiben-Warnung
|
|
|
|
|
|
|
|
while DoesEntityExist(vehicle) and DoesEntityExist(driver) do
|
|
|
|
local vehicleCoords = GetEntityCoords(vehicle)
|
|
|
|
local distance = #(vector3(destination.x, destination.y, destination.z) - vehicleCoords)
|
|
|
|
local distanceMoved = #(lastPos - vehicleCoords)
|
|
|
|
|
|
|
|
-- Überprüfen ob wir angekommen sind
|
|
|
|
if distance < 10.0 then
|
|
|
|
-- Angekommen
|
|
|
|
TaskVehicleTempAction(driver, vehicle, 27, 3000)
|
2025-07-30 02:17:38 +02:00
|
|
|
|
2025-07-30 08:31:19 +02:00
|
|
|
print("^2[TAXI STATIONS DEBUG]^7 Arrived at destination")
|
|
|
|
lib.notify({
|
|
|
|
title = 'Taxi Service',
|
|
|
|
description = 'Du bist angekommen! Preis: $' .. price,
|
|
|
|
type = 'success'
|
|
|
|
})
|
|
|
|
|
|
|
|
-- Bezahlung
|
|
|
|
TriggerServerEvent('taxi:payFare', price)
|
|
|
|
|
|
|
|
-- Blip entfernen
|
|
|
|
RemoveBlip(destinationBlip)
|
|
|
|
|
|
|
|
-- Nach 10 Sekunden Taxi zurück zur Station
|
|
|
|
SetTimeout(10000, function()
|
|
|
|
ReturnTaxiToStation(stationId, vehicleId, vehicle, driver)
|
|
|
|
end)
|
|
|
|
|
|
|
|
break
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Überprüfen ob das Taxi stecken geblieben ist
|
|
|
|
-- Prüfe auch ob das Fahrzeug steht (Geschwindigkeit nahe 0)
|
|
|
|
local speed = GetEntitySpeed(vehicle)
|
|
|
|
local isAtRedLight = IsVehicleStoppedAtTrafficLights(vehicle)
|
|
|
|
|
|
|
|
-- Wenn das Fahrzeug an einer Ampel steht, nicht als steckengeblieben betrachten
|
|
|
|
if distanceMoved < stuckThreshold and speed < 0.5 and not isAtRedLight then
|
|
|
|
stuckCounter = stuckCounter + 1
|
|
|
|
|
|
|
|
-- Nur alle 5 Zähler-Erhöhungen loggen, um Spam zu vermeiden
|
|
|
|
if stuckCounter % 5 == 0 then
|
|
|
|
print("^3[TAXI STATIONS DEBUG]^7 Taxi might be stuck: " .. stuckCounter .. "/" .. maxStuckCount)
|
2025-07-30 02:17:38 +02:00
|
|
|
end
|
|
|
|
|
2025-07-30 08:31:19 +02:00
|
|
|
-- Nur versuchen zu befreien, wenn wirklich lange steckengeblieben
|
|
|
|
if stuckCounter >= maxStuckCount then
|
|
|
|
-- Mindestens 30 Sekunden zwischen Befreiungsversuchen warten
|
|
|
|
local currentTime = GetGameTimer()
|
|
|
|
if currentTime - lastStuckWarning > 30000 then
|
|
|
|
lastStuckWarning = currentTime
|
|
|
|
|
2025-07-30 07:32:37 +02:00
|
|
|
print("^1[TAXI STATIONS DEBUG]^7 Taxi stuck during ride, attempting recovery")
|
|
|
|
|
|
|
|
-- Versuche, das Taxi zu befreien
|
|
|
|
ClearPedTasks(driver)
|
|
|
|
|
|
|
|
-- Rückwärts fahren
|
|
|
|
TaskVehicleTempAction(driver, vehicle, 8, 2000) -- Reverse
|
|
|
|
Wait(2000)
|
|
|
|
|
|
|
|
-- Drehen
|
|
|
|
TaskVehicleTempAction(driver, vehicle, 7, 2000) -- Turn left
|
|
|
|
Wait(1000)
|
|
|
|
TaskVehicleTempAction(driver, vehicle, 8, 1000) -- Reverse
|
|
|
|
Wait(1000)
|
|
|
|
TaskVehicleTempAction(driver, vehicle, 6, 2000) -- Turn right
|
|
|
|
Wait(1000)
|
|
|
|
|
2025-07-30 08:20:25 +02:00
|
|
|
-- Neue Route zum Ziel mit geduldiger Fahrweise
|
|
|
|
local drivingStyle = 786603 -- Normal/Vorsichtig
|
|
|
|
TaskVehicleDriveToCoordLongrange(driver, vehicle, destination.x, destination.y, destination.z, 20.0, drivingStyle, 10.0)
|
2025-07-30 07:32:37 +02:00
|
|
|
|
2025-07-30 08:31:19 +02:00
|
|
|
-- Steckenbleiben-Zähler zurücksetzen, aber nicht ganz auf 0
|
|
|
|
-- So kann ein wirklich festgefahrenes Taxi nach einiger Zeit einen neuen Versuch starten
|
|
|
|
stuckCounter = maxStuckCount / 2
|
2025-07-30 07:32:37 +02:00
|
|
|
end
|
2025-07-30 08:31:19 +02:00
|
|
|
end
|
|
|
|
else
|
|
|
|
-- Wenn sich das Fahrzeug bewegt oder an einer Ampel steht, Zähler langsamer reduzieren
|
|
|
|
if isAtRedLight then
|
|
|
|
-- An Ampel: Zähler nicht erhöhen, aber auch nicht stark reduzieren
|
|
|
|
stuckCounter = math.max(0, stuckCounter - 0.2)
|
2025-07-30 08:08:01 +02:00
|
|
|
else
|
2025-07-30 08:31:19 +02:00
|
|
|
-- In Bewegung: Zähler reduzieren
|
2025-07-30 07:32:37 +02:00
|
|
|
stuckCounter = math.max(0, stuckCounter - 1)
|
2025-07-30 08:08:01 +02:00
|
|
|
end
|
2025-07-30 08:31:19 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
-- Überprüfen ob die Fahrt zu lange dauert
|
|
|
|
if GetGameTimer() > rideTimeout then
|
|
|
|
print("^1[TAXI STATIONS DEBUG]^7 Taxi ride timed out!")
|
|
|
|
lib.notify({
|
|
|
|
title = 'Taxi Service',
|
|
|
|
description = 'Die Fahrt dauert zu lange. Wir sind fast da!',
|
|
|
|
type = 'warning'
|
|
|
|
})
|
2025-07-30 07:32:37 +02:00
|
|
|
|
2025-07-30 08:31:19 +02:00
|
|
|
-- Teleportiere Taxi in die Nähe des Ziels
|
|
|
|
local offset = vector3(
|
|
|
|
math.random(-20, 20),
|
|
|
|
math.random(-20, 20),
|
|
|
|
0
|
|
|
|
)
|
|
|
|
local nearDestination = vector3(destination.x, destination.y, destination.z) + offset
|
|
|
|
|
|
|
|
-- Finde gültige Z-Koordinate
|
|
|
|
local success, groundZ = GetGroundZFor_3dCoord(nearDestination.x, nearDestination.y, nearDestination.z, true)
|
|
|
|
if success then
|
|
|
|
nearDestination = vector3(nearDestination.x, nearDestination.y, groundZ)
|
2025-07-30 07:32:37 +02:00
|
|
|
end
|
|
|
|
|
2025-07-30 08:31:19 +02:00
|
|
|
-- Teleportiere Taxi
|
|
|
|
SetEntityCoords(vehicle, nearDestination.x, nearDestination.y, nearDestination.z, false, false, false, false)
|
|
|
|
|
|
|
|
-- Neues Timeout setzen (1 Minute)
|
|
|
|
rideTimeout = GetGameTimer() + (60 * 1000)
|
2025-07-30 02:17:38 +02:00
|
|
|
end
|
2025-07-30 08:31:19 +02:00
|
|
|
|
|
|
|
lastPos = vehicleCoords
|
|
|
|
Wait(checkInterval)
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
2025-07-30 02:17:38 +02:00
|
|
|
|
|
|
|
function ExitStationTaxi(stationId, vehicleId, vehicle, driver)
|
2025-07-30 02:46:15 +02:00
|
|
|
print("^2[TAXI STATIONS DEBUG]^7 Player exiting station taxi")
|
|
|
|
|
2025-07-30 02:17:38 +02:00
|
|
|
local playerPed = PlayerPedId()
|
|
|
|
TaskLeaveVehicle(playerPed, vehicle, 0)
|
|
|
|
|
|
|
|
lib.notify({
|
|
|
|
title = 'Taxi Service',
|
|
|
|
description = 'Du bist ausgestiegen',
|
|
|
|
type = 'info'
|
|
|
|
})
|
|
|
|
|
|
|
|
-- Taxi zurück zur Station nach 5 Sekunden
|
|
|
|
SetTimeout(5000, function()
|
|
|
|
ReturnTaxiToStation(stationId, vehicleId, vehicle, driver)
|
|
|
|
end)
|
|
|
|
end
|
|
|
|
|
|
|
|
function ReturnTaxiToStation(stationId, vehicleId, vehicle, driver)
|
2025-07-30 02:46:15 +02:00
|
|
|
print("^2[TAXI STATIONS DEBUG]^7 Returning taxi to station: " .. stationId .. "/" .. vehicleId)
|
|
|
|
|
2025-07-30 02:17:38 +02:00
|
|
|
if not stationVehicles[stationId] or not stationVehicles[stationId][vehicleId] then
|
2025-07-30 02:46:15 +02:00
|
|
|
print("^1[TAXI STATIONS DEBUG]^7 Station vehicle data not found for return")
|
2025-07-30 02:17:38 +02:00
|
|
|
return
|
|
|
|
end
|
|
|
|
|
2025-07-30 03:50:38 +02:00
|
|
|
if not DoesEntityExist(vehicle) then
|
|
|
|
print("^1[TAXI STATIONS DEBUG]^7 Vehicle doesn't exist anymore")
|
|
|
|
-- Fahrzeug als nicht besetzt markieren
|
|
|
|
stationVehicles[stationId][vehicleId].occupied = false
|
|
|
|
stationVehicles[stationId][vehicleId].driver = nil
|
|
|
|
stationVehicles[stationId][vehicleId].entity = nil
|
|
|
|
|
|
|
|
-- Nach Respawn-Zeit neues Fahrzeug spawnen
|
|
|
|
print("^2[TAXI STATIONS DEBUG]^7 Scheduling respawn in " .. Config.StationTaxiRespawnTime .. " seconds")
|
|
|
|
SetTimeout(Config.StationTaxiRespawnTime * 1000, function()
|
|
|
|
if stationVehicles[stationId] and stationVehicles[stationId][vehicleId] then
|
|
|
|
local vehicleData = stationVehicles[stationId][vehicleId].data
|
|
|
|
print("^2[TAXI STATIONS DEBUG]^7 Respawning vehicle at station")
|
|
|
|
SpawnStationVehicle(stationId, vehicleId, vehicleData)
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
return
|
2025-07-30 02:17:38 +02:00
|
|
|
end
|
|
|
|
|
2025-07-30 03:50:38 +02:00
|
|
|
-- Wenn Fahrer existiert, Taxi zur Station zurückfahren lassen
|
|
|
|
if driver and DoesEntityExist(driver) then
|
|
|
|
print("^2[TAXI STATIONS DEBUG]^7 Making taxi drive back to station")
|
|
|
|
|
|
|
|
-- Zufällige Position in der Nähe der Station finden
|
|
|
|
local stationCoords = Config.TaxiStations[stationId].coords
|
|
|
|
|
|
|
|
-- Taxi zur Station zurückfahren lassen
|
2025-07-30 07:32:37 +02:00
|
|
|
TaskVehicleDriveToCoordLongrange(driver, vehicle, stationCoords.x, stationCoords.y, stationCoords.z, 25.0, 786603, 5.0)
|
2025-07-30 03:50:38 +02:00
|
|
|
|
|
|
|
-- qb-target entfernen während der Fahrt
|
2025-07-30 02:17:38 +02:00
|
|
|
exports['qb-target']:RemoveTargetEntity(vehicle)
|
2025-07-30 03:50:38 +02:00
|
|
|
|
|
|
|
-- Nach 10 Sekunden tatsächlich löschen
|
|
|
|
SetTimeout(10000, function()
|
|
|
|
-- Fahrer löschen
|
|
|
|
if driver and DoesEntityExist(driver) then
|
|
|
|
DeleteEntity(driver)
|
|
|
|
print("^2[TAXI STATIONS DEBUG]^7 Driver deleted")
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Fahrzeug löschen
|
|
|
|
if DoesEntityExist(vehicle) then
|
|
|
|
DeleteEntity(vehicle)
|
|
|
|
print("^2[TAXI STATIONS DEBUG]^7 Vehicle deleted")
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Fahrzeug als nicht besetzt markieren
|
|
|
|
stationVehicles[stationId][vehicleId].occupied = false
|
|
|
|
stationVehicles[stationId][vehicleId].driver = nil
|
|
|
|
stationVehicles[stationId][vehicleId].entity = nil
|
|
|
|
|
|
|
|
-- Nach Respawn-Zeit neues Fahrzeug spawnen
|
|
|
|
print("^2[TAXI STATIONS DEBUG]^7 Scheduling respawn in " .. Config.StationTaxiRespawnTime .. " seconds")
|
|
|
|
SetTimeout(Config.StationTaxiRespawnTime * 1000, function()
|
|
|
|
if stationVehicles[stationId] and stationVehicles[stationId][vehicleId] then
|
|
|
|
local vehicleData = stationVehicles[stationId][vehicleId].data
|
|
|
|
print("^2[TAXI STATIONS DEBUG]^7 Respawning vehicle at station")
|
|
|
|
SpawnStationVehicle(stationId, vehicleId, vehicleData)
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
end)
|
|
|
|
else
|
|
|
|
-- Sofort löschen wenn kein Fahrer da ist
|
|
|
|
-- qb-target entfernen
|
|
|
|
if DoesEntityExist(vehicle) then
|
|
|
|
exports['qb-target']:RemoveTargetEntity(vehicle)
|
|
|
|
DeleteEntity(vehicle)
|
|
|
|
print("^2[TAXI STATIONS DEBUG]^7 Vehicle deleted")
|
2025-07-30 02:17:38 +02:00
|
|
|
end
|
2025-07-30 03:50:38 +02:00
|
|
|
|
|
|
|
-- Fahrzeug als nicht besetzt markieren
|
|
|
|
stationVehicles[stationId][vehicleId].occupied = false
|
|
|
|
stationVehicles[stationId][vehicleId].driver = nil
|
|
|
|
stationVehicles[stationId][vehicleId].entity = nil
|
|
|
|
|
|
|
|
-- Nach Respawn-Zeit neues Fahrzeug spawnen
|
|
|
|
print("^2[TAXI STATIONS DEBUG]^7 Scheduling respawn in " .. Config.StationTaxiRespawnTime .. " seconds")
|
|
|
|
SetTimeout(Config.StationTaxiRespawnTime * 1000, function()
|
|
|
|
if stationVehicles[stationId] and stationVehicles[stationId][vehicleId] then
|
|
|
|
local vehicleData = stationVehicles[stationId][vehicleId].data
|
|
|
|
print("^2[TAXI STATIONS DEBUG]^7 Respawning vehicle at station")
|
|
|
|
SpawnStationVehicle(stationId, vehicleId, vehicleData)
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
end
|
2025-07-30 02:17:38 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
function CalculateDistanceToCoords(coords)
|
|
|
|
local playerCoords = GetEntityCoords(PlayerPedId())
|
|
|
|
return #(playerCoords - coords)
|
|
|
|
end
|
|
|
|
|
2025-07-30 02:59:59 +02:00
|
|
|
-- Command um nächste Taxi-Station zu finden
|
|
|
|
RegisterCommand('nearesttaxi', function()
|
2025-07-30 02:20:13 +02:00
|
|
|
local playerCoords = GetEntityCoords(PlayerPedId())
|
|
|
|
local nearestStation = nil
|
|
|
|
local nearestDistance = math.huge
|
|
|
|
|
|
|
|
for stationId, station in pairs(Config.TaxiStations) do
|
|
|
|
local distance = #(playerCoords - station.blipCoords)
|
|
|
|
if distance < nearestDistance then
|
|
|
|
nearestDistance = distance
|
|
|
|
nearestStation = {id = stationId, data = station, distance = distance}
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2025-07-30 02:59:59 +02:00
|
|
|
if nearestStation then
|
2025-07-30 02:20:13 +02:00
|
|
|
lib.notify({
|
|
|
|
title = 'Taxi Service',
|
2025-07-30 03:50:38 +02:00
|
|
|
description = 'Nächste Station: ' .. nearestStation.data.name .. ' (' .. math.ceil(nearestDistance) .. 'm)',
|
2025-07-30 02:20:13 +02:00
|
|
|
type = 'info'
|
|
|
|
})
|
|
|
|
|
|
|
|
-- Waypoint zur nächsten Station setzen
|
2025-07-30 02:59:59 +02:00
|
|
|
SetNewWaypoint(nearestStation.data.blipCoords.x, nearestStation.data.blipCoords.y)
|
2025-07-30 02:20:13 +02:00
|
|
|
else
|
|
|
|
lib.notify({
|
|
|
|
title = 'Taxi Service',
|
|
|
|
description = 'Keine Taxi-Station gefunden',
|
|
|
|
type = 'error'
|
|
|
|
})
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
|
2025-07-30 02:46:15 +02:00
|
|
|
-- Event für Admin Respawn
|
|
|
|
RegisterNetEvent('taxi:respawnAllStations', function()
|
|
|
|
print("^2[TAXI STATIONS DEBUG]^7 Respawning all stations...")
|
2025-07-30 02:20:13 +02:00
|
|
|
|
2025-07-30 02:46:15 +02:00
|
|
|
-- Alle bestehenden Fahrzeuge löschen
|
|
|
|
for stationId, vehicles in pairs(stationVehicles) do
|
|
|
|
for vehicleId, vehicleInfo in pairs(vehicles) do
|
|
|
|
if vehicleInfo.entity and DoesEntityExist(vehicleInfo.entity) then
|
|
|
|
exports['qb-target']:RemoveTargetEntity(vehicleInfo.entity)
|
|
|
|
DeleteEntity(vehicleInfo.entity)
|
2025-07-30 02:20:13 +02:00
|
|
|
end
|
2025-07-30 02:46:15 +02:00
|
|
|
if vehicleInfo.driver and DoesEntityExist(vehicleInfo.driver) then
|
|
|
|
DeleteEntity(vehicleInfo.driver)
|
2025-07-30 02:20:13 +02:00
|
|
|
end
|
|
|
|
end
|
2025-07-30 02:46:15 +02:00
|
|
|
end
|
2025-07-30 02:20:13 +02:00
|
|
|
|
2025-07-30 02:46:15 +02:00
|
|
|
-- Alle Blips entfernen
|
|
|
|
for _, blip in pairs(stationBlips) do
|
|
|
|
RemoveBlip(blip)
|
2025-07-30 02:20:13 +02:00
|
|
|
end
|
|
|
|
|
2025-07-30 02:46:15 +02:00
|
|
|
-- Variablen zurücksetzen
|
|
|
|
stationVehicles = {}
|
|
|
|
stationBlips = {}
|
|
|
|
|
|
|
|
-- Stationen neu initialisieren
|
|
|
|
Wait(1000)
|
|
|
|
InitializeTaxiStations()
|
|
|
|
|
|
|
|
lib.notify({
|
|
|
|
title = 'Taxi Service',
|
2025-07-30 03:21:38 +02:00
|
|
|
description = 'Alle Taxi-Stationen wurden neu gespawnt',
|
2025-07-30 02:46:15 +02:00
|
|
|
type = 'success'
|
2025-07-30 02:20:13 +02:00
|
|
|
})
|
2025-07-30 02:46:15 +02:00
|
|
|
end)
|
2025-07-30 02:20:13 +02:00
|
|
|
|
2025-07-30 04:53:36 +02:00
|
|
|
-- Thread zum Überwachen der Tasten im Stations-Taxi
|
|
|
|
CreateThread(function()
|
|
|
|
while true do
|
|
|
|
Wait(0)
|
|
|
|
|
|
|
|
local playerPed = PlayerPedId()
|
|
|
|
local inStationTaxi = false
|
|
|
|
local currentStationTaxi = nil
|
|
|
|
local currentStationId = nil
|
|
|
|
local currentVehicleId = nil
|
|
|
|
local currentDriver = nil
|
|
|
|
local pricePerKm = 0
|
|
|
|
|
|
|
|
-- Prüfen ob Spieler in einem Stations-Taxi sitzt
|
|
|
|
for stationId, vehicles in pairs(stationVehicles) do
|
|
|
|
for vehicleId, vehicleInfo in pairs(vehicles) do
|
|
|
|
if vehicleInfo.entity and DoesEntityExist(vehicleInfo.entity) and vehicleInfo.occupied then
|
|
|
|
if IsPedInVehicle(playerPed, vehicleInfo.entity, false) then
|
|
|
|
inStationTaxi = true
|
|
|
|
currentStationTaxi = vehicleInfo.entity
|
|
|
|
currentStationId = stationId
|
|
|
|
currentVehicleId = vehicleId
|
|
|
|
currentDriver = vehicleInfo.driver
|
|
|
|
pricePerKm = vehicleInfo.data.pricePerKm
|
|
|
|
break
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
if inStationTaxi then break end
|
|
|
|
end
|
|
|
|
|
|
|
|
if inStationTaxi and currentStationTaxi then
|
|
|
|
-- Zeige Hinweise an
|
|
|
|
local helpText = '[E] - Ziel wählen [F] - Fahrt beenden'
|
|
|
|
lib.showTextUI(helpText, {
|
|
|
|
position = "top-center",
|
|
|
|
icon = 'taxi',
|
|
|
|
style = {
|
|
|
|
borderRadius = 10,
|
|
|
|
backgroundColor = '#48BB78',
|
|
|
|
color = 'white'
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
-- Wenn E gedrückt wird, öffne Menü
|
|
|
|
if IsControlJustReleased(0, 38) then -- E Taste
|
|
|
|
OpenStationTaxiMenu(currentStationId, currentVehicleId, currentStationTaxi, currentDriver, pricePerKm)
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Wenn F gedrückt wird, beende Fahrt
|
|
|
|
if IsControlJustReleased(0, 23) then -- F Taste
|
|
|
|
lib.hideTextUI()
|
|
|
|
EndStationTaxiRide(currentStationId, currentVehicleId, currentStationTaxi, currentDriver)
|
|
|
|
end
|
|
|
|
else
|
|
|
|
-- Nicht in einem Stations-Taxi
|
2025-07-30 07:32:37 +02:00
|
|
|
lib.hideTextUI()
|
2025-07-30 04:53:36 +02:00
|
|
|
Wait(1000)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
|
|
|
|
-- Funktion zum Beenden der Stations-Taxi Fahrt
|
|
|
|
function EndStationTaxiRide(stationId, vehicleId, vehicle, driver)
|
|
|
|
print("^2[TAXI STATIONS DEBUG]^7 Ending station taxi ride")
|
|
|
|
|
|
|
|
if not vehicle or not DoesEntityExist(vehicle) 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, vehicle, 0)
|
|
|
|
|
|
|
|
-- Warten bis ausgestiegen
|
|
|
|
CreateThread(function()
|
|
|
|
local timeout = GetGameTimer() + 5000
|
|
|
|
while GetGameTimer() < timeout do
|
|
|
|
if not IsPedInVehicle(playerPed, vehicle, false) then
|
|
|
|
-- Spieler ist ausgestiegen
|
|
|
|
break
|
|
|
|
end
|
|
|
|
Wait(100)
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Taxi nach 5 Sekunden zurück zur Station
|
|
|
|
SetTimeout(5000, function()
|
|
|
|
ReturnTaxiToStation(stationId, vehicleId, vehicle, driver)
|
|
|
|
end)
|
|
|
|
end)
|
|
|
|
end
|
|
|
|
|
2025-07-30 07:48:51 +02:00
|
|
|
-- Cleanup beim Resource Stop
|
|
|
|
AddEventHandler('onResourceStop', function(resourceName)
|
|
|
|
if GetCurrentResourceName() == resourceName then
|
|
|
|
print("^2[TAXI STATIONS DEBUG]^7 Cleaning up stations...")
|
|
|
|
|
|
|
|
-- TextUI verstecken falls noch angezeigt
|
|
|
|
lib.hideTextUI()
|
|
|
|
|
|
|
|
-- Alle Station-Fahrzeuge löschen
|
|
|
|
for stationId, vehicles in pairs(stationVehicles) do
|
|
|
|
for vehicleId, vehicleInfo in pairs(vehicles) do
|
|
|
|
if vehicleInfo.entity and DoesEntityExist(vehicleInfo.entity) then
|
|
|
|
exports['qb-target']:RemoveTargetEntity(vehicleInfo.entity)
|
|
|
|
DeleteEntity(vehicleInfo.entity)
|
|
|
|
end
|
|
|
|
if vehicleInfo.driver and DoesEntityExist(vehicleInfo.driver) then
|
|
|
|
DeleteEntity(vehicleInfo.driver)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Alle Blips entfernen
|
|
|
|
for _, blip in pairs(stationBlips) do
|
|
|
|
RemoveBlip(blip)
|
|
|
|
end
|
|
|
|
|
|
|
|
print("^2[TAXI STATIONS DEBUG]^7 Cleanup completed")
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
|