Progress Bar
Timer progress bar — the timer runs NUI-side without Lua polling. Supports ped animation, attached prop and per-tick callback.
3 min read
One-shot
exports.LastMenu:progress(function(p)
p:label("Loading data…")
p:duration(5000)
p:cancelable(true) -- show cancel button and allow Escape
p:confirm(function()
-- fires when the bar fills naturally (completion)
end)
p:cancel(function()
-- fires when the player cancels (only if cancelable = true)
end)
end) Reusable bar
local bar = exports.LastMenu:progress_build(function(p)
p:label("Manufacturing in progress…")
p:duration(8000)
p:cancelable(false) -- mandatory action; player cannot cancel
p:confirm(function() giveCraftedItem() end)
end)
bar.open() -- start
bar.close() -- interrupt programmatically (does NOT fire confirm or cancel) Builder methods
| Method | Args | Description |
|---|---|---|
p:label(str) | string | Text displayed above the bar |
p:duration(ms) | number | Total duration in milliseconds |
p:cancelable(bool) | bool | Allow cancel button + Escape (default: false) |
p:icon(str) | string | Lucide icon shown next to the label |
p:confirm(cb) | function() | Called when the bar fills naturally — completion callback |
p:cancel(cb) | function() | Called when the player cancels — cancellation callback |
p:cb_tick(cb) | function(pct) | Called every ~100ms with current percentage 0–100 |
p:anim(opts) | table | Play a ped animation for the full duration (see below) |
p:prop(opts) | table | Attach a prop to the player ped for the full duration (see below) |
Naming note:
p:confirm(cb)is the completion callback (bar fills → done).p:cancel(cb)is called when the player cancels the action.p:cancelable(bool)controls whether cancellation is allowed.
Position
Configurable in User Settings (F12):
| Preset | Location |
|---|---|
bottom-center | Default — HUD bar style |
top-center | Top of screen |
bottom-left | Bottom-left corner |
bottom-right | Bottom-right corner |
Side effects
p:icon(str) — label icon
Any Lucide icon shown inline with the label text:
p:label("Repairing engine…")
p:icon("wrench") p:cb_tick — per-interval progress
Called every ~100ms. Useful for partial rewards, sounds, or server sync:
local halfway = false
p:cb_tick(function(pct)
if pct >= 50 and not halfway then
halfway = true
TriggerServerEvent("craft:halfwayDone")
PlaySoundFrontend(-1, "CHECKPOINT_NORMAL", "HUD_MINI_GAME_SOUNDSET", true)
end
end) p:anim — ped animation
Plays an animation for the full duration. Automatically cleared on complete, cancel, or programmatic close:
p:anim({
dict = "amb@world_human_welding@male@base",
clip = "base",
flag = 1, -- AnimationFlag: 1 = loop, 49 = loop + upperbody only
}) | Field | Type | Description |
|---|---|---|
dict | string | Animation dictionary name |
clip | string | Clip name inside the dictionary |
flag | number | AnimationFlag bitmask (default: 49) |
p:prop — attached object
Attaches a prop to the player ped. Automatically detached and deleted on complete, cancel, or programmatic close:
p:prop({
model = "prop_tool_torch",
bone = 57005, -- ped bone index (57005 = right hand)
offset = vector3(0.12, 0.03, 0.0),
rot = vector3(0.0, 0.0, 0.0),
}) | Field | Type | Description |
|---|---|---|
model | string\|number | Model name or hash |
bone | number\|string | Bone index or bone name (resolved via GetEntityBoneIndexByName) |
offset | vector3 | Position offset relative to the bone |
rot | vector3 | Rotation offset (Euler angles) |
Complete example — Welding
exports.LastMenu:progress(function(p)
p:label("Welding…")
p:icon("zap")
p:duration(8000)
p:cancelable(true)
p:anim({
dict = "amb@world_human_welding@male@base",
clip = "base",
flag = 1,
})
p:prop({
model = "prop_tool_torch",
bone = 57005,
offset = vector3(0.12, 0.03, 0.0),
rot = vector3(0.0, 0.0, 0.0),
})
p:cb_tick(function(pct)
if pct % 25 < 1 then
PlaySoundFrontend(-1, "CHECKPOINT_NORMAL", "HUD_MINI_GAME_SOUNDSET", true)
end
end)
p:confirm(function() giveCraftedItem() end)
p:cancel(function() notifyWarn("Welding cancelled.") end)
end) Behavior
- While a progress bar is open it owns the stack — other menus cannot open until it finishes or is cancelled.
- Use
cancelable(false)for mandatory actions (crafting, mission interactions). Usecancelable(true)for player-interruptible tasks (lockpicking, hacking). bar.close()interrupts the bar silently — neitherp:confirm()norp:cancel()fires.- Both
animandpropside effects are cleaned up automatically regardless of how the bar closes.