summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/dat/clua/lm_flags.lua
blob: 770c80110e09124297f5fd20632248cb0dc9c64e (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
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
---------------------------------------------------------------------------
-- lm_flags.lua
-- Changing level flags and branch flags
--------------------------------------------------------------------------

--------------------------------------------------------------------------
-- There are three different types of pre-packaged "change level and
-- branch flags" marker types.  All three share the following parameters:
--
-- * level_flags: A space separated list of level flag names to set or unset.
--       To unset a flag, prefix the name with "!".
--
-- * branch_flags: Like level_flags, but for branch flags to set or unset.
--
-- * group: Different flag change markers on the same level can be put
--       into the same group by giving them the same group name.
--       Of all of the markers in the same group, only the last one
--       to have its conditions met will cause the flags to change.
--       This is useful if, for example, there are two magical fountains,
--       and you only want the flags to change when both dry up.
--       
-- * msg: A message to give the user when the flags are changed; suppress
--       any messages Crawl would normally give for the changes effected.
--       The message is not given if nothing is changed (i.e., if all
--       the flags to be set were already set and all the flags to be
--       unset were already unset).
--
-- The three different marker types can be created with the following
-- functions:
--
-- * mons_dies_change_flags(): Creates a marker which changes the flags
--        when a named monster dies.  Accepts the parameter "mon_name"
--        as the name of the monster to watch.  The marker can be
--        placed anywhere on the level, and doesn't have to be near the
--        monster when it dies.
--
-- * feat_change_change_flags(): Creates a marker which acts when the
--        feature of its grid changes.  Accepts the optional string
--        parameter "final_feat", which will cause the change to only
--        take place when the changed feature contains final_feat as
--        a substring.  For example, a sparkling fountain can dry up
--        either by turning directly into a dry_fountain_ii feature,
--        or by first turning into a blue_fountain feature, and then
--        into a dry_fountain_i feature.  Without final_feat, the
--        flags will change if the sparkling fountain changes into
--        a blue fountain.  However, if "final_feat" is set to
--        "dry_fountain", the marker will ignore the feature turning
--        into blue_fountain, and will only act when it changes into
--        dry_fountain_i or dry_fountain_ii
--
-- * item_pickup_change_flags(): Creates a marker which acts when
--        an item on its grid gets picked up.  Accepts the parameter
--        "item", which is the plain name of the item its watching
--        (i.e., "Orb of Zot" and "golden rune" rather than "the Orb of Zot"
--        or "a golden rune").
--------------------------------------------------------------------------
 
ChangeFlags = { }
ChangeFlags.__index = ChangeFlags

function ChangeFlags:_new()
  local cf = { }
  setmetatable(cf, self)
  self.__index = self

  return cf
end

function ChangeFlags:new(pars)
  pars = pars or { }

  pars.level_flags  = pars.level_flags  or ""
  pars.branch_flags = pars.branch_flags or ""
  pars.msg          = pars.msg          or ""

  if not (pars.level_flags ~= "" or pars.branch_flags ~= "") then
    error("Must provide at least one of level_flags or branch_flags.")
  end

  local cf = self:_new()
  cf.level_flags  = pars.level_flags
  cf.branch_flags = pars.branch_flags
  cf.msg          = pars.msg
  cf.props        = { flag_group = pars.group }

  return cf
end

function ChangeFlags:do_change(marker)
  local did_change1 = false
  local did_change2 = false
  local silent      = self.msg and self.msg ~= ""

  if self.props.flag_group and self.props.flag_group ~= "" then
    local num_markers = dgn.num_matching_markers("flag_group",
                                                 self.props.group)

    if num_markers > 1 then
      return false, false
    end
  end

  if self.level_flags and self.level_flags ~= "" then
    did_change1 = dgn.change_level_flags(self.level_flags, silent)
  end

  if self.branch_flags and self.branch_flags ~= "" then
    did_change2 = dgn.change_branch_flags(self.branch_flags, silent)
  end

  if did_change1 or did_change2 then
    if self.msg and self.msg ~= "" then
      crawl.mpr(self.smg)
    end

    return true, true
  end
  
  return true, false
end

function ChangeFlags:property(marker, pname)
  return self.props[pname] or ''
end

function ChangeFlags:write(marker, th)
  file.marshall(th, self.level_flags)
  file.marshall(th, self.branch_flags)
  file.marshall(th, self.msg)
  lmark.marshall_table(th, self.props)
end

function ChangeFlags:read(marker, th)
  self.level_flags  = file.unmarshall_string(th)
  self.branch_flags = file.unmarshall_string(th)
  self.msg          = file.unmarshall_string(th)
  self.props        = lmark.unmarshall_table(th)
  setmetatable(self, ChangeFlags) 

  return self
end

--------------------------------------------------------------------------
--------------------------------------------------------------------------

MonDiesChangeFlags = ChangeFlags:_new()
MonDiesChangeFlags.__index = MonDiesChangeFlags

function MonDiesChangeFlags:_new(pars)
  local mdcf

  if pars then
    mdcf = ChangeFlags:new(pars)
  else
    mdcf = ChangeFlags:_new()
  end
    
  setmetatable(mdcf, self)
  self.__index = self

  return mdcf
end

function MonDiesChangeFlags:new(pars)
  pars = pars or { }

  if not pars.mon_name then
    error("No monster name provided.")
  end

  local mdcf = self:_new(pars)
  mdcf.mon_name = pars.mon_name

  return mdcf
end

function MonDiesChangeFlags:activate(marker)
  dgn.register_listener(dgn.dgn_event_type('monster_dies'), marker)
end

function MonDiesChangeFlags:event(marker, ev)
  local midx = ev:arg1()
  local mons = dgn.mons_from_index(midx)

  if not mons then
    error("MonDiesChangeFlags:event() didn't get a valid monster index")
  end

  if mons.name == self.mon_name then
    ChangeFlags.do_change(self, marker)
    dgn.remove_listener(marker)
    dgn.remove_marker(marker)
  end
end

function MonDiesChangeFlags:write(marker, th)
  ChangeFlags.write(self, marker, th)
  file.marshall(th, self.mon_name)
end

function MonDiesChangeFlags:read(marker, th)
  ChangeFlags.read(self, marker, th)
  self.mon_name  = file.unmarshall_string(th)
  setmetatable(self, MonDiesChangeFlags) 

  return self
end

function mons_dies_change_flags(pars)
  return MonDiesChangeFlags:new(pars)
end

-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
FeatChangeChangeFlags = ChangeFlags:_new()
FeatChangeChangeFlags.__index = FeatChangeChangeFlags

function FeatChangeChangeFlags:_new(pars)
  local fccf

  if pars then
    fccf = ChangeFlags:new(pars)
  else
    fccf = ChangeFlags:_new()
  end
    
  setmetatable(fccf, self)
  self.__index = self

  return fccf
end

function FeatChangeChangeFlags:new(pars)
  pars = pars or { }

  local fccf = self:_new(pars)

  fccf.final_feat = pars.final_feat

  return fccf
end

function FeatChangeChangeFlags:activate(marker)
  dgn.register_listener(dgn.dgn_event_type('feat_change'), marker,
                        marker:pos())
end

function FeatChangeChangeFlags:event(marker, ev)
  if self.final_feat and self.final_feat ~= "" then
    local feat = dgn.feature_name(dgn.grid(ev:pos()))
    if not string.find(feat, self.final_feat) then
      return
    end
  end

  ChangeFlags.do_change(self, marker)
  dgn.remove_listener(marker, marker:pos())
  dgn.remove_marker(marker)
end

function FeatChangeChangeFlags:write(marker, th)
  ChangeFlags.write(self, marker, th)
  file.marshall(th, self.final_feat)
end

function FeatChangeChangeFlags:read(marker, th)
  ChangeFlags.read(self, marker, th)
  self.final_feat = file.unmarshall_string(th)
  setmetatable(self, FeatChangeChangeFlags) 

  return self
end

function feat_change_change_flags(pars)
  return FeatChangeChangeFlags:new(pars)
end

--------------------------------------------------------------------------
--------------------------------------------------------------------------

ItemPickupChangeFlags = ChangeFlags:_new()
ItemPickupChangeFlags.__index = ItemPickupChangeFlags

function ItemPickupChangeFlags:_new(pars)
  local ipcf

  if pars then
    ipcf = ChangeFlags:new(pars)
  else
    ipcf = ChangeFlags:_new()
  end
    
  setmetatable(ipcf, self)
  self.__index = self

  return ipcf
end

function ItemPickupChangeFlags:new(pars)
  pars = pars or { }

  if not pars.item then
    error("No item name provided.")
  end

  local ipcf = self:_new(pars)
  ipcf.item = pars.item

  return ipcf
end

function ItemPickupChangeFlags:activate(marker)
  dgn.register_listener(dgn.dgn_event_type('item_pickup'), marker,
                        marker:pos())
end

function ItemPickupChangeFlags:event(marker, ev)
  local obj_idx  = ev:arg1()
  local it       = dgn.item_from_index(obj_idx)

  if not it then
    error("ItemPickupChangeFlags:event() didn't get a valid item index")
  end

  if item.name(it) == self.item then
    ChangeFlags.do_change(self, marker)
    dgn.remove_listener(marker, marker:pos())
    dgn.remove_marker(marker)
  end
end

function ItemPickupChangeFlags:write(marker, th)
  ChangeFlags.write(self, marker, th)
  file.marshall(th, self.item)
end

function ItemPickupChangeFlags:read(marker, th)
  ChangeFlags.read(self, marker, th)
  self.item  = file.unmarshall_string(th)
  setmetatable(self, ItemPickupChangeFlags) 

  return self
end

function item_pickup_change_flags(pars)
  return ItemPickupChangeFlags:new(pars)
end