static void BDEF_AddSlotToSlotList (const aircraftSlot_t* slot, linkedList_t** slotList) { char defBuffer[512]; const int size = cgi->LIST_Count(*slotList) + 1; if (!slot->item) { Com_sprintf(defBuffer, lengthof(defBuffer), _("%i: empty"), size); cgi->LIST_AddString(slotList, defBuffer); } else { const technology_t* tech; const char* status; if (!slot->installationTime) status = _("Working"); else if (slot->installationTime > 0) status = _("Installing"); else if (slot->nextItem) status = _("Replacing"); else status = _("Removing"); if (slot->nextItem != nullptr) tech = RS_GetTechForItem(slot->nextItem); else tech = RS_GetTechForItem(slot->item); Com_sprintf(defBuffer, lengthof(defBuffer), "%i: %s (%s)", size, _(tech->name), status); cgi->LIST_AddString(slotList, defBuffer); } }
/** * @brief Run actions on finishing disassembling of a ufo * @param base The base to produce in * @param prod The production that is running */ static void PR_FinishDisassembly (base_t* base, production_t* prod) { storedUFO_t* ufo = prod->data.data.ufo; assert(ufo); for (int i = 0; i < ufo->comp->numItemtypes; i++) { const objDef_t* compOd = ufo->comp->items[i]; const int amount = (ufo->condition < 1 && ufo->comp->itemAmount2[i] != COMP_ITEMCOUNT_SCALED) ? ufo->comp->itemAmount2[i] : round(ufo->comp->itemAmount[i] * ufo->condition); assert(compOd); if (amount <= 0) continue; if (Q_streq(compOd->id, ANTIMATTER_ITEM_ID)) { B_AddAntimatter(base, amount); } else { technology_t* tech = RS_GetTechForItem(compOd); B_AddToStorage(base, compOd, amount); RS_MarkCollected(tech); } } Com_sprintf(cp_messageBuffer, sizeof(cp_messageBuffer), _("The disassembling of %s at %s has finished."), UFO_TypeToName(ufo->ufoTemplate->getUfoType()), base->name); MSO_CheckAddNewMessage(NT_PRODUCTION_FINISHED, _("Production finished"), cp_messageBuffer, MSG_PRODUCTION, ufo->ufoTemplate->tech); /* Removing UFO will remove the production too */ US_RemoveStoredUFO(ufo); }
/** * @brief For things like craft_ufo_scout that are no real items this function will * increase the collected counter by one * @note Mission trigger function * @sa CP_MissionTriggerFunctions * @sa CP_ExecuteMissionTrigger */ static void CP_AddItemAsCollected_f (void) { int baseID; const char* id; base_t *base; const objDef_t *item; if (Cmd_Argc() < 2) { Com_Printf("Usage: %s <item>\n", Cmd_Argv(0)); return; } id = Cmd_Argv(1); baseID = atoi(Cmd_Argv(2)); base = B_GetBaseByIDX(baseID); if (base == NULL) return; /* i = item index */ item = INVSH_GetItemByIDSilent(id); if (item) { technology_t *tech = RS_GetTechForItem(item); base->storage.numItems[item->idx]++; Com_DPrintf(DEBUG_CLIENT, "add item: '%s'\n", item->id); RS_MarkCollected(tech); } }
/** * @brief Set the ammo model to display to selected ammo (only for a reloadable weapon) * @param tech technology_t pointer for the weapon's tech * @sa UP_Article */ static void UP_DrawAssociatedAmmo (const technology_t* tech) { const objDef_t* od = INVSH_GetItemByID(tech->provides); /* If this is a weapon, we display the model of the associated ammunition in the lower right */ if (od->numAmmos > 0) { const technology_t* associated = RS_GetTechForItem(od->ammos[0]); cgi->Cvar_Set("mn_upmodel_bottom", "%s", associated->mdl); } }
/** * @brief Change UFOpaedia article when clicking on the name of associated ammo or weapon */ static void UP_ResearchedLinkClick_f (void) { const objDef_t* od; if (!upCurrentTech) /* if called from console */ return; od = INVSH_GetItemByID(upCurrentTech->provides); assert(od); if (od->isAmmo()) { const technology_t* t = RS_GetTechForItem(od->weapons[0]); if (UP_TechGetsDisplayed(t)) UP_OpenWith(t->id); } else if (od->weapon && od->isReloadable()) { const technology_t* t = RS_GetTechForItem(od->ammos[0]); if (UP_TechGetsDisplayed(t)) UP_OpenWith(t->id); } }
/** * @return The technology for the item that is assigned to the given production */ technology_t* PR_GetTech (const productionData_t* data) { switch (data->type) { case PRODUCTION_TYPE_ITEM: return RS_GetTechForItem(data->data.item); case PRODUCTION_TYPE_AIRCRAFT: return data->data.aircraft->tech; case PRODUCTION_TYPE_DISASSEMBLY: return data->data.ufo->ufoTemplate->tech; default: return nullptr; } }
/** * @brief Draw only slots existing for this aircraft, and emphases selected one * @return[out] aircraft Pointer to the aircraft */ static void AIM_DrawAircraftSlots (const aircraft_t *aircraft) { int i; /* initialise model cvars */ for (i = 0; i < AIR_POSITIONS_MAX; i++) Cvar_Set(va("mn_aircraft_item_model_slot%i", i), ""); for (i = 0; i < AIR_POSITIONS_MAX; i++) { const aircraftSlot_t *slot; int max, j; /* Default value */ cgi->UI_ExecuteConfunc("airequip_display_slot %i 0", i); /* Draw available slots */ switch (airequipID) { case AC_ITEM_AMMO: case AC_ITEM_WEAPON: max = aircraft->maxWeapons; slot = aircraft->weapons; break; case AC_ITEM_ELECTRONICS: max = aircraft->maxElectronics; slot = aircraft->electronics; break; /* do nothing for shield: there is only one slot */ default: continue; } for (j = 0; j < max; j++, slot++) { /* check if one of the aircraft slots is at this position */ if (slot->pos == i) { /* draw in white if this is the selected slot */ if (j == airequipSelectedSlot) { cgi->UI_ExecuteConfunc("airequip_display_slot %i 2", i); } else { cgi->UI_ExecuteConfunc("airequip_display_slot %i 1", i); } if (slot->item) { Cvar_Set(va("mn_aircraft_item_model_slot%i", i), RS_GetTechForItem(slot->item)->mdl); } else Cvar_Set(va("mn_aircraft_item_model_slot%i", i), ""); } } } }
/** * @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 sets market prices at start of the game * @sa CP_CampaignInit * @sa B_SetUpFirstBase * @sa BS_Load (Market load function) */ void BS_InitMarket (const campaign_t* campaign) { int i; market_t* market = BS_GetMarket(); for (i = 0; i < cgi->csi->numODs; i++) { const objDef_t* od = INVSH_GetItemByIDX(i); if (market->askItems[i] == 0) { market->askItems[i] = od->price; market->bidItems[i] = floor(market->askItems[i] * BID_FACTOR); } if (campaign->marketDef->numItems[i] <= 0) continue; if (RS_IsResearched_ptr(RS_GetTechForItem(od))) { /* the other relevant values were already set above */ market->numItems[i] = campaign->marketDef->numItems[i]; } else { Com_Printf("BS_InitMarket: Could not add item %s to the market - not marked as researched in campaign %s\n", od->id, campaign->id); } } for (i = 0; i < AIRCRAFTTYPE_MAX; i++) { const char* name = cgi->Com_DropShipTypeToShortName((humanAircraftType_t)i); const aircraft_t* aircraft = AIR_GetAircraft(name); if (market->askAircraft[i] == 0) { market->askAircraft[i] = aircraft->price; market->bidAircraft[i] = floor(market->askAircraft[i] * BID_FACTOR); } if (campaign->marketDef->numAircraft[i] <= 0) continue; if (RS_IsResearched_ptr(aircraft->tech)) { /* the other relevant values were already set above */ market->numAircraft[i] = campaign->marketDef->numAircraft[i]; } else { Com_Printf("BS_InitMarket: Could not add aircraft %s to the market - not marked as researched in campaign %s\n", aircraft->id, campaign->id); } } }
/** * @brief Sets/unsets or flips the autosell property of an item on the market */ static void BS_SetAutosell_f (void) { const objDef_t* od; const technology_t* tech; if (cgi->Cmd_Argc() < 2) { cgi->Com_Printf("Usage: %s <item-id> [0|1]\nWhere second parameter is the state (off/on), if omitted the autosell property will be flipped.\n", cgi->Cmd_Argv(0)); return; } /* aircraft check */ if (AIR_GetAircraftSilent(cgi->Cmd_Argv(1)) != nullptr) { cgi->Com_Printf("Aircraft can't be autosold!\n"); return; } /* items */ od = INVSH_GetItemByID(cgi->Cmd_Argv(1)); if (!od) { /* no printf, INVSH_GetItemByID gave warning already */ return; } if (od->isVirtual) { cgi->Com_Printf("Item %s is virtual, can't be autosold!\n", od->id); return; } if (od->notOnMarket) { cgi->Com_Printf("Item %s is not on market, can't be autosold!\n", od->id); return; } tech = RS_GetTechForItem(od); /* Don't allow to enable autosell for items not researched. */ if (!RS_IsResearched_ptr(tech)) { cgi->Com_Printf("Item %s is not researched, can't be autosold!\n", od->id); return; } if (cgi->Cmd_Argc() >= 3) ccs.eMarket.autosell[od->idx] = atoi(cgi->Cmd_Argv(2)); else ccs.eMarket.autosell[od->idx] = ! ccs.eMarket.autosell[od->idx]; }
/** * @brief Enable or disable autosell option for given itemtype. */ static void BS_Autosell_f (void) { int num; const objDef_t *item; base_t *base = B_GetCurrentSelectedBase(); /* Can be called from everywhere. */ if (!base) return; if (Cmd_Argc() < 2) { Com_Printf("Usage: %s <num>\n", Cmd_Argv(0)); return; } num = atoi(Cmd_Argv(1)); Com_DPrintf(DEBUG_CLIENT, "BS_Autosell_f: listnumber %i\n", num); if (num < 0 || num >= buyList.length) return; item = BS_GetObjectDefition(&buyList.l[num + buyList.scroll]); assert(item); if (ccs.eMarket.autosell[item->idx]) { ccs.eMarket.autosell[item->idx] = qfalse; Com_DPrintf(DEBUG_CLIENT, "item name: %s, autosell false\n", item->name); } else { const technology_t *tech = RS_GetTechForItem(item); /* Don't allow to enable autosell for items not researched. */ if (!RS_IsResearched_ptr(tech)) return; ccs.eMarket.autosell[item->idx] = qtrue; Com_DPrintf(DEBUG_CLIENT, "item name: %s, autosell true\n", item->name); } /* Reinit the menu. */ BS_BuyType(base); }
/** * @brief make number of items change every day. * @sa CP_CampaignRun * @sa daily called * @note This function makes items number on market slowly reach the asymptotic number of items defined in equipment.ufo * If an item has just been researched, it's not available on market until RESEARCH_LIMIT_DELAY days is reached. */ void CP_CampaignRunMarket (campaign_t* campaign) { int i; const float TYPICAL_TIME = 10.f; /**< Number of days to reach the asymptotic number of items */ const int RESEARCH_LIMIT_DELAY = 30; /**< Numbers of days after end of research to wait in order to have * items added on market */ market_t* market = BS_GetMarket(); assert(campaign->marketDef); assert(campaign->asymptoticMarketDef); for (i = 0; i < cgi->csi->numODs; i++) { const objDef_t* od = INVSH_GetItemByIDX(i); const technology_t* tech = RS_GetTechForItem(od); int asymptoticNumber; if (RS_IsResearched_ptr(tech) && (campaign->marketDef->numItems[i] != 0 || ccs.date.day > tech->researchedDate.day + RESEARCH_LIMIT_DELAY)) { /* if items are researched for more than RESEARCH_LIMIT_DELAY or was on the initial market, * there number tend to the value defined in equipment.ufo. * This value is the asymptotic value if it is not 0, or initial value else */ asymptoticNumber = campaign->asymptoticMarketDef->numItems[i] ? campaign->asymptoticMarketDef->numItems[i] : campaign->marketDef->numItems[i]; } else { /* items that have just been researched don't appear on market, but they can disappear */ asymptoticNumber = 0; } /* Store the evolution of the market in currentEvolution */ market->currentEvolutionItems[i] += (asymptoticNumber - market->numItems[i]) / TYPICAL_TIME; /* Check if new items appeared or disappeared on market */ if (fabs(market->currentEvolutionItems[i]) >= 1.0f) { const int num = (int)(market->currentEvolutionItems[i]); if (num >= 0) BS_AddItemToMarket(od, num); else BS_RemoveItemFromMarket(od, -num); market->currentEvolutionItems[i] -= num; } } for (i = 0; i < AIRCRAFTTYPE_MAX; i++) { const humanAircraftType_t type = (humanAircraftType_t)i; const char* aircraftID = cgi->Com_DropShipTypeToShortName(type); const aircraft_t* aircraft = AIR_GetAircraft(aircraftID); const technology_t* tech = aircraft->tech; int asymptoticNumber; if (RS_IsResearched_ptr(tech) && (campaign->marketDef->numAircraft[i] != 0 || ccs.date.day > tech->researchedDate.day + RESEARCH_LIMIT_DELAY)) { /* if aircraft is researched for more than RESEARCH_LIMIT_DELAY or was on the initial market, * there number tend to the value defined in equipment.ufo. * This value is the asymptotic value if it is not 0, or initial value else */ asymptoticNumber = campaign->asymptoticMarketDef->numAircraft[i] ? campaign->asymptoticMarketDef->numAircraft[i] : campaign->marketDef->numAircraft[i]; } else { /* items that have just been researched don't appear on market, but they can disappear */ asymptoticNumber = 0; } /* Store the evolution of the market in currentEvolution */ market->currentEvolutionAircraft[i] += (asymptoticNumber - market->numAircraft[i]) / TYPICAL_TIME; /* Check if new items appeared or disappeared on market */ if (fabs(market->currentEvolutionAircraft[i]) >= 1.0f) { const int num = (int)(market->currentEvolutionAircraft[i]); if (num >= 0) BS_AddAircraftToMarket(aircraft, num); else BS_RemoveAircraftFromMarket(aircraft, -num); market->currentEvolutionAircraft[i] -= num; } } }
/** * @brief check if an item is producable. * @param[in] item Pointer to the item that should be checked. */ bool PR_ItemIsProduceable (const objDef_t* item) { const technology_t* tech = RS_GetTechForItem(item); return tech->produceTime != -1; }
/** * @brief Prints the (UFOpaedia and other) description for aircraft items * @param item The object definition of the item * @sa UP_Article * Not only called from UFOpaedia but also from other places to display * @todo Don't display things like speed for base defence items - a missile * facility isn't getting slower or faster due a special weapon or ammunition */ void UP_AircraftItemDescription (const objDef_t* item) { static char itemText[1024]; const technology_t* tech; /* Set menu text node content to null. */ cgi->INV_ItemDescription(nullptr); *itemText = '\0'; /* no valid item id given */ if (!item) { cgi->Cvar_Set("mn_item", ""); cgi->Cvar_Set("mn_itemname", ""); cgi->Cvar_Set("mn_upmodel_top", ""); cgi->UI_ResetData(TEXT_ITEMDESCRIPTION); return; } tech = RS_GetTechForItem(item); /* select item */ cgi->Cvar_Set("mn_item", "%s", item->id); cgi->Cvar_Set("mn_itemname", "%s", _(item->name)); if (tech->mdl) cgi->Cvar_Set("mn_upmodel_top", "%s", tech->mdl); else cgi->Cvar_Set("mn_upmodel_top", ""); /* set description text */ if (RS_IsResearched_ptr(tech)) { const objDef_t* ammo = nullptr; switch (item->craftitem.type) { case AC_ITEM_WEAPON: Q_strcat(itemText, sizeof(itemText), _("Weight:\t%s\n"), AII_WeightToName(AII_GetItemWeightBySize(item))); break; case AC_ITEM_BASE_MISSILE: case AC_ITEM_BASE_LASER: Q_strcat(itemText, sizeof(itemText), _("Weapon for base defence system\n")); break; case AC_ITEM_AMMO: ammo = item; break; default: break; } /* check ammo of weapons */ if (item->craftitem.type <= AC_ITEM_WEAPON) { for(int i = 0; i < item->numAmmos; i++) if (item->ammos[i]->isVirtual) { ammo = item->ammos[i]; break; } } if (ammo) { /* We display the characteristics of this ammo */ Q_strcat(itemText, sizeof(itemText), _("Ammo:\t%i\n"), ammo->ammo); if (!EQUAL(ammo->craftitem.weaponDamage, 0)) Q_strcat(itemText, sizeof(itemText), _("Damage:\t%i\n"), (int) ammo->craftitem.weaponDamage); Q_strcat(itemText, sizeof(itemText), _("Reloading time:\t%i\n"), (int) ammo->craftitem.weaponDelay); } /* We write the range of the weapon */ if (!EQUAL(item->craftitem.stats[AIR_STATS_WRANGE], 0)) Q_strcat(itemText, sizeof(itemText), "%s:\t%i\n", UP_AircraftStatToName(AIR_STATS_WRANGE), AIR_AircraftMenuStatsValues(item->craftitem.stats[AIR_STATS_WRANGE], AIR_STATS_WRANGE)); /* we scan all stats except weapon range */ for (int i = 0; i < AIR_STATS_MAX; i++) { const char* statsName = UP_AircraftStatToName(i); if (i == AIR_STATS_WRANGE) continue; if (item->craftitem.stats[i] > 2.0f) Q_strcat(itemText, sizeof(itemText), "%s:\t+%i\n", statsName, AIR_AircraftMenuStatsValues(item->craftitem.stats[i], i)); else if (item->craftitem.stats[i] < -2.0f) Q_strcat(itemText, sizeof(itemText), "%s:\t%i\n", statsName, AIR_AircraftMenuStatsValues(item->craftitem.stats[i], i)); else if (item->craftitem.stats[i] > 1.0f) Q_strcat(itemText, sizeof(itemText), _("%s:\t+%i %%\n"), statsName, (int)(item->craftitem.stats[i] * 100) - 100); else if (!EQUAL(item->craftitem.stats[i], 0)) Q_strcat(itemText, sizeof(itemText), _("%s:\t%i %%\n"), statsName, (int)(item->craftitem.stats[i] * 100) - 100); } } else { Q_strcat(itemText, sizeof(itemText), _("Unknown - need to research this")); } cgi->Cvar_Set("mn_upmetadata", "1"); cgi->UI_RegisterText(TEXT_ITEMDESCRIPTION, itemText); }
/** * @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; }
static void AIM_AircraftEquipMenuUpdate (void) { static char smallbuffer1[256]; static char smallbuffer2[128]; const char *typeName; aircraft_t *aircraft; aircraftSlot_t *slot; base_t *base = B_GetCurrentSelectedBase(); if (!base) return; /* don't let old links appear on this menu */ cgi->UI_ResetData(TEXT_AIREQUIP_1); cgi->UI_ResetData(TEXT_AIREQUIP_2); cgi->UI_ResetData(TEXT_ITEMDESCRIPTION); cgi->UI_ResetData(TEXT_LIST); aircraft = base->aircraftCurrent; assert(aircraft); /* Check that airequipSelectedSlot corresponds to an existing slot for this aircraft */ AIM_CheckAirequipSelectedSlot(aircraft); /* Select slot */ slot = AII_SelectAircraftSlot(aircraft, airequipID); /* Check that the selected zone is OK */ AIM_CheckAirequipSelectedZone(slot); /* Fill the list of item you can equip your aircraft with */ AIM_UpdateAircraftItemList(slot); Cvar_Set("mn_equip_itemtype_name", AIM_AircraftItemtypeName(airequipID)); switch (airequipID) { case AC_ITEM_ELECTRONICS: typeName = "item"; break; case AC_ITEM_SHIELD: typeName = "armour"; break; case AC_ITEM_AMMO: typeName = "ammo"; break; case AC_ITEM_WEAPON: typeName = "weapon"; break; default: typeName = "unknown"; break; } Cvar_Set("mn_equip_itemtype", typeName); /* First slot: item currently assigned */ if (!slot->item) { Com_sprintf(smallbuffer1, sizeof(smallbuffer1), "%s", _("No item assigned.\n")); Q_strcat(smallbuffer1, va(_("This slot is for %s or smaller items."), AII_WeightToName(slot->size)), sizeof(smallbuffer1)); } else { technology_t *itemTech = RS_GetTechForItem(slot->item); technology_t *nextItemTech = slot->nextItem ? RS_GetTechForItem(slot->nextItem) : NULL; /* Print next item if we are removing item currently installed and a new item has been added. */ Com_sprintf(smallbuffer1, sizeof(smallbuffer1), "%s\n", slot->nextItem ? _(nextItemTech->name) : _(itemTech->name)); if (!slot->installationTime) { Q_strcat(smallbuffer1, _("This item is functional.\n"), sizeof(smallbuffer1)); } else if (slot->installationTime > 0) { Q_strcat(smallbuffer1, va(_("This item will be installed in %i hours.\n"), slot->installationTime), sizeof(smallbuffer1)); } else if (slot->nextItem) { Q_strcat(smallbuffer1, va(_("%s will be removed in %i hours.\n"), _(itemTech->name), - slot->installationTime), sizeof(smallbuffer1)); Q_strcat(smallbuffer1, va(_("%s will be installed in %i hours.\n"), _(nextItemTech->name), slot->nextItem->craftitem.installationTime - slot->installationTime), sizeof(smallbuffer1)); } else { Q_strcat(smallbuffer1, va(_("This item will be removed in %i hours.\n"), -slot->installationTime), sizeof(smallbuffer1)); } } cgi->UI_RegisterText(TEXT_AIREQUIP_1, smallbuffer1); /* Second slot: ammo slot (only used for weapons) */ if ((airequipID == AC_ITEM_WEAPON || airequipID == AC_ITEM_AMMO) && slot->item) { if (!slot->ammo) { AIM_EmphazeAmmoSlotText(); Com_sprintf(smallbuffer2, sizeof(smallbuffer2), "%s", _("No ammo assigned to this weapon.")); } else { const objDef_t *ammo = slot->nextAmmo ? slot->nextAmmo : slot->ammo; const technology_t *tech = RS_GetTechForItem(ammo); AIM_NoEmphazeAmmoSlotText(); if (!ammo->isVirtual) Q_strncpyz(smallbuffer2, _(tech->name), sizeof(smallbuffer2)); else Q_strncpyz(smallbuffer2, _("No ammo needed"), sizeof(smallbuffer2)); } } else *smallbuffer2 = '\0'; cgi->UI_RegisterText(TEXT_AIREQUIP_2, smallbuffer2); /* Draw existing slots for this aircraft */ AIM_DrawAircraftSlots(aircraft); }
/** * @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); }