diff options
Diffstat (limited to 'crawl-ref/source/direct.cc')
-rw-r--r-- | crawl-ref/source/direct.cc | 164 |
1 files changed, 113 insertions, 51 deletions
diff --git a/crawl-ref/source/direct.cc b/crawl-ref/source/direct.cc index b7921d6a3f..55c807cfc6 100644 --- a/crawl-ref/source/direct.cc +++ b/crawl-ref/source/direct.cc @@ -85,21 +85,21 @@ enum LOSSelect static void describe_feature(int mx, int my, bool oos); static void describe_cell(int mx, int my); -static bool find_object( int x, int y, int mode ); -static bool find_monster( int x, int y, int mode ); -static bool find_feature( int x, int y, int mode ); +static bool find_object( int x, int y, int mode, int range ); +static bool find_monster( int x, int y, int mode, int range ); +static bool find_feature( int x, int y, int mode, int range ); static char find_square_wrapper( int tx, int ty, FixedVector<char, 2> &mfp, char direction, - bool (*targ)(int, int, int), - int mode = TARG_ANY, + bool (*targ)(int, int, int, int), + int mode = TARG_ANY, int range = -1, bool wrap = false, int los = LOS_ANY); static char find_square( int xps, int yps, FixedVector<char, 2> &mfp, int direction, - bool (*targ)(int, int, int), - int mode = TARG_ANY, + bool (*targ)(int, int, int, int), + int mode = TARG_ANY, int range = -1, bool wrap = false, int los = LOS_ANY); @@ -121,7 +121,8 @@ void direction_choose_compass( dist& moves, targeting_behaviour *beh) beh->compass = true; - do { + do + { const command_type key_command = beh->get_command(); if (key_command == CMD_TARGET_SELECT) @@ -142,7 +143,8 @@ void direction_choose_compass( dist& moves, targeting_behaviour *beh) moves.isCancel = true; moves.isValid = false; } - } while ( !moves.isCancel && moves.dx == 0 && moves.dy == 0 ); + } + while ( !moves.isCancel && moves.dx == 0 && moves.dy == 0 ); return; } @@ -244,6 +246,15 @@ static void draw_ray_glyph(const coord_def &pos, int colour, #endif } +static bool _is_target_in_range(int x, int y, int range) +{ + // range doesn't matter + if (range == -1) + return true; + + return (grid_distance(you.x_pos, you.y_pos, x, y) <= range); +} + // We handle targeting for repeating commands and re-doing the // previous command differently (i.e., not just letting the keys // stuffed into the macro buffer replay as-is) because if the player @@ -251,7 +262,7 @@ static void draw_ray_glyph(const coord_def &pos, int colour, // moved between repititions, then simply replaying the keys in the // buffer will target an empty square. static void direction_again(dist& moves, targeting_type restricts, - targ_mode_type mode, bool just_looking, + targ_mode_type mode, int range, bool just_looking, const char *prompt, targeting_behaviour *beh) { moves.isValid = false; @@ -325,7 +336,16 @@ static void direction_again(dist& moves, targeting_type restricts, "square."); return; } + else if (!_is_target_in_range(you.prev_grd_targ.x, you.prev_grd_targ.y, + range)) + { + moves.isCancel = true; + crawl_state.cancel_cmd_repeat("Your previous target is now out of " + "range."); + return; + } + moves.tx = you.prev_grd_targ.x; moves.ty = you.prev_grd_targ.y; @@ -348,8 +368,8 @@ static void direction_again(dist& moves, targeting_type restricts, { const monsters *montarget = &menv[you.prev_targ]; - if (!mons_near(montarget) || - !player_monster_visible( montarget )) + if (!mons_near(montarget) + || !player_monster_visible( montarget )) { moves.isCancel = true; @@ -357,6 +377,15 @@ static void direction_again(dist& moves, targeting_type restricts, return; } + else if (!_is_target_in_range(you.prev_grd_targ.x, you.prev_grd_targ.y, + range)) + { + moves.isCancel = true; + + crawl_state.cancel_cmd_repeat("Your previous target is now out of " + "range."); + return; + } moves.tx = montarget->x; moves.ty = montarget->y; @@ -394,7 +423,7 @@ static void direction_again(dist& moves, targeting_type restricts, // //--------------------------------------------------------------- void direction(dist& moves, targeting_type restricts, - targ_mode_type mode, bool just_looking, + targ_mode_type mode, int range, bool just_looking, bool needs_path, const char *prompt, targeting_behaviour *beh) { @@ -406,7 +435,7 @@ void direction(dist& moves, targeting_type restricts, if (crawl_state.is_replaying_keys() && restricts != DIR_DIR) { - direction_again(moves, restricts, mode, just_looking, + direction_again(moves, restricts, mode, range, just_looking, prompt, beh); return; } @@ -449,7 +478,9 @@ void direction(dist& moves, targeting_type restricts, if ( you.prev_targ != MHITNOT && you.prev_targ != MHITYOU ) { const monsters *montarget = &menv[you.prev_targ]; - if (mons_near(montarget) && player_monster_visible(montarget)) + if ( mons_near(montarget) && player_monster_visible(montarget) + && !mons_friendly(montarget) // not made friendly since then + && _is_target_in_range(montarget->x, montarget->y, range) ) { found_autotarget = true; moves.tx = montarget->x; @@ -661,7 +692,7 @@ void direction(dist& moves, targeting_type restricts, { const int thing_to_find = targeting_cmd_to_feature(key_command); if (find_square_wrapper(moves.tx, moves.ty, objfind_pos, 1, - find_feature, thing_to_find, true, + find_feature, thing_to_find, range, true, Options.target_los_first ? LOS_FLIPVH : LOS_ANY)) { @@ -749,7 +780,7 @@ void direction(dist& moves, targeting_type restricts, case CMD_TARGET_OBJ_CYCLE_FORWARD: dir = (key_command == CMD_TARGET_OBJ_CYCLE_BACK) ? -1 : 1; if (find_square_wrapper( moves.tx, moves.ty, objfind_pos, dir, - find_object, 0, true, + find_object, 0, range, true, Options.target_los_first ? (dir == 1? LOS_FLIPVH : LOS_FLIPHV) : LOS_ANY)) @@ -768,7 +799,8 @@ void direction(dist& moves, targeting_type restricts, case CMD_TARGET_CYCLE_BACK: dir = (key_command == CMD_TARGET_CYCLE_BACK) ? -1 : 1; if (find_square_wrapper( moves.tx, moves.ty, monsfind_pos, dir, - find_monster, mode, Options.target_wrap )) + find_monster, mode, range, + Options.target_wrap)) { moves.tx = monsfind_pos[0]; moves.ty = monsfind_pos[1]; @@ -1081,27 +1113,45 @@ bool in_los(int x, int y) return (in_vlos(grid2view(coord_def(x, y)))); } -static bool find_monster( int x, int y, int mode ) +static bool find_monster( int x, int y, int mode, int range = -1) { - const int targ_mon = mgrd[ x ][ y ]; if ((mode == TARG_FRIEND || mode == TARG_ANY) - && x == you.x_pos && y == you.y_pos) + && x == you.x_pos && y == you.y_pos) + { return (true); + } - return (targ_mon != NON_MONSTER - && in_los(x, y) - && player_monster_visible( &(menv[targ_mon]) ) - && !mons_is_mimic( menv[targ_mon].type ) - && (mode == TARG_ANY - || (mode == TARG_FRIEND && mons_friendly( &menv[targ_mon] )) - || (mode == TARG_ENEMY - && !mons_friendly( &menv[targ_mon] ) - && - (Options.target_zero_exp || - !mons_class_flag( menv[targ_mon].type, M_NO_EXP_GAIN )) ))); + // don't target out of range + if (!_is_target_in_range(x, y, range)) + return (false); + + const int targ_mon = mgrd[ x ][ y ]; + + // Is target a (known) monster? + if (targ_mon == NON_MONSTER || !in_los(x,y) + || !player_monster_visible( &(menv[targ_mon]) ) + || mons_is_mimic(menv[targ_mon].type) + && !(menv[targ_mon].flags & MF_KNOWN_MIMIC)) + { + return (false); + } + + // Now compare target modes. + if (mode == TARG_ANY) + return true; + + if (mode == TARG_FRIEND) + return (mons_friendly(&menv[targ_mon] )); + + if (mode != TARG_ENEMY) + return false; + + return ( !mons_friendly( &menv[targ_mon] ) + && (Options.target_zero_exp + || !mons_class_flag( menv[targ_mon].type, M_NO_EXP_GAIN )) ); } -static bool find_feature( int x, int y, int mode ) +static bool find_feature( int x, int y, int mode, int /* range */) { // The stair need not be in LOS if the square is mapped. if (!in_los(x, y) && (!Options.target_oos || !is_terrain_seen(x, y))) @@ -1110,14 +1160,25 @@ static bool find_feature( int x, int y, int mode ) return is_feature(mode, x, y); } -static bool find_object(int x, int y, int mode) +static bool find_object(int x, int y, int mode, int /* range */) { + // First, check for mimics. + bool is_mimic = false; + const int mons = mgrd[ x ][ y ]; + if (mons != NON_MONSTER + && player_monster_visible( &(menv[mons]) ) + && mons_is_mimic(menv[mons].type) + && !(menv[mons].flags & MF_KNOWN_MIMIC)) + { + is_mimic = true; + } + const int item = igrd[x][y]; - // The square need not be in LOS if the stash tracker knows this item. - return (item != NON_ITEM - && (in_los(x, y) - || (Options.target_oos && is_terrain_seen(x, y) - && is_stash(x, y)))); + if (item == NON_ITEM && !is_mimic) + return false; + + return (in_los(x, y) || Options.target_oos && is_terrain_seen(x, y) + && (is_stash(x, y) || is_mimic)); } static int next_los(int dir, int los, bool wrap) @@ -1192,8 +1253,8 @@ bool in_los_bounds(int x, int y) //--------------------------------------------------------------- static char find_square( int xps, int yps, FixedVector<char, 2> &mfp, int direction, - bool (*find_targ)( int x, int y, int mode ), - int mode, bool wrap, int los ) + bool (*find_targ)( int x, int y, int mode, int range ), + int mode, int range, bool wrap, int los ) { // the day will come when [unsigned] chars will be consigned to // the fires of Gehenna. Not quite yet, though. @@ -1257,19 +1318,19 @@ static char find_square( int xps, int yps, { if (direction == 1 && temp_xps == minx && temp_yps == maxy) { - if (find_targ(you.x_pos, you.y_pos, mode)) + if (find_targ(you.x_pos, you.y_pos, mode, range)) { mfp[0] = ctrx; mfp[1] = ctry; return (1); } return find_square(ctrx, ctry, mfp, direction, find_targ, mode, - false, next_los(direction, los, wrap)); + range, false, next_los(direction, los, wrap)); } if (direction == -1 && temp_xps == ctrx && temp_yps == ctry) { return find_square(minx, maxy, mfp, direction, find_targ, mode, - false, next_los(direction, los, wrap)); + range, false, next_los(direction, los, wrap)); } if (direction == 1) @@ -1397,7 +1458,7 @@ static char find_square( int xps, int yps, if ((onlyVis || onlyHidden) && onlyVis != in_los(targ_x, targ_y)) continue; - if (find_targ(targ_x, targ_y, mode)) + if (find_targ(targ_x, targ_y, mode, range)) { mfp[0] = temp_xps; mfp[1] = temp_yps; @@ -1406,9 +1467,9 @@ static char find_square( int xps, int yps, } return (direction == 1? - find_square(ctrx, ctry, mfp, direction, find_targ, mode, false, + find_square(ctrx, ctry, mfp, direction, find_targ, mode, range, false, next_los(direction, los, wrap)) - : find_square(minx, maxy, mfp, direction, find_targ, mode, false, + : find_square(minx, maxy, mfp, direction, find_targ, mode, range, false, next_los(direction, los, wrap))); } @@ -1417,11 +1478,12 @@ static char find_square( int xps, int yps, // (mfp) are in grid coordinates rather than view coordinates. static char find_square_wrapper( int tx, int ty, FixedVector<char, 2> &mfp, char direction, - bool (*find_targ)( int x, int y, int mode ), - int mode, bool wrap, int los ) + bool (*find_targ)( int x, int y, int mode, + int range ), + int mode, int range, bool wrap, int los ) { - const char r = find_square(grid2viewX(tx), grid2viewY(ty), - mfp, direction, find_targ, mode, wrap, los); + const char r = find_square(grid2viewX(tx), grid2viewY(ty), mfp, + direction, find_targ, mode, range, wrap, los); mfp[0] = view2gridX(mfp[0]); mfp[1] = view2gridY(mfp[1]); return r; |