diff --git a/OpenRA.Game/Orders/UnitOrderGenerator.cs b/OpenRA.Game/Orders/UnitOrderGenerator.cs index 75d5fe3391..d3344ce9af 100644 --- a/OpenRA.Game/Orders/UnitOrderGenerator.cs +++ b/OpenRA.Game/Orders/UnitOrderGenerator.cs @@ -87,13 +87,19 @@ namespace OpenRA.Orders { var actorsAt = self.World.ActorMap.GetUnitsAt(xy).ToList(); - var forceAttack = mi.Modifiers.HasModifier(Modifiers.Ctrl); - var forceQueue = mi.Modifiers.HasModifier(Modifiers.Shift); + var modifiers = TargetModifiers.None; + if (mi.Modifiers.HasModifier(Modifiers.Ctrl)) + modifiers |= TargetModifiers.ForceAttack; + if (mi.Modifiers.HasModifier(Modifiers.Shift)) + modifiers |= TargetModifiers.ForceQueue; + if (mi.Modifiers.HasModifier(Modifiers.Alt)) + modifiers |= TargetModifiers.ForceMove; + string cursor = null; if (underCursor != null) - if (o.Order.CanTargetActor(self, underCursor, forceAttack, forceQueue, ref cursor)) + if (o.Order.CanTargetActor(self, underCursor, modifiers, ref cursor)) return new UnitOrderResult(self, o.Order, o.Trait, cursor, Target.FromActor(underCursor)); - if (o.Order.CanTargetLocation(self, xy, actorsAt, forceAttack, forceQueue, ref cursor)) + if (o.Order.CanTargetLocation(self, xy, actorsAt, modifiers, ref cursor)) return new UnitOrderResult(self, o.Order, o.Trait, cursor, Target.FromCell(xy)); } } diff --git a/OpenRA.Game/Traits/TraitsInterfaces.cs b/OpenRA.Game/Traits/TraitsInterfaces.cs index 30d6c152d2..f6b3d25f31 100755 --- a/OpenRA.Game/Traits/TraitsInterfaces.cs +++ b/OpenRA.Game/Traits/TraitsInterfaces.cs @@ -44,12 +44,19 @@ namespace OpenRA.Traits Order IssueOrder(Actor self, IOrderTargeter order, Target target, bool queued); } + [Flags] public enum TargetModifiers { None = 0, ForceAttack = 1, ForceQueue = 2, ForceMove = 4 }; + + public static class TargetModifiersExts + { + public static bool HasModifier(this TargetModifiers self, TargetModifiers m) { return (self & m) == m; } + } + public interface IOrderTargeter { string OrderID { get; } int OrderPriority { get; } - bool CanTargetActor(Actor self, Actor target, bool forceAttack, bool forceQueue, ref string cursor); - bool CanTargetLocation(Actor self, CPos location, List actorsAtLocation, bool forceAttack, bool forceQueue, ref string cursor); + bool CanTargetActor(Actor self, Actor target, TargetModifiers modifiers, ref string cursor); + bool CanTargetLocation(Actor self, CPos location, List actorsAtLocation, TargetModifiers modifiers, ref string cursor); bool IsQueued { get; } } diff --git a/OpenRA.Mods.RA/Air/Aircraft.cs b/OpenRA.Mods.RA/Air/Aircraft.cs index 4cb41ce53c..16d48d66f3 100755 --- a/OpenRA.Mods.RA/Air/Aircraft.cs +++ b/OpenRA.Mods.RA/Air/Aircraft.cs @@ -217,14 +217,14 @@ namespace OpenRA.Mods.RA.Air public string OrderID { get { return "Move"; } } public int OrderPriority { get { return 4; } } - public bool CanTargetActor(Actor self, Actor target, bool forceAttack, bool forceQueued, ref string cursor) + public bool CanTargetActor(Actor self, Actor target, TargetModifiers modifiers, ref string cursor) { return false; } - public bool CanTargetLocation(Actor self, CPos location, List actorsAtLocation, bool forceAttack, bool forceQueued, ref string cursor) + public bool CanTargetLocation(Actor self, CPos location, List actorsAtLocation, TargetModifiers modifiers, ref string cursor) { - IsQueued = forceQueued; + IsQueued = modifiers.HasModifier(TargetModifiers.ForceQueue); cursor = self.World.Map.IsInMap(location) ? "move" : "move-blocked"; return true; } diff --git a/OpenRA.Mods.RA/Attack/AttackBase.cs b/OpenRA.Mods.RA/Attack/AttackBase.cs index e85fc8aa5c..a3bd02a1f9 100644 --- a/OpenRA.Mods.RA/Attack/AttackBase.cs +++ b/OpenRA.Mods.RA/Attack/AttackBase.cs @@ -169,9 +169,9 @@ namespace OpenRA.Mods.RA public string OrderID { get; private set; } public int OrderPriority { get; private set; } - public bool CanTargetActor(Actor self, Actor target, bool forceAttack, bool forceQueued, ref string cursor) + public bool CanTargetActor(Actor self, Actor target, TargetModifiers modifiers, ref string cursor) { - IsQueued = forceQueued; + IsQueued = modifiers.HasModifier(TargetModifiers.ForceQueue); cursor = self.Info.Traits.Get().Cursor; @@ -181,20 +181,23 @@ namespace OpenRA.Mods.RA if (!self.Trait().HasAnyValidWeapons(Target.FromActor(target))) return false; - if (forceAttack) + if (modifiers.HasModifier(TargetModifiers.ForceAttack)) return true; + if (modifiers.HasModifier(TargetModifiers.ForceMove)) + return false; + var targetableRelationship = negativeDamage ? Stance.Ally : Stance.Enemy; return self.Owner.Stances[target.Owner] == targetableRelationship; } - public bool CanTargetLocation(Actor self, CPos location, List actorsAtLocation, bool forceAttack, bool forceQueued, ref string cursor) + public bool CanTargetLocation(Actor self, CPos location, List actorsAtLocation, TargetModifiers modifiers, ref string cursor) { if (!self.World.Map.IsInMap(location)) return false; - IsQueued = forceQueued; + IsQueued = modifiers.HasModifier(TargetModifiers.ForceQueue); cursor = self.Info.Traits.Get().Cursor; @@ -204,7 +207,7 @@ namespace OpenRA.Mods.RA if (!self.Trait().HasAnyValidWeapons(Target.FromCell(location))) return false; - if (forceAttack) + if (modifiers.HasModifier(TargetModifiers.ForceAttack)) if (self.Info.Traits.Get().CanAttackGround) return true; diff --git a/OpenRA.Mods.RA/Captures.cs b/OpenRA.Mods.RA/Captures.cs index 08b1383e48..1e7e97d530 100644 --- a/OpenRA.Mods.RA/Captures.cs +++ b/OpenRA.Mods.RA/Captures.cs @@ -93,9 +93,9 @@ namespace OpenRA.Mods.RA this.useEnterCursor = useEnterCursor; } - public override bool CanTargetActor(Actor self, Actor target, bool forceAttack, bool forceQueued, ref string cursor) + public override bool CanTargetActor(Actor self, Actor target, TargetModifiers modifiers, ref string cursor) { - if (!base.CanTargetActor(self, target, forceAttack, forceQueued, ref cursor)) + if (!base.CanTargetActor(self, target, modifiers, ref cursor)) return false; var ci = target.Info.Traits.GetOrDefault(); @@ -112,7 +112,7 @@ namespace OpenRA.Mods.RA if (playerRelationship == Stance.Neutral && !ci.AllowNeutral) return false; - IsQueued = forceQueued; + IsQueued = modifiers.HasModifier(TargetModifiers.ForceQueue); var Info = self.Info.Traits.Get(); if (captureTypes.Contains(ci.Type)) diff --git a/OpenRA.Mods.RA/EngineerRepair.cs b/OpenRA.Mods.RA/EngineerRepair.cs index d8cfe5a793..785c5029a6 100644 --- a/OpenRA.Mods.RA/EngineerRepair.cs +++ b/OpenRA.Mods.RA/EngineerRepair.cs @@ -57,9 +57,9 @@ namespace OpenRA.Mods.RA public EngineerRepairOrderTargeter() : base("EngineerRepair", 6, "goldwrench", false, true) { } - public override bool CanTargetActor(Actor self, Actor target, bool forceAttack, bool forceQueued, ref string cursor) + public override bool CanTargetActor(Actor self, Actor target, TargetModifiers modifiers, ref string cursor) { - if (!base.CanTargetActor(self, target, forceAttack, forceQueued, ref cursor)) + if (!base.CanTargetActor(self, target, modifiers, ref cursor)) return false; if (!target.HasTrait()) @@ -68,7 +68,7 @@ namespace OpenRA.Mods.RA if (self.Owner.Stances[target.Owner] != Stance.Ally) return false; - IsQueued = forceQueued; + IsQueued = modifiers.HasModifier(TargetModifiers.ForceQueue); if (target.GetDamageState() == DamageState.Undamaged) cursor = "goldwrench-blocked"; diff --git a/OpenRA.Mods.RA/Harvester.cs b/OpenRA.Mods.RA/Harvester.cs index c8b6db7f46..e959e489d6 100644 --- a/OpenRA.Mods.RA/Harvester.cs +++ b/OpenRA.Mods.RA/Harvester.cs @@ -417,12 +417,12 @@ namespace OpenRA.Mods.RA public int OrderPriority { get { return 10; } } public bool IsQueued { get; protected set; } - public bool CanTargetActor(Actor self, Actor target, bool forceAttack, bool forceQueued, ref string cursor) + public bool CanTargetActor(Actor self, Actor target, TargetModifiers modifiers, ref string cursor) { return false; } - public bool CanTargetLocation(Actor self, CPos location, List actorsAtLocation, bool forceAttack, bool forceQueued, ref string cursor) + public bool CanTargetLocation(Actor self, CPos location, List actorsAtLocation, TargetModifiers modifiers, ref string cursor) { // Don't leak info about resources under the shroud if (!self.Owner.Shroud.IsExplored(location)) return false; @@ -433,7 +433,7 @@ namespace OpenRA.Mods.RA if (res == null) return false; if (!info.Resources.Contains(res.info.Name)) return false; cursor = "harvest"; - IsQueued = forceQueued; + IsQueued = modifiers.HasModifier(TargetModifiers.ForceQueue); return true; } diff --git a/OpenRA.Mods.RA/Infiltrates.cs b/OpenRA.Mods.RA/Infiltrates.cs index e74c8a4e22..6fb09f79c4 100644 --- a/OpenRA.Mods.RA/Infiltrates.cs +++ b/OpenRA.Mods.RA/Infiltrates.cs @@ -98,10 +98,10 @@ namespace OpenRA.Mods.RA ForceAttack = false; this.useEnterCursor = useEnterCursor; } - - public override bool CanTargetActor(Actor self, Actor target, bool forceAttack, bool forceQueued, ref string cursor) + + public override bool CanTargetActor(Actor self, Actor target, TargetModifiers modifiers, ref string cursor) { - if (!base.CanTargetActor(self, target, forceAttack, forceQueued, ref cursor)) + if (!base.CanTargetActor(self, target, modifiers, ref cursor)) return false; if (!target.HasTrait()) diff --git a/OpenRA.Mods.RA/Minelayer.cs b/OpenRA.Mods.RA/Minelayer.cs index 37b940e853..da775f83fc 100644 --- a/OpenRA.Mods.RA/Minelayer.cs +++ b/OpenRA.Mods.RA/Minelayer.cs @@ -157,20 +157,20 @@ namespace OpenRA.Mods.RA public string OrderID { get { return "BeginMinefield"; } } public int OrderPriority { get { return 5; } } - public bool CanTargetActor(Actor self, Actor target, bool forceAttack, bool forceQueued, ref string cursor) + public bool CanTargetActor(Actor self, Actor target, TargetModifiers modifiers, ref string cursor) { return false; } - public bool CanTargetLocation(Actor self, CPos location, List actorsAtLocation, bool forceAttack, bool forceQueued, ref string cursor) + public bool CanTargetLocation(Actor self, CPos location, List actorsAtLocation, TargetModifiers modifiers, ref string cursor) { if (!self.World.Map.IsInMap(location)) return false; cursor = "ability"; - IsQueued = forceQueued; + IsQueued = modifiers.HasModifier(TargetModifiers.ForceQueue); - return (actorsAtLocation.Count == 0 && forceAttack); + return (actorsAtLocation.Count == 0 && modifiers.HasModifier(TargetModifiers.ForceAttack)); } public bool IsQueued { get; protected set; } } diff --git a/OpenRA.Mods.RA/Move/Mobile.cs b/OpenRA.Mods.RA/Move/Mobile.cs index f0e9dd977d..58180da219 100755 --- a/OpenRA.Mods.RA/Move/Mobile.cs +++ b/OpenRA.Mods.RA/Move/Mobile.cs @@ -476,14 +476,14 @@ namespace OpenRA.Mods.RA.Move public int OrderPriority { get { return 4; } } public bool IsQueued { get; protected set; } - public bool CanTargetActor(Actor self, Actor target, bool forceAttack, bool forceQueued, ref string cursor) + public bool CanTargetActor(Actor self, Actor target, TargetModifiers modifiers, ref string cursor) { return false; } - public bool CanTargetLocation(Actor self, CPos location, List actorsAtLocation, bool forceAttack, bool forceQueued, ref string cursor) + public bool CanTargetLocation(Actor self, CPos location, List actorsAtLocation, TargetModifiers modifiers, ref string cursor) { - IsQueued = forceQueued; + IsQueued = modifiers.HasModifier(TargetModifiers.ForceQueue); cursor = "move"; if (self.Owner.Shroud.IsExplored(location)) diff --git a/OpenRA.Mods.RA/Orders/DeployOrderTargeter.cs b/OpenRA.Mods.RA/Orders/DeployOrderTargeter.cs index 35b1354213..88491e5e83 100755 --- a/OpenRA.Mods.RA/Orders/DeployOrderTargeter.cs +++ b/OpenRA.Mods.RA/Orders/DeployOrderTargeter.cs @@ -35,14 +35,14 @@ namespace OpenRA.Mods.RA.Orders public string OrderID { get; private set; } public int OrderPriority { get; private set; } - public bool CanTargetActor( Actor self, Actor target, bool forceAttack, bool forceQueued, ref string cursor ) + public bool CanTargetActor(Actor self, Actor target, TargetModifiers modifiers, ref string cursor) { - IsQueued = forceQueued; + IsQueued = modifiers.HasModifier(TargetModifiers.ForceQueue); cursor = useDeployCursor() ? "deploy" : "deploy-blocked"; return self == target; } - public bool CanTargetLocation(Actor self, CPos location, List actorsAtLocation, bool forceAttack, bool forceQueued, ref string cursor) + public bool CanTargetLocation(Actor self, CPos location, List actorsAtLocation, TargetModifiers modifiers, ref string cursor) { return false; } diff --git a/OpenRA.Mods.RA/Orders/EnterBuildingOrderTargeter.cs b/OpenRA.Mods.RA/Orders/EnterBuildingOrderTargeter.cs index 8f314e5381..e679830493 100755 --- a/OpenRA.Mods.RA/Orders/EnterBuildingOrderTargeter.cs +++ b/OpenRA.Mods.RA/Orders/EnterBuildingOrderTargeter.cs @@ -9,6 +9,7 @@ #endregion using System; +using OpenRA.Traits; namespace OpenRA.Mods.RA.Orders { @@ -25,9 +26,9 @@ namespace OpenRA.Mods.RA.Orders this.useEnterCursor = useEnterCursor; } - public override bool CanTargetActor(Actor self, Actor target, bool forceAttack, bool forceQueued, ref string cursor) + public override bool CanTargetActor(Actor self, Actor target, TargetModifiers modifiers, ref string cursor) { - if (!base.CanTargetActor(self, target, forceAttack, forceQueued, ref cursor)) + if (!base.CanTargetActor(self, target, modifiers, ref cursor)) return false; if (!target.HasTrait()) @@ -37,7 +38,7 @@ namespace OpenRA.Mods.RA.Orders return false; cursor = useEnterCursor(target) ? "enter" : "enter-blocked"; - IsQueued = forceQueued; + IsQueued = modifiers.HasModifier(TargetModifiers.ForceQueue); return true; } } diff --git a/OpenRA.Mods.RA/Orders/UnitOrderTargeter.cs b/OpenRA.Mods.RA/Orders/UnitOrderTargeter.cs index f0e4d101d4..2f19c71a2b 100755 --- a/OpenRA.Mods.RA/Orders/UnitOrderTargeter.cs +++ b/OpenRA.Mods.RA/Orders/UnitOrderTargeter.cs @@ -33,28 +33,29 @@ namespace OpenRA.Mods.RA.Orders public int OrderPriority { get; private set; } public bool? ForceAttack = null; - public virtual bool CanTargetActor(Actor self, Actor target, bool forceAttack, bool forceQueued, ref string cursor) + public virtual bool CanTargetActor(Actor self, Actor target, TargetModifiers modifiers, ref string cursor) { if( self == null ) throw new ArgumentNullException( "self" ); if( target == null ) throw new ArgumentNullException( "target" ); cursor = this.cursor; - IsQueued = forceQueued; + IsQueued = modifiers.HasModifier(TargetModifiers.ForceQueue); - if (ForceAttack != null && forceAttack != ForceAttack) return false; + if (ForceAttack != null && modifiers.HasModifier(TargetModifiers.ForceAttack) != ForceAttack) return false; - var playerRelationship = self.Owner.Stances[ target.Owner ]; + var playerRelationship = self.Owner.Stances[target.Owner]; - if( !forceAttack && playerRelationship == Stance.Ally && !targetAllyUnits ) return false; - if( !forceAttack && playerRelationship == Stance.Enemy && !targetEnemyUnits ) return false; + if (!modifiers.HasModifier(TargetModifiers.ForceAttack) && playerRelationship == Stance.Ally && !targetAllyUnits) return false; + if (!modifiers.HasModifier(TargetModifiers.ForceAttack) && playerRelationship == Stance.Enemy && !targetEnemyUnits) return false; return true; } - public virtual bool CanTargetLocation(Actor self, CPos location, List actorsAtLocation, bool forceAttack, bool forceQueued, ref string cursor) + public virtual bool CanTargetLocation(Actor self, CPos location, List actorsAtLocation, TargetModifiers modifiers, ref string cursor) { return false; } + public virtual bool IsQueued { get; protected set; } } @@ -68,15 +69,15 @@ namespace OpenRA.Mods.RA.Orders this.targetType = targetType; } - public override bool CanTargetActor(Actor self, Actor target, bool forceAttack, bool forceQueued, ref string cursor) + public override bool CanTargetActor(Actor self, Actor target, TargetModifiers modifiers, ref string cursor) { - if (!base.CanTargetActor(self, target, forceAttack, forceQueued, ref cursor)) + if (!base.CanTargetActor(self, target, modifiers, ref cursor)) return false; if (!target.TraitsImplementing().Any(t => t.TargetTypes.Contains(targetType))) return false; - IsQueued = forceQueued; + IsQueued = modifiers.HasModifier(TargetModifiers.ForceQueue); return true; } diff --git a/OpenRA.Mods.RA/RallyPoint.cs b/OpenRA.Mods.RA/RallyPoint.cs index 2983d6c6c8..36a0ff52a3 100755 --- a/OpenRA.Mods.RA/RallyPoint.cs +++ b/OpenRA.Mods.RA/RallyPoint.cs @@ -58,12 +58,12 @@ namespace OpenRA.Mods.RA public string OrderID { get { return "SetRallyPoint"; } } public int OrderPriority { get { return 0; } } - public bool CanTargetActor(Actor self, Actor target, bool forceAttack, bool forceQueued, ref string cursor) + public bool CanTargetActor(Actor self, Actor target, TargetModifiers modifiers, ref string cursor) { return false; } - public bool CanTargetLocation(Actor self, CPos location, List actorsAtLocation, bool forceAttack, bool forceQueued, ref string cursor) + public bool CanTargetLocation(Actor self, CPos location, List actorsAtLocation, TargetModifiers modifiers, ref string cursor) { if (self.World.Map.IsInMap(location)) { diff --git a/OpenRA.Mods.RA/RepairsBridges.cs b/OpenRA.Mods.RA/RepairsBridges.cs index 08fa795f89..2e8ab2cf14 100644 --- a/OpenRA.Mods.RA/RepairsBridges.cs +++ b/OpenRA.Mods.RA/RepairsBridges.cs @@ -69,9 +69,9 @@ namespace OpenRA.Mods.RA public RepairBridgeOrderTargeter() : base("RepairBridge", 6, "goldwrench", true, true) { } - public override bool CanTargetActor(Actor self, Actor target, bool forceAttack, bool forceQueued, ref string cursor) + public override bool CanTargetActor(Actor self, Actor target, TargetModifiers modifiers, ref string cursor) { - if (!base.CanTargetActor(self, target, forceAttack, forceQueued, ref cursor)) + if (!base.CanTargetActor(self, target, modifiers, ref cursor)) return false; var bridge = target.TraitOrDefault(); @@ -80,10 +80,10 @@ namespace OpenRA.Mods.RA // Require force attack to heal partially damaged bridges to avoid unnecessary cursor noise var damage = bridge.BridgeDamageState; - if (!forceAttack && damage != DamageState.Dead) + if (!modifiers.HasModifier(TargetModifiers.ForceAttack) && damage != DamageState.Dead) return false; - IsQueued = forceQueued; + IsQueued = modifiers.HasModifier(TargetModifiers.ForceQueue); // Can't repair an undamaged bridge if (damage == DamageState.Undamaged) diff --git a/OpenRA.Mods.RA/SupplyTruck.cs b/OpenRA.Mods.RA/SupplyTruck.cs index 2253bc3141..b7b779caef 100644 --- a/OpenRA.Mods.RA/SupplyTruck.cs +++ b/OpenRA.Mods.RA/SupplyTruck.cs @@ -70,9 +70,9 @@ namespace OpenRA.Mods.RA { } - public override bool CanTargetActor(Actor self, Actor target, bool forceAttack, bool forceQueued, ref string cursor) + public override bool CanTargetActor(Actor self, Actor target, TargetModifiers modifiers, ref string cursor) { - if (!base.CanTargetActor(self, target, forceAttack, forceQueued, ref cursor)) + if (!base.CanTargetActor(self, target, modifiers, ref cursor)) return false; if (target.AppearsHostileTo(self)) @@ -81,7 +81,7 @@ namespace OpenRA.Mods.RA if (!target.HasTrait()) return false; - IsQueued = forceQueued; + IsQueued = modifiers.HasModifier(TargetModifiers.ForceQueue); return true; } }