示例#1
0
/**
 * @brief Start Base Attack.
 * @note Base attack mission -- Stage 2
 */
void CP_BaseAttackStartMission (mission_t *mission)
{
	base_t *base = mission->data.base;
	linkedList_t *hiredSoldiersInBase = NULL;
	employee_t *employee;

	assert(base);

	mission->stage = STAGE_BASE_ATTACK;

	CP_MissionDisableTimeLimit(mission);

	if (mission->ufo) {
		/* ufo becomes invisible on geoscape, but don't remove it from ufo global array (may reappear)*/
		CP_UFORemoveFromGeoscape(mission, qfalse);
	}

	/* we always need at least one command centre in the base - because the
	 * phalanx soldiers have their starting positions here.
	 * There should also always be an entrance - the aliens start there
	 * but we don't need to check that as entrance can't be destroyed */
	if (!B_GetNumberOfBuildingsInBaseByBuildingType(base, B_COMMAND)) {
		/** @todo handle command centre properly */
		Com_DPrintf(DEBUG_CLIENT, "CP_BaseAttackStartMission: Base '%s' has no Command Center: it can't defend itself. Destroy base.\n", base->name);
		CP_BaseAttackMissionDestroyBase(mission);
		return;
	}

	base->baseStatus = BASE_UNDER_ATTACK;
	ccs.campaignStats.basesAttacked++;

#if 0
	/** @todo implement onattack: add it to basemanagement.ufo and implement functions */
	if (base->onAttack[0] != '\0')
		/* execute next frame */
		Cbuf_AddText(va("%s %i", base->onAttack, base->id));
#endif

	MAP_SelectMission(mission);
	mission->active = qtrue;
	ccs.mapAction = MA_BASEATTACK;
	Com_DPrintf(DEBUG_CLIENT, "Base attack: %s at %.0f:%.0f\n", mission->id, mission->pos[0], mission->pos[1]);

	/** @todo EMPL_ROBOT */
	E_GetHiredEmployees(base, EMPL_SOLDIER, &hiredSoldiersInBase);

	/* Fill the fake aircraft */
	OBJZERO(baseAttackFakeAircraft);
	baseAttackFakeAircraft.homebase = base;
	/* needed for transfer of alien corpses */
	VectorCopy(base->pos, baseAttackFakeAircraft.pos);
#if 0
	/** @todo active this once more than 8 soldiers are working */
	/* needed to spawn soldiers on map */
	baseAttackFakeAircraft.maxTeamSize = LIST_Count(hiredSoldiersInBase);
#else
	baseAttackFakeAircraft.maxTeamSize = MAX_ACTIVETEAM;
#endif

	if (!hiredSoldiersInBase) {
		Com_DPrintf(DEBUG_CLIENT, "CP_BaseAttackStartMission: Base '%s' has no soldiers: it can't defend itself. Destroy base.\n", base->name);
		CP_BaseAttackMissionDestroyBase(mission);
		return;
	}

	LIST_Foreach(hiredSoldiersInBase, employee_t, employee) {
		if (E_IsAwayFromBase(employee))
			continue;
		AIR_AddToAircraftTeam(&baseAttackFakeAircraft, employee);
	}
	if (AIR_GetTeamSize(&baseAttackFakeAircraft) == 0) {
		Com_DPrintf(DEBUG_CLIENT, "CP_BaseAttackStartMission: Base '%s' has no soldiers at home: it can't defend itself. Destroy base.\n", base->name);
		CP_BaseAttackMissionDestroyBase(mission);
		return;
	}
#if 0
	/** @todo active this once more than 8 soldiers are working */
	/* all soldiers in the base should get used */
	baseAttackFakeAircraft.maxTeamSize = AIR_GetTeamSize(&baseAttackFakeAircraft);
#endif

	LIST_Delete(&hiredSoldiersInBase);
	base->aircraftCurrent = &baseAttackFakeAircraft;
	MAP_SetMissionAircraft(&baseAttackFakeAircraft);
	/** @todo remove me - this is not needed because we are using the base->aircraftCurrent
	 * pointer for resolving the aircraft - only CL_GameAutoGo needs this */
	MAP_SetInterceptorAircraft(&baseAttackFakeAircraft);	/* needed for updating soldier stats sa CL_UpdateCharacterStats*/
	B_SetCurrentSelectedBase(base);						/* needed for equipment menu */

	Com_sprintf(popupText, sizeof(popupText), _("Base '%s' is under attack! What to do ?"), base->name);
	UI_RegisterText(TEXT_POPUP, popupText);

	CL_GameTimeStop();
	UI_PushWindow("popup_baseattack", NULL, NULL);
}
/**
 * @brief Updates the hospital menu.
 * @sa HOS_Init_f
 */
