diff --git a/OpenRA.Game/OpenRA.Game.csproj b/OpenRA.Game/OpenRA.Game.csproj
index d917cb4b66..ce040adc49 100644
--- a/OpenRA.Game/OpenRA.Game.csproj
+++ b/OpenRA.Game/OpenRA.Game.csproj
@@ -226,6 +226,7 @@
+
diff --git a/OpenRA.Game/Traits/BodyOrientation.cs b/OpenRA.Game/Traits/BodyOrientation.cs
new file mode 100755
index 0000000000..653030a6da
--- /dev/null
+++ b/OpenRA.Game/Traits/BodyOrientation.cs
@@ -0,0 +1,58 @@
+#region Copyright & License Information
+/*
+ * Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
+ * 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. For more information,
+ * see COPYING.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using OpenRA.Graphics;
+using OpenRA.FileFormats;
+
+namespace OpenRA.Traits
+{
+ public class BodyOrientationInfo : ITraitInfo, IBodyOrientationInfo
+ {
+ [Desc("Camera pitch for rotation calculations")]
+ public readonly WAngle CameraPitch = WAngle.FromDegrees(40);
+ public object Create(ActorInitializer init) { return new BodyOrientation(init.self, this); }
+ }
+
+ public class BodyOrientation : IBodyOrientation
+ {
+ [Sync] public int QuantizedFacings { get; set; }
+ BodyOrientationInfo Info;
+
+ public BodyOrientation(Actor self, BodyOrientationInfo info)
+ {
+ Info = info;
+ }
+
+ public WAngle CameraPitch { get { return Info.CameraPitch; } }
+
+ public WVec LocalToWorld(WVec vec)
+ {
+ // RA's 2d perspective doesn't correspond to an orthonormal 3D
+ // coordinate system, so fudge the y axis to make things look good
+ return new WVec(vec.Y, -Info.CameraPitch.Sin()*vec.X/1024, vec.Z);
+ }
+
+ public WRot QuantizeOrientation(Actor self, WRot orientation)
+ {
+ // Quantization disabled
+ if (QuantizedFacings == 0)
+ return orientation;
+
+ // Map yaw to the closest facing
+ var facing = Util.QuantizeFacing(orientation.Yaw.Angle / 4, QuantizedFacings) * (256 / QuantizedFacings);
+
+ // Roll and pitch are always zero if yaw is quantized
+ return new WRot(WAngle.Zero, WAngle.Zero, WAngle.FromFacing(facing));
+ }
+ }
+}
diff --git a/OpenRA.Game/Traits/Render/RenderSimple.cs b/OpenRA.Game/Traits/Render/RenderSimple.cs
index 2f091ad5bd..36716979b1 100755
--- a/OpenRA.Game/Traits/Render/RenderSimple.cs
+++ b/OpenRA.Game/Traits/Render/RenderSimple.cs
@@ -16,13 +16,8 @@ using OpenRA.FileFormats;
namespace OpenRA.Traits
{
- public class RenderSimpleInfo : RenderSpritesInfo, IBodyOrientationInfo
+ public class RenderSimpleInfo : RenderSpritesInfo, Requires
{
- [Desc("Number of facings for gameplay calculations. -1 indiciates auto-detection from sequence")]
- public readonly int QuantizedFacings = -1;
-
- [Desc("Camera pitch the sprite was rendered with. Used to determine rotation ellipses")]
- public readonly WAngle CameraPitch = WAngle.FromDegrees(40);
public override object Create(ActorInitializer init) { return new RenderSimple(init.self); }
public virtual IEnumerable RenderPreview(ActorInfo ai, PaletteReference pr)
@@ -34,7 +29,7 @@ namespace OpenRA.Traits
}
}
- public class RenderSimple : RenderSprites, IBodyOrientation, IAutoSelectionSize
+ public class RenderSimple : RenderSprites, IAutoSelectionSize
{
RenderSimpleInfo Info;
@@ -49,6 +44,7 @@ namespace OpenRA.Traits
: this(self, MakeFacingFunc(self))
{
anim.PlayRepeating("idle");
+ self.Trait().QuantizedFacings = anim.CurrentSequence.Facings;
}
public int2 SelectionSize(Actor self)
@@ -74,22 +70,5 @@ namespace OpenRA.Traits
anim.PlayThen(NormalizeSequence(self, name),
() => anim.PlayRepeating(NormalizeSequence(self, "idle")));
}
-
- public WVec LocalToWorld(WVec vec)
- {
- // RA's 2d perspective doesn't correspond to an orthonormal 3D
- // coordinate system, so fudge the y axis to make things look good
- return new WVec(vec.Y, -Info.CameraPitch.Sin()*vec.X/1024, vec.Z);
- }
-
- public WRot QuantizeOrientation(Actor self, WRot orientation)
- {
- // Map yaw to the closest facing
- var numDirs = Info.QuantizedFacings == -1 ? anim.CurrentSequence.Facings : Info.QuantizedFacings;
- var facing = Util.QuantizeFacing(orientation.Yaw.Angle / 4, numDirs) * (256 / numDirs);
-
- // Roll and pitch are always zero
- return new WRot(WAngle.Zero, WAngle.Zero, WAngle.FromFacing(facing));
- }
}
}
diff --git a/OpenRA.Game/Traits/TraitsInterfaces.cs b/OpenRA.Game/Traits/TraitsInterfaces.cs
index 8138b6a872..4361998394 100755
--- a/OpenRA.Game/Traits/TraitsInterfaces.cs
+++ b/OpenRA.Game/Traits/TraitsInterfaces.cs
@@ -189,6 +189,8 @@ namespace OpenRA.Traits
public interface IRenderAsTerrain { IEnumerable RenderAsTerrain(WorldRenderer wr, Actor self); }
public interface IBodyOrientation
{
+ WAngle CameraPitch { get; }
+ int QuantizedFacings { get; set; }
WVec LocalToWorld(WVec vec);
WRot QuantizeOrientation(Actor self, WRot orientation);
}
diff --git a/OpenRA.Mods.Cnc/RenderGunboat.cs b/OpenRA.Mods.Cnc/RenderGunboat.cs
index 694f3a1a03..1e8a29fa34 100644
--- a/OpenRA.Mods.Cnc/RenderGunboat.cs
+++ b/OpenRA.Mods.Cnc/RenderGunboat.cs
@@ -45,6 +45,8 @@ namespace OpenRA.Mods.RA.Render
anims.Add("wake", new AnimationWithOffset(wake,
() => anims["wake"].Animation.CurrentSequence.Name == "left-wake" ? leftOffset : rightOffset,
() => false, -87));
+
+ self.Trait().QuantizedFacings = anim.CurrentSequence.Facings;
}
public override void Tick(Actor self)
diff --git a/OpenRA.Mods.RA/Render/RenderBuilding.cs b/OpenRA.Mods.RA/Render/RenderBuilding.cs
index 7fd16390df..d5cb08f4d6 100755
--- a/OpenRA.Mods.RA/Render/RenderBuilding.cs
+++ b/OpenRA.Mods.RA/Render/RenderBuilding.cs
@@ -57,6 +57,7 @@ namespace OpenRA.Mods.RA.Render
var self = init.self;
// Work around a bogus crash
anim.PlayRepeating( NormalizeSequence(self, "idle") );
+ self.Trait().QuantizedFacings = anim.CurrentSequence.Facings;
// Can't call Complete() directly from ctor because other traits haven't been inited yet
if (self.Info.Traits.Get().HasMakeAnimation && !init.Contains())
diff --git a/OpenRA.Mods.RA/Render/RenderInfantry.cs b/OpenRA.Mods.RA/Render/RenderInfantry.cs
index 5103fc84d7..c23055f3a6 100644
--- a/OpenRA.Mods.RA/Render/RenderInfantry.cs
+++ b/OpenRA.Mods.RA/Render/RenderInfantry.cs
@@ -61,6 +61,8 @@ namespace OpenRA.Mods.RA.Render
anim.PlayFetchIndex(NormalizeInfantrySequence(self, "stand"), () => 0);
State = AnimationState.Waiting;
mobile = self.Trait();
+
+ self.Trait().QuantizedFacings = anim.CurrentSequence.Facings;
}
public void Attacking(Actor self, Target target)
diff --git a/OpenRA.Mods.RA/Turreted.cs b/OpenRA.Mods.RA/Turreted.cs
index 02f9c03c1b..d863bf90af 100755
--- a/OpenRA.Mods.RA/Turreted.cs
+++ b/OpenRA.Mods.RA/Turreted.cs
@@ -33,7 +33,7 @@ namespace OpenRA.Mods.RA
public class Turreted : ITick, ISync, IResolveOrder
{
- [Sync] public int QuantizedFacings = -1;
+ [Sync] public int QuantizedFacings = 0;
[Sync] public int turretFacing = 0;
public int? desiredFacing;
TurretedInfo info;
@@ -96,7 +96,7 @@ namespace OpenRA.Mods.RA
// Hack: turretFacing is relative to the world, so subtract the body yaw
var local = WRot.FromYaw(WAngle.FromFacing(turretFacing) - self.Orientation.Yaw);
- if (QuantizedFacings == -1)
+ if (QuantizedFacings == 0)
return local;
// Quantize orientation to match a rendered sprite
diff --git a/mods/cnc/rules/civilian.yaml b/mods/cnc/rules/civilian.yaml
index 28b5e86d9d..7981d04c29 100644
--- a/mods/cnc/rules/civilian.yaml
+++ b/mods/cnc/rules/civilian.yaml
@@ -445,3 +445,4 @@ VICE:
AttackWander:
RenderUnit:
WithMuzzleFlash:
+ BodyOrientation:
diff --git a/mods/cnc/rules/defaults.yaml b/mods/cnc/rules/defaults.yaml
index 1f3e58336b..9d7e226c61 100644
--- a/mods/cnc/rules/defaults.yaml
+++ b/mods/cnc/rules/defaults.yaml
@@ -33,6 +33,7 @@
DebugMuzzlePositions:
Guard:
Guardable:
+ BodyOrientation:
^Tank:
AppearsOnRadar:
@@ -72,6 +73,7 @@
DebugMuzzlePositions:
Guard:
Guardable:
+ BodyOrientation:
^Helicopter:
AppearsOnRadar:
@@ -97,6 +99,7 @@
Weapon: HeliExplode
EmptyWeapon: HeliExplode
DebugMuzzlePositions:
+ BodyOrientation:
^Infantry:
AppearsOnRadar:
@@ -149,6 +152,7 @@
DebugMuzzlePositions:
Guard:
Guardable:
+ BodyOrientation:
^CivInfantry:
Inherits: ^Infantry
@@ -197,6 +201,7 @@
DrawLineToTarget:
ActorLostNotification:
DebugMuzzlePositions:
+ BodyOrientation:
^Ship:
AppearsOnRadar:
@@ -218,6 +223,7 @@
DebugMuzzlePositions:
Guard:
Guardable:
+ BodyOrientation:
^Building:
AppearsOnRadar:
@@ -266,6 +272,7 @@
DebugMuzzlePositions:
Guardable:
Range: 3
+ BodyOrientation:
^CivBuilding:
Inherits: ^Building
@@ -296,6 +303,7 @@
RelativeToTopLeft: yes
Tooltip:
Name: Civilian Building (Destroyed)
+ BodyOrientation:
^TechBuilding:
Inherits: ^CivBuilding
@@ -326,6 +334,7 @@
Tooltip:
Name: Field (Destroyed)
BelowUnits:
+ BodyOrientation:
^Wall:
AppearsOnRadar:
@@ -354,6 +363,7 @@
AutoTargetIgnore:
Sellable:
Guardable:
+ BodyOrientation:
^Tree:
Tooltip:
@@ -374,6 +384,7 @@
Armor:
Type: Wood
AutoTargetIgnore:
+ BodyOrientation:
^Rock:
Tooltip:
@@ -388,6 +399,7 @@
Terrain: Tree
EditorAppearance:
RelativeToTopLeft: yes
+ BodyOrientation:
^Husk:
Health:
@@ -403,6 +415,7 @@
TransformOnCapture:
ForceHealthPercentage: 25
BelowUnits:
+ BodyOrientation:
# Capturable:
# Type: husk
# AllowAllies: true
@@ -420,3 +433,4 @@
SoundOnDamageTransition:
DamagedSound: xplos.aud
DestroyedSound: xplobig4.aud
+ BodyOrientation:
diff --git a/mods/cnc/rules/system.yaml b/mods/cnc/rules/system.yaml
index 991dd0e609..1445012741 100644
--- a/mods/cnc/rules/system.yaml
+++ b/mods/cnc/rules/system.yaml
@@ -351,11 +351,14 @@ CRATE:
Unit: mcv
RenderSimple:
BelowUnits:
+ BodyOrientation:
mpspawn:
Waypoint:
RenderEditorOnly:
+ BodyOrientation:
waypoint:
Waypoint:
RenderEditorOnly:
+ BodyOrientation:
diff --git a/mods/d2k/rules/defaults.yaml b/mods/d2k/rules/defaults.yaml
index 41f594ac2b..d506700057 100644
--- a/mods/d2k/rules/defaults.yaml
+++ b/mods/d2k/rules/defaults.yaml
@@ -33,6 +33,7 @@
DebugMuzzlePositions:
Guard:
Guardable:
+ BodyOrientation:
^Tank:
AppearsOnRadar:
@@ -69,6 +70,7 @@
DebugMuzzlePositions:
Guard:
Guardable:
+ BodyOrientation:
^Husk:
Health:
@@ -84,6 +86,7 @@
Types:Husk
Tooltip:
Name: Destroyed Tank
+ BodyOrientation:
^TowerHusk:
Health:
@@ -101,6 +104,7 @@
Name: Destroyed Tower
ProximityCaptor:
Types:Husk
+ BodyOrientation:
^Infantry:
AppearsOnRadar:
@@ -149,6 +153,7 @@
DebugMuzzlePositions:
Guard:
Guardable:
+ BodyOrientation:
^Plane:
AppearsOnRadar:
@@ -168,6 +173,7 @@
Types:Plane
GivesBounty:
DebugMuzzlePositions:
+ BodyOrientation:
^Helicopter:
Inherits: ^Plane
@@ -216,3 +222,4 @@
Bib:
Guardable:
Range: 3
+ BodyOrientation:
diff --git a/mods/d2k/rules/structures.yaml b/mods/d2k/rules/structures.yaml
index 534591b790..452078c14c 100644
--- a/mods/d2k/rules/structures.yaml
+++ b/mods/d2k/rules/structures.yaml
@@ -372,6 +372,7 @@ WALL:
Types:Wall
Sellable:
Guardable:
+ BodyOrientation:
GUNTOWER:
Inherits: ^Building
diff --git a/mods/d2k/rules/system.yaml b/mods/d2k/rules/system.yaml
index 22a0faaf9a..11ec28e4c1 100644
--- a/mods/d2k/rules/system.yaml
+++ b/mods/d2k/rules/system.yaml
@@ -481,14 +481,17 @@ CRATE:
ProximityCaptor:
Types:Crate
Passenger:
+ BodyOrientation:
mpspawn:
Waypoint:
RenderEditorOnly:
+ BodyOrientation:
waypoint:
Waypoint:
RenderEditorOnly:
+ BodyOrientation:
SPICEBLOOM:
RenderBuilding:
@@ -508,6 +511,7 @@ SPICEBLOOM:
Interval: 75
RadarColorFromTerrain:
Terrain: Spice
+ BodyOrientation:
#SANDWORM:
# Buildable:
diff --git a/mods/ra/rules/defaults.yaml b/mods/ra/rules/defaults.yaml
index d67bdfe017..1f9d8a6413 100644
--- a/mods/ra/rules/defaults.yaml
+++ b/mods/ra/rules/defaults.yaml
@@ -36,6 +36,7 @@
DebugMuzzlePositions:
Guard:
Guardable:
+ BodyOrientation:
^Tank:
AppearsOnRadar:
@@ -75,6 +76,7 @@
DebugMuzzlePositions:
Guard:
Guardable:
+ BodyOrientation:
^Infantry:
AppearsOnRadar:
@@ -126,6 +128,7 @@
DebugMuzzlePositions:
Guard:
Guardable:
+ BodyOrientation:
^Ship:
AppearsOnRadar:
@@ -157,6 +160,7 @@
DebugMuzzlePositions:
Guard:
Guardable:
+ BodyOrientation:
^Plane:
AppearsOnRadar:
@@ -183,6 +187,7 @@
String:Plane
UpdatesPlayerStatistics:
DebugMuzzlePositions:
+ BodyOrientation:
^Helicopter:
Inherits: ^Plane
@@ -229,6 +234,7 @@
Guardable:
Range: 3
AutoTargetIgnore:
+ BodyOrientation:
^Wall:
AppearsOnRadar:
@@ -263,6 +269,7 @@
Sellable:
UpdatesPlayerStatistics:
Guardable:
+ BodyOrientation:
^TechBuilding:
Inherits: ^Building
@@ -344,6 +351,7 @@
Armor:
Type: Wood
AutoTargetIgnore:
+ BodyOrientation:
^Husk:
Husk:
@@ -358,6 +366,7 @@
ProximityCaptor:
Types:Husk
BelowUnits:
+ BodyOrientation:
^Bridge:
Tooltip:
@@ -373,6 +382,7 @@
ProximityCaptor:
Types:Bridge
AutoTargetIgnore:
+ BodyOrientation:
#Temperate Terrain Expansion
^SVBridge:
@@ -389,6 +399,7 @@
ProximityCaptor:
Types:Bridge
AutoTargetIgnore:
+ BodyOrientation:
^SHBridge:
Tooltip:
@@ -404,6 +415,7 @@
ProximityCaptor:
Types:Bridge
AutoTargetIgnore:
+ BodyOrientation:
^STDBridge:
Tooltip:
@@ -419,6 +431,7 @@
ProximityCaptor:
Types:Bridge
AutoTargetIgnore:
+ BodyOrientation:
#Desert Terrain Expansion:
^Rock:
@@ -437,6 +450,7 @@
UseTerrainPalette: true
ProximityCaptor:
Types:Tree
+ BodyOrientation:
^DesertCivBuilding:
Inherits: ^CivBuilding
diff --git a/mods/ra/rules/system.yaml b/mods/ra/rules/system.yaml
index d96879b3cf..34f027f938 100644
--- a/mods/ra/rules/system.yaml
+++ b/mods/ra/rules/system.yaml
@@ -670,6 +670,7 @@ MINP:
Types: Mine
TargetableUnit:
TargetTypes: Ground
+ BodyOrientation:
MINV:
Mine:
@@ -695,6 +696,7 @@ MINV:
Types: Mine
TargetableUnit:
TargetTypes: Ground
+ BodyOrientation:
CRATE:
Tooltip:
@@ -757,6 +759,7 @@ CRATE:
ProximityCaptor:
Types:Crate
Passenger:
+ BodyOrientation:
CAMERA:
Aircraft:
@@ -766,6 +769,7 @@ CAMERA:
Range: 10
ProximityCaptor:
Types:Camera
+ BodyOrientation:
FLARE:
Aircraft:
@@ -780,6 +784,7 @@ FLARE:
Name: Flare
ProximityCaptor:
Types: Flare
+ BodyOrientation:
powerproxy.parabombs:
AirstrikePower:
@@ -805,7 +810,9 @@ powerproxy.sonarpulse:
mpspawn:
Waypoint:
RenderEditorOnly:
+ BodyOrientation:
waypoint:
Waypoint:
RenderEditorOnly:
+ BodyOrientation: