summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/dat/clua/lm_flags.lua
blob: 996cd9dd5268ee0034f44e9304db7a0265706d03 (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
---------------------------------------------------------------------------
-- 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 of Zot" rather than
--        "the Orb of Zot" or "a golden rune of Zot").  You can also
--        just use "auto", in which case whichever item is on top of
--        the marker will autoamically be chosen.
--
-- ChangeFlags is a Triggerable subclass, and the above three functions
-- are just convenience functions which add a single triggerer.  Other
-- triggerers (or more than one) can be added.
--------------------------------------------------------------------------

require('clua/lm_trig.lua')

ChangeFlags       = util.subclass(Triggerable)
ChangeFlags.CLASS = "ChangeFlags"

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

  local cf = self.super.new(self)

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

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

  cf.level_flags  = pars.level_flags
  cf.branch_flags = pars.branch_flags
  cf.msg          = pars.msg
  cf.props        = util.append( cf.props, { flag_group = pars.group } )

  return cf
end

function ChangeFlags:on_trigger(triggerer, marker, ev)
  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

  self:remove(marker)

  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:write(marker, th)
  ChangeFlags.super.write(self, 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)
  ChangeFlags.super.read(self, 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

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

function mons_dies_change_flags(pars)
  local mon_name = pars.mon_name or pars.target

  pars.mon_name = nil
  pars.target   = nil

  local cf = ChangeFlags:new(pars)

  cf:add_triggerer(
                    DgnTriggerer:new {
                      type   = "monster_dies",
                      target = mon_name
                    }
                  )

  return cf
end

function feat_change_change_flags(pars)
  local final_feat = pars.final_feat or pars.target

  pars.final_feat = nil
  pars.target     = nil

  local cf = ChangeFlags:new(pars)

  cf:add_triggerer(
                    DgnTriggerer:new {
                      type   = "feat_change",
                      target = final_feat
                    }
                  )

  return cf
end

function item_pickup_change_flags(pars)
  local item = pars.item or pars.target

  pars.item   = nil
  pars.target = nil

  local cf = ChangeFlags:new(pars)

  cf:add_triggerer(
                    DgnTriggerer:new {
                      type   = "item_pickup",
                      target = item
                    }
                  )

  return cf
end