Skip to content

Loading Screen: config files ​

These files stay readable in every build (escrow too), so you can change them. Shown as shipped in version 1.0.0.

config.lua ​

lua
--[[
    Lumo Loading — configuration
    ─────────────────────────────
    This is the only file you need to edit. Everything here is sent to the
    loading screen when a player connects, so a restart of this resource is
    enough to see a change (no rebuild, no HTML editing).

    Paths to your own media are relative to this resource folder:
        'media/images/shot1.jpg'      ← a file you dropped into lumo-loading/media/images
        'https://i.imgur.com/x.png'   ← or any https URL
    Every player downloads local media on connect, so keep it small.
]]

Config = {}

-- ─── Layout ────────────────────────────────────────────────────────────────
-- 'cinematic'   your photos full screen with film-title typography and a caption per photo
-- 'summit'      mountain sunrise: the sun rises and a climber reaches the peak as the game loads
-- 'arrivals'    Dotted globe, live flight arc, a boarding pass with the player's name, split-flap board
-- 'broadcast'   Live TV news channel: headlines, "up next" events, ticker, a city that lights up
-- 'nightdrive'  Night highway: speedometer progress, radio music player, sat-nav tips, hillside sign
-- 'random'      a random one from LayoutPool on every connect
-- 'rotate'      the next one from LayoutPool on every connect
Config.Layout = 'cinematic'
Config.LayoutPool = { 'cinematic', 'summit', 'arrivals', 'broadcast', 'nightdrive' }

-- Players can press L to try the other layouts; their choice is remembered on their PC.
Config.AllowLayoutSwitch = true

-- ─── Your server ───────────────────────────────────────────────────────────
Config.Server = {
    name = nil,                     -- nil = use sv_projectName from server.cfg
    short = nil,                    -- short brand used in logos/signs; nil = first word of the name
    tagline = 'A new life awaits',
    logo = nil,                     -- 'media/images/logo.png' or an https URL; nil = text logo
    showPlayerCount = true,
}

-- ─── Look ──────────────────────────────────────────────────────────────────
Config.Theme = {
    accent = '#b7ff3a',             -- any hex colour; buttons, progress, highlights
    accentText = '#0a1400',         -- text drawn on top of the accent colour
}

-- Your photos. The Cinematic layout always shows them, with the caption of each
-- photo (title + place; both optional — a plain 'media/images/x.jpg' works too).
-- The four scene layouts draw their own animated scene instead, unless:
--   type = 'image' | 'slideshow' | 'video'   → they show these photos / the video too
--   playerChoice = true                      → players can switch (B key, Tab → Settings)
-- Every listed file is downloaded by every player, so keep each photo around 300 KB.
Config.Background = {
    type = 'scene',
    playerChoice = true,
    images = {
        { src = 'media/images/bg-01.jpg', title = 'Vinewood Hills', place = 'Los Santos at night' },
        { src = 'media/images/bg-02.jpg', title = 'Downtown',       place = 'After the rain' },
        { src = 'media/images/bg-03.jpg', title = 'Del Perro Pier', place = 'Last light' },
        { src = 'media/images/bg-04.jpg', title = 'Route 68',       place = 'Blaine County' },
        { src = 'media/images/bg-05.jpg', title = 'Mountain Sunrise', place = 'Above the clouds' },
        { src = 'media/images/bg-06.jpg', title = 'Mirror Park',    place = 'Quiet streets' },
    },
    slideSeconds = 8,
    video = nil,
    dim = 0.45,                     -- 0..1 darkening over pictures/video so text stays readable
}

-- ─── Welcome line ──────────────────────────────────────────────────────────
-- Remembers how many times each player has connected (stored on the server, by license).
-- Placeholders: {name} {server} {visits} {ago}
Config.Welcome = {
    enabled = true,
    rememberVisits = true,
    first = 'Welcome to {server}, {name}',
    returning = 'Welcome back, {name}',
    visitLine = 'Visit #{visits} · last seen {ago}',
}

-- ─── Music & sound ─────────────────────────────────────────────────────────
-- mode 'playlist'  plays Tracks below (local files or https URLs to .mp3/.ogg)
-- mode 'ambient'   a generative soundtrack made live for each layout (0 MB, never repeats)
-- mode 'off'       silence
-- Players: Space = play/pause, ← → = track, ↑ ↓ = volume. Their volume/mute is remembered.
Config.Music = {
    mode = 'playlist',
    autoplay = true,
    volume = 0.35,                  -- 0..1 starting volume
    shuffle = false,
    -- All four ship with the resource and are free to redistribute (see README → Credits).
    -- licence is shown in the info panel's credits; keep it when you add CC BY music.
    tracks = {
        { title = 'Midnight Drive',             artist = 'congusbongus',   src = 'media/music/midnight-drive.ogg',           licence = 'CC0' },
        { title = 'Passion (Atmosphere Phonk)', artist = 'Alexi Action',   src = 'media/music/passion-atmosphere-phonk.mp3', licence = 'CC BY 3.0' },
        { title = 'Cyberpunk Beauty',           artist = 'Tarush Singhal', src = 'media/music/cyberpunk-beauty.mp3',         licence = 'CC0' },
        { title = 'Lofi Again',                 artist = 'omfgdude',       src = 'media/music/lofi-again.ogg',               licence = 'CC0' },
    },
}

