FunctionMachine = { CLASS = "FunctionMachine" }
FunctionMachine.__index = FunctionMachine
function FunctionMachine:_new()
local m = { }
setmetatable(m, self)
self.__index = self
return m
end
function FunctionMachine:new(pars)
if not pars then
error("No parameters provided")
end
if not pars.func then
error("No function provided")
end
local f = function() end
if type(pars.func) ~= type(f) then
error("Need an actual function")
end
if not pars.marker_type then
error("No marker_type specified")
end
if (pars.marker_type == "random"
and not (pars.turns_min and pars.turns_max)) then
error("marker_type:random, but no turns_min or turns_max specified")
end
if pars.marker_type == "turns" and not pars.turns then
error("marker_type:turns, but no turns specified")
end
local m = FunctionMachine:_new()
m.func = pars.func
m.marker_type = pars.marker_type
m.activated = false
m.countdown = 0
m.turns_min = pars.turns_min or pars.turns or 0
m.turns_max = pars.turns_max or pars.turns or 0
m.repeated = pars.repeated or false
m.marker_params = pars.marker_params or {}
m.turns_min = m.turns_min * 10
m.turns_max = m.turns_max * 10
return m
end
function FunctionMachine:do_function(position, ...)
local largs = { ... }
if #largs == 0 then
self.func(position, self.marker_params)
else
self.func(position, self.marker_params, unpack(largs))
end
end
function FunctionMachine:activate(marker, verbose)
local _x, _y = marker:pos()
if (self.marker_type == "listener") then
return
else
dgn.register_listener(dgn.dgn_event_type('turn'), marker)
end
end
function FunctionMachine:event(marker, ev)
local x, y = marker:pos()
if ev:type() == dgn.dgn_event_type('turn') then
if self.marker_type == "random" or self.marker_type == "turns" then
self.countdown = self.countdown - ev:ticks()
while self.countdown <= 0 do
self:do_function(dgn.point(marker:pos()))
self.activated = true
self.countdown = self.countdown +
crawl.random_range(self.turns_min, self.turns_max, 1)
end
elseif self.marker_type == "in_los" then
if you.see_cell(x, y) then
if not self.activated or self.repeated then
self:do_function(dgn.point(marker:pos()))
self.activated = true
end
end
elseif self.marker_type == "player_at" then
you_x, you_y = you.pos()
if you_x == x and you_y == y then
if not self.activated or self.repeated then
self:do_function(dgn.point(marker:pos()))
self.activated = true
end
end
end
end
end
function FunctionMachine:write(marker, th)
file.marshall_meta(th, self.func)
file.marshall_meta(th, self.marker_type)
file.marshall_meta(th, self.activated)
file.marshall_meta(th, self.countdown)
file.marshall_meta(th, self.turns_min)
file.marshall_meta(th, self.turns_max)
file.marshall_meta(th, self.repeated)
lmark.marshall_table(th, self.marker_params)
end
function FunctionMachine:read(marker, th)
self.func = file.unmarshall_meta(th)
self.marker_type = file.unmarshall_meta(th)
self.activated = file.unmarshall_meta(th)
self.countdown = file.unmarshall_meta(th)
self.turns_min = file.unmarshall_meta(th)
self.turns_max = file.unmarshall_meta(th)
self.repeated = file.unmarshall_meta(th)
self.marker_params = lmark.unmarshall_table(th)
setmetatable(self, FunctionMachine)
return self
end
function function_machine(pars)
return FunctionMachine:new(pars)
end
function message_machine (pars)
local channel = pars.channel or false
local mtable = {message = pars.message, channel = pars.channel}
pars.func = function (position, mtable)
crawl.mpr(mtable.message, mtable.channel)
end
pars.marker_params = mtable
return FunctionMachine:new(pars)
end