summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/direct.cc
diff options
context:
space:
mode:
authorj-p-e-g <j-p-e-g@c06c8d41-db1a-0410-9941-cceddc491573>2008-03-31 22:56:26 +0000
committerj-p-e-g <j-p-e-g@c06c8d41-db1a-0410-9941-cceddc491573>2008-03-31 22:56:26 +0000
commit6ce835d28c2081d13222a9faedc350ece4abb11b (patch)
treefd4e17d21f8fcecb94a9e672717516eb25edadce /crawl-ref/source/direct.cc
parent14fce897135078ec3542c0d96b751f58544bae99 (diff)
downloadcrawl-ref-6ce835d28c2081d13222a9faedc350ece4abb11b.tar.gz
crawl-ref-6ce835d28c2081d13222a9faedc350ece4abb11b.zip
Fix 1869850: Targeting now respects mimics' (un)known status correctly,
so that * and / work for unknown ones, and + and - for known ones. Also, mimics become known if you hit them since the resulting message ("moderately damaged" or "looks slightly unstable") will give that away anyway. Implement the first part of FR 1903048: Added a range parameter to direction(), so that when targeting for weapons of reaching we can check whether a monster is within the range of 2 squares (grid_distance). Does not handle submerged monsters. Eventually, this could be used to also limit max range for certain spells (Freeze, I'm looking at you!) git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@3995 c06c8d41-db1a-0410-9941-cceddc491573
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;