From 5676d7be40a31ddfd9b89a90dad8a9c5eb1fa7d2 Mon Sep 17 00:00:00 2001 From: RoosterDragon Date: Thu, 10 Apr 2025 22:03:17 +0100 Subject: [PATCH] Prevent crash when using QuantizedFacings: 0 on BodyOrientation. This override allows quantization to be disabled, and is used by the TS mod as the voxel based actors can be rotated to any orientation/facing. To prevent a divide by zero error for these actors, we need to return early from QuantizeFacing just like we do in QuantizeOrientation. However, when QuantizedFacings is not explicitly set to zero, we still want to catch errors when artwork sequences have zero facings. The new check would cause such errors to be hidden. To prevent this add some exceptions with a detailed error message. --- .../Traits/ClassicFacingBodyOrientation.cs | 4 ++++ OpenRA.Mods.Common/Traits/BodyOrientation.cs | 12 ++++++++++-- .../Traits/QuantizeFacingsFromSequence.cs | 7 ++++++- OpenRA.Mods.Common/Traits/Turreted.cs | 12 +++++++++++- 4 files changed, 31 insertions(+), 4 deletions(-) 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;