/**
 * @brief Function to trigger UFO Recovered event.
 * @note This function prepares related cvars for the recovery dialog.
 * @note Command to call this: cp_uforecovery_init.
 */
static void UR_DialogInit_f (void)
{
	char ufoID[MAX_VAR];
	const aircraft_t *ufoCraft;
	float cond = 1.0f;

	if (cgi->Cmd_Argc() < 2) {
		Com_Printf("Usage: %s <ufoID> [UFO-Condition]\n", cgi->Cmd_Argv(0));
		return;
	}

	Q_strncpyz(ufoID, cgi->Cmd_Argv(1), sizeof(ufoID));

	if (cgi->Cmd_Argc() >= 3)
		cond = atof(cgi->Cmd_Argv(2));

	ufoCraft = AIR_GetAircraft(ufoID);

	/* Fill ufoRecovery structure */
	OBJZERO(ufoRecovery);
	ufoRecovery.ufoTemplate = ufoCraft;
	ufoRecovery.condition = cond;
	ufoRecovery.sortedColumn = ORDER_NATION;

	if (ufoCraft) {
		if (cond < 1.0)
			cgi->Cvar_Set("mn_uforecovery_actualufo", va(_("\nSecured crashed %s (%.0f%%)\n"), UFO_GetName(ufoCraft), cond * 100));
		else
			cgi->Cvar_Set("mn_uforecovery_actualufo", va(_("\nSecured landed %s\n"), UFO_GetName(ufoCraft)));

		cgi->UI_PushWindow("uforecovery");
	}
}
Exemple #2
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);
}
Exemple #3
0
/**
 * @brief sets market prices at start of the game
 * @sa CP_CampaignInit
 * @sa B_SetUpFirstBase
 * @sa BS_Load (Market load function)
 */
void BS_InitMarket (const campaign_t* campaign)
{
	int i;
	market_t* market = BS_GetMarket();

	for (i = 0; i < cgi->csi->numODs; i++) {
		const objDef_t* od = INVSH_GetItemByIDX(i);
		if (market->askItems[i] == 0) {
			market->askItems[i] = od->price;
			market->bidItems[i] = floor(market->askItems[i] * BID_FACTOR);
		}

		if (campaign->marketDef->numItems[i] <= 0)
			continue;

		if (RS_IsResearched_ptr(RS_GetTechForItem(od))) {
			/* the other relevant values were already set above */
			market->numItems[i] = campaign->marketDef->numItems[i];
		} else {
			Com_Printf("BS_InitMarket: Could not add item %s to the market - not marked as researched in campaign %s\n",
					od->id, campaign->id);
		}
	}

	for (i = 0; i < AIRCRAFTTYPE_MAX; i++) {
		const char* name = cgi->Com_DropShipTypeToShortName((humanAircraftType_t)i);
		const aircraft_t* aircraft = AIR_GetAircraft(name);
		if (market->askAircraft[i] == 0) {
			market->askAircraft[i] = aircraft->price;
			market->bidAircraft[i] = floor(market->askAircraft[i] * BID_FACTOR);
		}

		if (campaign->marketDef->numAircraft[i] <= 0)
			continue;

		if (RS_IsResearched_ptr(aircraft->tech)) {
			/* the other relevant values were already set above */
			market->numAircraft[i] = campaign->marketDef->numAircraft[i];
		} else {
			Com_Printf("BS_InitMarket: Could not add aircraft %s to the market - not marked as researched in campaign %s\n",
					aircraft->id, campaign->id);
		}
	}
}
Exemple #4
0
/**
 * @brief make number of items change every day.
 * @sa CP_CampaignRun
 * @sa daily called
 * @note This function makes items number on market slowly reach the asymptotic number of items defined in equipment.ufo
 * If an item has just been researched, it's not available on market until RESEARCH_LIMIT_DELAY days is reached.
 */
