From 017eca3dc183ea0d365606c88e73b662fec91135 Mon Sep 17 00:00:00 2001 From: Ivaylo Draganov Date: Mon, 1 Jul 2019 23:49:33 +0300 Subject: [PATCH] Add support for "select all" and "select by type" for multiple players --- OpenRA.Game/SelectableExts.cs | 6 +-- .../WorldInteractionControllerWidget.cs | 50 ++++++++++++------- 2 files changed, 36 insertions(+), 20 deletions(-) diff --git a/OpenRA.Game/SelectableExts.cs b/OpenRA.Game/SelectableExts.cs index 3fb7242078..c1128f4430 100644 --- a/OpenRA.Game/SelectableExts.cs +++ b/OpenRA.Game/SelectableExts.cs @@ -31,12 +31,12 @@ namespace OpenRA.Traits var info = a.Info.TraitInfo(); var basePriority = BaseSelectionPriority(info, modifiers); - var lp = a.World.LocalPlayer; + var viewer = (a.World.LocalPlayer == null || a.World.LocalPlayer.Spectating) ? a.World.RenderPlayer : a.World.LocalPlayer; - if (a.Owner == lp || lp == null) + if (a.Owner == viewer || viewer == null) return basePriority; - switch (lp.Stances[a.Owner]) + switch (viewer.Stances[a.Owner]) { case Stance.Ally: return basePriority - PriorityRange; case Stance.Neutral: return basePriority - 2 * PriorityRange; diff --git a/OpenRA.Mods.Common/Widgets/WorldInteractionControllerWidget.cs b/OpenRA.Mods.Common/Widgets/WorldInteractionControllerWidget.cs index 9060fad289..1556aaae82 100644 --- a/OpenRA.Mods.Common/Widgets/WorldInteractionControllerWidget.cs +++ b/OpenRA.Mods.Common/Widgets/WorldInteractionControllerWidget.cs @@ -128,13 +128,19 @@ namespace OpenRA.Mods.Common.Widgets var unit = World.ScreenMap.ActorsAtMouse(mousePos) .WithHighestSelectionPriority(mousePos, mi.Modifiers); - if (unit != null && unit.Owner == (World.RenderPlayer ?? World.LocalPlayer)) + // Players to be included in the selection (the viewer or all players in "Disable shroud" / "All players" mode) + var viewer = World.RenderPlayer ?? World.LocalPlayer; + var isShroudDisabled = viewer == null || (World.RenderPlayer == null && World.LocalPlayer.Spectating); + var isEveryone = viewer != null && viewer.NonCombatant && viewer.Spectating; + var eligiblePlayers = isShroudDisabled || isEveryone ? World.Players : new[] { viewer }; + + if (unit != null && eligiblePlayers.Contains(unit.Owner)) { var s = unit.TraitOrDefault(); 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 { s.Class }, unit.Owner); + var newSelection = SelectActorsOnScreen(World, worldRenderer, new HashSet { s.Class }, eligiblePlayers); World.Selection.Combine(World, newSelection, true, false); } @@ -245,14 +251,18 @@ namespace OpenRA.Mods.Common.Widgets public override bool HandleKeyPress(KeyInput e) { - var player = World.RenderPlayer ?? World.LocalPlayer; - if (e.Event == KeyInputEvent.Down) { + // Players to be included in the selection (the viewer or all players in "Disable shroud" / "All players" mode) + var viewer = World.RenderPlayer ?? World.LocalPlayer; + var isShroudDisabled = viewer == null || (World.RenderPlayer == null && World.LocalPlayer.Spectating); + var isEveryone = viewer != null && viewer.NonCombatant && viewer.Spectating; + var eligiblePlayers = isShroudDisabled || isEveryone ? World.Players : new[] { viewer }; + 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(e.Modifiers).ToList(); + // Select actors on the screen which belong to the current player(s) + var ownUnitsOnScreen = SelectActorsOnScreen(World, worldRenderer, null, eligiblePlayers).SubsetWithHighestSelectionPriority(e.Modifiers).ToList(); // Check if selecting actors on the screen has selected new units if (ownUnitsOnScreen.Count > World.Selection.Actors.Count()) @@ -260,7 +270,7 @@ namespace OpenRA.Mods.Common.Widgets else { // Select actors in the world that have highest selection priority - ownUnitsOnScreen = SelectActorsInWorld(World, null, player).SubsetWithHighestSelectionPriority(e.Modifiers).ToList(); + ownUnitsOnScreen = SelectActorsInWorld(World, null, eligiblePlayers).SubsetWithHighestSelectionPriority(e.Modifiers).ToList(); Game.AddSystemLine("Battlefield Control", "Selected across map"); } @@ -271,14 +281,20 @@ namespace OpenRA.Mods.Common.Widgets if (!World.Selection.Actors.Any()) return false; + var ownedActors = World.Selection.Actors + .Where(x => !x.IsDead && eligiblePlayers.Contains(x.Owner)) + .ToList(); + + if (!ownedActors.Any()) + return false; + // Get all the selected actors' selection classes - var selectedClasses = World.Selection.Actors - .Where(x => !x.IsDead && x.Owner == player) + var selectedClasses = ownedActors .Select(a => a.Trait().Class) .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, player).ToList(); + var newSelection = SelectActorsOnScreen(World, worldRenderer, selectedClasses, eligiblePlayers).ToList(); // Check if selecting actors on the screen has selected new units if (newSelection.Count > World.Selection.Actors.Count()) @@ -286,7 +302,7 @@ namespace OpenRA.Mods.Common.Widgets else { // Select actors in the world that have the same selection class as one of the already selected actors - newSelection = SelectActorsInWorld(World, selectedClasses, player).ToList(); + newSelection = SelectActorsInWorld(World, selectedClasses, eligiblePlayers).ToList(); Game.AddSystemLine("Battlefield Control", "Selected across map"); } @@ -297,22 +313,22 @@ namespace OpenRA.Mods.Common.Widgets return false; } - static IEnumerable SelectActorsOnScreen(World world, WorldRenderer wr, IEnumerable selectionClasses, Player player) + static IEnumerable SelectActorsOnScreen(World world, WorldRenderer wr, IEnumerable selectionClasses, IEnumerable 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 SelectActorsInWorld(World world, IEnumerable selectionClasses, Player player) + static IEnumerable SelectActorsInWorld(World world, IEnumerable selectionClasses, IEnumerable players) { - return SelectActorsByOwnerAndSelectionClass(world.Actors.Where(a => a.IsInWorld), player, selectionClasses); + return SelectActorsByOwnerAndSelectionClass(world.Actors.Where(a => a.IsInWorld), players, selectionClasses); } - static IEnumerable SelectActorsByOwnerAndSelectionClass(IEnumerable actors, Player owner, IEnumerable selectionClasses) + static IEnumerable SelectActorsByOwnerAndSelectionClass(IEnumerable actors, IEnumerable owners, IEnumerable selectionClasses) { return actors.Where(a => { - if (a.Owner != owner) + if (!owners.Contains(a.Owner)) return false; var s = a.TraitOrDefault();