Exemplo n.º 1
0
/**
 * @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));
}
Exemplo n.º 2
0
/**
 * @brief Buys the given UGV
 * @param[in] ugv The ugv template of the UGV to buy
 * @param[out] base Base to buy at
 * @return @c true if the ugv could get bought, @c false otherwise
 * @todo Implement this correctly once we have UGV
 */
bool BS_BuyUGV (const ugv_t* ugv, base_t* base)
{
	const objDef_t* ugvWeapon;

	if (!ugv)
		cgi->Com_Error(ERR_DROP, "BS_BuyUGV: Called on nullptr UGV!");
	if (!base)
		cgi->Com_Error(ERR_DROP, "BS_BuyUGV: Called on nullptr base!");
	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 (ccs.credits < ugv->price)
		return false;
	if (E_CountUnhiredRobotsByType(ugv) <= 0)
		return false;
	if (BS_GetItemOnMarket(ugvWeapon) <= 0)
		return false;
	if (CAP_GetFreeCapacity(base, CAP_ITEMS) < UGV_SIZE + ugvWeapon->size)
		return false;
	if (!E_HireRobot(base, ugv))
		return false;

	BS_RemoveItemFromMarket(ugvWeapon, 1);
	CP_UpdateCredits(ccs.credits - ugv->price);
	B_AddToStorage(base, ugvWeapon, 1);

	return true;
}
Exemplo n.º 3
0
/**
 * @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));
}
Exemplo n.º 4
0
/**
 * @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));
}
Exemplo n.º 5
0
/**
 * @brief Actions to perform when destroying one hangar.
 * @param[in] base Pointer to the base where hangar is destroyed.
 * @param[in] capacity Type of hangar capacity: CAP_AIRCRAFT_SMALL or CAP_AIRCRAFT_BIG
 * @note called when player destroy its building or hangar is destroyed during base attack.
 * @note These actions will be performed after we actually remove the building.
 * @pre we checked before calling this function that all parameters are valid.
 * @pre building is not under construction.
 * @sa B_BuildingDestroy_f
 * @todo If player choose to destroy the building, a popup should ask him if he wants to sell aircraft in it.
 */
void CAP_RemoveAircraftExceedingCapacity (base_t* base, baseCapacities_t capacity)
{
	linkedList_t *awayAircraft = nullptr;
	int numAwayAircraft;
	int randomNum;

	/* destroy aircraft only if there's not enough hangar (hangar is already destroyed) */
	if (CAP_GetFreeCapacity(base, capacity) >= 0)
		return;

	/* destroy one aircraft (must not be sold: may be destroyed by aliens) */
	AIR_ForeachFromBase(aircraft, base) {
		const int aircraftSize = aircraft->size;

		switch (aircraftSize) {
		case AIRCRAFT_SMALL:
			if (capacity != CAP_AIRCRAFT_SMALL)
				continue;
			break;
		case AIRCRAFT_LARGE:
			if (capacity != CAP_AIRCRAFT_BIG)
				continue;
			break;
		default:
			cgi->Com_Error(ERR_DROP, "B_RemoveAircraftExceedingCapacity: Unknown type of aircraft '%i'", aircraftSize);
		}

		/* Only aircraft in hangar will be destroyed by hangar destruction */
		if (!AIR_IsAircraftInBase(aircraft)) {
			if (AIR_IsAircraftOnGeoscape(aircraft))
				cgi->LIST_AddPointer(&awayAircraft, (void*)aircraft);
			continue;
		}

		/* Remove aircraft and aircraft items, but do not fire employees */
		AIR_DeleteAircraft(aircraft);
		cgi->LIST_Delete(&awayAircraft);
		return;
	}
	numAwayAircraft = cgi->LIST_Count(awayAircraft);

	if (!numAwayAircraft)
		return;
	/* All aircraft are away from base, pick up one and change it's homebase */
	randomNum = rand() % numAwayAircraft;
	if (!CL_DisplayHomebasePopup((aircraft_t*)cgi->LIST_GetByIdx(awayAircraft, randomNum), false)) {
		aircraft_t *aircraft = (aircraft_t*)cgi->LIST_GetByIdx(awayAircraft, randomNum);
		/* No base can hold this aircraft */
		UFO_NotifyPhalanxAircraftRemoved(aircraft);
		if (!MapIsWater(GEO_GetColor(aircraft->pos, MAPTYPE_TERRAIN, nullptr)))
			CP_SpawnRescueMission(aircraft, nullptr);
		else {
			/* Destroy the aircraft and everything onboard - the aircraft pointer
			 * is no longer valid after this point */
			/* Pilot skills; really kill pilot in this case? */
			AIR_DestroyAircraft(aircraft);
		}
	}
	cgi->LIST_Delete(&awayAircraft);
}
Exemplo n.º 6
0
/**
 * @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));
}
Exemplo n.º 7
0
/**
 * @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;
		}
	}
}
Exemplo n.º 8
0
/**
 * @brief Buys items from the market
 * @param[in] od pointer to the item (Object Definition record)
 * @param[out] base Base to buy at
 * @param[in ] count Number of items to buy
 * @return @c true if the ugv could get bought, @c false otherwise
 */
