diff --git a/OpenRa.Game/OpenRa.Game.csproj b/OpenRa.Game/OpenRa.Game.csproj
index 8b8cb29a1b..608ff6e91f 100644
--- a/OpenRa.Game/OpenRa.Game.csproj
+++ b/OpenRa.Game/OpenRa.Game.csproj
@@ -142,6 +142,7 @@
+
diff --git a/OpenRa.Game/Traits/AttackBase.cs b/OpenRa.Game/Traits/AttackBase.cs
new file mode 100644
index 0000000000..e2aef26186
--- /dev/null
+++ b/OpenRa.Game/Traits/AttackBase.cs
@@ -0,0 +1,95 @@
+using System;
+
+namespace OpenRa.Game.Traits
+{
+ class AttackBase : IOrder, ITick
+ {
+ public Actor target;
+
+ // time (in frames) until each weapon can fire again.
+ protected int primaryFireDelay = 0;
+ protected int secondaryFireDelay = 0;
+
+ public float primaryRecoil = 0.0f, secondaryRecoil = 0.0f;
+
+ public AttackBase(Actor self) { }
+
+ protected bool CanAttack(Actor self)
+ {
+ return target != null;
+ }
+
+ public virtual void Tick(Actor self)
+ {
+ if (primaryFireDelay > 0) --primaryFireDelay;
+ if (secondaryFireDelay > 0) --secondaryFireDelay;
+
+ primaryRecoil = Math.Max(0f, primaryRecoil - .2f);
+ secondaryRecoil = Math.Max(0f, secondaryRecoil - .2f);
+
+ if (target != null && target.IsDead) target = null; /* he's dead, jim. */
+ }
+
+ public void DoAttack(Actor self)
+ {
+ var unit = self.traits.Get();
+
+ if (self.unitInfo.Primary != null && CheckFire(self, unit, self.unitInfo.Primary, ref primaryFireDelay,
+ self.unitInfo.PrimaryOffset))
+ {
+ secondaryFireDelay = Math.Max(4, secondaryFireDelay);
+ primaryRecoil = 1;
+ return;
+ }
+
+ if (self.unitInfo.Secondary != null && CheckFire(self, unit, self.unitInfo.Secondary, ref secondaryFireDelay,
+ self.unitInfo.SecondaryOffset ?? self.unitInfo.PrimaryOffset))
+ {
+ if (self.unitInfo.SecondaryOffset != null) secondaryRecoil = 1;
+ else primaryRecoil = 1;
+ return;
+ }
+ }
+
+ bool CheckFire(Actor self, Unit unit, string weaponName, ref int fireDelay, int[] offset)
+ {
+ if (fireDelay > 0) return false;
+ var weapon = Rules.WeaponInfo[weaponName];
+ if (weapon.Range * weapon.Range < (target.Location - self.Location).LengthSquared) return false;
+
+ fireDelay = weapon.ROF;
+
+ Game.world.Add(new Bullet(weaponName, self.Owner, self,
+ self.CenterLocation.ToInt2() + Util.GetTurretPosition(self, unit, offset, 0f).ToInt2(),
+ target.CenterLocation.ToInt2()));
+
+ return true;
+ }
+
+ public Order IssueOrder(Actor self, int2 xy, bool lmb, Actor underCursor)
+ {
+ if (lmb || underCursor == null) return null;
+ if (underCursor.Owner == self.Owner) return null;
+ return Order.Attack(self, underCursor);
+ }
+
+ public void ResolveOrder(Actor self, Order order)
+ {
+ if (order.OrderString == "Attack")
+ {
+ self.CancelActivity();
+ QueueAttack(self, order);
+ }
+ }
+
+ protected virtual void QueueAttack(Actor self, Order order)
+ {
+ const int RangeTolerance = 1; /* how far inside our maximum range we should try to sit */
+ /* todo: choose the appropriate weapon, when only one works against this target */
+ var weapon = order.Subject.unitInfo.Primary ?? order.Subject.unitInfo.Secondary;
+
+ self.QueueActivity(new Traits.Activities.Attack(order.TargetActor,
+ Math.Max(0, (int)Rules.WeaponInfo[weapon].Range - RangeTolerance)));
+ }
+ }
+}
diff --git a/OpenRa.Game/Traits/AttackTurreted.cs b/OpenRa.Game/Traits/AttackTurreted.cs
index f498f6f64d..cfa6a2d3da 100755
--- a/OpenRa.Game/Traits/AttackTurreted.cs
+++ b/OpenRa.Game/Traits/AttackTurreted.cs
@@ -1,101 +1,7 @@
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
namespace OpenRa.Game.Traits
{
- class AttackBase : IOrder, ITick
- {
- public Actor target;
-
- // time (in frames) until each weapon can fire again.
- protected int primaryFireDelay = 0;
- protected int secondaryFireDelay = 0;
-
- public float primaryRecoil = 0.0f, secondaryRecoil = 0.0f;
-
- public AttackBase(Actor self) { }
-
- protected bool CanAttack( Actor self )
- {
- return target != null;
- }
-
- public virtual void Tick(Actor self)
- {
- if (primaryFireDelay > 0) --primaryFireDelay;
- if (secondaryFireDelay > 0) --secondaryFireDelay;
-
- primaryRecoil = Math.Max(0f, primaryRecoil - .2f);
- secondaryRecoil = Math.Max(0f, secondaryRecoil - .2f);
-
- if (target != null && target.IsDead) target = null; /* he's dead, jim. */
- }
-
- public void DoAttack( Actor self )
- {
- var unit = self.traits.Get();
-
- if( self.unitInfo.Primary != null && CheckFire( self, unit, self.unitInfo.Primary, ref primaryFireDelay,
- self.unitInfo.PrimaryOffset ) )
- {
- secondaryFireDelay = Math.Max( 4, secondaryFireDelay );
- primaryRecoil = 1;
- return;
- }
-
- if (self.unitInfo.Secondary != null && CheckFire(self, unit, self.unitInfo.Secondary, ref secondaryFireDelay,
- self.unitInfo.SecondaryOffset ?? self.unitInfo.PrimaryOffset))
- {
- if (self.unitInfo.SecondaryOffset != null) secondaryRecoil = 1;
- else primaryRecoil = 1;
- return;
- }
- }
-
- bool CheckFire( Actor self, Unit unit, string weaponName, ref int fireDelay, int[] offset )
- {
- if( fireDelay > 0 ) return false;
- var weapon = Rules.WeaponInfo[ weaponName ];
- if( weapon.Range * weapon.Range < ( target.Location - self.Location ).LengthSquared ) return false;
-
- fireDelay = weapon.ROF;
-
- Game.world.Add( new Bullet( weaponName, self.Owner, self,
- self.CenterLocation.ToInt2() + Util.GetTurretPosition( self, unit, offset, 0f ).ToInt2(),
- target.CenterLocation.ToInt2() ) );
-
- return true;
- }
-
- public Order IssueOrder( Actor self, int2 xy, bool lmb, Actor underCursor )
- {
- if( lmb || underCursor == null ) return null;
- if( underCursor.Owner == self.Owner ) return null;
- return Order.Attack( self, underCursor );
- }
-
- public void ResolveOrder( Actor self, Order order )
- {
- if( order.OrderString == "Attack" )
- {
- self.CancelActivity();
- QueueAttack( self, order );
- }
- }
-
- protected virtual void QueueAttack( Actor self, Order order )
- {
- const int RangeTolerance = 1; /* how far inside our maximum range we should try to sit */
- /* todo: choose the appropriate weapon, when only one works against this target */
- var weapon = order.Subject.unitInfo.Primary ?? order.Subject.unitInfo.Secondary;
-
- self.QueueActivity( new Traits.Activities.Attack( order.TargetActor,
- Math.Max( 0, (int)Rules.WeaponInfo[ weapon ].Range - RangeTolerance ) ) );
- }
- }
-
class AttackTurreted : AttackBase
{
public AttackTurreted( Actor self ) : base(self) { self.traits.Get(); }