00001
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "../cl_shared.h"
00027 #include "../ui/ui_main.h"
00028 #include "../ui/ui_popup.h"
00029 #include "cp_campaign.h"
00030 #include "cp_base_callbacks.h"
00031 #include "cp_base.h"
00032 #include "cp_map.h"
00033 #include "cp_popup.h"
00034 #include "cp_ufo.h"
00035
00037 #define CREATE_NEW_BASE_ID -1
00038
00039 static cvar_t *mn_base_title;
00040 static cvar_t *cl_start_buildings;
00041 static building_t *buildingConstructionList[MAX_BUILDINGS];
00042 static int buildingNumber = 0;
00043
00047 static void B_Destroy_AntimaterStorage_f (void)
00048 {
00049 base_t *base;
00050 const float prob = frand();
00051
00052 if (Cmd_Argc() < 4) {
00053 Com_Printf("Usage: %s <probability> <baseID> <buildingType>\n", Cmd_Argv(0));
00054 return;
00055 }
00056
00057 base = B_GetFoundedBaseByIDX(atoi(Cmd_Argv(2)));
00058 if (!base)
00059 return;
00060 if (base->capacities[CAP_ANTIMATTER].cur <= 0)
00061 return;
00062
00063 B_RemoveAntimatterExceedingCapacity(base);
00064
00065 if (base->baseStatus != BASE_WORKING)
00066 return;
00067
00068 if (prob < atof(Cmd_Argv(1))) {
00069 MS_AddNewMessage(_("Notice"), va(_("%s has been destroyed by an antimatter storage breach."), base->name), qfalse, MSG_STANDARD, NULL);
00070 UI_PopWindow(qfalse);
00071 B_Destroy(base);
00072 }
00073 }
00074
00083 static void B_BuildingAddToList (linkedList_t **buildingList, building_t *building)
00084 {
00085 int count;
00086 assert(building);
00087 assert(building->name);
00088
00089 count = LIST_Count(*buildingList);
00090 LIST_AddPointer(buildingList, _(building->name));
00091 buildingConstructionList[count] = building->tpl;
00092 }
00093
00098 static void B_SelectBase_f (void)
00099 {
00100 int baseID;
00101
00102 if (Cmd_Argc() < 2) {
00103 Com_Printf("Usage: %s <baseID>\n", Cmd_Argv(0));
00104 return;
00105 }
00106 baseID = atoi(Cmd_Argv(1));
00107
00108
00109
00110 if (baseID >= 0 && baseID < MAX_BASES) {
00111 const base_t *base = B_GetFoundedBaseByIDX(baseID);
00112
00113 if (base)
00114 B_SelectBase(base);
00115 } else if (baseID == CREATE_NEW_BASE_ID) {
00116
00117 B_SelectBase(NULL);
00118 }
00119 }
00120
00126 static void B_NextBase_f (void)
00127 {
00128 int baseID;
00129 const base_t *base = B_GetCurrentSelectedBase();
00130
00131 if (!base)
00132 return;
00133
00134 baseID = (base->idx + 1) % ccs.numBases;
00135 base = B_GetFoundedBaseByIDX(baseID);
00136 if (base)
00137 B_SelectBase(base);
00138 }
00139
00145 static void B_PrevBase_f (void)
00146 {
00147 int baseID;
00148 const base_t *base = B_GetCurrentSelectedBase();
00149
00150 if (!base)
00151 return;
00152
00153 baseID = base->idx;
00154 if (baseID > 0)
00155 baseID--;
00156 else
00157 baseID = ccs.numBases - 1;
00158
00159 base = B_GetFoundedBaseByIDX(baseID);
00160 if (base)
00161 B_SelectBase(base);
00162 }
00163
00167 static void B_SetBaseTitle_f (void)
00168 {
00169 if (ccs.numBases < MAX_BASES) {
00170 char baseName[MAX_VAR];
00171
00172 if (ccs.numBases > 0) {
00173 int j;
00174 int i = 2;
00175 do {
00176 j = 0;
00177 Com_sprintf(baseName, lengthof(baseName), _("Base #%i"), i);
00178 while (j <= ccs.numBases && strcmp(baseName, ccs.bases[j++].name));
00179 } while (i++ <= ccs.numBases && j <= ccs.numBases);
00180 } else {
00181 Q_strncpyz(baseName, _("Home"), lengthof(baseName));
00182 }
00183
00184 Cvar_Set("mn_base_title", baseName);
00185 } else {
00186 MS_AddNewMessage(_("Notice"), _("You've reached the base limit."), qfalse, MSG_STANDARD, NULL);
00187 UI_PopWindow(qfalse);
00188 }
00189 }
00190
00195 static void B_BuildBase_f (void)
00196 {
00197 const nation_t *nation;
00198 base_t *base = B_GetFirstUnfoundedBase();
00199 if (!base)
00200 return;
00201
00202 assert(!base->founded);
00203
00204 if (ccs.credits - ccs.curCampaign->basecost > 0) {
00205 const char *baseName = mn_base_title->string;
00206 if (baseName[0] == '\0')
00207 baseName = "Base";
00208
00209 Q_strncpyz(base->name, baseName, sizeof(base->name));
00210
00211 B_SetUpBase(base, newBasePos);
00212
00213 ccs.numBases++;
00214 ccs.campaignStats.basesBuilt++;
00215 ccs.mapAction = MA_NONE;
00216 CL_UpdateCredits(ccs.credits - ccs.curCampaign->basecost);
00217 nation = MAP_GetNation(base->pos);
00218 if (nation)
00219 Com_sprintf(cp_messageBuffer, sizeof(cp_messageBuffer), _("A new base has been built: %s (nation: %s)"), mn_base_title->string, _(nation->name));
00220 else
00221 Com_sprintf(cp_messageBuffer, sizeof(cp_messageBuffer), _("A new base has been built: %s"), mn_base_title->string);
00222 MS_AddNewMessage(_("Base built"), cp_messageBuffer, qfalse, MSG_CONSTRUCTION, NULL);
00223 B_ResetAllStatusAndCapacities(base, qtrue);
00224 AL_FillInContainment(base);
00225 PR_UpdateProductionCap(base);
00226
00227 B_UpdateBaseCount();
00228 B_SelectBase(base);
00229 } else {
00230 if (MAP_IsRadarOverlayActivated())
00231 MAP_SetOverlay("radar");
00232 if (ccs.mapAction == MA_NEWBASE)
00233 ccs.mapAction = MA_NONE;
00234
00235 CP_PopupList(_("Notice"), _("Not enough credits to set up a new base."));
00236 }
00237 }
00238
00244 static void B_ChangeBaseName_f (void)
00245 {
00246 base_t *base = B_GetCurrentSelectedBase();
00247
00248
00249 if (!base)
00250 return;
00251
00252 Q_strncpyz(base->name, Cvar_GetString("mn_base_title"), sizeof(base->name));
00253 }
00254
00260 static void B_ResetBuildingCurrent_f (void)
00261 {
00262 base_t *base = B_GetCurrentSelectedBase();
00263
00264 B_ResetBuildingCurrent(base);
00265 }
00266
00273 static void B_BaseInit_f (void)
00274 {
00275 base_t *base = B_GetCurrentSelectedBase();
00276
00277 if (!base)
00278 return;
00279
00280
00281 CL_UpdateCredits(ccs.credits);
00282
00283 Cvar_SetValue("mn_base_num_aircraft", LIST_Count(base->aircraft));
00284
00285
00286 if (AIR_AircraftAllowed(base)) {
00287 if (AIR_BaseHasAircraft(base))
00288 UI_ExecuteConfunc("update_basebutton aircraft false \"%s\"", _("Aircraft management and crew equipment"));
00289 else
00290 UI_ExecuteConfunc("update_basebutton aircraft true \"%s\"", _("Buy or produce at least one aircraft first."));
00291 } else {
00292 UI_ExecuteConfunc("update_basebutton aircraft true \"%s\"", _("No Hangar functional in base."));
00293 }
00294
00295 if (BS_BuySellAllowed(base))
00296 UI_ExecuteConfunc("update_basebutton buysell false \"%s\"", _("Buy/Sell equipment, aircraft and UGV"));
00297 else
00298 UI_ExecuteConfunc("update_basebutton buysell true \"%s\"", va(_("No %s functional in base."), _("Storage")));
00299
00300 if (ccs.numBases > 1)
00301 UI_ExecuteConfunc("update_basebutton transfer false \"%s\"", _("Transfer equipment, aircraft, UGV, aliens and employees to other bases"));
00302 else
00303 UI_ExecuteConfunc("update_basebutton transfer true \"%s\"", _("Build at least a second base to transfer equipment or personnel"));
00304
00305 if (RS_ResearchAllowed(base))
00306 UI_ExecuteConfunc("update_basebutton research false \"%s\"", _("Research new technology"));
00307 else
00308 UI_ExecuteConfunc("update_basebutton research true \"%s\"", va(_("No %s functional in base."), _("Laboratory")));
00309
00310 if (PR_ProductionAllowed(base))
00311 UI_ExecuteConfunc("update_basebutton production false \"%s\"", _("Produce equipment, aircraft and UGV"));
00312 else
00313 UI_ExecuteConfunc("update_basebutton production true \"%s\"", va(_("No %s functional in base."), _("Workshop")));
00314
00315 if (E_HireAllowed(base))
00316 UI_ExecuteConfunc("update_basebutton hire false \"%s\"", _("Hire or dismiss employees"));
00317 else
00318 UI_ExecuteConfunc("update_basebutton hire true \"%s\"", va(_("No %s functional in base."), _("Living Quarters")));
00319
00320 if (AC_ContainmentAllowed(base))
00321 UI_ExecuteConfunc("update_basebutton containment false \"%s\"", _("Manage captured aliens"));
00322 else
00323 UI_ExecuteConfunc("update_basebutton containment true \"%s\"", va(_("No %s functional in base."), _("Containment")));
00324
00325 if (HOS_HospitalAllowed(base))
00326 UI_ExecuteConfunc("update_basebutton hospital false \"%s\"", _("Treat wounded soldiers and perform implant surgery"));
00327 else
00328 UI_ExecuteConfunc("update_basebutton hospital true \"%s\"", va(_("No %s functional in base."), _("Hospital")));
00329 }
00330
00338 static void B_BuildingOnDestroy_f (void)
00339 {
00340 int baseIdx, buildingType;
00341 base_t *base;
00342
00343 if (Cmd_Argc() < 3) {
00344 Com_Printf("Usage: %s <baseIdx> <buildingType>\n", Cmd_Argv(0));
00345 return;
00346 }
00347
00348 buildingType = atoi(Cmd_Argv(2));
00349 if (buildingType < 0 || buildingType >= MAX_BUILDING_TYPE) {
00350 Com_Printf("B_BuildingOnDestroy_f: buildingType '%i' outside limits\n", buildingType);
00351 return;
00352 }
00353
00354 baseIdx = atoi(Cmd_Argv(1));
00355
00356 if (baseIdx < 0 || baseIdx >= MAX_BASES) {
00357 Com_Printf("B_BuildingOnDestroy_f: %i is outside bounds\n", baseIdx);
00358 return;
00359 }
00360
00361 base = B_GetFoundedBaseByIDX(baseIdx);
00362 if (base) {
00363 switch (buildingType) {
00364 case B_WORKSHOP:
00365 PR_UpdateProductionCap(base);
00366 break;
00367 case B_STORAGE:
00368 B_RemoveItemsExceedingCapacity(base);
00369 break;
00370 case B_ALIEN_CONTAINMENT:
00371 if (base->capacities[CAP_ALIENS].cur - base->capacities[CAP_ALIENS].max > 0)
00372 AL_RemoveAliens(base, NULL, (base->capacities[CAP_ALIENS].cur - base->capacities[CAP_ALIENS].max), AL_RESEARCH);
00373 break;
00374 case B_LAB:
00375 RS_RemoveScientistsExceedingCapacity(base);
00376 break;
00377 case B_HANGAR:
00378 case B_SMALL_HANGAR:
00379 B_RemoveAircraftExceedingCapacity(base, buildingType);
00380 break;
00381 case B_QUARTERS:
00382 E_DeleteEmployeesExceedingCapacity(base);
00383 break;
00384 default:
00385
00386
00387 break;
00388 }
00389 } else
00390 Com_Printf("B_BuildingOnDestroy_f: base %i is not founded\n", baseIdx);
00391 }
00392
00397 static void B_BuildingInit (base_t* base)
00398 {
00399 int i;
00400 linkedList_t *buildingList = NULL;
00401
00402
00403 if (!base)
00404 return;
00405
00406 for (i = 0; i < ccs.numBuildingTemplates; i++) {
00407 building_t *tpl = &ccs.buildingTemplates[i];
00408
00409
00410 if (tpl->visible) {
00411 const int numSameBuildings = B_GetNumberOfBuildingsInBaseByTemplate(base, tpl);
00412
00413 if (tpl->maxCount >= 0 && tpl->maxCount <= numSameBuildings)
00414 continue;
00415
00416 if (numSameBuildings >= BASE_SIZE * BASE_SIZE)
00417 continue;
00418
00419
00420 if (RS_IsResearched_ptr(tpl->tech))
00421 B_BuildingAddToList(&buildingList, tpl);
00422 }
00423 }
00424 if (base->buildingCurrent)
00425 B_DrawBuilding(base, base->buildingCurrent);
00426 else
00427 UI_ExecuteConfunc("mn_buildings_reset");
00428
00429 buildingNumber = LIST_Count(buildingList);
00430 UI_RegisterLinkedListText(TEXT_BUILDINGS, buildingList);
00431 }
00432
00436 static void B_BuildingInit_f (void)
00437 {
00438 base_t *base = B_GetCurrentSelectedBase();
00439
00440 if (!base)
00441 return;
00442
00443 B_BuildingInit(base);
00444 }
00445
00449 static void B_BuildingInfoClick_f (void)
00450 {
00451 base_t *base = B_GetCurrentSelectedBase();
00452
00453 if (!base)
00454 return;
00455
00456 if (base->buildingCurrent)
00457 UP_OpenWith(base->buildingCurrent->pedia);
00458 }
00459
00463 static void B_BuildingClick_f (void)
00464 {
00465 int num;
00466 building_t *building;
00467 base_t *base = B_GetCurrentSelectedBase();
00468
00469 if (!base)
00470 return;
00471
00472 if (Cmd_Argc() < 2) {
00473 Com_Printf("Usage: %s <building list index>\n", Cmd_Argv(0));
00474 return;
00475 }
00476
00477
00478 num = atoi(Cmd_Argv(1));
00479
00480 if (num > buildingNumber || num < 0) {
00481 Com_DPrintf(DEBUG_CLIENT, "B_BuildingClick_f: max exceeded %i/%i\n", num, buildingNumber);
00482 return;
00483 }
00484
00485 building = buildingConstructionList[num];
00486
00487 base->buildingCurrent = building;
00488 B_DrawBuilding(base, building);
00489
00490 ccs.baseAction = BA_NEWBUILDING;
00491 }
00492
00498 static void B_BuildingDestroy_f (void)
00499 {
00500 base_t *base = B_GetCurrentSelectedBase();
00501
00502 if (!base || !base->buildingCurrent)
00503 return;
00504
00505 B_BuildingDestroy(base, base->buildingCurrent);
00506
00507 B_ResetBuildingCurrent(base);
00508 B_BuildingInit(base);
00509 }
00510
00515 static void B_BuildingStatus_f (void)
00516 {
00517 base_t *base = B_GetCurrentSelectedBase();
00518
00519
00520 if (!base || !base->buildingCurrent)
00521 return;
00522
00523 B_BuildingStatus(base, base->buildingCurrent);
00524 }
00525
00531 static void B_AssembleMap_f (void)
00532 {
00533 const base_t* base;
00534
00535 if (Cmd_Argc() < 2) {
00536 Com_DPrintf(DEBUG_CLIENT, "Usage: %s <baseID>\n", Cmd_Argv(0));
00537 base = B_GetCurrentSelectedBase();
00538 } else {
00539 const int baseID = atoi(Cmd_Argv(1));
00540 base = B_GetBaseByIDX(baseID);
00541 }
00542
00543 B_AssembleMap(base);
00544 }
00545
00549 static void B_CheckBuildingStatusForMenu_f (void)
00550 {
00551 int num;
00552 const char *buildingID;
00553 building_t *building;
00554 base_t *base = B_GetCurrentSelectedBase();
00555
00556 if (Cmd_Argc() != 2) {
00557 Com_Printf("Usage: %s <buildingID>\n", Cmd_Argv(0));
00558 return;
00559 }
00560
00561 buildingID = Cmd_Argv(1);
00562 building = B_GetBuildingTemplate(buildingID);
00563
00564 if (!building || !base)
00565 return;
00566
00567
00568 if (base->baseStatus == BASE_UNDER_ATTACK) {
00569 UI_Popup(_("Notice"), _("Base is under attack, you can't access this building !"));
00570 return;
00571 }
00572
00573 if (building->buildingType == B_HANGAR) {
00574
00575 UI_Popup(_("Notice"), _("You need at least one Hangar (and its dependencies) to use aircraft."));
00576 return;
00577 }
00578
00579 num = B_GetNumberOfBuildingsInBaseByBuildingType(base, building->buildingType);
00580 if (num > 0) {
00581 int numUnderConstruction;
00582
00583 B_CheckBuildingTypeStatus(base, building->buildingType, B_STATUS_UNDER_CONSTRUCTION, &numUnderConstruction);
00584 if (numUnderConstruction == num) {
00585 int minDay = 99999;
00586 building_t *b = NULL;
00587
00588 while ((b = B_GetNextBuildingByType(base, b, building->buildingType))) {
00589 if (b->buildingStatus == B_STATUS_UNDER_CONSTRUCTION) {
00590 const int delta = b->buildTime - (ccs.date.day - b->timeStart);
00591 minDay = min(minDay, delta);
00592 }
00593 }
00594
00595 Com_sprintf(popupText, sizeof(popupText), ngettext("Construction of building will be over in %i day.\nPlease wait to enter.", "Construction of building will be over in %i days.\nPlease wait to enter.",
00596 minDay), minDay);
00597 UI_Popup(_("Notice"), popupText);
00598 return;
00599 }
00600
00601 if (!B_CheckBuildingDependencesStatus(base, building)) {
00602 building_t *dependenceBuilding = building->dependsBuilding;
00603 assert(building->dependsBuilding);
00604 if (B_GetNumberOfBuildingsInBaseByBuildingType(base, dependenceBuilding->buildingType) <= 0) {
00605
00606 Com_sprintf(popupText, sizeof(popupText), _("You need a building %s to make building %s functional."), _(dependenceBuilding->name), _(building->name));
00607 UI_Popup(_("Notice"), popupText);
00608 return;
00609 } else {
00610
00611
00612
00613 building_t *b = NULL;
00614
00615 while ((b = B_GetNextBuildingByType(base, b, dependenceBuilding->buildingType))) {
00616 if (b->buildTime > (ccs.date.day - b->timeStart)) {
00617 Com_sprintf(popupText, sizeof(popupText), _("Building %s is not finished yet, and is needed to use building %s."),
00618 _(dependenceBuilding->name), _(building->name));
00619 UI_Popup(_("Notice"), popupText);
00620 return;
00621 }
00622 }
00623
00624 Com_sprintf(popupText, sizeof(popupText), _("Make sure that the dependencies of building %s (%s) are operational, so that building %s may be used."),
00625 _(dependenceBuilding->name), _(dependenceBuilding->dependsBuilding->name), _(building->name));
00626 UI_Popup(_("Notice"), popupText);
00627 return;
00628 }
00629 }
00630
00631 if (building->buildingType == B_WORKSHOP && E_CountHired(base, EMPL_WORKER) <= 0) {
00632 Com_sprintf(popupText, sizeof(popupText), _("You need to recruit %s to use building %s."),
00633 E_GetEmployeeString(EMPL_WORKER), _(building->name));
00634 UI_Popup(_("Notice"), popupText);
00635 return;
00636 } else if (building->buildingType == B_LAB && E_CountHired(base, EMPL_SCIENTIST) <= 0) {
00637 Com_sprintf(popupText, sizeof(popupText), _("You need to recruit %s to use building %s."),
00638 E_GetEmployeeString(EMPL_SCIENTIST), _(building->name));
00639 UI_Popup(_("Notice"), popupText);
00640 return;
00641 }
00642 } else {
00643 Com_sprintf(popupText, sizeof(popupText), _("Build a %s first."), _(building->name));
00644 UI_Popup(_("Notice"), popupText);
00645 return;
00646 }
00647 }
00648
00655 static void BaseSummary_Init (const base_t *base)
00656 {
00657 static char textStatsBuffer[1024];
00658 static char textInfoBuffer[256];
00659 const aliensCont_t *containment = base->alienscont;
00660 int i;
00661
00662 baseCapacities_t cap;
00663 production_queue_t *queue;
00664 technology_t *tech;
00665 int tmp;
00666
00667
00668 textStatsBuffer[0] = textInfoBuffer[0] = 0;
00669
00670 Q_strcat(textInfoBuffer, _("^BAircraft\n"), sizeof(textInfoBuffer));
00671 for (i = 0; i <= MAX_HUMAN_AIRCRAFT_TYPE; i++)
00672 Q_strcat(textInfoBuffer, va("\t%s:\t\t\t\t%i\n", AIR_GetAircraftString(i),
00673 AIR_CountTypeInBase(base, i)), sizeof(textInfoBuffer));
00674
00675 Q_strcat(textInfoBuffer, "\n", sizeof(textInfoBuffer));
00676
00677 Q_strcat(textInfoBuffer, _("^BEmployees\n"), sizeof(textInfoBuffer));
00678 for (i = 0; i < MAX_EMPL; i++) {
00679 tmp = E_CountHired(base, i);
00680 Q_strcat(textInfoBuffer, va("\t%s:\t\t\t\t%i\n", E_GetEmployeeString(i), tmp), sizeof(textInfoBuffer));
00681 }
00682
00683 Q_strcat(textInfoBuffer, "\n", sizeof(textInfoBuffer));
00684
00685 Q_strcat(textInfoBuffer, _("^BAliens\n"), sizeof(textInfoBuffer));
00686 for (i = 0; i < ccs.numAliensTD; i++) {
00687 if (!containment[i].amountAlive && !containment[i].amountDead)
00688 continue;
00689 Q_strcat(textInfoBuffer, va("\t%s:\t\t\t\t%i/%i\n",
00690 _(containment[i].teamDef->name), containment[i].amountAlive,
00691 containment[i].amountDead), sizeof(textInfoBuffer));
00692 }
00693
00694
00695 UI_RegisterText(TEXT_STANDARD, textInfoBuffer);
00696
00697 Q_strcat(textStatsBuffer, _("^BBuildings\t\t\t\t\t\tCapacity\t\t\t\tAmount\n"), sizeof(textStatsBuffer));
00698 for (i = 0; i < ccs.numBuildingTemplates; i++) {
00699 const building_t* b = &ccs.buildingTemplates[i];
00700
00701
00702 if (!RS_IsResearched_ptr(b->tech))
00703 continue;
00704
00705 cap = B_GetCapacityFromBuildingType(b->buildingType);
00706 if (cap == MAX_CAP)
00707 continue;
00708
00709 if (!B_GetNumberOfBuildingsInBaseByBuildingType(base, b->buildingType))
00710 continue;
00711
00712
00713 if (B_GetBuildingStatus(base, b->buildingType)) {
00714 Q_strcat(textStatsBuffer, va("%s:\t\t\t\t\t\t%i/%i", _(b->name),
00715 base->capacities[cap].cur, base->capacities[cap].max), sizeof(textStatsBuffer));
00716 } else {
00717 if (b->buildingStatus == B_STATUS_UNDER_CONSTRUCTION) {
00718 const int daysLeft = b->timeStart + b->buildTime - ccs.date.day;
00719
00720 assert(daysLeft);
00721 Q_strcat(textStatsBuffer, va("%s:\t\t\t\t\t\t%i %s", _(b->name), daysLeft, ngettext("day", "days", daysLeft)), sizeof(textStatsBuffer));
00722 } else {
00723 Q_strcat(textStatsBuffer, va("%s:\t\t\t\t\t\t%i/%i", _(b->name), base->capacities[cap].cur, 0), sizeof(textStatsBuffer));
00724 }
00725 }
00726 Q_strcat(textStatsBuffer, va("\t\t\t\t%i\n", B_GetNumberOfBuildingsInBaseByBuildingType(base, b->buildingType)), sizeof(textStatsBuffer));
00727 }
00728
00729 Q_strcat(textStatsBuffer, "\n", sizeof(textStatsBuffer));
00730
00731 Q_strcat(textStatsBuffer, _("^BProduction\t\t\t\t\t\tQuantity\t\t\t\tPercent\n"), sizeof(textStatsBuffer));
00732 queue = &ccs.productions[base->idx];
00733 if (queue->numItems > 0) {
00734 for (i = 0; i < queue->numItems; i++) {
00735 const production_t *production = &queue->items[i];
00736 const objDef_t *objDef = production->item;
00737 const aircraft_t *aircraft = production->aircraft;
00738 const storedUFO_t *ufo = production->ufo;
00739 const char *name;
00740
00741 if (objDef)
00742 name = _(objDef->name);
00743 else if (aircraft)
00744 name = _(aircraft->tpl->name);
00745 else if (ufo)
00746 name = UFO_TypeToName(ufo->ufoTemplate->ufotype);
00747 else
00748 Com_Error(ERR_DROP, "BaseSummary_Init: Invalid production type (not item, not aircraft, not disassembly)\n");
00749
00751 Q_strcat(textStatsBuffer, va(_("%s\t\t\t\t\t\t%d\t\t\t\t%.2f%%\n"), name,
00752 production->amount, production->percentDone * 100), sizeof(textStatsBuffer));
00753 }
00754 } else {
00755 Q_strcat(textStatsBuffer, _("Nothing\n"), sizeof(textStatsBuffer));
00756 }
00757
00758 Q_strcat(textStatsBuffer, "\n", sizeof(textStatsBuffer));
00759
00760 Q_strcat(textStatsBuffer, _("^BResearch\t\t\t\t\t\tScientists\t\t\t\tPercent\n"), sizeof(textStatsBuffer));
00761 tmp = 0;
00762 for (i = 0; i < ccs.numTechnologies; i++) {
00763 tech = RS_GetTechByIDX(i);
00764 if (tech->base == base && (tech->statusResearch == RS_RUNNING || tech->statusResearch == RS_PAUSED)) {
00765 Q_strcat(textStatsBuffer, va(_("%s\t\t\t\t\t\t%d\t\t\t\t%1.2f%%\n"), _(tech->name),
00766 tech->scientists, (1 - tech->time / tech->overallTime) * 100), sizeof(textStatsBuffer));
00767 tmp++;
00768 }
00769 }
00770 if (!tmp)
00771 Q_strcat(textStatsBuffer, _("Nothing\n"), sizeof(textStatsBuffer));
00772
00773
00774 UI_RegisterText(TEXT_STATS_BASESUMMARY, textStatsBuffer);
00775 }
00776
00780 static void BaseSummary_SelectBase_f (void)
00781 {
00782 const base_t *base;
00783
00784 if (Cmd_Argc() >= 2) {
00785 int i = atoi(Cmd_Argv(1));
00786
00787 if (i < 0 || i >= ccs.numBases) {
00788 Com_Printf("Usage: %s [baseIdx]\nWithout baseIdx the current base is selected.\n", Cmd_Argv(0));
00789 return;
00790 }
00791 base = B_GetFoundedBaseByIDX(i);
00792 } else {
00793 base = B_GetCurrentSelectedBase();
00794 }
00795
00796 if (base != NULL) {
00797 BaseSummary_Init(base);
00798 UI_ExecuteConfunc("basesummary_change_color %i", base->idx);
00799 }
00800 }
00801
00806 static void B_MakeBaseMapShot_f (void)
00807 {
00808 if (!Com_ServerState()) {
00809 Com_Printf("Load the base map before you try to use this function\n");
00810 return;
00811 }
00812
00813 Cmd_ExecuteString(va("camsetangles %i %i", 60, 90));
00814 Cvar_SetValue("r_isometric", 1);
00815
00816 Cvar_SetValue("cl_worldlevel", 1);
00817 UI_PushWindow("nohud", NULL);
00818
00819 Cmd_ExecuteString("toggleconsole");
00820 Cmd_ExecuteString("r_screenshot tga");
00821 }
00822
00826 void B_InitCallbacks (void)
00827 {
00828 mn_base_title = Cvar_Get("mn_base_title", "", 0, NULL);
00829 cl_start_buildings = Cvar_Get("cl_start_buildings", "1", CVAR_ARCHIVE, "Start with initial buildings in your first base");
00830 Cvar_Set("mn_base_cost", va(_("%i c"), ccs.curCampaign->basecost));
00831 Cvar_SetValue("mn_base_count", ccs.numBases);
00832 Cvar_SetValue("mn_base_max", MAX_BASES);
00833
00834 Cmd_AddCommand("basemapshot", B_MakeBaseMapShot_f, "Command to make a screenshot for the baseview with the correct angles");
00835 Cmd_AddCommand("mn_base_prev", B_PrevBase_f, "Go to the previous base");
00836 Cmd_AddCommand("mn_base_next", B_NextBase_f, "Go to the next base");
00837 Cmd_AddCommand("mn_base_select", B_SelectBase_f, "Select a founded base by index");
00838 Cmd_AddCommand("mn_base_build", B_BuildBase_f, NULL);
00839 Cmd_AddCommand("mn_set_base_title", B_SetBaseTitle_f, NULL);
00840 Cmd_AddCommand("base_changename", B_ChangeBaseName_f, "Called after editing the cvar base name");
00841 Cmd_AddCommand("base_init", B_BaseInit_f, NULL);
00842 Cmd_AddCommand("base_assemble", B_AssembleMap_f, "Called to assemble the current selected base");
00843 Cmd_AddCommand("building_init", B_BuildingInit_f, NULL);
00844 Cmd_AddCommand("building_status", B_BuildingStatus_f, NULL);
00845 Cmd_AddCommand("building_destroy", B_BuildingDestroy_f, "Function to destroy a building (select via right click in baseview first)");
00846 Cmd_AddCommand("building_amdestroy", B_Destroy_AntimaterStorage_f, "Function called if antimatter storage destroyed");
00847 Cmd_AddCommand("building_ufopedia", B_BuildingInfoClick_f, "Opens the UFOpedia for the current selected building");
00848 Cmd_AddCommand("check_building_status", B_CheckBuildingStatusForMenu_f, "Create a popup to inform player why he can't use a button");
00849 Cmd_AddCommand("buildings_click", B_BuildingClick_f, "Opens the building information window in construction mode");
00850 Cmd_AddCommand("reset_building_current", B_ResetBuildingCurrent_f, NULL);
00851 Cmd_AddCommand("building_ondestroy", B_BuildingOnDestroy_f, "Destroy a building");
00852 Cmd_AddCommand("basesummary_selectbase", BaseSummary_SelectBase_f, "Opens Base Statistics menu in base");
00853 }
00854
00856 void B_ShutdownCallbacks (void)
00857 {
00858 Cmd_RemoveCommand("basemapshot");
00859 Cmd_RemoveCommand("basesummary_selectbase");
00860 Cmd_RemoveCommand("mn_base_prev");
00861 Cmd_RemoveCommand("mn_base_next");
00862 Cmd_RemoveCommand("mn_base_select");
00863 Cmd_RemoveCommand("mn_base_build");
00864 Cmd_RemoveCommand("base_changename");
00865 Cmd_RemoveCommand("mn_set_base_title");
00866 Cmd_RemoveCommand("base_init");
00867 Cmd_RemoveCommand("base_assemble");
00868 Cmd_RemoveCommand("building_init");
00869 Cmd_RemoveCommand("building_status");
00870 Cmd_RemoveCommand("building_destroy");
00871 Cmd_RemoveCommand("building_ufopedia");
00872 Cmd_RemoveCommand("check_building_status");
00873 Cmd_RemoveCommand("buildings_click");
00874 Cmd_RemoveCommand("reset_building_current");
00875 Cmd_RemoveCommand("building_ondestroy");
00876 Cvar_Delete("mn_base_max");
00877 Cvar_Delete("mn_base_cost");
00878 Cvar_Delete("mn_base_title");
00879 Cvar_Delete("mn_base_count");
00880 }