summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/dat/clua/lm_flags.lua
diff options
context:
space:
mode:
Diffstat (limited to 'crawl-ref/source/dat/clua/lm_flags.lua')
-rw-r--r--crawl-ref/source/dat/clua/lm_flags.lua347
1 files changed, 347 insertions, 0 deletions
diff --git a/crawl-ref/source/dat/clua/lm_flags.lua b/crawl-ref/source/dat/clua/lm_flags.lua
new file mode 100644
index 0000000000..770c80110e
--- /dev/null
+++ b/crawl-ref/source/dat/clua/lm_flags.lua
@@ -0,0 +1,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