Skip to content

Commit

Permalink
Add support for "select all" and "select by type" for multiple players
Browse files Browse the repository at this point in the history
  • Loading branch information
dragunoff committed Nov 27, 2018
1 parent 59c317b commit 89a2201
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 22 deletions.
2 changes: 1 addition & 1 deletion OpenRA.Game/SelectableExts.cs
Expand Up @@ -31,7 +31,7 @@ public static int SelectionPriority(this ActorInfo a)
public static int SelectionPriority(this Actor a)
{
var basePriority = a.Info.TraitInfo<SelectableInfo>().Priority;
var lp = a.World.LocalPlayer;
var lp = a.World.RenderPlayer;

if (a.Owner == lp || lp == null)
return basePriority;
Expand Down
41 changes: 20 additions & 21 deletions OpenRA.Mods.Common/Widgets/WorldInteractionControllerWidget.cs
Expand Up @@ -130,13 +130,13 @@ public override bool HandleMouseInput(MouseInput mi)
var unit = World.ScreenMap.ActorsAtMouse(mousePos)
.WithHighestSelectionPriority(mousePos);

if (unit != null && unit.Owner.IsAlliedWith(World.RenderPlayer ?? World.LocalPlayer))
if (unit != null && unit.Owner.IsAlliedWith(World.RenderPlayer))
{
var s = unit.TraitOrDefault<Selectable>();
if (s != null)
{
// Select actors on the screen that have the same selection class as the actor under the mouse cursor
var newSelection = SelectActorsOnScreen(World, worldRenderer, new HashSet<string> { s.Class }, unit.Owner);
var newSelection = SelectActorsOnScreen(World, worldRenderer, new HashSet<string> { s.Class }, World.Players.Where(p => p == unit.Owner));

World.Selection.Combine(World, newSelection, true, false);
}
Expand Down Expand Up @@ -247,22 +247,23 @@ public override string GetCursor(int2 screenPos)

public override bool HandleKeyPress(KeyInput e)
{
var player = World.RenderPlayer ?? World.LocalPlayer;
var localPlayer = World.RenderPlayer;
var eligiblePlayers = localPlayer == null || localPlayer.NonCombatant && localPlayer.Spectating ? World.Players : World.Players.Where(p => p == localPlayer);

if (e.Event == KeyInputEvent.Down)
{
if (SelectAllKey.IsActivatedBy(e) && !World.IsGameOver)
{
// Select actors on the screen which belong to the current player
var ownUnitsOnScreen = SelectActorsOnScreen(World, worldRenderer, null, player).SubsetWithHighestSelectionPriority().ToList();
// Select actors on the screen which belong to the current player(s)
var ownUnitsOnScreen = SelectActorsOnScreen(World, worldRenderer, null, eligiblePlayers).SubsetWithHighestSelectionPriority().ToList();

// Check if selecting actors on the screen has selected new units
if (ownUnitsOnScreen.Count > World.Selection.Actors.Count())
Game.AddChatLine(Color.White, "Battlefield Control", "Selected across screen");
else
{
// Select actors in the world that have highest selection priority
ownUnitsOnScreen = SelectActorsInWorld(World, null, player).SubsetWithHighestSelectionPriority().ToList();
ownUnitsOnScreen = SelectActorsInWorld(World, null, eligiblePlayers).SubsetWithHighestSelectionPriority().ToList();
Game.AddChatLine(Color.White, "Battlefield Control", "Selected across map");
}

Expand All @@ -276,18 +277,16 @@ public override bool HandleKeyPress(KeyInput e)
var selectedActors = World.Selection.Actors
.Where(x => !x.IsDead);

var actorOwners = selectedActors
var owners = selectedActors
.Select(a => a.Owner)
.ToList()
.Distinct();
.Distinct()
.Where(o => o.IsAlliedWith(localPlayer));

// Selection code works only for a single owner so prioritize local player
var owner = actorOwners.Count() > 1 ? player : actorOwners.First();

if (owner == null || !owner.IsAlliedWith(player))
if (!owners.Any())
return false;

var ownedActors = selectedActors.Where(x => x.Owner == owner);
var ownedActors = selectedActors.Where(x => owners.Contains(x.Owner));

if (!ownedActors.Any())
return false;
Expand All @@ -298,15 +297,15 @@ public override bool HandleKeyPress(KeyInput e)
.ToHashSet();

// Select actors on the screen that have the same selection class as one of the already selected actors
var newSelection = SelectActorsOnScreen(World, worldRenderer, selectedClasses, owner).ToList();
var newSelection = SelectActorsOnScreen(World, worldRenderer, selectedClasses, owners).ToList();

// Check if selecting actors on the screen has selected new units
if (newSelection.Count > World.Selection.Actors.Count())
Game.AddChatLine(Color.White, "Battlefield Control", "Selected across screen");
else
{
// Select actors in the world that have the same selection class as one of the already selected actors
newSelection = SelectActorsInWorld(World, selectedClasses, owner).ToList();
newSelection = SelectActorsInWorld(World, selectedClasses, owners).ToList();
Game.AddChatLine(Color.White, "Battlefield Control", "Selected across map");
}

Expand All @@ -317,22 +316,22 @@ public override bool HandleKeyPress(KeyInput e)
return false;
}

static IEnumerable<Actor> SelectActorsOnScreen(World world, WorldRenderer wr, IEnumerable<string> selectionClasses, Player player)
static IEnumerable<Actor> SelectActorsOnScreen(World world, WorldRenderer wr, IEnumerable<string> selectionClasses, IEnumerable<Player> players)
{
var actors = world.ScreenMap.ActorsInMouseBox(wr.Viewport.TopLeft, wr.Viewport.BottomRight).Select(a => a.Actor);
return SelectActorsByOwnerAndSelectionClass(actors, player, selectionClasses);
return SelectActorsByOwnerAndSelectionClass(actors, players, selectionClasses);
}

static IEnumerable<Actor> SelectActorsInWorld(World world, IEnumerable<string> selectionClasses, Player player)
static IEnumerable<Actor> SelectActorsInWorld(World world, IEnumerable<string> selectionClasses, IEnumerable<Player> players)
{
return SelectActorsByOwnerAndSelectionClass(world.Actors.Where(a => a.IsInWorld), player, selectionClasses);
return SelectActorsByOwnerAndSelectionClass(world.Actors.Where(a => a.IsInWorld), players, selectionClasses);
}

static IEnumerable<Actor> SelectActorsByOwnerAndSelectionClass(IEnumerable<Actor> actors, Player owner, IEnumerable<string> selectionClasses)
static IEnumerable<Actor> SelectActorsByOwnerAndSelectionClass(IEnumerable<Actor> actors, IEnumerable<Player> owners, IEnumerable<string> selectionClasses)
{
return actors.Where(a =>
{
if (a.Owner != owner)
if (!owners.Contains(a.Owner))
return false;
var s = a.TraitOrDefault<Selectable>();
Expand Down

0 comments on commit 89a2201

Please sign in to comment.