From acc9b37a015e6c7ff2590137392c150175c634e4 Mon Sep 17 00:00:00 2001 From: reaperrr Date: Sun, 6 Dec 2015 02:32:25 +0100 Subject: [PATCH 1/3] Remove ITraitInfo from AttackBase That is already included in UpgradableTraitInfo. --- OpenRA.Mods.Common/Traits/Attack/AttackBase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenRA.Mods.Common/Traits/Attack/AttackBase.cs b/OpenRA.Mods.Common/Traits/Attack/AttackBase.cs index 9fe9105413..615575fd14 100644 --- a/OpenRA.Mods.Common/Traits/Attack/AttackBase.cs +++ b/OpenRA.Mods.Common/Traits/Attack/AttackBase.cs @@ -18,7 +18,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { - public abstract class AttackBaseInfo : UpgradableTraitInfo, ITraitInfo + public abstract class AttackBaseInfo : UpgradableTraitInfo { [Desc("Armament names")] public readonly string[] Armaments = { "primary", "secondary" }; From 0e5ea959aa2411038b1a0bf8a861eda7d1a624fc Mon Sep 17 00:00:00 2001 From: reaperrr Date: Sun, 6 Dec 2015 03:08:31 +0100 Subject: [PATCH 2/3] Perform faster checks in AB.CanAttack much earlier Move self.IsDisabled right after IsInWorld and IsTraitDisabled checks. This should skip/avoid a lot of the following checks when actors are disabled by low power, EMP or similar, potentially saving some performance when there are many disabled actors with attack trait. Move IsValidFor before HasAnyValidWeapons because the latter is more expensive. --- OpenRA.Mods.Common/Traits/Attack/AttackBase.cs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/OpenRA.Mods.Common/Traits/Attack/AttackBase.cs b/OpenRA.Mods.Common/Traits/Attack/AttackBase.cs index 615575fd14..55fa16cb62 100644 --- a/OpenRA.Mods.Common/Traits/Attack/AttackBase.cs +++ b/OpenRA.Mods.Common/Traits/Attack/AttackBase.cs @@ -70,7 +70,10 @@ namespace OpenRA.Mods.Common.Traits protected virtual bool CanAttack(Actor self, Target target) { - if (!self.IsInWorld || IsTraitDisabled) + if (!self.IsInWorld || IsTraitDisabled || self.IsDisabled()) + return false; + + if (!target.IsValidFor(self)) return false; if (!HasAnyValidWeapons(target)) @@ -80,15 +83,9 @@ namespace OpenRA.Mods.Common.Traits if (building.Value != null && !building.Value.BuildComplete) return false; - if (!target.IsValidFor(self)) - return false; - if (Armaments.All(a => a.IsReloading)) return false; - if (self.IsDisabled()) - return false; - if (target.Type == TargetType.Actor && !self.Owner.CanTargetActor(target.Actor)) return false; From 2d55bbdedf2ba1851df47692c652fe71932be8a9 Mon Sep 17 00:00:00 2001 From: reaperrr Date: Sun, 6 Dec 2015 02:39:19 +0100 Subject: [PATCH 3/3] Cache trait look-ups and range modifiers directly in Armament Avoid the performance impact of accessing Lazy.Value by caching them when the actor is created and accessing the references directly when needed. --- OpenRA.Mods.Common/Traits/Armament.cs | 42 ++++++++++++++------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/OpenRA.Mods.Common/Traits/Armament.cs b/OpenRA.Mods.Common/Traits/Armament.cs index 3c64116f34..5bf642ef11 100644 --- a/OpenRA.Mods.Common/Traits/Armament.cs +++ b/OpenRA.Mods.Common/Traits/Armament.cs @@ -87,17 +87,17 @@ namespace OpenRA.Mods.Common.Traits } } - public class Armament : UpgradableTrait, ITick, IExplodeModifier + public class Armament : UpgradableTrait, INotifyCreated, ITick, IExplodeModifier { public readonly WeaponInfo Weapon; public readonly Barrel[] Barrels; readonly Actor self; - Lazy turret; - Lazy coords; - Lazy ammoPool; + Turreted turret; + AmmoPool ammoPool; + BodyOrientation coords; + IEnumerable rangeModifiers; List> delayedActions = new List>(); - Lazy> rangeModifiers; public WDist Recoil; public int FireDelay { get; private set; } @@ -108,12 +108,6 @@ namespace OpenRA.Mods.Common.Traits { this.self = self; - // We can't resolve these until runtime - turret = Exts.Lazy(() => self.TraitsImplementing().FirstOrDefault(t => t.Name == info.Turret)); - coords = Exts.Lazy(() => self.Trait()); - ammoPool = Exts.Lazy(() => self.TraitsImplementing().FirstOrDefault(la => la.Info.Name == info.AmmoPoolName)); - rangeModifiers = Exts.Lazy(() => self.TraitsImplementing().ToArray().Select(m => m.GetRangeModifier())); - Weapon = info.WeaponInfo; Burst = Weapon.Burst; @@ -135,7 +129,15 @@ namespace OpenRA.Mods.Common.Traits public WDist MaxRange() { - return new WDist(Util.ApplyPercentageModifiers(Weapon.Range.Length, rangeModifiers.Value)); + return new WDist(Util.ApplyPercentageModifiers(Weapon.Range.Length, rangeModifiers)); + } + + public void Created(Actor self) + { + turret = self.TraitsImplementing().FirstOrDefault(t => t.Name == Info.Turret); + ammoPool = self.TraitsImplementing().FirstOrDefault(la => la.Info.Name == Info.AmmoPoolName); + coords = self.Trait(); + rangeModifiers = self.TraitsImplementing().ToArray().Select(m => m.GetRangeModifier()); } public void Tick(Actor self) @@ -174,7 +176,7 @@ namespace OpenRA.Mods.Common.Traits if (IsReloading) return null; - if (ammoPool.Value != null && !ammoPool.Value.HasAmmo()) + if (ammoPool != null && !ammoPool.HasAmmo()) return null; if (!target.IsInRange(self.CenterPosition, MaxRange())) @@ -247,23 +249,23 @@ namespace OpenRA.Mods.Common.Traits public WVec MuzzleOffset(Actor self, Barrel b) { - var bodyOrientation = coords.Value.QuantizeOrientation(self, self.Orientation); + var bodyOrientation = coords.QuantizeOrientation(self, self.Orientation); var localOffset = b.Offset + new WVec(-Recoil, WDist.Zero, WDist.Zero); - if (turret.Value != null) + if (turret != null) { - var turretOrientation = coords.Value.QuantizeOrientation(self, turret.Value.LocalOrientation(self)); + var turretOrientation = coords.QuantizeOrientation(self, turret.LocalOrientation(self)); localOffset = localOffset.Rotate(turretOrientation); - localOffset += turret.Value.Offset; + localOffset += turret.Offset; } - return coords.Value.LocalToWorld(localOffset.Rotate(bodyOrientation)); + return coords.LocalToWorld(localOffset.Rotate(bodyOrientation)); } public WRot MuzzleOrientation(Actor self, Barrel b) { var orientation = self.Orientation + WRot.FromYaw(b.Yaw); - if (turret.Value != null) - orientation += turret.Value.LocalOrientation(self); + if (turret != null) + orientation += turret.LocalOrientation(self); return orientation; }