summaryrefslogtreecommitdiffstats
path: root/crawl-ref
diff options
context:
space:
mode:
Diffstat (limited to 'crawl-ref')
-rw-r--r--crawl-ref/source/acr.cc30
-rw-r--r--crawl-ref/source/monstuff.cc7
-rw-r--r--crawl-ref/source/player.cc57
-rw-r--r--crawl-ref/source/player.h1
-rw-r--r--crawl-ref/source/spells3.cc22
5 files changed, 113 insertions, 4 deletions
diff --git a/crawl-ref/source/acr.cc b/crawl-ref/source/acr.cc
index c52b723e25..fa477bac6d 100644
--- a/crawl-ref/source/acr.cc
+++ b/crawl-ref/source/acr.cc
@@ -1231,6 +1231,7 @@ bool apply_berserk_penalty = false;
static void input()
{
crawl_state.clear_god_acting();
+ check_beholders();
if (crawl_state.is_replaying_keys() && crawl_state.is_repeating_cmd()
&& kbhit())
@@ -1454,11 +1455,26 @@ static bool toggle_flag( bool* flag, const char* flagname )
return *flag;
}
+static bool stairs_check_beheld()
+{
+ if (you.duration[DUR_BEHELD] && !you.duration[DUR_CONF])
+ {
+ mprf("You cannot move away from %s!",
+ menv[you.beheld_by[0]].name(DESC_NOCAP_THE, true).c_str());
+ return true;
+ }
+
+ return false;
+}
+
static void go_downstairs();
static void go_upstairs()
{
const dungeon_feature_type ygrd = grd(you.pos());
+ if (stairs_check_beheld())
+ return;
+
// Allow both < and > to work for Abyss exits.
if (ygrd == DNGN_EXIT_ABYSS)
{
@@ -1500,6 +1516,10 @@ static void go_downstairs()
bool shaft = (trap_type_at_xy(you.x_pos, you.y_pos) == TRAP_SHAFT
&& grd[you.x_pos][you.y_pos] != DNGN_UNDISCOVERED_TRAP);
+
+ if (stairs_check_beheld())
+ return;
+
if (shaft && you.flies() == FL_LEVITATE)
{
mpr("You can't fall through a shaft while levitating.");
@@ -3663,14 +3683,16 @@ static void move_player(int move_x, int move_y)
{
for (unsigned int i = 0; i < you.beheld_by.size(); i++)
{
- coord_def pos = menv[you.beheld_by[i]].pos();
+ monsters* mon = &menv[you.beheld_by[i]];
+ coord_def pos = mon->pos();
int olddist = distance(you.x_pos, you.y_pos, pos.x, pos.y);
- int newdist = distance(you.x_pos + move_x, you.y_pos + move_y, pos.x, pos.y);
-
+ int newdist = distance(you.x_pos + move_x, you.y_pos + move_y,
+ pos.x, pos.y);
+
if (olddist < newdist)
{
mprf("You cannot move away from %s!",
- (menv[you.beheld_by[i]]).name(DESC_NOCAP_THE, true).c_str());
+ mon->name(DESC_NOCAP_THE, true).c_str());
move_x = 0;
move_y = 0;
diff --git a/crawl-ref/source/monstuff.cc b/crawl-ref/source/monstuff.cc
index 98ccfbf0f0..f46c35fed0 100644
--- a/crawl-ref/source/monstuff.cc
+++ b/crawl-ref/source/monstuff.cc
@@ -1166,6 +1166,13 @@ bool monster_polymorph( monsters *monster, monster_type targetc,
bool player_messaged =
simple_monster_message(monster, str_polymon.c_str() );
+ // Even if the monster transforms from one type that can behold the
+ // player into a different type which can also behold the player,
+ // the polymoprh disrupts the beholding process. Do this before
+ // changing monster->type, since unbeholding can only happen while
+ // monster is still a mermaid.
+ update_beholders(monster, true);
+
// the actual polymorphing:
const int old_hp = monster->hit_points;
const int old_hp_max = monster->max_hit_points;
diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc
index 77a94ded67..d137d8f1b6 100644
--- a/crawl-ref/source/player.cc
+++ b/crawl-ref/source/player.cc
@@ -2399,6 +2399,63 @@ void update_beholders(const monsters *mon, bool force)
}
}
+void check_beholders()
+{
+ for (int i = you.beheld_by.size() - 1; i >= 0; i--)
+ {
+ const monsters* mon = &menv[you.beheld_by[i]];
+ if (!mon->alive() || mon->type != MONS_MERMAID)
+ {
+#if DEBUG
+ if (!mon->alive())
+ mpr("Dead mermaid still beholding?", MSGCH_DIAGNOSTICS);
+ else if (mon->type != MONS_MERMAID)
+ mprf(MSGCH_DIAGNOSTICS, "Non-mermaid '%s' beholding?",
+ mon->name(DESC_PLAIN, true).c_str());
+#endif
+
+ you.beheld_by.erase(you.beheld_by.begin() + i);
+ if (you.beheld_by.empty())
+ {
+ mpr("You are no longer entranced.", MSGCH_RECOVERY);
+ you.duration[DUR_BEHELD] = 0;
+ break;
+ }
+ continue;
+ }
+ const coord_def pos = mon->pos();
+ int walls = num_feats_between(you.x_pos, you.y_pos,
+ pos.x, pos.y, DNGN_UNSEEN,
+ DNGN_MAXWALL);
+
+ if (walls > 0)
+ {
+#if DEBUG
+ mprf(MSGCH_DIAGNOSTICS, "%d walls between beholding '%s' "
+ "and player", walls, mon->name(DESC_PLAIN, true).c_str());
+#endif
+ you.beheld_by.erase(you.beheld_by.begin() + i);
+ if (you.beheld_by.empty())
+ {
+ mpr("You are no longer entranced.", MSGCH_RECOVERY);
+ you.duration[DUR_BEHELD] = 0;
+ break;
+ }
+ continue;
+ }
+ }
+
+ if (you.duration[DUR_BEHELD] > 0 && you.beheld_by.empty())
+ {
+#if DEBUG
+ mpr("Beheld with no mermaids left?", MSGCH_DIAGNOSTICS);
+#endif
+
+ mpr("You are no longer entranced.", MSGCH_RECOVERY);
+ you.duration[DUR_BEHELD] = 0;
+ }
+}
+
int player_sust_abil(bool calc_unid)
{
int sa = 0;
diff --git a/crawl-ref/source/player.h b/crawl-ref/source/player.h
index 95e35193f9..fcfcb6a0c1 100644
--- a/crawl-ref/source/player.h
+++ b/crawl-ref/source/player.h
@@ -265,6 +265,7 @@ bool player_monster_visible( const monsters *mon );
bool player_beheld_by( const monsters *mon );
void update_beholders( const monsters *mon, bool force = false);
+void check_beholders();
/* ***********************************************************************
* called from: acr - decks - it_use2 - ouch
diff --git a/crawl-ref/source/spells3.cc b/crawl-ref/source/spells3.cc
index f35ae60e35..9bbb8789e5 100644
--- a/crawl-ref/source/spells3.cc
+++ b/crawl-ref/source/spells3.cc
@@ -766,7 +766,29 @@ bool entomb(int powc)
}
if (number_built > 0)
+ {
mpr("Walls emerge from the floor!");
+
+ for (int i = you.beheld_by.size() - 1; i >= 0; i--)
+ {
+ const monsters* mon = &menv[you.beheld_by[i]];
+ const coord_def pos = mon->pos();
+ int walls = num_feats_between(you.x_pos, you.y_pos,
+ pos.x, pos.y, DNGN_UNSEEN,
+ DNGN_MAXWALL);
+
+ if (walls > 0)
+ {
+ update_beholders(mon, true);
+ if (you.beheld_by.empty())
+ {
+ you.duration[DUR_BEHELD] = 0;
+ break;
+ }
+ continue;
+ }
+ }
+ }
else
canned_msg(MSG_NOTHING_HAPPENS);