diff --git a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj
index 946bf86782..12122fdce1 100644
--- a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj
+++ b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj
@@ -465,7 +465,7 @@
-
+
@@ -485,7 +485,7 @@
-
+
@@ -949,6 +949,7 @@
+
diff --git a/OpenRA.Mods.Common/Traits/Render/WithResources.cs b/OpenRA.Mods.Common/Traits/Render/WithResourceLevelOverlay.cs
similarity index 82%
rename from OpenRA.Mods.Common/Traits/Render/WithResources.cs
rename to OpenRA.Mods.Common/Traits/Render/WithResourceLevelOverlay.cs
index f52d24ed20..ed1869808d 100644
--- a/OpenRA.Mods.Common/Traits/Render/WithResources.cs
+++ b/OpenRA.Mods.Common/Traits/Render/WithResourceLevelOverlay.cs
@@ -15,16 +15,15 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits.Render
{
[Desc("Displays the fill status of PlayerResources with an extra sprite overlay on the actor.")]
- class WithResourcesInfo : ConditionalTraitInfo, Requires, Requires
+ class WithResourceLevelOverlayInfo : ConditionalTraitInfo, Requires, Requires
{
[Desc("Sequence name to use")]
[SequenceReference] public readonly string Sequence = "resources";
- public override object Create(ActorInitializer init) { return new WithResources(init.Self, this); }
+ public override object Create(ActorInitializer init) { return new WithResourceLevelOverlay(init.Self, this); }
}
- // TODO: Rename to WithResourcesOverlay to conform with our naming conventions
- class WithResources : ConditionalTrait, INotifyOwnerChanged, INotifyDamageStateChanged
+ class WithResourceLevelOverlay : ConditionalTrait, INotifyOwnerChanged, INotifyDamageStateChanged
{
readonly AnimationWithOffset anim;
readonly RenderSprites rs;
@@ -32,7 +31,7 @@ namespace OpenRA.Mods.Common.Traits.Render
PlayerResources playerResources;
- public WithResources(Actor self, WithResourcesInfo info)
+ public WithResourceLevelOverlay(Actor self, WithResourceLevelOverlayInfo info)
: base(info)
{
rs = self.Trait();
diff --git a/OpenRA.Mods.Common/Traits/Render/WithResourceLevelSpriteBody.cs b/OpenRA.Mods.Common/Traits/Render/WithResourceLevelSpriteBody.cs
new file mode 100644
index 0000000000..6e31578cdd
--- /dev/null
+++ b/OpenRA.Mods.Common/Traits/Render/WithResourceLevelSpriteBody.cs
@@ -0,0 +1,76 @@
+#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.Collections.Generic;
+using System.Linq;
+using OpenRA.Graphics;
+using OpenRA.Mods.Common.Graphics;
+using OpenRA.Traits;
+
+namespace OpenRA.Mods.Common.Traits.Render
+{
+ [Desc("Render trait for buildings that change the sprite according to the remaining resource storage capacity across all depots.")]
+ public class WithResourceLevelSpriteBodyInfo : WithSpriteBodyInfo
+ {
+ [Desc("Internal resource stages. Does not have to match number of sequence frames.")]
+ public readonly int Stages = 10;
+
+ public override object Create(ActorInitializer init) { return new WithResourceLevelSpriteBody(init, this); }
+
+ public override IEnumerable RenderPreviewSprites(ActorPreviewInitializer init, RenderSpritesInfo rs, string image, int facings, PaletteReference p)
+ {
+ if (!EnabledByDefault)
+ yield break;
+
+ var anim = new Animation(init.World, image);
+ anim.PlayFetchIndex(RenderSprites.NormalizeSequence(anim, init.GetDamageState(), Sequence), () => 0);
+
+ yield return new SpriteActorPreview(anim, () => WVec.Zero, () => 0, p, rs.Scale);
+ }
+ }
+
+ public class WithResourceLevelSpriteBody : WithSpriteBody, INotifyOwnerChanged
+ {
+ readonly WithResourceLevelSpriteBodyInfo info;
+ PlayerResources playerResources;
+
+ public WithResourceLevelSpriteBody(ActorInitializer init, WithResourceLevelSpriteBodyInfo info)
+ : base(init, info, () => 0)
+ {
+ this.info = info;
+ playerResources = init.Self.Owner.PlayerActor.Trait();
+ ConfigureAnimation(init.Self);
+ }
+
+ void ConfigureAnimation(Actor self)
+ {
+ DefaultAnimation.PlayFetchIndex(NormalizeSequence(self, Info.Sequence),
+ () => playerResources.ResourceCapacity != 0
+ ? ((info.Stages * DefaultAnimation.CurrentSequence.Length - 1) * playerResources.Resources) / (info.Stages * playerResources.ResourceCapacity)
+ : 0);
+ }
+
+ void INotifyOwnerChanged.OnOwnerChanged(Actor self, Player oldOwner, Player newOwner)
+ {
+ playerResources = newOwner.PlayerActor.Trait();
+ }
+
+ protected override void TraitEnabled(Actor self)
+ {
+ // Do nothing - we just want to disable the default WithSpriteBody implementation
+ }
+
+ public override void CancelCustomAnimation(Actor self)
+ {
+ ConfigureAnimation(self);
+ }
+ }
+}
diff --git a/OpenRA.Mods.Common/Traits/Render/WithSiloAnimation.cs b/OpenRA.Mods.Common/Traits/Render/WithSiloAnimation.cs
deleted file mode 100644
index 9eb2524a71..0000000000
--- a/OpenRA.Mods.Common/Traits/Render/WithSiloAnimation.cs
+++ /dev/null
@@ -1,60 +0,0 @@
-#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
-{
- [Desc("Render trait for buildings that change the sprite according to the remaining resource storage capacity across all depots.")]
- class WithSiloAnimationInfo : ConditionalTraitInfo, Requires, Requires
- {
- [Desc("Sequence to use for resources-dependent 'stages'."), SequenceReference]
- public readonly string Sequence = "stages";
-
- [Desc("Internal resource stages. Does not have to match number of sequence frames.")]
- public readonly int Stages = 10;
-
- [Desc("Which sprite body to play the animation on.")]
- public readonly string Body = "body";
-
- public override object Create(ActorInitializer init) { return new WithSiloAnimation(init, this); }
- }
-
- class WithSiloAnimation : ConditionalTrait, INotifyOwnerChanged
- {
- readonly WithSpriteBody wsb;
- PlayerResources playerResources;
-
- public WithSiloAnimation(ActorInitializer init, WithSiloAnimationInfo info)
- : base(info)
- {
- wsb = init.Self.TraitsImplementing().Single(w => w.Info.Name == info.Body);
- playerResources = init.Self.Owner.PlayerActor.Trait();
- }
-
- void PlayAnimation(Actor self)
- {
- wsb.DefaultAnimation.PlayFetchIndex(wsb.NormalizeSequence(self, Info.Sequence),
- () => playerResources.ResourceCapacity != 0
- ? ((Info.Stages * wsb.DefaultAnimation.CurrentSequence.Length - 1) * playerResources.Resources) / (Info.Stages * playerResources.ResourceCapacity)
- : 0);
- }
-
- void INotifyOwnerChanged.OnOwnerChanged(Actor self, Player oldOwner, Player newOwner)
- {
- playerResources = newOwner.PlayerActor.Trait();
- PlayAnimation(self);
- }
-
- protected override void TraitEnabled(Actor self) { PlayAnimation(self); }
- }
-}
diff --git a/OpenRA.Mods.Common/UpdateRules/Rules/20180923/RefactorResourceLevelAnimating.cs b/OpenRA.Mods.Common/UpdateRules/Rules/20180923/RefactorResourceLevelAnimating.cs
new file mode 100644
index 0000000000..d569be720a
--- /dev/null
+++ b/OpenRA.Mods.Common/UpdateRules/Rules/20180923/RefactorResourceLevelAnimating.cs
@@ -0,0 +1,76 @@
+#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.Collections.Generic;
+using System.Linq;
+
+namespace OpenRA.Mods.Common.UpdateRules.Rules
+{
+ public class RefactorResourceLevelAnimating : UpdateRule
+ {
+ public override string Name { get { return "Streamlined traits animating player resource level"; } }
+ public override string Description
+ {
+ get
+ {
+ return "Replaced WithSiloAnimation with WithResourceLevelSpriteBody and\n" +
+ "renamed WithResources to WithResourceLevelOverlay.";
+ }
+ }
+
+ readonly List locations = new List();
+
+ public override IEnumerable AfterUpdate(ModData modData)
+ {
+ if (locations.Any())
+ yield return "WithSiloAnimation has been replaced by WithResourceLevelSpriteBody.\n" +
+ "You may need to disable/remove any previous (including inherited) *SpriteBody traits\n" +
+ "on the following actors:\n" +
+ UpdateUtils.FormatMessageList(locations);
+
+ locations.Clear();
+ }
+
+ public override IEnumerable UpdateActorNode(ModData modData, MiniYamlNode actorNode)
+ {
+ foreach (var wr in actorNode.ChildrenMatching("WithResources"))
+ wr.RenameKey("WithResourceLevelOverlay");
+
+ var siloAnims = actorNode.ChildrenMatching("WithSiloAnimation");
+ foreach (var sa in siloAnims)
+ {
+ // If it's a trait removal, we only rename it.
+ if (sa.IsRemoval())
+ {
+ sa.RenameKey("WithResourceLevelSpriteBody");
+ continue;
+ }
+
+ var sequence = sa.LastChildMatching("Sequence");
+ var body = sa.LastChildMatching("Body");
+
+ if (sequence == null)
+ {
+ var newSequenceNode = new MiniYamlNode("Sequence", "stages");
+ sa.AddNode(newSequenceNode);
+ }
+
+ if (body != null)
+ sa.RemoveNode(body);
+
+ sa.RenameKey("WithResourceLevelSpriteBody");
+ locations.Add("{0} ({1})".F(actorNode.Key, sa.Location.Filename));
+ }
+
+ yield break;
+ }
+ }
+}
diff --git a/OpenRA.Mods.Common/UpdateRules/UpdatePath.cs b/OpenRA.Mods.Common/UpdateRules/UpdatePath.cs
index cf74f08295..fd69c0ebaf 100644
--- a/OpenRA.Mods.Common/UpdateRules/UpdatePath.cs
+++ b/OpenRA.Mods.Common/UpdateRules/UpdatePath.cs
@@ -112,6 +112,7 @@ namespace OpenRA.Mods.Common.UpdateRules
new RemovedAutoCarryallCircleTurnSpeed(),
new RemoveAttackIgnoresVisibility(),
new ReplacedWithChargeAnimation(),
+ new RefactorResourceLevelAnimating(),
})
};
diff --git a/mods/cnc/rules/structures.yaml b/mods/cnc/rules/structures.yaml
index 141be47808..a2b2003184 100644
--- a/mods/cnc/rules/structures.yaml
+++ b/mods/cnc/rules/structures.yaml
@@ -228,7 +228,7 @@ PROC:
SpawnOffset: 1,2
Facing: 64
WithBuildingBib:
- WithResources:
+ WithResourceLevelOverlay:
RequiresCondition: !build-incomplete
Power:
Amount: -40
@@ -257,8 +257,9 @@ SILO:
Range: 4c0
WithBuildingBib:
HasMinibib: Yes
- WithSiloAnimation:
- RequiresCondition: !build-incomplete
+ -WithSpriteBody:
+ WithResourceLevelSpriteBody:
+ Sequence: stages
StoresResources:
PipCount: 10
PipColor: Green
diff --git a/mods/d2k/rules/structures.yaml b/mods/d2k/rules/structures.yaml
index d4bcec2cfc..cf286926e3 100644
--- a/mods/d2k/rules/structures.yaml
+++ b/mods/d2k/rules/structures.yaml
@@ -353,8 +353,9 @@ silo:
fremen: silo.atreides
harkonnen: silo.harkonnen
corrino: silo.harkonnen
- WithSiloAnimation:
- RequiresCondition: !build-incomplete
+ -WithSpriteBody:
+ WithResourceLevelSpriteBody:
+ Sequence: stages
StoresResources:
PipColor: green
PipCount: 5
diff --git a/mods/ra/rules/structures.yaml b/mods/ra/rules/structures.yaml
index ee2bb714f2..bb6939f6f5 100644
--- a/mods/ra/rules/structures.yaml
+++ b/mods/ra/rules/structures.yaml
@@ -1273,8 +1273,9 @@ SILO:
Notification: CreditsStolen
WithBuildingBib:
HasMinibib: Yes
- WithSiloAnimation:
- RequiresCondition: !build-incomplete
+ -WithSpriteBody:
+ WithResourceLevelSpriteBody:
+ Sequence: stages
StoresResources:
PipCount: 5
Capacity: 3000
diff --git a/mods/ts/rules/shared-structures.yaml b/mods/ts/rules/shared-structures.yaml
index 1a00738dc8..43cf713ce8 100644
--- a/mods/ts/rules/shared-structures.yaml
+++ b/mods/ts/rules/shared-structures.yaml
@@ -160,10 +160,10 @@ GASILO:
FactionImages:
gdi: gasilo.gdi
nod: gasilo.nod
- WithSiloAnimation:
- RequiresCondition: !build-incomplete
- WithIdleOverlay@UNDERLAY:
+ WithResourceLevelOverlay@FILLSTAGE:
RequiresCondition: !build-incomplete
+ Sequence: stages
+ WithSpriteBody:
Sequence: idle-underlay
WithIdleOverlay@LIGHTS:
RequiresCondition: !build-incomplete