Skip to content

Progress Bar

Timer progress bar — the timer runs NUI-side without Lua polling. Supports ped animation, attached prop and per-tick callback.

2 min read

Simple opening

exports.LastMenu:progress(function(p)
    p:label("Loading data...")
    p:duration(5000)
    p:cancel(true)   -- Escape / cancel button is available
    p:onComplete(function()
        -- triggered when bar reaches 100%
    end)
    p:onCancel(function()
        -- triggered if player cancels
    end)
end)

Reusable bar

local bar = exports.LastMenu:progress_build(function(p)
    p:label("Manufacturing in progress...")
    p:duration(8000)
    p:cancel(false)
    p:onComplete(function() giveCraftedItem() end)
end)

bar.open()    -- start
bar.close()   -- interrupt programmatically (doesn't trigger onComplete/onCancel)

Builder methods

MethodArgsDescription
p:label(str)stringText displayed above the bar
p:duration(ms)numberTotal duration in milliseconds
p:cancel(bool)boolCan player cancel? (default: false)
p:onComplete(cb)functionCalled when bar fills naturally
p:onCancel(cb)functionCalled if player cancels
p:icon(str)stringLucide icon displayed next to label
p:cb_tick(cb)function(pct)Called every ~100ms with current % (0–100)
p:anim(opts)tablePlays ped animation during duration
p:prop(opts)tableAttaches prop to ped during duration

Position

Configurable in User Settings (F12):

PresetLocation
bottom-centerDefault — HUD bar style
top-centerTop of screen
bottom-leftBottom-left corner
bottom-rightBottom-right corner

Side effects (v1.0.0)

Icon

p:label("Manufacturing...")
p:icon("hammer")

cb_tick — per-interval progress

Called every ~100ms. Useful for partial rewards, sounds, or server sync:

p:cb_tick(function(pct)
    if pct >= 50 and not halfway then
        halfway = true
        TriggerServerEvent('myCraft:halfwayDone')
    end
end)

anim — ped animation

Animation is automatically stopped on completion, cancellation or closure:

p:anim({
    dict  = "amb@world_human_welding@male@base",
    clip  = "base",
    flag  = 1,       -- AnimationFlag (1 = loop)
    speed = 1.0,     -- optional (default: 1.0)
    blend = 0.0,     -- optional blendInSpeed
})

prop — attached object

Object is detached and deleted automatically at the end:

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),
})

Complete example — Welding

exports.LastMenu:progress(function(p)
    p:label("Welding in progress...")
    p:icon("zap")
    p:duration(8000)
    p:cancel(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) })
    p:cb_tick(function(pct)
        -- checkpoint sound every 25%
        if pct % 25 < 1 then
            PlaySoundFrontend(-1, "CHECKPOINT_NORMAL", "HUD_MINI_GAME_SOUNDSET", true)
        end
    end)
    p:onComplete(function()
        giveCraftedItem()
        exports.LastMenu:notify(function(n) n:message("Welding completed!") n:type("success") end)
    end)
    p:onCancel(function()
        exports.LastMenu:notify(function(n) n:message("Welding cancelled.") n:type("warning") end)
    end)
end)

Behavior

  • While a bar is open, it owns the stack — no other menu can open.
  • Utilise cancel(false) pour les actions obligatoires (craft, interactions). Utilise cancel(true) pour les tâches interruptibles.
  • La fermeture programmatique via bar.close() ne déclenche ni onComplete ni onCancel.
  • Les side effects anim et prop sont nettoyés automatiquement, quelle que soit la façon dont la barre se ferme.