UFO: Alien Invasion
Doxygen documentation generating
cp_produce_callbacks.cpp
Go to the documentation of this file.
1 
6 /*
7 Copyright (C) 2002-2023 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 "../../cl_inventory.h"
27 #include "../../ui/ui_dataids.h"
28 #include "cp_campaign.h"
29 #include "cp_market.h"
30 #include "cp_ufo.h"
31 #include "cp_popup.h"
32 #include "cp_produce.h"
33 #include "cp_produce_callbacks.h"
34 #include "cp_base.h"
35 
41 
43 static production_t* selectedProduction = nullptr;
44 
47 
50 
52 static const int QUEUE_SPACERS = 2;
53 
58 static void PR_ClearSelectedItems (void)
59 {
62 }
63 
68 static void PR_ClearSelected (void)
69 {
71  selectedProduction = nullptr;
72 }
73 
78 static void PR_UpdateProductionList (const base_t* base)
79 {
80  int i;
81  linkedList_t* productionList = nullptr;
82  linkedList_t* productionQueued = nullptr;
83  linkedList_t* productionAmount = nullptr;
84  const production_queue_t* queue;
85 
86  assert(base);
87 
88  queue = PR_GetProductionForBase(base);
89 
90  /* First add all the queue items ... */
91  for (i = 0; i < queue->numItems; i++) {
92  const production_t* prod = &queue->items[i];
93  if (PR_IsItem(prod)) {
94  const objDef_t* od = prod->data.data.item;
95  cgi->LIST_AddString(&productionList, va("%s", _(od->name)));
96  cgi->LIST_AddString(&productionAmount, va("%i", B_ItemInBase(prod->data.data.item, base)));
97  cgi->LIST_AddString(&productionQueued, va("%i", prod->amount));
98  } else if (PR_IsAircraft(prod)) {
99  const aircraft_t* aircraftTemplate = prod->data.data.aircraft;
100 
101  cgi->LIST_AddString(&productionList, va("%s", _(aircraftTemplate->name)));
102  cgi->LIST_AddString(&productionAmount, va("%i", AIR_CountInBaseByTemplate(base, aircraftTemplate)));
103  cgi->LIST_AddString(&productionQueued, va("%i", prod->amount));
104  } else if (PR_IsDisassembly(prod)) {
105  const storedUFO_t* ufo = prod->data.data.ufo;
106 
107  cgi->LIST_AddString(&productionList, va("%s (%.0f%%)", UFO_TypeToName(ufo->ufoTemplate->getUfoType()), ufo->condition * 100));
108  cgi->LIST_AddString(&productionAmount, va("%i", US_UFOsInStorage(ufo->ufoTemplate, ufo->installation)));
109  cgi->LIST_AddString(&productionQueued, "1");
110  }
111  }
112 
113  /* Then spacers ... */
114  for (i = 0; i < QUEUE_SPACERS; i++) {
115  cgi->LIST_AddString(&productionList, "");
116  cgi->LIST_AddString(&productionAmount, "");
117  cgi->LIST_AddString(&productionQueued, "");
118  }
119 
120  cgi->LIST_Delete(&productionItemList);
121 
122  /* Then go through all object definitions ... */
125  US_Foreach(ufo) {
126  /* UFO is being transported */
127  if (ufo->status != SUFO_STORED)
128  continue;
129  /* UFO not researched */
130  if (!RS_IsResearched_ptr(ufo->ufoTemplate->tech))
131  continue;
132  /* The UFO is being disassembled already */
133  if (ufo->disassembly)
134  continue;
135 
136  cgi->LIST_AddPointer(&productionItemList, ufo);
137  cgi->LIST_AddString(&productionList, va("%s (%.0f%%)", UFO_TypeToName(ufo->ufoTemplate->getUfoType()), ufo->condition * 100));
138  cgi->LIST_AddString(&productionAmount, va("%i", US_UFOsInStorage(ufo->ufoTemplate, ufo->installation)));
139  cgi->LIST_AddString(&productionQueued, "");
140  }
141  } else if (produceCategory == FILTER_AIRCRAFT) {
142  for (i = 0; i < ccs.numAircraftTemplates; i++) {
143  aircraft_t* aircraftTemplate = &ccs.aircraftTemplates[i];
144  /* don't allow producing ufos */
145  if (AIR_IsUFO(aircraftTemplate))
146  continue;
147  if (!aircraftTemplate->tech) {
148  cgi->Com_Printf("PR_UpdateProductionList: no technology for craft %s!\n", aircraftTemplate->id);
149  continue;
150  }
151 
152  cgi->Com_DPrintf(DEBUG_CLIENT, "air: %s ufotype: %i tech: %s time: %i\n", aircraftTemplate->id,
153  aircraftTemplate->getUfoType(), aircraftTemplate->tech->id, aircraftTemplate->tech->produceTime);
154 
155  if (aircraftTemplate->tech->produceTime > 0 && RS_IsResearched_ptr(aircraftTemplate->tech)) {
156  cgi->LIST_AddPointer(&productionItemList, aircraftTemplate);
157  cgi->LIST_AddString(&productionList, va("%s", _(aircraftTemplate->name)));
158  cgi->LIST_AddString(&productionAmount, va("%i", AIR_CountInBaseByTemplate(base, aircraftTemplate)));
159  cgi->LIST_AddString(&productionQueued, "");
160  }
161  }
162  } else {
163  objDef_t* od;
164  for (i = 0, od = cgi->csi->ods; i < cgi->csi->numODs; i++, od++) {
165  const technology_t* tech;
166  if (od->isVirtual)
167  continue;
168  tech = RS_GetTechForItem(od);
169  /* We will not show items that are not producible.
170  * We can only produce what was researched before. */
171  if (RS_IsResearched_ptr(tech) && PR_ItemIsProduceable(od) && cgi->INV_ItemMatchesFilter(od, produceCategory)) {
172  cgi->LIST_AddPointer(&productionItemList, od);
173 
174  cgi->LIST_AddString(&productionList, va("%s", _(od->name)));
175  cgi->LIST_AddString(&productionAmount, va("%i", B_ItemInBase(od, base)));
176  cgi->LIST_AddString(&productionQueued, "");
177  }
178  }
179  }
180 
181  /* bind the menu text to our static char array */
182  cgi->UI_RegisterLinkedListText(TEXT_PRODUCTION_LIST, productionList);
183  /* bind the amount of available items */
184  cgi->UI_RegisterLinkedListText(TEXT_PRODUCTION_AMOUNT, productionAmount);
185  /* bind the amount of queued items */
186  cgi->UI_RegisterLinkedListText(TEXT_PRODUCTION_QUEUED, productionQueued);
187 }
188 
189 static void PR_RequirementsInfo (const base_t* base, const requirements_t* reqs) {
190  const vec4_t green = {0.0f, 1.0f, 0.0f, 0.8f};
191  const vec4_t yellow = {1.0f, 0.874f, 0.294f, 1.0f};
192  uiNode_t* req_root = nullptr;
193  uiNode_t* req_items = nullptr;
194 #if 0
195  uiNode_t* req_techs = nullptr;
196  uiNode_t* req_technots = nullptr;
197 #endif
198 
199  cgi->UI_ResetData(OPTION_PRODUCTION_REQUIREMENTS);
200 
201  if (!reqs->numLinks)
202  return;
203 
204  for (int i = 0; i < reqs->numLinks; i++) {
205  const requirement_t* req = &reqs->links[i];
206 
207  switch (req->type) {
208  case RS_LINK_ITEM: {
209  uiNode_t* node = cgi->UI_AddOption(&req_items, req->link.od->id, va("%i %s", req->amount, _(req->link.od->name)), va("%i", i));
210  if (B_ItemInBase(req->link.od, base) >= req->amount)
211  Vector4Copy(green, node->color);
212  else
213  Vector4Copy(yellow, node->color);
214  break;
215  }
216  case RS_LINK_ANTIMATTER: {
218  uiNode_t* node;
219 
220  assert(tech);
221  node = cgi->UI_AddOption(&req_items, ANTIMATTER_ITEM_ID, va("%i %s", req->amount, _(tech->name)), va("%i", i));
222  if (B_AntimatterInBase(base) >= req->amount)
223  Vector4Copy(green, node->color);
224  else
225  Vector4Copy(yellow, node->color);
226  break;
227  }
228 #if 0
229  case RS_LINK_TECH:
230 /* if (node && RS_IsResearched_ptr(req->link)) ... */
231  break;
232  case RS_LINK_TECH_NOT:
233 /* if (node && RS_IsResearched_ptr(req->link)) ... */
234  break;
235 #endif
236  default:
237  break;
238  }
239  }
240  if (req_items) {
241  uiNode_t* node = cgi->UI_AddOption(&req_root, "items", "_Items", "item");
242  node->firstChild = req_items;
243  }
244  cgi->UI_RegisterOption(OPTION_PRODUCTION_REQUIREMENTS, req_root);
245 }
246 
254 static void PR_ItemProductionInfo (const base_t* base, const objDef_t* od, int remainingHours)
255 {
256  static char productionInfo[512];
257 
258  assert(base);
259  assert(od);
260 
261  /* Don't try to display an item which is not producible. */
262  if (!PR_ItemIsProduceable(od)) {
263  Com_sprintf(productionInfo, sizeof(productionInfo), _("No item selected"));
264  cgi->Cvar_Set("mn_item", "");
265  } else {
266  const technology_t* tech = RS_GetTechForItem(od);
267 
268  Com_sprintf(productionInfo, sizeof(productionInfo), "%s\n", _(od->name));
269  Q_strcat(productionInfo, sizeof(productionInfo), _("Cost per item\t%i c\n"), PR_GetPrice(od->productionCost));
270  Q_strcat(productionInfo, sizeof(productionInfo), _("Production time\t%ih\n"), remainingHours);
271  Q_strcat(productionInfo, sizeof(productionInfo), _("Item size\t%i\n"), od->size);
272  cgi->Cvar_Set("mn_item", "%s", od->id);
273 
275  cgi->Cmd_ExecuteString("show_requirements %i", tech->requireForProduction.numLinks);
276  }
277  cgi->UI_RegisterText(TEXT_PRODUCTION_INFO, productionInfo);
278 }
279 
286 static void PR_DisassemblyInfo (const storedUFO_t* ufo, int remainingHours)
287 {
288  static char productionInfo[512];
289 
290  assert(ufo);
291  assert(ufo->ufoTemplate);
292 
293  Com_sprintf(productionInfo, sizeof(productionInfo), "%s (%.0f%%) - %s\n", _(UFO_TypeToName(ufo->ufoTemplate->getUfoType())), ufo->condition * 100, _("Disassembly"));
294  Q_strcat(productionInfo, sizeof(productionInfo), _("Stored at: %s\n"), ufo->installation->name);
295  Q_strcat(productionInfo, sizeof(productionInfo), _("Disassembly time: %ih\n"), remainingHours);
296  Q_strcat(productionInfo, sizeof(productionInfo), _("Components:\n"));
297  /* Print components. */
298  for (int i = 0; i < ufo->comp->numItemtypes; i++) {
299  const objDef_t* compOd = ufo->comp->items[i];
300  const int amount = (ufo->condition < 1 && ufo->comp->itemAmount2[i] != COMP_ITEMCOUNT_SCALED) ? ufo->comp->itemAmount2[i] : round(ufo->comp->itemAmount[i] * ufo->condition);
301 
302  if (amount == 0)
303  continue;
304 
305  assert(compOd);
306  Q_strcat(productionInfo, sizeof(productionInfo), " %s (%i)\n", _(compOd->name), amount);
307  }
308  cgi->UI_RegisterText(TEXT_PRODUCTION_INFO, productionInfo);
309  cgi->Cvar_Set("mn_item", "%s", ufo->id);
310  cgi->Cmd_ExecuteString("show_requirements 0");
311 }
312 
320 static void PR_AircraftInfo (const base_t* base, const aircraft_t* aircraftTemplate, int remainingHours)
321 {
322  static char productionInfo[512];
323 
324  Com_sprintf(productionInfo, sizeof(productionInfo), "%s\n", _(aircraftTemplate->name));
325  Q_strcat(productionInfo, sizeof(productionInfo), _("Production costs\t%i c\n"), PR_GetPrice(aircraftTemplate->productionCost));
326  Q_strcat(productionInfo, sizeof(productionInfo), _("Production time\t%ih\n"), remainingHours);
327  cgi->UI_RegisterText(TEXT_PRODUCTION_INFO, productionInfo);
328  cgi->Cvar_Set("mn_item", "%s", aircraftTemplate->id);
329  PR_RequirementsInfo(base, &aircraftTemplate->tech->requireForProduction);
330  cgi->Cmd_ExecuteString("show_requirements %i", aircraftTemplate->tech->requireForProduction.numLinks);
331 }
332 
340 static void PR_ProductionInfo (const base_t* base)
341 {
342  if (selectedProduction) {
343  const production_t* prod = selectedProduction;
344  const int time = PR_GetRemainingHours(prod);
345  cgi->UI_ExecuteConfunc("prod_taskselected");
346 
347  if (PR_IsAircraft(prod)) {
348  PR_AircraftInfo(base, prod->data.data.aircraft, time);
349  cgi->UI_ExecuteConfunc("amountsetter enable");
350  } else if (PR_IsItem(prod)) {
351  PR_ItemProductionInfo(base, prod->data.data.item, time);
352  cgi->UI_ExecuteConfunc("amountsetter enable");
353  } else if (PR_IsDisassembly(prod)) {
354  PR_DisassemblyInfo(prod->data.data.ufo, time);
355  cgi->UI_ExecuteConfunc("amountsetter disable");
356  } else {
357  cgi->Com_Error(ERR_DROP, "PR_ProductionInfo: Selected production is not item nor aircraft nor ufo.\n");
358  }
359  cgi->Cvar_SetValue("mn_production_amount", selectedProduction->amount);
360  } else {
361  if (!PR_IsDataValid(&selectedData)) {
362  cgi->UI_ExecuteConfunc("prod_nothingselected");
364  cgi->UI_RegisterText(TEXT_PRODUCTION_INFO, _("No aircraft selected."));
365  else
366  cgi->UI_RegisterText(TEXT_PRODUCTION_INFO, _("No item selected"));
367  cgi->Cvar_Set("mn_item", "");
368  } else {
369  cgi->UI_ExecuteConfunc("prod_availableselected");
372  } else if (PR_IsItemData(&selectedData)) {
374  } else if (PR_IsDisassemblyData(&selectedData)) {
376  }
377  }
378  }
379  /* update capacity counters */
380  cgi->UI_ExecuteConfunc("ui_prod_update_caps %d %d %d %d %d %d %d %d", CAP_GetFreeCapacity(base, CAP_ITEMS), CAP_GetMax(base, CAP_ITEMS),
384  );
385 }
386 
392 {
393  int num;
394  production_queue_t* queue;
396 
397  /* can be called from everywhere without a base set */
398  if (!base)
399  return;
400 
401  queue = PR_GetProductionForBase(base);
402 
403  /* not enough parameters */
404  if (cgi->Cmd_Argc() < 2) {
405  cgi->Com_Printf("Usage: %s <arg>\n", cgi->Cmd_Argv(0));
406  return;
407  }
408 
409  /* clicked which item? */
410  num = atoi(cgi->Cmd_Argv(1));
411 
412  /* Clicked the production queue or the item list? */
413  if (num < queue->numItems && num >= 0) {
414  production_t* prod = &queue->items[num];
415  const technology_t* tech = PR_GetTech(&prod->data);
416  selectedProduction = prod;
417  UP_OpenWith(tech->id);
418  } else if (num >= queue->numItems + QUEUE_SPACERS) {
419  /* Clicked in the item list. */
420  const int idx = num - queue->numItems - QUEUE_SPACERS;
421 
423  const aircraft_t* aircraftTemplate = (const aircraft_t*)cgi->LIST_GetByIdx(productionItemList, idx);
424  /* aircraftTemplate may be empty if rclicked below real entry.
425  * UFO research definition must not have a tech assigned,
426  * only RS_CRAFT types have */
427  if (aircraftTemplate && aircraftTemplate->tech)
428  UP_OpenWith(aircraftTemplate->tech->id);
429  } else if (produceCategory == FILTER_DISASSEMBLY) {
430  const storedUFO_t* ufo = (const storedUFO_t*)cgi->LIST_GetByIdx(productionItemList, idx);
431  if (ufo && ufo->ufoTemplate && ufo->ufoTemplate->tech) {
432  UP_OpenWith(ufo->ufoTemplate->tech->id);
433  }
434  } else {
436  const technology_t* tech = RS_GetTechForItem(od);
437 
438  /* Open up UFOpaedia for this entry. */
439  if (RS_IsResearched_ptr(tech) && cgi->INV_ItemMatchesFilter(od, produceCategory)) {
442  UP_OpenWith(tech->id);
443  return;
444  }
445  }
446  }
447 #ifdef DEBUG
448  else
449  cgi->Com_DPrintf(DEBUG_CLIENT, "PR_ProductionListRightClick_f: Click on spacer %i\n", num);
450 #endif
451 }
452 
458 static void PR_ProductionListClick_f (void)
459 {
460  int num;
461  production_queue_t* queue;
463 
464  /* can be called from everywhere without a base set */
465  if (!base)
466  return;
467 
468  queue = PR_GetProductionForBase(base);
469 
470  /* Break if there are not enough parameters. */
471  if (cgi->Cmd_Argc() < 2) {
472  cgi->Com_Printf("Usage: %s <arg>\n", cgi->Cmd_Argv(0));
473  return;
474  }
475 
476  /* Clicked which item? */
477  num = atoi(cgi->Cmd_Argv(1));
478 
479  /* Clicked the production queue or the item list? */
480  if (num < queue->numItems && num >= 0) {
481  selectedProduction = &queue->items[num];
482  PR_ProductionInfo(base);
483  } else if (num >= queue->numItems + QUEUE_SPACERS) {
484  /* Clicked in the item list. */
485  const int idx = num - queue->numItems - QUEUE_SPACERS;
486 
489 
492 
493  PR_ProductionInfo(base);
494  } else if (produceCategory == FILTER_AIRCRAFT) {
495  aircraft_t* aircraftTemplate = (aircraft_t*)cgi->LIST_GetByIdx(productionItemList, idx);
496  if (!aircraftTemplate) {
497  cgi->Com_DPrintf(DEBUG_CLIENT, "PR_ProductionListClick_f: No item found at the list-position %i!\n", idx);
498  return;
499  }
500  /* ufo research definition must not have a tech assigned
501  * only RS_CRAFT types have
502  * @sa RS_InitTree */
503  if (aircraftTemplate->tech && aircraftTemplate->tech->produceTime >= 0
504  && RS_IsResearched_ptr(aircraftTemplate->tech)) {
506  PR_SetData(&selectedData, PRODUCTION_TYPE_AIRCRAFT, aircraftTemplate);
507  PR_ProductionInfo(base);
508  }
509  } else {
511  const technology_t* tech = RS_GetTechForItem(od);
512 
513  /* We can only produce items that fulfill the following conditions... */
514  if (RS_IsResearched_ptr(tech) && PR_ItemIsProduceable(od) && cgi->INV_ItemMatchesFilter(od, produceCategory)) {
517  PR_ProductionInfo(base);
518  }
519  }
520  }
521 }
522 
526 static void PR_ProductionType_f (void)
527 {
528  itemFilterTypes_t cat;
530 
531  if (cgi->Cmd_Argc() < 2) {
532  cgi->Com_Printf("Usage: %s <category>\n", cgi->Cmd_Argv(0));
533  return;
534  }
535 
536  cat = cgi->INV_GetFilterTypeID(cgi->Cmd_Argv(1));
537 
538  /* Check if the given category index is valid. */
539  if (cat == MAX_FILTERTYPES)
540  cat = FILTER_S_PRIMARY;
541 
542  /* Can be called from everywhere without a base set */
543  if (!base)
544  return;
545 
546  produceCategory = cat;
547  cgi->Cvar_Set("mn_itemtype", "%s", cgi->INV_GetFilterType(produceCategory));
548 
549  /* Update list of entries for current production tab. */
551 
552  /* Reset selected entry, if it was not from the queue */
554 
555  /* Select first entry in the list (if any). */
556  if (cgi->LIST_Count(productionItemList) > 0) {
558  const aircraft_t* aircraft = (const aircraft_t*)cgi->LIST_GetByIdx(productionItemList, 0);
560  } else if (produceCategory == FILTER_DISASSEMBLY) {
561  const storedUFO_t* storedUFO = (const storedUFO_t*)cgi->LIST_GetByIdx(productionItemList, 0);
563  } else {
564  const objDef_t* item = (const objDef_t*)cgi->LIST_GetByIdx(productionItemList, 0);
566  }
567  }
568  /* update selection index if first entry of actual list was chosen */
569  if (!selectedProduction) {
570  const production_queue_t* prod = PR_GetProductionForBase(base);
571  cgi->UI_ExecuteConfunc("prod_selectline %i", prod->numItems + QUEUE_SPACERS);
572  }
573 
574  /* Update displayed info about selected entry (if any). */
575  PR_ProductionInfo(base);
576 }
577 
582 static void PR_ProductionList_f (void)
583 {
585  /* can be called from everywhere without a started game */
586  if (!base)
587  return;
588 
589  cgi->Cvar_SetValue("mn_production_basecap", CAP_GetMax(base, CAP_WORKSPACE));
590 
591  /* Set amount of workers - all/ready to work (determined by base capacity. */
593 
594  cgi->Cvar_Set("mn_production_workers", "%i/%i",
596 
597  cgi->Cvar_Set("mn_production_storage", "%i/%i",
599 
601 }
602 
606 static void PR_ProductionIncrease_f (void)
607 {
608  production_t* prod;
610  technology_t* tech = nullptr;
611  int amount = 1;
612  int producibleAmount;
613 
614  if (!base)
615  return;
616 
618  return;
619 
620  if (cgi->Cmd_Argc() == 2)
621  amount = atoi(cgi->Cmd_Argv(1));
622 
623  if (selectedProduction) {
624  prod = selectedProduction;
625 
626  /* We can disassembly UFOs only one-by-one. */
627  if (PR_IsDisassembly(prod))
628  return;
629 
630  if (PR_IsAircraft(prod)) {
631  /* Don't allow to queue more aircraft if there is no free space. */
633  CP_Popup(_("Hangars not ready"), _("You cannot queue aircraft.\nNo free space in hangars.\n"));
634  cgi->Cvar_SetValue("mn_production_amount", prod->amount);
635  return;
636  }
637  }
638 
639  /* amount limit per one production */
640  if (prod->amount + amount > MAX_PRODUCTION_AMOUNT) {
641  amount = std::max(0, MAX_PRODUCTION_AMOUNT - prod->amount);
642  }
643  if (amount == 0) {
644  cgi->Cvar_SetValue("mn_production_amount", prod->amount);
645  return;
646  }
647 
648  tech = PR_GetTech(&prod->data);
649  assert(tech);
650 
651  producibleAmount = PR_RequirementsMet(amount, &tech->requireForProduction, base);
652  if (producibleAmount == 0) {
653  CP_Popup(_("Not enough materials"), _("You don't have the materials needed for producing more of this item.\n"));
654  cgi->Cvar_SetValue("mn_production_amount", prod->amount);
655  return;
656  } else if (amount != producibleAmount) {
657  CP_Popup(_("Not enough material!"), _("You don't have enough material to produce all (%i) additional items. Only %i could be added."), amount, producibleAmount);
658  }
659 
660  PR_IncreaseProduction(prod, producibleAmount);
661  cgi->Cvar_SetValue("mn_production_amount", prod->amount);
662  } else {
663  const char* name = nullptr;
664 
665  tech = PR_GetTech(&selectedData);
667 
668  producibleAmount = PR_RequirementsMet(amount, &tech->requireForProduction, base);
669  if (producibleAmount == 0) {
670  CP_Popup(_("Not enough materials"), _("You don't have the materials needed for producing this item.\n"));
671  return;
672  } else if (amount != producibleAmount) {
673  CP_Popup(_("Not enough material!"), _("You don't have enough material to produce all (%i) items. Production will continue with a reduced (%i) number."), amount, producibleAmount);
674  }
681  CP_Popup(_("Hangars not ready"), _("You cannot queue aircraft.\nNo free space in hangars.\n"));
682  return;
683  }
684 
685  /* add production */
686  prod = PR_QueueNew(base, &selectedData, producibleAmount);
687 
689  if (!prod)
690  return;
691 
692  /* Now we select the item we just created. */
693  selectedProduction = prod;
694  cgi->UI_ExecuteConfunc("prod_selectline %i", selectedProduction->idx);
695 
696  /* messages */
697  Com_sprintf(cp_messageBuffer, sizeof(cp_messageBuffer), _("Work begun on %s"), _(name));
699  }
700 
701  PR_ProductionInfo(base);
703 }
704 
708 static void PR_ProductionStop_f (void)
709 {
710  production_queue_t* queue;
712  int prodIDX;
713 
714  if (!base || !selectedProduction)
715  return;
716 
717  prodIDX = selectedProduction->idx;
718  queue = PR_GetProductionForBase(base);
719 
720  PR_QueueDelete(base, queue, prodIDX);
721 
722  if (queue->numItems == 0) {
723  selectedProduction = nullptr;
724  cgi->UI_ExecuteConfunc("prod_selectline -1");
725  } else if (prodIDX >= queue->numItems) {
726  selectedProduction = &queue->items[queue->numItems - 1];
727  cgi->UI_ExecuteConfunc("prod_selectline %i", prodIDX);
728  }
729 
730  PR_ProductionInfo(base);
732 }
733 
737 static void PR_ProductionDecrease_f (void)
738 {
739  int amount = 1;
740  const base_t* base = B_GetCurrentSelectedBase();
742 
743  if (cgi->Cmd_Argc() == 2)
744  amount = atoi(cgi->Cmd_Argv(1));
745 
746  if (!prod)
747  return;
748 
749  if (prod->amount <= amount) {
751  return;
752  }
753 
755  PR_DecreaseProduction(prod, amount);
756 
757  if (base) {
758  PR_ProductionInfo(base);
760  }
761 }
762 
766 static void PR_ProductionChange_f (void)
767 {
768  int amount;
769 
770  if (!selectedProduction)
771  return;
772 
774  return;
775 
776  if (cgi->Cmd_Argc() != 2) {
777  cgi->Com_Printf("Usage: %s <diff> : change the production amount\n", cgi->Cmd_Argv(0));
778  return;
779  }
780 
781  amount = atoi(cgi->Cmd_Argv(1));
782  if (amount > 0) {
783  cgi->Cbuf_AddText("prod_inc %i\n", amount);
784  } else {
785  cgi->Cbuf_AddText("prod_dec %i\n", -amount);
786  }
787 }
788 
792 static void PR_ProductionUp_f (void)
793 {
794  production_queue_t* queue;
796 
797  if (!base || !selectedProduction)
798  return;
799 
800  /* first position already */
801  if (selectedProduction->idx == 0)
802  return;
803 
804  queue = PR_GetProductionForBase(base);
805  PR_QueueMove(queue, selectedProduction->idx, -1);
806 
808  cgi->UI_ExecuteConfunc("prod_selectline %i", selectedProduction->idx);
810 }
811 
815 static void PR_ProductionDown_f (void)
816 {
817  production_queue_t* queue;
819 
820  if (!base || !selectedProduction)
821  return;
822 
823  queue = PR_GetProductionForBase(base);
824 
825  if (selectedProduction->idx >= queue->numItems - 1)
826  return;
827 
828  PR_QueueMove(queue, selectedProduction->idx, 1);
829 
831  cgi->UI_ExecuteConfunc("prod_selectline %i", selectedProduction->idx);
833 }
834 
838 static void PR_ShowActiveProduction_f (void)
839 {
840  if (cgi->Cmd_Argc() < 2) {
841  cgi->Com_Printf("Usage: %s <base_idx>\n", cgi->Cmd_Argv(0));
842  return;
843  }
844  const base_t* const base = B_GetFoundedBaseByIDX(atoi(cgi->Cmd_Argv(1)));
845  if (base == nullptr) {
846  cgi->Com_Printf("PR_ShowActiveProduction_f: Invalid base_idx!\n");
847  return;
848  }
849  /* Get the production item closest to completion in the base if it exists */
850  if (!PR_ProductionAllowed(base))
851  return;
852  const production_queue_t* const queue = PR_GetProductionForBase(base);
853  if (queue->numItems <= 0)
854  return;
855  const production_t* const production = &queue->items[0];
856  cgi->UI_ExecuteConfunc("show_production %i \"%s\" %3.0f", production->idx, PR_GetName(&production->data), PR_GetProgress(production) * 100);
857 }
858 
859 static const cmdList_t productionCallbacks[] = {
860  {"prod_init", PR_ProductionList_f, nullptr},
861  {"prod_type", PR_ProductionType_f, nullptr},
862  {"prod_up", PR_ProductionUp_f, "Move production item up in the queue"},
863  {"prod_down", PR_ProductionDown_f, "Move production item down in the queue"},
864  {"prod_change", PR_ProductionChange_f, "Change production amount"},
865  {"prod_inc", PR_ProductionIncrease_f, "Increase production amount"},
866  {"prod_dec", PR_ProductionDecrease_f, "Decrease production amount"},
867  {"prod_stop", PR_ProductionStop_f, "Stop production"},
868  {"prodlist_rclick", PR_ProductionListRightClick_f, nullptr},
869  {"prodlist_click", PR_ProductionListClick_f, nullptr},
870  {"prod_show_active", PR_ShowActiveProduction_f, "Show the active production item and it's status"},
871  {nullptr, nullptr, nullptr}
872 };
873 void PR_InitCallbacks (void)
874 {
875  cgi->Cmd_TableAddList(productionCallbacks);
876 }
877 
879 {
880  cgi->Cmd_TableRemoveList(productionCallbacks);
881 }
production_t * PR_QueueNew(base_t *base, const productionData_t *data, signed int amount)
Add a new item to the bottom of the production queue.
Definition: cp_produce.cpp:234
static void PR_ProductionUp_f(void)
shift the current production up the list
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:2133
void PR_InitCallbacks(void)
const aircraft_t * ufoTemplate
void UP_OpenWith(const char *techID)
Opens the UFOpaedia from everywhere with the entry given through name.
csi_t * csi
Definition: cgame.h:100
static itemFilterTypes_t produceCategory
int numAircraftTemplates
Definition: cp_campaign.h:385
uiMessageListNodeMessage_t * MSO_CheckAddNewMessage(const notify_t messagecategory, const char *title, const char *text, messageType_t type, technology_t *pedia, bool popup)
Adds a new message to message stack. It uses message settings to verify whether sound should be playe...
requirement_t links[MAX_TECHLINKS]
Definition: cp_research.h:88
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&#39;t found.
Definition: inv_shared.cpp:282
static const int QUEUE_SPACERS
Number of blank lines between queued items and tech list.
static void PR_ProductionInfo(const base_t *base)
Prints information about the selected item in production.
static void PR_ItemProductionInfo(const base_t *base, const objDef_t *od, int remainingHours)
Prints information about the selected item (no aircraft) in production.
char id[MAX_VAR]
cvar_t *IMPORT * Cvar_Set(const char *varName, const char *value,...) __attribute__((format(__printf__
const char * va(const char *format,...)
does a varargs printf into a temp buffer, so I don&#39;t need to have varargs versions of all text functi...
Definition: shared.cpp:410
A base with all it&#39;s data.
Definition: cp_base.h:84
static void PR_ClearSelected(void)
Resets all "selected" pointers to nullptr.
const char * PR_GetName(const productionData_t *data)
Definition: cp_produce.cpp:182
installation_t * installation
Holds all information for the production of one item-type.
Definition: cp_produce.h:59
#define _(String)
Definition: cl_shared.h:44
char * id
Definition: cp_aircraft.h:120
csi_t csi
Definition: common.cpp:39
bool Com_sprintf(char *dest, size_t size, const char *fmt,...)
copies formatted string with buffer-size checking
Definition: shared.cpp:494
static void PR_ProductionDecrease_f(void)
Decrease the production amount by given parameter.
static productionData_t selectedData
Header for single player market stuff.
#define PR_GetProductionForBase(base)
Definition: cp_produce.h:96
itemFilterTypes_t
A list of filter types in the market and production view.
Definition: cl_inventory.h:35
#define PR_IsDisassembly(prod)
Definition: cp_produce.h:75
int PR_IncreaseProduction(production_t *prod, int amount)
increases production amount if possible
Definition: cp_produce.cpp:490
base_t * B_GetCurrentSelectedBase(void)
returns the currently selected base
Definition: cp_base.cpp:1578
requirements_t requireForProduction
Definition: cp_research.h:181
int US_UFOsInStorage(const aircraft_t *ufoTemplate, const installation_t *installation)
Returns the number of UFOs stored (on an installation or anywhere)
Structure for stored UFOs.
const char *IMPORT * Cmd_Argv(int n)
static void PR_RequirementsInfo(const base_t *base, const requirements_t *reqs)
char name[MAX_VAR]
Definition: cp_aircraft.h:121
#define PR_SetData(dataPtr, typeVal, ptr)
Definition: cp_produce.h:80
#define MAX_PRODUCTION_AMOUNT
Definition: cp_produce.h:30
#define PR_IsItem(prod)
Definition: cp_produce.h:77
static void PR_ProductionType_f(void)
Will select a new tab on the production list.
productionType_t type
Definition: cp_produce.h:53
static void PR_DisassemblyInfo(const storedUFO_t *ufo, int remainingHours)
Prints information about the selected disassembly task.
baseCapacities_t AIR_GetHangarCapacityType(const aircraft_t *aircraft)
Returns capacity type needed for an aircraft.
#define PR_IsItemData(data)
Definition: cp_produce.h:72
static void PR_ProductionIncrease_f(void)
Increases the production amount by given parameter.
#define CAP_GetCurrent(base, capacity)
Definition: cp_capacity.h:52
int E_CountHired(const base_t *const base, employeeType_t type)
Counts hired employees of a given type in a given base.
static void PR_AircraftInfo(const base_t *base, const aircraft_t *aircraftTemplate, int remainingHours)
Prints information about the selected aircraft in production.
int productionCost
Definition: inv_shared.h:333
base_t * B_GetFoundedBaseByIDX(int baseIdx)
Array bound check for the base index.
Definition: cp_base.cpp:326
int CAP_GetFreeCapacity(const base_t *base, baseCapacities_t capacityType)
Returns the free capacity of a type.
union productionData_t::productionItem_t data
Atomic structure used to define most of the UI.
Definition: ui_nodes.h:80
static linkedList_t * productionItemList
static void PR_ProductionDown_f(void)
shift the current production down the list
static void PR_ClearSelectedItems(void)
Resets the selected item data structure. Does not reset the selected production.
static void PR_ShowActiveProduction_f(void)
Show active production item in Base sections.
#define ERR_DROP
Definition: common.h:211
signed int amount
Definition: cp_produce.h:66
#define DEBUG_CLIENT
Definition: defines.h:59
void *IMPORT * LIST_GetByIdx(linkedList_t *list, int index)
#define OBJZERO(obj)
Definition: shared.h:178
int PR_GetRemainingHours(const production_t *prod)
Calculates the remaining hours for a technology.
Definition: cp_produce.cpp:90
#define US_Foreach(var)
void CP_Popup(const char *title, const char *text,...)
Wrapper around UI_Popup.
Definition: cp_popup.cpp:474
struct components_s * comp
static const cmdList_t productionCallbacks[]
const cgame_import_t * cgi
int PR_GetPrice(const int productionCost)
Used in production costs (to allow reducing prices below 1x).
Definition: cp_produce.cpp:667
const char uiNode_t *IMPORT * UI_AddOption(uiNode_t **tree, const char *name, const char *label, const char *value)
struct storedUFO_s * ufo
Definition: cp_produce.h:50
Header for production related stuff.
const char * UFO_TypeToName(const ufoType_t type)
Translate UFO type to name.
Definition: cp_ufo.cpp:231
ccs_t ccs
Definition: cp_campaign.cpp:63
int PR_GetProductionHours(const base_t *base, const productionData_t *prodData)
Calculates the production time (in hours) for a technology.
Definition: cp_produce.cpp:100
Header file for menu related console command callbacks for production menu.
int numODs
Definition: q_shared.h:518
A production queue. Lists all items to be produced.
Definition: cp_produce.h:90
aircraft_t aircraftTemplates[MAX_AIRCRAFT]
Definition: cp_campaign.h:384
void PR_QueueDelete(base_t *base, production_queue_t *queue, int index)
Delete the selected entry from the queue.
Definition: cp_produce.cpp:281
static const vec4_t yellow
Definition: cp_geoscape.cpp:57
ufoType_t getUfoType() const
Definition: cp_aircraft.h:180
char cp_messageBuffer[MAX_MESSAGE_TEXT]
Definition: cp_messages.cpp:33
objDef_t ods[MAX_OBJDEFS]
Definition: q_shared.h:517
static const vec4_t green
Definition: cp_geoscape.cpp:56
uiNode_t * firstChild
Definition: ui_nodes.h:89
productionData_t data
Definition: cp_produce.h:62
const char *IMPORT * INV_GetFilterType(itemFilterTypes_t id)
const struct aircraft_s * aircraft
Definition: cp_produce.h:49
#define CAP_GetMax(base, capacity)
Definition: cp_capacity.h:51
bool PR_ProductionAllowed(const base_t *base)
Returns true if the current base is able to produce items.
Definition: cp_produce.cpp:596
static void PR_ProductionChange_f(void)
Change the production amount by given diff.
An aircraft with all it&#39;s data.
Definition: cp_aircraft.h:115
struct technology_s * tech
Definition: cp_aircraft.h:163
bool isVirtual
Definition: inv_shared.h:284
technology_t * PR_GetTech(const productionData_t *data)
Definition: cp_produce.cpp:199
static void PR_ProductionStop_f(void)
Stops the current running production.
vec4_t color
Definition: ui_nodes.h:127
void PR_ShutdownCallbacks(void)
requirementType_t type
Definition: cp_research.h:74
const char * id
Definition: inv_shared.h:268
int B_AntimatterInBase(const base_t *base)
returns the amount of antimatter stored in a base
Definition: cp_base.cpp:2613
char name[MAX_VAR]
QGL_EXTERN GLint i
Definition: r_gl.h:113
#define AIR_IsUFO(aircraft)
Definition: cp_aircraft.h:206
#define PR_IsAircraftData(data)
Definition: cp_produce.h:71
This is the technology parsed from research.ufo.
Definition: cp_research.h:139
QGL_EXTERN GLuint GLsizei GLsizei GLint GLenum GLchar * name
Definition: r_gl.h:110
int PR_DecreaseProduction(production_t *prod, int amount)
decreases production amount
Definition: cp_produce.cpp:523
union requirement_t::typelink_t link
const char * name
Definition: inv_shared.h:267
static void PR_UpdateProductionList(const base_t *base)
update the list of queued and available items
void Q_strcat(char *dest, size_t destsize, const char *format,...)
Safely (without overflowing the destination buffer) concatenates two strings.
Definition: shared.cpp:475
Defines all attributes of objects used in the inventory.
Definition: inv_shared.h:264
Header file for single player campaign control.
static void PR_ProductionListClick_f(void)
Click function for production list.
#define PR_IsDataValid(dataPtr)
Definition: cp_produce.h:81
#define PR_IsAircraft(prod)
Definition: cp_produce.h:76
bool PR_ItemIsProduceable(const objDef_t *item)
check if an item is producable.
Definition: cp_produce.cpp:640
int PR_RequirementsMet(int amount, const requirements_t *reqs, base_t *base)
Checks if the production requirements are met for a defined amount.
Definition: cp_produce.cpp:147
static void PR_ProductionList_f(void)
Will fill the list of producible items.
void PR_UpdateProductionCap(base_t *base, int workerChange)
Update the current capacity of Workshop.
Definition: cp_produce.cpp:607
#define PR_IsDisassemblyData(data)
Definition: cp_produce.h:70
technology_t * RS_GetTechForItem(const objDef_t *item)
Returns technology entry for an item.
int size
Definition: inv_shared.h:334
Header for base management related stuff.
#define PR_GetProgress(prod)
Definition: cp_produce.h:83
static production_t * selectedProduction
#define ANTIMATTER_ITEM_ID
Definition: cp_research.h:37
void PR_QueueMove(production_queue_t *queue, int index, int offset)
Moves the given queue item in the given direction.
Definition: cp_produce.cpp:308
#define Vector4Copy(src, dest)
Definition: vector.h:53
#define COMP_ITEMCOUNT_SCALED
Definition: cp_component.h:30
int productionCost
Definition: cp_aircraft.h:129
struct production_s items[MAX_PRODUCTIONS]
Definition: cp_produce.h:93
static void PR_ProductionListRightClick_f(void)
Click function for production list.
int AIR_CountInBaseByTemplate(const base_t *base, const aircraft_t *aircraftTemplate)
Calculates the amount of aircraft (of the given type) in the selected base.
Definition: cmd.h:86
vec_t vec4_t[4]
Definition: ufotypes.h:40