00001
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "../cl_shared.h"
00026 #include "../ui/ui_data.h"
00027 #include "../ui/ui_main.h"
00028 #include "cp_campaign.h"
00029 #include "cp_basedefence_callbacks.h"
00030 #include "cp_fightequip_callbacks.h"
00031 #include "cp_mapfightequip.h"
00032 #include "cp_ufo.h"
00033
00038 static aircraftItemType_t BDEF_GetItemTypeFromID (const char *type)
00039 {
00040 assert(type);
00041 if (!strcmp(type, "missile"))
00042 return AC_ITEM_BASE_MISSILE;
00043 else if (!strcmp(type, "laser"))
00044 return AC_ITEM_BASE_LASER;
00045 else {
00046 return MAX_ACITEMS;
00047 }
00048 }
00053 static const char *BDEF_GetIDFromItemType (aircraftItemType_t type)
00054 {
00055 switch (type) {
00056 case AC_ITEM_BASE_MISSILE:
00057 return "missile";
00058 case AC_ITEM_BASE_LASER:
00059 return "laser";
00060 default:
00061 return "unknown";
00062 }
00063 }
00064
00069 static void BDEF_UpdateAircraftItemList (const aircraftSlot_t *slot)
00070 {
00071 linkedList_t *itemList = NULL;
00072 technology_t **list;
00073
00074 assert(slot);
00075
00076
00077 list = AII_GetCraftitemTechsByType(slot->type);
00078
00079
00080 while (*list) {
00081 if (AIM_SelectableCraftItem(slot, *list))
00082 LIST_AddString(&itemList, _((*list)->name));
00083 list++;
00084 }
00085
00086
00087 UI_RegisterLinkedListText(TEXT_LIST, itemList);
00088 }
00089
00094 static void BDEF_SelectItem_f (void)
00095 {
00096 aircraftSlot_t *slot;
00097 installation_t* installation = INS_GetCurrentSelectedInstallation();
00098 base_t *base = B_GetCurrentSelectedBase();
00099 int bdefType;
00100 int slotIDX;
00101 int itemIDX;
00102
00103 if (Cmd_Argc() < 4) {
00104 Com_Printf("Usage: %s <type> <slotIDX> <itemIDX>\n", Cmd_Argv(0));
00105 return;
00106 }
00107
00108 bdefType = BDEF_GetItemTypeFromID(Cmd_Argv(1));
00109 slotIDX = atoi(Cmd_Argv(2));
00110 itemIDX = atoi(Cmd_Argv(3));
00111
00112 if (bdefType == MAX_ACITEMS) {
00113 Com_Printf("BDEF_AddItem_f: Invalid defence type.\n");
00114 return;
00115 }
00116
00117 if (slotIDX >= 0) {
00118 const objDef_t *item;
00119 slot = (installation) ? BDEF_GetInstallationSlotByIDX(installation, bdefType, slotIDX) : BDEF_GetBaseSlotByIDX(base, bdefType, slotIDX);
00120 item = (slot) ? ( (slot->nextItem) ? slot->nextItem : slot->item ) : NULL;
00121 UP_AircraftItemDescription(item);
00122 } else if (itemIDX >= 0) {
00123 technology_t **list;
00124 technology_t *itemTech = NULL;
00125 int i = 0;
00126
00127 slot = (installation) ? BDEF_GetInstallationSlotByIDX(installation, bdefType, 0) : BDEF_GetBaseSlotByIDX(base, bdefType, 0);
00128 list = AII_GetCraftitemTechsByType(bdefType);
00129 while (*list && i <= itemIDX) {
00130 if (AIM_SelectableCraftItem(slot, *list)) {
00131 itemTech = *list;
00132 i++;
00133 break;
00134 }
00135 list++;
00136 }
00137 UP_AircraftItemDescription((itemTech) ? INVSH_GetItemByIDSilent(itemTech->provides) : NULL);
00138 } else {
00139 Com_Printf("BDEF_AddItem_f: Invalid item-space.\n");
00140 }
00141 }
00142
00143 static void BDEF_AddSlotToSlotList (const aircraftSlot_t *slot, linkedList_t **slotList)
00144 {
00145 char defBuffer[512];
00146 const int size = LIST_Count(*slotList) + 1;
00147 if (!slot->item) {
00148 Com_sprintf(defBuffer, lengthof(defBuffer), _("%i: empty"), size);
00149 LIST_AddString(slotList, defBuffer);
00150 } else {
00151 const technology_t *tech;
00152 const char *status;
00153 if (!slot->installationTime)
00154 status = _("Working");
00155 else if (slot->installationTime > 0)
00156 status = _("Installing");
00157 else if (slot->nextItem)
00158 status = _("Replacing");
00159 else
00160 status = _("Removing");
00161
00162 if (slot->nextItem != NULL)
00163 tech = RS_GetTechForItem(slot->nextItem);
00164 else
00165 tech = RS_GetTechForItem(slot->item);
00166
00167 Com_sprintf(defBuffer, lengthof(defBuffer), "%i: %s (%s)", size, _(tech->name), status);
00168 LIST_AddString(slotList, defBuffer);
00169 }
00170 }
00171
00172 static void BDEF_FillSlotList (const baseWeapon_t *batteries, int maxBatteries, linkedList_t **slotList)
00173 {
00174 int i;
00175
00176 BDEF_UpdateAircraftItemList(&batteries->slot);
00177
00178 for (i = 0; i < maxBatteries; i++, batteries++) {
00179 const aircraftSlot_t *slot = &batteries->slot;
00180 BDEF_AddSlotToSlotList(slot, slotList);
00181 }
00182 }
00183
00188 static void BDEF_BaseDefenceMenuUpdate_f (void)
00189 {
00190 char type[MAX_VAR];
00191 base_t *base = B_GetCurrentSelectedBase();
00192 installation_t *installation = INS_GetCurrentSelectedInstallation();
00193 aircraftItemType_t bdefType;
00194 linkedList_t *slotList = NULL;
00195 const qboolean missileResearched = RS_IsResearched_ptr(RS_GetTechByID("rs_building_missile"));
00196 const qboolean laserResearched = RS_IsResearched_ptr(RS_GetTechByID("rs_building_laser"));
00197
00198 if (Cmd_Argc() != 2)
00199 type[0] = '\0';
00200 else
00201 Q_strncpyz(type, Cmd_Argv(1), sizeof(type));
00202
00203
00204 UI_ResetData(TEXT_BASEDEFENCE_LIST);
00205 UI_ResetData(TEXT_LIST);
00206 UI_ResetData(TEXT_ITEMDESCRIPTION);
00207
00208
00209 if (!base && !installation)
00210 return;
00211
00212
00213 if (base && installation) {
00214 Com_Printf("BDEF_BaseDefenceMenuUpdate_f: both the base and installation are set. This shouldn't happen: you shouldn't be in this function.\n");
00215 return;
00216 }
00217
00218 Cvar_Set("mn_target", _("None"));
00219 Cmd_ExecuteString("setautofire disable");
00220 if (installation) {
00222 if (installation->numBatteries) {
00223 Cmd_ExecuteString(va("setautofire %i", installation->batteries[0].autofire));
00224
00225 if (installation->batteries[0].target)
00226 Cvar_Set("mn_target", UFO_AircraftToIDOnGeoscape(installation->batteries[0].target));
00227 }
00228 } else if (base) {
00229 qboolean autofire = qfalse;
00231 if (base->numBatteries) {
00232 autofire |= base->batteries[0].autofire;
00233 if (base->batteries[0].target)
00234 Cvar_Set("mn_target", UFO_AircraftToIDOnGeoscape(base->batteries[0].target));
00235 }
00236 if (base->numLasers) {
00237 autofire |= base->lasers[0].autofire;
00238 if (base->lasers[0].target && !base->batteries[0].target)
00239 Cvar_Set("mn_target", UFO_AircraftToIDOnGeoscape(base->lasers[0].target));
00240 }
00241 if (base->numBatteries || base->numLasers)
00242 Cmd_ExecuteString(va("setautofire %i", autofire));
00243 }
00244
00245
00246 if (base) {
00247 UI_ExecuteConfunc("set_defencetypes %s %s",
00248 (!missileResearched) ? "na" : (base && base->numBatteries > 0) ? "enable" : "disable",
00249 (!laserResearched) ? "na" : (base && base->numLasers > 0) ? "enable" : "disable");
00250 } else if (installation) {
00251 UI_ExecuteConfunc("set_defencetypes %s %s",
00252 (!missileResearched) ? "na" : (installation && installation->installationStatus == INSTALLATION_WORKING
00253 && installation->numBatteries > 0) ? "enable" : "disable", "na");
00254 }
00255
00256 if (!strcmp(type, "missile"))
00257 bdefType = AC_ITEM_BASE_MISSILE;
00258 else if (!strcmp(type, "laser"))
00259 bdefType = AC_ITEM_BASE_LASER;
00260 else
00261 return;
00262
00263
00264 if (base) {
00265 if (base->numBatteries + base->numLasers < 1) {
00266 Com_Printf("BDEF_BaseDefenceMenuUpdate_f: there is no defence battery in this base: you shouldn't be in this function.\n");
00267 return;
00268 }
00269 } else if (installation) {
00270 if (installation->installationStatus != INSTALLATION_WORKING) {
00271 Com_Printf("BDEF_BaseDefenceMenuUpdate_f: installation isn't working: you shouldn't be in this function.\n");
00272 return;
00273 } else if (installation->installationTemplate->maxBatteries < 1) {
00274 Com_Printf("BDEF_BaseDefenceMenuUpdate_f: there is no defence battery in this installation: you shouldn't be in this function.\n");
00275 return;
00276 }
00277 }
00278
00279 if (installation) {
00280
00281 if (installation->installationTemplate->maxBatteries == 0) {
00282 LIST_AddString(&slotList, _("No defence of this type in this installation"));
00283 } else {
00284 BDEF_FillSlotList(installation->batteries, installation->installationTemplate->maxBatteries, &slotList);
00285 }
00286 } else if (bdefType == AC_ITEM_BASE_MISSILE) {
00287
00288 if (base->numBatteries == 0) {
00289 LIST_AddString(&slotList, _("No defence of this type in this base"));
00290 } else {
00291 BDEF_FillSlotList(base->batteries, base->numBatteries, &slotList);
00292 }
00293 } else if (bdefType == AC_ITEM_BASE_LASER) {
00294
00295 if (base->numLasers == 0) {
00296 LIST_AddString(&slotList, _("No defence of this type in this base"));
00297 } else {
00298 BDEF_FillSlotList(base->lasers, base->numLasers, &slotList);
00299 }
00300 } else {
00301 Com_Printf("BDEF_BaseDefenceMenuUpdate_f: unknown bdefType.\n");
00302 return;
00303 }
00304 UI_RegisterLinkedListText(TEXT_BASEDEFENCE_LIST, slotList);
00305 }
00306
00310 static void BDEF_AddItem_f (void)
00311 {
00312 aircraftSlot_t *slot;
00313 installation_t* installation = INS_GetCurrentSelectedInstallation();
00314 base_t *base = B_GetCurrentSelectedBase();
00315 technology_t **list;
00316 technology_t *itemTech = NULL;
00317 int bdefType;
00318 int slotIDX;
00319
00320 if ((!base && !installation) || (base && installation)) {
00321 Com_Printf("Exiting early base and install both true or both false\n");
00322 return;
00323 }
00324
00325 if (Cmd_Argc() < 3) {
00326 Com_Printf("Usage: %s <type> <slotIDX>\n", Cmd_Argv(0));
00327 return;
00328 }
00329
00330 bdefType = BDEF_GetItemTypeFromID(Cmd_Argv(1));
00331 slotIDX = atoi(Cmd_Argv(2));
00332
00333 if (bdefType == MAX_ACITEMS) {
00334 Com_Printf("BDEF_AddItem_f: Invalid defence type.\n");
00335 return;
00336 }
00337
00338 slot = (installation) ? BDEF_GetInstallationSlotByIDX(installation, bdefType, slotIDX) : BDEF_GetBaseSlotByIDX(base, bdefType,slotIDX);
00339
00340 if (!slot) {
00341 Com_Printf("BDEF_AddItem_f: Invalid slot.\n");
00342 return;
00343 }
00344
00345 list = AII_GetCraftitemTechsByType(bdefType);
00346 while (*list) {
00347 if (AIM_SelectableCraftItem(slot, *list)) {
00348 itemTech = *list;
00349 break;
00350 }
00351 list++;
00352 }
00353
00354 if (!itemTech)
00355 return;
00356
00357 if (!slot->nextItem) {
00358
00359
00360 if (!slot->item || (slot->item && slot->installationTime == slot->item->craftitem.installationTime)) {
00361 AII_RemoveItemFromSlot(base, slot, qfalse);
00362 AII_AddItemToSlot(base, itemTech, slot, qfalse);
00363 AII_AutoAddAmmo(slot);
00364 } else if (slot->item == INVSH_GetItemByID(itemTech->provides)) {
00365
00366 if (slot->installationTime == -slot->item->craftitem.installationTime) {
00367
00368 slot->installationTime = 0;
00369 } else if (!slot->installationTime) {
00370
00371 }
00372 } else {
00373
00374 slot->installationTime = -slot->item->craftitem.installationTime;
00375 AII_AddItemToSlot(base, itemTech, slot, qtrue);
00376 AII_AutoAddAmmo(slot);
00377 }
00378 } else {
00379
00380 AII_RemoveItemFromSlot(base, slot, qfalse);
00381 AII_AddItemToSlot(base, itemTech, slot, qtrue);
00382 AII_AutoAddAmmo(slot);
00383 }
00384
00385
00386 Cmd_ExecuteString(va("basedef_updatemenu %s", BDEF_GetIDFromItemType(slot->type)));
00387 }
00388
00392 static void BDEF_RemoveItem_f (void)
00393 {
00394 aircraftSlot_t *slot;
00395 installation_t* installation = INS_GetCurrentSelectedInstallation();
00396 base_t *base = B_GetCurrentSelectedBase();
00397 int bdefType;
00398 int slotIDX;
00399
00400 if ((!base && !installation) || (base && installation)) {
00401 Com_Printf("Exiting early base and install both true or both false\n");
00402 return;
00403 }
00404
00405 if (Cmd_Argc() < 3) {
00406 Com_Printf("Usage: %s <type> <slotIDX>\n", Cmd_Argv(0));
00407 return;
00408 }
00409
00410 bdefType = BDEF_GetItemTypeFromID(Cmd_Argv(1));
00411 slotIDX = atoi(Cmd_Argv(2));
00412
00413 if (bdefType == MAX_ACITEMS) {
00414 Com_Printf("BDEF_AddItem_f: Invalid defence type.\n");
00415 return;
00416 }
00417
00418 slot = (installation) ? BDEF_GetInstallationSlotByIDX(installation, bdefType, slotIDX) : BDEF_GetBaseSlotByIDX(base, bdefType,slotIDX);
00419
00420 if (!slot) {
00421 Com_Printf("BDEF_AddItem_f: Invalid slot.\n");
00422 return;
00423 }
00424
00425 if (!slot->item)
00426 return;
00427
00428 if (!slot->nextItem) {
00429
00430
00431 if (slot->installationTime < slot->item->craftitem.installationTime) {
00432 slot->installationTime = -slot->item->craftitem.installationTime;
00433 AII_RemoveItemFromSlot(base, slot, qtrue);
00434 } else {
00435 AII_RemoveItemFromSlot(base, slot, qfalse);
00436 }
00437 } else {
00438
00439
00440 AII_RemoveItemFromSlot(base, slot, qfalse);
00441
00442 if (slot->installationTime == -slot->item->craftitem.installationTime) {
00443 slot->installationTime = 0;
00444 }
00445 }
00446 Cmd_ExecuteString(va("basedef_updatemenu %s", BDEF_GetIDFromItemType(slot->type)));
00447 }
00448
00456 static void BDEF_RemoveBattery_f (void)
00457 {
00458 int basedefType, baseIdx;
00459 base_t *base;
00460
00461 if (Cmd_Argc() < 3) {
00462 Com_Printf("Usage: %s <basedefType> <baseIdx>", Cmd_Argv(0));
00463 return;
00464 } else {
00465 char type[MAX_VAR];
00466
00467 Q_strncpyz(type, Cmd_Argv(1), sizeof(type));
00468 if (!strcmp(type, "missile"))
00469 basedefType = BASEDEF_MISSILE;
00470 else if (!strcmp(type, "laser"))
00471 basedefType = BASEDEF_LASER;
00472 else if (!strcmp(type, "random"))
00473 basedefType = BASEDEF_RANDOM;
00474 else
00475 return;
00476 baseIdx = atoi(Cmd_Argv(2));
00477 }
00478
00479
00480 if (baseIdx < 0 || baseIdx >= ccs.numBases) {
00481 Com_Printf("BDEF_RemoveBattery_f: baseIdx %i doesn't exist: there is only %i bases in game.\n", baseIdx, ccs.numBases);
00482 return;
00483 }
00484
00485 base = B_GetFoundedBaseByIDX(baseIdx);
00486 if (!base) {
00487 Com_Printf("BDEF_RemoveBattery_f: baseIdx %i is not founded.\n", baseIdx);
00488 return;
00489 }
00490
00491 if (basedefType == BASEDEF_RANDOM) {
00492
00493 if (base->numBatteries <= 0 && base->numLasers <= 0) {
00494 Com_Printf("No base defence to destroy\n");
00495 return;
00496 } else if (base->numBatteries <= 0) {
00497
00498 basedefType = BASEDEF_LASER;
00499 } else if (base->numLasers <= 0) {
00500
00501 basedefType = BASEDEF_MISSILE;
00502 } else {
00503
00504 basedefType = rand() % 2 + BASEDEF_MISSILE;
00505 }
00506 } else {
00507
00508 int type, max;
00509 int workingNum;
00510 building_t *building;
00511
00512 switch (basedefType) {
00513 case BASEDEF_MISSILE:
00514 type = B_DEFENCE_MISSILE;
00515 max = base->numBatteries;
00516 break;
00517 case BASEDEF_LASER:
00518 type = B_DEFENCE_LASER;
00519 max = base->numLasers;
00520 break;
00521 default:
00522 Com_Printf("BDEF_RemoveBattery_f: base defence type %i doesn't exist.\n", basedefType);
00523 return;
00524 }
00525
00526 building = NULL;
00527 workingNum = 0;
00528 while ((building = B_GetNextBuildingByType(base, building, type)))
00529 if (building->buildingStatus == B_STATUS_WORKING)
00530 workingNum++;
00531
00532 if (workingNum == max) {
00533
00534 return;
00535 } else if (workingNum != max - 1) {
00536
00537 Com_Printf("BDEF_RemoveBattery_f: Error while checking number of batteries (%i instead of %i) in base '%s'.\n",
00538 workingNum, max, base->name);
00539 return;
00540 }
00541
00542
00543 }
00544
00545 BDEF_RemoveBattery(base, basedefType, -1);
00546 }
00547
00551 static void BDEF_AddBattery_f (void)
00552 {
00553 int basedefType, baseIdx;
00554
00555 if (Cmd_Argc() < 3) {
00556 Com_Printf("Usage: %s <basedefType> <baseIdx>", Cmd_Argv(0));
00557 return;
00558 } else {
00559 char type[MAX_VAR];
00560
00561 Q_strncpyz(type, Cmd_Argv(1), sizeof(type));
00562 if (!strcmp(type, "missile"))
00563 basedefType = BASEDEF_MISSILE;
00564 else if (!strcmp(type, "laser"))
00565 basedefType = BASEDEF_LASER;
00566 else if (!strcmp(type, "random"))
00567 basedefType = BASEDEF_RANDOM;
00568 else
00569 return;
00570 baseIdx = atoi(Cmd_Argv(2));
00571 }
00572
00573
00574 if (baseIdx < 0 || baseIdx >= ccs.numBases) {
00575 Com_Printf("BDEF_AddBattery_f: baseIdx %i doesn't exist: there is only %i bases in game.\n", baseIdx, ccs.numBases);
00576 return;
00577 }
00578
00579
00580 if (basedefType != BASEDEF_MISSILE && basedefType != BASEDEF_LASER) {
00581 Com_Printf("BDEF_AddBattery_f: base defence type %i doesn't exist.\n", basedefType);
00582 return;
00583 }
00584
00585 BDEF_AddBattery(basedefType, B_GetBaseByIDX(baseIdx));
00586 }
00587
00592 static void BDEF_ChangeAutoFire (void)
00593 {
00594 installation_t* installation = INS_GetCurrentSelectedInstallation();
00595 base_t *base = B_GetCurrentSelectedBase();
00596 int i;
00597
00598 if (!base && !installation)
00599 return;
00600 if (base && installation)
00601 return;
00602 if (Cmd_Argc() < 2)
00603 return;
00604
00605 if (base) {
00606 for (i = 0; i < base->numBatteries; i++)
00607 base->batteries[i].autofire = atoi(Cmd_Argv(1));
00608 for (i = 0; i < base->numLasers; i++)
00609 base->lasers[i].autofire = atoi(Cmd_Argv(1));
00610 } else if (installation)
00611 for (i = 0; i < installation->numBatteries; i++)
00612 installation->batteries[i].autofire = atoi(Cmd_Argv(1));
00613 }
00614
00615 void BDEF_InitCallbacks (void)
00616 {
00617 Cmd_AddCommand("add_battery", BDEF_AddBattery_f, "Add a new battery to base");
00618 Cmd_AddCommand("remove_battery", BDEF_RemoveBattery_f, "Remove a battery from base");
00619 Cmd_AddCommand("basedef_updatemenu", BDEF_BaseDefenceMenuUpdate_f, "Inits base defence menu");
00620 Cmd_AddCommand("basedef_selectitem", BDEF_SelectItem_f, NULL);
00621 Cmd_AddCommand("basedef_additem", BDEF_AddItem_f, "Add item to slot");
00622 Cmd_AddCommand("basedef_removeitem", BDEF_RemoveItem_f, "Remove item from slot");
00623 Cmd_AddCommand("basedef_autofire", BDEF_ChangeAutoFire, "Change autofire option for selected defence system");
00624 }
00625
00626 void BDEF_ShutdownCallbacks (void)
00627 {
00628 Cmd_RemoveCommand("add_battery");
00629 Cmd_RemoveCommand("remove_battery");
00630 Cmd_RemoveCommand("basedef_updatemenu");
00631 Cmd_RemoveCommand("basedef_selectitem");
00632 Cmd_RemoveCommand("basedef_additem");
00633 Cmd_RemoveCommand("basedef_removeitem");
00634 Cmd_RemoveCommand("basedef_autofire");
00635 }