2018-11-24 03:07:41 -05:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.IO;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
using OpenDiablo2.Common.Interfaces;
|
|
|
|
|
|
|
|
|
|
namespace OpenDiablo2.Common.Models
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
public sealed class MPQDS1TileProps
|
|
|
|
|
{
|
|
|
|
|
public byte Prop1 { get; internal set; }
|
|
|
|
|
public byte Prop2 { get; internal set; }
|
|
|
|
|
public byte Prop3 { get; internal set; }
|
|
|
|
|
public byte Prop4 { get; internal set; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public sealed class MPQDS1WallOrientationTileProps
|
|
|
|
|
{
|
|
|
|
|
public byte Orientation1 { get; internal set; }
|
|
|
|
|
public byte Orientation2 { get; internal set; }
|
|
|
|
|
public byte Orientation3 { get; internal set; }
|
|
|
|
|
public byte Orientation4 { get; internal set; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public sealed class MPQDS1WallLayer
|
|
|
|
|
{
|
|
|
|
|
public MPQDS1TileProps[] Props { get; internal set; }
|
|
|
|
|
public MPQDS1WallOrientationTileProps[] Orientations { get; internal set; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public sealed class MPQDS1FloorLayer
|
|
|
|
|
{
|
|
|
|
|
public MPQDS1TileProps[] Props { get; internal set; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public sealed class MPQDS1ShadowLayer
|
|
|
|
|
{
|
|
|
|
|
public MPQDS1TileProps[] Props { get; internal set; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public sealed class MPQDS1Object
|
|
|
|
|
{
|
2018-11-24 11:45:10 -05:00
|
|
|
|
public Int32 Type { get; internal set; }
|
|
|
|
|
public Int32 Id { get; internal set; }
|
|
|
|
|
public Int32 X { get; internal set; }
|
|
|
|
|
public Int32 Y { get; internal set; }
|
|
|
|
|
public Int32 DS1Flags { get; internal set; }
|
2018-11-24 03:07:41 -05:00
|
|
|
|
}
|
|
|
|
|
|
2018-11-24 17:54:15 -05:00
|
|
|
|
public sealed class MPQDS1Group
|
|
|
|
|
{
|
|
|
|
|
public Int32 TileX { get; internal set; }
|
|
|
|
|
public Int32 TileY { get; internal set; }
|
|
|
|
|
public Int32 Width { get; internal set; }
|
|
|
|
|
public Int32 Height { get; internal set; }
|
|
|
|
|
}
|
|
|
|
|
|
2018-11-25 14:15:13 -05:00
|
|
|
|
public struct DS1LookupTable
|
|
|
|
|
{
|
|
|
|
|
public int Orientation;
|
|
|
|
|
public int MainIndex;
|
|
|
|
|
public int SubIndex;
|
|
|
|
|
public int Frame;
|
|
|
|
|
|
|
|
|
|
public MPQDT1Tile TileRef;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2018-11-24 03:07:41 -05:00
|
|
|
|
public sealed class MPQDS1
|
|
|
|
|
{
|
|
|
|
|
static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
|
|
|
|
|
2018-11-28 21:20:01 -05:00
|
|
|
|
public string MapFile { get; set; }
|
|
|
|
|
|
2018-11-24 11:45:10 -05:00
|
|
|
|
public Int32 Version { get; internal set; }
|
|
|
|
|
public Int32 Width { get; internal set; }
|
|
|
|
|
public Int32 Height { get; internal set; }
|
|
|
|
|
public Int32 Act { get; internal set; } // ???
|
|
|
|
|
public Int32 TagType { get; internal set; } // ???
|
|
|
|
|
public Int32 FileCount { get; internal set; }
|
|
|
|
|
public Int32 NumberOfWalls { get; internal set; }
|
|
|
|
|
public Int32 NumberOfFloors { get; internal set; }
|
|
|
|
|
public Int32 NumberOfObjects { get; internal set; }
|
|
|
|
|
public Int32 NumberOfNPCs { get; internal set; }
|
2018-11-24 17:54:15 -05:00
|
|
|
|
public Int32 NumberOfTags { get; internal set; }
|
|
|
|
|
public Int32 NumberOfGroups { get; internal set; }
|
|
|
|
|
|
|
|
|
|
public MPQDT1[] DT1s = new MPQDT1[33];
|
2018-11-25 14:15:13 -05:00
|
|
|
|
public List<DS1LookupTable> LookupTable { get; internal set; }
|
2018-11-24 03:07:41 -05:00
|
|
|
|
|
|
|
|
|
public List<string> FileNames { get; internal set; } = new List<string>();
|
2018-11-24 17:54:15 -05:00
|
|
|
|
public MPQDS1WallLayer[] WallLayers { get; internal set; }
|
|
|
|
|
public MPQDS1FloorLayer[] FloorLayers { get; internal set; }
|
|
|
|
|
public MPQDS1ShadowLayer[] ShadowLayers { get; internal set; }
|
|
|
|
|
public MPQDS1Object[] Objects { get; internal set; }
|
|
|
|
|
public MPQDS1Group[] Groups { get; internal set; }
|
2018-11-24 03:07:41 -05:00
|
|
|
|
|
|
|
|
|
// TODO: DI magic please
|
2018-11-25 01:51:21 -05:00
|
|
|
|
public MPQDS1(Stream stream, LevelPreset level, LevelDetail levelDetail, LevelType levelType, IEngineDataManager engineDataManager, IResourceManager resourceManager)
|
2018-11-24 03:07:41 -05:00
|
|
|
|
{
|
|
|
|
|
var br = new BinaryReader(stream);
|
2018-11-24 11:45:10 -05:00
|
|
|
|
Version = br.ReadInt32();
|
|
|
|
|
Width = br.ReadInt32() + 1;
|
|
|
|
|
Height = br.ReadInt32() + 1;
|
2018-11-24 17:54:15 -05:00
|
|
|
|
Act = br.ReadInt32() + 1;
|
2018-11-24 03:07:41 -05:00
|
|
|
|
|
2018-11-24 17:54:15 -05:00
|
|
|
|
if (Version >= 10)
|
|
|
|
|
{
|
|
|
|
|
TagType = br.ReadInt32();
|
|
|
|
|
if (TagType == 1 || TagType == 2)
|
|
|
|
|
NumberOfTags = 1;
|
|
|
|
|
}
|
2018-11-24 03:07:41 -05:00
|
|
|
|
|
2018-11-24 17:54:15 -05:00
|
|
|
|
FileCount = 0;
|
|
|
|
|
if (Version >= 3)
|
|
|
|
|
{
|
|
|
|
|
FileCount = br.ReadInt32();
|
|
|
|
|
for (int i = 0; i < FileCount; i++)
|
|
|
|
|
{
|
|
|
|
|
var fn = "";
|
|
|
|
|
while (true)
|
|
|
|
|
{
|
|
|
|
|
var b = br.ReadByte();
|
|
|
|
|
if (b == 0)
|
|
|
|
|
break;
|
|
|
|
|
fn += (char)b;
|
|
|
|
|
}
|
|
|
|
|
if (fn.StartsWith("\\d2\\"))
|
|
|
|
|
fn = fn.Substring(4);
|
|
|
|
|
FileNames.Add(fn);
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-11-24 03:07:41 -05:00
|
|
|
|
|
2018-11-24 17:54:15 -05:00
|
|
|
|
if (Version >= 9 && Version <= 13)
|
|
|
|
|
{
|
|
|
|
|
br.ReadBytes(8);
|
|
|
|
|
}
|
2018-11-24 03:07:41 -05:00
|
|
|
|
|
2018-11-24 17:54:15 -05:00
|
|
|
|
if (Version >= 4)
|
2018-11-24 03:07:41 -05:00
|
|
|
|
{
|
2018-11-24 17:54:15 -05:00
|
|
|
|
NumberOfWalls = br.ReadInt32();
|
|
|
|
|
|
|
|
|
|
if (Version >= 16)
|
2018-11-24 03:07:41 -05:00
|
|
|
|
{
|
2018-11-24 17:54:15 -05:00
|
|
|
|
NumberOfFloors = br.ReadInt32();
|
2018-11-24 03:07:41 -05:00
|
|
|
|
}
|
2018-11-24 17:54:15 -05:00
|
|
|
|
else NumberOfFloors = 1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
NumberOfFloors = 1;
|
|
|
|
|
NumberOfWalls = 1;
|
|
|
|
|
NumberOfTags = 1;
|
2018-11-24 03:07:41 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2018-11-24 17:54:15 -05:00
|
|
|
|
|
|
|
|
|
var layoutStream = new List<int>();
|
|
|
|
|
|
|
|
|
|
if (Version < 4)
|
2018-11-24 03:07:41 -05:00
|
|
|
|
{
|
2018-11-24 17:54:15 -05:00
|
|
|
|
layoutStream.AddRange(new int[] { 1, 9, 5, 12, 11 });
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
for (var x = 0; x < NumberOfWalls; x++)
|
2018-11-24 03:07:41 -05:00
|
|
|
|
{
|
2018-11-24 17:54:15 -05:00
|
|
|
|
layoutStream.Add(1 + x);
|
|
|
|
|
layoutStream.Add(5 + x);
|
|
|
|
|
}
|
|
|
|
|
for (var x = 0; x < NumberOfFloors; x++)
|
|
|
|
|
layoutStream.Add(9 + x);
|
|
|
|
|
|
|
|
|
|
layoutStream.Add(11);
|
2018-11-24 03:07:41 -05:00
|
|
|
|
|
2018-11-24 17:54:15 -05:00
|
|
|
|
if (NumberOfTags > 0)
|
|
|
|
|
layoutStream.Add(12);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
WallLayers = new MPQDS1WallLayer[NumberOfWalls];
|
|
|
|
|
for (var l = 0; l < NumberOfWalls; l++)
|
|
|
|
|
{
|
|
|
|
|
WallLayers[l] = new MPQDS1WallLayer
|
2018-11-24 03:07:41 -05:00
|
|
|
|
{
|
2018-11-24 17:54:15 -05:00
|
|
|
|
Orientations = new MPQDS1WallOrientationTileProps[Width * Height],
|
|
|
|
|
Props = new MPQDS1TileProps[Width * Height]
|
|
|
|
|
};
|
|
|
|
|
}
|
2018-11-24 03:07:41 -05:00
|
|
|
|
|
2018-11-24 17:54:15 -05:00
|
|
|
|
FloorLayers = new MPQDS1FloorLayer[NumberOfFloors];
|
|
|
|
|
for (var l = 0; l < NumberOfFloors; l++)
|
|
|
|
|
{
|
|
|
|
|
FloorLayers[l] = new MPQDS1FloorLayer
|
2018-11-24 03:07:41 -05:00
|
|
|
|
{
|
2018-11-24 17:54:15 -05:00
|
|
|
|
Props = new MPQDS1TileProps[Width * Height]
|
|
|
|
|
};
|
2018-11-24 03:07:41 -05:00
|
|
|
|
}
|
|
|
|
|
|
2018-11-24 17:54:15 -05:00
|
|
|
|
ShadowLayers = new MPQDS1ShadowLayer[1];
|
|
|
|
|
for (var l = 0; l < 1; l++)
|
2018-11-24 03:07:41 -05:00
|
|
|
|
{
|
2018-11-24 17:54:15 -05:00
|
|
|
|
ShadowLayers[l] = new MPQDS1ShadowLayer
|
2018-11-24 03:07:41 -05:00
|
|
|
|
{
|
|
|
|
|
Props = new MPQDS1TileProps[Width * Height]
|
|
|
|
|
};
|
2018-11-24 17:54:15 -05:00
|
|
|
|
}
|
2018-11-24 03:07:41 -05:00
|
|
|
|
|
2018-11-24 17:54:15 -05:00
|
|
|
|
|
|
|
|
|
for (int n = 0; n < layoutStream.Count(); n++)
|
|
|
|
|
{
|
|
|
|
|
for (var y = 0; y < Height; y++)
|
2018-11-24 03:07:41 -05:00
|
|
|
|
{
|
2018-11-24 17:54:15 -05:00
|
|
|
|
for (var x = 0; x < Width; x++)
|
2018-11-24 03:07:41 -05:00
|
|
|
|
{
|
2018-11-24 17:54:15 -05:00
|
|
|
|
switch (layoutStream[n])
|
2018-11-24 03:07:41 -05:00
|
|
|
|
{
|
2018-11-24 17:54:15 -05:00
|
|
|
|
// Walls
|
|
|
|
|
case 1:
|
|
|
|
|
case 2:
|
|
|
|
|
case 3:
|
|
|
|
|
case 4:
|
|
|
|
|
WallLayers[layoutStream[n] - 1].Props[x + (y * Width)] = new MPQDS1TileProps
|
|
|
|
|
{
|
|
|
|
|
Prop1 = br.ReadByte(),
|
|
|
|
|
Prop2 = br.ReadByte(),
|
|
|
|
|
Prop3 = br.ReadByte(),
|
|
|
|
|
Prop4 = br.ReadByte()
|
|
|
|
|
};
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
// Orientations
|
|
|
|
|
case 5:
|
|
|
|
|
case 6:
|
|
|
|
|
case 7:
|
|
|
|
|
case 8:
|
|
|
|
|
// TODO: Orientations
|
|
|
|
|
if (Version < 7)
|
|
|
|
|
{
|
|
|
|
|
br.ReadBytes(4);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2018-11-25 14:15:13 -05:00
|
|
|
|
WallLayers[layoutStream[n] - 5].Orientations[x + (y * Width)] = new MPQDS1WallOrientationTileProps
|
|
|
|
|
{
|
|
|
|
|
Orientation1 = br.ReadByte(),
|
|
|
|
|
Orientation2 = br.ReadByte(),
|
|
|
|
|
Orientation3 = br.ReadByte(),
|
|
|
|
|
Orientation4 = br.ReadByte(),
|
|
|
|
|
};
|
2018-11-24 17:54:15 -05:00
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
// Floors
|
|
|
|
|
case 9:
|
|
|
|
|
case 10:
|
|
|
|
|
FloorLayers[layoutStream[n] - 9].Props[x + (y * Width)] = new MPQDS1TileProps
|
|
|
|
|
{
|
|
|
|
|
Prop1 = br.ReadByte(),
|
|
|
|
|
Prop2 = br.ReadByte(),
|
|
|
|
|
Prop3 = br.ReadByte(),
|
|
|
|
|
Prop4 = br.ReadByte()
|
|
|
|
|
};
|
|
|
|
|
break;
|
|
|
|
|
// Shadow
|
|
|
|
|
case 11:
|
|
|
|
|
ShadowLayers[layoutStream[n] - 11].Props[x + (y * Width)] = new MPQDS1TileProps
|
|
|
|
|
{
|
|
|
|
|
Prop1 = br.ReadByte(),
|
|
|
|
|
Prop2 = br.ReadByte(),
|
|
|
|
|
Prop3 = br.ReadByte(),
|
|
|
|
|
Prop4 = br.ReadByte()
|
|
|
|
|
};
|
|
|
|
|
break;
|
|
|
|
|
// Tags
|
|
|
|
|
case 12:
|
|
|
|
|
// TODO: Tags
|
|
|
|
|
br.ReadBytes(4);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2018-11-24 03:07:41 -05:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-11-24 18:54:32 -05:00
|
|
|
|
|
2018-11-24 03:07:41 -05:00
|
|
|
|
|
2018-11-24 17:54:15 -05:00
|
|
|
|
|
2018-11-25 01:51:21 -05:00
|
|
|
|
var dt1Mask = level.Dt1Mask;
|
2018-11-24 03:07:41 -05:00
|
|
|
|
for (int i = 0; i < 32; i++)
|
|
|
|
|
{
|
|
|
|
|
var tilePath = levelType.File[i];
|
|
|
|
|
var isMasked = ((dt1Mask >> i) & 1) == 1;
|
2018-11-28 19:28:41 -05:00
|
|
|
|
if (!isMasked || levelType.File[i] == "0")
|
2018-11-24 03:07:41 -05:00
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
DT1s[i] = resourceManager.GetMPQDT1("data\\global\\tiles\\" + levelType.File[i].Replace("/", "\\"));
|
2018-11-24 18:54:32 -05:00
|
|
|
|
|
2018-11-24 03:07:41 -05:00
|
|
|
|
}
|
2018-11-25 14:15:13 -05:00
|
|
|
|
|
|
|
|
|
LookupTable = new List<DS1LookupTable>();
|
|
|
|
|
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
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2018-11-24 03:07:41 -05:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|