diff --git a/OpenRA.Mods.Cnc/OpenRA.Mods.Cnc.csproj b/OpenRA.Mods.Cnc/OpenRA.Mods.Cnc.csproj index f0756a9ca2..70b8c99318 100644 --- a/OpenRA.Mods.Cnc/OpenRA.Mods.Cnc.csproj +++ b/OpenRA.Mods.Cnc/OpenRA.Mods.Cnc.csproj @@ -68,6 +68,7 @@ + diff --git a/OpenRA.Mods.Cnc/Traits/Render/WithHarvesterSpriteBody.cs b/OpenRA.Mods.Cnc/Traits/Render/WithHarvesterSpriteBody.cs new file mode 100644 index 0000000000..2621a48cb8 --- /dev/null +++ b/OpenRA.Mods.Cnc/Traits/Render/WithHarvesterSpriteBody.cs @@ -0,0 +1,53 @@ +#region Copyright & License Information +/* + * Copyright 2007-2019 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.Collections.Generic; +using OpenRA.Activities; +using OpenRA.Graphics; +using OpenRA.Mods.Common.Graphics; +using OpenRA.Mods.Common.Traits; +using OpenRA.Mods.Common.Traits.Render; +using OpenRA.Traits; + +namespace OpenRA.Mods.Cnc.Traits.Render +{ + public class WithHarvesterSpriteBodyInfo : WithFacingSpriteBodyInfo, Requires + { + [Desc("Images switched between depending on fullness of harvester. Overrides RenderSprites.Image.")] + public readonly string[] ImageByFullness = { }; + + public override object Create(ActorInitializer init) { return new WithHarvesterSpriteBody(init, this); } + } + + public class WithHarvesterSpriteBody : WithFacingSpriteBody, ITick + { + readonly WithHarvesterSpriteBodyInfo info; + readonly Harvester harv; + + public WithHarvesterSpriteBody(ActorInitializer init, WithHarvesterSpriteBodyInfo info) + : base(init, info) + { + this.info = info; + harv = init.Self.Trait(); + } + + void ITick.Tick(Actor self) + { + if (harv == null || info.ImageByFullness.Length == 0) + return; + + var desiredState = harv.Fullness * (info.ImageByFullness.Length - 1) / 100; + var desiredImage = info.ImageByFullness[desiredState]; + + DefaultAnimation.ChangeImage(desiredImage, DefaultAnimation.CurrentSequence.Name); + } + } +} diff --git a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj index 9fa51d17b4..2d0ac08622 100644 --- a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj +++ b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj @@ -615,6 +615,7 @@ + diff --git a/OpenRA.Mods.Common/Traits/Render/WithHarvestAnimation.cs b/OpenRA.Mods.Common/Traits/Render/WithHarvestAnimation.cs index 955120dd61..8a29b5819f 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithHarvestAnimation.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithHarvestAnimation.cs @@ -17,9 +17,6 @@ namespace OpenRA.Mods.Common.Traits.Render { public class WithHarvestAnimationInfo : ITraitInfo, Requires, Requires { - [Desc("Prefix added to idle and harvest sequences depending on fullness of harvester.")] - [SequenceReference(null, true)] public readonly string[] PrefixByFullness = { "" }; - [Desc("Displayed while harvesting.")] [SequenceReference] public readonly string HarvestSequence = "harvest"; @@ -29,64 +26,26 @@ namespace OpenRA.Mods.Common.Traits.Render public object Create(ActorInitializer init) { return new WithHarvestAnimation(init, this); } } - public class WithHarvestAnimation : ITick, INotifyHarvesterAction + public class WithHarvestAnimation : INotifyHarvesterAction { public readonly WithHarvestAnimationInfo Info; readonly WithSpriteBody wsb; - readonly Harvester harv; - - // TODO: Remove this once WithSpriteBody has its own replacement - public bool IsModifying; public WithHarvestAnimation(ActorInitializer init, WithHarvestAnimationInfo info) { Info = info; - harv = init.Self.Trait(); wsb = init.Self.TraitsImplementing().Single(w => w.Info.Name == Info.Body); } - protected virtual string NormalizeHarvesterSequence(Actor self, string baseSequence) - { - var desiredState = harv.Fullness * (Info.PrefixByFullness.Length - 1) / 100; - var desiredPrefix = Info.PrefixByFullness[desiredState]; - - if (wsb.DefaultAnimation.HasSequence(desiredPrefix + baseSequence)) - return desiredPrefix + baseSequence; - else - return baseSequence; - } - - void ITick.Tick(Actor self) - { - var baseSequence = wsb.NormalizeSequence(self, wsb.Info.Sequence); - var sequence = NormalizeHarvesterSequence(self, baseSequence); - if (!IsModifying && wsb.DefaultAnimation.HasSequence(sequence) && wsb.DefaultAnimation.CurrentSequence.Name != sequence) - wsb.DefaultAnimation.ReplaceAnim(sequence); - } - void INotifyHarvesterAction.Harvested(Actor self, ResourceType resource) { - var baseSequence = wsb.NormalizeSequence(self, Info.HarvestSequence); - var sequence = NormalizeHarvesterSequence(self, baseSequence); - if (!IsModifying && wsb.DefaultAnimation.HasSequence(sequence)) - { - IsModifying = true; - wsb.PlayCustomAnimation(self, sequence, () => IsModifying = false); - } - } - - // If IsModifying isn't set to true, the docking animation - // will be overridden by the WithHarvestAnimation fullness modifier. - void INotifyHarvesterAction.Docked() - { - IsModifying = true; - } - - void INotifyHarvesterAction.Undocked() - { - IsModifying = false; + var sequence = wsb.NormalizeSequence(self, Info.HarvestSequence); + if (wsb.DefaultAnimation.HasSequence(sequence) && wsb.DefaultAnimation.CurrentSequence.Name != sequence) + wsb.PlayCustomAnimation(self, sequence); } + void INotifyHarvesterAction.Docked() { } + void INotifyHarvesterAction.Undocked() { } void INotifyHarvesterAction.MovingToResources(Actor self, CPos targetCell, Activity next) { } void INotifyHarvesterAction.MovingToRefinery(Actor self, Actor refineryActor, Activity next) { } void INotifyHarvesterAction.MovementCancelled(Actor self) { } diff --git a/OpenRA.Mods.Common/UpdateRules/Rules/20190314/SplitHarvesterSpriteBody.cs b/OpenRA.Mods.Common/UpdateRules/Rules/20190314/SplitHarvesterSpriteBody.cs new file mode 100644 index 0000000000..71d9446de1 --- /dev/null +++ b/OpenRA.Mods.Common/UpdateRules/Rules/20190314/SplitHarvesterSpriteBody.cs @@ -0,0 +1,64 @@ +#region Copyright & License Information +/* + * Copyright 2007-2019 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; +using System.Collections.Generic; +using System.Linq; + +namespace OpenRA.Mods.Common.UpdateRules.Rules +{ + public class SplitHarvesterSpriteBody : UpdateRule + { + public override string Name { get { return "Split fullness display from WithHarvestAnimation to new WithHarvesterSpriteBody"; } } + public override string Description + { + get + { + return "WithHarvestAnimation.PrefixByFullness logic was moved to a dedicated WithHarvesterSpriteBody."; + } + } + + readonly List> fullnessPrefixes = new List>(); + + public override IEnumerable AfterUpdate(ModData modData) + { + var message = "PrefixByFullness has been removed from WithHarvestAnimation.\n" + + "To display fullness levels, use the new WithHarvesterSpriteBody\n" + + "to switch between separate image sprites instead (see RA mod harvester for reference).\n" + + "The following places most likely need manual changes:\n" + + UpdateUtils.FormatMessageList(fullnessPrefixes.Select(n => n.Item1 + " (" + n.Item2 + ")")); + + if (fullnessPrefixes.Any()) + yield return message; + + fullnessPrefixes.Clear(); + } + + public override IEnumerable UpdateActorNode(ModData modData, MiniYamlNode actorNode) + { + var harvAnim = actorNode.LastChildMatching("WithHarvestAnimation"); + if (harvAnim != null) + { + var fullnessPrefix = harvAnim.LastChildMatching("PrefixByFullness"); + + // If PrefixByFullness is empty, no changes are needed. + if (fullnessPrefix == null) + yield break; + + harvAnim.RemoveNode(fullnessPrefix); + + fullnessPrefixes.Add(Tuple.Create(actorNode.Key, actorNode.Location.Filename)); + } + + yield break; + } + } +} diff --git a/OpenRA.Mods.Common/UpdateRules/UpdatePath.cs b/OpenRA.Mods.Common/UpdateRules/UpdatePath.cs index 4b97a8f865..30b8a9b6ba 100644 --- a/OpenRA.Mods.Common/UpdateRules/UpdatePath.cs +++ b/OpenRA.Mods.Common/UpdateRules/UpdatePath.cs @@ -124,6 +124,7 @@ namespace OpenRA.Mods.Common.UpdateRules new StreamlineRepairableTraits(), new ReplaceSpecialMoveConsiderations(), new RefactorHarvesterIdle(), + new SplitHarvesterSpriteBody(), }) }; diff --git a/mods/ra/rules/vehicles.yaml b/mods/ra/rules/vehicles.yaml index aae775c5f5..36a286c5e4 100644 --- a/mods/ra/rules/vehicles.yaml +++ b/mods/ra/rules/vehicles.yaml @@ -320,7 +320,6 @@ HARV: RevealsShroud: Range: 4c0 WithHarvestAnimation: - PrefixByFullness: empty-, half-, full- WithDockingAnimation: GpsDot: String: Harvester @@ -337,6 +336,9 @@ HARV: Explodes: RequiresCondition: !no-ore Weapon: OreExplosion + WithHarvesterSpriteBody: + ImageByFullness: harvempty, harvhalf, harv + -WithFacingSpriteBody: MCV: Inherits: ^Vehicle diff --git a/mods/ra/sequences/vehicles.yaml b/mods/ra/sequences/vehicles.yaml index e40e4ff4a4..91e7a01a74 100644 --- a/mods/ra/sequences/vehicles.yaml +++ b/mods/ra/sequences/vehicles.yaml @@ -17,43 +17,28 @@ truk: icon: trukicon harv: - idle: harvempty + idle: Facings: 32 UseClassicFacingFudge: True - harvest: harvempty + harvest: Start: 32 Length: 8 Facings: 8 - empty-idle: harvempty - Facings: 32 - UseClassicFacingFudge: True - empty-harvest: harvempty - Start: 32 - Length: 8 - Facings: 8 - half-idle: harvhalf - Facings: 32 - UseClassicFacingFudge: True - half-harvest: harvhalf - Start: 32 - Length: 8 - Facings: 8 - full-idle: - Facings: 32 - UseClassicFacingFudge: True - full-harvest: - Start: 32 - Length: 8 - Facings: 8 - dock: + dock: harv Start: 96 Length: 8 - dock-loop: + dock-loop: harv Start: 104 Length: 7 icon: harvicon Start: 0 +harvempty: + Inherits: harv + +harvhalf: + Inherits: harv + hhusk: idle: Facings: 32