Merge pull request #10182 from obrakmann/fix9851-attackmove-click-madness
Fix AttackMove not working properly under certain conditions
This commit is contained in:
@@ -13,19 +13,19 @@ using OpenRA.Graphics;
|
||||
|
||||
namespace OpenRA.Orders
|
||||
{
|
||||
public class GenericSelectTarget : IOrderGenerator
|
||||
public class GenericSelectTarget : UnitOrderGenerator
|
||||
{
|
||||
readonly IEnumerable<Actor> subjects;
|
||||
readonly string order;
|
||||
readonly string cursor;
|
||||
readonly MouseButton expectedButton;
|
||||
protected readonly IEnumerable<Actor> Subjects;
|
||||
protected readonly string OrderName;
|
||||
protected readonly string Cursor;
|
||||
protected readonly MouseButton ExpectedButton;
|
||||
|
||||
public GenericSelectTarget(IEnumerable<Actor> subjects, string order, string cursor, MouseButton button)
|
||||
{
|
||||
this.subjects = subjects;
|
||||
this.order = order;
|
||||
this.cursor = cursor;
|
||||
expectedButton = button;
|
||||
Subjects = subjects;
|
||||
OrderName = order;
|
||||
Cursor = cursor;
|
||||
ExpectedButton = button;
|
||||
}
|
||||
|
||||
public GenericSelectTarget(IEnumerable<Actor> subjects, string order, string cursor)
|
||||
@@ -37,26 +37,23 @@ namespace OpenRA.Orders
|
||||
public GenericSelectTarget(Actor subject, string order, string cursor, MouseButton button)
|
||||
: this(new Actor[] { subject }, order, cursor, button) { }
|
||||
|
||||
public IEnumerable<Order> Order(World world, CPos xy, MouseInput mi)
|
||||
public override IEnumerable<Order> Order(World world, CPos xy, MouseInput mi)
|
||||
{
|
||||
if (mi.Button != expectedButton)
|
||||
if (mi.Button != ExpectedButton)
|
||||
world.CancelInputMode();
|
||||
return OrderInner(world, xy, mi);
|
||||
}
|
||||
|
||||
IEnumerable<Order> OrderInner(World world, CPos xy, MouseInput mi)
|
||||
protected virtual IEnumerable<Order> OrderInner(World world, CPos xy, MouseInput mi)
|
||||
{
|
||||
if (mi.Button == expectedButton && world.Map.Contains(xy))
|
||||
if (mi.Button == ExpectedButton && world.Map.Contains(xy))
|
||||
{
|
||||
world.CancelInputMode();
|
||||
foreach (var subject in subjects)
|
||||
yield return new Order(order, subject, false) { TargetLocation = xy };
|
||||
foreach (var subject in Subjects)
|
||||
yield return new Order(OrderName, subject, false) { TargetLocation = xy };
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void Tick(World world) { }
|
||||
public IEnumerable<IRenderable> Render(WorldRenderer wr, World world) { yield break; }
|
||||
public IEnumerable<IRenderable> RenderAfterWorld(WorldRenderer wr, World world) { yield break; }
|
||||
public string GetCursor(World world, CPos xy, MouseInput mi) { return world.Map.Contains(xy) ? cursor : "generic-blocked"; }
|
||||
public override string GetCursor(World world, CPos xy, MouseInput mi) { return world.Map.Contains(xy) ? Cursor : "generic-blocked"; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Orders
|
||||
{
|
||||
class UnitOrderGenerator : IOrderGenerator
|
||||
public class UnitOrderGenerator : IOrderGenerator
|
||||
{
|
||||
static Target TargetForInput(World world, CPos xy, MouseInput mi)
|
||||
{
|
||||
@@ -36,7 +36,7 @@ namespace OpenRA.Orders
|
||||
return Target.FromCell(world, xy);
|
||||
}
|
||||
|
||||
public IEnumerable<Order> Order(World world, CPos xy, MouseInput mi)
|
||||
public virtual IEnumerable<Order> Order(World world, CPos xy, MouseInput mi)
|
||||
{
|
||||
var target = TargetForInput(world, xy, mi);
|
||||
var actorsAt = world.ActorMap.GetActorsAt(xy).ToList();
|
||||
@@ -58,11 +58,11 @@ namespace OpenRA.Orders
|
||||
yield return CheckSameOrder(o.Order, o.Trait.IssueOrder(o.Actor, o.Order, o.Target, mi.Modifiers.HasModifier(Modifiers.Shift)));
|
||||
}
|
||||
|
||||
public void Tick(World world) { }
|
||||
public IEnumerable<IRenderable> Render(WorldRenderer wr, World world) { yield break; }
|
||||
public IEnumerable<IRenderable> RenderAfterWorld(WorldRenderer wr, World world) { yield break; }
|
||||
public virtual void Tick(World world) { }
|
||||
public virtual IEnumerable<IRenderable> Render(WorldRenderer wr, World world) { yield break; }
|
||||
public virtual IEnumerable<IRenderable> RenderAfterWorld(WorldRenderer wr, World world) { yield break; }
|
||||
|
||||
public string GetCursor(World world, CPos xy, MouseInput mi)
|
||||
public virtual string GetCursor(World world, CPos xy, MouseInput mi)
|
||||
{
|
||||
var useSelect = false;
|
||||
var target = TargetForInput(world, xy, mi);
|
||||
|
||||
@@ -120,12 +120,25 @@ namespace OpenRA.Widgets
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (dragStart.HasValue)
|
||||
else
|
||||
{
|
||||
// Select actors in the dragbox
|
||||
var newSelection = SelectActorsInBoxWithDeadzone(World, dragStart.Value, xy);
|
||||
World.Selection.Combine(World, newSelection, mi.Modifiers.HasModifier(Modifiers.Shift), dragStart == xy);
|
||||
/* The block below does three things:
|
||||
// 1. Allows actor selection using a selection box regardless of input mode.
|
||||
// 2. Allows actor deselection with a single click in the default input mode (UnitOrderGenerator).
|
||||
// 3. Prevents units from getting deselected when exiting input modes (eg. AttackMove or Guard).
|
||||
//
|
||||
// We cannot check for UnitOrderGenerator here since it's the default order generator that gets activated in
|
||||
// World.CancelInputMode. If we did check it, actor de-selection would not be possible by just clicking somewhere,
|
||||
// only by dragging an empty selection box.
|
||||
*/
|
||||
if (dragStart.HasValue && (!(World.OrderGenerator is GenericSelectTarget) || hasBox))
|
||||
{
|
||||
var newSelection = SelectActorsInBoxWithDeadzone(World, dragStart.Value, xy);
|
||||
World.Selection.Combine(World, newSelection, mi.Modifiers.HasModifier(Modifiers.Shift), dragStart == xy);
|
||||
}
|
||||
}
|
||||
|
||||
World.CancelInputMode();
|
||||
}
|
||||
|
||||
dragStart = dragEnd = null;
|
||||
|
||||
@@ -14,6 +14,7 @@ using System.Linq;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Mods.Common;
|
||||
using OpenRA.Mods.Common.Activities;
|
||||
using OpenRA.Orders;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.Common.Traits
|
||||
@@ -59,52 +60,40 @@ namespace OpenRA.Mods.Common.Traits
|
||||
}
|
||||
}
|
||||
|
||||
public class GuardOrderGenerator : IOrderGenerator
|
||||
public class GuardOrderGenerator : GenericSelectTarget
|
||||
{
|
||||
readonly IEnumerable<Actor> subjects;
|
||||
public GuardOrderGenerator(IEnumerable<Actor> subjects, string order, string cursor, MouseButton button)
|
||||
: base(subjects, order, cursor, button) { }
|
||||
|
||||
public GuardOrderGenerator(IEnumerable<Actor> subjects)
|
||||
protected override IEnumerable<Order> OrderInner(World world, CPos xy, MouseInput mi)
|
||||
{
|
||||
this.subjects = subjects;
|
||||
}
|
||||
|
||||
public IEnumerable<Order> Order(World world, CPos xy, MouseInput mi)
|
||||
{
|
||||
if (mi.Button == Game.Settings.Game.MouseButtonPreference.Cancel)
|
||||
{
|
||||
world.CancelInputMode();
|
||||
yield break;
|
||||
}
|
||||
|
||||
var target = FriendlyGuardableUnits(world, mi).FirstOrDefault();
|
||||
|
||||
if (target == null || subjects.All(s => s.IsDead))
|
||||
if (target == null || Subjects.All(s => s.IsDead))
|
||||
yield break;
|
||||
|
||||
foreach (var subject in subjects)
|
||||
world.CancelInputMode();
|
||||
foreach (var subject in Subjects)
|
||||
if (subject != target)
|
||||
yield return new Order("Guard", subject, false) { TargetActor = target };
|
||||
yield return new Order(OrderName, subject, false) { TargetActor = target };
|
||||
}
|
||||
|
||||
public void Tick(World world)
|
||||
public override void Tick(World world)
|
||||
{
|
||||
if (subjects.All(s => s.IsDead || !s.Info.HasTraitInfo<GuardInfo>()))
|
||||
if (Subjects.All(s => s.IsDead || !s.Info.HasTraitInfo<GuardInfo>()))
|
||||
world.CancelInputMode();
|
||||
}
|
||||
|
||||
public IEnumerable<IRenderable> Render(WorldRenderer wr, World world) { yield break; }
|
||||
public IEnumerable<IRenderable> RenderAfterWorld(WorldRenderer wr, World world) { yield break; }
|
||||
|
||||
public string GetCursor(World world, CPos xy, MouseInput mi)
|
||||
public override string GetCursor(World world, CPos xy, MouseInput mi)
|
||||
{
|
||||
if (!subjects.Any())
|
||||
if (!Subjects.Any())
|
||||
return null;
|
||||
|
||||
var multiple = subjects.Count() > 1;
|
||||
var multiple = Subjects.Count() > 1;
|
||||
var canGuard = FriendlyGuardableUnits(world, mi)
|
||||
.Any(a => multiple || a != subjects.First());
|
||||
.Any(a => multiple || a != Subjects.First());
|
||||
|
||||
return canGuard ? "guard" : "move-blocked";
|
||||
return canGuard ? Cursor : "move-blocked";
|
||||
}
|
||||
|
||||
static IEnumerable<Actor> FriendlyGuardableUnits(World world, MouseInput mi)
|
||||
|
||||
@@ -184,7 +184,8 @@ namespace OpenRA.Mods.Common.Widgets
|
||||
.Where(a => !a.Disposed && a.Owner == world.LocalPlayer && a.Info.HasTraitInfo<GuardInfo>());
|
||||
|
||||
if (actors.Any())
|
||||
world.OrderGenerator = new GuardOrderGenerator(actors);
|
||||
world.OrderGenerator = new GuardOrderGenerator(actors,
|
||||
"Guard", "guard", Game.Settings.Game.MouseButtonPreference.Action);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user