Example #1
0
void CGameHelper::DoExplosionDamage(CFeature* feature,
                                    const float3& expPos, float expRad, CUnit* owner, const DamageArray& damages)
{
    CollisionVolume* cv = feature->collisionVolume;

    if (cv) {
        float3 dif = (feature->midPos + cv->GetOffsets()) - expPos;
        float expDist = std::max(dif.Length(), 0.1f);
        float expMod = (expRad - expDist) / expRad;

        // always do some damage with explosive stuff
        // (DDM wreckage etc. is too big to normally
        // be damaged otherwise, even by BB shells)
        // NOTE: this will also be only approximate
        // for non-spherical volumes
        if ((expRad > 8.0f) && (expDist < (cv->GetBoundingRadius() * 1.1f)) && (expMod < 0.1f)) {
            expMod = 0.1f;
        }
        if (expMod > 0.0f) {
            feature->DoDamage(damages * expMod, owner,
                              dif * (damages.impulseFactor * expMod / expDist *
                                     (damages[0] + damages.impulseBoost)));
        }
    }
}
Example #2
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;
}