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]