diff --git a/OpenRA.Mods.Common/Activities/Attack.cs b/OpenRA.Mods.Common/Activities/Attack.cs index 8d164ee376..bf8ab5eb35 100644 --- a/OpenRA.Mods.Common/Activities/Attack.cs +++ b/OpenRA.Mods.Common/Activities/Attack.cs @@ -8,6 +8,7 @@ */ #endregion +using System; using System.Linq; using OpenRA.Activities; using OpenRA.Mods.Common.Traits; @@ -18,8 +19,11 @@ namespace OpenRA.Mods.Common.Activities /* non-turreted attack */ public class Attack : Activity { + [Flags] + enum AttackStatus { UnableToAttack, NeedsToTurn, NeedsToMove, Attacking } + protected readonly Target Target; - readonly AttackBase attack; + readonly AttackBase[] attackTraits; readonly IMove move; readonly IFacing facing; readonly IPositionable positionable; @@ -27,6 +31,9 @@ namespace OpenRA.Mods.Common.Activities WDist minRange; WDist maxRange; + Activity turnActivity; + Activity moveActivity; + AttackStatus attackStatus = AttackStatus.UnableToAttack; public Attack(Actor self, Target target, bool allowMovement, bool forceAttack) { @@ -34,7 +41,7 @@ namespace OpenRA.Mods.Common.Activities this.forceAttack = forceAttack; - attack = self.Trait(); + attackTraits = self.TraitsImplementing().ToArray(); facing = self.Trait(); positionable = self.Trait(); @@ -43,9 +50,25 @@ namespace OpenRA.Mods.Common.Activities public override Activity Tick(Actor self) { - var ret = InnerTick(self, attack); - attack.IsAttacking = ret == this; - return ret; + turnActivity = moveActivity = null; + attackStatus = AttackStatus.UnableToAttack; + + foreach (var attack in attackTraits.Where(x => !x.IsTraitDisabled)) + { + var activity = InnerTick(self, attack); + attack.IsAttacking = activity == this; + } + + if (attackStatus.HasFlag(AttackStatus.Attacking)) + return this; + + if (attackStatus.HasFlag(AttackStatus.NeedsToTurn)) + return turnActivity; + + if (attackStatus.HasFlag(AttackStatus.NeedsToMove)) + return moveActivity; + + return NextActivity; } protected virtual Activity InnerTick(Actor self, AttackBase attack) @@ -81,13 +104,21 @@ namespace OpenRA.Mods.Common.Activities // Try to move within range, drop the target otherwise if (move == null) return NextActivity; - return ActivityUtils.SequenceActivities(move.MoveWithinRange(Target, minRange, maxRange), this); + + attackStatus |= AttackStatus.NeedsToMove; + moveActivity = ActivityUtils.SequenceActivities(move.MoveWithinRange(Target, minRange, maxRange), this); + return NextActivity; } var desiredFacing = (Target.CenterPosition - self.CenterPosition).Yaw.Facing; if (facing.Facing != desiredFacing) - return ActivityUtils.SequenceActivities(new Turn(self, desiredFacing), this); + { + attackStatus |= AttackStatus.NeedsToTurn; + turnActivity = ActivityUtils.SequenceActivities(new Turn(self, desiredFacing), this); + return NextActivity; + } + attackStatus |= AttackStatus.Attacking; attack.DoAttack(self, Target, armaments); return this; diff --git a/OpenRA.Mods.Common/Traits/CombatDebugOverlay.cs b/OpenRA.Mods.Common/Traits/CombatDebugOverlay.cs index 72d30fdbea..23203fa42c 100644 --- a/OpenRA.Mods.Common/Traits/CombatDebugOverlay.cs +++ b/OpenRA.Mods.Common/Traits/CombatDebugOverlay.cs @@ -27,17 +27,15 @@ namespace OpenRA.Mods.Common.Traits public class CombatDebugOverlay : IPostRender, INotifyDamage, INotifyCreated { readonly DeveloperMode devMode; - readonly HealthInfo healthInfo; + readonly Lazy coords; + IBlocksProjectiles[] allBlockers; - Lazy attack; - Lazy coords; public CombatDebugOverlay(Actor self) { healthInfo = self.Info.TraitInfoOrDefault(); - attack = Exts.Lazy(() => self.TraitOrDefault()); - coords = Exts.Lazy(() => self.Trait()); + coords = Exts.Lazy(self.Trait); var localPlayer = self.World.LocalPlayer; devMode = localPlayer != null ? localPlayer.PlayerActor.Trait() : null; @@ -71,14 +69,16 @@ namespace OpenRA.Mods.Common.Traits TargetLineRenderable.DrawTargetMarker(wr, hc, hb); } - // No armaments to draw - if (attack.Value == null) - return; + foreach (var attack in self.TraitsImplementing().Where(x => !x.IsTraitDisabled)) + DrawArmaments(self, attack, wr, wcr, iz); + } + void DrawArmaments(Actor self, AttackBase attack, WorldRenderer wr, RgbaColorRenderer wcr, float iz) + { var c = Color.White; // Fire ports on garrisonable structures - var garrison = attack.Value as AttackGarrisoned; + var garrison = attack as AttackGarrisoned; if (garrison != null) { var bodyOrientation = coords.Value.QuantizeOrientation(self, self.Orientation); @@ -98,7 +98,7 @@ namespace OpenRA.Mods.Common.Traits return; } - foreach (var a in attack.Value.Armaments) + foreach (var a in attack.Armaments) { foreach (var b in a.Barrels) {