452 lines
13 KiB
Markdown
452 lines
13 KiB
Markdown
|
# rprogress
|
||
|
Customisable radial progress bars for FiveM.
|
||
|
|
||
|
## Table of contents
|
||
|
* [Demo Videos](#demo-videos)
|
||
|
* [Requirements](#requirements)
|
||
|
* [Download & Installation](#download--installation)
|
||
|
* [Configuration](#configuration)
|
||
|
* [Upgrading](#upgrading)
|
||
|
* [Client Functions](#client-functions)
|
||
|
* [Scenarios and Animations](#scenarios-and-animations)
|
||
|
* [MiniGame](#minigame)
|
||
|
* [Sync vs Async](#sync-vs-async)
|
||
|
* [Static Progress Dials](#static-progress-dials)
|
||
|
* [Partial Progress Dials](#partial-progress-dials)
|
||
|
* [Pie Progress](#pie-progress)
|
||
|
* [Demo Commands](#demo-commands)
|
||
|
* [Contributing](#contributing)
|
||
|
* [To Do](#to-do)
|
||
|
|
||
|
## Demo Videos
|
||
|
* [Default](https://streamable.com/85j3gt)
|
||
|
* [Custom MaxAngle and Rotation](https://streamable.com/i6lhxx)
|
||
|
* [Animations](https://streamable.com/23r6jg)
|
||
|
* [Without Timer](https://streamable.com/d7qil2)
|
||
|
* [Demo with esx_doorlock](https://streamable.com/94b0ph)
|
||
|
* [Custom Label Position](https://streamable.com/4mqwgx)
|
||
|
* [Static Progress Dial](https://streamable.com/uzbfsd)
|
||
|
* [Mini Game](https://streamable.com/azhzhz)
|
||
|
|
||
|
## Requirements
|
||
|
|
||
|
* None!
|
||
|
|
||
|
## Download & Installation
|
||
|
|
||
|
* Download and extract the package: https://github.com/Mobius1/rprogress/archive/master.zip
|
||
|
* Drop the `rprogress-master` directory into you `resources` directory
|
||
|
* Rename the directory from `rprogress-master` to `rprogress`
|
||
|
* Add `ensure rprogress` in your `server.cfg`
|
||
|
* Edit `config.lua` to your liking
|
||
|
* Start your server and rejoice!
|
||
|
|
||
|
## Configuration
|
||
|
|
||
|
```lua
|
||
|
Config.Async = true -- Whether to run the progress dial asyncronously
|
||
|
|
||
|
Config.From = 0 -- Starting progress percentage
|
||
|
Config.To = 100 -- Ending progress percentage
|
||
|
|
||
|
Config.Duration = 5000 -- Duration of the progress
|
||
|
Config.Label = "Loading..." -- Text shown with the dial
|
||
|
Config.LabelPosition = "bottom"
|
||
|
|
||
|
Config.Color = "rgba(255, 255, 255, 1.0)" -- Progress dial colour
|
||
|
Config.BGColor = "rgba(0, 0, 0, 0.4)" -- Progress background colour
|
||
|
Config.ZoneColor = "rgba(51, 105, 30, 1)" -- Minigame Zone colour
|
||
|
|
||
|
Config.x = 0.5 -- Horizontal position
|
||
|
Config.y = 0.5 -- Vertical position
|
||
|
|
||
|
Config.Rotation = 0 -- Rotation angle of dial
|
||
|
Config.MaxAngle = 360 -- Max arc in degrees - 360 will be a full circle, 90 will be a quarter of a circle, etc
|
||
|
Config.Radius = 60 -- Radius of the radial dial
|
||
|
Config.Stroke = 10 -- stroke width of the radial dial
|
||
|
Config.Width = 300 -- Width of the linear bar
|
||
|
Config.Height = 40 -- Height of the linear bar
|
||
|
Config.Cap = 'butt' -- or 'round'
|
||
|
Config.Padding = 0 -- Background bar padding
|
||
|
Config.CancelKey = 178 -- Key used for cancelling progress
|
||
|
|
||
|
Config.ShowTimer = true -- Shows the timer countdown within the radial dial
|
||
|
Config.ShowProgress = false -- Shows the progress within the radial dial
|
||
|
|
||
|
Config.Easing = "easeLinear" -- The easing used for the dial animation - see "rprogress/ui/js/easings.js"
|
||
|
|
||
|
Config.DisableControls = {
|
||
|
Mouse = false, -- Disable mouse controls until progress is complete
|
||
|
Player = false, -- Disable player movement until progress is complete
|
||
|
Vehicle = false -- Disable vehicle control until progress is complete
|
||
|
}
|
||
|
```
|
||
|
NOTE: `Config.Position` is based on screen size so setting `Config.Position.x = 0.5` will be the center of the screen, `Config.Position.x = 1.0` with be right-side of the screen, `Config.Position.x = 0.0` will be the left-side of the screen, etc.
|
||
|
|
||
|
## Upgrading
|
||
|
|
||
|
#### Upgrading to v0.6.0
|
||
|
Replace all instances of `exports.rprogress:NewStaticProgress` with `exports.rprogress:Static`
|
||
|
|
||
|
## Client Functions
|
||
|
|
||
|
NOTE: DO NOT run these in a loop
|
||
|
|
||
|
Available exports:
|
||
|
|
||
|
```lua
|
||
|
-- starts the progress dial for the defined duration
|
||
|
-- This runs in sync so any code after this call won't be run until the progress is complete
|
||
|
exports.rprogress:Start(text, duration)
|
||
|
|
||
|
-- stops the progress dial early
|
||
|
exports.rprogress:Stop()
|
||
|
|
||
|
-- Display a custom progress dial by overriding config.lua values
|
||
|
exports.rprogress:Custom(options)
|
||
|
|
||
|
-- Create a static progress dial
|
||
|
exports.rprogress:Static(options)
|
||
|
|
||
|
-- Create a linear progress bar
|
||
|
exports.rprogress:Linear(text, duration)
|
||
|
|
||
|
-- or
|
||
|
|
||
|
exports.rprogress:Custom({
|
||
|
Type = 'linear'
|
||
|
Duration = 3000,
|
||
|
Width = 400,
|
||
|
Height = 50,
|
||
|
y = 0.75
|
||
|
})
|
||
|
```
|
||
|
|
||
|
##### Display a progress dial with text for set duration
|
||
|
|
||
|
```lua
|
||
|
exports.rprogress:Start(text, duration)
|
||
|
```
|
||
|
|
||
|
##### Stop the progress dial early
|
||
|
```lua
|
||
|
exports.rprogress:Stop()
|
||
|
```
|
||
|
|
||
|
##### Create a custom progress instance
|
||
|
```lua
|
||
|
exports.rprogress:Custom({
|
||
|
Async = true,
|
||
|
canCancel = true, -- Allow cancelling
|
||
|
cancelKey = 178, -- Custom cancel key
|
||
|
x = 0.5, -- Position on x-axis
|
||
|
y = 0.5, -- Position on y-axis
|
||
|
From = 0, -- Percentage to start from
|
||
|
To = 100, -- Percentage to end
|
||
|
Duration = 1000, -- Duration of the progress
|
||
|
Radius = 60, -- Radius of the dial
|
||
|
Stroke = 10, -- Thickness of the progress dial
|
||
|
Cap = 'butt', -- or 'round'
|
||
|
Padding = 0, -- Padding between the progress dial and the background dial
|
||
|
MaxAngle = 360, -- Maximum sweep angle of the dial in degrees
|
||
|
Rotation = 0, -- 2D rotation of the dial in degrees
|
||
|
Width = 300, -- Width of bar in px if Type = 'linear'
|
||
|
Height = 40, -- Height of bar in px if Type = 'linear'
|
||
|
ShowTimer = true, -- Shows the timer countdown within the radial dial
|
||
|
ShowProgress = false, -- Shows the progress % within the radial dial
|
||
|
Easing = "easeLinear",
|
||
|
Label = "My Custom Label",
|
||
|
LabelPosition = "right",
|
||
|
Color = "rgba(255, 255, 255, 1.0)",
|
||
|
BGColor = "rgba(0, 0, 0, 0.4)",
|
||
|
ZoneColor = "rgba(51, 105, 30, 1)",
|
||
|
Animation = {
|
||
|
scenario = "WORLD_HUMAN_AA_SMOKE", -- https://pastebin.com/6mrYTdQv
|
||
|
animationDictionary = "missheistfbisetup1", -- https://alexguirre.github.io/animations-list/
|
||
|
animationName = "unlock_loop_janitor",
|
||
|
},
|
||
|
DisableControls = {
|
||
|
Mouse = true,
|
||
|
Player = true,
|
||
|
Vehicle = true
|
||
|
},
|
||
|
onStart = function()
|
||
|
-- do something when progress starts
|
||
|
end,
|
||
|
onComplete = function(cancelled)
|
||
|
-- cancelled: boolean - whether player cancelled the progress
|
||
|
|
||
|
-- do something when progress is complete
|
||
|
end
|
||
|
})
|
||
|
```
|
||
|
|
||
|
## Scenarios and Animations
|
||
|
`rprogress` allows you to run a scenario or play an animation while the progress dial is running.
|
||
|
|
||
|
If you want to run a scenario, then provide the `Animation` table with the `scenario` key.
|
||
|
|
||
|
```lua
|
||
|
exports.rprogress:Custom({
|
||
|
Animation = {
|
||
|
scenario = "WORLD_HUMAN_AA_SMOKE"
|
||
|
}
|
||
|
})
|
||
|
```
|
||
|
|
||
|
You can find a list of scenarios [here](https://pastebin.com/6mrYTdQv)
|
||
|
|
||
|
If you want to play an animation, then provide the `Animation` table with the required `animationDictionary` and `animationName` keys. You can also provide the optional `flag` key (see [`TaskPlayAnim`](https://wiki.rage.mp/index.php?title=Player::taskPlayAnim)).
|
||
|
```lua
|
||
|
exports.rprogress:Custom({
|
||
|
Animation = {
|
||
|
animationDictionary = "missheistfbisetup1",
|
||
|
animationName = "unlock_loop_janitor",
|
||
|
flag = 1, -- optional
|
||
|
}
|
||
|
})
|
||
|
```
|
||
|
|
||
|
You can find a list of animation dictionaries / names [here](https://alexguirre.github.io/animations-list/).
|
||
|
|
||
|
If `scenario` is set as well as `animationDictionary` and `animationName`, then the `scenario` will take priority.
|
||
|
|
||
|
## MiniGame
|
||
|
`rProgress` can be set up to allow a minigame to test player reflexes by utilising the `MiniGame()` method.
|
||
|
|
||
|
The progress bar will flip back and forth and display a trigger zone for the player to hit the `SpaceBar` when the progress bar is within it.
|
||
|
|
||
|
As with the `Custom()` method, you can pass a variety of options. The `onComplete` callback will return the `success` parameter to indicate whether the player was successful or not.
|
||
|
|
||
|
```lua
|
||
|
exports.rprogress:MiniGame({
|
||
|
Difficulty = "Easy",
|
||
|
Timeout = 5000, -- Duration before minigame is cancelled
|
||
|
onComplete = function(success)
|
||
|
if success then
|
||
|
-- Player was successful
|
||
|
else
|
||
|
-- Player was unsuccessful
|
||
|
end
|
||
|
end,
|
||
|
onTimeout = function()
|
||
|
-- Player took too long to respond
|
||
|
end
|
||
|
})
|
||
|
```
|
||
|
|
||
|
You can define the defficulties in the `config.lua` file:
|
||
|
```lua
|
||
|
Config.MiniGameOptions = {
|
||
|
MaxAngle = 240,
|
||
|
Rotation = -120,
|
||
|
Difficulty = {
|
||
|
Easy = {
|
||
|
Zone = 40,
|
||
|
Duration = 500
|
||
|
},
|
||
|
Medium = {
|
||
|
Zone = 25,
|
||
|
Duration = 450
|
||
|
},
|
||
|
Hard = {
|
||
|
Zone = 20,
|
||
|
Duration = 400
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
```
|
||
|
|
||
|
To add you own difficulty you can define it in the `Config.MiniGameOptions.Difficulty` table and add the `Zone` and `Duration` values:
|
||
|
|
||
|
```lua
|
||
|
Config.MiniGameOptions = {
|
||
|
MaxAngle = 240,
|
||
|
Rotation = -120,
|
||
|
Difficulty = {
|
||
|
Custom = {
|
||
|
Zone = 40, -- The percentage of the dial that is the trigger zone (lower = harder)
|
||
|
Duration = 1000 -- Time in milliseconds for the dial to fill in one direction (lower = harder)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
```
|
||
|
|
||
|
Then use it in the `MiniGame()` method:
|
||
|
|
||
|
```lua
|
||
|
exports.rprogress:MiniGame({
|
||
|
Difficulty = "Custom",
|
||
|
onComplete = function(success)
|
||
|
|
||
|
end
|
||
|
})
|
||
|
```
|
||
|
|
||
|
You can also pass the `Zone` and `Duration` values instead of `Difficulty` for on-the-fly difficulty settings:
|
||
|
|
||
|
```lua
|
||
|
exports.rprogress:MiniGame({
|
||
|
Zone = 40,
|
||
|
Duration = 750,
|
||
|
onComplete = function(success)
|
||
|
|
||
|
end
|
||
|
})
|
||
|
```
|
||
|
|
||
|
## Sync vs Async
|
||
|
|
||
|
The `Start()` method runs in sync so any code after the call to the method won't be run until the progress is complete. If you want a progress dial to run asyncronously, you can use the `Custom()` method with `Async` set to `true` and utilise the `onStart` and `onComplete` callbacks.
|
||
|
|
||
|
##### Async
|
||
|
```lua
|
||
|
print("before")
|
||
|
|
||
|
exports.rprogress:Custom({
|
||
|
Async = true,
|
||
|
Duration = 3000,
|
||
|
onStart = function()
|
||
|
print("start")
|
||
|
end
|
||
|
onComplete = function()
|
||
|
print("complete")
|
||
|
end
|
||
|
})
|
||
|
|
||
|
print("after")
|
||
|
```
|
||
|
|
||
|
##### Output
|
||
|
```lua
|
||
|
before
|
||
|
after
|
||
|
start
|
||
|
complete
|
||
|
```
|
||
|
|
||
|
##### Sync
|
||
|
```lua
|
||
|
print("before")
|
||
|
|
||
|
exports.rprogress:Custom({
|
||
|
Async = false,
|
||
|
Duration = 3000,
|
||
|
onStart = function()
|
||
|
print("start")
|
||
|
end
|
||
|
onComplete = function()
|
||
|
print("complete")
|
||
|
end
|
||
|
})
|
||
|
|
||
|
print("after")
|
||
|
```
|
||
|
|
||
|
###### Output
|
||
|
```lua
|
||
|
before
|
||
|
start
|
||
|
complete
|
||
|
after
|
||
|
```
|
||
|
|
||
|
## Static Progress Dials
|
||
|
|
||
|
If you don't just want a progress dial that fills automatically, you can create a static one and update it as required.
|
||
|
|
||
|
[Demo Video](https://streamable.com/uzbfsd)
|
||
|
|
||
|
```lua
|
||
|
-- Create new static progress dial
|
||
|
local staticDial = exports.rprogress:Static(options)
|
||
|
|
||
|
-- Show the progress dial
|
||
|
staticDial.Show()
|
||
|
|
||
|
-- Update the progress of the dial (0-100)
|
||
|
staticDial.SetProgress(progress)
|
||
|
|
||
|
-- Hide the progress dial
|
||
|
staticDial.Hide()
|
||
|
|
||
|
-- Destroy the dial (set as no longer needed)
|
||
|
staticDial.Destroy()
|
||
|
```
|
||
|
|
||
|
## Partial Progress Dials
|
||
|
|
||
|
To create a partial progress dial set the `maxAngle` property to the desired value:
|
||
|
```lua
|
||
|
exports.rprogress:Custom({
|
||
|
maxAngle: 240
|
||
|
})
|
||
|
```
|
||
|
#### Result
|
||
|

|
||
|
|
||
|
You can also set `rotation` property to the desired value:
|
||
|
```lua
|
||
|
exports.rprogress:Custom({
|
||
|
maxAngle: 240,
|
||
|
rotation: -120
|
||
|
})
|
||
|
```
|
||
|
|
||
|
#### Result
|
||
|

|
||
|
|
||
|
## Pie Progress
|
||
|
Setting the `radius` and `stroke` properties to equal values will produce a pie chart type progress:
|
||
|
```lua
|
||
|
exports.rprogress:Custom({
|
||
|
Radius: 60,
|
||
|
Stroke: 60
|
||
|
})
|
||
|
```
|
||
|
|
||
|
#### Result
|
||
|

|
||
|
|
||
|
## Demo Commands
|
||
|
|
||
|
```lua
|
||
|
/rprogressStart [text] [duration]
|
||
|
/rprogressCustom [from] [to] [duration] [radius] [stroke] [MaxAngle] [rotation] [padding] [cap]
|
||
|
/rprogressMiniGame [difficulty]
|
||
|
/rprogressSync [duration]
|
||
|
/rprogressAsync [duration]
|
||
|
/rprogressStatic
|
||
|
/rprogressEasing [functionName] [duration]
|
||
|
/rprogressAnimation [animDictionary] [animName] [duration]
|
||
|
/rprogressScenario [scenarioName] [duration]
|
||
|
```
|
||
|
|
||
|
You can delete the `demo.lua` file and remove it's entry from `fxmanifest.lua` if these are not required.
|
||
|
|
||
|
## Contributing
|
||
|
Pull requests welcome.
|
||
|
|
||
|
|
||
|
## Legal
|
||
|
|
||
|
### License
|
||
|
|
||
|
```
|
||
|
rprogress - Customisable radial progress dials for FiveM.
|
||
|
|
||
|
Copyright (C) 2020 Karl Saunders
|
||
|
|
||
|
This program is free software: you can redistribute it and/or modify
|
||
|
it under the terms of the GNU General Public License as published by
|
||
|
the Free Software Foundation, either version 3 of the License, or
|
||
|
(at your option) any later version.
|
||
|
|
||
|
This program is distributed in the hope that it will be useful,
|
||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
GNU General Public License for more details.
|
||
|
|
||
|
You should have received a copy of the GNU General Public License
|
||
|
along with this program. If not, see <https://www.gnu.org/licenses/>
|
||
|
```
|