diff options
Diffstat (limited to 'crawl-ref/source')
-rw-r--r-- | crawl-ref/source/acr.cc | 4 | ||||
-rw-r--r-- | crawl-ref/source/beam.cc | 9 | ||||
-rw-r--r-- | crawl-ref/source/clua.cc | 7 | ||||
-rw-r--r-- | crawl-ref/source/dat/descript/features.txt | 12 | ||||
-rw-r--r-- | crawl-ref/source/dat/glass.des | 153 | ||||
-rw-r--r-- | crawl-ref/source/delay.cc | 2 | ||||
-rw-r--r-- | crawl-ref/source/direct.cc | 6 | ||||
-rw-r--r-- | crawl-ref/source/dungeon.cc | 9 | ||||
-rw-r--r-- | crawl-ref/source/enum.h | 14 | ||||
-rw-r--r-- | crawl-ref/source/externs.h | 5 | ||||
-rw-r--r-- | crawl-ref/source/luadgn.cc | 3 | ||||
-rw-r--r-- | crawl-ref/source/misc.cc | 3 | ||||
-rw-r--r-- | crawl-ref/source/monplace.cc | 5 | ||||
-rw-r--r-- | crawl-ref/source/monstuff.cc | 97 | ||||
-rw-r--r-- | crawl-ref/source/spells1.cc | 59 | ||||
-rw-r--r-- | crawl-ref/source/spells1.h | 3 | ||||
-rw-r--r-- | crawl-ref/source/spells2.cc | 13 | ||||
-rw-r--r-- | crawl-ref/source/spells4.cc | 60 | ||||
-rw-r--r-- | crawl-ref/source/spl-util.cc | 6 | ||||
-rw-r--r-- | crawl-ref/source/spl-util.h | 3 | ||||
-rw-r--r-- | crawl-ref/source/terrain.cc | 5 | ||||
-rw-r--r-- | crawl-ref/source/view.cc | 92 | ||||
-rw-r--r-- | crawl-ref/source/view.h | 17 |
23 files changed, 521 insertions, 66 deletions
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); |