summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/travel.cc
diff options
context:
space:
mode:
Diffstat (limited to 'crawl-ref/source/travel.cc')
-rw-r--r--crawl-ref/source/travel.cc90
1 files changed, 82 insertions, 8 deletions
diff --git a/crawl-ref/source/travel.cc b/crawl-ref/source/travel.cc
index 4dbbce3a68..e7f9d11f87 100644
--- a/crawl-ref/source/travel.cc
+++ b/crawl-ref/source/travel.cc
@@ -424,6 +424,7 @@ void clear_excludes()
toggle_exclude(curr_excludes[i].pos);
#endif
curr_excludes.clear();
+ clear_level_exclusion_annotation();
if (can_travel_interlevel())
{
@@ -456,19 +457,20 @@ void cycle_exclude_radius(const coord_def &p)
}
}
-void toggle_exclude(const coord_def &p)
+void toggle_exclude(const coord_def &p, bool autoexcl)
{
if (is_exclude_root(p))
set_exclude(p, 0);
else
- set_exclude(p, LOS_RADIUS);
+ set_exclude(p, LOS_RADIUS, autoexcl);
#ifdef USE_TILE
_tile_exclude_gmap_update(p);
#endif
+ set_level_exclusion_annotation(get_exclusion_desc());
}
-void set_exclude(const coord_def &p, int radius)
+void set_exclude(const coord_def &p, int radius, bool autoexcl)
{
// Sanity checks; excludes can be set in Pan and regular dungeon
// levels only.
@@ -499,7 +501,12 @@ void set_exclude(const coord_def &p, int radius)
}
else
{
- curr_excludes.push_back(travel_exclude(p, radius));
+ int montype = NON_MONSTER;
+ const monsters *m = monster_at(p);
+ if (m && mons_near(m) && you.can_see(m))
+ montype = m->type;
+
+ curr_excludes.push_back(travel_exclude(p, radius, autoexcl, montype));
}
if (can_travel_interlevel())
@@ -509,6 +516,64 @@ void set_exclude(const coord_def &p, int radius)
}
}
+// If a grid that was placed automatically no longer contains the original
+// monster (or it is invisible), remove the exclusion.
+void maybe_remove_autoexclusion(const coord_def &p)
+{
+ ASSERT(in_bounds(p) && see_grid(p) && is_exclude_root(p));
+
+ for (int i = 0, count = curr_excludes.size(); i < count; ++i)
+ {
+ if (curr_excludes[i].pos == p)
+ {
+ if (curr_excludes[i].autoexclude)
+ {
+ const monsters *m = monster_at(p);
+ if (!m || !you.can_see(m) || m->type != curr_excludes[i].mon)
+ {
+ set_exclude(p, 0);
+ set_level_exclusion_annotation(get_exclusion_desc());
+ }
+ }
+ break;
+ }
+ }
+}
+
+// Lists alls exclusions on the current level.
+std::string get_exclusion_desc()
+{
+ std::vector<std::string> monsters;
+ int count_other = 0;
+ for (int i = 0, count = curr_excludes.size(); i < count; ++i)
+ {
+ if (curr_excludes[i].mon != NON_MONSTER)
+ monsters.push_back(get_monster_data(curr_excludes[i].mon)->name);
+ else
+ count_other++;
+ }
+
+ if (count_other > 0)
+ {
+ snprintf(info, INFO_SIZE, "%d %sexclusion%s",
+ count_other, monsters.empty() ? "" : "more ",
+ count_other > 1 ? "s" : "");
+ monsters.push_back(info);
+ }
+ else if (monsters.empty())
+ return "";
+
+ std::string desc = "";
+ if (monsters.size() > 1 || count_other == 0)
+ {
+ snprintf(info, INFO_SIZE, "exclusion%s: ",
+ monsters.size() > 1 ? "s" : "");
+ desc += info;
+ }
+ return (desc + comma_separated_line(monsters.begin(), monsters.end(),
+ ", and ", ", "));
+}
+
static bool _is_monster_blocked(const coord_def& c)
{
const monsters *mons = monster_at(c);
@@ -3595,11 +3660,13 @@ void LevelInfo::save(writer& outf) const
{
marshallCoord(outf, excludes[i].pos);
marshallShort(outf, excludes[i].radius);
+ marshallBoolean(outf, excludes[i].autoexclude);
+ marshallShort(outf, excludes[i].mon);
}
}
}
-void LevelInfo::load(reader& inf)
+void LevelInfo::load(reader& inf, char minorVersion)
{
stairs.clear();
int stair_count = unmarshallShort(inf);
@@ -3635,7 +3702,14 @@ void LevelInfo::load(reader& inf)
coord_def c;
unmarshallCoord(inf, c);
const int radius = unmarshallShort(inf);
- excludes.push_back(travel_exclude(c, radius));
+ bool autoexcl = false;
+ int mon = NON_MONSTER;
+ if (minorVersion >= TAG_ANNOTATE_EXCL)
+ {
+ autoexcl = unmarshallBoolean(inf);
+ mon = unmarshallShort(inf);
+ }
+ excludes.push_back(travel_exclude(c, radius, autoexcl, mon));
}
}
}
@@ -3897,7 +3971,7 @@ void TravelCache::save(writer& outf) const
waypoints[wp].save(outf);
}
-void TravelCache::load(reader& inf)
+void TravelCache::load(reader& inf, char minorVersion)
{
levels.clear();
@@ -3916,7 +3990,7 @@ void TravelCache::load(reader& inf)
// Must set id before load, or travel_hell_entry will not be
// correctly set.
linfo.id = id;
- linfo.load(inf);
+ linfo.load(inf, minorVersion);
levels[id] = linfo;
}