diff options
| -rw-r--r-- | src/tools/extractor_common/ExtractorDB2LoadInfo.h | 39 | ||||
| -rw-r--r-- | src/tools/map_extractor/System.cpp | 162 | ||||
| -rw-r--r-- | src/tools/map_extractor/adt.h | 130 |
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 |
