diff --git a/OpenRA.Game/Traits/TraitsInterfaces.cs b/OpenRA.Game/Traits/TraitsInterfaces.cs index df81e3eb88..93f785f8fd 100755 --- a/OpenRA.Game/Traits/TraitsInterfaces.cs +++ b/OpenRA.Game/Traits/TraitsInterfaces.cs @@ -74,6 +74,7 @@ namespace OpenRA.Traits public interface INotifyBuildComplete { void BuildingComplete(Actor self); } public interface INotifyBuildingPlaced { void BuildingPlaced(Actor self); } public interface INotifyProduction { void UnitProduced(Actor self, Actor other, CPos exit); } + public interface INotifyDelivery { void IncomingDelivery(Actor self); void Delivered(Actor self); } public interface INotifyOwnerChanged { void OnOwnerChanged(Actor self, Player oldOwner, Player newOwner); } public interface INotifyCapture { void OnCapture(Actor self, Actor captor, Player oldOwner, Player newOwner); } public interface INotifyHarvest { void Harvested(Actor self, ResourceType resource); } diff --git a/OpenRA.Mods.Cnc/OpenRA.Mods.Cnc.csproj b/OpenRA.Mods.Cnc/OpenRA.Mods.Cnc.csproj index ec7117f3eb..cc401b6ba5 100644 --- a/OpenRA.Mods.Cnc/OpenRA.Mods.Cnc.csproj +++ b/OpenRA.Mods.Cnc/OpenRA.Mods.Cnc.csproj @@ -102,6 +102,7 @@ + diff --git a/OpenRA.Mods.Cnc/ProductionAirdrop.cs b/OpenRA.Mods.Cnc/ProductionAirdrop.cs index d093b56c20..6146002702 100644 --- a/OpenRA.Mods.Cnc/ProductionAirdrop.cs +++ b/OpenRA.Mods.Cnc/ProductionAirdrop.cs @@ -45,8 +45,8 @@ namespace OpenRA.Mods.Cnc // Assume a single exit point for simplicity var exit = self.Info.Traits.WithInterface().First(); - var rb = self.Trait(); - rb.PlayCustomAnimRepeating(self, "active"); + foreach (var tower in self.TraitsImplementing()) + tower.IncomingDelivery(self); var actorType = (Info as ProductionAirdropInfo).ActorType; @@ -67,7 +67,8 @@ namespace OpenRA.Mods.Cnc if (!self.IsInWorld || self.IsDead()) return; - rb.PlayCustomAnimRepeating(self, "idle"); + foreach (var cargo in self.TraitsImplementing()) + cargo.Delivered(self); self.World.AddFrameEndTask(ww => DoProduction(self, producee, exit)); Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", (Info as ProductionAirdropInfo).ReadyAudio, self.Owner.Country.Race); })); diff --git a/OpenRA.Mods.Cnc/WithDeliveryAnimation.cs b/OpenRA.Mods.Cnc/WithDeliveryAnimation.cs new file mode 100644 index 0000000000..ce38bdd30b --- /dev/null +++ b/OpenRA.Mods.Cnc/WithDeliveryAnimation.cs @@ -0,0 +1,52 @@ +#region Copyright & License Information +/* + * Copyright 2007-2014 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. For more information, + * see COPYING. + */ +#endregion + +using System.Collections.Generic; +using System.Linq; +using OpenRA.FileFormats; +using OpenRA.Graphics; +using OpenRA.Traits; +using OpenRA.Mods.RA.Buildings; +using OpenRA.Effects; + +namespace OpenRA.Mods.RA.Render +{ + public class WithDeliveryAnimationInfo : ITraitInfo, Requires + { + public readonly string ActiveSequence = "active"; + + public readonly string IdleSequence = "idle"; + + public object Create(ActorInitializer init) { return new WithDeliveryAnimation(init.self, this); } + } + + public class WithDeliveryAnimation : INotifyDelivery + { + WithDeliveryAnimationInfo info; + RenderBuilding building; + + public WithDeliveryAnimation(Actor self, WithDeliveryAnimationInfo info) + { + building = self.Trait(); + + this.info = info; + } + + public void IncomingDelivery(Actor self) + { + building.PlayCustomAnimRepeating(self, info.ActiveSequence); + } + + public void Delivered(Actor self) + { + building.PlayCustomAnimRepeating(self, info.IdleSequence); + } + } +} \ No newline at end of file diff --git a/OpenRA.Mods.D2k/OpenRA.Mods.D2k.csproj b/OpenRA.Mods.D2k/OpenRA.Mods.D2k.csproj index fd7d79d8a8..7218a94d50 100644 --- a/OpenRA.Mods.D2k/OpenRA.Mods.D2k.csproj +++ b/OpenRA.Mods.D2k/OpenRA.Mods.D2k.csproj @@ -90,6 +90,7 @@ + diff --git a/OpenRA.Mods.D2k/Render/WithDeliveryOverlay.cs b/OpenRA.Mods.D2k/Render/WithDeliveryOverlay.cs new file mode 100644 index 0000000000..6048990a0a --- /dev/null +++ b/OpenRA.Mods.D2k/Render/WithDeliveryOverlay.cs @@ -0,0 +1,74 @@ +#region Copyright & License Information +/* + * Copyright 2007-2014 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. For more information, + * see COPYING. + */ +#endregion + +using OpenRA.Effects; +using OpenRA.FileFormats; +using OpenRA.Graphics; +using OpenRA.Traits; +using OpenRA.Mods.RA.Buildings; + +namespace OpenRA.Mods.RA.Render +{ + public class WithDeliveryOverlayInfo : ITraitInfo, Requires, Requires + { + [Desc("Sequence name to use")] + public readonly string Sequence = "active"; + + [Desc("Position relative to body")] + public readonly WVec Offset = WVec.Zero; + + public object Create(ActorInitializer init) { return new WithDeliveryOverlay(init.self, this); } + } + + public class WithDeliveryOverlay : INotifyBuildComplete, INotifySold, INotifyDelivery + { + WithDeliveryOverlayInfo info; + Animation overlay; + bool buildComplete, delivering; + + public WithDeliveryOverlay(Actor self, WithDeliveryOverlayInfo info) + { + this.info = info; + + var rs = self.Trait(); + var body = self.Trait(); + + buildComplete = !self.HasTrait(); // always render instantly for units + + overlay = new Animation(self.World, rs.GetImage(self)); + overlay.Play(info.Sequence); + rs.anims.Add("delivery_overlay_{0}".F(info.Sequence), + new AnimationWithOffset(overlay, + () => body.LocalToWorld(info.Offset.Rotate(body.QuantizeOrientation(self, self.Orientation))), + () => !buildComplete)); + } + + void PlayDeliveryOverlay() + { + if (delivering) + overlay.PlayThen(info.Sequence, PlayDeliveryOverlay); + } + + public void BuildingComplete(Actor self) + { + self.World.AddFrameEndTask(w => w.Add(new DelayedAction(120, () => + buildComplete = true))); + } + + public void Sold(Actor self) { } + public void Selling(Actor self) + { + buildComplete = false; + } + + public void IncomingDelivery(Actor self) { delivering = true; PlayDeliveryOverlay(); } + public void Delivered(Actor self) { delivering = false; } + } +} \ No newline at end of file diff --git a/mods/cnc/rules/structures.yaml b/mods/cnc/rules/structures.yaml index 5fcf9e9ffe..da3c0bd4a7 100644 --- a/mods/cnc/rules/structures.yaml +++ b/mods/cnc/rules/structures.yaml @@ -269,6 +269,7 @@ AFLD: ExitCell: 3,1 ProductionAirdrop: Produces: Vehicle + WithDeliveryAnimation: ProductionQueue: Type: Vehicle Group: Vehicle diff --git a/mods/d2k/rules/structures.yaml b/mods/d2k/rules/structures.yaml index 2655ddabdc..d0d33ce578 100644 --- a/mods/d2k/rules/structures.yaml +++ b/mods/d2k/rules/structures.yaml @@ -379,6 +379,7 @@ CONCRETEB: ProductionAirdrop: Produces: Starport ActorType: frigate + WithDeliveryOverlay: ProductionBar: PrimaryBuilding: RequiresPower: diff --git a/mods/d2k/sequences/structures.yaml b/mods/d2k/sequences/structures.yaml index 5ee32b28ef..603f961982 100644 --- a/mods/d2k/sequences/structures.yaml +++ b/mods/d2k/sequences/structures.yaml @@ -309,19 +309,24 @@ starporta: Start: 2671 ZOffset: -1c511 Offset: -48,64 - active: DATA - Start: 2671 - Length: 1 - ZOffset: -1c511 - Offset: -48,64 damaged-idle: DATA Start: 2672 ZOffset: -1c511 Offset: -48,64 - damaged-active: DATA - Start: 2672 + active: DATA + Start: 4723 + Length: 23 ZOffset: -1c511 Offset: -48,64 + BlendMode: Alpha + Tick: 200 + damaged-active: DATA + Start: 4723 + Length: 23 + ZOffset: -1c511 + Offset: -48,64 + BlendMode: Alpha + Tick: 200 make: DATA Start: 4347 Length: 11 @@ -806,19 +811,24 @@ starporth: Start: 2831 ZOffset: -1c511 Offset: -48,64 - active: DATA - Start: 2831 - Length: 1 - Offset: -48,64 - ZOffset: -1c511 damaged-idle: DATA Start: 2832 Offset: -48,64 ZOffset: -1c511 - damaged-active: DATA - Start: 2832 - Offset: -48,64 + active: DATA + Start: 4723 + Length: 23 ZOffset: -1c511 + Offset: -48,64 + BlendMode: Alpha + Tick: 200 + damaged-active: DATA + Start: 4723 + Length: 23 + ZOffset: -1c511 + Offset: -48,64 + BlendMode: Alpha + Tick: 200 make: DATA Start: 4347 Length: 11 @@ -1212,19 +1222,24 @@ starporto: Start: 2991 Offset: -48,64 ZOffset: -1c511 - active: DATA - Start: 2991 - Length: 1 - Offset: -48,64 - ZOffset: -1c511 damaged-idle: DATA Start: 2992 Offset: -48,64 ZOffset: -1c511 - damaged-active: DATA - Start: 2992 - Offset: -48,64 + active: DATA + Start: 4723 + Length: 23 ZOffset: -1c511 + Offset: -48,64 + BlendMode: Alpha + Tick: 200 + damaged-active: DATA + Start: 4723 + Length: 23 + ZOffset: -1c511 + Offset: -48,64 + BlendMode: Alpha + Tick: 200 make: DATA Start: 4347 Length: 11 @@ -1600,19 +1615,24 @@ starportc: # TODO: unused Start: 2999 Offset: -48,64 ZOffset: -1c511 - active: DATA - Start: 2999 - Length: 1 - Offset: -48,64 - ZOffset: -1c511 damaged-idle: DATA Start: 3000 Offset: -48,64 ZOffset: -1c511 - damaged-active: DATA - Start: 3000 - Offset: -48,64 + active: DATA + Start: 4723 + Length: 23 ZOffset: -1c511 + Offset: -48,64 + BlendMode: Alpha + Tick: 200 + damaged-active: DATA + Start: 4723 + Length: 23 + ZOffset: -1c511 + Offset: -48,64 + BlendMode: Alpha + Tick: 200 make: DATA Start: 4347 Length: 11