I was disappointed we didn't have timers for timed events in this beta (1.005) like in old FPSC (remember [e]timerstart?) and thought a bit about that and then I remembered that each operating system has system clock that is available in most programming languages via operating system API and LUA was not an exception, we do have
date and time functions in LUA.
So I created this very simple LUA class that can work as regular and countdown timer. The idea is to remember system time when our timer is started [
started = os.time()] and then we can always check how much time has passed since the timer is started by simply subtracting our remembered value from current system time [
passed = os.time() - started]. So this is using system clock and doesn't depend on your FPS (it's independent from the game). It is precise to a second (can not check milliseconds for example) but that should be enough for most games.
Here it is in action (as a countdown timer):
The code for this video (actually only for the plant on the table; plant.lua):
-- include aTimer
require "scriptbank/Avram/aTimer.lua"
-- helper function to get player distance from entity
function PlrDist(e)
local PlayerDX = g_Entity[e]['x'] - g_PlayerPosX
local PlayerDY = g_Entity[e]['y'] - g_PlayerPosY
local PlayerDZ = g_Entity[e]['z'] - g_PlayerPosZ
return math.sqrt(math.abs(PlayerDX*PlayerDX)+math.abs(PlayerDY*PlayerDY)+math.abs(PlayerDZ*PlayerDZ))
end
-- main entity function
function plant_main(e)
-- get existing or create new timer for this entity
aTimers[e] = aTimers[e] or aTimer:new(10)
-- for easier access...
local myTimer = aTimers[e]
-- start timer if the player is near and if the timer is not already started
if PlrDist(e) < 80 and not myTimer:running() then
myTimer:start()
end
-- if the timer is running (is started, and for the first time) countdown or KABOOOM!
if myTimer:running() and myTimer.cnt == 1 then
if myTimer:expired() then
Prompt("KABOOOM!")
else
Prompt("tick, tick ... " .. myTimer:left())
end
end
-- wait 5 seconds prior to stopping timer (and hiding text)
if (myTimer:passed() > myTimer.countdown+5) then
myTimer:stop()
end
end
The key fact to remember here is that our *_main function can be called by engine numerous times per second, so it is very important to check when we are creating timer object or (re)starting/stopping the timer. Also, the timer object must be global (out of function scope) as it needs to preserve it's state between multiple calls to *_main. That's why I have introduced global
aTimers array (actually in LUA it's a table). You can use it however you want, but since we already have entity index
e, I thought it would be easy to use just
aTimers[e], but that's cool for one timer per entity. If you need more, figure something out (aTimers['my_custom_timer']). With this first line:
aTimers[e] = aTimers[e] or aTimer:new(10) we are telling the engine to give us current entity timer or to create new countdown timer (from 10). So the first time our *_main function is called, the timer will be created. Each subsequent call will give us existing timer for this entity. Woohoo!
DOCS:
-----------------------------------------------------
aTimer:new(countdown, autostart)
Desc: Class constructor used to initialize the timer.
Arguments:
number countdown - [optional] Number to countdown from. Use as a countdown timer if greater than 0; default: 0
boolean autostart - [optional] Should start automatically (true/false); default: false
Returns:
aTimer object of class aTimer
-----------------------------------------------------
aTimer:running()
Desc: Checks if the timer is running (is started).
Returns:
boolean true if timer is running, false if not
-----------------------------------------------------
aTimer:start(countdown)
Desc: Starts the timer.
Arguments:
number countdown - [optional] Number to countdown from. Use as a countdown timer if greater than 0; default: inherited from constructor
Returns:
boolean true if timer is started (and it is)
-----------------------------------------------------
aTimer:reset(countdown)
Desc: Alias for aTimer:start(countdown)
-----------------------------------------------------
aTimer:stop()
Desc: Stops the timer.
Returns:
number Number of seconds passed since start
-----------------------------------------------------
aTimer:passed()
Desc: Gets number of seconds passed since timer was started
Returns:
number Number of seconds or 0 if timer is not started
-----------------------------------------------------
aTimer:greater(seconds)
Desc: Checks if number of seconds passed since start is greater than provided value
Arguments:
number seconds - [required] Number of seconds to check
Returns:
boolean true if timer is running longer than provided value if seconds
-----------------------------------------------------
aTimer:lower(seconds)
Desc: Checks if number of seconds passed since start is lower than provided value
Arguments:
number seconds - [required] Number of seconds to check
Returns:
boolean true if timer is running shorter than provided value if seconds
-----------------------------------------------------
aTimer:between(min, max, inclusive)
Desc: Checks if number of seconds passed since start is between provided min and max values
Arguments:
number min - [required] Number of seconds to check (low)
number max - [required] Number of seconds to check (high)
boolean inclusive [optional] Should min and max be included in check; default: true
Returns:
boolean true if timer is between min and max values, false otherwise
-----------------------------------------------------
aTimer:left()
Desc: Gets number of seconds left to count down to zero (0)
Returns:
number Number of seconds or 0 if timer is not a countdown timer
-----------------------------------------------------
aTimer:expired()
Desc: Checks if the countdown timer has reached zero (0)
Returns:
boolean True if zero is reached or false if not. And false also if timer is not a countdown timer
-----------------------------------------------------
Additionally, each time the timer is (re)started, it's internal
aTimer.cnt counter will increase. This can be used to check if the timer is (re)started again (if you don't want to repeat timer-related actions)
Unzip attached archive to your "FPSC:R/Files" folder.