Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for TS-style tinted target flashes #19479

Merged
merged 4 commits into from Aug 2, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
22 changes: 20 additions & 2 deletions OpenRA.Game/Traits/Player/FrozenActorLayer.cs
Expand Up @@ -76,6 +76,9 @@ public class FrozenActor
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)
{
Expand Down Expand Up @@ -176,9 +179,20 @@ public void Invalidate()
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<IRenderable> Render(WorldRenderer wr)
Expand All @@ -192,7 +206,11 @@ public IEnumerable<IRenderable> Render(WorldRenderer wr)
.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;
}));
}

Expand Down
2 changes: 1 addition & 1 deletion OpenRA.Mods.Common/Activities/Demolish.cs
Expand Up @@ -71,7 +71,7 @@ protected override void OnEnterComplete(Actor self, Actor targetActor)
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);
Expand Down
31 changes: 26 additions & 5 deletions OpenRA.Mods.Common/Effects/FlashTarget.cs
Expand Up @@ -13,21 +13,25 @@
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;
Expand All @@ -38,6 +42,20 @@ public FlashTarget(Actor target, Player asPlayer = null, int count = 2, int inte
});
}

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)
Expand All @@ -48,13 +66,16 @@ public IEnumerable<IRenderable> Render(WorldRenderer wr)
{
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;
});
}

Expand Down
3 changes: 2 additions & 1 deletion OpenRA.Mods.Common/Scripting/Properties/GeneralProperties.cs
Expand Up @@ -14,6 +14,7 @@
using OpenRA.Mods.Common.Activities;
using OpenRA.Mods.Common.Effects;
using OpenRA.Mods.Common.Traits;
using OpenRA.Primitives;
using OpenRA.Scripting;
using OpenRA.Traits;

Expand Down Expand Up @@ -76,7 +77,7 @@ public bool HasProperty(string name)
"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.")]
Expand Down
4 changes: 2 additions & 2 deletions OpenRA.Mods.Common/Traits/CapturableProgressBlink.cs
Expand Up @@ -64,10 +64,10 @@ void ITick.Tick(Actor self)
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)
Expand Down
2 changes: 1 addition & 1 deletion OpenRA.Mods.Common/Traits/ProximityCapturable.cs
Expand Up @@ -179,7 +179,7 @@ void ChangeOwnership(Actor self, Actor captor)
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<ProximityCaptorInfo>();
foreach (var t in self.TraitsImplementing<INotifyCapture>())
Expand Down
142 changes: 90 additions & 52 deletions OpenRA.Mods.Common/Traits/World/OrderEffects.cs
Expand Up @@ -10,60 +10,98 @@
#endregion

using OpenRA.Mods.Common.Effects;
using OpenRA.Primitives;
using OpenRA.Traits;

namespace OpenRA.Mods.Common.Traits
{
[Desc("Renders an effect at the order target locations.")]
public class OrderEffectsInfo : TraitInfo
{
[Desc("The image to use.")]
[FieldLoader.Require]
public readonly string TerrainFlashImage;

[Desc("The sequence to use.")]
[FieldLoader.Require]
public readonly string TerrainFlashSequence;

[Desc("The palette to use.")]
public readonly string TerrainFlashPalette;

public override object Create(ActorInitializer init)
{
return new OrderEffects(this);
}
}

public class OrderEffects : INotifyOrderIssued
{
readonly OrderEffectsInfo info;

public OrderEffects(OrderEffectsInfo info)
{
this.info = info;
}

bool INotifyOrderIssued.OrderIssued(World world, Target target)
{
if (target.Type == TargetType.Actor)
{
world.AddFrameEndTask(w => w.Add(new FlashTarget(target.Actor)));
return true;
}

if (target.Type == TargetType.FrozenActor)
{
target.FrozenActor.Flash();
return true;
}

if (target.Type == TargetType.Terrain)
{
world.AddFrameEndTask(w => w.Add(new SpriteAnnotation(target.CenterPosition, world, info.TerrainFlashImage, info.TerrainFlashSequence, info.TerrainFlashPalette)));
return true;
}

return false;
}
}
public enum ActorFlashType { Overlay, Tint }

pchote marked this conversation as resolved.
Show resolved Hide resolved
[TraitLocation(SystemActors.World)]
[Desc("Renders an effect at the order target locations.")]
public class OrderEffectsInfo : TraitInfo
{
[Desc("The image to use.")]
[FieldLoader.Require]
public readonly string TerrainFlashImage = null;

[Desc("The sequence to use.")]
[FieldLoader.Require]
public readonly string TerrainFlashSequence = null;

[Desc("The palette to use.")]
public readonly string TerrainFlashPalette = null;

[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);
}
}

public class OrderEffects : INotifyOrderIssued
{
readonly OrderEffectsInfo info;

public OrderEffects(OrderEffectsInfo info)
{
this.info = info;
}

bool INotifyOrderIssued.OrderIssued(World world, Target target)
{
switch (target.Type)
{
case TargetType.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;
}

case TargetType.FrozenActor:
{
if (info.ActorFlashType == ActorFlashType.Overlay)
target.FrozenActor.Flash(info.ActorFlashOverlayColor, info.ActorFlashOverlayAlpha);
else
target.FrozenActor.Flash(info.ActorFlashTint);

return true;
}

case TargetType.Terrain:
{
world.AddFrameEndTask(w => w.Add(new SpriteAnnotation(target.CenterPosition, world, info.TerrainFlashImage, info.TerrainFlashSequence, info.TerrainFlashPalette)));
return true;
}

default:
return false;
}
}
}
}
1 change: 1 addition & 0 deletions mods/ts/rules/world.yaml
Expand Up @@ -388,6 +388,7 @@ World:
TerrainFlashImage: moveflsh
TerrainFlashSequence: idle
TerrainFlashPalette: moveflash
ActorFlashType: Tint

EditorWorld:
Inherits: ^BaseWorld
Expand Down