Configuration

9 min readUpdated Today

Overview

  • shared/config.lua: Global settings, vehicle defaults, commands
  • server/config_questions.lua: Server-only quiz questions and profiles (clients never receive them)
  • server/config_sv.lua: Discord webhooks and log toggles
  • shared/data/terminals/*.lua: Individual terminal definitions (one file per terminal)

General

shared/config.lua
1Config.Debug = false
2Config.Locale = 'en'
3Config.Interaction = 'target'
  • Debug: Console output. Keep off in production.
  • Locale: Language code. See the locales/ folder.
  • Interaction: 'target' for auto-detected target system, 'textui' to force 3D Text UI

Vehicle Defaults

shared/config.lua
1Config.Vehicles = {
2    garage = '',
3    plateFormat = 'LLNNNN',
4    defaults = {
5        fuel = 50, engine = 1000, body = 1000, tank = 1000,
6    },
7}

Used when a quiz profile awards a vehicle as a reward.

Commands

shared/config.lua
1Config.Commands = {
2    theme = 'mltheme',
3    setup = 'mlterminalsetup',
4    props = 'mltoggleprops',
5}

Discord Webhooks

server/config_sv.lua
1Config.DiscordWebhook = {
2    Default = 'YOUR_WEBHOOK',
3    Test = 'YOUR_WEBHOOK',
4    Minigame = 'YOUR_WEBHOOK',
5    Actions = 'YOUR_WEBHOOK',
6    Doors = 'YOUR_WEBHOOK',
7}

Set any webhook to false to disable that log channel entirely.

server/config_sv.lua
1Config.DiscordWebhook = {
2    Default = 'YOUR_WEBHOOK',
3    Test = false,           -- Disables all quiz-related logs
4    Minigame = false,       -- Disables all minigame logs
5    Actions = 'YOUR_WEBHOOK',
6    Doors = 'YOUR_WEBHOOK',
7}

Log Toggles

Each log event can be individually routed to a channel or disabled:

server/config_sv.lua
1Config.Log = {
2    TestResult = Config.DiscordWebhook.Test,
3    TestConfirmedFailure = Config.DiscordWebhook.Test,
4    ForceConfirm = Config.DiscordWebhook.Test,
5    ExecuteAction = Config.DiscordWebhook.Actions,
6    MinigameSuccess = Config.DiscordWebhook.Minigame,
7    PasswordFailed = Config.DiscordWebhook.Minigame,
8    DoorToggle = Config.DiscordWebhook.Doors,
9}

Set any individual log to nil to disable it while keeping its channel active for other logs.

Log Batching

server/config_sv.lua
1Config.LogSettings = {
2    Color = 3066993,
3    Interval = 60000,  -- Sends logs every 60 seconds
4}
Rate Limiting

Do not set Interval below 60000 ms. Discord will rate-limit your webhook and logs will be dropped.

Terminal Configuration

Each terminal is defined as a separate Lua file in shared/data/terminals/. Copy a bundled example such as example_full.lua and configure only the sections you need.

Section 1: Base (Required)

shared/data/terminals/my_terminal.lua
1Config.Terminals['my_terminal'] = {
2    label = 'Use Terminal',
3    model = 'ba_prop_battle_club_computer_01',
4    coords = vector4(100.0, 200.0, 30.0, 180.0),
5    theme = 'theme-default',
6}
  • label: Text shown on the target/textui interaction
  • model: GTA prop model hash
  • coords: Position and heading as vector4
  • theme: UI theme (see below)

Multi-Location: Replace coords with locations to spawn the same terminal at multiple positions:

lua
1locations = {
2    vector4(100.0, 200.0, 30.0, 180.0),
3    vector4(110.0, 200.0, 30.0, 90.0),
4},

Available Themes

  • theme-default: Industrial Orange
  • theme-wasteland: Rust / Post-Apocalyptic
  • theme-cyberpunk: Neon Magenta
  • theme-noir: Blood Red
  • theme-fantasy: Gold
  • theme-fruit: Fresh Green
  • theme-vintage-yellow: Retro Yellow
  • theme-vintage-blue: Retro Blue
  • theme-facade98-teal: Windows 98 Teal

Section 2: Spawn

lua
1spawn = {
2    distance = 15.0,
3    texture = 'prop_computer_screen',
4}
  • distance: Prop create/destroy streaming distance
  • texture: DUI replacement texture name (depends on the prop model)

Section 3: Camera

lua
1camera = {
2    enabled = true,
3    distance = 0.5,
4    height = 0.35,
5    offset = 0.3,
6    fov = { start = 70, final = 50 },
7    transition = 1500,
8}
  • enabled: Toggle cinematic camera when using the terminal
  • distance: How close the camera sits to the prop face
  • height: Camera height offset relative to the prop center
  • offset: Z offset for screen center
  • fov: Field of view transition (start → final)
  • transition: Camera movement duration in ms

Section 4: Access Control

lua
1access = {
2    exclusive = true,
3    showClose = true,
4    job = 'police',
5    item = 'keycard',
6}
  • exclusive: Only one player at a time
  • showClose: Show X button in UI
  • job: Restrict to a specific job. Set nil for no restriction
  • item: Require an item in inventory. Set nil for no restriction

Section 5: UI Customization

lua
1ui = {
2    header = 'SYSTEM v2.0',
3    bootLines = {
4        '> Initializing system...',
5        '> Loading modules...',
6        '> System ready.',
7    },
8    logo = {
9        text = 'MICIO OS',
10        duration = 3000,
11    },
12}
  • header: Text shown in the terminal header bar
  • bootLines: Array of strings displayed with typewriter effect during boot
  • logo.text: Text-based logo during boot (or use logo.image for an image file)
  • logo.duration: How long the logo screen is shown (ms)

App Types

Apps are the interactive modules on the terminal desktop. Each app has a type that determines its behavior.

quiz

Psychometric test with randomized questions, skill-based scoring, profile assignment, and rewards.

lua
1{
2    name = 'Psychometric Test',
3    icon = 'fa-solid fa-brain',
4    type = 'quiz',
5}

Requires a quiz section in the terminal config (see below).

folder

File browser with text-based files.

lua
1{
2    name = 'Documents',
3    icon = 'fa-solid fa-folder-open',
4    type = 'folder',
5    files = {
6        { name = 'readme.txt', content = 'File content here.' },
7        { name = 'log.dat', content = 'Entry 01: all clear.' },
8    },
9}

doors

Door control panel. Requires a doors section.

lua
1{
2    name = 'Door Control',
3    icon = 'fa-solid fa-door-open',
4    type = 'doors',
5}

actions

Action panel with cooldown-based buttons that trigger events. Requires an actions section.

lua
1{
2    name = 'Operations',
3    icon = 'fa-solid fa-bolt',
4    type = 'actions',
5}

minigame

Standalone minigame from the desktop.

lua
1{
2    name = 'Decrypt',
3    icon = 'fa-solid fa-lock',
4    type = 'minigame',
5    minigame = 'password',
6    difficulty = 5,
7}

locked_folder

Folder locked behind a minigame. Can also be gated behind a quiz result.

lua
1{
2    name = 'Classified Files',
3    icon = 'fa-solid fa-file-shield',
4    type = 'locked_folder',
5    unlock = 'password',
6    unlockDifficulty = 5,
7    files = {
8        { name = 'secret.dat', content = 'CLASSIFIED CONTENT' },
9    },
10    requireQuiz = true,
11    requiredProfile = 'tactician',
12}

Doors Section

lua
1doors = {
2    title = 'DOOR PANEL',
3    list = {
4        { id = 1, label = 'Main Entrance' },
5        { id = 2, label = 'Server Room' },
6    },
7}
  • id: Must match the door ID in your door lock system
  • label: Display name in the UI

Actions Section

lua
1actions = {
2    title = 'OPERATIONS PANEL',
3    list = {
4        {
5            id = 'alarm',
6            label = 'Activate Alarm',
7            icon = 'fa-solid fa-bell',
8            desc = 'Activate the alarm system.',
9            cooldown = 30,
10            trigger = {
11                type = 'client',
12                event = 'myScript:triggerAlarm',
13                args = { zone = 'main' },
14            },
15        },
16    },
17}
  • id: Unique action identifier
  • cooldown: Seconds before the player can re-use
  • trigger.type: 'client' or 'server'
  • trigger.event: Event name to fire
  • trigger.args: Arguments passed to the event handler

Minigames Section

lua
1-- These two live at the terminal root, NOT inside minigames:
2passwordLockoutDuration = 30,   -- Lockout seconds after a failed attempt
3lockoutType = 'personal',       -- 'global' locks everyone, 'personal' only the player
4
5minigames = {
6    onBoot = 'password',  -- 'password' | 'memory' | 'pipePuzzle' | 'simonSays' | nil
7
8    password = {
9        difficulty = 5,   -- Word length (3-10)
10        attempts = 4,
11        brackets = true,
12        bonusClicks = 2,
13        words = { 'NEXUS', 'VIPER', 'GHOST', 'RAVEN' },
14    },
15
16    memory = {
17        difficulty = 2,   -- 1=easy, 2=medium, 3=hard
18        gridSize = 4,     -- 4=4x4, 6=6x6
19        timeLimit = 60,
20    },
21
22    pipePuzzle = {
23        difficulty = '4x4',  -- '3x3' easy, '4x4' medium, '5x5' hard
24        timeLimit = 60,
25    },
26
27    simonSays = {
28        sequenceLength = 6,  -- 4=easy, 6=medium, 8=hard
29        timeLimit = 30,
30    },
31}
  • onBoot: Require a minigame before reaching the desktop. The four minigames are password, memory, pipePuzzle, simonSays. Set nil for no boot minigame.
  • passwordLockoutDuration: Seconds before the player can retry after a failure (set at the terminal root, not inside minigames)
  • lockoutType: 'global' locks all players, 'personal' locks only the failing player.

Quiz Section

lua
1-- Terminal root, client-safe quiz controls:
2showRewards = true,
3reopenifcompleted = false,
4allowRetakeOnSuccess = false,
5allowRetakeOnFailure = true,
6
7quiz = {
8    title = 'PSYCHOMETRIC ANALYSIS',
9    startButton = 'Start Analysis',
10    questionCount = 3,    -- Random questions pulled from the server pool
11    fingerprint = true,   -- Require a fingerprint scan before starting
12}
  • questionCount: Number of random questions picked from the server pool
  • showRewards / reopenifcompleted: terminal-root flags: show the reward summary; allow reopening after completion
  • fingerprint: Require a fingerprint scan before starting
  • allowRetakeOnSuccess: terminal-root flag: allow retake after receiving a profile
  • allowRetakeOnFailure: terminal-root flag: allow retake after failing to meet any threshold
  • Questions and profiles are defined server-side (anti-cheat). Profile rewards can include money, items, vehicle and job ({ name, grade })

Questions & Profiles (Server-Only)

Questions and profiles never reach the client. Define them in server/config_questions.lua under TerminalQuestions['terminal_id'], using the SAME terminal ID:

server/config_questions.lua
1TerminalQuestions['my_terminal'] = {
2    questions = {
3        {
4            question_key = 'How do you handle pressure?',
5            answers = {
6                { text_key = 'I analyze and plan', value = { skill = 'tactical', points = 15 } },
7                { text_key = 'I act on instinct',  value = { skill = 'combat',   points = 15 } },
8            },
9        },
10    },
11    profiles = {
12        {
13            id = 'tactician',
14            name = 'PROFILE: TACTICIAN',
15            description = 'Strategic mind, born leader.',
16            points_required = { skill = 'tactical', amount = 11 },
17            rewards = {
18                money = 5000,
19                items = { { name = 'radio', amount = 1 } },
20                job = { name = 'police', grade = 0 },
21                vehicle = { name = 'police' },
22            },
23        },
24        {
25            id = 'recruit',
26            name = 'PROFILE: RECRUIT',
27            description = 'Fallback, always matchable (no points_required).',
28            rewards = { money = 0 },
29        },
30    },
31}
  • question_key / text_key: question and answer text shown in the UI
  • value: score for an answer: { skill, points }
  • points_required: profile threshold: { skill, amount }. First matching profile wins (order = priority); a profile with no points_required is the fallback.
  • rewards: money, items ({ name, amount }), job ({ name, grade }), vehicle ({ name = "model" })

Kiosk Mode

Transforms the terminal into a single-app experience with no desktop.

lua
1kiosk = {
2    mode = 'simple',
3    app = 'doors',
4}
  • mode = 'simple': Opens the app directly, no boot or minigame
  • mode = 'locked': Requires a minigame to unlock, access expires after unlockDuration seconds
lua
1kiosk = {
2    mode = 'locked',
3    app = 'doors',
4    unlockGame = 'password',
5    unlockDuration = 300,
6}