summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/direct.cc
diff options
context:
space:
mode:
Diffstat (limited to 'crawl-ref/source/direct.cc')
-rw-r--r--crawl-ref/source/direct.cc164
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;