UFO: Alien Invasion
Loading...
Searching...
No Matches
cp_produce_callbacks.cpp
Go to the documentation of this file.
1
5
6/*
7Copyright (C) 2002-2025 UFO: Alien Invasion.
8
9This program is free software; you can redistribute it and/or
10modify it under the terms of the GNU General Public License
11as published by the Free Software Foundation; either version 2
12of the License, or (at your option) any later version.
13
14This program is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17
18See the GNU General Public License for more details.
19
20You should have received a copy of the GNU General Public License
21along with this program; if not, write to the Free Software
22Foundation, 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"
34#include "cp_base.h"
35
41
44
47
50
52static const int QUEUE_SPACERS = 2;
53
63
68static void PR_ClearSelected (void)
69{
71 selectedProduction = nullptr;
72}
73
78static 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
189static 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
254static 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
286static 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
320static 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
340static 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 {
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 {
435 objDef_t* od = (objDef_t*)cgi->LIST_GetByIdx(productionItemList, idx);
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
458static 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
488 storedUFO_t* ufo = (storedUFO_t*)cgi->LIST_GetByIdx(productionItemList, idx);
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)) {
507 PR_ProductionInfo(base);
508 }
509 } else {
510 objDef_t* od = (objDef_t*)cgi->LIST_GetByIdx(productionItemList, idx);
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
526static void PR_ProductionType_f (void)
527{
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) {
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
582static 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
606static 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 }
679
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
708static 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
737static 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
766static void PR_ProductionChange_f (void)
767{
768 int amount;
769
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
792static 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
807 selectedProduction = &queue->items[selectedProduction->idx - 1];
808 cgi->UI_ExecuteConfunc("prod_selectline %i", selectedProduction->idx);
810}
811
815static 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
830 selectedProduction = &queue->items[selectedProduction->idx + 1];
831 cgi->UI_ExecuteConfunc("prod_selectline %i", selectedProduction->idx);
833}
834
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
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};
874{
875 cgi->Cmd_TableAddList(productionCallbacks);
876}
877
879{
880 cgi->Cmd_TableRemoveList(productionCallbacks);
881}
Header file for inventory handling and Equipment menu.
itemFilterTypes_t
A list of filter types in the market and production view.
@ FILTER_S_PRIMARY
@ FILTER_AIRCRAFT
@ FILTER_DISASSEMBLY
@ MAX_FILTERTYPES
Share stuff between the different cgame implementations.
#define _(String)
Definition cl_shared.h:44
csi_t csi
Definition common.cpp:39
#define ERR_DROP
Definition common.h:211
int AIR_CountInBaseByTemplate(const base_t *base, const aircraft_t *aircraftTemplate)
Calculates the amount of aircraft (of the given type) in the selected base.
baseCapacities_t AIR_GetHangarCapacityType(const aircraft_t *aircraft)
Returns capacity type needed for an aircraft.
#define AIR_IsUFO(aircraft)
base_t * B_GetFoundedBaseByIDX(int baseIdx)
Array bound check for the base index.
Definition cp_base.cpp:326
base_t * B_GetCurrentSelectedBase(void)
returns the currently selected base
Definition cp_base.cpp:1578
int B_AntimatterInBase(const base_t *base)
returns the amount of antimatter stored in a base
Definition cp_base.cpp:2613
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
Header for base management related stuff.
bool PR_ProductionAllowed(const base_t *base)
Returns true if the current base is able to produce items.
ccs_t ccs
Header file for single player campaign control.
const cgame_import_t * cgi
int CAP_GetFreeCapacity(const base_t *base, baseCapacities_t capacityType)
Returns the free capacity of a type.
#define CAP_GetCurrent(base, capacity)
Definition cp_capacity.h:52
@ CAP_WORKSPACE
Definition cp_capacity.h:34
@ CAP_ITEMS
Definition cp_capacity.h:32
@ CAP_AIRCRAFT_BIG
Definition cp_capacity.h:30
@ CAP_AIRCRAFT_SMALL
Definition cp_capacity.h:29
#define CAP_GetMax(base, capacity)
Definition cp_capacity.h:51
#define COMP_ITEMCOUNT_SCALED
int E_CountHired(const base_t *const base, employeeType_t type)
Counts hired employees of a given type in a given base.
@ EMPL_WORKER
Definition cp_employee.h:33
static const vec4_t yellow
static const vec4_t green
Header for single player market stuff.
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...
@ NT_PRODUCTION_STARTED
char cp_messageBuffer[MAX_MESSAGE_TEXT]
@ MSG_PRODUCTION
Definition cp_messages.h:46
void CP_Popup(const char *title, const char *text,...)
Wrapper around UI_Popup.
Definition cp_popup.cpp:474
void PR_QueueDelete(base_t *base, production_queue_t *queue, int index)
Delete the selected entry from the queue.
const char * PR_GetName(const productionData_t *data)
int PR_GetPrice(const int productionCost)
Used in production costs (to allow reducing prices below 1x).
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.
int PR_DecreaseProduction(production_t *prod, int amount)
decreases production amount
int PR_IncreaseProduction(production_t *prod, int amount)
increases production amount if possible
int PR_RequirementsMet(int amount, const requirements_t *reqs, base_t *base)
Checks if the production requirements are met for a defined amount.
int PR_GetRemainingHours(const production_t *prod)
Calculates the remaining hours for a technology.
void PR_UpdateProductionCap(base_t *base, int workerChange)
Update the current capacity of Workshop.
int PR_GetProductionHours(const base_t *base, const productionData_t *prodData)
Calculates the production time (in hours) for a technology.
void PR_QueueMove(production_queue_t *queue, int index, int offset)
Moves the given queue item in the given direction.
technology_t * PR_GetTech(const productionData_t *data)
bool PR_ItemIsProduceable(const objDef_t *item)
check if an item is producable.
Header for production related stuff.
#define PR_IsDataValid(dataPtr)
Definition cp_produce.h:81
@ PRODUCTION_TYPE_MAX
Definition cp_produce.h:40
@ PRODUCTION_TYPE_DISASSEMBLY
Definition cp_produce.h:38
@ PRODUCTION_TYPE_ITEM
Definition cp_produce.h:36
@ PRODUCTION_TYPE_AIRCRAFT
Definition cp_produce.h:37
#define PR_IsAircraft(prod)
Definition cp_produce.h:76
#define MAX_PRODUCTION_AMOUNT
Definition cp_produce.h:30
#define PR_IsDisassemblyData(data)
Definition cp_produce.h:70
#define PR_SetData(dataPtr, typeVal, ptr)
Definition cp_produce.h:80
#define PR_GetProgress(prod)
Definition cp_produce.h:83
#define PR_GetProductionForBase(base)
Definition cp_produce.h:96
#define PR_IsItemData(data)
Definition cp_produce.h:72
#define PR_IsAircraftData(data)
Definition cp_produce.h:71
#define PR_IsDisassembly(prod)
Definition cp_produce.h:75
#define PR_IsItem(prod)
Definition cp_produce.h:77
static void PR_ProductionStop_f(void)
Stops the current running production.
static void PR_ProductionDecrease_f(void)
Decrease the production amount by given parameter.
static productionData_t selectedData
static void PR_ProductionListClick_f(void)
Click function for production list.
void PR_ShutdownCallbacks(void)
static void PR_ClearSelectedItems(void)
Resets the selected item data structure. Does not reset the selected production.
static void PR_ProductionDown_f(void)
shift the current production down the list
static void PR_RequirementsInfo(const base_t *base, const requirements_t *reqs)
static void PR_ProductionIncrease_f(void)
Increases the production amount by given parameter.
static const cmdList_t productionCallbacks[]
static void PR_ProductionUp_f(void)
shift the current production up the list
static void PR_ClearSelected(void)
Resets all "selected" pointers to nullptr.
static itemFilterTypes_t produceCategory
void PR_InitCallbacks(void)
static void PR_ProductionList_f(void)
Will fill the list of producible items.
static void PR_ProductionListRightClick_f(void)
Click function for production list.
static production_t * selectedProduction
static void PR_AircraftInfo(const base_t *base, const aircraft_t *aircraftTemplate, int remainingHours)
Prints information about the selected aircraft in production.
static void PR_ProductionChange_f(void)
Change the production amount by given diff.
static const int QUEUE_SPACERS
Number of blank lines between queued items and tech list.
static linkedList_t * productionItemList
static void PR_ProductionInfo(const base_t *base)
Prints information about the selected item in production.
static void PR_DisassemblyInfo(const storedUFO_t *ufo, int remainingHours)
Prints information about the selected disassembly task.
static void PR_ItemProductionInfo(const base_t *base, const objDef_t *od, int remainingHours)
Prints information about the selected item (no aircraft) in production.
static void PR_UpdateProductionList(const base_t *base)
update the list of queued and available items
static void PR_ProductionType_f(void)
Will select a new tab on the production list.
static void PR_ShowActiveProduction_f(void)
Show active production item in Base sections.
Header file for menu related console command callbacks for production menu.
technology_t * RS_GetTechForItem(const objDef_t *item)
Returns technology entry for an item.
bool RS_IsResearched_ptr(const technology_t *tech)
Checks whether an item is already researched.
@ RS_LINK_TECH
Definition cp_research.h:62
@ RS_LINK_ITEM
Definition cp_research.h:64
@ RS_LINK_TECH_NOT
Definition cp_research.h:63
@ RS_LINK_ANTIMATTER
Definition cp_research.h:69
#define ANTIMATTER_ITEM_ID
Definition cp_research.h:37
const char * UFO_TypeToName(const ufoType_t type)
Translate UFO type to name.
Definition cp_ufo.cpp:231
void UP_OpenWith(const char *techID)
Opens the UFOpaedia from everywhere with the entry given through name.
int US_UFOsInStorage(const aircraft_t *ufoTemplate, const installation_t *installation)
Returns the number of UFOs stored (on an installation or anywhere).
@ SUFO_STORED
#define US_Foreach(var)
#define DEBUG_CLIENT
Definition defines.h:59
const objDef_t * INVSH_GetItemByID(const char *id)
Returns the item that belongs to the given id or nullptr if it wasn't found.
QGL_EXTERN GLint i
Definition r_gl.h:113
QGL_EXTERN GLuint GLsizei GLsizei GLint GLenum GLchar * name
Definition r_gl.h:110
#define OBJZERO(obj)
Definition shared.h:178
void Q_strcat(char *dest, size_t destsize, const char *format,...)
Safely (without overflowing the destination buffer) concatenates two strings.
Definition shared.cpp:475
bool Com_sprintf(char *dest, size_t size, const char *fmt,...)
copies formatted string with buffer-size checking
Definition shared.cpp:494
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
An aircraft with all it's data.
int productionCost
char name[MAX_VAR]
ufoType_t getUfoType() const
struct technology_s * tech
A base with all it's data.
Definition cp_base.h:84
char name[MAX_VAR]
Defines all attributes of objects used in the inventory.
Definition inv_shared.h:264
bool isVirtual
Definition inv_shared.h:284
int productionCost
Definition inv_shared.h:333
const char * id
Definition inv_shared.h:268
const char * name
Definition inv_shared.h:267
A production queue. Lists all items to be produced.
Definition cp_produce.h:91
struct production_s items[MAX_PRODUCTIONS]
Definition cp_produce.h:93
Holds all information for the production of one item-type.
Definition cp_produce.h:60
signed int amount
Definition cp_produce.h:66
productionData_t data
Definition cp_produce.h:62
union productionData_t::productionItem_t data
union requirement_t::typelink_t link
requirementType_t type
Definition cp_research.h:74
requirement_t links[MAX_TECHLINKS]
Definition cp_research.h:88
Structure for stored UFOs.
struct components_s * comp
const aircraft_t * ufoTemplate
char id[MAX_VAR]
installation_t * installation
This is the technology parsed from research.ufo.
requirements_t requireForProduction
Atomic structure used to define most of the UI.
Definition ui_nodes.h:80
uiNode_t * firstChild
Definition ui_nodes.h:89
vec4_t color
Definition ui_nodes.h:127
vec_t vec4_t[4]
Definition ufotypes.h:40
@ TEXT_PRODUCTION_QUEUED
Definition ui_dataids.h:46
@ TEXT_PRODUCTION_LIST
Definition ui_dataids.h:42
@ TEXT_PRODUCTION_INFO
Definition ui_dataids.h:44
@ TEXT_PRODUCTION_AMOUNT
Definition ui_dataids.h:43
@ OPTION_PRODUCTION_REQUIREMENTS
Definition ui_dataids.h:85
const struct aircraft_s * aircraft
Definition cp_produce.h:49
#define Vector4Copy(src, dest)
Definition vector.h:53