static void HOS_UpdateMenu (void)
{
	char name[128];
	char rank[128];
	int j, type;
	int entry;
	base_t *base = B_GetCurrentSelectedBase();

	if (!base)
		return;

	/* Reset list. */
	cgi->UI_ExecuteConfunc("hospital_clear");

	for (type = 0, j = 0, entry = 0; type < MAX_EMPL; type++) {
		E_Foreach(type, employee) {
			float injuryLevel = HOS_InjuryLevel(&employee->chr);
			if (!E_IsInBase(employee, base))
				continue;
			/* Don't show soldiers who are gone in mission */
			if (E_IsAwayFromBase(employee))
				continue;
			/* Don't show healthy employees */
			if (employee->chr.HP >= employee->chr.maxHP && injuryLevel <= 0)
				continue;

			if (j >= hospitalFirstEntry && entry < HOS_MENU_MAX_ENTRIES) {
				/* Print name. */
				Q_strncpyz(name, employee->chr.name, sizeof(name));
				/* Print rank for soldiers or type for other personel. */
				if (type == EMPL_SOLDIER) {
					const rank_t *rankPtr = CL_GetRankByIdx(employee->chr.score.rank);
					Q_strncpyz(rank, _(rankPtr->name), sizeof(rank));
				} else
					Q_strncpyz(rank, E_GetEmployeeString(employee->type, 1), sizeof(rank));
				Com_DPrintf(DEBUG_CLIENT, "%s ucn: %i entry: %i\n", name, employee->chr.ucn, entry);
				/* If the employee is seriously wounded (HP <= 50% maxHP), make him red. */
				if (employee->chr.HP <= (int) (employee->chr.maxHP * 0.5) || injuryLevel >= 0.5)
					cgi->UI_ExecuteConfunc("hospitalserious %i", entry);
				/* If the employee is semi-seriously wounded (HP <= 85% maxHP), make him yellow. */
				else if (employee->chr.HP <= (int) (employee->chr.maxHP * 0.85) || injuryLevel >= 0.15)
					cgi->UI_ExecuteConfunc("hospitalmedium %i", entry);
				else
					cgi->UI_ExecuteConfunc("hospitallight %i", entry);

				/* Display name in the correct list-entry. */
				cgi->Cvar_Set(va("mn_hos_item%i", entry), name);
				/* Display rank in the correct list-entry. */
				cgi->Cvar_Set(va("mn_hos_rank%i", entry), rank);
				/* Prepare the health bar */
				cgi->Cvar_Set(va("mn_hos_hp%i", entry), va("%i", employee->chr.HP));
				cgi->Cvar_Set(va("mn_hos_hpmax%i", entry), va("%i", employee->chr.maxHP));

				/* Send wound info */
				HOS_EntryWoundData(&employee->chr, entry);

				/* Increase the counter of list entries. */
				entry++;
			}
			j++;
		}
	}
示例#3
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) {
		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) {
		Com_Printf("No/invalid base selected.\n");
		return;
	}

	type = 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->ugv;
			const technology_t* tech = RS_GetTechByProvided(ugv->id);

			if (!E_IsInBase(robot, base))
				continue;

			cgi->UI_ExecuteConfunc("ui_market_add \"ugv-%d\" \"%s\" 1 0 0 %d - \"%s\"", robot->chr.ucn, _(tech->name), ugv->price, E_IsAwayFromBase(robot) ? _("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 */
	case FILTER_S_PRIMARY:
	case FILTER_S_SECONDARY:
	case FILTER_S_HEAVY:
	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 && !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;
			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;
	}