diff --git a/OpenRa.Game/OpenRa.Game.csproj b/OpenRa.Game/OpenRa.Game.csproj index 57c74ffc8b..87e964d61f 100644 --- a/OpenRa.Game/OpenRa.Game.csproj +++ b/OpenRa.Game/OpenRa.Game.csproj @@ -113,6 +113,7 @@ + @@ -174,6 +175,7 @@ + diff --git a/OpenRa.Game/Traits/Activities/Circle.cs b/OpenRa.Game/Traits/Activities/Circle.cs index 6f8eaefffd..be4bf96765 100644 --- a/OpenRa.Game/Traits/Activities/Circle.cs +++ b/OpenRa.Game/Traits/Activities/Circle.cs @@ -16,15 +16,10 @@ namespace OpenRa.Game.Traits.Activities public IActivity Tick(Actor self) { if (isCanceled) return NextActivity; - var unit = self.traits.Get(); - return new Fly(Util.CenterOfCell(Cell)) - { - NextActivity = - new FlyTimed(50, 20) - { - NextActivity = this - } - }; + return Util.SequenceActivities( + new Fly(Util.CenterOfCell(Cell)), + new FlyTimed(50, 20), + this); } public void Cancel(Actor self) { isCanceled = true; NextActivity = null; } diff --git a/OpenRa.Game/Traits/Activities/FlyAttack.cs b/OpenRa.Game/Traits/Activities/FlyAttack.cs new file mode 100644 index 0000000000..0d47d92685 --- /dev/null +++ b/OpenRa.Game/Traits/Activities/FlyAttack.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace OpenRa.Game.Traits.Activities +{ + class FlyAttack : IActivity + { + public IActivity NextActivity { get; set; } + Actor Target; + + public FlyAttack(Actor target) { Target = target; } + + public IActivity Tick(Actor self) + { + if (Target == null || Target.IsDead) return NextActivity; + + var limitedAmmo = self.traits.GetOrDefault(); + if (limitedAmmo != null && !limitedAmmo.HasAmmo()) + return NextActivity; + + return Util.SequenceActivities( + new Fly(Target.CenterLocation), + new FlyTimed(50, 20), + this); + } + + public void Cancel(Actor self) { Target = null; NextActivity = null; } + } +} diff --git a/OpenRa.Game/Traits/AttackPlane.cs b/OpenRa.Game/Traits/AttackPlane.cs new file mode 100644 index 0000000000..47a51d61b2 --- /dev/null +++ b/OpenRa.Game/Traits/AttackPlane.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using OpenRa.Game.Traits.Activities; + +namespace OpenRa.Game.Traits +{ + // yet another ugly trait that does two things: + // - plane-specific attack order dispatch + // - forward-facing attack with a tolerance + + class AttackPlane : AttackBase + { + const int facingTolerance = 20; + + public AttackPlane(Actor self) : base(self) { } + + public override void Tick(Actor self) + { + base.Tick(self); + + if (target == null) return; + + var unit = self.traits.Get(); + var facingToTarget = Util.GetFacing(target.CenterLocation - self.CenterLocation, unit.Facing); + + if (Math.Abs(facingToTarget - unit.Facing) % 256 < facingTolerance) + DoAttack(self); + } + + protected override void QueueAttack(Actor self, Order order) + { + self.QueueActivity(new FlyAttack(order.TargetActor)); + target = order.TargetActor; + } + } +} diff --git a/OpenRa.Game/Traits/AttackTurreted.cs b/OpenRa.Game/Traits/AttackTurreted.cs index 3d9d40bd9d..256bd25379 100755 --- a/OpenRa.Game/Traits/AttackTurreted.cs +++ b/OpenRa.Game/Traits/AttackTurreted.cs @@ -41,7 +41,7 @@ namespace OpenRa.Game.Traits self.QueueActivity( new Traits.Activities.Follow( order.TargetActor, Math.Max( 0, (int)Rules.WeaponInfo[ weapon ].Range - RangeTolerance ) ) ); - self.traits.Get().target = order.TargetActor; + target = order.TargetActor; } bool buildComplete = false; diff --git a/OpenRa.Game/Traits/Util.cs b/OpenRa.Game/Traits/Util.cs index 8809c86d90..b578fa3ff6 100755 --- a/OpenRa.Game/Traits/Util.cs +++ b/OpenRa.Game/Traits/Util.cs @@ -2,6 +2,7 @@ using System.Linq; using OpenRa.Game.GameRules; using OpenRa.Game.Graphics; +using OpenRa.Game.Traits.Activities; namespace OpenRa.Game.Traits { @@ -135,5 +136,11 @@ namespace OpenRa.Game.Traits .Product(); return mi.Speed * modifier; } + + public static IActivity SequenceActivities(params IActivity[] acts) + { + return acts.Reverse().Aggregate((IActivity)null, + (next, a) => { a.NextActivity = next; return a; }); + } } } diff --git a/units.ini b/units.ini index 0457488a27..da6a29918e 100755 --- a/units.ini +++ b/units.ini @@ -165,13 +165,13 @@ HIND [MIG] Description=Mig Attack Plane BuiltAt=afld -Traits=Unit, Plane, RenderUnit, WithShadow, LimitedAmmo +Traits=Unit, AttackPlane, Plane, RenderUnit, WithShadow, LimitedAmmo InitialFacing=192 LongDesc=Fast Ground-Attack Plane.\n Strong vs Buildings\n Weak vs Infantry, Light Vehicles [YAK] Description=Yak Attack Plane BuiltAt=afld -Traits=Unit, Plane, RenderUnit, WithShadow, LimitedAmmo +Traits=Unit, AttackPlane, Plane, RenderUnit, WithShadow, LimitedAmmo InitialFacing=192 LongDesc=Anti-Tanks & Anti-Infantry Plane.\n Strong vs Infantry, Tanks\n Weak vs Buildings [TRAN]