diff --git a/OpenDiablo2.Common/Enums/eLevelId.cs b/OpenDiablo2.Common/Enums/eLevelId.cs new file mode 100644 index 00000000..94dcfd76 --- /dev/null +++ b/OpenDiablo2.Common/Enums/eLevelId.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace OpenDiablo2.Common.Enums +{ + public enum eLevelId + { + None, + Act1_Town = 1, + Act4_Fortress = 103, + Act5_Baal_Entrance = 120 + } +} diff --git a/OpenDiablo2.Common/Interfaces/IEngineDataManager.cs b/OpenDiablo2.Common/Interfaces/IEngineDataManager.cs index 9c9f2c5d..83f879ce 100644 --- a/OpenDiablo2.Common/Interfaces/IEngineDataManager.cs +++ b/OpenDiablo2.Common/Interfaces/IEngineDataManager.cs @@ -11,5 +11,6 @@ namespace OpenDiablo2.Common.Interfaces { List LevelPresets { get; } List LevelTypes { get; } + List LevelDetails { get; } } } diff --git a/OpenDiablo2.Common/Interfaces/IResourceManager.cs b/OpenDiablo2.Common/Interfaces/IResourceManager.cs index 5343f34e..81c7a68e 100644 --- a/OpenDiablo2.Common/Interfaces/IResourceManager.cs +++ b/OpenDiablo2.Common/Interfaces/IResourceManager.cs @@ -11,7 +11,7 @@ namespace OpenDiablo2.Common.Interfaces { ImageSet GetImageSet(string resourcePath); MPQFont GetMPQFont(string resourcePath); - MPQDS1 GetMPQDS1(string resourcePath, int definition, int act); + MPQDS1 GetMPQDS1(string resourcePath, LevelPreset level, LevelDetail levelDetail, LevelType levelType); MPQDT1 GetMPQDT1(string resourcePath); Palette GetPalette(string paletteName); } diff --git a/OpenDiablo2.Common/Models/LevelDetail.cs b/OpenDiablo2.Common/Models/LevelDetail.cs new file mode 100644 index 00000000..af41359e --- /dev/null +++ b/OpenDiablo2.Common/Models/LevelDetail.cs @@ -0,0 +1,180 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace OpenDiablo2.Common.Models +{ + public sealed class LevelDetail + { + public string Name { get; set; } + public int Id { get; set; } + public int Pal { get; set; } + public int Act { get; set; } + public int Layer { get; set; } + public int SizeX { get; set; } + public int SizeY { get; set; } + public int OffsetX { get; set; } + public int OffsetY { get; set; } + public int Depend { get; set; } + public int Rain { get; set; } + public int Mud { get; set; } + public int NoPer { get; set; } + public int LOSDraw { get; set; } + public int FloorFilter { get; set; } + public int BlankScreen { get; set; } + public int DrawEdges { get; set; } + public int IsInside { get; set; } + public int DrlgType { get; set; } + public int LevelType { get; set; } + public int SubType { get; set; } + public int SubTheme { get; set; } + public int SubWaypoint { get; set; } + public int SubShrine { get; set; } + public int Vis0 { get; set; } + public int Vis1 { get; set; } + public int Vis2 { get; set; } + public int Vis3 { get; set; } + public int Vis4 { get; set; } + public int Vis5 { get; set; } + public int Vis6 { get; set; } + public int Vis7 { get; set; } + public int Warp0 { get; set; } + public int Warp1 { get; set; } + public int Warp2 { get; set; } + public int Warp3 { get; set; } + public int Warp4 { get; set; } + public int Warp5 { get; set; } + public int Warp6 { get; set; } + public int Warp7 { get; set; } + public int Intensity { get; set; } + public int Red { get; set; } + public int Green { get; set; } + public int Blue { get; set; } + public int Portal { get; set; } + public int Position { get; set; } + public int SaveMonsters { get; set; } + public int Quest { get; set; } + public int WarpDist { get; set; } + public int MonLvl1 { get; set; } + public int MonLvl2 { get; set; } + public int MonLvl3 { get; set; } + public int MonDen { get; set; } + public int MonUMin { get; set; } + public int MonUMax { get; set; } + public int MonWndr { get; set; } + public int MonSpcWalk { get; set; } + public int Mtot { get; set; } + public int[] M1_25 { get; set; } + public int[] S1_25 { get; set; } + public int Utot { get; set; } + public int[] U1_25 { get; set; } + public int[] C1_5 { get; set; } + public int[] CA1_5 { get; set; } + public int[] CD1_5 { get; set; } + public int Themes { get; set; } + public int SoundEnv { get; set; } + public int Waypoint { get; set; } + public string LevelName { get; set; } + public string LevelWarp { get; set; } + public string EntryFile { get; set; } + public int[] ObjGrp0_7 { get; set; } + public int[] ObjPrb0_7 { get; set; } + public bool Beta { get; set; } + } + + public static class LevelDetailHelper + { + public static LevelDetail ToLevelDetail(this string[] v) + { + var result = new LevelDetail(); + int i = 0; + result.Name = v[i++]; + result.Id = Convert.ToInt32(v[i++]); + result.Pal = Convert.ToInt32(v[i++]); + result.Act = Convert.ToInt32(v[i++]); + result.Layer = Convert.ToInt32(v[i++]); + result.SizeX = Convert.ToInt32(v[i++]); + result.SizeY = Convert.ToInt32(v[i++]); + result.OffsetX = Convert.ToInt32(v[i++]); + result.OffsetY = Convert.ToInt32(v[i++]); + result.Depend = Convert.ToInt32(v[i++]); + result.Rain = Convert.ToInt32(v[i++]); + result.Mud = Convert.ToInt32(v[i++]); + result.NoPer = Convert.ToInt32(v[i++]); + result.LOSDraw = Convert.ToInt32(v[i++]); + result.FloorFilter = Convert.ToInt32(v[i++]); + result.BlankScreen = Convert.ToInt32(v[i++]); + result.DrawEdges = Convert.ToInt32(v[i++]); + result.IsInside = Convert.ToInt32(v[i++]); + result.DrlgType = Convert.ToInt32(v[i++]); + result.LevelType = Convert.ToInt32(v[i++]); + result.SubType = Convert.ToInt32(v[i++]); + result.SubTheme = Convert.ToInt32(v[i++]); + result.SubWaypoint = Convert.ToInt32(v[i++]); + result.SubShrine = Convert.ToInt32(v[i++]); + result.Vis0 = Convert.ToInt32(v[i++]); + result.Vis1 = Convert.ToInt32(v[i++]); + result.Vis2 = Convert.ToInt32(v[i++]); + result.Vis3 = Convert.ToInt32(v[i++]); + result.Vis4 = Convert.ToInt32(v[i++]); + result.Vis5 = Convert.ToInt32(v[i++]); + result.Vis6 = Convert.ToInt32(v[i++]); + result.Vis7 = Convert.ToInt32(v[i++]); + result.Warp0 = Convert.ToInt32(v[i++]); + result.Warp1 = Convert.ToInt32(v[i++]); + result.Warp2 = Convert.ToInt32(v[i++]); + result.Warp3 = Convert.ToInt32(v[i++]); + result.Warp4 = Convert.ToInt32(v[i++]); + result.Warp5 = Convert.ToInt32(v[i++]); + result.Warp6 = Convert.ToInt32(v[i++]); + result.Warp7 = Convert.ToInt32(v[i++]); + result.Intensity = Convert.ToInt32(v[i++]); + result.Red = Convert.ToInt32(v[i++]); + result.Green = Convert.ToInt32(v[i++]); + result.Blue = Convert.ToInt32(v[i++]); + result.Portal = Convert.ToInt32(v[i++]); + result.Position = Convert.ToInt32(v[i++]); + result.SaveMonsters = Convert.ToInt32(v[i++]); + result.Quest = Convert.ToInt32(v[i++]); + result.WarpDist = Convert.ToInt32(v[i++]); + result.MonLvl1 = Convert.ToInt32(v[i++]); + result.MonLvl2 = Convert.ToInt32(v[i++]); + result.MonLvl3 = Convert.ToInt32(v[i++]); + result.MonDen = Convert.ToInt32(v[i++]); + result.MonUMin = Convert.ToInt32(v[i++]); + result.MonUMax = Convert.ToInt32(v[i++]); + result.MonWndr = Convert.ToInt32(v[i++]); + result.MonSpcWalk = Convert.ToInt32(v[i++]); + result.Mtot = Convert.ToInt32(v[i++]); + result.M1_25 = new int[25]; + for (int j = 0; j < 25; j++) result.M1_25[j] = Convert.ToInt32(v[i++]); + result.S1_25 = new int[25]; + for (int j = 0; j < 25; j++) result.S1_25[j] = Convert.ToInt32(v[i++]); + result.Utot = Convert.ToInt32(v[i++]); + result.U1_25 = new int[25]; + for (int j = 0; j < 25; j++) result.U1_25[j] = Convert.ToInt32(v[i++]); + result.C1_5 = new int[5]; + for (int j = 0; j < 5; j++) result.C1_5[j] = Convert.ToInt32(v[i++]); + result.CA1_5 = new int[5]; + for (int j = 0; j < 5; j++) result.CA1_5[j] = Convert.ToInt32(v[i++]); + result.CD1_5 = new int[5]; + for (int j = 0; j < 5; j++) result.CD1_5[j] = Convert.ToInt32(v[i++]); + result.Themes = Convert.ToInt32(v[i++]); + result.SoundEnv = Convert.ToInt32(v[i++]); + result.Waypoint = Convert.ToInt32(v[i++]); + result.LevelName = v[i++]; + result.LevelWarp = v[i++]; + result.EntryFile = v[i++]; + result.ObjGrp0_7 = new int[8]; + for (int j = 0; j < 5; j++) result.ObjGrp0_7[j] = Convert.ToInt32(v[i++]); + result.ObjPrb0_7 = new int[8]; + for (int j = 0; j < 5; j++) result.ObjPrb0_7[j] = Convert.ToInt32(v[i++]); + result.Beta = Convert.ToInt32(v[i++]) == 1; + + + return result; + } + } +} diff --git a/OpenDiablo2.Common/Models/MPQDS1.cs b/OpenDiablo2.Common/Models/MPQDS1.cs index d3a99831..081b379d 100644 --- a/OpenDiablo2.Common/Models/MPQDS1.cs +++ b/OpenDiablo2.Common/Models/MPQDS1.cs @@ -85,9 +85,9 @@ namespace OpenDiablo2.Common.Models public MPQDS1Group[] Groups { get; internal set; } // TODO: DI magic please - public MPQDS1(Stream stream, string fileName, int definition, int act, IEngineDataManager engineDataManager, IResourceManager resourceManager) + public MPQDS1(Stream stream, LevelPreset level, LevelDetail levelDetail, LevelType levelType, IEngineDataManager engineDataManager, IResourceManager resourceManager) { - log.Debug($"Loading {fileName} (Act {act}) Def {definition}"); + log.Debug($"Loading {level.Name} (Act {levelDetail.Act})..."); var br = new BinaryReader(stream); Version = br.ReadInt32(); Width = br.ReadInt32() + 1; @@ -320,26 +320,9 @@ namespace OpenDiablo2.Common.Models }*/ - LevelPreset levelPreset; - if (definition == -1) - { - levelPreset = engineDataManager.LevelPresets.First(x => - x.File1.ToLower() == fileName.ToLower() - || x.File2.ToLower() == fileName.ToLower() - || x.File3.ToLower() == fileName.ToLower() - || x.File4.ToLower() == fileName.ToLower() - || x.File5.ToLower() == fileName.ToLower() - || x.File6.ToLower() == fileName.ToLower()); - } - else - { - levelPreset = engineDataManager.LevelPresets.First(x => x.Def == definition); - } - - var dt1Mask = levelPreset.Dt1Mask; - var levelType = engineDataManager.LevelTypes.First(x => x.Id == levelPreset.LevelId && x.Act == act); + var dt1Mask = level.Dt1Mask; for (int i = 0; i < 32; i++) { var tilePath = levelType.File[i]; diff --git a/OpenDiablo2.Common/OpenDiablo2.Common.csproj b/OpenDiablo2.Common/OpenDiablo2.Common.csproj index 598db43d..4b62b9e3 100644 --- a/OpenDiablo2.Common/OpenDiablo2.Common.csproj +++ b/OpenDiablo2.Common/OpenDiablo2.Common.csproj @@ -72,6 +72,7 @@ + @@ -95,6 +96,7 @@ + diff --git a/OpenDiablo2.Common/ResourcePaths.cs b/OpenDiablo2.Common/ResourcePaths.cs index b537e5aa..dbb8efdb 100644 --- a/OpenDiablo2.Common/ResourcePaths.cs +++ b/OpenDiablo2.Common/ResourcePaths.cs @@ -113,9 +113,8 @@ namespace OpenDiablo2.Common public static string ExpansionStringTable = "data\\local\\lng\\eng\\expansionstring.tbl"; public static string LevelPreset = "data\\global\\excel\\LvlPrest.txt"; public static string LevelType = "data\\global\\excel\\LvlTypes.txt"; + public static string LevelDetails = "data\\global\\excel\\Levels.txt"; - // --- Maps --- - public static string MapAct1TownE1 = "data\\global\\tiles\\ACT1\\Town\\townE1.ds1"; } } diff --git a/OpenDiablo2.Core/EngineDataManager.cs b/OpenDiablo2.Core/EngineDataManager.cs index 3340699e..c6bf1901 100644 --- a/OpenDiablo2.Core/EngineDataManager.cs +++ b/OpenDiablo2.Core/EngineDataManager.cs @@ -15,6 +15,7 @@ namespace OpenDiablo2.Core public List LevelPresets { get; internal set; } public List LevelTypes { get; internal set; } + public List LevelDetails { get; internal set; } public EngineDataManager(IMPQProvider mpqProvider) { @@ -22,6 +23,7 @@ namespace OpenDiablo2.Core LoadLevelPresets(); LoadLevelTypes(); + LoadLevelDetails(); } private void LoadLevelTypes() @@ -51,5 +53,19 @@ namespace OpenDiablo2.Core LevelPresets = new List(data); } + + private void LoadLevelDetails() + { + var data = mpqProvider + .GetTextFile(ResourcePaths.LevelDetails) + .Skip(1) + .Where(x => !String.IsNullOrWhiteSpace(x)) + .Select(x => x.Split('\t')) + .Where(x => x.Count() > 80 && x[0] != "Expansion") + .ToArray() + .Select(x => x.ToLevelDetail()); + + LevelDetails = new List(data); + } } } diff --git a/OpenDiablo2.Core/GameState/GameState.cs b/OpenDiablo2.Core/GameState/GameState.cs index 6e76fb75..671ca532 100644 --- a/OpenDiablo2.Core/GameState/GameState.cs +++ b/OpenDiablo2.Core/GameState/GameState.cs @@ -15,6 +15,7 @@ namespace OpenDiablo2.Core.GameState_ private readonly ISceneManager sceneManager; private readonly IResourceManager resourceManager; private readonly IPaletteProvider paletteProvider; + private readonly IEngineDataManager engineDataManager; private readonly Func getMapEngine; public MPQDS1 MapData { get; private set; } @@ -26,6 +27,7 @@ namespace OpenDiablo2.Core.GameState_ ISceneManager sceneManager, IResourceManager resourceManager, IPaletteProvider paletteProvider, + IEngineDataManager engineDataManager, Func getMapEngine ) { @@ -33,19 +35,35 @@ namespace OpenDiablo2.Core.GameState_ this.resourceManager = resourceManager; this.paletteProvider = paletteProvider; this.getMapEngine = getMapEngine; + this.engineDataManager = engineDataManager; } public void Initialize(string characterName, eHero hero) { sceneManager.ChangeScene("Game"); - ChangeMap(ResourcePaths.MapAct1TownE1, 1); + ChangeMap(eLevelId.Act5_Baal_Entrance); } - public void ChangeMap(string mapName, int act) + public void ChangeMap(eLevelId levelId) { - MapName = mapName; - Act = act; - MapData = resourceManager.GetMPQDS1(mapName, -1, act); + var level = engineDataManager.LevelPresets.First(x => x.LevelId == (int)levelId); + var levelDetails = engineDataManager.LevelDetails.First(x => x.Id == level.LevelId); + var levelType = engineDataManager.LevelTypes.First(x => x.Id == levelDetails.LevelType); + + + var mapNames = new List(); + if (level.File1 != "0") mapNames.Add(level.File1); + if (level.File2 != "0") mapNames.Add(level.File2); + if (level.File3 != "0") mapNames.Add(level.File3); + if (level.File4 != "0") mapNames.Add(level.File4); + if (level.File5 != "0") mapNames.Add(level.File5); + if (level.File6 != "0") mapNames.Add(level.File6); + + var random = new Random(); + var mapName = "data\\global\\tiles\\" + mapNames[random.Next(mapNames.Count())].Replace("/", "\\"); + MapName = level.Name; + Act = Convert.ToInt32(mapNames.First().ElementAt(3)); + 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 e9ee2e06..495d0e0b 100644 --- a/OpenDiablo2.Core/Map Engine/MapEngine.cs +++ b/OpenDiablo2.Core/Map Engine/MapEngine.cs @@ -25,16 +25,13 @@ namespace OpenDiablo2.Core.Map_Engine return; cameraLocation = value; - /* - cellOffsetX = CameraLocation.X / cellSizeX; - cellOffsetY = CameraLocation.Y / cellSizeY; - pixelOffsetX = CameraLocation.X % cellSizeX; - pixelOffsetY = CameraLocation.Y % cellSizeY; - */ + cOffX = (int)((cameraLocation.X - cameraLocation.Y) * (cellSizeX / 2)); + cOffY = (int)((cameraLocation.X + cameraLocation.Y) * (cellSizeY / 2)); } } private ISprite loadingSprite; + private int cOffX, cOffY; //private ISprite[] tempMapCell; private const int @@ -60,6 +57,7 @@ namespace OpenDiablo2.Core.Map_Engine { PurgeAllMapData(); LoadNewMapData(); + CameraLocation = new PointF(gameState.MapData.Width / 2, gameState.MapData.Height / 2); } private void LoadNewMapData() @@ -89,9 +87,6 @@ namespace OpenDiablo2.Core.Map_Engine public void Render() { - var cOffX = (int)((cameraLocation.X - cameraLocation.Y) * (cellSizeX / 2)); - var cOffY = (int)((cameraLocation.X + cameraLocation.Y) * (cellSizeY / 2)); - for (int y = 0; y < gameState.MapData.Width; y++) for (int x = 0; x < gameState.MapData.Height; x++) { diff --git a/OpenDiablo2.Core/ResourceManager.cs b/OpenDiablo2.Core/ResourceManager.cs index 7e401a4c..1eb650d9 100644 --- a/OpenDiablo2.Core/ResourceManager.cs +++ b/OpenDiablo2.Core/ResourceManager.cs @@ -40,10 +40,10 @@ namespace OpenDiablo2.Core return MPQFonts[resourcePath]; } - public MPQDS1 GetMPQDS1(string resourcePath, int definition, int act) + public MPQDS1 GetMPQDS1(string resourcePath, LevelPreset level, LevelDetail levelDetail, LevelType levelType) { var mapName = resourcePath.Replace("data\\global\\tiles\\", "").Replace("\\", "/"); - return new MPQDS1(mpqProvider.GetStream(resourcePath), mapName, definition, act, engineDataManager, this); + return new MPQDS1(mpqProvider.GetStream(resourcePath), level, levelDetail, levelType, engineDataManager, this); } public Palette GetPalette(string paletteFile) diff --git a/OpenDiablo2.Core/UI/Button.cs b/OpenDiablo2.Core/UI/Button.cs index 021bc622..71177c15 100644 --- a/OpenDiablo2.Core/UI/Button.cs +++ b/OpenDiablo2.Core/UI/Button.cs @@ -41,7 +41,7 @@ namespace OpenDiablo2.Core.UI private ILabel label; private bool pressed = false; private bool active = false; // When true, button is actively being focus pressed - private bool activeLock = false; // When true, something else is being pressed so ignore everything + private bool activeLock = false; // When true, we have locked the mouse from everything else private bool toggled = false; private Point labelOffset = new Point(); diff --git a/Screenshot2.png b/Screenshot2.png index c6c0a030..ae412a36 100644 Binary files a/Screenshot2.png and b/Screenshot2.png differ