diff --git a/OpenDiablo2.Common/Enums/eRenderCellType.cs b/OpenDiablo2.Common/Enums/eRenderCellType.cs index d8cc1640..9849af64 100644 --- a/OpenDiablo2.Common/Enums/eRenderCellType.cs +++ b/OpenDiablo2.Common/Enums/eRenderCellType.cs @@ -9,7 +9,7 @@ namespace OpenDiablo2.Common.Enums public enum eRenderCellType { Floor, - WallUpper, + WallNormal, WallLower, Roof, MAX diff --git a/OpenDiablo2.Common/Enums/eWildBorder.cs b/OpenDiablo2.Common/Enums/eWildBorder.cs index 855e4012..4e82c0bb 100644 --- a/OpenDiablo2.Common/Enums/eWildBorder.cs +++ b/OpenDiablo2.Common/Enums/eWildBorder.cs @@ -2,17 +2,19 @@ { public enum eWildBorder { - South, - West, - North, - East, - SouthWest, - NorthWest, - NorthEast, - SouthEast, - ClosedBoxTopRight, - ClosedBoxBottomRight, - ClosedBoxBottomLeft, - ClosedBoxTopLeft + South = 4, + West = 5, + North = 6, + East = 7, + SouthWest = 8, + NorthWest = 9, + NorthEast = 10, + SouthEast = 11, + ClosedBoxTopRight = 12, + ClosedBoxBottomRight = 13, + ClosedBoxBottomLeft = 14, + ClosedBoxTopLeft = 15, + RiverUpper = 26, + RiverLower = 27 } } diff --git a/OpenDiablo2.Common/Interfaces/IGameState.cs b/OpenDiablo2.Common/Interfaces/IGameState.cs index 50e98f12..d58143ea 100644 --- a/OpenDiablo2.Common/Interfaces/IGameState.cs +++ b/OpenDiablo2.Common/Interfaces/IGameState.cs @@ -26,6 +26,6 @@ namespace OpenDiablo2.Common.Interfaces IEnumerable GetMapCellInfo(int cellX, int cellY, eRenderCellType renderCellType); void UpdateMapCellInfo(int cellX, int cellY, eRenderCellType renderCellType, IEnumerable mapCellInfo); MapInfo LoadMap(eLevelId levelId, Point origin); - MapInfo LoadSubMap(int levelDefId, Point origin); + MapInfo LoadSubMap(int levelDefId, Point origin, MapInfo primaryMap, int subTile = -1); } } diff --git a/OpenDiablo2.Common/Models/MPQ.cs b/OpenDiablo2.Common/Models/MPQ.cs index 531731db..41145d97 100644 --- a/OpenDiablo2.Common/Models/MPQ.cs +++ b/OpenDiablo2.Common/Models/MPQ.cs @@ -120,6 +120,7 @@ namespace OpenDiablo2.Common.Models { this.Path = path; + // If you crash here, you may have Diablo2 open... can't do that :) fileStream = new FileStream(path, FileMode.Open); using (var br = new BinaryReader(fileStream, Encoding.Default, true)) diff --git a/OpenDiablo2.Core/GameEngine.cs b/OpenDiablo2.Core/GameEngine.cs index adc1b2f1..a1bcaa93 100644 --- a/OpenDiablo2.Core/GameEngine.cs +++ b/OpenDiablo2.Core/GameEngine.cs @@ -87,9 +87,9 @@ namespace OpenDiablo2.Core if (ms < 0) continue; - if (ms < 33) + if (ms < 40) { - Thread.Sleep(33 - (int)ms); + Thread.Sleep(40 - (int)ms); // Diablo 2 runs at 25FPS. } else { log.Info($"Full frame time used - {ms} milliseconds to frame"); diff --git a/OpenDiablo2.Core/GameState/GameState.cs b/OpenDiablo2.Core/GameState/GameState.cs index 313429d0..a1fa2460 100644 --- a/OpenDiablo2.Core/GameState/GameState.cs +++ b/OpenDiablo2.Core/GameState/GameState.cs @@ -115,7 +115,9 @@ namespace OpenDiablo2.Core.GameState_ new MapGenerator(this).Generate(); } - public MapInfo LoadSubMap(int levelDefId, Point origin) + + + public MapInfo LoadSubMap(int levelDefId, Point origin, MapInfo primaryMap, int subTile = -1) { var level = engineDataManager.LevelPresets.First(x => x.Def == levelDefId); var levelDetails = engineDataManager.LevelDetails.First(x => x.Id == level.LevelId); @@ -131,8 +133,8 @@ namespace OpenDiablo2.Core.GameState_ if (level.File6 != "0") mapNames.Add(level.File6); - var random = new Random(Seed); - var mapName = "data\\global\\tiles\\" + mapNames[random.Next(mapNames.Count)].Replace("/", "\\"); + var random = new Random(Seed + origin.X + origin.Y); + var mapName = "data\\global\\tiles\\" + mapNames[subTile == -1 ? random.Next(mapNames.Count) : subTile].Replace("/", "\\"); var fileData = resourceManager.GetMPQDS1(mapName, level, levelDetails, levelType); var result = new MapInfo @@ -142,6 +144,7 @@ namespace OpenDiablo2.Core.GameState_ LevelDetail = levelDetails, LevelType = levelType, FileData = fileData, + PrimaryMap = primaryMap, CellInfo = new Dictionary(), TileLocation = new Rectangle(origin, new Size(fileData.Width - 1, fileData.Height - 1)) }; @@ -168,12 +171,14 @@ namespace OpenDiablo2.Core.GameState_ var random = new Random(Seed); - var mapName = "data\\global\\tiles\\" + mapNames[random.Next(mapNames.Count)].Replace("/", "\\"); + //var mapName = "data\\global\\tiles\\" + mapNames[random.Next(mapNames.Count)].Replace("/", "\\"); + // TEMP FOR TESTING + var mapName = "data\\global\\tiles\\" + mapNames[0].Replace("/", "\\"); MapName = level.Name; Act = levelType.Act; var fileData = resourceManager.GetMPQDS1(mapName, level, levelDetails, levelType); - + var result = new MapInfo { LevelId = levelId, @@ -214,7 +219,7 @@ namespace OpenDiablo2.Core.GameState_ .Select(floorLayer => GetMapCellInfo(map, cellX, cellY, floorLayer.Props[idx], eRenderCellType.Floor, 0)) .Where(x => x != null); - case eRenderCellType.WallUpper: + case eRenderCellType.WallNormal: case eRenderCellType.WallLower: case eRenderCellType.Roof: return map.FileData.WallLayers @@ -281,38 +286,57 @@ namespace OpenDiablo2.Core.GameState_ var main_index = (props.Prop3 >> 4) + ((props.Prop4 & 0x03) << 4); var sub_index = props.Prop2; - switch(cellType) + if (orientation == 0) { - case eRenderCellType.Floor: - if (orientation != 0) - { - map.CellInfo[cellType][cellX + (cellY * map.FileData.Width)] = new MapCellInfo { Ignore = true }; - return null; - } - break; - case eRenderCellType.WallLower: - if (orientation != 0 && orientation <= 15) - { - map.CellInfo[cellType][cellX + (cellY * map.FileData.Width)] = new MapCellInfo { Ignore = true }; - return null; - } - break; - case eRenderCellType.WallUpper: - if (orientation >= 15) - { - map.CellInfo[cellType][cellX + (cellY * map.FileData.Width)] = new MapCellInfo { Ignore = true }; - return null; - } - break; - case eRenderCellType.Roof: - if (orientation != 15) - { - map.CellInfo[cellType][cellX + (cellY * map.FileData.Width)] = new MapCellInfo { Ignore = true }; - return null; - } - break; + // Floor + if (cellType != eRenderCellType.Floor) + { + map.CellInfo[cellType][cellX + (cellY * map.FileData.Width)] = new MapCellInfo { Ignore = true }; + return null; + } + } + else if (orientation == 10 || orientation == 11) + { + // Special tile + map.CellInfo[cellType][cellX + (cellY * map.FileData.Width)] = new MapCellInfo { Ignore = true }; + return null; + } + else if (orientation == 14) + { + // Walls (objects?) with precedent shadows + if (cellType != eRenderCellType.WallNormal) + { + map.CellInfo[cellType][cellX + (cellY * map.FileData.Width)] = new MapCellInfo { Ignore = true }; + return null; + } + } + else if (orientation < 15) + { + // Upper walls + if (cellType != eRenderCellType.WallNormal) + { + map.CellInfo[cellType][cellX + (cellY * map.FileData.Width)] = new MapCellInfo { Ignore = true }; + return null; + } + } + else if (orientation == 15) + { + // Roof + if (cellType != eRenderCellType.Roof) + { + map.CellInfo[cellType][cellX + (cellY * map.FileData.Width)] = new MapCellInfo { Ignore = true }; + return null; + } + } + else + { + // Lower Walls + if (cellType != eRenderCellType.WallLower) + { + map.CellInfo[cellType][cellX + (cellY * map.FileData.Width)] = new MapCellInfo { Ignore = true }; + return null; + } } - int frame = 0; var tiles = (map.PrimaryMap ?? map).FileData.LookupTable diff --git a/OpenDiablo2.Core/Map Engine/MapEngine.cs b/OpenDiablo2.Core/Map Engine/MapEngine.cs index 6020607e..0b3e77e3 100644 --- a/OpenDiablo2.Core/Map Engine/MapEngine.cs +++ b/OpenDiablo2.Core/Map Engine/MapEngine.cs @@ -122,13 +122,14 @@ namespace OpenDiablo2.Core.Map_Engine var oy = (cx + cy) * (cellSizeY / 2); - foreach (var cellInfo in gameState.GetMapCellInfo((int)ax, (int)ay, eRenderCellType.Floor)) - renderWindow.DrawMapCell(cellInfo, skewX + px + (int)ox + xOffset, skewY + py + (int)oy); - foreach (var cellInfo in gameState.GetMapCellInfo((int)ax, (int)ay, eRenderCellType.WallLower)) renderWindow.DrawMapCell(cellInfo, skewX + px + (int)ox + xOffset, skewY + py + (int)oy + 80); - foreach (var cellInfo in gameState.GetMapCellInfo((int)ax, (int)ay, eRenderCellType.WallUpper)) + foreach (var cellInfo in gameState.GetMapCellInfo((int)ax, (int)ay, eRenderCellType.Floor)) + renderWindow.DrawMapCell(cellInfo, skewX + px + (int)ox + xOffset, skewY + py + (int)oy); + + + foreach (var cellInfo in gameState.GetMapCellInfo((int)ax, (int)ay, eRenderCellType.WallNormal)) renderWindow.DrawMapCell(cellInfo, skewX + px + (int)ox + xOffset, skewY + py + (int)oy + 80); foreach (var character in characterRenderers.Where(x => Math.Truncate(x.LocationDetails.PlayerX) == ax && Math.Truncate(x.LocationDetails.PlayerY) == ay)) diff --git a/OpenDiablo2.Core/Map Engine/MapGenerator.cs b/OpenDiablo2.Core/Map Engine/MapGenerator.cs index 4dd20708..bb704789 100644 --- a/OpenDiablo2.Core/Map Engine/MapGenerator.cs +++ b/OpenDiablo2.Core/Map Engine/MapGenerator.cs @@ -16,57 +16,143 @@ namespace OpenDiablo2.Core.Map_Engine public void Generate() { - //var wildBorder = 5; // (4-15) - // TODO: Is there no data file that explicitly defines this?? - var townMap = gameState.LoadMap(eLevelId.Act1_Town1, new Point(0, 0)); + GenerateAct1Town(); + } + + private void GenerateAct1Town() + { + var townMap = gameState.LoadMap(eLevelId.Act1_Town1, new Point(0, 0)); + //var wildBorder = 5; // (4-15) - /* Rectangle bloodMooreRect; // 32-37 is grassy field? + bool westExit = false; + bool eastExit = false; + bool southExit = false; + bool northExit = false; if (townMap.FileData.MapFile.Contains("S1")) { var defId = 3; // Act 1 - Town 1 Transition S - var borderMap = gameState.LoadSubMap(defId, new Point(0, townMap.FileData.Height - 2)); + var borderMap = gameState.LoadSubMap(defId, new Point(0, townMap.FileData.Height - 2), townMap); borderMap.PrimaryMap = townMap; - var wilderness = gameState.LoadSubMap(wildBorder, new Point(26, townMap.FileData.Height + borderMap.FileData.Height - 2)); + var wilderness = gameState.LoadSubMap(defId, new Point(26, townMap.FileData.Height + borderMap.FileData.Height - 2), townMap); wilderness.PrimaryMap = townMap; - bloodMooreRect = new Rectangle(-40, townMap.FileData.Height + borderMap.FileData.Height, 120, 80); + bloodMooreRect = new Rectangle(-40, townMap.FileData.Height + borderMap.FileData.Height + 4, 120, 80); + southExit = true; } else if (townMap.FileData.MapFile.Contains("E1")) { var defId = 2; // Act 1 - Town 1 Transition E - var borderMap = gameState.LoadSubMap(defId, new Point(townMap.FileData.Width - 2, 0)); + var borderMap = gameState.LoadSubMap(defId, new Point(townMap.FileData.Width - 2, 0), townMap); borderMap.PrimaryMap = townMap; - bloodMooreRect = new Rectangle(townMap.FileData.Width + borderMap.FileData.Width, -40, 80, 120); + bloodMooreRect = new Rectangle(townMap.FileData.Width + borderMap.FileData.Width - 4, -40, 80, 120); + eastExit = true; } else if (townMap.FileData.MapFile.Contains("W1")) { + // West bloodMooreRect = new Rectangle(-120, 0, 120, townMap.FileData.Height); - } else // North + westExit = true; + } + else // North { - bloodMooreRect = new Rectangle(0, -120, townMap.FileData.Width, 120); + bloodMooreRect = new Rectangle(0, -120, townMap.FileData.Width - 8, 120); + northExit = true; } // Generate the Blood Moore? - for (var y = 0; y < bloodMooreRect.Height; y+= 8) + for (var y = 0; y < bloodMooreRect.Height; y += 8) { - for (var x = 0; x < bloodMooreRect.Width; x += 8) { - var tileIdx = 35; - var mapTile = gameState.LoadSubMap(tileIdx, new Point(bloodMooreRect.Left + x, bloodMooreRect.Top + y)); - mapTile.PrimaryMap = townMap; + var px = bloodMooreRect.Left + x; + var py = bloodMooreRect.Top + y; + + if ((x == 0) && (y == 0)) // North West + { + gameState.LoadSubMap((int)eWildBorder.NorthWest, new Point(px, py), townMap, 0); + } + else if ((x == bloodMooreRect.Width - 9) && (y == 0)) // North East + { + gameState.LoadSubMap((int)eWildBorder.NorthEast, new Point(px, py), townMap, 0); + } + else if ((x == bloodMooreRect.Width - 9) && (y == bloodMooreRect.Height - 9)) // South East + { + if (northExit) + { + gameState.LoadSubMap((int)eWildBorder.RiverUpper, new Point(bloodMooreRect.Left + x, bloodMooreRect.Top + y), townMap, 0); + } + else gameState.LoadSubMap((int)eWildBorder.SouthEast, new Point(px, py), townMap, 0); + } + else if ((x == 0) && (y == bloodMooreRect.Height - 9)) // South West + { + if (northExit) + { + gameState.LoadSubMap((int)eWildBorder.West, new Point(px, py), townMap, 0); + } + else gameState.LoadSubMap((int)eWildBorder.SouthWest, new Point(px, py), townMap, 0); + } + else if ((x == 0) && ((y % 8) == 0)) // West + { + if (westExit) + { + gameState.LoadSubMap((int)eWildBorder.RiverUpper, new Point(px, py), townMap, 3); + } + else if (eastExit) + { + // TODO: Transition to town + } + else gameState.LoadSubMap((int)eWildBorder.West, new Point(px, py), townMap, 0); + } + else if ((x == bloodMooreRect.Width - 9) && ((y % 8) == 0)) // East + { + if (westExit) + { + // TODO: Transition to town + } + if (northExit || eastExit) + { + gameState.LoadSubMap((int)eWildBorder.RiverUpper, new Point(px, py), townMap, 3); + } + else gameState.LoadSubMap((int)eWildBorder.East, new Point(px, py), townMap, 0); + } + else if (((x % 8) == 0) && (y == 0)) // North + { + if (southExit) + { + + } + else gameState.LoadSubMap((int)eWildBorder.North, new Point(px, py), townMap, 0); + } + else if (((x % 8) == 0) && (y == (bloodMooreRect.Height - 9))) // South + { + if (northExit) + { + //var tileIdx = 31; // 8x8 fill + //gameState.LoadSubMap(tileIdx, new Point(bloodMooreRect.Left + x, bloodMooreRect.Top + y), townMap); + } + else gameState.LoadSubMap((int)eWildBorder.South, new Point(px, py), townMap, 0); + } + else + { + if (((x % 8) == 0) && ((y % 8)) == 0) + { + var tileIdx = 31; // 8x8 fill + gameState.LoadSubMap(tileIdx, new Point(bloodMooreRect.Left + x, bloodMooreRect.Top + y), townMap, 0); + } + + } } } - */ + + } - } }