cp_uforecovery_callbacks.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 "cp_ufo.h"
00031 #include "cp_uforecovery.h"
00032 #include "cp_uforecovery_callbacks.h"
00033 
00034 #include "../ui/ui_main.h"
00035 
00036 #ifdef DEBUG
00037 #include "cp_time.h"
00038 #endif
00039 
00043 typedef struct ufoRecoveryNation_s {
00044     nation_t *nation;
00045     int price;                                      
00046 } ufoRecoveryNation_t;
00047 
00052 typedef int (*COMP_FUNCTION)(ufoRecoveryNation_t *a, ufoRecoveryNation_t *b);
00053 
00057 typedef enum {
00058     ORDER_NATION,
00059     ORDER_PRICE,
00060     ORDER_HAPPINESS,
00061 
00062     MAX_ORDER
00063 } ufoRecoveryNationOrder_t;
00064 
00066 typedef struct ufoRecovery_s {
00067     const aircraft_t *ufoTemplate;                  
00068     nation_t *nation;                               
00069     qboolean recoveryDone;                          
00070     float condition;                                
00071     ufoRecoveryNation_t UFONations[MAX_NATIONS];    
00072     ufoRecoveryNationOrder_t sortedColumn;          
00073     qboolean sortDescending;                        
00074 } ufoRecovery_t;
00075 
00076 static ufoRecovery_t ufoRecovery;
00077 
00081 static void UR_DialogRecoveryDone (void)
00082 {
00083     ufoRecovery.recoveryDone = qtrue;
00084 }
00085 
00091 static void UR_DialogInit_f (void)
00092 {
00093     char ufoID[MAX_VAR];
00094     const aircraft_t *ufoCraft;
00095     float cond = 1.0f;
00096 
00097     if (Cmd_Argc() < 2) {
00098         Com_Printf("Usage: %s <ufoID> [UFO-Condition]\n", Cmd_Argv(0));
00099         return;
00100     }
00101 
00102     Q_strncpyz(ufoID, Cmd_Argv(1), sizeof(ufoID));
00103 
00104     if (Cmd_Argc() >= 3) {
00105         cond = atof(Cmd_Argv(2));
00106     }
00107 
00108     ufoCraft = AIR_GetAircraft(ufoID);
00109 
00110     /* Put relevant info into missionResults array. */
00111     ccs.missionResults.recovery = qtrue;
00112     ccs.missionResults.ufoCondition = cond;
00113     ccs.missionResults.crashsite = (cond < 1);
00114     ccs.missionResults.ufotype = ufoCraft->ufotype;
00115     /* Prepare related cvars. */
00116     Cvar_SetValue("mission_uforecovered", 1);   /* This is used in menus to enable UFO Recovery nodes. */
00117     /* Fill ufoRecovery structure */
00118     memset(&ufoRecovery, 0, sizeof(ufoRecovery));
00119     ufoRecovery.ufoTemplate = ufoCraft;
00120     ufoRecovery.condition = cond;
00121     ufoRecovery.sortedColumn = ORDER_NATION;
00122 
00123     Cvar_Set("mn_uforecovery_actualufo", UFO_MissionResultToString());
00124 }
00125 
00131 static void UR_DialogInitStore_f (void)
00132 {
00133     int i;
00134     int count = 0;
00135     linkedList_t *recoveryYardName = NULL;
00136     linkedList_t *recoveryYardCapacity = NULL;
00137     static char cap[MAX_VAR];
00138 
00139     /* Do nothing if recovery process is finished. */
00140     if (ufoRecovery.recoveryDone)
00141         return;
00142 
00143     /* Check how many bases can store this UFO. */
00144     for (i = 0; i < ccs.numInstallations; i++) {
00145         const installation_t *installation = INS_GetFoundedInstallationByIDX(i);
00146 
00147         if (!installation)
00148             continue;
00149 
00150         if (installation->ufoCapacity.max > 0
00151          && installation->ufoCapacity.max > installation->ufoCapacity.cur) {
00152 
00153             Com_sprintf(cap, lengthof(cap), "%i/%i", (installation->ufoCapacity.max - installation->ufoCapacity.cur), installation->ufoCapacity.max);
00154             LIST_AddString(&recoveryYardName, installation->name);
00155             LIST_AddString(&recoveryYardCapacity, cap);
00156             count++;
00157         }
00158     }
00159 
00160     Cvar_Set("mn_uforecovery_actualufo", UFO_MissionResultToString());
00161     if (count == 0) {
00162         /* No UFO base with proper conditions, show a hint and disable list. */
00163         LIST_AddString(&recoveryYardName, _("No free UFO yard available."));
00164         UI_ExecuteConfunc("uforecovery_tabselect sell");
00165         UI_ExecuteConfunc("btbasesel disable");
00166     } else {
00167         UI_ExecuteConfunc("cp_basesel_select 0");
00168         UI_ExecuteConfunc("btbasesel enable");
00169     }
00170     UI_RegisterLinkedListText(TEXT_UFORECOVERY_UFOYARDS, recoveryYardName);
00171     UI_RegisterLinkedListText(TEXT_UFORECOVERY_CAPACITIES, recoveryYardCapacity);
00172 }
00173 
00178 static void UR_DialogStartStore_f (void)
00179 {
00180     installation_t *UFOYard = NULL;
00181     int idx;
00182     int i;
00183     int count = 0;
00184     date_t date;
00185 
00186     if (Cmd_Argc() < 2) {
00187         Com_Printf("Usage: %s <installationIDX>\n", Cmd_Argv(0));
00188         return;
00189     }
00190 
00191     idx = atoi(Cmd_Argv(1));
00192 
00193     for (i = 0; i < ccs.numInstallations; i++) {
00194         installation_t *installation = INS_GetFoundedInstallationByIDX(i);
00195 
00196         if (!installation)
00197             continue;
00198 
00199         if (installation->ufoCapacity.max <= 0
00200          || installation->ufoCapacity.max <= installation->ufoCapacity.cur)
00201             continue;
00202 
00203         if (count == idx) {
00204             UFOYard = installation;
00205             break;
00206         }
00207         count++;
00208     }
00209 
00210     if (!UFOYard)
00211         return;
00212 
00213     Com_sprintf(cp_messageBuffer, lengthof(cp_messageBuffer), _("Recovered %s from the battlefield. UFO is being transported to %s."),
00214             UFO_TypeToName(ufoRecovery.ufoTemplate->ufotype), UFOYard->name);
00215     MS_AddNewMessage(_("UFO Recovery"), cp_messageBuffer, qfalse, MSG_STANDARD, NULL);
00216     date = ccs.date;
00217     date.day += (int) RECOVERY_DELAY;
00218 
00219     US_StoreUFO(ufoRecovery.ufoTemplate, UFOYard, date, ufoRecovery.condition);
00220     UR_DialogRecoveryDone();
00221 }
00222 
00226 static void UR_DialogFillNations (void)
00227 {
00228     int i;
00229     linkedList_t *nationList = NULL;
00230 
00231     for (i = 0; i < ccs.numNations; i++) {
00232         const nation_t *nation = ufoRecovery.UFONations[i].nation;
00233         if (nation) {
00234             char row[512];
00235             Com_sprintf(row, lengthof(row), "%s\t\t\t%i\t\t%s", _(nation->name),
00236                 ufoRecovery.UFONations[i].price, NAT_GetHappinessString(nation));
00237             LIST_AddString(&nationList, row);
00238         }
00239     }
00240 
00241     UI_RegisterLinkedListText(TEXT_UFORECOVERY_NATIONS, nationList);
00242 }
00243 
00250 static int UR_CompareByName (ufoRecoveryNation_t *a, ufoRecoveryNation_t *b)
00251 {
00252     return strcmp(_(a->nation->name), _(b->nation->name));
00253 }
00254 
00264 static int UR_CompareByPrice (ufoRecoveryNation_t *a, ufoRecoveryNation_t *b)
00265 {
00266     if (a->price > b->price)
00267         return 1;
00268     if (a->price < b->price)
00269         return -1;
00270     return 0;
00271 }
00272 
00282 static int UR_CompareByHappiness (ufoRecoveryNation_t *a, ufoRecoveryNation_t *b)
00283 {
00284     const nationInfo_t *statsA = &a->nation->stats[0];
00285     const nationInfo_t *statsB = &b->nation->stats[0];
00286 
00287     if (statsA->happiness > statsB->happiness)
00288         return 1;
00289     if (statsA->happiness < statsB->happiness)
00290         return -1;
00291     return 0;
00292 }
00293 
00303 static void UR_SortNations (COMP_FUNCTION comp, qboolean order)
00304 {
00305     int i;
00306 
00307     for (i = 0; i < ccs.numNations; i++) {
00308         qboolean swapped = qfalse;
00309         int j;
00310 
00311         for (j = 0; j < ccs.numNations - 1; j++) {
00312             int value = (*comp)(&ufoRecovery.UFONations[j], &ufoRecovery.UFONations[j + 1]);
00313             ufoRecoveryNation_t tmp;
00314 
00315             if (order)
00316                 value *= -1;
00317             if (value > 0) {
00318                 /* swap nations */
00319                 tmp = ufoRecovery.UFONations[j];
00320                 ufoRecovery.UFONations[j] = ufoRecovery.UFONations[j + 1];
00321                 ufoRecovery.UFONations[j + 1] = tmp;
00322                 swapped = qtrue;
00323             }
00324         }
00325         if (!swapped)
00326             break;
00327     }
00328 }
00329 
00334 static COMP_FUNCTION UR_GetSortFunctionByColumn (ufoRecoveryNationOrder_t column)
00335 {
00336     switch (column) {
00337     case ORDER_NATION:
00338         return UR_CompareByName;
00339     case ORDER_PRICE:
00340         return UR_CompareByPrice;
00341     case ORDER_HAPPINESS:
00342         return UR_CompareByHappiness;
00343     default:
00344         Com_Printf("UR_DialogSortByColumn_f: Invalid sort option!\n");
00345         return NULL;
00346     }
00347 }
00348 
00353 static void UR_DialogInitSell_f (void)
00354 {
00355     int i;
00356 
00357     /* Do nothing if recovery process is finished. */
00358     if (ufoRecovery.recoveryDone)
00359         return;
00360     /* Do nothing without a ufoTemplate set */
00361     if (!ufoRecovery.ufoTemplate)
00362         return;
00363 
00364     for (i = 0; i < ccs.numNations; i++) {
00365         nation_t *nation = NAT_GetNationByIDX(i);
00366         int price;
00367 
00368         price = (int) (ufoRecovery.ufoTemplate->price * (.85f + frand() * .3f));
00369         /* Nation will pay less if corrupted */
00370         price = (int) (price * exp(-nation->stats[0].xviInfection / 20.0f));
00371 
00372         ufoRecovery.UFONations[i].nation = nation;
00373         ufoRecovery.UFONations[i].price = price;
00374     }
00375     UR_SortNations(UR_GetSortFunctionByColumn(ufoRecovery.sortedColumn), ufoRecovery.sortDescending);
00376     UR_DialogFillNations();
00377     UI_ExecuteConfunc("btnatsel disable");
00378 }
00379 
00383 static int UR_DialogGetCurrentNationIndex (void)
00384 {
00385     int i;
00386 
00387     for (i = 0; i < ccs.numNations; i++)
00388         if (ufoRecovery.UFONations[i].nation == ufoRecovery.nation)
00389             return i;
00390     return -1;
00391 }
00392 
00398 static ufoRecoveryNationOrder_t UR_GetOrderTypeByID (const char *id)
00399 {
00400     if (!id)
00401         return MAX_ORDER;
00402     if (!strcmp(id, "nation"))
00403         return ORDER_NATION;
00404     if (!strcmp(id, "price"))
00405         return ORDER_PRICE;
00406     if (!strcmp(id, "happiness"))
00407         return ORDER_HAPPINESS;
00408     return MAX_ORDER;
00409 }
00410 
00414 static void UR_DialogSortByColumn_f (void)
00415 {
00416     COMP_FUNCTION comp = 0;
00417     ufoRecoveryNationOrder_t column;
00418 
00419     if (Cmd_Argc() < 2) {
00420         Com_Printf("Usage: %s <nation|price|happiness>\n", Cmd_Argv(0));
00421         return;
00422     }
00423 
00424     column = UR_GetOrderTypeByID(Cmd_Argv(1));
00425     if (ufoRecovery.sortedColumn != column) {
00426         ufoRecovery.sortDescending = qfalse;
00427         ufoRecovery.sortedColumn = column;
00428     } else {
00429         ufoRecovery.sortDescending = !ufoRecovery.sortDescending;
00430     }
00431 
00432     comp = UR_GetSortFunctionByColumn(column);
00433     if (comp) {
00434         int index;
00435 
00436         UR_SortNations(comp, ufoRecovery.sortDescending);
00437         UR_DialogFillNations();
00438 
00439         /* changed line selection corresponding to current nation */
00440         index = UR_DialogGetCurrentNationIndex();
00441         if (index != -1)
00442             UI_ExecuteConfunc("cp_nationsel_select %d", index);
00443     }
00444 }
00445 
00451 static void UR_DialogSelectSellNation_f (void)
00452 {
00453     int num;
00454     nation_t *nation;
00455 
00456     if (Cmd_Argc() < 2) {
00457         Com_Printf("Usage: %s <nationid>\n", Cmd_Argv(0));
00458         return;
00459     }
00460 
00461     num = atoi(Cmd_Argv(1));
00462 
00463     /* don't do anything if index is higher than visible nations */
00464     if (0 > num || num >= ccs.numNations)
00465         return;
00466 
00467     nation = ufoRecovery.UFONations[num].nation;
00468 
00469     ufoRecovery.nation = nation;
00470     Com_DPrintf(DEBUG_CLIENT, "CP_UFORecoveryNationSelectPopup_f: picked nation: %s\n", nation->name);
00471 
00472     Cvar_Set("mission_recoverynation", _(nation->name));
00473     UI_ExecuteConfunc("btnatsel enable");
00474 }
00475 
00480 static void UR_DialogStartSell_f (void)
00481 {
00482     int price = -1;
00483     nation_t *nation;
00484     int i;
00485 
00486     if (!ufoRecovery.nation)
00487         return;
00488 
00489     nation = ufoRecovery.nation;
00490     assert(nation->name);
00491 
00492     i = UR_DialogGetCurrentNationIndex();
00493     price = ufoRecovery.UFONations[i].price;
00494 
00495     assert(price >= 0);
00496 #if 0
00497     if (ufoRecovery.selectedStorage) {
00498         Com_sprintf(cp_messageBuffer, sizeof(cp_messageBuffer), _("Sold previously recovered %s from %s to nation %s, gained %i credits."), UFO_TypeToName(
00499                 ufoRecovery.selectedStorage->ufoTemplate->ufotype), ufoRecovery.selectedStorage->base->name, _(nation->name), price);
00500     } else
00501 #endif
00502     {
00503         Com_sprintf(cp_messageBuffer, sizeof(cp_messageBuffer), _("Recovered %s from the battlefield. UFO sold to nation %s, gained %i credits."), UFO_TypeToName(
00504                 ufoRecovery.ufoTemplate->ufotype), _(nation->name), price);
00505     }
00506     MS_AddNewMessage(_("UFO Recovery"), cp_messageBuffer, qfalse, MSG_STANDARD, NULL);
00507     CL_UpdateCredits(ccs.credits + price);
00508 
00509     /* update nation happiness */
00510     for (i = 0; i < ccs.numNations; i++) {
00511         nation_t *nat = NAT_GetNationByIDX(i);
00512 
00513         assert(nat);
00514         if (nat == nation)
00515             /* nation is happy because it got the UFO */
00516             NAT_SetHappiness(nation, nation->stats[0].happiness + HAPPINESS_UFO_SALE_GAIN);
00517         else
00518             /* nation is unhappy because it wanted the UFO */
00519             NAT_SetHappiness(nat, nat->stats[0].happiness + HAPPINESS_UFO_SALE_LOSS);
00520     }
00521 
00522     /* UFO recovery process is done, disable buttons. */
00523     UR_DialogRecoveryDone();
00524 }
00525 
00526 
00527 /* === UFO Storing === */
00528 
00529 #ifdef DEBUG
00530 
00533 static void US_ListStoredUFOs_f (void)
00534 {
00535     storedUFO_t *ufo = NULL;
00536 
00537     while ((ufo = US_GetNext(ufo)) != NULL) {
00538         const base_t *prodBase = PR_ProductionBase(ufo->disassembly);
00539         dateLong_t date;
00540 
00541         Com_Printf("IDX: %i\n", ufo->idx);
00542         Com_Printf("id: %s\n", ufo->id);
00543         Com_Printf("stored at %s\n", (ufo->installation) ? ufo->installation->name : "NOWHERE");
00544 
00545         CL_DateConvertLong(&(ufo->arrive), &date);
00546         Com_Printf("arrived at: %i %s %02i, %02i:%02i\n", date.year,
00547         Date_GetMonthName(date.month - 1), date.day, date.hour, date.min);
00548 
00549         if (ufo->ufoTemplate->tech->base)
00550             Com_Printf("tech being researched at %s\n", ufo->ufoTemplate->tech->base->name);
00551         if (prodBase)
00552             Com_Printf("being disassembled at %s\n", prodBase->name);
00553     }
00554 }
00555 
00559 static void US_StoreUFO_f (void)
00560 {
00561     char ufoId[MAX_VAR];
00562     int installationIDX;
00563     installation_t *installation;
00564     aircraft_t *ufoType = NULL;
00565     int i;
00566 
00567     if (Cmd_Argc() <= 2) {
00568         Com_Printf("Usage: %s <ufoType> <installationIdx>\n", Cmd_Argv(0));
00569         return;
00570     }
00571 
00572     Q_strncpyz(ufoId, Cmd_Argv(1), sizeof(ufoId));
00573     installationIDX = atoi(Cmd_Argv(2));
00574 
00575     /* Get The UFO Yard */
00576     if (installationIDX < 0 || installationIDX >= MAX_INSTALLATIONS) {
00577         Com_Printf("US_StoreUFO_f: Invalid Installation index.\n");
00578         return;
00579     }
00580     installation = INS_GetFoundedInstallationByIDX(installationIDX);
00581     if (!installation) {
00582         Com_Printf("US_StoreUFO_f: There is no Installation: idx=%i.\n", installationIDX);
00583         return;
00584     }
00585 
00586     /* Get UFO Type */
00587     for (i = 0; i < ccs.numAircraftTemplates; i++) {
00588         if (strstr(ccs.aircraftTemplates[i].id, ufoId)) {
00589             ufoType = &ccs.aircraftTemplates[i];
00590             break;
00591         }
00592     }
00593     if (ufoType == NULL) {
00594         Com_Printf("US_StoreUFO_f: In valid UFO Id.\n");
00595         return;
00596     }
00597 
00598     US_StoreUFO(ufoType, installation, ccs.date, 1.0f);
00599 }
00600 
00604 static void US_RemoveStoredUFO_f (void)
00605 {
00606     if (Cmd_Argc() < 2) {
00607         Com_Printf("Usage: %s <idx>\n", Cmd_Argv(0));
00608         return;
00609     } else {
00610         const int idx = atoi(Cmd_Argv(1));
00611         storedUFO_t *storedUFO = US_GetStoredUFOByIDX(idx);
00612         if (!storedUFO) {
00613             Com_Printf("US_RemoveStoredUFO_f: No such ufo index.\n");
00614             return;
00615         }
00616         US_RemoveStoredUFO(storedUFO);
00617     }
00618 }
00619 
00620 #endif
00621 
00622 void UR_InitCallbacks (void)
00623 {
00624     Cmd_AddCommand("cp_uforecovery_init", UR_DialogInit_f, "Function to trigger UFO Recovered event");
00625     Cmd_AddCommand("cp_uforecovery_sell_init", UR_DialogInitSell_f, "Function to initialize sell recovered UFO to desired nation.");
00626     Cmd_AddCommand("cp_uforecovery_store_init", UR_DialogInitStore_f, "Function to initialize store recovered UFO in desired base.");
00627     Cmd_AddCommand("cp_uforecovery_nationlist_click", UR_DialogSelectSellNation_f, "Callback for recovery sell to nation list.");
00628     Cmd_AddCommand("cp_uforecovery_store_start", UR_DialogStartStore_f, "Function to start UFO recovery processing.");
00629     Cmd_AddCommand("cp_uforecovery_sell_start", UR_DialogStartSell_f, "Function to start UFO selling processing.");
00630     Cmd_AddCommand("cp_uforecovery_sort", UR_DialogSortByColumn_f, "Sorts nations and update ui state.");
00631 #ifdef DEBUG
00632     Cmd_AddCommand("debug_liststoredufos", US_ListStoredUFOs_f, "Debug function to list UFOs in Hangars.");
00633     Cmd_AddCommand("debug_storeufo", US_StoreUFO_f, "Debug function to Add UFO to Hangars.");
00634     Cmd_AddCommand("debug_removestoredufo", US_RemoveStoredUFO_f, "Debug function to Remove UFO from Hangars.");
00635 #endif
00636 }
00637 
00638 void UR_ShutdownCallbacks (void)
00639 {
00640     Cmd_RemoveCommand("cp_uforecovery_init");
00641     Cmd_RemoveCommand("cp_uforecovery_sell_init");
00642     Cmd_RemoveCommand("cp_uforecovery_store_init");
00643     Cmd_RemoveCommand("cp_uforecovery_nationlist_click");
00644     Cmd_RemoveCommand("cp_uforecovery_store_start");
00645     Cmd_RemoveCommand("cp_uforecovery_sell_start");
00646     Cmd_RemoveCommand("cp_uforecovery_sort");
00647 #ifdef DEBUG
00648     Cmd_RemoveCommand("debug_liststoredufos");
00649     Cmd_RemoveCommand("debug_storeufo");
00650     Cmd_RemoveCommand("debug_removestoredufo");
00651 #endif
00652 }
00653 

Generated by  doxygen 1.6.2