/**
 * @brief Fills the UI with ufo yard data
 */
static void INS_FillUFOYardData_f (void)
{
	installation_t* ins;

	cgi->UI_ExecuteConfunc("ufolist_clear");
	if (cgi->Cmd_Argc() < 2 || atoi(cgi->Cmd_Argv(1)) < 0) {
		ins = INS_GetCurrentSelectedInstallation();
		if (!ins || ins->installationTemplate->type != INSTALLATION_UFOYARD)
			ins = INS_GetFirstUFOYard(false);
	} else {
		ins = INS_GetByIDX(atoi(cgi->Cmd_Argv(1)));
		if (!ins)
			Com_DPrintf(DEBUG_CLIENT, "Installation not founded (idx %i)\n", atoi(cgi->Cmd_Argv(1)));
	}

	if (ins) {
		const nation_t* nat = GEO_GetNation(ins->pos);
		const int timeToBuild = std::max(0, ins->installationTemplate->buildTime - (ccs.date.day - ins->buildStart));
		const char* buildTime = (timeToBuild > 0 && ins->installationStatus == INSTALLATION_UNDER_CONSTRUCTION) ? va(ngettext("%d day", "%d days", timeToBuild), timeToBuild) : "-";
		const int freeCap = std::max(0, ins->ufoCapacity.max - ins->ufoCapacity.cur);
		const char* nationName = nat ? _(nat->name) : "";

		cgi->UI_ExecuteConfunc("ufolist_addufoyard %d \"%s\" \"%s\" %d %d \"%s\"", ins->idx, ins->name, nationName, ins->ufoCapacity.max, freeCap, buildTime);

		US_Foreach(ufo) {
			if (ufo->installation != ins)
				continue;

			const char* ufoName = UFO_GetName(ufo->ufoTemplate);
			const char* condition = va(_("Condition: %3.0f%%"), ufo->condition * 100);
			const char* status = US_StoredUFOStatus(ufo);
			cgi->UI_ExecuteConfunc("ufolist_addufo %d \"%s\" \"%s\" \"%s\" \"%s\"", ufo->idx, ufoName, condition, ufo->ufoTemplate->model, status);
		}
	}
}
/**
 * @brief Constructs a new installation.
 */
static void INS_BuildInstallation_f (void)
{
	const installationTemplate_t* installationTemplate;

	if (cgi->Cmd_Argc() < 1) {
		Com_Printf("Usage: %s <installationType>\n", cgi->Cmd_Argv(0));
		return;
	}

	/* We shouldn't build more installations than the actual limit */
	if (B_GetInstallationLimit() <= INS_GetCount())
		return;

	installationTemplate = INS_GetInstallationTemplateByID(cgi->Cmd_Argv(1));
	if (!installationTemplate) {
		Com_Printf("The installation type %s passed for %s is not valid.\n", cgi->Cmd_Argv(1), cgi->Cmd_Argv(0));
		return;
	}

	assert(installationTemplate->cost >= 0);

	if (ccs.credits - installationTemplate->cost > 0) {
		/* set up the installation */
		installation_t* installation = INS_Build(installationTemplate, ccs.newBasePos, cgi->Cvar_GetString("mn_installation_title"));

		CP_UpdateCredits(ccs.credits - installationTemplate->cost);
		/* this cvar is used for disabling the installation build button on geoscape if MAX_INSTALLATIONS was reached */
		cgi->Cvar_SetValue("mn_installation_count", INS_GetCount());

		const nation_t* nation = GEO_GetNation(installation->pos);
		if (nation)
			Com_sprintf(cp_messageBuffer, sizeof(cp_messageBuffer), _("A new installation has been built: %s (nation: %s)"), installation->name, _(nation->name));
		else
			Com_sprintf(cp_messageBuffer, sizeof(cp_messageBuffer), _("A new installation has been built: %s"), installation->name);
		MSO_CheckAddNewMessage(NT_INSTALLATION_BUILDSTART, _("Installation building"), cp_messageBuffer, MSG_CONSTRUCTION);
	} else {
		if (installationTemplate->type == INSTALLATION_RADAR) {
			if (GEO_IsRadarOverlayActivated())
					GEO_SetOverlay("radar");
		}
		if (ccs.mapAction == MA_NEWINSTALLATION)
			ccs.mapAction = MA_NONE;

		CP_Popup(_("Notice"), _("Not enough credits to set up a new installation."));
	}
	ccs.mapAction = MA_NONE;
}
Esempio n. 3
0
/**
 * @brief Constructs a new base.
 * @sa B_NewBase
 */
