Sleep Lua script while letting the master program continue - lua

I am programming a plugin to a program that has integrated Lua scripting, and need to have my script check a condition every x seconds.
I have tried different methods of "sleeping" the Lua script, but all my methods so far also hang/pause the main program.
Is there a way to have my Lua script run every x seconds without pausing the master program.

You can use os.time() and os.difftime():
local waitTime = 3
if t1 == nil then t1 = os.time() end
--Check
if math.floor(os.difftime(os.time(),t1)) == waitTime then
t1 = os.time()
-- Do stuff
end
This runs your code every 3 seconds.

Related

How to turn off a function after a desired amount of time?

I know my question would sound silly but I'm new to Lua so I'm trying to make the best practice as I can.
function wait(n)
local start = os.time()
repeat until os.time() > start + n
end
function hi(x)
while x do
print("Hi")
wait(.5)
end
end
hi(true)
For example, I want to turn off the function "hi" after running for 6 seconds and re-enable it after stopping for 2 seconds, how can I do it? Thank you so much!
Try this changes...
function wait(n)
local start = os.clock()
repeat until os.clock() > start + n
end
function hi(x)
for i = 1, x do
print("Hi")
wait(.5)
end
end
hi(4) -- With the hardcoded wait(.5) this will end after 2s
One warning.
Lua is fast so wait() will run in high performance mode.
Let it run by hi(120) for a minute will also run your fans in high cooling mode.
...it is better to have a more CPU friendly wait/sleep.
Easy Peasy with LuaJIT: https://luajit.org/ext_ffi_tutorial.html

Can I make my Lua program to sleep for AROUND a day?

I want to make my mydicebot (by seuntje) Lua program sleep AROUND A DAY, after betting for a day... like
function sleep(n)
t = os.clock()
while os.clock() - t <= n do
-- nothing
end
end
function playsleep()
sec = math.random(80000,90000)
sleep(sec) -- around 86400 seconds
end
timestart = os.time()
dur = math.random(70000,80000)
function dobet()
if os.time() - timestart < math.random then
playsleep()
end
timestart = os.time() -- reset the time counter
end
but when I call the playsleep function in the dobet function
it ends up I cannot click anything in my program, cannot move another tab also
and the CPU is not sleeping either, even get busy
and sometimes it stucks even after 90000 seconds
-- THE QUESTIONS --
A. so can I make a function where the sleep is a real sleep?
B. can it sleep until 90000 seconds?
C. or what is the max number of sleep in seconds for the variable "sec" above?
Use the posix module to sleep:
posix = require("posix")
posix.sleep(86400)
But this will still block your program and you won't be able to click anything. You will need to provide more detail about your program in order to receive better advice.
Also os is there.
Why not...
do os.execute('$(type -path sleep) '..(3600*24)) end
...?

Getting my Lua file to update

I'm making an addon for world of warcraft, and I'm to the point where my project is done, but it runs once and is done.
My objective is to make an interface on my screen that shows certain stats, and during combat you may get a proc of some sort and your stats will increase.
Right now my code creates the interface and shows base stats.
This is a function I wrote that I can use to update it correctly.
local function updateFunction()
AgilityLine.text:SetText("Agility = ".. getRangedAgility())
AttackPowerLine.text:SetText("AP = ".. getRangedAttackPower())
CritLine.text:SetText("Crit = ".. getRangedCrit() .."%")
MasteryLine.text:SetText("Mastery = ".. getRangedMastery())
HasteLine.text:SetText("Haste = ".. getHaste() .."%")
end
I test it by making an in game command to run the function. How can I make the function run itself at a reasonable rate, maybe twice a second.
Here's how you update every 2s seconds :
local total = 0
local function onUpdate(self,elapsed)
total = total + elapsed
if total >= 2 then
updateFunction()
total = 0
end
end
local f = CreateFrame("frame")
f:SetScript("OnUpdate", onUpdate)
Just using intern update system for addon =)
Source : http://wowprogramming.com/snippets/Create_a_mini-timer_using_OnUpdate_3
you should add this function into the game loop function, maybe like timetick(); or you should write the timetick function yourself and call this updateFunction

Lua Coroutine Error

I'm currently working on a simple 'guess the number' game using Lua. I'm programming through an app on my iPad called TouchLua+. One of the game modes is you have a certain amount of time to guess the number. I thought that to do this, I would create a coroutine that counts down from the given time. For some reason, I can't input a number while the coroutine is running. Can anyone help? Here is what I have so far.
target = math.random(1, 100)
coroutine.resume(coroutine.create(function()
for i = 1, roundTime do
sleep(1000)
sys.alert("tock")
end
lose = true
coroutine.yield()
end))
repeat
local n = tonumber(io.read())
if (n > target) then
print("Try a lower number.\n")
elseif (n < target) then
print("Try a higher number.\n")
else
win = true
end
until (lose or win)
return true
Coroutines are not a form of multiprocessing, they are a form of cooperative multithreading. As such, while the coroutine is running, nothing else is running. A coroutine is meant to yield control back to the caller often, and the caller is meant to resume the coroutine so the coroutine can continue where it yielded. You can see how this will appear to be parallel processing.
So in your case you would want to yield from inside the loop, after a small sleep time:
co = coroutine.create(function()
for i = 1, roundTime do
sleep(1)
sys.alert("tock")
coroutine.yield()
end
lose = true
end)
Unfortunately, you can't interrupt io.read(), which means the above is of no use. Ideally you would want a "io.peek" function so you could do the following:
while coroutine.status(co) ~= "dead" do
coroutine.resume(co)
if io.peek() then -- non-blocking, just checks if a key has been pressed
... get the answer and process ...
end
end
I am not aware of a non-blocking keyboard IO in Lua. You could create a C extension that exposes some of C non-blocking keyboard input to Lua, assuming that TouchLua+ supports C extensions. I doubt it, given that it is an iOS app.
It doesn't appear that there is a time loop or callbacks or such, and couldn't find docs. If you have option of creating a text box where user can enter answer and they have to click accept then you can measure how long it took. If there is a time loop you could check time there and show message if run out of time. All this is very easy to do in Corona, maybe not possible in TouchLua+.

