commit b03fc9271aa5c4aaf4e90a940c78d004e2962148
Author: Daniel Gibson <metalcaedes@gmail.com>
Date:   Sun Dec 13 03:06:52 2015 +0100

    Fix crash by assert in last RoE level (and maybe elsewhere)
    
    The assertion in idBounds::operator-(const idBounds&) was triggered
    from idWeapon::Event_LaunchProjectiles() (ownerBounds - projBounds)
    It only happened when using the BFG.
    So I added a check to make sure calling operator- is legal.
    
    I guess this also caused #122

diff --git neo/d3xp/Weapon.cpp neo/d3xp/Weapon.cpp
index 2101381..30f8882 100644
--- d3xp/Weapon.cpp
+++ d3xp/Weapon.cpp
@@ -3446,7 +3446,14 @@ void idWeapon::Event_LaunchProjectiles( int num_projectiles, float spread, float
 			// make sure the projectile starts inside the bounding box of the owner
 			if ( i == 0 ) {
 				muzzle_pos = muzzleOrigin + playerViewAxis[ 0 ] * 2.0f;
-				if ( ( ownerBounds - projBounds).RayIntersection( muzzle_pos, playerViewAxis[0], distance ) ) {
+
+				// DG: sometimes the assertion in idBounds::operator-(const idBounds&) triggers
+				//     (would get bounding box with negative volume)
+				//     => check that before doing ownerBounds - projBounds (equivalent to the check in the assertion)
+				idVec3 obDiff = ownerBounds[1] - ownerBounds[0];
+				idVec3 pbDiff = projBounds[1] - projBounds[0];
+				bool boundsSubLegal =  obDiff.x > pbDiff.x && obDiff.y > pbDiff.y && obDiff.z > pbDiff.z;
+				if ( boundsSubLegal && ( ownerBounds - projBounds ).RayIntersection( muzzle_pos, playerViewAxis[0], distance ) ) {
 					start = muzzle_pos + distance * playerViewAxis[0];
 				} else {
 					start = ownerBounds.GetCenter();
diff --git neo/game/Weapon.cpp neo/game/Weapon.cpp
index d889c68..a381ae2 100644
--- game/Weapon.cpp
+++ game/Weapon.cpp
@@ -2941,7 +2941,13 @@ void idWeapon::Event_LaunchProjectiles( int num_projectiles, float spread, float
 			// make sure the projectile starts inside the bounding box of the owner
 			if ( i == 0 ) {
 				muzzle_pos = muzzleOrigin + playerViewAxis[ 0 ] * 2.0f;
-				if ( ( ownerBounds - projBounds).RayIntersection( muzzle_pos, playerViewAxis[0], distance ) ) {
+				// DG: sometimes the assertion in idBounds::operator-(const idBounds&) triggers
+				//     (would get bounding box with negative volume)
+				//     => check that before doing ownerBounds - projBounds (equivalent to the check in the assertion)
+				idVec3 obDiff = ownerBounds[1] - ownerBounds[0];
+				idVec3 pbDiff = projBounds[1] - projBounds[0];
+				bool boundsSubLegal =  obDiff.x > pbDiff.x && obDiff.y > pbDiff.y && obDiff.z > pbDiff.z;
+				if ( boundsSubLegal && ( ownerBounds - projBounds ).RayIntersection( muzzle_pos, playerViewAxis[0], distance ) ) {
 					start = muzzle_pos + distance * playerViewAxis[0];
 				} else {
 					start = ownerBounds.GetCenter();
