1
0
Fork 0
forked from Simnation/Main
Main/resources/[tools]/nordi_taxi/client/main.lua
2025-07-30 02:46:15 +02:00

443 lines
14 KiB
Lua

local QBCore = exports['qb-core']:GetCoreObject()
local currentTaxi = nil
local taxiDriver = nil
local inTaxi = false
local taxiBlip = nil
local destinationBlip = nil
local meterRunning = false
local currentFare = 0
local lastTaxiCall = 0
print("^2[TAXI DEBUG]^7 Client script loaded")
-- Taxi rufen Command (Mobile Taxi)
RegisterCommand('taxi', function()
print("^2[TAXI DEBUG]^7 /taxi command executed")
local currentTime = GetGameTimer()
if currentTime - lastTaxiCall < (Config.TaxiCallCooldown * 1000) then
local remainingTime = math.ceil((Config.TaxiCallCooldown * 1000 - (currentTime - lastTaxiCall)) / 1000)
print("^1[TAXI DEBUG]^7 Cooldown active: " .. remainingTime .. " seconds")
lib.notify({
title = 'Taxi Service',
description = 'Du musst noch ' .. remainingTime .. ' Sekunden warten',
type = 'error'
})
return
end
if currentTaxi then
print("^1[TAXI DEBUG]^7 Taxi already exists")
lib.notify({
title = 'Taxi Service',
description = 'Du hast bereits ein Taxi gerufen',
type = 'error'
})
return
end
print("^2[TAXI DEBUG]^7 Calling mobile taxi...")
CallMobileTaxi()
end)
function CallMobileTaxi()
print("^2[TAXI DEBUG]^7 CallMobileTaxi function started")
lastTaxiCall = GetGameTimer()
lib.notify({
title = 'Taxi Service',
description = 'Ein Taxi wurde gerufen und ist auf dem Weg zu dir',
type = 'success'
})
CreateThread(function()
print("^2[TAXI DEBUG]^7 Taxi spawn thread started")
local playerPed = PlayerPedId()
local playerCoords = GetEntityCoords(playerPed)
print("^2[TAXI DEBUG]^7 Player coords: " .. tostring(playerCoords))
-- Prüfe ob Config existiert
if not Config.MobileTaxiSpawns then
print("^1[TAXI DEBUG]^7 Config.MobileTaxiSpawns not found!")
return
end
-- Zufällige Spawn-Location wählen
local spawnLocation = Config.MobileTaxiSpawns[math.random(#Config.MobileTaxiSpawns)]
print("^2[TAXI DEBUG]^7 Spawn location: " .. tostring(spawnLocation))
-- Zufälliges Taxi-Fahrzeug wählen
local selectedVehicle = SelectRandomTaxi()
print("^2[TAXI DEBUG]^7 Selected vehicle: " .. selectedVehicle.model)
-- Fahrzeug spawnen
local vehicleHash = GetHashKey(selectedVehicle.model)
print("^2[TAXI DEBUG]^7 Vehicle hash: " .. vehicleHash)
RequestModel(vehicleHash)
local timeout = GetGameTimer() + 10000
while not HasModelLoaded(vehicleHash) and GetGameTimer() < timeout do
print("^3[TAXI DEBUG]^7 Waiting for model to load...")
Wait(100)
end
if not HasModelLoaded(vehicleHash) then
print("^1[TAXI DEBUG]^7 Failed to load vehicle model!")
return
end
print("^2[TAXI DEBUG]^7 Creating vehicle...")
currentTaxi = CreateVehicle(vehicleHash, spawnLocation.x, spawnLocation.y, spawnLocation.z, spawnLocation.w, true, false)
if not DoesEntityExist(currentTaxi) then
print("^1[TAXI DEBUG]^7 Failed to create vehicle!")
return
end
print("^2[TAXI DEBUG]^7 Vehicle created successfully: " .. currentTaxi)
SetEntityAsMissionEntity(currentTaxi, true, true)
SetVehicleOnGroundProperly(currentTaxi)
-- Fahrer spawnen
local driverHash = GetHashKey("a_m_m_taxi_01")
RequestModel(driverHash)
timeout = GetGameTimer() + 10000
while not HasModelLoaded(driverHash) and GetGameTimer() < timeout do
print("^3[TAXI DEBUG]^7 Waiting for driver model to load...")
Wait(100)
end
if not HasModelLoaded(driverHash) then
print("^1[TAXI DEBUG]^7 Failed to load driver model!")
DeleteEntity(currentTaxi)
currentTaxi = nil
return
end
print("^2[TAXI DEBUG]^7 Creating driver...")
taxiDriver = CreatePedInsideVehicle(currentTaxi, 26, driverHash, -1, true, false)
if not DoesEntityExist(taxiDriver) then
print("^1[TAXI DEBUG]^7 Failed to create driver!")
DeleteEntity(currentTaxi)
currentTaxi = nil
return
end
print("^2[TAXI DEBUG]^7 Driver created successfully: " .. taxiDriver)
SetEntityAsMissionEntity(taxiDriver, true, true)
SetPedFleeAttributes(taxiDriver, 0, 0)
SetPedCombatAttributes(taxiDriver, 17, 1)
SetPedSeeingRange(taxiDriver, 0.0)
SetPedHearingRange(taxiDriver, 0.0)
SetPedAlertness(taxiDriver, 0)
SetPedKeepTask(taxiDriver, true)
-- Blip erstellen
taxiBlip = AddBlipForEntity(currentTaxi)
SetBlipSprite(taxiBlip, 198)
SetBlipColour(taxiBlip, 5)
SetBlipScale(taxiBlip, 0.8)
BeginTextCommandSetBlipName("STRING")
AddTextComponentString("Taxi")
EndTextCommandSetBlipName(taxiBlip)
print("^2[TAXI DEBUG]^7 Blip created")
-- Zum Spieler fahren
print("^2[TAXI DEBUG]^7 Sending taxi to player...")
TaskVehicleDriveToCoord(taxiDriver, currentTaxi, playerCoords.x, playerCoords.y, playerCoords.z, 20.0, 0, vehicleHash, 786603, 1.0, true)
-- Warten bis Taxi ankommt
local arrived = false
timeout = GetGameTimer() + (Config.MaxWaitTime * 1000)
while not arrived and GetGameTimer() < timeout do
if not DoesEntityExist(currentTaxi) or not DoesEntityExist(taxiDriver) then
print("^1[TAXI DEBUG]^7 Taxi or driver disappeared!")
break
end
local taxiCoords = GetEntityCoords(currentTaxi)
local distance = #(playerCoords - taxiCoords)
if distance < 10.0 then
arrived = true
TaskVehicleTempAction(taxiDriver, currentTaxi, 27, 3000)
print("^2[TAXI DEBUG]^7 Taxi arrived!")
lib.notify({
title = 'Taxi Service',
description = 'Dein Taxi ist angekommen! Steige ein.',
type = 'success'
})
WaitForPlayerToEnter(selectedVehicle.pricePerKm)
end
Wait(1000)
end
if not arrived then
print("^1[TAXI DEBUG]^7 Taxi failed to arrive in time")
lib.notify({
title = 'Taxi Service',
description = 'Das Taxi konnte dich nicht erreichen',
type = 'error'
})
CleanupMobileTaxi()
end
end)
end
function SelectRandomTaxi()
if not Config.TaxiVehicles or #Config.TaxiVehicles == 0 then
print("^1[TAXI DEBUG]^7 No taxi vehicles configured!")
return {model = 'taxi', pricePerKm = 5}
end
local totalChance = 0
for _, vehicle in pairs(Config.TaxiVehicles) do
totalChance = totalChance + vehicle.spawnChance
end
local randomValue = math.random(1, totalChance)
local currentChance = 0
for _, vehicle in pairs(Config.TaxiVehicles) do
currentChance = currentChance + vehicle.spawnChance
if randomValue <= currentChance then
return vehicle
end
end
return Config.TaxiVehicles[1]
end
function WaitForPlayerToEnter(pricePerKm)
print("^2[TAXI DEBUG]^7 Waiting for player to enter...")
CreateThread(function()
local timeout = GetGameTimer() + 60000
while currentTaxi and GetGameTimer() < timeout do
local playerPed = PlayerPedId()
if IsPedInVehicle(playerPed, currentTaxi, false) then
inTaxi = true
print("^2[TAXI DEBUG]^7 Player entered taxi")
OpenMobileTaxiMenu(pricePerKm)
break
end
Wait(1000)
end
if not inTaxi then
print("^1[TAXI DEBUG]^7 Player didn't enter taxi in time")
lib.notify({
title = 'Taxi Service',
description = 'Das Taxi ist weggefahren',
type = 'error'
})
CleanupMobileTaxi()
end
end)
end
function OpenMobileTaxiMenu(pricePerKm)
print("^2[TAXI DEBUG]^7 Opening mobile taxi menu")
local options = {}
-- Bekannte Ziele hinzufügen
for _, destination in pairs(Config.KnownDestinations) do
local customPrice = math.max(Config.MinFare, math.ceil((CalculateDistance(destination.coords) / 1000) * pricePerKm))
table.insert(options, {
title = destination.name,
description = 'Preis: $' .. customPrice,
icon = 'map-marker',
onSelect = function()
StartMobileTaxiRide(destination.coords, customPrice)
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)
local distance = CalculateDistance(coords) / 1000
local price = math.max(Config.MinFare, math.ceil(distance * pricePerKm))
StartMobileTaxiRide(coords, price)
else
lib.notify({
title = 'Taxi Service',
description = 'Du hast keinen Waypoint gesetzt',
type = 'error'
})
OpenMobileTaxiMenu(pricePerKm)
end
end
})
-- Aussteigen Option
table.insert(options, {
title = 'Aussteigen',
description = 'Das Taxi verlassen',
icon = 'door-open',
onSelect = function()
ExitMobileTaxi()
end
})
lib.registerContext({
id = 'mobile_taxi_menu',
title = 'Taxi - Ziel wählen',
options = options
})
lib.showContext('mobile_taxi_menu')
end
function StartMobileTaxiRide(destination, price)
if not currentTaxi or not taxiDriver then
print("^1[TAXI DEBUG]^7 No taxi or driver for ride")
return
end
print("^2[TAXI DEBUG]^7 Starting taxi ride to: " .. tostring(destination))
currentFare = price
meterRunning = true
-- Destination Blip erstellen
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)
lib.notify({
title = 'Taxi Service',
description = 'Fahrt gestartet - Preis: $' .. price,
type = 'success'
})
-- Zum Ziel fahren
TaskVehicleDriveToCoord(taxiDriver, currentTaxi, destination.x, destination.y, destination.z, 25.0, 0, GetEntityModel(currentTaxi), 786603, 1.0, true)
-- Überwachen der Fahrt
CreateThread(function()
while meterRunning and currentTaxi do
local taxiCoords = GetEntityCoords(currentTaxi)
local distance = #(vector3(destination.x, destination.y, destination.z) - taxiCoords)
if distance < 10.0 then
TaskVehicleTempAction(taxiDriver, currentTaxi, 27, 3000)
print("^2[TAXI DEBUG]^7 Arrived at destination")
lib.notify({
title = 'Taxi Service',
description = 'Du bist angekommen! Preis: $' .. currentFare,
type = 'success'
})
TriggerServerEvent('taxi:payFare', currentFare)
SetTimeout(10000, function()
CleanupMobileTaxi()
end)
break
end
Wait(2000)
end
end)
end
function CalculateDistance(coords)
local playerCoords = GetEntityCoords(PlayerPedId())
return #(playerCoords - coords)
end
function ExitMobileTaxi()
print("^2[TAXI DEBUG]^7 Player exiting taxi")
local playerPed = PlayerPedId()
TaskLeaveVehicle(playerPed, currentTaxi, 0)
lib.notify({
title = 'Taxi Service',
description = 'Du bist ausgestiegen',
type = 'info'
})
SetTimeout(5000, function()
CleanupMobileTaxi()
end)
end
function CleanupMobileTaxi()
print("^2[TAXI DEBUG]^7 Cleaning up mobile taxi")
meterRunning = false
inTaxi = false
if taxiBlip then
RemoveBlip(taxiBlip)
taxiBlip = nil
end
if destinationBlip then
RemoveBlip(destinationBlip)
destinationBlip = nil
end
if currentTaxi then
if taxiDriver then
DeleteEntity(taxiDriver)
taxiDriver = nil
end
DeleteEntity(currentTaxi)
currentTaxi = nil
end
end
-- Menu erneut öffnen wenn im Mobile Taxi
CreateThread(function()
while true do
if inTaxi and currentTaxi and not meterRunning then
if IsControlJustPressed(0, 38) then -- E Taste
local selectedVehicle = nil
local vehicleModel = GetEntityModel(currentTaxi)
for _, vehicle in pairs(Config.TaxiVehicles) do
if GetHashKey(vehicle.model) == vehicleModel then
selectedVehicle = vehicle
break
end
end
if selectedVehicle then
OpenMobileTaxiMenu(selectedVehicle.pricePerKm)
end
end
lib.showTextUI('[E] - Ziel wählen')
else
lib.hideTextUI()
end
Wait(0)
end
end)
-- Cleanup beim Disconnect
AddEventHandler('onResourceStop', function(resourceName)
if GetCurrentResourceName() == resourceName then
CleanupMobileTaxi()
end
end)