cp_transfer_callbacks.c

Go to the documentation of this file.
00001 
00005 /*
00006 Copyright (C) 2002-2010 UFO: Alien Invasion.
00007 
00008 This program is free software; you can redistribute it and/or
00009 modify it under the terms of the GNU General Public License
00010 as published by the Free Software Foundation; either version 2
00011 of the License, or (at your option) any later version.
00012 
00013 This program is distributed in the hope that it will be useful,
00014 but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00016 
00017 See the GNU General Public License for more details.
00018 
00019 You should have received a copy of the GNU General Public License
00020 along with this program; if not, write to the Free Software
00021 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00022 
00023 */
00024 
00025 #include "../cl_shared.h"
00026 #include "cp_campaign.h"
00027 #include "cp_transfer_callbacks.h"
00028 #include "cp_transfer.h"
00029 #include "../ui/ui_main.h"
00030 #include "../ui/ui_popup.h"
00031 #include "../ui/ui_data.h"
00032 
00036 static const char* transferTypeIDs[] = {
00037     "item",
00038     "employee",
00039     "alien",
00040     "aircraft"
00041 };
00042 CASSERT(lengthof(transferTypeIDs) == TRANS_TYPE_MAX);
00043 
00045 static transferData_t td;
00046 
00048 static const int MAX_TR_FACTORS = 500;
00050 static const int MAX_TRANSLIST_MENU_ENTRIES = 21;
00051 
00056 static int TR_CountStunnedAliensInCargo (const aircraft_t *transferAircraft)
00057 {
00058     int stunnedAliens = 0;
00059     const aliensTmp_t *cargo = AL_GetAircraftAlienCargo(transferAircraft);
00060 
00061     if (cargo) {
00062         int i;
00063         for (i = 0; i < MAX_CARGO; i++)
00064             stunnedAliens += cargo[i].amountAlive;
00065     }
00066     return stunnedAliens;
00067 }
00068 
00074 static void TR_TransferBaseListClick_f (void)
00075 {
00076     int num;
00077     base_t *base;
00078 
00079     assert(td.transferStartAircraft);
00080 
00081     if (Cmd_Argc() < 2) {
00082         Com_Printf("Usage: %s <base index>\n", Cmd_Argv(0));
00083         return;
00084     }
00085 
00086     num = atoi(Cmd_Argv(1));
00087     base = B_GetFoundedBaseByIDX(num);
00088     if (!base) {
00089         Com_Printf("TR_TransferBaseListClick_f: baseIdx %i doesn't exist.\n", num);
00090         return;
00091     }
00092 
00093     TR_TransferAlienAfterMissionStart(base, td.transferStartAircraft);
00094 }
00095 
00100 static void TR_TransferAliensFromMission_f (void)
00101 {
00102     const vec4_t green = {0.0f, 1.0f, 0.0f, 0.8f};
00103     const vec4_t yellow = {1.0f, 0.874f, 0.294f, 1.0f};
00104     const vec4_t red = {1.0f, 0.0f, 0.0f, 0.8f};
00105     int i;
00106     aircraft_t *aircraft;
00107     int stunnedAliens;
00108     uiNode_t *baseList = NULL;
00109 
00110     if (Cmd_Argc() < 2) {
00111         Com_Printf("Usage: %s <aircraft index>\n", Cmd_Argv(0));
00112         return;
00113     }
00114 
00115     i = atoi(Cmd_Argv(1));
00116     aircraft = AIR_AircraftGetFromIDX(i);
00117     if (!aircraft) {
00118         Com_Printf("Usage: No aircraft with index %i\n", i);
00119         return;
00120     }
00121 
00122     stunnedAliens = TR_CountStunnedAliensInCargo(aircraft);
00123 
00124     /* store the aircraft to be able to remove alien bodies */
00125     td.transferStartAircraft = aircraft;
00126 
00127     for (i = 0; i < ccs.numBases; i++) {
00128         base_t *base = B_GetFoundedBaseByIDX(i);
00129         const char* string;
00130         uiNode_t *option;
00131         int freeSpace;
00132 
00133         if (!base)
00134             continue;
00135         if (!AC_ContainmentAllowed(base))
00136             continue;
00137         freeSpace = B_FreeCapacity(base, CAP_ALIENS);
00138 
00139         string = va(ngettext("(can host %i live alien)", "(can host %i live aliens)", freeSpace), freeSpace);
00140         string = va("%s %s", base->name, string);
00141         option = UI_AddOption(&baseList, va("base%i", base->idx), string, va("%i", base->idx));
00142 
00144         if (freeSpace >= stunnedAliens) {
00145             Vector4Copy(green, option->color);
00146             /* option->tooltip = _("Has free space for all captured aliens."); */
00147         } else if (freeSpace > 0) {
00148             Vector4Copy(yellow, option->color);
00149             /* option->tooltip = _("Has free space for some captured aliens, others will die."); */
00150         } else {
00151             Vector4Copy(red, option->color);
00152             /* option->tooltip = _("Doesn't have free space captured aliens, only dead ones can be stored."); */
00153         }
00154     }
00155 
00156     if (baseList != NULL){
00157         UI_RegisterOption(OPTION_BASELIST, baseList);
00158         UI_PushWindow("popup_transferbaselist", NULL);
00159     } else {
00161         Com_Printf("TR_TransferAliensFromMission_f: No base with alien containment available.\n");
00162     }
00163 }
00164 
00170 static void TR_TransferStart_f (void)
00171 {
00172     char message[1024];
00173     base_t *base = B_GetCurrentSelectedBase();
00174 
00175     if (td.currentTransferType == TRANS_TYPE_INVALID) {
00176         Com_Printf("TR_TransferStart_f: currentTransferType is wrong!\n");
00177         return;
00178     }
00179     TR_TransferStart(base, &td);
00180 
00181     /* Clear temporary cargo arrays. */
00182     memset(td.trItemsTmp, 0, sizeof(td.trItemsTmp));
00183     memset(td.trAliensTmp, 0, sizeof(td.trAliensTmp));
00184     memset(td.trEmployeesTmp, 0, sizeof(td.trEmployeesTmp));
00185     memset(td.trAircraftsTmp, TRANS_LIST_EMPTY_SLOT, sizeof(td.trAircraftsTmp));
00186 
00187     Com_sprintf(message, sizeof(message), _("Transport mission started, cargo is being transported to %s"), td.transferBase->name);
00188     MSO_CheckAddNewMessage(NT_TRANSFER_STARTED, _("Transport mission"), message, qfalse, MSG_TRANSFERFINISHED, NULL);
00189     UI_PopWindow(qfalse);
00190 }
00191 
00192 
00198 static transferType_t TR_GetTransferType (const char *id)
00199 {
00200     int i;
00201     for (i = 0; i < TRANS_TYPE_MAX; i++) {
00202         if (!strcmp(transferTypeIDs[i], id))
00203             return i;
00204     }
00205     return TRANS_TYPE_INVALID;
00206 }
00207 
00215 static int TR_CheckItem (const objDef_t *od, const base_t *destbase, int amount)
00216 {
00217     int i;
00218     int intransfer = 0;
00219     int amtransfer = 0;
00220 
00221     assert(od);
00222     assert(destbase);
00223 
00224     /* Count size of all items already on the transfer list. */
00225     for (i = 0; i < csi.numODs; i++) {
00226         const objDef_t *object = INVSH_GetItemByIDX(i);
00227         if (td.trItemsTmp[i] > 0) {
00228             if (!strcmp(object->id, ANTIMATTER_TECH_ID))
00229                 amtransfer = td.trItemsTmp[i];
00230             else
00231                 intransfer += object->size * td.trItemsTmp[i];
00232         }
00233     }
00234 
00235     /* Is this antimatter and destination base has enough space in Antimatter Storage? */
00236     if (!strcmp(od->id, ANTIMATTER_TECH_ID)) {
00237         /* Give some meaningful feedback to the player if the player clicks on an a.m. item but base doesn't have am storage. */
00238         if (!B_GetBuildingStatus(destbase, B_ANTIMATTER)) {
00239             UI_Popup(_("Missing storage"), _("Destination base does not have an Antimatter Storage.\n"));
00240             return 0;
00241         }
00242         amount = min(amount, B_FreeCapacity(destbase, CAP_ANTIMATTER) - amtransfer);
00243         if (amount <= 0) {
00244             UI_Popup(_("Not enough space"), _("Destination base does not have enough\nAntimatter Storage space to store more antimatter.\n"));
00245             return 0;
00246         }
00247     } else {    /*This is not antimatter */
00248         if (!B_GetBuildingStatus(destbase, B_STORAGE))  /* Return if the target base doesn't have storage or power. */
00249             return 0;
00250 
00251         /* Does the destination base has enough space in storage? */
00252         amount = min(amount, destbase->capacities[CAP_ITEMS].max - destbase->capacities[CAP_ITEMS].cur - intransfer / od->size);
00253         if (amount <= 0) {
00254             UI_Popup(_("Not enough space"), _("Destination base does not have enough\nStorage space to store this item.\n"));
00255             return 0;
00256         }
00257     }
00258 
00259     return amount;
00260 }
00261 
00268 static qboolean TR_CheckEmployee (const employee_t *employee, const base_t *destbase)
00269 {
00270     int i, intransfer = 0;
00271     employeeType_t emplType;
00272 
00273     assert(employee && destbase);
00274 
00275     /* Count amount of all employees already on the transfer list. */
00276     for (emplType = 0; emplType < MAX_EMPL; emplType++) {
00277         for (i = 0; i < ccs.numEmployees[emplType]; i++) {
00278             if (td.trEmployeesTmp[emplType][i])
00279                 intransfer++;
00280         }
00281     }
00282 
00283     /* Does the destination base has enough space in living quarters? */
00284     if (destbase->capacities[CAP_EMPLOYEES].max - destbase->capacities[CAP_EMPLOYEES].cur - intransfer < 1) {
00285         UI_Popup(_("Not enough space"), _("Destination base does not have enough space\nin Living Quarters.\n"));
00286         return qfalse;
00287     }
00288 
00289     switch (employee->type) {
00290     case EMPL_SOLDIER:
00291         /* Is this a soldier assigned to aircraft? */
00292         if (AIR_IsEmployeeInAircraft(employee, NULL)) {
00293             const rank_t *rank = CL_GetRankByIdx(employee->chr.score.rank);
00294             Com_sprintf(popupText, sizeof(popupText), _("%s %s is assigned to aircraft and cannot be\ntransfered to another base.\n"),
00295                 _(rank->shortname), employee->chr.name);
00296             UI_Popup(_("Soldier in aircraft"), popupText);
00297             return qfalse;
00298         }
00299         break;
00300     case EMPL_PILOT:
00301         /* Is this a pilot assigned to aircraft? */
00302         if (AIR_IsEmployeeInAircraft(employee, NULL)) {
00303             Com_sprintf(popupText, sizeof(popupText), _("%s is assigned to aircraft and cannot be\ntransfered to another base.\n"),
00304                 employee->chr.name);
00305             UI_Popup(_("Pilot in aircraft"), popupText);
00306             return qfalse;
00307         }
00308         break;
00309     default:
00310         break;
00311     }
00312 
00313     return qtrue;
00314 }
00315 
00322 static qboolean TR_CheckAlien (base_t *destbase)
00323 {
00324     int i, intransfer = 0;
00325 
00326     assert(destbase);
00327 
00328     /* Count amount of live aliens already on the transfer list. */
00329     for (i = 0; i < ccs.numAliensTD; i++) {
00330         if (td.trAliensTmp[i][TRANS_ALIEN_ALIVE] > 0)
00331             intransfer += td.trAliensTmp[i][TRANS_ALIEN_ALIVE];
00332     }
00333 
00334     /* add the alien we are trying to transfer */
00335     intransfer++;
00336 
00337     /* Does the destination base has enough space in alien containment? */
00338     if (!AL_CheckAliveFreeSpace(destbase, NULL, intransfer)) {
00339         UI_Popup(_("Not enough space"), _("Destination base does not have enough space\nin Alien Containment.\n"));
00340         return qfalse;
00341     }
00342 
00343     return qtrue;
00344 }
00345 
00352 static qboolean TR_CheckAircraft (const aircraft_t *aircraft, const base_t *destbase)
00353 {
00354     int i, hangarStorage, numAircraftTransfer = 0;
00355     assert(aircraft);
00356     assert(destbase);
00357 
00358     /* Count weight and number of all aircraft already on the transfer list that goes
00359      * into the same hangar type than aircraft. */
00360     for (i = 0; i < ccs.numAircraft; i++)
00361         if (td.trAircraftsTmp[i] > TRANS_LIST_EMPTY_SLOT) {
00362             const aircraft_t *aircraftTemp = AIR_AircraftGetFromIDX(i);
00363             assert(aircraftTemp);
00364             if (aircraftTemp->size == aircraft->size)
00365                 numAircraftTransfer++;
00366         }
00367 
00368     /* Hangars in destbase functional? */
00369     if (!B_GetBuildingStatus(destbase, B_POWER)) {
00370         UI_Popup(_("Hangars not ready"), _("Destination base does not have hangars ready.\nProvide power supplies.\n"));
00371         return qfalse;
00372     } else if (!B_GetBuildingStatus(destbase, B_COMMAND)) {
00373         UI_Popup(_("Hangars not ready"), _("Destination base does not have command centre.\nHangars not functional.\n"));
00374         return qfalse;
00375     } else if (!B_GetBuildingStatus(destbase, B_HANGAR) && !B_GetBuildingStatus(destbase, B_SMALL_HANGAR)) {
00376         UI_Popup(_("Hangars not ready"), _("Destination base does not have any hangar."));
00377         return qfalse;
00378     }
00379     /* Is there a place for this aircraft in destination base? */
00380     hangarStorage = AIR_CalculateHangarStorage(aircraft->tpl, destbase, numAircraftTransfer);
00381     if (hangarStorage == 0) {
00382         UI_Popup(_("Not enough space"), _("Destination base does not have enough space in hangars.\n"));
00383         return qfalse;
00384     } else if (hangarStorage > 0) {
00385         return qtrue;
00386     }
00387 
00388     return qtrue;
00389 }
00390 
00394 static void TR_CargoList (void)
00395 {
00396     int i = 0;
00397     employeeType_t emplType;
00398     int trempl[MAX_EMPL];
00399     linkedList_t *cargoList = NULL;
00400     linkedList_t *cargoListAmount = NULL;
00401     char str[128];
00402 
00403     td.trCargoCountTmp = 0;
00404     memset(td.cargo, 0, sizeof(td.cargo));
00405     memset(trempl, 0, sizeof(trempl));
00406 
00407     /* Show items. */
00408     for (i = 0; i < csi.numODs; i++) {
00409         const objDef_t *od = INVSH_GetItemByIDX(i);
00410         if (td.trItemsTmp[i] > 0) {
00411             LIST_AddString(&cargoList, _(od->name));
00412             LIST_AddString(&cargoListAmount, va("%i", td.trItemsTmp[i]));
00413             td.cargo[td.trCargoCountTmp].type = CARGO_TYPE_ITEM;
00414             td.cargo[td.trCargoCountTmp].itemidx = i;
00415             td.trCargoCountTmp++;
00416             if (td.trCargoCountTmp >= MAX_CARGO) {
00417                 Com_DPrintf(DEBUG_CLIENT, "TR_CargoList: Cargo is full\n");
00418                 break;
00419             }
00420         }
00421     }
00422 
00423     /* Show employees. */
00424     for (emplType = 0; emplType < MAX_EMPL; emplType++) {
00425         for (i = 0; i < ccs.numEmployees[emplType]; i++) {
00426             if (td.trEmployeesTmp[emplType][i]) {
00427                 if (emplType == EMPL_SOLDIER || emplType == EMPL_PILOT) {
00428                     const employee_t *employee = td.trEmployeesTmp[emplType][i];
00429                     if (emplType == EMPL_SOLDIER) {
00430                         const rank_t *rank = CL_GetRankByIdx(employee->chr.score.rank);
00431                         Com_sprintf(str, lengthof(str), _("Soldier %s %s"), _(rank->shortname), employee->chr.name);
00432                     } else
00433                         Com_sprintf(str, lengthof(str), _("Pilot %s"), employee->chr.name);
00434                     LIST_AddString(&cargoList, str);
00435                     LIST_AddString(&cargoListAmount, "1");
00436                     td.cargo[td.trCargoCountTmp].type = CARGO_TYPE_EMPLOYEE;
00437                     td.cargo[td.trCargoCountTmp].itemidx = employee->idx;
00438                     td.trCargoCountTmp++;
00439                     if (td.trCargoCountTmp >= MAX_CARGO) {
00440                         Com_DPrintf(DEBUG_CLIENT, "TR_CargoList: Cargo is full\n");
00441                         break;
00442                     }
00443                 }
00444                 trempl[emplType]++;
00445             }
00446         }
00447     }
00448     for (emplType = 0; emplType < MAX_EMPL; emplType++) {
00449         if (emplType == EMPL_SOLDIER || emplType == EMPL_PILOT)
00450             continue;
00451         if (trempl[emplType] > 0) {
00452             LIST_AddString(&cargoList, E_GetEmployeeString(emplType));
00453             LIST_AddString(&cargoListAmount, va("%i", trempl[emplType]));
00454             td.cargo[td.trCargoCountTmp].type = CARGO_TYPE_EMPLOYEE;
00455             td.trCargoCountTmp++;
00456             if (td.trCargoCountTmp >= MAX_CARGO) {
00457                 Com_DPrintf(DEBUG_CLIENT, "TR_CargoList: Cargo is full\n");
00458                 break;
00459             }
00460         }
00461     }
00462 
00463     /* Show aliens. */
00464     for (i = 0; i < ccs.numAliensTD; i++) {
00465         if (td.trAliensTmp[i][TRANS_ALIEN_DEAD] > 0) {
00466             Com_sprintf(str, sizeof(str), _("Corpse of %s"),
00467                 _(AL_AlienTypeToName(AL_GetAlienGlobalIDX(i))));
00468             LIST_AddString(&cargoList, str);
00469             LIST_AddString(&cargoListAmount, va("%i", td.trAliensTmp[i][TRANS_ALIEN_DEAD]));
00470             td.cargo[td.trCargoCountTmp].type = CARGO_TYPE_ALIEN_DEAD;
00471             td.cargo[td.trCargoCountTmp].itemidx = i;
00472             td.trCargoCountTmp++;
00473             if (td.trCargoCountTmp >= MAX_CARGO) {
00474                 Com_DPrintf(DEBUG_CLIENT, "TR_CargoList: Cargo is full\n");
00475                 break;
00476             }
00477         }
00478     }
00479     for (i = 0; i < ccs.numAliensTD; i++) {
00480         if (td.trAliensTmp[i][TRANS_ALIEN_ALIVE] > 0) {
00481             LIST_AddString(&cargoList, _(AL_AlienTypeToName(AL_GetAlienGlobalIDX(i))));
00482             LIST_AddString(&cargoListAmount, va("%i", td.trAliensTmp[i][TRANS_ALIEN_ALIVE]));
00483             td.cargo[td.trCargoCountTmp].type = CARGO_TYPE_ALIEN_ALIVE;
00484             td.cargo[td.trCargoCountTmp].itemidx = i;
00485             td.trCargoCountTmp++;
00486             if (td.trCargoCountTmp >= MAX_CARGO) {
00487                 Com_DPrintf(DEBUG_CLIENT, "TR_CargoList: Cargo is full\n");
00488                 break;
00489             }
00490         }
00491     }
00492 
00493     /* Show all aircraft. */
00494     for (i = 0; i < ccs.numAircraft; i++) {
00495         if (td.trAircraftsTmp[i] > TRANS_LIST_EMPTY_SLOT) {
00496             aircraft_t *aircraft = AIR_AircraftGetFromIDX(td.trAircraftsTmp[i]);
00497             assert(aircraft);
00498             Com_sprintf(str, lengthof(str), _("Aircraft %s"), aircraft->name);
00499             LIST_AddString(&cargoList, str);
00500             LIST_AddString(&cargoListAmount, "1");
00501             td.cargo[td.trCargoCountTmp].type = CARGO_TYPE_AIRCRAFT;
00502             td.cargo[td.trCargoCountTmp].itemidx = i;
00503             td.trCargoCountTmp++;
00504             if (td.trCargoCountTmp >= MAX_CARGO) {
00505                 Com_DPrintf(DEBUG_CLIENT, "TR_CargoList: Cargo is full\n");
00506                 break;
00507             }
00508         }
00509     }
00510 
00511     UI_RegisterLinkedListText(TEXT_CARGO_LIST, cargoList);
00512     UI_RegisterLinkedListText(TEXT_CARGO_LIST_AMOUNT, cargoListAmount);
00513 }
00514 
00520 static qboolean TR_AircraftListSelect (int i)
00521 {
00522     aircraft_t *aircraft;
00523 
00524     if (td.trAircraftsTmp[i] > TRANS_LIST_EMPTY_SLOT)   /* Already on transfer list. */
00525         return qfalse;
00526 
00527     aircraft = AIR_AircraftGetFromIDX(i);
00528     if (!AIR_IsAircraftInBase(aircraft))    /* Aircraft is not in base. */
00529         return qfalse;
00530 
00531     return qtrue;
00532 }
00533 
00542 static void TR_TransferSelect (base_t *srcbase, base_t *destbase, transferType_t transferType)
00543 {
00544     linkedList_t *transferList = NULL;
00545     linkedList_t *transferListAmount = NULL;
00546     linkedList_t *transferListTransfered = NULL;
00547     int numempl[MAX_EMPL], trempl[MAX_EMPL];
00548     int i, j, cnt = 0;
00549     char str[128];
00550 
00551     /* reset for every new call */
00552     UI_ResetData(TEXT_TRANSFER_LIST);
00553     UI_ResetData(TEXT_TRANSFER_LIST_AMOUNT);
00554     UI_ResetData(TEXT_TRANSFER_LIST_TRANSFERED);
00555 
00556     /* Reset and fill temp employees arrays. */
00557     for (i = 0; i < MAX_EMPL; i++) {
00558         trempl[i] = numempl[i] = 0;
00559         for (j = 0; j < MAX_EMPLOYEES; j++) {
00560             if (td.trEmployeesTmp[i][j])
00561                 trempl[i]++;
00562         }
00563     }
00564 
00565     switch (transferType) {
00566     case TRANS_TYPE_ITEM:
00567         if (B_GetBuildingStatus(destbase, B_ANTIMATTER)) {
00568             const objDef_t *od = INVSH_GetItemByID(ANTIMATTER_TECH_ID);
00569             if (B_AntimatterInBase(srcbase) || td.trItemsTmp[od->idx]) {
00570                 if (td.trItemsTmp[od->idx] > 0)
00571                     LIST_AddString(&transferListTransfered, va("%i", td.trItemsTmp[od->idx]));
00572                 else
00573                     LIST_AddString(&transferListTransfered, "");
00574                 Com_sprintf(str, sizeof(str), "%s", _(od->name));
00575                 LIST_AddString(&transferList, str);
00576                 LIST_AddString(&transferListAmount, va("%i", B_AntimatterInBase(srcbase)));
00577                 cnt++;
00578             }
00579         }
00580         if (B_GetBuildingStatus(destbase, B_STORAGE)) {
00581             for (i = 0; i < csi.numODs; i++) {
00582                 const objDef_t *od = INVSH_GetItemByIDX(i);
00583                 if (!B_ItemIsStoredInBaseStorage(od))
00584                     continue;
00585                 if (od->isVirtual)
00586                     continue;
00587                 if (td.trItemsTmp[od->idx] || B_ItemInBase(od, srcbase) > 0) {
00588                     if (td.trItemsTmp[od->idx] > 0)
00589                         LIST_AddString(&transferListTransfered, va("%i", td.trItemsTmp[od->idx]));
00590                     else
00591                         LIST_AddString(&transferListTransfered, "");
00592                     Com_sprintf(str, sizeof(str), "%s", _(od->name));
00593                     LIST_AddString(&transferList, str);
00594                     LIST_AddString(&transferListAmount, va("%i", srcbase->storage.numItems[od->idx]));
00595                     cnt++;
00596                 }
00597             }
00598             if (!cnt) {
00599                 LIST_AddString(&transferList, _("Storage is empty."));
00600                 LIST_AddString(&transferListAmount, "");
00601                 LIST_AddString(&transferListTransfered, "");
00602             }
00603         } else if (B_GetBuildingStatus(destbase, B_POWER) && cnt == 0) {
00604             LIST_AddString(&transferList, _("Transfer is not possible - the base doesn't have a Storage."));
00605             LIST_AddString(&transferListAmount, "");
00606             LIST_AddString(&transferListTransfered, "");
00607         } else if (cnt == 0) {
00608             LIST_AddString(&transferList, _("Transfer is not possible - the base does not have power supplies."));
00609             LIST_AddString(&transferListAmount, "");
00610             LIST_AddString(&transferListTransfered, "");
00611         }
00612         UI_ExecuteConfunc("trans_display_spinners %i", cnt);
00613         break;
00614     case TRANS_TYPE_EMPLOYEE:
00615         if (B_GetBuildingStatus(destbase, B_QUARTERS)) {
00616             employeeType_t emplType;
00617             for (emplType = 0; emplType < MAX_EMPL; emplType++) {
00618                 employee_t *employee = NULL;
00619                 while ((employee = E_GetNextFromBase(emplType, employee, srcbase))) {
00620                     if (td.trEmployeesTmp[emplType][employee->idx]) /* Already on transfer list. */
00621                         continue;
00622                     if (emplType == EMPL_SOLDIER || emplType == EMPL_PILOT) {
00623                         if (emplType == EMPL_SOLDIER) {
00624                             const rank_t *rank = CL_GetRankByIdx(employee->chr.score.rank);
00625                             Com_sprintf(str, sizeof(str), _("Soldier %s %s"), rank->shortname, employee->chr.name);
00626                         } else
00627                             Com_sprintf(str, sizeof(str), _("Pilot %s"), employee->chr.name);
00628                         LIST_AddString(&transferList, str);
00629                         LIST_AddString(&transferListAmount, "1");
00630                         LIST_AddString(&transferListTransfered, "");
00631                         cnt++;
00632                     }
00633                     numempl[emplType]++;
00634                 }
00635             }
00636             for (i = 0; i < MAX_EMPL; i++) {
00637                 if (i == EMPL_SOLDIER || i == EMPL_PILOT)
00638                     continue;
00639                 if (numempl[i] > 0) {
00640                     LIST_AddString(&transferList, E_GetEmployeeString(i));
00641                     LIST_AddString(&transferListAmount, va("%i", numempl[i]));
00642                     if (trempl[i] > 0)
00643                         LIST_AddString(&transferListTransfered, va("%i", trempl[i]));
00644                     else
00645                         LIST_AddString(&transferListTransfered, "");
00646                     cnt++;
00647                 }
00648             }
00649             if (!cnt) {
00650                 LIST_AddString(&transferList, _("Living Quarters empty."));
00651                 LIST_AddString(&transferListAmount, "");
00652                 LIST_AddString(&transferListTransfered, "");
00653             }
00654         } else {
00655             LIST_AddString(&transferList, _("Transfer is not possible - the base doesn't have Living Quarters."));
00656             LIST_AddString(&transferListAmount, "");
00657             LIST_AddString(&transferListTransfered, "");
00658         }
00659         UI_ExecuteConfunc("trans_display_spinners 0");
00660         break;
00661     case TRANS_TYPE_ALIEN:
00662         if (B_GetBuildingStatus(destbase, B_ALIEN_CONTAINMENT)) {
00663             for (i = 0; i < ccs.numAliensTD; i++) {
00664                 const aliensCont_t *alienCont = &srcbase->alienscont[i];
00665                 if (alienCont->teamDef && alienCont->amountDead > 0) {
00666                     Com_sprintf(str, sizeof(str), _("Corpse of %s"),
00667                     _(AL_AlienTypeToName(AL_GetAlienGlobalIDX(i))));
00668                     LIST_AddString(&transferList, str);
00669                     LIST_AddString(&transferListAmount, va("%i", alienCont->amountDead));
00670                     if (td.trAliensTmp[i][TRANS_ALIEN_DEAD] > 0)
00671                         LIST_AddString(&transferListTransfered, va("%i", td.trAliensTmp[i][TRANS_ALIEN_DEAD]));
00672                     else
00673                         LIST_AddString(&transferListTransfered, "");
00674                     cnt++;
00675                 }
00676                 if (alienCont->teamDef && alienCont->amountAlive > 0) {
00677                     Com_sprintf(str, sizeof(str), _("Alive %s"),
00678                         _(AL_AlienTypeToName(AL_GetAlienGlobalIDX(i))));
00679                     LIST_AddString(&transferList, str);
00680                     LIST_AddString(&transferListAmount, va("%i", alienCont->amountAlive));
00681                     if (td.trAliensTmp[i][TRANS_ALIEN_ALIVE] > 0)
00682                         LIST_AddString(&transferListTransfered, va("%i", td.trAliensTmp[i][TRANS_ALIEN_ALIVE]));
00683                     else
00684                         LIST_AddString(&transferListTransfered, "");
00685                     cnt++;
00686                 }
00687             }
00688             if (!cnt) {
00689                 LIST_AddString(&transferList, _("Alien Containment is empty."));
00690                 LIST_AddString(&transferListAmount, "");
00691                 LIST_AddString(&transferListTransfered, "");
00692             }
00693         } else if (B_GetBuildingStatus(destbase, B_POWER)) {
00694             LIST_AddString(&transferList, _("Transfer is not possible - the base doesn't have an Alien Containment."));
00695             LIST_AddString(&transferListAmount, "");
00696             LIST_AddString(&transferListTransfered, "");
00697         } else {
00698             LIST_AddString(&transferList, _("Transfer is not possible - the base does not have power supplies."));
00699             LIST_AddString(&transferListAmount, "");
00700             LIST_AddString(&transferListTransfered, "");
00701         }
00702         UI_ExecuteConfunc("trans_display_spinners 0");
00703         break;
00704     case TRANS_TYPE_AIRCRAFT:
00705         if (B_GetBuildingStatus(destbase, B_HANGAR) || B_GetBuildingStatus(destbase, B_SMALL_HANGAR)) {
00706             for (i = 0; i < MAX_AIRCRAFT; i++) {
00707                 aircraft_t *aircraft = AIR_AircraftGetFromIDX(i);
00708                 if (aircraft) {
00709                     if (aircraft->homebase == srcbase && TR_AircraftListSelect(i)) {
00710                         Com_sprintf(str, sizeof(str), _("Aircraft %s"), aircraft->name);
00711                         LIST_AddString(&transferList, str);
00712                         LIST_AddString(&transferListAmount, "1");
00713                         LIST_AddString(&transferListTransfered, "");
00714                         cnt++;
00715                     }
00716                 }
00717             }
00718             if (!cnt) {
00719                 LIST_AddString(&transferList, _("No aircraft available for transfer."));
00720                 LIST_AddString(&transferListAmount, "");
00721                 LIST_AddString(&transferListTransfered, "");
00722             }
00723         } else {
00724             LIST_AddString(&transferList, _("Transfer is not possible - the base doesn't have a functional hangar."));
00725             LIST_AddString(&transferListAmount, "");
00726             LIST_AddString(&transferListTransfered, "");
00727         }
00728         UI_ExecuteConfunc("trans_display_spinners 0");
00729         break;
00730     default:
00731         Com_Printf("TR_TransferSelect: Unknown transferType id %i\n", transferType);
00732         UI_ExecuteConfunc("trans_display_spinners 0");
00733         return;
00734     }
00735 
00736     /* Update cargo list. */
00737     TR_CargoList();
00738 
00739     td.currentTransferType = transferType;
00740     UI_RegisterLinkedListText(TEXT_TRANSFER_LIST, transferList);
00741     UI_RegisterLinkedListText(TEXT_TRANSFER_LIST_AMOUNT, transferListAmount);
00742     UI_RegisterLinkedListText(TEXT_TRANSFER_LIST_TRANSFERED, transferListTransfered);
00743 }
00744 
00750 static void TR_TransferSelect_f (void)
00751 {
00752     int type;
00753     base_t *base = B_GetCurrentSelectedBase();
00754 
00755     if (!td.transferBase || !base)
00756         return;
00757 
00758     if (Cmd_Argc() < 2)
00759         type = td.currentTransferType;
00760     else
00761         type = TR_GetTransferType(Cmd_Argv(1));
00762 
00763     if (type < TRANS_TYPE_ITEM || type >= TRANS_TYPE_MAX)
00764         return;
00765 
00766     TR_TransferSelect(base, td.transferBase, type);
00767 }
00768 
00773 static void TR_TransferListClear_f (void)
00774 {
00775     int i;
00776     base_t *base = B_GetCurrentSelectedBase();
00777 
00778     if (!base)
00779         return;
00780 
00781     for (i = 0; i < csi.numODs; i++) {  /* Return items. */
00782         const objDef_t *od = INVSH_GetItemByIDX(i);
00783         if (td.trItemsTmp[od->idx] > 0) {
00784             if (!strcmp(od->id, ANTIMATTER_TECH_ID))
00785                 B_ManageAntimatter(base, td.trItemsTmp[od->idx], qtrue);
00786             else
00787                 B_UpdateStorageAndCapacity(base, od, td.trItemsTmp[od->idx], qfalse, qfalse);
00788         }
00789     }
00790     for (i = 0; i < ccs.numAliensTD; i++) { /* Return aliens. */
00791         if (td.trAliensTmp[i][TRANS_ALIEN_ALIVE] > 0)
00792             AL_ChangeAliveAlienNumber(base, &(base->alienscont[i]), td.trAliensTmp[i][TRANS_ALIEN_ALIVE]);
00793         if (td.trAliensTmp[i][TRANS_ALIEN_DEAD] > 0)
00794             base->alienscont[i].amountDead += td.trAliensTmp[i][TRANS_ALIEN_DEAD];
00795     }
00796 
00797     /* Clear temporary cargo arrays. */
00798     memset(td.trItemsTmp, 0, sizeof(td.trItemsTmp));
00799     memset(td.trAliensTmp, 0, sizeof(td.trAliensTmp));
00800     memset(td.trEmployeesTmp, 0, sizeof(td.trEmployeesTmp));
00801     memset(td.trAircraftsTmp, TRANS_LIST_EMPTY_SLOT, sizeof(td.trAircraftsTmp));
00802     /* Update cargo list and items list. */
00803     TR_CargoList();
00804     TR_TransferSelect(base, td.transferBase, td.currentTransferType);
00805     UI_ExecuteConfunc("trans_resetscroll");
00806 }
00807 
00811 static int TR_GetTransferFactor (void)
00812 {
00813     return 1;
00814 }
00815 
00816 static qboolean TR_GetTransferEmployee (employeeType_t emplType, int *cnt, const base_t *base, int num)
00817 {
00818     employee_t *employee = NULL;
00819     while ((employee = E_GetNextFromBase(emplType, employee, base))) {
00820         if (td.trEmployeesTmp[employee->type][employee->idx])
00821             continue;
00822         if (*cnt == num) {
00823             if (TR_CheckEmployee(employee, td.transferBase)) {
00824                 td.trEmployeesTmp[employee->type][employee->idx] = employee;
00825                 return qtrue;
00826             }
00831             return qfalse;
00832         }
00833         (*cnt)++;
00834     }
00835     return qfalse;
00836 }
00837 
00843 static void TR_TransferListSelect_f (void)
00844 {
00845     int num, cnt = 0, i;
00846     employeeType_t emplType;
00847     int numEmployees[MAX_EMPL];
00848     base_t *base = B_GetCurrentSelectedBase();
00849 
00850     if (Cmd_Argc() < 2)
00851         return;
00852 
00853     if (!base)
00854         return;
00855 
00856     if (!td.transferBase) {
00857         UI_Popup(_("No target base selected"), _("Please select the target base from the list"));
00858         return;
00859     }
00860 
00861     num = atoi(Cmd_Argv(1));
00862     if (num < 0 || num >= csi.numODs)
00863         return;
00864 
00865     switch (td.currentTransferType) {
00866     case TRANS_TYPE_INVALID:    
00867         return;
00868     case TRANS_TYPE_ITEM:
00869         if (B_GetBuildingStatus(td.transferBase, B_ANTIMATTER)) {
00870             const objDef_t *od = INVSH_GetItemByID(ANTIMATTER_TECH_ID);
00871             if (B_AntimatterInBase(base) || td.trItemsTmp[od->idx]) {
00872                 if (cnt == num) {
00873                     int amount;
00874 
00875                     if (Cmd_Argc() == 3)
00876                         amount = atoi(Cmd_Argv(2));
00877                     else
00878                         amount = TR_GetTransferFactor();
00879 
00880                     /* you can't transfer more item than you have */
00881                     if (amount > 0) {
00882                         amount = min(amount, B_AntimatterInBase(base));
00883                         if (amount == 0)
00884                             return;
00885                         /* you can only transfer items that destination base can accept */
00886                         amount = TR_CheckItem(od, td.transferBase, amount);
00887                     } else if (amount < 0) {
00888                         amount = max(amount, - td.trItemsTmp[od->idx]);
00889                     }
00890 
00891                     if (amount) {
00892                         td.trItemsTmp[od->idx] += amount;
00893                         B_ManageAntimatter(base, amount, qfalse);
00894                         break;
00895                     } else
00896                         return;
00897                 }
00898                 cnt++;
00899             }
00900         }
00901         for (i = 0; i < csi.numODs; i++) {
00902             const objDef_t *od = INVSH_GetItemByIDX(i);
00903             if (!B_ItemIsStoredInBaseStorage(od))
00904                 continue;
00905             if (od->isVirtual)
00906                 continue;
00907             if (td.trItemsTmp[od->idx] || B_ItemInBase(od, base) > 0) {
00908                 if (cnt == num) {
00909                     int amount;
00910 
00911                     if (Cmd_Argc() == 3)
00912                         amount = atoi(Cmd_Argv(2));
00913                     else
00914                         amount = TR_GetTransferFactor();
00915 
00916                     /* you can't transfer more item than you have */
00917                     if (amount > 0) {
00918                         amount = min(amount, base->storage.numItems[od->idx]);
00919                         if (amount == 0)
00920                             return;
00921                         /* you can only transfer items that destination base can accept */
00922                         amount = TR_CheckItem(od, td.transferBase, amount);
00923                     } else if (amount < 0) {
00924                         amount = max(amount, - td.trItemsTmp[od->idx]);
00925                     }
00926 
00927                     if (amount) {
00928                         td.trItemsTmp[od->idx] += amount;
00929                         B_UpdateStorageAndCapacity(base, od, -amount, qfalse, qfalse);
00930                         break;
00931                     } else
00932                         return;
00933                 }
00934                 cnt++;
00935             }
00936         }
00937         break;
00938     case TRANS_TYPE_EMPLOYEE:
00939         if (TR_GetTransferEmployee(EMPL_SOLDIER, &cnt, base, num))
00940             break;
00941 
00942         if (TR_GetTransferEmployee(EMPL_PILOT, &cnt, base, num))
00943             break;
00944 
00945         /* Reset and fill temp employees arrays. */
00946         for (emplType = 0; emplType < MAX_EMPL; emplType++) {
00947             numEmployees[emplType] = E_CountHired(base, emplType);
00948             for (i = 0; i < MAX_EMPLOYEES; i++) {
00949                 if (td.trEmployeesTmp[emplType][i])
00950                     numEmployees[emplType]--;
00951             }
00952         }
00953 
00954         for (emplType = 0; emplType < MAX_EMPL; emplType++) {
00955             if (emplType == EMPL_SOLDIER || emplType == EMPL_PILOT)
00956                 continue;
00957             /* no employee in base or all employees already in the transfer list */
00958             if (numEmployees[emplType] < 1)
00959                 continue;
00960             if (cnt == num) {
00961                 int amount = min(E_CountHired(base, emplType), TR_GetTransferFactor());
00962                 employee_t *employee = NULL;
00963                 while ((employee = E_GetNextFromBase(emplType, employee, base))) {
00964                     if (td.trEmployeesTmp[emplType][employee->idx]) /* Already on transfer list. */
00965                         continue;
00966                     if (TR_CheckEmployee(employee, td.transferBase)) {
00967                         td.trEmployeesTmp[emplType][employee->idx] = employee;
00968                         amount--;
00969                         if (amount == 0)
00970                             break;
00971                     } else
00972                         return;
00973                 }
00974             }
00975             cnt++;
00976         }
00977         break;
00978     case TRANS_TYPE_ALIEN:
00979         if (!B_GetBuildingStatus(td.transferBase, B_ALIEN_CONTAINMENT))
00980             return;
00981         for (i = 0; i < ccs.numAliensTD; i++) {
00982             if (base->alienscont[i].teamDef && base->alienscont[i].amountDead > 0) {
00983                 if (cnt == num) {
00984                     td.trAliensTmp[i][TRANS_ALIEN_DEAD]++;
00985                     /* Remove the corpse from Alien Containment. */
00986                     base->alienscont[i].amountDead--;
00987                     break;
00988                 }
00989                 cnt++;
00990             }
00991             if (base->alienscont[i].teamDef && base->alienscont[i].amountAlive > 0) {
00992                 if (cnt == num) {
00993                     if (TR_CheckAlien(td.transferBase)) {
00994                         td.trAliensTmp[i][TRANS_ALIEN_ALIVE]++;
00995                         /* Remove an alien from Alien Containment. */
00996                         AL_ChangeAliveAlienNumber(base, &(base->alienscont[i]), -1);
00997                         break;
00998                     } else
00999                         return;
01000                 }
01001                 cnt++;
01002             }
01003         }
01004         break;
01005     case TRANS_TYPE_AIRCRAFT:
01006         if (!B_GetBuildingStatus(td.transferBase, B_HANGAR) && !B_GetBuildingStatus(td.transferBase, B_SMALL_HANGAR))
01007             return;
01008         for (i = 0; i < MAX_AIRCRAFT; i++) {
01009             const aircraft_t *aircraft = AIR_AircraftGetFromIDX(i);
01010             if (!aircraft)
01011                 return;
01012             if (aircraft->homebase == base && TR_AircraftListSelect(i)) {
01013                 if (cnt == num) {
01014                     if (TR_CheckAircraft(aircraft, td.transferBase)) {
01015                         td.trAircraftsTmp[i] = i;
01016                         break;
01017                     } else
01018                         return;
01019                 }
01020                 cnt++;
01021             }
01022         }
01023         break;
01024     default:
01025         return;
01026     }
01027 
01028     TR_TransferSelect(base, td.transferBase, td.currentTransferType);
01029 }
01030 
01037 static void TR_TransferBaseSelect (base_t *srcbase, base_t *destbase)
01038 {
01039     static char baseInfo[1024];
01040     qboolean powercomm = qfalse;
01041 
01042     if (!destbase || !srcbase)
01043         return;
01044 
01045     baseInfo[0] = '\0';
01046     powercomm = B_GetBuildingStatus(destbase, B_POWER);
01047 
01048     /* if there is no power supply facility this check will fail, too */
01049     if (B_GetBuildingStatus(destbase, B_STORAGE)) {
01050         Q_strcat(baseInfo, _("You can transfer equipment - this base has a Storage.\n"), sizeof(baseInfo));
01051     } else if (powercomm) {
01052         /* if there is a power supply facility we really don't have a storage */
01053         Q_strcat(baseInfo, _("No Storage in this base.\n"), sizeof(baseInfo));
01054     }
01055 
01056     if (B_GetBuildingStatus(destbase, B_QUARTERS)) {
01057         Q_strcat(baseInfo, _("You can transfer employees - this base has Living Quarters.\n"), sizeof(baseInfo));
01058     } else {
01059         Q_strcat(baseInfo, _("No Living Quarters in this base.\n"), sizeof(baseInfo));
01060     }
01061 
01062     if (B_GetBuildingStatus(destbase, B_ALIEN_CONTAINMENT)) {
01063         Q_strcat(baseInfo, _("You can transfer Aliens - this base has an Alien Containment.\n"), sizeof(baseInfo));
01064     } else if (powercomm) {
01065         Q_strcat(baseInfo, _("No Alien Containment in this base.\n"), sizeof(baseInfo));
01066     }
01067 
01068     if (B_GetBuildingStatus(destbase, B_ANTIMATTER)) {
01069         Q_strcat(baseInfo, _("You can transfer antimatter - this base has an Antimatter Storage.\n"), sizeof(baseInfo));
01070     } else if (powercomm) {
01071         Q_strcat(baseInfo, _("No Antimatter Storage in this base.\n"), sizeof(baseInfo));
01072     }
01073 
01074     if (B_GetBuildingStatus(destbase, B_HANGAR) || B_GetBuildingStatus(destbase, B_SMALL_HANGAR)) {
01075         Q_strcat(baseInfo, _("You can transfer aircraft - this base has a Hangar.\n"), sizeof(baseInfo));
01076     } else if (!B_GetBuildingStatus(destbase, B_COMMAND)) {
01077         Q_strcat(baseInfo, _("Aircraft transfer not possible - this base does not have a Command Centre.\n"), sizeof(baseInfo));
01078     } else if (powercomm) {
01079         Q_strcat(baseInfo, _("No Hangar in this base.\n"), sizeof(baseInfo));
01080     }
01081 
01082     if (!powercomm)
01083         Q_strcat(baseInfo, _("No power supplies in this base.\n"), sizeof(baseInfo));
01084 
01085     UI_RegisterText(TEXT_BASE_INFO, baseInfo);
01086 
01087     /* Set global pointer to current selected base. */
01088     td.transferBase = destbase;
01089     Cvar_Set("mn_trans_base_name", destbase->name);
01090     Cvar_SetValue("mn_trans_base_id", destbase->idx);
01091 
01092     /* Update stuff-in-base list. */
01093     TR_TransferSelect(srcbase, destbase, td.currentTransferType);
01094 }
01095 
01099 static void TR_InitBaseList (void)
01100 {
01101     int baseIdx;
01102     const base_t const *currentBase = B_GetCurrentSelectedBase();
01103     uiNode_t *baseList = NULL;
01104 
01105     for (baseIdx = 0; baseIdx < ccs.numBases; baseIdx++) {
01106         const base_t const *base = B_GetFoundedBaseByIDX(baseIdx);
01107         if (!base)
01108             continue;
01109         if (base == currentBase)
01110             continue;
01111 
01112         UI_AddOption(&baseList, va("base%i", baseIdx), base->name, va("%i", baseIdx));
01113     }
01114 
01115     UI_RegisterOption(OPTION_BASELIST, baseList);
01116 }
01117 
01121 static void TR_SelectBase_f (void)
01122 {
01123     int baseIdx;
01124     base_t *base = B_GetCurrentSelectedBase();
01125     base_t *destbase;
01126 
01127     if (Cmd_Argc() < 2) {
01128         Com_Printf("Usage: %s <baseIdx>\n", Cmd_Argv(0));
01129         return;
01130     }
01131 
01132     baseIdx = atoi(Cmd_Argv(1));
01133     destbase = B_GetFoundedBaseByIDX(baseIdx);
01134 
01135     TR_TransferBaseSelect(base, destbase);
01136 }
01137 
01141 static void TR_CargoListSelect_f (void)
01142 {
01143     int num, cnt = 0, entries = 0, i, j;
01144     qboolean removed = qfalse;
01145     int numempl[MAX_EMPL];
01146     employeeType_t emplType;
01147     base_t *base = B_GetCurrentSelectedBase();
01148 
01149     if (Cmd_Argc() < 2)
01150         return;
01151 
01152     if (!base)
01153         return;
01154 
01155     num = atoi(Cmd_Argv(1));
01156     if (num < 0 || num >= MAX_CARGO)
01157         return;
01158 
01159     switch (td.cargo[num].type) {
01160     case CARGO_TYPE_ITEM:
01161         for (i = 0; i < csi.numODs; i++) {
01162             const objDef_t *od = INVSH_GetItemByIDX(i);
01163             if (td.trItemsTmp[od->idx] > 0) {
01164                 if (cnt == num) {
01165                     const int amount = min(TR_GetTransferFactor(), td.trItemsTmp[od->idx]);
01166                     /* you can't transfer more item than there are in current transfer */
01167                     td.trItemsTmp[i] -= amount;
01168                     if (!strcmp(od->id, ANTIMATTER_TECH_ID))
01169                         B_ManageAntimatter(base, amount, qfalse);
01170                     else
01171                         B_UpdateStorageAndCapacity(base, od, amount, qfalse, qfalse);
01172                     break;
01173                 }
01174                 cnt++;
01175             }
01176         }
01177         break;
01178     case CARGO_TYPE_EMPLOYEE:
01179         for (i = 0; i < MAX_CARGO; i++) {
01180             /* Count previous types on the list. */
01181             switch (td.cargo[i].type) {
01182             case CARGO_TYPE_ITEM:
01183                 entries++;
01184             default:
01185                 break;
01186             }
01187         }
01188         /* Start increasing cnt from the amount of previous entries. */
01189         cnt = entries;
01190         for (i = 0; i < ccs.numEmployees[EMPL_SOLDIER]; i++) {
01191             if (td.trEmployeesTmp[EMPL_SOLDIER][i]) {
01192                 if (cnt == num) {
01193                     td.trEmployeesTmp[EMPL_SOLDIER][i] = NULL;
01194                     removed = qtrue;
01195                     break;
01196                 }
01197                 cnt++;
01198             }
01199         }
01200         if (removed)    /* We already removed soldier, break here. */
01201             break;
01202         for (i = 0; i < ccs.numEmployees[EMPL_PILOT]; i++) {
01203             if (td.trEmployeesTmp[EMPL_PILOT][i]) {
01204                 if (cnt == num) {
01205                     td.trEmployeesTmp[EMPL_PILOT][i] = NULL;
01206                     removed = qtrue;
01207                     break;
01208                 }
01209                 cnt++;
01210             }
01211         }
01212         if (removed)    /* We already removed pilot, break here. */
01213             break;
01214 
01215         Com_DPrintf(DEBUG_CLIENT, "TR_CargoListSelect_f: cnt: %i, num: %i\n", cnt, num);
01216 
01217         /* Reset and fill temp employees arrays. */
01218         for (emplType = 0; emplType < MAX_EMPL; emplType++) {
01219             numempl[emplType] = 0;
01222             for (i = 0; i < MAX_EMPLOYEES; i++) {
01223                 if (td.trEmployeesTmp[emplType][i])
01224                     numempl[emplType]++;
01225             }
01226         }
01227 
01228         for (emplType = 0; emplType < MAX_EMPL; emplType++) {
01229             if (numempl[emplType] < 1 || emplType == EMPL_SOLDIER || emplType == EMPL_PILOT)
01230                 continue;
01231             if (cnt == num) {
01232                 int amount = min(TR_GetTransferFactor(), E_CountHired(base, emplType));
01233                 for (j = 0; j < ccs.numEmployees[emplType]; j++) {
01234                     if (td.trEmployeesTmp[emplType][j]) {
01235                         td.trEmployeesTmp[emplType][j] = NULL;
01236                         amount--;
01237                         removed = qtrue;
01238                         if (amount == 0)
01239                             break;
01240                     } else
01241                         continue;
01242                 }
01243             }
01244             if (removed)    /* We already removed employee, break here. */
01245                 break;
01246             cnt++;
01247         }
01248         break;
01249     case CARGO_TYPE_ALIEN_DEAD:
01250         for (i = 0; i < MAX_CARGO; i++) {
01251             /* Count previous types on the list. */
01252             switch (td.cargo[i].type) {
01253             case CARGO_TYPE_ITEM:
01254             case CARGO_TYPE_EMPLOYEE:
01255                 entries++;
01256             default:
01257                 break;
01258             }
01259         }
01260         /* Start increasing cnt from the amount of previous entries. */
01261         cnt = entries;
01262         for (i = 0; i < ccs.numAliensTD; i++) {
01263             if (td.trAliensTmp[i][TRANS_ALIEN_DEAD] > 0) {
01264                 if (cnt == num) {
01265                     td.trAliensTmp[i][TRANS_ALIEN_DEAD]--;
01266                     base->alienscont[i].amountDead++;
01267                     break;
01268                 }
01269                 cnt++;
01270             }
01271         }
01272         break;
01273     case CARGO_TYPE_ALIEN_ALIVE:
01274         for (i = 0; i < MAX_CARGO; i++) {
01275             /* Count previous types on the list. */
01276             switch (td.cargo[i].type) {
01277             case CARGO_TYPE_ITEM:
01278             case CARGO_TYPE_EMPLOYEE:
01279             case CARGO_TYPE_ALIEN_DEAD:
01280                 entries++;
01281             default:
01282                 break;
01283             }
01284         }
01285         /* Start increasing cnt from the amount of previous entries. */
01286         cnt = entries;
01287         for (i = 0; i < ccs.numAliensTD; i++) {
01288             if (td.trAliensTmp[i][TRANS_ALIEN_ALIVE] > 0) {
01289                 if (cnt == num) {
01290                     td.trAliensTmp[i][TRANS_ALIEN_ALIVE]--;
01291                     AL_ChangeAliveAlienNumber(base, &(base->alienscont[i]), 1);
01292                     break;
01293                 }
01294                 cnt++;
01295             }
01296         }
01297         break;
01298     case CARGO_TYPE_AIRCRAFT:
01299         for (i = 0; i < MAX_CARGO; i++) {
01300             /* Count previous types on the list. */
01301             switch (td.cargo[i].type) {
01302             case CARGO_TYPE_ITEM:
01303             case CARGO_TYPE_EMPLOYEE:
01304             case CARGO_TYPE_ALIEN_DEAD:
01305             case CARGO_TYPE_ALIEN_ALIVE:
01306                 entries++;
01307             default:
01308                 break;
01309             }
01310         }
01311         /* Start increasing cnt from the amount of previous entries. */
01312         cnt = entries;
01313         for (i = 0; i < ccs.numAircraft; i++) {
01314             if (td.trAircraftsTmp[i] > TRANS_LIST_EMPTY_SLOT) {
01315                 if (cnt == num) {
01316                     td.trAircraftsTmp[i] = TRANS_LIST_EMPTY_SLOT;
01317                     break;
01318                 }
01319                 cnt++;
01320             }
01321         }
01322         break;
01323     default:
01324         return;
01325     }
01326 
01327     TR_TransferSelect(base, td.transferBase, td.currentTransferType);
01328 }
01329 
01335 static void TR_Init_f (void)
01336 {
01337     base_t *base = B_GetCurrentSelectedBase();
01338 
01339     /* Clear employees temp array. */
01340     memset(td.trEmployeesTmp, 0, sizeof(td.trEmployeesTmp));
01341     /* Clear aircraft temp array. */
01342     memset(td.trAircraftsTmp, TRANS_LIST_EMPTY_SLOT, sizeof(td.trAircraftsTmp));
01343 
01344     /* Update destination base list */
01345     TR_InitBaseList();
01346 
01347     /* Select first available base. */
01348     td.transferBase = B_GetFoundedBaseByIDX((base->idx + 1) % ccs.numBases);
01349     TR_TransferBaseSelect(base, td.transferBase);
01350     /* Set up cvar used to display transferBase. */
01351     if (td.transferBase) {
01352         Cvar_Set("mn_trans_base_name", td.transferBase->name);
01353         Cvar_SetValue("mn_trans_base_id", td.transferBase->idx);
01354     } else {
01355         Cvar_Set("mn_trans_base_id", "");
01356     }
01357 
01358     /* Set up cvar used with tabset */
01359     Cvar_Set("mn_itemtype", transferTypeIDs[0]);
01360     /* Select first available item */
01361     Cmd_ExecuteString(va("trans_type %s", transferTypeIDs[0]));
01362 
01363     /* Reset scrolling for item-in-base list */
01364     UI_ExecuteConfunc("trans_resetscroll");
01365 }
01366 
01370 static void TR_TransferClose_f (void)
01371 {
01372     base_t *base = B_GetCurrentSelectedBase();
01373 
01374     if (!base)
01375         return;
01376 
01377     /* Unload what was loaded. */
01378     TR_TransferListClear_f();
01379 
01380     /* Clear temporary cargo arrays. */
01381     memset(td.trItemsTmp, 0, sizeof(td.trItemsTmp));
01382     memset(td.trAliensTmp, 0, sizeof(td.trAliensTmp));
01383     memset(td.trEmployeesTmp, 0, sizeof(td.trEmployeesTmp));
01384     memset(td.trAircraftsTmp, TRANS_LIST_EMPTY_SLOT, sizeof(td.trAircraftsTmp));
01385 }
01386 
01390 static void TR_TransferList_Scroll_f (void)
01391 {
01392     int i;
01393     int cnt = 0;
01394     int transferType;
01395     int viewPos;
01396     base_t *srcBase = B_GetCurrentSelectedBase();
01397     const objDef_t *od = INVSH_GetItemByID(ANTIMATTER_TECH_ID);
01398 
01399     if (!srcBase)
01400         return;
01401 
01402     if (Cmd_Argc() < 3) {
01403         Com_Printf("Usage: %s <transferType> <viewPos>\n", Cmd_Argv(0));
01404         return;
01405     }
01406 
01407     transferType = TR_GetTransferType(Cmd_Argv(1));
01408     viewPos = atoi(Cmd_Argv(2));
01409 
01410     /* spinners are only on items screen */
01411     if (transferType != TRANS_TYPE_ITEM)
01412         return;
01413 
01414     if (B_GetBuildingStatus(td.transferBase, B_ANTIMATTER) && (td.trItemsTmp[od->idx] || B_AntimatterInBase(srcBase))) {
01415         if (cnt >= viewPos && cnt < viewPos + MAX_TRANSLIST_MENU_ENTRIES)
01416             UI_ExecuteConfunc("trans_updatespinners %i %i %i %i", cnt - viewPos,
01417                     td.trItemsTmp[od->idx], 0, B_AntimatterInBase(srcBase) + td.trItemsTmp[od->idx]);
01418         cnt++;
01419     }
01420     for (i = 0; i < csi.numODs; i++) {
01421         const objDef_t *od = INVSH_GetItemByIDX(i);
01422         if (!B_ItemIsStoredInBaseStorage(od))
01423             continue;
01424         if (od->isVirtual)
01425             continue;
01426         if (srcBase->storage.numItems[od->idx] || td.trItemsTmp[od->idx]) {
01427             if (cnt >= viewPos + MAX_TRANSLIST_MENU_ENTRIES)
01428                 break;
01429             if (cnt >= viewPos)
01430                 UI_ExecuteConfunc("trans_updatespinners %i %i %i %i", cnt - viewPos,
01431                         td.trItemsTmp[od->idx], 0, srcBase->storage.numItems[od->idx] + td.trItemsTmp[od->idx]);
01432             cnt++;
01433         }
01434     }
01435 }
01436 
01437 void TR_InitCallbacks (void)
01438 {
01439     memset(&td, 0, sizeof(td));
01440     memset(td.trAircraftsTmp, TRANS_LIST_EMPTY_SLOT, sizeof(td.trAircraftsTmp));
01441     Cmd_AddCommand("trans_init", TR_Init_f, "Init function for Transfer menu");
01442     Cmd_AddCommand("trans_list_scroll", TR_TransferList_Scroll_f, "Scrolls the transferlist");
01443     Cmd_AddCommand("trans_close", TR_TransferClose_f, "Callback for closing Transfer Menu");
01444     Cmd_AddCommand("trans_start", TR_TransferStart_f, "Starts the transfer");
01445     Cmd_AddCommand("trans_type", TR_TransferSelect_f, "Switch between transfer types (employees, techs, items)");
01446     Cmd_AddCommand("trans_emptyairstorage", TR_TransferListClear_f, "Unload everything from transfer cargo back to base");
01447     Cmd_AddCommand("trans_list_click", TR_TransferListSelect_f, "Callback for transfer list node click");
01448     Cmd_AddCommand("trans_cargolist_click", TR_CargoListSelect_f, "Callback for cargo list node click");
01449     Cmd_AddCommand("trans_selectbase", TR_SelectBase_f, "Callback for selecting a base");
01450     Cmd_AddCommand("trans_baselist_click", TR_TransferBaseListClick_f, "Callback for choosing base while recovering alien after mission");
01451 
01452     Cmd_AddCommand("trans_aliens", TR_TransferAliensFromMission_f, "Transfer aliens collected at missions");
01453 }
01454 
01455 void TR_ShutdownCallbacks (void)
01456 {
01457     Cmd_RemoveCommand("trans_init");
01458     Cmd_RemoveCommand("trans_list_scroll");
01459     Cmd_RemoveCommand("trans_close");
01460     Cmd_RemoveCommand("trans_start");
01461     Cmd_RemoveCommand("trans_type");
01462     Cmd_RemoveCommand("trans_emptyairstorage");
01463     Cmd_RemoveCommand("trans_list_click");
01464     Cmd_RemoveCommand("trans_cargolist_click");
01465     Cmd_RemoveCommand("trans_selectbase");
01466     Cmd_RemoveCommand("trans_baselist_click");
01467     Cmd_RemoveCommand("trans_aliens");
01468 }
01469 

Generated by  doxygen 1.6.2