示例#1
0
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);
	}
}
示例#2
0
/**
 * @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);
}
示例#3
0
/**
 * @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);
	}
}
示例#4
0
/**
 * @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);
	}
}
示例#5
0
/**
 * @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);
	}
}
示例#6
0
/**
 * @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);
		}
	}
}
示例#9
0
/**
 * @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);
		}
	}
}
示例#10
0
/**
 * @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);
}
示例#12
0
/**
 * @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;
		}
	}
}
示例#13
0
/**
 * @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;
}
示例#14
0
/**
 * @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);
}
示例#15
0
/**
 * @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);
}