Example #1
0
bool CWeapon::AdjustTargetVectorLength(
	CUnit* targetUnit,
	float3& targetPos,
	float3& targetVec,
	float3& targetDir)
const {
	bool retCode = false;
	const float tbScale = math::fabsf(targetBorder);

	CollisionVolume* cvOld = targetUnit->collisionVolume;
	CollisionVolume  cvNew = CollisionVolume(targetUnit->collisionVolume);
	CollisionQuery   cq;

	// test for "collision" with a temporarily volume
	// (scaled uniformly by the absolute target-border
	// factor)
	cvNew.RescaleAxes(tbScale, tbScale, tbScale);
	cvNew.SetTestType(CollisionVolume::COLVOL_HITTEST_DISC);

	targetUnit->collisionVolume = &cvNew;

	if (CCollisionHandler::DetectHit(targetUnit, weaponMuzzlePos, ZeroVector, NULL)) {
		// our weapon muzzle is inside the target unit's volume; this
		// means we do not need to make any adjustments to targetVec
		targetVec = ZeroVector;
	} else {
		targetDir.SafeNormalize();

		// otherwise, perform a raytrace to find the proper length correction
		// factor for non-spherical coldet volumes based on the ray's ingress
		// (for positive TB values) or egress (for negative TB values) position;
		// this either increases or decreases the length of <targetVec> but does
		// not change its direction
		cvNew.SetTestType(CollisionVolume::COLVOL_HITTEST_CONT);

		// make the ray-segment long enough so it can reach the far side of the
		// scaled collision volume (helps to ensure a ray-intersection is found)
		//
		// note: ray-intersection is NOT guaranteed if the volume itself has a
		// non-zero offset, since here we are "shooting" at the target UNIT's
		// midpoint
		const float3 targetOffset = targetDir * (cvNew.GetBoundingRadius() * 2.0f);
		const float3 targetRayPos = targetPos + targetOffset;

		if (CCollisionHandler::DetectHit(targetUnit, weaponMuzzlePos, targetRayPos, &cq)) {
			if (targetBorder > 0.0f) { targetVec -= (targetDir * ((targetPos - cq.p0).Length())); }
			if (targetBorder < 0.0f) { targetVec += (targetDir * ((cq.p1 - targetPos).Length())); }
		}

		retCode = true;
	}

	targetUnit->collisionVolume = cvOld;

	// true indicates we took the else-branch and targetDir is now normalized
	return retCode;
}