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.
This commit is contained in:
RoosterDragon
2025-04-10 22:03:17 +01:00
committed by Gustas Kažukauskas
parent d459d3883d
commit 5676d7be40
4 changed files with 31 additions and 4 deletions

View File

@@ -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);
}

View File

@@ -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;
});
}

View File

@@ -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<RenderSpritesInfo>();
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); }

View File

@@ -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;