summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crawl-ref/source/beam.cc3
-rw-r--r--crawl-ref/source/directn.cc29
-rw-r--r--crawl-ref/source/los.cc42
-rw-r--r--crawl-ref/source/los.h9
-rw-r--r--crawl-ref/source/spells4.cc3
5 files changed, 56 insertions, 30 deletions
diff --git a/crawl-ref/source/beam.cc b/crawl-ref/source/beam.cc
index fc7c8d2d98..e0c7dc5f99 100644
--- a/crawl-ref/source/beam.cc
+++ b/crawl-ref/source/beam.cc
@@ -2852,8 +2852,7 @@ bool check_line_of_sight(const coord_def& source, const coord_def& target)
// Note that we are guaranteed to be within the player LOS range,
// so fallback is unnecessary.
- ray_def ray;
- return find_ray(source, target, ray);
+ return exists_ray(source, target);
}
// When a mimic is hit by a ranged attack, it teleports away (the slow
diff --git a/crawl-ref/source/directn.cc b/crawl-ref/source/directn.cc
index 15d3ebd572..45aaacbdcb 100644
--- a/crawl-ref/source/directn.cc
+++ b/crawl-ref/source/directn.cc
@@ -960,26 +960,17 @@ bool _dist_ok(const dist& moves, int range, targ_mode_type mode,
return (true);
}
-// XXX: fold this into generalized find_ray.
+// Assuming the target is in view, is line-of-fire
+// blocked, and by what?
static bool _blocked_ray(const coord_def &where,
dungeon_feature_type* feat = NULL)
{
- ray_def ray;
- if (!find_ray(you.pos(), where, ray))
- fallback_ray(you.pos(), where, ray);
- ray.advance_through(where);
-
- while (ray.pos() != where)
- {
- if (grd(ray.pos()) <= DNGN_MINMOVE)
- {
- if (feat != NULL)
- *feat = grd(ray.pos());
- return (true);
- }
- ray.advance_through(where);
- }
- return (false);
+ if (exists_ray(you.pos(), where))
+ return (false);
+ if (feat == NULL)
+ return (true);
+ *feat = ray_blocker(you.pos(), where);
+ return (true);
}
void direction(dist& moves, targetting_type restricts,
@@ -1316,7 +1307,8 @@ void direction(dist& moves, targetting_type restricts,
#ifdef WIZARD
case CMD_TARGET_CYCLE_BEAM:
show_beam = true;
- have_beam = find_ray(you.pos(), moves.target, ray, show_beam);
+ have_beam = find_ray(you.pos(), moves.target, ray,
+ opc_solid, bds_default, show_beam);
need_beam_redraw = true;
break;
#endif
@@ -3353,6 +3345,7 @@ std::string get_monster_equipment_desc(const monsters *mon, bool full_desc,
return desc;
}
+// Describe a cell, guaranteed to be in view.
static void _describe_cell(const coord_def& where, bool in_range)
{
bool mimic_item = false;
diff --git a/crawl-ref/source/los.cc b/crawl-ref/source/los.cc
index c7b8ddef74..38de458419 100644
--- a/crawl-ref/source/los.cc
+++ b/crawl-ref/source/los.cc
@@ -581,8 +581,8 @@ void cellray::calc_params()
// opc has been translated for this quadrant.
// XXX: Allow finding ray of minimum opacity.
bool _find_ray_se(const coord_def& target, ray_def& ray,
- bool cycle, const opacity_func& opc,
- const bounds_func& bds)
+ const opacity_func& opc, const bounds_func& bds,
+ bool cycle)
{
ASSERT(target.x >= 0 && target.y >= 0 && !target.origin());
if (!bds(target))
@@ -653,8 +653,8 @@ struct opacity_trans : opacity_func
// assume that ray is appropriately filled in, and look for the next
// ray. We only ever use ray.cycle_idx.
bool find_ray(const coord_def& source, const coord_def& target,
- ray_def& ray, bool cycle,
- const opacity_func& opc, const bounds_func &bds)
+ ray_def& ray, const opacity_func& opc, const bounds_func &bds,
+ bool cycle)
{
if (target == source || !map_bounds(source) || !map_bounds(target))
return false;
@@ -666,7 +666,7 @@ bool find_ray(const coord_def& source, const coord_def& target,
const coord_def abs = coord_def(absx, absy);
opacity_trans opc_trans = opacity_trans(opc, source, signx, signy);
- if (!_find_ray_se(abs, ray, cycle, opc_trans, bds))
+ if (!_find_ray_se(abs, ray, opc_trans, bds, cycle))
return (false);
if (signx < 0)
@@ -682,6 +682,38 @@ bool find_ray(const coord_def& source, const coord_def& target,
return (true);
}
+bool exists_ray(const coord_def& source, const coord_def& target,
+ const opacity_func& opc, const bounds_func &bds)
+{
+ ray_def ray;
+ return (find_ray(source, target, ray, opc, bds));
+}
+
+// Assuming that target is in view of source, but line of
+// fire is blocked, what is it blocked by?
+dungeon_feature_type ray_blocker(const coord_def& source,
+ const coord_def& target)
+{
+ ray_def ray;
+ if (!find_ray(source, target, ray, opc_default))
+ {
+ ASSERT (false);
+ return (NUM_REAL_FEATURES);
+ }
+
+ ray.advance(false); // Must not cut corners!
+ int blocked = 0;
+ while (ray.pos() != target)
+ {
+ blocked += opc_solid(ray.pos());
+ if (blocked >= OPC_OPAQUE)
+ return (env.grid(ray.pos()));
+ ray.advance(false);
+ }
+ ASSERT (false);
+ return (NUM_REAL_FEATURES);
+}
+
// Returns a straight ray from source to target.
void fallback_ray(const coord_def& source, const coord_def& target,
ray_def& ray)
diff --git a/crawl-ref/source/los.h b/crawl-ref/source/los.h
index 7041c2af0d..92d00090e0 100644
--- a/crawl-ref/source/los.h
+++ b/crawl-ref/source/los.h
@@ -19,9 +19,12 @@ int get_los_radius_squared(); // XXX
struct ray_def;
bool find_ray(const coord_def& source, const coord_def& target,
- ray_def& ray, bool cycle = false,
- const opacity_func &opc = opc_solid,
- const bounds_func &bds = bds_default);
+ ray_def& ray, const opacity_func &opc = opc_solid,
+ const bounds_func &bds = bds_default, bool cycle = false);
+bool exists_ray(const coord_def& source, const coord_def& target,
+ const opacity_func &opc = opc_solid,
+ const bounds_func &bds = bds_default);
+dungeon_feature_type ray_blocker(const coord_def& source, const coord_def& target);
void fallback_ray(const coord_def& source, const coord_def& target,
ray_def& ray);
diff --git a/crawl-ref/source/spells4.cc b/crawl-ref/source/spells4.cc
index 5fe91b53bd..0339e79934 100644
--- a/crawl-ref/source/spells4.cc
+++ b/crawl-ref/source/spells4.cc
@@ -1371,8 +1371,7 @@ bool cast_fragmentation(int pow, const dist& spd)
bool hole = true;
const char *what = NULL;
- ray_def ray;
- if (!find_ray(you.pos(), spd.target, ray))
+ if (!exists_ray(you.pos(), spd.target))
{
mpr("There's a wall in the way!");
return (false);