diff --git a/OpenRA.Mods.Cnc/Traits/Render/WithDeliveryAnimation.cs b/OpenRA.Mods.Cnc/Traits/Render/WithDeliveryAnimation.cs index 5a11468d14..d7761756b5 100644 --- a/OpenRA.Mods.Cnc/Traits/Render/WithDeliveryAnimation.cs +++ b/OpenRA.Mods.Cnc/Traits/Render/WithDeliveryAnimation.cs @@ -17,38 +17,40 @@ using OpenRA.Traits; namespace OpenRA.Mods.Cnc.Traits.Render { [Desc("Building animation to play when ProductionAirdrop is used to deliver units.")] - public class WithDeliveryAnimationInfo : ITraitInfo, Requires + public class WithDeliveryAnimationInfo : ConditionalTraitInfo, Requires { [SequenceReference] public readonly string ActiveSequence = "active"; - [SequenceReference] public readonly string IdleSequence = "idle"; - [Desc("Which sprite body to play the animation on.")] public readonly string Body = "body"; - public object Create(ActorInitializer init) { return new WithDeliveryAnimation(init.Self, this); } + public override object Create(ActorInitializer init) { return new WithDeliveryAnimation(init.Self, this); } } - public class WithDeliveryAnimation : INotifyDelivery + public class WithDeliveryAnimation : ConditionalTrait, INotifyDelivery { - readonly WithDeliveryAnimationInfo info; readonly WithSpriteBody wsb; public WithDeliveryAnimation(Actor self, WithDeliveryAnimationInfo info) + : base(info) { wsb = self.TraitsImplementing().Single(w => w.Info.Name == info.Body); - - this.info = info; } public void IncomingDelivery(Actor self) { - wsb.PlayCustomAnimationRepeating(self, info.ActiveSequence); + if (!IsTraitDisabled) + wsb.PlayCustomAnimationRepeating(self, Info.ActiveSequence); } public void Delivered(Actor self) { - wsb.PlayCustomAnimationRepeating(self, info.IdleSequence); + wsb.CancelCustomAnimation(self); + } + + protected override void TraitDisabled(Actor self) + { + wsb.CancelCustomAnimation(self); } } } \ No newline at end of file diff --git a/OpenRA.Mods.Cnc/Traits/Render/WithDockingOverlay.cs b/OpenRA.Mods.Cnc/Traits/Render/WithDockingOverlay.cs index 8a9b09925e..a5100108fa 100644 --- a/OpenRA.Mods.Cnc/Traits/Render/WithDockingOverlay.cs +++ b/OpenRA.Mods.Cnc/Traits/Render/WithDockingOverlay.cs @@ -17,7 +17,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Cnc.Traits.Render { [Desc("Rendered on the refinery when a voxel harvester is docking and undocking.")] - public class WithDockingOverlayInfo : ITraitInfo, Requires, Requires + public class WithDockingOverlayInfo : PausableConditionalTraitInfo, Requires, Requires { [Desc("Sequence name to use")] [SequenceReference] public readonly string Sequence = "unload-overlay"; @@ -31,29 +31,27 @@ namespace OpenRA.Mods.Cnc.Traits.Render [Desc("Custom palette is a player palette BaseName")] public readonly bool IsPlayerPalette = false; - public object Create(ActorInitializer init) { return new WithDockingOverlay(init.Self, this); } + public override object Create(ActorInitializer init) { return new WithDockingOverlay(init.Self, this); } } - public class WithDockingOverlay + public class WithDockingOverlay : PausableConditionalTrait { - public readonly WithDockingOverlayInfo Info; public readonly AnimationWithOffset WithOffset; public bool Visible; public WithDockingOverlay(Actor self, WithDockingOverlayInfo info) + : base(info) { - Info = info; - var rs = self.Trait(); var body = self.Trait(); - var overlay = new Animation(self.World, rs.GetImage(self)); + var overlay = new Animation(self.World, rs.GetImage(self), () => IsTraitPaused); overlay.Play(info.Sequence); WithOffset = new AnimationWithOffset(overlay, () => body.LocalToWorld(info.Offset.Rotate(body.QuantizeOrientation(self, self.Orientation))), - () => !Visible); + () => !Visible || IsTraitDisabled); rs.Add(WithOffset, info.Palette, info.IsPlayerPalette); } diff --git a/OpenRA.Mods.Common/Traits/Render/WithAcceptDeliveredCashAnimation.cs b/OpenRA.Mods.Common/Traits/Render/WithAcceptDeliveredCashAnimation.cs index a61f45a264..47decbc749 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithAcceptDeliveredCashAnimation.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithAcceptDeliveredCashAnimation.cs @@ -15,7 +15,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits.Render { [Desc("Replaces the building animation when it accepts a cash delivery unit.")] - public class WithAcceptDeliveredCashAnimationInfo : ITraitInfo, Requires + public class WithAcceptDeliveredCashAnimationInfo : ConditionalTraitInfo, Requires { [Desc("Sequence name to use")] [SequenceReference] public readonly string Sequence = "active"; @@ -23,41 +23,27 @@ namespace OpenRA.Mods.Common.Traits.Render [Desc("Which sprite body to play the animation on.")] public readonly string Body = "body"; - public object Create(ActorInitializer init) { return new WithAcceptDeliveredCashAnimation(init.Self, this); } + public override object Create(ActorInitializer init) { return new WithAcceptDeliveredCashAnimation(init.Self, this); } } - public class WithAcceptDeliveredCashAnimation : INotifyCashTransfer, INotifyBuildComplete, INotifySold + public class WithAcceptDeliveredCashAnimation : ConditionalTrait, INotifyCashTransfer { - readonly WithAcceptDeliveredCashAnimationInfo info; readonly WithSpriteBody wsb; - bool buildComplete; public WithAcceptDeliveredCashAnimation(Actor self, WithAcceptDeliveredCashAnimationInfo info) + : base(info) { - this.info = info; wsb = self.TraitsImplementing().Single(w => w.Info.Name == info.Body); } - void INotifyBuildComplete.BuildingComplete(Actor self) - { - buildComplete = true; - } - - void INotifySold.Selling(Actor self) - { - buildComplete = false; - } - - void INotifySold.Sold(Actor self) { } - bool playing; void INotifyCashTransfer.OnAcceptingCash(Actor self, Actor donor) { - if (!buildComplete || playing) + if (IsTraitDisabled || playing) return; playing = true; - wsb.PlayCustomAnimation(self, info.Sequence, () => playing = false); + wsb.PlayCustomAnimation(self, Info.Sequence, () => playing = false); } void INotifyCashTransfer.OnDeliveringCash(Actor self, Actor acceptor) { } diff --git a/OpenRA.Mods.Common/Traits/Render/WithBridgeSpriteBody.cs b/OpenRA.Mods.Common/Traits/Render/WithBridgeSpriteBody.cs index fd54e11c26..44392d3eb8 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithBridgeSpriteBody.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithBridgeSpriteBody.cs @@ -68,8 +68,10 @@ namespace OpenRA.Mods.Common.Traits.Render bridgeLayer = init.World.WorldActor.Trait(); } - protected override void OnBuildComplete(Actor self) + protected override void TraitEnabled(Actor self) { + base.TraitEnabled(self); + if (bridgeInfo.AOffset != CVec.Zero) UpdateNeighbour(bridgeInfo.AOffset); diff --git a/OpenRA.Mods.Common/Traits/Render/WithBuildingPlacedAnimation.cs b/OpenRA.Mods.Common/Traits/Render/WithBuildingPlacedAnimation.cs index 771a830229..700c20da25 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithBuildingPlacedAnimation.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithBuildingPlacedAnimation.cs @@ -26,41 +26,25 @@ namespace OpenRA.Mods.Common.Traits.Render public override object Create(ActorInitializer init) { return new WithBuildingPlacedAnimation(init.Self, this); } } - public class WithBuildingPlacedAnimation : ConditionalTrait, INotifyBuildingPlaced, INotifyBuildComplete, INotifySold, INotifyTransform + public class WithBuildingPlacedAnimation : ConditionalTrait, INotifyBuildingPlaced { readonly WithSpriteBody wsb; - bool buildComplete; public WithBuildingPlacedAnimation(Actor self, WithBuildingPlacedAnimationInfo info) : base(info) { wsb = self.TraitsImplementing().Single(w => w.Info.Name == info.Body); - buildComplete = !self.Info.HasTraitInfo(); } - void INotifyBuildComplete.BuildingComplete(Actor self) - { - buildComplete = true; - } - - void INotifySold.Sold(Actor self) { } - void INotifySold.Selling(Actor self) - { - buildComplete = false; - } - - void INotifyTransform.BeforeTransform(Actor self) - { - buildComplete = false; - } - - void INotifyTransform.OnTransform(Actor self) { } - void INotifyTransform.AfterTransform(Actor self) { } - void INotifyBuildingPlaced.BuildingPlaced(Actor self) { - if (!IsTraitDisabled && buildComplete) + if (!IsTraitDisabled) wsb.PlayCustomAnimation(self, Info.Sequence); } + + protected override void TraitDisabled(Actor self) + { + wsb.CancelCustomAnimation(self); + } } } \ No newline at end of file diff --git a/OpenRA.Mods.Common/Traits/Render/WithBuildingPlacedOverlay.cs b/OpenRA.Mods.Common/Traits/Render/WithBuildingPlacedOverlay.cs index 3c2e8a873c..66ab5637df 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithBuildingPlacedOverlay.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithBuildingPlacedOverlay.cs @@ -15,7 +15,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits.Render { [Desc("Rendered when the actor constructed a building.")] - public class WithBuildingPlacedOverlayInfo : ITraitInfo, Requires, Requires + public class WithBuildingPlacedOverlayInfo : ConditionalTraitInfo, Requires, Requires { [Desc("Sequence name to use")] [SequenceReference] public readonly string Sequence = "crane-overlay"; @@ -29,52 +29,30 @@ namespace OpenRA.Mods.Common.Traits.Render [Desc("Custom palette is a player palette BaseName")] public readonly bool IsPlayerPalette = false; - public object Create(ActorInitializer init) { return new WithBuildingPlacedOverlay(init.Self, this); } + public override object Create(ActorInitializer init) { return new WithBuildingPlacedOverlay(init.Self, this); } } - public class WithBuildingPlacedOverlay : INotifyBuildComplete, INotifySold, INotifyDamageStateChanged, INotifyBuildingPlaced, INotifyTransform + public class WithBuildingPlacedOverlay : ConditionalTrait, INotifyDamageStateChanged, INotifyBuildingPlaced { readonly Animation overlay; - bool buildComplete; bool visible; public WithBuildingPlacedOverlay(Actor self, WithBuildingPlacedOverlayInfo info) + : base(info) { var rs = self.Trait(); var body = self.Trait(); - buildComplete = !self.Info.HasTraitInfo(); // always render instantly for units - overlay = new Animation(self.World, rs.GetImage(self)); var anim = new AnimationWithOffset(overlay, () => body.LocalToWorld(info.Offset.Rotate(body.QuantizeOrientation(self, self.Orientation))), - () => !visible || !buildComplete); + () => !visible || IsTraitDisabled); overlay.PlayThen(info.Sequence, () => visible = false); rs.Add(anim, info.Palette, info.IsPlayerPalette); } - void INotifyBuildComplete.BuildingComplete(Actor self) - { - buildComplete = true; - visible = false; - } - - void INotifySold.Sold(Actor self) { } - void INotifySold.Selling(Actor self) - { - buildComplete = false; - } - - void INotifyTransform.BeforeTransform(Actor self) - { - buildComplete = false; - } - - void INotifyTransform.OnTransform(Actor self) { } - void INotifyTransform.AfterTransform(Actor self) { } - void INotifyDamageStateChanged.DamageStateChanged(Actor self, AttackInfo e) { overlay.ReplaceAnim(RenderSprites.NormalizeSequence(overlay, e.DamageState, overlay.CurrentSequence.Name)); diff --git a/OpenRA.Mods.Common/Traits/Render/WithChargeAnimation.cs b/OpenRA.Mods.Common/Traits/Render/WithChargeAnimation.cs index 1982c8ece8..b5253aefe2 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithChargeAnimation.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithChargeAnimation.cs @@ -15,7 +15,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits.Render { [Desc("Render trait that varies the animation frame based on the AttackCharges trait's charge level.")] - class WithChargeAnimationInfo : ITraitInfo, Requires, Requires + class WithChargeAnimationInfo : ConditionalTraitInfo, Requires, Requires { [SequenceReference] [Desc("Sequence to use for the charge levels.")] @@ -24,26 +24,25 @@ namespace OpenRA.Mods.Common.Traits.Render [Desc("Which sprite body to play the animation on.")] public readonly string Body = "body"; - public object Create(ActorInitializer init) { return new WithChargeAnimation(init.Self, this); } + public override object Create(ActorInitializer init) { return new WithChargeAnimation(init.Self, this); } } - class WithChargeAnimation : INotifyBuildComplete + class WithChargeAnimation : ConditionalTrait { - readonly WithChargeAnimationInfo info; readonly WithSpriteBody wsb; readonly AttackCharges attackCharges; public WithChargeAnimation(Actor self, WithChargeAnimationInfo info) + : base(info) { - this.info = info; wsb = self.TraitsImplementing().Single(w => w.Info.Name == info.Body); attackCharges = self.Trait(); } - void INotifyBuildComplete.BuildingComplete(Actor self) + protected override void TraitEnabled(Actor self) { var attackChargesInfo = (AttackChargesInfo)attackCharges.Info; - wsb.DefaultAnimation.PlayFetchIndex(wsb.NormalizeSequence(self, info.Sequence), + wsb.DefaultAnimation.PlayFetchIndex(wsb.NormalizeSequence(self, Info.Sequence), () => int2.Lerp(0, wsb.DefaultAnimation.CurrentSequence.Length, attackCharges.ChargeLevel, attackChargesInfo.ChargeLevel + 1)); } } diff --git a/OpenRA.Mods.Common/Traits/Render/WithChargeOverlay.cs b/OpenRA.Mods.Common/Traits/Render/WithChargeOverlay.cs index 53a2ab7abd..acd7aa1524 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithChargeOverlay.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithChargeOverlay.cs @@ -15,7 +15,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits.Render { [Desc("Render overlay that varies the animation frame based on the AttackCharges trait's charge level.")] - class WithChargeOverlayInfo : ITraitInfo, Requires, Requires + class WithChargeOverlayInfo : PausableConditionalTraitInfo, Requires, Requires { [SequenceReference] [Desc("Sequence to use for the charge levels.")] @@ -27,46 +27,33 @@ namespace OpenRA.Mods.Common.Traits.Render [Desc("Custom palette is a player palette BaseName")] public readonly bool IsPlayerPalette = false; - public object Create(ActorInitializer init) { return new WithChargeOverlay(init.Self, this); } + public override object Create(ActorInitializer init) { return new WithChargeOverlay(init.Self, this); } } - class WithChargeOverlay : INotifyBuildComplete, INotifySold, INotifyDamageStateChanged + class WithChargeOverlay : PausableConditionalTrait, INotifyDamageStateChanged { - readonly WithChargeOverlayInfo info; readonly Animation overlay; - readonly RenderSprites rs; - readonly WithSpriteBody wsb; - - bool buildComplete; public WithChargeOverlay(Actor self, WithChargeOverlayInfo info) + : base(info) { - this.info = info; - rs = self.Trait(); - wsb = self.Trait(); + var rs = self.Trait(); + var wsb = self.Trait(); var attackCharges = self.Trait(); var attackChargesInfo = (AttackChargesInfo)attackCharges.Info; - overlay = new Animation(self.World, rs.GetImage(self)); + overlay = new Animation(self.World, rs.GetImage(self), () => IsTraitPaused); overlay.PlayFetchIndex(wsb.NormalizeSequence(self, info.Sequence), () => int2.Lerp(0, overlay.CurrentSequence.Length, attackCharges.ChargeLevel, attackChargesInfo.ChargeLevel + 1)); - rs.Add(new AnimationWithOffset(overlay, null, () => !buildComplete, 1024), + rs.Add(new AnimationWithOffset(overlay, null, () => IsTraitDisabled, 1024), info.Palette, info.IsPlayerPalette); } - void INotifyBuildComplete.BuildingComplete(Actor self) - { - buildComplete = true; - } - void INotifyDamageStateChanged.DamageStateChanged(Actor self, AttackInfo e) { - overlay.ReplaceAnim(RenderSprites.NormalizeSequence(overlay, e.DamageState, info.Sequence)); + overlay.ReplaceAnim(RenderSprites.NormalizeSequence(overlay, e.DamageState, Info.Sequence)); } - - void INotifySold.Selling(Actor self) { buildComplete = false; } - void INotifySold.Sold(Actor self) { } } } diff --git a/OpenRA.Mods.Common/Traits/Render/WithDeadBridgeSpriteBody.cs b/OpenRA.Mods.Common/Traits/Render/WithDeadBridgeSpriteBody.cs index 235460ad3e..3c343f56ff 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithDeadBridgeSpriteBody.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithDeadBridgeSpriteBody.cs @@ -81,8 +81,10 @@ namespace OpenRA.Mods.Common.Traits.Render return bridgeInfo.RampActors.Contains(neighbour.Info.Name); } - protected override void OnBuildComplete(Actor self) + protected override void TraitEnabled(Actor self) { + base.TraitEnabled(self); + self.World.AddFrameEndTask(w => { var aRamp = bridgeInfo.AOffset != CVec.Zero && RampExists(self, bridgeInfo.AOffset); diff --git a/OpenRA.Mods.Common/Traits/Render/WithDockedOverlay.cs b/OpenRA.Mods.Common/Traits/Render/WithDockedOverlay.cs index 7cf107e99e..32cf530f6e 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithDockedOverlay.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithDockedOverlay.cs @@ -16,7 +16,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits.Render { [Desc("Rendered when a harvester is docked.")] - public class WithDockedOverlayInfo : ITraitInfo, Requires, Requires + public class WithDockedOverlayInfo : PausableConditionalTraitInfo, Requires, Requires { [Desc("Sequence name to use")] [SequenceReference] public readonly string Sequence = "docking-overlay"; @@ -30,31 +30,26 @@ namespace OpenRA.Mods.Common.Traits.Render [Desc("Custom palette is a player palette BaseName")] public readonly bool IsPlayerPalette = false; - public object Create(ActorInitializer init) { return new WithDockedOverlay(init.Self, this); } + public override object Create(ActorInitializer init) { return new WithDockedOverlay(init.Self, this); } } - public class WithDockedOverlay : INotifyDocking, INotifyBuildComplete, INotifySold + public class WithDockedOverlay : PausableConditionalTrait, INotifyDocking { - readonly WithDockedOverlayInfo info; readonly AnimationWithOffset anim; - bool buildComplete; bool docked; public WithDockedOverlay(Actor self, WithDockedOverlayInfo info) + : base(info) { - this.info = info; - var rs = self.Trait(); var body = self.Trait(); - buildComplete = !self.Info.HasTraitInfo(); // always render instantly for units - - var overlay = new Animation(self.World, rs.GetImage(self)); + var overlay = new Animation(self.World, rs.GetImage(self), () => IsTraitPaused); overlay.Play(info.Sequence); anim = new AnimationWithOffset(overlay, () => body.LocalToWorld(info.Offset.Rotate(body.QuantizeOrientation(self, self.Orientation))), - () => !buildComplete || !docked); + () => IsTraitDisabled || !docked); rs.Add(anim, info.Palette, info.IsPlayerPalette); } @@ -62,18 +57,7 @@ namespace OpenRA.Mods.Common.Traits.Render void PlayDockingOverlay() { if (docked) - anim.Animation.PlayThen(info.Sequence, PlayDockingOverlay); - } - - void INotifyBuildComplete.BuildingComplete(Actor self) - { - buildComplete = true; - } - - void INotifySold.Sold(Actor self) { } - void INotifySold.Selling(Actor self) - { - buildComplete = false; + anim.Animation.PlayThen(Info.Sequence, PlayDockingOverlay); } void INotifyDocking.Docked(Actor self, Actor harvester) { docked = true; PlayDockingOverlay(); } diff --git a/OpenRA.Mods.Common/Traits/Render/WithGateSpriteBody.cs b/OpenRA.Mods.Common/Traits/Render/WithGateSpriteBody.cs index bb4c00a977..aa0e90651e 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithGateSpriteBody.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithGateSpriteBody.cs @@ -63,7 +63,7 @@ namespace OpenRA.Mods.Common.Traits.Render void UpdateState(Actor self) { - if (renderOpen) + if (renderOpen || IsTraitPaused) DefaultAnimation.PlayRepeating(NormalizeSequence(self, gateBodyInfo.OpenSequence)); else DefaultAnimation.PlayFetchIndex(NormalizeSequence(self, Info.Sequence), GetGateFrame); @@ -91,8 +91,10 @@ namespace OpenRA.Mods.Common.Traits.Render UpdateState(self); } - protected override void OnBuildComplete(Actor self) + protected override void TraitEnabled(Actor self) { + base.TraitEnabled(self); + UpdateState(self); UpdateNeighbours(self); } diff --git a/OpenRA.Mods.Common/Traits/Render/WithIdleAnimation.cs b/OpenRA.Mods.Common/Traits/Render/WithIdleAnimation.cs index 8bc391a03e..0a3c7d6f9c 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithIdleAnimation.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithIdleAnimation.cs @@ -28,23 +28,21 @@ namespace OpenRA.Mods.Common.Traits.Render public override object Create(ActorInitializer init) { return new WithIdleAnimation(init.Self, this); } } - public class WithIdleAnimation : ConditionalTrait, ITick, INotifyBuildComplete, INotifySold + public class WithIdleAnimation : ConditionalTrait, ITick { readonly WithSpriteBody wsb; - bool buildComplete; int ticks; public WithIdleAnimation(Actor self, WithIdleAnimationInfo info) : base(info) { wsb = self.TraitsImplementing().Single(w => w.Info.Name == Info.Body); - buildComplete = !self.Info.HasTraitInfo(); // always render instantly for units ticks = info.Interval; } void ITick.Tick(Actor self) { - if (!buildComplete || IsTraitDisabled) + if (IsTraitDisabled) return; if (--ticks <= 0) @@ -54,16 +52,9 @@ namespace OpenRA.Mods.Common.Traits.Render } } - void INotifyBuildComplete.BuildingComplete(Actor self) + protected override void TraitDisabled(Actor self) { - buildComplete = true; + wsb.CancelCustomAnimation(self); } - - void INotifySold.Selling(Actor self) - { - buildComplete = false; - } - - void INotifySold.Sold(Actor self) { } } } diff --git a/OpenRA.Mods.Common/Traits/Render/WithIdleOverlay.cs b/OpenRA.Mods.Common/Traits/Render/WithIdleOverlay.cs index 0685463e9c..f90b54975c 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithIdleOverlay.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithIdleOverlay.cs @@ -35,9 +35,6 @@ namespace OpenRA.Mods.Common.Traits.Render [Desc("Custom palette is a player palette BaseName")] public readonly bool IsPlayerPalette = false; - // TODO: Remove this when the buildComplete code is replaced with conditions. - public readonly bool RenderBeforeBuildComplete = false; - public override object Create(ActorInitializer init) { return new WithIdleOverlay(init.Self, this); } public IEnumerable RenderPreviewSprites(ActorPreviewInitializer init, RenderSpritesInfo rs, string image, int facings, PaletteReference p) @@ -73,10 +70,9 @@ namespace OpenRA.Mods.Common.Traits.Render } } - public class WithIdleOverlay : PausableConditionalTrait, INotifyDamageStateChanged, INotifyBuildComplete, INotifySold, INotifyTransform + public class WithIdleOverlay : PausableConditionalTrait, INotifyDamageStateChanged { readonly Animation overlay; - bool buildComplete; public WithIdleOverlay(Actor self, WithIdleOverlayInfo info) : base(info) @@ -84,8 +80,7 @@ namespace OpenRA.Mods.Common.Traits.Render var rs = self.Trait(); var body = self.Trait(); - buildComplete = !self.Info.HasTraitInfo(); // always render instantly for units - overlay = new Animation(self.World, rs.GetImage(self), () => IsTraitPaused || (!info.RenderBeforeBuildComplete && !buildComplete)); + overlay = new Animation(self.World, rs.GetImage(self), () => IsTraitPaused); if (info.StartSequence != null) overlay.PlayThen(RenderSprites.NormalizeSequence(overlay, self.GetDamageState(), info.StartSequence), () => overlay.PlayRepeating(RenderSprites.NormalizeSequence(overlay, self.GetDamageState(), info.Sequence))); @@ -94,31 +89,12 @@ namespace OpenRA.Mods.Common.Traits.Render var anim = new AnimationWithOffset(overlay, () => body.LocalToWorld(info.Offset.Rotate(body.QuantizeOrientation(self, self.Orientation))), - () => IsTraitDisabled || (!info.RenderBeforeBuildComplete && !buildComplete), + () => IsTraitDisabled, p => RenderUtils.ZOffsetFromCenter(self, p, 1)); rs.Add(anim, info.Palette, info.IsPlayerPalette); } - void INotifyBuildComplete.BuildingComplete(Actor self) - { - buildComplete = true; - } - - void INotifySold.Sold(Actor self) { } - void INotifySold.Selling(Actor self) - { - buildComplete = false; - } - - void INotifyTransform.BeforeTransform(Actor self) - { - buildComplete = false; - } - - void INotifyTransform.OnTransform(Actor self) { } - void INotifyTransform.AfterTransform(Actor self) { } - void INotifyDamageStateChanged.DamageStateChanged(Actor self, AttackInfo e) { overlay.ReplaceAnim(RenderSprites.NormalizeSequence(overlay, e.DamageState, overlay.CurrentSequence.Name)); diff --git a/OpenRA.Mods.Common/Traits/Render/WithNukeLaunchAnimation.cs b/OpenRA.Mods.Common/Traits/Render/WithNukeLaunchAnimation.cs index c098d98dda..70100aabad 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithNukeLaunchAnimation.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithNukeLaunchAnimation.cs @@ -26,33 +26,25 @@ namespace OpenRA.Mods.Common.Traits.Render public override object Create(ActorInitializer init) { return new WithNukeLaunchAnimation(init.Self, this); } } - public class WithNukeLaunchAnimation : ConditionalTrait, INotifyNuke, INotifyBuildComplete, INotifySold + public class WithNukeLaunchAnimation : ConditionalTrait, INotifyNuke { - readonly WithSpriteBody spriteBody; - bool buildComplete; + readonly WithSpriteBody wsb; public WithNukeLaunchAnimation(Actor self, WithNukeLaunchAnimationInfo info) : base(info) { - spriteBody = self.TraitsImplementing().Single(w => w.Info.Name == Info.Body); + wsb = self.TraitsImplementing().Single(w => w.Info.Name == Info.Body); } void INotifyNuke.Launching(Actor self) { - if (buildComplete && !IsTraitDisabled) - spriteBody.PlayCustomAnimation(self, Info.Sequence, () => spriteBody.CancelCustomAnimation(self)); + if (!IsTraitDisabled) + wsb.PlayCustomAnimation(self, Info.Sequence, () => wsb.CancelCustomAnimation(self)); } - void INotifyBuildComplete.BuildingComplete(Actor self) + protected override void TraitDisabled(Actor self) { - buildComplete = true; + wsb.CancelCustomAnimation(self); } - - void INotifySold.Selling(Actor self) - { - buildComplete = false; - } - - void INotifySold.Sold(Actor self) { } } } \ No newline at end of file diff --git a/OpenRA.Mods.Common/Traits/Render/WithNukeLaunchOverlay.cs b/OpenRA.Mods.Common/Traits/Render/WithNukeLaunchOverlay.cs index 4dbe0a7462..85e5604337 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithNukeLaunchOverlay.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithNukeLaunchOverlay.cs @@ -33,10 +33,9 @@ namespace OpenRA.Mods.Common.Traits.Render public override object Create(ActorInitializer init) { return new WithNukeLaunchOverlay(init.Self, this); } } - public class WithNukeLaunchOverlay : ConditionalTrait, INotifyBuildComplete, INotifySold, INotifyNuke + public class WithNukeLaunchOverlay : ConditionalTrait, INotifyNuke { readonly Animation overlay; - bool buildComplete; bool visible; public WithNukeLaunchOverlay(Actor self, WithNukeLaunchOverlayInfo info) @@ -45,29 +44,17 @@ namespace OpenRA.Mods.Common.Traits.Render var rs = self.Trait(); var body = self.Trait(); - buildComplete = !self.Info.HasTraitInfo(); // always render instantly for units overlay = new Animation(self.World, rs.GetImage(self)); overlay.PlayThen(info.Sequence, () => visible = false); var anim = new AnimationWithOffset(overlay, () => body.LocalToWorld(info.Offset.Rotate(body.QuantizeOrientation(self, self.Orientation))), - () => IsTraitDisabled || !visible || !buildComplete, + () => IsTraitDisabled || !visible, p => RenderUtils.ZOffsetFromCenter(self, p, 1)); rs.Add(anim, info.Palette, info.IsPlayerPalette); } - void INotifyBuildComplete.BuildingComplete(Actor self) - { - buildComplete = true; - } - - void INotifySold.Sold(Actor self) { } - void INotifySold.Selling(Actor self) - { - buildComplete = false; - } - void INotifyNuke.Launching(Actor self) { visible = true; diff --git a/OpenRA.Mods.Common/Traits/Render/WithProductionDoorOverlay.cs b/OpenRA.Mods.Common/Traits/Render/WithProductionDoorOverlay.cs index d6caedfe2e..4a8e7b3d32 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithProductionDoorOverlay.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithProductionDoorOverlay.cs @@ -18,12 +18,10 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits.Render { [Desc("Play an animation when a unit exits or blocks the exit after production finished.")] - class WithProductionDoorOverlayInfo : ITraitInfo, IRenderActorPreviewSpritesInfo, Requires, Requires, Requires + class WithProductionDoorOverlayInfo : ConditionalTraitInfo, IRenderActorPreviewSpritesInfo, Requires, Requires, Requires { public readonly string Sequence = "build-door"; - public object Create(ActorInitializer init) { return new WithProductionDoorOverlay(init.Self, this); } - public IEnumerable RenderPreviewSprites(ActorPreviewInitializer init, RenderSpritesInfo rs, string image, int facings, PaletteReference p) { var anim = new Animation(init.World, image, () => 0); @@ -33,18 +31,18 @@ namespace OpenRA.Mods.Common.Traits.Render var offset = bi.CenterOffset(init.World).Y + 512; // Additional 512 units move from center -> top of cell yield return new SpriteActorPreview(anim, () => WVec.Zero, () => offset, p, rs.Scale); } + + public override object Create(ActorInitializer init) { return new WithProductionDoorOverlay(init.Self, this); } } - class WithProductionDoorOverlay : INotifyBuildComplete, ITick, INotifyProduction, INotifySold, INotifyTransform, INotifyDamageStateChanged + class WithProductionDoorOverlay : ConditionalTrait, ITick, INotifyProduction, INotifyDamageStateChanged { readonly Animation door; - int desiredFrame; - CPos openExit; - bool buildComplete; public WithProductionDoorOverlay(Actor self, WithProductionDoorOverlayInfo info) + : base(info) { var renderSprites = self.Trait(); door = new Animation(self.World, renderSprites.GetImage(self)); @@ -54,12 +52,7 @@ namespace OpenRA.Mods.Common.Traits.Render var buildingInfo = self.Info.TraitInfo(); var offset = buildingInfo.CenterOffset(self.World).Y + 512; - renderSprites.Add(new AnimationWithOffset(door, null, () => !buildComplete, offset)); - } - - void INotifyBuildComplete.BuildingComplete(Actor self) - { - buildComplete = true; + renderSprites.Add(new AnimationWithOffset(door, null, () => IsTraitDisabled, offset)); } void ITick.Tick(Actor self) @@ -79,12 +72,5 @@ namespace OpenRA.Mods.Common.Traits.Render openExit = exit; desiredFrame = door.CurrentSequence.Length - 1; } - - void INotifySold.Selling(Actor self) { buildComplete = false; } - void INotifySold.Sold(Actor self) { } - - void INotifyTransform.BeforeTransform(Actor self) { buildComplete = false; } - void INotifyTransform.OnTransform(Actor self) { } - void INotifyTransform.AfterTransform(Actor self) { } } } diff --git a/OpenRA.Mods.Common/Traits/Render/WithProductionOverlay.cs b/OpenRA.Mods.Common/Traits/Render/WithProductionOverlay.cs index a057f44274..f019c3f6e1 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithProductionOverlay.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithProductionOverlay.cs @@ -19,7 +19,7 @@ namespace OpenRA.Mods.Common.Traits.Render { [Desc("Renders an animation when the Production trait of the actor is activated.", "Works both with per player ClassicProductionQueue and per building ProductionQueue, but needs any of these.")] - public class WithProductionOverlayInfo : ITraitInfo, Requires, Requires, Requires + public class WithProductionOverlayInfo : PausableConditionalTraitInfo, Requires, Requires, Requires { [Desc("Queues that should be producing for this overlay to render.")] public readonly HashSet Queues = new HashSet(); @@ -36,16 +36,14 @@ namespace OpenRA.Mods.Common.Traits.Render [Desc("Custom palette is a player palette BaseName")] public readonly bool IsPlayerPalette = false; - public object Create(ActorInitializer init) { return new WithProductionOverlay(init.Self, this); } + public override object Create(ActorInitializer init) { return new WithProductionOverlay(init.Self, this); } } - public class WithProductionOverlay : INotifyDamageStateChanged, INotifyCreated, INotifyBuildComplete, INotifySold, INotifyOwnerChanged + public class WithProductionOverlay : PausableConditionalTrait, INotifyDamageStateChanged, INotifyCreated, INotifyOwnerChanged { - readonly WithProductionOverlayInfo info; readonly Animation overlay; readonly ProductionInfo production; ProductionQueue[] queues; - bool buildComplete; bool IsProducing { @@ -53,21 +51,19 @@ namespace OpenRA.Mods.Common.Traits.Render } public WithProductionOverlay(Actor self, WithProductionOverlayInfo info) + : base(info) { - this.info = info; - var rs = self.Trait(); var body = self.Trait(); - buildComplete = !self.Info.HasTraitInfo(); // always render instantly for units production = self.Info.TraitInfo(); - overlay = new Animation(self.World, rs.GetImage(self)); + overlay = new Animation(self.World, rs.GetImage(self), () => IsTraitPaused); overlay.PlayRepeating(info.Sequence); var anim = new AnimationWithOffset(overlay, () => body.LocalToWorld(info.Offset.Rotate(body.QuantizeOrientation(self, self.Orientation))), - () => !IsProducing || !buildComplete); + () => !IsProducing || IsTraitDisabled); rs.Add(anim, info.Palette, info.IsPlayerPalette); } @@ -77,7 +73,7 @@ namespace OpenRA.Mods.Common.Traits.Render // Per-actor production queues = self.TraitsImplementing() .Where(q => production.Produces.Contains(q.Info.Type)) - .Where(q => !info.Queues.Any() || info.Queues.Contains(q.Info.Type)) + .Where(q => !Info.Queues.Any() || Info.Queues.Contains(q.Info.Type)) .ToArray(); if (!queues.Any()) @@ -85,20 +81,13 @@ namespace OpenRA.Mods.Common.Traits.Render // Player-wide production queues = self.Owner.PlayerActor.TraitsImplementing() .Where(q => production.Produces.Contains(q.Info.Type)) - .Where(q => !info.Queues.Any() || info.Queues.Contains(q.Info.Type)) + .Where(q => !Info.Queues.Any() || Info.Queues.Contains(q.Info.Type)) .ToArray(); } } - void INotifyCreated.Created(Actor self) + protected override void TraitEnabled(Actor self) { - if (buildComplete) - CacheQueues(self); - } - - void INotifyBuildComplete.BuildingComplete(Actor self) - { - buildComplete = true; CacheQueues(self); } @@ -107,12 +96,6 @@ namespace OpenRA.Mods.Common.Traits.Render self.World.AddFrameEndTask(w => CacheQueues(self)); } - void INotifySold.Sold(Actor self) { } - void INotifySold.Selling(Actor self) - { - buildComplete = false; - } - void INotifyDamageStateChanged.DamageStateChanged(Actor self, AttackInfo e) { overlay.ReplaceAnim(RenderSprites.NormalizeSequence(overlay, e.DamageState, overlay.CurrentSequence.Name)); diff --git a/OpenRA.Mods.Common/Traits/Render/WithRepairOverlay.cs b/OpenRA.Mods.Common/Traits/Render/WithRepairOverlay.cs index 0305b88aea..f773b2e48f 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithRepairOverlay.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithRepairOverlay.cs @@ -39,10 +39,9 @@ namespace OpenRA.Mods.Common.Traits.Render public override object Create(ActorInitializer init) { return new WithRepairOverlay(init.Self, this); } } - public class WithRepairOverlay : PausableConditionalTrait, INotifyDamageStateChanged, INotifyBuildComplete, INotifySold, INotifyRepair + public class WithRepairOverlay : PausableConditionalTrait, INotifyDamageStateChanged, INotifyRepair { readonly Animation overlay; - bool buildComplete; bool visible; public WithRepairOverlay(Actor self, WithRepairOverlayInfo info) @@ -51,29 +50,17 @@ namespace OpenRA.Mods.Common.Traits.Render var rs = self.Trait(); var body = self.Trait(); - buildComplete = !self.Info.HasTraitInfo(); // always render instantly for units overlay = new Animation(self.World, rs.GetImage(self), () => IsTraitPaused); overlay.PlayThen(info.Sequence, () => visible = false); var anim = new AnimationWithOffset(overlay, () => body.LocalToWorld(info.Offset.Rotate(body.QuantizeOrientation(self, self.Orientation))), - () => IsTraitDisabled || !visible || !buildComplete, + () => IsTraitDisabled || !visible, p => RenderUtils.ZOffsetFromCenter(self, p, 1)); rs.Add(anim, info.Palette, info.IsPlayerPalette); } - void INotifyBuildComplete.BuildingComplete(Actor self) - { - buildComplete = true; - } - - void INotifySold.Sold(Actor self) { } - void INotifySold.Selling(Actor self) - { - buildComplete = false; - } - void INotifyDamageStateChanged.DamageStateChanged(Actor self, AttackInfo e) { overlay.ReplaceAnim(RenderSprites.NormalizeSequence(overlay, e.DamageState, overlay.CurrentSequence.Name)); diff --git a/OpenRA.Mods.Common/Traits/Render/WithResources.cs b/OpenRA.Mods.Common/Traits/Render/WithResources.cs index 9760699b8c..f52d24ed20 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithResources.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithResources.cs @@ -15,27 +15,26 @@ 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 : ITraitInfo, Requires, Requires + class WithResourcesInfo : ConditionalTraitInfo, Requires, Requires { [Desc("Sequence name to use")] [SequenceReference] public readonly string Sequence = "resources"; - public object Create(ActorInitializer init) { return new WithResources(init.Self, this); } + public override object Create(ActorInitializer init) { return new WithResources(init.Self, this); } } - class WithResources : INotifyBuildComplete, INotifySold, INotifyOwnerChanged, INotifyDamageStateChanged + // TODO: Rename to WithResourcesOverlay to conform with our naming conventions + class WithResources : ConditionalTrait, INotifyOwnerChanged, INotifyDamageStateChanged { - readonly WithResourcesInfo info; readonly AnimationWithOffset anim; readonly RenderSprites rs; readonly WithSpriteBody wsb; PlayerResources playerResources; - bool buildComplete; public WithResources(Actor self, WithResourcesInfo info) + : base(info) { - this.info = info; rs = self.Trait(); wsb = self.Trait(); playerResources = self.Owner.PlayerActor.Trait(); @@ -46,27 +45,19 @@ namespace OpenRA.Mods.Common.Traits.Render ((10 * a.CurrentSequence.Length - 1) * playerResources.Resources) / (10 * playerResources.ResourceCapacity) : 0); - anim = new AnimationWithOffset(a, null, () => !buildComplete, 1024); + anim = new AnimationWithOffset(a, null, () => IsTraitDisabled, 1024); rs.Add(anim); } - void INotifyBuildComplete.BuildingComplete(Actor self) - { - buildComplete = true; - } - void INotifyDamageStateChanged.DamageStateChanged(Actor self, AttackInfo e) { if (anim.Animation.CurrentSequence != null) - anim.Animation.ReplaceAnim(wsb.NormalizeSequence(self, info.Sequence)); + anim.Animation.ReplaceAnim(wsb.NormalizeSequence(self, Info.Sequence)); } void INotifyOwnerChanged.OnOwnerChanged(Actor self, Player oldOwner, Player newOwner) { playerResources = newOwner.PlayerActor.Trait(); } - - void INotifySold.Selling(Actor self) { rs.Remove(anim); } - void INotifySold.Sold(Actor self) { } } } diff --git a/OpenRA.Mods.Common/Traits/Render/WithResupplyAnimation.cs b/OpenRA.Mods.Common/Traits/Render/WithResupplyAnimation.cs index b23e369d5c..e7c4a8b36c 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithResupplyAnimation.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithResupplyAnimation.cs @@ -37,10 +37,9 @@ namespace OpenRA.Mods.Common.Traits.Render public override object Create(ActorInitializer init) { return new WithResupplyAnimation(init.Self, this); } } - public class WithResupplyAnimation : ConditionalTrait, INotifyRepair, INotifyRearm, INotifyBuildComplete, INotifySold, ITick + public class WithResupplyAnimation : ConditionalTrait, INotifyRepair, INotifyRearm, ITick { - readonly WithSpriteBody spriteBody; - bool buildComplete; + readonly WithSpriteBody wsb; bool animPlaying; bool repairing; bool rearming; @@ -48,26 +47,26 @@ namespace OpenRA.Mods.Common.Traits.Render public WithResupplyAnimation(Actor self, WithResupplyAnimationInfo info) : base(info) { - spriteBody = self.TraitsImplementing().Single(w => w.Info.Name == Info.Body); + wsb = self.TraitsImplementing().Single(w => w.Info.Name == Info.Body); } void ITick.Tick(Actor self) { - if (!buildComplete || IsTraitDisabled) + if (IsTraitDisabled) return; if (!animPlaying && ((repairing && Info.PlayAnimationOn.HasFlag(ResupplyType.Repair)) || (rearming && Info.PlayAnimationOn.HasFlag(ResupplyType.Rearm)))) { - spriteBody.PlayCustomAnimationRepeating(self, Info.Sequence); + wsb.PlayCustomAnimationRepeating(self, Info.Sequence); animPlaying = true; } else if (animPlaying && (!repairing || !Info.PlayAnimationOn.HasFlag(ResupplyType.Repair)) && (!rearming || !Info.PlayAnimationOn.HasFlag(ResupplyType.Rearm))) { - spriteBody.CancelCustomAnimation(self); + wsb.CancelCustomAnimation(self); animPlaying = false; } } @@ -96,16 +95,11 @@ namespace OpenRA.Mods.Common.Traits.Render rearming = false; } - void INotifyBuildComplete.BuildingComplete(Actor self) + protected override void TraitDisabled(Actor self) { - buildComplete = true; + // Cancel immediately instead of waiting for the next tick + repairing = rearming = animPlaying = false; + wsb.CancelCustomAnimation(self); } - - void INotifySold.Selling(Actor self) - { - buildComplete = false; - } - - void INotifySold.Sold(Actor self) { } } } \ No newline at end of file diff --git a/OpenRA.Mods.Common/Traits/Render/WithSiloAnimation.cs b/OpenRA.Mods.Common/Traits/Render/WithSiloAnimation.cs index 5a3999cfc8..9eb2524a71 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithSiloAnimation.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithSiloAnimation.cs @@ -15,7 +15,7 @@ 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 : ITraitInfo, Requires, Requires + class WithSiloAnimationInfo : ConditionalTraitInfo, Requires, Requires { [Desc("Sequence to use for resources-dependent 'stages'."), SequenceReference] public readonly string Sequence = "stages"; @@ -26,38 +26,35 @@ namespace OpenRA.Mods.Common.Traits.Render [Desc("Which sprite body to play the animation on.")] public readonly string Body = "body"; - public object Create(ActorInitializer init) { return new WithSiloAnimation(init, this); } + public override object Create(ActorInitializer init) { return new WithSiloAnimation(init, this); } } - class WithSiloAnimation : INotifyBuildComplete, INotifyOwnerChanged + class WithSiloAnimation : ConditionalTrait, INotifyOwnerChanged { - readonly WithSiloAnimationInfo info; readonly WithSpriteBody wsb; PlayerResources playerResources; public WithSiloAnimation(ActorInitializer init, WithSiloAnimationInfo info) + : base(info) { - this.info = info; wsb = init.Self.TraitsImplementing().Single(w => w.Info.Name == info.Body); playerResources = init.Self.Owner.PlayerActor.Trait(); } - void INotifyBuildComplete.BuildingComplete(Actor self) + void PlayAnimation(Actor self) { - wsb.DefaultAnimation.PlayFetchIndex(wsb.NormalizeSequence(self, info.Sequence), + wsb.DefaultAnimation.PlayFetchIndex(wsb.NormalizeSequence(self, Info.Sequence), () => playerResources.ResourceCapacity != 0 - ? ((info.Stages * wsb.DefaultAnimation.CurrentSequence.Length - 1) * playerResources.Resources) / (info.Stages * playerResources.ResourceCapacity) + ? ((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(); - - 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); + PlayAnimation(self); } + + protected override void TraitEnabled(Actor self) { PlayAnimation(self); } } } diff --git a/OpenRA.Mods.Common/Traits/Render/WithSpriteBody.cs b/OpenRA.Mods.Common/Traits/Render/WithSpriteBody.cs index c5a1608cc6..5ab8d107d3 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithSpriteBody.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithSpriteBody.cs @@ -44,7 +44,7 @@ namespace OpenRA.Mods.Common.Traits.Render } } - public class WithSpriteBody : PausableConditionalTrait, INotifyDamageStateChanged, INotifyBuildComplete, IAutoMouseBounds + public class WithSpriteBody : PausableConditionalTrait, INotifyDamageStateChanged, IAutoMouseBounds { public readonly Animation DefaultAnimation; readonly RenderSprites rs; @@ -80,17 +80,11 @@ namespace OpenRA.Mods.Common.Traits.Render return RenderSprites.NormalizeSequence(DefaultAnimation, self.GetDamageState(), sequence); } - protected virtual void OnBuildComplete(Actor self) + protected override void TraitEnabled(Actor self) { DefaultAnimation.PlayRepeating(NormalizeSequence(self, Info.Sequence)); } - // TODO: Get rid of INotifyBuildComplete in favor of using the condition system - void INotifyBuildComplete.BuildingComplete(Actor self) - { - OnBuildComplete(self); - } - public void PlayCustomAnimation(Actor self, string name, Action after = null) { DefaultAnimation.PlayThen(NormalizeSequence(self, name), () => diff --git a/OpenRA.Mods.Common/Traits/Render/WithSpriteTurret.cs b/OpenRA.Mods.Common/Traits/Render/WithSpriteTurret.cs index 45030d6f79..52214b8e4e 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithSpriteTurret.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithSpriteTurret.cs @@ -70,7 +70,7 @@ namespace OpenRA.Mods.Common.Traits.Render } } - public class WithSpriteTurret : ConditionalTrait, INotifyBuildComplete, INotifySold, INotifyTransform, INotifyDamageStateChanged + public class WithSpriteTurret : ConditionalTrait, INotifyDamageStateChanged { public readonly Animation DefaultAnimation; readonly RenderSprites rs; @@ -78,9 +78,6 @@ namespace OpenRA.Mods.Common.Traits.Render readonly Turreted t; readonly Armament[] arms; - // TODO: This should go away once https://github.com/OpenRA/OpenRA/issues/7035 is implemented - bool buildComplete; - public WithSpriteTurret(Actor self, WithSpriteTurretInfo info) : base(info) { @@ -90,13 +87,12 @@ namespace OpenRA.Mods.Common.Traits.Render .First(tt => tt.Name == info.Turret); arms = self.TraitsImplementing() .Where(w => w.Info.Turret == info.Turret).ToArray(); - buildComplete = !self.Info.HasTraitInfo(); // always render instantly for units DefaultAnimation = new Animation(self.World, rs.GetImage(self), () => t.TurretFacing); DefaultAnimation.PlayRepeating(NormalizeSequence(self, info.Sequence)); rs.Add(new AnimationWithOffset(DefaultAnimation, () => TurretOffset(self), - () => IsTraitDisabled || !buildComplete, + () => IsTraitDisabled, p => RenderUtils.ZOffsetFromCenter(self, p, 1)), info.Palette, info.IsPlayerPalette); // Restrict turret facings to match the sprite @@ -144,12 +140,5 @@ namespace OpenRA.Mods.Common.Traits.Render { DefaultAnimation.PlayRepeating(NormalizeSequence(self, Info.Sequence)); } - - void INotifyBuildComplete.BuildingComplete(Actor self) { buildComplete = true; } - void INotifySold.Selling(Actor self) { buildComplete = false; } - void INotifySold.Sold(Actor self) { } - void INotifyTransform.BeforeTransform(Actor self) { buildComplete = false; } - void INotifyTransform.OnTransform(Actor self) { } - void INotifyTransform.AfterTransform(Actor toActor) { } } } diff --git a/OpenRA.Mods.Common/Traits/Render/WithVoxelBarrel.cs b/OpenRA.Mods.Common/Traits/Render/WithVoxelBarrel.cs index b4b2ead812..c40294e395 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithVoxelBarrel.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithVoxelBarrel.cs @@ -63,16 +63,13 @@ namespace OpenRA.Mods.Common.Traits.Render } } - public class WithVoxelBarrel : ConditionalTrait, INotifyBuildComplete, INotifySold, INotifyTransform + public class WithVoxelBarrel : ConditionalTrait { readonly Actor self; readonly Armament armament; readonly Turreted turreted; readonly BodyOrientation body; - // TODO: This should go away once https://github.com/OpenRA/OpenRA/issues/7035 is implemented - bool buildComplete; - public WithVoxelBarrel(Actor self, WithVoxelBarrelInfo info) : base(info) { @@ -83,12 +80,10 @@ namespace OpenRA.Mods.Common.Traits.Render turreted = self.TraitsImplementing() .First(tt => tt.Name == armament.Info.Turret); - buildComplete = !self.Info.HasTraitInfo(); // always render instantly for units - var rv = self.Trait(); rv.Add(new ModelAnimation(self.World.ModelCache.GetModelSequence(rv.Image, Info.Sequence), BarrelOffset, BarrelRotation, - () => IsTraitDisabled || !buildComplete, () => 0, info.ShowShadow)); + () => IsTraitDisabled, () => 0, info.ShowShadow)); } WVec BarrelOffset() @@ -110,12 +105,5 @@ namespace OpenRA.Mods.Common.Traits.Render yield return turreted.WorldOrientation(self) - b + WRot.FromYaw(b.Yaw - qb.Yaw); yield return qb; } - - void INotifyBuildComplete.BuildingComplete(Actor self) { buildComplete = true; } - void INotifySold.Selling(Actor self) { buildComplete = false; } - void INotifySold.Sold(Actor self) { } - void INotifyTransform.BeforeTransform(Actor self) { buildComplete = false; } - void INotifyTransform.OnTransform(Actor self) { } - void INotifyTransform.AfterTransform(Actor toActor) { } } } diff --git a/OpenRA.Mods.Common/Traits/Render/WithVoxelTurret.cs b/OpenRA.Mods.Common/Traits/Render/WithVoxelTurret.cs index adbee366e3..d1b95fd751 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithVoxelTurret.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithVoxelTurret.cs @@ -51,15 +51,12 @@ namespace OpenRA.Mods.Common.Traits.Render } } - public class WithVoxelTurret : ConditionalTrait, INotifyBuildComplete, INotifySold, INotifyTransform + public class WithVoxelTurret : ConditionalTrait { readonly Actor self; readonly Turreted turreted; readonly BodyOrientation body; - // TODO: This should go away once https://github.com/OpenRA/OpenRA/issues/7035 is implemented - bool buildComplete; - public WithVoxelTurret(Actor self, WithVoxelTurretInfo info) : base(info) { @@ -67,12 +64,11 @@ namespace OpenRA.Mods.Common.Traits.Render body = self.Trait(); turreted = self.TraitsImplementing() .First(tt => tt.Name == Info.Turret); - buildComplete = !self.Info.HasTraitInfo(); // always render instantly for units var rv = self.Trait(); rv.Add(new ModelAnimation(self.World.ModelCache.GetModelSequence(rv.Image, Info.Sequence), () => turreted.Position(self), TurretRotation, - () => IsTraitDisabled || !buildComplete, () => 0, info.ShowShadow)); + () => IsTraitDisabled, () => 0, info.ShowShadow)); } IEnumerable TurretRotation() @@ -82,12 +78,5 @@ namespace OpenRA.Mods.Common.Traits.Render yield return turreted.WorldOrientation(self) - b + WRot.FromYaw(b.Yaw - qb.Yaw); yield return qb; } - - void INotifyBuildComplete.BuildingComplete(Actor self) { buildComplete = true; } - void INotifySold.Selling(Actor self) { buildComplete = false; } - void INotifySold.Sold(Actor self) { } - void INotifyTransform.BeforeTransform(Actor self) { buildComplete = false; } - void INotifyTransform.OnTransform(Actor self) { } - void INotifyTransform.AfterTransform(Actor toActor) { } } } diff --git a/OpenRA.Mods.Common/Traits/Render/WithWallSpriteBody.cs b/OpenRA.Mods.Common/Traits/Render/WithWallSpriteBody.cs index 84f2a4de75..ae1e2a9305 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithWallSpriteBody.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithWallSpriteBody.cs @@ -139,8 +139,11 @@ namespace OpenRA.Mods.Common.Traits.Render dirty = false; } - protected override void OnBuildComplete(Actor self) + protected override void TraitEnabled(Actor self) { + base.TraitEnabled(self); + dirty = true; + DefaultAnimation.PlayFetchIndex(NormalizeSequence(self, Info.Sequence), () => adjacent); UpdateNeighbours(self); @@ -162,8 +165,6 @@ namespace OpenRA.Mods.Common.Traits.Render { UpdateNeighbours(self); } - - protected override void TraitEnabled(Actor self) { dirty = true; } } public class RuntimeNeighbourInit : IActorInit>, ISuppressInitExport diff --git a/OpenRA.Mods.D2k/Traits/Render/WithCrumbleOverlay.cs b/OpenRA.Mods.D2k/Traits/Render/WithCrumbleOverlay.cs index ee496606e7..f9b60ed2e4 100644 --- a/OpenRA.Mods.D2k/Traits/Render/WithCrumbleOverlay.cs +++ b/OpenRA.Mods.D2k/Traits/Render/WithCrumbleOverlay.cs @@ -17,7 +17,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.D2k.Traits.Render { [Desc("Rendered together with the \"make\" animation.")] - public class WithCrumbleOverlayInfo : ITraitInfo, Requires + public class WithCrumbleOverlayInfo : ConditionalTraitInfo, Requires { [Desc("Sequence name to use")] [SequenceReference] public readonly string Sequence = "crumble-overlay"; @@ -28,14 +28,13 @@ namespace OpenRA.Mods.D2k.Traits.Render [Desc("Custom palette is a player palette BaseName")] public readonly bool IsPlayerPalette = false; - public object Create(ActorInitializer init) { return new WithCrumbleOverlay(init, this); } + public override object Create(ActorInitializer init) { return new WithCrumbleOverlay(init, this); } } - public class WithCrumbleOverlay : INotifyBuildComplete + public class WithCrumbleOverlay : ConditionalTrait { - bool buildComplete = false; - public WithCrumbleOverlay(ActorInitializer init, WithCrumbleOverlayInfo info) + : base(info) { if (init.Contains()) return; @@ -43,17 +42,12 @@ namespace OpenRA.Mods.D2k.Traits.Render var rs = init.Self.Trait(); var overlay = new Animation(init.World, rs.GetImage(init.Self)); - var anim = new AnimationWithOffset(overlay, null, () => !buildComplete); + var anim = new AnimationWithOffset(overlay, null, () => IsTraitDisabled); // Remove the animation once it is complete overlay.PlayThen(info.Sequence, () => init.World.AddFrameEndTask(w => rs.Remove(anim))); rs.Add(anim, info.Palette, info.IsPlayerPalette); } - - void INotifyBuildComplete.BuildingComplete(Actor self) - { - buildComplete = true; - } } } \ No newline at end of file diff --git a/OpenRA.Mods.D2k/Traits/Render/WithDeliveryOverlay.cs b/OpenRA.Mods.D2k/Traits/Render/WithDeliveryOverlay.cs index 0ec0eb3eaf..5eae3ecf90 100644 --- a/OpenRA.Mods.D2k/Traits/Render/WithDeliveryOverlay.cs +++ b/OpenRA.Mods.D2k/Traits/Render/WithDeliveryOverlay.cs @@ -18,7 +18,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.D2k.Traits.Render { [Desc("Rendered when ProductionAirdrop is in progress.")] - public class WithDeliveryOverlayInfo : ITraitInfo, Requires, Requires + public class WithDeliveryOverlayInfo : PausableConditionalTraitInfo, Requires, Requires { [Desc("Sequence name to use")] [SequenceReference] public readonly string Sequence = "active"; @@ -32,28 +32,21 @@ namespace OpenRA.Mods.D2k.Traits.Render [Desc("Custom palette is a player palette BaseName")] public readonly bool IsPlayerPalette = false; - public object Create(ActorInitializer init) { return new WithDeliveryOverlay(init.Self, this); } + public override object Create(ActorInitializer init) { return new WithDeliveryOverlay(init.Self, this); } } - public class WithDeliveryOverlay : INotifyBuildComplete, INotifySold, INotifyDelivery + public class WithDeliveryOverlay : PausableConditionalTrait, INotifyDelivery { - readonly WithDeliveryOverlayInfo info; readonly AnimationWithOffset anim; - - bool buildComplete; bool delivering; public WithDeliveryOverlay(Actor self, WithDeliveryOverlayInfo info) + : base(info) { - this.info = info; - var rs = self.Trait(); var body = self.Trait(); - // always render instantly for units - buildComplete = !self.Info.HasTraitInfo(); - - var overlay = new Animation(self.World, rs.GetImage(self)); + var overlay = new Animation(self.World, rs.GetImage(self), () => IsTraitPaused); overlay.Play(info.Sequence); // These translucent overlays should not be included in highlight flashes @@ -61,7 +54,7 @@ namespace OpenRA.Mods.D2k.Traits.Render anim = new AnimationWithOffset(overlay, () => body.LocalToWorld(info.Offset.Rotate(body.QuantizeOrientation(self, self.Orientation))), - () => !buildComplete || !delivering); + () => IsTraitDisabled || !delivering); rs.Add(anim, info.Palette, info.IsPlayerPalette); } @@ -69,18 +62,7 @@ namespace OpenRA.Mods.D2k.Traits.Render void PlayDeliveryOverlay() { if (delivering) - anim.Animation.PlayThen(info.Sequence, PlayDeliveryOverlay); - } - - void INotifyBuildComplete.BuildingComplete(Actor self) - { - buildComplete = true; - } - - void INotifySold.Sold(Actor self) { } - void INotifySold.Selling(Actor self) - { - buildComplete = false; + anim.Animation.PlayThen(Info.Sequence, PlayDeliveryOverlay); } void INotifyDelivery.IncomingDelivery(Actor self) { delivering = true; PlayDeliveryOverlay(); }