mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-02-14 16:03:45 +00:00
feat(Tools/Mapextractor): Implemented liquid object detection (#11402)
* . * . * . * . * . * . * . * Delete Utils.cpp
This commit is contained in:
committed by
GitHub
parent
5036360c1e
commit
a31a30566e
@@ -22,6 +22,7 @@
|
||||
#include <deque>
|
||||
#include <filesystem>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "direct.h"
|
||||
@@ -62,8 +63,13 @@ typedef struct
|
||||
uint32 id;
|
||||
} map_id;
|
||||
|
||||
map_id* map_ids;
|
||||
uint16* LiqType;
|
||||
struct LiquidTypeEntry
|
||||
{
|
||||
uint8 SoundBank;
|
||||
};
|
||||
|
||||
std::vector<map_id> map_ids;
|
||||
std::unordered_map<uint32, LiquidTypeEntry> LiquidTypes;
|
||||
#define MAX_PATH_LENGTH 128
|
||||
char output_path[MAX_PATH_LENGTH] = ".";
|
||||
char input_path[MAX_PATH_LENGTH] = ".";
|
||||
@@ -271,7 +277,7 @@ uint32 ReadMapDBC()
|
||||
}
|
||||
|
||||
size_t map_count = dbc.getRecordCount();
|
||||
map_ids = new map_id[map_count];
|
||||
map_ids.resize(map_count);
|
||||
for (uint32 x = 0; x < map_count; ++x)
|
||||
{
|
||||
map_ids[x].id = dbc.getRecord(x).getUInt(0);
|
||||
@@ -291,15 +297,13 @@ void ReadLiquidTypeTableDBC()
|
||||
exit(1);
|
||||
}
|
||||
|
||||
size_t liqTypeCount = dbc.getRecordCount();
|
||||
size_t liqTypeMaxId = dbc.getMaxId();
|
||||
LiqType = new uint16[liqTypeMaxId + 1];
|
||||
memset(LiqType, 0xff, (liqTypeMaxId + 1) * sizeof(uint16));
|
||||
for (uint32 x = 0; x < dbc.getRecordCount(); ++x)
|
||||
{
|
||||
LiquidTypeEntry& liquidType = LiquidTypes[dbc.getRecord(x).getUInt(0)];
|
||||
liquidType.SoundBank = dbc.getRecord(x).getUInt(3);
|
||||
}
|
||||
|
||||
for (uint32 x = 0; x < liqTypeCount; ++x)
|
||||
LiqType[dbc.getRecord(x).getUInt(0)] = dbc.getRecord(x).getUInt(3);
|
||||
|
||||
printf("Done! (%u LiqTypes loaded)\n", (uint32)liqTypeCount);
|
||||
printf("Done! (%lu LiquidTypes loaded)\n", LiquidTypes.size());
|
||||
}
|
||||
|
||||
//
|
||||
@@ -357,7 +361,6 @@ struct map_heightHeader
|
||||
#define MAP_LIQUID_TYPE_SLIME 0x08
|
||||
|
||||
#define MAP_LIQUID_TYPE_DARK_WATER 0x10
|
||||
#define MAP_LIQUID_TYPE_WMO_WATER 0x20
|
||||
|
||||
#define MAP_LIQUID_NO_TYPE 0x0001
|
||||
#define MAP_LIQUID_NO_HEIGHT 0x0002
|
||||
@@ -365,7 +368,8 @@ struct map_heightHeader
|
||||
struct map_liquidHeader
|
||||
{
|
||||
uint32 fourcc;
|
||||
uint16 flags;
|
||||
uint8 flags;
|
||||
uint8 liquidFlags;
|
||||
uint16 liquidType;
|
||||
uint8 offsetX;
|
||||
uint8 offsetY;
|
||||
@@ -720,73 +724,57 @@ bool ConvertADT(std::string const& inputPath, std::string const& outputPath, int
|
||||
adt_MH2O* h2o = adt.a_grid->getMH2O();
|
||||
if (h2o)
|
||||
{
|
||||
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++)
|
||||
adt_liquid_attributes attrs = h2o->GetLiquidAttributes(i, j);
|
||||
|
||||
int32 count = 0;
|
||||
uint64 existsMask = h2o->GetLiquidExistsBitmap(h);
|
||||
for (int32 y = 0; y < h->GetHeight(); 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->GetOffsetY();
|
||||
for (int32 x = 0; x < h->GetWidth(); x++)
|
||||
{
|
||||
int cx = j * ADT_CELL_SIZE + x + h->xOffset;
|
||||
if (show & 1)
|
||||
int32 cx = j * ADT_CELL_SIZE + x + h->GetOffsetX();
|
||||
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;
|
||||
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; if (attrs.Deep) liquid_flags[i][j] |= MAP_LIQUID_TYPE_DARK_WATER; 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->GetHeight(); y++)
|
||||
{
|
||||
int cy = i * ADT_CELL_SIZE + y + h->yOffset;
|
||||
for (int x = 0; x <= h->width; x++)
|
||||
int cy = i * ADT_CELL_SIZE + y + h->GetOffsetY();
|
||||
for (int32 x = 0; x <= h->GetWidth(); x++)
|
||||
{
|
||||
int cx = j * ADT_CELL_SIZE + x + h->xOffset;
|
||||
if (height)
|
||||
liquid_height[cy][cx] = height[pos];
|
||||
else
|
||||
liquid_height[cy][cx] = h->heightLevel1;
|
||||
int32 cx = j * ADT_CELL_SIZE + x + h->GetOffsetX();
|
||||
liquid_height[cy][cx] = h2o->GetLiquidHeight(h, pos);
|
||||
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
@@ -796,13 +784,14 @@ bool ConvertADT(std::string const& inputPath, std::string const& outputPath, int
|
||||
//============================================
|
||||
// Pack liquid data
|
||||
//============================================
|
||||
uint8 type = liquid_flags[0][0];
|
||||
uint16 firstLiquidType = liquid_entry[0][0];
|
||||
uint8 firstLiquidFlag = liquid_flags[0][0];
|
||||
bool fullType = false;
|
||||
for (int y = 0; y < ADT_CELLS_PER_GRID; y++)
|
||||
{
|
||||
for (int x = 0; x < ADT_CELLS_PER_GRID; x++)
|
||||
{
|
||||
if (liquid_flags[y][x] != type)
|
||||
if (liquid_entry[y][x] != firstLiquidType || liquid_flags[y][x] != firstLiquidFlag)
|
||||
{
|
||||
fullType = true;
|
||||
y = ADT_CELLS_PER_GRID;
|
||||
@@ -814,7 +803,7 @@ bool ConvertADT(std::string const& inputPath, std::string const& outputPath, int
|
||||
map_liquidHeader liquidHeader;
|
||||
|
||||
// no water data (if all grid have 0 liquid type)
|
||||
if (type == 0 && !fullType)
|
||||
if (firstLiquidFlag == 0 && !fullType)
|
||||
{
|
||||
// No liquid data
|
||||
map.liquidMapOffset = 0;
|
||||
@@ -873,7 +862,10 @@ bool ConvertADT(std::string const& inputPath, std::string const& outputPath, int
|
||||
liquidHeader.flags |= MAP_LIQUID_NO_TYPE;
|
||||
|
||||
if (liquidHeader.flags & MAP_LIQUID_NO_TYPE)
|
||||
liquidHeader.liquidType = type;
|
||||
{
|
||||
liquidHeader.liquidFlags = firstLiquidFlag;
|
||||
liquidHeader.liquidType = firstLiquidType;
|
||||
}
|
||||
else
|
||||
map.liquidMapSize += sizeof(liquid_entry) + sizeof(liquid_flags);
|
||||
|
||||
@@ -1020,7 +1012,6 @@ void ExtractMapsFromMpq(uint32 build)
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
delete[] map_ids;
|
||||
}
|
||||
|
||||
bool ExtractFile( char const* mpq_name, std::string const& filename )
|
||||
|
||||
@@ -177,21 +177,36 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
#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,
|
||||
};
|
||||
|
||||
struct adt_liquid_instance
|
||||
{
|
||||
uint16 LiquidType; // Index from LiquidType.db2
|
||||
LiquidVertexFormatType LiquidVertexFormat;
|
||||
float MinHeightLevel;
|
||||
float MaxHeightLevel;
|
||||
uint8 OffsetX;
|
||||
uint8 OffsetY;
|
||||
uint8 Width;
|
||||
uint8 Height;
|
||||
uint32 OffsetExistsBitmap;
|
||||
uint32 OffsetVertexData;
|
||||
|
||||
uint8 GetOffsetX() const { return OffsetX; }
|
||||
uint8 GetOffsetY() const { return OffsetY; }
|
||||
uint8 GetWidth() const { return Width; }
|
||||
uint8 GetHeight() const { return Height; }
|
||||
};
|
||||
|
||||
struct adt_liquid_attributes
|
||||
{
|
||||
uint64 Fishable;
|
||||
uint64 Deep;
|
||||
};
|
||||
|
||||
//
|
||||
@@ -209,59 +224,99 @@ public:
|
||||
|
||||
struct adt_LIQUID
|
||||
{
|
||||
uint32 offsData1;
|
||||
uint32 OffsetInstances;
|
||||
uint32 used;
|
||||
uint32 offsData2;
|
||||
uint32 OffsetAttributes;
|
||||
} liquid[ADT_CELLS_PER_GRID][ADT_CELLS_PER_GRID];
|
||||
|
||||
bool prepareLoadedData();
|
||||
|
||||
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);
|
||||
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)
|
||||
adt_liquid_attributes GetLiquidAttributes(int32 x, int32 y) const
|
||||
{
|
||||
if (h->formatFlags & ADT_LIQUID_HEADER_NO_HIGHT)
|
||||
return nullptr;
|
||||
if (h->offsData2b)
|
||||
return (float*)((uint8*)this + 8 + h->offsData2b);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint8* getLiquidLightMap(adt_liquid_header* h)
|
||||
{
|
||||
if (h->formatFlags & ADT_LIQUID_HEADER_FULL_LIGHT)
|
||||
return nullptr;
|
||||
if (h->offsData2b)
|
||||
if (liquid[x][y].used)
|
||||
{
|
||||
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);
|
||||
if (liquid[x][y].OffsetAttributes)
|
||||
return *((adt_liquid_attributes *)((uint8*)this + 8 + liquid[x][y].OffsetAttributes));
|
||||
return { 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF };
|
||||
}
|
||||
return { 0, 0 };
|
||||
}
|
||||
|
||||
uint16 GetLiquidType(adt_liquid_instance const* h) const
|
||||
{
|
||||
if (h->LiquidVertexFormat == LiquidVertexFormatType::Depth)
|
||||
return 2;
|
||||
|
||||
return h->LiquidType;
|
||||
}
|
||||
|
||||
float GetLiquidHeight(adt_liquid_instance const* h, int32 pos) const
|
||||
{
|
||||
if (!h->OffsetVertexData)
|
||||
return 0.0f;
|
||||
|
||||
switch (h->LiquidVertexFormat)
|
||||
{
|
||||
case LiquidVertexFormatType::HeightDepth:
|
||||
case LiquidVertexFormatType::HeightTextureCoord:
|
||||
return ((float const*)((uint8*)this + 8 + h->OffsetVertexData))[pos];
|
||||
case LiquidVertexFormatType::Depth:
|
||||
return 0.0f;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
int8 GetLiquidDepth(adt_liquid_instance const* h, int32 pos) const
|
||||
{
|
||||
if (!h->OffsetVertexData)
|
||||
return -1;
|
||||
|
||||
switch (h->LiquidVertexFormat)
|
||||
{
|
||||
case LiquidVertexFormatType::HeightDepth:
|
||||
return ((int8 const*)((int8 const*)this + 8 + h->OffsetVertexData + (h->GetWidth() + 1) * (h->GetHeight() + 1) * 4))[pos];
|
||||
case LiquidVertexFormatType::HeightTextureCoord:
|
||||
return 0;
|
||||
case LiquidVertexFormatType::Depth:
|
||||
return ((int8 const*)((uint8*)this + 8 + h->OffsetVertexData))[pos];
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16 const* GetLiquidTextureCoordMap(adt_liquid_instance const* h, int32 pos) const
|
||||
{
|
||||
if (!h->OffsetVertexData)
|
||||
return nullptr;
|
||||
|
||||
switch (h->LiquidVertexFormat)
|
||||
{
|
||||
case LiquidVertexFormatType::HeightDepth:
|
||||
case LiquidVertexFormatType::Depth:
|
||||
return nullptr;
|
||||
case LiquidVertexFormatType::HeightTextureCoord:
|
||||
return (uint16 const*)((uint8 const*)this + 8 + h->OffsetVertexData + 4 * ((h->GetWidth() + 1) * (h->GetHeight() + 1) + pos));
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint32* getLiquidFullLightMap(adt_liquid_header* h)
|
||||
uint64 GetLiquidExistsBitmap(adt_liquid_instance const* h) const
|
||||
{
|
||||
if (!(h->formatFlags & ADT_LIQUID_HEADER_FULL_LIGHT))
|
||||
return nullptr;
|
||||
if (h->offsData2b)
|
||||
{
|
||||
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);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint64 getLiquidShowMap(adt_liquid_header* h)
|
||||
{
|
||||
if (h->offsData2a)
|
||||
return *((uint64*)((uint8*)this + 8 + h->offsData2a));
|
||||
if (h->OffsetExistsBitmap)
|
||||
return *((uint64 *)((uint8*)this + 8 + h->OffsetExistsBitmap));
|
||||
else
|
||||
return 0xFFFFFFFFFFFFFFFFuLL;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user