diff --git a/OpenRA.Mods.RA/Armament.cs b/OpenRA.Mods.RA/Armament.cs index f58b982bf0..2b819b44a6 100644 --- a/OpenRA.Mods.RA/Armament.cs +++ b/OpenRA.Mods.RA/Armament.cs @@ -47,13 +47,15 @@ namespace OpenRA.Mods.RA public object Create(ActorInitializer init) { return new Armament(init.self, this); } } - public class Armament : ITick + public class Armament : ITick, IExplodeModifier { public readonly ArmamentInfo Info; public readonly WeaponInfo Weapon; public readonly Barrel[] Barrels; Lazy Turret; Lazy Coords; + Lazy limitedAmmo; + List> delayedActions = new List>(); public WRange Recoil; public int FireDelay { get; private set; } @@ -66,6 +68,7 @@ namespace OpenRA.Mods.RA // We can't resolve these until runtime Turret = Lazy.New(() => self.TraitsImplementing().FirstOrDefault(t => t.Name == info.Turret)); Coords = Lazy.New(() => self.Trait()); + limitedAmmo = Lazy.New(() => self.TraitOrDefault()); Weapon = Rules.Weapons[info.Weapon.ToLowerInvariant()]; Burst = Weapon.Burst; @@ -94,17 +97,34 @@ namespace OpenRA.Mods.RA if (FireDelay > 0) --FireDelay; Recoil = new WRange(Math.Max(0, Recoil.Range - Info.RecoilRecovery.Range)); + + for (var i = 0; i < delayedActions.Count; i++) + { + var x = delayedActions[i]; + if (--x.First <= 0) + x.Second(); + delayedActions[i] = x; + } + + delayedActions.RemoveAll(a => a.First <= 0); + } + + void ScheduleDelayedAction(int t, Action a) + { + if (t > 0) + delayedActions.Add(Pair.New(t, a)); + else + a(); } // Note: facing is only used by the legacy positioning code // The world coordinate model uses Actor.Orientation - public void CheckFire(Actor self, AttackBase attack, IFacing facing, Target target) + public void CheckFire(Actor self, IFacing facing, Target target) { if (FireDelay > 0) return; - var limitedAmmo = self.TraitOrDefault(); - if (limitedAmmo != null && !limitedAmmo.HasAmmo()) + if (limitedAmmo.Value != null && !limitedAmmo.Value.HasAmmo()) return; if (!target.IsInRange(self.CenterPosition, Weapon.Range)) @@ -134,7 +154,7 @@ namespace OpenRA.Mods.RA GuidedTarget = target }; - attack.ScheduleDelayedAction(Info.FireDelay, () => + ScheduleDelayedAction(Info.FireDelay, () => { if (args.Weapon.Projectile != null) { @@ -162,6 +182,7 @@ namespace OpenRA.Mods.RA } public bool IsReloading { get { return FireDelay > 0; } } + public bool ShouldExplode(Actor self) { return !IsReloading; } public WVec MuzzleOffset(Actor self, Barrel b) { diff --git a/OpenRA.Mods.RA/Attack/AttackBase.cs b/OpenRA.Mods.RA/Attack/AttackBase.cs index 1ef88832f4..75d18ea141 100644 --- a/OpenRA.Mods.RA/Attack/AttackBase.cs +++ b/OpenRA.Mods.RA/Attack/AttackBase.cs @@ -25,7 +25,7 @@ namespace OpenRA.Mods.RA public abstract object Create(ActorInitializer init); } - public abstract class AttackBase : IIssueOrder, IResolveOrder, ITick, IExplodeModifier, IOrderVoice, ISync + public abstract class AttackBase : IIssueOrder, IResolveOrder, IOrderVoice, ISync { [Sync] public bool IsAttacking { get; internal set; } @@ -35,7 +35,6 @@ namespace OpenRA.Mods.RA protected Lazy facing; Lazy> armaments; protected IEnumerable Armaments { get { return armaments.Value; } } - List> delayedActions = new List>(); public AttackBase(Actor self, AttackBaseInfo info) { @@ -63,38 +62,13 @@ namespace OpenRA.Mods.RA return true; } - public bool ShouldExplode(Actor self) { return !IsReloading(); } - - public bool IsReloading() { return Armaments.Any(a => a.IsReloading); } - - public virtual void Tick(Actor self) - { - for (var i = 0; i < delayedActions.Count; i++) - { - var x = delayedActions[i]; - if (--x.First <= 0) - x.Second(); - delayedActions[i] = x; - } - - delayedActions.RemoveAll(a => a.First <= 0); - } - - internal void ScheduleDelayedAction(int t, Action a) - { - if (t > 0) - delayedActions.Add(Pair.New(t, a)); - else - a(); - } - public virtual void DoAttack(Actor self, Target target) { if (!CanAttack(self, target)) return; foreach (var a in Armaments) - a.CheckFire(self, this, facing.Value, target); + a.CheckFire(self, facing.Value, target); } public IEnumerable Orders diff --git a/OpenRA.Mods.RA/Attack/AttackCharge.cs b/OpenRA.Mods.RA/Attack/AttackCharge.cs index a566d89bc0..c69a4a4316 100644 --- a/OpenRA.Mods.RA/Attack/AttackCharge.cs +++ b/OpenRA.Mods.RA/Attack/AttackCharge.cs @@ -41,12 +41,10 @@ namespace OpenRA.Mods.RA charges = aci.MaxCharges; } - public override void Tick(Actor self) + public void Tick(Actor self) { if (--timeToRecharge <= 0) charges = aci.MaxCharges; - - base.Tick(self); } public void Attacking(Actor self, Target target, Armament a, Barrel barrel) diff --git a/OpenRA.Mods.RA/Attack/AttackLoyalty.cs b/OpenRA.Mods.RA/Attack/AttackLoyalty.cs index 28537fc62a..dcd56c5f93 100644 --- a/OpenRA.Mods.RA/Attack/AttackLoyalty.cs +++ b/OpenRA.Mods.RA/Attack/AttackLoyalty.cs @@ -36,7 +36,7 @@ namespace OpenRA.Mods.RA var facing = self.TraitOrDefault(); foreach (var a in Armaments) - a.CheckFire(self, this, facing, target); + a.CheckFire(self, facing, target); if (target.Actor != null) target.Actor.ChangeOwner(self.Owner); diff --git a/OpenRA.Mods.RA/Attack/AttackTurreted.cs b/OpenRA.Mods.RA/Attack/AttackTurreted.cs index 052bc67486..9f7ee484c4 100644 --- a/OpenRA.Mods.RA/Attack/AttackTurreted.cs +++ b/OpenRA.Mods.RA/Attack/AttackTurreted.cs @@ -22,7 +22,7 @@ namespace OpenRA.Mods.RA public override object Create(ActorInitializer init) { return new AttackTurreted(init.self, this); } } - class AttackTurreted : AttackBase, INotifyBuildComplete, ISync + class AttackTurreted : AttackBase, ITick, INotifyBuildComplete, ISync { public Target Target { get; protected set; } protected IEnumerable turrets; @@ -53,9 +53,8 @@ namespace OpenRA.Mods.RA return base.CanAttack(self, target); } - public override void Tick(Actor self) + public void Tick(Actor self) { - base.Tick(self); DoAttack(self, Target); IsAttacking = Target.IsValidFor(self); } diff --git a/OpenRA.Mods.RA/AttackBomber.cs b/OpenRA.Mods.RA/AttackBomber.cs index f39df8820c..32716e57ad 100644 --- a/OpenRA.Mods.RA/AttackBomber.cs +++ b/OpenRA.Mods.RA/AttackBomber.cs @@ -27,7 +27,7 @@ namespace OpenRA.Mods.RA public override object Create(ActorInitializer init) { return new AttackBomber(init.self, this); } } - class AttackBomber : AttackBase, ISync, INotifyRemovedFromWorld + class AttackBomber : AttackBase, ITick, ISync, INotifyRemovedFromWorld { AttackBomberInfo info; [Sync] Target target; @@ -43,10 +43,8 @@ namespace OpenRA.Mods.RA this.info = info; } - public override void Tick(Actor self) + public void Tick(Actor self) { - base.Tick(self); - var cp = self.CenterPosition; var bombTarget = Target.FromPos(cp - new WVec(0, 0, cp.Z)); var wasInAttackRange = inAttackRange; @@ -59,7 +57,7 @@ namespace OpenRA.Mods.RA continue; inAttackRange = true; - a.CheckFire(self, this, facing.Value, bombTarget); + a.CheckFire(self, facing.Value, bombTarget); } // Guns only fire when approaching the target @@ -74,7 +72,7 @@ namespace OpenRA.Mods.RA var t = Target.FromPos(cp - new WVec(0, a.Weapon.Range.Range / 2, cp.Z).Rotate(WRot.FromFacing(f))); inAttackRange = true; - a.CheckFire(self, this, facing.Value, t); + a.CheckFire(self, facing.Value, t); } } diff --git a/OpenRA.Mods.RA/Render/RenderUnitReload.cs b/OpenRA.Mods.RA/Render/RenderUnitReload.cs index ffc5e63f11..b3f9599c4a 100755 --- a/OpenRA.Mods.RA/Render/RenderUnitReload.cs +++ b/OpenRA.Mods.RA/Render/RenderUnitReload.cs @@ -1,6 +1,6 @@ #region Copyright & License Information /* - * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) + * Copyright 2007-2014 The OpenRA Developers (see AUTHORS) * This file is part of OpenRA, which is free software. It is made * available to you under the terms of the GNU General Public License * as published by the Free Software Foundation. For more information, @@ -8,25 +8,39 @@ */ #endregion +using System.Linq; +using OpenRA.FileFormats; +using OpenRA.Traits; + namespace OpenRA.Mods.RA.Render { - class RenderUnitReloadInfo : RenderUnitInfo + class RenderUnitReloadInfo : RenderUnitInfo, Requires, Requires { - public override object Create(ActorInitializer init) { return new RenderUnitReload(init.self); } + [Desc("Armament name")] + public readonly string Armament = "primary"; + + public override object Create(ActorInitializer init) { return new RenderUnitReload(init.self, this); } } class RenderUnitReload : RenderUnit { - public RenderUnitReload(Actor self) - : base(self) { } + readonly AttackBase attack; + readonly Armament armament; + + public RenderUnitReload(Actor self, RenderUnitReloadInfo info) + : base(self) + { + attack = self.Trait(); + armament = self.TraitsImplementing() + .Single(a => a.Info.Name == info.Armament); + } public override void Tick(Actor self) { - var attack = self.TraitOrDefault(); + var sequence = (armament.IsReloading ? "empty-" : "") + (attack.IsAttacking ? "aim" : "idle"); + if (sequence != anim.CurrentSequence.Name) + anim.ReplaceAnim(sequence); - if (attack != null) - anim.ReplaceAnim((attack.IsReloading() ? "empty-" : "") - + (attack.IsAttacking ? "aim" : "idle")); base.Tick(self); } }