Merge pull request #10182 from obrakmann/fix9851-attackmove-click-madness

Fix AttackMove not working properly under certain conditions
This commit is contained in:
abcdefg30
2015-12-13 16:06:51 +01:00
5 changed files with 57 additions and 57 deletions

View File

@@ -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"; }
}
}

View File

@@ -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);

View File

@@ -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;

View File

@@ -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)

View File

@@ -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;
}