diff --git a/OpenRA.Mods.Cnc/Traits/ClassicFacingBodyOrientation.cs b/OpenRA.Mods.Cnc/Traits/ClassicFacingBodyOrientation.cs index 90ca6011a8..609bb78c0c 100644 --- a/OpenRA.Mods.Cnc/Traits/ClassicFacingBodyOrientation.cs +++ b/OpenRA.Mods.Cnc/Traits/ClassicFacingBodyOrientation.cs @@ -18,6 +18,10 @@ namespace OpenRA.Mods.Cnc.Traits { public override WAngle QuantizeFacing(WAngle facing, int facings) { + // Quantization disabled + if (facings == 0) + return facing; + return Util.ClassicQuantizeFacing(facing, facings); } diff --git a/OpenRA.Mods.Common/Traits/BodyOrientation.cs b/OpenRA.Mods.Common/Traits/BodyOrientation.cs index 767933d44f..e16fbd649f 100644 --- a/OpenRA.Mods.Common/Traits/BodyOrientation.cs +++ b/OpenRA.Mods.Common/Traits/BodyOrientation.cs @@ -17,7 +17,7 @@ namespace OpenRA.Mods.Common.Traits { public class BodyOrientationInfo : TraitInfo { - [Desc("Number of facings for gameplay calculations. -1 indicates auto-detection from another trait.")] + [Desc("Number of facings for gameplay calculations. -1 indicates auto-detection from another trait. 0 disables quantization.")] public readonly int QuantizedFacings = -1; [Desc("Camera pitch for rotation calculations.")] @@ -52,6 +52,10 @@ namespace OpenRA.Mods.Common.Traits public virtual WAngle QuantizeFacing(WAngle facing, int facings) { + // Quantization disabled + if (facings == 0) + return facing; + return Util.QuantizeFacing(facing, facings); } @@ -90,7 +94,11 @@ namespace OpenRA.Mods.Common.Traits throw new InvalidOperationException("Actor type '" + self.Info.Name + "' does not define a quantized body orientation."); } - return qboi.QuantizedBodyFacings(self.Info, self.World.Map.Sequences, faction); + var facings = qboi.QuantizedBodyFacings(self.Info, self.World.Map.Sequences, faction); + if (facings == 0) + throw new InvalidOperationException($"Actor {self.Info.Name} defines a quantized body orientation from {qboi.GetType().Name} with zero facings."); + + return facings; }); } diff --git a/OpenRA.Mods.Common/Traits/QuantizeFacingsFromSequence.cs b/OpenRA.Mods.Common/Traits/QuantizeFacingsFromSequence.cs index d96134a991..10a5cc35b9 100644 --- a/OpenRA.Mods.Common/Traits/QuantizeFacingsFromSequence.cs +++ b/OpenRA.Mods.Common/Traits/QuantizeFacingsFromSequence.cs @@ -29,7 +29,12 @@ namespace OpenRA.Mods.Common.Traits throw new InvalidOperationException($"Actor {ai.Name} is missing sequence to quantize facings from."); var rsi = ai.TraitInfo(); - return sequences.GetSequence(rsi.GetImage(ai, faction), Sequence).Facings; + var image = rsi.GetImage(ai, faction); + var facings = sequences.GetSequence(image, Sequence).Facings; + if (facings == 0) + throw new InvalidOperationException( + $"Actor {ai.Name} defines a quantized body orientation with zero facings. Faction: {faction} Image: {image} Sequence: {Sequence}"); + return facings; } public override object Create(ActorInitializer init) { return new QuantizeFacingsFromSequence(this); } diff --git a/OpenRA.Mods.Common/Traits/Turreted.cs b/OpenRA.Mods.Common/Traits/Turreted.cs index 3aa845909b..90a0797a6e 100644 --- a/OpenRA.Mods.Common/Traits/Turreted.cs +++ b/OpenRA.Mods.Common/Traits/Turreted.cs @@ -132,9 +132,19 @@ namespace OpenRA.Mods.Common.Traits AttackTurreted attack; IFacing facing; BodyOrientation body; + int quantizedFacings; [Sync] - public int QuantizedFacings = 0; + public int QuantizedFacings + { + get => quantizedFacings; + set + { + if (value == 0) + throw new ArgumentOutOfRangeException(nameof(value), value, "Expected nonzero facings for turret."); + quantizedFacings = value; + } + } WVec desiredDirection; int realignTick = 0;