summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/dat/clua/lm_func.lua
blob: 692990f2de0b3331542857fdfa2ead51194b5973 (plain) (blame)
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