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