aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/tools/extractor_common/ExtractorDB2LoadInfo.h39
-rw-r--r--src/tools/map_extractor/System.cpp162
-rw-r--r--src/tools/map_extractor/adt.h130
3 files changed, 250 insertions, 81 deletions
diff --git a/src/tools/extractor_common/ExtractorDB2LoadInfo.h b/src/tools/extractor_common/ExtractorDB2LoadInfo.h
index c088ac663ec..fccfc924205 100644
--- a/src/tools/extractor_common/ExtractorDB2LoadInfo.h
+++ b/src/tools/extractor_common/ExtractorDB2LoadInfo.h
@@ -70,6 +70,45 @@ struct GameobjectDisplayInfoLoadInfo
}
};
+struct LiquidMaterialLoadInfo
+{
+ static DB2FileLoadInfo const* Instance()
+ {
+ static DB2FieldMeta const fields[] =
+ {
+ { false, FT_INT, "ID" },
+ { true, FT_BYTE, "LVF" },
+ { true, FT_BYTE, "Flags" },
+ };
+ static char const* types = "bb";
+ static uint8 const arraySizes[2] = { 1, 1 };
+ static DB2Meta meta(-1, 2, 0x62BE0340, types, arraySizes, -1);
+ static DB2FileLoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, &meta);
+ return &loadInfo;
+ }
+};
+
+struct LiquidObjectLoadInfo
+{
+ static DB2FileLoadInfo const* Instance()
+ {
+ static DB2FieldMeta const fields[] =
+ {
+ { false, FT_INT, "ID" },
+ { false, FT_FLOAT, "FlowDirection" },
+ { false, FT_FLOAT, "FlowSpeed" },
+ { true, FT_SHORT, "LiquidTypeID" },
+ { false, FT_BYTE, "Fishable" },
+ { false, FT_BYTE, "Reflection" },
+ };
+ static char const* types = "ffhbb";
+ static uint8 const arraySizes[5] = { 1, 1, 1, 1, 1 };
+ static DB2Meta meta(-1, 5, 0xACC168A6, types, arraySizes, -1);
+ static DB2FileLoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, &meta);
+ return &loadInfo;
+ }
+};
+
struct LiquidTypeLoadInfo
{
static DB2FileLoadInfo const* Instance()
diff --git a/src/tools/map_extractor/System.cpp b/src/tools/map_extractor/System.cpp
index e108d1be20c..98644181e9a 100644
--- a/src/tools/map_extractor/System.cpp
+++ b/src/tools/map_extractor/System.cpp
@@ -45,8 +45,26 @@ typedef struct
uint32 id;
} map_id;
+struct LiquidMaterialEntry
+{
+ int8 LVF;
+};
+
+struct LiquidObjectEntry
+{
+ int16 LiquidTypeID;
+};
+
+struct LiquidTypeEntry
+{
+ uint8 SoundBank;
+ uint8 MaterialID;
+};
+
std::vector<map_id> map_ids;
-std::vector<uint16> LiqType;
+std::unordered_map<uint32, LiquidMaterialEntry> LiquidMaterials;
+std::unordered_map<uint32, LiquidObjectEntry> LiquidObjects;
+std::unordered_map<uint32, LiquidTypeEntry> LiquidTypes;
std::set<std::string> CameraFileNames;
boost::filesystem::path input_path;
boost::filesystem::path output_path;
@@ -246,7 +264,57 @@ void ReadMapDBC()
printf("Done! (" SZFMTD " maps loaded)\n", map_ids.size());
}
-void ReadLiquidTypeTableDBC()
+void ReadLiquidMaterialTable()
+{
+ printf("Read LiquidMaterial.db2 file...\n");
+
+ DB2CascFileSource source(CascStorage, "DBFilesClient\\LiquidMaterial.db2");
+ DB2FileLoader db2;
+ if (!db2.Load(&source, LiquidMaterialLoadInfo::Instance()))
+ {
+ printf("Fatal error: Invalid LiquidMaterial.db2 file format!\n");
+ exit(1);
+ }
+
+ for (uint32 x = 0; x < db2.GetRecordCount(); ++x)
+ {
+ DB2Record record = db2.GetRecord(x);
+ LiquidMaterialEntry& liquidType = LiquidMaterials[record.GetId()];
+ liquidType.LVF = record.GetUInt8("LVF");
+ }
+
+ for (uint32 x = 0; x < db2.GetRecordCopyCount(); ++x)
+ LiquidMaterials[db2.GetRecordCopy(x).NewRowId] = LiquidMaterials[db2.GetRecordCopy(x).SourceRowId];
+
+ printf("Done! (" SZFMTD " LiquidMaterials loaded)\n", LiquidMaterials.size());
+}
+
+void ReadLiquidObjectTable()
+{
+ printf("Read LiquidObject.db2 file...\n");
+
+ DB2CascFileSource source(CascStorage, "DBFilesClient\\LiquidObject.db2");
+ DB2FileLoader db2;
+ if (!db2.Load(&source, LiquidObjectLoadInfo::Instance()))
+ {
+ printf("Fatal error: Invalid LiquidObject.db2 file format!\n");
+ exit(1);
+ }
+
+ for (uint32 x = 0; x < db2.GetRecordCount(); ++x)
+ {
+ DB2Record record = db2.GetRecord(x);
+ LiquidObjectEntry& liquidType = LiquidObjects[record.GetId()];
+ liquidType.LiquidTypeID = record.GetUInt16("LiquidTypeID");
+ }
+
+ for (uint32 x = 0; x < db2.GetRecordCopyCount(); ++x)
+ LiquidObjects[db2.GetRecordCopy(x).NewRowId] = LiquidObjects[db2.GetRecordCopy(x).SourceRowId];
+
+ printf("Done! (" SZFMTD " LiquidObjects loaded)\n", LiquidObjects.size());
+}
+
+void ReadLiquidTypeTable()
{
printf("Read LiquidType.db2 file...\n");
@@ -258,18 +326,18 @@ void ReadLiquidTypeTableDBC()
exit(1);
}
- LiqType.resize(db2.GetMaxId() + 1, 0xFFFF);
-
for (uint32 x = 0; x < db2.GetRecordCount(); ++x)
{
DB2Record record = db2.GetRecord(x);
- LiqType[record.GetId()] = record.GetUInt8("SoundBank");
+ LiquidTypeEntry& liquidType = LiquidTypes[record.GetId()];
+ liquidType.SoundBank = record.GetUInt8("SoundBank");
+ liquidType.MaterialID = record.GetUInt8("MaterialID");
}
for (uint32 x = 0; x < db2.GetRecordCopyCount(); ++x)
- LiqType[db2.GetRecordCopy(x).NewRowId] = LiqType[db2.GetRecordCopy(x).SourceRowId];
+ LiquidTypes[db2.GetRecordCopy(x).NewRowId] = LiquidTypes[db2.GetRecordCopy(x).SourceRowId];
- printf("Done! (" SZFMTD " LiqTypes loaded)\n", LiqType.size());
+ printf("Done! (" SZFMTD " LiquidTypes loaded)\n", LiquidTypes.size());
}
bool ReadCinematicCameraDBC()
@@ -286,7 +354,7 @@ bool ReadCinematicCameraDBC()
// get camera file list from DB2
for (size_t i = 0; i < db2.GetRecordCount(); ++i)
- CameraFileNames.insert(Trinity::StringFormat("FILE%08X.xxx", db2.GetRecord(i).GetUInt32("ModelFileDataID")));
+ CameraFileNames.insert(Trinity::StringFormat("FILE%08X.xxx", db2.GetRecord(i).GetUInt32("FileDataID")));
printf("Done! (" SZFMTD " CinematicCameras loaded)\n", CameraFileNames.size());
return true;
@@ -393,6 +461,25 @@ uint8 holes[ADT_CELLS_PER_GRID][ADT_CELLS_PER_GRID][8];
int16 flight_box_max[3][3];
int16 flight_box_min[3][3];
+LiquidVertexFormatType adt_MH2O::GetLiquidVertexFormat(adt_liquid_instance const* liquidInstance) const
+{
+ if (liquidInstance->LiquidVertexFormat < 42)
+ return static_cast<LiquidVertexFormatType>(liquidInstance->LiquidVertexFormat);
+
+ if (liquidInstance->LiquidType == 2)
+ return LiquidVertexFormatType::Depth;
+
+ auto liquidType = LiquidTypes.find(liquidInstance->LiquidType);
+ if (liquidType != LiquidTypes.end())
+ {
+ auto liquidMaterial = LiquidMaterials.find(liquidType->second.MaterialID);
+ if (liquidMaterial != LiquidMaterials.end())
+ return static_cast<LiquidVertexFormatType>(liquidMaterial->second.LVF);
+ }
+
+ return static_cast<LiquidVertexFormatType>(-1);
+}
+
bool TransformToHighRes(uint16 lowResHoles, uint8 hiResHoles[8])
{
for (uint8 i = 0; i < 8; i++)
@@ -580,66 +667,59 @@ bool ConvertADT(std::string const& inputPath, std::string const& outputPath, int
if (FileChunk* chunk = adt.GetChunk("MH2O"))
{
adt_MH2O* h2o = chunk->As<adt_MH2O>();
- for (int i = 0; i < ADT_CELLS_PER_GRID; i++)
+ for (int32 i = 0; i < ADT_CELLS_PER_GRID; i++)
{
- for (int j = 0; j < ADT_CELLS_PER_GRID; j++)
+ for (int32 j = 0; j < ADT_CELLS_PER_GRID; j++)
{
- adt_liquid_header *h = h2o->getLiquidData(i, j);
+ adt_liquid_instance const* h = h2o->GetLiquidInstance(i, j);
if (!h)
continue;
- int count = 0;
- uint64 show = h2o->getLiquidShowMap(h);
- for (int y = 0; y < h->height; y++)
+ int32 count = 0;
+ uint64 existsMask = h2o->GetLiquidExistsBitmap(h);
+ for (int32 y = 0; y < h->Height; y++)
{
- int cy = i * ADT_CELL_SIZE + y + h->yOffset;
- for (int x = 0; x < h->width; x++)
+ int32 cy = i * ADT_CELL_SIZE + y + h->OffsetY;
+ for (int32 x = 0; x < h->Width; x++)
{
- int cx = j * ADT_CELL_SIZE + x + h->xOffset;
- if (show & 1)
+ int32 cx = j * ADT_CELL_SIZE + x + h->OffsetX;
+ if (existsMask & 1)
{
liquid_show[cy][cx] = true;
++count;
}
- show >>= 1;
+ existsMask >>= 1;
}
}
- liquid_entry[i][j] = h->liquidType;
- switch (LiqType[h->liquidType])
+ liquid_entry[i][j] = h->LiquidType;
+ switch (LiquidTypes.at(h->LiquidType).SoundBank)
{
case LIQUID_TYPE_WATER: liquid_flags[i][j] |= MAP_LIQUID_TYPE_WATER; break;
case LIQUID_TYPE_OCEAN: liquid_flags[i][j] |= MAP_LIQUID_TYPE_OCEAN; break;
case LIQUID_TYPE_MAGMA: liquid_flags[i][j] |= MAP_LIQUID_TYPE_MAGMA; break;
case LIQUID_TYPE_SLIME: liquid_flags[i][j] |= MAP_LIQUID_TYPE_SLIME; break;
default:
- printf("\nCan't find Liquid type %u for map %s\nchunk %d,%d\n", h->liquidType, inputPath.c_str(), i, j);
+ printf("\nCan't find Liquid type %u for map %s\nchunk %d,%d\n", h->LiquidType, inputPath.c_str(), i, j);
break;
}
- // Dark water detect
- if (LiqType[h->liquidType] == LIQUID_TYPE_OCEAN)
- {
- uint8* lm = h2o->getLiquidLightMap(h);
- if (!lm)
- liquid_flags[i][j] |= MAP_LIQUID_TYPE_DARK_WATER;
- }
if (!count && liquid_flags[i][j])
printf("Wrong liquid detect in MH2O chunk");
- float* height = h2o->getLiquidHeightMap(h);
- int pos = 0;
- for (int y = 0; y <= h->height; y++)
+ int32 pos = 0;
+ for (int32 y = 0; y <= h->Height; y++)
{
- int cy = i * ADT_CELL_SIZE + y + h->yOffset;
- for (int x = 0; x <= h->width; x++)
+ int32 cy = i * ADT_CELL_SIZE + y + h->OffsetY;
+ for (int32 x = 0; x <= h->Width; x++)
{
- int cx = j * ADT_CELL_SIZE + x + h->xOffset;
+ int32 cx = j * ADT_CELL_SIZE + x + h->OffsetX;
+
+ liquid_height[cy][cx] = h2o->GetLiquidHeight(h, pos);
- if (height)
- liquid_height[cy][cx] = height[pos];
- else
- liquid_height[cy][cx] = h->heightLevel1;
+ // Dark water detect
+ if (liquid_flags[i][j] & MAP_LIQUID_TYPE_OCEAN && h2o->GetLiquidDepth(h, pos) == -1)
+ liquid_flags[i][j] |= MAP_LIQUID_TYPE_DARK_WATER;
pos++;
}
@@ -965,7 +1045,9 @@ void ExtractMaps(uint32 build)
ReadMapDBC();
- ReadLiquidTypeTableDBC();
+ ReadLiquidMaterialTable();
+ ReadLiquidObjectTable();
+ ReadLiquidTypeTable();
CreateDir(output_path / "maps");
diff --git a/src/tools/map_extractor/adt.h b/src/tools/map_extractor/adt.h
index fa92062cd0f..ca0082349d4 100644
--- a/src/tools/map_extractor/adt.h
+++ b/src/tools/map_extractor/adt.h
@@ -136,18 +136,28 @@ struct adt_MCNK
#define ADT_LIQUID_HEADER_FULL_LIGHT 0x01
#define ADT_LIQUID_HEADER_NO_HIGHT 0x02
-struct adt_liquid_header
+enum class LiquidVertexFormatType : uint16
{
- uint16 liquidType; // Index from LiquidType.dbc
- uint16 formatFlags;
- float heightLevel1;
- float heightLevel2;
- uint8 xOffset;
- uint8 yOffset;
- uint8 width;
- uint8 height;
- uint32 offsData2a;
- uint32 offsData2b;
+ HeightDepth = 0,
+ HeightTextureCoord = 1,
+ Depth = 2,
+ HeightDepthTextureCoord = 3,
+ Unk4 = 4,
+ Unk5 = 5
+};
+
+struct adt_liquid_instance
+{
+ uint16 LiquidType; // Index from LiquidType.db2
+ uint16 LiquidVertexFormat; // Id from LiquidObject.db2 if >= 42
+ float MinHeightLevel;
+ float MaxHeightLevel;
+ uint8 OffsetX;
+ uint8 OffsetY;
+ uint8 Width;
+ uint8 Height;
+ uint32 OffsetExistsBitmap;
+ uint32 OffsetVertexData;
};
//
@@ -162,61 +172,99 @@ struct adt_MH2O
uint32 size;
struct adt_LIQUID{
- uint32 offsData1;
+ uint32 OffsetInstances;
uint32 used;
- uint32 offsData2;
+ uint32 OffsetAttributes;
} liquid[ADT_CELLS_PER_GRID][ADT_CELLS_PER_GRID];
- adt_liquid_header *getLiquidData(int x, int y)
+ adt_liquid_instance const* GetLiquidInstance(int32 x, int32 y) const
{
- if (liquid[x][y].used && liquid[x][y].offsData1)
- return (adt_liquid_header *)((uint8*)this + 8 + liquid[x][y].offsData1);
- return 0;
+ if (liquid[x][y].used && liquid[x][y].OffsetInstances)
+ return (adt_liquid_instance *)((uint8*)this + 8 + liquid[x][y].OffsetInstances);
+ return nullptr;
}
- float *getLiquidHeightMap(adt_liquid_header *h)
+ float GetLiquidHeight(adt_liquid_instance const* h, int32 pos) const
{
- if (h->formatFlags & ADT_LIQUID_HEADER_NO_HIGHT)
- return 0;
- if (h->offsData2b)
- return (float *)((uint8*)this + 8 + h->offsData2b);
- return 0;
+ if (!h->OffsetVertexData)
+ return 0.0f;
+ if (GetLiquidVertexFormat(h) == LiquidVertexFormatType::Depth)
+ return 0.0f;
+
+ switch (GetLiquidVertexFormat(h))
+ {
+ case LiquidVertexFormatType::HeightDepth:
+ case LiquidVertexFormatType::HeightTextureCoord:
+ case LiquidVertexFormatType::HeightDepthTextureCoord:
+ return ((float const*)((uint8*)this + 8 + h->OffsetVertexData))[pos];
+ case LiquidVertexFormatType::Depth:
+ return 0.0f;
+ case LiquidVertexFormatType::Unk4:
+ case LiquidVertexFormatType::Unk5:
+ return ((float const*)((uint8*)this + 8 + h->OffsetVertexData + 4))[pos * 2];
+ default:
+ break;
+ }
+
+ return 0.0f;
}
- uint8 *getLiquidLightMap(adt_liquid_header *h)
+ int8 GetLiquidDepth(adt_liquid_instance const* h, int32 pos) const
{
- if (h->formatFlags&ADT_LIQUID_HEADER_FULL_LIGHT)
- return 0;
- if (h->offsData2b)
+ if (!h->OffsetVertexData)
+ return -1;
+
+ switch (GetLiquidVertexFormat(h))
{
- if (h->formatFlags & ADT_LIQUID_HEADER_NO_HIGHT)
- return (uint8 *)((uint8*)this + 8 + h->offsData2b);
- return (uint8 *)((uint8*)this + 8 + h->offsData2b + (h->width+1)*(h->height+1)*4);
+ case LiquidVertexFormatType::HeightDepth:
+ return ((int8 const*)((int8 const*)this + 8 + h->OffsetVertexData + (h->Width + 1) * (h->Height + 1) * 4))[pos];
+ case LiquidVertexFormatType::HeightTextureCoord:
+ return 0;
+ case LiquidVertexFormatType::Depth:
+ return ((int8 const*)((uint8*)this + 8 + h->OffsetVertexData))[pos];
+ case LiquidVertexFormatType::HeightDepthTextureCoord:
+ return ((int8 const*)((int8 const*)this + 8 + h->OffsetVertexData + (h->Width + 1) * (h->Height + 1) * 8))[pos];
+ case LiquidVertexFormatType::Unk4:
+ return ((int8 const*)((uint8*)this + 8 + h->OffsetVertexData))[pos * 8];
+ case LiquidVertexFormatType::Unk5:
+ return 0;
+ default:
+ break;
}
return 0;
}
- uint32 *getLiquidFullLightMap(adt_liquid_header *h)
+ uint16 const* GetLiquidTextureCoordMap(adt_liquid_instance const* h, int32 pos) const
{
- if (!(h->formatFlags&ADT_LIQUID_HEADER_FULL_LIGHT))
- return 0;
- if (h->offsData2b)
+ if (!h->OffsetVertexData)
+ return nullptr;
+
+ switch (GetLiquidVertexFormat(h))
{
- if (h->formatFlags & ADT_LIQUID_HEADER_NO_HIGHT)
- return (uint32 *)((uint8*)this + 8 + h->offsData2b);
- return (uint32 *)((uint8*)this + 8 + h->offsData2b + (h->width+1)*(h->height+1)*4);
+ case LiquidVertexFormatType::HeightDepth:
+ case LiquidVertexFormatType::Depth:
+ case LiquidVertexFormatType::Unk4:
+ return nullptr;
+ case LiquidVertexFormatType::HeightTextureCoord:
+ case LiquidVertexFormatType::HeightDepthTextureCoord:
+ return (uint16 const*)((uint8 const*)this + 8 + h->OffsetVertexData + 4 * ((h->Width + 1) * (h->Height + 1) + pos));
+ case LiquidVertexFormatType::Unk5:
+ return (uint16 const*)((uint8 const*)this + 8 + h->OffsetVertexData + 8 * ((h->Width + 1) * (h->Height + 1) + pos));
+ default:
+ break;
}
- return 0;
+ return nullptr;
}
- uint64 getLiquidShowMap(adt_liquid_header *h)
+ uint64 GetLiquidExistsBitmap(adt_liquid_instance const* h) const
{
- if (h->offsData2a)
- return *((uint64 *)((uint8*)this + 8 + h->offsData2a));
+ if (h->OffsetExistsBitmap)
+ return *((uint64 *)((uint8*)this + 8 + h->OffsetExistsBitmap));
else
return 0xFFFFFFFFFFFFFFFFuLL;
}
+ LiquidVertexFormatType GetLiquidVertexFormat(adt_liquid_instance const* liquidInstance) const;
};
struct adt_MFBO