diff --git a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj
index 58d2580718..54abd31fa3 100644
--- a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj
+++ b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj
@@ -423,6 +423,7 @@
+
diff --git a/OpenRA.Mods.Common/Traits/Render/WithTurretAimAnimation.cs b/OpenRA.Mods.Common/Traits/Render/WithTurretAimAnimation.cs
new file mode 100644
index 0000000000..5abe658248
--- /dev/null
+++ b/OpenRA.Mods.Common/Traits/Render/WithTurretAimAnimation.cs
@@ -0,0 +1,68 @@
+#region Copyright & License Information
+/*
+ * Copyright 2007-2018 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, either version 3 of
+ * the License, or (at your option) any later version. For more
+ * information, see COPYING.
+ */
+#endregion
+
+using System.Linq;
+using OpenRA.Traits;
+
+namespace OpenRA.Mods.Common.Traits.Render
+{
+ public class WithTurretAimAnimationInfo : ITraitInfo, Requires, Requires, Requires
+ {
+ [Desc("Armament name")]
+ public readonly string Armament = "primary";
+
+ [Desc("Turret name")]
+ public readonly string Turret = "primary";
+
+ [Desc("Displayed while targeting.")]
+ [SequenceReference] public readonly string Sequence = null;
+
+ [Desc("Shown while reloading.")]
+ [SequenceReference(null, true)] public readonly string ReloadPrefix = null;
+
+ public object Create(ActorInitializer init) { return new WithTurretAimAnimation(init, this); }
+ }
+
+ public class WithTurretAimAnimation : ITick
+ {
+ readonly WithTurretAimAnimationInfo info;
+ readonly AttackBase attack;
+ readonly Armament armament;
+ readonly WithSpriteTurret wst;
+
+ public WithTurretAimAnimation(ActorInitializer init, WithTurretAimAnimationInfo info)
+ {
+ this.info = info;
+ attack = init.Self.Trait();
+ armament = init.Self.TraitsImplementing()
+ .Single(a => a.Info.Name == info.Armament);
+ wst = init.Self.TraitsImplementing()
+ .Single(st => st.Info.Turret == info.Turret);
+ }
+
+ void ITick.Tick(Actor self)
+ {
+ if (string.IsNullOrEmpty(info.Sequence) && string.IsNullOrEmpty(info.ReloadPrefix))
+ return;
+
+ var sequence = wst.Info.Sequence;
+ if (!string.IsNullOrEmpty(info.Sequence) && attack.IsAiming)
+ sequence = info.Sequence;
+
+ var prefix = (armament.IsReloading && !string.IsNullOrEmpty(info.ReloadPrefix)) ? info.ReloadPrefix : "";
+
+ if (!string.IsNullOrEmpty(prefix) && sequence != (prefix + sequence))
+ sequence = prefix + sequence;
+
+ wst.DefaultAnimation.ReplaceAnim(sequence);
+ }
+ }
+}
diff --git a/OpenRA.Mods.Common/Traits/Render/WithTurretAttackAnimation.cs b/OpenRA.Mods.Common/Traits/Render/WithTurretAttackAnimation.cs
index 16ca34ba87..1a09ac7aeb 100644
--- a/OpenRA.Mods.Common/Traits/Render/WithTurretAttackAnimation.cs
+++ b/OpenRA.Mods.Common/Traits/Render/WithTurretAttackAnimation.cs
@@ -14,7 +14,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits.Render
{
- public class WithTurretAttackAnimationInfo : ITraitInfo, Requires, Requires, Requires
+ public class WithTurretAttackAnimationInfo : ITraitInfo, Requires, Requires
{
[Desc("Armament name")]
public readonly string Armament = "primary";
@@ -23,13 +23,7 @@ namespace OpenRA.Mods.Common.Traits.Render
public readonly string Turret = "primary";
[Desc("Displayed while attacking.")]
- [SequenceReference] public readonly string AttackSequence = null;
-
- [Desc("Displayed while targeting.")]
- [SequenceReference] public readonly string AimSequence = null;
-
- [Desc("Shown while reloading.")]
- [SequenceReference(null, true)] public readonly string ReloadPrefix = null;
+ [SequenceReference] public readonly string Sequence = null;
[Desc("Delay in ticks before animation starts, either relative to attack preparation or attack.")]
public readonly int Delay = 0;
@@ -43,8 +37,6 @@ namespace OpenRA.Mods.Common.Traits.Render
public class WithTurretAttackAnimation : ITick, INotifyAttack
{
readonly WithTurretAttackAnimationInfo info;
- readonly AttackBase attack;
- readonly Armament armament;
readonly WithSpriteTurret wst;
int tick;
@@ -52,21 +44,21 @@ namespace OpenRA.Mods.Common.Traits.Render
public WithTurretAttackAnimation(ActorInitializer init, WithTurretAttackAnimationInfo info)
{
this.info = info;
- attack = init.Self.Trait();
- armament = init.Self.TraitsImplementing()
- .Single(a => a.Info.Name == info.Armament);
wst = init.Self.TraitsImplementing()
.Single(st => st.Info.Turret == info.Turret);
}
void PlayAttackAnimation(Actor self)
{
- if (!string.IsNullOrEmpty(info.AttackSequence))
- wst.PlayCustomAnimation(self, info.AttackSequence);
+ if (!string.IsNullOrEmpty(info.Sequence))
+ wst.PlayCustomAnimation(self, info.Sequence);
}
void INotifyAttack.Attacking(Actor self, Target target, Armament a, Barrel barrel)
{
+ if (a.Info.Name != info.Armament)
+ return;
+
if (info.DelayRelativeTo == AttackDelayType.Attack)
{
if (info.Delay > 0)
@@ -78,6 +70,9 @@ namespace OpenRA.Mods.Common.Traits.Render
void INotifyAttack.PreparingAttack(Actor self, Target target, Armament a, Barrel barrel)
{
+ if (a.Info.Name != info.Armament)
+ return;
+
if (info.DelayRelativeTo == AttackDelayType.Preparation)
{
if (info.Delay > 0)
@@ -91,20 +86,6 @@ namespace OpenRA.Mods.Common.Traits.Render
{
if (info.Delay > 0 && --tick == 0)
PlayAttackAnimation(self);
-
- if (string.IsNullOrEmpty(info.AimSequence) && string.IsNullOrEmpty(info.ReloadPrefix))
- return;
-
- var sequence = wst.Info.Sequence;
- if (!string.IsNullOrEmpty(info.AimSequence) && attack.IsAiming)
- sequence = info.AimSequence;
-
- var prefix = (armament.IsReloading && !string.IsNullOrEmpty(info.ReloadPrefix)) ? info.ReloadPrefix : "";
-
- if (!string.IsNullOrEmpty(prefix) && sequence != (prefix + sequence))
- sequence = prefix + sequence;
-
- wst.DefaultAnimation.ReplaceAnim(sequence);
}
}
}
diff --git a/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs b/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs
index 12b629b922..2b5decb0b4 100644
--- a/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs
+++ b/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs
@@ -1709,6 +1709,53 @@ namespace OpenRA.Mods.Common.UtilityCommands
}
}
+ // Split aim animation logic from WithTurretAttackAnimation to separate WithTurretAimAnimation
+ if (engineVersion < 20180223)
+ {
+ var turAttackAnim = node.Value.Nodes.FirstOrDefault(n => n.Key.StartsWith("WithTurretAttackAnimation", StringComparison.Ordinal));
+ if (turAttackAnim != null)
+ {
+ var atkSequence = turAttackAnim.Value.Nodes.FirstOrDefault(n => n.Key == "AttackSequence");
+ var aimSequence = turAttackAnim.Value.Nodes.FirstOrDefault(n => n.Key == "AimSequence");
+
+ // If only AimSequence is null, just rename AttackSequence to Sequence (ReloadPrefix is very unlikely to be defined in that case).
+ // If only AttackSequence is null, just rename the trait and property (the delay properties will likely be undefined).
+ // If both aren't null, split/copy everything relevant to the new WithTurretAimAnimation.
+ // If both are null (extremely unlikely), do nothing.
+ if (atkSequence == null && aimSequence != null)
+ {
+ RenameNodeKey(turAttackAnim, "WithTurretAimAnimation");
+ RenameNodeKey(aimSequence, "Sequence");
+ }
+ else if (atkSequence != null && aimSequence == null)
+ RenameNodeKey(atkSequence, "Sequence");
+ else if (atkSequence != null && aimSequence != null)
+ {
+ var aimAnim = new MiniYamlNode("WithTurretAimAnimation", "");
+ RenameNodeKey(aimSequence, "Sequence");
+ aimAnim.Value.Nodes.Add(aimSequence);
+ turAttackAnim.Value.Nodes.Remove(aimSequence);
+
+ var relPrefix = turAttackAnim.Value.Nodes.FirstOrDefault(n => n.Key == "ReloadPrefix");
+ var turr = turAttackAnim.Value.Nodes.FirstOrDefault(n => n.Key == "Turret");
+ var arm = turAttackAnim.Value.Nodes.FirstOrDefault(n => n.Key == "Armament");
+ if (relPrefix != null)
+ {
+ aimAnim.Value.Nodes.Add(relPrefix);
+ turAttackAnim.Value.Nodes.Remove(relPrefix);
+ }
+
+ if (turr != null)
+ aimAnim.Value.Nodes.Add(turr);
+ if (arm != null)
+ aimAnim.Value.Nodes.Add(arm);
+
+ RenameNodeKey(atkSequence, "Sequence");
+ node.Value.Nodes.Add(aimAnim);
+ }
+ }
+ }
+
UpgradeActorRules(modData, engineVersion, ref node.Value.Nodes, node, depth + 1);
}