I also made a simple task queue to aid with timing things. There are two classes: task (which tracks time and then calls the function requested), and taskqueue (which holds tasks).
task.lua:
Code: Select all
Task = class.new();
function Task:constructor(_func, _time)
-- Ensure that we were given a function to execute.
if( type(_func) ~= "function" ) then
return
end
self.fullTime = _time; -- Save time between runs
self.func = _func; -- And the actual function to run
self.timeLeft = _time; -- And set our timer to full
end
function Task:update()
-- Remove a small piece of time from our timer
self.timeLeft = self.timeLeft - time.deltaTime();
-- Now check if it is ready to run
if( self.timeLeft < 0 ) then
local ret = self.func();
-- Reset it if requested to keep
if( ret ) then
self.timeLeft = self.fullTime;
end
-- Return our functions return value to the task queue
return ret;
end
-- Return true to signal that we need to keep this task for now.
return true;
end
Code: Select all
include("task.lua");
TaskQueue = class.new();
function TaskQueue:constructor()
-- This is our table for holding upcomming tasks
self.tasks = {};
end
function TaskQueue:push(task, secsTilExecute)
-- Make sure we were given a task object
if( type(task) ~= "function" ) then
error("Not given a function to execute for argument #1.", 2);
end
-- Need to also know how long until we execute
if( type(secsTilExecute) ~= "number" ) then
error("Argument #2 to TaskQueue:push() needs to be a number.", 2);
end
table.insert(self.tasks, Task(task, secsTilExecute));
end
function TaskQueue:update()
for i,v in pairs(self.tasks) do
local ret = v:update();
-- Check if we need to remove this task
if( not ret ) then
table.remove(self.tasks, i);
end
end
end
Now you can create a task that will automatically be called after the specified amount of time (in seconds), and may be repeated or not. If the task function returns true, the task will be reset instead of removed from the queue. So, now we can do this:
Code: Select all
include("taskqueue.lua");
function macro.init()
taskqueue = TaskQueue();
taskqueue:push(function() print("Hello") end, 1);
taskqueue:push(function() print("How") end, 1.5);
taskqueue:push(function() print("Are") end, 2);
taskqueue:push(function() print("You") end, 2.5);
taskqueue:push(function() print("Spam"); return true end, 3);
end
function macro.main()
taskqueue:update();
end
Certain things would still be recommended to be built into a class rather than this kind of queue. For instance, a player class might have two timers: 1 for global cooldown (reset every time you perform an action), and 1 for cast time/channel time. In this way, that player can take no action while waiting on those two timers. Why two? Well, the global cooldown is always required to be over before the player could possibly take action. The cast/channel, however, could be interrupted for important events (such as low health). When a skill is cast, you would simply set the global cooldown timer to the actual global cooldown (probably 1 second in most games), and set the skill timer to the skill's cast time. If both of them are > 0, then you know you cannot take any action and should instead return from that function.