diff --git a/OpenRA.Game/Traits/Player/FrozenActorLayer.cs b/OpenRA.Game/Traits/Player/FrozenActorLayer.cs index 00bcc69219..24fecae879 100644 --- a/OpenRA.Game/Traits/Player/FrozenActorLayer.cs +++ b/OpenRA.Game/Traits/Player/FrozenActorLayer.cs @@ -76,6 +76,9 @@ namespace OpenRA.Traits static readonly Rectangle[] NoBounds = new Rectangle[0]; int flashTicks; + TintModifiers flashModifiers; + float3 flashTint; + float? flashAlpha; public FrozenActor(Actor actor, ICreatesFrozenActors frozenTrait, PPos[] footprint, Player viewer, bool startsRevealed) { @@ -176,9 +179,20 @@ namespace OpenRA.Traits Owner = null; } - public void Flash() + public void Flash(Color color, float alpha) { flashTicks = 5; + flashModifiers = TintModifiers.ReplaceColor; + flashTint = new float3(color.R, color.G, color.B) / 255f; + flashAlpha = alpha; + } + + public void Flash(float3 tint) + { + flashTicks = 5; + flashModifiers = TintModifiers.None; + flashTint = tint; + flashAlpha = null; } public IEnumerable Render(WorldRenderer wr) @@ -192,7 +206,11 @@ namespace OpenRA.Traits .Select(r => { var mr = (IModifyableRenderable)r; - return mr.WithTint(float3.Ones, mr.TintModifiers | TintModifiers.ReplaceColor).WithAlpha(0.5f); + mr = mr.WithTint(flashTint, mr.TintModifiers | flashModifiers); + if (flashAlpha.HasValue) + mr = mr.WithAlpha(flashAlpha.Value); + + return mr; })); } diff --git a/OpenRA.Mods.Common/Activities/Demolish.cs b/OpenRA.Mods.Common/Activities/Demolish.cs index 7fe1c5cf20..2e877cd2e7 100644 --- a/OpenRA.Mods.Common/Activities/Demolish.cs +++ b/OpenRA.Mods.Common/Activities/Demolish.cs @@ -71,7 +71,7 @@ namespace OpenRA.Mods.Common.Activities if (!enterDemolishables.Any(i => i.IsValidTarget(enterActor, self))) return; - w.Add(new FlashTarget(enterActor, count: flashes, delay: flashesDelay, interval: flashInterval)); + w.Add(new FlashTarget(enterActor, Color.White, count: flashes, interval: flashInterval, delay: flashesDelay)); foreach (var ind in notifiers) ind.Demolishing(self); diff --git a/OpenRA.Mods.Common/Effects/FlashTarget.cs b/OpenRA.Mods.Common/Effects/FlashTarget.cs index 999bedf909..0c27440aeb 100644 --- a/OpenRA.Mods.Common/Effects/FlashTarget.cs +++ b/OpenRA.Mods.Common/Effects/FlashTarget.cs @@ -13,21 +13,25 @@ using System.Collections.Generic; using System.Linq; using OpenRA.Effects; using OpenRA.Graphics; +using OpenRA.Primitives; namespace OpenRA.Mods.Common.Effects { public class FlashTarget : IEffect { readonly Actor target; - readonly Player player; readonly int count; readonly int interval; + + readonly TintModifiers modifiers; + readonly float3 tint; + readonly float? alpha; + int tick; - public FlashTarget(Actor target, Player asPlayer = null, int count = 2, int interval = 2, int delay = 0) + FlashTarget(Actor target, int count, int interval, int delay) { this.target = target; - player = asPlayer; this.count = count; this.interval = interval; tick = -delay; @@ -38,6 +42,20 @@ namespace OpenRA.Mods.Common.Effects }); } + public FlashTarget(Actor target, Color color, float alpha = 0.5f, int count = 2, int interval = 2, int delay = 0) + : this(target, count, interval, delay) + { + modifiers = TintModifiers.ReplaceColor; + tint = new float3(color.R, color.G, color.B) / 255f; + this.alpha = alpha; + } + + public FlashTarget(Actor target, float3 tint, int count = 2, int interval = 2, int delay = 0) + : this(target, count, interval, delay) + { + this.tint = tint; + } + public void Tick(World world) { if (++tick >= count * interval || !target.IsInWorld) @@ -48,13 +66,16 @@ namespace OpenRA.Mods.Common.Effects { if (target.IsInWorld && tick >= 0 && tick % interval == 0) { - var color = player == null ? float3.Ones : new float3(player.Color.R, player.Color.G, player.Color.B) / 255f; return target.Render(wr) .Where(r => !r.IsDecoration && r is IModifyableRenderable) .Select(r => { var mr = (IModifyableRenderable)r; - return mr.WithTint(color, mr.TintModifiers | TintModifiers.ReplaceColor).WithAlpha(0.5f); + mr = mr.WithTint(tint, mr.TintModifiers | modifiers); + if (alpha.HasValue) + mr = mr.WithAlpha(alpha.Value); + + return mr; }); } diff --git a/OpenRA.Mods.Common/Scripting/Properties/GeneralProperties.cs b/OpenRA.Mods.Common/Scripting/Properties/GeneralProperties.cs index a59691b105..1a2ca2f2df 100644 --- a/OpenRA.Mods.Common/Scripting/Properties/GeneralProperties.cs +++ b/OpenRA.Mods.Common/Scripting/Properties/GeneralProperties.cs @@ -14,6 +14,7 @@ using Eluant; using OpenRA.Mods.Common.Activities; using OpenRA.Mods.Common.Effects; using OpenRA.Mods.Common.Traits; +using OpenRA.Primitives; using OpenRA.Scripting; using OpenRA.Traits; @@ -76,7 +77,7 @@ namespace OpenRA.Mods.Common.Scripting "defines which player palette to use. Duration is in ticks.")] public void Flash(int duration = 4, Player asPlayer = null) { - Self.World.Add(new FlashTarget(Self, asPlayer, duration)); + Self.World.Add(new FlashTarget(Self, asPlayer?.Color ?? Color.White, duration)); } [Desc("The effective owner of the actor.")] diff --git a/OpenRA.Mods.Common/Traits/CapturableProgressBlink.cs b/OpenRA.Mods.Common/Traits/CapturableProgressBlink.cs index a27fb294b4..3ec6c344da 100644 --- a/OpenRA.Mods.Common/Traits/CapturableProgressBlink.cs +++ b/OpenRA.Mods.Common/Traits/CapturableProgressBlink.cs @@ -64,10 +64,10 @@ namespace OpenRA.Mods.Common.Traits if (tick / 4 < captorOwners.Count && tick % 4 == 0) { var captorOwner = captorOwners[tick / 4]; - self.World.Add(new FlashTarget(self, captorOwner)); + self.World.Add(new FlashTarget(self, captorOwner.Color)); foreach (var captor in captors) if (captor.Owner == captorOwner) - self.World.Add(new FlashTarget(captor, captorOwner)); + self.World.Add(new FlashTarget(captor, captorOwner.Color)); } if (++tick >= Info.Interval) diff --git a/OpenRA.Mods.Common/Traits/ProximityCapturable.cs b/OpenRA.Mods.Common/Traits/ProximityCapturable.cs index 0e44d8bc80..2f14f080ea 100644 --- a/OpenRA.Mods.Common/Traits/ProximityCapturable.cs +++ b/OpenRA.Mods.Common/Traits/ProximityCapturable.cs @@ -179,7 +179,7 @@ namespace OpenRA.Mods.Common.Traits self.ChangeOwner(captor.Owner); if (self.Owner == self.World.LocalPlayer) - w.Add(new FlashTarget(self)); + w.Add(new FlashTarget(self, Color.White)); var pc = captor.Info.TraitInfoOrDefault(); foreach (var t in self.TraitsImplementing()) diff --git a/OpenRA.Mods.Common/Traits/World/OrderEffects.cs b/OpenRA.Mods.Common/Traits/World/OrderEffects.cs index b849f085ec..28f9d31077 100644 --- a/OpenRA.Mods.Common/Traits/World/OrderEffects.cs +++ b/OpenRA.Mods.Common/Traits/World/OrderEffects.cs @@ -10,10 +10,13 @@ #endregion using OpenRA.Mods.Common.Effects; +using OpenRA.Primitives; using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { + public enum ActorFlashType { Overlay, Tint } + [Desc("Renders an effect at the order target locations.")] public class OrderEffectsInfo : TraitInfo { @@ -28,6 +31,24 @@ namespace OpenRA.Mods.Common.Traits [Desc("The palette to use.")] public readonly string TerrainFlashPalette; + [Desc("The type of effect to apply to targeted (frozen) actors. Accepts values Overlay and Tint.")] + public readonly ActorFlashType ActorFlashType = ActorFlashType.Overlay; + + [Desc("The overlay color to display when ActorFlashType is Overlay.")] + public readonly Color ActorFlashOverlayColor = Color.White; + + [Desc("The overlay transparency to display when ActorFlashType is Overlay.")] + public readonly float ActorFlashOverlayAlpha = 0.5f; + + [Desc("The tint to apply when ActorFlashType is Tint.")] + public readonly float3 ActorFlashTint = new float3(1.4f, 1.4f, 1.4f); + + [Desc("Number of times to flash (frozen) actors.")] + public readonly int ActorFlashCount = 2; + + [Desc("Number of ticks between (frozen) actor flashes.")] + public readonly int ActorFlashInterval = 2; + public override object Create(ActorInitializer init) { return new OrderEffects(this); @@ -47,13 +68,25 @@ namespace OpenRA.Mods.Common.Traits { if (target.Type == TargetType.Actor) { - world.AddFrameEndTask(w => w.Add(new FlashTarget(target.Actor))); + if (info.ActorFlashType == ActorFlashType.Overlay) + world.AddFrameEndTask(w => w.Add(new FlashTarget( + target.Actor, info.ActorFlashOverlayColor, info.ActorFlashOverlayAlpha, + info.ActorFlashCount, info.ActorFlashInterval))); + else + world.AddFrameEndTask(w => w.Add(new FlashTarget( + target.Actor, info.ActorFlashTint, + info.ActorFlashCount, info.ActorFlashInterval))); + return true; } if (target.Type == TargetType.FrozenActor) { - target.FrozenActor.Flash(); + if (info.ActorFlashType == ActorFlashType.Overlay) + target.FrozenActor.Flash(info.ActorFlashOverlayColor, info.ActorFlashOverlayAlpha); + else + target.FrozenActor.Flash(info.ActorFlashTint); + return true; } diff --git a/mods/ts/rules/world.yaml b/mods/ts/rules/world.yaml index fe3e9b7c1b..7ef27694b3 100644 --- a/mods/ts/rules/world.yaml +++ b/mods/ts/rules/world.yaml @@ -388,6 +388,7 @@ World: TerrainFlashImage: moveflsh TerrainFlashSequence: idle TerrainFlashPalette: moveflash + ActorFlashType: Tint EditorWorld: Inherits: ^BaseWorld