initial release
This commit is contained in:
180
cosmic rage/lua/wait.lua
Normal file
180
cosmic rage/lua/wait.lua
Normal file
@@ -0,0 +1,180 @@
|
||||
-- wait.lua
|
||||
-- ----------------------------------------------------------
|
||||
-- 'wait' stuff - lets you build pauses into scripts.
|
||||
-- See forum thread:
|
||||
-- http://www.gammon.com.au/forum/?id=4957
|
||||
-- ----------------------------------------------------------
|
||||
|
||||
--[[
|
||||
|
||||
Example of an alias 'send to script':
|
||||
|
||||
|
||||
require "wait"
|
||||
|
||||
wait.make (function () --- coroutine below here
|
||||
|
||||
repeat
|
||||
Send "cast heal"
|
||||
line, wildcards =
|
||||
wait.regexp ("^(You heal .*|You lose your concentration)$")
|
||||
|
||||
until string.find (line, "heal")
|
||||
|
||||
-- wait a second for luck
|
||||
wait.time (1)
|
||||
|
||||
end) -- end of coroutine
|
||||
|
||||
--]]
|
||||
|
||||
require "check"
|
||||
|
||||
module (..., package.seeall)
|
||||
|
||||
-- ----------------------------------------------------------
|
||||
-- table of outstanding threads that are waiting
|
||||
-- ----------------------------------------------------------
|
||||
local threads = {}
|
||||
|
||||
-- ----------------------------------------------------------
|
||||
-- wait.timer_resume: called by a timer to resume a thread
|
||||
-- ----------------------------------------------------------
|
||||
function timer_resume (name)
|
||||
local thread = threads [name]
|
||||
if thread then
|
||||
threads [name] = nil
|
||||
local ok, err = coroutine.resume (thread)
|
||||
if not ok then
|
||||
ColourNote ("deeppink", "black", "Error raised in timer function (in wait module).")
|
||||
ColourNote ("darkorange", "black", debug.traceback (thread))
|
||||
error (err)
|
||||
end -- if
|
||||
end -- if
|
||||
end -- function timer_resume
|
||||
|
||||
-- ----------------------------------------------------------
|
||||
-- wait.trigger_resume: called by a trigger to resume a thread
|
||||
-- ----------------------------------------------------------
|
||||
function trigger_resume (name, line, wildcards, styles)
|
||||
local thread = threads [name]
|
||||
if thread then
|
||||
threads [name] = nil
|
||||
local ok, err = coroutine.resume (thread, line, wildcards, styles)
|
||||
if not ok then
|
||||
ColourNote ("deeppink", "black", "Error raised in trigger function (in wait module)")
|
||||
ColourNote ("darkorange", "black", debug.traceback (thread))
|
||||
error (err)
|
||||
end -- if
|
||||
end -- if
|
||||
end -- function trigger_resume
|
||||
|
||||
-- ----------------------------------------------------------
|
||||
-- convert x seconds to hours, minutes, seconds (for AddTimer)
|
||||
-- ----------------------------------------------------------
|
||||
local function convert_seconds (seconds)
|
||||
local hours = math.floor (seconds / 3600)
|
||||
seconds = seconds - (hours * 3600)
|
||||
local minutes = math.floor (seconds / 60)
|
||||
seconds = seconds - (minutes * 60)
|
||||
return hours, minutes, seconds
|
||||
end -- function convert_seconds
|
||||
|
||||
-- ----------------------------------------------------------
|
||||
-- wait.time: we call this to wait in a script
|
||||
-- ----------------------------------------------------------
|
||||
function time (seconds)
|
||||
local id = "wait_timer_" .. GetUniqueNumber ()
|
||||
threads [id] = assert (coroutine.running (), "Must be in coroutine")
|
||||
|
||||
local hours, minutes, seconds = convert_seconds (seconds)
|
||||
|
||||
check (AddTimer (id, hours, minutes, seconds, "",
|
||||
bit.bor (timer_flag.Enabled,
|
||||
timer_flag.OneShot,
|
||||
timer_flag.Temporary,
|
||||
timer_flag.ActiveWhenClosed,
|
||||
timer_flag.Replace),
|
||||
"wait.timer_resume"))
|
||||
|
||||
return coroutine.yield ()
|
||||
end -- function time
|
||||
|
||||
-- ----------------------------------------------------------
|
||||
-- wait.regexp: we call this to wait for a trigger with a regexp
|
||||
-- ----------------------------------------------------------
|
||||
function regexp (regexp, timeout, flags)
|
||||
local id = "wait_trigger_" .. GetUniqueNumber ()
|
||||
threads [id] = assert (coroutine.running (), "Must be in coroutine")
|
||||
|
||||
check (AddTriggerEx (id, regexp,
|
||||
"-- added by wait.regexp",
|
||||
bit.bor (flags or 0, -- user-supplied extra flags, like omit from output
|
||||
trigger_flag.Enabled,
|
||||
trigger_flag.RegularExpression,
|
||||
trigger_flag.Temporary,
|
||||
trigger_flag.Replace,
|
||||
trigger_flag.OneShot),
|
||||
custom_colour.NoChange,
|
||||
0, "", -- wildcard number, sound file name
|
||||
"wait.trigger_resume",
|
||||
12, 100)) -- send to script (in case we have to delete the timer)
|
||||
|
||||
-- if timeout specified, also add a timer
|
||||
if timeout and timeout > 0 then
|
||||
local hours, minutes, seconds = convert_seconds (timeout)
|
||||
|
||||
-- if timer fires, it deletes this trigger
|
||||
check (AddTimer (id, hours, minutes, seconds,
|
||||
"DeleteTrigger ('" .. id .. "')",
|
||||
bit.bor (timer_flag.Enabled,
|
||||
timer_flag.OneShot,
|
||||
timer_flag.Temporary,
|
||||
timer_flag.ActiveWhenClosed,
|
||||
timer_flag.Replace),
|
||||
"wait.timer_resume"))
|
||||
|
||||
check (SetTimerOption (id, "send_to", "12")) -- send to script
|
||||
|
||||
-- if trigger fires, it should delete the timer we just added
|
||||
check (SetTriggerOption (id, "send", "DeleteTimer ('" .. id .. "')"))
|
||||
|
||||
end -- if having a timeout
|
||||
|
||||
return coroutine.yield () -- return line, wildcards
|
||||
end -- function regexp
|
||||
|
||||
-- ----------------------------------------------------------
|
||||
-- wait.match: we call this to wait for a trigger (not a regexp)
|
||||
-- ----------------------------------------------------------
|
||||
function match (match, timeout, flags)
|
||||
return regexp (MakeRegularExpression (match), timeout, flags)
|
||||
end -- function match
|
||||
|
||||
-- ----------------------------------------------------------
|
||||
-- wait.make: makes a coroutine and resumes it
|
||||
-- ----------------------------------------------------------
|
||||
function make (f)
|
||||
assert (type (f) == "function", "wait.make requires a function")
|
||||
|
||||
-- More friendly failure, suggested by Fiendish
|
||||
local errors = {}
|
||||
if GetOption ("enable_timers") ~= 1 then
|
||||
table.insert (errors, "TIMERS")
|
||||
end -- if timers disabled
|
||||
if GetOption ("enable_triggers") ~= 1 then
|
||||
table.insert (errors, "TRIGGERS")
|
||||
end -- if triggers disabled
|
||||
if #errors ~= 0 then
|
||||
ColourNote("white", "red",
|
||||
"One of your scripts (in '" ..
|
||||
(GetPluginInfo(GetPluginID(), 1) or "World") ..
|
||||
"') just did something that requires " ..
|
||||
table.concat (errors, " and ") ..
|
||||
" to be enabled, but they aren't. " ..
|
||||
"Please check your configuration settings.")
|
||||
return nil, "Trigger/Timers not enabled" -- bad return
|
||||
end -- if have errors
|
||||
coroutine.wrap (f) () -- make coroutine, resume it
|
||||
return true -- good return
|
||||
end -- make
|
||||
Reference in New Issue
Block a user