Initial commit: OpenRA game engine
Fork from OpenRA/OpenRA with one-click launch script (start-ra.cmd) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
127
OpenRA.Mods.Common/Traits/BodyOrientation.cs
Normal file
127
OpenRA.Mods.Common/Traits/BodyOrientation.cs
Normal file
@@ -0,0 +1,127 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright (c) The OpenRA Developers and Contributors
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using OpenRA.Mods.Common.Traits.Render;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.Common.Traits
|
||||
{
|
||||
public class BodyOrientationInfo : TraitInfo
|
||||
{
|
||||
[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.")]
|
||||
public readonly WAngle CameraPitch = WAngle.FromDegrees(40);
|
||||
|
||||
[Desc("Fudge the coordinate system angles to simulate non-top-down perspective in mods with square cells.")]
|
||||
public readonly bool UseClassicPerspectiveFudge = true;
|
||||
|
||||
public WVec LocalToWorld(in WVec vec)
|
||||
{
|
||||
// Rotate by 90 degrees
|
||||
if (!UseClassicPerspectiveFudge)
|
||||
return new WVec(vec.Y, -vec.X, vec.Z);
|
||||
|
||||
// The 2d perspective of older games with square cells doesn't correspond to an orthonormal 3D
|
||||
// coordinate system, so fudge the y axis to make things look good
|
||||
return new WVec(vec.Y, -CameraPitch.Sin() * vec.X / 1024, vec.Z);
|
||||
}
|
||||
|
||||
public WRot QuantizeOrientation(in WRot orientation, int facings)
|
||||
{
|
||||
// Quantization disabled
|
||||
if (facings == 0)
|
||||
return orientation;
|
||||
|
||||
// Map yaw to the closest facing
|
||||
var facing = QuantizeFacing(orientation.Yaw, facings);
|
||||
|
||||
// Roll and pitch are always zero if yaw is quantized
|
||||
return WRot.FromYaw(facing);
|
||||
}
|
||||
|
||||
public virtual WAngle QuantizeFacing(WAngle facing, int facings)
|
||||
{
|
||||
// Quantization disabled
|
||||
if (facings == 0)
|
||||
return facing;
|
||||
|
||||
return Util.QuantizeFacing(facing, facings);
|
||||
}
|
||||
|
||||
public override object Create(ActorInitializer init) { return new BodyOrientation(init, this); }
|
||||
}
|
||||
|
||||
public class BodyOrientation : ISync
|
||||
{
|
||||
readonly BodyOrientationInfo info;
|
||||
readonly Lazy<int> quantizedFacings;
|
||||
|
||||
[VerifySync]
|
||||
public int QuantizedFacings => quantizedFacings.Value;
|
||||
|
||||
public BodyOrientation(ActorInitializer init, BodyOrientationInfo info)
|
||||
{
|
||||
this.info = info;
|
||||
var self = init.Self;
|
||||
var faction = init.GetValue<FactionInit, string>(self.Owner.Faction.InternalName);
|
||||
|
||||
quantizedFacings = Exts.Lazy(() =>
|
||||
{
|
||||
// Override value is set
|
||||
if (info.QuantizedFacings >= 0)
|
||||
return info.QuantizedFacings;
|
||||
|
||||
var qboi = self.Info.TraitInfoOrDefault<IQuantizeBodyOrientationInfo>();
|
||||
|
||||
// If a sprite actor has neither custom QuantizedFacings nor a trait implementing IQuantizeBodyOrientationInfo, throw
|
||||
if (qboi == null)
|
||||
{
|
||||
if (self.Info.HasTraitInfo<WithSpriteBodyInfo>())
|
||||
throw new InvalidOperationException("Actor '" + self.Info.Name + "' has a sprite body but no facing quantization."
|
||||
+ " Either add the QuantizeFacingsFromSequence trait or set custom QuantizedFacings on BodyOrientation.");
|
||||
else
|
||||
throw new InvalidOperationException("Actor type '" + self.Info.Name + "' does not define a quantized body orientation.");
|
||||
}
|
||||
|
||||
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;
|
||||
});
|
||||
}
|
||||
|
||||
public WAngle CameraPitch => info.CameraPitch;
|
||||
|
||||
public WVec LocalToWorld(in WVec vec)
|
||||
{
|
||||
return info.LocalToWorld(vec);
|
||||
}
|
||||
|
||||
public WRot QuantizeOrientation(in WRot orientation)
|
||||
{
|
||||
return info.QuantizeOrientation(orientation, quantizedFacings.Value);
|
||||
}
|
||||
|
||||
public WAngle QuantizeFacing(WAngle facing)
|
||||
{
|
||||
return info.QuantizeFacing(facing, quantizedFacings.Value);
|
||||
}
|
||||
|
||||
public WAngle QuantizeFacing(WAngle facing, int facings)
|
||||
{
|
||||
return info.QuantizeFacing(facing, facings);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user