-- Small sound cues when a loading stage completes (singing bowl, airport chime, …).
Config.Sounds = {
    cues = true,
    volume = 0.5,
}

-- ─── Content ───────────────────────────────────────────────────────────────
-- Tips rotate on every layout (sat-nav in Night Drive, field notes in Summit, …).
Config.Tips = {
    'Press Tab for news, events, rules and the team.',
    'Read the rules before you play — they are in the info panel (Tab).',
    'Need help in the city? Ask staff on our Discord.',
    'Space plays or pauses the music; the arrow keys change track and volume.',
    'Press H to hide the interface and just enjoy the view.',
}
Config.TipSeconds = 9

-- Headlines: the split-flap board in Arrivals, breaking news in Broadcast, the info panel everywhere.
Config.News = {
    { tag = 'NEW',    title = 'Loading screen 2.0',      text = 'Four living layouts — press L to try them all.' },
    { tag = 'EVENT',  title = 'Friday car meet',         text = 'Bring your best build to the docks, 20:00.' },
    { tag = 'JOBS',   title = 'Mechanics are hiring',    text = 'Apply at the city hall job centre.' },
    { tag = 'CITY',   title = 'Road works on the coast', text = 'Expect delays on the Great Ocean Highway.' },
}

-- Upcoming events: "Up next" in Broadcast and the info panel.
Config.Events = {
    { day = 'FRI', time = '20:00', title = 'Car meet',        place = 'Elysian Island docks' },
    { day = 'SAT', time = '19:00', title = 'Street race',     place = 'Vinewood Hills' },
    { day = 'SUN', time = '18:00', title = 'Town hall',       place = 'City Hall' },
}

-- Shown in the info panel (Tab).
Config.Rules = {
    'Stay in character in the city; use /ooc for out-of-character chat.',
    'No random deathmatch — every conflict needs a reason.',
    'Value your life: act as if you have only one.',
    'Respect everyone, in and out of character.',
}

Config.Changelog = {
    { version = '2.0', date = 'This week', items = { 'Brand new loading screen', 'Housing tours and co-ownership', 'Phone store opened' } },
}

-- avatar: an https URL or 'media/images/name.png' (square works best); nil = initials
Config.Team = {
    { name = 'Founder', role = 'Owner' },
    { name = 'Staff',   role = 'Admin' },
}

-- type picks the icon: discord, website, store, youtube, tiktok, twitch, instagram, x, github
-- Players can click these while loading; they open in their browser.
Config.Socials = {
    { type = 'discord', label = 'discord.gg/yourserver', url = 'https://discord.gg/' },
    { type = 'store',   label = 'Store',                 url = 'https://tebex.io/' },
}

