Example #1
0
/**
 * @brief Decide what an attacking aircraft can do.
 * @param[in] campaign The campaign data structure
 * @param[in] shooter The aircraft we attack with.
 * @param[in] target The ufo we are going to attack.
 * @todo Implement me and display an attack popup.
 */
void AIRFIGHT_ExecuteActions (const campaign_t* campaign, aircraft_t* shooter, aircraft_t* target)
{
	/* some asserts */
	assert(shooter);
	assert(target);

	/* Check if the attacking aircraft can shoot */
	const int slotIdx = AIRFIGHT_ChooseWeapon(shooter->weapons, shooter->maxWeapons, shooter->pos, target->pos);

	/* if weapon found that can shoot */
	if (slotIdx >= AIRFIGHT_WEAPON_CAN_SHOOT) {
		aircraftSlot_t* weaponSlot = &shooter->weapons[slotIdx];
		const objDef_t* ammo = weaponSlot->ammo;

		/* shoot */
		if (AIRFIGHT_AddProjectile(nullptr, nullptr, shooter, target, weaponSlot)) {
			/* will we miss the target ? */
			const float probability = frand();
			Com_DPrintf(DEBUG_CLIENT, "AIRFIGHT_ExecuteActions: %s - Random probability to hit: %f\n", shooter->name, probability);
			weaponSlot->delayNextShot = ammo->craftitem.weaponDelay;

			const float calculatedProbability = AIRFIGHT_ProbabilityToHit(shooter, target, shooter->weapons + slotIdx);
			Com_DPrintf(DEBUG_CLIENT, "AIRFIGHT_ExecuteActions: %s - Calculated probability to hit: %f\n", shooter->name, calculatedProbability);

			if (probability > calculatedProbability)
				AIRFIGHT_MissTarget(&ccs.projectiles[ccs.numProjectiles - 1]);

			if (shooter->type != AIRCRAFT_UFO) {
				/* Maybe UFO is going to shoot back ? */
				UFO_CheckShootBack(campaign, target, shooter);
			} else {
				/* an undetected UFO within radar range and firing should become detected */
				if (!shooter->detected && RADAR_CheckRadarSensored(shooter->pos)) {
					/* stop time and notify */
					MSO_CheckAddNewMessage(NT_UFO_ATTACKING, _("Notice"), va(_("A UFO is shooting at %s"), target->name));
					RADAR_AddDetectedUFOToEveryRadar(shooter);
					UFO_DetectNewUFO(shooter);
				}
			}
		}
	} else if (slotIdx == AIRFIGHT_WEAPON_CAN_NOT_SHOOT_AT_THE_MOMENT) {
		/* no ammo to fire atm (too far or reloading), pursue target */
		if (shooter->type == AIRCRAFT_UFO) {
			/** @todo This should be calculated only when target destination changes, or when aircraft speed changes.
			 *  @sa AIR_GetDestination */
			UFO_SendPursuingAircraft(shooter, target);
		} else
			AIR_SendAircraftPursuingUFO(shooter, target);
	} else {
		/* no ammo left, or no weapon, proceed with mission */
		if (shooter->type == AIRCRAFT_UFO) {
			shooter->aircraftTarget = nullptr;		/* reset target */
			CP_UFOProceedMission(campaign, shooter);
		} else {
			MS_AddNewMessage(_("Notice"), _("Our aircraft has no more ammo left - returning to home base now."));
			AIR_AircraftReturnToBase(shooter);
		}
	}
}
Example #2
0
/**
 * @brief Check events for UFOs: Appears or disappears on radars
 * @return qtrue if any new ufo was detected during this iteration, qfalse otherwise
 */
