diff --git a/OpenRa.Game/Chrome.cs b/OpenRa.Game/Chrome.cs
index a5eca45aed..811125bbb6 100644
--- a/OpenRa.Game/Chrome.cs
+++ b/OpenRa.Game/Chrome.cs
@@ -493,9 +493,7 @@ namespace OpenRa.Game
}
void TickPaletteAnimation()
- {
- Log.Write("{0} {1} {2} {3}", paletteAnimationFrame, paletteOrigin.X, paletteAnimating, paletteOpen);
-
+ {
if (!paletteAnimating)
return;
diff --git a/OpenRa.Game/Graphics/Minimap.cs b/OpenRa.Game/Graphics/Minimap.cs
index f80cb3a066..021abe1a8c 100644
--- a/OpenRa.Game/Graphics/Minimap.cs
+++ b/OpenRa.Game/Graphics/Minimap.cs
@@ -103,7 +103,7 @@ namespace OpenRa.Game.Graphics
{
for (var y = 0; y < 128; y++)
for (var x = 0; x < 128; x++)
- if (!Game.LocalPlayer.Shroud.IsExplored(new int2(x, y)))
+ if (!Game.LocalPlayer.Shroud.DisplayOnRadar(x,y))
*(c + (y * bitmapData.Stride >> 2) + x) = shroudColor.ToArgb();
}
}
diff --git a/OpenRa.Game/OpenRa.Game.csproj b/OpenRa.Game/OpenRa.Game.csproj
index 3de25df83c..e4494b326d 100644
--- a/OpenRa.Game/OpenRa.Game.csproj
+++ b/OpenRa.Game/OpenRa.Game.csproj
@@ -227,6 +227,7 @@
+
@@ -234,6 +235,7 @@
+
diff --git a/OpenRa.Game/Player.cs b/OpenRa.Game/Player.cs
index 3a0ade12bd..2cb84bd562 100644
--- a/OpenRa.Game/Player.cs
+++ b/OpenRa.Game/Player.cs
@@ -131,6 +131,7 @@ namespace OpenRa.Game
{
UpdatePower();
UpdateOreCapacity();
+ Shroud.Tick();
foreach (var sp in SupportPowers.Values)
sp.Tick();
diff --git a/OpenRa.Game/Shroud.cs b/OpenRa.Game/Shroud.cs
index a64cd32edb..35c6f6abec 100644
--- a/OpenRa.Game/Shroud.cs
+++ b/OpenRa.Game/Shroud.cs
@@ -16,31 +16,78 @@ namespace OpenRa.Game
bool dirty;
bool hasGPS = false;
+ float gapOpaqueTicks = (int)(Rules.General.GapRegenInterval * 25 * 60);
+ int[,] gapField = new int[128, 128];
+ bool[,] gapActive = new bool[128, 128];
+
public bool HasGPS
{
get { return hasGPS; }
set { hasGPS = value; dirty = true;}
}
+ public void Tick()
+ {
+ // Clear active flags
+ gapActive = new bool[128, 128];
+ foreach (var a in Game.world.Actors.Where(a => a.traits.Contains()))
+ {
+ foreach (var t in a.traits.Get().GetShroudedTiles())
+ gapActive[t.X, t.Y] = true;
+ }
+
+ for (int j = 1; j < 127; j++)
+ for (int i = 1; i < 127; i++)
+ {
+ if (gapField[i, j] > 0 && !gapActive[i, j])
+ {
+ // Convert gap to shroud
+ if (gapField[i, j] >= gapOpaqueTicks && explored[i, j])
+ explored[i, j] = false;
+
+ // Clear gap
+ gapField[i, j] = 0;
+ dirty = true;
+ }
+ // Increase gap tick; rerender if necessary
+ if (gapActive[i, j] && 0 == gapField[i, j]++)
+ dirty = true;
+ }
+ }
+
public bool IsExplored(int2 xy) { return IsExplored(xy.X, xy.Y); }
public bool IsExplored(int x, int y)
{
+ if (gapField[ x, y ] >= Rules.General.GapRegenInterval * 25 * 60)
+ return false;
+
if (hasGPS)
return true;
return explored[ x, y ];
}
+ public bool DisplayOnRadar(int x, int y)
+ {
+ // Active gap is never shown on radar, even if a unit is in range
+ if (gapActive[x , y])
+ return false;
+
+ return IsExplored(x,y);
+ }
+
public void Explore(Actor a)
{
foreach (var t in Game.FindTilesInCircle(
(1f / Game.CellSize * a.CenterLocation).ToInt2(),
- a.Info.Traits.Get().Sight))
+ a.Info.Traits.Get().Sight))
+ {
explored[t.X, t.Y] = true;
-
+ gapField[t.X, t.Y] = 0;
+ }
dirty = true;
}
-
+
static readonly byte[][] SpecialShroudTiles =
{
new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
@@ -60,7 +107,7 @@ namespace OpenRa.Game
new byte[] { 41 },
new byte[] { 46 },
};
-
+
Sprite ChooseShroud(int i, int j)
{
if( !IsExplored( i, j ) ) return shadowBits[ 0xf ];
@@ -69,7 +116,7 @@ namespace OpenRa.Game
var v = 0;
// bits are for unexploredness: TL, TR, BR, BL
var u = 0;
-
+
if( !IsExplored( i, j - 1 ) ) { v |= 1; u |= 3; }
if( !IsExplored( i + 1, j ) ) { v |= 2; u |= 6; }
if( !IsExplored( i, j + 1 ) ) { v |= 4; u |= 12; }
@@ -82,7 +129,7 @@ namespace OpenRa.Game
if( !IsExplored( i + 1, j + 1 ) ) u |= 4;
if( !IsExplored( i - 1, j + 1 ) ) u |= 8;
- return shadowBits[ SpecialShroudTiles[ u ^ uSides ][ v ] ];
+ return shadowBits[ SpecialShroudTiles[ u ^ uSides ][ v ] ];
}
public void Draw(SpriteRenderer r)
diff --git a/OpenRa.Game/Traits/GeneratesGap.cs b/OpenRa.Game/Traits/GeneratesGap.cs
new file mode 100644
index 0000000000..7c68de6804
--- /dev/null
+++ b/OpenRa.Game/Traits/GeneratesGap.cs
@@ -0,0 +1,36 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using OpenRa.FileFormats;
+using OpenRa.Game.Support;
+using OpenRa.Game.Traits;
+
+namespace OpenRa.Game.Traits
+{
+ class GeneratesGapInfo : ITraitInfo
+ {
+ public readonly int Range = 10;
+ public object Create(Actor self) { return new GeneratesGap(self); }
+ }
+
+ class GeneratesGap
+ {
+ Actor self;
+ public GeneratesGap(Actor self)
+ {
+ this.self = self;
+ }
+
+ public IEnumerable GetShroudedTiles()
+ {
+ int range = self.Info.Traits.Get().Range;
+
+ // Gap Generator building; powered down
+ if (self.traits.Contains() && self.traits.Get().Disabled)
+ yield break;
+
+ foreach (var t in Game.FindTilesInCircle(self.Location, range))
+ yield return t;
+ }
+ }
+}
diff --git a/OpenRa.Game/Traits/LightPaletteRotator.cs b/OpenRa.Game/Traits/LightPaletteRotator.cs
new file mode 100644
index 0000000000..330708e685
--- /dev/null
+++ b/OpenRa.Game/Traits/LightPaletteRotator.cs
@@ -0,0 +1,25 @@
+using System.Drawing;
+
+namespace OpenRa.Game.Traits
+{
+ class LightPaletteRotatorInfo : StatelessTraitInfo { }
+ class LightPaletteRotator : ITick, IPaletteModifier
+ {
+ float t = 0;
+ public void Tick(Actor self)
+ {
+ t += .5f;
+ }
+
+ public void AdjustPalette(Bitmap b)
+ {
+ var rotate = (int)t % 18;
+ if (rotate > 9)
+ rotate = 18 - rotate;
+
+ using (var bitmapCopy = new Bitmap(b))
+ for (int j = 0; j < 16; j++)
+ b.SetPixel(0x67, j, b.GetPixel(230+rotate, j));
+ }
+ }
+}
diff --git a/merge-ra.yaml b/merge-ra.yaml
index 563e567090..6504564f5a 100644
--- a/merge-ra.yaml
+++ b/merge-ra.yaml
@@ -4,3 +4,11 @@ Player:
World:
WaterPaletteRotation:
ChronoshiftPaletteEffect:
+
+MGG:
+ GeneratesGap:
+ Range: 10
+
+GAP:
+ GeneratesGap:
+ Range: 10
diff --git a/ra.yaml b/ra.yaml
index 3e8bcf7fab..cbb726bc60 100644
--- a/ra.yaml
+++ b/ra.yaml
@@ -5,6 +5,52 @@ World:
WaterPaletteRotation:
ChronoshiftPaletteEffect:
+MGG:
+ GeneratesGap:
+ Range: 10
+ Inherits: ^Vehicle
+ Buildable:
+ TechLevel: 11
+ Prerequisites: weap,atek
+ Owner: allies
+ Cost: 600
+ Description: Mobile Gap Generator
+ LongDesc: Regenerates Fog of War in a small area \naround the unit.\n Unarmed
+ Selectable:
+ Priority: 3
+ Unit:
+ HP: 110
+ Armor: light
+ Crewed: yes
+ Sight: 4
+ Speed: 9
+ RenderUnitSpinner:
+ Offset: 0,6,0,-3
+
+GAP:
+ GeneratesGap:
+ Range: 10
+ Inherits: ^Building
+ Buildable:
+ TechLevel: 10
+ Prerequisites: atek
+ Owner: allies
+ Cost: 500
+ Description: Gap Generator
+ LongDesc: Regenerates the Fog of War nearby, \nobscuring the area.\n Unarmed
+ Building:
+ Power: -60
+ RequiresPower: true
+ Footprint: _ x
+ Dimensions: 1,2
+ Capturable: true
+ HP: 1000
+ Armor: wood
+ Crewed: yes
+ Sight: 10
+ RenderBuilding:
+ IronCurtainable:
+
V2RL:
Inherits: ^Vehicle
Buildable:
@@ -153,26 +199,6 @@ MRJ:
RenderUnitSpinner:
Offset: 0,4,0,-6
-MGG:
- Inherits: ^Vehicle
- Buildable:
- TechLevel: 11
- Prerequisites: weap,atek
- Owner: allies
- Cost: 600
- Description: Mobile Gap Generator
- LongDesc: Regenerates Fog of War in a small area \naround the unit.\n Unarmed
- Selectable:
- Priority: 3
- Unit:
- HP: 110
- Armor: light
- Crewed: yes
- Sight: 4
- Speed: 9
- RenderUnitSpinner:
- Offset: 0,6,0,-3
-
ARTY:
Inherits: ^Vehicle
Buildable:
@@ -824,28 +850,6 @@ FTUR:
AutoTarget:
IronCurtainable:
-GAP:
- Inherits: ^Building
- Buildable:
- TechLevel: 10
- Prerequisites: atek
- Owner: allies
- Cost: 500
- Description: Gap Generator
- LongDesc: Regenerates the Fog of War nearby, \nobscuring the area.\n Unarmed
- Building:
- Power: -60
- RequiresPower: true
- Footprint: _ x
- Dimensions: 1,2
- Capturable: true
- HP: 1000
- Armor: wood
- Crewed: yes
- Sight: 10
- RenderBuilding:
- IronCurtainable:
-
SAM:
Inherits: ^Building
Buildable:
diff --git a/units.ini b/units.ini
index c5da8b7f26..5ababd4b2b 100644
--- a/units.ini
+++ b/units.ini
@@ -77,7 +77,7 @@ Voice=VehicleVoice
LongDesc=Hides nearby units on the enemy's minimap.\n Unarmed
[MGG]
Description=Mobile Gap Generator
-Traits=Unit, Mobile, RenderUnitSpinner, Repairable, Chronoshiftable, Passenger, IronCurtainable
+Traits=Unit, Mobile, RenderUnitSpinner, Repairable, Chronoshiftable, Passenger, IronCurtainable, GeneratesGap
PrimaryOffset=0,6,0,-3
SelectionPriority=3
Voice=VehicleVoice
@@ -337,7 +337,7 @@ SelectionPriority=3
LongDesc=Teleports a unit from one place \nto another, for a limited time.\n Special Ability: Chronoshift
[GAP]
Description=Gap Generator
-Traits=Building, RenderBuilding, IronCurtainable
+Traits=Building, RenderBuilding, IronCurtainable, GeneratesGap
Dimensions=1,2
Footprint=_ x
SelectionPriority=3