Skip to content

Commit 4d368c1

Browse files
committed
Merge pull request OpenRA#10213 from obrakmann/fix9851_prep-edition
[prep] Fix AttackMove not working properly under certain conditions
2 parents c504b2a + 71d4e29 commit 4d368c1

File tree

5 files changed

+58
-57
lines changed

5 files changed

+58
-57
lines changed

OpenRA.Game/Orders/GenericSelectTarget.cs

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,19 @@
1313

1414
namespace OpenRA.Orders
1515
{
16-
public class GenericSelectTarget : IOrderGenerator
16+
public class GenericSelectTarget : UnitOrderGenerator
1717
{
18-
readonly IEnumerable<Actor> subjects;
19-
readonly string order;
20-
readonly string cursor;
21-
readonly MouseButton expectedButton;
18+
protected readonly IEnumerable<Actor> Subjects;
19+
protected readonly string OrderName;
20+
protected readonly string Cursor;
21+
protected readonly MouseButton ExpectedButton;
2222

2323
public GenericSelectTarget(IEnumerable<Actor> subjects, string order, string cursor, MouseButton button)
2424
{
25-
this.subjects = subjects;
26-
this.order = order;
27-
this.cursor = cursor;
28-
expectedButton = button;
25+
Subjects = subjects;
26+
OrderName = order;
27+
Cursor = cursor;
28+
ExpectedButton = button;
2929
}
3030

3131
public GenericSelectTarget(IEnumerable<Actor> subjects, string order, string cursor)
@@ -37,26 +37,23 @@ public GenericSelectTarget(Actor subject, string order, string cursor)
3737
public GenericSelectTarget(Actor subject, string order, string cursor, MouseButton button)
3838
: this(new Actor[] { subject }, order, cursor, button) { }
3939

40-
public IEnumerable<Order> Order(World world, CPos xy, MouseInput mi)
40+
public override IEnumerable<Order> Order(World world, CPos xy, MouseInput mi)
4141
{
42-
if (mi.Button != expectedButton)
42+
if (mi.Button != ExpectedButton)
4343
world.CancelInputMode();
4444
return OrderInner(world, xy, mi);
4545
}
4646

47-
IEnumerable<Order> OrderInner(World world, CPos xy, MouseInput mi)
47+
protected virtual IEnumerable<Order> OrderInner(World world, CPos xy, MouseInput mi)
4848
{
49-
if (mi.Button == expectedButton && world.Map.Contains(xy))
49+
if (mi.Button == ExpectedButton && world.Map.Contains(xy))
5050
{
5151
world.CancelInputMode();
52-
foreach (var subject in subjects)
53-
yield return new Order(order, subject, false) { TargetLocation = xy };
52+
foreach (var subject in Subjects)
53+
yield return new Order(OrderName, subject, false) { TargetLocation = xy };
5454
}
5555
}
5656

57-
public virtual void Tick(World world) { }
58-
public IEnumerable<IRenderable> Render(WorldRenderer wr, World world) { yield break; }
59-
public IEnumerable<IRenderable> RenderAfterWorld(WorldRenderer wr, World world) { yield break; }
60-
public string GetCursor(World world, CPos xy, MouseInput mi) { return world.Map.Contains(xy) ? cursor : "generic-blocked"; }
57+
public override string GetCursor(World world, CPos xy, MouseInput mi) { return world.Map.Contains(xy) ? Cursor : "generic-blocked"; }
6158
}
6259
}

OpenRA.Game/Orders/UnitOrderGenerator.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@
1515

1616
namespace OpenRA.Orders
1717
{
18-
class UnitOrderGenerator : IOrderGenerator
18+
public class UnitOrderGenerator : IOrderGenerator
1919
{
20-
public IEnumerable<Order> Order(World world, CPos xy, MouseInput mi)
20+
public virtual IEnumerable<Order> Order(World world, CPos xy, MouseInput mi)
2121
{
2222
var underCursor = world.ScreenMap.ActorsAt(mi)
2323
.Where(a => !world.FogObscures(a) && a.Info.HasTraitInfo<ITargetableInfo>())
@@ -50,11 +50,11 @@ public IEnumerable<Order> Order(World world, CPos xy, MouseInput mi)
5050
yield return CheckSameOrder(o.Order, o.Trait.IssueOrder(o.Actor, o.Order, o.Target, mi.Modifiers.HasModifier(Modifiers.Shift)));
5151
}
5252

53-
public void Tick(World world) { }
54-
public IEnumerable<IRenderable> Render(WorldRenderer wr, World world) { yield break; }
55-
public IEnumerable<IRenderable> RenderAfterWorld(WorldRenderer wr, World world) { yield break; }
53+
public virtual void Tick(World world) { }
54+
public virtual IEnumerable<IRenderable> Render(WorldRenderer wr, World world) { yield break; }
55+
public virtual IEnumerable<IRenderable> RenderAfterWorld(WorldRenderer wr, World world) { yield break; }
5656

57-
public string GetCursor(World world, CPos xy, MouseInput mi)
57+
public virtual string GetCursor(World world, CPos xy, MouseInput mi)
5858
{
5959
var useSelect = false;
6060
var underCursor = world.ScreenMap.ActorsAt(mi)

OpenRA.Game/Widgets/WorldInteractionControllerWidget.cs

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -120,12 +120,26 @@ public override bool HandleMouseInput(MouseInput mi)
120120
}
121121
}
122122
}
123-
else if (dragStart.HasValue)
123+
else
124124
{
125-
// Select actors in the dragbox
126-
var newSelection = SelectActorsInBoxWithDeadzone(World, dragStart.Value, xy);
127-
World.Selection.Combine(World, newSelection, mi.Modifiers.HasModifier(Modifiers.Shift), dragStart == xy);
125+
/* The block below does three things:
126+
// 1. Allows actor selection using a selection box regardless of input mode.
127+
// 2. Allows actor deselection with a single click in the default input mode (UnitOrderGenerator).
128+
// 3. Prevents units from getting deselected when exiting input modes (eg. AttackMove or Guard).
129+
//
130+
// We cannot check for UnitOrderGenerator here since it's the default order generator that gets activated in
131+
// World.CancelInputMode. If we did check it, actor de-selection would not be possible by just clicking somewhere,
132+
// only by dragging an empty selection box.
133+
*/
134+
if (dragStart.HasValue && (!(World.OrderGenerator is GenericSelectTarget) || hasBox))
135+
{
136+
// Select actors in the dragbox
137+
var newSelection = SelectActorsInBoxWithDeadzone(World, dragStart.Value, xy);
138+
World.Selection.Combine(World, newSelection, mi.Modifiers.HasModifier(Modifiers.Shift), dragStart == xy);
139+
}
128140
}
141+
142+
World.CancelInputMode();
129143
}
130144

