diff options
Diffstat (limited to 'crawl-ref/source/dat/clua/lm_flags.lua')
-rw-r--r-- | crawl-ref/source/dat/clua/lm_flags.lua | 347 |
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 |