summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/ray.cc
diff options
context:
space:
mode:
authorNeil Moore <neil@s-z.org>2013-09-06 23:39:35 -0400
committerNeil Moore <neil@s-z.org>2013-09-06 23:41:56 -0400
commitd5d8a818bb7867862396b3f76bcd511b574ef457 (patch)
tree39e7498f602137410606c969d37463e0e69110bf /crawl-ref/source/ray.cc
parentd60a8dff6c7b2c4ff34715fb0f15f1e556779101 (diff)
downloadcrawl-ref-d5d8a818bb7867862396b3f76bcd511b574ef457.tar.gz
crawl-ref-d5d8a818bb7867862396b3f76bcd511b574ef457.zip
Fix a chaos bounce crash (#5892).
It wasn't safe to change the angle of a ray that was on a corner of the 45-degree diamond grid: if the new angle pointed inside the cell, we would violate the _valid() checks. Have set_degrees (only called for chaos bouncing currently) nudge the ray inside the diamond to avoid this problem.
Diffstat (limited to 'crawl-ref/source/ray.cc')
-rw-r--r--crawl-ref/source/ray.cc28
1 files changed, 20 insertions, 8 deletions
diff --git a/crawl-ref/source/ray.cc b/crawl-ref/source/ray.cc
index c14204e2ce..0066bce38a 100644
--- a/crawl-ref/source/ray.cc
+++ b/crawl-ref/source/ray.cc
@@ -468,6 +468,17 @@ static geom::ray _bounce_corner(const geom::ray &rorig, const coord_def &side,
return r;
}
+// Nudge an on-corner ray to be inside the diamond.
+void ray_def::nudge_inside()
+{
+ ASSERT(on_corner);
+ geom::vector centre(pos().x + 0.5, pos().y + 0.5);
+ // Move a little bit towards cell center.
+ r.start = 0.9 * r.start + 0.1 * centre;
+ on_corner = false;
+ ASSERT(in_diamond_int(r.start));
+}
+
void ray_def::bounce(const reflect_grid &rg)
{
ASSERT(_valid());
@@ -476,20 +487,16 @@ void ray_def::bounce(const reflect_grid &rg)
const coord_def old_pos = pos();
#endif
+ // If we're exactly on a corner, adjust to slightly inside the diamond.
+ if (on_corner)
+ nudge_inside();
+
// Translate to cell (0,0).
geom::vector p(pos().x, pos().y);
geom::ray rtrans;
rtrans.start = r.start - p;
rtrans.dir = r.dir;
- if (on_corner)
- {
- // Move a little bit towards cell center (0.5, 0.5).
- rtrans.start = 0.9 * rtrans.start + 0.1 * geom::vector(0.5, 0.5);
- on_corner = false;
- ASSERT(in_diamond_int(rtrans.start));
- }
-
// Move to the diamond edge to determine the side.
coord_def side;
bool corner = _to_grid(&rtrans, false);
@@ -531,5 +538,10 @@ double ray_def::get_degrees() const
void ray_def::set_degrees(double d)
{
+ // Changing the angle while on a diamond corner causes problems when the
+ // new direction points inside a diamond (#5892). Move the ray slightly
+ // inside the diamond first correct for this.
+ if (on_corner)
+ nudge_inside();
r.dir = geom::degree_to_vector(d);
}