bool CWeapon::TryTarget(const float3 &pos,bool userTarget,CUnit* unit)
{
	if (unit && !(onlyTargetCategory & unit->category)) {
		return false;
	}

	if(unit && ((unit->isDead   && (modInfo.fireAtKilled==0)) ||
	            (unit->crashing && (modInfo.fireAtCrashing==0)))) {
		return false;
	}
	if (weaponDef->stockpile && !numStockpiled) {
		return false;
	}

	float3 dif=pos-weaponMuzzlePos;
	float heightDiff; // negative when target below owner

	if (targetBorder != 0 && unit) {
		float3 diff(dif);
		diff.Normalize();
		// weapon inside target sphere
		if (dif.SqLength() < unit->sqRadius*targetBorder*targetBorder) {
			dif -= diff*(dif.Length() - 10); // a hack
			//logOutput << "inside\n";
		} else {
			dif -= diff*(unit->radius*targetBorder);
			//logOutput << "outside\n";
		}
		//geometricObjects->AddLine(weaponMuzzlePos, weaponMuzzlePos+dif, 3, 0, 16);
		heightDiff = (weaponPos.y + dif.y) - owner->pos.y;
	} else {
		heightDiff = pos.y - owner->pos.y;
	}

	float r;
	if (!unit || cylinderTargetting < 0.01) {
		r=GetRange2D(heightDiff*heightMod);
	} else {
		if (cylinderTargetting * range > fabs(heightDiff)*heightMod) {
			r = GetRange2D(0);
		} else {
			r = 0;
		}
	}

	if(dif.SqLength2D()>=r*r)
		return false;

	if(maxMainDirAngleDif>-0.999f){
		dif.Normalize();
		float3 modMainDir=owner->frontdir*mainDir.z+owner->rightdir*mainDir.x+owner->updir*mainDir.y;

//		geometricObjects->AddLine(weaponPos,weaponPos+modMainDir*50,3,0,16);
		if(modMainDir.dot(dif)<maxMainDirAngleDif)
			return false;
	}
	return true;
}
Beispiel #2
0
bool CWeapon::TryTarget(const float3& tgtPos, bool /*userTarget*/, CUnit* targetUnit)
{
	if (targetUnit && !(onlyTargetCategory & targetUnit->category)) {
		return false;
	}

	if (targetUnit && ((targetUnit->isDead   && (modInfo.fireAtKilled   == 0)) ||
	                   (targetUnit->crashing && (modInfo.fireAtCrashing == 0)))) {
		return false;
	}
	if (weaponDef->stockpile && !numStockpiled) {
		return false;
	}

	float3 targetPos = tgtPos;
	float3 targetVec = targetPos - weaponMuzzlePos;
	float3 targetDir = targetVec;

	float heightDiff = 0.0f; // negative when target below owner
	float weaponRange = 0.0f; // range modified by heightDiff and cylinderTargetting
	bool targetDirNormalized = false;

	if (targetBorder != 0.0f && targetUnit != NULL) {
		// adjust the length of <targetVec> based on the targetBorder factor
		targetDirNormalized = AdjustTargetVectorLength(targetUnit, targetPos, targetVec, targetDir);
		targetPos.y = weaponPos.y + targetVec.y;
	}

	heightDiff = targetPos.y - owner->pos.y;

	if (targetUnit == NULL || cylinderTargetting < 0.01f) {
		// check range in a sphere (with extra radius <heightDiff * heightMod>)
		weaponRange = GetRange2D(heightDiff * heightMod);
	} else {
		// check range in a cylinder (with height <cylinderTargetting * range>)
		if ((cylinderTargetting * range) > (math::fabsf(heightDiff) * heightMod)) {
			weaponRange = GetRange2D(0.0f);
		}
	}

	if (targetVec.SqLength2D() >= (weaponRange * weaponRange))
		return false;

	if (maxMainDirAngleDif > -0.999f) {
		const float3 targetNormDir = targetDirNormalized? targetDir: targetDir.SafeNormalize();
		const float3 modMainDir =
			owner->frontdir * mainDir.z +
			owner->rightdir * mainDir.x +
			owner->updir    * mainDir.y;

		if (modMainDir.dot(targetNormDir) < maxMainDirAngleDif)
			return false;
	}

	return true;
}
Beispiel #3
0
void CCannon::Init(void)
{
	gravity = weaponDef->myGravity==0 ? mapInfo->map.gravity : -(weaponDef->myGravity);
	highTrajectory = weaponDef->highTrajectory == 1;
	if(highTrajectory){
		maxPredict=projectileSpeed*2/-gravity;
		minPredict=projectileSpeed*1.41f/-gravity;
	} else {
		maxPredict=projectileSpeed*1.41f/-gravity;
	}
	CWeapon::Init();

	// initialize range factor
	rangeFactor = 1;
	rangeFactor = (float)range/GetRange2D(0);
	// do not extend range if the modder specified speed too low
	// for the projectile to reach specified range
	if (rangeFactor > 1.f || rangeFactor <= 0.f)
		rangeFactor = 1.f;
	// some magical (but working) equations
	// useful properties: if rangeFactor == 1, heightBoostFactor == 1
	// TODO find something better?
	if (heightBoostFactor < 0.f)
		heightBoostFactor = (2.f - rangeFactor) / math::sqrt(rangeFactor);
}
Beispiel #4
0
void CCannon::UpdateRange(const float val)
{
	// clamp so as to not extend range if projectile
	// speed is too low to reach the *updated* range
	// note: new range can be zero (!) making range
	// and height factors irrelevant
	range = val;
	rangeFactor = Clamp(range / GetRange2D(0.0f, 1.0f), 0.0f, 1.0f);

	// some magical (but working) equations
	// useful properties: if rangeFactor == 1, heightBoostFactor == 1
	// TODO find something better?
	if (heightBoostFactor < 0.0f && rangeFactor > 0.0f) {
		heightBoostFactor = (2.0f - rangeFactor) / math::sqrt(rangeFactor);
	}
}
Beispiel #5
0
void CCannon::UpdateRange(float val)
{
	range = val;
	// initialize range factor
	rangeFactor = 1.f;
	rangeFactor = range / GetRange2D(0);
	// do not extend range if the modder specified speed too low
	// for the projectile to reach specified range
	if (rangeFactor > 1.f || rangeFactor <= 0.f)
		rangeFactor = 1.f;
	// some magical (but working) equations
	// useful properties: if rangeFactor == 1, heightBoostFactor == 1
	// TODO find something better?
	if (heightBoostFactor < 0.f)
		heightBoostFactor = (2.f - rangeFactor) / math::sqrt(rangeFactor);
}
Beispiel #6
0
float CCannon::GetRange2D(const float yDiff) const
{
	return (GetRange2D(yDiff, rangeFactor));
}