summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crawl-ref/source/dat/clua/lm_flags.lua6
-rw-r--r--crawl-ref/source/dat/lair.des2
-rw-r--r--crawl-ref/source/files.cc114
-rw-r--r--crawl-ref/source/files.h8
-rw-r--r--crawl-ref/source/monstuff.cc26
-rw-r--r--crawl-ref/source/spl-util.cc6
-rw-r--r--crawl-ref/source/travel.cc5
-rw-r--r--crawl-ref/source/travel.h2
8 files changed, 118 insertions, 51 deletions
diff --git a/crawl-ref/source/dat/clua/lm_flags.lua b/crawl-ref/source/dat/clua/lm_flags.lua
index 68bf42177e..86814a26a8 100644
--- a/crawl-ref/source/dat/clua/lm_flags.lua
+++ b/crawl-ref/source/dat/clua/lm_flags.lua
@@ -73,8 +73,10 @@ function ChangeFlags:new(pars)
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.")
+ if pars.level_flags == "" and pars.branch_flags == ""
+ and not pars.trigger
+ then
+ error("Must provide at least one of level_flags, branch_flags, or trigger.")
end
local cf = self:_new()
diff --git a/crawl-ref/source/dat/lair.des b/crawl-ref/source/dat/lair.des
index 9b63a34ad1..c476cb5581 100644
--- a/crawl-ref/source/dat/lair.des
+++ b/crawl-ref/source/dat/lair.des
@@ -786,7 +786,7 @@ NSUBST: P = O / *|
SHUFFLE: ([{
LFLAGS: no_tele_control
MARKER: X = lua:mons_dies_change_flags { \
- level_flags="!no_tele_control", mon_name="royal jelly", \
+ mon_name="royal jelly", \
trigger=slime_wall_morph \
}
SUBST: X = .
diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc
index d6de3741da..c60c60b706 100644
--- a/crawl-ref/source/files.cc
+++ b/crawl-ref/source/files.cc
@@ -1475,62 +1475,94 @@ void restore_game(void)
}
}
-bool apply_to_all_dungeons(bool (*applicator)())
+static void _restore_level(const level_id &original)
{
- const branch_type original_branch = you.where_are_you;
- const int original_level = you.your_level;
- const level_area_type original_type = you.level_type;
+ // Reload the original level.
+ you.where_are_you = original.branch;
+ you.your_level = original.absdepth();
+ you.level_type = original.level_type;
+
+ load( DNGN_STONE_STAIRS_DOWN_I, LOAD_VISITOR,
+ you.level_type, you.your_level, you.where_are_you );
+}
- branch_type last_visited_branch = original_branch;
- int last_visited_level = original_level;
- const coord_def old_pos(you.pos());
+// Given a level in the dungeon (i.e. level_type == LEVEL_DUNGEON),
+// returns true if the level has been created already in this game.
+// Asserts if the level_type is not LEVEL_DUNGEON.
+bool is_existing_level(const level_id &level)
+{
+ ASSERT(level.level_type == LEVEL_DUNGEON);
+ return (tmp_file_pairs[level.absdepth()][level.branch]);
+}
+
+// Applies an operation (applicator) after switching to the specified level.
+// If preserve_current is true, will reload the original level after
+// modifying the target level.
+//
+// If the target level has not already been visited by the player, this
+// function will assert.
+//
+bool apply_to_level(const level_id &level, bool preserve_current,
+ bool (*applicator)())
+{
+ ASSERT(is_existing_level(level));
+
+ const level_id original = level_id::current();
+ if (level != original)
+ {
+ you.where_are_you = level.branch;
+ you.your_level = level.absdepth();
+ you.level_type = level.level_type;
+
+ // Load the dungeon level...
+ load( DNGN_STONE_STAIRS_DOWN_I, LOAD_VISITOR,
+ LEVEL_DUNGEON, original.absdepth(),
+ original.branch );
+ }
+
+ // Apply the change.
+ const bool result = applicator();
+
+ if (level != original)
+ {
+ // And save it back.
+ save_level(you.your_level, you.level_type, you.where_are_you);
+
+ if (preserve_current)
+ _restore_level(original);
+ }
+
+ return (result);
+}
+
+bool apply_to_all_dungeons(bool (*applicator)())
+{
+ const level_id original = level_id::current();
// Apply to current level, then save it out.
bool success = applicator();
- save_level(original_level, original_type, original_branch);
-
- you.level_type = LEVEL_DUNGEON;
+ save_level(original.absdepth(), original.level_type, original.branch);
for ( int i = 0; i < MAX_LEVELS; ++i )
{
for ( int j = 0; j < NUM_BRANCHES; ++j )
{
- if ( tmp_file_pairs[i][j] )
- {
- you.your_level = i;
- you.where_are_you = static_cast<branch_type>(j);
+ const branch_type br = static_cast<branch_type>(j);
+ const level_id thislevel(br, subdungeon_depth(br, i));
- // Don't apply to the original level - already done up top.
- if ( original_type == you.level_type &&
- original_level == you.your_level &&
- original_branch == you.where_are_you )
- continue;
-
- // Load the dungeon level...
- load( DNGN_STONE_STAIRS_DOWN_I, LOAD_VISITOR,
- LEVEL_DUNGEON, last_visited_level,
- last_visited_branch );
-
- // Modify it...
- if ( applicator() )
- success = true;
-
- // And save it back.
- save_level(you.your_level, LEVEL_DUNGEON, you.where_are_you);
+ if (!is_existing_level(thislevel))
+ continue;
+
+ // Don't apply to the original level - already done up top.
+ if (original == thislevel)
+ continue;
- last_visited_branch = you.where_are_you;
- last_visited_level = you.your_level;
- }
+ if (apply_to_level(thislevel, false, applicator))
+ success = true;
}
}
- // Reload the original level.
- you.where_are_you = original_branch;
- you.your_level = original_level;
- you.level_type = original_type;
-
- load( DNGN_STONE_STAIRS_DOWN_I, LOAD_VISITOR,
- original_type, original_level, original_branch );
+ _restore_level(original);
return success;
}
diff --git a/crawl-ref/source/files.h b/crawl-ref/source/files.h
index 422925343e..830f99bc41 100644
--- a/crawl-ref/source/files.h
+++ b/crawl-ref/source/files.h
@@ -83,6 +83,14 @@ void restore_game(void);
bool apply_to_all_dungeons(bool (*applicator)());
+class level_id;
+
+bool apply_to_level(const level_id &level, bool preserve_current,
+ bool (*applicator)());
+
+bool is_existing_level(const level_id &level);
+
+
// last updated 12may2000 {dlb}
/* ***********************************************************************
* called from: ouch
diff --git a/crawl-ref/source/monstuff.cc b/crawl-ref/source/monstuff.cc
index 28b340f0fb..39651da8f0 100644
--- a/crawl-ref/source/monstuff.cc
+++ b/crawl-ref/source/monstuff.cc
@@ -38,6 +38,7 @@
#include "describe.h"
#include "dgnevent.h"
#include "fight.h"
+#include "files.h"
#include "ghost.h"
#include "hiscores.h"
#include "it_use2.h"
@@ -639,6 +640,25 @@ static bool _is_mons_mutator_or_rotter(monsters *mons)
return (attk_flavour == AF_MUTATE || attk_flavour == AF_ROT);
}
+static bool _slime_pit_enable_teleport_control()
+{
+ return unset_level_flags(LFLAG_NO_TELE_CONTROL);
+}
+
+static void _fire_monster_death_event(monsters *monster,
+ killer_type killer,
+ int i)
+{
+ dungeon_events.fire_event(
+ dgn_event(DET_MONSTER_DIED, monster->pos(), 0,
+ monster_index(monster), killer));
+
+ if (monster->type == MONS_ROYAL_JELLY)
+ apply_to_level( level_id(BRANCH_SLIME_PITS, 6),
+ true,
+ _slime_pit_enable_teleport_control );
+}
+
void monster_die(monsters *monster, killer_type killer, int i, bool silent)
{
if (monster->type == -1)
@@ -1202,9 +1222,7 @@ void monster_die(monsters *monster, killer_type killer, int i, bool silent)
}
}
- dungeon_events.fire_event(
- dgn_event(DET_MONSTER_DIED, monster->pos(), 0,
- monster_index(monster), killer));
+ _fire_monster_death_event(monster, killer, i);
const coord_def mwhere = monster->pos();
if (drop_items)
@@ -1217,7 +1235,7 @@ void monster_die(monsters *monster, killer_type killer, int i, bool silent)
view_update_at(mwhere);
update_screen();
}
-} // end monster_die
+}
void monster_cleanup(monsters *monster)
{
diff --git a/crawl-ref/source/spl-util.cc b/crawl-ref/source/spl-util.cc
index 7f6adfe75d..abf3ebabc6 100644
--- a/crawl-ref/source/spl-util.cc
+++ b/crawl-ref/source/spl-util.cc
@@ -114,10 +114,10 @@ spell_type spell_by_name(std::string name, bool partial_match)
for (int i = 0; i < NUM_SPELLS; i++)
{
spell_type type = static_cast<spell_type>(i);
- const char *sptitle = spell_title(type);
- if (!sptitle)
+ if (!is_valid_spell(type))
continue;
-
+
+ const char *sptitle = spell_title(type);
const std::string spell_name = lowercase_string(sptitle);
if (spell_name.find(name) != std::string::npos)
diff --git a/crawl-ref/source/travel.cc b/crawl-ref/source/travel.cc
index f48abe8b81..20ec7cd138 100644
--- a/crawl-ref/source/travel.cc
+++ b/crawl-ref/source/travel.cc
@@ -2927,6 +2927,11 @@ level_id level_id::current()
return id;
}
+int level_id::absdepth() const
+{
+ return absdungeon_depth(branch, depth);
+}
+
level_id level_id::get_next_level_id(const coord_def &pos)
{
int gridc = grd[pos.x][pos.y];
diff --git a/crawl-ref/source/travel.h b/crawl-ref/source/travel.h
index 78b924ad66..bada932b2b 100644
--- a/crawl-ref/source/travel.h
+++ b/crawl-ref/source/travel.h
@@ -260,6 +260,8 @@ public:
return (branch < id.branch) || (branch==id.branch && depth < id.depth);
}
+ int absdepth() const;
+
void save(writer&) const;
void load(reader&);
};