-- train_interaction.lua -- Configuration for the interaction point local interactionPoint = { coords = vector3(126.0, -1037.0, 29.3), -- Change to your desired location radius = 2.0, text = "Press ~INPUT_CONTEXT~ to use train transportation" } -- Available scenarios local scenarios = { {name = "Welcome", label = "City Center"}, {name = "Jail", label = "Prison"}, {name = "Paleto", label = "Paleto Bay"} } -- Variables local isInMarker = false local menuOpen = false -- Function to draw 3D text function Draw3DText(x, y, z, text) local onScreen, _x, _y = World3dToScreen2d(x, y, z) local px, py, pz = table.unpack(GetGameplayCamCoords()) SetTextScale(0.35, 0.35) SetTextFont(4) SetTextProportional(1) SetTextColour(255, 255, 255, 215) 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, 41, 11, 41, 68) end -- Function to open scenario selection menu function OpenScenarioMenu() menuOpen = true -- Simple menu display Citizen.CreateThread(function() local selected = 1 while menuOpen do Citizen.Wait(0) -- Draw background DrawRect(0.5, 0.5, 0.3, 0.5, 0, 0, 0, 200) -- Draw title SetTextFont(4) SetTextScale(0.5, 0.5) SetTextColour(255, 255, 255, 255) SetTextCentre(true) SetTextEntry("STRING") AddTextComponentString("Train Transportation") DrawText(0.5, 0.3) -- Draw options for i, scenario in ipairs(scenarios) do local y = 0.35 + (i * 0.05) local color = {r = 255, g = 255, b = 255} if selected == i then color = {r = 255, g = 255, b = 0} DrawRect(0.5, y, 0.28, 0.04, 41, 41, 41, 200) end SetTextFont(4) SetTextScale(0.35, 0.35) SetTextColour(color.r, color.g, color.b, 255) SetTextCentre(true) SetTextEntry("STRING") AddTextComponentString(scenario.label) DrawText(0.5, y - 0.015) end -- Instructions SetTextFont(4) SetTextScale(0.3, 0.3) SetTextColour(255, 255, 255, 255) SetTextCentre(true) SetTextEntry("STRING") AddTextComponentString("↑/↓: Navigate | ENTER: Select | BACKSPACE: Cancel") DrawText(0.5, 0.65) -- Handle controls DisableControlAction(0, 172, true) -- UP DisableControlAction(0, 173, true) -- DOWN DisableControlAction(0, 176, true) -- ENTER DisableControlAction(0, 177, true) -- BACKSPACE if IsDisabledControlJustPressed(0, 172) then -- UP selected = selected - 1 if selected < 1 then selected = #scenarios end PlaySoundFrontend(-1, "NAV_UP_DOWN", "HUD_FRONTEND_DEFAULT_SOUNDSET", true) elseif IsDisabledControlJustPressed(0, 173) then -- DOWN selected = selected + 1 if selected > #scenarios then selected = 1 end PlaySoundFrontend(-1, "NAV_UP_DOWN", "HUD_FRONTEND_DEFAULT_SOUNDSET", true) elseif IsDisabledControlJustPressed(0, 176) then -- ENTER menuOpen = false PlaySoundFrontend(-1, "SELECT", "HUD_FRONTEND_DEFAULT_SOUNDSET", true) TriggerEvent('train:startscenario', scenarios[selected].name) elseif IsDisabledControlJustPressed(0, 177) then -- BACKSPACE menuOpen = false PlaySoundFrontend(-1, "CANCEL", "HUD_FRONTEND_DEFAULT_SOUNDSET", true) end end end) end -- Main thread for checking player position Citizen.CreateThread(function() while true do Citizen.Wait(0) local playerPed = PlayerPedId() local coords = GetEntityCoords(playerPed) local dist = #(coords - interactionPoint.coords) if dist < interactionPoint.radius then isInMarker = true Draw3DText(interactionPoint.coords.x, interactionPoint.coords.y, interactionPoint.coords.z + 1.0, interactionPoint.text) -- Check for E press if IsControlJustReleased(0, 38) and not menuOpen then -- 38 is E OpenScenarioMenu() end else isInMarker = false if menuOpen then menuOpen = false end end end end) -- Create a blip on the map (optional) Citizen.CreateThread(function() local blip = AddBlipForCoord(interactionPoint.coords) SetBlipSprite(blip, 513) -- Train sprite SetBlipDisplay(blip, 4) SetBlipScale(blip, 0.8) SetBlipColour(blip, 2) SetBlipAsShortRange(blip, true) BeginTextCommandSetBlipName("STRING") AddTextComponentString("Train Transportation") EndTextCommandSetBlipName(blip) end)