-- ─── Per-layout options ────────────────────────────────────────────────────
-- phases: the six loading stages, in order (connect, boot, world, systems, session, ready).
Config.Layouts = {
    cinematic = {
        fontStyle = 'city',         -- 'city' (street signage), 'supercar' (wide, car-badge) or 'gallery' (bold, art-house)
        accentLastWord = true,      -- the last word of the name in the accent colour: LUMO ROLEPLAY
        phases = { 'Connecting', 'Starting up', 'Loading the city', 'Preparing the city', 'Joining', 'Welcome' },
    },
    summit = {
        eyebrow = 'Expedition',
        peak = 'Mount Chiliad',     -- the mountain being climbed
        altitude = 798,             -- summit height shown at 100%
        startAltitude = 0,          -- height shown at 0%
        unit = 'm',
        prayerFlags = false,        -- colourful flags strung from a pole in the foreground
        birds = true,
        phases = { 'Base camp', 'Camp I', 'Camp II', 'Camp III', 'Camp IV', 'Summit' },
    },
    arrivals = {
        airline = nil,              -- nil = '<short> Air'
        from = { code = 'LCY', city = 'Liberty City', lat = 40.71, lon = -74.01 },
        to   = { code = 'LSA', city = 'Los Santos',   lat = 34.05, lon = -118.24 },
        flightPrefix = 'LM',
        cabin = 'Citizen',
        gate = 'B7',
        labels = {
            arriving = 'Now arriving', pass = 'Boarding pass', passenger = 'Passenger', flight = 'Flight',
            gate = 'Gate', seat = 'Seat', boarding = 'Boarding', class = 'Class', status = 'Status',
            visit = 'Visit', bulletin = 'City bulletin', deck = 'From the flight deck',
        },
        phases = { 'Check-in', 'Boarding', 'Taxiing', 'In flight', 'Final approach', 'Landed' },
    },
    broadcast = {
        channel = nil,              -- nil = '<short> 24'
        liveLabel = 'LIVE',
        weather = { temp = 24, unit = 'C', text = 'Clear skies' },
        tickerSpeed = 90,           -- pixels per second
        labels = { breaking = 'Breaking', arriving = 'Now arriving', wire = 'City wire' },
        phases = { 'Dialling in', 'Signal found', 'Receiving feed', 'Syncing city', 'Going live', 'On air' },
    },
    nightdrive = {
        destination = 'Los Santos',
        distance = 42,              -- distance shown on the road sign at 0%
        unit = 'km',
        topSpeed = 180,
        speedUnit = 'km/h',
        station = 'FM 101.1',
        hillSign = true,            -- your short name on the hills, Vinewood-style
        labels = { exit = 'Exit', nav = 'Navigation' },
        phases = { 'Ignition', 'On-ramp', 'Freeway', 'City limits', 'Downtown', 'Arrived' },
    },
}

-- ─── Text ──────────────────────────────────────────────────────────────────
Config.Locale = {
    loading = 'Loading',
    ready = 'Ready',
    playersOnline = '{n} / {max} in the city',
    tip = 'Tip',
    upNext = 'Up next',
    nowPlaying = 'Now playing',
    ambientTitle = 'Ambient — {layout}',
    ambientArtist = 'Generative · made live',
    info = 'Info',
    credits = 'Music credits',
    settings = { layout = 'Layout', background = 'Background', scene = 'Live scene', photos = 'Photos', music = 'Music', on = 'On', off = 'Off', volume = 'Volume' },
    tabs = { settings = 'Settings', news = 'News', events = 'Events', updates = 'Updates', rules = 'Rules', team = 'Team', keys = 'Keys' },
    keys = {
        music = 'Play / pause music', track = 'Previous / next track', volume = 'Volume',
        layout = 'Switch layout', hide = 'Hide the interface', info = 'Info panel', background = 'Live scene / photos',
    },
    hints = { music = 'music', layout = 'layout', info = 'info', hide = 'hide UI' },
    status = {
        connect = 'Connecting to the city', core = 'Starting the game', map = 'Preparing the map',
        world = 'Streaming the world', systems = 'Starting city systems', session = 'Joining the session',
        ready = 'Ready',
    },
    previewBadge = 'Preview · Esc to close',
    agoNow = 'just now', agoMinutes = '{n} min ago', agoHours = '{n} h ago', agoDays = '{n} days ago',
}

-- ─── Closing the loading screen ────────────────────────────────────────────
-- 'framework'  your multicharacter / core closes it (QBCore, Qbox and ESX all do). Default.
-- 'auto'       this resource closes it as soon as the game is ready (servers without one).
-- Either way the screen shows its "arrived" state (summit, landed, on air…) once the game is ready.
-- Other resources can close it with the outro: exports['lumo-loading']:Close()
Config.Shutdown = {
    mode = 'framework',
    holdMs = 1500,                  -- 'auto': how long the arrived state shows before closing
    outroMs = 900,                  -- fade-out length
    failsafeSeconds = 0,            -- 'framework': force-close this long after the game is ready (0 = never)
    hideEngineSpinner = true,       -- hides GTA's own "Preloading collisions" box in the corner
}

-- ─── In-game preview ───────────────────────────────────────────────────────
-- /loadingpreview                show the loading screen in game with a fake load (Esc closes it)
-- /loadingpreview arrivals       a given layout (summit, arrivals, broadcast, nightdrive)
-- /loadingpreview demo           every layout in turn
-- adminOnly uses the ace 'command.loadingpreview'; servers with
-- 'add_ace group.admin command allow' (the QBCore/Qbox default) already give it to admins.
Config.Preview = {
    command = 'loadingpreview',     -- nil = no command
    adminOnly = true,
    seconds = 18,                   -- length of the fake load
}

-- ─── Performance ───────────────────────────────────────────────────────────
-- The scenes are light, but the game is loading at the same time.
-- quality 'high' draws at full resolution, 'low' at half (softer, much cheaper).
Config.Performance = {
    fps = 30,
    quality = 'high',
}