void CP_CampaignRunMarket (campaign_t* campaign)
{
	int i;
	const float TYPICAL_TIME = 10.f;			/**< Number of days to reach the asymptotic number of items */
	const int RESEARCH_LIMIT_DELAY = 30;		/**< Numbers of days after end of research to wait in order to have
												 * items added on market */
	market_t* market = BS_GetMarket();

	assert(campaign->marketDef);
	assert(campaign->asymptoticMarketDef);

	for (i = 0; i < cgi->csi->numODs; i++) {
		const objDef_t* od = INVSH_GetItemByIDX(i);
		const technology_t* tech = RS_GetTechForItem(od);
		int asymptoticNumber;

		if (RS_IsResearched_ptr(tech) && (campaign->marketDef->numItems[i] != 0 || ccs.date.day > tech->researchedDate.day + RESEARCH_LIMIT_DELAY)) {
			/* if items are researched for more than RESEARCH_LIMIT_DELAY or was on the initial market,
			 * there number tend to the value defined in equipment.ufo.
			 * This value is the asymptotic value if it is not 0, or initial value else */
			asymptoticNumber = campaign->asymptoticMarketDef->numItems[i] ? campaign->asymptoticMarketDef->numItems[i] : campaign->marketDef->numItems[i];
		} else {
			/* items that have just been researched don't appear on market, but they can disappear */
			asymptoticNumber = 0;
		}

		/* Store the evolution of the market in currentEvolution */
		market->currentEvolutionItems[i] += (asymptoticNumber - market->numItems[i]) / TYPICAL_TIME;

		/* Check if new items appeared or disappeared on market */
		if (fabs(market->currentEvolutionItems[i]) >= 1.0f) {
			const int num = (int)(market->currentEvolutionItems[i]);
			if (num >= 0)
				BS_AddItemToMarket(od, num);
			else
				BS_RemoveItemFromMarket(od, -num);
			market->currentEvolutionItems[i] -= num;
		}
	}

	for (i = 0; i < AIRCRAFTTYPE_MAX; i++) {
		const humanAircraftType_t type = (humanAircraftType_t)i;
		const char* aircraftID = cgi->Com_DropShipTypeToShortName(type);
		const aircraft_t* aircraft = AIR_GetAircraft(aircraftID);
		const technology_t* tech = aircraft->tech;
		int asymptoticNumber;

		if (RS_IsResearched_ptr(tech) && (campaign->marketDef->numAircraft[i] != 0 || ccs.date.day > tech->researchedDate.day + RESEARCH_LIMIT_DELAY)) {
			/* if aircraft is researched for more than RESEARCH_LIMIT_DELAY or was on the initial market,
			 * there number tend to the value defined in equipment.ufo.
			 * This value is the asymptotic value if it is not 0, or initial value else */
			asymptoticNumber = campaign->asymptoticMarketDef->numAircraft[i] ? campaign->asymptoticMarketDef->numAircraft[i] : campaign->marketDef->numAircraft[i];
		} else {
			/* items that have just been researched don't appear on market, but they can disappear */
			asymptoticNumber = 0;
		}
		/* Store the evolution of the market in currentEvolution */
		market->currentEvolutionAircraft[i] += (asymptoticNumber - market->numAircraft[i]) / TYPICAL_TIME;

		/* Check if new items appeared or disappeared on market */
		if (fabs(market->currentEvolutionAircraft[i]) >= 1.0f) {
			const int num = (int)(market->currentEvolutionAircraft[i]);
			if (num >= 0)
				BS_AddAircraftToMarket(aircraft, num);
			else
				BS_RemoveAircraftFromMarket(aircraft, -num);
			market->currentEvolutionAircraft[i] -= num;
		}
	}
}
Exemple #5
0
/**
 * @brief Load callback for xml savegames
 * @param[in] p XML Node structure, where we get the information from
 * @sa PR_SaveXML
 * @sa SAV_GameLoadXML
 */
bool PR_LoadXML (xmlNode_t* p)
{
	xmlNode_t* node = cgi->XML_GetNode(p, SAVE_PRODUCE_PRODUCTION);

	for (xmlNode_t* snode = cgi->XML_GetNode(node, SAVE_PRODUCE_QUEUE); snode;
			snode = cgi->XML_GetNextNode(snode, node, SAVE_PRODUCE_QUEUE)) {
		xmlNode_t* ssnode;
		const int baseIDX = cgi->XML_GetInt(snode, SAVE_PRODUCE_QUEUEIDX, MAX_BASES);
		base_t* base = B_GetBaseByIDX(baseIDX);
		production_queue_t* pq;

		if (base == nullptr) {
			Com_Printf("Invalid production queue index %i\n", baseIDX);
			continue;
		}

		pq = PR_GetProductionForBase(base);

		for (ssnode = cgi->XML_GetNode(snode, SAVE_PRODUCE_ITEM); pq->numItems < MAX_PRODUCTIONS && ssnode;
				ssnode = cgi->XML_GetNextNode(ssnode, snode, SAVE_PRODUCE_ITEM)) {
			const char* s1 = cgi->XML_GetString(ssnode, SAVE_PRODUCE_ITEMID);
			production_t* prod = &pq->items[pq->numItems];

			prod->idx = pq->numItems;
			prod->amount = cgi->XML_GetInt(ssnode, SAVE_PRODUCE_AMOUNT, 0);
			prod->frame = cgi->XML_GetInt(ssnode, SAVE_PRODUCE_PROGRESS, 0);

			/* amount */
			if (prod->amount <= 0) {
				Com_Printf("PR_LoadXML: Production with amount <= 0 dropped (baseidx=%i, production idx=%i).\n",
						baseIDX, pq->numItems);
				continue;
			}
			/* item */
			if (s1[0] != '\0')
				PR_SetData(&prod->data, PRODUCTION_TYPE_ITEM, INVSH_GetItemByID(s1));
			/* UFO */
			const int ufoIDX = cgi->XML_GetInt(ssnode, SAVE_PRODUCE_UFOIDX, -1);
			if (ufoIDX != -1) {
				storedUFO_t* ufo = US_GetStoredUFOByIDX(ufoIDX);

				if (!ufo) {
					Com_Printf("PR_LoadXML: Could not find ufo idx: %i\n", ufoIDX);
					continue;
				}

				PR_SetData(&prod->data, PRODUCTION_TYPE_DISASSEMBLY, ufo);
				PR_SetUFODisassembly(prod);
			}
			/* aircraft */
			const char* s2 = cgi->XML_GetString(ssnode, SAVE_PRODUCE_AIRCRAFTID);
			if (s2[0] != '\0')
				PR_SetData(&prod->data, PRODUCTION_TYPE_AIRCRAFT, AIR_GetAircraft(s2));

			if (!PR_IsDataValid(&prod->data)) {
				Com_Printf("PR_LoadXML: Production is not an item an aircraft nor a disassembly\n");
				continue;
			}

			pq->numItems++;
		}
	}
	return true;
}