cp_transfer.c

Go to the documentation of this file.
00001 
00008 /*
00009 Copyright (C) 2002-2010 UFO: Alien Invasion.
00010 
00011 This program is free software; you can redistribute it and/or
00012 modify it under the terms of the GNU General Public License
00013 as published by the Free Software Foundation; either version 2
00014 of the License, or (at your option) any later version.
00015 
00016 This program is distributed in the hope that it will be useful,
00017 but WITHOUT ANY WARRANTY; without even the implied warranty of
00018 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00019 
00020 See the GNU General Public License for more details.
00021 
00022 You should have received a copy of the GNU General Public License
00023 along with this program; if not, write to the Free Software
00024 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00025 
00026 */
00027 
00028 #include "../cl_shared.h"
00029 #include "cp_campaign.h"
00030 #include "save/save_transfer.h"
00031 #include "cp_transfer_callbacks.h"
00032 #include "../ui/ui_main.h"
00033 
00038 transfer_t* TR_GetNext (transfer_t *lastTransfer)
00039 {
00040     transfer_t *endOfTransfers = &ccs.transfers[ccs.numTransfers];
00041     transfer_t* transfer;
00042 
00043     if (!ccs.numTransfers)
00044         return NULL;
00045 
00046     if (!lastTransfer)
00047         return ccs.transfers;
00048     assert(lastTransfer >= ccs.transfers);
00049     assert(lastTransfer < endOfTransfers);
00050 
00051     transfer = lastTransfer;
00052 
00053     transfer++;
00054     if (transfer >= endOfTransfers)
00055         return NULL;
00056     else
00057         return transfer;
00058 }
00059 
00068 static void TR_EmptyTransferCargo (base_t *destination, transfer_t *transfer, qboolean success)
00069 {
00070     assert(transfer);
00071 
00072     if (transfer->hasItems && success) {    /* Items. */
00073         const objDef_t *od = INVSH_GetItemByID(ANTIMATTER_TECH_ID);
00074         int i;
00075 
00076         /* antimatter */
00077         if (transfer->itemAmount[od->idx] > 0) {
00078             if (B_GetBuildingStatus(destination, B_ANTIMATTER)) {
00079                 B_ManageAntimatter(destination, transfer->itemAmount[od->idx], qtrue);
00080             } else {
00081                 Com_sprintf(cp_messageBuffer, sizeof(cp_messageBuffer), _("%s does not have Antimatter Storage, antimatter are removed!"), destination->name);
00082                 MSO_CheckAddNewMessage(NT_TRANSFER_LOST, _("Transport mission"), cp_messageBuffer, qfalse, MSG_TRANSFERFINISHED, NULL);
00083             }
00084         } 
00085         /* items */
00086         for (i = 0; i < csi.numODs; i++) {
00087             od = INVSH_GetItemByIDX(i);
00088 
00089             if (transfer->itemAmount[od->idx] <= 0)
00090                 continue;
00091             if (!B_ItemIsStoredInBaseStorage(od))
00092                 continue;
00093             if (!B_GetBuildingStatus(destination, B_STORAGE)) {
00094                 Com_sprintf(cp_messageBuffer, sizeof(cp_messageBuffer), _("%s does not have Storage, items are removed!"), destination->name);
00095                 MSO_CheckAddNewMessage(NT_TRANSFER_LOST, _("Transport mission"), cp_messageBuffer, qfalse, MSG_TRANSFERFINISHED, NULL);
00096                 break;
00097             }
00098             B_UpdateStorageAndCapacity(destination, od, transfer->itemAmount[od->idx], qfalse, qtrue);
00099         }
00100     }
00101 
00102     if (transfer->hasEmployees && transfer->srcBase) {  /* Employees. (cannot come from a mission) */
00103         if (!success || !B_GetBuildingStatus(destination, B_QUARTERS)) {    /* Employees will be unhired. */
00104             int i;
00105             if (success) {
00106                 Com_sprintf(cp_messageBuffer, sizeof(cp_messageBuffer), _("%s does not have Living Quarters, employees got unhired!"), destination->name);
00107                 MSO_CheckAddNewMessage(NT_TRANSFER_LOST, _("Transport mission"), cp_messageBuffer, qfalse, MSG_TRANSFERFINISHED, NULL);
00108             }
00109             for (i = 0; i < MAX_EMPL; i++) {
00110                 int j;
00111                 for (j = 0; j < ccs.numEmployees[i]; j++) {
00112                     if (transfer->employeeArray[i][j]) {
00113                         employee_t *employee = transfer->employeeArray[i][j];
00114                         employee->baseHired = transfer->srcBase;    /* Restore back the original baseid. */
00115                         /* every employee that we have transfered should have a
00116                          * base he is hire in - otherwise we couldn't have transfered him */
00117                         assert(employee->baseHired);
00118                         employee->transfer = qfalse;
00119                         E_UnhireEmployee(employee);
00120                     }
00121                 }
00122             }
00123         } else {
00124             int i;
00125             for (i = 0; i < MAX_EMPL; i++) {
00126                 int j;
00127                 for (j = 0; j < ccs.numEmployees[i]; j++) {
00128                     if (transfer->employeeArray[i][j]) {
00129                         employee_t *employee = transfer->employeeArray[i][j];
00130                         employee->baseHired = transfer->srcBase;    /* Restore back the original baseid. */
00131                         /* every employee that we have transfered should have a
00132                          * base he is hire in - otherwise we couldn't have transfered him */
00133                         assert(employee->baseHired);
00134                         employee->transfer = qfalse;
00135                         E_UnhireEmployee(employee);
00136                         E_HireEmployee(destination, employee);
00137                     }
00138                 }
00139             }
00140         }
00141     }
00142 
00143     if (transfer->hasAliens && success) {   /* Aliens. */
00144         if (!B_GetBuildingStatus(destination, B_ALIEN_CONTAINMENT)) {
00145             Com_sprintf(cp_messageBuffer, sizeof(cp_messageBuffer), _("%s does not have Alien Containment, Aliens are removed!"), destination->name);
00146             MSO_CheckAddNewMessage(NT_TRANSFER_LOST, _("Transport mission"), cp_messageBuffer, qfalse, MSG_TRANSFERFINISHED, NULL);
00147             /* Aliens cargo is not unloaded, will be destroyed in TR_TransferCheck(). */
00148         } else {
00149             int i;
00150             for (i = 0; i < ccs.numAliensTD; i++) {
00151                 if (transfer->alienAmount[i][TRANS_ALIEN_ALIVE] > 0) {
00152                     AL_ChangeAliveAlienNumber(destination, &(destination->alienscont[i]), transfer->alienAmount[i][TRANS_ALIEN_ALIVE]);
00153                 }
00154                 if (transfer->alienAmount[i][TRANS_ALIEN_DEAD] > 0) {
00155                     destination->alienscont[i].amountDead += transfer->alienAmount[i][TRANS_ALIEN_DEAD];
00156                 }
00157             }
00158         }
00159     }
00160 
00164     if (transfer->hasAircraft && success && transfer->srcBase) {    /* Aircraft. Cannot come from mission */
00165         int i;
00166         for (i = 0; i < ccs.numAircraft; i++) {
00167             if (transfer->aircraftArray[i] > TRANS_LIST_EMPTY_SLOT) {
00168                 aircraft_t *aircraft = AIR_AircraftGetFromIDX(i);
00169                 assert(aircraft);
00170 
00171                 if (AIR_CalculateHangarStorage(aircraft->tpl, destination, 0) > 0) {
00172                     /* Move aircraft */
00173                     AIR_MoveAircraftIntoNewHomebase(aircraft, destination);
00174                 } else {
00175                     /* No space, aircraft will be lost. */
00176                     Com_sprintf(cp_messageBuffer, sizeof(cp_messageBuffer), _("%s does not have enough free space in hangars. Aircraft is lost!"), destination->name);
00177                     MSO_CheckAddNewMessage(NT_TRANSFER_LOST, _("Transport mission"), cp_messageBuffer, qfalse, MSG_TRANSFERFINISHED, NULL);
00178                     AIR_DeleteAircraft(aircraft);
00179                 }
00180             }
00181         }
00182     }
00183 }
00184 
00191 void TR_TransferAlienAfterMissionStart (const base_t *base, aircraft_t *transferAircraft)
00192 {
00193     int i, j;
00194     transfer_t *transfer;
00195     float time;
00196     char message[256];
00197     int alienCargoTypes;
00198     aliensTmp_t *cargo;
00199 
00200     const technology_t *breathingTech;
00201     qboolean alienBreathing = qfalse;
00202     const objDef_t *alienBreathingObjDef;
00203 
00204     breathingTech = RS_GetTechByID(BREATHINGAPPARATUS_TECH);
00205     if (!breathingTech)
00206         Com_Error(ERR_DROP, "AL_AddAliens: Could not get breathing apparatus tech definition");
00207     alienBreathing = RS_IsResearched_ptr(breathingTech);
00208     alienBreathingObjDef = INVSH_GetItemByID(breathingTech->provides);
00209     if (!alienBreathingObjDef)
00210         Com_Error(ERR_DROP, "AL_AddAliens: Could not get breathing apparatus item definition");
00211 
00212     if (!base) {
00213         Com_Printf("TR_TransferAlienAfterMissionStart_f: No base selected!\n");
00214         return;
00215     }
00216 
00217     if (ccs.numTransfers >= MAX_TRANSFERS) {
00218         Com_DPrintf(DEBUG_CLIENT, "TR_TransferAlienAfterMissionStart: Max transfers reached.");
00219         return;
00220     }
00221 
00222     transfer = &ccs.transfers[ccs.numTransfers];
00223 
00224     if (transfer->active)
00225         Com_Error(ERR_DROP, "Transfer idx %i shouldn't be active.", ccs.numTransfers);
00226 
00227     /* Initialize transfer.
00228      * calculate time to go from 1 base to another : 1 day for one quarter of the globe*/
00229     time = GetDistanceOnGlobe(base->pos, transferAircraft->pos) / 90.0f;
00230     transfer->event.day = ccs.date.day + floor(time);   /* add day */
00231     time = (time - floor(time)) * SECONDS_PER_DAY;  /* convert remaining time in second */
00232     transfer->event.sec = ccs.date.sec + round(time);
00233     /* check if event is not the following day */
00234     if (transfer->event.sec > SECONDS_PER_DAY) {
00235         transfer->event.sec -= SECONDS_PER_DAY;
00236         transfer->event.day++;
00237     }
00238     transfer->destBase = B_GetFoundedBaseByIDX(base->idx);  /* Destination base. */
00239     transfer->srcBase = NULL;   /* Source base. */
00240     transfer->active = qtrue;
00241     ccs.numTransfers++;
00242 
00243     alienCargoTypes = AL_GetAircraftAlienCargoTypes(transferAircraft);
00244     cargo = AL_GetAircraftAlienCargo(transferAircraft);
00245     for (i = 0; i < alienCargoTypes; i++, cargo++) {        /* Aliens. */
00246         if (!alienBreathing) {
00247             cargo->amountDead += cargo->amountAlive;
00248             cargo->amountAlive = 0;
00249         }
00250         if (cargo->amountAlive > 0) {
00251             for (j = 0; j < ccs.numAliensTD; j++) {
00252                 if (!CHRSH_IsTeamDefAlien(&csi.teamDef[j]))
00253                     continue;
00254                 if (base->alienscont[j].teamDef == cargo->teamDef) {
00255                     transfer->hasAliens = qtrue;
00256                     transfer->alienAmount[j][TRANS_ALIEN_ALIVE] = cargo->amountAlive;
00257                     cargo->amountAlive = 0;
00258                     break;
00259                 }
00260             }
00261         }
00262         if (cargo->amountDead > 0) {
00263             for (j = 0; j < ccs.numAliensTD; j++) {
00264                 if (!CHRSH_IsTeamDefAlien(&csi.teamDef[j]))
00265                     continue;
00266                 if (base->alienscont[j].teamDef == cargo->teamDef) {
00267                     transfer->hasAliens = qtrue;
00268                     transfer->alienAmount[j][TRANS_ALIEN_DEAD] = cargo->amountDead;
00269 
00270                     /* If we transfer aliens from battlefield add also breathing apparatur(s) */
00271                     transfer->hasItems = qtrue;
00272                     transfer->itemAmount[alienBreathingObjDef->idx] += cargo->amountDead;
00273                     cargo->amountDead = 0;
00274                     break;
00275                 }
00276             }
00277         }
00278     }
00279     AL_SetAircraftAlienCargoTypes(transferAircraft, 0);
00280 
00281     Com_sprintf(message, sizeof(message), _("Transport mission started, cargo is being transported to %s"), transfer->destBase->name);
00282     MSO_CheckAddNewMessage(NT_TRANSFER_ALIENBODIES_DEFERED, _("Transport mission"), message, qfalse, MSG_TRANSFERFINISHED, NULL);
00283     UI_PopWindow(qfalse);
00284 }
00285 
00290 static void TR_TransferEnd (transfer_t *transfer)
00291 {
00292     base_t* destination = transfer->destBase;
00293     assert(destination);
00294 
00295     if (!destination->founded) {
00296         TR_EmptyTransferCargo(NULL, transfer, qfalse);
00297         MSO_CheckAddNewMessage(NT_TRANSFER_LOST, _("Transport mission"), _("The destination base no longer exists! Transfer carge was lost, personnel has been discharged."), qfalse, MSG_TRANSFERFINISHED, NULL);
00299     } else {
00300         char message[256];
00301         TR_EmptyTransferCargo(destination, transfer, qtrue);
00302         Com_sprintf(message, sizeof(message), _("Transport mission ended, unloading cargo in %s"), destination->name);
00303         MSO_CheckAddNewMessage(NT_TRANSFER_COMPLETED_SUCCESS, _("Transport mission"), message, qfalse, MSG_TRANSFERFINISHED, NULL);
00304     }
00305     transfer->active = qfalse;
00306 }
00307 
00313 void TR_TransferStart (base_t *srcBase, struct transferData_s *transData)
00314 {
00315     transfer_t *transfer;
00316     float time;
00317     int i;
00318     int j;
00319 
00320     if (!transData->transferBase || !srcBase) {
00321         Com_Printf("TR_TransferStart_f: No base selected!\n");
00322         return;
00323     }
00324 
00325     /* don't start any empty transport */
00326     if (!transData->trCargoCountTmp) {
00327         return;
00328     }
00329 
00330     if (ccs.numTransfers >= MAX_TRANSFERS) {
00331         Com_DPrintf(DEBUG_CLIENT, "TR_TransferStart_f: Max transfers reached.");
00332         return;
00333     }
00334 
00335     transfer = &ccs.transfers[ccs.numTransfers];
00336 
00337     if (transfer->active)
00338         Com_Error(ERR_DROP, "Transfer idx %i shouldn't be active.", ccs.numTransfers);
00339 
00340     /* Initialize transfer. */
00341     /* calculate time to go from 1 base to another : 1 day for one quarter of the globe*/
00342     time = GetDistanceOnGlobe(transData->transferBase->pos, srcBase->pos) / 90.0f;
00343     transfer->event.day = ccs.date.day + floor(time);   /* add day */
00344     time = (time - floor(time)) * SECONDS_PER_DAY;  /* convert remaining time in second */
00345     transfer->event.sec = ccs.date.sec + round(time);
00346     /* check if event is not the following day */
00347     if (transfer->event.sec > SECONDS_PER_DAY) {
00348         transfer->event.sec -= SECONDS_PER_DAY;
00349         transfer->event.day++;
00350     }
00351     transfer->destBase = transData->transferBase;   /* Destination base. */
00352     assert(transfer->destBase);
00353     transfer->srcBase = srcBase;    /* Source base. */
00354     transfer->active = qtrue;
00355     ccs.numTransfers++;
00356 
00357     for (i = 0; i < csi.numODs; i++) {  /* Items. */
00358         if (transData->trItemsTmp[i] > 0) {
00359             transfer->hasItems = qtrue;
00360             transfer->itemAmount[i] = transData->trItemsTmp[i];
00361         }
00362     }
00363     /* Note that the employee remains hired in source base during the transfer, that is
00364      * it takes Living Quarters capacity, etc, but it cannot be used anywhere. */
00365     for (i = 0; i < MAX_EMPL; i++) {        /* Employees. */
00366         for (j = 0; j < ccs.numEmployees[i]; j++) {
00367             if (transData->trEmployeesTmp[i][j]) {
00368                 employee_t *employee = transData->trEmployeesTmp[i][j];
00369                 transfer->hasEmployees = qtrue;
00370 
00371                 assert(E_IsInBase(employee, srcBase));
00372 
00373                 E_ResetEmployee(employee);
00374                 transfer->employeeArray[i][j] = employee;
00375                 employee->baseHired = NULL;
00376                 employee->transfer = qtrue;
00377             }
00378         }
00379     }
00383     for (i = 0; i < ccs.numAliensTD; i++) {     /* Aliens. */
00384         if (!CHRSH_IsTeamDefAlien(&csi.teamDef[i]))
00385             continue;
00386         if (transData->trAliensTmp[i][TRANS_ALIEN_ALIVE] > 0) {
00387             transfer->hasAliens = qtrue;
00388             transfer->alienAmount[i][TRANS_ALIEN_ALIVE] = transData->trAliensTmp[i][TRANS_ALIEN_ALIVE];
00389         }
00390         if (transData->trAliensTmp[i][TRANS_ALIEN_DEAD] > 0) {
00391             transfer->hasAliens = qtrue;
00392             transfer->alienAmount[i][TRANS_ALIEN_DEAD] = transData->trAliensTmp[i][TRANS_ALIEN_DEAD];
00393         }
00394     }
00395     memset(transfer->aircraftArray, TRANS_LIST_EMPTY_SLOT, sizeof(transfer->aircraftArray));
00396     for (i = 0; i < ccs.numAircraft; i++) { /* Aircraft. */
00397         if (transData->trAircraftsTmp[i] > TRANS_LIST_EMPTY_SLOT) {
00398             aircraft_t *aircraft = AIR_AircraftGetFromIDX(i);
00399             aircraft->status = AIR_TRANSFER;
00400             AIR_RemoveEmployees(aircraft);
00401             transfer->hasAircraft = qtrue;
00402             transfer->aircraftArray[i] = i;
00403         } else {
00404             transfer->aircraftArray[i] = TRANS_LIST_EMPTY_SLOT;
00405         }
00406     }
00407 
00408     /* Recheck if production/research can be done on srcbase (if there are workers/scientists) */
00409     PR_ProductionAllowed(srcBase);
00410     RS_ResearchAllowed(srcBase);
00411 }
00412 
00418 void TR_NotifyAircraftRemoved (const aircraft_t *aircraft)
00419 {
00420     transfer_t *transfer = NULL;
00421 
00422     assert(aircraft->idx >= 0 && aircraft->idx < MAX_AIRCRAFT);
00423     while ((transfer = TR_GetNext(transfer))) {
00424         int tmp = ccs.numAircraft;
00425         /* skip non active transfer */
00426         if (!transfer->active)
00427             continue;
00428         if (!transfer->hasAircraft)
00429             continue;
00430         REMOVE_ELEM_MEMSET(transfer->aircraftArray, aircraft->idx, tmp, TRANS_LIST_EMPTY_SLOT);
00431     }
00432 }
00433 
00438 void TR_TransferCheck (void)
00439 {
00440     transfer_t *transfer = NULL;
00441     while ((transfer = TR_GetNext(transfer))) {
00442         if (!transfer->active)
00443             continue;
00444         if (transfer->event.day == ccs.date.day && ccs.date.sec >= transfer->event.sec) {
00445             const ptrdiff_t idx = (ptrdiff_t)(transfer - ccs.transfers);
00446             assert(transfer->destBase);
00447             TR_TransferEnd(transfer);
00449             REMOVE_ELEM(ccs.transfers, idx, ccs.numTransfers);
00450             return;
00451         }
00452     }
00453 }
00454 
00455 #ifdef DEBUG
00456 
00459 static void TR_ListTransfers_f (void)
00460 {
00461     int transIdx = -1;
00462     int i = 0;
00463     transfer_t *transfer = NULL;
00464 
00465     if (Cmd_Argc() == 2) {
00466         transIdx = atoi(Cmd_Argv(1));
00467         if (transIdx < 0 || transIdx > MAX_TRANSFERS) {
00468             Com_Printf("Usage: %s [transferIDX]\nWithout parameter it lists all.\n", Cmd_Argv(0));
00469             return;
00470         }
00471     }
00472 
00473     if (!ccs.numTransfers)
00474         Com_Printf("No active transfers.\n");
00475 
00476     for (; (transfer = TR_GetNext(transfer)); i++) {
00477         dateLong_t date;
00478 
00479         if (transIdx >= 0 && i != transIdx)
00480             continue;
00481         if (!transfer->active)
00482             continue;
00483 
00484         /* @todo: we need a strftime feature to make this easier */
00485         CL_DateConvertLong(&transfer->event, &date);
00486 
00487         Com_Printf("Transfer #%d\n", i);
00488         Com_Printf("...From %d (%s) To %d (%s) Arrival: %04i-%02i-%02i %02i:%02i:%02i\n",
00489             (transfer->srcBase) ? transfer->srcBase->idx : -1,
00490             (transfer->srcBase) ? transfer->srcBase->name : "(null)",
00491             (transfer->destBase) ? transfer->destBase->idx : -1,
00492             (transfer->destBase) ? transfer->destBase->name : "(null)",
00493             date.year, date.month, date.day, date.hour, date.min, date.sec);
00494 
00495         /* ItemCargo */
00496         if (transfer->hasItems) {
00497             int j;
00498             Com_Printf("...ItemCargo:\n");
00499             for (j = 0; j < csi.numODs; j++) {
00500                 const objDef_t *od = INVSH_GetItemByIDX(j);
00501                 if (transfer->itemAmount[od->idx])
00502                     Com_Printf("......%s: %i\n", od->id, transfer->itemAmount[od->idx]);
00503             }
00504         }
00505         /* Carried Employees */
00506         if (transfer->hasEmployees) {
00507             int j;
00508             Com_Printf("...Carried Employee:\n");
00509             for (j = 0; j < MAX_EMPL; j++) {
00510                 int k;
00511                 for (k = 0; k < MAX_EMPLOYEES; k++) {
00512                     const struct employee_s *employee = transfer->employeeArray[j][k];
00513                     if (!employee)
00514                         continue;
00515                     if (employee->ugv) {
00517                         Com_Printf("......ugv: %s [idx: %i]\n", employee->ugv->id, employee->idx);
00518                     } else {
00519                         Com_Printf("......%s (%s) / %s [idx: %i ucn: %i]\n", employee->chr.name,
00520                             E_GetEmployeeString(employee->type),
00521                             (employee->nation) ? employee->nation->id : "(nonation)",
00522                             employee->idx, employee->chr.ucn);
00523                         if (!E_IsHired(employee))
00524                             Com_Printf("Warning: employee^ not hired!\n");
00525                         if (!employee->transfer)
00526                             Com_Printf("Warning: employee^ not marked as being transfered!\n");
00527                     }
00528                 }
00529             }
00530         }
00531         /* AlienCargo */
00532         if (transfer->hasAliens) {
00533             int j;
00534             Com_Printf("...AlienCargo:\n");
00535             for (j = 0; j < csi.numTeamDefs; j++) {
00536                 if (transfer->alienAmount[j][TRANS_ALIEN_ALIVE] + transfer->alienAmount[j][TRANS_ALIEN_DEAD])
00537                     Com_Printf("......%s alive: %i dead: %i\n", csi.teamDef[j].id, transfer->alienAmount[j][TRANS_ALIEN_ALIVE], transfer->alienAmount[j][TRANS_ALIEN_DEAD]);
00538             }
00539         }
00540         /* Transfered Aircraft */
00541         if (transfer->hasAircraft) {
00542             int j;
00543             Com_Printf("...Transfered Aircraft:\n");
00544             for (j = 0; j < ccs.numAircraft; j++) {
00545                 const aircraft_t *aircraft;
00546                 if (transfer->aircraftArray[j] == TRANS_LIST_EMPTY_SLOT)
00547                     continue;
00548                 aircraft = AIR_AircraftGetFromIDX(transfer->aircraftArray[j]);
00549                 Com_Printf("......%s [idx: %i]\n", (aircraft) ? aircraft->id : "(null)", j);
00550             }
00551         }
00552 
00553     }
00554 }
00555 #endif
00556 
00563 qboolean TR_SaveXML (mxml_node_t *p)
00564 {
00565     transfer_t *transfer = NULL;
00566     mxml_node_t *n = mxml_AddNode(p, SAVE_TRANSFER_TRANSFERS);
00567 
00568     while ((transfer = TR_GetNext(transfer))) {
00569         int j;
00570         mxml_node_t *s;
00571 
00572         s = mxml_AddNode(n, SAVE_TRANSFER_TRANSFER);
00573         mxml_AddInt(s, SAVE_TRANSFER_DAY, transfer->event.day);
00574         mxml_AddInt(s, SAVE_TRANSFER_SEC, transfer->event.sec);
00575         if (!transfer->destBase) {
00576             Com_Printf("Could not save transfer, no destBase is set\n");
00577             return qfalse;
00578         }
00579         mxml_AddInt(s, SAVE_TRANSFER_DESTBASE, transfer->destBase->idx);
00580         /* scrBase can be NULL if this is alien (mission->base) transport 
00581          * @sa TR_TransferAlienAfterMissionStart */
00582         if (transfer->srcBase)
00583             mxml_AddInt(s, SAVE_TRANSFER_SRCBASE, transfer->srcBase->idx);
00584         /* save items */
00585         if (transfer->hasItems) {
00586             for (j = 0; j < MAX_OBJDEFS; j++) {
00587                 if (transfer->itemAmount[j] > 0) {
00588                     const objDef_t *od = INVSH_GetItemByIDX(j);
00589                     mxml_node_t *ss = mxml_AddNode(s, SAVE_TRANSFER_ITEM);
00590 
00591                     assert(od);
00592                     mxml_AddString(ss, SAVE_TRANSFER_ITEMID, od->id);
00593                     mxml_AddInt(ss, SAVE_TRANSFER_AMOUNT, transfer->itemAmount[j]);
00594                 }
00595             }
00596         }
00597         /* save aliens */
00598         if (transfer->hasAliens) {
00599             for (j = 0; j < ccs.numAliensTD; j++) {
00600                 if (transfer->alienAmount[j][TRANS_ALIEN_ALIVE] > 0
00601                  || transfer->alienAmount[j][TRANS_ALIEN_DEAD] > 0)
00602                 {
00603                     teamDef_t *team = ccs.alienTeams[j];
00604                     mxml_node_t *ss = mxml_AddNode(s, SAVE_TRANSFER_ALIEN);
00605 
00606                     assert(team);
00607                     mxml_AddString(ss, SAVE_TRANSFER_ALIENID, team->id);
00608                     mxml_AddIntValue(ss, SAVE_TRANSFER_ALIVEAMOUNT, transfer->alienAmount[j][TRANS_ALIEN_ALIVE]);
00609                     mxml_AddIntValue(ss, SAVE_TRANSFER_DEADAMOUNT, transfer->alienAmount[j][TRANS_ALIEN_DEAD]);
00610                 }
00611             }
00612         }
00613         /* save employee */
00614         if (transfer->hasEmployees) {
00615             for (j = 0; j < MAX_EMPL; j++) {
00616                 int k;
00617                 for (k = 0; k < MAX_EMPLOYEES; k++) {
00618                     const employee_t *empl = transfer->employeeArray[j][k];
00619                     if (empl) {
00620                         mxml_node_t *ss = mxml_AddNode(s, SAVE_TRANSFER_EMPLOYEE);
00621 
00622                         mxml_AddInt(ss, SAVE_TRANSFER_UCN, empl->chr.ucn);
00623                     }
00624                 }
00625             }
00626         }
00627         /* save aircraft */
00628         if (transfer->hasAircraft) {
00629             for (j = 0; j < ccs.numAircraft; j++) {
00630                 if (transfer->aircraftArray[j] > TRANS_LIST_EMPTY_SLOT) {
00631                     mxml_node_t *ss = mxml_AddNode(s, SAVE_TRANSFER_AIRCRAFT);
00632                     mxml_AddInt(ss, SAVE_TRANSFER_ID, j);
00633                 }
00634             }
00635         }
00636     }
00637     return qtrue;
00638 }
00639 
00646 qboolean TR_LoadXML (mxml_node_t *p)
00647 {
00648     mxml_node_t *n, *s;
00649 
00650     n = mxml_GetNode(p, SAVE_TRANSFER_TRANSFERS);
00651     if (!n)
00652         return qfalse;
00653 
00654     assert(ccs.numBases);
00655 
00656     for (s = mxml_GetNode(n, SAVE_TRANSFER_TRANSFER); s && ccs.numTransfers < MAX_TRANSFERS; s = mxml_GetNextNode(s, n, SAVE_TRANSFER_TRANSFER)) {
00657         mxml_node_t *ss;
00658         transfer_t *transfer = &ccs.transfers[ccs.numTransfers];
00659 
00660         transfer->destBase = B_GetBaseByIDX(mxml_GetInt(s, SAVE_TRANSFER_DESTBASE, BYTES_NONE));
00661         if (!transfer->destBase) {
00662             Com_Printf("Error: Transfer has no destBase set\n");
00663             return qfalse;
00664         }
00665         transfer->srcBase = B_GetBaseByIDX(mxml_GetInt(s, SAVE_TRANSFER_SRCBASE, BYTES_NONE));
00666 
00667         transfer->event.day = mxml_GetInt(s, SAVE_TRANSFER_DAY, 0);
00668         transfer->event.sec = mxml_GetInt(s, SAVE_TRANSFER_SEC, 0);
00669         transfer->active = qtrue;
00670 
00671         /* Initializing some variables */
00672         transfer->hasItems = qfalse;
00673         transfer->hasEmployees = qfalse;
00674         transfer->hasAliens = qfalse;
00675         transfer->hasAircraft = qfalse;
00676         memset(transfer->itemAmount, 0, sizeof(transfer->itemAmount));
00677         memset(transfer->alienAmount, 0, sizeof(transfer->alienAmount));
00678         memset(transfer->employeeArray, 0, sizeof(transfer->employeeArray));
00679         memset(transfer->aircraftArray, TRANS_LIST_EMPTY_SLOT, sizeof(transfer->aircraftArray));
00680 
00681         /* load items */
00682         /* If there is at last one element, hasItems is true */
00683         ss = mxml_GetNode(s, SAVE_TRANSFER_ITEM);
00684         if (ss) {
00685             transfer->hasItems = qtrue;
00686             for (; ss; ss = mxml_GetNextNode(ss, s, SAVE_TRANSFER_ITEM)) {
00687                 const char *itemId = mxml_GetString(ss, SAVE_TRANSFER_ITEMID);
00688                 const objDef_t *od = INVSH_GetItemByID(itemId);
00689 
00690                 if (od)
00691                     transfer->itemAmount[od->idx] = mxml_GetInt(ss, SAVE_TRANSFER_AMOUNT, 1);
00692             }
00693         }
00694         /* load aliens */
00695         ss = mxml_GetNode(s, SAVE_TRANSFER_ALIEN);
00696         if (ss) {
00697             transfer->hasAliens = qtrue;
00698             for (; ss; ss = mxml_GetNextNode(ss, s, SAVE_TRANSFER_ALIEN)) {
00699                 const int alive = mxml_GetInt(ss, SAVE_TRANSFER_ALIVEAMOUNT, 0);
00700                 const int dead  = mxml_GetInt(ss, SAVE_TRANSFER_DEADAMOUNT, 0);
00701                 const char *id = mxml_GetString(ss, SAVE_TRANSFER_ALIENID);
00702                 int j;
00703 
00704                 /* look for alien teamDef */
00705                 for (j = 0; j < ccs.numAliensTD; j++) {
00706                     if (ccs.alienTeams[j] && !strcmp(id, ccs.alienTeams[j]->id))
00707                         break;
00708                 }
00709 
00710                 if (j < ccs.numAliensTD) {
00711                     transfer->alienAmount[j][TRANS_ALIEN_ALIVE] = alive;
00712                     transfer->alienAmount[j][TRANS_ALIEN_DEAD] = dead;
00713                 } else {
00714                     Com_Printf("CL_LoadXML: AlienId '%s' is invalid\n", id);
00715                 }
00716             }
00717         }
00718         /* load employee */
00719         ss = mxml_GetNode(s, SAVE_TRANSFER_EMPLOYEE);
00720         if (ss) {
00721             transfer->hasEmployees = qtrue;
00722             for (; ss; ss = mxml_GetNextNode(ss, s, SAVE_TRANSFER_EMPLOYEE)) {
00723                 const int ucn = mxml_GetInt(ss, SAVE_TRANSFER_UCN, -1);
00724                 employee_t *empl = E_GetEmployeeFromChrUCN(ucn);
00725 
00726                 if (!empl) {
00727                     Com_Printf("Error: No employee found with UCN: %i\n", ucn);
00728                     return qfalse;
00729                 }
00730 
00731                 transfer->employeeArray[empl->type][empl->idx] = empl;
00732                 transfer->employeeArray[empl->type][empl->idx]->transfer = qtrue;
00733             }
00734         }
00735         /* load aircraft */
00736         ss = mxml_GetNode(s, SAVE_TRANSFER_AIRCRAFT);
00737         if (ss) {
00738             transfer->hasAircraft = qtrue;
00739             for (; ss; ss = mxml_GetNextNode(ss, s, SAVE_TRANSFER_AIRCRAFT)) {
00740                 const int j = mxml_GetInt(ss, SAVE_TRANSFER_ID, -1);
00741 
00742                 if (j >= 0 && j < ccs.numAircraft)
00743                     transfer->aircraftArray[j] = j;
00744             }
00745         }
00746         ccs.numTransfers++;
00747     }
00748 
00749     return qtrue;
00750 }
00751 
00756 void TR_InitStartup (void)
00757 {
00758     /* add commands */
00759 #ifdef DEBUG
00760     Cmd_AddCommand("debug_listtransfers", TR_ListTransfers_f, "Lists an/all active transfer(s)");
00761 #endif
00762 }
00763 

Generated by  doxygen 1.6.2