mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-15 23:20:36 +01:00
Tools:
* mapextractor - fixed fatigue in Thousand Needles
* mapextractor - fixed compressing liquid data
* vmapextractor - fixed extracting liquids inside WMOs
* vmapextractor - implemented new WMO flags
* vmapextractor - store model type for gameobject models
* mmap_generator - fixed processing liquids broken in e5d23103f3
This commit is contained in:
@@ -227,7 +227,7 @@ namespace VMAP
|
||||
while (!feof(dirf))
|
||||
{
|
||||
check = 0;
|
||||
// read mapID, tileX, tileY, Flags, adtID, ID, Pos, Rot, Scale, Bound_lo, Bound_hi, name
|
||||
// read mapID, tileX, tileY, Flags, NameSet, UniqueId, Pos, Rot, Scale, Bound_lo, Bound_hi, name
|
||||
check += fread(&mapID, sizeof(uint32), 1, dirf);
|
||||
if (check == 0) // EoF...
|
||||
break;
|
||||
@@ -300,14 +300,16 @@ namespace VMAP
|
||||
return true;
|
||||
}
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct WMOLiquidHeader
|
||||
{
|
||||
int xverts, yverts, xtiles, ytiles;
|
||||
float pos_x;
|
||||
float pos_y;
|
||||
float pos_z;
|
||||
short type;
|
||||
short material;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
//=================================================================
|
||||
bool TileAssembler::convertRawFile(const std::string& pModelFilename)
|
||||
{
|
||||
@@ -351,6 +353,10 @@ namespace VMAP
|
||||
if (!model_list)
|
||||
return;
|
||||
|
||||
char ident[8];
|
||||
if (fread(ident, 1, 8, model_list) != 8 || memcmp(ident, VMAP::RAW_VMAP_MAGIC, 8) != 0)
|
||||
return;
|
||||
|
||||
FILE* model_list_copy = fopen((iDestDir + "/" + GAMEOBJECT_MODELS).c_str(), "wb");
|
||||
if (!model_list_copy)
|
||||
{
|
||||
@@ -358,7 +364,10 @@ namespace VMAP
|
||||
return;
|
||||
}
|
||||
|
||||
fwrite(VMAP::VMAP_MAGIC, 1, 8, model_list_copy);
|
||||
|
||||
uint32 name_length, displayId;
|
||||
uint8 isWmo;
|
||||
char buff[500];
|
||||
while (true)
|
||||
{
|
||||
@@ -366,7 +375,8 @@ namespace VMAP
|
||||
if (feof(model_list)) // EOF flag is only set after failed reading attempt
|
||||
break;
|
||||
|
||||
if (fread(&name_length, sizeof(uint32), 1, model_list) != 1
|
||||
if (fread(&isWmo, sizeof(uint8), 1, model_list) != 1
|
||||
|| fread(&name_length, sizeof(uint32), 1, model_list) != 1
|
||||
|| name_length >= sizeof(buff)
|
||||
|| fread(&buff, sizeof(char), name_length, model_list) != name_length)
|
||||
{
|
||||
@@ -411,6 +421,7 @@ namespace VMAP
|
||||
}
|
||||
|
||||
fwrite(&displayId, sizeof(uint32), 1, model_list_copy);
|
||||
fwrite(&isWmo, sizeof(uint8), 1, model_list_copy);
|
||||
fwrite(&name_length, sizeof(uint32), 1, model_list_copy);
|
||||
fwrite(&buff, sizeof(char), name_length, model_list_copy);
|
||||
fwrite(&bounds.low(), sizeof(Vector3), 1, model_list_copy);
|
||||
@@ -495,25 +506,34 @@ namespace VMAP
|
||||
delete[] vectorarray;
|
||||
}
|
||||
// ----- liquid
|
||||
liquid = 0;
|
||||
if (liquidflags& 1)
|
||||
liquid = nullptr;
|
||||
if (liquidflags & 3)
|
||||
{
|
||||
WMOLiquidHeader hlq;
|
||||
READ_OR_RETURN(&blockId, 4);
|
||||
CMP_OR_RETURN(blockId, "LIQU");
|
||||
READ_OR_RETURN(&blocksize, sizeof(int));
|
||||
READ_OR_RETURN(&hlq, sizeof(WMOLiquidHeader));
|
||||
liquid = new WmoLiquid(hlq.xtiles, hlq.ytiles, Vector3(hlq.pos_x, hlq.pos_y, hlq.pos_z), hlq.type);
|
||||
uint32 size = hlq.xverts*hlq.yverts;
|
||||
READ_OR_RETURN(liquid->GetHeightStorage(), size*sizeof(float));
|
||||
size = hlq.xtiles*hlq.ytiles;
|
||||
READ_OR_RETURN(liquid->GetFlagsStorage(), size);
|
||||
uint32 liquidType;
|
||||
READ_OR_RETURN(&liquidType, sizeof(uint32));
|
||||
if (liquidflags & 1)
|
||||
{
|
||||
WMOLiquidHeader hlq;
|
||||
READ_OR_RETURN(&hlq, sizeof(WMOLiquidHeader));
|
||||
liquid = new WmoLiquid(hlq.xtiles, hlq.ytiles, Vector3(hlq.pos_x, hlq.pos_y, hlq.pos_z), liquidType);
|
||||
uint32 size = hlq.xverts * hlq.yverts;
|
||||
READ_OR_RETURN(liquid->GetHeightStorage(), size * sizeof(float));
|
||||
size = hlq.xtiles * hlq.ytiles;
|
||||
READ_OR_RETURN(liquid->GetFlagsStorage(), size);
|
||||
}
|
||||
else
|
||||
{
|
||||
liquid = new WmoLiquid(0, 0, Vector3::zero(), liquidType);
|
||||
liquid->GetHeightStorage()[0] = bounds.high().z;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
GroupModel_Raw::~GroupModel_Raw()
|
||||
{
|
||||
delete liquid;
|
||||
|
||||
@@ -31,11 +31,12 @@ using G3D::AABox;
|
||||
|
||||
struct GameobjectModelData
|
||||
{
|
||||
GameobjectModelData(const std::string& name_, const AABox& box) :
|
||||
bound(box), name(name_) { }
|
||||
GameobjectModelData(char const* name_, uint32 nameLength, Vector3 const& lowBound, Vector3 const& highBound, bool isWmo_) :
|
||||
bound(lowBound, highBound), name(name_, nameLength), isWmo(isWmo_) { }
|
||||
|
||||
AABox bound;
|
||||
std::string name;
|
||||
bool isWmo;
|
||||
};
|
||||
|
||||
typedef std::unordered_map<uint32, GameobjectModelData> ModelList;
|
||||
@@ -52,7 +53,16 @@ void LoadGameObjectModelList(std::string const& dataPath)
|
||||
return;
|
||||
}
|
||||
|
||||
char magic[8];
|
||||
if (fread(magic, 1, 8, model_list_file) != 8
|
||||
|| memcmp(magic, VMAP::VMAP_MAGIC, 8) != 0)
|
||||
{
|
||||
TC_LOG_ERROR("misc", "File '%s' has wrong header, expected %s.", VMAP::GAMEOBJECT_MODELS, VMAP::VMAP_MAGIC);
|
||||
return;
|
||||
}
|
||||
|
||||
uint32 name_length, displayId;
|
||||
uint8 isWmo;
|
||||
char buff[500];
|
||||
while (true)
|
||||
{
|
||||
@@ -61,7 +71,8 @@ void LoadGameObjectModelList(std::string const& dataPath)
|
||||
if (feof(model_list_file)) // EOF flag is only set after failed reading attempt
|
||||
break;
|
||||
|
||||
if (fread(&name_length, sizeof(uint32), 1, model_list_file) != 1
|
||||
if (fread(&isWmo, sizeof(uint8), 1, model_list_file) != 1
|
||||
|| fread(&name_length, sizeof(uint32), 1, model_list_file) != 1
|
||||
|| name_length >= sizeof(buff)
|
||||
|| fread(&buff, sizeof(char), name_length, model_list_file) != name_length
|
||||
|| fread(&v1, sizeof(Vector3), 1, model_list_file) != 1
|
||||
@@ -77,10 +88,7 @@ void LoadGameObjectModelList(std::string const& dataPath)
|
||||
continue;
|
||||
}
|
||||
|
||||
model_list.insert
|
||||
(
|
||||
ModelList::value_type(displayId, GameobjectModelData(std::string(buff, name_length), AABox(v1, v2)))
|
||||
);
|
||||
model_list.emplace(std::piecewise_construct, std::forward_as_tuple(displayId), std::forward_as_tuple(&buff[0], name_length, v1, v2, isWmo != 0));
|
||||
}
|
||||
|
||||
fclose(model_list_file);
|
||||
|
||||
@@ -42,14 +42,14 @@ class TC_COMMON_API GameObjectModelOwnerBase
|
||||
public:
|
||||
virtual ~GameObjectModelOwnerBase() = default;
|
||||
|
||||
virtual bool IsSpawned() const { return false; }
|
||||
virtual uint32 GetDisplayId() const { return 0; }
|
||||
virtual uint8 GetNameSetId() const { return 0; }
|
||||
virtual bool IsInPhase(PhaseShift const& /*phaseShift*/) const { return false; }
|
||||
virtual G3D::Vector3 GetPosition() const { return G3D::Vector3::zero(); }
|
||||
virtual float GetOrientation() const { return 0.0f; }
|
||||
virtual float GetScale() const { return 1.0f; }
|
||||
virtual void DebugVisualizeCorner(G3D::Vector3 const& /*corner*/) const { }
|
||||
virtual bool IsSpawned() const = 0;
|
||||
virtual uint32 GetDisplayId() const = 0;
|
||||
virtual uint8 GetNameSetId() const = 0;
|
||||
virtual bool IsInPhase(PhaseShift const& /*phaseShift*/) const = 0;
|
||||
virtual G3D::Vector3 GetPosition() const = 0;
|
||||
virtual float GetOrientation() const = 0;
|
||||
virtual float GetScale() const = 0;
|
||||
virtual void DebugVisualizeCorner(G3D::Vector3 const& /*corner*/) const = 0;
|
||||
};
|
||||
|
||||
class TC_COMMON_API GameObjectModel /*, public Intersectable*/
|
||||
|
||||
@@ -103,8 +103,16 @@ namespace VMAP
|
||||
WmoLiquid::WmoLiquid(uint32 width, uint32 height, const Vector3 &corner, uint32 type):
|
||||
iTilesX(width), iTilesY(height), iCorner(corner), iType(type)
|
||||
{
|
||||
iHeight = new float[(width+1)*(height+1)];
|
||||
iFlags = new uint8[width*height];
|
||||
if (width && height)
|
||||
{
|
||||
iHeight = new float[(width + 1) * (height + 1)];
|
||||
iFlags = new uint8[width * height];
|
||||
}
|
||||
else
|
||||
{
|
||||
iHeight = new float[1];
|
||||
iFlags = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
WmoLiquid::WmoLiquid(const WmoLiquid &other): iHeight(nullptr), iFlags(nullptr)
|
||||
@@ -126,8 +134,8 @@ namespace VMAP
|
||||
iTilesY = other.iTilesY;
|
||||
iCorner = other.iCorner;
|
||||
iType = other.iType;
|
||||
delete iHeight;
|
||||
delete iFlags;
|
||||
delete[] iHeight;
|
||||
delete[] iFlags;
|
||||
if (other.iHeight)
|
||||
{
|
||||
iHeight = new float[(iTilesX+1)*(iTilesY+1)];
|
||||
@@ -147,6 +155,13 @@ namespace VMAP
|
||||
|
||||
bool WmoLiquid::GetLiquidHeight(const Vector3 &pos, float &liqHeight) const
|
||||
{
|
||||
// simple case
|
||||
if (!iFlags)
|
||||
{
|
||||
liqHeight = iHeight[0];
|
||||
return true;
|
||||
}
|
||||
|
||||
float tx_f = (pos.x - iCorner.x)/LIQUID_TILE_SIZE;
|
||||
uint32 tx = uint32(tx_f);
|
||||
if (tx_f < 0.0f || tx >= iTilesX)
|
||||
@@ -198,8 +213,8 @@ namespace VMAP
|
||||
{
|
||||
return 2 * sizeof(uint32) +
|
||||
sizeof(Vector3) +
|
||||
(iTilesX + 1)*(iTilesY + 1) * sizeof(float) +
|
||||
iTilesX * iTilesY;
|
||||
sizeof(uint32) +
|
||||
(iFlags ? ((iTilesX + 1) * (iTilesY + 1) * sizeof(float) + iTilesX * iTilesY) : sizeof(float));
|
||||
}
|
||||
|
||||
bool WmoLiquid::writeToFile(FILE* wf)
|
||||
@@ -210,12 +225,17 @@ namespace VMAP
|
||||
fwrite(&iCorner, sizeof(Vector3), 1, wf) == 1 &&
|
||||
fwrite(&iType, sizeof(uint32), 1, wf) == 1)
|
||||
{
|
||||
uint32 size = (iTilesX + 1) * (iTilesY + 1);
|
||||
if (fwrite(iHeight, sizeof(float), size, wf) == size)
|
||||
if (iTilesX && iTilesY)
|
||||
{
|
||||
size = iTilesX*iTilesY;
|
||||
result = fwrite(iFlags, sizeof(uint8), size, wf) == size;
|
||||
uint32 size = (iTilesX + 1) * (iTilesY + 1);
|
||||
if (fwrite(iHeight, sizeof(float), size, wf) == size)
|
||||
{
|
||||
size = iTilesX * iTilesY;
|
||||
result = fwrite(iFlags, sizeof(uint8), size, wf) == size;
|
||||
}
|
||||
}
|
||||
else
|
||||
result = fwrite(iHeight, sizeof(float), 1, wf) == 1;
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -231,13 +251,21 @@ namespace VMAP
|
||||
fread(&liquid->iCorner, sizeof(Vector3), 1, rf) == 1 &&
|
||||
fread(&liquid->iType, sizeof(uint32), 1, rf) == 1)
|
||||
{
|
||||
uint32 size = (liquid->iTilesX + 1) * (liquid->iTilesY + 1);
|
||||
liquid->iHeight = new float[size];
|
||||
if (fread(liquid->iHeight, sizeof(float), size, rf) == size)
|
||||
if (liquid->iTilesX && liquid->iTilesY)
|
||||
{
|
||||
size = liquid->iTilesX * liquid->iTilesY;
|
||||
liquid->iFlags = new uint8[size];
|
||||
result = fread(liquid->iFlags, sizeof(uint8), size, rf) == size;
|
||||
uint32 size = (liquid->iTilesX + 1) * (liquid->iTilesY + 1);
|
||||
liquid->iHeight = new float[size];
|
||||
if (fread(liquid->iHeight, sizeof(float), size, rf) == size)
|
||||
{
|
||||
size = liquid->iTilesX * liquid->iTilesY;
|
||||
liquid->iFlags = new uint8[size];
|
||||
result = fread(liquid->iFlags, sizeof(uint8), size, rf) == size;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
liquid->iHeight = new float[1];
|
||||
result = fread(liquid->iHeight, sizeof(float), 1, rf) == 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,8 +25,8 @@
|
||||
|
||||
namespace VMAP
|
||||
{
|
||||
const char VMAP_MAGIC[] = "VMAP_4.6";
|
||||
const char RAW_VMAP_MAGIC[] = "VMAP046"; // used in extracted vmap files with raw data
|
||||
const char VMAP_MAGIC[] = "VMAP_4.7";
|
||||
const char RAW_VMAP_MAGIC[] = "VMAP047"; // used in extracted vmap files with raw data
|
||||
const char GAMEOBJECT_MODELS[] = "GameObjectModels.dtree";
|
||||
|
||||
// defined in TileAssembler.cpp currently...
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
#include "WorldSession.h"
|
||||
|
||||
u_map_magic MapMagic = { {'M','A','P','S'} };
|
||||
u_map_magic MapVersionMagic = { {'v','1','.','8'} };
|
||||
u_map_magic MapVersionMagic = { {'v','1','.','9'} };
|
||||
u_map_magic MapAreaMagic = { {'A','R','E','A'} };
|
||||
u_map_magic MapHeightMagic = { {'M','H','G','T'} };
|
||||
u_map_magic MapLiquidMagic = { {'M','L','I','Q'} };
|
||||
@@ -1914,7 +1914,8 @@ GridMap::GridMap()
|
||||
m_V8 = nullptr;
|
||||
_minHeightPlanes = nullptr;
|
||||
// Liquid data
|
||||
_liquidType = 0;
|
||||
_liquidGlobalEntry = 0;
|
||||
_liquidGlobalFlags = 0;
|
||||
_liquidOffX = 0;
|
||||
_liquidOffY = 0;
|
||||
_liquidWidth = 0;
|
||||
@@ -2117,7 +2118,8 @@ bool GridMap::loadLiquidData(FILE* in, uint32 offset, uint32 /*size*/)
|
||||
if (fread(&header, sizeof(header), 1, in) != 1 || header.fourcc != MapLiquidMagic.asUInt)
|
||||
return false;
|
||||
|
||||
_liquidType = header.liquidType;
|
||||
_liquidGlobalEntry = header.liquidType;
|
||||
_liquidGlobalFlags = header.liquidFlags;
|
||||
_liquidOffX = header.offsetX;
|
||||
_liquidOffY = header.offsetY;
|
||||
_liquidWidth = header.width;
|
||||
@@ -2442,7 +2444,7 @@ uint8 GridMap::getTerrainType(float x, float y) const
|
||||
inline ZLiquidStatus GridMap::getLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData* data)
|
||||
{
|
||||
// Check water type (if no water return)
|
||||
if (!_liquidType && !_liquidFlags)
|
||||
if (!_liquidGlobalFlags && !_liquidFlags)
|
||||
return LIQUID_MAP_NO_WATER;
|
||||
|
||||
// Get cell
|
||||
@@ -2454,37 +2456,33 @@ inline ZLiquidStatus GridMap::getLiquidStatus(float x, float y, float z, uint8 R
|
||||
|
||||
// Check water type in cell
|
||||
int idx=(x_int>>3)*16 + (y_int>>3);
|
||||
uint8 type = _liquidFlags ? _liquidFlags[idx] : _liquidType;
|
||||
uint32 entry = 0;
|
||||
if (_liquidEntry)
|
||||
uint8 type = _liquidFlags ? _liquidFlags[idx] : _liquidGlobalFlags;
|
||||
uint32 entry = _liquidEntry ? _liquidEntry[idx] : _liquidGlobalEntry;
|
||||
if (LiquidTypeEntry const* liquidEntry = sLiquidTypeStore.LookupEntry(entry))
|
||||
{
|
||||
if (LiquidTypeEntry const* liquidEntry = sLiquidTypeStore.LookupEntry(_liquidEntry[idx]))
|
||||
type &= MAP_LIQUID_TYPE_DARK_WATER;
|
||||
uint32 liqTypeIdx = liquidEntry->SoundBank;
|
||||
if (entry < 21)
|
||||
{
|
||||
entry = liquidEntry->ID;
|
||||
type &= MAP_LIQUID_TYPE_DARK_WATER;
|
||||
uint32 liqTypeIdx = liquidEntry->SoundBank;
|
||||
if (entry < 21)
|
||||
if (AreaTableEntry const* area = sAreaTableStore.LookupEntry(getArea(x, y)))
|
||||
{
|
||||
if (AreaTableEntry const* area = sAreaTableStore.LookupEntry(getArea(x, y)))
|
||||
uint32 overrideLiquid = area->LiquidTypeID[liquidEntry->SoundBank];
|
||||
if (!overrideLiquid && area->ParentAreaID)
|
||||
{
|
||||
uint32 overrideLiquid = area->LiquidTypeID[liquidEntry->SoundBank];
|
||||
if (!overrideLiquid && area->ParentAreaID)
|
||||
{
|
||||
area = sAreaTableStore.LookupEntry(area->ParentAreaID);
|
||||
if (area)
|
||||
overrideLiquid = area->LiquidTypeID[liquidEntry->SoundBank];
|
||||
}
|
||||
area = sAreaTableStore.LookupEntry(area->ParentAreaID);
|
||||
if (area)
|
||||
overrideLiquid = area->LiquidTypeID[liquidEntry->SoundBank];
|
||||
}
|
||||
|
||||
if (LiquidTypeEntry const* liq = sLiquidTypeStore.LookupEntry(overrideLiquid))
|
||||
{
|
||||
entry = overrideLiquid;
|
||||
liqTypeIdx = liq->SoundBank;
|
||||
}
|
||||
if (LiquidTypeEntry const* liq = sLiquidTypeStore.LookupEntry(overrideLiquid))
|
||||
{
|
||||
entry = overrideLiquid;
|
||||
liqTypeIdx = liq->SoundBank;
|
||||
}
|
||||
}
|
||||
|
||||
type |= 1 << liqTypeIdx;
|
||||
}
|
||||
|
||||
type |= 1 << liqTypeIdx;
|
||||
}
|
||||
|
||||
if (type == 0)
|
||||
|
||||
@@ -129,7 +129,8 @@ struct map_heightHeader
|
||||
struct map_liquidHeader
|
||||
{
|
||||
uint32 fourcc;
|
||||
uint16 flags;
|
||||
uint8 flags;
|
||||
uint8 liquidFlags;
|
||||
uint16 liquidType;
|
||||
uint8 offsetX;
|
||||
uint8 offsetY;
|
||||
@@ -156,7 +157,6 @@ enum ZLiquidStatus
|
||||
#define MAP_ALL_LIQUIDS (MAP_LIQUID_TYPE_WATER | MAP_LIQUID_TYPE_OCEAN | MAP_LIQUID_TYPE_MAGMA | MAP_LIQUID_TYPE_SLIME)
|
||||
|
||||
#define MAP_LIQUID_TYPE_DARK_WATER 0x10
|
||||
#define MAP_LIQUID_TYPE_WMO_WATER 0x20
|
||||
|
||||
struct LiquidData
|
||||
{
|
||||
@@ -193,7 +193,8 @@ class TC_GAME_API GridMap
|
||||
uint8* _liquidFlags;
|
||||
float* _liquidMap;
|
||||
uint16 _gridArea;
|
||||
uint16 _liquidType;
|
||||
uint16 _liquidGlobalEntry;
|
||||
uint8 _liquidGlobalFlags;
|
||||
uint8 _liquidOffX;
|
||||
uint8 _liquidOffY;
|
||||
uint8 _liquidWidth;
|
||||
|
||||
@@ -366,7 +366,7 @@ bool ReadCinematicCameraDBC()
|
||||
|
||||
// Map file format data
|
||||
static char const* MAP_MAGIC = "MAPS";
|
||||
static char const* MAP_VERSION_MAGIC = "v1.8";
|
||||
static char const* MAP_VERSION_MAGIC = "v1.9";
|
||||
static char const* MAP_AREA_MAGIC = "AREA";
|
||||
static char const* MAP_HEIGHT_MAGIC = "MHGT";
|
||||
static char const* MAP_LIQUID_MAGIC = "MLIQ";
|
||||
@@ -415,8 +415,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
|
||||
@@ -424,7 +422,8 @@ struct map_heightHeader
|
||||
struct map_liquidHeader
|
||||
{
|
||||
uint32 fourcc;
|
||||
uint16 flags;
|
||||
uint8 flags;
|
||||
uint8 liquidFlags;
|
||||
uint16 liquidType;
|
||||
uint8 offsetX;
|
||||
uint8 offsetY;
|
||||
@@ -694,8 +693,8 @@ bool ConvertADT(std::string const& inputPath, std::string const& outputPath, int
|
||||
}
|
||||
}
|
||||
|
||||
liquid_entry[i][j] = h->LiquidType;
|
||||
switch (LiquidTypes.at(h->LiquidType).SoundBank)
|
||||
liquid_entry[i][j] = h2o->GetLiquidType(h);
|
||||
switch (LiquidTypes.at(liquid_entry[i][j]).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; if (!ignoreDeepWater && attrs.Deep) liquid_flags[i][j] |= MAP_LIQUID_TYPE_DARK_WATER; break;
|
||||
@@ -877,13 +876,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;
|
||||
@@ -895,7 +895,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;
|
||||
@@ -947,7 +947,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);
|
||||
|
||||
@@ -955,15 +958,20 @@ bool ConvertADT(std::string const& inputPath, std::string const& outputPath, int
|
||||
map.liquidMapSize += sizeof(float)*liquidHeader.width*liquidHeader.height;
|
||||
}
|
||||
|
||||
if (map.liquidMapOffset)
|
||||
map.holesOffset = map.liquidMapOffset + map.liquidMapSize;
|
||||
else
|
||||
map.holesOffset = map.heightMapOffset + map.heightMapSize;
|
||||
|
||||
if (hasHoles)
|
||||
{
|
||||
if (map.liquidMapOffset)
|
||||
map.holesOffset = map.liquidMapOffset + map.liquidMapSize;
|
||||
else
|
||||
map.holesOffset = map.heightMapOffset + map.heightMapSize;
|
||||
|
||||
map.holesSize = sizeof(holes);
|
||||
}
|
||||
else
|
||||
{
|
||||
map.holesOffset = 0;
|
||||
map.holesSize = 0;
|
||||
}
|
||||
|
||||
// Ok all data prepared - store it
|
||||
std::ofstream outFile(outputPath, std::ofstream::out | std::ofstream::binary);
|
||||
@@ -1034,20 +1042,29 @@ bool ConvertADT(std::string const& inputPath, std::string const& outputPath, int
|
||||
|
||||
bool IsDeepWaterIgnored(uint32 mapId, uint32 x, uint32 y)
|
||||
{
|
||||
if (mapId != 0)
|
||||
return false;
|
||||
if (mapId == 0)
|
||||
{
|
||||
// GRID(39, 24) || GRID(39, 25) || GRID(39, 26) ||
|
||||
// GRID(40, 24) || GRID(40, 25) || GRID(40, 26) ||
|
||||
//GRID(41, 18) || GRID(41, 19) || GRID(41, 20) || GRID(41, 21) || GRID(41, 22) || GRID(41, 23) || GRID(41, 24) || GRID(41, 25) || GRID(41, 26) ||
|
||||
//GRID(42, 18) || GRID(42, 19) || GRID(42, 20) || GRID(42, 21) || GRID(42, 22) || GRID(42, 23) || GRID(42, 24) || GRID(42, 25) || GRID(42, 26) ||
|
||||
//GRID(43, 18) || GRID(43, 19) || GRID(43, 20) || GRID(43, 21) || GRID(43, 22) || GRID(43, 23) || GRID(43, 24) || GRID(43, 25) || GRID(43, 26) ||
|
||||
//GRID(44, 18) || GRID(44, 19) || GRID(44, 20) || GRID(44, 21) || GRID(44, 22) || GRID(44, 23) || GRID(44, 24) || GRID(44, 25) || GRID(44, 26) ||
|
||||
//GRID(45, 18) || GRID(45, 19) || GRID(45, 20) || GRID(45, 21) || GRID(45, 22) || GRID(45, 23) || GRID(45, 24) || GRID(45, 25) || GRID(45, 26) ||
|
||||
//GRID(46, 18) || GRID(46, 19) || GRID(46, 20) || GRID(46, 21) || GRID(46, 22) || GRID(46, 23) || GRID(46, 24) || GRID(46, 25) || GRID(46, 26)
|
||||
|
||||
// GRID(39, 24) || GRID(39, 25) || GRID(39, 26) ||
|
||||
// GRID(40, 24) || GRID(40, 25) || GRID(40, 26) ||
|
||||
//GRID(41, 18) || GRID(41, 19) || GRID(41, 20) || GRID(41, 21) || GRID(41, 22) || GRID(41, 23) || GRID(41, 24) || GRID(41, 25) || GRID(41, 26) ||
|
||||
//GRID(42, 18) || GRID(42, 19) || GRID(42, 20) || GRID(42, 21) || GRID(42, 22) || GRID(42, 23) || GRID(42, 24) || GRID(42, 25) || GRID(42, 26) ||
|
||||
//GRID(43, 18) || GRID(43, 19) || GRID(43, 20) || GRID(43, 21) || GRID(43, 22) || GRID(43, 23) || GRID(43, 24) || GRID(43, 25) || GRID(43, 26) ||
|
||||
//GRID(44, 18) || GRID(44, 19) || GRID(44, 20) || GRID(44, 21) || GRID(44, 22) || GRID(44, 23) || GRID(44, 24) || GRID(44, 25) || GRID(44, 26) ||
|
||||
//GRID(45, 18) || GRID(45, 19) || GRID(45, 20) || GRID(45, 21) || GRID(45, 22) || GRID(45, 23) || GRID(45, 24) || GRID(45, 25) || GRID(45, 26) ||
|
||||
//GRID(46, 18) || GRID(46, 19) || GRID(46, 20) || GRID(46, 21) || GRID(46, 22) || GRID(46, 23) || GRID(46, 24) || GRID(46, 25) || GRID(46, 26)
|
||||
// Vashj'ir grids completely ignore fatigue
|
||||
return (x >= 39 && x <= 40 && y >= 24 && y <= 26) || (x >= 41 && x <= 46 && y >= 18 && y <= 26);
|
||||
}
|
||||
|
||||
// Vashj'ir grids completely ignore fatigue
|
||||
return (x >= 39 && x <= 40 && y >= 24 && y <= 26) || (x >= 41 && x <= 46 && y >= 18 && y <= 26);
|
||||
if (mapId == 1)
|
||||
{
|
||||
// GRID(43, 39) || GRID(43, 40)
|
||||
// Thousand Needles
|
||||
return x == 43 && (y == 39 || y == 40);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ExtractMaps(uint32 build)
|
||||
|
||||
@@ -206,6 +206,14 @@ struct adt_MH2O
|
||||
return { 0, 0 };
|
||||
}
|
||||
|
||||
uint16 GetLiquidType(adt_liquid_instance const* h) const
|
||||
{
|
||||
if (GetLiquidVertexFormat(h) == LiquidVertexFormatType::Depth)
|
||||
return 2;
|
||||
|
||||
return h->LiquidType;
|
||||
}
|
||||
|
||||
float GetLiquidHeight(adt_liquid_instance const* h, int32 pos) const
|
||||
{
|
||||
if (!h->OffsetVertexData)
|
||||
|
||||
@@ -59,7 +59,8 @@ struct map_heightHeader
|
||||
struct map_liquidHeader
|
||||
{
|
||||
uint32 fourcc;
|
||||
uint16 flags;
|
||||
uint8 flags;
|
||||
uint8 liquidFlags;
|
||||
uint16 liquidType;
|
||||
uint8 offsetX;
|
||||
uint8 offsetY;
|
||||
@@ -74,12 +75,10 @@ struct map_liquidHeader
|
||||
#define MAP_LIQUID_TYPE_MAGMA 0x04
|
||||
#define MAP_LIQUID_TYPE_SLIME 0x08
|
||||
#define MAP_LIQUID_TYPE_DARK_WATER 0x10
|
||||
#define MAP_LIQUID_TYPE_WMO_WATER 0x20
|
||||
|
||||
namespace MMAP
|
||||
{
|
||||
|
||||
char const* MAP_VERSION_MAGIC = "v1.8";
|
||||
char const* MAP_VERSION_MAGIC = "v1.9";
|
||||
|
||||
TerrainBuilder::TerrainBuilder(bool skipLiquid) : m_skipLiquid (skipLiquid){ }
|
||||
TerrainBuilder::~TerrainBuilder() { }
|
||||
@@ -179,8 +178,10 @@ namespace MMAP
|
||||
// data used later
|
||||
uint8 holes[16][16][8];
|
||||
memset(holes, 0, sizeof(holes));
|
||||
uint8 liquid_type[16][16];
|
||||
memset(liquid_type, 0, sizeof(liquid_type));
|
||||
uint16 liquid_entry[16][16];
|
||||
memset(liquid_entry, 0, sizeof(liquid_entry));
|
||||
uint8 liquid_flags[16][16];
|
||||
memset(liquid_flags, 0, sizeof(liquid_flags));
|
||||
G3D::Array<int> ltriangles;
|
||||
G3D::Array<int> ttriangles;
|
||||
|
||||
@@ -288,79 +289,90 @@ namespace MMAP
|
||||
if (fread(&lheader, sizeof(map_liquidHeader), 1, mapFile) != 1)
|
||||
printf("TerrainBuilder::loadMap: Failed to read some data expected 1, read 0\n");
|
||||
|
||||
|
||||
float* liquid_map = NULL;
|
||||
float* liquid_map = nullptr;
|
||||
|
||||
if (!(lheader.flags & MAP_LIQUID_NO_TYPE))
|
||||
if (fread(liquid_type, sizeof(liquid_type), 1, mapFile) != 1)
|
||||
{
|
||||
if (fread(liquid_entry, sizeof(liquid_entry), 1, mapFile) != 1)
|
||||
printf("TerrainBuilder::loadMap: Failed to read some data expected 1, read 0\n");
|
||||
if (fread(liquid_flags, sizeof(liquid_flags), 1, mapFile) != 1)
|
||||
printf("TerrainBuilder::loadMap: Failed to read some data expected 1, read 0\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
std::fill_n(&liquid_entry[0][0], 16 * 16, lheader.liquidType);
|
||||
std::fill_n(&liquid_flags[0][0], 16 * 16, lheader.liquidFlags);
|
||||
}
|
||||
|
||||
if (!(lheader.flags & MAP_LIQUID_NO_HEIGHT))
|
||||
{
|
||||
uint32 toRead = lheader.width * lheader.height;
|
||||
liquid_map = new float [toRead];
|
||||
if (fread(liquid_map, sizeof(float), toRead, mapFile) != toRead)
|
||||
{
|
||||
printf("TerrainBuilder::loadMap: Failed to read some data expected 1, read 0\n");
|
||||
delete[] liquid_map;
|
||||
liquid_map = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (liquid_map)
|
||||
int count = meshData.liquidVerts.size() / 3;
|
||||
float xoffset = (float(tileX)-32)*GRID_SIZE;
|
||||
float yoffset = (float(tileY)-32)*GRID_SIZE;
|
||||
|
||||
float coord[3];
|
||||
int row, col;
|
||||
|
||||
// generate coordinates
|
||||
if (!(lheader.flags & MAP_LIQUID_NO_HEIGHT))
|
||||
{
|
||||
int count = meshData.liquidVerts.size() / 3;
|
||||
float xoffset = (float(tileX)-32)*GRID_SIZE;
|
||||
float yoffset = (float(tileY)-32)*GRID_SIZE;
|
||||
|
||||
float coord[3];
|
||||
int row, col;
|
||||
|
||||
// generate coordinates
|
||||
if (!(lheader.flags & MAP_LIQUID_NO_HEIGHT))
|
||||
int j = 0;
|
||||
for (int i = 0; i < V9_SIZE_SQ; ++i)
|
||||
{
|
||||
int j = 0;
|
||||
for (int i = 0; i < V9_SIZE_SQ; ++i)
|
||||
row = i / V9_SIZE;
|
||||
col = i % V9_SIZE;
|
||||
|
||||
if (row < lheader.offsetY || row >= lheader.offsetY + lheader.height ||
|
||||
col < lheader.offsetX || col >= lheader.offsetX + lheader.width)
|
||||
{
|
||||
row = i / V9_SIZE;
|
||||
col = i % V9_SIZE;
|
||||
|
||||
if (row < lheader.offsetY || row >= lheader.offsetY + lheader.height ||
|
||||
col < lheader.offsetX || col >= lheader.offsetX + lheader.width)
|
||||
{
|
||||
// dummy vert using invalid height
|
||||
meshData.liquidVerts.append((xoffset+col*GRID_PART_SIZE)*-1, INVALID_MAP_LIQ_HEIGHT, (yoffset+row*GRID_PART_SIZE)*-1);
|
||||
continue;
|
||||
}
|
||||
|
||||
getLiquidCoord(i, j, xoffset, yoffset, coord, liquid_map);
|
||||
meshData.liquidVerts.append(coord[0]);
|
||||
meshData.liquidVerts.append(coord[2]);
|
||||
meshData.liquidVerts.append(coord[1]);
|
||||
j++;
|
||||
// dummy vert using invalid height
|
||||
meshData.liquidVerts.append((xoffset+col*GRID_PART_SIZE)*-1, INVALID_MAP_LIQ_HEIGHT, (yoffset+row*GRID_PART_SIZE)*-1);
|
||||
continue;
|
||||
}
|
||||
|
||||
getLiquidCoord(i, j, xoffset, yoffset, coord, liquid_map);
|
||||
meshData.liquidVerts.append(coord[0]);
|
||||
meshData.liquidVerts.append(coord[2]);
|
||||
meshData.liquidVerts.append(coord[1]);
|
||||
j++;
|
||||
}
|
||||
else
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < V9_SIZE_SQ; ++i)
|
||||
{
|
||||
for (int i = 0; i < V9_SIZE_SQ; ++i)
|
||||
{
|
||||
row = i / V9_SIZE;
|
||||
col = i % V9_SIZE;
|
||||
meshData.liquidVerts.append((xoffset+col*GRID_PART_SIZE)*-1, lheader.liquidLevel, (yoffset+row*GRID_PART_SIZE)*-1);
|
||||
}
|
||||
row = i / V9_SIZE;
|
||||
col = i % V9_SIZE;
|
||||
meshData.liquidVerts.append((xoffset+col*GRID_PART_SIZE)*-1, lheader.liquidLevel, (yoffset+row*GRID_PART_SIZE)*-1);
|
||||
}
|
||||
}
|
||||
|
||||
delete [] liquid_map;
|
||||
delete[] liquid_map;
|
||||
|
||||
int indices[] = { 0, 0, 0 };
|
||||
int loopStart = 0, loopEnd = 0, loopInc = 0, triInc = BOTTOM-TOP;
|
||||
getLoopVars(portion, loopStart, loopEnd, loopInc);
|
||||
int indices[] = { 0, 0, 0 };
|
||||
int loopStart = 0, loopEnd = 0, loopInc = 0, triInc = BOTTOM-TOP;
|
||||
getLoopVars(portion, loopStart, loopEnd, loopInc);
|
||||
|
||||
// generate triangles
|
||||
for (int i = loopStart; i < loopEnd; i+=loopInc)
|
||||
for (int j = TOP; j <= BOTTOM; j+= triInc)
|
||||
{
|
||||
getHeightTriangle(i, Spot(j), indices, true);
|
||||
ltriangles.append(indices[2] + count);
|
||||
ltriangles.append(indices[1] + count);
|
||||
ltriangles.append(indices[0] + count);
|
||||
}
|
||||
// generate triangles
|
||||
for (int i = loopStart; i < loopEnd; i += loopInc)
|
||||
{
|
||||
for (int j = TOP; j <= BOTTOM; j += triInc)
|
||||
{
|
||||
getHeightTriangle(i, Spot(j), indices, true);
|
||||
ltriangles.append(indices[2] + count);
|
||||
ltriangles.append(indices[1] + count);
|
||||
ltriangles.append(indices[0] + count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -404,31 +416,24 @@ namespace MMAP
|
||||
useLiquid = false;
|
||||
else
|
||||
{
|
||||
liquidType = getLiquidType(i, liquid_type);
|
||||
switch (liquidType)
|
||||
liquidType = getLiquidType(i, liquid_flags);
|
||||
if (liquidType & MAP_LIQUID_TYPE_DARK_WATER)
|
||||
{
|
||||
default:
|
||||
useLiquid = false;
|
||||
break;
|
||||
case MAP_LIQUID_TYPE_WATER:
|
||||
case MAP_LIQUID_TYPE_OCEAN:
|
||||
// merge different types of water
|
||||
liquidType = NAV_WATER;
|
||||
break;
|
||||
case MAP_LIQUID_TYPE_MAGMA:
|
||||
liquidType = NAV_MAGMA;
|
||||
break;
|
||||
case MAP_LIQUID_TYPE_SLIME:
|
||||
liquidType = NAV_SLIME;
|
||||
break;
|
||||
case MAP_LIQUID_TYPE_DARK_WATER:
|
||||
// players should not be here, so logically neither should creatures
|
||||
useTerrain = false;
|
||||
useLiquid = false;
|
||||
break;
|
||||
// players should not be here, so logically neither should creatures
|
||||
useTerrain = false;
|
||||
useLiquid = false;
|
||||
}
|
||||
else if ((liquidType & (MAP_LIQUID_TYPE_WATER | MAP_LIQUID_TYPE_OCEAN)) != 0)
|
||||
liquidType = NAV_WATER;
|
||||
else if (liquidType & MAP_LIQUID_TYPE_MAGMA)
|
||||
liquidType = NAV_MAGMA;
|
||||
else if (liquidType & MAP_LIQUID_TYPE_SLIME)
|
||||
liquidType = NAV_SLIME;
|
||||
else
|
||||
useLiquid = false;
|
||||
}
|
||||
|
||||
|
||||
// if there is no terrain, don't use terrain
|
||||
if (!ttriangles.size())
|
||||
useTerrain = false;
|
||||
@@ -699,7 +704,7 @@ namespace MMAP
|
||||
copyIndices(tempTriangles, meshData.solidTris, offset, isM2);
|
||||
|
||||
// now handle liquid data
|
||||
if (liquid)
|
||||
if (liquid && liquid->GetFlagsStorage())
|
||||
{
|
||||
std::vector<G3D::Vector3> liqVerts;
|
||||
std::vector<int> liqTris;
|
||||
|
||||
@@ -51,7 +51,7 @@ namespace MMAP
|
||||
static const float GRID_PART_SIZE = GRID_SIZE/V8_SIZE;
|
||||
|
||||
// see contrib/extractor/system.cpp, CONF_use_minHeight
|
||||
static const float INVALID_MAP_LIQ_HEIGHT = -500.f;
|
||||
static const float INVALID_MAP_LIQ_HEIGHT = -2000.f;
|
||||
static const float INVALID_MAP_LIQ_HEIGHT_MAX = 5000.0f;
|
||||
|
||||
// see following files:
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
#include "vmapexport.h"
|
||||
#include "adtfile.h"
|
||||
|
||||
#include "StringFormat.h"
|
||||
#include <algorithm>
|
||||
#include <cstdio>
|
||||
|
||||
@@ -79,7 +79,7 @@ char* GetExtension(char* FileName)
|
||||
|
||||
extern CASC::StorageHandle CascStorage;
|
||||
|
||||
ADTFile::ADTFile(char* filename, bool cache) : ADT(CascStorage, filename, false), nWMO(0), nMDX(0)
|
||||
ADTFile::ADTFile(char* filename, bool cache) : _file(CascStorage, filename, false)
|
||||
{
|
||||
Adtfilename.append(filename);
|
||||
cacheable = cache;
|
||||
@@ -91,7 +91,7 @@ bool ADTFile::init(uint32 map_num, uint32 tileX, uint32 tileY, uint32 originalMa
|
||||
if (dirfileCache)
|
||||
return initFromCache(map_num, tileX, tileY, originalMapId);
|
||||
|
||||
if (ADT.isEof())
|
||||
if (_file.isEof())
|
||||
return false;
|
||||
|
||||
uint32 size;
|
||||
@@ -106,15 +106,15 @@ bool ADTFile::init(uint32 map_num, uint32 tileX, uint32 tileY, uint32 originalMa
|
||||
if (cacheable)
|
||||
dirfileCache = new std::vector<ADTOutputCache>();
|
||||
|
||||
while (!ADT.isEof())
|
||||
while (!_file.isEof())
|
||||
{
|
||||
char fourcc[5];
|
||||
ADT.read(&fourcc,4);
|
||||
ADT.read(&size, 4);
|
||||
_file.read(&fourcc,4);
|
||||
_file.read(&size, 4);
|
||||
flipcc(fourcc);
|
||||
fourcc[4] = 0;
|
||||
|
||||
size_t nextpos = ADT.getPos() + size;
|
||||
size_t nextpos = _file.getPos() + size;
|
||||
|
||||
if (!strcmp(fourcc,"MCIN"))
|
||||
{
|
||||
@@ -127,7 +127,7 @@ bool ADTFile::init(uint32 map_num, uint32 tileX, uint32 tileY, uint32 originalMa
|
||||
if (size)
|
||||
{
|
||||
char* buf = new char[size];
|
||||
ADT.read(buf, size);
|
||||
_file.read(buf, size);
|
||||
char* p = buf;
|
||||
while (p < buf + size)
|
||||
{
|
||||
@@ -151,7 +151,7 @@ bool ADTFile::init(uint32 map_num, uint32 tileX, uint32 tileY, uint32 originalMa
|
||||
if (size)
|
||||
{
|
||||
char* buf = new char[size];
|
||||
ADT.read(buf, size);
|
||||
_file.read(buf, size);
|
||||
char* p = buf;
|
||||
while (p < buf + size)
|
||||
{
|
||||
@@ -171,16 +171,25 @@ bool ADTFile::init(uint32 map_num, uint32 tileX, uint32 tileY, uint32 originalMa
|
||||
}
|
||||
}
|
||||
//======================
|
||||
else if (!strcmp(fourcc,"MDDF"))
|
||||
else if (!strcmp(fourcc, "MDDF"))
|
||||
{
|
||||
if (size)
|
||||
{
|
||||
nMDX = (int)size / 36;
|
||||
for (int i=0; i<nMDX; ++i)
|
||||
uint32 doodadCount = size / sizeof(ADT::MDDF);
|
||||
for (uint32 i = 0; i < doodadCount; ++i)
|
||||
{
|
||||
uint32 id;
|
||||
ADT.read(&id, 4);
|
||||
ModelInstance inst(ADT, ModelInstanceNames[id].c_str(), map_num, tileX, tileY, originalMapId, dirfile, dirfileCache);
|
||||
ADT::MDDF doodadDef;
|
||||
_file.read(&doodadDef, sizeof(ADT::MDDF));
|
||||
if (!(doodadDef.Flags & 0x40))
|
||||
{
|
||||
Doodad::Extract(doodadDef, ModelInstanceNames[doodadDef.Id].c_str(), map_num, tileX, tileY, originalMapId, dirfile, dirfileCache);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string fileName = Trinity::StringFormat("FILE%08X.xxx", doodadDef.Id);
|
||||
ExtractSingleModel(fileName);
|
||||
Doodad::Extract(doodadDef, fileName.c_str(), map_num, tileX, tileY, originalMapId, dirfile, dirfileCache);
|
||||
}
|
||||
}
|
||||
|
||||
ModelInstanceNames.clear();
|
||||
@@ -190,12 +199,21 @@ bool ADTFile::init(uint32 map_num, uint32 tileX, uint32 tileY, uint32 originalMa
|
||||
{
|
||||
if (size)
|
||||
{
|
||||
nWMO = (int)size / 64;
|
||||
for (int i=0; i<nWMO; ++i)
|
||||
uint32 mapObjectCount = size / sizeof(ADT::MODF);
|
||||
for (uint32 i = 0; i < mapObjectCount; ++i)
|
||||
{
|
||||
uint32 id;
|
||||
ADT.read(&id, 4);
|
||||
WMOInstance inst(ADT, WmoInstanceNames[id].c_str(), map_num, tileX, tileY, originalMapId, dirfile, dirfileCache);
|
||||
ADT::MODF mapObjDef;
|
||||
_file.read(&mapObjDef, sizeof(ADT::MODF));
|
||||
if (!(mapObjDef.Flags & 0x8))
|
||||
{
|
||||
MapObject::Extract(mapObjDef, WmoInstanceNames[mapObjDef.Id].c_str(), map_num, tileX, tileY, originalMapId, dirfile, dirfileCache);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string fileName = Trinity::StringFormat("FILE%08X.xxx", mapObjDef.Id);
|
||||
ExtractSingleModel(fileName);
|
||||
MapObject::Extract(mapObjDef, fileName.c_str(), map_num, tileX, tileY, originalMapId, dirfile, dirfileCache);
|
||||
}
|
||||
}
|
||||
|
||||
WmoInstanceNames.clear();
|
||||
@@ -203,10 +221,10 @@ bool ADTFile::init(uint32 map_num, uint32 tileX, uint32 tileY, uint32 originalMa
|
||||
}
|
||||
|
||||
//======================
|
||||
ADT.seek(nextpos);
|
||||
_file.seek(nextpos);
|
||||
}
|
||||
|
||||
ADT.close();
|
||||
_file.close();
|
||||
fclose(dirfile);
|
||||
return true;
|
||||
}
|
||||
@@ -242,6 +260,6 @@ bool ADTFile::initFromCache(uint32 map_num, uint32 tileX, uint32 tileY, uint32 o
|
||||
|
||||
ADTFile::~ADTFile()
|
||||
{
|
||||
ADT.close();
|
||||
_file.close();
|
||||
delete dirfileCache;
|
||||
}
|
||||
|
||||
@@ -23,88 +23,33 @@
|
||||
#include "wmo.h"
|
||||
#include "model.h"
|
||||
|
||||
#define TILESIZE (533.33333f)
|
||||
#define CHUNKSIZE ((TILESIZE) / 16.0f)
|
||||
#define UNITSIZE (CHUNKSIZE / 8.0f)
|
||||
|
||||
class Liquid;
|
||||
|
||||
typedef struct
|
||||
#pragma pack(push, 1)
|
||||
namespace ADT
|
||||
{
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
}svec;
|
||||
struct MDDF
|
||||
{
|
||||
uint32 Id;
|
||||
uint32 UniqueId;
|
||||
Vec3D Position;
|
||||
Vec3D Rotation;
|
||||
uint16 Scale;
|
||||
uint16 Flags;
|
||||
};
|
||||
|
||||
struct vec
|
||||
{
|
||||
double x;
|
||||
double y;
|
||||
double z;
|
||||
};
|
||||
|
||||
struct triangle
|
||||
{
|
||||
vec v[3];
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float v9[16*8+1][16*8+1];
|
||||
float v8[16*8][16*8];
|
||||
}Cell;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
double v9[9][9];
|
||||
double v8[8][8];
|
||||
uint16 area_id;
|
||||
//Liquid *lq;
|
||||
float waterlevel[9][9];
|
||||
uint8 flag;
|
||||
}chunk;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
chunk ch[16][16];
|
||||
}mcell;
|
||||
|
||||
struct MapChunkHeader
|
||||
{
|
||||
uint32 flags;
|
||||
uint32 ix;
|
||||
uint32 iy;
|
||||
uint32 nLayers;
|
||||
uint32 nDoodadRefs;
|
||||
uint32 ofsHeight;
|
||||
uint32 ofsNormal;
|
||||
uint32 ofsLayer;
|
||||
uint32 ofsRefs;
|
||||
uint32 ofsAlpha;
|
||||
uint32 sizeAlpha;
|
||||
uint32 ofsShadow;
|
||||
uint32 sizeShadow;
|
||||
uint32 areaid;
|
||||
uint32 nMapObjRefs;
|
||||
uint32 holes;
|
||||
uint16 s1;
|
||||
uint16 s2;
|
||||
uint32 d1;
|
||||
uint32 d2;
|
||||
uint32 d3;
|
||||
uint32 predTex;
|
||||
uint32 nEffectDoodad;
|
||||
uint32 ofsSndEmitters;
|
||||
uint32 nSndEmitters;
|
||||
uint32 ofsLiquid;
|
||||
uint32 sizeLiquid;
|
||||
float zpos;
|
||||
float xpos;
|
||||
float ypos;
|
||||
uint32 textureId;
|
||||
uint32 props;
|
||||
uint32 effectId;
|
||||
};
|
||||
struct MODF
|
||||
{
|
||||
uint32 Id;
|
||||
uint32 UniqueId;
|
||||
Vec3D Position;
|
||||
Vec3D Rotation;
|
||||
AaBox3D Bounds;
|
||||
uint16 Flags;
|
||||
uint16 DoodadSet;
|
||||
uint16 NameSet;
|
||||
uint16 Scale;
|
||||
};
|
||||
}
|
||||
#pragma pack(pop)
|
||||
|
||||
struct ADTOutputCache
|
||||
{
|
||||
@@ -115,15 +60,13 @@ struct ADTOutputCache
|
||||
class ADTFile
|
||||
{
|
||||
private:
|
||||
CASCFile ADT;
|
||||
CASCFile _file;
|
||||
std::string Adtfilename;
|
||||
bool cacheable;
|
||||
std::vector<ADTOutputCache>* dirfileCache;
|
||||
public:
|
||||
ADTFile(char* filename, bool cache);
|
||||
~ADTFile();
|
||||
int nWMO;
|
||||
int nMDX;
|
||||
std::vector<std::string> WmoInstanceNames;
|
||||
std::vector<std::string> ModelInstanceNames;
|
||||
bool init(uint32 map_num, uint32 tileX, uint32 tileY, uint32 originalMapId);
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "model.h"
|
||||
#include "StringFormat.h"
|
||||
#include "vmapexport.h"
|
||||
#include "VMapDefinitions.h"
|
||||
#include <CascLib.h>
|
||||
#include <algorithm>
|
||||
#include <cstdio>
|
||||
@@ -101,6 +102,8 @@ void ExtractGameobjectModels()
|
||||
return;
|
||||
}
|
||||
|
||||
fwrite(VMAP::RAW_VMAP_MAGIC, 1, 8, model_list);
|
||||
|
||||
for (uint32 rec = 0; rec < db2.GetRecordCount(); ++rec)
|
||||
{
|
||||
DB2Record record = db2.GetRecord(rec);
|
||||
@@ -114,8 +117,12 @@ void ExtractGameobjectModels()
|
||||
if (!GetHeaderMagic(fileName, &header))
|
||||
continue;
|
||||
|
||||
uint8 isWmo = 0;
|
||||
if (header == MODEL_WMO)
|
||||
{
|
||||
isWmo = 1;
|
||||
result = ExtractSingleWmo(fileName);
|
||||
}
|
||||
else if (header == MODEL_MD20 || header == MODEL_MD21)
|
||||
result = ExtractSingleModel(fileName);
|
||||
else
|
||||
@@ -126,6 +133,7 @@ void ExtractGameobjectModels()
|
||||
uint32 displayId = record.GetId();
|
||||
uint32 path_length = fileName.length();
|
||||
fwrite(&displayId, sizeof(uint32), 1, model_list);
|
||||
fwrite(&isWmo, sizeof(uint8), 1, model_list);
|
||||
fwrite(&path_length, sizeof(uint32), 1, model_list);
|
||||
fwrite(fileName.c_str(), sizeof(char), path_length, model_list);
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "wmo.h"
|
||||
#include "adtfile.h"
|
||||
#include "cascfile.h"
|
||||
#include "VMapDefinitions.h"
|
||||
#include <cassert>
|
||||
#include <algorithm>
|
||||
#include <cstdio>
|
||||
@@ -89,7 +90,7 @@ bool Model::ConvertToVMAPModel(const char * outfilename)
|
||||
printf("Can't create the output file '%s'\n",outfilename);
|
||||
return false;
|
||||
}
|
||||
fwrite(szRawVMAPMagic, 8, 1, output);
|
||||
fwrite(VMAP::RAW_VMAP_MAGIC, 8, 1, output);
|
||||
uint32 nVertices = header.nBoundingVertices;
|
||||
fwrite(&nVertices, sizeof(int), 1, output);
|
||||
uint32 nofgroups = 1;
|
||||
@@ -155,29 +156,17 @@ Vec3D fixCoordSystem2(Vec3D v)
|
||||
return Vec3D(v.x, v.z, v.y);
|
||||
}
|
||||
|
||||
ModelInstance::ModelInstance(CASCFile& f, char const* ModelInstName, uint32 mapID, uint32 tileX, uint32 tileY, uint32 originalMapId, FILE* pDirfile, std::vector<ADTOutputCache>* dirfileCache)
|
||||
: id(0), scale(0), flags(0)
|
||||
void Doodad::Extract(ADT::MDDF const& doodadDef, char const* ModelInstName, uint32 mapID, uint32 tileX, uint32 tileY, uint32 originalMapId, FILE* pDirfile, std::vector<ADTOutputCache>* dirfileCache)
|
||||
{
|
||||
float ff[3];
|
||||
f.read(&id, 4);
|
||||
f.read(ff, 12);
|
||||
pos = fixCoords(Vec3D(ff[0], ff[1], ff[2]));
|
||||
f.read(ff, 12);
|
||||
rot = Vec3D(ff[0], ff[1], ff[2]);
|
||||
f.read(&scale, 2);
|
||||
f.read(&flags, 2);
|
||||
// scale factor - divide by 1024. blizzard devs must be on crack, why not just use a float?
|
||||
sc = scale / 1024.0f;
|
||||
float sc = doodadDef.Scale / 1024.0f;
|
||||
|
||||
char tempname[512];
|
||||
sprintf(tempname, "%s/%s", szWorkDirWmo, ModelInstName);
|
||||
FILE* input = fopen(tempname, "r+b");
|
||||
|
||||
if (!input)
|
||||
{
|
||||
//printf("ModelInstance::ModelInstance couldn't open %s\n", tempname);
|
||||
return;
|
||||
}
|
||||
|
||||
fseek(input, 8, SEEK_SET); // get the correct no of vertices
|
||||
int nVertices;
|
||||
@@ -187,22 +176,24 @@ ModelInstance::ModelInstance(CASCFile& f, char const* ModelInstName, uint32 mapI
|
||||
if (count != 1 || nVertices == 0)
|
||||
return;
|
||||
|
||||
uint16 adtId = 0;// not used for models
|
||||
Vec3D position = fixCoords(doodadDef.Position);
|
||||
|
||||
uint16 nameSet = 0;// not used for models
|
||||
uint32 tcflags = MOD_M2;
|
||||
if (tileX == 65 && tileY == 65)
|
||||
tcflags |= MOD_WORLDSPAWN;
|
||||
if (mapID != originalMapId)
|
||||
tcflags |= MOD_PARENT_SPAWN;
|
||||
|
||||
//write mapID, tileX, tileY, Flags, ID, Pos, Rot, Scale, name
|
||||
//write mapID, tileX, tileY, Flags, NameSet, UniqueId, Pos, Rot, Scale, name
|
||||
fwrite(&mapID, sizeof(uint32), 1, pDirfile);
|
||||
fwrite(&tileX, sizeof(uint32), 1, pDirfile);
|
||||
fwrite(&tileY, sizeof(uint32), 1, pDirfile);
|
||||
fwrite(&tcflags, sizeof(uint32), 1, pDirfile);
|
||||
fwrite(&adtId, sizeof(uint16), 1, pDirfile);
|
||||
fwrite(&id, sizeof(uint32), 1, pDirfile);
|
||||
fwrite(&pos, sizeof(float), 3, pDirfile);
|
||||
fwrite(&rot, sizeof(float), 3, pDirfile);
|
||||
fwrite(&nameSet, sizeof(uint16), 1, pDirfile);
|
||||
fwrite(&doodadDef.UniqueId, sizeof(uint32), 1, pDirfile);
|
||||
fwrite(&position, sizeof(Vec3D), 1, pDirfile);
|
||||
fwrite(&doodadDef.Rotation, sizeof(Vec3D), 1, pDirfile);
|
||||
fwrite(&sc, sizeof(float), 1, pDirfile);
|
||||
uint32 nlen = strlen(ModelInstName);
|
||||
fwrite(&nlen, sizeof(uint32), 1, pDirfile);
|
||||
@@ -214,41 +205,25 @@ ModelInstance::ModelInstance(CASCFile& f, char const* ModelInstName, uint32 mapI
|
||||
ADTOutputCache& cacheModelData = dirfileCache->back();
|
||||
cacheModelData.Flags = tcflags & ~MOD_PARENT_SPAWN;
|
||||
cacheModelData.Data.resize(
|
||||
sizeof(uint16) + // adtId
|
||||
sizeof(uint32) + // id
|
||||
sizeof(float) * 3 + // pos
|
||||
sizeof(float) * 3 + // rot
|
||||
sizeof(uint16) + // nameSet
|
||||
sizeof(uint32) + // doodadDef.UniqueId
|
||||
sizeof(Vec3D) + // position
|
||||
sizeof(Vec3D) + // doodadDef.Rotation
|
||||
sizeof(float) + // sc
|
||||
sizeof(uint32) + // nlen
|
||||
nlen); // ModelInstName
|
||||
|
||||
uint8* cacheData = cacheModelData.Data.data();
|
||||
#define CACHE_WRITE(value, size, count, dest) memcpy(dest, value, size * count); dest += size * count;
|
||||
#define CACHE_WRITE(value, size, cnt, dest) memcpy(dest, value, size * cnt); dest += size * cnt;
|
||||
|
||||
CACHE_WRITE(&adtId, sizeof(uint16), 1, cacheData);
|
||||
CACHE_WRITE(&id, sizeof(uint32), 1, cacheData);
|
||||
CACHE_WRITE(&pos, sizeof(float), 3, cacheData);
|
||||
CACHE_WRITE(&rot, sizeof(float), 3, cacheData);
|
||||
CACHE_WRITE(&nameSet, sizeof(uint16), 1, cacheData);
|
||||
CACHE_WRITE(&doodadDef.UniqueId, sizeof(uint32), 1, cacheData);
|
||||
CACHE_WRITE(&position, sizeof(Vec3D), 1, cacheData);
|
||||
CACHE_WRITE(&doodadDef.Rotation, sizeof(Vec3D), 1, cacheData);
|
||||
CACHE_WRITE(&sc, sizeof(float), 1, cacheData);
|
||||
CACHE_WRITE(&nlen, sizeof(uint32), 1, cacheData);
|
||||
CACHE_WRITE(ModelInstName, sizeof(char), nlen, cacheData);
|
||||
|
||||
#undef CACHE_WRITE
|
||||
}
|
||||
|
||||
/* int realx1 = (int) ((float) pos.x / 533.333333f);
|
||||
int realy1 = (int) ((float) pos.z / 533.333333f);
|
||||
int realx2 = (int) ((float) pos.x / 533.333333f);
|
||||
int realy2 = (int) ((float) pos.z / 533.333333f);
|
||||
|
||||
fprintf(pDirfile,"%s/%s %f,%f,%f_%f,%f,%f %f %d %d %d,%d %d\n",
|
||||
MapName,
|
||||
ModelInstName,
|
||||
(float) pos.x, (float) pos.y, (float) pos.z,
|
||||
(float) rot.x, (float) rot.y, (float) rot.z,
|
||||
sc,
|
||||
nVertices,
|
||||
realx1, realy1,
|
||||
realx2, realy2
|
||||
); */
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
class CASCFile;
|
||||
struct ADTOutputCache;
|
||||
namespace ADT { struct MDDF; }
|
||||
|
||||
Vec3D fixCoordSystem(Vec3D v);
|
||||
|
||||
@@ -51,17 +52,9 @@ public:
|
||||
~Model() { _unload(); }
|
||||
};
|
||||
|
||||
class ModelInstance
|
||||
namespace Doodad
|
||||
{
|
||||
public:
|
||||
uint32 id;
|
||||
Vec3D pos, rot;
|
||||
uint16 scale, flags;
|
||||
float sc;
|
||||
|
||||
ModelInstance() : id(0), scale(0), flags(0), sc(0.0f) {}
|
||||
ModelInstance(CASCFile& f, char const* ModelInstName, uint32 mapID, uint32 tileX, uint32 tileY, uint32 originalMapId, FILE* pDirfile, std::vector<ADTOutputCache>* dirfileCache);
|
||||
|
||||
};
|
||||
void Extract(ADT::MDDF const& doodadDef, char const* ModelInstName, uint32 mapID, uint32 tileX, uint32 tileY, uint32 originalMapId, FILE* pDirfile, std::vector<ADTOutputCache>* dirfileCache);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -137,6 +137,12 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class AaBox3D
|
||||
{
|
||||
public:
|
||||
Vec3D min;
|
||||
Vec3D max;
|
||||
};
|
||||
|
||||
class Vec2D
|
||||
{
|
||||
|
||||
@@ -70,7 +70,6 @@ bool preciseVectorData = false;
|
||||
|
||||
//static const char * szWorkDirMaps = ".\\Maps";
|
||||
const char* szWorkDirWmo = "./Buildings";
|
||||
const char* szRawVMAPMagic = "VMAP046";
|
||||
|
||||
#define CASC_LOCALES_COUNT 17
|
||||
char const* CascLocaleNames[CASC_LOCALES_COUNT] =
|
||||
@@ -214,7 +213,7 @@ bool ExtractSingleWmo(std::string& fname)
|
||||
{
|
||||
std::string s = Trinity::StringFormat("FILE%08X.xxx", froot.groupFileDataIDs[i]);
|
||||
WMOGroup fgroup(s);
|
||||
if(!fgroup.open())
|
||||
if (!fgroup.open(&froot))
|
||||
{
|
||||
printf("Could not open all Group file for: %s\n", plain_name);
|
||||
file_ok = false;
|
||||
|
||||
@@ -30,7 +30,6 @@ enum ModelFlags
|
||||
};
|
||||
|
||||
extern const char * szWorkDirWmo;
|
||||
extern const char * szRawVMAPMagic; // vmap magic string for extracted raw vmap data
|
||||
|
||||
bool FileExists(const char * file);
|
||||
void strToLower(char* str);
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "wdtfile.h"
|
||||
#include "adtfile.h"
|
||||
#include "Common.h"
|
||||
#include "StringFormat.h"
|
||||
#include <cstdio>
|
||||
|
||||
char * wdtGetPlainName(char * FileName)
|
||||
@@ -104,13 +105,21 @@ bool WDTFile::init(uint32 mapId)
|
||||
// global wmo instance data
|
||||
if (size)
|
||||
{
|
||||
int32 gnWMO = (int)size / 64;
|
||||
|
||||
for (int i = 0; i < gnWMO; ++i)
|
||||
uint32 mapObjectCount = size / sizeof(ADT::MODF);
|
||||
for (uint32 i = 0; i < mapObjectCount; ++i)
|
||||
{
|
||||
int id;
|
||||
_file.read(&id, 4);
|
||||
WMOInstance inst(_file, _wmoNames[id].c_str(), mapId, 65, 65, mapId, dirfile, nullptr);
|
||||
ADT::MODF mapObjDef;
|
||||
_file.read(&mapObjDef, sizeof(ADT::MODF));
|
||||
if (!(mapObjDef.Flags & 0x8))
|
||||
{
|
||||
MapObject::Extract(mapObjDef, _wmoNames[mapObjDef.Id].c_str(), mapId, 65, 65, mapId, dirfile, nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string fileName = Trinity::StringFormat("FILE%08X.xxx", mapObjDef.Id);
|
||||
ExtractSingleModel(fileName);
|
||||
MapObject::Extract(mapObjDef, fileName.c_str(), mapId, 65, 65, mapId, dirfile, nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "wmo.h"
|
||||
#include "adtfile.h"
|
||||
#include "vec3d.h"
|
||||
#include "VMapDefinitions.h"
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cassert>
|
||||
@@ -29,8 +30,6 @@
|
||||
#undef max
|
||||
#include "cascfile.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
WMORoot::WMORoot(std::string &filename)
|
||||
: filename(filename), color(0), nTextures(0), nGroups(0), nPortals(0), nLights(0),
|
||||
nDoodadNames(0), nDoodadDefs(0), nDoodadSets(0), RootWMOID(0), flags(0), numLod(0)
|
||||
@@ -102,7 +101,6 @@ bool WMORoot::open()
|
||||
if (fileDataId)
|
||||
groupFileDataIDs.push_back(fileDataId);
|
||||
}
|
||||
// break;
|
||||
//}
|
||||
}
|
||||
/*
|
||||
@@ -156,7 +154,7 @@ bool WMORoot::ConvertToVMAPRootWmo(FILE* pOutfile)
|
||||
{
|
||||
//printf("Convert RootWmo...\n");
|
||||
|
||||
fwrite(szRawVMAPMagic, 1, 8, pOutfile);
|
||||
fwrite(VMAP::RAW_VMAP_MAGIC, 1, 8, pOutfile);
|
||||
unsigned int nVectors = 0;
|
||||
fwrite(&nVectors,sizeof(nVectors), 1, pOutfile); // will be filled later
|
||||
fwrite(&nGroups, 4, 1, pOutfile);
|
||||
@@ -168,14 +166,14 @@ WMOGroup::WMOGroup(const std::string &filename) :
|
||||
filename(filename), MOPY(0), MOVI(0), MoviEx(0), MOVT(0), MOBA(0), MobaEx(0),
|
||||
hlq(0), LiquEx(0), LiquBytes(0), groupName(0), descGroupName(0), mogpFlags(0),
|
||||
moprIdx(0), moprNItems(0), nBatchA(0), nBatchB(0), nBatchC(0), fogIdx(0),
|
||||
liquidType(0), groupWMOID(0), mopy_size(0), moba_size(0), LiquEx_size(0),
|
||||
groupLiquid(0), groupWMOID(0), mopy_size(0), moba_size(0), LiquEx_size(0),
|
||||
nVertices(0), nTriangles(0), liquflags(0)
|
||||
{
|
||||
memset(bbcorn1, 0, sizeof(bbcorn1));
|
||||
memset(bbcorn2, 0, sizeof(bbcorn2));
|
||||
}
|
||||
|
||||
bool WMOGroup::open()
|
||||
bool WMOGroup::open(WMORoot* rootWMO)
|
||||
{
|
||||
CASCFile f(CascStorage, filename.c_str());
|
||||
if(f.isEof ())
|
||||
@@ -209,9 +207,19 @@ bool WMOGroup::open()
|
||||
f.read(&nBatchB, 2);
|
||||
f.read(&nBatchC, 4);
|
||||
f.read(&fogIdx, 4);
|
||||
f.read(&liquidType, 4);
|
||||
f.read(&groupLiquid, 4);
|
||||
f.read(&groupWMOID,4);
|
||||
|
||||
// according to WoW.Dev Wiki:
|
||||
if (rootWMO->flags & 4)
|
||||
groupLiquid = GetLiquidTypeId(groupLiquid);
|
||||
else if (groupLiquid == 15)
|
||||
groupLiquid = 0;
|
||||
else
|
||||
groupLiquid = GetLiquidTypeId(groupLiquid + 1);
|
||||
|
||||
if (groupLiquid)
|
||||
liquflags |= 2;
|
||||
}
|
||||
else if (!strcmp(fourcc,"MOPY"))
|
||||
{
|
||||
@@ -247,7 +255,7 @@ bool WMOGroup::open()
|
||||
{
|
||||
liquflags |= 1;
|
||||
hlq = new WMOLiquidHeader();
|
||||
f.read(hlq, 0x1E);
|
||||
f.read(hlq, sizeof(WMOLiquidHeader));
|
||||
LiquEx_size = sizeof(WMOLiquidVert) * hlq->xverts * hlq->yverts;
|
||||
LiquEx = new WMOLiquidVert[hlq->xverts * hlq->yverts];
|
||||
f.read(LiquEx, LiquEx_size);
|
||||
@@ -255,6 +263,19 @@ bool WMOGroup::open()
|
||||
LiquBytes = new char[nLiquBytes];
|
||||
f.read(LiquBytes, nLiquBytes);
|
||||
|
||||
// Determine legacy liquid type
|
||||
if (!groupLiquid)
|
||||
{
|
||||
for (int i = 0; i < hlq->xtiles * hlq->ytiles; ++i)
|
||||
{
|
||||
if ((LiquBytes[i] & 0xF) != 15)
|
||||
{
|
||||
groupLiquid = GetLiquidTypeId((LiquBytes[i] & 0xF) + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* std::ofstream llog("Buildings/liquid.log", ios_base::out | ios_base::app);
|
||||
llog << filename;
|
||||
llog << "\nbbox: " << bbcorn1[0] << ", " << bbcorn1[1] << ", " << bbcorn1[2] << " | " << bbcorn2[0] << ", " << bbcorn2[1] << ", " << bbcorn2[2];
|
||||
@@ -429,78 +450,54 @@ int WMOGroup::ConvertToVMAPGroupWmo(FILE *output, WMORoot *rootWMO, bool precise
|
||||
}
|
||||
|
||||
//------LIQU------------------------
|
||||
if (LiquEx_size != 0)
|
||||
if (liquflags & 3)
|
||||
{
|
||||
int LIQU_h[] = {0x5551494C, static_cast<int>(sizeof(WMOLiquidHeader) + LiquEx_size) + hlq->xtiles*hlq->ytiles};// "LIQU"
|
||||
int LIQU_totalSize = sizeof(uint32);
|
||||
if (liquflags & 1)
|
||||
{
|
||||
LIQU_totalSize += sizeof(WMOLiquidHeader);
|
||||
LIQU_totalSize += LiquEx_size / sizeof(WMOLiquidVert) * sizeof(float);
|
||||
LIQU_totalSize += hlq->xtiles * hlq->ytiles;
|
||||
}
|
||||
int LIQU_h[] = { 0x5551494C, LIQU_totalSize };// "LIQU"
|
||||
fwrite(LIQU_h, 4, 2, output);
|
||||
|
||||
// according to WoW.Dev Wiki:
|
||||
uint32 liquidEntry;
|
||||
if (rootWMO->flags & 4)
|
||||
liquidEntry = liquidType;
|
||||
else if (liquidType == 15)
|
||||
liquidEntry = 0;
|
||||
else
|
||||
liquidEntry = liquidType + 1;
|
||||
|
||||
if (!liquidEntry)
|
||||
{
|
||||
int v1; // edx@1
|
||||
int v2; // eax@1
|
||||
|
||||
v1 = hlq->xtiles * hlq->ytiles;
|
||||
v2 = 0;
|
||||
if (v1 > 0)
|
||||
{
|
||||
while ((LiquBytes[v2] & 0xF) == 15)
|
||||
{
|
||||
++v2;
|
||||
if (v2 >= v1)
|
||||
break;
|
||||
}
|
||||
|
||||
if (v2 < v1 && (LiquBytes[v2] & 0xF) != 15)
|
||||
liquidEntry = (LiquBytes[v2] & 0xF) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (liquidEntry && liquidEntry < 21)
|
||||
{
|
||||
switch ((liquidEntry - 1) & 3)
|
||||
{
|
||||
case 0:
|
||||
liquidEntry = ((mogpFlags & 0x80000) != 0) + 13;
|
||||
break;
|
||||
case 1:
|
||||
liquidEntry = 14;
|
||||
break;
|
||||
case 2:
|
||||
liquidEntry = 19;
|
||||
break;
|
||||
case 3:
|
||||
liquidEntry = 20;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
hlq->type = liquidEntry;
|
||||
|
||||
/* std::ofstream llog("Buildings/liquid.log", ios_base::out | ios_base::app);
|
||||
llog << filename;
|
||||
llog << ":\nliquidEntry: " << liquidEntry << " type: " << hlq->type << " (root:" << rootWMO->flags << " group:" << flags << ")\n";
|
||||
llog.close(); */
|
||||
|
||||
fwrite(hlq, sizeof(WMOLiquidHeader), 1, output);
|
||||
// only need height values, the other values are unknown anyway
|
||||
for (uint32 i = 0; i<LiquEx_size/sizeof(WMOLiquidVert); ++i)
|
||||
fwrite(&LiquEx[i].height, sizeof(float), 1, output);
|
||||
// todo: compress to bit field
|
||||
fwrite(LiquBytes, 1, hlq->xtiles*hlq->ytiles, output);
|
||||
fwrite(&groupLiquid, sizeof(uint32), 1, output);
|
||||
if (liquflags & 1)
|
||||
{
|
||||
fwrite(hlq, sizeof(WMOLiquidHeader), 1, output);
|
||||
// only need height values, the other values are unknown anyway
|
||||
for (uint32 i = 0; i < LiquEx_size / sizeof(WMOLiquidVert); ++i)
|
||||
fwrite(&LiquEx[i].height, sizeof(float), 1, output);
|
||||
// todo: compress to bit field
|
||||
fwrite(LiquBytes, 1, hlq->xtiles * hlq->ytiles, output);
|
||||
}
|
||||
}
|
||||
|
||||
return nColTriangles;
|
||||
}
|
||||
|
||||
uint32 WMOGroup::GetLiquidTypeId(uint32 liquidTypeId)
|
||||
{
|
||||
if (liquidTypeId < 21 && liquidTypeId)
|
||||
{
|
||||
switch (((static_cast<uint8>(liquidTypeId) - 1) & 3))
|
||||
{
|
||||
case 0: return ((mogpFlags & 0x80000) != 0) + 13;
|
||||
case 1: return 14;
|
||||
case 2: return 19;
|
||||
case 3: return 20;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
return liquidTypeId;
|
||||
}
|
||||
|
||||
WMOGroup::~WMOGroup()
|
||||
{
|
||||
delete [] MOPY;
|
||||
@@ -512,33 +509,11 @@ WMOGroup::~WMOGroup()
|
||||
delete [] LiquBytes;
|
||||
}
|
||||
|
||||
WMOInstance::WMOInstance(CASCFile& f, char const* WmoInstName, uint32 mapID, uint32 tileX, uint32 tileY, uint32 originalMapId, FILE* pDirfile, std::vector<ADTOutputCache>* dirfileCache)
|
||||
: currx(0), curry(0), wmo(NULL), doodadset(0), pos(), indx(0), id(0)
|
||||
void MapObject::Extract(ADT::MODF const& mapObjDef, char const* WmoInstName, uint32 mapID, uint32 tileX, uint32 tileY, uint32 originalMapId, FILE* pDirfile, std::vector<ADTOutputCache>* dirfileCache)
|
||||
{
|
||||
float ff[3];
|
||||
f.read(&id, 4);
|
||||
f.read(ff,12);
|
||||
pos = Vec3D(ff[0],ff[1],ff[2]);
|
||||
f.read(ff,12);
|
||||
rot = Vec3D(ff[0],ff[1],ff[2]);
|
||||
f.read(ff,12);
|
||||
pos2 = Vec3D(ff[0],ff[1],ff[2]); // bounding box corners
|
||||
f.read(ff,12);
|
||||
pos3 = Vec3D(ff[0],ff[1],ff[2]); // bounding box corners
|
||||
|
||||
uint16 fflags;
|
||||
f.read(&fflags, 2);
|
||||
|
||||
uint16 doodadSet;
|
||||
f.read(&doodadSet, 2);
|
||||
|
||||
uint16 trash,adtId;
|
||||
f.read(&adtId,2);
|
||||
f.read(&trash,2);
|
||||
|
||||
// destructible wmo, do not dump. we can handle the vmap for these
|
||||
// in dynamic tree (gameobject vmaps)
|
||||
if ((fflags & 0x01) != 0)
|
||||
if ((mapObjDef.Flags & 0x1) != 0)
|
||||
return;
|
||||
|
||||
//-----------add_in _dir_file----------------
|
||||
@@ -562,37 +537,41 @@ WMOInstance::WMOInstance(CASCFile& f, char const* WmoInstName, uint32 mapID, uin
|
||||
if (count != 1 || nVertices == 0)
|
||||
return;
|
||||
|
||||
float x,z;
|
||||
x = pos.x;
|
||||
z = pos.z;
|
||||
if(x==0 && z == 0)
|
||||
Vec3D position = mapObjDef.Position;
|
||||
|
||||
float x, z;
|
||||
x = position.x;
|
||||
z = position.z;
|
||||
if (x == 0 && z == 0)
|
||||
{
|
||||
pos.x = 533.33333f*32;
|
||||
pos.z = 533.33333f*32;
|
||||
position.x = 533.33333f * 32;
|
||||
position.z = 533.33333f * 32;
|
||||
}
|
||||
pos = fixCoords(pos);
|
||||
pos2 = fixCoords(pos2);
|
||||
pos3 = fixCoords(pos3);
|
||||
position = fixCoords(position);
|
||||
AaBox3D bounds;
|
||||
bounds.min = fixCoords(mapObjDef.Bounds.min);
|
||||
bounds.max = fixCoords(mapObjDef.Bounds.max);
|
||||
|
||||
float scale = 1.0f;
|
||||
if (mapObjDef.Flags & 0x4)
|
||||
scale = mapObjDef.Scale / 1024.0f;
|
||||
uint32 flags = MOD_HAS_BOUND;
|
||||
if (tileX == 65 && tileY == 65)
|
||||
flags |= MOD_WORLDSPAWN;
|
||||
if (mapID != originalMapId)
|
||||
flags |= MOD_PARENT_SPAWN;
|
||||
|
||||
//write mapID, tileX, tileY, Flags, ID, Pos, Rot, Scale, Bound_lo, Bound_hi, name
|
||||
//write mapID, tileX, tileY, Flags, NameSet, UniqueId, Pos, Rot, Scale, Bound_lo, Bound_hi, name
|
||||
fwrite(&mapID, sizeof(uint32), 1, pDirfile);
|
||||
fwrite(&tileX, sizeof(uint32), 1, pDirfile);
|
||||
fwrite(&tileY, sizeof(uint32), 1, pDirfile);
|
||||
fwrite(&flags, sizeof(uint32), 1, pDirfile);
|
||||
fwrite(&adtId, sizeof(uint16), 1, pDirfile);
|
||||
fwrite(&id, sizeof(uint32), 1, pDirfile);
|
||||
fwrite(&pos, sizeof(float), 3, pDirfile);
|
||||
fwrite(&rot, sizeof(float), 3, pDirfile);
|
||||
fwrite(&mapObjDef.NameSet, sizeof(uint16), 1, pDirfile);
|
||||
fwrite(&mapObjDef.UniqueId, sizeof(uint32), 1, pDirfile);
|
||||
fwrite(&position, sizeof(Vec3D), 1, pDirfile);
|
||||
fwrite(&mapObjDef.Rotation, sizeof(Vec3D), 1, pDirfile);
|
||||
fwrite(&scale, sizeof(float), 1, pDirfile);
|
||||
fwrite(&pos2, sizeof(float), 3, pDirfile);
|
||||
fwrite(&pos3, sizeof(float), 3, pDirfile);
|
||||
fwrite(&bounds, sizeof(AaBox3D), 1, pDirfile);
|
||||
uint32 nlen = strlen(WmoInstName);
|
||||
fwrite(&nlen, sizeof(uint32), 1, pDirfile);
|
||||
fwrite(WmoInstName, sizeof(char), nlen, pDirfile);
|
||||
@@ -603,41 +582,27 @@ WMOInstance::WMOInstance(CASCFile& f, char const* WmoInstName, uint32 mapID, uin
|
||||
ADTOutputCache& cacheModelData = dirfileCache->back();
|
||||
cacheModelData.Flags = flags & ~MOD_PARENT_SPAWN;
|
||||
cacheModelData.Data.resize(
|
||||
sizeof(uint16) + // adtId
|
||||
sizeof(uint32) + // id
|
||||
sizeof(float) * 3 + // pos
|
||||
sizeof(float) * 3 + // rot
|
||||
sizeof(uint16) + // mapObjDef.NameSet
|
||||
sizeof(uint32) + // mapObjDef.UniqueId
|
||||
sizeof(Vec3D) + // position
|
||||
sizeof(Vec3D) + // mapObjDef.Rotation
|
||||
sizeof(float) + // scale
|
||||
sizeof(float) * 3 + // pos2
|
||||
sizeof(float) * 3 + // pos3
|
||||
sizeof(AaBox3D) + // bounds
|
||||
sizeof(uint32) + // nlen
|
||||
nlen); // WmoInstName
|
||||
|
||||
uint8* cacheData = cacheModelData.Data.data();
|
||||
#define CACHE_WRITE(value, size, count, dest) memcpy(dest, value, size * count); dest += size * count;
|
||||
|
||||
CACHE_WRITE(&adtId, sizeof(uint16), 1, cacheData);
|
||||
CACHE_WRITE(&id, sizeof(uint32), 1, cacheData);
|
||||
CACHE_WRITE(&pos, sizeof(float), 3, cacheData);
|
||||
CACHE_WRITE(&rot, sizeof(float), 3, cacheData);
|
||||
CACHE_WRITE(&mapObjDef.NameSet, sizeof(uint16), 1, cacheData);
|
||||
CACHE_WRITE(&mapObjDef.UniqueId, sizeof(uint32), 1, cacheData);
|
||||
CACHE_WRITE(&position, sizeof(Vec3D), 1, cacheData);
|
||||
CACHE_WRITE(&mapObjDef.Rotation, sizeof(Vec3D), 1, cacheData);
|
||||
CACHE_WRITE(&scale, sizeof(float), 1, cacheData);
|
||||
CACHE_WRITE(&pos2, sizeof(float), 3, cacheData);
|
||||
CACHE_WRITE(&pos3, sizeof(float), 3, cacheData);
|
||||
CACHE_WRITE(&bounds, sizeof(AaBox3D), 1, cacheData);
|
||||
CACHE_WRITE(&nlen, sizeof(uint32), 1, cacheData);
|
||||
CACHE_WRITE(WmoInstName, sizeof(char), nlen, cacheData);
|
||||
|
||||
#undef CACHE_WRITE
|
||||
}
|
||||
|
||||
/* fprintf(pDirfile,"%s/%s %f,%f,%f_%f,%f,%f 1.0 %d %d %d,%d %d\n",
|
||||
MapName,
|
||||
WmoInstName,
|
||||
(float) x, (float) pos.y, (float) z,
|
||||
(float) rot.x, (float) rot.y, (float) rot.z,
|
||||
nVertices,
|
||||
realx1, realy1,
|
||||
realx2, realy2
|
||||
); */
|
||||
|
||||
// fclose(dirfile);
|
||||
}
|
||||
|
||||
@@ -18,8 +18,6 @@
|
||||
|
||||
#ifndef WMO_H
|
||||
#define WMO_H
|
||||
#define TILESIZE (533.33333f)
|
||||
#define CHUNKSIZE ((TILESIZE) / 16.0f)
|
||||
|
||||
#include <string>
|
||||
#include <set>
|
||||
@@ -44,6 +42,7 @@ class WMOInstance;
|
||||
class WMOManager;
|
||||
class CASCFile;
|
||||
struct ADTOutputCache;
|
||||
namespace ADT { struct MODF; }
|
||||
|
||||
/* for whatever reason a certain company just can't stick to one coordinate system... */
|
||||
static inline Vec3D fixCoords(const Vec3D &v){ return Vec3D(v.z, v.x, v.y); }
|
||||
@@ -67,17 +66,17 @@ public:
|
||||
bool ConvertToVMAPRootWmo(FILE* output);
|
||||
};
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
struct WMOLiquidHeader
|
||||
{
|
||||
int xverts, yverts, xtiles, ytiles;
|
||||
float pos_x;
|
||||
float pos_y;
|
||||
float pos_z;
|
||||
short type;
|
||||
short material;
|
||||
};
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
struct WMOLiquidVert
|
||||
{
|
||||
uint16 unk1;
|
||||
@@ -111,7 +110,7 @@ public:
|
||||
uint16 moprNItems;
|
||||
uint16 nBatchA;
|
||||
uint16 nBatchB;
|
||||
uint32 nBatchC, fogIdx, liquidType, groupWMOID;
|
||||
uint32 nBatchC, fogIdx, groupLiquid, groupWMOID;
|
||||
|
||||
int mopy_size, moba_size;
|
||||
int LiquEx_size;
|
||||
@@ -122,24 +121,14 @@ public:
|
||||
WMOGroup(std::string const& filename);
|
||||
~WMOGroup();
|
||||
|
||||
bool open();
|
||||
bool open(WMORoot* rootWMO);
|
||||
int ConvertToVMAPGroupWmo(FILE* output, WMORoot* rootWMO, bool preciseVectorData);
|
||||
uint32 GetLiquidTypeId(uint32 liquidTypeId);
|
||||
};
|
||||
|
||||
class WMOInstance
|
||||
namespace MapObject
|
||||
{
|
||||
static std::set<int> ids;
|
||||
public:
|
||||
std::string MapName;
|
||||
int currx;
|
||||
int curry;
|
||||
WMOGroup* wmo;
|
||||
int doodadset;
|
||||
Vec3D pos;
|
||||
Vec3D pos2, pos3, rot;
|
||||
uint32 indx, id;
|
||||
|
||||
WMOInstance(CASCFile&f , char const* WmoInstName, uint32 mapID, uint32 tileX, uint32 tileY, uint32 originalMapId, FILE* pDirfile, std::vector<ADTOutputCache>* dirfileCache);
|
||||
};
|
||||
void Extract(ADT::MODF const& mapObjDef, char const* WmoInstName, uint32 mapID, uint32 tileX, uint32 tileY, uint32 originalMapId, FILE* pDirfile, std::vector<ADTOutputCache>* dirfileCache);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user