diff --git a/OpenDiablo2.Common/Enums/eLevelId.cs b/OpenDiablo2.Common/Enums/eLevelId.cs index 94dcfd76..0bf2e59c 100644 --- a/OpenDiablo2.Common/Enums/eLevelId.cs +++ b/OpenDiablo2.Common/Enums/eLevelId.cs @@ -10,6 +10,9 @@ namespace OpenDiablo2.Common.Enums { None, Act1_Town = 1, + Act2_Town = 40, + Act2_Harem = 50, + Act3_Town = 75, Act4_Fortress = 103, Act5_Baal_Entrance = 120 } diff --git a/OpenDiablo2.Common/Interfaces/IGameState.cs b/OpenDiablo2.Common/Interfaces/IGameState.cs index 294bdeff..9556584c 100644 --- a/OpenDiablo2.Common/Interfaces/IGameState.cs +++ b/OpenDiablo2.Common/Interfaces/IGameState.cs @@ -12,6 +12,7 @@ namespace OpenDiablo2.Common.Interfaces { MPQDS1 MapData { get; } int Act { get; } + int Seed { get; } string MapName { get; } Palette CurrentPalette { get; } diff --git a/OpenDiablo2.Common/Interfaces/IRenderWindow.cs b/OpenDiablo2.Common/Interfaces/IRenderWindow.cs index 184ad56d..d7912df6 100644 --- a/OpenDiablo2.Common/Interfaces/IRenderWindow.cs +++ b/OpenDiablo2.Common/Interfaces/IRenderWindow.cs @@ -29,6 +29,6 @@ namespace OpenDiablo2.Common.Interfaces void Draw(ISprite sprite, int frame); void Draw(ISprite sprite, int xSegments, int ySegments, int offset); void Draw(ILabel label); - void DrawMapCell(int xCell, int yCell, int xPixel, int yPixel, MPQDS1 mapData, int main_index, int sub_index, Palette palette); + void DrawMapCell(int xCell, int yCell, int xPixel, int yPixel, MPQDS1 mapData, int main_index, int sub_index, Palette palette, MPQDS1WallOrientationTileProps orientation); } } diff --git a/OpenDiablo2.Common/Models/MPQDS1.cs b/OpenDiablo2.Common/Models/MPQDS1.cs index 081b379d..56c47879 100644 --- a/OpenDiablo2.Common/Models/MPQDS1.cs +++ b/OpenDiablo2.Common/Models/MPQDS1.cs @@ -58,6 +58,17 @@ namespace OpenDiablo2.Common.Models public Int32 Height { get; internal set; } } + public struct DS1LookupTable + { + public int Orientation; + public int MainIndex; + public int SubIndex; + public int Frame; + + public MPQDT1Tile TileRef; + + } + public sealed class MPQDS1 { static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); @@ -76,6 +87,7 @@ namespace OpenDiablo2.Common.Models public Int32 NumberOfGroups { get; internal set; } public MPQDT1[] DT1s = new MPQDT1[33]; + public List LookupTable { get; internal set; } public List FileNames { get; internal set; } = new List(); public MPQDS1WallLayer[] WallLayers { get; internal set; } @@ -230,7 +242,13 @@ namespace OpenDiablo2.Common.Models } else { - br.ReadBytes(4); + WallLayers[layoutStream[n] - 5].Orientations[x + (y * Width)] = new MPQDS1WallOrientationTileProps + { + Orientation1 = br.ReadByte(), + Orientation2 = br.ReadByte(), + Orientation3 = br.ReadByte(), + Orientation4 = br.ReadByte(), + }; } break; @@ -264,60 +282,6 @@ namespace OpenDiablo2.Common.Models } } } - /* - NumberOfObjects = 0; - if (Version >= 2) - { - - NumberOfObjects = br.ReadInt32(); - Objects = new MPQDS1Object[NumberOfObjects]; - - for (int i = 0; i < NumberOfObjects; i++) - { - Objects[i] = new MPQDS1Object - { - Type = br.ReadInt32(), - Id = br.ReadInt32(), - X = br.ReadInt32(), - Y = br.ReadInt32() - }; - - if (Version > 5) - Objects[i].DS1Flags = br.ReadInt32(); - - } - } - - - if (Version >= 12 && TagType == 1 || TagType == 2) - { - if (Version >= 18) - br.ReadBytes(4); - - NumberOfGroups = br.ReadInt32(); - } - else NumberOfGroups = 0; - - - Groups = new MPQDS1Group[NumberOfGroups]; - for (var x = 0; x < NumberOfGroups; x++) - { - Groups[x] = new MPQDS1Group - { - TileX = br.ReadInt32(), - TileY = br.ReadInt32(), - Width = br.ReadInt32(), - Height = br.ReadInt32(), - }; - if (Version >= 13) - br.ReadBytes(4); - } - - if (Version >= 14) - { - - NumberOfNPCs = br.ReadInt32(); - }*/ @@ -335,6 +299,24 @@ namespace OpenDiablo2.Common.Models DT1s[i] = resourceManager.GetMPQDT1("data\\global\\tiles\\" + levelType.File[i].Replace("/", "\\")); } + + LookupTable = new List(); + foreach(var dt1 in DT1s.Where(x => x != null)) + { + foreach(var tile in dt1.Tiles) + { + LookupTable.Add(new DS1LookupTable + { + MainIndex = tile.MainIndex, + Orientation = tile.Orientation, + SubIndex = tile.SubIndex, + Frame = tile.RarityOrFrameIndex, + TileRef = tile + }); + } + } + + } } } diff --git a/OpenDiablo2.Core/GameState/GameState.cs b/OpenDiablo2.Core/GameState/GameState.cs index 3427489f..dd6db22a 100644 --- a/OpenDiablo2.Core/GameState/GameState.cs +++ b/OpenDiablo2.Core/GameState/GameState.cs @@ -23,6 +23,8 @@ namespace OpenDiablo2.Core.GameState_ public string MapName { get; private set; } public Palette CurrentPalette => paletteProvider.PaletteTable[$"ACT{Act}"]; + public int Seed { get; internal set; } + public GameState( ISceneManager sceneManager, IResourceManager resourceManager, @@ -36,10 +38,15 @@ namespace OpenDiablo2.Core.GameState_ this.paletteProvider = paletteProvider; this.getMapEngine = getMapEngine; this.engineDataManager = engineDataManager; + + } public void Initialize(string characterName, eHero hero) { + var random = new Random(); + Seed = random.Next(); + sceneManager.ChangeScene("Game"); ChangeMap(eLevelId.Act1_Town); } @@ -59,10 +66,10 @@ namespace OpenDiablo2.Core.GameState_ if (level.File5 != "0") mapNames.Add(level.File5); if (level.File6 != "0") mapNames.Add(level.File6); - var random = new Random(); + var random = new Random(Seed); var mapName = "data\\global\\tiles\\" + mapNames[random.Next(mapNames.Count())].Replace("/", "\\"); MapName = level.Name; - Act = Convert.ToInt32(mapNames.First().Substring(3, 1)); + Act = levelType.Act; MapData = resourceManager.GetMPQDS1(mapName, level, levelDetails, levelType); getMapEngine().NotifyMapChanged(); } diff --git a/OpenDiablo2.Core/Map Engine/MapEngine.cs b/OpenDiablo2.Core/Map Engine/MapEngine.cs index 39b1e2f6..80f5d480 100644 --- a/OpenDiablo2.Core/Map Engine/MapEngine.cs +++ b/OpenDiablo2.Core/Map Engine/MapEngine.cs @@ -57,36 +57,27 @@ namespace OpenDiablo2.Core.Map_Engine { PurgeAllMapData(); LoadNewMapData(); - CameraLocation = new PointF(gameState.MapData.Width / 2, gameState.MapData.Height / 2); + //CameraLocation = new PointF(gameState.MapData.Width / 2, gameState.MapData.Height / 2); } private void LoadNewMapData() { - /* - var cellsToLoad = gameState.MapData.Width * gameState.MapData.Height; - tempMapCell = new ISprite[cellsToLoad]; - for (var cell = 0; cell < cellsToLoad; cell++) - { - renderWindow.Clear(); - loadingSprite.Frame = (int)(loadingSprite.TotalFrames * ((float)cell / (float)cellsToLoad)); - renderWindow.Draw(loadingSprite); - renderWindow.Sync(); - - tempMapCell[cell] = renderWindow.GenerateMapCell( - gameState.MapData, - cell % gameState.MapData.Width, - cell / gameState.MapData.Width, - Common.Enums.eRenderCellType.Floor, - gameState.CurrentPalette - ); - } - */ - //CameraLocation = new Point(((gameState.MapData.Width * cellSizeX) / 2) - 400, ((gameState.MapData.Height * cellSizeY) / 2) - 300); } public void Render() { + // Lower Walls, Floors, and Shadows + + // Shadows of objects + + // Objects with OrderFlag = 1 + + // Upper Walls and objects with ORderFlag = 0 or 2 + + // Roofs + + for (int y = 0; y < gameState.MapData.Width; y++) for (int x = 0; x < gameState.MapData.Height; x++) { @@ -94,27 +85,63 @@ namespace OpenDiablo2.Core.Map_Engine var visualX = ((x - y) * (cellSizeX / 2)) - cOffX; var visualY = ((x + y) * (cellSizeY / 2)) - cOffY; - if (visualX < -160 || visualX > 800 || visualY < -80 || visualY > 600) + if (visualX < -160 || visualX > 800 || visualY < -120 || visualY > 650) continue; - var floorLayer = gameState.MapData.FloorLayers[0]; - var idx = x + (y * gameState.MapData.Width); - if (idx >= floorLayer.Props.Length) - break; - var floor = floorLayer.Props[idx]; + // Render the floor + foreach (var floorLayer in gameState.MapData.FloorLayers) + { + var idx = x + (y * gameState.MapData.Width); + if (idx >= floorLayer.Props.Length) + break; + var floor = floorLayer.Props[idx]; - if (floor.Prop1 == 0) - return; + if (floor.Prop1 == 0) + continue; - var sub_index = floor.Prop2; - var main_index = (floor.Prop3 >> 4) + ((floor.Prop4 & 0x03) << 4); + var sub_index = floor.Prop2; + var main_index = (floor.Prop3 >> 4) + ((floor.Prop4 & 0x03) << 4); - if (x < 0 || y < 0 || x >= gameState.MapData.Width || y >= gameState.MapData.Height) - continue; + renderWindow.DrawMapCell(x, y, ((x - y) * 80) - cOffX, ((x + y) * 40) - cOffY, gameState.MapData, main_index, sub_index, gameState.CurrentPalette, null); + } - renderWindow.DrawMapCell(x, y, ((x - y) * 80) - cOffX, ((x + y) * 40) - cOffY, gameState.MapData, main_index, sub_index, gameState.CurrentPalette); } + /* + + // Render the walls + foreach (var wallLayer in gameState.MapData.WallLayers) + { + + for (int y = 0; y < gameState.MapData.Width; y++) + for (int x = 0; x < gameState.MapData.Height; x++) + { + + var visualX = ((x - y) * (cellSizeX / 2)) - cOffX; + var visualY = ((x + y) * (cellSizeY / 2)) - cOffY; + + if (visualX < -160 || visualX > 800 || visualY < -120 || visualY > 650) + continue; + + var idx = x + (y * gameState.MapData.Width); + if (idx >= wallLayer.Props.Length) + continue; + var wall = wallLayer.Props[idx]; + + if (wall.Prop1 == 0) + continue; + + var sub_index = wall.Prop2; + var main_index = (wall.Prop3 >> 4) + ((wall.Prop4 & 0x03) << 4); + + var orientation = wallLayer.Orientations[x + (y * gameState.MapData.Width)]; + renderWindow.DrawMapCell(x, y, ((x - y) * 80) - cOffX, ((x + y) * 40) - cOffY + 80, gameState.MapData, main_index, sub_index, gameState.CurrentPalette, orientation); + + } + + } + */ + } public void Update(long ms) diff --git a/OpenDiablo2.SDL2/SDL2RenderWindow.cs b/OpenDiablo2.SDL2/SDL2RenderWindow.cs index 266a6710..36b5b075 100644 --- a/OpenDiablo2.SDL2/SDL2RenderWindow.cs +++ b/OpenDiablo2.SDL2/SDL2RenderWindow.cs @@ -32,18 +32,21 @@ namespace OpenDiablo2.SDL2_ private readonly IMPQProvider mpqProvider; private readonly IPaletteProvider paletteProvider; private readonly IResourceManager resourceManager; + private readonly IGameState gameState; private IntPtr cellTexture; public SDL2RenderWindow( IMPQProvider mpqProvider, IPaletteProvider paletteProvider, - IResourceManager resourceManager + IResourceManager resourceManager, + IGameState gameState ) { this.mpqProvider = mpqProvider; this.paletteProvider = paletteProvider; this.resourceManager = resourceManager; + this.gameState = gameState; SDL.SDL_Init(SDL.SDL_INIT_EVERYTHING); if (SDL.SDL_SetHint(SDL.SDL_HINT_RENDER_SCALE_QUALITY, "0") == SDL.SDL_bool.SDL_FALSE) @@ -61,7 +64,7 @@ namespace OpenDiablo2.SDL2_ SDL.SDL_SetRenderDrawBlendMode(renderer, SDL.SDL_BlendMode.SDL_BLENDMODE_BLEND); SDL.SDL_ShowCursor(0); - cellTexture = SDL.SDL_CreateTexture(renderer, SDL.SDL_PIXELFORMAT_ARGB8888, (int)SDL.SDL_TextureAccess.SDL_TEXTUREACCESS_STREAMING, 256, 256); + cellTexture = SDL.SDL_CreateTexture(renderer, SDL.SDL_PIXELFORMAT_ARGB8888, (int)SDL.SDL_TextureAccess.SDL_TEXTUREACCESS_STREAMING, 256, 1024); SDL.SDL_SetTextureBlendMode(cellTexture, SDL.SDL_BlendMode.SDL_BLENDMODE_BLEND); @@ -277,23 +280,34 @@ namespace OpenDiablo2.SDL2_ SDL.SDL_RenderCopy(renderer, lbl.texture, IntPtr.Zero, ref destRect); } - public unsafe void DrawMapCell(int xCell, int yCell, int xPixel, int yPixel, MPQDS1 mapData, int main_index, int sub_index, Palette palette) + public unsafe void DrawMapCell(int xCell, int yCell, int xPixel, int yPixel, MPQDS1 mapData, int main_index, int sub_index, Palette palette, MPQDS1WallOrientationTileProps orientation) { + var tiles = mapData.LookupTable.Where(x => + x.MainIndex == main_index && + x.SubIndex == sub_index && + (orientation == null || x.Orientation == orientation.Orientation1)).Select(x => x.TileRef); + + if (!tiles.Any()) + return; // TODO: Why does this happen.... + MPQDT1Tile tile = null; - for (int i = 0; i < mapData.DT1s.Count(); i++) + if (tiles.Count() > 0) { - if (mapData.DT1s[i] == null) - continue; - - tile = mapData.DT1s[i].Tiles.FirstOrDefault(z => z.MainIndex == main_index && z.SubIndex == sub_index); - if (tile != null) - break; - } - - if (tile == null) - throw new ApplicationException("Could not locate tile!"); - + var totalRarity = tiles.Sum(q => q.RarityOrFrameIndex); + var random = new Random(gameState.Seed + xCell + (mapData.Width * yCell)); + var x = random.Next(totalRarity); + var z = 0; + foreach(var t in tiles) + { + z += t.RarityOrFrameIndex; + if (x <= z) + { + tile = t; + break; + } + } + } else tile = tiles.First(); var frameSize = new Size(tile.Width, Math.Abs(tile.Height)); var srcRect = new SDL.SDL_Rect { x = 0, y = 0, w = frameSize.Width, h = frameSize.Height }; @@ -315,16 +329,20 @@ namespace OpenDiablo2.SDL2_ { var index = block.PositionX + ((block.PositionY) * pitchChange); var xx = 0; + var yy = 0; foreach (var colorIndex in block.PixelData) { try { + if (colorIndex == 0) + continue; var color = palette.Colors[colorIndex]; - + if ((color & 0xFFFFFF) > 0) data[index] = color; - } finally + } + finally { index++; xx++; @@ -333,6 +351,7 @@ namespace OpenDiablo2.SDL2_ index -= 32; index += pitchChange; xx = 0; + yy++; } } } @@ -343,8 +362,9 @@ namespace OpenDiablo2.SDL2_ SDL.SDL_UnlockTexture(cellTexture); } - - var dstRect = new SDL.SDL_Rect { x = xPixel, y = yPixel, w = frameSize.Width, h = frameSize.Height }; + SDL.SDL_SetRenderDrawBlendMode(renderer, SDL.SDL_BlendMode.SDL_BLENDMODE_BLEND); + SDL.SDL_SetTextureBlendMode(cellTexture, SDL.SDL_BlendMode.SDL_BLENDMODE_BLEND); + var dstRect = new SDL.SDL_Rect { x = xPixel, y = yPixel - tile.RoofHeight, w = frameSize.Width, h = frameSize.Height }; SDL.SDL_RenderCopy(renderer, cellTexture, ref srcRect, ref dstRect); }