/** * @brief Calculates the total frame count (minutes) needed for producing an item * @param[in] base Pointer to the base the production happen * @param[in] prodData Pointer to the productionData structure */ static int PR_CalculateTotalFrames (const base_t* base, const productionData_t* prodData) { /* Check how many workers hired in this base. */ const signed int allWorkers = E_CountHired(base, EMPL_WORKER); /* We will not use more workers than workspace capacity in this base. */ const signed int maxWorkers = std::min(allWorkers, CAP_GetMax(base, CAP_WORKSPACE)); double timeDefault; if (PR_IsProductionData(prodData)) { const technology_t* tech = PR_GetTech(prodData); /* This is the default production time for PRODUCE_WORKERS workers. */ timeDefault = tech->produceTime; } else { const storedUFO_t* storedUFO = prodData->data.ufo; /* This is the default disassemble time for PRODUCE_WORKERS workers. */ timeDefault = storedUFO->comp->time; /* Production is 4 times longer when installation is on Antipodes * Penalty starts when distance is greater than 45 degrees */ timeDefault *= std::max(1.0, GetDistanceOnGlobe(storedUFO->installation->pos, base->pos) / 45.0); } /* Calculate the time needed for production of the item for our amount of workers. */ const float rate = PRODUCE_WORKERS / ccs.curCampaign->produceRate; double const timeScaled = timeDefault * (MINUTES_PER_HOUR * rate) / std::max(1, maxWorkers); /* Don't allow to return a time of less than 1 (you still need at least 1 minute to produce an item). */ return std::max(1.0, timeScaled) + 1; }
/** * @brief Alien containment menu init function. * @note Command to call this: ui_aliencont_init * @note Should be called whenever the alien containment menu gets active. */ static void AC_Init_f (void) { base_t* base; if (cgi->Cmd_Argc() < 2) base = B_GetCurrentSelectedBase(); else base = B_GetFoundedBaseByIDX(atoi(cgi->Cmd_Argv(1))); if (!base) { Com_Printf("No base selected\n"); return; } cgi->UI_ExecuteConfunc("ui_aliencont_cap %d %d", CAP_GetCurrent(base, CAP_ALIENS), CAP_GetMax(base, CAP_ALIENS)); cgi->UI_ExecuteConfunc("ui_aliencont_clear"); if (!base->alienContainment) return; linkedList_t* list = base->alienContainment->list(); LIST_Foreach(list, alienCargo_t, item) { const technology_t* tech = RS_GetTechForTeam(item->teamDef); cgi->UI_ExecuteConfunc("ui_aliencont_add \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" %f %d %d", item->teamDef->id, _(item->teamDef->name), tech->id, tech->image, (RS_IsResearched_ptr(tech)) ? _("Researched") : _("Awaiting autopsy"), (1.0f - tech->time / tech->overallTime) * 100, item->alive, item->dead); } cgi->LIST_Delete(&list); }
/** * @brief Script function to add and remove a scientist to the technology entry in the research-list. */ static void RS_Change_f (void) { base_t* base = B_GetCurrentSelectedBase(); if (cgi->Cmd_Argc() < 2) { Com_Printf("Usage: %s <tech_id>\n", cgi->Cmd_Argv(0)); return; } technology_t* tech = RS_GetTechByID(cgi->Cmd_Argv(1)); if (!tech) { Com_Printf("RS_ChangeScientist_f: Invalid tech '%s'\n", cgi->Cmd_Argv(1)); return; } if (tech->base && tech->base != base) { Com_Printf("RS_ChangeScientist_f: Tech '%s' is not researched in this base\n", cgi->Cmd_Argv(1)); return; } const int diff = atoi(cgi->Cmd_Argv(2)); if (diff == 0) return; if (diff > 0) { RS_AssignScientist(tech, base); } else if (tech->base) { RS_RemoveScientist(tech, nullptr); } cgi->UI_ExecuteConfunc("ui_research_update_topic %s %d", tech->id, tech->scientists); cgi->UI_ExecuteConfunc("ui_research_update_caps %d %d %d %d", E_CountUnassigned(base, EMPL_SCIENTIST), E_CountHired(base, EMPL_SCIENTIST), CAP_GetFreeCapacity(base, CAP_LABSPACE), CAP_GetMax(base, CAP_LABSPACE)); }
/** * @brief Remove aliens that exceed containment capacity * @note called on destroying an Alien Containment (from building_ondestroy) * @param[in, out] base Pointer to the base to check */ void AL_RemoveAliensExceedingCapacity (base_t *base) { const int max = CAP_GetMax(base, CAP_ALIENS); int current = CAP_GetCurrent(base, CAP_ALIENS); int i; assert(base); assert(max >= 0); for (i = 0; i < ccs.numAliensTD; i++) { const int remove = min(base->alienscont[i].amountAlive, current - max); if (!base->alienscont[i].teamDef) continue; /* remove dead aliens if there is no alien containment */ if (max == 0) base->alienscont[i].amountDead = 0; if (remove > 0) { base->alienscont[i].amountAlive -= remove; CAP_SetCurrent(base, CAP_ALIENS, current - remove); current = CAP_GetCurrent(base, CAP_ALIENS); } } assert(max >= current); }
/** * @brief Removes all scientists from the selected research-list entry. */ static void RS_Stop_f (void) { const base_t* base = B_GetCurrentSelectedBase(); if (cgi->Cmd_Argc() < 2) { Com_Printf("Usage: %s <tech_id>\n", cgi->Cmd_Argv(0)); return; } technology_t* tech = RS_GetTechByID(cgi->Cmd_Argv(1)); if (!tech) { Com_Printf("RS_Stop_f: Invalid tech '%s'\n", cgi->Cmd_Argv(1)); return; } if (!tech->base) { return; } if (tech->base != base) { Com_Printf("RS_Stop_f: Tech '%s' is not researched in this base\n", cgi->Cmd_Argv(1)); return; } RS_StopResearch(tech); cgi->UI_ExecuteConfunc("ui_research_update_topic %s %d", tech->id, tech->scientists); cgi->UI_ExecuteConfunc("ui_research_update_caps %d %d %d %d", E_CountUnassigned(base, EMPL_SCIENTIST), E_CountHired(base, EMPL_SCIENTIST), CAP_GetFreeCapacity(base, CAP_LABSPACE), CAP_GetMax(base, CAP_LABSPACE)); }
/** * @brief Remove exceeding antimatter if an antimatter tank has been destroyed. * @param[in] base Pointer to the base. */ void CAP_RemoveAntimatterExceedingCapacity (base_t* base) { const int amount = CAP_GetCurrent(base, CAP_ANTIMATTER) - CAP_GetMax(base, CAP_ANTIMATTER); if (amount <= 0) return; B_ManageAntimatter(base, amount, false); }
/** * @brief Returns the numer of workers available to produce an item * @param[in] base Pointer to the base the production happen */ int PR_WorkersAvailable (const base_t* base) { assert(base); /* Check how many workers hired in this base. */ const signed int allWorkers = E_CountHired(base, EMPL_WORKER); /* We will not use more workers than workspace capacity in this base. */ const signed int maxWorkers = std::min(allWorkers, CAP_GetMax(base, CAP_WORKSPACE)); return maxWorkers; }
/** * @brief Remove items until everything fits in storage. * @note items will be randomly selected for removal. * @param[in] base Pointer to the base */ void CAP_RemoveItemsExceedingCapacity (base_t *base) { int i; int objIdx[MAX_OBJDEFS]; /**< Will contain idx of items that can be removed */ int num, cnt; if (CAP_GetFreeCapacity(base, CAP_ITEMS) >= 0) return; for (i = 0, num = 0; i < cgi->csi->numODs; i++) { const objDef_t *obj = INVSH_GetItemByIDX(i); if (!B_ItemIsStoredInBaseStorage(obj)) continue; /* Don't count item that we don't have in base */ if (B_ItemInBase(obj, base) <= 0) continue; objIdx[num++] = i; } cnt = E_CountHired(base, EMPL_ROBOT); /* UGV takes room in storage capacity: we store them with a value MAX_OBJDEFS that can't be used by objIdx */ for (i = 0; i < cnt; i++) { objIdx[num++] = MAX_OBJDEFS; } while (num && CAP_GetFreeCapacity(base, CAP_ITEMS) < 0) { /* Select the item to remove */ const int randNumber = rand() % num; if (objIdx[randNumber] >= MAX_OBJDEFS) { /* A UGV is destroyed: get first one */ Employee* employee = E_GetHiredRobot(base, 0); /* There should be at least a UGV */ assert(employee); E_DeleteEmployee(employee); } else { /* items are destroyed. We guess that all items of a given type are stored in the same location * => destroy all items of this type */ const int idx = objIdx[randNumber]; const objDef_t *od = INVSH_GetItemByIDX(idx); B_UpdateStorageAndCapacity(base, od, -B_ItemInBase(od, base), false); } REMOVE_ELEM(objIdx, randNumber, num); /* Make sure that we don't have an infinite loop */ if (num <= 0) break; } Com_DPrintf(DEBUG_CLIENT, "B_RemoveItemsExceedingCapacity: Remains %i in storage for a maximum of %i\n", CAP_GetCurrent(base, CAP_ITEMS), CAP_GetMax(base, CAP_ITEMS)); }
/** * @brief Update GUI with the current number of employee per category */ static void E_UpdateGUICount_f (void) { int max; base_t* base = B_GetCurrentSelectedBase(); if (!base) return; max = CAP_GetMax(base, CAP_EMPLOYEES); cgi->Cvar_SetValue("mn_hiresoldiers", E_CountHired(base, EMPL_SOLDIER)); cgi->Cvar_SetValue("mn_hireworkers", E_CountHired(base, EMPL_WORKER)); cgi->Cvar_SetValue("mn_hirescientists", E_CountHired(base, EMPL_SCIENTIST)); cgi->Cvar_SetValue("mn_hirepilots", E_CountHired(base, EMPL_PILOT)); cgi->Cvar_Set("mn_hirepeople", "%d/%d", E_CountAllHired(base), max); }
/** * @brief Fills technology list on research UI */ static void RS_FillTechnologyList_f (void) { base_t* base = B_GetCurrentSelectedBase(); if (!base) return; RS_MarkResearchable(base); cgi->UI_ExecuteConfunc("ui_research_update_caps %d %d %d %d", E_CountUnassigned(base, EMPL_SCIENTIST), E_CountHired(base, EMPL_SCIENTIST), CAP_GetFreeCapacity(base, CAP_LABSPACE), CAP_GetMax(base, CAP_LABSPACE)); cgi->UI_ExecuteConfunc("ui_techlist_clear"); for (int i = 0; i < ccs.numTechnologies; i++) { technology_t* tech = RS_GetTechByIDX(i); /* Don't show technologies with time == 0 - those are NOT separate research topics. */ if (tech->time == 0) continue; /* hide finished research */ if (tech->statusResearch == RS_FINISH) continue; int percentage = 0; if (tech->overallTime > 0.0) { percentage = std::min(100, std::max(0, 100 - int(round(tech->time * 100.0 / tech->overallTime)))); } /* show researches that are running */ if (tech->base && tech->scientists > 0) { if (tech->base == base) { cgi->UI_ExecuteConfunc("ui_techlist_add %s \"%s\" %d %d", tech->id, _(tech->name), tech->scientists, percentage); } else { cgi->UI_ExecuteConfunc("ui_techlist_add %s \"%s\" %d %d base %d \"%s\"", tech->id, _(tech->name), tech->scientists, percentage, tech->base->idx, tech->base->name); } continue; } /* show topics that are researchable on this base */ const bool req = RS_RequirementsMet(tech, base); if (tech->statusResearchable && req) { cgi->UI_ExecuteConfunc("ui_techlist_add %s \"%s\" %d %d", tech->id, _(tech->name), tech->scientists, percentage); continue; } if (tech->statusCollected && !req) { cgi->UI_ExecuteConfunc("ui_techlist_add %s \"%s\" %d %d missing", tech->id, _(tech->name), tech->scientists, percentage); continue; } } }
/** * @brief Assign as many scientists to the research project as possible. */ static void RS_Max_f (void) { /* The base the tech is researched in. */ base_t* base = B_GetCurrentSelectedBase(); if (!base) return; if (cgi->Cmd_Argc() < 2) { Com_Printf("Usage: %s <tech_id>\n", cgi->Cmd_Argv(0)); return; } /* The technology you want to max out. */ technology_t* tech = RS_GetTechByID(cgi->Cmd_Argv(1)); if (!tech) { Com_Printf("RS_Max_f: Invalid tech '%s'\n", cgi->Cmd_Argv(1)); return; } if (tech->base && tech->base != base) { Com_Printf("RS_Max_f: Tech '%s' is not researched in this base\n", cgi->Cmd_Argv(1)); return; } /* Add as many scientists as possible to this tech. */ while (CAP_GetFreeCapacity(base, CAP_LABSPACE) > 0) { Employee* employee = E_GetUnassignedEmployee(base, EMPL_SCIENTIST); if (!employee) break; RS_AssignScientist(tech, base, employee); if (!employee->isAssigned()) break; } cgi->UI_ExecuteConfunc("ui_research_update_topic %s %d", tech->id, tech->scientists); cgi->UI_ExecuteConfunc("ui_research_update_caps %d %d %d %d", E_CountUnassigned(base, EMPL_SCIENTIST), E_CountHired(base, EMPL_SCIENTIST), CAP_GetFreeCapacity(base, CAP_LABSPACE), CAP_GetMax(base, CAP_LABSPACE)); }
/** * @brief Base Summary menu init function. * @note Should be called whenever the Base Summary menu gets active. */ static void BaseSummary_Init (const base_t *base) { static char textStatsBuffer[1024]; static char textInfoBuffer[256]; const aliensCont_t *containment = base->alienscont; int i; baseCapacities_t cap; const production_queue_t *queue; const technology_t *tech; int tmp; /* wipe away old buffers */ textStatsBuffer[0] = textInfoBuffer[0] = 0; Q_strcat(textInfoBuffer, _("^BAircraft\n"), sizeof(textInfoBuffer)); for (i = 0; i <= MAX_HUMAN_AIRCRAFT_TYPE; i++) { const aircraftType_t airType = (aircraftType_t)i; const int count = AIR_CountTypeInBase(base, airType); if (count == 0) continue; Q_strcat(textInfoBuffer, va("\t%s:\t\t\t\t%i\n", AIR_GetAircraftString(airType), count), sizeof(textInfoBuffer)); } Q_strcat(textInfoBuffer, "\n", sizeof(textInfoBuffer)); Q_strcat(textInfoBuffer, _("^BEmployees\n"), sizeof(textInfoBuffer)); for (i = 0; i < MAX_EMPL; i++) { const employeeType_t emplType = (employeeType_t)i; tmp = E_CountHired(base, emplType); if (tmp == 0) continue; Q_strcat(textInfoBuffer, va("\t%s:\t\t\t\t%i\n", E_GetEmployeeString(emplType, tmp), tmp), sizeof(textInfoBuffer)); } Q_strcat(textInfoBuffer, "\n", sizeof(textInfoBuffer)); Q_strcat(textInfoBuffer, _("^BAliens\n"), sizeof(textInfoBuffer)); for (i = 0; i < ccs.numAliensTD; i++) { if (!containment[i].amountAlive && !containment[i].amountDead) continue; Q_strcat(textInfoBuffer, va("\t%s:\t\t\t\t%i/%i\n", _(containment[i].teamDef->name), containment[i].amountAlive, containment[i].amountDead), sizeof(textInfoBuffer)); } /* link into the menu */ cgi->UI_RegisterText(TEXT_STANDARD, textInfoBuffer); Q_strcat(textStatsBuffer, _("^BBuildings\t\t\t\t\t\tCapacity\t\t\t\tAmount\n"), sizeof(textStatsBuffer)); for (i = 0; i < ccs.numBuildingTemplates; i++) { const building_t* b = &ccs.buildingTemplates[i]; /* only show already researched buildings */ if (!RS_IsResearched_ptr(b->tech)) continue; cap = B_GetCapacityFromBuildingType(b->buildingType); if (cap == MAX_CAP) continue; if (!B_GetNumberOfBuildingsInBaseByBuildingType(base, b->buildingType)) continue; /* Check if building is functional (see comments in B_UpdateBaseCapacities) */ if (B_GetBuildingStatus(base, b->buildingType)) { Q_strcat(textStatsBuffer, va("%s:\t\t\t\t\t\t%i/%i", _(b->name), CAP_GetCurrent(base, cap), CAP_GetMax(base, cap)), sizeof(textStatsBuffer)); } else { if (b->buildingStatus == B_STATUS_UNDER_CONSTRUCTION) { const float remaining = B_GetConstructionTimeRemain(b); const float timeLeft = std::max(0.0f, remaining); Q_strcat(textStatsBuffer, va("%s:\t\t\t\t\t\t%3.1f %s", _(b->name), timeLeft, ngettext("day", "days", timeLeft)), sizeof(textStatsBuffer)); } else { Q_strcat(textStatsBuffer, va("%s:\t\t\t\t\t\t%i/%i", _(b->name), CAP_GetCurrent(base, cap), 0), sizeof(textStatsBuffer)); } } Q_strcat(textStatsBuffer, va("\t\t\t\t%i\n", B_GetNumberOfBuildingsInBaseByBuildingType(base, b->buildingType)), sizeof(textStatsBuffer)); } Q_strcat(textStatsBuffer, "\n", sizeof(textStatsBuffer)); Q_strcat(textStatsBuffer, _("^BProduction\t\t\t\t\t\tQuantity\t\t\t\tPercent\n"), sizeof(textStatsBuffer)); queue = PR_GetProductionForBase(base); if (queue->numItems > 0) { for (i = 0; i < queue->numItems; i++) { const production_t *production = &queue->items[i]; const char *name = PR_GetName(&production->data); /** @todo use the same method as we do in PR_ProductionInfo */ Q_strcat(textStatsBuffer, va(_("%s\t\t\t\t\t\t%d\t\t\t\t%.2f%%\n"), name, production->amount, PR_GetProgress(production) * 100), sizeof(textStatsBuffer)); } } else { Q_strcat(textStatsBuffer, _("Nothing\n"), sizeof(textStatsBuffer)); } Q_strcat(textStatsBuffer, "\n", sizeof(textStatsBuffer)); Q_strcat(textStatsBuffer, _("^BResearch\t\t\t\t\t\tScientists\t\t\t\tPercent\n"), sizeof(textStatsBuffer)); tmp = 0; for (i = 0; i < ccs.numTechnologies; i++) { tech = RS_GetTechByIDX(i); if (tech->base == base && (tech->statusResearch == RS_RUNNING || tech->statusResearch == RS_PAUSED)) { Q_strcat(textStatsBuffer, va(_("%s\t\t\t\t\t\t%d\t\t\t\t%1.2f%%\n"), _(tech->name), tech->scientists, (1 - tech->time / tech->overallTime) * 100), sizeof(textStatsBuffer)); tmp++; } } if (!tmp) Q_strcat(textStatsBuffer, _("Nothing\n"), sizeof(textStatsBuffer)); /* link into the menu */ cgi->UI_RegisterText(TEXT_STATS_BASESUMMARY, textStatsBuffer); }
const aircraft_t* aircraft = &ccs.aircraftTemplates[i]; if (!BS_AircraftIsOnMarket(aircraft)) continue; if (!RS_IsResearched_ptr(aircraft->tech)) continue; if (BS_GetAircraftOnMarket(aircraft) <= 0) continue; cgi->UI_ExecuteConfunc("ui_market_add \"%s\" \"%s\" 0 %d %d %d - -", aircraft->id, _(aircraft->tech->name), BS_GetAircraftOnMarket(aircraft), BS_GetAircraftBuyingPrice(aircraft), BS_GetAircraftSellingPrice(aircraft)); } break; } default: break; } /* update capacity counters */ cgi->UI_ExecuteConfunc("ui_market_update_caps %d %d %d %d %d %d", CAP_GetFreeCapacity(base, CAP_ITEMS), CAP_GetMax(base, CAP_ITEMS), CAP_GetFreeCapacity(base, CAP_AIRCRAFT_SMALL), CAP_GetMax(base, CAP_AIRCRAFT_SMALL), CAP_GetFreeCapacity(base, CAP_AIRCRAFT_BIG), CAP_GetMax(base, CAP_AIRCRAFT_BIG)); } #ifdef DEBUG static void BS_AddMarket_f (void) { if (cgi->Cmd_Argc() < 3) { cgi->Com_Printf("Usage: %s <itemid> <count>\n", cgi->Cmd_Argv(0)); return; } const objDef_t* obj = INVSH_GetItemByID(cgi->Cmd_Argv(1)); if (!obj) return;
/** * @brief Updates the Buy/Sell menu list. * @param[in] base Pointer to the base to buy/sell at * @sa BS_BuyType_f */ static void BS_BuyType (const base_t *base) { const objDef_t *od; int i, j = 0; char tmpbuf[MAX_VAR]; if (!base || buyCat >= MAX_FILTERTYPES || buyCat < 0) return; CP_UpdateCredits(ccs.credits); bsMarketNames = NULL; bsMarketStorage = NULL; bsMarketMarket = NULL; bsMarketPrices = NULL; UI_ResetData(TEXT_ITEMDESCRIPTION); /* hide autosell checkboxes by default */ for (i = 0; i < MAX_MARKET_MENU_ENTRIES; i++) { UI_ExecuteConfunc("buy_autoselli %i", i); } switch (buyCat) { case FILTER_AIRCRAFT: /* Aircraft */ { const aircraft_t *aircraftTemplate; for (i = 0, j = 0, aircraftTemplate = ccs.aircraftTemplates; i < ccs.numAircraftTemplates; i++, aircraftTemplate++) { if (!BS_AircraftIsOnMarket(aircraftTemplate)) continue; assert(aircraftTemplate->tech); if (BS_GetStorageAmountInBase(base, aircraftTemplate->id) + BS_GetAircraftOnMarket(aircraftTemplate) > 0) { if (j >= buyList.scroll && j < MAX_MARKET_MENU_ENTRIES) { UI_ExecuteConfunc("buy_show %i", j - buyList.scroll); } BS_AddToList(aircraftTemplate->name, BS_GetStorageAmountInBase(base, aircraftTemplate->id), BS_GetAircraftOnMarket(aircraftTemplate), BS_GetAircraftBuyingPrice(aircraftTemplate)); if (j >= MAX_BUYLIST) Com_Error(ERR_DROP, "Increase the MAX_BUYLIST value to handle that much items\n"); buyList.l[j].item = NULL; buyList.l[j].aircraft = aircraftTemplate; buyList.length = j + 1; BS_UpdateItem(base, j - buyList.scroll); j++; } } } break; case FILTER_CRAFTITEM: /* Aircraft items */ /* get item list */ for (i = 0, j = 0, od = csi.ods; i < csi.numODs; i++, od++) { if (!BS_IsOnMarket(od)) continue; /* Check whether the item matches the proper filter, storage in current base and market. */ if ((B_ItemInBase(od, base) || ccs.eMarket.numItems[i]) && INV_ItemMatchesFilter(od, FILTER_CRAFTITEM)) { if (j >= buyList.scroll && j < MAX_MARKET_MENU_ENTRIES) { const technology_t *tech = RS_GetTechForItem(od); UI_ExecuteConfunc("buy_show %i", j - buyList.scroll); if (RS_IsResearched_ptr(tech)) { if (ccs.eMarket.autosell[i]) UI_ExecuteConfunc("buy_autoselle %i", j - buyList.scroll); else UI_ExecuteConfunc("buy_autoselld %i", j - buyList.scroll); } } BS_AddToList(od->name, B_ItemInBase(od, base), ccs.eMarket.numItems[i], BS_GetItemBuyingPrice(od)); if (j >= MAX_BUYLIST) Com_Error(ERR_DROP, "Increase the MAX_FILTERLIST value to handle that much items\n"); buyList.l[j].item = od; buyList.l[j].aircraft = NULL; buyList.length = j + 1; BS_UpdateItem(base, j - buyList.scroll); j++; } } break; default: /* Normal items */ if (buyCat < MAX_SOLDIER_FILTERTYPES || buyCat == FILTER_DUMMY) { /* get item list */ for (i = 0, j = 0, od = csi.ods; i < csi.numODs; i++, od++) { if (!BS_IsOnMarket(od)) continue; /* Check whether the item matches the proper filter, storage in current base and market. */ if ((B_ItemInBase(od, base) || ccs.eMarket.numItems[i]) && INV_ItemMatchesFilter(od, buyCat)) { BS_AddToList(od->name, B_ItemInBase(od, base), ccs.eMarket.numItems[i], BS_GetItemBuyingPrice(od)); /* Set state of Autosell button. */ if (j >= buyList.scroll && j < MAX_MARKET_MENU_ENTRIES) { const technology_t *tech = RS_GetTechForItem(od); UI_ExecuteConfunc("buy_show %i", j - buyList.scroll); if (RS_IsResearched_ptr(tech)) { if (ccs.eMarket.autosell[i]) UI_ExecuteConfunc("buy_autoselle %i", j - buyList.scroll); else UI_ExecuteConfunc("buy_autoselld %i", j - buyList.scroll); } } if (j >= MAX_BUYLIST) Com_Error(ERR_DROP, "Increase the MAX_BUYLIST value to handle that much items\n"); buyList.l[j].item = od; buyList.l[j].aircraft = NULL; buyList.length = j + 1; BS_UpdateItem(base, j - buyList.scroll); j++; } } } break; } for (; j < MAX_MARKET_MENU_ENTRIES; j++) { /* Hide the rest of the entries. */ UI_ExecuteConfunc("buy_hide %i", j); } /* Update some menu cvars. */ /* Set up base capacities. */ Com_sprintf(tmpbuf, sizeof(tmpbuf), "%i/%i", CAP_GetCurrent(base, CAP_ITEMS), CAP_GetMax(base, CAP_ITEMS)); Cvar_Set("mn_bs_storage", tmpbuf); /* select first item */ if (buyList.length) { switch (buyCat) { /** @sa BS_MarketClick_f */ case FILTER_AIRCRAFT: BS_MarketAircraftDescription(buyList.l[0].aircraft); break; case FILTER_CRAFTITEM: Cvar_Set("mn_aircraftname", ""); /** @todo Use craftitem name here? See also BS_MarketClick_f */ /* Select current item or first one. */ if (currentSelectedMenuEntry) UP_AircraftItemDescription(currentSelectedMenuEntry); else UP_AircraftItemDescription(buyList.l[0].item); break; default: assert(buyCat != MAX_FILTERTYPES); /* Select current item or first one. */ if (currentSelectedMenuEntry) INV_ItemDescription(currentSelectedMenuEntry); else INV_ItemDescription(buyList.l[0].item); break; } } else { /* reset description */ INV_ItemDescription(NULL); } UI_RegisterLinkedListText(TEXT_MARKET_NAMES, bsMarketNames); UI_RegisterLinkedListText(TEXT_MARKET_STORAGE, bsMarketStorage); UI_RegisterLinkedListText(TEXT_MARKET_MARKET, bsMarketMarket); UI_RegisterLinkedListText(TEXT_MARKET_PRICES, bsMarketPrices); }
/** * @brief Updates the alienscont menu. */ static void AC_UpdateMenu (const base_t *base) { Cvar_Set("mn_al_alientype", ""); Cvar_Set("mn_al_alienimage", ""); Cvar_SetValue("mn_al_dead", 0); Cvar_SetValue("mn_al_alive", 0); Cvar_SetValue("mn_al_capacity", CAP_GetCurrent(base, CAP_ALIENS)); Cvar_SetValue("mn_al_capacity_max", CAP_GetMax(base, CAP_ALIENS)); /* Reset list. */ cgi->UI_ExecuteConfunc("aliencont_clear"); if (B_GetBuildingStatus(base, B_ALIEN_CONTAINMENT)) { const aliensCont_t *containment = base->alienscont; int i, j; for (i = 0, j = 0; i < ccs.numAliensTD; i++) { if (j < MAX_AC_MENU_ENTRIES) { if (containment[i].teamDef) { const technology_t *tech = containment[i].tech; if (!tech) { Com_Printf("AC_UpdateMenu: Tech entry for containment %i not set!\n", i); /* to let the click function still work */ continue; } if (!aliencontCurrent) { aliencontCurrent = &containment[i]; } if (containment[i].amountAlive > 0 || containment[i].amountDead > 0) { /* Generate a list entry. */ if (RS_IsResearched_ptr(tech)) { Cvar_Set(va("mn_ac_statusstr%i", j), _("Researched")); } else { Cvar_Set(va("mn_ac_statusstr%i", j), _("Awaiting autopsy")); if (!containment[i].amountDead) { cgi->UI_ExecuteConfunc("aliencontkill %i", j); } else { cgi->UI_ExecuteConfunc("aliencontneedautopsy %i", j); } } Cvar_SetValue(va("mn_ac_progress%i", j), (1 - tech->time / tech->overallTime) * 100); /* Display name in the correct list-entry. */ Cvar_Set(va("mn_ac_name%i", j), _(containment[i].teamDef->name)); /* Display amount of dead aliens in the correct list-entry. */ Cvar_SetValue(va("mn_ac_dead%i", j), containment[i].amountDead); /* Display number of live aliens in the correct list-entry. */ Cvar_SetValue(va("mn_ac_alive%i", j), containment[i].amountAlive); j++; } } } } numAliensOnList = j; for (; j < MAX_AC_MENU_ENTRIES; j++) { Cvar_Set(va("mn_ac_statusstr%i", j), _("Free slot")); Cvar_Set(va("mn_ac_name%i", j), _("None")); Cvar_Set(va("mn_ac_dead%i", j), ""); Cvar_Set(va("mn_ac_alive%i", j), ""); Cvar_SetValue(va("mn_ac_progress%i", j), 0); } } /** @todo Select the containment we (maybe) just clicked again */ AC_AlienClick(base, 0); }