static void B_BuildBase_f (void)
{
	const campaign_t* campaign = ccs.curCampaign;

	if (ccs.mapAction == MA_NEWBASE)
		ccs.mapAction = MA_NONE;

	if (ccs.credits - campaign->basecost > 0) {
		const nation_t* nation;
		const char* baseName = mn_base_title->string;
		base_t* base;
		/* there may be no " in the base name */
		if (!Com_IsValidName(baseName))
			baseName = _("Base");

		base = B_Build(campaign, ccs.newBasePos, baseName);
		if (!base)
			cgi->Com_Error(ERR_DROP, "Cannot build base");

		CP_UpdateCredits(ccs.credits - campaign->basecost);
		nation = GEO_GetNation(base->pos);
		if (nation)
			Com_sprintf(cp_messageBuffer, sizeof(cp_messageBuffer), _("A new base has been built: %s (nation: %s)"), mn_base_title->string, _(nation->name));
		else
			Com_sprintf(cp_messageBuffer, sizeof(cp_messageBuffer), _("A new base has been built: %s"), mn_base_title->string);
		MS_AddNewMessage(_("Base built"), cp_messageBuffer, MSG_CONSTRUCTION);

		/* First base */
		if (ccs.campaignStats.basesBuilt == 1)
			B_SetUpFirstBase(campaign, base);

		cgi->Cvar_SetValue("mn_base_count", B_GetCount());
		B_SelectBase(base);
	} else {
		/** @todo Why is this needed? Also see bug #5401 */
		if (GEO_IsRadarOverlayActivated())
			GEO_SetOverlay("radar", 0);

		CP_PopupList(_("Notice"), _("Not enough credits to set up a new base."));
	}
}
Esempio n. 4
0
/**
 * @brief Subverting Mission ends: UFO leave earth.
 * @note Build Base mission -- Stage 3
 */
static void CP_BuildBaseGovernmentLeave (const campaign_t* campaign, mission_t* mission)
{
	nation_t* nation;

	assert(mission);
	assert(mission->ufo);

	mission->stage = STAGE_RETURN_TO_ORBIT;

	/* Mission is a success: government is subverted => lower happiness */
	nation = GEO_GetNation(mission->pos);
	/** @todo when the mission is created, we should select a position where nation exists,
	 * otherwise subverting a government is meaningless */
	if (nation) {
		const nationInfo_t* stats = NAT_GetCurrentMonthInfo(nation);
		NAT_SetHappiness(campaign->minhappiness, nation, stats->happiness + HAPPINESS_SUBVERSION_LOSS);
	}

	CP_MissionDisableTimeLimit(mission);
	UFO_SetRandomDest(mission->ufo);
	/* Display UFO on geoscape if it is detected */
	mission->ufo->landed = false;
}
/**
 * @brief Fills UFO Yard UI with transfer destinations
 */
static void US_FillUFOTransfer_f (void)
{
	if (cgi->Cmd_Argc() < 2) {
		Com_DPrintf(DEBUG_CLIENT, "Usage: %s <idx>\n", cgi->Cmd_Argv(0));
		return;
	}

	storedUFO_t *ufo = US_GetStoredUFOByIDX(atoi(cgi->Cmd_Argv(1)));
	if (!ufo) {
		Com_DPrintf(DEBUG_CLIENT, "Stored UFO with idx: %i does not exist\n", atoi(cgi->Cmd_Argv(1)));
		return;
	}

	cgi->UI_ExecuteConfunc("ufotransferlist_clear");
	INS_ForeachOfType(ins, INSTALLATION_UFOYARD) {
		if (ins == ufo->installation)
			continue;
		nation_t *nat = GEO_GetNation(ins->pos);
		const char *nationName = nat ? _(nat->name) : "";
		const int freeSpace = std::max(0, ins->ufoCapacity.max - ins->ufoCapacity.cur);
		cgi->UI_ExecuteConfunc("ufotransferlist_addyard %d \"%s\" \"%s\" %d %d", ins->idx, ins->name, nationName, freeSpace, ins->ufoCapacity.max);
	}
}
Esempio n. 6
0
/**
 * @brief Changes nation happiness by given value.
 * @note There must be argument passed to this function being converted to float.
 */
