diff --git a/OpenRa.Game/Game.cs b/OpenRa.Game/Game.cs
index 964f9012e7..a068834f48 100644
--- a/OpenRa.Game/Game.cs
+++ b/OpenRa.Game/Game.cs
@@ -73,6 +73,7 @@ namespace OpenRa.Game
var worldActor = new Actor(null, new int2(int.MaxValue, int.MaxValue), null);
worldActor.traits.Add(new Traits.WaterPaletteRotation(worldActor));
+ worldActor.traits.Add(new Traits.ChronoshiftPaletteEffect(worldActor));
Game.world.Add(worldActor);
Rules.Map.InitOreDensity();
diff --git a/OpenRa.Game/OpenRa.Game.csproj b/OpenRa.Game/OpenRa.Game.csproj
index d13fdbe492..68cfee2a41 100644
--- a/OpenRa.Game/OpenRa.Game.csproj
+++ b/OpenRa.Game/OpenRa.Game.csproj
@@ -198,6 +198,7 @@
+
diff --git a/OpenRa.Game/Traits/ChronoshiftDeploy.cs b/OpenRa.Game/Traits/ChronoshiftDeploy.cs
index 6208a7ef4e..cd02343320 100644
--- a/OpenRa.Game/Traits/ChronoshiftDeploy.cs
+++ b/OpenRa.Game/Traits/ChronoshiftDeploy.cs
@@ -1,21 +1,14 @@
using System.Collections.Generic;
using System.Linq;
using OpenRa.Game.Orders;
-using System.Drawing;
-using OpenRa.Game.Graphics;
namespace OpenRa.Game.Traits
{
- class ChronoshiftDeploy : IOrder, ISpeedModifier, ITick, IPips, IPaletteModifier
+ class ChronoshiftDeploy : IOrder, ISpeedModifier, ITick, IPips
{
// Recharge logic
int chargeTick = 0; // How long until we can chronoshift again?
int chargeLength = (int)(Rules.Aftermath.ChronoTankDuration * 60 * 25); // How long between shifts?
-
- // Screen fade logic
- int animationTick = 0;
- int animationLength = 10;
- bool animationStarted = false;
public ChronoshiftDeploy(Actor self) { }
@@ -23,19 +16,6 @@ namespace OpenRa.Game.Traits
{
if (chargeTick > 0)
chargeTick--;
-
- if (animationStarted)
- {
- if (animationTick < animationLength)
- animationTick++;
- else
- animationStarted = false;
- }
- if (!animationStarted)
- {
- if (animationTick > 0)
- animationTick--;
- }
}
public Order IssueOrder(Actor self, int2 xy, MouseInput mi, Actor underCursor)
@@ -62,7 +42,9 @@ namespace OpenRa.Game.Traits
self.QueueActivity(new Activities.Teleport(order.TargetLocation));
Sound.Play("chrotnk1.aud");
chargeTick = chargeLength;
- animationStarted = true;
+
+ foreach (var a in Game.world.Actors.Where(a => a.traits.Contains()))
+ a.traits.Get().DoChronoshift();
}
}
@@ -100,51 +82,5 @@ namespace OpenRa.Game.Traits
}
}
}
-
- public void AdjustPalette(Bitmap bmp)
- {
- if (!animationStarted && animationTick == 0)
- return;
-
- // saturation modifier
- var f = 1 - (animationTick * 1.0f / animationLength);
-
- using (var bitmapCopy = new Bitmap(bmp))
- for (int j = 0; j < (int)PaletteType.Chrome; j++)
- for (int i = 0; i < bmp.Width; i++)
- {
- var h = bitmapCopy.GetPixel(i, j).GetHue(); // 0-360
- var s = f * bitmapCopy.GetPixel(i, j).GetSaturation(); // 0-1.0
- var l = bitmapCopy.GetPixel(i, j).GetBrightness(); // 0-1.0
- var alpha = bitmapCopy.GetPixel(i, j).A;
-
- // Convert from HSL to RGB
- // Refactor me!
- var q = (l < 0.5f) ? l * (1 + s) : l + s - (l * s);
- var p = 2 * l - q;
- var hk = h / 360.0f;
-
- double[] trgb = { hk + 1 / 3.0f,
- hk,
- hk - 1/3.0f };
- double[] rgb = { 0, 0, 0 };
-
- for (int k = 0; k < 3; k++)
- {
- // mod doesn't seem to work right... do it manually
- while (trgb[k] < 0) trgb[k] += 1.0f;
- while (trgb[k] > 1) trgb[k] -= 1.0f;
- }
-
- for (int k = 0; k < 3; k++)
- {
- if (trgb[k] < 1 / 6.0f) { rgb[k] = (p + ((q - p) * 6 * trgb[k])); }
- else if (trgb[k] >= 1 / 6.0f && trgb[k] < 0.5) { rgb[k] = q; }
- else if (trgb[k] >= 0.5f && trgb[k] < 2.0f / 3) { rgb[k] = (p + ((q - p) * 6 * (2.0f / 3 - trgb[k]))); }
- else { rgb[k] = p; }
- }
- bmp.SetPixel(i, j, Color.FromArgb(alpha, (int)(rgb[0] * 255), (int)(rgb[1] * 255), (int)(rgb[2] * 255)));
- }
- }
}
}
diff --git a/OpenRa.Game/Traits/ChronoshiftPaletteEffect.cs b/OpenRa.Game/Traits/ChronoshiftPaletteEffect.cs
new file mode 100644
index 0000000000..09efc58efb
--- /dev/null
+++ b/OpenRa.Game/Traits/ChronoshiftPaletteEffect.cs
@@ -0,0 +1,54 @@
+using System.Drawing;
+using OpenRa.Game.Graphics;
+
+namespace OpenRa.Game.Traits
+{
+ class ChronoshiftPaletteEffect : IPaletteModifier, ITick
+ {
+ const int chronoEffectLength = 10;
+ int remainingFrames;
+
+ public ChronoshiftPaletteEffect(Actor self) { }
+
+ public void DoChronoshift()
+ {
+ remainingFrames = chronoEffectLength;
+ }
+
+ public void Tick(Actor self)
+ {
+ if (remainingFrames > 0)
+ remainingFrames--;
+ }
+
+ public void AdjustPalette(Bitmap b)
+ {
+ if (remainingFrames == 0)
+ return;
+
+ var frac = (float)remainingFrames / chronoEffectLength;
+ for( var y = 0; y < (int)PaletteType.Chrome; y++ )
+ for (var x = 0; x < 256; x++)
+ {
+ var orig = b.GetPixel(x, y);
+ var lum = (int)(255 * orig.GetBrightness());
+ var desat = Color.FromArgb(orig.A, lum, lum, lum);
+ b.SetPixel(x, y, Lerp(frac, orig, desat));
+ }
+ }
+
+ static Color Lerp(float t, Color a, Color b)
+ {
+ return Color.FromArgb(
+ LerpChannel(t, a.A, b.A),
+ LerpChannel(t, a.R, b.R),
+ LerpChannel(t, a.G, b.G),
+ LerpChannel(t, a.B, b.B));
+ }
+
+ static int LerpChannel(float t, int a, int b)
+ {
+ return (int)((1 - t) * a + t * b);
+ }
+ }
+}
diff --git a/OpenRa.Game/Traits/Chronoshiftable.cs b/OpenRa.Game/Traits/Chronoshiftable.cs
index 84f004a310..bbdbb88048 100644
--- a/OpenRa.Game/Traits/Chronoshiftable.cs
+++ b/OpenRa.Game/Traits/Chronoshiftable.cs
@@ -6,31 +6,16 @@ using System.Drawing;
namespace OpenRa.Game.Traits
{
- class Chronoshiftable : IOrder, ISpeedModifier, ITick, IPaletteModifier
+ class Chronoshiftable : IOrder, ISpeedModifier, ITick
{
// Return-to-sender logic
int2 chronoshiftOrigin;
int chronoshiftReturnTicks = 0;
- // Screen fade logic
- int animationTick = 0;
- int animationLength = 10;
- bool animationStarted = false;
-
public Chronoshiftable(Actor self) { }
public void Tick(Actor self)
{
- if (animationStarted)
- {
- if (animationTick < animationLength)
- animationTick++;
- else
- animationStarted = false;
- }
- else if (animationTick > 0)
- animationTick--;
-
if (chronoshiftReturnTicks <= 0)
return;
@@ -68,7 +53,9 @@ namespace OpenRa.Game.Traits
self.CancelActivity();
self.QueueActivity(new Activities.Teleport(order.TargetLocation));
Sound.Play("chrono2.aud");
- animationStarted = true;
+
+ foreach (var a in Game.world.Actors.Where(a => a.traits.Contains()))
+ a.traits.Get().DoChronoshift();
}
}
@@ -77,51 +64,5 @@ namespace OpenRa.Game.Traits
// ARGH! You must not do this, it will desync!
return (Game.controller.orderGenerator is ChronoshiftDestinationOrderGenerator) ? 0f : 1f;
}
-
- public void AdjustPalette(Bitmap bmp)
- {
- if (!animationStarted && animationTick == 0)
- return;
-
- // saturation modifier
- var f = 1 - (animationTick * 1.0f / animationLength);
-
- using (var bitmapCopy = new Bitmap(bmp))
- for (int j = 0; j < 8; j++)
- for (int i = 0; i < bmp.Width; i++)
- {
- var h = bitmapCopy.GetPixel(i, j).GetHue(); // 0-360
- var s = f * bitmapCopy.GetPixel(i, j).GetSaturation(); // 0-1.0
- var l = bitmapCopy.GetPixel(i, j).GetBrightness(); // 0-1.0
- var alpha = bitmapCopy.GetPixel(i, j).A;
-
- // Convert from HSL to RGB
- // Refactor me!
- var q = (l < 0.5f) ? l * (1 + s) : l + s - (l * s);
- var p = 2 * l - q;
- var hk = h / 360.0f;
-
- double[] trgb = { hk + 1 / 3.0f,
- hk,
- hk - 1/3.0f };
- double[] rgb = { 0, 0, 0 };
-
- for (int k = 0; k < 3; k++)
- {
- // mod doesn't seem to work right... do it manually
- while (trgb[k] < 0) trgb[k] += 1.0f;
- while (trgb[k] > 1) trgb[k] -= 1.0f;
- }
-
- for (int k = 0; k < 3; k++)
- {
- if (trgb[k] < 1 / 6.0f) { rgb[k] = (p + ((q - p) * 6 * trgb[k])); }
- else if (trgb[k] >= 1 / 6.0f && trgb[k] < 0.5) { rgb[k] = q; }
- else if (trgb[k] >= 0.5f && trgb[k] < 2.0f / 3) { rgb[k] = (p + ((q - p) * 6 * (2.0f / 3 - trgb[k]))); }
- else { rgb[k] = p; }
- }
- bmp.SetPixel(i, j, Color.FromArgb(alpha, (int)(rgb[0] * 255), (int)(rgb[1] * 255), (int)(rgb[2] * 255)));
- }
- }
}
}