diff --git a/OpenRA.Mods.Common/Effects/Beacon.cs b/OpenRA.Mods.Common/Effects/Beacon.cs index 172a9e0567..434df3b015 100644 --- a/OpenRA.Mods.Common/Effects/Beacon.cs +++ b/OpenRA.Mods.Common/Effects/Beacon.cs @@ -30,9 +30,11 @@ namespace OpenRA.Mods.Common.Effects readonly Animation circles; readonly Animation poster; readonly Animation clock; + readonly int duration; int arrowHeight = MaxArrowHeight; int arrowSpeed = 50; + int tick; // Player-placed beacons are removed after a delay public Beacon(Player owner, WPos position, int duration, string beaconPalette, bool isPlayerPalette, string beaconCollection, string arrowSprite, string circleSprite) @@ -41,6 +43,7 @@ namespace OpenRA.Mods.Common.Effects this.position = position; this.beaconPalette = beaconPalette; this.isPlayerPalette = isPlayerPalette; + this.duration = duration; if (!string.IsNullOrEmpty(arrowSprite)) { @@ -53,9 +56,6 @@ namespace OpenRA.Mods.Common.Effects circles = new Animation(owner.World, beaconCollection); circles.Play(circleSprite); } - - if (duration > 0) - owner.World.AddFrameEndTask(w => w.Add(new DelayedAction(duration, () => owner.World.Remove(this)))); } // Support power beacons are expected to clean themselves up @@ -96,6 +96,9 @@ namespace OpenRA.Mods.Common.Effects if (clock != null) clock.Tick(); + + if (duration > 0 && duration <= tick++) + owner.World.AddFrameEndTask(w => w.Remove(this)); } IEnumerable IEffect.Render(WorldRenderer r) { return SpriteRenderable.None; } diff --git a/OpenRA.Mods.Common/Traits/Player/PlaceBuilding.cs b/OpenRA.Mods.Common/Traits/Player/PlaceBuilding.cs index f76f7f652a..0ca7bf6fe8 100644 --- a/OpenRA.Mods.Common/Traits/Player/PlaceBuilding.cs +++ b/OpenRA.Mods.Common/Traits/Player/PlaceBuilding.cs @@ -31,16 +31,18 @@ namespace OpenRA.Mods.Common.Traits public object Create(ActorInitializer init) { return new PlaceBuilding(this); } } - public class PlaceBuilding : IResolveOrder + public class PlaceBuilding : IResolveOrder, ITick { readonly PlaceBuildingInfo info; + bool triggerNotification; + int tick; public PlaceBuilding(PlaceBuildingInfo info) { this.info = info; } - public void ResolveOrder(Actor self, Order order) + void IResolveOrder.ResolveOrder(Actor self, Order order) { var os = order.OrderString; if (os != "PlaceBuilding" && @@ -143,11 +145,26 @@ namespace OpenRA.Mods.Common.Traits } if (GetNumBuildables(self.Owner) > prevItems) - w.Add(new DelayedAction(info.NewOptionsNotificationDelay, - () => Game.Sound.PlayNotification(self.World.Map.Rules, order.Player, "Speech", info.NewOptionsNotification, order.Player.Faction.InternalName))); + triggerNotification = true; }); } + void ITick.Tick(Actor self) + { + if (!triggerNotification) + return; + + if (tick++ >= info.NewOptionsNotificationDelay) + PlayNotification(self); + } + + void PlayNotification(Actor self) + { + Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", info.NewOptionsNotification, self.Owner.Faction.InternalName); + triggerNotification = false; + tick = 0; + } + static int GetNumBuildables(Player p) { // This only matters for local players. diff --git a/OpenRA.Mods.TS/Effects/AnimatedBeacon.cs b/OpenRA.Mods.TS/Effects/AnimatedBeacon.cs index 58b61097ad..317dd2b596 100644 --- a/OpenRA.Mods.TS/Effects/AnimatedBeacon.cs +++ b/OpenRA.Mods.TS/Effects/AnimatedBeacon.cs @@ -25,6 +25,9 @@ namespace OpenRA.Mods.TS.Effects readonly string beaconPalette; readonly bool isPlayerPalette; readonly Animation beacon; + readonly int duration; + + int tick; public AnimatedBeacon(Player owner, WPos position, int duration, string beaconPalette, bool isPlayerPalette, string beaconImage, string beaconSequence) { @@ -32,6 +35,7 @@ namespace OpenRA.Mods.TS.Effects this.position = position; this.beaconPalette = beaconPalette; this.isPlayerPalette = isPlayerPalette; + this.duration = duration; if (!string.IsNullOrEmpty(beaconSequence)) { @@ -47,6 +51,9 @@ namespace OpenRA.Mods.TS.Effects { if (beacon != null) beacon.Tick(); + + if (duration > 0 && duration <= tick++) + owner.World.AddFrameEndTask(w => w.Remove(this)); } IEnumerable IEffect.Render(WorldRenderer r) { return SpriteRenderable.None; }