diff --git a/OpenRA.Game/OpenRA.Game.csproj b/OpenRA.Game/OpenRA.Game.csproj
index ad5a320dcc..bb9a09f303 100644
--- a/OpenRA.Game/OpenRA.Game.csproj
+++ b/OpenRA.Game/OpenRA.Game.csproj
@@ -191,7 +191,6 @@
-
diff --git a/OpenRA.Game/Traits/TraitsInterfaces.cs b/OpenRA.Game/Traits/TraitsInterfaces.cs
index cb97e131c3..00526d6d00 100644
--- a/OpenRA.Game/Traits/TraitsInterfaces.cs
+++ b/OpenRA.Game/Traits/TraitsInterfaces.cs
@@ -308,22 +308,6 @@ namespace OpenRA.Traits
public interface IPostRenderSelection { IEnumerable RenderAfterWorld(WorldRenderer wr); }
- public interface IBodyOrientation
- {
- WAngle CameraPitch { get; }
- int QuantizedFacings { get; }
- WVec LocalToWorld(WVec vec);
- WRot QuantizeOrientation(Actor self, WRot orientation);
- }
-
- public interface IBodyOrientationInfo : ITraitInfo
- {
- WVec LocalToWorld(WVec vec);
- WRot QuantizeOrientation(WRot orientation, int facings);
- }
-
- public interface IQuantizeBodyOrientationInfo { int QuantizedBodyFacings(ActorInfo ai, SequenceProvider sequenceProvider, string faction); }
-
public interface ITargetableInfo
{
string[] GetTargetTypes();
diff --git a/OpenRA.Mods.Cnc/Traits/Render/WithGunboatBody.cs b/OpenRA.Mods.Cnc/Traits/Render/WithGunboatBody.cs
index a03e44246e..41a162ac47 100644
--- a/OpenRA.Mods.Cnc/Traits/Render/WithGunboatBody.cs
+++ b/OpenRA.Mods.Cnc/Traits/Render/WithGunboatBody.cs
@@ -27,11 +27,6 @@ namespace OpenRA.Mods.Cnc.Traits
[SequenceReference] public readonly string WakeRightSequence = "wake-right";
public override object Create(ActorInitializer init) { return new WithGunboatBody(init, this); }
-
- public override int QuantizedBodyFacings(ActorInfo ai, SequenceProvider sequenceProvider, string faction)
- {
- return 2;
- }
}
class WithGunboatBody : WithSpriteBody, ITick
diff --git a/OpenRA.Mods.Common/Effects/Contrail.cs b/OpenRA.Mods.Common/Effects/Contrail.cs
index c5c54df60b..aba9a1d131 100644
--- a/OpenRA.Mods.Common/Effects/Contrail.cs
+++ b/OpenRA.Mods.Common/Effects/Contrail.cs
@@ -12,6 +12,7 @@ using System.Collections.Generic;
using System.Drawing;
using OpenRA.Graphics;
using OpenRA.Mods.Common.Graphics;
+using OpenRA.Mods.Common.Traits;
using OpenRA.Traits;
namespace OpenRA.Mods.Common.Effects
diff --git a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj
index 9bf8805b53..3314d73807 100644
--- a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj
+++ b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj
@@ -398,6 +398,8 @@
+
+
diff --git a/OpenRA.Game/Traits/BodyOrientation.cs b/OpenRA.Mods.Common/Traits/BodyOrientation.cs
similarity index 83%
rename from OpenRA.Game/Traits/BodyOrientation.cs
rename to OpenRA.Mods.Common/Traits/BodyOrientation.cs
index 54afb6dbd8..39c47652a3 100644
--- a/OpenRA.Game/Traits/BodyOrientation.cs
+++ b/OpenRA.Mods.Common/Traits/BodyOrientation.cs
@@ -9,8 +9,11 @@
#endregion
using System;
+using System.Collections.Generic;
+using System.Linq;
+using OpenRA.Traits;
-namespace OpenRA.Traits
+namespace OpenRA.Mods.Common.Traits
{
public class BodyOrientationInfo : ITraitInfo, IBodyOrientationInfo
{
@@ -70,8 +73,12 @@ namespace OpenRA.Traits
return info.QuantizedFacings;
var qboi = self.Info.Traits.GetOrDefault();
- if (qboi == null)
- throw new InvalidOperationException("Actor type '" + self.Info.Name + "' does not define a quantized body orientation.");
+ var isb = self.HasTrait();
+
+ // If a sprite actor has neither custom QuantizedFacings nor a trait implementing IQuantizeBodyOrientationInfo, throw
+ if (qboi == null && isb)
+ 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.");
return qboi.QuantizedBodyFacings(self.Info, self.World.Map.SequenceProvider, faction);
});
diff --git a/OpenRA.Mods.Common/Traits/QuantizeFacingsFromSequence.cs b/OpenRA.Mods.Common/Traits/QuantizeFacingsFromSequence.cs
new file mode 100644
index 0000000000..93c10dab09
--- /dev/null
+++ b/OpenRA.Mods.Common/Traits/QuantizeFacingsFromSequence.cs
@@ -0,0 +1,43 @@
+#region Copyright & License Information
+/*
+ * Copyright 2007-2015 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.Mods.Common.Graphics;
+using OpenRA.Traits;
+
+namespace OpenRA.Mods.Common.Traits
+{
+ [Desc("Derive facings from sprite body sequence.")]
+ public class QuantizeFacingsFromSequenceInfo : UpgradableTraitInfo, IQuantizeBodyOrientationInfo, Requires
+ {
+ [Desc("Defines sequence to derive facings from."), SequenceReference]
+ public readonly string Sequence = "idle";
+
+ public int QuantizedBodyFacings(ActorInfo ai, SequenceProvider sequenceProvider, string race)
+ {
+ if (string.IsNullOrEmpty(Sequence))
+ throw new InvalidOperationException("Actor " + ai.Name + " is missing sequence to quantize facings from.");
+
+ var rsi = ai.Traits.Get();
+ return sequenceProvider.GetSequence(rsi.GetImage(ai, sequenceProvider, race), Sequence).Facings;
+ }
+
+ public override object Create(ActorInitializer init) { return new QuantizeFacingsFromSequence(this); }
+ }
+
+ public class QuantizeFacingsFromSequence : UpgradableTrait
+ {
+ public QuantizeFacingsFromSequence(QuantizeFacingsFromSequenceInfo info)
+ : base(info) { }
+ }
+}
diff --git a/OpenRA.Mods.Common/Traits/Render/RenderSimple.cs b/OpenRA.Mods.Common/Traits/Render/RenderSimple.cs
index 311b4cf1e3..5bcdd33c73 100644
--- a/OpenRA.Mods.Common/Traits/Render/RenderSimple.cs
+++ b/OpenRA.Mods.Common/Traits/Render/RenderSimple.cs
@@ -17,7 +17,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[Desc("Basic render trait for immobile actors. Deprecated, use RenderSprites + WithSpriteBody instead.")]
- public class RenderSimpleInfo : RenderSpritesInfo, IRenderActorPreviewSpritesInfo, IQuantizeBodyOrientationInfo, Requires
+ public class RenderSimpleInfo : RenderSpritesInfo, IRenderActorPreviewSpritesInfo, Requires
{
[SequenceReference] public readonly string Sequence = "idle";
@@ -33,11 +33,6 @@ namespace OpenRA.Mods.Common.Traits
yield return new SpriteActorPreview(anim, WVec.Zero, 0, p, rs.Scale);
}
-
- public virtual int QuantizedBodyFacings(ActorInfo ai, SequenceProvider sequenceProvider, string faction)
- {
- return sequenceProvider.GetSequence(GetImage(ai, sequenceProvider, faction), Sequence).Facings;
- }
}
public class RenderSimple : RenderSprites, IAutoSelectionSize
diff --git a/OpenRA.Mods.Common/Traits/Render/WithCrateBody.cs b/OpenRA.Mods.Common/Traits/Render/WithCrateBody.cs
index 523f20e399..7f392a5365 100644
--- a/OpenRA.Mods.Common/Traits/Render/WithCrateBody.cs
+++ b/OpenRA.Mods.Common/Traits/Render/WithCrateBody.cs
@@ -18,7 +18,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[Desc("Renders crates with both water and land variants.")]
- class WithCrateBodyInfo : ITraitInfo, Requires, IQuantizeBodyOrientationInfo, IRenderActorPreviewSpritesInfo
+ class WithCrateBodyInfo : ITraitInfo, Requires, IRenderActorPreviewSpritesInfo
{
[Desc("Easteregg sequences to use in december.")]
public readonly string[] XmasImages = { };
@@ -35,8 +35,6 @@ namespace OpenRA.Mods.Common.Traits
anim.PlayRepeating(RenderSprites.NormalizeSequence(anim, init.GetDamageState(), IdleSequence));
yield return new SpriteActorPreview(anim, WVec.Zero, 0, p, rs.Scale);
}
-
- public int QuantizedBodyFacings(ActorInfo ai, SequenceProvider sequenceProvider, string faction) { return 1; }
}
class WithCrateBody : INotifyParachuteLanded
diff --git a/OpenRA.Mods.Common/Traits/Render/WithFacingSpriteBody.cs b/OpenRA.Mods.Common/Traits/Render/WithFacingSpriteBody.cs
index d1c9132d32..7f5f9e2dfb 100644
--- a/OpenRA.Mods.Common/Traits/Render/WithFacingSpriteBody.cs
+++ b/OpenRA.Mods.Common/Traits/Render/WithFacingSpriteBody.cs
@@ -30,12 +30,6 @@ namespace OpenRA.Mods.Common.Traits
yield return new SpriteActorPreview(anim, WVec.Zero, 0, p, rs.Scale);
}
-
- public override int QuantizedBodyFacings(ActorInfo ai, SequenceProvider sequenceProvider, string faction)
- {
- var rsi = ai.Traits.Get();
- return sequenceProvider.GetSequence(rsi.GetImage(ai, sequenceProvider, faction), Sequence).Facings;
- }
}
public class WithFacingSpriteBody : WithSpriteBody
diff --git a/OpenRA.Mods.Common/Traits/Render/WithInfantryBody.cs b/OpenRA.Mods.Common/Traits/Render/WithInfantryBody.cs
index 4ba38ac7d8..23d97a0b7b 100644
--- a/OpenRA.Mods.Common/Traits/Render/WithInfantryBody.cs
+++ b/OpenRA.Mods.Common/Traits/Render/WithInfantryBody.cs
@@ -16,8 +16,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
- public class WithInfantryBodyInfo : UpgradableTraitInfo, IQuantizeBodyOrientationInfo, IRenderActorPreviewSpritesInfo,
- Requires, Requires
+ public class WithInfantryBodyInfo : UpgradableTraitInfo, IRenderActorPreviewSpritesInfo, Requires, Requires
{
public readonly int MinIdleWaitTicks = 30;
public readonly int MaxIdleWaitTicks = 110;
@@ -40,12 +39,6 @@ namespace OpenRA.Mods.Common.Traits
anim.PlayRepeating(RenderSprites.NormalizeSequence(anim, init.GetDamageState(), StandSequences.First()));
yield return new SpriteActorPreview(anim, WVec.Zero, 0, p, rs.Scale);
}
-
- public int QuantizedBodyFacings(ActorInfo ai, SequenceProvider sequenceProvider, string faction)
- {
- var rsi = ai.Traits.Get();
- return sequenceProvider.GetSequence(rsi.GetImage(ai, sequenceProvider, faction), StandSequences.First()).Facings;
- }
}
public class WithInfantryBody : UpgradableTrait, ITick, INotifyAttack, INotifyIdle, INotifyCreated
diff --git a/OpenRA.Mods.Common/Traits/Render/WithSpriteBody.cs b/OpenRA.Mods.Common/Traits/Render/WithSpriteBody.cs
index 838b02faad..c4861111ce 100644
--- a/OpenRA.Mods.Common/Traits/Render/WithSpriteBody.cs
+++ b/OpenRA.Mods.Common/Traits/Render/WithSpriteBody.cs
@@ -17,8 +17,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[Desc("Default trait for rendering sprite-based actors.")]
- public class WithSpriteBodyInfo : UpgradableTraitInfo, IRenderActorPreviewSpritesInfo, IQuantizeBodyOrientationInfo,
- Requires
+ public class WithSpriteBodyInfo : UpgradableTraitInfo, IRenderActorPreviewSpritesInfo, Requires
{
[Desc("Animation to play when the actor is created.")]
[SequenceReference] public readonly string StartSequence = null;
@@ -35,11 +34,6 @@ namespace OpenRA.Mods.Common.Traits
yield return new SpriteActorPreview(anim, WVec.Zero, 0, p, rs.Scale);
}
-
- public virtual int QuantizedBodyFacings(ActorInfo ai, SequenceProvider sequenceProvider, string faction)
- {
- return 1;
- }
}
public class WithSpriteBody : UpgradableTrait, ISpriteBody, INotifyDamageStateChanged
diff --git a/OpenRA.Mods.Common/Traits/Render/WithVoxelBody.cs b/OpenRA.Mods.Common/Traits/Render/WithVoxelBody.cs
index 3926876452..7cd11fa474 100644
--- a/OpenRA.Mods.Common/Traits/Render/WithVoxelBody.cs
+++ b/OpenRA.Mods.Common/Traits/Render/WithVoxelBody.cs
@@ -18,7 +18,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[Desc("Also returns a default selection size that is calculated automatically from the voxel dimensions.")]
- public class WithVoxelBodyInfo : ITraitInfo, IQuantizeBodyOrientationInfo, IRenderActorPreviewVoxelsInfo, Requires
+ public class WithVoxelBodyInfo : ITraitInfo, IRenderActorPreviewVoxelsInfo, Requires
{
public readonly string Sequence = "idle";
@@ -33,8 +33,6 @@ namespace OpenRA.Mods.Common.Traits
() => bodyOrientation,
() => false, () => 0);
}
-
- public int QuantizedBodyFacings(ActorInfo ai, SequenceProvider sequenceProvider, string faction) { return 0; }
}
public class WithVoxelBody : IAutoSelectionSize
diff --git a/OpenRA.Mods.Common/TraitsInterfaces.cs b/OpenRA.Mods.Common/TraitsInterfaces.cs
index b8918172d3..90de79ea57 100644
--- a/OpenRA.Mods.Common/TraitsInterfaces.cs
+++ b/OpenRA.Mods.Common/TraitsInterfaces.cs
@@ -25,6 +25,25 @@ namespace OpenRA.Mods.Common.Traits
void PlayCustomAnimationBackwards(Actor self, string name, Action after);
}
+ public interface IBodyOrientation
+ {
+ WAngle CameraPitch { get; }
+ int QuantizedFacings { get; }
+ WVec LocalToWorld(WVec vec);
+ WRot QuantizeOrientation(Actor self, WRot orientation);
+ }
+
+ public interface IBodyOrientationInfo : ITraitInfo
+ {
+ WVec LocalToWorld(WVec vec);
+ WRot QuantizeOrientation(WRot orientation, int facings);
+ }
+
+ public interface IQuantizeBodyOrientationInfo : ITraitInfo
+ {
+ int QuantizedBodyFacings(ActorInfo ai, SequenceProvider sequenceProvider, string race);
+ }
+
public interface INotifyResourceClaimLost
{
void OnNotifyResourceClaimLost(Actor self, ResourceClaim claim, Actor claimer);
diff --git a/OpenRA.Mods.TS/Traits/Render/WithVoxelUnloadBody.cs b/OpenRA.Mods.TS/Traits/Render/WithVoxelUnloadBody.cs
index 67610f4da5..0c4e8b14b3 100644
--- a/OpenRA.Mods.TS/Traits/Render/WithVoxelUnloadBody.cs
+++ b/OpenRA.Mods.TS/Traits/Render/WithVoxelUnloadBody.cs
@@ -18,7 +18,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.TS.Traits
{
- public class WithVoxelUnloadBodyInfo : ITraitInfo, IQuantizeBodyOrientationInfo, IRenderActorPreviewVoxelsInfo, Requires
+ public class WithVoxelUnloadBodyInfo : ITraitInfo, IRenderActorPreviewVoxelsInfo, Requires
{
[Desc("Voxel sequence name to use when docked to a refinery.")]
public readonly string UnloadSequence = "unload";
@@ -36,8 +36,6 @@ namespace OpenRA.Mods.TS.Traits
() => new[] { body.QuantizeOrientation(orientation, facings) },
() => false, () => 0);
}
-
- public int QuantizedBodyFacings(ActorInfo ai, SequenceProvider sequenceProvider, string faction) { return 0; }
}
public class WithVoxelUnloadBody : IAutoSelectionSize
diff --git a/OpenRA.Mods.TS/Traits/Render/WithVoxelWalkerBody.cs b/OpenRA.Mods.TS/Traits/Render/WithVoxelWalkerBody.cs
index e3e27e0a09..adb4682911 100644
--- a/OpenRA.Mods.TS/Traits/Render/WithVoxelWalkerBody.cs
+++ b/OpenRA.Mods.TS/Traits/Render/WithVoxelWalkerBody.cs
@@ -16,12 +16,10 @@ using OpenRA.Traits;
namespace OpenRA.Mods.TS.Traits
{
- public class WithVoxelWalkerBodyInfo : ITraitInfo, IQuantizeBodyOrientationInfo, Requires, Requires
+ public class WithVoxelWalkerBodyInfo : ITraitInfo, Requires, Requires
{
public readonly int TickRate = 5;
public object Create(ActorInitializer init) { return new WithVoxelWalkerBody(init.Self, this); }
-
- public int QuantizedBodyFacings(ActorInfo ai, SequenceProvider sequenceProvider, string faction) { return 0; }
}
public class WithVoxelWalkerBody : IAutoSelectionSize, ITick
diff --git a/OpenRA.Mods.TS/Traits/Render/WithVoxelWaterBody.cs b/OpenRA.Mods.TS/Traits/Render/WithVoxelWaterBody.cs
index 387756235a..933e146cb3 100644
--- a/OpenRA.Mods.TS/Traits/Render/WithVoxelWaterBody.cs
+++ b/OpenRA.Mods.TS/Traits/Render/WithVoxelWaterBody.cs
@@ -18,7 +18,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.TS.Traits
{
- public class WithVoxelWaterBodyInfo : ITraitInfo, IQuantizeBodyOrientationInfo, IRenderActorPreviewVoxelsInfo, Requires
+ public class WithVoxelWaterBodyInfo : ITraitInfo, IRenderActorPreviewVoxelsInfo, Requires
{
public readonly string WaterSequence = "water";
public readonly string LandSequence = "idle";
@@ -41,8 +41,6 @@ namespace OpenRA.Mods.TS.Traits
() => new[] { body.QuantizeOrientation(orientation, facings) },
() => false, () => 0);
}
-
- public int QuantizedBodyFacings(ActorInfo ai, SequenceProvider sequenceProvider, string faction) { return 0; }
}
public class WithVoxelWaterBody : IAutoSelectionSize