summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crawl-ref/source/acr.cc10
-rw-r--r--crawl-ref/source/beam.cc60
-rw-r--r--crawl-ref/source/fight.cc44
-rw-r--r--crawl-ref/source/mon-data.h5
-rw-r--r--crawl-ref/source/mon-util.cc2
-rw-r--r--crawl-ref/source/mon-util.h2
-rw-r--r--crawl-ref/source/monplace.cc13
-rw-r--r--crawl-ref/source/monstuff.cc12
-rw-r--r--crawl-ref/source/terrain.cc9
-rw-r--r--crawl-ref/source/terrain.h5
10 files changed, 145 insertions, 17 deletions
diff --git a/crawl-ref/source/acr.cc b/crawl-ref/source/acr.cc
index 515d82eb04..5af97eb4a9 100644
--- a/crawl-ref/source/acr.cc
+++ b/crawl-ref/source/acr.cc
@@ -3223,7 +3223,6 @@ static void open_door(int move_x, int move_y, bool check_confused)
if (mon != NON_MONSTER && player_can_hit_monster(&menv[mon]))
{
-
if (mons_is_caught(&menv[mon]))
{
@@ -3737,6 +3736,11 @@ static void move_player(int move_x, int move_y)
}
else // attack!
{
+ // XXX: Moving into a normal wall does nothing and uses no
+ // turns or energy, but moving into a wall which contains
+ // an invisible monster attacks the monster, thus allowing
+ // the player to figure out which adjacent wall an invis
+ // monster is in "for free".
you_attack( targ_monst, true );
you.turn_is_over = true;
@@ -3772,9 +3776,9 @@ static void move_player(int move_x, int move_y)
}
// BCR - Easy doors single move
- if (targ_grid == DNGN_CLOSED_DOOR && Options.easy_open)
+ if (targ_grid == DNGN_CLOSED_DOOR && Options.easy_open && !attacking)
open_door(move_x, move_y, false);
- else if (!targ_pass)
+ else if (!targ_pass && !attacking)
{
stop_running();
diff --git a/crawl-ref/source/beam.cc b/crawl-ref/source/beam.cc
index 6a497e9aba..b3879d27a4 100644
--- a/crawl-ref/source/beam.cc
+++ b/crawl-ref/source/beam.cc
@@ -1240,6 +1240,32 @@ static void zappy( zap_type z_type, int power, bolt &pbolt )
*/
+// Affect monster in wall unless it can shield itself using the wall
+// (M_WALL_SHIELDED). The wall will always shield the monster if the
+// beam bounces off the wall, and a monster can't use a metal wall to
+// shield itself from electricty.
+static bool affect_mon_in_wall(bolt &pbolt, item_def *item, int tx, int ty)
+{
+ UNUSED(item);
+
+ int mid = mgrd[tx][ty];
+
+ if (mid == NON_MONSTER)
+ return false;
+
+ if (pbolt.is_enchant
+ || (!pbolt.is_explosion && !pbolt.is_big_cloud
+ && (grd[tx][ty] != DNGN_METAL_WALL
+ || !pbolt.flavour != BEAM_ELECTRICITY)))
+ {
+ monsters *mons = &menv[mid];
+ if (!mons_class_flag(mons->type, M_WALL_SHIELDED))
+ return true;
+ }
+
+ return false;
+}
+
/*
* Beam pseudo code:
*
@@ -1350,6 +1376,12 @@ void fire_beam( bolt &pbolt, item_def *item )
// should we ever get a tracer with a wall-affecting
// beam (possible I suppose), we'll quit tracing now.
if (!pbolt.is_tracer)
+ {
+ pbolt.is_tracer = false;
+ rangeRemaining -= affect(pbolt, tx, ty);
+ pbolt.is_tracer = true;
+ }
+ else
rangeRemaining -= affect(pbolt, tx, ty);
// if it's still a wall, quit.
@@ -1358,9 +1390,13 @@ void fire_beam( bolt &pbolt, item_def *item )
}
else
{
- // BEGIN bounce case
+ // BEGIN bounce case. Bouncing protects any monster
+ // in the wall.
if (!isBouncy(pbolt, grd[tx][ty]))
{
+ // Affect any monster that might be in the wall.
+ rangeRemaining -= affect(pbolt, tx, ty);
+
do
ray.regress();
while (grid_is_solid(grd(ray.pos())));
@@ -2491,10 +2527,28 @@ int affect(bolt &beam, int x, int y)
{
rangeUsed += affect_wall(beam, x, y);
}
- // if it's still a wall, quit - we can't do anything else to
- // a wall. Otherwise effects (like clouds, etc) are still possible.
+ // if it's still a wall, quit - we can't do anything else to a
+ // wall (but we still might be able to do something to any
+ // monster inside the wall). Otherwise effects (like clouds,
+ // etc) are still possible.
if (grid_is_solid(grd[x][y]))
+ {
+ int mid = mgrd[x][y];
+ if (mid != NON_MONSTER)
+ {
+ monsters *mon = &menv[mid];
+ if (affect_mon_in_wall(beam, NULL, x, y))
+ rangeUsed += affect_monster( beam, mon );
+ else if (you.can_see(mon))
+ {
+ mprf("The %s protects %s from harm.",
+ raw_feature_description(grd(mon->pos())).c_str(),
+ mon->name(DESC_NOCAP_THE).c_str());
+ }
+ }
+
return (rangeUsed);
+ }
}
// grd[x][y] will NOT be a wall for the remainder of this function.
diff --git a/crawl-ref/source/fight.cc b/crawl-ref/source/fight.cc
index 50b5869f77..a77844f618 100644
--- a/crawl-ref/source/fight.cc
+++ b/crawl-ref/source/fight.cc
@@ -505,6 +505,50 @@ bool melee_attack::attack()
xom_is_stimulated(128);
}
+ // Defending monster protects itself from attacks using the
+ // wall it's in.
+ if (defender->atype() == ACT_MONSTER && grid_is_solid(def->pos())
+ && mons_class_flag(def->type, M_WALL_SHIELDED))
+ {
+ std::string feat_name = raw_feature_description(grd(def->pos()));
+
+ if (attacker->atype() == ACT_PLAYER)
+ {
+ player_apply_attack_delay();
+
+ if (you.can_see(def))
+ {
+ mprf("The %s protects %s from harm.",
+ feat_name.c_str(),
+ def->name(DESC_NOCAP_THE).c_str());
+ }
+ else
+ {
+ mprf("You hit the %s.",
+ feat_name.c_str());
+ }
+ }
+ else if (you.can_see(atk))
+ {
+ // Make sure the monster uses up some energy, even though
+ // it didn't actually land a blow.
+ monsterentry *entry = get_monster_data(atk->type);
+ atk->speed_increment -= entry->energy_usage.attack;
+
+ if (!mons_near(def))
+ simple_monster_message(atk, " hits something");
+ else if (!you.can_see(atk))
+ mprf("%s hits the %s.", def->name(DESC_CAP_THE).c_str(),
+ feat_name.c_str());
+ else
+ mprf("%s tries to hit the %s, but is blocked by the %s.",
+ atk->name(DESC_CAP_THE).c_str(),
+ def->name(DESC_NOCAP_THE).c_str(),
+ feat_name.c_str());
+ }
+ return (true);
+ }
+
// Allow god to get offended, etc.
attacker->attacking(defender);
diff --git a/crawl-ref/source/mon-data.h b/crawl-ref/source/mon-data.h
index 0c8b71c8e1..de9adb26e2 100644
--- a/crawl-ref/source/mon-data.h
+++ b/crawl-ref/source/mon-data.h
@@ -3875,7 +3875,7 @@
{
MONS_WATER_ELEMENTAL, '{', LIGHTBLUE, "water elemental",
- M_FLIES,
+ M_FLIES | M_AMPHIBIOUS,
MR_RES_POISON | MR_VUL_FIRE | MR_RES_ELEC,
0, 10, MONS_EARTH_ELEMENTAL, MONS_WATER_ELEMENTAL, MH_NONLIVING, MAG_IMMUNE,
{ {AT_HIT, AF_PLAIN, 25}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK },
@@ -3900,7 +3900,8 @@
// begin "move through rock" monsters {mpc}
{
MONS_ROCK_WORM, 'w', BROWN, "rock worm",
- M_NO_FLAGS,
+ //M_NO_FLAGS,
+ M_WALL_SHIELDED,
MR_RES_POISON | MR_RES_FIRE | MR_RES_COLD | MR_RES_ELEC,
0, 10, MONS_WORM, MONS_ROCK_WORM, MH_NATURAL, -3,
{ {AT_BITE, AF_PLAIN, 20}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK },
diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc
index 3474059a72..0c1d290cf6 100644
--- a/crawl-ref/source/mon-util.cc
+++ b/crawl-ref/source/mon-util.cc
@@ -2413,7 +2413,7 @@ bool mons_class_can_pass(const int mclass, const dungeon_feature_type grid)
switch (mclass)
{
case MONS_ROCK_WORM:
- return (grid >= DNGN_ROCK_WALL && grid <= DNGN_CLEAR_PERMAROCK_WALL);
+ return (!grid_is_solid(grid) || grid_is_rock(grid));
}
return !grid_is_solid(grid);
diff --git a/crawl-ref/source/mon-util.h b/crawl-ref/source/mon-util.h
index ef8aa03a2b..3c39e81179 100644
--- a/crawl-ref/source/mon-util.h
+++ b/crawl-ref/source/mon-util.h
@@ -116,6 +116,8 @@ enum mons_class_flags
M_ARCHER = (1<<23), // gets various archery boosts
+ M_WALL_SHIELDED = (1<<24), // Shielded from attacks if in wall
+
M_SPECIAL_ABILITY = (1<<26), // XXX: eventually make these spells?
M_NO_SKELETON = (1<<29), // boneless corpses
diff --git a/crawl-ref/source/monplace.cc b/crawl-ref/source/monplace.cc
index ea96452e24..3380be6130 100644
--- a/crawl-ref/source/monplace.cc
+++ b/crawl-ref/source/monplace.cc
@@ -105,15 +105,16 @@ bool monster_habitable_grid(int monster_class, int actual_grid, int flies,
&& (actual_grid == DNGN_LAVA
|| actual_grid == DNGN_DEEP_WATER))
- // Amphibious critters are happy in the water.
+ // Amphibious critters are happy in water or on land.
|| (mons_class_flag(monster_class, M_AMPHIBIOUS)
- && grid_compatible(DNGN_DEEP_WATER, actual_grid))
+ && ((preferred_habitat == DNGN_FLOOR
+ && grid_compatible(DNGN_DEEP_WATER, actual_grid))
+ || (preferred_habitat == DNGN_DEEP_WATER
+ && grid_compatible(DNGN_FLOOR, actual_grid))))
- // And water elementals are native to the water but happy on land
+ // Rock worms are native to walls but are happy on the floor
// as well.
- || ((monster_class == MONS_WATER_ELEMENTAL
- || monster_class == MONS_MERFOLK
- || monster_class == MONS_MERMAID)
+ || (monster_class == MONS_ROCK_WORM
&& grid_compatible(DNGN_FLOOR, actual_grid)));
}
diff --git a/crawl-ref/source/monstuff.cc b/crawl-ref/source/monstuff.cc
index 71e832426f..14130fa1ae 100644
--- a/crawl-ref/source/monstuff.cc
+++ b/crawl-ref/source/monstuff.cc
@@ -1759,6 +1759,11 @@ void behaviour_event( monsters *mon, int event, int src,
// 1. Evalutates current AI state
// 2. Sets monster targetx,y based on current foe
//
+// XXX: Monsters of I_NORMAL or above should select a new target
+// if their current target is another monser which is sitting in
+// a wall and is immune to most attacks while in a wall
+// (M_WALL_SHIELDED), unless the monster has a spell or special/nearby
+// ability which isn't affected by M_WALL_SHIELDED.
//---------------------------------------------------------------
static void handle_behaviour(monsters *mon)
{
@@ -2095,6 +2100,13 @@ static void handle_behaviour(monsters *mon)
// we can jump back to WANDER if the foe
// isn't present.
+ // XXX: If a monster can move through solid grids then it
+ // should preferentially flee towards the nearest solid grid
+ // it can move through. If it has M_WALL_SHIELDED is will
+ // be (mostly) safe as soon as it enters the wall, and even
+ // if it doesn't once it moves again it will be on the other
+ // side of the wall and likely beyond the reach of the player.
+
if (isFriendly)
{
// Special-cased below so that it will flee *towards* you
diff --git a/crawl-ref/source/terrain.cc b/crawl-ref/source/terrain.cc
index af31a735d5..8c9e122944 100644
--- a/crawl-ref/source/terrain.cc
+++ b/crawl-ref/source/terrain.cc
@@ -175,6 +175,15 @@ bool grid_is_solid(const coord_def &c)
return (grid_is_solid(grd(c)));
}
+bool grid_is_rock( dungeon_feature_type grid )
+{
+ return (grid == DNGN_ORCISH_IDOL
+ || grid == DNGN_GRANITE_STATUE
+ || grid == DNGN_SECRET_DOOR
+ || (grid >= DNGN_ROCK_WALL
+ && grid <= DNGN_CLEAR_PERMAROCK_WALL));
+}
+
bool grid_is_trap(dungeon_feature_type grid)
{
return (grid == DNGN_TRAP_MECHANICAL || grid == DNGN_TRAP_MAGICAL
diff --git a/crawl-ref/source/terrain.h b/crawl-ref/source/terrain.h
index 5839d4d02e..51caa559d6 100644
--- a/crawl-ref/source/terrain.h
+++ b/crawl-ref/source/terrain.h
@@ -28,10 +28,11 @@ bool fall_into_a_pool( int entry_x, int entry_y, bool allow_shift,
bool grid_is_wall(dungeon_feature_type grid);
bool grid_is_opaque(dungeon_feature_type grid);
bool grid_is_solid(dungeon_feature_type grid);
-bool grid_is_stone_stair(dungeon_feature_type grid);
-bool grid_is_rock_stair(dungeon_feature_type grid);
bool grid_is_solid(int x, int y);
bool grid_is_solid(const coord_def &c);
+bool grid_is_rock(dungeon_feature_type grid);
+bool grid_is_stone_stair(dungeon_feature_type grid);
+bool grid_is_rock_stair(dungeon_feature_type grid);
bool grid_is_trap(dungeon_feature_type grid);
command_type grid_stair_direction(dungeon_feature_type grid);
bool grid_sealable_portal(dungeon_feature_type grid);