/** * @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; }
/** * @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.")); } }
/** * @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); } }
/** * @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); }
/** * @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; }