1
0
Fork 0
forked from Simnation/Main
Main/resources/[freizeit]/nordi_ai_train/client.lua

471 lines
17 KiB
Lua
Raw Normal View History

2025-08-11 18:33:49 +02:00
local QBCore = exports['qb-core']:GetCoreObject()
local lib = exports.ox_lib
local PlayerData = {}
2025-08-11 18:38:20 +02:00
-- Zug Status
2025-08-11 18:33:49 +02:00
local currentTrain = nil
local isRiding = false
2025-08-11 18:38:20 +02:00
local trainAtStation = {}
2025-08-11 18:33:49 +02:00
local cinemaCam = nil
2025-08-11 18:38:20 +02:00
local waitingForTrain = false
2025-08-11 18:33:49 +02:00
2025-08-11 18:44:12 +02:00
-- Beim Laden des Scripts
CreateThread(function()
Wait(1000) -- Kurz warten bis alles geladen ist
CreateStationBlips()
print("^2[TRAIN] Blips erstellt^7")
end)
2025-08-11 18:33:49 +02:00
RegisterNetEvent('QBCore:Client:OnPlayerLoaded', function()
PlayerData = QBCore.Functions.GetPlayerData()
2025-08-11 18:44:12 +02:00
Wait(2000)
2025-08-11 18:33:49 +02:00
CreateStationBlips()
2025-08-11 18:44:12 +02:00
print("^2[TRAIN] Player loaded - Blips erstellt^7")
2025-08-11 18:33:49 +02:00
end)
-- Bahnhof Blips erstellen
function CreateStationBlips()
2025-08-11 18:44:12 +02:00
print("^3[TRAIN] Erstelle Blips für " .. #Config.TrainStations .. " Bahnhöfe^7")
for i, station in pairs(Config.TrainStations) do
print("^3[TRAIN] Erstelle Blip für: " .. station.name .. " bei " .. station.coords.x .. ", " .. station.coords.y .. "^7")
2025-08-11 18:33:49 +02:00
local blip = AddBlipForCoord(station.coords.x, station.coords.y, station.coords.z)
SetBlipSprite(blip, station.blip.sprite)
SetBlipDisplay(blip, 4)
SetBlipScale(blip, station.blip.scale)
SetBlipColour(blip, station.blip.color)
BeginTextCommandSetBlipName("STRING")
AddTextComponentString("🚂 " .. station.name)
EndTextCommandSetBlipName(blip)
2025-08-11 18:44:12 +02:00
print("^2[TRAIN] Blip erstellt für: " .. station.name .. "^7")
2025-08-11 18:33:49 +02:00
end
end
2025-08-11 18:44:12 +02:00
-- Bahnhof Interaktionen - Haupt-Loop
CreateThread(function()
print("^2[TRAIN] Interaktions-Loop gestartet^7")
while true do
local sleep = 1000
local playerPed = PlayerPedId()
local playerCoords = GetEntityCoords(playerPed)
if not isRiding then
for i, station in pairs(Config.TrainStations) do
local interactionPoint = station.interactionPoint or vector3(station.coords.x, station.coords.y, station.coords.z)
local distance = #(playerCoords - interactionPoint)
if distance <= Config.StationInteractionDistance then
sleep = 0
2025-08-11 18:38:20 +02:00
2025-08-11 18:44:12 +02:00
-- DrawText anzeigen
DrawText3D(interactionPoint.x, interactionPoint.y, interactionPoint.z + 1.0,
Config.DrawText.stationText)
-- Debug Info
if Config.Debug then
DrawText3D(interactionPoint.x, interactionPoint.y, interactionPoint.z + 2.0,
"Station: " .. station.name .. " | Dist: " .. math.floor(distance))
end
-- Interaktion
if IsControlJustPressed(0, 38) then -- E
print("^3[TRAIN] E gedrückt bei Station: " .. station.name .. "^7")
2025-08-11 18:38:20 +02:00
2025-08-11 18:44:12 +02:00
if not waitingForTrain then
OpenStationMenu(station)
else
lib:notify({
title = 'Bitte warten',
description = 'Ein Zug ist bereits unterwegs',
type = 'warning'
})
2025-08-11 18:38:20 +02:00
end
end
2025-08-11 18:44:12 +02:00
end
-- Prüfen ob Zug am Bahnhof wartet
if trainAtStation[station.id] then
local train = trainAtStation[station.id]
if DoesEntityExist(train) then
local trainCoords = GetEntityCoords(train)
local trainDistance = #(playerCoords - trainCoords)
2025-08-11 18:38:20 +02:00
if trainDistance <= 8.0 then
sleep = 0
2025-08-11 18:44:12 +02:00
DrawText3D(trainCoords.x, trainCoords.y, trainCoords.z + 2.0, Config.DrawText.boardText)
2025-08-11 18:38:20 +02:00
if IsControlJustPressed(0, 38) then -- E
2025-08-11 18:44:12 +02:00
print("^3[TRAIN] Einsteigen in Zug^7")
BoardTrain(train, station)
2025-08-11 18:38:20 +02:00
end
end
end
2025-08-11 18:33:49 +02:00
end
end
end
2025-08-11 18:44:12 +02:00
Wait(sleep)
end
end)
2025-08-11 18:33:49 +02:00
2025-08-11 18:38:20 +02:00
-- Bahnhof Menü öffnen
function OpenStationMenu(station)
2025-08-11 18:44:12 +02:00
print("^3[TRAIN] Öffne Menü für Station: " .. station.name .. "^7")
2025-08-11 18:33:49 +02:00
local options = {}
2025-08-11 18:38:20 +02:00
-- Verfügbare Ziele anzeigen
2025-08-11 18:44:12 +02:00
if station.destinations then
for _, destinationId in pairs(station.destinations) do
local destination = GetStationById(destinationId)
if destination then
local price = CalculatePrice(station, destination)
local icon = GetStationIcon(destination.name)
table.insert(options, {
title = icon .. " " .. destination.name,
description = destination.description .. " - Preis: $" .. price,
icon = 'train',
onSelect = function()
print("^3[TRAIN] Ziel gewählt: " .. destination.name .. "^7")
CallTrainToStation(station, destination, price)
end,
metadata = {
{label = "Preis", value = "$" .. price},
{label = "Entfernung", value = math.floor(GetDistanceBetweenStations(station, destination)) .. "m"}
}
})
end
2025-08-11 18:33:49 +02:00
end
end
2025-08-11 18:38:20 +02:00
if #options == 0 then
table.insert(options, {
title = "Keine Ziele verfügbar",
description = "Momentan keine Verbindungen",
disabled = true
})
end
2025-08-11 18:33:49 +02:00
table.insert(options, {
2025-08-11 18:38:20 +02:00
title = "❌ Abbrechen",
2025-08-11 18:33:49 +02:00
description = "Menü schließen",
icon = 'xmark'
})
lib:registerContext({
2025-08-11 18:38:20 +02:00
id = 'station_menu',
title = "🚉 " .. station.name,
2025-08-11 18:33:49 +02:00
options = options,
position = Config.Menu.position
})
2025-08-11 18:38:20 +02:00
lib:showContext('station_menu')
2025-08-11 18:33:49 +02:00
end
2025-08-11 18:38:20 +02:00
-- Zug zum Bahnhof rufen
function CallTrainToStation(station, destination, price)
2025-08-11 18:44:12 +02:00
print("^3[TRAIN] Rufe Zug für " .. station.name .. " -> " .. destination.name .. "^7")
2025-08-11 18:33:49 +02:00
-- Geld prüfen
QBCore.Functions.TriggerCallback('train:server:canAfford', function(canAfford)
if canAfford then
2025-08-11 18:38:20 +02:00
waitingForTrain = true
lib:notify({
title = '🚂 ' .. Config.Menu.texts.trainComing,
description = 'Der Zug fährt zum Bahnhof',
type = 'info',
duration = Config.Notifications.duration.medium
})
-- Zug spawnen und heranfahren lassen
SpawnAndMoveTrainToStation(station, destination)
2025-08-11 18:33:49 +02:00
else
lib:notify({
title = 'Nicht genug Geld',
2025-08-11 18:38:20 +02:00
description = "Benötigt: $" .. price,
type = 'error',
duration = Config.Notifications.duration.short
2025-08-11 18:33:49 +02:00
})
end
2025-08-11 18:38:20 +02:00
end, price)
2025-08-11 18:33:49 +02:00
end
2025-08-11 18:38:20 +02:00
-- Zug spawnen und zum Bahnhof fahren lassen
function SpawnAndMoveTrainToStation(station, destination)
2025-08-11 18:33:49 +02:00
CreateThread(function()
2025-08-11 18:44:12 +02:00
print("^3[TRAIN] Spawne Zug für Station: " .. station.name .. "^7")
-- Spawn-Punkt bestimmen
local spawnPoint = station.trainSpawnPoint or vector4(station.coords.x - 500, station.coords.y, station.coords.z, station.coords.w)
2025-08-11 18:38:20 +02:00
-- Zug am Spawn-Punkt erstellen
2025-08-11 18:44:12 +02:00
local train = SpawnTrainAtLocation(spawnPoint)
2025-08-11 18:33:49 +02:00
2025-08-11 18:38:20 +02:00
if not train then
waitingForTrain = false
lib:notify({
title = 'Fehler',
description = 'Zug konnte nicht gespawnt werden',
type = 'error'
})
2025-08-11 18:44:12 +02:00
print("^1[TRAIN] Fehler beim Spawnen des Zugs^7")
2025-08-11 18:38:20 +02:00
return
2025-08-11 18:33:49 +02:00
end
2025-08-11 18:38:20 +02:00
2025-08-11 18:44:12 +02:00
print("^2[TRAIN] Zug gespawnt, ID: " .. train .. "^7")
2025-08-11 18:38:20 +02:00
-- Zug zum Bahnhof fahren lassen
local targetCoords = vector3(station.coords.x, station.coords.y, station.coords.z)
2025-08-11 18:33:49 +02:00
local arrived = false
2025-08-11 18:38:20 +02:00
-- Zug in Bewegung setzen
SetTrainSpeed(train, Config.TrainArrival.approachSpeed)
SetTrainCruiseSpeed(train, Config.TrainArrival.approachSpeed)
2025-08-11 18:33:49 +02:00
2025-08-11 18:38:20 +02:00
lib:notify({
title = '🚂 ' .. Config.Menu.texts.trainArriving,
description = 'Der Zug nähert sich dem Bahnhof',
type = 'info',
duration = Config.Notifications.duration.short
})
-- Warten bis Zug am Bahnhof ankommt
while not arrived and DoesEntityExist(train) do
2025-08-11 18:33:49 +02:00
local trainCoords = GetEntityCoords(train)
local distance = #(trainCoords - targetCoords)
2025-08-11 18:44:12 +02:00
if Config.Debug then
print("^3[TRAIN] Zug Entfernung zum Bahnhof: " .. math.floor(distance) .. "m^7")
end
2025-08-11 18:38:20 +02:00
if distance < 100 then
-- Langsamer werden
SetTrainSpeed(train, Config.TrainArrival.arrivalSpeed)
SetTrainCruiseSpeed(train, Config.TrainArrival.arrivalSpeed)
2025-08-11 18:33:49 +02:00
end
2025-08-11 18:38:20 +02:00
if distance < 30 then
-- Ankunft
2025-08-11 18:33:49 +02:00
SetTrainSpeed(train, 0)
SetTrainCruiseSpeed(train, 0)
2025-08-11 18:38:20 +02:00
arrived = true
2025-08-11 18:33:49 +02:00
2025-08-11 18:44:12 +02:00
print("^2[TRAIN] Zug angekommen am Bahnhof: " .. station.name .. "^7")
2025-08-11 18:38:20 +02:00
-- Zug am Bahnhof registrieren
trainAtStation[station.id] = train
waitingForTrain = false
2025-08-11 18:33:49 +02:00
lib:notify({
2025-08-11 18:38:20 +02:00
title = '🚂 ' .. Config.Menu.texts.trainWaiting,
description = 'Zug wartet am Bahnhof - [E] zum Einsteigen',
type = 'success',
duration = Config.Notifications.duration.long
2025-08-11 18:33:49 +02:00
})
2025-08-11 18:38:20 +02:00
-- Zug nach Wartezeit entfernen wenn niemand einsteigt
if Config.TrainArrival.despawnAfterWait then
SetTimeout(Config.TrainArrival.waitTime, function()
if trainAtStation[station.id] == train and not isRiding then
2025-08-11 18:44:12 +02:00
print("^3[TRAIN] Zug fährt ab - keine Passagiere^7")
2025-08-11 18:38:20 +02:00
lib:notify({
title = '🚂 Zug fährt ab',
description = 'Der Zug verlässt den Bahnhof',
type = 'warning',
duration = Config.Notifications.duration.short
})
-- Zug wegfahren lassen
SetTrainSpeed(train, 15.0)
SetTrainCruiseSpeed(train, 15.0)
SetTimeout(10000, function()
if DoesEntityExist(train) then
DeleteMissionTrain(train)
end
end)
trainAtStation[station.id] = nil
end
end)
end
2025-08-11 18:33:49 +02:00
end
Wait(1000)
end
end)
end
2025-08-11 18:44:12 +02:00
-- In Zug einsteigen
function BoardTrain(train, station)
2025-08-11 18:38:20 +02:00
local playerPed = PlayerPedId()
SetPedIntoVehicle(playerPed, train, 1)
2025-08-11 18:44:12 +02:00
isRiding = true
currentTrain = train
2025-08-11 18:38:20 +02:00
lib:notify({
title = '🚂 Willkommen an Bord',
description = 'Die Fahrt beginnt in Kürze',
type = 'success',
duration = Config.Notifications.duration.medium
})
2025-08-11 18:33:49 +02:00
2025-08-11 18:38:20 +02:00
-- Hier würde die normale Zugfahrt-Logik weitergehen
2025-08-11 18:44:12 +02:00
-- Für jetzt einfach nach 10 Sekunden wieder aussteigen lassen
SetTimeout(10000, function()
TaskLeaveVehicle(playerPed, train, 0)
isRiding = false
currentTrain = nil
trainAtStation[station.id] = nil
lib:notify({
title = '🚂 Ankunft',
description = 'Sie sind angekommen',
type = 'success'
})
-- Zug wegfahren lassen
SetTrainSpeed(train, 15.0)
SetTimeout(5000, function()
if DoesEntityExist(train) then
DeleteMissionTrain(train)
end
end)
end)
2025-08-11 18:38:20 +02:00
end
2025-08-11 18:44:12 +02:00
-- Zug spawnen
2025-08-11 18:38:20 +02:00
function SpawnTrainAtLocation(spawnPoint)
local model = GetHashKey(Config.TrainCars.main)
RequestModel(model)
while not HasModelLoaded(model) do
Wait(500)
2025-08-11 18:33:49 +02:00
end
2025-08-11 18:38:20 +02:00
local train = CreateMissionTrain(24, spawnPoint.x, spawnPoint.y, spawnPoint.z, true)
if DoesEntityExist(train) then
SetEntityHeading(train, spawnPoint.w)
SetTrainSpeed(train, 0.0)
SetTrainCruiseSpeed(train, 0.0)
-- Waggons hinzufügen
2025-08-11 18:44:12 +02:00
CreateThread(function()
Wait(1000)
for _, carModel in pairs(Config.TrainCars.cars) do
local carHash = GetHashKey(carModel)
RequestModel(carHash)
while not HasModelLoaded(carHash) do
Wait(500)
end
CreateMissionTrainCar(train, carHash, false, false, false)
2025-08-11 18:38:20 +02:00
end
2025-08-11 18:44:12 +02:00
end)
2025-08-11 18:38:20 +02:00
return train
2025-08-11 18:33:49 +02:00
end
2025-08-11 18:38:20 +02:00
return nil
end
2025-08-11 18:44:12 +02:00
-- Hilfsfunktionen
2025-08-11 18:38:20 +02:00
function GetStationById(id)
for _, station in pairs(Config.TrainStations) do
if station.id == id then
return station
end
end
return nil
end
function CalculatePrice(fromStation, toStation)
local distance = GetDistanceBetweenStations(fromStation, toStation)
local price = Config.PriceCalculation.basePrice + (distance * Config.PriceCalculation.pricePerKm / 100)
2025-08-11 18:33:49 +02:00
2025-08-11 18:38:20 +02:00
-- Kostenlose Stationen prüfen
for _, freeStation in pairs(Config.PriceCalculation.freeStations) do
if fromStation.id == freeStation then
price = price * 0.5 -- 50% Rabatt
end
end
2025-08-11 18:33:49 +02:00
2025-08-11 18:38:20 +02:00
return math.min(math.floor(price), Config.PriceCalculation.maxPrice)
end
function GetDistanceBetweenStations(station1, station2)
local coords1 = vector3(station1.coords.x, station1.coords.y, station1.coords.z)
local coords2 = vector3(station2.coords.x, station2.coords.y, station2.coords.z)
return #(coords1 - coords2)
end
function GetStationIcon(stationName)
if string.find(stationName:lower(), "depot") then
return Config.Menu.stationIcons.depot
elseif string.find(stationName:lower(), "island") then
return Config.Menu.stationIcons.port
elseif string.find(stationName:lower(), "terminal") then
return Config.Menu.stationIcons.industrial
elseif string.find(stationName:lower(), "bay") then
return Config.Menu.stationIcons.rural
elseif string.find(stationName:lower(), "hauptbahnhof") then
return Config.Menu.stationIcons.main
else
return Config.Menu.stationIcons.city
end
2025-08-11 18:33:49 +02:00
end
function DrawText3D(x, y, z, text)
local onScreen, _x, _y = World3dToScreen2d(x, y, z)
if onScreen then
SetTextScale(Config.DrawText.scale, Config.DrawText.scale)
SetTextFont(Config.DrawText.font)
SetTextProportional(1)
SetTextColour(Config.DrawText.color.r, Config.DrawText.color.g, Config.DrawText.color.b, Config.DrawText.color.a)
SetTextEntry("STRING")
SetTextCentre(1)
AddTextComponentString(text)
DrawText(_x, _y)
local factor = (string.len(text)) / 370
DrawRect(_x, _y + 0.0125, 0.015 + factor, 0.03,
Config.DrawText.backgroundColor.r,
Config.DrawText.backgroundColor.g,
Config.DrawText.backgroundColor.b,
Config.DrawText.backgroundColor.a)
end
end
2025-08-11 18:44:12 +02:00
-- Debug Commands
RegisterCommand('trainblips', function()
CreateStationBlips()
print("^2[TRAIN] Blips neu erstellt^7")
end)
RegisterCommand('traintest', function()
local playerCoords = GetEntityCoords(PlayerPedId())
print("^3[TRAIN] Player Position: " .. playerCoords.x .. ", " .. playerCoords.y .. ", " .. playerCoords.z .. "^7")
for i, station in pairs(Config.TrainStations) do
local distance = #(playerCoords - vector3(station.coords.x, station.coords.y, station.coords.z))
print("^3[TRAIN] " .. station.name .. " - Entfernung: " .. math.floor(distance) .. "m^7")
end
end)
2025-08-11 18:33:49 +02:00
-- Cleanup
AddEventHandler('onResourceStop', function(resourceName)
if GetCurrentResourceName() == resourceName then
2025-08-11 18:38:20 +02:00
for stationId, train in pairs(trainAtStation) do
if DoesEntityExist(train) then
DeleteMissionTrain(train)
end
2025-08-11 18:33:49 +02:00
end
end
end)