NullSect
Systems nominal

Docs / HUD / Overview

ns-hud — NullSect HUD Engine

Simple by default, powerful when customised. A widget-based FiveM HUD: players get a clean classic GTA-style HUD out of the box, and can rebuild almost every part of it in a live in-game editor. Other resources plug their own widgets, rules and notifications into it through a public API.

Turkish: README.tr.md · Install: INSTALLATION.md · Config: CONFIGURATION.md

Features

  • 27 built-in widgets — health, armor, hunger, thirst, stamina, stress, oxygen, cash, bank, player ID, server time, voice, compass, street, zone, speed, RPM, gear, fuel, engine, vehicle damage, seatbelt, weapon, ammo, job, objective, notifications.
  • Live editor (/hud) on the real HUD: drag & drop, corner resize, 11 anchors (9 screen anchors + beside / above minimap), offset, size, scale, opacity, rotation, colour, icon, font, spacing, variant, visibility, smart-hide. Snap grid, undo/redo, keyboard nudging, ESC to close (asks before discarding).
  • Layouts & profiles — ready layouts Classic, Minimal, RP, Racing, Streamer plus up to 10 personal layouts per player (save, save-as, rename, delete, switch at any time).
  • Themes — Classic, Minimal, Modern, Racing, all on the same engine (CSS variables + widget variants: bar / pill / ring / vertical, digital / gauge, bar / segments / line).
  • Context-aware — vehicle / on-foot / armed / firearm / underwater / job / phone / paused / dead; widgets hide when irrelevant.
  • Rule system — data-driven WHEN … THEN … (show, hide, style, opacity, scale) from config, per layout (rule editor in the UI) and from scripts.
  • Notification manager — 4 levels (critical / important / normal / background), stacking, max visible, priority queue, de-duplication (×3), per-resource spam limit, synthesized sounds with volume.
  • Focus mode (one key, keeps speed / compass / objective…), cinematic mode (HUD, minimap, notifications, black bars), phone behaviour (shrink / hide).
  • Accessibility — HUD / text / icon scale, global opacity, animation speed, UI sound volume, high contrast, larger text, reduced motion, colour-blind palettes (protanopia / deuteranopia / tritanopia).
  • Resolution-safe — reference grid scaled by screen height, GTA safezone respected, game aspect followed (multi-monitor), every widget clamped inside the safe area (rotation included). Tested 720p → 4K, 21:9 and 32:9.
  • Persistent — oxmysql (auto-migrated tables) or server KVP fallback; per license or per character.
  • Performance — one adaptive loop (80 ms in vehicle, 250 ms on foot, 1 s hidden), values diffed and batched into a single NUI message per 40 ms window; zero NUI traffic while nothing changes.
  • Secure — server-authoritative storage, strict validation of every layout / rule / pref, ownership checks, rate limits, per-player lock; external widget data is sanitised and rendered with textContent only.
  • Qbox first, QBCore / ESX / standalone through bridge/; voice adapters for pma-voice, SaltyChat and mumble.

Commands

CommandDefault keyDescription
/hud—Open / close the HUD editor
/hudfocusF7Toggle focus mode
/cinematic—Toggle cinematic mode
/togglehud—Hide / show the HUD
/hudreset <id>—Admin: wipe a player's HUD data
/hudtest—Admin + Config.Debug: demo widget, objective and notification spam test

Keys are registered with RegisterKeyMapping, players can rebind them in Settings → Key Bindings → FiveM.

Client exports

All exports remember the calling resource; everything it registered is cleaned up automatically when it stops.

local hud = exports['ns-hud']

hud:RegisterWidget(def)            --> ok, errKey
hud:RemoveWidget(id)
hud:ShowWidget(id) / hud:HideWidget(id)
hud:SetWidgetVisible(id, true|false|nil)   -- nil = back to automatic
hud:UpdateWidget(id, data)         -- merge
hud:SetWidgetData(id, data)        -- replace
hud:GetWidget(id)                  --> { definition, data, override }
hud:ResetWidget(id)
hud:Notify(data)                   -- or Notify(message, type, duration)
hud:ClearNotifications()
hud:SetObjective(title, text) / hud:ClearObjective()
hud:AddRule(rule) / hud:RemoveRule(id)
hud:SetContext(key, value)         -- custom rule field 'ext.<key>'
hud:SetPhoneOpen(bool|nil) / hud:SetSeatbelt(bool) / hud:SetPlayerStatus({ hunger = 80, thirst = 60, stress = 10 })
hud:SetFocusMode(bool) / hud:ToggleFocusMode() / hud:IsFocusMode()
hud:SetCinematicMode(bool) / hud:IsCinematicMode()
hud:SetHudHidden(bool) / hud:IsHudVisible()
hud:OpenEditor() / hud:IsReady()

Server: exports['ns-hud']:Notify(playerId | -1, data).

Registering a job widget (taxi example)

local function registerTaxiWidget()
    exports['ns-hud']:RegisterWidget({
        id = 'taxi_ride', label = 'Taxi', category = 'job', icon = 'taxi', color = '#f5c518',
        template = 'panel',           -- 'panel' (title + rows) | 'value' | 'status' (bar)
        focus = true,                 -- stays visible in focus mode
        fields = {
            { key = 'passenger', label = 'Passenger', icon = 'user' },
            { key = 'destination', label = 'Destination', icon = 'pin' },
            { key = 'fare', label = 'Fare', format = 'money' },     -- text | number | money | percent | distance | time | speed
            { key = 'eta', label = 'ETA', format = 'time' },
        },
        defaults = { anchor = 'cr', x = 0, y = -40 },
    })
end
AddEventHandler('ns-hud:cl:ready', registerTaxiWidget)            -- ns-hud (re)started
CreateThread(function()
    if GetResourceState('ns-hud') == 'started' then registerTaxiWidget() end
end)

-- during a ride
exports['ns-hud']:SetWidgetVisible('taxi_ride', true)
exports['ns-hud']:UpdateWidget('taxi_ride', { passenger = 'Michael', destination = 'Airport', fare = 84, eta = 95 })
-- ride finished
exports['ns-hud']:SetWidgetVisible('taxi_ride', false)

Same pattern for other jobs, e.g. bus { route, next_stop, passengers, stop_requests }, locksmith { job, target, distance (format = 'distance'), objective }, tow { call, vehicle, distance, objective }. Instead of manual visibility, set jobs = { 'taxi' } and the widget shows whenever the player has that job.

Rules

exports['ns-hud']:AddRule({
    id = 'taxi_meter_running',
    when = { { 'ext.meter', '==', true }, { 'speed', '>', 120 } },
    actions = { { 'style', 'taxi_ride', 'warning' }, { 'show', 'objective' } },
})
exports['ns-hud']:SetContext('meter', true)

Fields: vehicle onfoot armed firearm dead underwater health armor hunger thirst stress stamina oxygen speed rpm fuel engine body seatbelt job duty phone talking radio hour and ext.<key>. Operators: == != < <= > >= in. Actions: show hide style opacity scale; styles: warning danger highlight pulse muted success.

Notifications

exports['ns-hud']:Notify({
    title = 'Dispatch', message = 'New call at Legion Square',
    level = 'important',   -- critical | important | normal | background
    type = 'info',         -- info | success | warning | error
    icon = 'bell', duration = 6000, sound = 'chime', priority = 60, position = 'top-right',
})

License

© NullSect. Fonts: Barlow, Barlow Condensed, Share Tech Mono — SIL Open Font License (see nui/fonts/OFL-*.txt).

Cart

Your cart is empty.