00001
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
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
00111 ccs.missionResults.recovery = qtrue;
00112 ccs.missionResults.ufoCondition = cond;
00113 ccs.missionResults.crashsite = (cond < 1);
00114 ccs.missionResults.ufotype = ufoCraft->ufotype;
00115
00116 Cvar_SetValue("mission_uforecovered", 1);
00117
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
00140 if (ufoRecovery.recoveryDone)
00141 return;
00142
00143
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
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
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
00358 if (ufoRecovery.recoveryDone)
00359 return;
00360
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
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
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
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
00510 for (i = 0; i < ccs.numNations; i++) {
00511 nation_t *nat = NAT_GetNationByIDX(i);
00512
00513 assert(nat);
00514 if (nat == nation)
00515
00516 NAT_SetHappiness(nation, nation->stats[0].happiness + HAPPINESS_UFO_SALE_GAIN);
00517 else
00518
00519 NAT_SetHappiness(nat, nat->stats[0].happiness + HAPPINESS_UFO_SALE_LOSS);
00520 }
00521
00522
00523 UR_DialogRecoveryDone();
00524 }
00525
00526
00527
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
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
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