示例#1
0
void CInterceptHandler::AddInterceptTarget(CWeaponProjectile* target, const float3& destination)
{
	int targTeam = -1;
	if (target->owner()) {
		targTeam=target->owner()->allyteam;
	}

	for (std::list<CWeapon*>::iterator wi = interceptors.begin(); wi != interceptors.end(); ++wi) {
		CWeapon* w = *wi;
		if (((targTeam == -1) || !teamHandler->Ally(w->owner->allyteam,targTeam)) &&
			(target->weaponDef->targetable & w->weaponDef->interceptor) &&
			(w->weaponPos.SqDistance2D(destination) < Square(w->weaponDef->coverageRange)))
		{
			w->incoming.push_back(target);
			w->AddDeathDependence(target, CObject::DEPENDENCE_INTERCEPT);
		}
	}
}
示例#2
0
void CInterceptHandler::Update(bool forced) {
	if (((gs->frameNum % UNIT_SLOWUPDATE_RATE) != 0) && !forced)
		return;

	std::list<CWeapon*>::iterator wit;
	std::map<int, CWeaponProjectile*>::const_iterator pit;

	for (wit = interceptors.begin(); wit != interceptors.end(); ++wit) {
		CWeapon* w = *wit;
		const WeaponDef* wDef = w->weaponDef;
		const CUnit* wOwner = w->owner;
		// const float3& wOwnerPos = wOwner->pos;
		const float3& wPos = w->weaponPos;

		assert(wDef->interceptor || wDef->isShield);

		for (pit = interceptables.begin(); pit != interceptables.end(); ++pit) {
			CWeaponProjectile* p = pit->second;
			const WeaponDef* pDef = p->weaponDef;

			if ((pDef->targetable & wDef->interceptor) == 0)
				continue;
			if (w->incomingProjectiles.find(p->id) != w->incomingProjectiles.end())
				continue;

			const CUnit* pOwner = p->owner();
			const int pAllyTeam = (pOwner != NULL)? pOwner->allyteam: -1;

			if (pAllyTeam != -1 && teamHandler->Ally(wOwner->allyteam, pAllyTeam))
				continue;

			// there are four cases when an interceptor <w> should fire at a projectile <p>:
			//     1. p's target position inside w's interception circle (w's owner can move!)
			//     2. p's current position inside w's interception circle
			//     3. p's projected impact position inside w's interception circle
			//     4. p's trajectory intersects w's interception circle
			//
			// these checks all need to be evaluated periodically, not just
			// when a projectile is created and handed to AddInterceptTarget
			const float interceptDist = w->weaponPos.distance(p->pos);
			const float impactDist = ground->LineGroundCol(p->pos, p->pos + p->dir * interceptDist);

			const float3& pFlightPos = p->pos;
			const float3& pImpactPos = p->pos + p->dir * impactDist;
			const float3& pTargetPos = p->targetPos;

			if ((pTargetPos - wPos).SqLength2D() < Square(wDef->coverageRange)) {
				w->AddDeathDependence(p, CObject::DEPENDENCE_INTERCEPT);
				w->incomingProjectiles[p->id] = p;
				continue; // 1
			}

			if (wDef->interceptor == 1) {
				// <w> is just a static interceptor and fires only at projectiles
				// TARGETED within its current interception area; any projectiles
				// CROSSING its interception area are fired at only if interceptor
				// is >= 2
				continue;
			}

			if ((pFlightPos - wPos).SqLength2D() < Square(wDef->coverageRange)) {
				w->AddDeathDependence(p, CObject::DEPENDENCE_INTERCEPT);
				w->incomingProjectiles[p->id] = p;
				continue; // 2
			}

			if ((pImpactPos - wPos).SqLength2D() < Square(wDef->coverageRange)) {
				const float3 pTargetDir = (pTargetPos - pFlightPos).SafeNormalize();
				const float3 pImpactDir = (pImpactPos - pFlightPos).SafeNormalize();

				// the projected impact position can briefly shift into the covered
				// area during transition from vertical to horizontal flight, so we
				// perform an extra test (NOTE: assumes non-parabolic trajectory)
				if (pTargetDir.dot(pImpactDir) >= 0.999f) {
					w->AddDeathDependence(p, CObject::DEPENDENCE_INTERCEPT);
					w->incomingProjectiles[p->id] = p;
					continue; // 3
				}
			}

			const float3 pCurSeparationVec = wPos - pFlightPos;
			const float pMinSeparationDist = std::max(pCurSeparationVec.dot(p->dir), 0.0f);
			const float3 pMinSeparationPos = pFlightPos + (p->dir * pMinSeparationDist);
			const float3 pMinSeparationVec = wPos - pMinSeparationPos;

			if (pMinSeparationVec.SqLength() < Square(wDef->coverageRange)) {
				w->AddDeathDependence(p, CObject::DEPENDENCE_INTERCEPT);
				w->incomingProjectiles[p->id] = p;
				continue; // 4
			}
		}
	}
}