ngd-ui

Custom menu, input, cameras, ped interaction and more!

ngd-ui

Installation Steps

  1. Install ngd-ui
    Put ngd-ui into your resources folder. Preferably into a [ngd] folder that is started after all of your main resources. If you are using this with ngd-Bridge, please refer to the start page to make sure your start order is correct.

  2. Click the UI element below to view it's features.

Helper Text (Click to Expand)

Help Text System

Overview

A bottom-center screen text display system for showing control hints and instructions to players. Supports both vertical and horizontal layouts with GTA color codes.

Features

  • Two Layouts - Vertical (stacked) or horizontal (inline) text display
  • Color Support - Full GTA color code support for highlighting
  • Update Support - Change text without hiding/reshowing
  • Protected Display - Prevents multiple instances from conflicting
  • Zero Configuration - Works out of the box

Usage

Show Help Text

Display help text at the bottom center of the screen.

-- Basic usage (vertical layout)
exports['ngd-ui']:ShowHelpText('E: ~g~Interact | G: ~r~Cancel')

-- Horizontal layout
exports['ngd-ui']:ShowHelpText('Arrow Keys: Move | ENTER: ~g~Confirm', 'horizontal')

-- Force show (override existing)
exports['ngd-ui']:ShowHelpText('New text', 'vertical', true)

Update Help Text

Update the text without hiding/reshowing (useful for timers or counters).

exports['ngd-ui']:UpdateHelpText('TIME: ~r~5s~w~ remaining')

Hide Help Text

exports['ngd-ui']:HideHelpText()

Check if Showing

local isShowing = exports['ngd-ui']:IsHelpTextShowing()
if not isShowing then
    -- Safe to show new help text
end

Parameters

ShowHelpText

ParameterTypeRequiredDefaultDescription
textstringYes-Text to display with pipe-separated items
layoutstringNo'vertical''vertical' or 'horizontal'
forcebooleanNofalseOverride existing help text

Returns: boolean - true if shown, false if blocked

UpdateHelpText

ParameterTypeRequiredDescription
textstringYesNew text to display

Returns: boolean - true if updated, false if not showing

Implementation Examples

Placement Mode

CreateThread(function()
    while placementMode do
        exports['ngd-ui']:ShowHelpText('Arrow Keys: Move | Q/E: Rotate | ENTER: ~g~Place | BACKSPACE: ~r~Cancel')
        Wait(0)
    end
    exports['ngd-ui']:HideHelpText()
end)

Vehicle Entry

CreateThread(function()
    while nearVehicle do
        exports['ngd-ui']:ShowHelpText('F: ~g~Enter Vehicle | H: ~y~Lock/Unlock', 'horizontal')
        Wait(0)
    end
    exports['ngd-ui']:HideHelpText()
end)

Countdown Timer

CreateThread(function()
    for i = 10, 0, -1 do
        local color = i <= 3 and '~r~' or '~y~'
        exports['ngd-ui']:UpdateHelpText('TIME: ' .. color .. i .. 's~w~ remaining | SPACE: ~g~Skip')
        Wait(1000)
    end
    exports['ngd-ui']:HideHelpText()
end)

ATM Instructions

AddEventHandler('bank:atmOpened', function()
    exports['ngd-ui']:ShowHelpText('Arrow Keys: Navigate | ENTER: ~g~Confirm | BACKSPACE: ~r~Exit')
end)

AddEventHandler('bank:atmClosed', function()
    exports['ngd-ui']:HideHelpText()
end)

Dynamic Interaction Help

local function UpdateInteractionHelp(options)
    local helpText = ''
    for i, opt in ipairs(options) do
        if i > 1 then helpText = helpText .. ' | ' end
        helpText = helpText .. opt.key .. ': ' .. opt.color .. opt.label
    end
    exports['ngd-ui']:ShowHelpText(helpText, 'horizontal')
end

-- Usage
UpdateInteractionHelp({
    { key = 'E', color = '~g~', label = 'Open' },
    { key = 'G', color = '~b~', label = 'Lock' },
    { key = 'H', color = '~r~', label = 'Break In' }
})

Color Codes

Use GTA color codes to highlight text:

  • r - Red
  • g - Green
  • b - Blue
  • y - Yellow
  • p - Purple
  • w - White
  • s - Default

Example: 'E: gConfirmw | BACKSPACE: rCancel'

Layout Options

Vertical Layout (Default)

E: Open Door
G: Lock Door
H: Break In

Horizontal Layout

E: Open Door | G: Lock Door | H: Break In

Best Practices

  1. Always Hide When Done - Call HideHelpText() when the context ends to prevent lingering text
  2. Use in Loops - Call ShowHelpText() every frame in your interaction loops with Wait(0)
  3. Update Don't Replace - Use UpdateHelpText() for changing values (timers, counters) instead of hide/show

