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

380 lines
13 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
RegisterNetEvent('QBCore:Client:OnPlayerLoaded', function()
PlayerData = QBCore.Functions.GetPlayerData()
CreateStationBlips()
2025-08-11 18:38:20 +02:00
CreateStationInteractionPoints()
2025-08-11 18:33:49 +02:00
end)
-- Bahnhof Blips erstellen
function CreateStationBlips()
for _, station in pairs(Config.TrainStations) do
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)
end
end
2025-08-11 18:38:20 +02:00
-- Bahnhof Interaktionspunkte erstellen
function CreateStationInteractionPoints()
CreateThread(function()
while true do
local sleep = 1000
local playerPed = PlayerPedId()
local playerCoords = GetEntityCoords(playerPed)
2025-08-11 18:33:49 +02:00
2025-08-11 18:38:20 +02:00
if not isRiding then
for stationId, station in pairs(Config.TrainStations) do
local distance = #(playerCoords - station.interactionPoint)
if distance <= Config.StationInteractionDistance then
sleep = 0
-- DrawText anzeigen
DrawText3D(station.interactionPoint.x, station.interactionPoint.y, station.interactionPoint.z + 1.0,
Config.DrawText.stationText)
-- Interaktion
if IsControlJustPressed(0, 38) then -- E
if not waitingForTrain then
OpenStationMenu(station)
else
lib:notify({
title = 'Bitte warten',
description = 'Ein Zug ist bereits unterwegs',
type = 'warning'
})
end
end
end
-- Prüfen ob Zug am Bahnhof wartet
if trainAtStation[station.id] then
local trainDistance = #(playerCoords - GetEntityCoords(trainAtStation[station.id]))
if trainDistance <= 8.0 then
sleep = 0
DrawText3D(GetEntityCoords(trainAtStation[station.id]), Config.DrawText.boardText)
if IsControlJustPressed(0, 38) then -- E
-- Hier würde das Zielmenü für die Fahrt geöffnet
OpenDestinationMenu(trainAtStation[station.id], station)
end
end
end
2025-08-11 18:33:49 +02:00
end
end
2025-08-11 18:38:20 +02:00
Wait(sleep)
2025-08-11 18:33:49 +02:00
end
2025-08-11 18:38:20 +02:00
end)
2025-08-11 18:33:49 +02:00
end
2025-08-11 18:38:20 +02:00
-- Bahnhof Menü öffnen
function OpenStationMenu(station)
2025-08-11 18:33:49 +02:00
local options = {}
2025-08-11 18:38:20 +02:00
-- Verfügbare Ziele anzeigen
for _, destinationId in pairs(station.destinations) do
local destination = GetStationById(destinationId)
if destination then
local price = CalculatePrice(station, destination)
local icon = GetStationIcon(destination.name)
2025-08-11 18:33:49 +02:00
table.insert(options, {
2025-08-11 18:38:20 +02:00
title = icon .. " " .. destination.name,
description = destination.description .. " - Preis: $" .. price,
2025-08-11 18:33:49 +02:00
icon = 'train',
onSelect = function()
2025-08-11 18:38:20 +02:00
CallTrainToStation(station, destination, price)
2025-08-11 18:33:49 +02:00
end,
metadata = {
2025-08-11 18:38:20 +02:00
{label = "Preis", value = "$" .. price},
{label = "Entfernung", value = math.floor(GetDistanceBetweenStations(station, destination)) .. "m"}
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: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:38:20 +02:00
-- Zug am Spawn-Punkt erstellen
local train = SpawnTrainAtLocation(station.trainSpawnPoint)
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'
})
return
2025-08-11 18:33:49 +02:00
end
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: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: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
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:38:20 +02:00
-- Zielmenü für Fahrt öffnen
function OpenDestinationMenu(train, currentStation)
-- Hier das normale Zielmenü wie vorher, aber mit dem wartenden Zug
local playerPed = PlayerPedId()
SetPedIntoVehicle(playerPed, train, 1)
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
-- StartTrainJourney(train, destination) etc.
end
-- Hilfsfunktionen
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
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)
end
return train
2025-08-11 18:33:49 +02:00
end
2025-08-11 18:38:20 +02:00
return nil
end
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
-- 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)