131145
dragStart = dragEnd = null;

OpenRA.Mods.Common/Traits/Guard.cs

Lines changed: 16 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
using OpenRA.Graphics;
1515
using OpenRA.Mods.Common;
1616
using OpenRA.Mods.Common.Activities;
17+
using OpenRA.Orders;
1718
using OpenRA.Traits;
1819

1920
namespace OpenRA.Mods.Common.Traits
@@ -59,52 +60,40 @@ public string VoicePhraseForOrder(Actor self, Order order)
5960
}
6061
}
6162

62-
public class GuardOrderGenerator : IOrderGenerator
63+
public class GuardOrderGenerator : GenericSelectTarget
6364
{
64-
readonly IEnumerable<Actor> subjects;
65+
public GuardOrderGenerator(IEnumerable<Actor> subjects, string order, string cursor, MouseButton button)
66+
: base(subjects, order, cursor, button) { }
6567

66-
public GuardOrderGenerator(IEnumerable<Actor> subjects)
68+
protected override IEnumerable<Order> OrderInner(World world, CPos xy, MouseInput mi)
6769
{
68-
this.subjects = subjects;
69-
}
70-
71-
public IEnumerable<Order> Order(World world, CPos xy, MouseInput mi)
72-
{
73-
if (mi.Button == Game.Settings.Game.MouseButtonPreference.Cancel)
74-
{
75-
world.CancelInputMode();
76-
yield break;
77-
}
78-
7970
var target = FriendlyGuardableUnits(world, mi).FirstOrDefault();
8071

81-
if (target == null || subjects.All(s => s.IsDead))
72+
if (target == null || Subjects.All(s => s.IsDead))
8273
yield break;
8374

84-
foreach (var subject in subjects)
75+
world.CancelInputMode();
76+
foreach (var subject in Subjects)
8577
if (subject != target)
86-
yield return new Order("Guard", subject, false) { TargetActor = target };
78+
yield return new Order(OrderName, subject, false) { TargetActor = target };
8779
}
8880

89-
public void Tick(World world)
81+
public override void Tick(World world)
9082
{
91-
if (subjects.All(s => s.IsDead || !s.Info.HasTraitInfo<GuardInfo>()))
83+
if (Subjects.All(s => s.IsDead || !s.Info.HasTraitInfo<GuardInfo>()))
9284
world.CancelInputMode();
9385
}
9486

95-
public IEnumerable<IRenderable> Render(WorldRenderer wr, World world) { yield break; }
96-
public IEnumerable<IRenderable> RenderAfterWorld(WorldRenderer wr, World world) { yield break; }
97-
98-
public string GetCursor(World world, CPos xy, MouseInput mi)
87+
public override string GetCursor(World world, CPos xy, MouseInput mi)
9988
{
100-
if (!subjects.Any())
89+
if (!Subjects.Any())
10190
return null;
10291

103-
var multiple = subjects.Count() > 1;
92+
var multiple = Subjects.Count() > 1;
10493
var canGuard = FriendlyGuardableUnits(world, mi)
105-
.Any(a => multiple || a != subjects.First());
94+
.Any(a => multiple || a != Subjects.First());
10695

107-
return canGuard ? "guard" : "move-blocked";
96+
return canGuard ? Cursor : "move-blocked";
10897
}
10998

11099
static IEnumerable<Actor> FriendlyGuardableUnits(World world, MouseInput mi)

OpenRA.Mods.Common/Widgets/WorldCommandWidget.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,8 @@ bool PerformGuard()
184184
.Where(a => !a.Disposed && a.Owner == world.LocalPlayer && a.Info.HasTraitInfo<GuardInfo>());
185185

186186
if (actors.Any())
187-
world.OrderGenerator = new GuardOrderGenerator(actors);
187+
world.OrderGenerator = new GuardOrderGenerator(actors,
188+
"Guard", "guard", Game.Settings.Game.MouseButtonPreference.Action);
188189

189190
return true;
190191
}

0 commit comments

Comments
 (0)