Notes

  • Help text automatically prevents multiple instances unless force is true
  • Text remains on screen until manually hidden or overridden
  • Works seamlessly with other UI elements (doesn't block NUI focus)
  • Supports unlimited text length, but keep it concise for readability
Input (Click to Expand)

Input Dialog System

Overview

A comprehensive input dialog system supporting multiple field types including text, password, number, date, time, select, checkbox, and textarea. Perfect for forms, character creation, transactions, and data collection.

Features

  • 9 Input Types - Text, password, number, date, time, select, checkbox, textarea, and multi-select
  • Field Validation - Required fields, min/max values, character limits
  • Rich Formatting - Icons, descriptions, placeholders, default values
  • Flexible Layout - Standard or full-width fields
  • Promise-based - Clean async/await pattern for handling results

Usage

Basic Input Dialog

local result = exports['ngd-ui']:InputDialog('Dialog Title', {
    { type = 'input', label = 'Player Name', required = true },
    { type = 'number', label = 'Amount', min = 1, max = 1000 }
}, { allowCancel = true })

if result then
    local name = result[1]
    local amount = result[2]
    -- Process results
end

All Available Input Types

local result = exports['ngd-ui']:InputDialog('Form Title', {
    -- Text Input
    {
        type = 'input',
        label = 'Text Field',
        description = 'Enter some text',
        placeholder = 'Type here...',
        icon = 'font',
        required = true,
        min = 3,  -- Min characters
        max = 50  -- Max characters
    },
    
    -- Password Input
    {
        type = 'password',
        label = 'Password',
        placeholder = 'Enter password...',
        icon = 'lock',
        min = 4,
        max = 20
    },
    
    -- Number Input
    {
        type = 'number',
        label = 'Amount',
        icon = 'dollar-sign',
        default = 0,
        min = 0,
        max = 999999,
        precision = 2,  -- Decimal places
        step = 0.01     -- Increment step
    },
    
    -- Date Picker
    {
        type = 'date',
        label = 'Select Date',
        icon = 'calendar',
        format = 'MM/DD/YYYY',
        minDate = '01/01/2020',
        maxDate = '12/31/2025'
    },
    
    -- Time Picker
    {
        type = 'time',
        label = 'Select Time',
        icon = 'clock'
    },
    
    -- Select Dropdown
    {
        type = 'select',
        label = 'Choose Option',
        icon = 'list',
        options = {
            { value = 'option1', label = 'Option 1' },
            { value = 'option2', label = 'Option 2' },
            { value = 'option3', label = 'Option 3' }
        },
        searchable = true  -- Enable search in dropdown
    },
    
    -- Multi-Select
    {
        type = 'multi-select',
        label = 'Choose Multiple',
        icon = 'list-check',
        options = {
            { value = 'a', label = 'Choice A' },
            { value = 'b', label = 'Choice B' },
            { value = 'c', label = 'Choice C' }
        },
        maxSelectedValues = 3
    },
    
    -- Checkbox
    {
        type = 'checkbox',
        label = 'I agree to terms',
        checked = false,
        required = true
    },
    
    -- Textarea
    {
        type = 'textarea',
        label = 'Description',
        placeholder = 'Enter detailed description...',
        autosize = true,
        fullWidth = true  -- Makes dialog wider for this field
    }
})

Parameters

Common Field Properties

PropertyTypeRequiredDefaultDescription
typestringYes'input'Field type (input, password, number, date, time, select, checkbox, textarea)
labelstringYes-Field label displayed to user
descriptionstringNo-Helper text below label
placeholderstringNo-Placeholder text in input
iconstringNo-FontAwesome icon name
defaultanyNo-Default value
requiredbooleanNofalseField is required
disabledbooleanNofalseField is disabled
fullWidthbooleanNofalseMakes dialog wider for this field

Text/Password Specific

PropertyTypeDescription
minnumberMinimum character length
maxnumberMaximum character length

Number Specific

PropertyTypeDescription
minnumberMinimum value
maxnumberMaximum value
precisionnumberDecimal places (e.g., 2 for currency)
stepnumberIncrement/decrement step
hideControlsbooleanHide +/- buttons

Date Specific

PropertyTypeDescription
formatstringDate format (e.g., 'MM/DD/YYYY')
minDatestringMinimum selectable date
maxDatestringMaximum selectable date
clearablebooleanShow clear button
returnStringbooleanReturn as string instead of date object

Select/Multi-Select Specific

PropertyTypeDescription
optionstableArray of {value, label} objects
searchablebooleanEnable search in dropdown
maxSelectedValuesnumberMax selections (multi-select only)

Textarea Specific

PropertyTypeDescription
autosizebooleanAuto-resize based on content

Implementation Examples

Character Creation

local result = exports['ngd-ui']:InputDialog('Create Character', {
    { type = 'input', label = 'First Name', icon = 'user', required = true, min = 2, max = 20 },
    { type = 'input', label = 'Last Name', icon = 'user', required = true, min = 2, max = 20 },
    { type = 'date', label = 'Date of Birth', icon = 'calendar', required = true },
    { type = 'number', label = 'Height (cm)', icon = 'ruler-vertical', min = 100, max = 220, default = 170 },
    { type = 'select', label = 'Gender', icon = 'venus-mars', options = {
        { value = 'male', label = 'Male' },
        { value = 'female', label = 'Female' }
    }},
    { type = 'checkbox', label = 'I agree to server rules', required = true }
})

if result then
    local firstName = result[1]
    local lastName = result[2]
    local dob = result[3]
    local height = result[4]
    local gender = result[5]
    local agreedToRules = result[6]
    
    -- Create character
end

Bank Transfer

local result = exports['ngd-ui']:InputDialog('Bank Transfer', {
    { type = 'number', label = 'Recipient ID', icon = 'user', required = true, min = 1 },
    { type = 'number', label = 'Amount', icon = 'dollar-sign', required = true, precision = 2, min = 0.01 },
    { type = 'textarea', label = 'Note (optional)', placeholder = 'Add a message...', autosize = true }
})

if result then
    local recipientId = result[1]
    local amount = result[2]
    local note = result[3] or ''
    
    TriggerServerEvent('bank:transfer', recipientId, amount, note)
end

Job Application

local result = exports['ngd-ui']:InputDialog('Job Application', {
    { type = 'input', label = 'Full Name', icon = 'user', required = true },
    { type = 'number', label = 'Age', icon = 'calendar', min = 18, max = 99, required = true },
    { type = 'select', label = 'Position', icon = 'briefcase', required = true, options = {
        { value = 'officer', label = 'Police Officer' },
        { value = 'detective', label = 'Detective' },
        { value = 'cadet', label = 'Cadet' }
    }},
    { type = 'textarea', label = 'Why do you want this job?', required = true, fullWidth = true }
})

if result then
    local name = result[1]
    local age = result[2]
    local position = result[3]
    local reason = result[4]
    
    TriggerServerEvent('job:submitApplication', name, age, position, reason)
end

Vehicle Sale

local result = exports['ngd-ui']:InputDialog('Sell Vehicle', {
    { type = 'input', label = 'Buyer Name', icon = 'user', required = true },
    { type = 'number', label = 'Sale Price', icon = 'dollar-sign', required = true, precision = 2, min = 1 },
    { type = 'select', label = 'Payment Method', icon = 'credit-card', options = {
        { value = 'cash', label = 'Cash' },
        { value = 'bank', label = 'Bank Transfer' }
    }},
    { type = 'checkbox', label = 'Include vehicle warranty', checked = true }
})

if result then
    TriggerServerEvent('vehicle:processSale', result[1], result[2], result[3], result[4])
end

Store Order Form

local result = exports['ngd-ui']:InputDialog('Place Order', {
    { type = 'select', label = 'Product', icon = 'box', required = true, searchable = true, options = {
        { value = 'burger', label = 'Hamburger - $5' },
        { value = 'fries', label = 'French Fries - $3' },
        { value = 'soda', label = 'Soda - $2' }
    }},
    { type = 'number', label = 'Quantity', icon = 'hashtag', min = 1, max = 99, default = 1 },
    { type = 'multi-select', label = 'Extra Toppings', icon = 'plus', options = {
        { value = 'cheese', label = 'Cheese (+$1)' },
        { value = 'bacon', label = 'Bacon (+$2)' },
        { value = 'onions', label = 'Onions (+$0.5)' }
    }},
    { type = 'textarea', label = 'Special Instructions', placeholder = 'Any special requests?' }
})

if result then
    local product = result[1]
    local quantity = result[2]
    local toppings = result[3] or {}
    local instructions = result[4] or ''
    
    TriggerServerEvent('store:placeOrder', product, quantity, toppings, instructions)
end

Return Values

The dialog returns:

  • nil if cancelled
  • table of values in field order if submitted
local result = exports['ngd-ui']:InputDialog('Title', {
    { type = 'input', label = 'Name' },
    { type = 'number', label = 'Age' }
})

if result then
    local name = result[1]  -- First field value
    local age = result[2]   -- Second field value
end

Notes

  • Dialog automatically closes when submitted or cancelled
  • Required fields prevent submission if empty
  • Number fields enforce min/max constraints
  • Date fields show a calendar picker
  • Select fields support search with searchable = true
  • Use fullWidth = true on textarea for better multi-line input
  • Icons use FontAwesome class names (without 'fa-' prefix)
Menu (Click to Expand)

Menu System

Overview

A flexible context menu system for creating interactive menus with support for buttons, checkboxes, and nested submenus. Perfect for game menus, interaction menus, and admin panels.

Features

  • Multiple Option Types - Buttons, checkboxes, menu headers
  • Event Triggers - Client events, server events
  • Nested Menus - Support for submenu navigation with history
  • Icon Support - FontAwesome icons or custom images
  • Menu Registration - Register reusable menus by ID
  • Position Control - Place menu anywhere on screen

Usage

Simple Menu (CreateMenu)

Create and display a menu immediately.

exports['ngd-ui']:CreateMenu({
    { header = 'Main Menu', isMenuHeader = true },
    {
        header = 'Option 1',
        txt = 'Description of option 1',
        icon = 'circle',
        params = {
            event = 'my:clientEvent',
            args = {{ data = 'value', shouldClose = true }}
        }
    },
    {
        header = 'Option 2',
        txt = 'This triggers a server event',
        icon = 'square',
        params = {
            isServer = true,
            event = 'my:serverEvent',
            args = {{ id = 123, shouldClose = true }}
        }
    }
})

Registered Menu (RegisterMenu + OpenMenu)

Register a menu for reuse and open it later.

-- Register the menu
exports['ngd-ui']:RegisterMenu('main_menu', {
    title = 'Main Menu',
    position = 'center-right',
    options = {
        { header = 'Settings Menu', isMenuHeader = true },
        {
            header = 'Settings',
            txt = 'Configure your settings',
            icon = 'gear',
            params = {
                event = 'menu:openSettings'
            }
        },
        {
            header = 'Exit',
            txt = 'Close the menu',
            icon = 'times',
            params = {
                event = 'menu:close'
            }
        }
    }
})

-- Open the menu later
exports['ngd-ui']:OpenMenu('main_menu')

Menu Option Properties

PropertyTypeRequiredDescription
headerstringYesMain text displayed
txtstringNoDescription/subtitle text
iconstringNoFontAwesome icon (without 'fa-' prefix) or image path
isMenuHeaderbooleanNoMakes this a non-clickable header
disabledbooleanNoDisable the option
paramstableNoEvent/action parameters

Params Properties

PropertyTypeDescription
eventstringEvent name to trigger
argstableArguments to pass to event
isServerbooleanIf true, triggers server event

⚠️ Important Note on Args: Due to NUI serialization, args must be wrapped in a double table format.

Menu Functions

CreateMenu

Create and immediately display a menu.

exports['ngd-ui']:CreateMenu(options, position)

Parameters:

  • options - Table of menu options
  • position - Menu position ('center-right', 'top-right', etc.) - Default: 'center-right'

RegisterMenu

Register a menu for later use.

exports['ngd-ui']:RegisterMenu(id, menuData)

Parameters:

  • id - Unique menu identifier
  • menuData - Table containing title, position, options

OpenMenu

Open a previously registered menu.

exports['ngd-ui']:OpenMenu(id, keepHistory)

Parameters:

  • id - Menu identifier
  • keepHistory - If true, adds to navigation history - Default: false

CloseMenu

Close the currently open menu.

exports['ngd-ui']:CloseMenu()

GoBackMenu

Navigate to the previous menu in history.

exports['ngd-ui']:GoBackMenu()

UpdateMenuOptions

Update options of a registered menu.

exports['ngd-ui']:UpdateMenuOptions(id, options)

IsMenuOpen

Check if any menu is currently open.

local isOpen = exports['ngd-ui']:IsMenuOpen()

GetOpenMenu

Get the ID of the currently open menu.

local menuId = exports['ngd-ui']:GetOpenMenu()

Implementation Examples

Crafting Menu

exports['ngd-ui']:CreateMenu({
    { header = 'Pour Wine Menu', isMenuHeader = true },
    {
        header = 'Red Wine',
        txt = 'Required: Grapes, Sugar',
        icon = 'wine-bottle',
        params = {
            event = 'wine:pour',
            args = {{ drink = 'red_wine' }}
        }
    },
    {
        header = 'White Wine',
        txt = 'Required: White Grapes, Sugar',
        icon = 'wine-glass',
        params = {
            isServer = true,
            event = 'wine:pourServer',
            args = {{ drink = 'white_wine' }}
        }
    },
    {
        header = 'Champagne',
        txt = 'Required: Special Grapes',
        icon = 'glass-cheers',
        disabled = true
    }
})

Vehicle Interaction Menu

exports['ngd-ui']:CreateMenu({
    { header = 'Vehicle Options', isMenuHeader = true },
    {
        header = 'Toggle Engine',
        txt = 'Turn engine on/off',
        icon = 'car',
        params = {
            event = 'vehicle:toggleEngine'
        }
    },
    {
        header = 'Open Trunk',
        txt = 'Access vehicle storage',
        icon = 'box',
        params = {
            event = 'vehicle:openTrunk'
        }
    },
    {
        header = 'Lock/Unlock',
        txt = 'Toggle vehicle locks',
        icon = 'lock',
        params = {
            event = 'vehicle:toggleLock'
        }
    }
})

Position Options

Available menu positions:

  • 'center-right' (default)
  • 'center-left'
  • 'top-left'
  • 'top-right'
  • 'bottom-left'
  • 'bottom-right'
  • 'center'

Event Handling

Client Event

RegisterNetEvent('myEvent', function(args)
    print('Received:', args.data)
end)

Server Event

RegisterNetEvent('myServerEvent', function(args)
    local src = source
    print('Player:', src, 'Args:', args.id)
end)

Checkbox Event

RegisterNetEvent('settings:toggleHUD', function(checked)
    print('HUD toggled:', checked) -- true or false
end)

Icon Usage

Icons can be specified in two ways:

FontAwesome Icons

Use the icon name without the fa- prefix:

icon = 'circle'        -- renders as fa-solid fa-circle
icon = 'gear'          -- renders as fa-solid fa-gear
icon = 'wine-bottle'   -- renders as fa-solid fa-wine-bottle

Custom Images

Use NUI path for custom images:

icon = 'nui://myresource/images/custom.png'

Notes

  • Menus automatically handle NUI focus (mouse cursor)
  • Args use single table format (not double-nested like other exports)
  • Menu headers with isMenuHeader = true are non-clickable section labels
  • Checkbox options trigger events with boolean checked state
  • Menu history allows navigation with GoBackMenu()
  • Default menu position is center-right
  • Icons without path prefix are treated as FontAwesome icons
Security Camera (Click to Expand)

Security Camera System

Overview

The Security Camera System provides an optimized camera viewing interface with zero idle CPU usage when cameras are not active. Players can cycle through multiple security cameras with keyboard controls and a clean HUD overlay.

Features

  • Zero Idle Performance Impact - No CPU usage when cameras are inactive
  • Multiple Camera Support - Configure unlimited cameras per system
  • Smooth Navigation - Arrow key controls to switch between cameras
  • System Branding - Custom system name and subtitle for each installation
  • HUD Integration - Automatic HUD hiding with camera info overlay
  • Debounced Switching - 500ms cooldown prevents accidental double-switches

Configuration

Basic Setup

Config.CameraSystem = {
    systemName = "Daddy Tobacco",
    systemSubtitle = "Security System",
    cameras = {
        { 
            coords = vector3(-34.05, 2895.45, 63.90), 
            heading = 225.31, 
            pitch = -20.0, 
            roll = 0.0, 
            name = "Front Gate" 
        },
        { 
            coords = vector3(-72.86, 2927.90, 65.13), 
            heading = 277.27, 
            pitch = -35.0, 
            roll = 0.0, 
            name = "North Sideyard" 
        },
    }
}

Camera Properties

PropertyTypeRequiredDescription
coordsvector3YesCamera position in world space
headingfloatYesCamera yaw rotation (0-360)
pitchfloatNoCamera pitch rotation (default: 0.0)
rollfloatNoCamera roll rotation (default: 0.0)
namestringYesDisplay name shown in UI

System Properties

PropertyTypeRequiredDescription
systemNamestringNoMain title (e.g., "Daddy Tobacco")
systemSubtitlestringNoSubtitle (e.g., "Security System")
camerastableYesArray of camera configurations

Usage

Opening Camera System

-- With full configuration
exports['ngd-ui']:OpenCameras(Config.CameraSystem)

-- With just cameras array (no system name/subtitle)
exports['ngd-ui']:OpenCameras({
    { coords = vector3(x, y, z), heading = 0.0, name = "Camera 1" },
    { coords = vector3(x, y, z), heading = 90.0, name = "Camera 2" }
})

Closing Camera System

exports['ngd-ui']:CloseCameras()

Manual Camera Navigation

-- Switch to next camera
exports['ngd-ui']:NextCamera()

-- Switch to previous camera
exports['ngd-ui']:PreviousCamera()

Controls

KeyAction
Left Arrow (174)Previous camera
Right Arrow (175)Next camera
Backspace (194)Exit camera system

Exports

OpenCameras

Opens the camera viewing system.

Parameters:

  • data (table): Configuration table or camera array

Example:

exports['ngd-ui']:OpenCameras({
    systemName = "Prison",
    systemSubtitle = "Maximum Security",
    cameras = {
        { coords = vector3(1845.0, 2585.0, 45.0), heading = 180.0, name = "Cell Block A" }
    }
})

CloseCameras

Closes the camera system and restores normal view.

Example:

exports['ngd-ui']:CloseCameras()

NextCamera

Switches to the next camera in the sequence (wraps to first camera at end).

Example:

exports['ngd-ui']:NextCamera()

PreviousCamera

Switches to the previous camera in the sequence (wraps to last camera at start).

Example:

exports['ngd-ui']:PreviousCamera()

Implementation Examples

Example 1: Simple Security Office

RegisterCommand('officesecurity', function()
    exports['ngd-ui']:OpenCameras({
        systemName = "Downtown Office",
        systemSubtitle = "Security Cameras",
        cameras = {
            { coords = vector3(-75.0, -818.0, 326.0), heading = 90.0, pitch = -25.0, name = "Lobby" },
            { coords = vector3(-75.0, -827.0, 326.0), heading = 180.0, pitch = -30.0, name = "Elevator" },
            { coords = vector3(-68.0, -823.0, 326.0), heading = 270.0, pitch = -20.0, name = "Parking" }
        }
    })
end)

Example 2: Store Security System

local storeCameras = {
    systemName = "24/7 Supermarket",
    systemSubtitle = "Store #143",
    cameras = {
        { coords = vector3(28.0, -1339.0, 31.0), heading = 225.0, pitch = -30.0, name = "Entrance" },
        { coords = vector3(25.0, -1345.0, 31.0), heading = 135.0, pitch = -25.0, name = "Counter" },
        { coords = vector3(31.0, -1343.0, 31.0), heading = 315.0, pitch = -20.0, name = "Aisles" }
    }
}

-- Triggered by interaction with security monitor
RegisterNetEvent('store:viewCameras', function()
    exports['ngd-ui']:OpenCameras(storeCameras)
end)

Notes

  • No idle CPU usage when cameras are inactive
  • 500ms cooldown between camera switches prevents accidental double-switching
  • Camera rotation uses standard FiveM format: Heading (0-360┬░), Pitch (negative looks down), Roll (usually 0.0)
Flipbook (Click to Expand)

Flipbook/Menu System

Overview

A visual flipbook system for displaying multi-page menus, catalogs, or documents. Players can flip through pages with a clean interface and optional title/subtitle branding.

Features

  • Multi-Page Support - Display unlimited pages with automatic numbering
  • Custom Branding - Optional title and subtitle for each flipbook
  • Flexible Format - Supports JPG, PNG, and other image formats
  • Resource Integration - Load images from any resource using NUI paths
  • Simple Controls - Arrow keys or buttons to flip pages

Configuration

Basic Setup

Config.Menu = {
    title = "Vanilla Unicorn",
    subtitle = "Drink Menu",
    imagePath = "nui://ngd-vu/web/images/",
    pages = 2,
    imageFormat = "jpg"
}

Image File Structure

Your images should be named sequentially starting from 1:

your-resource/
  web/
    images/
      1.jpg
      2.jpg
      3.jpg

Usage

Opening a Flipbook

-- With full configuration
exports['ngd-ui']:OpenFlipbook(Config.Menu)

-- Inline configuration
exports['ngd-ui']:OpenFlipbook({
    title = "Gun Store",
    subtitle = "Available Weapons",
    imagePath = "nui://myresource/web/pages/",
    pages = 5
})

-- Simple version (no title/subtitle)
exports['ngd-ui']:OpenFlipbook({
    imagePath = "nui://ngd-vu/web/images/",
    pages = 2
})

Closing a Flipbook

exports['ngd-ui']:CloseFlipbook()

Parameters

ParameterTypeRequiredDefaultDescription
titlestringNo''Main title displayed on flipbook
subtitlestringNo''Subtitle displayed under title
imagePathstringYes-NUI path to image folder (must end with /)
pagesnumberYes-Number of page images
imageFormatstringNo'jpg'Image file extension (jpg, png, etc.)

Implementation Examples

Restaurant Menu

exports['ngd-ui']:OpenFlipbook({
    title = "Burger Shot",
    subtitle = "Menu",
    imagePath = "nui://burgershot/web/menu/",
    pages = 4,
    imageFormat = "png"
})

Nightclub Drink Menu

local vuMenu = {
    title = "Vanilla Unicorn",
    subtitle = "Drink Menu",
    imagePath = "nui://ngd-vu/web/images/",
    pages = 2
}

RegisterNetEvent('vu:openMenu', function()
    exports['ngd-ui']:OpenFlipbook(vuMenu)
end)

Clothing Catalog

exports['ngd-ui']:OpenFlipbook({
    title = "Ponsonbys",
    subtitle = "Spring Collection 2024",
    imagePath = "nui://clothing-store/catalog/",
    pages = 8
})

Gun Store Catalog

AddEventHandler('gunstore:openCatalog', function()
    exports['ngd-ui']:OpenFlipbook({
        title = "Ammu-Nation",
        subtitle = "Firearms Catalog",
        imagePath = "nui://gunstore/web/catalog/",
        pages = 6,
        imageFormat = "png"
    })
end)

Simple Product Catalog (No Branding)

exports['ngd-ui']:OpenFlipbook({
    imagePath = "nui://my-store/products/",
    pages = 3
})

Image Preparation Tips

  1. Naming Convention: Name your images sequentially: 1.jpg, 2.jpg, 3.jpg, etc.
  2. Resolution: Recommended 1920x1080 or 16:9 aspect ratio for best display
  3. File Size: Optimize images to reduce load times (under 500KB per image recommended)
  4. Path: Always end imagePath with a forward slash /

NUI Path Examples

-- From your resource
imagePath = "nui://my-resource/web/images/"

-- From another resource
imagePath = "nui://qb-shops/html/menus/"

-- Nested folders
imagePath = "nui://server-ui/public/catalogs/guns/"

Notes

  • Players can close the flipbook by pressing ESC or clicking the close button
  • Images are loaded dynamically as players flip through pages
  • The imagePath must be a valid NUI path accessible from your resource
  • Image files must be sequential starting from 1 (no gaps in numbering)
3D Drawtext (Click to Expand)

3D Draw Text & Interaction System

Overview

An optimized 3D text rendering and interaction system that replaces traditional target systems. Features distance-based rendering, persistent markers, and interactive prompts with zero idle CPU usage.

Features

  • Interaction System - Target replacement with keypress detection
  • Text Markers - Persistent 3D text labels (no interaction)
  • 3D Text - Persistent text that auto-manages rendering
  • Draw3DText - Simple draw function for manual loops
  • Smart Sleep - Distance-based thread optimization

Configuration

None required. Optional debug flag: Config.ThreeDTextDebug = true

Usage

Interaction System

Create interactive points that respond to key presses.

Single Option

exports['ngd-ui']:AddInteraction({
    id = 'shop_door',
    coords = vector3(25.0, -1347.0, 29.5),
    key = 'E',
    keyLabel = 'E',
    label = 'Open Shop',
    icon = 'fa-solid fa-store',
    color = '~g~',
    range = 2.5,
    onInteract = function(id, data)
        -- Your code here
    end
})

Multiple Options

exports['ngd-ui']:AddInteraction({
    id = 'boss_safe',
    coords = vector3(25.0, -1347.0, 29.5),
    icon = 'fa-solid fa-briefcase',
    range = 3.0,
    options = {
        {
            key = 'E',
            keyLabel = 'E',
            label = 'Open Stash',
            color = '~g~',
            onInteract = function()
                -- Your code here
            end
        },
        {
            key = 'G',
            keyLabel = 'G',
            label = 'Boss Menu',
            color = '~b~',
            job = 'police',
            onInteract = function()
                -- Your code here
            end
        }
    }
})

Managing Interactions

-- Update label
exports['ngd-ui']:UpdateInteraction('shop_door', 'Shop Closed')

-- Update position
exports['ngd-ui']:UpdateInteractionCoords('shop_door', vector3(x, y, z))

-- Remove specific interaction
exports['ngd-ui']:RemoveInteraction('shop_door')

-- Clear all interactions
exports['ngd-ui']:ClearAllInteractions()

Text Markers

Display 3D text without interaction (informational only).

-- Add marker
exports['ngd-ui']:AddTextMarker(
    'parking_sign',
    vector3(215.0, -810.0, 30.0),
    'Public Parking',
    10.0,
    'fa-solid fa-parking'
)

-- Update text
exports['ngd-ui']:UpdateTextMarker('parking_sign', 'Parking Full')

-- Update position
exports['ngd-ui']:UpdateTextMarkerCoords('parking_sign', vector3(x, y, z))

-- Remove marker
exports['ngd-ui']:RemoveTextMarker('parking_sign')

-- Clear all markers
exports['ngd-ui']:ClearAllTextMarkers()

Persistent 3D Text

Auto-managed 3D text that handles its own rendering loop.

-- Add persistent text
exports['ngd-ui']:Add3DText(
    'welcome_sign',
    vector3(0.0, 0.0, 70.0),
    'Welcome to Los Santos',
    15.0,
    'fa-solid fa-star'
)

-- Update text
exports['ngd-ui']:Update3DText('welcome_sign', 'Welcome Back!')

-- Update position
exports['ngd-ui']:Update3DTextCoords('welcome_sign', vector3(x, y, z))

-- Remove text
exports['ngd-ui']:Remove3DText('welcome_sign')

-- Clear all texts
exports['ngd-ui']:ClearAll3DTexts()

Draw3DText (Manual Loop)

Simple draw function for use inside your own loops.

CreateThread(function()
    while someCondition do
        exports['ngd-ui']:Draw3DText(
            vector3(x, y, z),
            'E: ~g~Interact',
            10.0,
            'fa-solid fa-hand'
        )
        Wait(0)
    end
    exports['ngd-ui']:Hide3DText()
end)

Parameters

Interaction Options

ParameterTypeRequiredDefaultDescription
idstringYes-Unique identifier
coordsvector3Yes-World position
keystring/numberNo-Key to press (single option)
keyLabelstringNo'E'Display label for key
labelstringNo-Text to display (single option)
iconstringNo-FontAwesome icon class
colorstringNo'g'GTA color code
rangenumberNo2.5Interaction range
jobstring/tableNo-Required job(s)
notJobstring/tableNo-Excluded job(s)
onInteractfunctionNo-Callback function
optionstableNo-Array of multiple options

Text Marker Parameters

ParameterTypeRequiredDefaultDescription
idstringYes-Unique identifier
coordsvector3Yes-World position
textstringYes-Text to display
rangenumberNo5.0Visibility range
iconstringNo-FontAwesome icon class

3D Text Parameters

ParameterTypeRequiredDefaultDescription
idstringYes-Unique identifier
coordsvector3Yes-World position
textstringYes-Text to display
distancenumberNo10.0Visibility distance
iconstringNo-FontAwesome icon class

Color Codes

Use GTA color codes in your text:

  • r - Red
  • g - Green
  • b - Blue
  • y - Yellow
  • p - Purple
  • w - White
  • s - Default

Example: 'E: gOpen w| rG: Close'

Job Filtering

-- Single job
job = 'police'

-- Multiple jobs
job = {'police', 'ambulance'}

-- Exclude jobs
notJob = 'unemployed'
notJob = {'unemployed', 'civilian'}

Implementation Examples

Store Entrance

exports['ngd-ui']:AddInteraction({
    id = 'store_24_7',
    coords = vector3(25.0, -1347.0, 29.5),
    key = 'E',
    label = 'Open Store',
    icon = 'fa-solid fa-store',
    range = 2.0,
    onInteract = function()
        TriggerEvent('store:openMenu')
    end
})

ATM Machine

exports['ngd-ui']:AddInteraction({
    id = 'atm_main_1',
    coords = vector3(-386.7, 6046.0, 31.5),
    key = 'E',
    label = 'Use ATM',
    icon = 'fa-solid fa-credit-card',
    color = '~b~',
    range = 1.5,
    onInteract = function()
        TriggerEvent('bank:openATM')
    end
})

Police Evidence Locker

exports['ngd-ui']:AddInteraction({
    id = 'pd_evidence',
    coords = vector3(475.0, -995.0, 26.3),
    icon = 'fa-solid fa-box-archive',
    range = 2.0,
    options = {
        {
            key = 'E',
            label = 'View Evidence',
            job = 'police',
            onInteract = function()
                -- Open evidence UI
            end
        },
        {
            key = 'G',
            label = 'Submit Evidence',
            job = 'police',
            color = '~y~',
            onInteract = function()
                -- Submit evidence
            end
        }
    }
})

Parking Zone Sign

exports['ngd-ui']:AddTextMarker(
    'parking_downtown',
    vector3(215.0, -810.0, 30.0),
    '~b~Public Parking~w~\n$5 per hour',
    12.0,
    'fa-solid fa-square-parking'
)

Notes

  • Interactions use Wait(0) when player is in range for precise key detection
  • Out of range, threads use smart sleep (100ms-1000ms) based on distance
  • Text scale automatically adjusts based on distance (0.7-1.0)
  • All loops automatically stop when no elements are registered
Notification System (Click to Expand)

Notification System

Overview

A clean, modern notification system for FiveM that supports icons, sounds, positions, themes, and server-side triggering. Offers two interfaces ΓÇö standard Notify and advanced Notify with icon support.

Features

  • Simple syntax ΓÇö one-line usage
  • Themed notifications ΓÇö success, error, warning, info, default
  • Position control ΓÇö choose where your notifications display
  • Progress bar toggle ΓÇö show or hide the bar
  • Icon support ΓÇö FontAwesome icons
  • Sound toggle

Parameters

Notify

ParameterTypeRequiredDefaultDescription
titlestringYes-Main text heading
messagestringNo''Secondary text line
timenumberYes5000Duration in ms
typestringNo'default'success | error | warning | info | default
positionstringNo'center-right'See position list below
hideprogressbarbooleanNofalseHides progress bar
soundbooleanNotruePlays notification sound

Usage

Notify (Standard)

exports['ngd-ui']:Notify(
    title,              -- string (required)
    message,            -- string (optional)
    time,               -- number in ms (required)
    type,               -- string (optional)
    position,           -- string (optional)
    hideprogressbar,    -- boolean (optional)
    sound               -- boolean (optional)
)

NotifyAdvanced (With Icon Support)

exports['ngd-ui']:NotifyAdvanced({
    title       = "",
    message     = "",
    time        = 5000,
    type        = "default",
    icon        = "",       -- FontAwesome icon name
    position    = "",
    hideProgressBar = false,
    sound       = true
})

Examples

Basic Notification

exports['ngd-ui']:Notify("Success!", "You did the thing", 5000, "success")

Error Notification

exports['ngd-ui']:Notify("Error", "Something went wrong", 5000, "error")

Custom Position

exports['ngd-ui']:Notify("Warning", "Low fuel detected", 5000, "warning", "top-center")

Without Progress Bar

exports['ngd-ui']:Notify("Note", "Progress bar disabled", 5000, "info", "top-right", true)

No Sound

exports['ngd-ui']:Notify("Shhh...", "Sound disabled for this notification", 5000, "info", nil, nil, false)

Advanced Notification Examples

Custom Icon Notification

exports['ngd-ui']:NotifyAdvanced({
    title    = "Vehicle Stored",
    message  = "Your vehicle has been stored in the garage",
    time     = 5000,
    type     = "success",
    icon     = "car",
    position = "top-right"
})

Server-Side Usage

Trigger a Client Notification from Server

TriggerClientEvent('ngd-ui:Notify', source, "Job Complete!", "You earned $500", 5000, "success")

NotifyAdvanced

FieldTypeRequiredDefaultDescription
titlestringYes-Main text heading
messagestringNo''Secondary text line
timenumberYes5000Duration in ms
typestringNo'default'success | error | warning | info | default
iconstringNonilFontAwesome icon name
positionstringNo'center-right'See position list
hideProgressBarbooleanNofalseHides progress bar
soundbooleanNotruePlays sound

Returns: none


Position Options

top-right
top-left
top-center
bottom-right
bottom-left
bottom-center
center-right (default)
above-center-right

Notification Types

TypeColor/Style
successGreen highlight
errorRed highlight
warningYellow highlight
infoBlue highlight
defaultNeutral style

Example Implementation

Item Pickup

AddEventHandler('items:pickup', function(label)
    exports['ngd-ui']:Notify("Picked Up", "You collected: " .. label, 3000, "success")
end)

Fuel Warning

if fuel <= 5 then
    exports['ngd-ui']:Notify("Fuel Low", "Find a gas station!", 5000, "warning", "bottom-center")
end

Crafting Complete

exports['ngd-ui']:NotifyAdvanced({
    title = "Crafting Complete",
    message = "Your item is ready to use!",
    type = "success",
    icon = "hammer",
    sound = true
})

Simple Shops (Click to Expand)

Shop UI System

Overview

A flexible NUI-based shop interface for FiveM that supports dynamic shop data, custom server events, and automatic item image paths. Intended for clean, modern shop implementations using a single data format.


Features

  • Config-based shops ΓÇô reusable, structured shop definitions
  • Inline shops ΓÇô create shops directly from code
  • Custom server events ΓÇô handle purchases in any resource
  • Image auto-resolution ΓÇô automatic full nui:// path building
  • Slot sorting ΓÇô automatic sort by slot ordering
  • Simple exports ΓÇô OpenShop and CloseShop

Exports

OpenShop

exports['ngd-ui']:OpenShop(data)

data should be a shop table containing:

{
    name        = "Shop Name",
    imagePath   = "path/to/images/",
    serverEvent = "myresource:Server:Purchase",
    items = {
        { name = "water", label = "Water", price = 5 },
        ...
    }
}

CloseShop

exports['ngd-ui']:CloseShop()

Closes the currently open shop and releases UI focus.


Shop Data Format

Structure

local shop = {
    name        = "My Shop",
    imagePath   = "nui://ox_inventory/web/images/",
    serverEvent = "myresource:Server:Purchase",
    items = {
        { name = "vodka", label = "Vodka", price = 10 },
        ...
    }
}

Open with:

exports['ngd-ui']:OpenShop(shop)

Item Fields

FieldTypeRequiredDefaultDescription
namestringYes-Item database name
labelstringNoautoDisplay label in UI
pricenumberNo0Price per item
countnumberNonilOptional stock control
imagestringNoautoCustom image path
slotnumberNoautoDisplay ordering
infotableNonilExtra purchase info
typestringNonilFor your own logic

Image Handling

The UI will automatically:

  • Normalize image paths
  • Append missing prefixes (nui://)
  • Append missing file extensions if needed
  • Build fallback images using item names

Example fallback:

imagePath .. "water.png"

Server Event Behavior

When a shop purchase occurs, the client sends:

local purchaseData = {
    shopId = data.shopId,
    items  = data.items,
    total  = data.total
}

If a custom serverEvent is defined

TriggerServerEvent("myresource:Server:Purchase", purchaseData)

If no serverEvent is defined

The shop system defaults to:

TriggerServerEvent("ngd-ui:Server:ShopPurchase", purchaseData)

Inline Example

exports['ngd-ui']:OpenShop({
    name        = "Snack Bar",
    serverEvent = "my_snacks:Server:Purchase",
    items = {
        { name = "water",   label = "Water Bottle", price = 5 },
        { name = "sandwich", label = "Sandwich",    price = 25 }
    }
})

Config Example

Config = Config or {}

Config.AlcoholStore = {
    name        = "Alcohol Store",
    imagePath   = "nui://ngd-vu/web/images/",
    serverEvent = "ngd-vu:Server:StorePurchases",
    items = {
        { name = "vodka", label = "Vodka", price = 10 },
        { name = "whiskey", label = "Whiskey", price = 15 }
    }
}

exports['ngd-ui']:OpenShop(Config.AlcoholStore)

Closing the Shop

exports['ngd-ui']:CloseShop()

This gets called automatically when the shop items are purchased or the shop gets closed out. This is just useful for your other resources to potentially close the shop menu. (Maybe if a player dies while in a shop?)


Progress Bars (Click to Expand)

Progress Bar System

Overview

A flexible progress bar system for ngd-ui that is compatible with common progressbar-style exports.
Supports linear and circular progress bars, animations, props, control disabling, cancellation, and both synchronous and callback-based usage.


Features

  • Drop-in compatible with progressbar-style data and callbacks
  • Two styles ΓÇô standard bar and circular progress
  • Cancelable ΓÇô X or BACKSPACE (configurable via canCancel)
  • Control locking ΓÇô movement, vehicle, mouse, and combat
  • Animations & props ΓÇô play an animation and attach one or two props
  • Synchronous or async ΓÇô return boolean or use a callback
  • Dead checks ΓÇô optional useWhileDead protection
  • Helpers ΓÇô cancel & state check exports

Exports

exports['ngd-ui']:Progress(data, cb?)         -- linear bar
exports['ngd-ui']:ProgressCircle(data, cb?)   -- circular bar
exports['ngd-ui']:CancelProgress()            -- force-cancel active progress
exports['ngd-ui']:IsDoingProgress()           -- returns boolean

-- Optional direct sync access (internal helpers)
exports['ngd-ui']:ProgressSync(data)
exports['ngd-ui']:ProgressCircleSync(data)

cb? = optional callback


Basic Usage

1. Simple linear bar (callback style)

exports['ngd-ui']:Progress({
    label      = "Lockpicking...",
    duration   = 5000, -- ms
    canCancel  = true,
    controlDisables = {
        disableMovement    = true,
        disableCarMovement = true,
        disableMouse       = false,
        disableCombat      = true
    }
}, function(cancelled)
    if not cancelled then
        print("Success!")
    else
        print("Cancelled")
    end
end)

2. Simple linear bar (sync / blocking)

local success = exports['ngd-ui']:Progress({
    label    = "Searching...",
    duration = 3000
})

if success then
    print("Search complete")
else
    print("Search cancelled or failed")
end

3. Circular progress bar

exports['ngd-ui']:ProgressCircle({
    label     = "Scanning Area...",
    duration  = 7000,
    canCancel = true
}, function(cancelled)
    if not cancelled then
        print("Scan finished")
    end
end)

Data Format

The system accepts one unified data table and will internally normalise common progressbar fields.

Top-level fields

FieldTypeRequiredDefaultDescription
labelstringNo"Loading..."Text shown in the progress UI
namestringNoused if label is nilAlternative label (progressbar-style)
durationnumberYes-Duration in milliseconds
canCancelbooleanNofalseWhether player can cancel with X/BACKSPACE
useWhileDeadbooleanNonilIf false and ped is dead, progress is cancelled immediately
disabletableNoderivedExplicit control disable table (see below)
controlDisablestableNo-Common progressbar-style control flags (mapped to disable)
animtableNoderivedAnimation definition (see below)
animationtableNo-Progressbar-style animation table (mapped to anim)
proptableNonilProp to attach (see props)
propTwotableNonilSecond prop to attach

Control Disables

You may use either disable (native format) or controlDisables (progressbar-style).

disable format

disable = {
    disableMovement = true,
    disableMouse    = false,
    disableCar      = true,
    disableCombat   = true
}

controlDisables (mapped automatically)

controlDisables = {
    disableMovement    = true,
    disableCarMovement = true,
    disableMouse       = false,
    disableCombat      = true
}

Mapped internally to:

  • disable.disableCar = disableCarMovement or disableCar

Animations

You can play an animation during the progress bar.

Native anim format

anim = {
    dict = "amb@world_human_hammering@male@base",
    anim = "base",
    flag = 49 -- optional
}

Progressbar-style animation (mapped automatically)

animation = {
    animDict = "amb@world_human_bum_wash@male@low@idle_a",
    anim     = "idle_a",
    flag     = 49,   -- or
    flags    = 49
}

If both are supplied, anim takes priority.

Animations are started before the bar and stopped automatically when it completes or is cancelled.


Props

You can optionally attach one or two props to the ped during progress.

Prop fields

Each prop / propTwo may contain:

FieldTypeRequiredDescription
modelstring/intYesModel name or hash
bonenumberNoPed bone index (default: 60309 hand)
posvector3NoOffset position relative to bone
rotvector3NoRotation relative to bone
coordstableNo{ x, y, z } alternative to pos
rotationtableNo{ x, y, z } alternative to rot

Example:

prop = {
    model = "prop_tool_hammer",
    bone  = 57005,
    pos   = vector3(0.1, 0.02, -0.02),
    rot   = vector3(90.0, 0.0, 0.0)
}

coords / rotation are automatically converted into vector3 if provided instead of pos / rot.

Props are deleted automatically after completion or cancellation.


Cancellation

If canCancel = true, the player can cancel using:

  • X key (INPUT_VEH_DUCK, control 73)
  • BACKSPACE key (control 177)

Internally, the system:

  • Sends cancelProgress / cancelProgressCircle to NUI
  • Resolves the promise with { completed = false, cancelled = true }
  • Sets isDoingProgress back to false

For callback-based usage, the callback receives:

function(cancelled)
    if cancelled then
        -- user cancelled or failed
    else
        -- success
    end
end

For synchronous usage, Progress / ProgressCircle return:

  • true ΓåÆ completed
  • false ΓåÆ cancelled or failed

CancelProgress Export

exports['ngd-ui']:CancelProgress()

Force-cancel whichever progress (bar or circle) is active.
Safe to call even if no progress is running.

Typical use:

if exports['ngd-ui']:IsDoingProgress() then
    exports['ngd-ui']:CancelProgress()
end

IsDoingProgress Export

local active = exports['ngd-ui']:IsDoingProgress()
if active then
    print("Progress in progress...")
end

Returns true if a progress bar or circle is currently running, otherwise false.


Notes & Best Practices

  1. Always set duration ΓÇô progress without a duration is rejected and logged as an error.
  2. Use callbacks for non-blocking flows ΓÇô when running in threads that shouldnΓÇÖt block gameplay logic.
  3. Use useWhileDead = false when the action shouldnΓÇÖt be possible while dead.
  4. Avoid double starts ΓÇô if Progress is called while another is active, it returns false and does nothing.
  5. Keep labels short ΓÇô long labels may wrap or clip depending on UI design.

PED Dialog (Click to Expand)

Dialog / PED Interaction System

Overview

A lightweight dialog system for ngd-ui that lets you open an interactive conversation UI with any PED or object.
It supports titles, icons, descriptions, tags, and a list of clickable choices that can trigger client events, server events, commands, or Lua functions.
When opened, a cinematic camera focuses on the target PED for a more immersive interaction.


Features

  • Cinematic camera focused on the interacting PED
  • Custom dialog content ΓÇô title, icon, description, tags
  • Multi-choice interactions per dialog
  • Supported action types:
    • client events
    • server events
    • commands
    • custom Lua functions
  • Dynamic dialog updates without closing the UI
  • Automatic focus management between game + UI

Exports

TalkToNPC

exports['ngd-ui']:TalkToNPC(entity, dialog)

Opens the dialog UI for a given PED or entity.

Parameters

NameTypeRequiredDescription
entitynumberYesEntity handle (usually a PED/object)
dialogtableYesDialog configuration (structure below)

UpdateDialog

exports['ngd-ui']:UpdateDialog(dialog)

Updates the currently open dialog contents.
Useful for multi-step interactions, branching dialogs, and dynamic text.

Parameters

NameTypeRequiredDescription
dialogtableYesNew dialog structure to display

If no dialog is currently open, nothing happens.


Dialog Structure

A dialog is a Lua table:

local dialog = {
    title       = "Character Name",
    icon        = "user",
    description = "Some dialog text here.",
    choices     = { /* choice list */ },
    tags        = { "NPC", "Quest" }
}

Fields

FieldTypeRequiredDescription
titlestringYesHeader label in dialog
iconstringNoFontAwesome icon name
descriptionstringNoBody text
choicestable[]YesAction list
tagsstring[]NoOptional info labels

Choice Structure

Each entry in dialog.choices is a clickable option:

{
    title       = "Redeem Ticket",
    shouldClose = false,
    shouldHide  = false,
    clientEvent = "myresource:Client:Redeem",
    serverEvent = "myresource:Server:Redeem",
    command     = "me waves",
    func        = function(args) end,
    args        = { some = "data" }
}

Choice Fields

FieldTypeRequiredDefaultDescription
titlestringYes-UI text for button
shouldClosebooleanNofalseClose dialog after click
shouldHidebooleanNofalseHide UI during function execution
clientEventstringNonilClient event to trigger
serverEventstringNonilServer event to trigger
commandstringNonilCommand string to run
funcfunctionNonilCustom Lua function
argsany/tableNonilOptional data for events/function

Action Order

When a choice is clicked, ngd-ui does:

  1. Calls SetPedTalk(CurrentNPC) (if present in your project).

  2. Reads CurrentDialog.choices[index].

  3. If choice.shouldClose == true, closes the dialog & camera.

  4. If choice.clientEvent is set:

    TriggerEvent(choice.clientEvent, choice.args)
    
  5. If choice.serverEvent is set:

    TriggerServerEvent(choice.serverEvent, choice.args)
    
  6. If choice.command is set:

    ExecuteCommand(choice.command)
    
  7. If choice.func is set:

    • If choice.shouldHide is true, the dialog is hidden first.
    • choice.func(args) is executed.
    • If choice.shouldHide is true, the dialog is shown again afterwards.

Camera Behavior

When TalkToNPC is called:

  1. CurrentNPC is stored.
  2. A camera is placed slightly in front of the NPC.
  3. A scripted camera is created and activated:
    • Focused on the NPC
    • Slightly above and facing them
  4. NUI focus is enabled.

When the dialog is closed (e.g. via shouldClose = true):

  • Scripted camera is destroyed.
  • Script cam rendering stops.
  • NUI focus is released.
  • Internal dialog/NPC references are cleared.

Basic Usage Example

Simple vendor dialog

local function OpenVendorDialog(ped)
    exports['ngd-ui']:TalkToNPC(ped, {
        title       = "Ticket Vendor",
        icon        = "ticket",
        description = "Welcome! What would you like to do?",
        tags        = { "Service", "Vendor" },
        choices     = {
            {
                title       = "Redeem Ticket",
                shouldClose = false,
                clientEvent = "myresource:Client:RedeemTicket",
                args        = { type = "standard" }
            },
            {
                title       = "Ask a Question",
                shouldClose = false,
                command     = "me asks a question"
            },
            {
                title       = "Goodbye",
                shouldClose = true
            }
        }
    })
end

You can hook this into a target system or interaction:

AddEventHandler("myresource:OpenVendor", function(ped)
    OpenVendorDialog(ped)
end)

Real-World Example

Test PED dialog from ngd-ui

local function BuildIntroDialog(ped)
    local serverId = GetPlayerServerId(PlayerId())

    local choices = {}

    -- Option 1: Who are you?
    choices[#choices + 1] = {
        title       = "Who are you?",
        shouldClose = false,
        func        = function()
            exports['ngd-ui']:UpdateDialog({
                title       = "About Me",
                icon        = "user",
                description = "I'm just a test NPC used to demonstrate the ngd-ui dialog system.",
                tags        = { "ngd-ui is cool!" },
                choices     = {
                    {
                        title       = "Back",
                        shouldClose = false,
                        func        = function()
                            exports['ngd-ui']:UpdateDialog(BuildIntroDialog(ped))
                        end
                    },
                    {
                        title       = "Goodbye",
                        shouldClose = true,
                        func        = function()
                            CreateTestPedText()
                        end
                    }
                }
            })
        end
    }

    -- Option 2: What is this UI?
    choices[#choices + 1] = {
        title       = "What is this UI?",
        shouldClose = false,
        func        = function()
            exports['ngd-ui']:UpdateDialog({
                title       = "ngd-ui Dialog",
                icon        = "info-circle",
                description = "This is a demo conversation showing how dialogs can update without closing.",
                tags        = { "Dialog Update Example" },
                choices     = {
                    {
                        title       = "Back",
                        shouldClose = false,
                        func        = function()
                            exports['ngd-ui']:UpdateDialog(BuildIntroDialog(ped))
                        end
                    },
                    {
                        title       = "Goodbye",
                        shouldClose = true,
                        func        = function()
                            CreateTestPedText()
                        end
                    }
                }
            })
        end
    }

    -- Option 3: Goodbye (main menu)
    choices[#choices + 1] = {
        title       = "Goodbye",
        shouldClose = true,
        func        = function()
            CreateTestPedText()
        end
    }

    return {
        title       = "Test NPC",
        icon        = "user",
        description = "Hi there! Choose an option below to see dialog updates in action.",
        tags        = { "TAG Example", "I am just an NPC :(", "Live Variables. Server ID: " .. serverId },
        choices     = choices
    }
end

Triggered with:

exports['ngd-ui']:TalkToNPC(testPed, BuildIntroDialog(testPed))

Notes & Best Practices

  1. Always provide a title and at least one choice.
  2. Use UpdateDialog for multi-step flows instead of closing and reopening.
  3. Use shouldHide when you temporarily need to hide the dialog to show another UI.
  4. Prefer server events for game-changing actions (items/money) and client events for local visuals.
  5. Keep descriptions and choice titles concise for readability.



Test Commands (Click to Expand)

Test Commands

Enable test commands by setting Config.TestCommands = true in your configuration.

Camera System

CommandDescription
/testcamerasOpens a test camera system with 3 cameras. Use arrow keys to switch, backspace to exit.

Flipbook

CommandDescription
/testflipbookOpens a test flipbook menu. Use arrow keys or buttons to flip pages, ESC to close.

Menu

CommandDescription
/testmenuOpens a basic context menu with 3 options (button, server event, checkbox).

Input Dialog

CommandDescription
/testinputOpens a basic input dialog with 2 fields (name and age).
/testinputfullOpens a dialog showcasing all input types (text, password, number, date, select, checkbox).

Help Text

CommandDescription
/testhelptextShows vertical help text at bottom center for 5 seconds.
/testhelptexthShows horizontal help text at bottom center for 5 seconds.

3D Text & Interactions

CommandDescription
/testinteractCreates a single interaction point 2m ahead. Press E when in range.
/testmultiCreates a multi-option interaction 2m ahead. Press E or G when in range.
/testmarkerCreates an information text marker 3m ahead.
/cleartestsRemoves all test interactions and markers.

Notification System

CommandDescription
/testnotifyShows a standard notification
/testnotifyallShows all of the notifications.
/testnotifyiconShows an 'advanced' notification with FA icon.

Simple Shops

CommandDescription
/testshopOpens a shop.

Progress Bars

CommandDescription
/testprogressRuns a test progress bar.
/testpcircleRuns a circle test progress bar.
/testppropRuns a progress bar with a prop.

PED Dialog

| Command | Description | Requires | |---------|-------------| | /testdialog | This opens the dialog for the test ped found at coords: 116.36, -1088.41, 28.23 | Config.TestPedInteractions = true

Debug Commands

CommandDescriptionRequires
/drawtextdebugShows debug info for all active 3D text elements, markers, and interactions.Config.ThreeDTextDebug = true

Usage Example

-- Enable in your config file
Config.TestCommands = true
Config.ThreeDTextDebug = true

-- In-game
Use the / commands listed above to show examples of each UI element.

Configuration Notes

  • Editable Files
    Please review the editable files in the client and server folder and enter in the correct exports for your servers configuration.

Do you still need help? Open a ticket in our Discord