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