UFO: Alien Invasion
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
cp_fightequip_callbacks.cpp
Go to the documentation of this file.
1 
6 /*
7 Copyright (C) 2002-2020 UFO: Alien Invasion.
8 
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License
11 as published by the Free Software Foundation; either version 2
12 of the License, or (at your option) any later version.
13 
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 
18 See the GNU General Public License for more details.
19 
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 
24 */
25 #include "../../cl_shared.h"
26 #include "../../ui/ui_dataids.h"
27 #include "cp_campaign.h"
29 #include "cp_mapfightequip.h"
30 #include "cp_ufo.h"
31 
41 static void AIM_CheckAirequipID (void)
42 {
43  switch (airequipID) {
44  case AC_ITEM_AMMO:
45  case AC_ITEM_WEAPON:
46  case AC_ITEM_SHIELD:
48  return;
49  default:
51  break;
52  }
53 }
54 
60 static void AIM_CheckAirequipSelectedSlot (const aircraft_t* aircraft)
61 {
62  switch (airequipID) {
63  case AC_ITEM_AMMO:
64  case AC_ITEM_WEAPON:
65  if (airequipSelectedSlot >= aircraft->maxWeapons) {
67  }
68  break;
70  if (airequipSelectedSlot >= aircraft->maxElectronics) {
72  }
73  break;
74  default:
75  break;
76  }
77 }
78 
87 {
88  aircraftSlot_t* slot;
89 
91  switch (type) {
92  case AC_ITEM_SHIELD:
93  slot = &aircraft->shield;
94  break;
96  slot = aircraft->electronics + airequipSelectedSlot;
97  break;
98  case AC_ITEM_AMMO:
99  case AC_ITEM_WEAPON:
100  slot = aircraft->weapons + airequipSelectedSlot;
101  break;
102  default:
103  cgi->Com_Printf("AII_SelectAircraftSlot: Unknown airequipID: %i\n", type);
104  return nullptr;
105  }
106 
107  return slot;
108 }
109 
115 {
116  assert(slot);
117 
118  if (airequipSelectedZone == ZONE_AMMO && airequipID < AC_ITEM_AMMO && airequipID > AC_ITEM_WEAPON) {
119  /* you can select ammo only for weapons and ammo */
121  }
122 
123  /* You can choose an ammo only if a weapon has already been selected */
124  if (airequipID >= AC_ITEM_AMMO && !slot->item) {
126  }
127 }
128 
132 static inline const char* AIM_AircraftItemtypeName (const int equiptype)
133 {
134  switch (equiptype) {
135  case AC_ITEM_WEAPON:
136  return _("Weapons");
137  case AC_ITEM_SHIELD:
138  return _("Armour");
139  case AC_ITEM_ELECTRONICS:
140  return _("Items");
141  case AC_ITEM_AMMO:
142  /* ammo - only available from weapons */
143  return _("Ammo");
144  default:
145  return _("Unknown");
146  }
147 }
148 
152 static bool AIM_CrafttypeFilter (const base_t* base, aircraftItemType_t filterType, const technology_t* tech)
153 {
154  const objDef_t* item;
155  if (!base)
156  return false;
157 
158  if (!RS_IsResearched_ptr(tech))
159  return false;
160 
161  item = INVSH_GetItemByID(tech->provides);
162  if (!item)
163  return false;
164  if (item->isVirtual)
165  return false;
166  if (!B_BaseHasItem(base, item))
167  return false;
168 
169  /* filter by type: special case for ammo because more than 1 type is an ammo type */
170  if (filterType != AC_ITEM_AMMO) {
171  if (item->craftitem.type != filterType)
172  return false;
173  } else {
174  if (item->craftitem.type < AC_ITEM_AMMO)
175  return false;
176  }
177 
178  /* you can't install an item that does not have an installation time (alien item)
179  * except for ammo which does not have installation time */
180  if (item->craftitem.installationTime == -1 && filterType >= AC_ITEM_AMMO)
181  return false;
182 
183  return true;
184 }
185 
191 {
192  linkedList_t* amountList = nullptr;
193  technology_t** techList;
194  technology_t** currentTech;
195  const base_t* base = slot->aircraft->homebase;
196  int count = 0;
197  uiNode_t* AIM_items = nullptr;
198 
199  /* Add all items corresponding to airequipID to list */
201 
202  /* Count only those which are researched to buffer */
203  currentTech = techList;
204  while (*currentTech) {
205  if (AIM_CrafttypeFilter(base, airequipID, *currentTech))
206  count++;
207  currentTech++;
208  }
209 
210  /* List only those which are researched to buffer */
211  currentTech = techList;
212  while (*currentTech) {
213  if (AIM_CrafttypeFilter(base, airequipID, *currentTech)) {
214  const objDef_t* item = INVSH_GetItemByID((*currentTech)->provides);
215  const int amount = B_ItemInBase(item, base);
216 
217  cgi->LIST_AddString(&amountList, va("%d", amount));
218  uiNode_t* option = cgi->UI_AddOption(&AIM_items, (*currentTech)->name, _((*currentTech)->name), va("%d", (*currentTech)->idx));
219  if (!AIM_SelectableCraftItem(slot, *currentTech))
220  option->disabled = true;
221  }
222  currentTech++;
223  }
224 
225  cgi->UI_RegisterOption(TEXT_LIST, AIM_items);
226  cgi->UI_RegisterLinkedListText(TEXT_LIST2, amountList);
227 }
228 
233 static void AIM_DrawAircraftSlots (const aircraft_t* aircraft)
234 {
235  /* initialise model cvars */
236  for (int i = 0; i < AIR_POSITIONS_MAX; i++)
237  cgi->Cvar_Set(va("mn_aircraft_item_model_slot%i", i), "");
238 
239  for (int i = 0; i < AIR_POSITIONS_MAX; i++) {
240  const aircraftSlot_t* slot;
241  int max;
242 
243  /* Default value */
244  cgi->UI_ExecuteConfunc("airequip_display_slot %i 0", i);
245 
246  /* Draw available slots */
247  switch (airequipID) {
248  case AC_ITEM_AMMO:
249  case AC_ITEM_WEAPON:
250  max = aircraft->maxWeapons;
251  slot = aircraft->weapons;
252  break;
253  case AC_ITEM_ELECTRONICS:
254  max = aircraft->maxElectronics;
255  slot = aircraft->electronics;
256  break;
257  /* do nothing for shield: there is only one slot */
258  default:
259  continue;
260  }
261  for (int j = 0; j < max; j++, slot++) {
262  /* check if one of the aircraft slots is at this position */
263  if (slot->pos == i) {
264  /* draw in white if this is the selected slot */
265  if (j == airequipSelectedSlot) {
266  cgi->UI_ExecuteConfunc("airequip_display_slot %i 2", i);
267  } else {
268  cgi->UI_ExecuteConfunc("airequip_display_slot %i 1", i);
269  }
270  if (slot->item) {
271  cgi->Cvar_Set(va("mn_aircraft_item_model_slot%i", i), "%s", RS_GetTechForItem(slot->item)->mdl);
272  } else {
273  cgi->Cvar_Set(va("mn_aircraft_item_model_slot%i", i), "");
274  }
275  }
276  }
277  }
278 }
279 
285 static inline void AIM_EmphazeAmmoSlotText (void)
286 {
287  cgi->UI_ExecuteConfunc("airequip_zone2_color \"1 0 0 1\"");
288 }
289 
295 static inline void AIM_NoEmphazeAmmoSlotText (void)
296 {
297  cgi->UI_ExecuteConfunc("airequip_zone2_color \"1 1 1 1\"");
298 }
299 
300 static void AIM_AircraftEquipMenuUpdate (void)
301 {
302  static char smallbuffer1[256];
303  static char smallbuffer2[128];
304  const char* typeName;
305  aircraft_t* aircraft;
306  aircraftSlot_t* slot;
308 
309  if (!base)
310  return;
311 
312  /* don't let old links appear on this menu */
313  cgi->UI_ResetData(TEXT_AIREQUIP_1);
314  cgi->UI_ResetData(TEXT_AIREQUIP_2);
315  cgi->UI_ResetData(TEXT_ITEMDESCRIPTION);
316  cgi->UI_ResetData(TEXT_LIST);
317 
318  aircraft = base->aircraftCurrent;
319 
320  assert(aircraft);
321 
322  /* Check that airequipSelectedSlot corresponds to an existing slot for this aircraft */
324 
325  /* Select slot */
326  slot = AII_SelectAircraftSlot(aircraft, airequipID);
327 
328  /* Check that the selected zone is OK */
330 
331  /* Fill the list of item you can equip your aircraft with */
333 
334  cgi->Cvar_Set("mn_equip_itemtype_name", "%s", AIM_AircraftItemtypeName(airequipID));
335  switch (airequipID) {
336  case AC_ITEM_ELECTRONICS:
337  typeName = "item";
338  break;
339  case AC_ITEM_SHIELD:
340  typeName = "armour";
341  break;
342  case AC_ITEM_AMMO:
343  typeName = "ammo";
344  break;
345  case AC_ITEM_WEAPON:
346  typeName = "weapon";
347  break;
348  default:
349  typeName = "unknown";
350  break;
351  }
352  cgi->Cvar_Set("mn_equip_itemtype", "%s", typeName);
353 
354  /* First slot: item currently assigned */
355  if (!slot->item) {
356  Com_sprintf(smallbuffer1, sizeof(smallbuffer1), "%s", _("No item assigned.\n"));
357  Q_strcat(smallbuffer1, sizeof(smallbuffer1), _("This slot is for %s or smaller items."),
358  AII_WeightToName(slot->size));
359  } else {
360  technology_t* itemTech = RS_GetTechForItem(slot->item);
361  technology_t* nextItemTech = slot->nextItem ? RS_GetTechForItem(slot->nextItem) : nullptr;
362  /* Print next item if we are removing item currently installed and a new item has been added. */
363  Com_sprintf(smallbuffer1, sizeof(smallbuffer1), "%s\n", slot->nextItem ? _(nextItemTech->name) : _(itemTech->name));
364  if (!slot->installationTime) {
365  Q_strcat(smallbuffer1, sizeof(smallbuffer1), _("This item is functional.\n"));
366  } else if (slot->installationTime > 0) {
367  Q_strcat(smallbuffer1, sizeof(smallbuffer1), ngettext("This item will be installed in %i hour.\n",
368  "This item will be installed in %i hours.\n", slot->installationTime), slot->installationTime);
369  } else if (slot->nextItem) {
370  Q_strcat(smallbuffer1, sizeof(smallbuffer1), ngettext("%s will be removed in %i hour.\n", "%s will be removed in %i hours.\n",
371  -slot->installationTime), _(itemTech->name), -slot->installationTime);
372  Q_strcat(smallbuffer1, sizeof(smallbuffer1), ngettext("%s will be installed in %i hour.\n",
373  "%s will be installed in %i hours.\n", slot->nextItem->craftitem.installationTime - slot->installationTime),
374  _(nextItemTech->name), slot->nextItem->craftitem.installationTime - slot->installationTime);
375  } else {
376  Q_strcat(smallbuffer1, sizeof(smallbuffer1), ngettext("This item will be removed in %i hour.\n",
377  "This item will be removed in %i hours.\n", -slot->installationTime), -slot->installationTime);
378  }
379  }
380  cgi->UI_RegisterText(TEXT_AIREQUIP_1, smallbuffer1);
381 
382  /* Second slot: ammo slot (only used for weapons) */
383  if ((airequipID == AC_ITEM_WEAPON || airequipID == AC_ITEM_AMMO) && slot->item) {
384  if (!slot->ammo) {
386  Com_sprintf(smallbuffer2, sizeof(smallbuffer2), "%s", _("No ammo assigned to this weapon."));
387  } else {
388  const objDef_t* ammo = slot->nextAmmo ? slot->nextAmmo : slot->ammo;
389  const technology_t* tech = RS_GetTechForItem(ammo);
391  if (!ammo->isVirtual)
392  Q_strncpyz(smallbuffer2, _(tech->name), sizeof(smallbuffer2));
393  else
394  Q_strncpyz(smallbuffer2, _("No ammo needed"), sizeof(smallbuffer2));
395  }
396  } else
397  *smallbuffer2 = '\0';
398 
399  cgi->UI_RegisterText(TEXT_AIREQUIP_2, smallbuffer2);
400 
401  /* Draw existing slots for this aircraft */
402  AIM_DrawAircraftSlots(aircraft);
403 }
404 
405 #define AIM_LOADING_OK 0
406 #define AIM_LOADING_NOSLOTSELECTED 1
407 #define AIM_LOADING_NOTECHNOLOGYSELECTED 2
408 #define AIM_LOADING_ALIENTECH 3
409 #define AIM_LOADING_TECHNOLOGYNOTRESEARCHED 4
410 #define AIM_LOADING_TOOHEAVY 5
411 #define AIM_LOADING_UNKNOWNPROBLEM 6
412 #define AIM_LOADING_NOWEAPON 7
413 #define AIM_LOADING_NOTUSABLEWITHWEAPON 8
414 
421 static int AIM_CheckTechnologyIntoSlot (const aircraftSlot_t* slot, const technology_t* tech)
422 {
423  const objDef_t* item;
424 
425  if (!tech)
427 
428  if (!slot)
430 
431  if (!RS_IsResearched_ptr(tech))
433 
434  item = INVSH_GetItemByID(tech->provides);
435  if (!item)
437 
438  if (item->craftitem.type >= AC_ITEM_AMMO) {
439  const objDef_t* weapon = slot->item;
440  int k;
441  if (slot->nextItem != nullptr)
442  weapon = slot->nextItem;
443 
444  if (weapon == nullptr)
445  return AIM_LOADING_NOWEAPON;
446 
447  /* Is the ammo is usable with the slot */
448  for (k = 0; k < weapon->numAmmos; k++) {
449  const objDef_t* usable = weapon->ammos[k];
450  if (usable && item->idx == usable->idx)
451  break;
452  }
453  if (k >= weapon->numAmmos)
455 
456 #if 0
457 
459  if (!slot->nextItem && item->weapons[0] != slot->item)
461 
462  /* are we trying to change ammos for nextItem? */
463  if (slot->nextItem && item->weapons[0] != slot->nextItem)
465 #endif
466  }
467 
468  /* you can install an item only if its weight is small enough for the slot */
469  if (AII_GetItemWeightBySize(item) > slot->size)
470  return AIM_LOADING_TOOHEAVY;
471 
472  /* you can't install an item that you don't possess
473  * virtual ammo don't need to be possessed
474  * installations always have weapon and ammo */
475  if (slot->aircraft) {
476  if (!B_BaseHasItem(slot->aircraft->homebase, item))
478  } else if (slot->base) {
479  if (!B_BaseHasItem(slot->base, item))
481  }
482 
483  /* you can't install an item that does not have an installation time (alien item)
484  * except for ammo which does not have installation time */
485  if (item->craftitem.installationTime == -1 && slot->type < AC_ITEM_AMMO)
486  return AIM_LOADING_ALIENTECH;
487 
488  return AIM_LOADING_OK;
489 }
490 
494 static void AIM_UpdateItemDescription (bool fromList, bool fromSlot)
495 {
496  int status;
497  aircraft_t* aircraft;
498  aircraftSlot_t* slot;
500  assert(base);
501 
502  aircraft = base->aircraftCurrent;
503  assert(aircraft);
504  slot = AII_SelectAircraftSlot(aircraft, airequipID);
505 
506  /* update mini ufopedia */
508  if (fromList)
509  UP_AircraftItemDescription(INVSH_GetItemByIDSilent(aimSelectedTechnology ? aimSelectedTechnology->provides : nullptr));
510  else if (fromSlot) {
511  if (airequipID == AC_ITEM_AMMO)
513  else
515  }
516 
517  /* update status */
518  status = AIM_CheckTechnologyIntoSlot(slot, aimSelectedTechnology);
519  switch (status) {
521  cgi->Cvar_Set("mn_aircraft_item_warning", _("No slot selected."));
522  break;
524  cgi->Cvar_Set("mn_aircraft_item_warning", _("No item selected."));
525  break;
527  cgi->Cvar_Set("mn_aircraft_item_warning", _("You can't equip an alien technology."));
528  break;
530  cgi->Cvar_Set("mn_aircraft_item_warning", _("Technology requested is not yet completed."));
531  break;
533  cgi->Cvar_Set("mn_aircraft_item_warning", _("This item is too heavy for the selected slot."));
534  break;
536  cgi->Cvar_Set("mn_aircraft_item_warning", _("Equip a weapon first."));
537  break;
539  cgi->Cvar_Set("mn_aircraft_item_warning", _("Ammo not usable with current weapon."));
540  break;
542  cgi->Cvar_Set("mn_aircraft_item_warning", _("Unknown problem."));
543  break;
544  case AIM_LOADING_OK:
545  cgi->Cvar_Set("mn_aircraft_item_warning", _("Ok"));
546  break;
547  }
548 
549  if (*cgi->Cvar_GetString("mn_item") == '\0') {
550  cgi->UI_ExecuteConfunc("airequip_no_item");
551  } else {
552  if (fromSlot) {
553  cgi->UI_ExecuteConfunc("airequip_installed_item");
554  } else {
555  if (status == AIM_LOADING_OK)
556  cgi->UI_ExecuteConfunc("airequip_installable_item");
557  else
558  cgi->UI_ExecuteConfunc("airequip_noinstallable_item");
559  }
560  }
561 }
562 
568 {
569  if (cgi->Cmd_Argc() != 2) {
570  if (airequipID == MAX_ACITEMS) {
571  cgi->Com_Printf("Usage: %s <num>\n", cgi->Cmd_Argv(0));
572  return;
573  }
575  } else {
577  switch (type) {
578  case AC_ITEM_ELECTRONICS:
579  case AC_ITEM_SHIELD:
580  airequipID = type;
581  cgi->UI_ExecuteConfunc("airequip_zone2_off");
582  break;
583  case AC_ITEM_AMMO:
584  case AC_ITEM_WEAPON:
585  airequipID = type;
586  cgi->UI_ExecuteConfunc("airequip_zone2_on");
587  break;
588  default:
590  break;
591  }
592  }
593 
595 }
596 
602 {
603  int i;
604  itemPos_t pos;
605  aircraft_t* aircraft;
607  int updateZone = 0;
608 
609  if (!base)
610  return;
611 
612  if (cgi->Cmd_Argc() < 2) {
613  cgi->Com_Printf("Usage: %s <arg> <zone1|zone2|item>\n", cgi->Cmd_Argv(0));
614  return;
615  }
616 
617  aircraft = base->aircraftCurrent;
618  assert(aircraft);
619 
620  i = atoi(cgi->Cmd_Argv(1));
621  pos = (itemPos_t)i;
622 
623  if (cgi->Cmd_Argc() == 3) {
624  if (Q_streq(cgi->Cmd_Argv(2), "zone1")) {
625  updateZone = 1;
626  } else if (Q_streq(cgi->Cmd_Argv(2), "zone2")) {
627  updateZone = 2;
628  }
629  }
630 
632 
633  /* select the slot corresponding to pos, and set airequipSelectedSlot to this slot */
634  switch (airequipID) {
635  case AC_ITEM_ELECTRONICS:
636  /* electronics selected */
637  for (i = 0; i < aircraft->maxElectronics; i++) {
638  if (aircraft->electronics[i].pos == pos) {
640  break;
641  }
642  }
643  if (i == aircraft->maxElectronics)
644  cgi->Com_Printf("this slot hasn't been found in aircraft electronics slots\n");
645  break;
646  case AC_ITEM_AMMO:
647  case AC_ITEM_WEAPON:
648  /* weapon selected */
649  for (i = 0; i < aircraft->maxWeapons; i++) {
650  if (aircraft->weapons[i].pos == pos) {
652  break;
653  }
654  }
655  if (i == aircraft->maxWeapons)
656  cgi->Com_Printf("this slot hasn't been found in aircraft weapon slots\n");
657  break;
658  default:
659  cgi->Com_Printf("AIM_AircraftEquipSlotSelect_f : only weapons and electronics have several slots\n");
660  break;
661  }
662 
663  /* Update menu after changing slot */
665 
666  /* update description with the selected slot */
667  if (updateZone > 0)
668  AIM_UpdateItemDescription(false, true);
669  else
670  AIM_UpdateItemDescription(true, false);
671 }
672 
677 {
678  int zone;
679  aircraft_t* aircraft;
680  aircraftSlot_t* slot;
682 
683  if (!base)
684  return;
685 
686  if (cgi->Cmd_Argc() < 2) {
687  cgi->Com_Printf("Usage: %s <arg>\n", cgi->Cmd_Argv(0));
688  return;
689  }
690 
691  zone = atoi(cgi->Cmd_Argv(1));
692 
693  aircraft = base->aircraftCurrent;
694  assert(aircraft);
695  /* Select slot */
696  slot = AII_SelectAircraftSlot(aircraft, airequipID);
697 
698  /* ammos are only available for weapons */
699  switch (airequipID) {
700  /* a weapon was selected - select ammo type corresponding to this weapon */
701  case AC_ITEM_WEAPON:
702  if (zone == ZONE_AMMO) {
703  if (slot->item)
705  }
706  break;
707  /* an ammo was selected - select weapon type corresponding to this ammo */
708  case AC_ITEM_AMMO:
709  if (zone != ZONE_AMMO)
711  break;
712  default :
713  /* ZONE_AMMO is not available for electronics and shields */
714  if (zone == ZONE_AMMO)
715  return;
716  }
717  airequipSelectedZone = zone;
718 
719  /* update menu */
721  /* Check that the selected zone is OK */
723 
724  AIM_UpdateItemDescription(false, true);
725 }
726 
732 static void AIM_AircraftEquipAddItem_f (void)
733 {
734  int zone;
735  aircraftSlot_t* slot;
736  aircraft_t* aircraft = nullptr;
738 
739  zone = (airequipID == AC_ITEM_AMMO) ? 2 : 1;
740 
741  /* proceed only if an item has been selected */
742  if (!aimSelectedTechnology)
743  return;
744 
745  assert(base);
746  aircraft = base->aircraftCurrent;
747  assert(aircraft);
748  base = aircraft->homebase; /* we need to know where items will be removed */
749  slot = AII_SelectAircraftSlot(aircraft, airequipID);
750  if (slot == nullptr)
751  return;
752 
753  /* the clicked button doesn't correspond to the selected zone */
754  if (zone != airequipSelectedZone)
755  return;
756 
757  /* check if the zone exists */
758  if (zone >= ZONE_MAX)
759  return;
760 
761  /* update the new item to slot */
762 
763  switch (zone) {
764  case ZONE_MAIN:
765  if (!slot->nextItem) {
766  /* we add the weapon, shield, item if slot is free or the installation of current item just began */
767  if (!slot->item || (slot->item && slot->installationTime == slot->item->craftitem.installationTime)) {
768  AII_RemoveItemFromSlot(base, slot, false);
769  AII_AddItemToSlot(base, aimSelectedTechnology, slot, false); /* Aircraft stats are updated below */
770  AII_AutoAddAmmo(slot);
771  break;
772  } else if (slot->item == INVSH_GetItemByID(aimSelectedTechnology->provides)) {
773  /* the added item is the same than the one in current slot */
774  if (slot->installationTime == -slot->item->craftitem.installationTime) {
775  /* player changed his mind: he just want to re-add the item he just removed */
776  slot->installationTime = 0;
777  break;
778  } else if (!slot->installationTime) {
779  /* player try to add a weapon he already have: just skip */
780  return;
781  }
782  } else {
783  /* We start removing current item in slot, and the selected item will be installed afterwards */
785  /* more below */
786  }
787  } else {
788  /* remove weapon and ammo of next item */
789  AII_RemoveNextItemFromSlot(base, slot, false);
790  /* more below */
791  }
792 
793  /* we change the weapon, shield, item, or base defence that will be installed AFTER the removal
794  * of the one in the slot atm */
795  AII_AddItemToSlot(base, aimSelectedTechnology, slot, true);
796  AII_AutoAddAmmo(slot);
797  break;
798  case ZONE_AMMO:
799  /* we can change ammo only if the selected item is an ammo (for weapon or base defence system) */
800  if (airequipID >= AC_ITEM_AMMO) {
801  AII_AddAmmoToSlot(base, aimSelectedTechnology, slot);
802  }
803  break;
804  default:
805  /* Zone higher than ZONE_AMMO shouldn't exist */
806  return;
807  }
808 
809  /* Update the values of aircraft stats (just in case an item has an installationTime of 0) */
810  AII_UpdateAircraftStats(aircraft);
811 
813 }
814 
819 {
820  int zone;
821  aircraftSlot_t* slot;
822  aircraft_t* aircraft = nullptr;
824 
825  zone = (airequipID == AC_ITEM_AMMO) ? 2 : 1;
826 
827  assert(base);
828  aircraft = base->aircraftCurrent;
829  assert(aircraft);
830  slot = AII_SelectAircraftSlot(aircraft, airequipID);
831 
832  /* no item in slot: nothing to remove */
833  if (!slot->item)
834  return;
835 
836  /* update the new item to slot */
837 
838  switch (zone) {
839  case ZONE_MAIN:
840  if (!slot->nextItem) {
841  /* we change the weapon, shield, item, or base defence that is already in the slot */
842  /* if the item has been installed since less than 1 hour, you don't need time to remove it */
843  if (slot->installationTime < slot->item->craftitem.installationTime) {
845  AII_RemoveItemFromSlot(base, slot, true); /* we remove only ammo, not item */
846  } else {
847  AII_RemoveItemFromSlot(base, slot, false); /* we remove weapon and ammo */
848  }
849  /* aircraft stats are updated below */
850  } else {
851  /* we change the weapon, shield, item, or base defence that will be installed AFTER the removal
852  * of the one in the slot atm */
853  AII_RemoveNextItemFromSlot(base, slot, false); /* we remove weapon and ammo */
854  /* if you canceled next item for less than 1 hour, previous item is still functional */
855  if (slot->installationTime == -slot->item->craftitem.installationTime) {
856  slot->installationTime = 0;
857  }
858  }
859  break;
860  case ZONE_AMMO:
861  /* we can change ammo only if the selected item is an ammo (for weapon or base defence system) */
862  if (airequipID >= AC_ITEM_AMMO) {
863  if (slot->nextAmmo)
864  AII_RemoveNextItemFromSlot(base, slot, true);
865  else
866  AII_RemoveItemFromSlot(base, slot, true);
867  }
868  break;
869  default:
870  /* Zone higher than ZONE_AMMO shouldn't exist */
871  return;
872  }
873 
874  /* Update the values of aircraft stats */
875  AII_UpdateAircraftStats(aircraft);
876 
878 }
879 
885 {
886  int techIdx;
887 
888  if (cgi->Cmd_Argc() < 2) {
889  cgi->Com_Printf("Usage: %s <num>\n", cgi->Cmd_Argv(0));
890  return;
891  }
892 
893  /* Which tech? */
894  techIdx = atoi(cgi->Cmd_Argv(1));
895  aimSelectedTechnology = RS_GetTechByIDX(techIdx);
896  AIM_UpdateItemDescription(true, false);
897 }
898 
903 {
905  const char* name;
906 
907  if (cgi->Cmd_Argc() != 2) {
908  cgi->Com_Printf("Usage: %s <weapon|ammo|armour|item>\n", cgi->Cmd_Argv(0));
909  return;
910  }
911 
912  name = cgi->Cmd_Argv(1);
913 
914  if (Q_streq(name, "weapon"))
915  i = AC_ITEM_WEAPON;
916  else if (Q_streq(name, "ammo"))
917  i = AC_ITEM_AMMO;
918  else if (Q_streq(name, "armour"))
919  i = AC_ITEM_SHIELD;
920  else if (Q_streq(name, "item"))
922  else {
923  cgi->Com_Printf("AIM_AircraftItemtypeByName_f: Invalid itemtype!\n");
924  return;
925  }
926 
927  airequipID = i;
928  cgi->Cmd_ExecuteString("airequip_updatemenu %d", airequipID);
929 }
930 
931 static const cmdList_t airequipCmds[] = {
932  {"airequip_updatemenu", AIM_AircraftEquipMenuUpdate_f, "Init function for the aircraft equip menu"},
933  {"airequip_selectcategory", AIM_AircraftItemtypeByName_f, "Select an item category and update the GUI"},
934  {"airequip_list_click", AIM_AircraftEquipMenuClick_f, nullptr},
935  {"airequip_slot_select", AIM_AircraftEquipSlotSelect_f, nullptr},
936  {"airequip_add_item", AIM_AircraftEquipAddItem_f, "Add item to slot"},
937  {"airequip_remove_item", AIM_AircraftEquipRemoveItem_f, "Remove item from slot"},
938  {"airequip_zone_select", AIM_AircraftEquipZoneSelect_f, nullptr},
939  {nullptr, nullptr, nullptr}
940 };
941 void AIM_InitCallbacks (void)
942 {
943  cgi->Cmd_TableAddList(airequipCmds);
944 }
945 
947 {
948  cgi->Cmd_TableRemoveList(airequipCmds);
949 }
const objDef_t * nextItem
Definition: cp_aircraft.h:91
const objDef_t * INVSH_GetItemByIDSilent(const char *id)
Returns the item that belongs to the given id or nullptr if it wasn't found.
Definition: inv_shared.cpp:249
int B_ItemInBase(const objDef_t *item, const base_t *base)
Check if the item has been collected (i.e it is in the storage) in the given base.
Definition: cp_base.cpp:2134
static void AIM_AircraftEquipSlotSelect_f(void)
Select the current slot you want to assign the item to.
#define AIM_LOADING_NOWEAPON
technology_t * RS_GetTechByIDX(int techIdx)
Returns the technology pointer for a tech index. You can use this instead of "&ccs.technologies[techIdx]" to avoid having to check valid indices.
void AIM_ShutdownCallbacks(void)
bool RS_IsResearched_ptr(const technology_t *tech)
Checks whether an item is already researched.
const objDef_t * INVSH_GetItemByID(const char *id)
Returns the item that belongs to the given id or nullptr if it wasn't found.
Definition: inv_shared.cpp:282
QGL_EXTERN GLint GLenum type
Definition: r_gl.h:94
const char * va(const char *format,...)
does a varargs printf into a temp buffer, so I don't need to have varargs versions of all text functi...
Definition: shared.cpp:410
static void AIM_AircraftItemtypeByName_f(void)
Update the GUI with a named itemtype.
void AII_UpdateAircraftStats(aircraft_t *aircraft)
Update the value of stats array of an aircraft.
static const cmdList_t airequipCmds[]
#define _(String)
Definition: cl_shared.h:43
static void AIM_AircraftEquipMenuClick_f(void)
Set AIM_selectedTechnology to the technology of current selected aircraft item.
bool Com_sprintf(char *dest, size_t size, const char *fmt,...)
copies formatted string with buffer-size checking
Definition: shared.cpp:494
static void AIM_EmphazeAmmoSlotText(void)
Write in red the text in zone ammo (zone 2)
static void AIM_AircraftEquipMenuUpdate(void)
bool AII_AddAmmoToSlot(base_t *base, const technology_t *tech, aircraftSlot_t *slot)
Add an ammo to an aircraft weapon slot.
char name[MAX_VAR]
Definition: ui_nodes.h:82
base_t * B_GetCurrentSelectedBase(void)
returns the currently selected base
Definition: cp_base.cpp:1578
static const char * AIM_AircraftItemtypeName(const int equiptype)
Returns the userfriendly name for craftitem types (shown in aircraft equip menu)
static void AIM_CheckAirequipSelectedSlot(const aircraft_t *aircraft)
Check that airequipSelectedSlot is the indice of an existing slot in the aircraft.
const struct objDef_s * ammos[MAX_AMMOS_PER_OBJDEF]
Definition: inv_shared.h:307
Defines all attributes of objects used in the inventory.
Definition: inv_shared.h:264
itemWeight_t AII_GetItemWeightBySize(const objDef_t *od)
Returns craftitem weight based on size.
int maxElectronics
Definition: cp_aircraft.h:147
A base with all it's data.
Definition: cp_base.h:84
static void AIM_CheckAirequipSelectedZone(aircraftSlot_t *slot)
Check that airequipSelectedZone is available.
char * provides
Definition: cp_research.h:154
const char *IMPORT * Cvar_GetString(const char *varName)
#define AIM_LOADING_NOTUSABLEWITHWEAPON
static void AIM_AircraftEquipZoneSelect_f(void)
Select the current zone you want to assign the item to.
void Q_strncpyz(char *dest, const char *src, size_t destsize)
Safe strncpy that ensures a trailing zero.
Definition: shared.cpp:457
aircraftItemType_t type
Definition: cp_aircraft.h:82
cvar_t *IMPORT * Cvar_Set(const char *varName, const char *value,...) __attribute__((format(__printf__
aircraft_t * aircraftCurrent
Definition: cp_base.h:100
#define ngettext(x, y, cnt)
Definition: g_local.h:40
Header file for menu callback functions used for base and aircraft equip menu.
static void AIM_UpdateAircraftItemList(const aircraftSlot_t *slot)
Update the list of item you can choose.
struct base_s * base
Definition: cp_aircraft.h:79
const objDef_t * ammo
Definition: cp_aircraft.h:85
static void AIM_AircraftEquipRemoveItem_f(void)
Delete an object from a zone.
const cgame_import_t * cgi
void UP_AircraftItemDescription(const objDef_t *item)
Prints the (UFOpaedia and other) description for aircraft items.
#define AIM_LOADING_OK
This is the technology parsed from research.ufo.
Definition: cp_research.h:137
Definition: cmd.h:86
#define AIM_LOADING_NOTECHNOLOGYSELECTED
void AIM_InitCallbacks(void)
#define AIM_LOADING_TECHNOLOGYNOTRESEARCHED
itemWeight_t size
Definition: cp_aircraft.h:86
aircraftSlot_t weapons[MAX_AIRCRAFTSLOT]
Definition: cp_aircraft.h:143
Atomic structure used to define most of the UI.
Definition: ui_nodes.h:80
#define AIM_LOADING_UNKNOWNPROBLEM
bool disabled
Definition: ui_nodes.h:102
slot of aircraft
Definition: cp_aircraft.h:77
bool AII_AddItemToSlot(base_t *base, const technology_t *tech, aircraftSlot_t *slot, bool nextItem)
Add an item to an aircraft slot.
QGL_EXTERN GLuint count
Definition: r_gl.h:99
const objDef_t * nextAmmo
Definition: cp_aircraft.h:93
static int airequipSelectedSlot
struct base_s * homebase
Definition: cp_aircraft.h:149
static void AIM_AircraftEquipAddItem_f(void)
Add selected item to current zone.
static void AIM_CheckAirequipID(void)
Check airequipID value and set the correct values for aircraft items.
static bool AIM_CrafttypeFilter(const base_t *base, aircraftItemType_t filterType, const technology_t *tech)
int maxWeapons
Definition: cp_aircraft.h:144
#define AIM_LOADING_NOSLOTSELECTED
QGL_EXTERN GLint i
Definition: r_gl.h:113
aircraftSlot_t * AII_SelectAircraftSlot(aircraft_t *aircraft, aircraftItemType_t type)
Returns a pointer to the selected slot.
static int AIM_CheckTechnologyIntoSlot(const aircraftSlot_t *slot, const technology_t *tech)
Header for slot management related stuff.
#define AIM_LOADING_TOOHEAVY
bool AIM_SelectableCraftItem(const aircraftSlot_t *slot, const technology_t *tech)
Check if an aircraft item should or should not be displayed in airequip menu.
aircraftItemType_t
All different types of craft items.
Definition: inv_shared.h:197
static void AIM_AircraftEquipMenuUpdate_f(void)
Fills the weapon and shield list of the aircraft equip menu.
QGL_EXTERN GLuint GLsizei GLsizei GLint GLenum GLchar * name
Definition: r_gl.h:110
bool B_BaseHasItem(const base_t *base, const objDef_t *item)
Check if an item is available on a base.
Definition: cp_base.cpp:2120
aircraftSlot_t shield
Definition: cp_aircraft.h:145
void AII_AutoAddAmmo(aircraftSlot_t *slot)
Auto add ammo corresponding to weapon, if there is enough in storage.
static int airequipSelectedZone
const char * AII_WeightToName(itemWeight_t weight)
Translate a weight int to a translated string.
aircraftItemType_t type
Definition: inv_shared.h:247
void Q_strcat(char *dest, size_t destsize, const char *format,...)
Safely (without overflowing the destination buffer) concatenates two strings.
Definition: shared.cpp:475
static aircraftItemType_t airequipID
itemPos_t pos
Definition: cp_aircraft.h:94
#define AIM_LOADING_ALIENTECH
Header file for single player campaign control.
static void AIM_NoEmphazeAmmoSlotText(void)
Write in white the text in zone ammo (zone 2)
int installationTime
Definition: inv_shared.h:252
technology_t ** AII_GetCraftitemTechsByType(aircraftItemType_t type)
Returns a list of craftitem technologies for the given type.
#define Q_streq(a, b)
Definition: shared.h:136
void AII_RemoveNextItemFromSlot(base_t *base, aircraftSlot_t *slot, bool ammo)
Cancel replacing item, move nextItem (or optionally its ammo only) back to the base storage...
static technology_t * aimSelectedTechnology
int numAmmos
Definition: inv_shared.h:308
An aircraft with all it's data.
Definition: cp_aircraft.h:114
static void AIM_DrawAircraftSlots(const aircraft_t *aircraft)
Draw only slots existing for this aircraft, and emphases selected one.
technology_t * RS_GetTechForItem(const objDef_t *item)
Returns technology entry for an item.
const char uiNode_t *IMPORT * UI_AddOption(uiNode_t **tree, const char *name, const char *label, const char *value)
void AII_RemoveItemFromSlot(base_t *base, aircraftSlot_t *slot, bool ammo)
Remove the item from the slot (or optionally its ammo only) and put it the base storage.
itemPos_t
different positions for aircraft items
Definition: cp_aircraft.h:54
bool isVirtual
Definition: inv_shared.h:284
craftItem craftitem
Definition: inv_shared.h:331
struct aircraft_s * aircraft
Definition: cp_aircraft.h:81
const char *IMPORT * Cmd_Argv(int n)
aircraftSlot_t electronics[MAX_AIRCRAFTSLOT]
Definition: cp_aircraft.h:146
const objDef_t * item
Definition: cp_aircraft.h:84
const struct objDef_s * weapons[MAX_WEAPONS_PER_OBJDEF]
Definition: inv_shared.h:311
int installationTime
Definition: cp_aircraft.h:89
static void AIM_UpdateItemDescription(bool fromList, bool fromSlot)
Update the item description according to the tech and the slot selected.