NOTE: This uses a weird hack to prevent a bug which sometimes happens when a chaos beam is fired into the corner of a room. I think it's caused by ray.advance(true) and ray.regress() not being symmetrical.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@7783 c06c8d41-db1a-0410-9941-cceddc491573
Q52ILIIFMJ6HBSIUF7V7XQ6DQJGGYMHUZJ6CWVQKDX2JKBHEP2HAC AYU5OVG2HZO46KDAPKUWAVHS5HTYFKUWIMIRMTHAXVVFEDJE7YPAC GVCGKTH5IJ4VSQEIN4CRC7ZFVZW26JPIYNCPTO7GY66CSZZEW3ZQC RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC SVY2PTCLXR3KNPQAWXVXTTGCC5DR334HOAKHYO3VDDRWM2BWMALAC AS2IQQJNNCEQNXXKTGYHLB7RO3ZKCF4F7GK6FJH66BOOKDDRGNIQC JJULXW764V5C2HJKZNWQAEWB6QM5YZADD7ZCE35LYTBFEM6PMYCAC CDFS7Z74W5HKPQIHQICOG442KQFXUSBGGLDDQLE3MG74T44YU6AQC FLAGBNUNSIQNFDN53CDWABJRTTFWDL4PG34AI474ZKPXDEPYHOAQC Z3YHSEJ2ELRDG5DIDLP4MQSHNDRCTD5BSMVRBWOLF2S7TLRBGSBAC 5FHWTG7M6FW4B3I33YI7QSM3OZIB6ZGC6TI6JISSLY5Y43HI56VAC }double ray_def::get_degrees() const{if (slope > 100.0){if (quadrant == 3 || quadrant == 2)return (90.0);elsereturn (270.0);}else if (double_is_zero(slope)){if (quadrant == 0 || quadrant == 3)return (0.0);elsereturn (180.0);}double deg = atan(slope) * 180.0 / M_PI;switch (quadrant){case 0:return (360.0 - deg);case 1:return (180.0 + deg);case 2:return (180.0 - deg);case 3:return (deg);}ASSERT(!"ray has illegal quadrant");return (0.0);}void ray_def::set_degrees(double deg){while (deg < 0.0)deg += 360.0;while (deg >= 360.0)deg -= 360.0;double _slope = tan(deg / 180.0 * M_PI);if (double_is_zero(_slope)){slope = 0.0;if (deg < 90.0 || deg > 270.0)quadrant = 0; // right/eastelsequadrant = 1; // left/west}else if (_slope > 0){slope = _slope;if (deg >= 180.0 && deg <= 270.0)quadrant = 1;elsequadrant = 3;}else{slope = -_slope;if (deg >= 90 && deg <= 180)quadrant = 2;elsequadrant = 0;}if (slope > 1000.0)slope = 1000.0;
}static void _munge_bounced_bolt(bolt &old_bolt, bolt &new_bolt,ray_def &old_ray, ray_def &new_ray){if (new_bolt.real_flavour != BEAM_CHAOS)return;double old_deg = old_ray.get_degrees();double new_deg = new_ray.get_degrees();double angle = abs(old_deg - new_deg);if (angle >= 180.0)angle -= 180.0;double max = 90.0 + (angle / 2.0);double min = -90.0 + (angle / 2.0);double shift = (double) random_range(min * 10000, max * 10000) / 10000.0;if (new_deg < old_deg)shift = -shift;new_ray.set_degrees(new_deg + shift);#if DEBUG_DIAGNOSTICS || DEBUG_CHAOS_BOUNCEmprf(MSGCH_DIAGNOSTICS,"chaos beam: old_deg = %5.2f, new_deg = %5.2f, shift = %5.2f",(float) old_deg, (float) new_deg, (float) shift);#endif// Don't use up range in bouncing off walls, so that chaos beams have// as many chances as possible to bounce. They're like demented// ping-pong balls on caffeine.int range_spent = new_bolt.range_used - old_bolt.range_used;new_bolt.range += range_spent;// 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();
// enchantment is yours.if (pbolt.is_enchantment())
// enchantment is yours (and it wasn't a chaos beam, since with chaos// enchantments are entirely random, and if it randomly attempts// something which ends up having no obvious effect then the player// isn't going to realize it).if (pbolt.is_enchantment() && pbolt.real_flavour != BEAM_CHAOS)