How do I execute a global function on a specific day at a specific time in Lua?

I'm writing a script in Lua that among many other functions will perform a single loop at a specific time on a specific day. The loop is started when a button is pressed, pondering over this for a while now I have gathered that I will have to check the system time in millis using os.time which in table form can return the date too which is very helpful. The only thing I am stuck with is how to express it, and if it would be possible to include multiple definitions of os.time; so on day (x), loop1 will run and on day (y) loop 2 will occur and so on. I'm most likely over complicating this a lot...
Here's my code so far: (it crashes and burns when called by the button press)
function runiftime()
day1 = a;
day2 = b;
day3 = c;
day4 = d;
status = 0; -- Default status == 0
target = day4;
-- Where a, b, c & d are shown above I would like different os.time outputs which relate to days in the future an example output of os.time is => = os.time() outputs '1384988715'.
repeat
if os.time() == "day1" then
os.execute("Some command");
result = Shell.Execute("Some program", "open", "", "", SW_SHOWNORMAL, false);
status = 1;
end
if os.time() == "day2" then
os.execute("Some command");
result = Shell.Execute("Some program", "open", "", "", SW_SHOWNORMAL, false);
status = 1;
end
if os.time == "day3" then
os.execute("Some command");
result = Shell.Execute("Some program", "open", "", "", SW_SHOWNORMAL, false);
status = 1;
end
if os.time == "day4" then
os.execute("Some command");
result = Shell.Execute("Some program", "open", "", "", SW_SHOWNORMAL, false);
status = 1;
end
if status == 1 then
Input.SetText("feed", "Routine Successful! Waiting for Command...");
else
Input.SetText("feed", "Automated Routine Started! Waiting for OS Clock...");
end
until (os.time == target);
end
I've noticed a few issues with your code. First of all, half the time, you're comparing to os.time which is a function and os.time() which will be a number. Secondly, you're going into an infinite loop with until (os.time == target);, since os.time will never change unless you change it.
Even then, if you were correctly comparing with os.time(), going into an infinite loop to check the time all the time is going to max out CPU usage for the Lua VM, as infinite loops are wont to do. This will probably freeze up the process, which might be what you mean by "crash and burn."
Last but not least, comparing the current time to a time in the future with an == is generally a bad idea, due to the low probability of the condition executing precisely during the exact desired time.
I'd recommend sleeping as long as possible until the earliest task is ready to be carried out. This way, you avoid taking up any unnecessary CPU time with constant polling. From Lua, you could do something like this.
local target = os.time{year = 2013, month = 11, day = 21, hour = 9, min = 30}
local function sleep(s) -- wait for `s` seconds
if type(s) ~= 'number' then
error's is not a number'
elseif s < 1 then
return
end
s = math.floor(s)
-- Windows (delay range limited to 0-9999)
--os.execute('choice /n /d:y /t:' .. math.min(s, 9999) .. ' > NUL')
-- *nix
os.execute('sleep ' .. s)
end
local d
repeat
d = target - os.time()
if d <= 0 then break end
sleep(d) -- sleep for the difference
until false
print'Target time has arrived.'
Ideally, you'd accomplish something like this by having your operating system's scheduler, such as cron on *nix or Task Scheduler on Windows, control the timing of the script's execution. However, if you plan to handle the timing through Lua, have a look through this page in Programming in Lua.
Edit: Making use of our sleep function from last time, we can easily create the foundation for a complete task scheduler in Lua that can handle multiple events with only a few lines of code.
local alarm = {}
local function sort_alarm(a, b) return a.time > b.time end
local function schedule(when, what)
if os.time() <= when then
table.insert(alarm, {time = when, event = what})
table.sort(alarm, sort_alarm)
else -- What to do when a scheduled event is in the past?
what()
end
end
local function run_scheduler()
local d
while #alarm > 0 do
d = alarm[#alarm].time - os.time()
if d <= 0 then
-- Pop the latest alarm from the stack and call it.
table.remove(alarm).event()
else
sleep(d)
end
end
end
-- Schedule some events.
schedule(os.time{year = 2013, month = 11, day = 22, hour = 9}, function()
print'This function runs at a specific point in time.'
end)
schedule(os.time() + 30, function()
print'This function will run 30 seconds from the start of the script.'
end)
schedule(os.time() + 5, function()
print'This function will run 5 seconds from the start of the script.'
schedule(os.time() + 10, function()
print'You can even schedule new functions this way.'
print'This one will run 15 seconds from the start of the script.'
end)
end)
local function repeater()
print'How about a repeating event?'
print'This function will run every 10 seconds.'
schedule(os.time() + 10, repeater)
end
schedule(os.time() + 10, repeater)
-- Start the scheduler loop.
run_scheduler()
-- No more events left at this point, thus the script will end.
In closing, I must note that if you plan to use this seriously, you'll want to replace the sleep function with something more robust in the future. There's a page on the users wiki listing some solutions. I'd say it's easiest to do from LuaJIT using the FFI, if you happen to be using it already.

Resources