summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source
diff options
context:
space:
mode:
authorzelgadis <zelgadis@c06c8d41-db1a-0410-9941-cceddc491573>2008-06-12 00:02:52 +0000
committerzelgadis <zelgadis@c06c8d41-db1a-0410-9941-cceddc491573>2008-06-12 00:02:52 +0000
commit510a5b2129d86a9c6591e701725379f6f1a6a67f (patch)
tree603269f3c6af78668bbb23a96ed19bf2ea19718b /crawl-ref/source
parent9fd7f5bc149e7fa7ae2597bc39ca7fd348997424 (diff)
downloadcrawl-ref-510a5b2129d86a9c6591e701725379f6f1a6a67f.tar.gz
crawl-ref-510a5b2129d86a9c6591e701725379f6f1a6a67f.zip
Bug 1990763: if a monster tries to unsubmerge while under the player,
attempt to move it to an adjacent square before doing so. If there are no appropriate adjacent squares then try to make it stay submerged. If it can't stay submerged because the terrain changed then teleport it away. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@5738 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref/source')
-rw-r--r--crawl-ref/source/mon-util.cc95
-rw-r--r--crawl-ref/source/monplace.cc2
-rw-r--r--crawl-ref/source/monstuff.cc19
-rw-r--r--crawl-ref/source/terrain.cc13
-rw-r--r--crawl-ref/source/view.cc5
5 files changed, 117 insertions, 17 deletions
diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc
index d89a16e0fd..9d87f166eb 100644
--- a/crawl-ref/source/mon-util.cc
+++ b/crawl-ref/source/mon-util.cc
@@ -4907,6 +4907,81 @@ void monsters::add_enchantment_effect(const mon_enchant &ench, bool quiet)
}
}
+static bool _prepare_del_ench(monsters* mons, const mon_enchant &me)
+{
+ if (me.ench != ENCH_SUBMERGED)
+ return true;
+
+ if (mons->pos() != you.pos())
+ return true;
+
+ // Monster un-submerging while under player. Try to move to an
+ // adjacent square in which the monster could have been submerged
+ // and have it unusbmerge from there.
+ coord_def pos, target_square;
+ int okay_squares = 0;
+
+ for (pos.x = you.x_pos - 1; pos.x <= you.x_pos + 1; pos.x++)
+ for (pos.y = you.y_pos - 1; pos.y <= you.y_pos + 1; pos.y++)
+ {
+ if (pos == you.pos())
+ continue;
+
+ if (in_bounds(pos) && mgrd(pos) == NON_MONSTER
+ && monster_can_submerge(mons, grd(pos)))
+ {
+ if (one_chance_in(++okay_squares))
+ target_square = pos;
+ }
+ }
+
+ if (okay_squares > 0)
+ {
+ int mnum = mgrd(mons->pos());
+ mgrd(mons->pos()) = NON_MONSTER;
+
+ mgrd(target_square) = mnum;
+ mons->x = target_square.x;
+ mons->y = target_square.y;
+
+ return true;
+ }
+
+ // No available adjacent squares from which the monster could also
+ // have unsubmerged. Can it just stay submerged where it is?
+ if ( monster_can_submerge(mons, grd( mons->pos() )) )
+ return false;
+
+ // The terrain changed and the monster can't remain submerged.
+ // Try to move to an adjacent square where it would be happy.
+ for (pos.x = you.x_pos - 1; pos.x <= you.x_pos + 1; pos.x++)
+ for (pos.y = you.y_pos - 1; pos.y <= you.y_pos + 1; pos.y++)
+ {
+ if (pos == you.pos())
+ continue;
+
+ if (in_bounds(pos) && mgrd(pos) == NON_MONSTER
+ && monster_habitable_grid(mons, grd(pos))
+ && trap_type_at_xy(pos.x, pos.y) == NUM_TRAPS)
+ {
+ if (one_chance_in(++okay_squares))
+ target_square = pos;
+ }
+ }
+
+ if (okay_squares > 0)
+ {
+ int mnum = mgrd(mons->pos());
+ mgrd(mons->pos()) = NON_MONSTER;
+
+ mgrd(target_square) = mnum;
+ mons->x = target_square.x;
+ mons->y = target_square.y;
+ }
+
+ return ( true );
+}
+
bool monsters::del_ench(enchant_type ench, bool quiet, bool effect)
{
mon_enchant_list::iterator i = enchantments.find(ench);
@@ -4915,6 +4990,10 @@ bool monsters::del_ench(enchant_type ench, bool quiet, bool effect)
const mon_enchant me = i->second;
const enchant_type et = i->first;
+
+ if (!_prepare_del_ench(this, me))
+ return false;
+
enchantments.erase(et);
if (effect)
remove_enchantment_effect(me, quiet);
@@ -5061,6 +5140,16 @@ void monsters::remove_enchantment_effect(const mon_enchant &me, bool quiet)
break;
case ENCH_SUBMERGED:
+ if (behaviour == BEH_WANDER)
+ {
+ behaviour = BEH_SEEK;
+ behaviour_event(this, ME_EVAL);
+ }
+
+ if (you.pos() == this->pos())
+ mprf(MSGCH_ERROR, "%s is on the same square as you!",
+ name(DESC_CAP_A).c_str());
+
if (you.can_see(this))
{
if (!mons_is_safe( static_cast<const monsters*>(this))
@@ -5099,12 +5188,6 @@ void monsters::remove_enchantment_effect(const mon_enchant &me, bool quiet)
interrupt_activity( AI_FORCE_INTERRUPT );
}
- if (behaviour == BEH_WANDER)
- {
- behaviour = BEH_SEEK;
- behaviour_event(this, ME_EVAL);
- }
-
break;
default:
diff --git a/crawl-ref/source/monplace.cc b/crawl-ref/source/monplace.cc
index e5f46985b6..b007d5374b 100644
--- a/crawl-ref/source/monplace.cc
+++ b/crawl-ref/source/monplace.cc
@@ -159,7 +159,7 @@ bool monster_habitable_grid(int monster_class,
bool monster_can_submerge(const monsters *mons, dungeon_feature_type grid)
{
if (mons->type == MONS_TRAPDOOR_SPIDER && grid == DNGN_FLOOR)
- return (true);
+ return (trap_type_at_xy(mons->x, mons->y) == NUM_TRAPS);
// Zombies of watery critters can not submerge.
switch (mons_habitat(mons))
diff --git a/crawl-ref/source/monstuff.cc b/crawl-ref/source/monstuff.cc
index 8aeb15df70..d6a0f29e54 100644
--- a/crawl-ref/source/monstuff.cc
+++ b/crawl-ref/source/monstuff.cc
@@ -2182,7 +2182,9 @@ void behaviour_event( monsters *mon, int event, int src,
default:
if (mon->has_ench(ENCH_SUBMERGED))
- mon->del_ench(ENCH_SUBMERGED);
+ if(!mon->del_ench(ENCH_SUBMERGED))
+ // Couldn't unsubmerge.
+ mon->behaviour = BEH_LURK;
break;
}
}
@@ -5639,18 +5641,21 @@ static void _handle_monster_move(int i, monsters *monster)
{
if (monster->has_ench(ENCH_SUBMERGED))
{
- // Don't unsubmerge if the player is right on top,
- // if the monster is too damaged or if the monster
- // is afraid.
- if (monster->pos() == you.pos()
- || monster->hit_points <= monster->max_hit_points / 2
+ // Don't unsubmerge if the monster is too damaged or
+ // if the monster is afraid.
+ if (monster->hit_points <= monster->max_hit_points / 2
|| monster->has_ench(ENCH_FEAR))
{
monster->speed_increment -= non_move_energy;
continue;
}
- monster->del_ench(ENCH_SUBMERGED);
+ if (!monster->del_ench(ENCH_SUBMERGED))
+ {
+ // Couldn't unsubmerge.
+ monster->speed_increment -= non_move_energy;
+ continue;
+ }
}
monster->behaviour = BEH_SEEK;
}
diff --git a/crawl-ref/source/terrain.cc b/crawl-ref/source/terrain.cc
index c1cb3097cf..2ae8d1c2d6 100644
--- a/crawl-ref/source/terrain.cc
+++ b/crawl-ref/source/terrain.cc
@@ -432,8 +432,7 @@ static void _dgn_check_terrain_monsters(const coord_def &pos)
monsters *mons = &menv[mindex];
if (mons->has_ench(ENCH_SUBMERGED)
- && !monster_can_submerge(mons, grd(pos))
- && pos != you.pos())
+ && !monster_can_submerge(mons, grd(pos)))
{
mons->del_ench(ENCH_SUBMERGED);
}
@@ -504,7 +503,17 @@ void dungeon_terrain_changed(const coord_def &pos,
if (!grid_is_solid(grd(pos)))
{
if (!you.airborne())
+ {
+ // If the monster can't stay submerged in the new terrain
+ // and there aren't any adjacent squares where it can
+ // stay submerged then move it.
+ if (mgrd(you.pos()) != NON_MONSTER
+ && !mons_is_submerged( &menv[ mgrd(you.pos()) ] ))
+ {
+ monster_teleport( &menv[ mgrd(you.pos()) ], true, false);
+ }
move_player_to_grid(pos.x, pos.y, false, true, false);
+ }
}
else
you_teleport_now(true, false);
diff --git a/crawl-ref/source/view.cc b/crawl-ref/source/view.cc
index 61d2bb6821..84be11376f 100644
--- a/crawl-ref/source/view.cc
+++ b/crawl-ref/source/view.cc
@@ -1063,7 +1063,10 @@ void handle_monster_shouts(monsters* monster, bool force)
// shout.
if (mons_is_submerged(monster))
{
- monster->del_ench(ENCH_SUBMERGED);
+ if (!monster->del_ench(ENCH_SUBMERGED))
+ // Couldn't unsubmerge.
+ return;
+
if (you.can_see(monster))
{
monster->seen_context = "bursts forth shouting";