예제 #1
0
/**
**  Replace a group of selected units by an other group of units.
**
**  @param units  Array of units to be selected.
**  @param count  Number of units in array to be selected.
*/
static void ChangeSelectedUnits(CUnit **units, unsigned int count)
{
	Assert(count <= MaxSelectable);

	if (count == 1 && units[0]->Type->ClicksToExplode &&
		!units[0]->Type->IsNotSelectable) {
		HandleSuicideClick(*units[0]);
		if (!units[0]->IsAlive()) {
			NetworkSendSelection(units, count);
			return ;
		}
	}
	UnSelectAll();
	NetworkSendSelection(units, count);
	for (unsigned int i = 0; i < count; ++i) {
		CUnit &unit = *units[i];
		if (!unit.Removed && !unit.TeamSelected && !unit.Type->IsNotSelectable) {
			Selected.push_back(&unit);
			unit.Selected = 1;
			if (count > 1) {
				unit.LastGroup = GroupId;
			}
		}
	}
}
예제 #2
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();
}
예제 #3
0
/**
**  Replace a group of selected units by an other group of units.
**
**  @param units  Array of units to be selected.
**  @param count  Number of units in array to be selected.
*/
static void ChangeSelectedUnits(CUnit **units, unsigned int count)
{
	Assert(count <= MaxSelectable);

	if (count == 1 && units[0]->Type->ClicksToExplode &&
		!units[0]->Type->BoolFlag[ISNOTSELECTABLE_INDEX].value) {
		HandleSuicideClick(*units[0]);
		if (!units[0]->IsAlive()) {
			NetworkSendSelection(units, count);
			return ;
		}
	}
	//Wyrmgus start
	bool suitable_selectee = false;
	for (unsigned int i = 0; i < count; ++i) {
		CUnit &unit = *units[i];
		if (!unit.Removed && !unit.TeamSelected && !unit.Type->BoolFlag[ISNOTSELECTABLE_INDEX].value && unit.IsAlive()) {
			suitable_selectee = true;
		}
	}
	if (!suitable_selectee) {
		return;
	}
	//Wyrmgus end
	UnSelectAll();
	NetworkSendSelection(units, count);
	for (unsigned int i = 0; i < count; ++i) {
		CUnit &unit = *units[i];
		if (!unit.Removed && !unit.TeamSelected && !unit.Type->BoolFlag[ISNOTSELECTABLE_INDEX].value && unit.IsAlive()) {
			Selected.push_back(&unit);
			unit.Selected = 1;
			if (count > 1) {
				unit.LastGroup = GroupId;
			}
		}
	}
}
예제 #4
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();
}
예제 #5
0
/**
**  Unselect all currently selected units.
*/
static void UiUnselectAll()
{
	UnSelectAll();
	NetworkSendSelection((CUnit **)NULL, 0);
	SelectionChanged();
}