static void CP_ChangeNationHappiness_f (void)
{
	float change;
	nation_t* nation;
	const nationInfo_t* stats;
	const mission_t* mission = GEO_GetSelectedMission();

	if (cgi->Cmd_Argc() < 2) {
		Com_Printf("Usage: %s <absolute change value>\n", cgi->Cmd_Argv(0));
		return;
	}
	change = atof(cgi->Cmd_Argv(1));

	if (!mission) {
		Com_Printf("No mission selected - could not determine nation to use\n");
		return;
	}

	nation = GEO_GetNation(mission->pos);
	assert(nation);

	stats = NAT_GetCurrentMonthInfo(nation);
	NAT_SetHappiness(ccs.curCampaign->minhappiness, nation, stats->happiness + change);
}
Esempio n. 7
0
/**
 * @brief Update xviInfection value for each nation, using the XVI overlay.
 * @note should be executed after all daily event that could change XVI overlay
 */
void CP_UpdateNationXVIInfection (void)
{
	/* No need to update XVI levels if the overlay didn't change */
	if (!xviNationInfectionNeedsUpdate)
		return;

	/* width in pixel of the XVI overlay */
	int width;
	/* height in pixel of the XVI overlay */
	int height;
	CP_GetXVIMapDimensions(&width, &height);

	const float heightPerDegree = height / 180.0f;
	const float widthPerDegree = width / 360.0f;
	/* parameter used to normalize nation XVI level.
	 * decrease this factor to increase XVI level per nation */
	const float AREA_FACTOR = 650.0f;
	/* area used to normalized XVI infection level for each nation.
	 * depend on overlay size so that if we change resolution of
	 * overlay it doesn't impact nation XIInfection */
	const float normalizingArea = width * height / AREA_FACTOR;

	/* temporary array to store the XVI levels */
	float xviInfection[MAX_NATIONS];
	/* Initialize array */
	OBJZERO(xviInfection);

	for (int y = 0; y < height; y++) {
		int sum[MAX_NATIONS];
		const byte* previousNationColor;
		const nation_t* nation;
		/* current position (in latitude / longitude) */
		vec2_t currentPos;

		OBJZERO(sum);

		Vector2Set(currentPos, 180.0f, 90.0f - y / heightPerDegree);
		previousNationColor = GEO_GetColor(currentPos, MAPTYPE_NATIONS, nullptr);
		nation = GEO_GetNation(currentPos);

		for (int x = 0; x < width; x++) {
			const byte* nationColor;
			currentPos[0] = 180.0f - x / widthPerDegree;
			nationColor = GEO_GetColor(currentPos, MAPTYPE_NATIONS, nullptr);
			if (!VectorCompare(nationColor, previousNationColor)) {
				previousNationColor = nationColor;
				nation = GEO_GetNation(currentPos);
			}
			if (nation) {
				const int xviLevel = CP_GetXVILevel(x, y);
				if (xviLevel > 0)
					sum[nation->idx] += xviLevel;
			}
		}
		/* divide the total XVI infection by the area of a pixel
		 * because pixel are smaller as you go closer from the pole */
		for (int nationIdx = 0; nationIdx < ccs.numNations; nationIdx++)
			xviInfection[nationIdx] += ((float) sum[nationIdx]) / (cos(torad * currentPos[1]) * normalizingArea);
	}

	/* copy the new values of XVI infection level into nation array */
	for (int nationIdx = 0; nationIdx < ccs.numNations; nationIdx++) {
		nation_t* nation = NAT_GetNationByIDX(nationIdx);
		nation->stats[0].xviInfection = ceil(xviInfection[nation->idx]);
	}

	xviNationInfectionNeedsUpdate = false;
}