TombEngine/Scripts/Timer.lua
2022-08-01 20:41:06 +01:00

190 lines
5.6 KiB
Lua

-----
--- Basic timer - after a specified number of seconds, the specified thing happens.
-- Usage:
-- local Timer = require("Timer")
--
-- LevelFuncs.FinishTimer = function(healthWhenStarted, victoryMessage)
-- DoSomething(healthWhenStarted, victoryMessage)
-- end
--
-- LevelFuncs.TriggerTimer = function(obj)
-- local myTimer = Timer.Create("my_timer", 5.0, false, true, "FinishTimer", Lara:GetHP(), "Well done!")
-- myTimer:Start()
-- end
--
-- LevelFuncs.OnControlPhase = function(dt)
-- Timer.UpdateAll(dt)
-- end
--
-- @luautil Timer
LevelVars.__TEN_timer = {timers = {}}
local Timer
local unpausedColor = Color(255, 255, 255)
local pausedColor = Color(255, 255, 0)
local str = TEN.Strings.DisplayString("TIMER", 0, 0, unpausedColor, false, {TEN.Strings.DisplayStringOption.CENTER, TEN.Strings.DisplayStringOption.SHADOW} )
Timer = {
--- Create (but do not start) a new timer.
-- @string name A label to give this timer; used to retrieve the timer later
-- @number totalTime The duration of the timer, in seconds
-- @bool loop if true, the timer will start again immediately after the time has elapsed
-- @bool showString if true, the remaining time, rounded up, will show at the bottom of the screen. __At any given time, only one timer can show its remaining time__.
-- @string func The name of the LevelFunc member to call when the time is up
-- @param funcArgs the arguments with which the above function will be called
-- @return The timer in its paused state
Create = function(name, totalTime, loop, showString, func, ...)
local obj = {}
local mt = {}
mt.__index = Timer
setmetatable(obj, mt)
obj.name = name
LevelVars.__TEN_timer.timers[name] ={}
local thisTimer = LevelVars.__TEN_timer.timers[name]
thisTimer.name = name
thisTimer.showString = showString
thisTimer.totalTime = totalTime
thisTimer.remainingTime = totalTime
thisTimer.func = func
thisTimer.funcArgs = {...}
thisTimer.loop = loop
thisTimer.active = false
thisTimer.paused = true
return obj
end;
--- Get a timer by its name.
-- @string name The label that was given to the timer when it was created
-- @return The timer
Get = function(name)
if LevelVars.__TEN_timer.timers[name] then
local obj = {}
local mt = {}
mt.__index = Timer
setmetatable(obj, mt)
obj.name = name
return obj
end
return nil
end,
--- Give the timer a new function and args
-- @param t the timer in question
-- @string func The name of the LevelFunc member to call when the time is up
-- @param funcArgs the arguments with which the above function will be called
SetFunction = function(t, func, ...)
local thisTimer = LevelVars.__TEN_timer.timers[t.name]
thisTimer.func = func
thisTimer.funcArgs = {...}
end,
--- Begin or unpause a timer. If showing the remaining time on-screen, its color will be set to white.
-- @param t the timer in question
Start = function(t)
local thisTimer = LevelVars.__TEN_timer.timers[t.name]
if not thisTimer.active then
thisTimer.active = true
end
LevelVars.__TEN_timer.timers[t.name].paused = false
if thisTimer.showString then
str:SetColor(unpausedColor)
end
end;
--- Pause the timer. If showing the remaining time on-screen, its color will be set to yellow.
-- @param t the timer in question
Pause = function(t)
local thisTimer = LevelVars.__TEN_timer.timers[t.name]
thisTimer.paused = true
if thisTimer.showString then
str:SetColor(pausedColor)
end
end,
--- Stop the timer.
-- @param t the timer in question
Stop = function(t)
LevelVars.__TEN_timer.timers[t.name].active = false
end,
--- Get the remaining time for a timer.
-- @param t the timer in question
-- @return the time in seconds remaining on the clock
GetRemainingTime = function(t)
return LevelVars.__TEN_timer.timers[t.name].remainingTime
end,
--- Set the remaining time for a timer
-- @param t the timer in question
-- @number remainingTime the new time remaining for the timer
SetRemainingTime = function(t, remainingTime)
LevelVars.__TEN_timer.timers[t.name].remainingTime = remainingTime
end,
--- Get the total time for a timer.
-- This is the amount of time the timer will start with, as well as when starting a new loop
-- @param t the timer in question
-- @return the timer's total time
GetTotalTime = function(t)
return LevelVars.__TEN_timer.timers[t.name].totalTime
end,
--- Set the total time for a timer
-- @param t the timer in question
-- @number totalTime timer's new total time
SetTotalTime = function(t, totalTime)
LevelVars.__TEN_timer.timers[t.name].totalTime = totalTime
end,
--- Set whether or not the timer loops
-- @param t the timer in question
-- @bool looping whether or not the timer loops
SetLooping = function(t, looping)
LevelVars.__TEN_timer.timers[t.name].loop = looping
end,
--- Update all active timers.
-- Should be called in LevelFuncs.OnControlPhase
-- @number dt The time in seconds since the last frame
UpdateAll = function(dt)
for _, t in pairs(LevelVars.__TEN_timer.timers) do
Timer.Update(t, dt)
end
end;
Update = function(t, dt)
if t.active then
if not t.paused then
t.remainingTime = t.remainingTime - dt
if t.remainingTime <= 0 then
LevelFuncs[t.func](table.unpack(t.funcArgs))
if not t.loop then
t.active = false
else
t.remainingTime = t.remainingTime + t.totalTime
end
end
end
if t.showString then
TEN.Strings.HideString(str)
str:SetKey(tostring(math.ceil(t.remainingTime)))
local myX, myY = PercentToScreen(50, 90)
str:SetPosition(myX, myY)
TEN.Strings.ShowString(str, 1)
end
end
end;
}
return Timer