From 33075c6a84cc933d35de9e860542776ffb132275 Mon Sep 17 00:00:00 2001 From: Nordi98 Date: Mon, 11 Aug 2025 18:38:20 +0200 Subject: [PATCH] ed --- .../[freizeit]/nordi_ai_train/client.lua | 639 ++++++++---------- .../[freizeit]/nordi_ai_train/config.lua | 361 +++++----- 2 files changed, 477 insertions(+), 523 deletions(-) diff --git a/resources/[freizeit]/nordi_ai_train/client.lua b/resources/[freizeit]/nordi_ai_train/client.lua index 0dda1b1e4..c3105c4ec 100644 --- a/resources/[freizeit]/nordi_ai_train/client.lua +++ b/resources/[freizeit]/nordi_ai_train/client.lua @@ -1,14 +1,18 @@ local QBCore = exports['qb-core']:GetCoreObject() local lib = exports.ox_lib local PlayerData = {} -local nearbyTrains = {} + +-- Zug Status local currentTrain = nil local isRiding = false +local trainAtStation = {} local cinemaCam = nil +local waitingForTrain = false RegisterNetEvent('QBCore:Client:OnPlayerLoaded', function() PlayerData = QBCore.Functions.GetPlayerData() CreateStationBlips() + CreateStationInteractionPoints() end) -- Bahnhof Blips erstellen @@ -25,8 +29,247 @@ function CreateStationBlips() end end --- Zug spawnen -function SpawnTrainAtLocation(station) +-- Bahnhof Interaktionspunkte erstellen +function CreateStationInteractionPoints() + CreateThread(function() + while true do + local sleep = 1000 + local playerPed = PlayerPedId() + local playerCoords = GetEntityCoords(playerPed) + + 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 + end + end + + Wait(sleep) + end + end) +end + +-- Bahnhof Menü öffnen +function OpenStationMenu(station) + local options = {} + + -- 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) + + table.insert(options, { + title = icon .. " " .. destination.name, + description = destination.description .. " - Preis: $" .. price, + icon = 'train', + onSelect = function() + CallTrainToStation(station, destination, price) + end, + metadata = { + {label = "Preis", value = "$" .. price}, + {label = "Entfernung", value = math.floor(GetDistanceBetweenStations(station, destination)) .. "m"} + } + }) + end + end + + if #options == 0 then + table.insert(options, { + title = "Keine Ziele verfügbar", + description = "Momentan keine Verbindungen", + disabled = true + }) + end + + table.insert(options, { + title = "❌ Abbrechen", + description = "Menü schließen", + icon = 'xmark' + }) + + lib:registerContext({ + id = 'station_menu', + title = "🚉 " .. station.name, + options = options, + position = Config.Menu.position + }) + + lib:showContext('station_menu') +end + +-- Zug zum Bahnhof rufen +function CallTrainToStation(station, destination, price) + -- Geld prüfen + QBCore.Functions.TriggerCallback('train:server:canAfford', function(canAfford) + if canAfford then + 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) + else + lib:notify({ + title = 'Nicht genug Geld', + description = "Benötigt: $" .. price, + type = 'error', + duration = Config.Notifications.duration.short + }) + end + end, price) +end + +-- Zug spawnen und zum Bahnhof fahren lassen +function SpawnAndMoveTrainToStation(station, destination) + CreateThread(function() + -- Zug am Spawn-Punkt erstellen + local train = SpawnTrainAtLocation(station.trainSpawnPoint) + + if not train then + waitingForTrain = false + lib:notify({ + title = 'Fehler', + description = 'Zug konnte nicht gespawnt werden', + type = 'error' + }) + return + end + + -- Zug zum Bahnhof fahren lassen + local targetCoords = vector3(station.coords.x, station.coords.y, station.coords.z) + local arrived = false + + -- Zug in Bewegung setzen + SetTrainSpeed(train, Config.TrainArrival.approachSpeed) + SetTrainCruiseSpeed(train, Config.TrainArrival.approachSpeed) + + 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 + local trainCoords = GetEntityCoords(train) + local distance = #(trainCoords - targetCoords) + + if distance < 100 then + -- Langsamer werden + SetTrainSpeed(train, Config.TrainArrival.arrivalSpeed) + SetTrainCruiseSpeed(train, Config.TrainArrival.arrivalSpeed) + end + + if distance < 30 then + -- Ankunft + SetTrainSpeed(train, 0) + SetTrainCruiseSpeed(train, 0) + arrived = true + + -- Zug am Bahnhof registrieren + trainAtStation[station.id] = train + waitingForTrain = false + + lib:notify({ + title = '🚂 ' .. Config.Menu.texts.trainWaiting, + description = 'Zug wartet am Bahnhof - [E] zum Einsteigen', + type = 'success', + duration = Config.Notifications.duration.long + }) + + -- 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 + end + + Wait(1000) + end + end) +end + +-- 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 + }) + + -- 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) @@ -34,10 +277,10 @@ function SpawnTrainAtLocation(station) Wait(500) end - local train = CreateMissionTrain(24, station.coords.x, station.coords.y, station.coords.z, true) + local train = CreateMissionTrain(24, spawnPoint.x, spawnPoint.y, spawnPoint.z, true) if DoesEntityExist(train) then - SetEntityHeading(train, station.coords.w) + SetEntityHeading(train, spawnPoint.w) SetTrainSpeed(train, 0.0) SetTrainCruiseSpeed(train, 0.0) @@ -52,294 +295,56 @@ function SpawnTrainAtLocation(station) CreateMissionTrainCar(train, carHash, false, false, false) end - if Config.Debug then - print("Zug gespawnt bei: " .. station.name) - end - return train end return nil end --- Züge in der Nähe finden -function FindNearbyTrains() - local playerPed = PlayerPedId() - local playerCoords = GetEntityCoords(playerPed) - local trains = {} - - local vehicles = GetGamePool('CVehicle') - for _, vehicle in pairs(vehicles) do - if DoesEntityExist(vehicle) then - local model = GetEntityModel(vehicle) - - if IsThisModelATrain(model) then - local trainCoords = GetEntityCoords(vehicle) - local distance = #(playerCoords - trainCoords) - - if distance <= Config.InteractionDistance then - table.insert(trains, { - entity = vehicle, - coords = trainCoords, - distance = distance - }) - end - end - end - end - - return trains -end - --- ox_lib Zielmenü öffnen -function OpenDestinationMenu(train) - local playerCoords = GetEntityCoords(PlayerPedId()) - local currentStation = GetNearestStation(playerCoords) - - local options = {} - +function GetStationById(id) for _, station in pairs(Config.TrainStations) do - if station.name ~= currentStation then - local icon = Config.Menu.stationIcons.city -- Standard Icon - - -- Icon basierend auf Station wählen - if string.find(station.name:lower(), "depot") then - icon = Config.Menu.stationIcons.depot - elseif string.find(station.name:lower(), "island") or string.find(station.name:lower(), "terminal") then - icon = Config.Menu.stationIcons.port - elseif string.find(station.name:lower(), "industrial") then - icon = Config.Menu.stationIcons.industrial - elseif string.find(station.name:lower(), "bay") then - icon = Config.Menu.stationIcons.rural - end - - table.insert(options, { - title = icon .. " " .. station.name, - description = station.description .. " - " .. Config.Menu.texts.price .. ": $" .. station.price, - icon = 'train', - onSelect = function() - SelectDestination(train, station) - end, - metadata = { - {label = Config.Menu.texts.price, value = "$" .. station.price}, - {label = "Entfernung", value = math.floor(#(playerCoords - vector3(station.coords.x, station.coords.y, station.coords.z))) .. "m"} - } - }) + 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) + + -- 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 - table.insert(options, { - title = "❌ " .. Config.Menu.texts.cancel, - description = "Menü schließen", - icon = 'xmark' - }) - - lib:registerContext({ - id = 'train_destination_menu', - title = Config.Menu.title, - options = options, - position = Config.Menu.position - }) - - lib:showContext('train_destination_menu') + return math.min(math.floor(price), Config.PriceCalculation.maxPrice) end --- Ziel auswählen -function SelectDestination(train, destination) - if not DoesEntityExist(train) then - lib:notify({ - title = 'Fehler', - description = Config.Menu.texts.trainNotAvailable, - type = Config.Notifications.types.error, - duration = Config.Notifications.duration.short - }) - return - end - - -- Geld prüfen - QBCore.Functions.TriggerCallback('train:server:canAfford', function(canAfford) - if canAfford then - StartTrainJourney(train, destination) - else - lib:notify({ - title = 'Nicht genug Geld', - description = Config.Menu.texts.notEnoughMoney .. " ($" .. destination.price .. ")", - type = Config.Notifications.types.error, - duration = Config.Notifications.duration.medium - }) - end - end, destination.price) +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 --- Nächste Station finden -function GetNearestStation(coords) - local nearestStation = nil - local nearestDistance = math.huge - - for _, station in pairs(Config.TrainStations) do - local distance = #(coords - vector3(station.coords.x, station.coords.y, station.coords.z)) - if distance < nearestDistance then - nearestDistance = distance - nearestStation = station.name - end - end - - return nearestStation -end - --- Zugfahrt starten -function StartTrainJourney(train, destination) - local playerPed = PlayerPedId() - currentTrain = train - isRiding = true - - -- Spieler in Zug setzen - SetPedIntoVehicle(playerPed, train, 1) - - -- Benachrichtigung - lib:notify({ - title = '🚂 ' .. Config.Menu.texts.journeyStarted, - description = "Fahrt nach " .. destination.name, - type = Config.Notifications.types.success, - duration = Config.Notifications.duration.medium - }) - - -- Cinema Kamera starten - if Config.CinemaCamera.enabled then - StartCinemaCamera(train) - end - - -- Automatische Fahrt - CreateThread(function() - Wait(3000) - - lib:notify({ - title = '🚂 ' .. Config.Menu.texts.trainDeparting, - description = "Nächster Halt: " .. destination.name, - type = Config.Notifications.types.info, - duration = Config.Notifications.duration.short - }) - - DriveTrainToDestination(train, destination) - end) - - -- Journey loggen - if Config.DebugOptions.logJourneys then - TriggerServerEvent('train:server:logJourney', GetNearestStation(GetEntityCoords(playerPed)), destination.name, destination.price) +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 end --- Cinema Kamera -function StartCinemaCamera(train) - if cinemaCam then - DestroyCam(cinemaCam, false) - end - - CreateThread(function() - while isRiding and DoesEntityExist(train) do - for _, camPos in pairs(Config.CinemaCamera.positions) do - if not isRiding then break end - - if cinemaCam then - DestroyCam(cinemaCam, false) - end - - local trainCoords = GetEntityCoords(train) - local trainHeading = GetEntityHeading(train) - local camCoords = trainCoords + camPos.offset - - cinemaCam = CreateCam("DEFAULT_SCRIPTED_CAMERA", true) - SetCamCoord(cinemaCam, camCoords.x, camCoords.y, camCoords.z) - SetCamRot(cinemaCam, camPos.rotation.x, camPos.rotation.y, camPos.rotation.z + trainHeading, 2) - SetCamActive(cinemaCam, true) - RenderScriptCams(true, true, 1000, true, true) - - local holdTime = math.random(Config.CinemaCamera.switchInterval.min, Config.CinemaCamera.switchInterval.max) - Wait(holdTime) - end - end - end) -end - --- Zug zur Destination fahren -function DriveTrainToDestination(train, destination) - CreateThread(function() - local targetCoords = vector3(destination.coords.x, destination.coords.y, destination.coords.z) - local arrived = false - - -- Beschleunigung - for speed = 0, Config.TrainSpeed.max, Config.TrainSpeed.acceleration do - if not DoesEntityExist(train) then return end - SetTrainSpeed(train, speed) - SetTrainCruiseSpeed(train, speed) - Wait(500) - end - - -- Fahrt - while not arrived and DoesEntityExist(train) and isRiding do - local trainCoords = GetEntityCoords(train) - local distance = #(trainCoords - targetCoords) - - if distance < 200 then - local newSpeed = math.max(Config.TrainSpeed.min, distance / 20) - SetTrainSpeed(train, newSpeed) - SetTrainCruiseSpeed(train, newSpeed) - end - - if distance < 50 then - arrived = true - SetTrainSpeed(train, 0) - SetTrainCruiseSpeed(train, 0) - - Wait(2000) - - lib:notify({ - title = '🚂 ' .. Config.Menu.texts.arrived, - description = destination.name, - type = Config.Notifications.types.success, - duration = Config.Notifications.duration.medium - }) - - lib:notify({ - title = Config.Menu.texts.thankYou, - description = "Gute Weiterreise!", - type = Config.Notifications.types.info, - duration = Config.Notifications.duration.short - }) - - EndTrainJourney() - end - - Wait(1000) - end - end) -end - --- Zugfahrt beenden -function EndTrainJourney() - isRiding = false - - if cinemaCam then - RenderScriptCams(false, true, 1000, true, true) - DestroyCam(cinemaCam, false) - cinemaCam = nil - end - - if currentTrain and DoesEntityExist(currentTrain) then - local playerPed = PlayerPedId() - TaskLeaveVehicle(playerPed, currentTrain, 0) - end - - currentTrain = nil - - Wait(3000) - lib:notify({ - title = Config.Menu.texts.canExit, - type = Config.Notifications.types.info, - duration = Config.Notifications.duration.short - }) -end - --- 3D Text zeichnen function DrawText3D(x, y, z, text) local onScreen, _x, _y = World3dToScreen2d(x, y, z) @@ -362,85 +367,13 @@ function DrawText3D(x, y, z, text) end end --- Haupt-Loop -CreateThread(function() - while true do - local sleep = 1000 - local playerPed = PlayerPedId() - local playerCoords = GetEntityCoords(playerPed) - - if not isRiding and not IsPedInAnyVehicle(playerPed, false) then - nearbyTrains = FindNearbyTrains() - - for _, train in pairs(nearbyTrains) do - if train.distance <= 5.0 then - sleep = 0 - - DrawText3D(train.coords.x, train.coords.y, train.coords.z + 2.0, Config.DrawText.interactText) - - if IsControlJustPressed(0, 38) then -- E - OpenDestinationMenu(train.entity) - end - end - end - end - - if isRiding then - sleep = 0 - if IsControlJustPressed(0, 23) then -- F - lib:notify({ - title = Config.Menu.texts.emergencyExit, - type = Config.Notifications.types.warning, - duration = Config.Notifications.duration.short - }) - EndTrainJourney() - end - end - - Wait(sleep) - end -end) - --- Commands -RegisterCommand('spawntrain', function(source, args) - local stationId = args[1] or Config.TrainStations[1].id - local station = nil - - for _, s in pairs(Config.TrainStations) do - if s.id == stationId then - station = s - break - end - end - - if station then - SpawnTrainAtLocation(station) - lib:notify({ - title = 'Zug gespawnt', - description = station.name, - type = Config.Notifications.types.success - }) - end -end) - --- Auto-Spawn -if Config.AutoSpawn.enabled then - CreateThread(function() - Wait(Config.AutoSpawn.delay) - - for i = 1, Config.AutoSpawn.maxTrains do - local randomStation = Config.TrainStations[math.random(1, #Config.TrainStations)] - SpawnTrainAtLocation(randomStation) - Wait(Config.AutoSpawn.spawnInterval) - end - end) -end - -- Cleanup AddEventHandler('onResourceStop', function(resourceName) if GetCurrentResourceName() == resourceName then - if isRiding then - EndTrainJourney() + for stationId, train in pairs(trainAtStation) do + if DoesEntityExist(train) then + DeleteMissionTrain(train) + end end end end) diff --git a/resources/[freizeit]/nordi_ai_train/config.lua b/resources/[freizeit]/nordi_ai_train/config.lua index cd663e059..481ee14cd 100644 --- a/resources/[freizeit]/nordi_ai_train/config.lua +++ b/resources/[freizeit]/nordi_ai_train/config.lua @@ -2,18 +2,200 @@ Config = {} -- Allgemeine Einstellungen Config.Debug = false -Config.DefaultCurrency = 'cash' -- 'cash' oder 'bank' -Config.InteractionDistance = 8.0 -Config.TrainSpeed = { - min = 5.0, - max = 25.0, - acceleration = 2.0 +Config.DefaultCurrency = 'cash' +Config.InteractionDistance = 5.0 +Config.StationInteractionDistance = 3.0 + +-- Zug Ankunft Einstellungen +Config.TrainArrival = { + enabled = true, + spawnDistance = 500.0, -- Entfernung von wo der Zug spawnt + approachSpeed = 15.0, -- Geschwindigkeit beim Heranfahren + arrivalSpeed = 5.0, -- Geschwindigkeit bei Ankunft + waitTime = 30000, -- Wartezeit am Bahnhof (30 Sekunden) + despawnAfterWait = true -- Zug nach Wartezeit löschen wenn niemand einsteigt } --- Cinema Kamera Einstellungen +-- Bahnhof Konfiguration +Config.TrainStations = { + { + id = "sandy_depot", + coords = vector4(2533.0, 2833.0, 38.0, 0.0), + name = "Sandy Shores Depot", + description = "Hauptdepot in Sandy Shores", + + -- Spawn-Punkt für ankommende Züge (weiter entfernt) + trainSpawnPoint = vector4(2033.0, 2833.0, 38.0, 0.0), + + -- Interaktionspunkt für Spieler + interactionPoint = vector3(2535.0, 2835.0, 38.0), + + blip = { + sprite = 795, + color = 2, + scale = 0.8 + }, + + -- Verfügbare Ziele von diesem Bahnhof + destinations = { + "sandy_north", "ls_depot", "elysian", "terminal", "downtown", "paleto" + } + }, + { + id = "sandy_north", + coords = vector4(2606.0, 2927.0, 40.0, 90.0), + name = "Sandy Shores Nord", + description = "Nördlicher Bahnhof von Sandy Shores", + trainSpawnPoint = vector4(2106.0, 2927.0, 40.0, 90.0), + interactionPoint = vector3(2608.0, 2929.0, 40.0), + blip = { + sprite = 795, + color = 3, + scale = 0.7 + }, + destinations = { + "sandy_depot", "ls_depot", "elysian", "terminal", "downtown", "paleto" + } + }, + { + id = "ls_depot", + coords = vector4(1164.0, -3250.0, 7.0, 180.0), + name = "Los Santos Hauptbahnhof", + description = "Zentraler Bahnhof in Los Santos", + trainSpawnPoint = vector4(1164.0, -2750.0, 7.0, 180.0), + interactionPoint = vector3(1166.0, -3252.0, 7.0), + blip = { + sprite = 795, + color = 1, + scale = 0.9 + }, + destinations = { + "sandy_depot", "sandy_north", "elysian", "terminal", "downtown", "paleto" + } + }, + { + id = "elysian", + coords = vector4(219.0, -2487.0, 6.0, 270.0), + name = "Elysian Island", + description = "Industriegebiet am Hafen", + trainSpawnPoint = vector4(719.0, -2487.0, 6.0, 270.0), + interactionPoint = vector3(217.0, -2489.0, 6.0), + blip = { + sprite = 795, + color = 4, + scale = 0.7 + }, + destinations = { + "sandy_depot", "sandy_north", "ls_depot", "terminal", "downtown", "paleto" + } + }, + { + id = "terminal", + coords = vector4(-1100.0, -2724.0, 13.0, 0.0), + name = "Fracht Terminal", + description = "Großes Frachtterminal", + trainSpawnPoint = vector4(-1600.0, -2724.0, 13.0, 0.0), + interactionPoint = vector3(-1098.0, -2726.0, 13.0), + blip = { + sprite = 795, + color = 5, + scale = 0.8 + }, + destinations = { + "sandy_depot", "sandy_north", "ls_depot", "elysian", "downtown", "paleto" + } + }, + { + id = "downtown", + coords = vector4(-500.0, -1500.0, 10.0, 45.0), + name = "Downtown Station", + description = "Bahnhof in der Innenstadt", + trainSpawnPoint = vector4(-1000.0, -1500.0, 10.0, 45.0), + interactionPoint = vector3(-498.0, -1502.0, 10.0), + blip = { + sprite = 795, + color = 6, + scale = 0.7 + }, + destinations = { + "sandy_depot", "sandy_north", "ls_depot", "elysian", "terminal", "paleto" + } + }, + { + id = "paleto", + coords = vector4(100.0, 6500.0, 32.0, 180.0), + name = "Paleto Bay", + description = "Kleiner Bahnhof in Paleto Bay", + trainSpawnPoint = vector4(100.0, 6000.0, 32.0, 180.0), + interactionPoint = vector3(102.0, 6502.0, 32.0), + blip = { + sprite = 795, + color = 7, + scale = 0.7 + }, + destinations = { + "sandy_depot", "sandy_north", "ls_depot", "elysian", "terminal", "downtown" + } + } +} + +-- Preise basierend auf Entfernung +Config.PriceCalculation = { + basePrice = 25, + pricePerKm = 0.5, + maxPrice = 300, + freeStations = {"sandy_depot"} -- Kostenlose Startbahnhöfe +} + +-- Zug Konfiguration +Config.TrainCars = { + main = "freight", + cars = {"freightcar", "freightcont1", "freightgrain"} +} + +-- Menü Einstellungen +Config.Menu = { + title = "🚂 Zugfahrkarten", + subtitle = "Wählen Sie Ihr Reiseziel", + position = "top-right", + + texts = { + callTrain = "Zug rufen", + selectDestination = "Ziel auswählen", + trainComing = "Zug wird gerufen...", + trainArriving = "Zug fährt ein", + trainWaiting = "Zug wartet am Bahnhof", + boardTrain = "Zug besteigen", + trainLeaving = "Zug fährt ab", + noDestinations = "Keine Ziele verfügbar", + cancel = "Abbrechen" + }, + + stationIcons = { + depot = "🏭", + city = "🏢", + industrial = "🏗️", + port = "⚓", + rural = "🌾", + main = "🚉" + } +} + +-- DrawText Einstellungen +Config.DrawText = { + font = 4, + scale = 0.35, + color = {r = 255, g = 255, b = 255, a = 215}, + backgroundColor = {r = 41, g = 128, b = 185, a = 100}, + stationText = "[E] Zug rufen", + boardText = "[E] Einsteigen", + emergencyText = "[F] Notfall-Ausstieg" +} + +-- Kamera Einstellungen Config.CinemaCamera = { enabled = true, - switchInterval = {min = 8000, max = 12000}, -- Zeit zwischen Kamerawechseln + switchInterval = {min = 8000, max = 12000}, positions = { { offset = vector3(15.0, 5.0, 5.0), @@ -26,176 +208,15 @@ Config.CinemaCamera = { { offset = vector3(-10.0, -15.0, 6.0), rotation = vector3(-5.0, 0.0, -135.0) - }, - { - offset = vector3(0.0, -20.0, 15.0), - rotation = vector3(-20.0, 0.0, 0.0) } } } --- Zug Waggon Konfiguration -Config.TrainCars = { - main = "freight", -- Hauptlok - cars = {"freightcar", "freightcont1", "freightgrain", "tankercar"} -} - --- Bahnhöfe / Ziele -Config.TrainStations = { - { - id = "sandy_depot", - coords = vector4(2533.0, 2833.0, 38.0, 0.0), - name = "Sandy Shores Depot", - description = "Hauptdepot in Sandy Shores", - price = 0, -- Startbahnhof kostenlos - blip = { - sprite = 795, - color = 2, - scale = 0.7 - } - }, - { - id = "sandy_north", - coords = vector4(2606.0, 2927.0, 40.0, 90.0), - name = "Sandy Shores Nord", - description = "Nördlicher Bahnhof von Sandy Shores", - price = 50, - blip = { - sprite = 795, - color = 3, - scale = 0.7 - } - }, - { - id = "ls_depot", - coords = vector4(1164.0, -3250.0, 7.0, 180.0), - name = "Los Santos Hauptbahnhof", - description = "Zentraler Bahnhof in Los Santos", - price = 150, - blip = { - sprite = 795, - color = 1, - scale = 0.8 - } - }, - { - id = "elysian", - coords = vector4(219.0, -2487.0, 6.0, 270.0), - name = "Elysian Island", - description = "Industriegebiet am Hafen", - price = 100, - blip = { - sprite = 795, - color = 4, - scale = 0.7 - } - }, - { - id = "terminal", - coords = vector4(-1100.0, -2724.0, 13.0, 0.0), - name = "Fracht Terminal", - description = "Großes Frachtterminal", - price = 200, - blip = { - sprite = 795, - color = 5, - scale = 0.7 - } - }, - { - id = "downtown", - coords = vector4(-500.0, -1500.0, 10.0, 45.0), - name = "Downtown Station", - description = "Bahnhof in der Innenstadt", - price = 75, - blip = { - sprite = 795, - color = 6, - scale = 0.7 - } - }, - { - id = "paleto", - coords = vector4(100.0, 6500.0, 32.0, 180.0), - name = "Paleto Bay", - description = "Kleiner Bahnhof in Paleto Bay", - price = 250, - blip = { - sprite = 795, - color = 7, - scale = 0.7 - } - } -} - --- Menü Texte und Einstellungen -Config.Menu = { - title = "🚂 Zugfahrkarten", - subtitle = "Wählen Sie Ihr Reiseziel", - position = "top-right", -- ox_lib menu position - - -- Texte - texts = { - selectDestination = "Ziel auswählen", - price = "Preis", - description = "Beschreibung", - cancel = "Abbrechen", - notEnoughMoney = "Nicht genug Geld", - trainNotAvailable = "Zug nicht verfügbar", - journeyStarted = "Zugfahrt gestartet", - trainDeparting = "Der Zug fährt ab", - arrived = "Ankunft", - thankYou = "Vielen Dank für die Fahrt", - emergencyExit = "Notfall-Ausstieg", - canExit = "Sie können jetzt aussteigen" - }, - - -- Icons für verschiedene Stationstypen - stationIcons = { - depot = "🏭", - city = "🏢", - industrial = "🏗️", - port = "⚓", - rural = "🌾" - } -} - --- Nachrichten Einstellungen +-- Benachrichtigungen Config.Notifications = { duration = { short = 3000, medium = 5000, long = 8000 - }, - types = { - success = "success", - error = "error", - info = "info", - warning = "warning" } } - --- Automatisches Spawnen -Config.AutoSpawn = { - enabled = true, - delay = 10000, -- Wartezeit nach Server-Start - maxTrains = 4, -- Maximale Anzahl gespawnter Züge - spawnInterval = 3000 -- Zeit zwischen Spawns -} - --- DrawText Einstellungen -Config.DrawText = { - font = 4, - scale = 0.35, - color = {r = 255, g = 255, b = 255, a = 215}, - backgroundColor = {r = 41, g = 128, b = 185, a = 100}, - interactText = "[E] Zug besteigen", - emergencyText = "[F] Notfall-Ausstieg" -} - --- Debug Einstellungen -Config.DebugOptions = { - showCoords = false, - showDistance = false, - logJourneys = true -}