qboolean UFO_CampaignCheckEvents (void)
{
	qboolean newDetection;
	aircraft_t *ufo;

	newDetection = qfalse;

	/* For each ufo in geoscape */
	ufo = NULL;
	while ((ufo = UFO_GetNext(ufo)) != NULL) {
		char detectedBy[MAX_VAR] = "";
		float minDistance = -1;
		/* detected tells us whether or not a UFO is detected NOW, whereas ufo->detected tells
		 * us whether or not the UFO was detected PREVIOUSLY. */
		qboolean detected = qfalse;
		base_t *base;

		/* don't update UFO status id UFO is landed or crashed */
		if (ufo->landed)
			continue;

		/* note: We can't exit these loops as soon as we found the UFO detected
		 * RADAR_CheckUFOSensored registers the UFO in every radars' detection list
		 * which detect it */

		/* Check if UFO is detected by an aircraft */
		AIR_Foreach(aircraft) {
			if (!AIR_IsAircraftOnGeoscape(aircraft))
				continue;
			/* maybe the ufo is already detected, don't reset it */
			if (RADAR_CheckUFOSensored(&aircraft->radar, aircraft->pos, ufo, detected | ufo->detected)) {
				const int distance = GetDistanceOnGlobe(aircraft->pos, ufo->pos);
				detected = qtrue;
				if (minDistance < 0 || minDistance > distance) {
					minDistance = distance;
					Q_strncpyz(detectedBy, aircraft->name, sizeof(detectedBy));
				}
			}
		}

		/* Check if UFO is detected by a base */
		base = NULL;
		while ((base = B_GetNext(base)) != NULL) {
			if (!B_GetBuildingStatus(base, B_POWER))
				continue;

			/* maybe the ufo is already detected, don't reset it */
			if (RADAR_CheckUFOSensored(&base->radar, base->pos, ufo, detected | ufo->detected)) {
				const int distance = GetDistanceOnGlobe(base->pos, ufo->pos);
				detected = qtrue;
				if (minDistance < 0 || minDistance > distance) {
					minDistance = distance;
					Q_strncpyz(detectedBy, base->name, sizeof(detectedBy));
				}
			}

		}

		/* Check if UFO is detected by a radartower */
		INS_Foreach(installation) {
			/* maybe the ufo is already detected, don't reset it */
			if (RADAR_CheckUFOSensored(&installation->radar, installation->pos, ufo, detected | ufo->detected)) {
				const int distance = GetDistanceOnGlobe(installation->pos, ufo->pos);
				detected = qtrue;
				if (minDistance < 0 || minDistance > distance) {
					minDistance = distance;
					Q_strncpyz(detectedBy, installation->name, sizeof(detectedBy));
				}
			}
		}

		/* Check if ufo appears or disappears on radar */
		if (detected != ufo->detected) {
			if (detected) {
				/* if UFO is aiming a PHALANX aircraft, warn player */
				if (ufo->aircraftTarget) {
					/* stop time and notify */
					MSO_CheckAddNewMessage(NT_UFO_ATTACKING, _("Notice"), va(_("A UFO is flying toward %s"), ufo->aircraftTarget->name), qfalse,
							MSG_STANDARD, NULL);
					/** @todo present a popup with possible orders like: return to base, attack the ufo, try to flee the rockets
					 * @sa UFO_SearchAircraftTarget */
				} else {
					MSO_CheckAddNewMessage(NT_UFO_SPOTTED, _("Notice"), va(_("Our radar detected a new UFO near %s"), detectedBy), qfalse,
							MSG_UFOSPOTTED, NULL);
				}
				newDetection = qtrue;
				UFO_DetectNewUFO(ufo);
			} else if (!detected) {
				MSO_CheckAddNewMessage(NT_UFO_SIGNAL_LOST, _("Notice"), _("Our radar has lost the tracking on a UFO"), qfalse, MSG_UFOLOST, NULL);
				/* Make this UFO undetected */
				ufo->detected = qfalse;
				/* Notify that ufo disappeared */
				AIR_AircraftsUFODisappear(ufo);
				MAP_NotifyUFODisappear(ufo);

				/* Deactivate Radar overlay */
				RADAR_DeactivateRadarOverlay();
			}
		}
	}
	return newDetection;
}