1
0
Fork 0
forked from Simnation/Main
Main/resources/[tools]/nordi_taxi/client/stations.lua

940 lines
34 KiB
Lua
Raw Normal View History

2025-07-30 02:17:38 +02:00
local QBCore = exports['qb-core']:GetCoreObject()
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 02:46:15 +02:00
Wait(2000) -- Längere Wartezeit
print("^2[TAXI STATIONS DEBUG]^7 Initializing taxi stations...")
2025-07-30 02:17:38 +02:00
InitializeTaxiStations()
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 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] = {}
for vehicleId, vehicleData in pairs(station.vehicles) do
2025-07-30 02:46:15 +02:00
print("^2[TAXI STATIONS DEBUG]^7 Spawning vehicle " .. vehicleId .. " (" .. vehicleData.model .. ") at station " .. stationId)
2025-07-30 02:17:38 +02:00
SpawnStationVehicle(stationId, vehicleId, vehicleData)
end
end
2025-07-30 02:46:15 +02:00
print("^2[TAXI STATIONS DEBUG]^7 All stations initialized")
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 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)
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!")
return
end
print("^2[TAXI STATIONS DEBUG]^7 Vehicle created: " .. vehicle)
2025-07-30 02:17:38 +02:00
SetEntityAsMissionEntity(vehicle, true, true)
SetVehicleOnGroundProperly(vehicle)
SetVehicleDoorsLocked(vehicle, 2) -- Locked
SetVehicleEngineOn(vehicle, false, true, false)
-- Fahrzeug-Info speichern
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 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 03:21:38 +02:00
"mp_m_freemode_01", -- Standard Male (sollte immer verfügbar sein)
"mp_f_freemode_01", -- Standard Female
"a_m_y_business_01", -- Business Male
"a_f_y_business_01", -- Business Female
"a_m_m_business_01", -- Business Male 2
"a_m_y_downtown_01", -- Downtown Male
"s_m_m_pilot_01", -- Pilot
"s_m_y_dealer_01" -- Dealer
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 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 02:46:15 +02:00
print("^2[TAXI STATIONS DEBUG]^7 Starting station taxi ride to: " .. tostring(destination))
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)
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)
BeginTextCommandSetBlipName("STRING")
AddTextComponentString("Taxi Ziel")
EndTextCommandSetBlipName(destinationBlip)
-- Zum Ziel fahren
TaskVehicleDriveToCoord(driver, vehicle, destination.x, destination.y, destination.z, 25.0, 0, GetEntityModel(vehicle), 786603, 1.0, true)
-- Fahrt überwachen
CreateThread(function()
while DoesEntityExist(vehicle) and DoesEntityExist(driver) do
local vehicleCoords = GetEntityCoords(vehicle)
local distance = #(vector3(destination.x, destination.y, destination.z) - vehicleCoords)
if distance < 10.0 then
-- Angekommen
TaskVehicleTempAction(driver, vehicle, 27, 3000)
2025-07-30 02:46:15 +02:00
print("^2[TAXI STATIONS DEBUG]^7 Arrived at destination")
2025-07-30 02:17:38 +02:00
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
Wait(2000)
end
end)
end
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
TaskVehicleDriveToCoord(driver, vehicle, stationCoords.x, stationCoords.y, stationCoords.z, 25.0, 0, GetEntityModel(vehicle), 786603, 1.0, true)
-- 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 02:46:15 +02:00
-- Cleanup beim Resource Stop
AddEventHandler('onResourceStop', function(resourceName)
if GetCurrentResourceName() == resourceName then
print("^2[TAXI STATIONS DEBUG]^7 Cleaning up stations...")
2025-07-30 02:59:59 +02:00
-- TextUI verstecken falls noch angezeigt
lib.hideTextUI()
2025-07-30 02:46:15 +02:00
-- 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)
2025-07-30 03:50:38 +02:00
2025-07-30 03:26:19 +02:00