diff --git a/OpenRa.Game/Exts.cs b/OpenRa.Game/Exts.cs index b66ad80010..cc04e81a91 100644 --- a/OpenRa.Game/Exts.cs +++ b/OpenRa.Game/Exts.cs @@ -22,5 +22,10 @@ namespace OpenRa.Game // this is probably a shockingly-slow way to do this, but it's concise. return xs.Except(ys).Concat(ys.Except(xs)); } + + public static float Product(this IEnumerable xs) + { + return xs.Aggregate((a, x) => a * x); + } } } diff --git a/OpenRa.Game/Traits/Activities/Move.cs b/OpenRa.Game/Traits/Activities/Move.cs index 4392571a68..c63702b180 100755 --- a/OpenRa.Game/Traits/Activities/Move.cs +++ b/OpenRa.Game/Traits/Activities/Move.cs @@ -168,11 +168,7 @@ namespace OpenRa.Game.Traits.Activities var oldFraction = moveFraction; var oldTotal = moveFractionTotal; - var actualSpeed = (int)self.traits.WithInterface().Aggregate( - (float)(self.Info as MobileInfo).Speed, - (a, t) => t.GetSpeedModifier() * a); - - moveFraction += actualSpeed; + moveFraction += (int)Util.GetEffectiveSpeed(self); UpdateCenterLocation( self, mobile ); if( moveFraction >= moveFractionTotal ) { diff --git a/OpenRa.Game/Traits/Helicopter.cs b/OpenRa.Game/Traits/Helicopter.cs index 5a958f16ee..2b16d5432d 100644 --- a/OpenRa.Game/Traits/Helicopter.cs +++ b/OpenRa.Game/Traits/Helicopter.cs @@ -48,12 +48,7 @@ namespace OpenRa.Game.Traits Util.TickFacing(ref unit.Facing, desiredFacing, self.Info.ROT); - var actualSpeed = self.traits.WithInterface().Aggregate( - (float)(self.Info as MobileInfo).Speed, - (a, t) => t.GetSpeedModifier() * a); - - // .6f going the wrong way; .8f going sideways, 1f going forward. - var rawSpeed = .2f * actualSpeed; + var rawSpeed = .2f * Util.GetEffectiveSpeed(self); var angle = (unit.Facing - desiredFacing) / 128f * Math.PI; var scale = .4f + .6f * (float)Math.Cos(angle); diff --git a/OpenRa.Game/Traits/Mobile.cs b/OpenRa.Game/Traits/Mobile.cs index 8b242b842c..8e8908f13f 100644 --- a/OpenRa.Game/Traits/Mobile.cs +++ b/OpenRa.Game/Traits/Mobile.cs @@ -32,6 +32,7 @@ namespace OpenRa.Game.Traits { if (mi.Button == MouseButton.Left) return null; if (underCursor != null) return null; + if (Util.GetEffectiveSpeed(self) == 0) return null; /* allow disabling move orders from modifiers */ if (xy == toCell) return null; return Order.Move(self, xy); } diff --git a/OpenRa.Game/Traits/Util.cs b/OpenRa.Game/Traits/Util.cs index 818688e05f..e3a77389db 100755 --- a/OpenRa.Game/Traits/Util.cs +++ b/OpenRa.Game/Traits/Util.cs @@ -1,6 +1,7 @@ using System; using System.Linq; using OpenRa.Game.Graphics; +using OpenRa.Game.GameRules; namespace OpenRa.Game.Traits { @@ -124,5 +125,17 @@ namespace OpenRa.Game.Traits var loc = location - 0.5f * s.size; return Tuple.New(s, loc.Round(), 8); } + + public static float GetEffectiveSpeed(Actor self) + { + var mi = self.Info as MobileInfo; + if (mi == null) return 0f; + + var modifier = self.traits + .WithInterface() + .Select(t => t.GetSpeedModifier()) + .Product(); + return mi.Speed * modifier; + } } }