mirror of
https://github.com/CommunityOx/ox_lib.git
synced 2026-08-17 15:06:02 +01:00
Some people accidentally, mistakenly, and without any malicious intent forget to attribute code from this resource to its source. This change will hopefully assist people, so that they do not make that mistake again.
152 lines
4.3 KiB
Lua
152 lines
4.3 KiB
Lua
--[[
|
|
https://github.com/overextended/ox_lib
|
|
|
|
This file is licensed under LGPL-3.0 or higher <https://www.gnu.org/licenses/lgpl-3.0.en.html>
|
|
|
|
Copyright (c) 2025 Linden <https://github.com/thelindat/fivem>
|
|
]]
|
|
|
|
---@class TimerPrivateProps
|
|
---@field initialTime number the initial duration of the timer.
|
|
---@field async? boolean wether the timer should run asynchronously or not
|
|
---@field startTime number the gametimer stamp of when the timer starts. changes when paused and played
|
|
---@field triggerOnEnd boolean set in the forceEnd method using the optional param. wether or not the onEnd function is triggered when force ending the timer early
|
|
---@field currentTimeLeft number current timer length
|
|
---@field paused boolean the pause state of the timer
|
|
|
|
---@class OxTimer : OxClass
|
|
---@field private private TimerPrivateProps
|
|
---@field start fun(self: self, async?: boolean) starts the timer
|
|
---@field onEnd? fun() cb function triggered when the timer finishes
|
|
---@field forceEnd fun(self: self, triggerOnEnd: boolean) end timer early and optionally trigger the onEnd function still
|
|
---@field isPaused fun(self: self): boolean returns wether the timer is paused or not
|
|
---@field pause fun(self: self) pauses the timer until play method is called
|
|
---@field play fun(self: self) resumes the timer if paused
|
|
---@field getTimeLeft fun(self: self, format?: 'ms' | 's' | 'm' | 'h'): number | table returns the time left on the timer with the specified format rounded to 2 decimal places (miliseconds, seconds, minutes, hours). returns a table of all if not specified.
|
|
local timer = lib.class('OxTimer')
|
|
|
|
---@private
|
|
---@param time number
|
|
---@param onEnd fun(self: OxTimer)
|
|
---@param async? boolean
|
|
function timer:constructor(time, onEnd, async)
|
|
assert(type(time) == "number" and time > 0, "Time must be a positive number")
|
|
assert(onEnd == nil or type(onEnd) == "function", "onEnd must be a function or nil")
|
|
assert(type(async) == "boolean" or async == nil, "async must be a boolean or nil")
|
|
|
|
self.onEnd = onEnd
|
|
self.private.initialTime = time
|
|
self.private.currentTimeLeft = time
|
|
self.private.startTime = 0
|
|
self.private.paused = false
|
|
self.private.triggerOnEnd = true
|
|
|
|
self:start(async)
|
|
end
|
|
|
|
---@protected
|
|
function timer:run()
|
|
while self:isPaused() or self:getTimeLeft('ms') > 0 do
|
|
Wait(0)
|
|
end
|
|
|
|
if self.private.triggerOnEnd then
|
|
self:onEnd()
|
|
end
|
|
|
|
self.private.triggerOnEnd = true
|
|
end
|
|
|
|
function timer:start(async)
|
|
if self.private.startTime > 0 then error('Cannot start a timer that is already running') end
|
|
|
|
self.private.startTime = GetGameTimer()
|
|
|
|
if not async then return self:run() end
|
|
|
|
Citizen.CreateThreadNow(function()
|
|
self:run()
|
|
end)
|
|
end
|
|
|
|
function timer:forceEnd(triggerOnEnd)
|
|
if self:getTimeLeft('ms') <= 0 then return end
|
|
|
|
self.private.paused = false
|
|
self.private.currentTimeLeft = 0
|
|
self.private.triggerOnEnd = triggerOnEnd
|
|
|
|
Wait(0)
|
|
end
|
|
|
|
function timer:pause()
|
|
if self.private.paused then return end
|
|
|
|
self.private.currentTimeLeft = self:getTimeLeft('ms') --[[@as number]]
|
|
self.private.paused = true
|
|
end
|
|
|
|
function timer:play()
|
|
if not self.private.paused then return end
|
|
self.private.startTime = GetGameTimer()
|
|
self.private.paused = false
|
|
end
|
|
|
|
function timer:isPaused()
|
|
return self.private.paused
|
|
end
|
|
|
|
function timer:restart(async)
|
|
self:forceEnd(false)
|
|
Wait(0)
|
|
self.private.currentTimeLeft = self.private.initialTime
|
|
self.private.startTime = 0
|
|
self:start(async)
|
|
end
|
|
|
|
function timer:getTimeLeft(format)
|
|
local ms = self.private.currentTimeLeft - (GetGameTimer() - self.private.startTime)
|
|
|
|
local roundedfloat = function(value)
|
|
return tonumber(string.format('%.2f', value))
|
|
end
|
|
|
|
if format == 'ms' then
|
|
return roundedfloat(ms)
|
|
end
|
|
|
|
local s = ms / 1000
|
|
|
|
if format == 's' then
|
|
return roundedfloat(s)
|
|
end
|
|
|
|
local m = s / 60
|
|
|
|
if format == 'm' then
|
|
return roundedfloat(m)
|
|
end
|
|
|
|
local h = m / 60
|
|
|
|
if format == 'h' then
|
|
return roundedfloat(h)
|
|
end
|
|
|
|
return {
|
|
ms = roundedfloat(ms),
|
|
s = roundedfloat(s),
|
|
m = roundedfloat(m),
|
|
h = roundedfloat(h)
|
|
}
|
|
end
|
|
|
|
---@param time number
|
|
---@param onEnd fun(self: OxTimer)
|
|
---@param async? boolean
|
|
function lib.timer(time, onEnd, async)
|
|
return timer:new(time, onEnd, async)
|
|
end
|
|
|
|
return lib.timer
|