1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
|
------------------------------------------------------------------------------
-- lm_func.lua:
-- Function execution.
--
-- Calls a specific Lua function when activated; activation of the
-- function can occur when certain conditions are met. See the
-- marker_type parameter as listed below.
--
-- Marker parameters:
-- func: The function to be called.
-- marker_type: Can be one of the following:
-- * "random": Call the function randomly, takes the following parameters
-- "turns_min", "turns_max", and will call every random(min, max) turns.
-- * "turns": Call the function regularly, takes the parameter "turns", and
-- will call the function every "turns".
-- * "in_los": Calls the function whenever the marker is in the
-- player's line of sight. Takes the parameter "repeated", which
-- is "false" by default, meaning that the function is only
-- called once. Passing true means that the function is called
-- every turn that the marker is in LOS.
-- * "player_at": Calls the function whenever the player is at the
-- same position as the marker. Takes the same "repeated"
-- parameter as "in_los".
-- * "listener": A function machine that can be linked into other lua
-- markers and machines. It is not triggered independently, but
-- called by the "parent" marker, though always with the same
-- marker_table parameter as other machines. May take further
-- parameters, see the parent's documentation.
--
-- marker_table: Table to be passed to the function when called.
-- Defaults to {}.
--
-- Specific markers take specific parameters, as listed under marker_type.
--
-- The function will be called with the "marker" object and the table
-- marker_params.
--
------------------------------------------------------------------------------
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
-- Setting turns is basically the same as setting turns_min and
-- turns_max to the same value; there's no point duplicating
-- functionality later.
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 {}
-- Some arithmetic to make these make sense in terms of actual turns
-- versus ticks.
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
|