Beispiel #1
0
/**
 * @brief Prints the UFOpaedia description for aircraft
 * @note Also checks whether the aircraft tech is already researched or collected
 * @sa BS_MarketAircraftDescription
 * @sa UP_Article
 */
void UP_AircraftDescription (const technology_t* tech)
{
	cgi->INV_ItemDescription(nullptr);

	/* ensure that the buffer is emptied in every case */
	upBuffer[0] = '\0';

	if (RS_IsResearched_ptr(tech)) {
		const aircraft_t* aircraft = AIR_GetAircraft(tech->provides);
		for (int i = 0; i < AIR_STATS_MAX; i++) {
			switch (i) {
			case AIR_STATS_SPEED:
				/* speed may be converted to km/h : multiply by pi / 180 * earth_radius */
				Q_strcat(upBuffer, sizeof(upBuffer), _("%s:\t%i km/h\n"), UP_AircraftStatToName(i),
					AIR_AircraftMenuStatsValues(aircraft->stats[i], i));
				break;
			case AIR_STATS_MAXSPEED:
				/* speed may be converted to km/h : multiply by pi / 180 * earth_radius */
				Q_strcat(upBuffer, sizeof(upBuffer), _("%s:\t%i km/h\n"), UP_AircraftStatToName(i),
					AIR_AircraftMenuStatsValues(aircraft->stats[i], i));
				break;
			case AIR_STATS_FUELSIZE:
				Q_strcat(upBuffer, sizeof(upBuffer), _("Operational range:\t%i km\n"),
					AIR_GetOperationRange(aircraft));
				break;
			case AIR_STATS_ACCURACY:
				Q_strcat(upBuffer, sizeof(upBuffer), _("%s:\t%i\n"), UP_AircraftStatToName(i),
					AIR_AircraftMenuStatsValues(aircraft->stats[i], i));
				break;
			default:
				break;
			}
		}

		const baseCapacities_t cap = AIR_GetCapacityByAircraftWeight(aircraft);
		const buildingType_t buildingType = B_GetBuildingTypeByCapacity(cap);
		const building_t* building = B_GetBuildingTemplateByType(buildingType);

		Q_strcat(upBuffer, sizeof(upBuffer), _("Required Hangar:\t%s\n"), _(building->name));
		/* @note: while MAX_ACTIVETEAM limits the number of soldiers on a craft
		 * there is no use to show this in case of an UFO (would be misleading): */
		if (!AIR_IsUFO(aircraft))
			Q_strcat(upBuffer, sizeof(upBuffer), _("Max. soldiers:\t%i\n"), aircraft->maxTeamSize);
	} else if (RS_Collected_(tech)) {
		/** @todo Display crippled info and pre-research text here */
		Com_sprintf(upBuffer, sizeof(upBuffer), _("Unknown - need to research this"));
	} else {
		Com_sprintf(upBuffer, sizeof(upBuffer), _("Unknown - need to research this"));
	}

	cgi->Cvar_Set("mn_upmetadata", "1");
	cgi->UI_RegisterText(TEXT_ITEMDESCRIPTION, upBuffer);
	UP_DisplayTechTree(tech);
}
Beispiel #2
0
/**
 * @brief Set all projectile aiming a given aircraft to an idle destination.
 * @param[in] aircraft Pointer to the aimed aircraft.
 * @note This function is called when @c aircraft is destroyed.
 * @sa AIRFIGHT_ActionsAfterAirfight
 */
void AIRFIGHT_RemoveProjectileAimingAircraft (const aircraft_t* aircraft)
{
	aircraftProjectile_t* projectile;
	int idx = 0;

	if (!aircraft)
		return;

	for (projectile = ccs.projectiles; idx < ccs.numProjectiles; projectile++, idx++) {
		if (projectile->aimedAircraft != aircraft)
			continue;

		AIRFIGHT_MissTarget(projectile);
		if (projectile->attackingAircraft && projectile->attackingAircraft->homebase) {
			assert(!AIR_IsUFO(projectile->attackingAircraft));
			AIR_AircraftReturnToBase(projectile->attackingAircraft);
		}
	}
}
/**
 * @brief Change destination of projectile to an idle point of the map, close to its former target.
 * @param[in] projectile The projectile to update
 */
static void AIRFIGHT_MissTarget (aircraftProjectile_t *projectile, qboolean returnToBase)
{
	vec3_t newTarget;
	float distance;
	float offset;

	assert(projectile);

	if (projectile->aimedAircraft) {
		VectorCopy(projectile->aimedAircraft->pos, newTarget);
		projectile->aimedAircraft = NULL;
	} else {
		VectorCopy(projectile->idleTarget, newTarget);
	}

	/* get the distance between the projectile and target */
	distance = GetDistanceOnGlobe(projectile->pos[0], newTarget);

	/* Work out how much the projectile should miss the target by.  We dont want it too close
	 * or too far from the original target.
	 * * 1/3 distance between target and projectile * random (range -0.5 to 0.5)
	 * * Then make sure the value is at least greater than 0.1 or less than -0.1 so that
	 *   the projectile doesn't land too close to the target. */
	offset = (distance / 3) * (frand() - 0.5f);

	if (abs(offset) < 0.1f)
		offset = 0.1f;

	newTarget[0] = newTarget[0] + offset;
	newTarget[1] = newTarget[1] + offset;

	VectorCopy(newTarget, projectile->idleTarget);

	if (returnToBase && projectile->attackingAircraft) {
		if (projectile->attackingAircraft->homebase) {
			assert(!AIR_IsUFO(projectile->attackingAircraft));
			AIR_AircraftReturnToBase(projectile->attackingAircraft);
		}
	}
}