diff --git a/OpenRa.Game/OpenRa.Game.csproj b/OpenRa.Game/OpenRa.Game.csproj index c0c2bfd35a..f601117070 100644 --- a/OpenRa.Game/OpenRa.Game.csproj +++ b/OpenRa.Game/OpenRa.Game.csproj @@ -83,6 +83,7 @@ + diff --git a/OpenRa.Game/Traits/Activities/Attack.cs b/OpenRa.Game/Traits/Activities/Attack.cs new file mode 100644 index 0000000000..545233dd35 --- /dev/null +++ b/OpenRa.Game/Traits/Activities/Attack.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace OpenRa.Game.Traits.Activities +{ + /* non-turreted attack */ + class Attack : IActivity + { + Actor Target; + int Range; + + public Attack(Actor target, int range) + { + Target = target; + Range = range; + } + + public IActivity NextActivity { get; set; } + + public void Tick(Actor self, Mobile mobile) + { + if (Target.IsDead) + { + mobile.InternalSetActivity(NextActivity); + return; + } + + if ((Target.Location - self.Location).LengthSquared >= Range * Range) + { + mobile.InternalSetActivity(new Move(Target, Range)); + mobile.QueueActivity(this); + return; + } + + var desiredFacing = Util.GetFacing((Target.Location - self.Location).ToFloat2(), 0); + var renderUnit = self.traits.WithInterface().First(); + + if (Util.QuantizeFacing(mobile.facing, renderUnit.anim.CurrentSequence.Length) + != Util.QuantizeFacing(desiredFacing, renderUnit.anim.CurrentSequence.Length)) + { + mobile.InternalSetActivity(new Turn(desiredFacing)); + mobile.QueueActivity(this); + return; + } + + var attack = self.traits.WithInterface().First(); + attack.target = Target; + attack.DoAttack(self); + } + + public void Cancel(Actor self, Mobile mobile) + { + mobile.InternalSetActivity(null); + } + } +} diff --git a/OpenRa.Game/Traits/AttackTurreted.cs b/OpenRa.Game/Traits/AttackTurreted.cs index 78085f1288..5b71262fa7 100755 --- a/OpenRa.Game/Traits/AttackTurreted.cs +++ b/OpenRa.Game/Traits/AttackTurreted.cs @@ -5,13 +5,15 @@ using System.Text; namespace OpenRa.Game.Traits { - abstract class AttackBase : IOrder, ITick + class AttackBase : IOrder, ITick { public Actor target; // time (in frames) until each weapon can fire again. protected int primaryFireDelay = 0; - protected int secondaryFireDelay = 0; + protected int secondaryFireDelay = 0; + + public AttackBase(Actor self) { } protected bool CanAttack( Actor self ) { @@ -26,7 +28,7 @@ namespace OpenRa.Game.Traits if (target != null && target.IsDead) target = null; /* he's dead, jim. */ } - protected void DoAttack( Actor self ) + public void DoAttack( Actor self ) { var rut = self.traits.GetOrDefault(); @@ -79,7 +81,7 @@ namespace OpenRa.Game.Traits class AttackTurreted : AttackBase { - public AttackTurreted( Actor self ) { self.traits.Get(); } + public AttackTurreted( Actor self ) : base(self) { self.traits.Get(); } public override void Tick(Actor self) { diff --git a/OpenRa.Game/UnitOrders.cs b/OpenRa.Game/UnitOrders.cs index 490b2143a3..df36cd1574 100755 --- a/OpenRa.Game/UnitOrders.cs +++ b/OpenRa.Game/UnitOrders.cs @@ -31,11 +31,20 @@ namespace OpenRa.Game var weapon = order.Subject.unitInfo.Primary ?? order.Subject.unitInfo.Secondary; mobile.Cancel(order.Subject); - mobile.QueueActivity( - new Traits.Activities.Follow(order.TargetActor, - Math.Max(0, (int)Rules.WeaponInfo[weapon].Range - RangeTolerance))); + if (order.Subject.traits.Contains()) + { + mobile.QueueActivity( + new Traits.Activities.Follow(order.TargetActor, + Math.Max(0, (int)Rules.WeaponInfo[weapon].Range - RangeTolerance))); - order.Subject.traits.Get().target = order.TargetActor; + order.Subject.traits.Get().target = order.TargetActor; + } + else + { + mobile.QueueActivity( + new Traits.Activities.Attack(order.TargetActor, + Math.Max(0, (int)Rules.WeaponInfo[weapon].Range - RangeTolerance))); + } break; } case "DeployMcv": diff --git a/units.ini b/units.ini index 1a31212213..1f194060e3 100755 --- a/units.ini +++ b/units.ini @@ -41,7 +41,7 @@ Traits=Mobile, RenderUnitTurreted PrimaryOffset=0,6,0,-3 [ARTY] Description=Artillery -Traits=Mobile, RenderUnit +Traits=Mobile, RenderUnit, AttackBase [HARV] Description=Ore Truck Traits=Harvester, Mobile, RenderUnit @@ -55,7 +55,7 @@ PrimaryOffset=0,0,0,-2 MuzzleFlash=yes [APC] Description=Armored Personnel Carrier -Traits=Mobile, RenderUnit +Traits=Mobile, RenderUnit, AttackBase [MNLY] Description=Minelayer Traits=Mobile, RenderUnit