diff --git a/OpenRA.Mods.Cnc/Graphics/ClassicSpriteSequence.cs b/OpenRA.Mods.Cnc/Graphics/ClassicSpriteSequence.cs index eea3c404fb..6d15743236 100644 --- a/OpenRA.Mods.Cnc/Graphics/ClassicSpriteSequence.cs +++ b/OpenRA.Mods.Cnc/Graphics/ClassicSpriteSequence.cs @@ -44,7 +44,7 @@ namespace OpenRA.Mods.Cnc.Graphics protected override int GetFacingFrameOffset(WAngle facing) { - return Util.ClassicQuantizeFacing(facing.Facing, Facings, useClassicFacings); + return useClassicFacings ? Util.ClassicIndexFacing(facing.Facing, Facings) : Common.Util.IndexFacing(facing.Facing, Facings); } } } diff --git a/OpenRA.Mods.Cnc/Traits/ClassicFacingBodyOrientation.cs b/OpenRA.Mods.Cnc/Traits/ClassicFacingBodyOrientation.cs index feb2045678..493a3a7c1a 100644 --- a/OpenRA.Mods.Cnc/Traits/ClassicFacingBodyOrientation.cs +++ b/OpenRA.Mods.Cnc/Traits/ClassicFacingBodyOrientation.cs @@ -18,7 +18,7 @@ namespace OpenRA.Mods.Cnc.Traits { public override int QuantizeFacing(int facing, int facings) { - return OpenRA.Mods.Cnc.Util.ClassicQuantizeFacing(facing, facings, true) * (256 / facings); + return Util.ClassicQuantizeFacing(facing, facings); } public override object Create(ActorInitializer init) { return new ClassicFacingBodyOrientation(init, this); } diff --git a/OpenRA.Mods.Cnc/Util.cs b/OpenRA.Mods.Cnc/Util.cs index 8864a6484c..ef7a7ba615 100644 --- a/OpenRA.Mods.Cnc/Util.cs +++ b/OpenRA.Mods.Cnc/Util.cs @@ -17,7 +17,7 @@ namespace OpenRA.Mods.Cnc // This table defines the exclusive maximum facing for the i'th sprite frame. // i.e. sprite frame 1 is used for facings 5-13, sprite frame 2 for 14-21, and so on. // Sprite frame 0 is used for facings smaller than 5 or larger than 249. - static readonly int[] SpriteFacings = + static readonly int[] SpriteRanges = { 5, 14, 22, 33, 39, 46, 53, 60, 67, 74, 81, 88, 96, 104, 113, 122, @@ -25,18 +25,44 @@ namespace OpenRA.Mods.Cnc 195, 202, 209, 216, 224, 232, 241, 250 }; - public static int ClassicQuantizeFacing(int facing, int numFrames, bool useClassicFacingFudge) + // The actual facing associated with each sprite frame. + static readonly int[] SpriteFacings = { - if (useClassicFacingFudge && numFrames == 32) + 0, 10, 18, 28, 36, 43, 50, 57, + 64, 71, 78, 85, 92, 100, 109, 118, + 128, 138, 147, 156, 164, 171, 178, 185, + 192, 199, 206, 213, 220, 228, 237, 246 + }; + + /// + /// Calculate the frame index (between 0..numFrames) that + /// should be used for the given facing value, accounting + /// for the non-linear facing mapping for sprites with 32 directions. + /// + public static int ClassicIndexFacing(int facing, int numFrames) + { + if (numFrames == 32) { - for (var i = 0; i < SpriteFacings.Length; i++) - if (facing < SpriteFacings[i]) + for (var i = 0; i < SpriteRanges.Length; i++) + if (facing < SpriteRanges[i]) return i; return 0; } - return Common.Util.QuantizeFacing(facing, numFrames); + return Common.Util.IndexFacing(facing, numFrames); + } + + /// + /// Rounds the given facing value to the nearest quantized step, + /// accounting for the non-linear facing mapping for sprites with 32 directions. + /// + public static int ClassicQuantizeFacing(int facing, int steps) + { + if (steps == 32) + return SpriteFacings[ClassicIndexFacing(facing, steps)]; + + return Common.Util.QuantizeFacing(facing, steps); } } } diff --git a/OpenRA.Mods.Common/Graphics/DefaultSpriteSequence.cs b/OpenRA.Mods.Common/Graphics/DefaultSpriteSequence.cs index 525569185b..41b570e9d4 100644 --- a/OpenRA.Mods.Common/Graphics/DefaultSpriteSequence.cs +++ b/OpenRA.Mods.Common/Graphics/DefaultSpriteSequence.cs @@ -395,7 +395,7 @@ namespace OpenRA.Mods.Common.Graphics protected virtual int GetFacingFrameOffset(WAngle facing) { - return Util.QuantizeFacing(facing.Facing, Facings); + return Util.IndexFacing(facing.Facing, Facings); } } } diff --git a/OpenRA.Mods.Common/Traits/Attack/AttackGarrisoned.cs b/OpenRA.Mods.Common/Traits/Attack/AttackGarrisoned.cs index b07124fd4f..cdbc428a59 100644 --- a/OpenRA.Mods.Common/Traits/Attack/AttackGarrisoned.cs +++ b/OpenRA.Mods.Common/Traits/Attack/AttackGarrisoned.cs @@ -176,7 +176,7 @@ namespace OpenRA.Mods.Common.Traits var sequence = a.Info.MuzzleSequence; if (a.Info.MuzzleSplitFacings > 0) - sequence += Util.QuantizeFacing(muzzleFacing, a.Info.MuzzleSplitFacings).ToString(); + sequence += Util.IndexFacing(muzzleFacing, a.Info.MuzzleSplitFacings).ToString(); var muzzleFlash = new AnimationWithOffset(muzzleAnim, () => PortOffset(self, port), diff --git a/OpenRA.Mods.Common/Traits/BodyOrientation.cs b/OpenRA.Mods.Common/Traits/BodyOrientation.cs index 1bf6275dfd..5ca0182f08 100644 --- a/OpenRA.Mods.Common/Traits/BodyOrientation.cs +++ b/OpenRA.Mods.Common/Traits/BodyOrientation.cs @@ -52,7 +52,7 @@ namespace OpenRA.Mods.Common.Traits public virtual int QuantizeFacing(int facing, int facings) { - return Util.QuantizeFacing(facing, facings) * (256 / facings); + return Util.QuantizeFacing(facing, facings); } public override object Create(ActorInitializer init) { return new BodyOrientation(init, this); } diff --git a/OpenRA.Mods.Common/Traits/Render/WithMuzzleOverlay.cs b/OpenRA.Mods.Common/Traits/Render/WithMuzzleOverlay.cs index 8d4694006f..ede50674f6 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithMuzzleOverlay.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithMuzzleOverlay.cs @@ -79,7 +79,7 @@ namespace OpenRA.Mods.Common.Traits.Render var sequence = a.Info.MuzzleSequence; if (a.Info.MuzzleSplitFacings > 0) - sequence += Util.QuantizeFacing(getFacing().Facing, a.Info.MuzzleSplitFacings).ToString(); + sequence += Util.IndexFacing(getFacing().Facing, a.Info.MuzzleSplitFacings).ToString(); visible[barrel] = true; anims[barrel].Animation.PlayThen(sequence, () => visible[barrel] = false); diff --git a/OpenRA.Mods.Common/Util.cs b/OpenRA.Mods.Common/Util.cs index bef861098d..2b3f2a6fb8 100644 --- a/OpenRA.Mods.Common/Util.cs +++ b/OpenRA.Mods.Common/Util.cs @@ -46,13 +46,23 @@ namespace OpenRA.Mods.Common return facing + turn; } - public static int QuantizeFacing(int facing, int numFrames) + /// + /// Calculate the frame index (between 0..numFrames) that + /// should be used for the given facing value. + /// + public static int IndexFacing(int facing, int numFrames) { var step = 256 / numFrames; var a = (facing + step / 2) & 0xff; return a / step; } + /// Rounds the given facing value to the nearest quantized step. + public static int QuantizeFacing(int facing, int steps) + { + return IndexFacing(facing, steps) * (256 / steps); + } + /// Wraps an arbitrary integer facing value into the range 0 - 255 public static int NormalizeFacing(int f) {