bool BS_BuyItem (const objDef_t* od, base_t* base, int count)
{
	if (!od)
		cgi->Com_Error(ERR_DROP, "BS_BuyItem: Called on nullptr objDef!");
	if (!base)
		cgi->Com_Error(ERR_DROP, "BS_BuyItem: Called on nullptr base!");

	if (count <= 0)
		return false;
	if (!BS_IsOnMarket(od))
		return false;
	if (ccs.credits < BS_GetItemBuyingPrice(od) * count)
		return false;
	if (BS_GetItemOnMarket(od) < count)
		return false;
	if (CAP_GetFreeCapacity(base, CAP_ITEMS) < od->size * count)
		return false;

	B_AddToStorage(base, od, count);
	BS_RemoveItemFromMarket(od, count);
	CP_UpdateCredits(ccs.credits - BS_GetItemBuyingPrice(od) * count);

	return true;
}
Exemplo n.º 9
0
/**
 * @brief Mark a building for destruction - you only have to confirm it now
 * @param[in] building Pointer to the base to destroy
 */
static void B_MarkBuildingDestroy (building_t* building)
{
	baseCapacities_t cap;
	base_t *base = building->base;

	/* you can't destroy buildings if base is under attack */
	if (B_IsUnderAttack(base)) {
		CP_Popup(_("Notice"), _("Base is under attack, you can't destroy buildings!"));
		return;
	}

	cap = B_GetCapacityFromBuildingType(building->buildingType);
	/* store the pointer to the building you wanna destroy */
	base->buildingCurrent = building;

	/** @todo: make base destroyable by destroying entrance */
	if (building->buildingType == B_ENTRANCE) {
		CP_Popup(_("Destroy Entrance"), _("You can't destroy the entrance of the base!"));
		return;
	}

	if (!B_IsBuildingDestroyable(building)) {
			CP_Popup(_("Notice"), _("You can't destroy this building! It is the only connection to other buildings!"));
			return;
	}

	if (building->buildingStatus == B_STATUS_WORKING) {
		const bool hasMoreBases = B_GetCount() > 1;
		switch (building->buildingType) {
		case B_HANGAR:
		case B_SMALL_HANGAR:
			if (CAP_GetFreeCapacity(base, cap) <= 0) {
				cgi->UI_PopupButton(_("Destroy Hangar"), _("If you destroy this hangar, you will also destroy the aircraft inside.\nAre you sure you want to destroy this building?"),
					"ui_pop;ui_push aircraft;aircraft_select;", _("Go to hangar"), _("Go to hangar without destroying building"),
					va("building_destroy %i %i confirmed; ui_pop;", base->idx, building->idx), _("Destroy"), _("Destroy the building"),
					hasMoreBases ? "ui_pop;ui_push transfer;" : NULL, hasMoreBases ? _("Transfer") : NULL,
					_("Go to transfer menu without destroying the building"));
				return;
			}
			break;
		case B_QUARTERS:
			if (CAP_GetFreeCapacity(base, cap) < building->capacity) {
				cgi->UI_PopupButton(_("Destroy Quarter"), _("If you destroy this Quarters, every employee inside will be killed.\nAre you sure you want to destroy this building?"),
					"ui_pop;ui_push employees;employee_list 0;", _("Dismiss"), _("Go to hiring menu without destroying building"),
					va("building_destroy %i %i confirmed; ui_pop;", base->idx, building->idx), _("Destroy"), _("Destroy the building"),
					hasMoreBases ? "ui_pop;ui_push transfer;" : NULL, hasMoreBases ? _("Transfer") : NULL,
					_("Go to transfer menu without destroying the building"));
				return;
			}
			break;
		case B_STORAGE:
			if (CAP_GetFreeCapacity(base, cap) < building->capacity) {
				cgi->UI_PopupButton(_("Destroy Storage"), _("If you destroy this Storage, every items inside will be destroyed.\nAre you sure you want to destroy this building?"),
					"ui_pop;ui_push market;buy_type *mn_itemtype", _("Go to storage"), _("Go to buy/sell menu without destroying building"),
					va("building_destroy %i %i confirmed; ui_pop;", base->idx, building->idx), _("Destroy"), _("Destroy the building"),
					hasMoreBases ? "ui_pop;ui_push transfer;" : NULL, hasMoreBases ? _("Transfer") : NULL,
					_("Go to transfer menu without destroying the building"));
				return;
			}
			break;
		default:
			break;
		}
	}

	cgi->UI_PopupButton(_("Destroy building"), _("Are you sure you want to destroy this building?"),
		NULL, NULL, NULL,
		va("building_destroy %i %i confirmed; ui_pop;", base->idx, building->idx), _("Destroy"), _("Destroy the building"),
		NULL, NULL, NULL);
}
Exemplo n.º 10
0
/**
 * @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");
}
Exemplo n.º 11
0
			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;