diff --git a/OpenDiablo2.Common/Interfaces/Drawing/IRenderWindow.cs b/OpenDiablo2.Common/Interfaces/Drawing/IRenderWindow.cs index 5d3fe613..90e8e670 100644 --- a/OpenDiablo2.Common/Interfaces/Drawing/IRenderWindow.cs +++ b/OpenDiablo2.Common/Interfaces/Drawing/IRenderWindow.cs @@ -1,5 +1,6 @@ using System; using System.Drawing; +using OpenDiablo2.Common.Enums; using OpenDiablo2.Common.Interfaces.Drawing; using OpenDiablo2.Common.Models; @@ -28,7 +29,7 @@ namespace OpenDiablo2.Common.Interfaces void Draw(ISprite sprite, int xSegments, int ySegments, int offset); IMouseCursor LoadCursor(ISprite sprite, int frame, Point hotspot); void Draw(ILabel label); - MapCellInfo CacheMapCell(MPQDT1Tile mapCell); + MapCellInfo CacheMapCell(MPQDT1Tile mapCell, eRenderCellType cellType); void DrawMapCell(MapCellInfo mapCellInfo, int xPixel, int yPixel); ICharacterRenderer CreateCharacterRenderer(); } diff --git a/OpenDiablo2.Common/Models/MapCellInfo.cs b/OpenDiablo2.Common/Models/MapCellInfo.cs index d36d9fb6..1c5f6d62 100644 --- a/OpenDiablo2.Common/Models/MapCellInfo.cs +++ b/OpenDiablo2.Common/Models/MapCellInfo.cs @@ -9,8 +9,6 @@ namespace OpenDiablo2.Common.Models { public bool Ignore { get; set; } = false; public int AnimationId { get; set; } - public int OffX { get; set; } - public int OffY { get; set; } public int FrameWidth { get; set; } public int FrameHeight { get; set; } public MPQDT1Tile Tile { get; set; } diff --git a/OpenDiablo2.Core/GameState/GameState.cs b/OpenDiablo2.Core/GameState/GameState.cs index 8d612fa6..c4e0667f 100644 --- a/OpenDiablo2.Core/GameState/GameState.cs +++ b/OpenDiablo2.Core/GameState/GameState.cs @@ -200,14 +200,14 @@ namespace OpenDiablo2.Core.GameState_ { case eRenderCellType.Floor: return map.FileData.FloorLayers - .Select(floorLayer => GetMapCellInfo(map, cellX, cellY, floorLayer.Props[idx], eRenderCellType.Floor)) + .Select(floorLayer => GetMapCellInfo(map, cellX, cellY, floorLayer.Props[idx], eRenderCellType.Floor, 0)) .Where(x => x != null); case eRenderCellType.WallUpper: case eRenderCellType.WallLower: case eRenderCellType.Roof: return map.FileData.WallLayers - .Select(wallLayer => GetMapCellInfo(map, cellX, cellY, wallLayer.Props[idx], renderCellType, wallLayer.Orientations[idx])) + .Select(wallLayer => GetMapCellInfo(map, cellX, cellY, wallLayer.Props[idx], renderCellType, wallLayer.Orientations[idx].Orientation1)) .Where(x => x != null); default: @@ -252,7 +252,7 @@ namespace OpenDiablo2.Core.GameState_ this.SelectedItem = item; } - private MapCellInfo GetMapCellInfo(MapInfo map, int cellX, int cellY, MPQDS1TileProps props, eRenderCellType cellType, MPQDS1WallOrientationTileProps wallOrientations = null) + private MapCellInfo GetMapCellInfo(MapInfo map, int cellX, int cellY, MPQDS1TileProps props, eRenderCellType cellType, byte orientation) { if (!map.CellInfo.ContainsKey(cellType)) { @@ -260,13 +260,12 @@ namespace OpenDiablo2.Core.GameState_ } var cellInfo = map.CellInfo[cellType][cellX + (cellY * map.FileData.Width)]; - if (cellInfo != null) + if (cellInfo != null && cellInfo?.Tile?.Animated != true) return cellInfo.Ignore ? null : cellInfo; var sub_index = props.Prop2; var main_index = (props.Prop3 >> 4) + ((props.Prop4 & 0x03) << 4); - var orientation = 0; // Floors can't have rotations, should we blow up here? if (cellType == eRenderCellType.Floor && props.Prop1 == 0) @@ -282,7 +281,7 @@ namespace OpenDiablo2.Core.GameState_ map.CellInfo[cellType][cellX + (cellY * map.FileData.Width)] = new MapCellInfo { Ignore = true }; return null; } - + if (props.Prop1 == 0) { map.CellInfo[cellType][cellX + (cellY * map.FileData.Width)] = new MapCellInfo { Ignore = true }; @@ -294,13 +293,10 @@ namespace OpenDiablo2.Core.GameState_ map.CellInfo[cellType][cellX + (cellY * map.FileData.Width)] = new MapCellInfo { Ignore = true }; return null; } - + } - if (cellType == eRenderCellType.WallUpper || cellType == eRenderCellType.WallLower) + else if (cellType == eRenderCellType.WallUpper || cellType == eRenderCellType.WallLower) { - orientation = wallOrientations.Orientation1; - - if (props.Prop1 == 0) { map.CellInfo[cellType][cellX + (cellY * map.FileData.Width)] = new MapCellInfo { Ignore = true }; @@ -374,6 +370,39 @@ namespace OpenDiablo2.Core.GameState_ else tile = tiles.First(); } + switch (cellType) + { + case eRenderCellType.Floor: + if (tile.Orientation != 0) + { + map.CellInfo[cellType][cellX + (cellY * map.FileData.Width)] = new MapCellInfo { Ignore = true }; + return null; + } + break; + case eRenderCellType.WallLower: + if (tile.Orientation < 1 || tile.Orientation == 10 || tile.Orientation == 11 || tile.Orientation == 13 || tile.Orientation > 14) + { + map.CellInfo[cellType][cellX + (cellY * map.FileData.Width)] = new MapCellInfo { Ignore = true }; + return null; + } + break; + case eRenderCellType.WallUpper: + if (tile.Orientation <= 15) + { + map.CellInfo[cellType][cellX + (cellY * map.FileData.Width)] = new MapCellInfo { Ignore = true }; + return null; + } + break; + case eRenderCellType.Roof: + if (tile.Orientation != 15) + { + map.CellInfo[cellType][cellX + (cellY * map.FileData.Width)] = new MapCellInfo { Ignore = true }; + return null; + } + break; + default: + break; + } // This WILL happen to you if (tile.Width == 0 || tile.Height == 0) { @@ -392,17 +421,8 @@ namespace OpenDiablo2.Core.GameState_ var mapCellInfo = mapDataLookup.FirstOrDefault(x => x.Tile.Id == tile.Id && x.AnimationId == frame); if (mapCellInfo == null) { - mapCellInfo = renderWindow.CacheMapCell(tile); + mapCellInfo = renderWindow.CacheMapCell(tile, cellType); mapDataLookup.Add(mapCellInfo); - - switch (cellType) - { - case eRenderCellType.WallUpper: - case eRenderCellType.WallLower: - mapCellInfo.OffY -= 80; - break; - } - } map.CellInfo[cellType][cellX + (cellY * map.FileData.Width)] = mapCellInfo; diff --git a/OpenDiablo2.Core/Map Engine/MapEngine.cs b/OpenDiablo2.Core/Map Engine/MapEngine.cs index 66a6cd24..41dbd4e0 100644 --- a/OpenDiablo2.Core/Map Engine/MapEngine.cs +++ b/OpenDiablo2.Core/Map Engine/MapEngine.cs @@ -28,8 +28,6 @@ namespace OpenDiablo2.Core.Map_Engine return; cameraLocation = value; - //cOffX = (int)((cameraLocation.X - cameraLocation.Y) * (cellSizeX / 2)); - //cOffY = (int)((cameraLocation.X + cameraLocation.Y) * (cellSizeY / 2)); } } @@ -102,6 +100,7 @@ namespace OpenDiablo2.Core.Map_Engine const int skewX = 400; const int skewY = 300; + public void Render() { var xOffset = gameState.CameraOffset; @@ -126,25 +125,12 @@ namespace OpenDiablo2.Core.Map_Engine foreach (var cellInfo in gameState.GetMapCellInfo((int)ax, (int)ay, eRenderCellType.Floor)) renderWindow.DrawMapCell(cellInfo, skewX + px + (int)ox + xOffset, skewY + py + (int)oy); - } - } - - for (int ty = -7; ty <= 9; ty++) - { - for (int tx = -8; tx <= 8; tx++) - { - var ax = tx + Math.Truncate(cameraLocation.X); - var ay = ty + Math.Truncate(cameraLocation.Y); - - var px = (tx - ty) * (cellSizeX / 2); - var py = (tx + ty) * (cellSizeY / 2); - - var ox = (cx - cy) * (cellSizeX / 2); - var oy = (cx + cy) * (cellSizeY / 2); - 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)) + 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)) { var ptx = character.LocationDetails.PlayerX - Math.Truncate(cameraLocation.X); @@ -156,11 +142,8 @@ namespace OpenDiablo2.Core.Map_Engine character.Render(skewX + (int)ppx + (int)ox + xOffset, skewY + (int)ppy + (int)oy); } - foreach (var cellInfo in gameState.GetMapCellInfo((int)ax, (int)ay, eRenderCellType.WallUpper)) - renderWindow.DrawMapCell(cellInfo, skewX + px + (int)ox + xOffset, skewY + py + (int)oy); - foreach (var cellInfo in gameState.GetMapCellInfo((int)ax, (int)ay, eRenderCellType.Roof)) - renderWindow.DrawMapCell(cellInfo, 320 + px + (int)ox + xOffset, 300 + py + (int)oy); + renderWindow.DrawMapCell(cellInfo, skewX + px + (int)ox + xOffset, skewY + py + (int)oy); } } diff --git a/OpenDiablo2.Core/Map Engine/MapGenerator.cs b/OpenDiablo2.Core/Map Engine/MapGenerator.cs index bff4241d..4dd20708 100644 --- a/OpenDiablo2.Core/Map Engine/MapGenerator.cs +++ b/OpenDiablo2.Core/Map Engine/MapGenerator.cs @@ -16,9 +16,11 @@ namespace OpenDiablo2.Core.Map_Engine public void Generate() { - var wildBorder = 5; // (4-15) + //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)); + + /* Rectangle bloodMooreRect; // 32-37 is grassy field? @@ -61,6 +63,7 @@ namespace OpenDiablo2.Core.Map_Engine mapTile.PrimaryMap = townMap; } } + */ } diff --git a/OpenDiablo2.Core/ResourceManager.cs b/OpenDiablo2.Core/ResourceManager.cs index 351a4028..3e079b10 100644 --- a/OpenDiablo2.Core/ResourceManager.cs +++ b/OpenDiablo2.Core/ResourceManager.cs @@ -25,6 +25,8 @@ namespace OpenDiablo2.Core { public sealed class ResourceManager : IResourceManager { + static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + private readonly ICache cache; private readonly IMPQProvider mpqProvider; private readonly IEngineDataManager engineDataManager; @@ -73,10 +75,14 @@ namespace OpenDiablo2.Core // TODO: We need to cache this... byte[] binaryData; - using (var stream = mpqProvider.GetStream(cofLayer.GetDCCPath(armorType))) + var streamPath = cofLayer.GetDCCPath(armorType); + using (var stream = mpqProvider.GetStream(streamPath)) { if (stream == null) + { + log.Error($"Could not load Player DCC: {streamPath}"); return null; + } binaryData = new byte[stream.Length]; stream.Read(binaryData, 0, (int)stream.Length); diff --git a/OpenDiablo2.SDL2/SDL2RenderWindow.cs b/OpenDiablo2.SDL2/SDL2RenderWindow.cs index 68219e62..be25b9b0 100644 --- a/OpenDiablo2.SDL2/SDL2RenderWindow.cs +++ b/OpenDiablo2.SDL2/SDL2RenderWindow.cs @@ -18,6 +18,7 @@ using System; using System.Drawing; using System.Linq; using System.Runtime.InteropServices; +using OpenDiablo2.Common.Enums; using OpenDiablo2.Common.Exceptions; using OpenDiablo2.Common.Interfaces; using OpenDiablo2.Common.Interfaces.Drawing; @@ -342,28 +343,33 @@ namespace OpenDiablo2.SDL2_ SDL.SDL_RenderCopy(renderer, lbl.texture, IntPtr.Zero, ref destRect); } - public unsafe MapCellInfo CacheMapCell(MPQDT1Tile mapCell) + public unsafe MapCellInfo CacheMapCell(MPQDT1Tile mapCell, eRenderCellType cellType) { var minX = mapCell.Blocks.Min(x => x.PositionX); var minY = mapCell.Blocks.Min(x => x.PositionY); var maxX = mapCell.Blocks.Max(x => x.PositionX + 32); var maxY = mapCell.Blocks.Max(x => x.PositionY + 32); - var diffX = maxX - minX; - var diffY = maxY - minY; + var frameWidth = maxX - minX; + var frameHeight = maxY - minY; - var offX = -minX; - var offY = -minY; + var dx = minX; + var dy = minY; - var frameSize = new Size(Math.Abs(diffX), Math.Abs(diffY)); + dx -= 80; - var srcRect = new SDL.SDL_Rect { x = minX, y = minY, w = frameSize.Width, h = frameSize.Height }; + + var srcRect = new SDL.SDL_Rect { x = dx, y = dy, w = frameWidth, h = frameHeight }; + + var texId = SDL.SDL_CreateTexture(renderer, SDL.SDL_PIXELFORMAT_ARGB8888, (int)SDL.SDL_TextureAccess.SDL_TEXTUREACCESS_STREAMING, frameWidth, frameHeight); + + if (texId == IntPtr.Zero) + throw new OpenDiablo2Exception("Could not create texture"); - var texId = SDL.SDL_CreateTexture(renderer, SDL.SDL_PIXELFORMAT_ARGB8888, (int)SDL.SDL_TextureAccess.SDL_TEXTUREACCESS_STREAMING, frameSize.Width, frameSize.Height); SDL.SDL_SetTextureBlendMode(texId, SDL.SDL_BlendMode.SDL_BLENDMODE_BLEND); if (SDL.SDL_LockTexture(texId, IntPtr.Zero, out IntPtr pixels, out int pitch) != 0) throw new OpenDiablo2Exception("Could not lock texture for map rendering"); - + try { UInt32* data = (UInt32*)pixels; @@ -373,15 +379,15 @@ namespace OpenDiablo2.SDL2_ foreach (var block in mapCell.Blocks) { - var index = block.PositionX + offX + ((block.PositionY + offY) * pitchChange); + var index = (block.PositionX - minX) + ((block.PositionY - minY) * pitchChange); var xx = 0; - var yy = 0; foreach (var colorIndex in block.PixelData) { try { if (colorIndex == 0) continue; + var color = colors[colorIndex]; if (color > 0) @@ -396,7 +402,6 @@ namespace OpenDiablo2.SDL2_ { index += pitchChange - 32; xx = 0; - yy++; } } } @@ -410,10 +415,8 @@ namespace OpenDiablo2.SDL2_ return new MapCellInfo { Tile = mapCell, - FrameHeight = frameSize.Height, - FrameWidth = frameSize.Width, - OffX = offX, - OffY = offY, + FrameHeight = frameHeight, + FrameWidth = frameWidth, Rect = srcRect.ToRectangle(), Texture = new SDL2Texture { Pointer = texId } };