prevents chaos beams from bouncing thorugh walls.
If the beam passes out of bounds (the player was right at an edge of the map and fired the beam off the map) then finish the beam and regress back into bounds.
Always finish beam if it hits a wall and neither affects the wall nor bounces.
Regress out of walls before dropping an item.
Don't regress out of walls if target == source.
More assertions.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@7977 c06c8d41-db1a-0410-9941-cceddc491573
SNSU5AMDAZNG55NQ4JDHU2YBK62MXPIE2QTSYS7PGV7Y2N3VJBFQC
if (new_deg < old_deg)
shift = -shift;
new_ray.set_degrees(new_deg + shift);
ray_def temp_ray = new_ray;
for (int tries = 0; tries < 20; tries++)
{
shift = (double) random_range(min * 10000, max * 10000) / 10000.0;
if (new_deg < old_deg)
shift = -shift;
temp_ray.set_degrees(new_deg + shift);
// Don't bounce straight into another wall. Can happen if the beam
// is shot into an inside corner.
ray_def test_ray = temp_ray;
test_ray.advance(true);
if (in_bounds(test_ray.pos()) && !grid_is_solid(test_ray.pos()))
break;
shift = 0.0;
temp_ray = new_ray;
}
// XXX HACK: This is to avoid a problem which seems to be caused by
// ray.advance(true) taking the shortest path but ray.regress() using raw
// advancement to backtrack: say that the user fires a chaos beam
// south-west into the corner, the bouncing code regresses it to point X,
// then it randomly changes direction to slightly south of
// due east:
//
// #####
// # @ #
// #X #
// Y#####
//
// The ray advances via shortest path into the wall grid two squares
// directly south of the player, and then tries to regress for another
// bounce. However, it uses raw advancement to regress, which updates the
// internal floating point representation of the position, and since it's
// now travelling almost due west as it "regresses" it stays inside the
// wall until it reaches point Y. (At least, I think that's what's
// happening. The result is definitely the chaos beam passing through
// the corner and ending up outside the room)
//
// Everything else I've tried to fix this causes an assertion somewhere
// else.
new_ray.advance(true);
new_ray.regress();
// Regress for explosions: blow up one step earlier.
if (is_explosion && !in_explosion_phase)
// Regress for explosions: blow up in an open grid (if regressing
// makes any sense). Also regress when dropping items.
if (!aimed_at_spot
&& ((is_explosion && !in_explosion_phase) || drop_item))