summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/godcompanions.cc
diff options
context:
space:
mode:
authorNicholas Feinberg <pleasingfung@gmail.com>2014-06-22 16:57:57 -0700
committerNicholas Feinberg <pleasingfung@gmail.com>2014-06-22 16:59:12 -0700
commitc76c7bb6881a3b5127f762cadb91379564033b49 (patch)
tree4b2cbdd642875675757e896bbd014262675c319a /crawl-ref/source/godcompanions.cc
parent3dc87739768dc6fa52fe3f348614188964a58dc6 (diff)
downloadcrawl-ref-c76c7bb6881a3b5127f762cadb91379564033b49.tar.gz
crawl-ref-c76c7bb6881a3b5127f762cadb91379564033b49.zip
Fix a crash when recalling monsters onto shafts (8717)
Also removes a layer of indentation from recall_offlevel_ally(); apologies for the messy diff!
Diffstat (limited to 'crawl-ref/source/godcompanions.cc')
-rw-r--r--crawl-ref/source/godcompanions.cc71
1 files changed, 42 insertions, 29 deletions
diff --git a/crawl-ref/source/godcompanions.cc b/crawl-ref/source/godcompanions.cc
index 466d8ac02c..9b655ebed3 100644
--- a/crawl-ref/source/godcompanions.cc
+++ b/crawl-ref/source/godcompanions.cc
@@ -123,49 +123,62 @@ void populate_offlevel_recall_list(vector<pair<mid_t, int> > &recall_list)
}
}
+/**
+ * Attempt to recall an ally from offlevel.
+ *
+ * @param mid The ID of the monster to be recalled.
+ * @return Whether the monster was successfully recalled onto the level.
+ * Note that the monster may not still be alive or onlevel, due to shafts, etc,
+ * but they were here at least briefly!
+ */
bool recall_offlevel_ally(mid_t mid)
{
if (!companion_is_elsewhere(mid, true))
return false;
companion* comp = &companion_list[mid];
- if (comp->mons.place(true))
- {
- monster* mons = monster_by_mid(mid);
+ if (!comp->mons.place(true))
+ return false;
- // The monster is now on this level
- remove_monster_from_transit(comp->level, mid);
- comp->level = level_id::current();
- simple_monster_message(mons, " is recalled.");
+ monster* mons = monster_by_mid(mid);
- // Catch up time for off-level monsters
- // (We move the player away so that we don't get expiry
- // messages for things that supposed wore off ages ago)
- const coord_def old_pos = you.pos();
- you.moveto(coord_def(0, 0));
+ // The monster is now on this level
+ remove_monster_from_transit(comp->level, mid);
+ comp->level = level_id::current();
+ simple_monster_message(mons, " is recalled.");
- int turns = you.elapsed_time - comp->timestamp;
- // Note: these are auts, not turns, thus healing is 10 times as fast as
- // for other monsters, confusion goes away after a single turn, etc.
+ // Now that the monster is onlevel, we can safely apply traps to it.
+ // old location isn't very meaningful, so use current loc
+ mons->apply_location_effects(mons->pos());
+ // check if it was killed/shafted by a trap...
+ if (!mons->alive())
+ return true; // still successfully recalled!
- mons->heal(div_rand_round(turns * mons->off_level_regen_rate(), 100));
+ // Catch up time for off-level monsters
+ // (We move the player away so that we don't get expiry
+ // messages for things that supposed wore off ages ago)
+ const coord_def old_pos = you.pos();
+ you.moveto(coord_def(0, 0));
- if (turns >= 10 && mons->alive())
- {
- // Remove confusion manually (so that the monster
- // doesn't blink after being recalled)
- mons->del_ench(ENCH_CONFUSION, true);
- mons->timeout_enchantments(turns / 10);
- }
- you.moveto(old_pos);
- // Do this after returning the player to the proper position
- // because it uses player position
- recall_orders(mons);
+ int turns = you.elapsed_time - comp->timestamp;
+ // Note: these are auts, not turns, thus healing is 10 times as fast as
+ // for other monsters, confusion goes away after a single turn, etc.
+
+ mons->heal(div_rand_round(turns * mons->off_level_regen_rate(), 100));
- return true;
+ if (turns >= 10 && mons->alive())
+ {
+ // Remove confusion manually (so that the monster
+ // doesn't blink after being recalled)
+ mons->del_ench(ENCH_CONFUSION, true);
+ mons->timeout_enchantments(turns / 10);
}
+ you.moveto(old_pos);
+ // Do this after returning the player to the proper position
+ // because it uses player position
+ recall_orders(mons);
- return false;
+ return true;
}
bool companion_is_elsewhere(mid_t mid, bool must_exist)