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