A flexible, progress bar system for FiveM.
Supports animations, props, stages/minigames, cancel/death monitoring, networked props with blacklist protection, and more.
- Multi-stage progress with optional skill-check / minigame support
- Animation helper with synchronized scenes and entity attachments
- Automatic cleanup server and client side
- Prop support: multiple props per action
- Customizable cancel button
- Animation hooks
- Themes
Clone or download this repository into your FiveM resources folder.
If using QBCore, move/delete the progressbar resource from your [standalone] and place keep-progressbar in [standalone]
resources/[standalone]/keep-progressbarIf using ESX, move/delete the esx_progressbar resource from your [core] and place keep-progressbar in [core]
resources/[core]/keep-progressbarTo integrate progress bars made for ox_lib:
-
First open:
ox_lib/resource/interface/progress.lua -
Make a backup of the file.
-
Delete all contents, then replace them with:
function lib.progressBar(data) return exports['keep-progressbar']:ox_lib_progressBar(data) end function lib.progressCircle(data) return exports['keep-progressbar']:ox_lib_progressBar(data) end function lib.cancelProgress() exports['keep-progressbar']:ox_lib_cancelProgress() end function lib.progressActive() exports['keep-progressbar']:ox_lib_progressActive() end
-
Ensure it's loading before ox_lib and it's placed at
[standalont].resources/[standalone]/keep-progressbar
ensure keep-progressbar ensure ox_lib
exports['keep-progressbar']:Start({ duration = 5000, label = "Loading Crate", icon = "fa-solid fa-box", canCancel = true, useWhileDead = false, controlDisables = { disableMovement = true, disableCombat = true, }, animation = { animDict = "anim@heists@box_crate@load", anim = "load_box", duration = 5000, lockX = true, lockY = false, lockZ = true, }, prop = { model = "prop_crate_01a", bone = 28422, coords = vec3(0.0, 0.0, 0.0), rotation = vec3(0.0, 0.0, 0.0), } }, function(cancelled) if not cancelled then print("✅ completed") else print("❌ Cancelled.") end end)exports['keep-progressbar']:Start({ label = "Opening Crate", icon = "fa-solid fa-box-open", animation = { task = "WORLD_HUMAN_CLIPBOARD" }, canCancel = true, controlDisables = { disableMovement = true, disableCombat = true }, stages = { { message = "Breaking lock...", duration = 3000 }, { message = "Opening door...", duration = 2000 }, }, props = { { model = "prop_ld_case_01", bone = 57005, coords = vec3(0, 0, 0), rotation = vec3(0, 0, 0), }, } }, function(cancel, result) if not cancel then print("✅ Crate opened!") else print("❌ Aborted opening crate.") end end)I’ve provided a bunch of examples for different features in lua/examples.lua
| Key | Type | Description |
|---|---|---|
duration | number(ms) | Total duration if no stages are used |
label | string | Title of progress window |
icon | string | Icon (FontAwesome) |
useWhileDead | boolean | Allow while dead |
canCancel | boolean | Whether player can progress cancel or not |
controlDisables | table | e.g. { disableMovement=true, disableCarMovement=true, disableMouse=false, disableCombat=true } |
theme | string | Optional theme name |
position | string | UI position (e.g. center-top) |
offset | vec3 | Progress bar offset |
prop | table | Single prop attached during progress |
propTwo | table | Single prop attached during progress |
props | table[] | Array of props |
animation | table | Single animation |
animations | table[] | Array of animations |
stages | table[] | Array of stages |
Prop, PropTwo, Props:
| Field | Type | Description |
|---|---|---|
model | string | Model name |
bone | number | Bone index |
coords | vector3 | Offset coordinates |
rotation | vector3 | Rotation |
prop = { model = "prop_police_phone", bone = 28422, coords = vector3(0.00, 0.0, 0.0), rotation = vector3(0.0, 0.0, 0.0), }, propTwo = { model = "prop_police_phone", bone = 28422, coords = vector3(0.00, 0.0, 0.0), rotation = vector3(0.0, 0.0, 0.0), },Or simply using an array
props = { { model = "prop_police_phone", bone = 28422, coords = vector3(0.00, 0.0, 0.0), rotation = vector3(0.0, 0.0, 0.0), } }Animation:
| Field | Type | Description |
|---|---|---|
animDict | string | Animation dictionary |
anim | string | Animation name |
flags | number | Animation flags |
duration | number | Duration in ms |
blendIn | number | Blend-in speed |
blendOut | number | Blend-out speed |
onStart | func | Called at start |
onTick | func | Called during, with frame time |
onFinish | func | Called after |
Single animation
animation = { animDict = "anim@heists@humane_labs@emp@hack_door", anim = "hack_loop", },Array of animations
animations = { { animDict = "anim@heists@humane_labs@emp@hack_door", anim = "hack_intro", flags = 1, duration = 2500, blendIn = 3.0, blendOut = 3.0, }, { animDict = "anim@heists@humane_labs@emp@hack_door", anim = "hack_loop", flags = 1, duration = 3000, blendIn = 3.0, blendOut = 3.0, }, { animDict = "anim@heists@humane_labs@emp@hack_door", anim = "hack_outro", flags = 1, duration = 2000, blendIn = 3.0, blendOut = 3.0, } }, Each stage is a table inside stages array.
| Field | Type | Description |
|---|---|---|
message | string | Stage text shown to player |
duration | number | Stage duration (ms) |
progressColor | string | Optional color |
animation | table | Stage specific animation |
minigame | func | Returns boolean or result |
cancelMode | boolean | Changes how minigame works: hard = reset/close on fail, soft = continue on fail |
onFinish | func | Called when stage completes |
condition | func | Must return true before stage proceeds |
stages = { { message = "Breaking lock...", duration = 1000 }, { message = "Opening door...", duration = 2000, condition = function() return trigger_condition end, minigame = function() return lib .skillCheck({ 'easy', 'easy' }, { 'w', 'a', 's', 'd' }) end, animation = { animDict = "anim@heists@humane_labs@emp@hack_door", anim = "hack_intro", flags = 1, duration = 2500, blendIn = 3.0, blendOut = 3.0, } }, { message = "Opening door...", duration = 2000 }, }, | Parameter | Type | Description |
|---|---|---|
cancelled | bool | Whether progress was cancelled |
result | any | Skill check outcome |
exports['keep-progressbar']:Start({ ... }, function(cancelled, result) end)