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