Ejemplo n.º 1
0
/**
**  Toggle units from a particular type and belonging to the local player.
**
**  The base is included in the selection and defines
**  the type of the other units to be selected.
**
**  @param base  Toggle all units of same type.
**
**  @return      Number of units found, 0 means selection unchanged
**
**  FIXME: toggle not written
**  FIXME: should always select the nearest 9 units to the base!
*/
int ToggleUnitsByType(CUnit &base)
{
	const CUnitType &type = *base.Type;

	// if unit is a cadaver or hidden (not on map)
	// no unit can be selected.
	if (base.Removed || base.IsAlive() == false) {
		return 0;
	}
	// if unit isn't belonging to the player, or is a static unit
	// (like a building), only 1 unit can be selected at the same time.
	if (!CanSelectMultipleUnits(*base.Player) || !type.SelectableByRectangle) {
		return 0;
	}

	if (!SelectUnit(base)) { // Add base to selection
		return 0;
	}
	//
	//  Search for other visible units of the same type
	//

	// select all visible units.
	// StephanR: should be (MapX,MapY,MapX+MapWidth-1,MapY+MapHeight-1) ???
	// FIXME: this should probably be cleaner implemented if SelectUnitsByType()
	// took parameters of the selection rectangle as arguments */
	const CViewport *vp = UI.MouseViewport;
	const Vec2i offset(1, 1);
	const Vec2i minPos = vp->MapPos - offset;
	const Vec2i vpSize(vp->MapWidth, vp->MapHeight);
	const Vec2i maxPos = vp->MapPos + vpSize + offset;
	std::vector<CUnit *> table;

	Select(minPos, maxPos, table, HasSameTypeAs(type));

	// FIXME: peon/peasant with gold/wood & co are considered from
	// different type... idem for tankers
	for (size_t i = 0; i < table.size(); ++i) {
		CUnit &unit = *table[i];

		if (!CanSelectMultipleUnits(*unit.Player)) {
			continue;
		}
		if (unit.IsUnusable()) { // guess SelectUnits doesn't check this
			continue;
		}
		if (&unit == &base) { // no need to have the same unit twice
			continue;
		}
		if (unit.TeamSelected) { // Somebody else onteam has this unit
			continue;
		}
		if (!SelectUnit(unit)) { // add unit to selection
			return Selected.size();
		}
	}

	NetworkSendSelection(&Selected[0], Selected.size());
	return Selected.size();
}
Ejemplo n.º 2
0
/**
**  Add the ground units in the rectangle to the current selection
**
**  @param corner_topleft,     start of selection rectangle
**  @param corner_bottomright  end of selection rectangle
**
**  @return     the number of units found.
*/
int AddSelectedGroundUnitsInRectangle(const PixelPos &corner_topleft, const PixelPos &corner_bottomright)
{
	// Check if the original selected unit (if it's alone) is ours,
	// and can be selectable by rectangle.
	// In this case, do nothing.
	if (Selected.size() == 1
		&& (!CanSelectMultipleUnits(*Selected[0]->Player)
			|| !Selected[0]->Type->SelectableByRectangle)) {
		return Selected.size();
	}

	// If there is no selected unit yet, do a simple selection.
	if (Selected.empty()) {
		return SelectGroundUnitsInRectangle(corner_topleft, corner_bottomright);
	}

	const Vec2i t0 = Map.MapPixelPosToTilePos(corner_topleft);
	const Vec2i t1 = Map.MapPixelPosToTilePos(corner_bottomright);
	const Vec2i range(2, 2);
	std::vector<CUnit *> table;

	Select(t0 - range, t1 + range, table);
	SelectSpritesInsideRectangle(corner_topleft, corner_bottomright, table);

	unsigned int n = 0;
	for (size_t i = 0; i < table.size(); ++i) {
		CUnit &unit = *table[i];

		if (!CanSelectMultipleUnits(*unit.Player) ||
			!unit.Type->SelectableByRectangle) {
			continue;
		}
		if (unit.IsUnusable()) {  // guess SelectUnits doesn't check this
			continue;
		}
		if (unit.Type->UnitType == UnitTypeFly) {
			continue;
		}
		if (unit.TeamSelected) { // Somebody else onteam has this unit
			continue;
		}
		table[n++] = &unit;
		if (n == MaxSelectable) {
			break;
		}
	}

	// Add the units to selected.
	for (unsigned int i = 0; i < n && Selected.size() < MaxSelectable; ++i) {
		SelectUnit(*table[i]);
	}
	return Selected.size();
}
Ejemplo n.º 3
0
/**
**  Select own air units in a rectangle.
**
**  @param corner_topleft,  start of selection rectangle
**  @param corner_bottomright end of selection rectangle
**
**  @return     the number of units found.
*/
int SelectAirUnitsInRectangle(const PixelPos &corner_topleft, const PixelPos &corner_bottomright)
{
	const Vec2i t0 = Map.MapPixelPosToTilePos(corner_topleft);
	const Vec2i t1 = Map.MapPixelPosToTilePos(corner_bottomright);
	const Vec2i range(2, 2);
	std::vector<CUnit *> table;

	Select(t0 - range, t1 + range, table);
	SelectSpritesInsideRectangle(corner_topleft, corner_bottomright, table);
	unsigned int n = 0;
	for (size_t i = 0; i != table.size(); ++i) {
		CUnit &unit = *table[i];
		if (!CanSelectMultipleUnits(*unit.Player) || !unit.Type->SelectableByRectangle) {
			continue;
		}
		if (unit.IsUnusable()) { // guess SelectUnits doesn't check this
			continue;
		}
		if (unit.Type->UnitType != UnitTypeFly) {
			continue;
		}
		if (unit.TeamSelected) { // Somebody else onteam has this unit
			continue;
		}
		table[n++] = &unit;
		if (n == MaxSelectable) {
			break;
		}
	}
	if (n) {
		ChangeSelectedUnits(&table[0], n);
	}
	return n;
}
Ejemplo n.º 4
0
/**
**  Select the units selectable by rectangle in a local table.
**  Act like a filter: The source table is modified.
**  Return the original table if no unit is found.
**
**  @param table      Input/Output table of units.
**
**  return true if at least a unit is found;
*/
static bool SelectOrganicUnitsInTable(std::vector<CUnit *> &table)
{
	unsigned int n = 0;

	for (size_t i = 0; i != table.size(); ++i) {
		CUnit &unit = *table[i];

		if (!CanSelectMultipleUnits(*unit.Player) || !unit.Type->SelectableByRectangle) {
			continue;
		}
		if (unit.IsUnusable()) {  // guess SelectUnits doesn't check this
			continue;
		}
		if (unit.TeamSelected) { // Somebody else onteam has this unit
			continue;
		}
		table[n++] = &unit;
		if (n == MaxSelectable) {
			break;
		}
	}
	if (n != 0) {
		table.resize(n);
		return true;
	}
	return false;
}
Ejemplo n.º 5
0
//Wyrmgus start
//static bool SelectOrganicUnitsInTable(std::vector<CUnit *> &table)
static bool SelectOrganicUnitsInTable(std::vector<CUnit *> &table, bool added_table)
//Wyrmgus end
{
	unsigned int n = 0;
	
	//Wyrmgus start
	//check if has non-building
	bool hasNonBuilding = false;
	
	if (added_table == false) {
		for (size_t i = 0; i != table.size(); ++i) {
			CUnit &unit = *table[i];
			
			if (!unit.Type->BoolFlag[BUILDING_INDEX].value) {
				hasNonBuilding = true;
			}
		}
	}
	//Wyrmgus end

	for (size_t i = 0; i != table.size(); ++i) {
		CUnit &unit = *table[i];

		if (!CanSelectMultipleUnits(*unit.Player) || !unit.Type->BoolFlag[SELECTABLEBYRECTANGLE_INDEX].value) {
			continue;
		}
		if (unit.IsUnusable()) {  // guess SelectUnits doesn't check this
			continue;
		}
		if (unit.TeamSelected) { // Somebody else onteam has this unit
			continue;
		}
		//Wyrmgus start
		//only select buildings if another building of the same type is already selected
		if (added_table == false && unit.Type->BoolFlag[BUILDING_INDEX].value && ((i != 0 && !UnitCanBeSelectedWith(*table[0], unit)) || hasNonBuilding)) {
			continue;
		}
		//Wyrmgus end
		table[n++] = &unit;
		if (n == MaxSelectable) {
			break;
		}
	}
	if (n != 0) {
		table.resize(n);
		return true;
	}
	return false;
}
Ejemplo n.º 6
0
/**
**  Add the units in the rectangle to the current selection
**
**  @param corner_topleft,  start of selection rectangle
**  @param corner_bottomright end of selection rectangle
**
**  @return    the _total_ number of units selected.
*/
int AddSelectedUnitsInRectangle(const PixelPos &corner_topleft, const PixelPos &corner_bottomright)
{
	// Check if the original selected unit (if it's alone) is ours,
	// and can be selectable by rectangle.
	// In this case, do nothing.
	if (Selected.size() == 1
		&& (!CanSelectMultipleUnits(*Selected[0]->Player)
			|| !Selected[0]->Type->BoolFlag[SELECTABLEBYRECTANGLE_INDEX].value)) {
		return Selected.empty();
	}
	// If there is no selected unit yet, do a simple selection.
	if (Selected.empty()) {
		return SelectUnitsInRectangle(corner_topleft, corner_bottomright);
	}
	const Vec2i tilePos0 = Map.MapPixelPosToTilePos(corner_topleft, UI.CurrentMapLayer->ID);
	const Vec2i tilePos1 = Map.MapPixelPosToTilePos(corner_bottomright, UI.CurrentMapLayer->ID);
	const Vec2i range(2, 2);
	std::vector<CUnit *> table;

	//Wyrmgus start
//	Select(tilePos0 - range, tilePos1 + range, table);
	Select(tilePos0 - range, tilePos1 + range, table, UI.CurrentMapLayer->ID);
	//Wyrmgus end
	SelectSpritesInsideRectangle(corner_topleft, corner_bottomright, table);
	// If no unit in rectangle area... do nothing
	if (table.empty()) {
		return Selected.size();
	}

	// Now we should only have mobile (organic) units belonging to us,
	// so if there's no such units in the rectangle, do nothing.
	//Wyrmgus start
//	if (SelectOrganicUnitsInTable(table) == false) {
	if (SelectOrganicUnitsInTable(table, true) == false) {
	//Wyrmgus end
		return Selected.size();
	}

	for (size_t i = 0; i < table.size() && Selected.size() < MaxSelectable; ++i) {
		//Wyrmgus start
		if (Selected.size() && !UnitCanBeSelectedWith(*Selected[0], *table[i])) {
			continue;
		}
		//Wyrmgus end
		SelectUnit(*table[i]);
	}
	return Selected.size();
}
Ejemplo n.º 7
0
/**
**  Select own ground units in a rectangle.
**
**  @param corner_topleft,  start of selection rectangle
**  @param corner_bottomright end of selection rectangle
**
**  @return     the number of units found.
*/
int SelectGroundUnitsInRectangle(const PixelPos &corner_topleft, const PixelPos &corner_bottomright)
{
	const Vec2i t0 = Map.MapPixelPosToTilePos(corner_topleft, UI.CurrentMapLayer->ID);
	const Vec2i t1 = Map.MapPixelPosToTilePos(corner_bottomright, UI.CurrentMapLayer->ID);
	const Vec2i range(2, 2);
	std::vector<CUnit *> table;

	//Wyrmgus start
//	Select(t0 - range, t1 + range, table);
	Select(t0 - range, t1 + range, table, UI.CurrentMapLayer->ID);
	//Wyrmgus end
	SelectSpritesInsideRectangle(corner_topleft, corner_bottomright, table);

	unsigned int n = 0;
	for (size_t i = 0; i != table.size(); ++i) {
		CUnit &unit = *table[i];

		if (!CanSelectMultipleUnits(*unit.Player) || !unit.Type->BoolFlag[SELECTABLEBYRECTANGLE_INDEX].value) {
			continue;
		}
		if (unit.IsUnusable()) {  // guess SelectUnits doesn't check this
			continue;
		}
		if (unit.Type->UnitType == UnitTypeFly) {
			continue;
		}
		if (unit.TeamSelected) { // Somebody else onteam has this unit
			continue;
		}
		//Wyrmgus start
		if (unit.Type->BoolFlag[BUILDING_INDEX].value) { //this selection mode is not for buildings
			continue;
		}
		//Wyrmgus end
		table[n++] = &unit;
		if (n == MaxSelectable) {
			break;
		}
	}
	if (n) {
		ChangeSelectedUnits(&table[0], n);
	}
	return n;
}
Ejemplo n.º 8
0
/**
**  Select entire army.
**
**
**  @return     the number of units found.
*/
int SelectArmy()
{
	const Vec2i minPos(0, 0);
	const Vec2i maxPos(UI.CurrentMapLayer->GetWidth() - 1, UI.CurrentMapLayer->GetHeight() - 1);
	std::vector<CUnit *> table;

	//Wyrmgus start
//	Select(minPos, maxPos, table);
	Select(minPos, maxPos, table, UI.CurrentMapLayer->ID);
	//Wyrmgus end

	unsigned int n = 0;
	for (size_t i = 0; i != table.size(); ++i) {
		CUnit &unit = *table[i];

		if (!CanSelectMultipleUnits(*unit.Player) || !unit.Type->BoolFlag[SELECTABLEBYRECTANGLE_INDEX].value) {
			continue;
		}
		if (unit.IsUnusable()) {  // guess SelectUnits doesn't check this
			continue;
		}
		if (unit.Type->UnitType == UnitTypeNaval || unit.Type->UnitType == UnitTypeFly) {
			continue;
		}
		if (unit.TeamSelected) { // Somebody else on team has this unit
			continue;
		}
		if (unit.Type->BoolFlag[BUILDING_INDEX].value) { //this selection mode is not for buildings
			continue;
		}
		if (unit.Type->BoolFlag[HARVESTER_INDEX].value) { //this selection mode is not for workers
			continue;
		}
		table[n++] = &unit;
		if (n == MaxSelectable) {
			break;
		}
	}
	if (n) {
		ChangeSelectedUnits(&table[0], n);
	}
	return n;
}
Ejemplo n.º 9
0
/**
**  Add the units in the rectangle to the current selection
**
**  @param corner_topleft,  start of selection rectangle
**  @param corner_bottomright end of selection rectangle
**
**  @return    the _total_ number of units selected.
*/
int AddSelectedUnitsInRectangle(const PixelPos &corner_topleft, const PixelPos &corner_bottomright)
{
	// Check if the original selected unit (if it's alone) is ours,
	// and can be selectable by rectangle.
	// In this case, do nothing.
	if (Selected.size() == 1
		&& (!CanSelectMultipleUnits(*Selected[0]->Player)
			|| !Selected[0]->Type->SelectableByRectangle)) {
		return Selected.empty();
	}
	// If there is no selected unit yet, do a simple selection.
	if (Selected.empty()) {
		return SelectUnitsInRectangle(corner_topleft, corner_bottomright);
	}
	const Vec2i tilePos0 = Map.MapPixelPosToTilePos(corner_topleft);
	const Vec2i tilePos1 = Map.MapPixelPosToTilePos(corner_bottomright);
	const Vec2i range(2, 2);
	std::vector<CUnit *> table;

	Select(tilePos0 - range, tilePos1 + range, table);
	SelectSpritesInsideRectangle(corner_topleft, corner_bottomright, table);
	// If no unit in rectangle area... do nothing
	if (table.empty()) {
		return Selected.size();
	}

	// Now we should only have mobile (organic) units belonging to us,
	// so if there's no such units in the rectangle, do nothing.
	if (SelectOrganicUnitsInTable(table) == false) {
		return Selected.size();
	}

	for (size_t i = 0; i < table.size() && Selected.size() < MaxSelectable; ++i) {
		SelectUnit(*table[i]);
	}
	return Selected.size();
}
Ejemplo n.º 10
0
/**
**  Select units in a rectangle.
**  Proceed in order in none found:
**    @li select local player mobile units
**    @li select one local player static unit (random)
**    @li select one neutral unit (critter, mine...)
**    @li select one enemy unit (random)
**
**  @param corner_topleft,  start of selection rectangle
**  @param corner_bottomright end of selection rectangle
**
**  @return     the number of units found.
*/
int SelectUnitsInRectangle(const PixelPos &corner_topleft, const PixelPos &corner_bottomright)
{
	const Vec2i t0 = Map.MapPixelPosToTilePos(corner_topleft);
	const Vec2i t1 = Map.MapPixelPosToTilePos(corner_bottomright);
	const Vec2i range(2, 2);
	std::vector<CUnit *> table;

	Select(t0 - range, t1 + range, table);
	SelectSpritesInsideRectangle(corner_topleft, corner_bottomright, table);

	// 1) search for the player units selectable with rectangle
	if (SelectOrganicUnitsInTable(table)) {
		const int size = static_cast<int>(table.size());
		ChangeSelectedUnits(&table[0], size);
		return size;
	}

	// 2) If no unit found, try a player's unit not selectable by rectangle
	for (size_t i = 0; i != table.size(); ++i) {
		CUnit &unit = *table[i];

		if (!CanSelectMultipleUnits(*unit.Player)) {
			continue;
		}
		// FIXME: Can we get this?
		if (!unit.Removed && unit.IsAlive()) {
			SelectSingleUnit(unit);
			return 1;
		}
	}

	// 3) If no unit found, try a resource or a neutral critter
	for (size_t i = 0; i != table.size(); ++i) {
		CUnit &unit = *table[i];
		// Unit visible FIXME: write function UnitSelectable
		if (!unit.IsVisibleInViewport(*UI.SelectedViewport)) {
			continue;
		}
		const CUnitType &type = *unit.Type;
		// Buildings are visible but not selectable
		if (type.Building && !unit.IsVisibleOnMap(*ThisPlayer)) {
			continue;
		}
		if ((type.GivesResource && !unit.Removed)) { // no built resources.
			SelectSingleUnit(unit);
			return 1;
		}
	}

	// 4) If no unit found, select an enemy unit (first found)
	for (size_t i = 0; i != table.size(); ++i) {
		CUnit &unit = *table[i];
		// Unit visible FIXME: write function UnitSelectable
		if (!unit.IsVisibleInViewport(*UI.SelectedViewport)) {
			continue;
		}
		// Buildings are visible but not selectable
		if (unit.Type->Building && !unit.IsVisibleOnMap(*ThisPlayer)) {
			continue;
		}
		if (unit.IsAliveOnMap()) {
			SelectSingleUnit(unit);
			return 1;
		}
	}
	return 0;
}
Ejemplo n.º 11
0
/**
**  Select units from a particular type and belonging to the local player.
**
**  The base is included in the selection and defines
**  the type of the other units to be selected.
**
**  @param base  Select all units of same type.
**
**  @return      Number of units found, 0 means selection unchanged
**
**  FIXME: 0 can't happen. Maybe when scripting will use it?
**
**  FIXME: should always select the nearest 9 units to the base!
*/
int SelectUnitsByType(CUnit &base)
{
	const CUnitType &type = *base.Type;
	const CViewport *vp = UI.MouseViewport;

	Assert(UI.MouseViewport);

	if (type.ClicksToExplode) {
		HandleSuicideClick(base);
	}

	// if unit is a cadaver or hidden (not on map)
	// no unit can be selected.
	if (base.Removed || base.IsAlive() == false) {
		return 0;
	}

	if (type.IsNotSelectable && GameRunning) {
		return 0;
	}
	if (base.TeamSelected) { // Somebody else onteam has this unit
		return 0;
	}

	UnSelectAll();
	Selected.push_back(&base);
	base.Selected = 1;

	// if unit isn't belonging to the player or allied player, or is a static unit
	// (like a building), only 1 unit can be selected at the same time.
	if (!CanSelectMultipleUnits(*base.Player) || !type.SelectableByRectangle) {
		return Selected.size();
	}

	//
	// Search for other visible units of the same type
	//
	std::vector<CUnit *> table;
	// select all visible units.
	// StephanR: should be (MapX,MapY,MapX+MapWidth-1,MapY+MapHeight-1) ???
	/* FIXME: this should probably be cleaner implemented if SelectUnitsByType()
	 * took parameters of the selection rectangle as arguments */
	const Vec2i offset(1, 1);
	const Vec2i minPos = vp->MapPos - offset;
	const Vec2i vpSize(vp->MapWidth, vp->MapHeight);
	const Vec2i maxPos = vp->MapPos + vpSize + offset;
	Select(minPos, maxPos, table, HasSameTypeAs(type));

	// FIXME: peon/peasant with gold/wood & co are considered from
	//   different type... idem for tankers
	for (size_t i = 0; i != table.size(); ++i) {
		CUnit &unit = *table[i];
		if (!CanSelectMultipleUnits(*unit.Player)) {
			continue;
		}
		if (unit.IsUnusable()) {  // guess SelectUnits doesn't check this
			continue;
		}
		if (&unit == &base) {  // no need to have the same unit twice :)
			continue;
		}
		if (unit.TeamSelected) { // Somebody else onteam has this unit
			continue;
		}
		Selected.push_back(&unit);
		unit.Selected = 1;
		if (Selected.size() == MaxSelectable) {
			break;
		}
	}
	if (Selected.size() > 1) {
		for (size_t i = 0; i != Selected.size(); ++i) {
			Selected[i]->LastGroup = GroupId;
		}
	}
	NetworkSendSelection(&Selected[0], Selected.size());
	return Selected.size();
}
Ejemplo n.º 12
0
/**
**  Add the air units in the rectangle to the current selection
**
**  @param corner_topleft,     start of selection rectangle
**  @param corner_bottomright  end of selection rectangle
**
**  @return     the number of units found.
*/
int AddSelectedAirUnitsInRectangle(const PixelPos &corner_topleft, const PixelPos &corner_bottomright)
{
	// Check if the original selected unit (if it's alone) is ours,
	// and can be selectable by rectangle.
	// In this case, do nothing.
	if (Selected.size() == 1
		&& (!CanSelectMultipleUnits(*Selected[0]->Player)
			|| !Selected[0]->Type->BoolFlag[SELECTABLEBYRECTANGLE_INDEX].value)) {
		return Selected.size();
	}

	// If there is no selected unit yet, do a simple selection.
	//Wyrmgus start
//	if (Selected.empty()) {
	if (Selected.empty() || (Selected.size() && Selected[0]->Type->BoolFlag[BUILDING_INDEX].value)) {
	//Wyrmgus end
		return SelectAirUnitsInRectangle(corner_topleft, corner_bottomright);
	}

	const Vec2i t0 = Map.MapPixelPosToTilePos(corner_topleft, UI.CurrentMapLayer->ID);
	const Vec2i t1 = Map.MapPixelPosToTilePos(corner_bottomright, UI.CurrentMapLayer->ID);
	const Vec2i range(2, 2);
	std::vector<CUnit *> table;

	//Wyrmgus start
//	Select(t0 - range, t1 + range, table);
	Select(t0 - range, t1 + range, table, UI.CurrentMapLayer->ID);
	//Wyrmgus end
	SelectSpritesInsideRectangle(corner_topleft, corner_bottomright, table);
	unsigned int n = 0;
	for (size_t i = 0; i < table.size(); ++i) {
		CUnit &unit = *table[i];
		if (!CanSelectMultipleUnits(*unit.Player) ||
			!unit.Type->BoolFlag[SELECTABLEBYRECTANGLE_INDEX].value) {
			continue;
		}
		if (unit.IsUnusable()) {  // guess SelectUnits doesn't check this
			continue;
		}
		if (unit.Type->UnitType != UnitTypeFly) {
			continue;
		}
		if (unit.TeamSelected) { // Somebody else onteam has this unit
			continue;
		}
		//Wyrmgus start
		if (unit.Type->BoolFlag[BUILDING_INDEX].value) { //this selection mode is not for buildings
			continue;
		}
		//Wyrmgus end
		table[n++] = &unit;
		if (n == MaxSelectable) {
			break;
		}
	}

	// Add the units to selected.
	for (unsigned int i = 0; i < n && Selected.size() < MaxSelectable; ++i) {
		SelectUnit(*table[i]);
	}
	return Selected.size();
}