/** ** 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; } } } }
/** ** 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(); }
/** ** 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; } } } }
/** ** 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(); }
/** ** Unselect all currently selected units. */ static void UiUnselectAll() { UnSelectAll(); NetworkSendSelection((CUnit **)NULL, 0); SelectionChanged(); }