diff --git a/OpenRA.Mods.Cnc/Activities/VoxelHarvesterDockSequence.cs b/OpenRA.Mods.Cnc/Activities/VoxelHarvesterDockSequence.cs deleted file mode 100644 index e94ab5d013..0000000000 --- a/OpenRA.Mods.Cnc/Activities/VoxelHarvesterDockSequence.cs +++ /dev/null @@ -1,70 +0,0 @@ -#region Copyright & License Information -/* - * Copyright (c) The OpenRA Developers and Contributors - * 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 OpenRA.Mods.Cnc.Traits.Render; -using OpenRA.Mods.Common.Activities; -using OpenRA.Mods.Common.Traits; - -namespace OpenRA.Mods.Cnc.Activities -{ - public class VoxelHarvesterDockSequence : HarvesterDockSequence - { - readonly WithVoxelUnloadBody body; - readonly WithDockingOverlay spriteOverlay; - - public VoxelHarvesterDockSequence(Actor self, Actor refineryActor, Refinery refinery) - : base(self, refineryActor, refinery) - { - body = self.Trait(); - spriteOverlay = RefineryActor.TraitOrDefault(); - } - - public override void OnStateDock(Actor self) - { - body.Docked = true; - - if (spriteOverlay != null && !spriteOverlay.Visible) - { - spriteOverlay.Visible = true; - spriteOverlay.WithOffset.Animation.PlayThen(spriteOverlay.Info.Sequence, () => - { - dockingState = DockingState.Loop; - spriteOverlay.Visible = false; - }); - } - else - dockingState = DockingState.Loop; - } - - public override void OnStateUndock(Actor self) - { - // If body.Docked wasn't set, we didn't actually dock and have to skip the undock overlay - if (!body.Docked) - dockingState = DockingState.Complete; - else if (RefineryActor.IsInWorld && !RefineryActor.IsDead && spriteOverlay != null && !spriteOverlay.Visible) - { - dockingState = DockingState.Wait; - spriteOverlay.Visible = true; - spriteOverlay.WithOffset.Animation.PlayBackwardsThen(spriteOverlay.Info.Sequence, () => - { - dockingState = DockingState.Complete; - body.Docked = false; - spriteOverlay.Visible = false; - }); - } - else - { - dockingState = DockingState.Complete; - body.Docked = false; - } - } - } -} diff --git a/OpenRA.Mods.Cnc/Traits/Buildings/TiberianSunRefinery.cs b/OpenRA.Mods.Cnc/Traits/Buildings/TiberianSunRefinery.cs deleted file mode 100644 index 616ac92c9b..0000000000 --- a/OpenRA.Mods.Cnc/Traits/Buildings/TiberianSunRefinery.cs +++ /dev/null @@ -1,33 +0,0 @@ -#region Copyright & License Information -/* - * Copyright (c) The OpenRA Developers and Contributors - * 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 OpenRA.Activities; -using OpenRA.Mods.Cnc.Activities; -using OpenRA.Mods.Common.Traits; - -namespace OpenRA.Mods.Cnc.Traits -{ - public class TiberianSunRefineryInfo : RefineryInfo - { - public override object Create(ActorInitializer init) { return new TiberianSunRefinery(init.Self, this); } - } - - public class TiberianSunRefinery : Refinery - { - public TiberianSunRefinery(Actor self, RefineryInfo info) - : base(self, info) { } - - public override Activity DockSequence(Actor harv, Actor self) - { - return new VoxelHarvesterDockSequence(harv, self, this); - } - } -} diff --git a/OpenRA.Mods.Cnc/Traits/Render/WithVoxelUnloadBody.cs b/OpenRA.Mods.Cnc/Traits/Render/WithVoxelUnloadBody.cs index f210fa1acc..a00adc70e7 100644 --- a/OpenRA.Mods.Cnc/Traits/Render/WithVoxelUnloadBody.cs +++ b/OpenRA.Mods.Cnc/Traits/Render/WithVoxelUnloadBody.cs @@ -45,9 +45,9 @@ namespace OpenRA.Mods.Cnc.Traits.Render } } - public class WithVoxelUnloadBody : IAutoMouseBounds + public class WithVoxelUnloadBody : IAutoMouseBounds, IDockClientBody { - public bool Docked; + bool docked; readonly ModelAnimation modelAnimation; readonly RenderVoxels rv; @@ -60,7 +60,7 @@ namespace OpenRA.Mods.Cnc.Traits.Render var idleModel = self.World.ModelCache.GetModelSequence(rv.Image, info.IdleSequence); modelAnimation = new ModelAnimation(idleModel, () => WVec.Zero, () => body.QuantizeOrientation(self.Orientation), - () => Docked, + () => docked, () => 0, info.ShowShadow); rv.Add(modelAnimation); @@ -68,10 +68,22 @@ namespace OpenRA.Mods.Cnc.Traits.Render var unloadModel = self.World.ModelCache.GetModelSequence(rv.Image, info.UnloadSequence); rv.Add(new ModelAnimation(unloadModel, () => WVec.Zero, () => body.QuantizeOrientation(self.Orientation), - () => !Docked, + () => !docked, () => 0, info.ShowShadow)); } + void IDockClientBody.PlayDockAnimation(Actor self, Action after) + { + docked = true; + after(); + } + + void IDockClientBody.PlayReverseDockAnimation(Actor self, Action after) + { + docked = false; + after(); + } + Rectangle IAutoMouseBounds.AutoMouseoverBounds(Actor self, WorldRenderer wr) { return modelAnimation.ScreenBounds(self.CenterPosition, wr, rv.Info.Scale); diff --git a/OpenRA.Mods.Common/Activities/HarvesterDockSequence.cs b/OpenRA.Mods.Common/Activities/HarvesterDockSequence.cs index a6cb230f14..0d585951a2 100644 --- a/OpenRA.Mods.Common/Activities/HarvesterDockSequence.cs +++ b/OpenRA.Mods.Common/Activities/HarvesterDockSequence.cs @@ -14,18 +14,21 @@ using System.Collections.Generic; using System.Linq; using OpenRA.Activities; using OpenRA.Mods.Common.Traits; +using OpenRA.Mods.Common.Traits.Render; using OpenRA.Primitives; using OpenRA.Traits; namespace OpenRA.Mods.Common.Activities { - public abstract class HarvesterDockSequence : Activity + public class HarvesterDockSequence : Activity { protected enum DockingState { Wait, Turn, Drag, Dock, Loop, Undock, Complete } protected readonly Actor RefineryActor; protected readonly Refinery Refinery; + protected readonly WithDockingOverlay DockHostSpriteOverlay; protected readonly Harvester Harv; + protected readonly IDockClientBody DockClientBody; protected readonly WAngle DockAngle; protected readonly bool IsDragRequired; protected readonly WVec DragOffset; @@ -38,16 +41,20 @@ namespace OpenRA.Mods.Common.Activities readonly INotifyDockClient[] notifyDockClients; readonly INotifyDockHost[] notifyDockHosts; + bool dockInitiated = false; + public HarvesterDockSequence(Actor self, Actor refineryActor, Refinery refinery) { dockingState = DockingState.Turn; Refinery = refinery; RefineryActor = refineryActor; + DockHostSpriteOverlay = refineryActor.TraitOrDefault(); DockAngle = refinery.DeliveryAngle; IsDragRequired = refinery.IsDragRequired; DragOffset = refinery.DragOffset; DragLength = refinery.DragLength; Harv = self.Trait(); + DockClientBody = self.TraitOrDefault(); StartDrag = self.CenterPosition; EndDrag = refineryActor.CenterPosition + DragOffset; notifyDockClients = self.TraitsImplementing().ToArray(); @@ -79,7 +86,8 @@ namespace OpenRA.Mods.Common.Activities case DockingState.Dock: if (!IsCanceling && RefineryActor.IsInWorld && !RefineryActor.IsDead && !Harv.IsTraitDisabled) { - OnStateDock(self); + dockInitiated = true; + PlayDockAnimations(self); NotifyDocked(self); } else @@ -94,7 +102,11 @@ namespace OpenRA.Mods.Common.Activities return false; case DockingState.Undock: - OnStateUndock(self); + if (dockInitiated) + PlayUndockAnimations(self); + else + dockingState = DockingState.Complete; + return false; case DockingState.Complete: @@ -110,19 +122,65 @@ namespace OpenRA.Mods.Common.Activities throw new InvalidOperationException("Invalid harvester dock state"); } - public override IEnumerable GetTargets(Actor self) + public virtual void PlayDockAnimations(Actor self) { - yield return Target.FromActor(RefineryActor); + PlayDockCientAnimation(self, () => + { + if (DockHostSpriteOverlay != null && !DockHostSpriteOverlay.Visible) + { + dockingState = DockingState.Wait; + DockHostSpriteOverlay.Visible = true; + DockHostSpriteOverlay.WithOffset.Animation.PlayThen(DockHostSpriteOverlay.Info.Sequence, () => + { + dockingState = DockingState.Loop; + DockHostSpriteOverlay.Visible = false; + }); + } + else + dockingState = DockingState.Loop; + }); } - public override IEnumerable TargetLineNodes(Actor self) + public virtual void PlayDockCientAnimation(Actor self, Action after) { - yield return new TargetLineNode(Target.FromActor(RefineryActor), Color.Green); + if (DockClientBody != null) + { + dockingState = DockingState.Wait; + DockClientBody.PlayDockAnimation(self, () => after()); + } + else + after(); } - public abstract void OnStateDock(Actor self); + public virtual void PlayUndockAnimations(Actor self) + { + if (RefineryActor.IsInWorld && !RefineryActor.IsDead && DockHostSpriteOverlay != null && !DockHostSpriteOverlay.Visible) + { + dockingState = DockingState.Wait; + DockHostSpriteOverlay.Visible = true; + DockHostSpriteOverlay.WithOffset.Animation.PlayBackwardsThen(DockHostSpriteOverlay.Info.Sequence, () => + { + PlayUndockClientAnimation(self, () => + { + dockingState = DockingState.Complete; + DockHostSpriteOverlay.Visible = false; + }); + }); + } + else + PlayUndockClientAnimation(self, () => dockingState = DockingState.Complete); + } - public abstract void OnStateUndock(Actor self); + public virtual void PlayUndockClientAnimation(Actor self, Action after) + { + if (DockClientBody != null) + { + dockingState = DockingState.Wait; + DockClientBody.PlayReverseDockAnimation(self, () => after()); + } + else + after(); + } void NotifyDocked(Actor self) { @@ -142,5 +200,15 @@ namespace OpenRA.Mods.Common.Activities foreach (var nd in notifyDockHosts) nd.Undocked(RefineryActor, self); } + + public override IEnumerable GetTargets(Actor self) + { + yield return Target.FromActor(RefineryActor); + } + + public override IEnumerable TargetLineNodes(Actor self) + { + yield return new TargetLineNode(Target.FromActor(RefineryActor), Color.Green); + } } } diff --git a/OpenRA.Mods.Common/Activities/SpriteHarvesterDockSequence.cs b/OpenRA.Mods.Common/Activities/SpriteHarvesterDockSequence.cs deleted file mode 100644 index e1ed2527b9..0000000000 --- a/OpenRA.Mods.Common/Activities/SpriteHarvesterDockSequence.cs +++ /dev/null @@ -1,56 +0,0 @@ -#region Copyright & License Information -/* - * Copyright (c) The OpenRA Developers and Contributors - * 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 OpenRA.Mods.Common.Traits; -using OpenRA.Mods.Common.Traits.Render; - -namespace OpenRA.Mods.Common.Activities -{ - public class SpriteHarvesterDockSequence : HarvesterDockSequence - { - readonly WithSpriteBody wsb; - readonly WithDockingAnimationInfo wda; - protected bool dockAnimPlayed; - - public SpriteHarvesterDockSequence(Actor self, Actor refineryActor, Refinery refinery) - : base(self, refineryActor, refinery) - { - wsb = self.Trait(); - wda = self.Info.TraitInfoOrDefault(); - } - - public override void OnStateDock(Actor self) - { - if (wda != null) - wsb.PlayCustomAnimation(self, wda.DockSequence, () => wsb.PlayCustomAnimationRepeating(self, wda.DockLoopSequence)); - - dockAnimPlayed = true; - dockingState = DockingState.Loop; - } - - public override void OnStateUndock(Actor self) - { - // If dock animation hasn't played, we didn't actually dock and have to skip the undock anim and notification - if (!dockAnimPlayed) - { - dockingState = DockingState.Complete; - return; - } - - dockingState = DockingState.Wait; - - if (wda == null) - dockingState = DockingState.Complete; - else - wsb.PlayCustomAnimationBackwards(self, wda.DockSequence, () => dockingState = DockingState.Complete); - } - } -} diff --git a/OpenRA.Mods.Common/Traits/Buildings/Refinery.cs b/OpenRA.Mods.Common/Traits/Buildings/Refinery.cs index d8cb5a3607..f886716196 100644 --- a/OpenRA.Mods.Common/Traits/Buildings/Refinery.cs +++ b/OpenRA.Mods.Common/Traits/Buildings/Refinery.cs @@ -89,11 +89,6 @@ namespace OpenRA.Mods.Common.Traits resourceValueModifiers = self.TraitsImplementing().ToArray().Select(m => m.GetResourceValueModifier()); } - public virtual Activity DockSequence(Actor harv, Actor self) - { - return new SpriteHarvesterDockSequence(harv, self, this); - } - public IEnumerable> GetLinkedHarvesters() { return self.World.ActorsWithTrait() @@ -171,7 +166,7 @@ namespace OpenRA.Mods.Common.Traits if (!preventDock) { dockOrder.QueueChild(new CallFunc(() => dockedHarv = harv, false)); - dockOrder.QueueChild(DockSequence(harv, self)); + dockOrder.QueueChild(new HarvesterDockSequence(harv, self, this)); dockOrder.QueueChild(new CallFunc(() => dockedHarv = null, false)); } } diff --git a/OpenRA.Mods.Common/Traits/Render/WithDockingAnimation.cs b/OpenRA.Mods.Common/Traits/Render/WithDockingAnimation.cs index db579d2ec1..dea4ccb68f 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithDockingAnimation.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithDockingAnimation.cs @@ -9,11 +9,12 @@ */ #endregion +using System; using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits.Render { - public class WithDockingAnimationInfo : TraitInfo, Requires, Requires + public class WithDockingAnimationInfo : TraitInfo, Requires, Requires { [SequenceReference] [Desc("Displayed when docking to refinery.")] @@ -22,7 +23,29 @@ namespace OpenRA.Mods.Common.Traits.Render [SequenceReference] [Desc("Looped while unloading at refinery.")] public readonly string DockLoopSequence = "dock-loop"; + + public override object Create(ActorInitializer init) { return new WithDockingAnimation(init.Self, this); } } - public class WithDockingAnimation { } + public class WithDockingAnimation : IDockClientBody + { + readonly WithDockingAnimationInfo info; + readonly WithSpriteBody wsb; + + public WithDockingAnimation(Actor self, WithDockingAnimationInfo info) + { + this.info = info; + wsb = self.Trait(); + } + + void IDockClientBody.PlayDockAnimation(Actor self, Action after) + { + wsb.PlayCustomAnimation(self, info.DockSequence, () => { wsb.PlayCustomAnimationRepeating(self, info.DockLoopSequence); after(); }); + } + + void IDockClientBody.PlayReverseDockAnimation(Actor self, Action after) + { + wsb.PlayCustomAnimationBackwards(self, info.DockSequence, () => after()); + } + } } diff --git a/OpenRA.Mods.Cnc/Traits/Render/WithDockingOverlay.cs b/OpenRA.Mods.Common/Traits/Render/WithDockingOverlay.cs similarity index 94% rename from OpenRA.Mods.Cnc/Traits/Render/WithDockingOverlay.cs rename to OpenRA.Mods.Common/Traits/Render/WithDockingOverlay.cs index 50ee7dd624..f4307da3fe 100644 --- a/OpenRA.Mods.Cnc/Traits/Render/WithDockingOverlay.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithDockingOverlay.cs @@ -10,11 +10,9 @@ #endregion using OpenRA.Graphics; -using OpenRA.Mods.Common.Traits; -using OpenRA.Mods.Common.Traits.Render; using OpenRA.Traits; -namespace OpenRA.Mods.Cnc.Traits.Render +namespace OpenRA.Mods.Common.Traits.Render { [Desc("Rendered on the refinery when a voxel harvester is docking and undocking.")] public class WithDockingOverlayInfo : PausableConditionalTraitInfo, Requires, Requires diff --git a/OpenRA.Mods.Common/TraitsInterfaces.cs b/OpenRA.Mods.Common/TraitsInterfaces.cs index 0d2f6a5f8b..bba83eff8b 100644 --- a/OpenRA.Mods.Common/TraitsInterfaces.cs +++ b/OpenRA.Mods.Common/TraitsInterfaces.cs @@ -273,6 +273,12 @@ namespace OpenRA.Mods.Common.Traits bool AllowDocking { get; } } + public interface IDockClientBody + { + void PlayDockAnimation(Actor self, Action after); + void PlayReverseDockAnimation(Actor self, Action after); + } + public interface IProvidesAssetBrowserPalettes { IEnumerable PaletteNames { get; } diff --git a/OpenRA.Mods.Common/UpdateRules/Rules/20221203/RemoveTSRefinery.cs b/OpenRA.Mods.Common/UpdateRules/Rules/20221203/RemoveTSRefinery.cs new file mode 100644 index 0000000000..eb6a48aff8 --- /dev/null +++ b/OpenRA.Mods.Common/UpdateRules/Rules/20221203/RemoveTSRefinery.cs @@ -0,0 +1,29 @@ +#region Copyright & License Information +/* + * Copyright (c) The OpenRA Developers and Contributors + * 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; + +namespace OpenRA.Mods.Common.UpdateRules.Rules +{ + public class RemoveTSRefinery : UpdateRule + { + public override string Name => "TiberianSunRefinery removed."; + + public override string Description => "TiberianSunRefinery was removed, use Refinery instead."; + + public override IEnumerable UpdateActorNode(ModData modData, MiniYamlNode actorNode) + { + actorNode.RenameChildrenMatching("TiberianSunRefinery", "Refinery"); + + yield break; + } + } +} diff --git a/OpenRA.Mods.Common/UpdateRules/UpdatePath.cs b/OpenRA.Mods.Common/UpdateRules/UpdatePath.cs index f7569a7eca..e6115e4032 100644 --- a/OpenRA.Mods.Common/UpdateRules/UpdatePath.cs +++ b/OpenRA.Mods.Common/UpdateRules/UpdatePath.cs @@ -105,7 +105,8 @@ namespace OpenRA.Mods.Common.UpdateRules new TextNotificationsDisplayWidgetRemoveTime(), new ExplicitSequenceFilenames(), new RenameEngineerRepair(), - new ProductionTabsWidgetAddTabButtonCollection() + new ProductionTabsWidgetAddTabButtonCollection(), + new RemoveTSRefinery(), }) }; diff --git a/mods/ts/rules/nod-structures.yaml b/mods/ts/rules/nod-structures.yaml index d49d800212..f9ba52f131 100644 --- a/mods/ts/rules/nod-structures.yaml +++ b/mods/ts/rules/nod-structures.yaml @@ -584,7 +584,7 @@ NAWAST: RevealsShroud: Range: 6c0 MaxHeightDelta: 3 - TiberianSunRefinery: + Refinery: DockAngle: 640 DockOffset: 2,1 StoresResources: diff --git a/mods/ts/rules/shared-structures.yaml b/mods/ts/rules/shared-structures.yaml index f2c721a302..466d4f6b35 100644 --- a/mods/ts/rules/shared-structures.yaml +++ b/mods/ts/rules/shared-structures.yaml @@ -119,7 +119,7 @@ PROC: RevealsShroud: Range: 6c0 MaxHeightDelta: 3 - TiberianSunRefinery: + Refinery: DockAngle: 640 DockOffset: 2,1 DiscardExcessResources: true