cp_produce_callbacks.c

Go to the documentation of this file.
00001 
00006 /*
00007 Copyright (C) 2002-2010 UFO: Alien Invasion.
00008 
00009 This program is free software; you can redistribute it and/or
00010 modify it under the terms of the GNU General Public License
00011 as published by the Free Software Foundation; either version 2
00012 of the License, or (at your option) any later version.
00013 
00014 This program is distributed in the hope that it will be useful,
00015 but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00017 
00018 See the GNU General Public License for more details.
00019 
00020 You should have received a copy of the GNU General Public License
00021 along with this program; if not, write to the Free Software
00022 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00023 
00024 */
00025 
00026 #include "../cl_shared.h"
00027 #include "../cl_inventory.h"
00028 #include "../ui/ui_main.h"
00029 #include "../ui/ui_popup.h"
00030 #include "cp_campaign.h"
00031 #include "cp_market.h"
00032 #include "cp_ufo.h"
00033 #include "cp_produce.h"
00034 #include "cp_produce_callbacks.h"
00035 
00040 static int produceCategory = FILTER_S_PRIMARY;
00041 
00043 static production_t *selectedProduction = NULL;
00044 
00046 static linkedList_t *productionItemList;
00047 
00049 static objDef_t *selectedItem = NULL;
00050 static storedUFO_t *selectedDisassembly = NULL;
00051 static aircraft_t *selectedAircraft = NULL;
00052 
00054 static const int QUEUE_SPACERS = 2;
00055 
00059 static void PR_ClearSelected (void)
00060 {
00061     selectedProduction = NULL;
00062     selectedAircraft = NULL;
00063     selectedItem = NULL;
00064     selectedDisassembly = NULL;
00065 }
00066 
00071 static void PR_UpdateProductionList (const base_t* base)
00072 {
00073     int i, j, counter;
00074     linkedList_t *productionList = NULL;
00075     linkedList_t *productionQueued = NULL;
00076     linkedList_t *productionAmount = NULL;
00077     const production_queue_t *queue;
00078 
00079     assert(base);
00080 
00081     queue = &ccs.productions[base->idx];
00082 
00083     /* First add all the queue items ... */
00084     for (i = 0; i < queue->numItems; i++) {
00085         const production_t *prod = &queue->items[i];
00086         if (prod->item) {
00087             const objDef_t *od = prod->item;
00088             LIST_AddString(&productionList, va("%s", _(od->name)));
00089             LIST_AddString(&productionAmount, va("%i", base->storage.numItems[prod->item->idx]));
00090             LIST_AddString(&productionQueued, va("%i", prod->amount));
00091         } else if (prod->aircraft) {
00092             const aircraft_t *aircraftTemplate = prod->aircraft;
00093             LIST_AddString(&productionList, va("%s", _(aircraftTemplate->name)));
00094             for (j = 0, counter = 0; j < ccs.numAircraft; j++) {
00095                 const aircraft_t *aircraftBase = AIR_AircraftGetFromIDX(j);
00096                 assert(aircraftBase);
00097                 if (aircraftBase->homebase == base && aircraftBase->tpl == aircraftTemplate)
00098                     counter++;
00099             }
00100             LIST_AddString(&productionAmount, va("%i", counter));
00101             LIST_AddString(&productionQueued, va("%i", prod->amount));
00102         } else if (prod->ufo) {
00103             const storedUFO_t *ufo = prod->ufo;
00104 
00105             LIST_AddString(&productionList, va("%s (%.0f%%)", UFO_TypeToName(ufo->ufoTemplate->ufotype), ufo->condition * 100));
00106             LIST_AddString(&productionAmount, va("%i", US_UFOsInStorage(ufo->ufoTemplate, ufo->installation)));
00107             LIST_AddString(&productionQueued, "1");
00108         }
00109     }
00110 
00111     /* Then spacers ... */
00112     for (i = 0; i < QUEUE_SPACERS; i++) {
00113         LIST_AddString(&productionList, "");
00114         LIST_AddString(&productionAmount, "");
00115         LIST_AddString(&productionQueued, "");
00116     }
00117 
00118     LIST_Delete(&productionItemList);
00119 
00120     /* Then go through all object definitions ... */
00121     if (produceCategory == FILTER_DISASSEMBLY) {
00122         storedUFO_t *ufo = NULL;
00124         while ((ufo = US_GetNext(ufo)) != NULL) {
00125             /* UFO is being transported */
00126             if (ufo->status != SUFO_STORED)
00127                 continue;
00128             /* UFO not researched */
00129             if (!RS_IsResearched_ptr(ufo->ufoTemplate->tech))
00130                 continue;
00131             /* The UFO is being disassembled aready */
00132             if (ufo->disassembly)
00133                 continue;
00134 
00135             LIST_AddPointer(&productionItemList, ufo);
00136             LIST_AddString(&productionList, va("%s (%.0f%%)", UFO_TypeToName(ufo->ufoTemplate->ufotype), ufo->condition * 100));
00137             LIST_AddString(&productionAmount, va("%i", US_UFOsInStorage(ufo->ufoTemplate, ufo->installation)));
00138             LIST_AddString(&productionQueued, "");
00139         }
00140     } else if (produceCategory == FILTER_AIRCRAFT) {
00141         for (i = 0; i < ccs.numAircraftTemplates; i++) {
00142             aircraft_t *aircraftTemplate = &ccs.aircraftTemplates[i];
00143             /* don't allow producing ufos */
00144             if (AIR_IsUFO(aircraftTemplate))
00145                 continue;
00146             if (!aircraftTemplate->tech) {
00147                 Com_Printf("PR_UpdateProductionList: no technology for craft %s!\n", aircraftTemplate->id);
00148                 continue;
00149             }
00150 
00151             Com_DPrintf(DEBUG_CLIENT, "air: %s ufotype: %i tech: %s time: %i\n", aircraftTemplate->id,
00152                     aircraftTemplate->ufotype, aircraftTemplate->tech->id, aircraftTemplate->tech->produceTime);
00153 
00154             if (aircraftTemplate->tech->produceTime > 0 && RS_IsResearched_ptr(aircraftTemplate->tech)) {
00155                 LIST_AddPointer(&productionItemList, aircraftTemplate);
00156 
00157                 LIST_AddString(&productionList, va("%s", _(aircraftTemplate->name)));
00158                 for (j = 0, counter = 0; j < ccs.numAircraft; j++) {
00159                     const aircraft_t *aircraftBase = AIR_AircraftGetFromIDX(j);
00160                     assert(aircraftBase);
00161                     if (aircraftBase->homebase == base && aircraftBase->tpl == aircraftTemplate)
00162                         counter++;
00163                 }
00164                 LIST_AddString(&productionAmount, va("%i", counter));
00165                 LIST_AddString(&productionQueued, "");
00166             }
00167         }
00168     } else {
00169         objDef_t *od;
00170         for (i = 0, od = csi.ods; i < csi.numODs; i++, od++) {
00171             const technology_t *tech;
00172             if (od->isVirtual)
00173                 continue;
00174             tech = RS_GetTechForItem(od);
00175             /* We will not show items that are not producible.
00176              * We can only produce what was researched before. */
00177             if (RS_IsResearched_ptr(tech) && PR_ItemIsProduceable(od) && INV_ItemMatchesFilter(od, produceCategory)) {
00178                 LIST_AddPointer(&productionItemList, od);
00179 
00180                 LIST_AddString(&productionList, va("%s", _(od->name)));
00181                 LIST_AddString(&productionAmount, va("%i", base->storage.numItems[i]));
00182                 LIST_AddString(&productionQueued, "");
00183             }
00184         }
00185     }
00186 
00187     /* bind the menu text to our static char array */
00188     UI_RegisterLinkedListText(TEXT_PRODUCTION_LIST, productionList);
00189     /* bind the amount of available items */
00190     UI_RegisterLinkedListText(TEXT_PRODUCTION_AMOUNT, productionAmount);
00191     /* bind the amount of queued items */
00192     UI_RegisterLinkedListText(TEXT_PRODUCTION_QUEUED, productionQueued);
00193 }
00194 
00202 static void PR_ItemProductionInfo (const base_t *base, const objDef_t *od, const float percentDone)
00203 {
00204     static char productionInfo[512];
00205 
00206     assert(base);
00207     assert(od);
00208 
00209     /* Don't try to display an item which is not producible. */
00210     if (!PR_ItemIsProduceable(od)) {
00211         Com_sprintf(productionInfo, sizeof(productionInfo), _("No item selected"));
00212         Cvar_Set("mn_item", "");
00213     } else {
00214         const technology_t *tech = RS_GetTechForItem(od);
00215         const float prodPerHour = PR_CalculateProductionPercentDone(base, tech, NULL);
00216         /* If you entered production menu, that means that prodPerHour > 0 (must not divide by 0) */
00217         const int time = ceil((1.0f - percentDone) / prodPerHour);
00218 
00219         Com_sprintf(productionInfo, sizeof(productionInfo), "%s\n", _(od->name));
00220         Q_strcat(productionInfo, va(_("Costs per item\t%i c\n"), (od->price * PRODUCE_FACTOR / PRODUCE_DIVISOR)),
00221             sizeof(productionInfo));
00222         Q_strcat(productionInfo, va(_("Production time\t%ih\n"), time), sizeof(productionInfo));
00223         Q_strcat(productionInfo, va(_("Item size\t%i\n"), od->size), sizeof(productionInfo));
00224         Cvar_Set("mn_item", od->id);
00225     }
00226     UI_RegisterText(TEXT_PRODUCTION_INFO, productionInfo);
00227 }
00228 
00236 static void PR_DisassemblyInfo (const base_t *base, const storedUFO_t *ufo, float percentDone)
00237 {
00238     static char productionInfo[512];
00239     int time, i;
00240     float prodPerHour;
00241 
00242     assert(base);
00243     assert(ufo);
00244     assert(ufo->ufoTemplate);
00245     assert(ufo->ufoTemplate->tech);
00246 
00247     prodPerHour = PR_CalculateProductionPercentDone(base, ufo->ufoTemplate->tech, ufo);
00248     /* If you entered production menu, that means that prodPerHour > 0 (must not divide by 0) */
00249     assert(prodPerHour > 0);
00250     time = ceil((1.0f - percentDone) / prodPerHour);
00251 
00252     Com_sprintf(productionInfo, sizeof(productionInfo), "%s (%.0f%%) - %s\n", _(UFO_TypeToName(ufo->ufoTemplate->ufotype)), ufo->condition * 100, _("Disassembly"));
00253     Q_strcat(productionInfo, va(_("Stored at: %s\n"), ufo->installation->name), sizeof(productionInfo));
00254     Q_strcat(productionInfo, va(_("Disassembly time: %ih\n"), time), sizeof(productionInfo));
00255     Q_strcat(productionInfo, _("Components:\n"), sizeof(productionInfo));
00256     /* Print components. */
00257     for (i = 0; i < ufo->comp->numItemtypes; i++) {
00258         const objDef_t *compOd = ufo->comp->items[i];
00259         const int amount = (ufo->condition < 1 && ufo->comp->itemAmount2[i] != COMP_ITEMCOUNT_SCALED) ? ufo->comp->itemAmount2[i] : round(ufo->comp->itemAmount[i] * ufo->condition);
00260 
00261         assert(compOd);
00262         if (amount == 0)
00263             continue;
00264 
00265         Q_strcat(productionInfo, va("  %s (%i)\n", _(compOd->name), amount), sizeof(productionInfo));
00266     }
00267     UI_RegisterText(TEXT_PRODUCTION_INFO, productionInfo);
00268     Cvar_Set("mn_item", ufo->id);
00269 }
00270 
00276 static void PR_AircraftInfo (const base_t *base, const aircraft_t *aircraftTemplate, float percentDone)
00277 {
00278     static char productionInfo[512];
00279     int time;
00280     float prodPerHour;
00281     assert(aircraftTemplate);
00282 
00283     prodPerHour = PR_CalculateProductionPercentDone(base, aircraftTemplate->tech, NULL);
00284     /* If you entered production menu, that means that prodPerHour > 0 (must not divide by 0) */
00285     assert(prodPerHour > 0);
00286     time = ceil((1.0f - percentDone) / prodPerHour);
00287 
00288     Com_sprintf(productionInfo, sizeof(productionInfo), "%s\n", _(aircraftTemplate->name));
00289     Q_strcat(productionInfo, va(_("Production costs\t%i c\n"), (aircraftTemplate->price * PRODUCE_FACTOR / PRODUCE_DIVISOR)),
00290         sizeof(productionInfo));
00291     assert(aircraftTemplate->tech);
00292     Q_strcat(productionInfo, va(_("Production time\t%ih\n"), time), sizeof(productionInfo));
00293     UI_RegisterText(TEXT_PRODUCTION_INFO, productionInfo);
00294     Cvar_Set("mn_item", aircraftTemplate->id);
00295 }
00296 
00304 static void PR_ProductionInfo (const base_t *base)
00305 {
00306     if (selectedProduction) {
00307         production_t *prod = selectedProduction;
00308         UI_ExecuteConfunc("prod_taskselected");
00309         if (prod->aircraft) {
00310             PR_AircraftInfo(base, prod->aircraft, prod->percentDone);
00311             UI_ExecuteConfunc("amountsetter enable");
00312         } else if (prod->item) {
00313             PR_ItemProductionInfo(base, prod->item, prod->percentDone);
00314             UI_ExecuteConfunc("amountsetter enable");
00315         } else if (prod->ufo) {
00316             PR_DisassemblyInfo(base, prod->ufo, prod->percentDone);
00317             UI_ExecuteConfunc("amountsetter disable");
00318         } else {
00319             Com_Error(ERR_DROP, "PR_ProductionInfo: Selected production is not item nor aircraft nor ufo.\n");
00320         }
00321         Cvar_SetValue("mn_production_amount", selectedProduction->amount);
00322     } else {
00323         if (!(selectedAircraft || selectedItem || selectedDisassembly)) {
00324             UI_ExecuteConfunc("prod_nothingselected");
00325             if (produceCategory == FILTER_AIRCRAFT)
00326                 UI_RegisterText(TEXT_PRODUCTION_INFO, _("No aircraft selected."));
00327             else
00328                 UI_RegisterText(TEXT_PRODUCTION_INFO, _("No item selected"));
00329             Cvar_Set("mn_item", "");
00330         } else {
00331             UI_ExecuteConfunc("prod_availableselected");
00332             if (selectedAircraft) {
00333                 PR_AircraftInfo(base, selectedAircraft, 0.0);
00334             } else if (selectedItem) {
00335                 PR_ItemProductionInfo(base, selectedItem, 0.0);
00336             } else if (selectedDisassembly) {
00337                 PR_DisassemblyInfo(base, selectedDisassembly, 0.0);
00338             }
00339         }
00340     }
00341 }
00342 
00347 static void PR_ProductionListRightClick_f (void)
00348 {
00349     int num;
00350     production_queue_t *queue;
00351     base_t *base = B_GetCurrentSelectedBase();
00352 
00353     /* can be called from everywhere without a base set */
00354     if (!base)
00355         return;
00356 
00357     queue = &ccs.productions[base->idx];
00358 
00359     /* not enough parameters */
00360     if (Cmd_Argc() < 2) {
00361         Com_Printf("Usage: %s <arg>\n", Cmd_Argv(0));
00362         return;
00363     }
00364 
00365     /* clicked which item? */
00366     num = atoi(Cmd_Argv(1));
00367 
00368     /* Clicked the production queue or the item list? */
00369     if (num < queue->numItems && num >= 0) {
00370         selectedProduction = &queue->items[num];
00371         if (selectedProduction->aircraft) {
00372             assert(selectedProduction->aircraft->tech);
00373             UP_OpenWith(selectedProduction->aircraft->tech->id);
00374         } else if (selectedProduction->item) {
00375             const objDef_t *od = selectedProduction->item;
00376             const technology_t *tech = RS_GetTechForItem(od);
00377             UP_OpenWith(tech->id);
00378         } else if (selectedProduction->ufo) {
00379             const aircraft_t *ufoTemplate = selectedProduction->ufo->ufoTemplate;
00380             const technology_t *tech = ufoTemplate->tech;
00381             UP_OpenWith(tech->id);
00382         }
00383     } else if (num >= queue->numItems + QUEUE_SPACERS) {
00384         /* Clicked in the item list. */
00385         const int idx = num - queue->numItems - QUEUE_SPACERS;
00386 
00387         if (produceCategory == FILTER_AIRCRAFT) {
00388             const aircraft_t *aircraftTemplate = (aircraft_t*)LIST_GetByIdx(productionItemList, idx);
00389             /* aircraftTemplate may be empty if rclicked below real entry.
00390              * UFO research definition must not have a tech assigned,
00391              * only RS_CRAFT types have */
00392             if (aircraftTemplate && aircraftTemplate->tech)
00393                 UP_OpenWith(aircraftTemplate->tech->id);
00394         } else if (produceCategory == FILTER_DISASSEMBLY) {
00395             storedUFO_t *ufo = (storedUFO_t*)LIST_GetByIdx(productionItemList, idx);
00396             if (ufo && ufo->ufoTemplate && ufo->ufoTemplate->tech) {
00397                 UP_OpenWith(ufo->ufoTemplate->tech->id);
00398             }
00399         } else {
00400             objDef_t *od = (objDef_t*)LIST_GetByIdx(productionItemList, idx);
00401             const technology_t *tech = RS_GetTechForItem(od);
00402 
00403             /* Open up UFOpaedia for this entry. */
00404             if (RS_IsResearched_ptr(tech) && INV_ItemMatchesFilter(od, produceCategory)) {
00405                 PR_ClearSelected();
00406                 selectedItem = od;
00407                 UP_OpenWith(tech->id);
00408                 return;
00409             }
00410         }
00411     }
00412 #ifdef DEBUG
00413     else
00414         Com_DPrintf(DEBUG_CLIENT, "PR_ProductionListRightClick_f: Click on spacer %i\n", num);
00415 #endif
00416 }
00417 
00423 static void PR_ProductionListClick_f (void)
00424 {
00425     int num;
00426     production_queue_t *queue;
00427     base_t *base = B_GetCurrentSelectedBase();
00428 
00429     /* can be called from everywhere without a base set */
00430     if (!base)
00431         return;
00432 
00433     queue = &ccs.productions[base->idx];
00434 
00435     /* Break if there are not enough parameters. */
00436     if (Cmd_Argc() < 2) {
00437         Com_Printf("Usage: %s <arg>\n", Cmd_Argv(0));
00438         return;
00439     }
00440 
00441     /* Clicked which item? */
00442     num = atoi(Cmd_Argv(1));
00443 
00444     /* Clicked the production queue or the item list? */
00445     if (num < queue->numItems && num >= 0) {
00446         selectedProduction = &queue->items[num];
00447         PR_ProductionInfo(base);
00448     } else if (num >= queue->numItems + QUEUE_SPACERS) {
00449         /* Clicked in the item list. */
00450         const int idx = num - queue->numItems - QUEUE_SPACERS;
00451 
00452         if (produceCategory == FILTER_DISASSEMBLY) {
00453             storedUFO_t *ufo = (storedUFO_t*)LIST_GetByIdx(productionItemList, idx);
00454 
00455             PR_ClearSelected();
00456             selectedDisassembly = ufo;
00457 
00458             PR_ProductionInfo(base);
00459         } else if (produceCategory == FILTER_AIRCRAFT) {
00460             aircraft_t *aircraftTemplate = (aircraft_t*)LIST_GetByIdx(productionItemList, idx);
00461             if (!aircraftTemplate) {
00462                 Com_DPrintf(DEBUG_CLIENT, "PR_ProductionListClick_f: No item found at the list-position %i!\n", idx);
00463                 return;
00464             }
00465             /* ufo research definition must not have a tech assigned
00466              * only RS_CRAFT types have
00467              * @sa RS_InitTree */
00468             if (aircraftTemplate->tech && aircraftTemplate->tech->produceTime >= 0
00469              && RS_IsResearched_ptr(aircraftTemplate->tech)) {
00470                 PR_ClearSelected();
00471                 selectedAircraft = aircraftTemplate;
00472                 PR_ProductionInfo(base);
00473             }
00474         } else {
00475             objDef_t *od = (objDef_t*)LIST_GetByIdx(productionItemList, idx);
00476             const technology_t *tech = RS_GetTechForItem(od);
00477 
00478             /* We can only produce items that fulfill the following conditions... */
00479             if (RS_IsResearched_ptr(tech) && PR_ItemIsProduceable(od) && INV_ItemMatchesFilter(od, produceCategory)) {
00480                 PR_ClearSelected();
00481                 selectedItem = od;
00482                 PR_ProductionInfo(base);
00483             }
00484         }
00485     }
00486 }
00487 
00491 static void PR_ProductionType_f (void)
00492 {
00493     int cat;
00494     base_t *base = B_GetCurrentSelectedBase();
00495 
00496     if (Cmd_Argc() < 2) {
00497         Com_Printf("Usage: %s <category>\n", Cmd_Argv(0));
00498         return;
00499     }
00500 
00501     cat = INV_GetFilterTypeID(Cmd_Argv(1));
00502 
00503     /* Check if the given category index is valid. */
00504     if (cat < 0 || cat >= MAX_FILTERTYPES)
00505         cat = FILTER_S_PRIMARY;
00506 
00507     /* Can be called from everywhere without a base set */
00508     if (!base)
00509         return;
00510 
00511     produceCategory = cat;
00512     Cvar_Set("mn_itemtype", INV_GetFilterType(produceCategory));
00513 
00514     /* Update list of entries for current production tab. */
00515     PR_UpdateProductionList(base);
00516 
00517     /* Reset selected entry, if it was not from the queue */
00518     selectedItem = NULL;
00519     selectedDisassembly = NULL;
00520     selectedAircraft = NULL;
00521 
00522     /* Select first entry in the list (if any). */
00523     if (LIST_Count(productionItemList) > 0) {
00524         if (produceCategory == FILTER_AIRCRAFT)
00525             selectedAircraft = (aircraft_t*)LIST_GetByIdx(productionItemList, 0);
00526         else if (produceCategory == FILTER_DISASSEMBLY)
00527             selectedDisassembly = (storedUFO_t*)LIST_GetByIdx(productionItemList, 0);
00528         else
00529             selectedItem = (objDef_t*)LIST_GetByIdx(productionItemList, 0);
00530     }
00531     /* update selection index if first entry of actual list was chosen */
00532     if (!selectedProduction)
00533         UI_ExecuteConfunc("prod_selectline %i", ccs.productions[base->idx].numItems + QUEUE_SPACERS);
00534 
00535     /* Update displayed info about selected entry (if any). */
00536     PR_ProductionInfo(base);
00537 }
00538 
00543 static void PR_ProductionList_f (void)
00544 {
00545     char tmpbuf[MAX_VAR];
00546     int numWorkshops;
00547     base_t *base = B_GetCurrentSelectedBase();
00548 
00549     /* can be called from everywhere without a started game */
00550     if (!base)
00551         return;
00552 
00553     numWorkshops = max(0, B_GetNumberOfBuildingsInBaseByBuildingType(base, B_WORKSHOP));
00554 
00555     Cvar_SetValue("mn_production_limit", MAX_PRODUCTIONS_PER_WORKSHOP * numWorkshops);
00556     Cvar_SetValue("mn_production_basecap", base->capacities[CAP_WORKSPACE].max);
00557 
00558     /* Set amount of workers - all/ready to work (determined by base capacity. */
00559     PR_UpdateProductionCap(base);
00560 
00561     Com_sprintf(tmpbuf, sizeof(tmpbuf), "%i/%i",
00562         base->capacities[CAP_WORKSPACE].cur,
00563         E_CountHired(base, EMPL_WORKER));
00564     Cvar_Set("mn_production_workers", tmpbuf);
00565 
00566     Com_sprintf(tmpbuf, sizeof(tmpbuf), "%i/%i",
00567         base->capacities[CAP_ITEMS].cur,
00568         base->capacities[CAP_ITEMS].max);
00569     Cvar_Set("mn_production_storage", tmpbuf);
00570 
00571     PR_ClearSelected();
00572 }
00573 
00577 static void PR_ProductionIncrease_f (void)
00578 {
00579     production_queue_t *queue;
00580     production_t *prod;
00581     base_t *base = B_GetCurrentSelectedBase();
00582     technology_t *tech = NULL;
00583     int amount = 1;
00584     int producibleAmount;
00585     static char productionPopup[UI_MAX_SMALLTEXTLEN];
00586 
00587     if (!base)
00588         return;
00589 
00590     if (!(selectedProduction || selectedAircraft || selectedItem || selectedDisassembly))
00591         return;
00592 
00593     if (Cmd_Argc() == 2)
00594         amount = atoi(Cmd_Argv(1));
00595 
00596     queue = &ccs.productions[base->idx];
00597 
00598     if (selectedProduction) {
00599         prod = selectedProduction;
00600 
00601         /* We can disassembly UFOs only one-by-one. */
00602         if (prod->ufo)
00603             return;
00604 
00605         if (prod->aircraft) {
00606             /* Don't allow to queue more aircraft if there is no free space. */
00607             if (AIR_CalculateHangarStorage(prod->aircraft, base, 0) <= 0) {
00608                 UI_Popup(_("Hangars not ready"), _("You cannot queue aircraft.\nNo free space in hangars.\n"));
00609                 Cvar_SetValue("mn_production_amount", prod->amount);
00610                 return;
00611             }
00612         }
00613 
00614         /* amount limit per one production */
00615         if (prod->amount + amount > MAX_PRODUCTION_AMOUNT) {
00616             amount = max(0, MAX_PRODUCTION_AMOUNT - prod->amount);
00617         }
00618         if (amount == 0) {
00619             Cvar_SetValue("mn_production_amount", prod->amount);
00620             return;
00621         }
00622 
00623         if (prod->item) {
00624             tech = RS_GetTechForItem(prod->item);
00625         } else if (prod->aircraft) {
00626             tech = prod->aircraft->tech;
00627         }
00628         assert(tech);
00629 
00630         producibleAmount = PR_RequirementsMet(amount, &tech->requireForProduction, base);
00631         if (producibleAmount == 0) {
00632             UI_Popup(_("Not enough materials"), _("You don't have the materials needed for producing more of this item.\n"));
00633             Cvar_SetValue("mn_production_amount", prod->amount);
00634             return;
00635         } else if (amount != producibleAmount) {
00636             Com_sprintf(productionPopup, lengthof(productionPopup), _("You don't have enough material to produce all (%i) additional items. Only %i could be added."), amount, producibleAmount);
00637             UI_Popup(_("Not enough material!"), productionPopup);
00638         }
00639 
00640         PR_IncreaseProduction(prod, producibleAmount);
00641         Cvar_SetValue("mn_production_amount", prod->amount);
00642     } else {
00643         const char *name = NULL;
00644 
00645         /* no free production slot */
00646         if (PR_QueueFreeSpace(queue) <= 0) {
00647             UI_Popup(_("Not enough workshops"), _("You cannot queue more items.\nBuild more workshops.\n"));
00648             return;
00649         }
00650 
00651         if (selectedItem) {
00652             tech = RS_GetTechForItem(selectedItem);
00653             name = selectedItem->name;
00654         } else if (selectedAircraft) {
00655             tech = selectedAircraft->tech;
00656             name = selectedAircraft->name;
00657         } else if (selectedDisassembly) {
00658             assert(selectedDisassembly->ufoTemplate);
00659             tech = selectedDisassembly->ufoTemplate->tech;
00660             name = selectedDisassembly->ufoTemplate->name;
00661             amount = 1;
00662         }
00663         assert(tech);
00664         assert(name);
00665 
00666         producibleAmount = PR_RequirementsMet(amount, &tech->requireForProduction, base);
00667         if (producibleAmount == 0) {
00668             UI_Popup(_("Not enough materials"), _("You don't have the materials needed for producing this item.\n"));
00669             return;
00670         } else if (amount != producibleAmount) {
00671             Com_sprintf(productionPopup, lengthof(productionPopup), _("You don't have enough material to produce all (%i) items. Production will continue with a reduced (%i) number."), amount, producibleAmount);
00672             UI_Popup(_("Not enough material!"), productionPopup);
00673         }
00679         if (selectedAircraft && AIR_CalculateHangarStorage(selectedAircraft, base, 0) <= 0) {
00680             UI_Popup(_("Hangars not ready"), _("You cannot queue aircraft.\nNo free space in hangars.\n"));
00681             return;
00682         }
00683 
00684         /* add production */
00685         prod = PR_QueueNew(base, queue, selectedItem, selectedAircraft, selectedDisassembly, producibleAmount);
00686 
00688         if (!prod)
00689             return;
00690 
00691         /* Now we select the item we just created. */
00692         UI_ExecuteConfunc("prod_selectline %i", prod->idx);
00693         PR_ClearSelected();
00694         selectedProduction = &queue->items[queue->numItems - 1];
00695 
00696         /* messages */
00697         Com_sprintf(cp_messageBuffer, sizeof(cp_messageBuffer), _("Production of %s started"), _(name));
00698         MSO_CheckAddNewMessage(NT_PRODUCTION_STARTED, _("Production started"), cp_messageBuffer, qfalse, MSG_PRODUCTION, tech);
00699     }
00700 
00701     PR_ProductionInfo(base);
00702     PR_UpdateProductionList(base);
00703 }
00704 
00708 static void PR_ProductionStop_f (void)
00709 {
00710     production_queue_t *queue;
00711     base_t *base = B_GetCurrentSelectedBase();
00712     int prodIDX;
00713 
00714     if (!base || !selectedProduction)
00715         return;
00716 
00717     prodIDX = selectedProduction->idx;
00718     queue = &ccs.productions[base->idx];
00719 
00720     PR_QueueDelete(base, queue, prodIDX);
00721 
00722     if (queue->numItems == 0) {
00723         selectedProduction = NULL;
00724         UI_ExecuteConfunc("prod_selectline -1");
00725     } else if (prodIDX >= queue->numItems) {
00726         selectedProduction = &queue->items[queue->numItems - 1];
00727         UI_ExecuteConfunc("prod_selectline %i", prodIDX);
00728     }
00729 
00730     PR_ProductionInfo(base);
00731     PR_UpdateProductionList(base);
00732 }
00733 
00737 static void PR_ProductionDecrease_f (void)
00738 {
00739     int amount = 1;
00740     base_t *base = B_GetCurrentSelectedBase();
00741     production_t *prod = selectedProduction;
00742 
00743     if (Cmd_Argc() == 2)
00744         amount = atoi(Cmd_Argv(1));
00745 
00746     if (!prod)
00747         return;
00748 
00749     if (prod->amount <= amount) {
00750         PR_ProductionStop_f();
00751         return;
00752     }
00753 
00755     PR_DecreaseProduction(prod, amount);
00756 
00757     if (base) {
00758         PR_ProductionInfo(base);
00759         PR_UpdateProductionList(base);
00760     }
00761 }
00762 
00766 static void PR_ProductionChange_f (void)
00767 {
00768     int amount;
00769 
00770     if (!(selectedProduction || selectedAircraft || selectedItem || selectedDisassembly))
00771         return;
00772 
00773     if (Cmd_Argc() != 2) {
00774         Com_Printf("Usage: %s <diff> : change the production amount\n", Cmd_Argv(0));
00775         return;
00776     }
00777 
00778     amount = atoi(Cmd_Argv(1));
00779     if (amount > 0) {
00780         Cbuf_AddText(va("prod_inc %i\n", amount));
00781     } else {
00782         Cbuf_AddText(va("prod_dec %i\n", -amount));
00783     }
00784 }
00785 
00789 static void PR_ProductionUp_f (void)
00790 {
00791     production_queue_t *queue;
00792     base_t *base = B_GetCurrentSelectedBase();
00793 
00794     if (!base || !selectedProduction)
00795         return;
00796 
00797     /* first position already */
00798     if (selectedProduction->idx == 0)
00799         return;
00800 
00801     queue = &ccs.productions[base->idx];
00802     PR_QueueMove(queue, selectedProduction->idx, -1);
00803 
00804     selectedProduction = &queue->items[selectedProduction->idx - 1];
00805     UI_ExecuteConfunc("prod_selectline %i", selectedProduction->idx);
00806     PR_UpdateProductionList(base);
00807 }
00808 
00812 static void PR_ProductionDown_f (void)
00813 {
00814     production_queue_t *queue;
00815     base_t *base = B_GetCurrentSelectedBase();
00816 
00817     if (!base || !selectedProduction)
00818         return;
00819 
00820     queue = &ccs.productions[base->idx];
00821 
00822     if (selectedProduction->idx >= queue->numItems - 1)
00823         return;
00824 
00825     PR_QueueMove(queue, selectedProduction->idx, 1);
00826 
00827     selectedProduction = &queue->items[selectedProduction->idx + 1];
00828     UI_ExecuteConfunc("prod_selectline %i", selectedProduction->idx);
00829     PR_UpdateProductionList(base);
00830 }
00831 
00832 void PR_InitCallbacks (void)
00833 {
00834     Cmd_AddCommand("prod_init", PR_ProductionList_f, NULL);
00835     Cmd_AddCommand("prod_type", PR_ProductionType_f, NULL);
00836     Cmd_AddCommand("prod_up", PR_ProductionUp_f, "Move production item up in the queue");
00837     Cmd_AddCommand("prod_down", PR_ProductionDown_f, "Move production item down in the queue");
00838     Cmd_AddCommand("prod_change", PR_ProductionChange_f, "Change production amount");
00839     Cmd_AddCommand("prod_inc", PR_ProductionIncrease_f, "Increase production amount");
00840     Cmd_AddCommand("prod_dec", PR_ProductionDecrease_f, "Decrease production amount");
00841     Cmd_AddCommand("prod_stop", PR_ProductionStop_f, "Stop production");
00842     Cmd_AddCommand("prodlist_rclick", PR_ProductionListRightClick_f, NULL);
00843     Cmd_AddCommand("prodlist_click", PR_ProductionListClick_f, NULL);
00844 }
00845 
00846 void PR_ShutdownCallbacks (void)
00847 {
00848     Cmd_RemoveCommand("prod_init");
00849     Cmd_RemoveCommand("prod_type");
00850     Cmd_RemoveCommand("prod_up");
00851     Cmd_RemoveCommand("prod_down");
00852     Cmd_RemoveCommand("prod_change");
00853     Cmd_RemoveCommand("prod_inc");
00854     Cmd_RemoveCommand("prod_dec");
00855     Cmd_RemoveCommand("prod_stop");
00856     Cmd_RemoveCommand("prodlist_rclick");
00857     Cmd_RemoveCommand("prodlist_click");
00858 }

Generated by  doxygen 1.6.2