summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crawl-ref/docs/level-design.txt3
-rw-r--r--crawl-ref/source/acr.cc4
-rw-r--r--crawl-ref/source/beam.cc9
-rw-r--r--crawl-ref/source/clua.cc7
-rw-r--r--crawl-ref/source/dat/descript/features.txt12
-rw-r--r--crawl-ref/source/dat/glass.des153
-rw-r--r--crawl-ref/source/delay.cc2
-rw-r--r--crawl-ref/source/direct.cc6
-rw-r--r--crawl-ref/source/dungeon.cc9
-rw-r--r--crawl-ref/source/enum.h14
-rw-r--r--crawl-ref/source/externs.h5
-rw-r--r--crawl-ref/source/luadgn.cc3
-rw-r--r--crawl-ref/source/misc.cc3
-rw-r--r--crawl-ref/source/monplace.cc5
-rw-r--r--crawl-ref/source/monstuff.cc97
-rw-r--r--crawl-ref/source/spells1.cc59
-rw-r--r--crawl-ref/source/spells1.h3
-rw-r--r--crawl-ref/source/spells2.cc13
-rw-r--r--crawl-ref/source/spells4.cc60
-rw-r--r--crawl-ref/source/spl-util.cc6
-rw-r--r--crawl-ref/source/spl-util.h3
-rw-r--r--crawl-ref/source/terrain.cc5
-rw-r--r--crawl-ref/source/view.cc92
-rw-r--r--crawl-ref/source/view.h17
24 files changed, 524 insertions, 66 deletions
diff --git a/crawl-ref/docs/level-design.txt b/crawl-ref/docs/level-design.txt
index 939ccfaacb..df23716945 100644
--- a/crawl-ref/docs/level-design.txt
+++ b/crawl-ref/docs/level-design.txt
@@ -159,6 +159,9 @@ Terrain
x - rock wall (DNGN_ROCK_WALL)
X - permanent rock wall - always undiggable (DNGN_PERMAROCK_WALL)
c - stone wall - only affected by Shatter (DNGN_STONE_WALL)
+ m - clear rock wall (DNGN_CLEAR_ROCK_WALL)
+ n - clear stone wall - only affected by Shatter (DNGN_CLEAR_STONE_WALL)
+ o - clear permanent rock wall - always undiggable (DNGN_CLEAR_PERMAROCK_WALL)
v - metal wall - grounds electricity (DNGN_METAL_WALL)
b - crystal wall - reflects cold and fire (DNGN_GREEN_CRYSTAL_WALL)
a - wax wall - can melt (DNGN_WAX_WALL)
diff --git a/crawl-ref/source/acr.cc b/crawl-ref/source/acr.cc
index 5869e7fbac..ce04b6e51f 100644
--- a/crawl-ref/source/acr.cc
+++ b/crawl-ref/source/acr.cc
@@ -627,7 +627,9 @@ static void handle_wizard_command( void )
break;
case 'b':
- blink(1000, true); // wizards can always blink
+ // wizards can always blink, with no restrictions or
+ // magical contamination.
+ blink(1000, true, true);
break;
case '~':
diff --git a/crawl-ref/source/beam.cc b/crawl-ref/source/beam.cc
index 4fed730bd2..16614b3cc5 100644
--- a/crawl-ref/source/beam.cc
+++ b/crawl-ref/source/beam.cc
@@ -2588,13 +2588,15 @@ static int affect_wall(bolt &beam, int x, int y)
if (grd[x][y] == DNGN_STONE_WALL
|| grd[x][y] == DNGN_METAL_WALL
|| grd[x][y] == DNGN_PERMAROCK_WALL
+ || grd[x][y] == DNGN_CLEAR_STONE_WALL
+ || grd[x][y] == DNGN_CLEAR_PERMAROCK_WALL
|| x <= 5 || x >= (GXM - 5)
|| y <= 5 || y >= (GYM - 5))
{
return (0);
}
- if (grd[x][y] == DNGN_ROCK_WALL)
+ if (grd[x][y] == DNGN_ROCK_WALL || grd[x][y] == DNGN_CLEAR_ROCK_WALL)
{
grd[x][y] = DNGN_FLOOR;
@@ -2653,8 +2655,9 @@ static int affect_wall(bolt &beam, int x, int y)
{
int targ_grid = grd[x][y];
- if ((targ_grid == DNGN_ROCK_WALL || targ_grid == DNGN_WAX_WALL)
- && !(x <= 6 || y <= 6 || x >= (GXM - 6) || y >= (GYM - 6)))
+ if ((targ_grid == DNGN_ROCK_WALL || targ_grid == DNGN_WAX_WALL
+ || targ_grid == DNGN_CLEAR_ROCK_WALL)
+ && !(x <= 6 || y <= 6 || x >= (GXM - 6) || y >= (GYM - 6)))
{
grd[ x ][ y ] = DNGN_FLOOR;
if (!silenced(you.x_pos, you.y_pos))
diff --git a/crawl-ref/source/clua.cc b/crawl-ref/source/clua.cc
index 9c6cca38a5..cf16990557 100644
--- a/crawl-ref/source/clua.cc
+++ b/crawl-ref/source/clua.cc
@@ -739,6 +739,8 @@ LUAWRAP(you_stop_activity, interrupt_activity(AI_FORCE_INTERRUPT))
LUARET1(you_turns, number, you.num_turns)
LUARET1(you_see_grid, boolean,
see_grid(luaL_checkint(ls, 1), luaL_checkint(ls, 2)))
+LUARET1(you_see_grid_no_trans, boolean,
+ see_grid_no_trans(luaL_checkint(ls, 1), luaL_checkint(ls, 2)))
// increase by 1 because check happens on old level
LUARET1(bzr_floor_colour, string,
colour_to_str(bazaar_floor_colour(you.your_level + 2)))
@@ -820,8 +822,9 @@ static const struct luaL_reg you_lib[] =
{ "subdepth", you_subdepth },
{ "absdepth", you_absdepth },
- { "see_grid", you_see_grid },
- { "bazaar_floor", bzr_floor_colour },
+ { "see_grid", you_see_grid },
+ { "see_grid_no_trans", you_see_grid_no_trans },
+ { "bazaar_floor", bzr_floor_colour },
{ NULL, NULL },
};
diff --git a/crawl-ref/source/dat/descript/features.txt b/crawl-ref/source/dat/descript/features.txt
index 897ab8c343..7b8d2207a3 100644
--- a/crawl-ref/source/dat/descript/features.txt
+++ b/crawl-ref/source/dat/descript/features.txt
@@ -217,7 +217,17 @@ A stone staircase leading up
%%%%
A stone wall
-A harder obstacle than rock walls. Only the mightiest magic can shatter stone walls.
+A harder obstacle than rock walls. Only the mightiest magic can shatter stone walls.
+%%%%
+A translucent rock wall
+
+%%%%
+A translucent stone wall
+
+A harder obstacle than rock walls. Only the mightiest magic can shatter stone walls. It has been imbued with arcane magics which render it translucent.
+%%%%
+An translucent unnaturally hard rock wall
+
%%%%
A trap
diff --git a/crawl-ref/source/dat/glass.des b/crawl-ref/source/dat/glass.des
new file mode 100644
index 0000000000..3731eb9e25
--- /dev/null
+++ b/crawl-ref/source/dat/glass.des
@@ -0,0 +1,153 @@
+###########################################################################
+# Small areas with translucent rock (glass) columns which you can duck
+# behind, but still see the monster you're ducking from (and they can
+# still see you
+NAME: glass_columns_a
+DEPTH:
+MAP
+.....
+.m.m.
+.....
+.m.m.
+.....
+ENDMAP
+
+NAME: glass_columns_b
+DEPTH:
+MAP
+.......
+.m.m.m.
+.......
+.m.m.m.
+.......
+.m.m.m.
+.......
+ENDMAP
+
+NAME: glass_columns_c
+DEPTH:
+MAP
+.........
+.m.m.m.m.
+.........
+.m.m.m.m.
+.........
+.m.m.m.m.
+.........
+.m.m.m.m.
+.........
+ENDMAP
+
+##########################################################
+# A feature encased in glass, for flavour.
+NAME: feat_on_display
+DEPTH:
+SUBST: ? = TUl
+TAGS: no_monster_gen no_item_gen
+MAP
+.....
+.mmm.
+.m?m.
+.mmm.
+.....
+ENDMAP
+
+#######################################################################
+# An item encased in glass. If the player wants it, it can be dug out.
+NAME: item_on_display_a
+DEPTH:
+TAGS: no_monster_gen no_item_gen
+MAP
+.....
+.mmm.
+.m%m.
+.mmm.
+.....
+ENDMAP
+
+#####################################################################
+# A good item encased in *permanet* glass. If the player wants it,
+# teleport control will be needed.
+NAME: item_on_display_b
+DEPTH:
+TAGS: no_monster_gen no_item_gen
+MAP
+.....
+.ooo.
+.o*o.
+.ooo.
+.....
+ENDMAP
+
+#####################################################################
+# An average monster in a cage of glass; can get out if it has the
+# ability to dig or blink like a blink-frog. Also, the player can
+# dig it out.
+NAME: caged_monster_a
+DEPTH: D, Elf, Snake, Vault
+MAP
+.....
+.mmm.
+.m0m.
+.mmm.
+.....
+ENDMAP
+
+############################################################################
+# Entry vaults using translucent (glass) walls
+
+# A spiral made entirely of glass
+
+NAME: glass_entry_001
+TAGS: entry
+ORIENT: float
+SHUFFLE: {[(<
+SUBST: < = .
+MAP
+mmmmmmmmmmmmmmmmmm
+m................m
+m.mmmmmmmmmmmmmm.m
+m.m............m.m
+m.m.mmmmmmmmmm.m.m
+m.m.m........m.m.m
+m.m.m.mmmmmm.m.m.m
+m.m.m.m....m.m.m.m
+m.m.m.m.mm.m.m.m.m
+m.m.m.m{[m.m.m.m.m
+m.m.m.m(<m.m.m.m.m
+m.m.m.mmmm.m.m.m.m
+m.m.m......m.m.m.m
+m.m.mmmmmmmm.m.m.m
+m.m..........m.m.m
+m.mmmmmmmmmmmm.m.m
+m..............m.m
+mmmmmmmmmmmmmmmm@m
+ENDMAP
+
+# A spiral made of rock, with lots of "windows".
+
+NAME: glass_entry_002
+TAGS: entry
+ORIENT: float
+SHUFFLE: {[(<
+SUBST: < = .
+MAP
+mxmxmxmxmxmxxmxxmx
+x................m
+m.xmxmxmxmxmxmxm.x
+x.m............x.m
+m.x.mxmxmxmxmx.m.x
+x.m.x........m.x.m
+m.x.m.xmxmxx.x.m.x
+x.m.x.m....x.m.x.m
+m.x.m.x.mx.m.x.m.x
+x.m.x.m{[m.x.m.x.m
+m.x.m.x(<x.m.x.m.x
+x.m.x.xmxx.x.m.x.m
+m.x.m......m.x.m.x
+x.m.xxmxmxmx.m.x.m
+m.x..........x.m.x
+x.xmxmxmxmxmxm.x.m
+m..............m.x
+xxmxmxmxmxmxmxmx@m
+ENDMAP
diff --git a/crawl-ref/source/delay.cc b/crawl-ref/source/delay.cc
index b2b443c0d1..d77fd9d269 100644
--- a/crawl-ref/source/delay.cc
+++ b/crawl-ref/source/delay.cc
@@ -532,6 +532,8 @@ static void finish_delay(const delay_queue_item &delay)
{
case DNGN_ROCK_WALL:
case DNGN_STONE_WALL:
+ case DNGN_CLEAR_ROCK_WALL:
+ case DNGN_CLEAR_STONE_WALL:
case DNGN_METAL_WALL:
case DNGN_GREEN_CRYSTAL_WALL:
case DNGN_WAX_WALL:
diff --git a/crawl-ref/source/direct.cc b/crawl-ref/source/direct.cc
index 02ef032460..ff7c5d4162 100644
--- a/crawl-ref/source/direct.cc
+++ b/crawl-ref/source/direct.cc
@@ -1511,6 +1511,12 @@ std::string raw_feature_description(dungeon_feature_type grid,
return ("metal wall");
case DNGN_GREEN_CRYSTAL_WALL:
return ("wall of green crystal");
+ case DNGN_CLEAR_ROCK_WALL:
+ return ("translucent rock wall");
+ case DNGN_CLEAR_STONE_WALL:
+ return ("translucent stone wall");
+ case DNGN_CLEAR_PERMAROCK_WALL:
+ return ("translucent unnaturally hard rock wall");
case DNGN_ORCISH_IDOL:
if (you.species == SP_HILL_ORC)
{
diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc
index 8abb604604..af0495e0e5 100644
--- a/crawl-ref/source/dungeon.cc
+++ b/crawl-ref/source/dungeon.cc
@@ -4003,6 +4003,9 @@ dungeon_feature_type map_feature(map_def *map, const coord_def &c, int rawfeat)
(rawfeat == 'v') ? DNGN_METAL_WALL :
(rawfeat == 'b') ? DNGN_GREEN_CRYSTAL_WALL :
(rawfeat == 'a') ? DNGN_WAX_WALL :
+ (rawfeat == 'm') ? DNGN_CLEAR_ROCK_WALL :
+ (rawfeat == 'n') ? DNGN_CLEAR_STONE_WALL :
+ (rawfeat == 'o') ? DNGN_CLEAR_PERMAROCK_WALL :
(rawfeat == '+') ? DNGN_CLOSED_DOOR :
(rawfeat == '=') ? DNGN_SECRET_DOOR :
(rawfeat == 'w') ? DNGN_DEEP_WATER :
@@ -4099,6 +4102,9 @@ static int vault_grid( vault_placement &place,
(vgrid == 'v') ? DNGN_METAL_WALL :
(vgrid == 'b') ? DNGN_GREEN_CRYSTAL_WALL :
(vgrid == 'a') ? DNGN_WAX_WALL :
+ (vgrid == 'm') ? DNGN_CLEAR_ROCK_WALL :
+ (vgrid == 'n') ? DNGN_CLEAR_STONE_WALL :
+ (vgrid == 'o') ? DNGN_CLEAR_PERMAROCK_WALL :
(vgrid == '+') ? DNGN_CLOSED_DOOR :
(vgrid == '=') ? DNGN_SECRET_DOOR :
(vgrid == 'w') ? DNGN_DEEP_WATER :
@@ -5897,6 +5903,9 @@ static bool is_wall(int x, int y)
case DNGN_METAL_WALL:
case DNGN_GREEN_CRYSTAL_WALL:
case DNGN_WAX_WALL:
+ case DNGN_CLEAR_ROCK_WALL:
+ case DNGN_CLEAR_STONE_WALL:
+ case DNGN_CLEAR_PERMAROCK_WALL:
return true;
default:
return false;
diff --git a/crawl-ref/source/enum.h b/crawl-ref/source/enum.h
index 7190d429cf..1343e4d5f9 100644
--- a/crawl-ref/source/enum.h
+++ b/crawl-ref/source/enum.h
@@ -812,7 +812,14 @@ enum dungeon_char_type
// * Any: edit dat/descript.txt and add a long description if appropriate.
// * Any: check the grid_* functions in misc.cc and make sure
// they return sane values for your new feature.
-//
+// * Any: edit dungeon.cc and add a symbol to map_feature() and
+// vault_grid() for the feature, if you want vault maps to
+// be able to use it. If you do, also update
+// docs/level-design.txt with the new symbol.
+// * Any: edit luadgn.cc and add the feature's name to the dngn_feature_names
+// array, if you want vault map Lua code to be able to use the
+// feature, and/or you want to be able to create the feature
+// using the "create feature by name" wizard command.
// Also take note of MINMOVE and MINSEE above.
//
enum dungeon_feature_type
@@ -827,9 +834,12 @@ enum dungeon_feature_type
DNGN_ORCISH_IDOL,
DNGN_WAX_WALL, // 8
DNGN_PERMAROCK_WALL, // 9 - for undiggable walls
+ DNGN_CLEAR_ROCK_WALL, // 10 - Transparent
+ DNGN_CLEAR_STONE_WALL, // 11 - Transparent
+ DNGN_CLEAR_PERMAROCK_WALL, // 12 - Transparent
// XXX: lowest grid value which can be seen through
- DNGN_MINSEE = 11,
+ DNGN_MINSEE = 10,
DNGN_GRANITE_STATUE = 21, // 21
DNGN_STATUE_RESERVED_1,
diff --git a/crawl-ref/source/externs.h b/crawl-ref/source/externs.h
index c0a379326a..a54827e4bf 100644
--- a/crawl-ref/source/externs.h
+++ b/crawl-ref/source/externs.h
@@ -1191,6 +1191,11 @@ public:
FixedArray<unsigned short, ENV_SHOW_DIAMETER, ENV_SHOW_DIAMETER>
show_col; // view window colour
+ // What would be visible, if all of the translucent wall were
+ // made opaque.
+ FixedArray<unsigned, ENV_SHOW_DIAMETER, ENV_SHOW_DIAMETER>
+ no_trans_show;
+
FixedVector< cloud_struct, MAX_CLOUDS > cloud; // cloud list
unsigned char cloud_no;
diff --git a/crawl-ref/source/luadgn.cc b/crawl-ref/source/luadgn.cc
index 9e4188a1cb..043ae46966 100644
--- a/crawl-ref/source/luadgn.cc
+++ b/crawl-ref/source/luadgn.cc
@@ -822,7 +822,8 @@ const char *dngn_feature_names[] =
{
"unseen", "rock_wall", "stone_wall", "closed_door", "metal_wall",
"secret_door", "green_crystal_wall", "orcish_idol", "wax_wall",
- "permarock_wall", "", "", "", "", "", "", "", "", "", "", "",
+ "permarock_wall", "clear_rock_wall", "clear_stone_wall",
+ "clear_permarock_wall", "", "", "", "", "", "", "", "",
"silver_statue", "granite_statue", "orange_crystal_statue",
"statue_reserved_1", "statue_reserved_2", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
diff --git a/crawl-ref/source/misc.cc b/crawl-ref/source/misc.cc
index 9163f37b87..e0b013e45c 100644
--- a/crawl-ref/source/misc.cc
+++ b/crawl-ref/source/misc.cc
@@ -168,7 +168,8 @@ void search_around( bool only_adjacent )
{
for ( int sry=you.y_pos - max_dist; sry<=you.y_pos + max_dist; ++sry )
{
- if ( see_grid(srx,sry) ) // must have LOS
+ // must have LOS, with no translucent walls in the way.
+ if ( see_grid_no_trans(srx,sry) )
{
// maybe we want distance() instead of grid_distance()?
int dist = grid_distance(srx, sry, you.x_pos, you.y_pos);
diff --git a/crawl-ref/source/monplace.cc b/crawl-ref/source/monplace.cc
index df14577fe7..536ffb52cb 100644
--- a/crawl-ref/source/monplace.cc
+++ b/crawl-ref/source/monplace.cc
@@ -1687,8 +1687,9 @@ bool empty_surrounds(int emx, int emy, unsigned char spc_wanted,
if (mgrd[tx][ty] != NON_MONSTER)
continue;
- // players won't summon out of LOS
- if (!see_grid(tx, ty) && playerSummon)
+ // players won't summon out of LOS, or past transparent
+ // walls.
+ if (!see_grid_no_trans(tx, ty) && playerSummon)
continue;
if (grd[tx][ty] == spc_wanted)
diff --git a/crawl-ref/source/monstuff.cc b/crawl-ref/source/monstuff.cc
index 47ecdc7e8d..ef499b6f53 100644
--- a/crawl-ref/source/monstuff.cc
+++ b/crawl-ref/source/monstuff.cc
@@ -1245,31 +1245,93 @@ bool monster_blink(monsters *monster)
// allow_adjacent: allow target to be adjacent to origin
// restrict_LOS: restict target to be within PLAYER line of sight
bool random_near_space(int ox, int oy, int &tx, int &ty, bool allow_adjacent,
- bool restrict_LOS)
+ bool restrict_LOS)
{
- int tries = 0;
- do
+ // This might involve ray tracing (via num_feats_between()), so
+ // cache results to avoid duplicating ray traces.
+ FixedArray<bool, 14, 14> tried;
+ tried.init(false);
+
+ // Is the monster on the other side of a tranparent wall?
+ bool trans_wall_block = trans_wall_blocking(ox, oy);
+ bool origin_is_player = (you.pos() == coord_def(ox, oy));
+ int min_walls_between = 0;
+
+ // Skip ray tracing if possible.
+ if (trans_wall_block)
+ min_walls_between = num_feats_between(ox, oy, you.x_pos, you.y_pos,
+ DNGN_CLEAR_ROCK_WALL,
+ DNGN_CLEAR_PERMAROCK_WALL);
+ int tries = 0;
+ while (tries++ < 150)
{
- tx = ox - 6 + random2(14);
- ty = oy - 6 + random2(14);
+ int dx = random2(14);
+ int dy = random2(14);
+
+ tx = ox - 6 + dx;
+ ty = oy - 6 + dy;
// origin is not 'near'
if (tx == ox && ty == oy)
continue;
- tries++;
+ if (tried[dx][dy])
+ continue;
- if (tries > 149)
- break;
+ tried[dx][dy] = true;
+
+ if ((!see_grid(tx, ty) && restrict_LOS)
+ || grd[tx][ty] < DNGN_SHALLOW_WATER
+ || mgrd[tx][ty] != NON_MONSTER
+ || (tx == you.x_pos && ty == you.y_pos)
+ || (!allow_adjacent && distance(ox, oy, tx, ty) <= 2))
+ continue;
+
+ if (!trans_wall_block && !origin_is_player)
+ return (true);
+
+ // If the monster is on a visible square which is on the other
+ // side of one or more translucent from the player, then it
+ // can only blink through translucent walls if the end point
+ // is either not visible to the player, or there are at least
+ // as many translucent walls between the player and the end
+ // point as between the player and the start point. However,
+ // monsters can still blink through translucent walls to get
+ // away from the player, since in the absence of tranlucent
+ // walls monsters can blink to places which are not in either
+ // the monster's nor the player's LOS.
+ if (!see_grid(tx, ty) && !origin_is_player)
+ return (true);
+
+ // Player can't randomly pass through translucent walls.
+ if (origin_is_player)
+ {
+ if (see_grid_no_trans(tx, ty))
+ return (true);
+
+ continue;
+ }
+
+ int walls_passed = num_feats_between(tx, ty, ox, oy,
+ DNGN_CLEAR_ROCK_WALL,
+ DNGN_CLEAR_PERMAROCK_WALL);
+ if (walls_passed == 0)
+ return (true);
+
+ // Player can't randomly pass through translucent walls.
+ if (origin_is_player)
+ continue;
+
+ int walls_between = num_feats_between(tx, ty, you.x_pos, you.y_pos,
+ DNGN_CLEAR_ROCK_WALL,
+ DNGN_CLEAR_PERMAROCK_WALL);
+
+ if (walls_between >= min_walls_between)
+ return (true);
}
- while ((!see_grid(tx, ty) && restrict_LOS)
- || grd[tx][ty] < DNGN_SHALLOW_WATER
- || mgrd[tx][ty] != NON_MONSTER
- || (tx == you.x_pos && ty == you.y_pos)
- || (!allow_adjacent && distance(ox, oy, tx, ty) <= 2));
- return (tries < 150);
+ return (false);
} // end random_near_space()
static bool habitat_okay( const monsters *monster, int targ )
@@ -4597,7 +4659,8 @@ static void monster_move(monsters *monster)
deep_water_available = true;
if (monster->type == MONS_BORING_BEETLE
- && target_grid == DNGN_ROCK_WALL)
+ && (target_grid == DNGN_ROCK_WALL
+ || target_grid == DNGN_CLEAR_ROCK_WALL))
{
// don't burrow out of bounds
if (targ_x <= 7 || targ_x >= (GXM - 8)
@@ -4948,7 +5011,9 @@ forget_it:
// take care of beetle burrowing
if (monster->type == MONS_BORING_BEETLE)
{
- if (grd[monster->x + mmov_x][monster->y + mmov_y] == DNGN_ROCK_WALL
+ dungeon_feature_type feat =
+ grd[monster->x + mmov_x][monster->y + mmov_y];
+ if ((feat == DNGN_ROCK_WALL || feat == DNGN_ROCK_WALL)
&& good_move[mmov_x + 1][mmov_y + 1] == true)
{
grd[monster->x + mmov_x][monster->y + mmov_y] = DNGN_FLOOR;
diff --git a/crawl-ref/source/spells1.cc b/crawl-ref/source/spells1.cc
index bd82ad3684..b419fe0bf7 100644
--- a/crawl-ref/source/spells1.cc
+++ b/crawl-ref/source/spells1.cc
@@ -62,7 +62,10 @@ static bool abyss_blocks_teleport(bool cblink)
return (cblink? one_chance_in(3) : !one_chance_in(3));
}
-int blink(int pow, bool high_level_controlled_blink)
+// If wizard_blink is set, all restriction are ignored (except for
+// a monster being at the target spot), and the player gains no
+// contamination.
+int blink(int pow, bool high_level_controlled_blink, bool wizard_blink)
{
dist beam;
@@ -75,14 +78,17 @@ int blink(int pow, bool high_level_controlled_blink)
}
// yes, there is a logic to this ordering {dlb}:
- if (scan_randarts(RAP_PREVENT_TELEPORTATION))
+ if (scan_randarts(RAP_PREVENT_TELEPORTATION) && !wizard_blink)
mpr("You feel a weird sense of stasis.");
else if (you.level_type == LEVEL_ABYSS
- && abyss_blocks_teleport(high_level_controlled_blink))
+ && abyss_blocks_teleport(high_level_controlled_blink)
+ && !wizard_blink)
+ {
mpr("The power of the Abyss keeps you in your place!");
- else if (you.duration[DUR_CONF])
+ }
+ else if (you.duration[DUR_CONF] && !wizard_blink)
random_blink(false);
- else if (!allow_control_teleport(true))
+ else if (!allow_control_teleport(true) && !wizard_blink)
{
mpr("A powerful magic interferes with your control of the blink.");
if (high_level_controlled_blink)
@@ -98,7 +104,8 @@ int blink(int pow, bool high_level_controlled_blink)
if (!beam.isValid || coord_def(beam.tx, beam.ty) == you.pos())
{
- if (!yesno("Are you sure you want to cancel this blink?",
+ if (!wizard_blink &&
+ !yesno("Are you sure you want to cancel this blink?",
false, 'n'))
{
mesclr();
@@ -108,22 +115,37 @@ int blink(int pow, bool high_level_controlled_blink)
return (-1); // early return {dlb}
}
- if (see_grid(beam.tx, beam.ty))
+ // Wizard blink can move past translucent walls.
+ if (see_grid_no_trans(beam.tx, beam.ty))
break;
+ else if (trans_wall_blocking( beam.tx, beam.ty ))
+ {
+ // Wizard blink can move past translucent walls.
+ if (wizard_blink)
+ break;
+
+ mesclr();
+ mpr("You can't blink through translucent walls.");
+ }
else
{
mesclr();
- mpr("You can't blink there!");
+ mpr("You can only blink to visible locations.");
}
}
+ // Allow wizard blink to send player into walls, in case
+ // the user wants to alter that grid to something else.
+ if (grid_is_solid(grd[beam.tx][beam.ty]) && wizard_blink)
+ grd[beam.tx][beam.ty] = DNGN_FLOOR;
+
if (grid_is_solid(grd[beam.tx][beam.ty])
|| mgrd[beam.tx][beam.ty] != NON_MONSTER)
{
mpr("Oops! Maybe something was there already.");
random_blink(false);
}
- else if (you.level_type == LEVEL_ABYSS)
+ else if (you.level_type == LEVEL_ABYSS && !wizard_blink)
{
abyss_teleport( false );
you.pet_target = MHITNOT;
@@ -142,10 +164,11 @@ int blink(int pow, bool high_level_controlled_blink)
move_player_to_grid(beam.tx, beam.ty, false, true, true);
// controlling teleport contaminates the player -- bwr
- contaminate_player( 1 );
+ if (!wizard_blink)
+ contaminate_player( 1 );
}
- if (you.duration[DUR_CONDENSATION_SHIELD] > 0)
+ if (you.duration[DUR_CONDENSATION_SHIELD] > 0 && !wizard_blink)
{
you.duration[DUR_CONDENSATION_SHIELD] = 0;
you.redraw_armour_class = 1;
@@ -170,7 +193,10 @@ void random_blink(bool allow_partial_control, bool override_abyss)
{
mpr("The power of the Abyss keeps you in your place!");
}
- else if (!random_near_space(you.x_pos, you.y_pos, tx, ty))
+ // First try to find a random square not adjacent to the player,
+ // then one adjacent if that fails.
+ else if (!random_near_space(you.x_pos, you.y_pos, tx, ty)
+ && !random_near_space(you.x_pos, you.y_pos, tx, ty, true))
{
mpr("You feel jittery for a moment.");
}
@@ -377,7 +403,7 @@ void cast_chain_lightning( int powc )
else if (!see_source && see_targ)
mpr( "The lightning arc suddenly appears!" );
- if (!see_targ)
+ if (!see_grid_no_trans( tx, ty ))
{
// It's no longer in the caster's LOS and influence.
powc = powc / 2 + 1;
@@ -476,7 +502,12 @@ bool conjure_flame(int pow)
return false;
}
- if (!see_grid(spelld.tx, spelld.ty))
+ if (trans_wall_blocking(spelld.tx, spelld.ty))
+ {
+ mpr("A translucent wall is in the way.");
+ return false;
+ }
+ else if (!see_grid(spelld.tx, spelld.ty))
{
mpr("You can't see that place!");
continue;
diff --git a/crawl-ref/source/spells1.h b/crawl-ref/source/spells1.h
index b9146d8ffd..2504f7670d 100644
--- a/crawl-ref/source/spells1.h
+++ b/crawl-ref/source/spells1.h
@@ -65,7 +65,8 @@ void big_cloud(cloud_type cl_type, kill_category whose, int cl_x, int cl_y,
/* ***********************************************************************
* called from: acr (WIZARD only) - item_use - spell
* *********************************************************************** */
-int blink(int pow, bool high_level_controlled_blink);
+int blink(int pow, bool high_level_controlled_blink,
+ bool wizard_blink = false);
/* ***********************************************************************
diff --git a/crawl-ref/source/spells2.cc b/crawl-ref/source/spells2.cc
index 2731f206d3..e9b9cbd960 100644
--- a/crawl-ref/source/spells2.cc
+++ b/crawl-ref/source/spells2.cc
@@ -248,7 +248,7 @@ int corpse_rot(int power)
{
for (ady = miny; ady != maxy; ady += yinc)
{
- if (see_grid(adx, ady))
+ if (see_grid_no_trans(adx, ady))
{
if (igrd[adx][ady] == NON_ITEM
|| env.cgrid[adx][ady] != EMPTY_CLOUD)
@@ -328,7 +328,7 @@ int animate_dead( int power, beh_type corps_beh, int corps_hit, int actual )
{
for (ady = miny; ady != maxy; ady += yinc)
{
- if (see_grid(adx, ady))
+ if (see_grid_no_trans(adx, ady))
{
if (igrd[adx][ady] != NON_ITEM)
{
@@ -1076,6 +1076,12 @@ char burn_freeze(int pow, char flavour)
mpr("There isn't anything close enough!");
return 0;
}
+
+ if (trans_wall_blocking( bmove.tx, bmove.ty ))
+ {
+ mpr("A translucent wall is in the way.");
+ return 0;
+ }
}
monster = &menv[mgr];
@@ -1195,7 +1201,8 @@ int summon_elemental(int pow, int restricted_type,
break;
}
- if (grd[ targ_x ][ targ_y ] == DNGN_ROCK_WALL
+ if ((grd[ targ_x ][ targ_y ] == DNGN_ROCK_WALL
+ || grd[ targ_x ][ targ_y ] == DNGN_CLEAR_ROCK_WALL)
&& (restricted_type == 0 || restricted_type == MONS_EARTH_ELEMENTAL))
{
type_summoned = MONS_EARTH_ELEMENTAL;
diff --git a/crawl-ref/source/spells4.cc b/crawl-ref/source/spells4.cc
index 8a7b7511d7..852ca6cb68 100644
--- a/crawl-ref/source/spells4.cc
+++ b/crawl-ref/source/spells4.cc
@@ -360,11 +360,13 @@ static int shatter_walls(int x, int y, int pow, int garbage)
stuff = DEBRIS_STONE;
break;
+ case DNGN_CLEAR_STONE_WALL:
case DNGN_STONE_WALL:
chance = pow / 6;
stuff = DEBRIS_STONE;
break;
+ case DNGN_CLEAR_ROCK_WALL:
case DNGN_ROCK_WALL:
chance = pow / 4;
stuff = DEBRIS_ROCK;
@@ -1622,7 +1624,7 @@ static int passwall(int x, int y, int pow, int garbage)
int shallow = 1 + (you.skills[SK_EARTH_MAGIC] / 8);
// allow statues as entry points?
- if (grd[x][y] != DNGN_ROCK_WALL)
+ if (grd[x][y] != DNGN_ROCK_WALL && grd[x][y] != DNGN_CLEAR_ROCK_WALL)
// Irony: you can start on a secret door but not a door.
// Worked stone walls are out, they're not diggable and
// are used for impassable walls... I'm not sure we should
@@ -1651,6 +1653,7 @@ static int passwall(int x, int y, int pow, int garbage)
done = true;
break;
case DNGN_ROCK_WALL:
+ case DNGN_CLEAR_ROCK_WALL:
case DNGN_ORCISH_IDOL:
case DNGN_GRANITE_STATUE:
case DNGN_SECRET_DOOR:
@@ -2516,9 +2519,11 @@ void cast_fragmentation(int pow) // jmf: ripped idea from airstrike
// Stone and rock terrain
//
case DNGN_ROCK_WALL:
+ case DNGN_CLEAR_ROCK_WALL:
case DNGN_SECRET_DOOR:
blast.colour = env.rock_colour;
// fall-through
+ case DNGN_CLEAR_STONE_WALL:
case DNGN_STONE_WALL:
what = "wall";
if (player_in_branch( BRANCH_HALL_OF_ZOT ))
@@ -2545,7 +2550,11 @@ void cast_fragmentation(int pow) // jmf: ripped idea from airstrike
&& (grid == DNGN_ORCISH_IDOL
|| grid == DNGN_GRANITE_STATUE
|| (pow >= 40 && grid == DNGN_ROCK_WALL && one_chance_in(3))
- || (pow >= 60 && grid == DNGN_STONE_WALL && one_chance_in(10))))
+ || (pow >= 40 && grid == DNGN_CLEAR_ROCK_WALL
+ && one_chance_in(3))
+ || (pow >= 60 && grid == DNGN_STONE_WALL && one_chance_in(10))
+ || (pow >= 60 && grid == DNGN_CLEAR_STONE_WALL &&
+ one_chance_in(10)) ))
{
// terrain blew up real good:
blast.ex_size = 2;
@@ -2732,6 +2741,12 @@ bool cast_portaled_projectile(int pow, bolt& beam)
return false;
}
+ if (trans_wall_blocking( beam.target_x, beam.target_y ))
+ {
+ mpr("A translucent wall is in the way.");
+ return 0;
+ }
+
const int idx = get_fire_item_index();
if ( idx == ENDOFPACK )
{
@@ -2776,6 +2791,12 @@ void cast_far_strike(int pow)
return;
}
+ if (trans_wall_blocking( targ.tx, targ.ty ))
+ {
+ mpr("A translucent wall is in the way.");
+ return;
+ }
+
// Start with weapon base damage...
const int weapon = you.equip[ EQ_WEAPON ];
@@ -2898,6 +2919,12 @@ int cast_apportation(int pow)
return (-1);
}
+ if (trans_wall_blocking( beam.tx, beam.ty ))
+ {
+ mpr("A translucent wall is in the way.");
+ return (0);
+ }
+
// Protect the player from destroying the item
const dungeon_feature_type grid = grd[ you.x_pos ][ you.y_pos ];
@@ -3074,20 +3101,35 @@ static int quadrant_blink(int x, int y, int pow, int garbage)
const int dist = random2(6) + 2; // 2-7
const int ox = you.x_pos + (x - you.x_pos) * dist;
const int oy = you.y_pos + (y - you.y_pos) * dist;
-
+
+ // This can take a while if pow is high and there's lots of translucent
+ // walls nearby.
int tx, ty;
+ bool found = false;
for ( int i = 0; i < (pow*pow) / 500 + 1; ++i )
{
- // find a space near our target...
- if ( !random_near_space(ox, oy, tx, ty) )
+ // find a space near our target... First try to find a random
+ // square not adjacent to the player, then one adjacent if
+ // that fails.
+ if ( !random_near_space(ox, oy, tx, ty) &&
+ !random_near_space(ox, oy, tx, ty, true))
return 0;
-
+
// which is close enough, and also far enough from us
- if ( distance(ox, oy, tx, ty) <= 10 &&
- distance(you.x_pos, you.y_pos, tx, ty) >= 8 )
- break;
+ if ( distance(ox, oy, tx, ty) > 10 &&
+ distance(you.x_pos, you.y_pos, tx, ty) < 8 )
+ continue;
+
+ if (!see_grid_no_trans(tx, ty))
+ continue;
+
+ found = true;
+ break;
}
+ if (!found)
+ return(0);
+
you.moveto(tx, ty);
return 1;
}
diff --git a/crawl-ref/source/spl-util.cc b/crawl-ref/source/spl-util.cc
index ee09d5b374..d1b606199b 100644
--- a/crawl-ref/source/spl-util.cc
+++ b/crawl-ref/source/spl-util.cc
@@ -266,7 +266,8 @@ const char *spell_title(spell_type spell)
// Apply a function-pointer to all visible squares
// Returns summation of return values from passed in function.
-int apply_area_visible( int (*func) (int, int, int, int), int power )
+int apply_area_visible( int (*func) (int, int, int, int), int power,
+ bool pass_through_trans)
{
int x, y;
int rv = 0;
@@ -276,7 +277,8 @@ int apply_area_visible( int (*func) (int, int, int, int), int power )
{
for (y = you.y_pos - 8; y <= you.y_pos + 8; y++)
{
- if (see_grid(x, y))
+ if ((pass_through_trans && see_grid(x, y))
+ || (!pass_through_trans && see_grid_no_trans(x, y)))
rv += func(x, y, power, 0);
}
}
diff --git a/crawl-ref/source/spl-util.h b/crawl-ref/source/spl-util.h
index a29feb3a73..4570ea017a 100644
--- a/crawl-ref/source/spl-util.h
+++ b/crawl-ref/source/spl-util.h
@@ -101,7 +101,8 @@ const char* spelltype_short_name( int which_spelltype );
//int spell_restriction(int which_spell, int which_restriction);
-int apply_area_visible(int (*func) (int, int, int, int), int power);
+int apply_area_visible(int (*func) (int, int, int, int), int power,
+ bool pass_through_trans = false);
int apply_area_square(int (*func) (int, int, int, int),
int cx, int cy, int power);
diff --git a/crawl-ref/source/terrain.cc b/crawl-ref/source/terrain.cc
index 94decd4f1e..43ae6dc5b1 100644
--- a/crawl-ref/source/terrain.cc
+++ b/crawl-ref/source/terrain.cc
@@ -38,7 +38,10 @@ bool grid_is_wall( dungeon_feature_type grid )
|| grid == DNGN_METAL_WALL
|| grid == DNGN_GREEN_CRYSTAL_WALL
|| grid == DNGN_WAX_WALL
- || grid == DNGN_PERMAROCK_WALL);
+ || grid == DNGN_PERMAROCK_WALL
+ || grid == DNGN_CLEAR_ROCK_WALL
+ || grid == DNGN_CLEAR_STONE_WALL
+ || grid == DNGN_CLEAR_PERMAROCK_WALL);
}
bool grid_is_stone_stair(dungeon_feature_type grid)
diff --git a/crawl-ref/source/view.cc b/crawl-ref/source/view.cc
index 852bb65699..9d53d930d0 100644
--- a/crawl-ref/source/view.cc
+++ b/crawl-ref/source/view.cc
@@ -2064,7 +2064,7 @@ static bool superior_ray(int shortest, int imbalance,
bool find_ray( int sourcex, int sourcey, int targetx, int targety,
bool allow_fallback, ray_def& ray, int cycle_dir,
- bool find_shortest )
+ bool find_shortest, bool ignore_solid )
{
int cellray, inray;
const int signx = ((targetx - sourcex >= 0) ? 1 : -1);
@@ -2106,7 +2106,7 @@ bool find_ray( int sourcex, int sourcey, int targetx, int targety,
{
const int xi = signx * ray_coord_x[inray + cur_offset];
const int yi = signy * ray_coord_y[inray + cur_offset];
- if (inray < cellray
+ if (inray < cellray && !ignore_solid
&& grid_is_solid(grd[sourcex + xi][sourcey + yi]))
{
blocked = true;
@@ -2224,6 +2224,48 @@ bool find_ray( int sourcex, int sourcey, int targetx, int targety,
return false;
}
+// Count the number of matching features between two points along
+// a beam-like path; the path will pass through solid features.
+// By default, it exludes enpoints from the count.
+int num_feats_between(int sourcex, int sourcey, int targetx, int targety,
+ dungeon_feature_type min_feat,
+ dungeon_feature_type max_feat,
+ bool exclude_endpoints)
+{
+ ray_def ray;
+ int count = 0;
+ int max_dist = grid_distance(sourcex, sourcey, targetx, targety);
+
+ ray.fullray_idx = -1; // to quiet valgrind
+ find_ray( sourcex, sourcey, targetx, targety, true, ray, 0, true, true );
+
+ if (exclude_endpoints && ray.x() == sourcex && ray.y() == sourcey)
+ {
+ ray.advance(true);
+ max_dist--;
+ }
+
+ int dist = 0;
+ while (dist++ <= max_dist)
+ {
+ dungeon_feature_type feat = grd[ray.x()][ray.y()];
+
+ if (feat >= min_feat && feat <= max_feat)
+ count++;
+
+ if (ray.x() == targetx && ray.y() == targety)
+ {
+ if (exclude_endpoints && feat >= min_feat && feat <= max_feat)
+ count--;
+
+ break;
+ }
+ ray.advance(true);
+ }
+
+ return count;
+}
+
// The rule behind LOS is:
// Two cells can see each other if there is any line from some point
// of the first to some point of the second ("generous" LOS.)
@@ -2262,7 +2304,8 @@ bool find_ray( int sourcex, int sourcey, int targetx, int targety,
// Smoke will now only block LOS after two cells of smoke. This is
// done by updating with a second array.
void losight(FixedArray < unsigned int, 19, 19 > &sh,
- FixedArray < dungeon_feature_type, 80, 70 > &gr, int x_p, int y_p)
+ FixedArray < dungeon_feature_type, 80, 70 > &gr, int x_p, int y_p,
+ bool clear_walls_block)
{
raycast();
// go quadrant by quadrant
@@ -2299,7 +2342,8 @@ void losight(FixedArray < unsigned int, 19, 19 > &sh,
continue;
// if this cell is opaque...
- if ( grid_is_opaque(gr[realx][realy]) )
+ if ( grid_is_opaque(gr[realx][realy])
+ || (clear_walls_block && grid_is_wall(gr[realx][realy])))
{
// then block the appropriate rays
for ( unsigned int i = 0; i < num_words; ++i )
@@ -3341,6 +3385,33 @@ bool see_grid( int grx, int gry )
return (false);
} // end see_grid()
+// answers the question: "Would a grid be within character's line of sight,
+// even if all translucent/clear walls were made opaque?"
+bool see_grid_no_trans( int grx, int gry )
+{
+ // rare case: can player see self? (of course!)
+ if (grx == you.x_pos && gry == you.y_pos)
+ return (true);
+
+ // check no_trans_show array
+ if (grid_distance( grx, gry, you.x_pos, you.y_pos ) < 9)
+ {
+ const int ex = grx - you.x_pos + 9;
+ const int ey = gry - you.y_pos + 9;
+
+ if (env.no_trans_show[ex][ey])
+ return (true);
+ }
+
+ return (false);
+}
+
+// Is the grid visible, but a translucent wall is in the way?
+bool trans_wall_blocking( int grx, int gry )
+{
+ return see_grid(grx, gry) && !see_grid_no_trans(grx, gry);
+}
+
static const unsigned table[ NUM_CSET ][ NUM_DCHAR_TYPES ] =
{
// CSET_ASCII
@@ -3464,6 +3535,15 @@ void init_feature_table( void )
Feature[i].magic_symbol = Options.char_table[ DCHAR_WALL_MAGIC ];
break;
+ case DNGN_CLEAR_ROCK_WALL:
+ case DNGN_CLEAR_STONE_WALL:
+ case DNGN_CLEAR_PERMAROCK_WALL:
+ Feature[i].symbol = Options.char_table[ DCHAR_WALL ];
+ Feature[i].magic_symbol = Options.char_table[ DCHAR_WALL_MAGIC ];
+ Feature[i].colour = LIGHTCYAN;
+ break;
+
+
case DNGN_OPEN_DOOR:
Feature[i].symbol = Options.char_table[ DCHAR_DOOR_OPEN ];
Feature[i].colour = LIGHTGREY;
@@ -4217,6 +4297,10 @@ void viewwindow(bool draw_it, bool do_updates)
losight( env.show, grd, you.x_pos, you.y_pos ); // must be done first
+ // What would be visible, if all of the translucent walls were
+ // made opaque.
+ losight( env.no_trans_show, grd, you.x_pos, you.y_pos, true );
+
env.show_col.init(LIGHTGREY);
Show_Backup.init(0);
diff --git a/crawl-ref/source/view.h b/crawl-ref/source/view.h
index 3afd19bab6..d1fa30116b 100644
--- a/crawl-ref/source/view.h
+++ b/crawl-ref/source/view.h
@@ -93,7 +93,7 @@ void find_features(const std::vector<coord_def>& features,
* *********************************************************************** */
void losight(FixedArray<unsigned int, ENV_SHOW_DIAMETER, ENV_SHOW_DIAMETER>& sh,
FixedArray<dungeon_feature_type, GXM, GYM>& gr,
- int x_p, int y_p);
+ int x_p, int y_p, bool clear_walls_block = false);
bool magic_mapping(int map_radius, int proportion, bool suppress_msg,
@@ -184,6 +184,14 @@ void add_cset_override(char_set_type set, const std::string &overrides);
bool see_grid( int grx, int gry );
inline bool see_grid(const coord_def &p) { return see_grid(p.x, p.y); }
+bool see_grid_no_trans( int grx, int gry );
+inline bool see_grid_no_trans(const coord_def &p)
+{
+ return see_grid_no_trans(p.x, p.y);
+}
+
+bool trans_wall_blocking( int grx, int gry );
+
std::string screenshot(bool fullscreen = false);
unsigned get_sightmap_char(int feature);
@@ -197,7 +205,12 @@ void fire_monster_alerts();
struct ray_def;
bool find_ray( int sourcex, int sourcey, int targetx, int targety,
bool allow_fallback, ray_def& ray, int cycle_dir = 0,
- bool find_shortest = false );
+ bool find_shortest = false, bool ignore_solid = false );
+
+int num_feats_between(int sourcex, int sourcey, int targetx, int targety,
+ dungeon_feature_type min_feat,
+ dungeon_feature_type max_feat,
+ bool exclude_endpoints = true);
dungeon_char_type dchar_by_name(const std::string &name);