예제 #1
0
/**
 * @brief Check if one type of battery (missile or laser) can shoot now.
 * @param[in] installation Pointer to the firing intallation.
 * @param[in] weapons The installation weapon to check and fire.
 */
static void AIRFIGHT_InstallationShoot (const installation_t *installation, baseWeapon_t *weapons, int maxWeapons)
{
	int i, test;
	float distance;

	for (i = 0; i < maxWeapons; i++) {
		aircraft_t *target = weapons[i].target;
		aircraftSlot_t *slot = &(weapons[i].slot);
		/* if no target, can't shoot */
		if (!target)
			continue;

		/* If the weapon is not ready in base, can't shoot. */
		if (slot->installationTime > 0)
			continue;

		/* if weapon is reloading, can't shoot */
		if (slot->delayNextShot > 0)
			continue;

		/* check that the ufo is still visible */
		if (!UFO_IsUFOSeenOnGeoscape(target)) {
			weapons[i].target = NULL;
			continue;
		}

		/* Check if we can still fire on this target. */
		distance = GetDistanceOnGlobe(installation->pos, target->pos);
		test = AIRFIGHT_CheckWeapon(slot, distance);
		/* weapon unable to shoot, reset target */
		if (test == AIRFIGHT_WEAPON_CAN_NEVER_SHOOT) {
			weapons[i].target = NULL;
			continue;
		}
		/* we can't shoot with this weapon atm, wait to see if UFO comes closer */
		else if (test == AIRFIGHT_WEAPON_CAN_NOT_SHOOT_AT_THE_MOMENT)
			continue;
		/* target is too far, wait to see if UFO comes closer */
		else if (distance > slot->ammo->craftitem.stats[AIR_STATS_WRANGE])
			continue;

		/* shoot */
		if (AIRFIGHT_AddProjectile(NULL, installation, NULL, target, slot)) {
			slot->delayNextShot = slot->ammo->craftitem.weaponDelay;
			/* will we miss the target ? */
			if (frand() > AIRFIGHT_ProbabilityToHit(NULL, target, slot))
				AIRFIGHT_MissTarget(&ccs.projectiles[ccs.numProjectiles - 1], qfalse);
		}
	}
}
예제 #2
0
/**
 * @sa AIR_IsAircraftOnGeoscape
 */
aircraft_t *UFO_GetNextOnGeoscape (aircraft_t *lastUFO)
{
	aircraft_t* ufo = lastUFO;
	while ((ufo = UFO_GetNext(ufo)) != NULL) {
		if (UFO_IsUFOSeenOnGeoscape(ufo)
#ifdef DEBUG
		|| Cvar_GetInteger("debug_showufos")
#endif
		)
			return ufo;
	}

	return NULL;
}
예제 #3
0
/**
 * @brief Check if the ufo can shoot at a PHALANX aircraft
 */
static void UFO_SearchAircraftTarget (const campaign_t* campaign, aircraft_t *ufo)
{
	float distance = 999999.;

	/* UFO never try to attack a PHALANX aircraft except if they came on earth in that aim */
	if (ufo->mission->stage != STAGE_INTERCEPT) {
		/* Check if UFO is defending itself */
		if (ufo->aircraftTarget)
			UFO_CheckShootBack(campaign, ufo, ufo->aircraftTarget);
		return;
	}

	/* check if the ufo is already attacking an aircraft */
	if (ufo->aircraftTarget) {
		/* check if the target disappeared from geoscape (fled in a base) */
		if (AIR_IsAircraftOnGeoscape(ufo->aircraftTarget))
			AIRFIGHT_ExecuteActions(campaign, ufo, ufo->aircraftTarget);
		else
			ufo->aircraftTarget = NULL;
		return;
	}

	ufo->status = AIR_TRANSIT;
	AIR_Foreach(phalanxAircraft) {
		/* check that aircraft is flying */
		if (AIR_IsAircraftOnGeoscape(phalanxAircraft)) {
			/* get the distance from ufo to aircraft */
			const float dist = GetDistanceOnGlobe(ufo->pos, phalanxAircraft->pos);
			/* check out of reach */
			if (dist > MAX_DETECTING_RANGE)
				continue;
			/* choose the nearest target */
			if (dist < distance) {
				distance = dist;
				if (UFO_SendPursuingAircraft(ufo, phalanxAircraft) && UFO_IsUFOSeenOnGeoscape(ufo)) {
					/* stop time and notify */
					MSO_CheckAddNewMessage(NT_UFO_ATTACKING, _("Notice"), va(_("A UFO is flying toward %s"), phalanxAircraft->name), qfalse,
						MSG_STANDARD, NULL);
					/** @todo present a popup with possible orders like: return to base, attack the ufo, try to flee the rockets */
				}
			}
		}
	}
}
예제 #4
0
/**
 * @brief Check if the ufo can shoot at a PHALANX aircraft and whether it should follow another ufo
 */
static void UFO_SearchAircraftTarget (const campaign_t* campaign, aircraft_t* ufo, float maxDetectionRange = MAX_DETECTING_RANGE)
{
	float distance = 999999.;

	/* UFO never try to attack a PHALANX aircraft except if they came on earth in that aim */
	if (ufo->mission->stage != STAGE_INTERCEPT) {
		/* Check if UFO is defending itself */
		if (ufo->aircraftTarget)
			UFO_CheckShootBack(campaign, ufo, ufo->aircraftTarget);
		return;
	}

	/* check if the ufo is already attacking an aircraft */
	if (ufo->aircraftTarget) {
		/* check if the target disappeared from geoscape (fled in a base) */
		if (AIR_IsAircraftOnGeoscape(ufo->aircraftTarget))
			AIRFIGHT_ExecuteActions(campaign, ufo, ufo->aircraftTarget);
		else
			ufo->aircraftTarget = nullptr;
		return;
	}

	ufo->status = AIR_TRANSIT;
	AIR_Foreach(phalanxAircraft) {
		/* check that aircraft is flying */
		if (AIR_IsAircraftOnGeoscape(phalanxAircraft)) {
			/* get the distance from ufo to aircraft */
			const float dist = GetDistanceOnGlobe(ufo->pos, phalanxAircraft->pos);
			/* check out of reach */
			if (dist > maxDetectionRange)
				continue;
			/* choose the nearest target */
			if (dist < distance) {
				distance = dist;
				if (UFO_SendPursuingAircraft(ufo, phalanxAircraft) && UFO_IsUFOSeenOnGeoscape(ufo)) {
					/* stop time and notify */
					MSO_CheckAddNewMessage(NT_UFO_ATTACKING, _("Notice"), va(_("A UFO is flying toward %s"), phalanxAircraft->name));
					/** @todo present a popup with possible orders like: return to base, attack the ufo, try to flee the rockets */
					return;
				}
			}
		}
	}

	/* if this ufo is a leader, it does not try to search another one */
	if (ufo->leader)
		return;
	aircraft_t* otherUFO = nullptr;
	const float polarCoordinatesOffset = 1.0f;
	while ((otherUFO = UFO_GetNextOnGeoscape(otherUFO)) != nullptr) {
		if (otherUFO == ufo)
			continue;
		if (otherUFO->leader) {
			vec2_t dest;
			AIR_GetDestinationWhilePursuing(ufo, otherUFO, dest);
			dest[0] += polarCoordinatesOffset;
			dest[1] += polarCoordinatesOffset;
			GEO_CalcLine(ufo->pos, dest, &ufo->route);
			ufo->time = 0;
			ufo->point = 0;
			break;
		}
	}
}