summaryrefslogtreecommitdiffstats
path: root/crawl-ref
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
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')
-rw-r--r--crawl-ref/source/acr.cc2
-rw-r--r--crawl-ref/source/beam.cc19
-rw-r--r--crawl-ref/source/direct.cc164
-rw-r--r--crawl-ref/source/direct.h6
-rw-r--r--crawl-ref/source/effects.cc4
-rw-r--r--crawl-ref/source/it_use3.cc2
-rw-r--r--crawl-ref/source/item_use.cc2
-rw-r--r--crawl-ref/source/spells1.cc4
-rw-r--r--crawl-ref/source/spl-util.cc2
9 files changed, 140 insertions, 65 deletions
diff --git a/crawl-ref/source/acr.cc b/crawl-ref/source/acr.cc
index c928a43982..534c6117c5 100644
--- a/crawl-ref/source/acr.cc
+++ b/crawl-ref/source/acr.cc
@@ -2180,7 +2180,7 @@ void process_command( command_type cmd )
MSGCH_PROMPT);
struct dist lmove; // will be initialized by direction()
- direction(lmove, DIR_TARGET, TARG_ANY, true);
+ direction(lmove, DIR_TARGET, TARG_ANY, -1, true);
if (lmove.isValid && lmove.isTarget && !lmove.isCancel)
start_travel( lmove.tx, lmove.ty );
break;
diff --git a/crawl-ref/source/beam.cc b/crawl-ref/source/beam.cc
index bc76bf2e5d..a9d8abf02c 100644
--- a/crawl-ref/source/beam.cc
+++ b/crawl-ref/source/beam.cc
@@ -2347,10 +2347,25 @@ bool check_line_of_sight( int sx, int sy, int tx, int ty )
*/
void mimic_alert(monsters *mimic)
{
+ bool should_id = !testbits(mimic->flags, MF_KNOWN_MIMIC)
+ && player_monster_visible(mimic) && mons_near(mimic);
+
+ // If we got here, we at least got a resists message, if not
+ // a full wounds printing. Thus, might as well id the mimic.
if (mimic->has_ench(ENCH_TP))
+ {
+ if (should_id)
+ mimic->flags |= MF_KNOWN_MIMIC;
+
return;
-
- monster_teleport( mimic, !one_chance_in(3) );
+ }
+
+ const bool instant_tele = !one_chance_in(3);
+ monster_teleport( mimic, instant_tele );
+
+ // at least for this short while, we know it's a mimic
+ if (!instant_tele && should_id)
+ mimic->flags |= MF_KNOWN_MIMIC;
} // end mimic_alert()
static bool _isBouncy(bolt &beam, unsigned char gridtype)
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;
diff --git a/crawl-ref/source/direct.h b/crawl-ref/source/direct.h
index a7b8382691..702d2ffd97 100644
--- a/crawl-ref/source/direct.h
+++ b/crawl-ref/source/direct.h
@@ -147,9 +147,9 @@ struct dist
};
void direction( dist &moves, targeting_type restricts = DIR_NONE,
- targ_mode_type mode = TARG_ANY, bool just_looking = false,
- bool needs_path = true, const char *prompt = NULL,
- targeting_behaviour *mod = NULL );
+ targ_mode_type mode = TARG_ANY, int range = -1,
+ bool just_looking = false, bool needs_path = true,
+ const char *prompt = NULL, targeting_behaviour *mod = NULL );
bool in_los_bounds(int x, int y);
bool in_viewport_bounds(int x, int y);
diff --git a/crawl-ref/source/effects.cc b/crawl-ref/source/effects.cc
index 0913e3a9ba..5921bece0f 100644
--- a/crawl-ref/source/effects.cc
+++ b/crawl-ref/source/effects.cc
@@ -1915,7 +1915,7 @@ void yell(bool force)
}
mpr("Gang up on whom?", MSGCH_PROMPT);
- direction( targ, DIR_TARGET, TARG_ENEMY, false, false );
+ direction( targ, DIR_TARGET, TARG_ENEMY, -1, false, false );
if (targ.isCancel)
{
@@ -2024,7 +2024,6 @@ bool vitrify_area(int radius)
const int clear_plus = DNGN_CLEAR_ROCK_WALL - DNGN_ROCK_WALL;
bool something_happened = false;
for ( int x = X_BOUND_1; x <= X_BOUND_2; ++x )
- {
for ( int y = Y_BOUND_1; y <= Y_BOUND_2; ++y )
{
if ( distance(x,y,you.x_pos,you.y_pos) < radius2 )
@@ -2041,7 +2040,6 @@ bool vitrify_area(int radius)
}
}
}
- }
return (something_happened);
}
diff --git a/crawl-ref/source/it_use3.cc b/crawl-ref/source/it_use3.cc
index 6f7da402d3..3ce951dc19 100644
--- a/crawl-ref/source/it_use3.cc
+++ b/crawl-ref/source/it_use3.cc
@@ -257,7 +257,7 @@ static bool reaching_weapon_attack(const item_def& wpn)
mpr("Attack whom?", MSGCH_PROMPT);
- direction(beam, DIR_TARGET, TARG_ENEMY);
+ direction(beam, DIR_TARGET, TARG_ENEMY, 2);
if (!beam.isValid)
return false;
diff --git a/crawl-ref/source/item_use.cc b/crawl-ref/source/item_use.cc
index 1fbbb65bea..ca1cf7a46f 100644
--- a/crawl-ref/source/item_use.cc
+++ b/crawl-ref/source/item_use.cc
@@ -1511,7 +1511,7 @@ static bool _fire_choose_item_and_target(int& item, dist& target)
beh.message_ammo_prompt();
message_current_target(); // XXX: this stuff should be done by direction()
- direction( target, DIR_NONE, TARG_ENEMY, false, true, NULL, &beh );
+ direction( target, DIR_NONE, TARG_ENEMY, -1, false, true, NULL, &beh );
if (beh.item == ENDOFPACK)
{
diff --git a/crawl-ref/source/spells1.cc b/crawl-ref/source/spells1.cc
index 01c06d2fd7..e9e2e21617 100644
--- a/crawl-ref/source/spells1.cc
+++ b/crawl-ref/source/spells1.cc
@@ -102,7 +102,7 @@ int blink(int pow, bool high_level_controlled_blink, bool wizard_blink)
// query for location {dlb}:
for (;;)
{
- direction(beam, DIR_TARGET, TARG_ANY, false, false,
+ direction(beam, DIR_TARGET, TARG_ANY, -1, false, false,
"Blink to where?");
if (!beam.isValid || coord_def(beam.tx, beam.ty) == you.pos())
@@ -489,7 +489,7 @@ bool conjure_flame(int pow)
done_first_message = true;
}
- direction( spelld, DIR_TARGET, TARG_ENEMY, false, false );
+ direction( spelld, DIR_TARGET, TARG_ENEMY, -1, false, false );
if (!spelld.isValid)
{
diff --git a/crawl-ref/source/spl-util.cc b/crawl-ref/source/spl-util.cc
index 1a35365798..2aec6deff0 100644
--- a/crawl-ref/source/spl-util.cc
+++ b/crawl-ref/source/spl-util.cc
@@ -756,7 +756,7 @@ bool spell_direction( dist &spelld, bolt &pbolt,
if (restrict != DIR_DIR)
message_current_target();
- direction( spelld, restrict, mode, false, needs_path, prompt );
+ direction( spelld, restrict, mode, -1, false, needs_path, prompt );
if (!spelld.isValid)
{