static inline qboolean BS_GetMinMaxValueByItemID (const base_t *base, int itemNum, int *min, int *max, int *value) { assert(base); if (itemNum < 0 || itemNum + buyList.scroll >= buyList.length) return qfalse; if (buyCat == FILTER_AIRCRAFT && buyList.l[itemNum + buyList.scroll].aircraft) { const aircraft_t *aircraft = buyList.l[itemNum + buyList.scroll].aircraft; if (!aircraft) return qfalse; *value = BS_GetStorageAmountInBase(base, aircraft->id); *max = BS_GetStorageAmountInBase(base, aircraft->id) + BS_GetAircraftOnMarket(aircraft); *min = 0; } else { const objDef_t *item = BS_GetObjectDefition(&buyList.l[itemNum + buyList.scroll]); if (!item) return qfalse; *value = B_ItemInBase(item, base); *max = B_ItemInBase(item, base) + ccs.eMarket.numItems[item->idx]; *min = 0; } return qtrue; }
/** * @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 Checks if the production requirements are met for a defined amount. * @param[in] amount How many items are planned to be produced. * @param[in] reqs The production requirements of the item that is to be produced. * @param[in] base Pointer to base. * @return how much item/aircraft/etc can be produced */ int PR_RequirementsMet (int amount, const requirements_t* reqs, base_t* base) { int producibleAmount = amount; for (int i = 0; i < reqs->numLinks; i++) { const requirement_t* req = &reqs->links[i]; switch (req->type) { case RS_LINK_ITEM: { const int items = std::min(amount, B_ItemInBase(req->link.od, base) / ((req->amount) ? req->amount : 1)); producibleAmount = std::min(producibleAmount, items); break; } case RS_LINK_ANTIMATTER: { const int am = std::min(amount, B_AntimatterInBase(base) / ((req->amount) ? req->amount : 1)); producibleAmount = std::min(producibleAmount, am); break; } case RS_LINK_TECH: producibleAmount = (RS_IsResearched_ptr(req->link.tech)) ? producibleAmount : 0; break; case RS_LINK_TECH_NOT: producibleAmount = (RS_IsResearched_ptr(req->link.tech)) ? 0 : producibleAmount; break; default: break; } } return producibleAmount; }
/** * @brief Update Storage Capacity. * @param[in] base Pointer to the base * @sa B_ResetAllStatusAndCapacities_f */ void CAP_UpdateStorageCap (base_t* base) { CAP_SetCurrent(base, CAP_ITEMS, 0); for (int i = 0; i < cgi->csi->numODs; i++) { const objDef_t* obj = INVSH_GetItemByIDX(i); if (!B_ItemIsStoredInBaseStorage(obj)) continue; CAP_AddCurrent(base, CAP_ITEMS, B_ItemInBase(obj, base) * obj->size); } /* UGV takes room in storage capacity */ CAP_AddCurrent(base, CAP_ITEMS, UGV_SIZE * E_CountHired(base, EMPL_ROBOT)); }
/** * @brief * @sa BS_MarketClick_f * @sa BS_AddToList */ static void BS_MarketScroll_f (void) { int i; base_t *base = B_GetCurrentSelectedBase(); if (!base || buyCat >= MAX_FILTERTYPES || buyCat < 0) return; if (Cmd_Argc() < 2) { Com_Printf("Usage: %s <scrollpos>\n", Cmd_Argv(0)); return; } buyList.scroll = atoi(Cmd_Argv(1)); assert(buyList.scroll >= 0); assert(!((buyList.length > MAX_MARKET_MENU_ENTRIES && buyList.scroll >= buyList.length - MAX_MARKET_MENU_ENTRIES))); /* now update the menu pics */ for (i = 0; i < MAX_MARKET_MENU_ENTRIES; i++) { UI_ExecuteConfunc("buy_autoselli %i", i); } /* get item list */ for (i = buyList.scroll; i < buyList.length - buyList.scroll; i++) { const objDef_t *od = BS_GetObjectDefition(&buyList.l[i]); if (i >= MAX_MARKET_MENU_ENTRIES) break; /* Check whether the item matches the proper filter, storage in current base and market. */ if (od && (B_ItemInBase(od, base) > 0 || ccs.eMarket.numItems[od->idx]) && INV_ItemMatchesFilter(od, buyCat)) { const technology_t *tech = RS_GetTechForItem(od); UI_ExecuteConfunc("buy_show %i", i - buyList.scroll); BS_UpdateItem(base, i - buyList.scroll); /* autosell setting */ if (!RS_IsResearched_ptr(tech)) continue; if (ccs.eMarket.autosell[od->idx]) UI_ExecuteConfunc("buy_autoselle %i", i - buyList.scroll); else UI_ExecuteConfunc("buy_autoselld %i", i - buyList.scroll); } } }
/** * @brief Sell one item of a given type. * @sa BS_BuyItem_f * @sa BS_SellAircraft_f * @sa BS_BuyAircraft_f */ static void BS_SellItem_f (void) { int num; base_t *base = B_GetCurrentSelectedBase(); if (Cmd_Argc() < 2) { Com_Printf("Usage: %s <num>\n", Cmd_Argv(0)); return; } if (!base) return; if (buyCat == FILTER_AIRCRAFT) { Com_DPrintf(DEBUG_CLIENT, "BS_SellItem_f: Redirects to BS_SellAircraft_f\n"); BS_SellAircraft_f(); return; } num = atoi(Cmd_Argv(1)); if (num < 0 || num >= buyList.length) return; UI_ExecuteConfunc("buy_selectitem %i", num + buyList.scroll); { const objDef_t *item = BS_GetObjectDefition(&buyList.l[num + buyList.scroll]); /* don't sell more items than we have */ const int numItems = min(B_ItemInBase(item, base), BS_GetBuySellFactor()); /* Normal item (or equipment for UGVs/Robots if buyCategory==BUY_HEAVY) */ assert(item); currentSelectedMenuEntry = item; INV_ItemDescription(item); /* don't sell more items than we have */ if (numItems) { /* reinit the menu */ B_UpdateStorageAndCapacity(base, item, -numItems, qfalse); BS_AddItemToMarket(item, numItems); BS_BuyType(base); CP_UpdateCredits(ccs.credits + BS_GetItemSellingPrice(item) * numItems); BS_UpdateItem(base, num); } } }
/** * @brief Sells items from the market * @param[in] od pointer to the item (Object Definition record) * @param[out] base Base to sell at * @param[in ] count Number of items to sell * @return @c true if the ugv could get sold, @c false otherwise */ bool BS_SellItem (const objDef_t* od, base_t* base, int count) { if (!od) cgi->Com_Error(ERR_DROP, "BS_SellItem: Called on nullptr objDef!"); if (count <= 0) return false; if (!BS_IsOnMarket(od)) return false; if (base) { if (B_ItemInBase(od, base) < count) return false; B_AddToStorage(base, od, -count); } BS_AddItemToMarket(od, count); CP_UpdateCredits(ccs.credits + BS_GetItemSellingPrice(od) * count); return true; }
/** * @brief Update the list of item you can choose * @param[in] slot Pointer to aircraftSlot where items can be equiped */ static void AIM_UpdateAircraftItemList (const aircraftSlot_t *slot) { linkedList_t *amountList = NULL; technology_t **techList; technology_t **currentTech; const base_t *base = slot->aircraft->homebase; int count = 0; uiNode_t *AIM_items = NULL; /* Add all items corresponding to airequipID to list */ techList = AII_GetCraftitemTechsByType(airequipID); /* Count only those which are researched to buffer */ currentTech = techList; while (*currentTech) { if (AIM_CrafttypeFilter(base, airequipID, *currentTech)) count++; currentTech++; } /* List only those which are researched to buffer */ currentTech = techList; while (*currentTech) { if (AIM_CrafttypeFilter(base, airequipID, *currentTech)) { uiNode_t *option; const objDef_t *item = INVSH_GetItemByID((*currentTech)->provides); const int amount = B_ItemInBase(item, base); LIST_AddString(&amountList, va("%d", amount)); option = cgi->UI_AddOption(&AIM_items, (*currentTech)->name, _((*currentTech)->name), va("%d", (*currentTech)->idx)); if (!AIM_SelectableCraftItem(slot, *currentTech)) option->disabled = true; } currentTech++; } cgi->UI_RegisterOption(TEXT_LIST, AIM_items); cgi->UI_RegisterLinkedListText(TEXT_LIST2, amountList); }
/** * @brief Fill market item list */ static void BS_FillMarket_f (void) { const base_t* base = B_GetCurrentSelectedBase(); itemFilterTypes_t type; if (cgi->Cmd_Argc() < 2) { cgi->Com_Printf("Usage: %s <category>\n", cgi->Cmd_Argv(0)); return; } if (cgi->Cmd_Argc() >= 3) base = B_GetFoundedBaseByIDX(atoi(cgi->Cmd_Argv(2))); if (!base) { cgi->Com_Printf("No/invalid base selected.\n"); return; } type = cgi->INV_GetFilterTypeID(cgi->Cmd_Argv(1)); cgi->UI_ExecuteConfunc("ui_market_clear"); switch (type) { case FILTER_UGVITEM: /* show own UGV */ E_Foreach(EMPL_ROBOT, robot) { const ugv_t* ugv = robot->getUGV(); const technology_t* tech = RS_GetTechByProvided(ugv->id); if (!robot->isHiredInBase(base)) continue; cgi->UI_ExecuteConfunc("ui_market_add \"ugv-%d\" \"%s\" 1 0 0 %d - \"%s\"", robot->chr.ucn, _(tech->name), ugv->price, robot->isAwayFromBase() ? _("UGV is away from home") : "-"); } /* show buyable UGV */ for (int i = 0; i < cgi->csi->numUGV; i++) { const ugv_t* ugv = &cgi->csi->ugvs[i]; const technology_t* tech = RS_GetTechByProvided(ugv->id); const objDef_t* ugvWeapon = INVSH_GetItemByID(ugv->weapon); const int buyable = std::min(E_CountUnhiredRobotsByType(ugv), BS_GetItemOnMarket(ugvWeapon)); assert(tech); if (!RS_IsResearched_ptr(tech)) continue; if (buyable <= 0) continue; cgi->UI_ExecuteConfunc("ui_market_add %s \"%s\" 0 %d %d %d - -", ugv->id, _(tech->name), buyable, ugv->price, ugv->price); } /* show (UGV) items, fall through */ case FILTER_S_PRIMARY: case FILTER_S_SECONDARY: case FILTER_S_HEAVY: case FILTER_S_IMPLANT: case FILTER_S_MISC: case FILTER_S_ARMOUR: case FILTER_DUMMY: case FILTER_CRAFTITEM: case MAX_FILTERTYPES: { for (int i = 0; i < cgi->csi->numODs; i++) { const objDef_t* od = &cgi->csi->ods[i]; const technology_t* tech = RS_GetTechForItem(od); if (!BS_IsOnMarket(od)) continue; if (B_ItemInBase(od, base) + BS_GetItemOnMarket(od) <= 0) continue; if (type != MAX_FILTERTYPES && !cgi->INV_ItemMatchesFilter(od, type)) continue; cgi->UI_ExecuteConfunc("ui_market_add %s \"%s\" %d %d %d %d %s -", od->id, _(od->name), B_ItemInBase(od, base), BS_GetItemOnMarket(od), BS_GetItemBuyingPrice(od), BS_GetItemSellingPrice(od), RS_IsResearched_ptr(tech) ? va("%d", ccs.eMarket.autosell[i]) : "-"); } break; } case FILTER_AIRCRAFT: { AIR_ForeachFromBase(aircraft, base) { cgi->UI_ExecuteConfunc("ui_market_add \"aircraft_%d\" \"%s\" 1 0 0 %d - \"%s\"", aircraft->idx, aircraft->name, BS_GetAircraftSellingPrice(aircraft), AIR_IsAircraftInBase(aircraft) ? "-" : _("Aircraft is away from home")); } for (int i = 0; i < ccs.numAircraftTemplates; i++) { 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; }
/** * @brief Buy/Sell item/aircraft/ugv on the market */ static void BS_Buy_f (void) { const char* itemid; int count; base_t* base = B_GetCurrentSelectedBase(); const aircraft_t* aircraft; const ugv_t* ugv; const objDef_t* od; if (cgi->Cmd_Argc() < 2) { cgi->Com_Printf("Usage: %s <item-id> <count> [base-idx] \nNegative count means selling. If base index is omitted buys on the currently selected base.\n", cgi->Cmd_Argv(0)); return; } itemid = cgi->Cmd_Argv(1); count = atoi(cgi->Cmd_Argv(2)); if (cgi->Cmd_Argc() >= 4) base = B_GetFoundedBaseByIDX(atoi(cgi->Cmd_Argv(3))); if (char const* const rest = Q_strstart(itemid, "aircraft_")) { /* aircraft sell - with aircraft golbal idx */ int idx = atoi(rest); aircraft_t* aircraft = AIR_AircraftGetFromIDX(idx); if (!aircraft) { cgi->Com_Printf("Invalid aircraft index!\n"); return; } AIR_RemoveEmployees(*aircraft); BS_SellAircraft(aircraft); return; } if (char const* const rest = Q_strstart(itemid, "ugv-")) { /* ugv sell - with unique character number index */ int ucn = atoi(rest); Employee* robot = E_GetEmployeeByTypeFromChrUCN(EMPL_ROBOT, ucn); if (!robot) { cgi->Com_Printf("Invalid UCN for UGV!\n"); return; } BS_SellUGV(robot); return; } if (!base) { cgi->Com_Printf("No/invalid base selected.\n"); return; } aircraft = AIR_GetAircraftSilent(itemid); if (aircraft) { if (!B_GetBuildingStatus(base, B_COMMAND)) { CP_Popup(_("Note"), _("No Command Centre in this base.\nHangars are not functional.\n")); return; } /* We cannot buy aircraft if there is no power in our base. */ if (!B_GetBuildingStatus(base, B_POWER)) { CP_Popup(_("Note"), _("No power supplies in this base.\nHangars are not functional.")); return; } /* We cannot buy aircraft without any hangar. */ if (!AIR_AircraftAllowed(base)) { CP_Popup(_("Note"), _("Build a hangar first.")); return; } /* Check free space in hangars. */ if (CAP_GetFreeCapacity(base, AIR_GetHangarCapacityType(aircraft)) <= 0) { CP_Popup(_("Notice"), _("You cannot buy this aircraft.\nNot enough space in hangars.\n")); return; } if (ccs.credits < BS_GetAircraftBuyingPrice(aircraft)) { CP_Popup(_("Notice"), _("You cannot buy this aircraft.\nNot enough credits.\n")); return; } BS_BuyAircraft(aircraft, base); return; } ugv = cgi->Com_GetUGVByIDSilent(itemid); if (ugv) { const objDef_t* ugvWeapon = INVSH_GetItemByID(ugv->weapon); if (!ugvWeapon) cgi->Com_Error(ERR_DROP, "BS_BuyItem_f: Could not get weapon '%s' for ugv/tank '%s'.", ugv->weapon, ugv->id); if (E_CountUnhiredRobotsByType(ugv) < 1) return; if (ccs.eMarket.numItems[ugvWeapon->idx] < 1) return; if (ccs.credits < ugv->price) { CP_Popup(_("Not enough money"), _("You cannot buy this item as you don't have enough credits.")); return; } if (CAP_GetFreeCapacity(base, CAP_ITEMS) < UGV_SIZE + ugvWeapon->size) { CP_Popup(_("Not enough storage space"), _("You cannot buy this item.\nNot enough space in storage.\nBuild more storage facilities.")); return; } BS_BuyUGV(ugv, base); return; } if (count == 0) { cgi->Com_Printf("Invalid number of items to buy/sell: %s\n", cgi->Cmd_Argv(2)); return; } /* item */ od = INVSH_GetItemByID(cgi->Cmd_Argv(1)); if (od) { if (!BS_IsOnMarket(od)) return; if (count > 0) { /* buy */ const int price = BS_GetItemBuyingPrice(od); count = std::min(count, BS_GetItemOnMarket(od)); /* no items available on market */ if (count <= 0) return; if (price <= 0) { cgi->Com_Printf("Item on market with invalid buying price: %s (%d)\n", od->id, BS_GetItemBuyingPrice(od)); return; } /** @todo warn if player can buy less item due to available credits? */ count = std::min(count, ccs.credits / price); /* not enough money for a single item */ if (count <= 0) { CP_Popup(_("Not enough money"), _("You cannot buy this item as you don't have enough credits.")); return; } if (od->size <= 0) { cgi->Com_Printf("Item on market with invalid size: %s (%d)\n", od->id, od->size); return; } count = std::min(count, CAP_GetFreeCapacity(base, CAP_ITEMS) / od->size); if (count <= 0) { CP_Popup(_("Not enough storage space"), _("You cannot buy this item.\nNot enough space in storage.\nBuild more storage facilities.")); return; } BS_BuyItem(od, base, count); } else { /* sell */ count = std::min(-1 * count, B_ItemInBase(od, base)); /* no items in storage */ if (count <= 0) return; BS_SellItem(od, base, count); } return; } cgi->Com_Printf("Invalid item ID\n"); }
/** * @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); }