summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crawl-ref/docs/options_guide.txt14
-rw-r--r--crawl-ref/settings/init.txt2
-rw-r--r--crawl-ref/source/acr.cc6
-rw-r--r--crawl-ref/source/externs.h4
-rw-r--r--crawl-ref/source/initfile.cc5
-rw-r--r--crawl-ref/source/stash.cc138
-rw-r--r--crawl-ref/source/stash.h15
7 files changed, 177 insertions, 7 deletions
diff --git a/crawl-ref/docs/options_guide.txt b/crawl-ref/docs/options_guide.txt
index 98d5e94395..f2b13e265d 100644
--- a/crawl-ref/docs/options_guide.txt
+++ b/crawl-ref/docs/options_guide.txt
@@ -51,7 +51,8 @@ The contents of this text are:
trap_prompt, rest_wait_both
4-h Stashes.
stash_tracking, stash_filter, annotate_item_class,
- annoate_item_dropped
+ annoate_item_dropped, stash_track_decay,
+ stash_remove_decay
4-i Command Enhancements.
auto_list, easy_open, easy_unequip, easy_confirm,
easy_butcher, always_confirm_butcher, chunks_autopickup,
@@ -882,6 +883,17 @@ annotate_item_dropped = false
init.txt. Annotates dropped items with {dropped} for stash
searching.
+stash_track_decay = false
+ If set to true then the stash tracker will remember how long its
+ been since you've seen chunks of meat or a corpse or skeleton and
+ tell you what state its in by adding "rotten by now",
+ "skeletalised by now" or "gone by now" to its name.
+
+stash_remove_decay = false
+ If both this and stash_track_decay are set to true, anything that
+ would have been reported as "gone by now" will instead be
+ removed from the stash tracker's memory.
+
4-i Command Enhancements.
-----------------------------
diff --git a/crawl-ref/settings/init.txt b/crawl-ref/settings/init.txt
index af9b1a424a..c915c1ac57 100644
--- a/crawl-ref/settings/init.txt
+++ b/crawl-ref/settings/init.txt
@@ -197,6 +197,8 @@ include = travel_stoppers.txt
# stash_filter = 14, 4:21
# annotate_item_class = true
# annotate_item_dropped = true
+# stash_track_decay = true
+# stash_remove_decay = true
##### 4-i Command Enhancements ##################
#
diff --git a/crawl-ref/source/acr.cc b/crawl-ref/source/acr.cc
index 969fff663f..c9dcd815d8 100644
--- a/crawl-ref/source/acr.cc
+++ b/crawl-ref/source/acr.cc
@@ -1441,6 +1441,12 @@ static void _input()
_world_reacts();
return;
}
+ else
+ {
+ // Don't do this while delayed, so as to not slow down resting
+ // and travel by iterating over all stahses once per player turn.
+ StashTrack.update_corpses();
+ }
if ( you.turn_is_over )
{
diff --git a/crawl-ref/source/externs.h b/crawl-ref/source/externs.h
index 102e7f7fc3..6a04a5081b 100644
--- a/crawl-ref/source/externs.h
+++ b/crawl-ref/source/externs.h
@@ -1714,6 +1714,10 @@ public:
int stash_tracking; // How stashes are tracked
+ bool stash_track_decay; // Keep track of how decayed corpses are
+ bool stash_remove_decay; // Remove corpses that have most probably
+ // completely rotted away
+
int tc_reachable; // Colour for squares that are reachable
int tc_excluded; // Colour for excluded squares.
int tc_exclude_circle; // Colour for squares in the exclusion radius
diff --git a/crawl-ref/source/initfile.cc b/crawl-ref/source/initfile.cc
index 1b6b0025ff..3f53faf6bd 100644
--- a/crawl-ref/source/initfile.cc
+++ b/crawl-ref/source/initfile.cc
@@ -738,6 +738,9 @@ void game_options::reset_options()
stash_tracking = STM_ALL;
+ stash_track_decay = false;
+ stash_remove_decay = false;
+
explore_stop = ES_ITEM | ES_STAIR | ES_PORTAL | ES_SHOP | ES_ALTAR
| ES_GREEDY_PICKUP;
@@ -2573,6 +2576,8 @@ void game_options::read_option_line(const std::string &str, bool runscript)
field == "all" ? STM_ALL :
STM_EXPLICIT;
}
+ else BOOL_OPTION(stash_track_decay);
+ else BOOL_OPTION(stash_remove_decay);
else if (key == "stash_filter")
{
std::vector<std::string> seg = split_string(",", field);
diff --git a/crawl-ref/source/stash.cc b/crawl-ref/source/stash.cc
index c6f8bc0ea6..694a2996a4 100644
--- a/crawl-ref/source/stash.cc
+++ b/crawl-ref/source/stash.cc
@@ -25,6 +25,7 @@
#include "menu.h"
#include "message.h"
#include "misc.h"
+#include "mon-util.h"
#include "notes.h"
#include "overmap.h"
#include "place.h"
@@ -49,7 +50,7 @@
StashTracker StashTrack;
#define ST_MAJOR_VER ((unsigned char) 4)
-#define ST_MINOR_VER ((unsigned char) 7)
+#define ST_MINOR_VER ((unsigned char) 8)
void stash_init_new_level()
{
@@ -279,7 +280,7 @@ void Stash::update()
while (objl != NON_ITEM)
{
if (!is_filtered(mitm[objl]))
- items.push_back(mitm[objl]);
+ add_item(mitm[objl]);
objl = mitm[objl].link;
}
@@ -310,7 +311,7 @@ void Stash::update()
if (items.size() == 0)
{
if (!is_filtered(item))
- items.push_back(item);
+ add_item(item);
verified = (item.link == NON_ITEM);
return ;
}
@@ -354,17 +355,61 @@ void Stash::update()
// Items are different. We'll put this item in the front of our
// vector, and mark this as unverified
- items.insert(items.begin(), item);
+ add_item(item, true);
verified = false;
}
}
}
+static bool _is_rottable(const item_def &item)
+{
+ return (item.base_type == OBJ_CORPSES
+ || (item.base_type == OBJ_FOOD && item.sub_type == FOOD_CHUNK));
+}
+
+static short _min_rot(const item_def &item)
+{
+ if (item.base_type == OBJ_FOOD)
+ return 0;
+
+ if (item.base_type == OBJ_CORPSES && item.sub_type == CORPSE_SKELETON)
+ return 0;
+
+ if (!mons_skeleton(item.plus))
+ return 0;
+ else
+ return -200;
+}
+
// Returns the item name for a given item, with any appropriate
// stash-tracking pre/suffixes.
std::string Stash::stash_item_name(const item_def &item)
{
- return item.name(DESC_NOCAP_A);
+ std::string name = item.name(DESC_NOCAP_A);
+
+ if (!Options.stash_track_decay || !_is_rottable(item))
+ return name;
+
+ if (item.plus2 <= _min_rot(item))
+ {
+ name += " (gone by now)";
+ return name;
+ }
+
+ // Skeletons show no signs of rotting before they're gone
+ if (item.base_type == OBJ_CORPSES && item.sub_type == CORPSE_SKELETON)
+ return name;
+
+ // Item was already seen to be rotten
+ if (item.special < 100)
+ return name;
+
+ if (item.plus2 <= 0)
+ name += " (skeletalised by now)";
+ else if (item.plus2 < 100)
+ name += " (rotten by now)";
+
+ return name;
}
class StashMenu : public InvMenu
@@ -544,6 +589,54 @@ bool Stash::matches_search(const std::string &prefix,
return !!res.matches;
}
+void Stash::_update_corpses(long rot_time)
+{
+ for (int i = items.size() - 1; i >= 0; i--)
+ {
+ item_def &item = items[i];
+
+ if (!_is_rottable(item))
+ continue;
+
+ long new_rot = static_cast<long>(item.plus2) - rot_time;
+
+ if (new_rot <= _min_rot(item))
+ {
+ if (Options.stash_remove_decay)
+ {
+ items.erase(items.begin() + i);
+ continue;
+ }
+ new_rot = _min_rot(item);
+ }
+ item.plus2 = static_cast<short>(new_rot);
+ }
+}
+
+void Stash::add_item(const item_def &item, bool add_to_front)
+{
+ if (add_to_front)
+ items.insert(items.begin(), item);
+ else
+ items.push_back(item);
+
+ if (!_is_rottable(item))
+ return;
+
+ // item.special remains unchanged in the stash, to show how fresh it
+ // was when last seen. It's plus2 that's decayed over time.
+ if (add_to_front)
+ {
+ item_def &it = items.front();
+ it.plus2 = it.special;
+ }
+ else
+ {
+ item_def &it = items.back();
+ it.plus2 = it.special;
+ }
+}
+
void Stash::write(std::ostream &os, int refx, int refy,
std::string place, bool identify)
const
@@ -1128,6 +1221,15 @@ void LevelStashes::get_matching_stashes(
}
}
+void LevelStashes::_update_corpses(long rot_time)
+{
+ for (stashes_t::iterator iter = m_stashes.begin();
+ iter != m_stashes.end(); iter++)
+ {
+ iter->second._update_corpses(rot_time);
+ }
+}
+
void LevelStashes::write(std::ostream &os, bool identify) const
{
if (visible_stash_count() == 0)
@@ -1299,6 +1401,9 @@ void StashTracker::save(writer& outf) const
marshallByte(outf, ST_MAJOR_VER);
marshallByte(outf, ST_MINOR_VER);
+ // Time of last corpse update.
+ marshallFloat(outf, (float) last_corpse_update);
+
// How many levels have we?
marshallShort(outf, (short) levels.size());
@@ -1316,6 +1421,9 @@ void StashTracker::load(reader& inf)
minor = unmarshallByte(inf);
if (major != ST_MAJOR_VER || minor != ST_MINOR_VER) return ;
+ // Time of last corpse update.
+ last_corpse_update = (double) unmarshallFloat(inf);
+
int count = unmarshallShort(inf);
levels.clear();
@@ -1742,3 +1850,23 @@ bool StashTracker::display_search_results(
}
return false;
}
+
+void StashTracker::update_corpses()
+{
+ if (!Options.stash_track_decay)
+ return;
+
+ if (you.elapsed_time - last_corpse_update < 20.0)
+ return;
+
+ const long rot_time = static_cast<long>((you.elapsed_time -
+ last_corpse_update) / 20.0);
+
+ last_corpse_update = you.elapsed_time;
+
+ for (stash_levels_t::iterator iter = levels.begin();
+ iter != levels.end(); iter++)
+ {
+ iter->second._update_corpses(rot_time);
+ }
+}
diff --git a/crawl-ref/source/stash.h b/crawl-ref/source/stash.h
index 8ca50d0ca3..570a611257 100644
--- a/crawl-ref/source/stash.h
+++ b/crawl-ref/source/stash.h
@@ -90,6 +90,10 @@ public:
// also never removed from the level's map of
// stashes.
private:
+ void _update_corpses(long rot_time);
+ void add_item(const item_def &item, bool add_to_front = false);
+
+private:
bool verified; // Is this correct to the best of our knowledge?
unsigned char x, y;
int abspos;
@@ -109,6 +113,8 @@ private:
static bool are_items_same(const item_def &, const item_def &);
static bool is_filtered(const item_def &item);
+
+ friend class LevelStashes;
};
class ShopInfo
@@ -247,6 +253,7 @@ public:
private:
int _num_enabled_stashes() const;
+ void _update_corpses(long rot_time);
private:
typedef std::map<int, Stash> stashes_t;
@@ -256,6 +263,8 @@ public:
level_id m_place;
stashes_t m_stashes;
shops_t m_shops;
+
+ friend class StashTracker;
};
extern std::ostream &operator << (std::ostream &, const LevelStashes &);
@@ -269,7 +278,7 @@ public:
|| you.level_type == LEVEL_ABYSS;
}
- StashTracker() : levels()
+ StashTracker() : levels(), last_corpse_update(0.0)
{
}
@@ -294,6 +303,8 @@ public:
// previously marked as stashes.
};
+ void update_corpses();
+
void update_visible_stashes(StashTracker::stash_update_mode = ST_PASSIVE);
// Update stash at (x,y) on current level, defaulting to player's current
@@ -326,6 +337,8 @@ private:
private:
typedef std::map<level_id, LevelStashes> stash_levels_t;
stash_levels_t levels;
+
+ double last_corpse_update;
};
extern StashTracker StashTrack;