cp_base_callbacks.c

Go to the documentation of this file.
00001 
00006 /*
00007 Copyright (C) 2002-2010 UFO: Alien Invasion.
00008 
00009 This program is free software; you can redistribute it and/or
00010 modify it under the terms of the GNU General Public License
00011 as published by the Free Software Foundation; either version 2
00012 of the License, or (at your option) any later version.
00013 
00014 This program is distributed in the hope that it will be useful,
00015 but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00017 
00018 See the GNU General Public License for more details.
00019 
00020 You should have received a copy of the GNU General Public License
00021 along with this program; if not, write to the Free Software
00022 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
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     /* check against MAX_BASES here! - only -1 will create a new base
00108      * if we would check against ccs.numBases here, a click on the base summary
00109      * base nodes would try to select unfounded bases */
00110     if (baseID >= 0 && baseID < MAX_BASES) {
00111         const base_t *base = B_GetFoundedBaseByIDX(baseID);
00112         /* don't create a new base if the index was valid */
00113         if (base)
00114             B_SelectBase(base);
00115     } else if (baseID == CREATE_NEW_BASE_ID) {
00116         /* create a new base */
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);       /* remove the new base popup */
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         /* set up the base with buildings from template */
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     /* maybe called without base initialized or active */
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     /* make sure the credits cvar is up-to-date */
00281     CL_UpdateCredits(ccs.credits);
00282 
00283     Cvar_SetValue("mn_base_num_aircraft", LIST_Count(base->aircraft));
00284 
00285     /* activate or deactivate the aircraft button */
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: /* the Dropship 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             /* handled in a seperate function, or number of buildings have no impact
00386              * on how the building works */
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     /* maybe someone call this command before the bases are parsed?? */
00403     if (!base)
00404         return;
00405 
00406     for (i = 0; i < ccs.numBuildingTemplates; i++) {
00407         building_t *tpl = &ccs.buildingTemplates[i];
00408         /* make an entry in list for this building */
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             /* skip if limit of BASE_SIZE*BASE_SIZE exceeded */
00416             if (numSameBuildings >= BASE_SIZE * BASE_SIZE)
00417                 continue;
00418 
00419             /* if the building is researched add it to the list */
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     /* which building? */
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     /* maybe someone called this command before the buildings are parsed?? */
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     /* Maybe base is under attack ? */
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         /* this is an exception because you must have a small or large hangar to enter aircraft menu */
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         /* maybe all buildings of this type are under construction ? */
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                 /* the dependence of the building is not built */
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                 /* maybe the dependence of the building is under construction
00611                  * note that we can't use B_STATUS_UNDER_CONSTRUCTION here, because this value
00612                  * is not use for every building (for exemple Command Centre) */
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                 /* the dependence is built but doesn't work - must be because of their dependendes */
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         /* all buildings are OK: employees must be missing */
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     /* wipe away old buffers */
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     /* link into the menu */
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         /* only show already researched buildings */
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         /* Check if building is functional (see comments in B_UpdateBaseCapacities) */
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                 /* if there is no day left the status should not be B_STATUS_UNDER_CONSTRUCTION */
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     /* link into the menu */
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     /* we are interested in the second level only */
00816     Cvar_SetValue("cl_worldlevel", 1);
00817     UI_PushWindow("nohud", NULL);
00818     /* hide any active console */
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 }

Generated by  doxygen 1.6.2