Exemplo n.º 1
0
void CMissileLauncher::FireImpl(bool scriptCall)
{
	float3 dir = targetPos - weaponMuzzlePos;
	const float dist = dir.LengthNormalize();

	if (onlyForward) {
		dir = owner->frontdir;
	} else if (weaponDef->fixedLauncher) {
		dir = weaponDir;
	} else if (weaponDef->trajectoryHeight > 0.0f) {
		dir.y += weaponDef->trajectoryHeight;
		dir.Normalize();
	}

	dir += (gs->randVector() * SprayAngleExperience() + SalvoErrorExperience());
	dir.Normalize();

	float3 startSpeed = dir * weaponDef->startvelocity;

	// NOTE: why only for SAMT units?
	if (onlyForward && owner->unitDef->IsStrafingAirUnit())
		startSpeed += owner->speed;

	ProjectileParams params = GetProjectileParams();
	params.pos = weaponMuzzlePos;
	params.end = targetPos;
	params.speed = startSpeed;
	params.ttl = weaponDef->flighttime == 0? std::ceil(std::max(dist, range) / projectileSpeed + 25 * weaponDef->selfExplode): weaponDef->flighttime;

	WeaponProjectileFactory::LoadProjectile(params);
}
Exemplo n.º 2
0
void CCannon::FireImpl(const bool scriptCall)
{
	float3 diff = currentTargetPos - weaponMuzzlePos;
	float3 dir = (diff.SqLength() > 4.0f) ? GetWantedDir(diff) : diff; // prevent vertical aim when emit-sfx firing the weapon

	dir += (gsRNG.NextVector() * SprayAngleExperience() + SalvoErrorExperience());
	dir.SafeNormalize();

	int ttl = 0;
	const float sqSpeed2D = dir.SqLength2D() * projectileSpeed * projectileSpeed;
	const int predict = math::ceil((sqSpeed2D == 0.0f) ?
		(-2.0f * projectileSpeed * dir.y / gravity):
		math::sqrt(diff.SqLength2D() / sqSpeed2D));

	if (weaponDef->flighttime > 0) {
		ttl = weaponDef->flighttime;
	} else if (weaponDef->selfExplode) {
		ttl = (predict + gsRNG.NextFloat() * 2.5f - 0.5f);
	} else if ((weaponDef->groundBounce || weaponDef->waterBounce) && weaponDef->numBounce > 0) {
		ttl = (predict * (1 + weaponDef->numBounce * weaponDef->bounceRebound));
	} else {
		ttl = predict * 2;
	}

	ProjectileParams params = GetProjectileParams();
	params.pos = weaponMuzzlePos;
	params.end = currentTargetPos;
	params.speed = dir * projectileSpeed;
	params.ttl = ttl;
	params.gravity = gravity;

	WeaponProjectileFactory::LoadProjectile(params);
}
Exemplo n.º 3
0
float3 CBeamLaser::GetFireDir(bool sweepFire, bool scriptCall)
{
	float3 dir = targetPos - weaponMuzzlePos;

	if (!sweepFire) {
		if (scriptCall) {
			dir = dir.SafeNormalize();
		} else {
			if (onlyForward && owner->unitDef->IsStrafingAirUnit()) {
				// [?] StrafeAirMovetype cannot align itself properly, change back when that is fixed
				dir = owner->frontdir;
			} else {
				if (salvoLeft == salvoSize - 1) {
					oldDir = (dir = dir.SafeNormalize());
				} else if (weaponDef->beamburst) {
					dir = dir.SafeNormalize();
				} else {
					dir = oldDir;
				}
			}

			dir += SalvoErrorExperience();
			dir.SafeNormalize();

			// NOTE:
			//  on units with (extremely) long weapon barrels the muzzle
			//  can be on the far side of the target unit such that <dir>
			//  would point away from it
			if ((targetPos - weaponMuzzlePos).dot(targetPos - owner->aimPos) < 0.0f) {
				dir = -dir;
			}
		}
	} else {
		// need to emit the sweeping beams from the right place
		// NOTE:
		//   this way of implementing sweep-fire is extremely bugged
		//   the intersection points traced by rays from the turning
		//   weapon piece do NOT describe a fluid arc segment between
		//   old and new target positions (nor even a straight line)
		//   --> animation scripts cannot be relied upon to smoothly
		//   vary pitch of the weapon muzzle piece so use workaround
		//
		dir = sweepFireState.GetSweepTempDir();
		dir.Normalize2D();

		const float3 tgtPos = float3(dir.x * sweepFireState.GetTargetDist2D(), 0.0f, dir.z * sweepFireState.GetTargetDist2D());
		const float tgtHgt = CGround::GetHeightReal(weaponMuzzlePos.x + tgtPos.x, weaponMuzzlePos.z + tgtPos.z);

		// NOTE: INTENTIONALLY NOT NORMALIZED HERE
		dir = (tgtPos + UpVector * (tgtHgt - weaponMuzzlePos.y));
	}

	return dir;
}
Exemplo n.º 4
0
void CDGunWeapon::FireImpl(const bool scriptCall)
{
	float3 dir = wantedDir;

	dir += (gsRNG.NextVector() * SprayAngleExperience() + SalvoErrorExperience());
	dir.Normalize();

	ProjectileParams params = GetProjectileParams();
	params.pos = weaponMuzzlePos;
	params.end = currentTargetPos;
	params.speed = dir * projectileSpeed;
	params.ttl = 1;

	WeaponProjectileFactory::LoadProjectile(params);
}
Exemplo n.º 5
0
void CStarburstLauncher::FireImpl(bool scriptCall)
{
	const float3 speed = ((weaponDef->fixedLauncher)? weaponDir: UpVector) * weaponDef->startvelocity;
	const float3 aimError = (gs->randVector() * SprayAngleExperience() + SalvoErrorExperience());

	ProjectileParams params = GetProjectileParams();
	params.pos = weaponMuzzlePos + UpVector * 2.0f;
	params.end = targetPos;
	params.speed = speed;
	params.error = aimError;
	params.ttl = 200; //???
	params.tracking = tracking;
	params.maxRange = (weaponDef->flighttime > 0 || weaponDef->fixedLauncher)? MAX_PROJECTILE_RANGE: range;

	WeaponProjectileFactory::LoadProjectile(params);
}
Exemplo n.º 6
0
void CFlameThrower::FireImpl(bool scriptCall)
{
	float3 dir = targetPos - weaponMuzzlePos;

	const float dist = dir.LengthNormalize();
	const float3 spread =
		(gs->randVector() * SprayAngleExperience() + SalvoErrorExperience()) -
		(dir * 0.001f);

	ProjectileParams params = GetProjectileParams();
	params.pos = weaponMuzzlePos;
	params.speed = dir * projectileSpeed;
	params.spread = spread;
	params.ttl = std::ceil(std::max(dist, range) / projectileSpeed * weaponDef->duration);

	WeaponProjectileFactory::LoadProjectile(params);
}
Exemplo n.º 7
0
void CEmgCannon::FireImpl(const bool scriptCall)
{
	float3 dir = currentTargetPos - weaponMuzzlePos;
	const float dist = dir.LengthNormalize();

	if (onlyForward && owner->unitDef->IsStrafingAirUnit()) {
		// [?] StrafeAirMoveType cannot align itself properly, change back when that is fixed
		dir = owner->frontdir;
	}

	dir += (gs->randVector() * SprayAngleExperience() + SalvoErrorExperience());
	dir.Normalize();

	ProjectileParams params = GetProjectileParams();
	params.pos = weaponMuzzlePos;
	params.speed = dir * projectileSpeed;
	params.ttl = std::ceil(std::max(dist, range) / projectileSpeed);

	WeaponProjectileFactory::LoadProjectile(params);
}
Exemplo n.º 8
0
void CLightningCannon::FireImpl(bool scriptCall)
{
	float3 curPos = weaponMuzzlePos;
	float3 curDir = (targetPos - curPos).Normalize();
	float3 newDir = curDir;

	curDir +=
		(gs->randVector() * SprayAngleExperience() + SalvoErrorExperience());
	curDir.Normalize();

	CUnit* hitUnit = NULL;
	CFeature* hitFeature = NULL;
	CPlasmaRepulser* hitShield = NULL;
	CollisionQuery hitColQuery;

	float boltLength = TraceRay::TraceRay(curPos, curDir, range, collisionFlags, owner, hitUnit, hitFeature, &hitColQuery);

	if (!weaponDef->waterweapon) {
		// terminate bolt at water surface if necessary
		if ((curDir.y < 0.0f) && ((curPos.y + curDir.y * boltLength) <= 0.0f)) {
			boltLength = curPos.y / -curDir.y;
		}
	}

	const float shieldLength = interceptHandler.AddShieldInterceptableBeam(this, curPos, curDir, range, newDir, hitShield);

	if (shieldLength < boltLength) {
		boltLength = shieldLength;
		hitShield->BeamIntercepted(this);
	}

	if (hitUnit != NULL) {
		hitUnit->SetLastAttackedPiece(hitColQuery.GetHitPiece(), gs->frameNum);
	}

	const DamageArray& damageArray = (weaponDef->dynDamageExp <= 0.0f)?
		weaponDef->damages:
		weaponDefHandler->DynamicDamages(
			weaponDef->damages,
			weaponMuzzlePos,
			targetPos,
			(weaponDef->dynDamageRange > 0.0f)?
				weaponDef->dynDamageRange:
				weaponDef->range,
			weaponDef->dynDamageExp,
			weaponDef->dynDamageMin,
			weaponDef->dynDamageInverted
		);

	const CGameHelper::ExplosionParams params = {
		curPos + curDir * boltLength,                     // hitPos (same as hitColQuery.GetHitPos() if no water or shield in way)
		curDir,
		damageArray,
		weaponDef,
		owner,
		hitUnit,
		hitFeature,
		craterAreaOfEffect,
		damageAreaOfEffect,
		weaponDef->edgeEffectiveness,
		weaponDef->explosionSpeed,
		0.5f,                                             // gfxMod
		weaponDef->impactOnly,
		weaponDef->noExplode || weaponDef->noSelfDamage,  // ignoreOwner
		false,                                            // damageGround
		-1u                                               // projectileID
	};

	helper->Explosion(params);

	ProjectileParams pparams = GetProjectileParams();
	pparams.pos = curPos;
	pparams.end = curPos + curDir * (boltLength + 10.0f);
	pparams.ttl = 10;

	WeaponProjectileFactory::LoadProjectile(pparams);
}
Exemplo n.º 9
0
void CLightningCannon::FireImpl(const bool scriptCall)
{
	float3 curPos = weaponMuzzlePos;
	float3 curDir = (currentTargetPos - weaponMuzzlePos).SafeNormalize();

	curDir +=
		(gs->randVector() * SprayAngleExperience() + SalvoErrorExperience());
	curDir.Normalize();

	CUnit* hitUnit = NULL;
	CFeature* hitFeature = NULL;
	CollisionQuery hitColQuery;

	float boltLength = TraceRay::TraceRay(curPos, curDir, range, collisionFlags, owner, hitUnit, hitFeature, &hitColQuery);

	if (!weaponDef->waterweapon) {
		// terminate bolt at water surface if necessary
		if ((curDir.y < 0.0f) && ((curPos.y + curDir.y * boltLength) <= 0.0f)) {
			boltLength = curPos.y / -curDir.y;
			hitUnit = NULL;
			hitFeature = NULL;
		}
	}

	static std::vector<TraceRay::SShieldDist> hitShields;
	hitShields.clear();
	TraceRay::TraceRayShields(this, curPos, curDir, range, hitShields);
	for (const TraceRay::SShieldDist& sd: hitShields) {
		if(sd.dist < boltLength && sd.rep->IncomingBeam(this, curPos)) {
			boltLength = sd.dist;
			hitUnit = NULL;
			hitFeature = NULL;
			break;
		}
	}

	if (hitUnit != NULL) {
		hitUnit->SetLastHitPiece(hitColQuery.GetHitPiece(), gs->frameNum);
	}

	const DamageArray& damageArray = damages->GetDynamicDamages(weaponMuzzlePos, currentTargetPos);
	const CGameHelper::ExplosionParams params = {
		curPos + curDir * boltLength,                     // hitPos (same as hitColQuery.GetHitPos() if no water or shield in way)
		curDir,
		damageArray,
		weaponDef,
		owner,
		hitUnit,
		hitFeature,
		damages->craterAreaOfEffect,
		damages->damageAreaOfEffect,
		damages->edgeEffectiveness,
		damages->explosionSpeed,
		0.5f,                                             // gfxMod
		weaponDef->impactOnly,
		weaponDef->noExplode || weaponDef->noSelfDamage,  // ignoreOwner
		false,                                            // damageGround
		-1u                                               // projectileID
	};

	helper->Explosion(params);

	ProjectileParams pparams = GetProjectileParams();
	pparams.pos = curPos;
	pparams.end = curPos + curDir * (boltLength + 10.0f);
	pparams.ttl = weaponDef->beamLaserTTL;

	WeaponProjectileFactory::LoadProjectile(pparams);
}