diff --git a/OpenRa.FileFormats/Map.cs b/OpenRa.FileFormats/Map.cs index ca87813241..bb326e1863 100644 --- a/OpenRa.FileFormats/Map.cs +++ b/OpenRa.FileFormats/Map.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Text; using System.IO; using System.Drawing; +using System.Linq; namespace OpenRa.FileFormats { @@ -22,6 +23,33 @@ namespace OpenRa.FileFormats public readonly TileReference[ , ] MapTiles = new TileReference[ 128, 128 ]; public readonly List Trees = new List(); + public static bool[] overlayIsFence = + { + true, true, true, true, true, + false, false, false, false, + false, false, false, false, + false, false, false, false, false, false, false, + false, false, false, true, true, + }; + + public static bool[] overlayIsOre = + { + false, false, false, false, false, + true, true, true, true, + false, false, false, false, + false, false, false, false, false, false, false, + false, false, false, false, false, + }; + + public static bool[] overlayIsGems = + { + false, false, false, false, false, + false, false, false, false, + true, true, true, true, + false, false, false, false, false, false, false, + false, false, false, false, false, + }; + static string Truncate( string s, int maxLength ) { return s.Length <= maxLength ? s : s.Substring(0,maxLength ); @@ -47,9 +75,90 @@ namespace OpenRa.FileFormats Width = int.Parse(map.GetValue("Width", "0")); Height = int.Parse(map.GetValue("Height", "0")); - UnpackTileData( ReadPackedSection( file.GetSection( "MapPack" ) ) ); - UnpackOverlayData( ReadPackedSection( file.GetSection( "OverlayPack" ) ) ); + UnpackTileData(ReadPackedSection(file.GetSection("MapPack"))); + UnpackOverlayData(ReadPackedSection(file.GetSection("OverlayPack"))); ReadTrees(file); + + InitOreDensity(); + } + + IEnumerable AdjacentTiles(int2 p) + { + for (var u = -1; u < 2; u++) + for (var v = -1; v < 2; v++) + yield return new int2(u, v) + p; + } + + byte GetOreDensity(int i, int j) + { + return (byte)Math.Min(11, (3 * AdjacentTiles(new int2(i, j)).Sum( + p => ContainsOre(p.X, p.Y) ? 1 : 0) / 2)); + } + + byte GetGemDensity(int i, int j) + { + return (byte)Math.Min(2, (AdjacentTiles(new int2(i, j)).Sum( + p => ContainsGem(p.X, p.Y) ? 1 : 0) / 3)); + } + + void InitOreDensity() + { + for( int j = 0; j < 128; j++ ) + for (int i = 0; i < 128; i++) + { + if (ContainsOre(i,j)) MapTiles[i, j].density = GetOreDensity(i, j); + if (ContainsGem(i,j)) MapTiles[i,j].density = GetGemDensity(i,j); + } + } + + bool HasOverlay(int i, int j) + { + return MapTiles[i, j].overlay < overlayIsOre.Length; + } + + bool ContainsOre(int i, int j) + { + return HasOverlay(i,j) && overlayIsOre[MapTiles[i,j].overlay]; + } + + bool ContainsGem(int i, int j) + { + return HasOverlay(i, j) && overlayIsGems[MapTiles[i, j].overlay]; + } + + public void GrowOre( Func canSpreadIntoCell ) /* todo: deal with ore pits */ + { + /* phase 1: grow into neighboring regions */ + var newOverlay = new byte[128, 128]; + for( int j = 1; j < 127; j++ ) + for (int i = 1; i < 127; i++) + { + newOverlay[i,j] = 0xff; + if (!HasOverlay(i, j) && GetOreDensity(i, j) > 0 && canSpreadIntoCell(new int2(i,j))) + newOverlay[i, j] = 5; /* todo: randomize [5..8] */ + + if (!HasOverlay(i, j) && GetGemDensity(i, j) > 0 && canSpreadIntoCell(new int2(i, j))) + newOverlay[i, j] = 9; /* todo: randomize [9..12] */ + } + + for (int j = 1; j < 127; j++) + for (int i = 1; i < 127; i++) + if (newOverlay[i, j] != 0xff) + MapTiles[i, j].overlay = newOverlay[i, j]; + + /* phase 2: increase density of existing areas */ + var newDensity = new byte[128, 128]; + for (int j = 1; j < 127; j++) + for (int i = 1; i < 127; i++) + { + if (ContainsOre(i, j)) newDensity[i,j] = GetOreDensity(i, j); + if (ContainsGem(i, j)) newDensity[i,j] = GetGemDensity(i, j); + } + + for (int j = 1; j < 127; j++) + for (int i = 1; i < 127; i++) + if (MapTiles[i, j].density < newDensity[i, j]) + MapTiles[i, j].density = newDensity[i, j]; } static MemoryStream ReadPackedSection(IniSection mapPackSection) diff --git a/OpenRa.FileFormats/TileReference.cs b/OpenRa.FileFormats/TileReference.cs index c0b1601b1a..484f75ec32 100644 --- a/OpenRa.FileFormats/TileReference.cs +++ b/OpenRa.FileFormats/TileReference.cs @@ -10,6 +10,7 @@ namespace OpenRa.FileFormats public byte image; public byte overlay; public byte smudge; + public byte density; /* used for ore/gems */ public override int GetHashCode() { return tile.GetHashCode() ^ image.GetHashCode(); } diff --git a/OpenRa.Game/Graphics/OverlayRenderer.cs b/OpenRa.Game/Graphics/OverlayRenderer.cs index ab07aa0c91..eb4ddabd84 100755 --- a/OpenRa.Game/Graphics/OverlayRenderer.cs +++ b/OpenRa.Game/Graphics/OverlayRenderer.cs @@ -16,32 +16,7 @@ namespace OpenRa.Game.Graphics "v12", "v13", "v14", "v15", "v16", "v17", "v18", "fpls", "wcrate", "scrate", "barb", "sbag", }; - static bool[] overlayIsFence = - { - true, true, true, true, true, - false, false, false, false, - false, false, false, false, - false, false, false, false, false, false, false, - false, false, false, true, true, - }; - - static bool[] overlayIsOre = - { - false, false, false, false, false, - true, true, true, true, - false, false, false, false, - false, false, false, false, false, false, false, - false, false, false, false, false, - }; - - static bool[] overlayIsGems = - { - false, false, false, false, false, - false, false, false, false, - true, true, true, true, - false, false, false, false, false, false, false, - false, false, false, false, false, - }; + Sprite[][] overlaySprites; Sprite[] smudgeSprites; @@ -82,9 +57,9 @@ namespace OpenRa.Game.Graphics var location = new int2(x, y); var sprites = overlaySprites[o]; var spriteIndex = 0; - if (overlayIsFence[o]) spriteIndex = NearbyFences(x, y); - else if (overlayIsOre[o]) spriteIndex = 11; - else if (overlayIsGems[o]) spriteIndex = 2; + if (Map.overlayIsFence[o]) spriteIndex = NearbyFences(x, y); + else if (Map.overlayIsOre[o]) spriteIndex = map.MapTiles[x,y].density; + else if (Map.overlayIsGems[o]) spriteIndex = map.MapTiles[x,y].density; spriteRenderer.DrawSprite(sprites[spriteIndex], Game.CellSize * (float2)location, 0); } @@ -96,8 +71,8 @@ namespace OpenRa.Game.Graphics bool IsFence( int x, int y ) { var o = map.MapTiles[ x, y ].overlay; - if( o < overlayIsFence.Length ) - return overlayIsFence[ o ]; + if (o < Map.overlayIsFence.Length) + return Map.overlayIsFence[o]; return false; }