diff --git a/src/common/Collision/Maps/TileAssembler.cpp b/src/common/Collision/Maps/TileAssembler.cpp index 3cf5314a87..2714c8907a 100644 --- a/src/common/Collision/Maps/TileAssembler.cpp +++ b/src/common/Collision/Maps/TileAssembler.cpp @@ -225,7 +225,7 @@ namespace VMAP ModelSpawn spawn; while (!feof(dirf)) { - // read mapID, tileX, tileY, Flags, NameSet, UniqueId, Pos, Rot, Scale, Bound_lo, Bound_hi, name + // read mapID, tileX, tileY, Flags, adtID, ID, Pos, Rot, Scale, Bound_lo, Bound_hi, name check = fread(&mapID, sizeof(uint32), 1, dirf); if (check == 0) // EoF... break; @@ -298,16 +298,14 @@ 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 material; + short type; }; -#pragma pack(pop) //================================================================= bool TileAssembler::convertRawFile(const std::string& pModelFilename) { @@ -351,13 +349,6 @@ 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) - { - fclose(model_list); - return; - } - FILE* model_list_copy = fopen((iDestDir + "/" + GAMEOBJECT_MODELS).c_str(), "wb"); if (!model_list_copy) { @@ -365,10 +356,7 @@ namespace VMAP return; } - fwrite(VMAP::VMAP_MAGIC, 1, 8, model_list_copy); - uint32 name_length, displayId; - uint8 isWmo; char buff[500]; while (true) { @@ -376,8 +364,7 @@ namespace VMAP if (feof(model_list)) // EOF flag is only set after failed reading attempt break; - if (fread(&isWmo, sizeof(uint8), 1, model_list) != 1 - || fread(&name_length, sizeof(uint32), 1, model_list) != 1 + if (fread(&name_length, sizeof(uint32), 1, model_list) != 1 || name_length >= sizeof(buff) || fread(&buff, sizeof(char), name_length, model_list) != name_length) { @@ -422,7 +409,6 @@ 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); @@ -507,34 +493,25 @@ namespace VMAP delete[] vectorarray; } // ----- liquid - liquid = nullptr; - if (liquidflags & 3) + liquid = 0; + if (liquidflags& 1) { + WMOLiquidHeader hlq; READ_OR_RETURN(&blockId, 4); CMP_OR_RETURN(blockId, "LIQU"); READ_OR_RETURN(&blocksize, sizeof(int)); - 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; - } + 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); } return true; } + GroupModel_Raw::~GroupModel_Raw() { delete liquid; diff --git a/src/common/Collision/Models/GameObjectModel.cpp b/src/common/Collision/Models/GameObjectModel.cpp index fb113172d7..1c5f7ada0b 100644 --- a/src/common/Collision/Models/GameObjectModel.cpp +++ b/src/common/Collision/Models/GameObjectModel.cpp @@ -30,12 +30,11 @@ using G3D::AABox; struct GameobjectModelData { - GameobjectModelData(char const* name_, uint32 nameLength, Vector3 const& lowBound, Vector3 const& highBound, bool isWmo_) : - bound(lowBound, highBound), name(name_, nameLength), isWmo(isWmo_) { } + GameobjectModelData(const std::string& name_, const AABox& box) : + bound(box), name(name_) { } AABox bound; std::string name; - bool isWmo; }; typedef std::unordered_map ModelList; @@ -54,17 +53,7 @@ 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); - fclose(model_list_file); - return; - } - uint32 name_length, displayId; - uint8 isWmo; char buff[500]; while (true) { @@ -73,8 +62,7 @@ void LoadGameObjectModelList(std::string const& dataPath) if (feof(model_list_file)) // EOF flag is only set after failed reading attempt break; - if (fread(&isWmo, sizeof(uint8), 1, model_list_file) != 1 - || fread(&name_length, sizeof(uint32), 1, model_list_file) != 1 + if (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 @@ -90,7 +78,10 @@ void LoadGameObjectModelList(std::string const& dataPath) continue; } - model_list.emplace(std::piecewise_construct, std::forward_as_tuple(displayId), std::forward_as_tuple(&buff[0], name_length, v1, v2, isWmo != 0)); + model_list.insert + ( + ModelList::value_type(displayId, GameobjectModelData(std::string(buff, name_length), AABox(v1, v2))) + ); } fclose(model_list_file); diff --git a/src/common/Collision/Models/GameObjectModel.h b/src/common/Collision/Models/GameObjectModel.h index 3dec7fdfa1..a8dd854775 100644 --- a/src/common/Collision/Models/GameObjectModel.h +++ b/src/common/Collision/Models/GameObjectModel.h @@ -40,15 +40,14 @@ struct GameObjectDisplayInfoEntry; class TC_COMMON_API GameObjectModelOwnerBase { public: - virtual ~GameObjectModelOwnerBase() = default; - - virtual bool IsSpawned() const = 0; - virtual uint32 GetDisplayId() 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; + virtual bool IsSpawned() const { return false; } + virtual uint32 GetDisplayId() 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 ~GameObjectModelOwnerBase() { } }; class TC_COMMON_API GameObjectModel /*, public Intersectable*/ diff --git a/src/common/Collision/Models/WorldModel.cpp b/src/common/Collision/Models/WorldModel.cpp index 465fda2f0c..58c47c1d63 100644 --- a/src/common/Collision/Models/WorldModel.cpp +++ b/src/common/Collision/Models/WorldModel.cpp @@ -105,16 +105,8 @@ namespace VMAP WmoLiquid::WmoLiquid(uint32 width, uint32 height, const Vector3 &corner, uint32 type): iTilesX(width), iTilesY(height), iCorner(corner), iType(type) { - if (width && height) - { - iHeight = new float[(width + 1) * (height + 1)]; - iFlags = new uint8[width * height]; - } - else - { - iHeight = new float[1]; - iFlags = nullptr; - } + iHeight = new float[(width+1)*(height+1)]; + iFlags = new uint8[width*height]; } WmoLiquid::WmoLiquid(const WmoLiquid &other): iHeight(nullptr), iFlags(nullptr) @@ -157,13 +149,6 @@ 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) @@ -215,8 +200,8 @@ namespace VMAP { return 2 * sizeof(uint32) + sizeof(Vector3) + - sizeof(uint32) + - (iFlags ? ((iTilesX + 1) * (iTilesY + 1) * sizeof(float) + iTilesX * iTilesY) : sizeof(float)); + (iTilesX + 1)*(iTilesY + 1) * sizeof(float) + + iTilesX * iTilesY; } bool WmoLiquid::writeToFile(FILE* wf) @@ -227,17 +212,12 @@ namespace VMAP fwrite(&iCorner, sizeof(Vector3), 1, wf) == 1 && fwrite(&iType, sizeof(uint32), 1, wf) == 1) { - if (iTilesX && iTilesY) + uint32 size = (iTilesX + 1) * (iTilesY + 1); + if (fwrite(iHeight, sizeof(float), 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; - } + size = iTilesX*iTilesY; + result = fwrite(iFlags, sizeof(uint8), size, wf) == size; } - else - result = fwrite(iHeight, sizeof(float), 1, wf) == 1; } return result; @@ -253,21 +233,13 @@ namespace VMAP fread(&liquid->iCorner, sizeof(Vector3), 1, rf) == 1 && fread(&liquid->iType, sizeof(uint32), 1, rf) == 1) { - if (liquid->iTilesX && liquid->iTilesY) + uint32 size = (liquid->iTilesX + 1) * (liquid->iTilesY + 1); + liquid->iHeight = new float[size]; + if (fread(liquid->iHeight, sizeof(float), 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; + size = liquid->iTilesX * liquid->iTilesY; + liquid->iFlags = new uint8[size]; + result = fread(liquid->iFlags, sizeof(uint8), size, rf) == size; } } diff --git a/src/common/Collision/VMapDefinitions.h b/src/common/Collision/VMapDefinitions.h index c8f3f2fdbe..5410eb2130 100644 --- a/src/common/Collision/VMapDefinitions.h +++ b/src/common/Collision/VMapDefinitions.h @@ -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.5"; + const char RAW_VMAP_MAGIC[] = "VMAP045"; // used in extracted vmap files with raw data const char GAMEOBJECT_MODELS[] = "GameObjectModels.dtree"; // defined in TileAssembler.cpp currently... diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index f4d9d044b6..3b310a7b5c 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -46,7 +46,7 @@ #include "WeatherMgr.h" u_map_magic MapMagic = { {'M','A','P','S'} }; -u_map_magic MapVersionMagic = { {'v','1','.','7'} }; +u_map_magic MapVersionMagic = { {'v','1','.','6'} }; u_map_magic MapAreaMagic = { {'A','R','E','A'} }; u_map_magic MapHeightMagic = { {'M','H','G','T'} }; u_map_magic MapLiquidMagic = { {'M','L','I','Q'} }; @@ -1741,8 +1741,7 @@ GridMap::GridMap() m_V9 = nullptr; m_V8 = nullptr; // Liquid data - _liquidGlobalEntry = 0; - _liquidGlobalFlags = 0; + _liquidType = 0; _liquidOffX = 0; _liquidOffY = 0; _liquidWidth = 0; @@ -1902,8 +1901,7 @@ bool GridMap::loadLiquidData(FILE* in, uint32 offset, uint32 /*size*/) if (fread(&header, sizeof(header), 1, in) != 1 || header.fourcc != MapLiquidMagic.asUInt) return false; - _liquidGlobalEntry = header.liquidType; - _liquidGlobalFlags = header.liquidFlags; + _liquidType = header.liquidType; _liquidOffX = header.offsetX; _liquidOffY = header.offsetY; _liquidWidth = header.width; @@ -2198,7 +2196,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 (!_liquidGlobalFlags && !_liquidFlags) + if (!_liquidType && !_liquidFlags) return LIQUID_MAP_NO_WATER; // Get cell @@ -2210,33 +2208,37 @@ 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] : _liquidGlobalFlags; - uint32 entry = _liquidEntry ? _liquidEntry[idx] : _liquidGlobalEntry; - if (LiquidTypeEntry const* liquidEntry = sLiquidTypeStore.LookupEntry(entry)) + uint8 type = _liquidFlags ? _liquidFlags[idx] : _liquidType; + uint32 entry = 0; + if (_liquidEntry) { - type &= MAP_LIQUID_TYPE_DARK_WATER; - uint32 liqTypeIdx = liquidEntry->Type; - if (entry < 21) + if (LiquidTypeEntry const* liquidEntry = sLiquidTypeStore.LookupEntry(_liquidEntry[idx])) { - if (AreaTableEntry const* area = sAreaTableStore.LookupEntry(getArea(x, y))) + entry = liquidEntry->Id; + type &= MAP_LIQUID_TYPE_DARK_WATER; + uint32 liqTypeIdx = liquidEntry->Type; + if (entry < 21) { - uint32 overrideLiquid = area->LiquidTypeOverride[liquidEntry->Type]; - if (!overrideLiquid && area->zone) + if (AreaTableEntry const* area = sAreaTableStore.LookupEntry(getArea(x, y))) { - area = sAreaTableStore.LookupEntry(area->zone); - if (area) - overrideLiquid = area->LiquidTypeOverride[liquidEntry->Type]; - } + uint32 overrideLiquid = area->LiquidTypeOverride[liquidEntry->Type]; + if (!overrideLiquid && area->zone) + { + area = sAreaTableStore.LookupEntry(area->zone); + if (area) + overrideLiquid = area->LiquidTypeOverride[liquidEntry->Type]; + } - if (LiquidTypeEntry const* liq = sLiquidTypeStore.LookupEntry(overrideLiquid)) - { - entry = overrideLiquid; - liqTypeIdx = liq->Type; + if (LiquidTypeEntry const* liq = sLiquidTypeStore.LookupEntry(overrideLiquid)) + { + entry = overrideLiquid; + liqTypeIdx = liq->Type; + } } } - } - type |= 1 << liqTypeIdx; + type |= 1 << liqTypeIdx; + } } if (type == 0) diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h index a0b3a9f991..57b56e02d5 100644 --- a/src/server/game/Maps/Map.h +++ b/src/server/game/Maps/Map.h @@ -123,8 +123,7 @@ struct map_heightHeader struct map_liquidHeader { uint32 fourcc; - uint8 flags; - uint8 liquidFlags; + uint16 flags; uint16 liquidType; uint8 offsetX; uint8 offsetY; @@ -151,6 +150,7 @@ enum ZLiquidStatus : uint32 #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 { @@ -186,8 +186,7 @@ class TC_GAME_API GridMap uint8* _liquidFlags; float* _liquidMap; uint16 _gridArea; - uint16 _liquidGlobalEntry; - uint8 _liquidGlobalFlags; + uint16 _liquidType; uint8 _liquidOffX; uint8 _liquidOffY; uint8 _liquidWidth; diff --git a/src/tools/map_extractor/System.cpp b/src/tools/map_extractor/System.cpp index 5f3a7ea8b5..c8afdf0a4b 100644 --- a/src/tools/map_extractor/System.cpp +++ b/src/tools/map_extractor/System.cpp @@ -416,7 +416,7 @@ void ReadLiquidTypeTable() // Map file format data static char const* MAP_MAGIC = "MAPS"; -static char const* MAP_VERSION_MAGIC = "v1.7"; +static char const* MAP_VERSION_MAGIC = "v1.6"; static char const* MAP_AREA_MAGIC = "AREA"; static char const* MAP_HEIGHT_MAGIC = "MHGT"; static char const* MAP_LIQUID_MAGIC = "MLIQ"; @@ -464,6 +464,8 @@ 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 @@ -471,8 +473,7 @@ struct map_heightHeader struct map_liquidHeader { uint32 fourcc; - uint8 flags; - uint8 liquidFlags; + uint16 flags; uint16 liquidType; uint8 offsetX; uint8 offsetY; @@ -847,8 +848,8 @@ bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/, } } - liquid_entry[i][j] = h2o->GetLiquidType(h); - switch (LiquidTypes.at(liquid_entry[i][j]).SoundBank) + 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; if (!ignoreDeepWater && attrs.Deep) liquid_flags[i][j] |= MAP_LIQUID_TYPE_DARK_WATER; break; @@ -882,14 +883,13 @@ bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/, //============================================ // Pack liquid data //============================================ - uint16 firstLiquidType = liquid_entry[0][0]; - uint8 firstLiquidFlag = liquid_flags[0][0]; + uint8 type = 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_entry[y][x] != firstLiquidType || liquid_flags[y][x] != firstLiquidFlag) + if (liquid_flags[y][x] != type) { fullType = true; y = ADT_CELLS_PER_GRID; @@ -901,7 +901,7 @@ bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/, map_liquidHeader liquidHeader; // no water data (if all grid have 0 liquid type) - if (firstLiquidFlag == 0 && !fullType) + if (type == 0 && !fullType) { // No liquid data map.liquidMapOffset = 0; @@ -953,10 +953,7 @@ bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/, liquidHeader.flags |= MAP_LIQUID_NO_TYPE; if (liquidHeader.flags & MAP_LIQUID_NO_TYPE) - { - liquidHeader.liquidFlags = firstLiquidFlag; - liquidHeader.liquidType = firstLiquidType; - } + liquidHeader.liquidType = type; else map.liquidMapSize += sizeof(liquid_entry) + sizeof(liquid_flags); @@ -967,6 +964,11 @@ bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/, // map hole info uint16 holes[ADT_CELLS_PER_GRID][ADT_CELLS_PER_GRID]; + if (map.liquidMapOffset) + map.holesOffset = map.liquidMapOffset + map.liquidMapSize; + else + map.holesOffset = map.heightMapOffset + map.heightMapSize; + memset(holes, 0, sizeof(holes)); bool hasHoles = false; @@ -984,19 +986,9 @@ bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/, } 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 FILE* output = fopen(filename2, "wb"); @@ -1060,29 +1052,20 @@ bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/, bool IsDeepWaterIgnored(uint32 mapId, uint32 x, uint32 y) { - 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) + if (mapId != 0) + return false; - // Vashj'ir grids completely ignore fatigue - return (x >= 39 && x <= 40 && y >= 24 && y <= 26) || (x >= 41 && x <= 46 && y >= 18 && y <= 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) - if (mapId == 1) - { - // GRID(43, 39) || GRID(43, 40) - // Thousand Needles - return x == 43 && (y == 39 || y == 40); - } - - return false; + // Vashj'ir grids completely ignore fatigue + return (x >= 39 && x <= 40 && y >= 24 && y <= 26) || (x >= 41 && x <= 46 && y >= 18 && y <= 26); } void ExtractMapsFromMpq(uint32 build) diff --git a/src/tools/map_extractor/adt.h b/src/tools/map_extractor/adt.h index 29d3dbde9f..d71ee143dd 100644 --- a/src/tools/map_extractor/adt.h +++ b/src/tools/map_extractor/adt.h @@ -250,14 +250,6 @@ public: 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) diff --git a/src/tools/mmaps_generator/TerrainBuilder.cpp b/src/tools/mmaps_generator/TerrainBuilder.cpp index 600dea7c80..e2aa8fe7f8 100644 --- a/src/tools/mmaps_generator/TerrainBuilder.cpp +++ b/src/tools/mmaps_generator/TerrainBuilder.cpp @@ -60,8 +60,7 @@ struct map_heightHeader struct map_liquidHeader { uint32 fourcc; - uint8 flags; - uint8 liquidFlags; + uint16 flags; uint16 liquidType; uint8 offsetX; uint8 offsetY; @@ -76,11 +75,12 @@ 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.7"; + char const* MAP_VERSION_MAGIC = "v1.6"; TerrainBuilder::TerrainBuilder(bool skipLiquid) : m_skipLiquid (skipLiquid){ } TerrainBuilder::~TerrainBuilder() { } @@ -180,10 +180,8 @@ namespace MMAP // data used later uint16 holes[16][16]; memset(holes, 0, sizeof(holes)); - uint16 liquid_entry[16][16]; - memset(liquid_entry, 0, sizeof(liquid_entry)); - uint8 liquid_flags[16][16]; - memset(liquid_flags, 0, sizeof(liquid_flags)); + uint8 liquid_type[16][16]; + memset(liquid_type, 0, sizeof(liquid_type)); G3D::Array ltriangles; G3D::Array ttriangles; @@ -291,90 +289,79 @@ 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 = nullptr; if (!(lheader.flags & MAP_LIQUID_NO_TYPE)) - { - if (fread(liquid_entry, sizeof(liquid_entry), 1, mapFile) != 1) + if (fread(liquid_type, sizeof(liquid_type), 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]; + 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; - } } - 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)) + if (liquid_map) { - int j = 0; - for (int i = 0; i < V9_SIZE_SQ; ++i) - { - row = i / V9_SIZE; - col = i % V9_SIZE; + int count = meshData.liquidVerts.size() / 3; + float xoffset = (float(tileX)-32)*GRID_SIZE; + float yoffset = (float(tileY)-32)*GRID_SIZE; - if (row < lheader.offsetY || row >= lheader.offsetY + lheader.height || - col < lheader.offsetX || col >= lheader.offsetX + lheader.width) + 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) { - // 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; + 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++; } - - 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 - { - for (int i = 0; i < V9_SIZE_SQ; ++i) + else { - 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); + 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); + } } - } - 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); + } } } @@ -418,21 +405,29 @@ namespace MMAP useLiquid = false; else { - liquidType = getLiquidType(i, liquid_flags); - if (liquidType & MAP_LIQUID_TYPE_DARK_WATER) + liquidType = getLiquidType(i, liquid_type); + switch (liquidType) { - // players should not be here, so logically neither should creatures - useTerrain = false; - useLiquid = false; + 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; } - 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 @@ -710,7 +705,7 @@ namespace MMAP copyIndices(tempTriangles, meshData.solidTris, offset, isM2); // now handle liquid data - if (liquid && liquid->GetFlagsStorage()) + if (liquid) { std::vector liqVerts; std::vector liqTris; diff --git a/src/tools/mmaps_generator/TerrainBuilder.h b/src/tools/mmaps_generator/TerrainBuilder.h index 15cd974375..71bccd8e94 100644 --- a/src/tools/mmaps_generator/TerrainBuilder.h +++ b/src/tools/mmaps_generator/TerrainBuilder.h @@ -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 = -2000.f; + static const float INVALID_MAP_LIQ_HEIGHT = -500.f; static const float INVALID_MAP_LIQ_HEIGHT_MAX = 5000.0f; // see following files: diff --git a/src/tools/vmap4_extractor/adtfile.cpp b/src/tools/vmap4_extractor/adtfile.cpp index 773cf8fbc2..e01e79a9e4 100644 --- a/src/tools/vmap4_extractor/adtfile.cpp +++ b/src/tools/vmap4_extractor/adtfile.cpp @@ -18,7 +18,7 @@ #include "vmapexport.h" #include "adtfile.h" -#include "StringFormat.h" + #include #include @@ -79,7 +79,7 @@ char* GetExtension(char* FileName) extern HANDLE WorldMpq; -ADTFile::ADTFile(char* filename, bool cache) : _file(WorldMpq, filename, false) +ADTFile::ADTFile(char* filename, bool cache) : ADT(WorldMpq, 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 (_file.isEof()) + if (ADT.isEof ()) return false; uint32 size; @@ -122,15 +122,15 @@ bool ADTFile::init(uint32 map_num, uint32 tileX, uint32 tileY, uint32 originalMa if (cacheable) dirfileCache = new std::vector(); - while (!_file.isEof()) + while (!ADT.isEof()) { char fourcc[5]; - _file.read(&fourcc,4); - _file.read(&size, 4); + ADT.read(&fourcc,4); + ADT.read(&size, 4); flipcc(fourcc); fourcc[4] = 0; - size_t nextpos = _file.getPos() + size; + size_t nextpos = ADT.getPos() + size; if (!strcmp(fourcc,"MCIN")) { @@ -143,7 +143,7 @@ bool ADTFile::init(uint32 map_num, uint32 tileX, uint32 tileY, uint32 originalMa if (size) { char* buf = new char[size]; - _file.read(buf, size); + ADT.read(buf, size); char* p = buf; int t = 0; ModelInstanceNames = new std::string[size]; @@ -169,7 +169,7 @@ bool ADTFile::init(uint32 map_num, uint32 tileX, uint32 tileY, uint32 originalMa if (size) { char* buf = new char[size]; - _file.read(buf, size); + ADT.read(buf, size); char* p = buf; int q = 0; WmoInstanceNames = new std::string[size]; @@ -187,25 +187,16 @@ bool ADTFile::init(uint32 map_num, uint32 tileX, uint32 tileY, uint32 originalMa } } //====================== - else if (!strcmp(fourcc, "MDDF")) + else if (!strcmp(fourcc,"MDDF")) { if (size) { - uint32 doodadCount = size / sizeof(ADT::MDDF); - for (uint32 i = 0; i < doodadCount; ++i) + nMDX = (int)size / 36; + for (int i=0; i* dirfileCache; public: ADTFile(char* filename, bool cache); ~ADTFile(); + int nWMO; + int nMDX; std::string* WmoInstanceNames; std::string* ModelInstanceNames; bool init(uint32 map_num, uint32 tileX, uint32 tileY, uint32 originalMapId); diff --git a/src/tools/vmap4_extractor/gameobject_extract.cpp b/src/tools/vmap4_extractor/gameobject_extract.cpp index 31d2db8a12..1af3e51a45 100644 --- a/src/tools/vmap4_extractor/gameobject_extract.cpp +++ b/src/tools/vmap4_extractor/gameobject_extract.cpp @@ -20,7 +20,7 @@ #include "dbcfile.h" #include "adtfile.h" #include "vmapexport.h" -#include "VMapDefinitions.h" + #include #include @@ -76,8 +76,6 @@ void ExtractGameobjectModels() return; } - fwrite(VMAP::RAW_VMAP_MAGIC, 1, 8, model_list); - for (DBCFile::Iterator it = dbc.begin(); it != dbc.end(); ++it) { path = it->getString(1); @@ -95,13 +93,9 @@ void ExtractGameobjectModels() strToLower(ch_ext); - uint8 isWmo = 0; bool result = false; if (!strcmp(ch_ext, ".wmo")) - { - isWmo = 1; result = ExtractSingleWmo(path); - } else if (!strcmp(ch_ext, ".mdl")) // TODO: extract .mdl files, if needed continue; else //if (!strcmp(ch_ext, ".mdx") || !strcmp(ch_ext, ".m2")) @@ -112,7 +106,6 @@ void ExtractGameobjectModels() uint32 displayId = it->getUInt(0); uint32 path_length = strlen(name); fwrite(&displayId, sizeof(uint32), 1, model_list); - fwrite(&isWmo, sizeof(uint8), 1, model_list); fwrite(&path_length, sizeof(uint32), 1, model_list); fwrite(name, sizeof(char), path_length, model_list); } diff --git a/src/tools/vmap4_extractor/model.cpp b/src/tools/vmap4_extractor/model.cpp index 2ed50352ec..d797a28a61 100644 --- a/src/tools/vmap4_extractor/model.cpp +++ b/src/tools/vmap4_extractor/model.cpp @@ -21,7 +21,6 @@ #include "wmo.h" #include "adtfile.h" #include "mpqfile.h" -#include "VMapDefinitions.h" #include #include #include @@ -80,7 +79,7 @@ bool Model::ConvertToVMAPModel(const char * outfilename) printf("Can't create the output file '%s'\n",outfilename); return false; } - fwrite(VMAP::RAW_VMAP_MAGIC, 8, 1, output); + fwrite(szRawVMAPMagic, 8, 1, output); uint32 nVertices = header.nBoundingVertices; fwrite(&nVertices, sizeof(int), 1, output); uint32 nofgroups = 1; @@ -146,17 +145,29 @@ Vec3D fixCoordSystem2(Vec3D v) return Vec3D(v.x, v.z, v.y); } -void Doodad::Extract(ADT::MDDF const& doodadDef, char const* ModelInstName, uint32 mapID, uint32 tileX, uint32 tileY, uint32 originalMapId, FILE* pDirfile, std::vector* dirfileCache) +ModelInstance::ModelInstance(MPQFile& f, char const* ModelInstName, uint32 mapID, uint32 tileX, uint32 tileY, uint32 originalMapId, FILE* pDirfile, std::vector* dirfileCache) + : id(0), scale(0), flags(0) { + 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? - float sc = doodadDef.Scale / 1024.0f; + sc = 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; @@ -166,24 +177,22 @@ void Doodad::Extract(ADT::MDDF const& doodadDef, char const* ModelInstName, uint if (count != 1 || nVertices == 0) return; - Vec3D position = fixCoords(doodadDef.Position); - - uint16 nameSet = 0;// not used for models + uint16 adtId = 0;// not used for models uint32 flags = MOD_M2; if (tileX == 65 && tileY == 65) flags |= MOD_WORLDSPAWN; if (mapID != originalMapId) flags |= MOD_PARENT_SPAWN; - //write mapID, tileX, tileY, Flags, NameSet, UniqueId, Pos, Rot, Scale, name + //write mapID, tileX, tileY, Flags, ID, Pos, Rot, Scale, 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(&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(&adtId, sizeof(uint16), 1, pDirfile); + fwrite(&id, sizeof(uint32), 1, pDirfile); + fwrite(&pos, sizeof(float), 3, pDirfile); + fwrite(&rot, sizeof(float), 3, pDirfile); fwrite(&sc, sizeof(float), 1, pDirfile); uint32 nlen=strlen(ModelInstName); fwrite(&nlen, sizeof(uint32), 1, pDirfile); @@ -195,25 +204,41 @@ void Doodad::Extract(ADT::MDDF const& doodadDef, char const* ModelInstName, uint ADTOutputCache& cacheModelData = dirfileCache->back(); cacheModelData.Flags = flags & ~MOD_PARENT_SPAWN; cacheModelData.Data.resize( - sizeof(uint16) + // nameSet - sizeof(uint32) + // doodadDef.UniqueId - sizeof(Vec3D) + // position - sizeof(Vec3D) + // doodadDef.Rotation + sizeof(uint16) + // adtId + sizeof(uint32) + // id + sizeof(float) * 3 + // pos + sizeof(float) * 3 + // rot sizeof(float) + // sc sizeof(uint32) + // nlen nlen); // ModelInstName uint8* cacheData = cacheModelData.Data.data(); -#define CACHE_WRITE(value, size, cnt, dest) memcpy(dest, value, size * cnt); dest += size * cnt; +#define CACHE_WRITE(value, size, count, dest) memcpy(dest, value, size * count); dest += size * count; - 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(&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(&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 + ); */ } diff --git a/src/tools/vmap4_extractor/model.h b/src/tools/vmap4_extractor/model.h index 27fb27c541..8376a50e03 100644 --- a/src/tools/vmap4_extractor/model.h +++ b/src/tools/vmap4_extractor/model.h @@ -25,7 +25,6 @@ class MPQFile; struct ADTOutputCache; -namespace ADT { struct MDDF; } Vec3D fixCoordSystem(Vec3D v); @@ -52,9 +51,17 @@ public: ~Model() { _unload(); } }; -namespace Doodad +class ModelInstance { - void Extract(ADT::MDDF const& doodadDef, char const* ModelInstName, uint32 mapID, uint32 tileX, uint32 tileY, uint32 originalMapId, FILE* pDirfile, std::vector* dirfileCache); -} +public: + uint32 id; + Vec3D pos, rot; + uint16 scale, flags; + float sc; + + ModelInstance() : id(0), scale(0), flags(0), sc(0.0f) {} + ModelInstance(MPQFile& f, char const* ModelInstName, uint32 mapID, uint32 tileX, uint32 tileY, uint32 originalMapId, FILE* pDirfile, std::vector* dirfileCache); + +}; #endif diff --git a/src/tools/vmap4_extractor/vec3d.h b/src/tools/vmap4_extractor/vec3d.h index 56d4513045..0fa5f328e5 100644 --- a/src/tools/vmap4_extractor/vec3d.h +++ b/src/tools/vmap4_extractor/vec3d.h @@ -137,12 +137,6 @@ public: } }; -class AaBox3D -{ -public: - Vec3D min; - Vec3D max; -}; class Vec2D { diff --git a/src/tools/vmap4_extractor/vmapexport.cpp b/src/tools/vmap4_extractor/vmapexport.cpp index 4bba3fa462..68398bdc77 100644 --- a/src/tools/vmap4_extractor/vmapexport.cpp +++ b/src/tools/vmap4_extractor/vmapexport.cpp @@ -132,6 +132,7 @@ bool preciseVectorData = false; //static const char * szWorkDirMaps = ".\\Maps"; char const* szWorkDirWmo = "./Buildings"; +char const* szRawVMAPMagic = "VMAP045"; bool LoadLocaleMPQFile(int locale) { @@ -416,14 +417,14 @@ bool ExtractSingleWmo(std::string& fname) std::string s = groupFileName; WMOGroup fgroup(s); - if (!fgroup.open(&froot)) + if (!fgroup.open()) { printf("Could not open all Group file for: %s\n", plain_name); file_ok = false; break; } - Wmo_nVertices += fgroup.ConvertToVMAPGroupWmo(output, preciseVectorData); + Wmo_nVertices += fgroup.ConvertToVMAPGroupWmo(output, &froot, preciseVectorData); } } diff --git a/src/tools/vmap4_extractor/vmapexport.h b/src/tools/vmap4_extractor/vmapexport.h index b81073ebd8..c798fb496b 100644 --- a/src/tools/vmap4_extractor/vmapexport.h +++ b/src/tools/vmap4_extractor/vmapexport.h @@ -30,6 +30,7 @@ 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); diff --git a/src/tools/vmap4_extractor/wdtfile.cpp b/src/tools/vmap4_extractor/wdtfile.cpp index 1b77426c5b..86e4bcef46 100644 --- a/src/tools/vmap4_extractor/wdtfile.cpp +++ b/src/tools/vmap4_extractor/wdtfile.cpp @@ -19,7 +19,7 @@ #include "vmapexport.h" #include "wdtfile.h" #include "adtfile.h" -#include "StringFormat.h" + #include char * wdtGetPlainName(char * FileName) @@ -104,21 +104,13 @@ bool WDTFile::init(uint32 mapId) // global wmo instance data if (size) { - uint32 mapObjectCount = size / sizeof(ADT::MODF); - for (uint32 i = 0; i < mapObjectCount; ++i) + int32 gnWMO = (int)size / 64; + + for (int i = 0; i < gnWMO; ++i) { - 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); - } + int id; + _file.read(&id, 4); + WMOInstance inst(_file, _wmoNames[id].c_str(), mapId, 65, 65, mapId, dirfile, nullptr); } } } diff --git a/src/tools/vmap4_extractor/wmo.cpp b/src/tools/vmap4_extractor/wmo.cpp index 99d7b5b00b..74bb69b511 100644 --- a/src/tools/vmap4_extractor/wmo.cpp +++ b/src/tools/vmap4_extractor/wmo.cpp @@ -20,7 +20,7 @@ #include "wmo.h" #include "adtfile.h" #include "vec3d.h" -#include "VMapDefinitions.h" + #include #include #include @@ -28,6 +28,8 @@ #undef max #include "mpqfile.h" +extern uint16 *LiqType; + WMORoot::WMORoot(std::string &filename) : filename(filename), col(0), nTextures(0), nGroups(0), nP(0), nLights(0), nModels(0), nDoodads(0), nDoodadSets(0), RootWMOID(0), liquidType(0) @@ -127,7 +129,7 @@ bool WMORoot::ConvertToVMAPRootWmo(FILE* pOutfile) { //printf("Convert RootWmo...\n"); - fwrite(VMAP::RAW_VMAP_MAGIC, 1, 8, pOutfile); + fwrite(szRawVMAPMagic, 1, 8, pOutfile); unsigned int nVectors = 0; fwrite(&nVectors,sizeof(nVectors), 1, pOutfile); // will be filled later fwrite(&nGroups, 4, 1, pOutfile); @@ -139,14 +141,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), - groupLiquid(0), groupWMOID(0), mopy_size(0), moba_size(0), LiquEx_size(0), + liquidType(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(WMORoot* rootWMO) +bool WMOGroup::open() { MPQFile f(WorldMpq, filename.c_str()); if (f.isEof ()) @@ -181,19 +183,8 @@ bool WMOGroup::open(WMORoot* rootWMO) f.read(&nBatchB, 2); f.read(&nBatchC, 4); f.read(&fogIdx, 4); - f.read(&groupLiquid, 4); - f.read(&groupWMOID, 4); - - // according to WoW.Dev Wiki: - if (rootWMO->liquidType & 4) - groupLiquid = GetLiquidTypeId(groupLiquid); - else if (groupLiquid == 15) - groupLiquid = 0; - else - groupLiquid = GetLiquidTypeId(groupLiquid + 1); - - if (groupLiquid) - liquflags |= 2; + f.read(&liquidType, 4); + f.read(&groupWMOID,4); } else if (!strcmp(fourcc,"MOPY")) @@ -230,7 +221,7 @@ bool WMOGroup::open(WMORoot* rootWMO) { liquflags |= 1; hlq = new WMOLiquidHeader(); - f.read(hlq, sizeof(WMOLiquidHeader)); + f.read(hlq, 0x1E); LiquEx_size = sizeof(WMOLiquidVert) * hlq->xverts * hlq->yverts; LiquEx = new WMOLiquidVert[hlq->xverts * hlq->yverts]; f.read(LiquEx, LiquEx_size); @@ -238,19 +229,6 @@ bool WMOGroup::open(WMORoot* rootWMO) 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]; @@ -264,7 +242,7 @@ bool WMOGroup::open(WMORoot* rootWMO) return true; } -int WMOGroup::ConvertToVMAPGroupWmo(FILE* output, bool preciseVectorData) +int WMOGroup::ConvertToVMAPGroupWmo(FILE *output, WMORoot *rootWMO, bool preciseVectorData) { fwrite(&mogpFlags,sizeof(uint32),1,output); fwrite(&groupWMOID,sizeof(uint32),1,output); @@ -423,54 +401,78 @@ int WMOGroup::ConvertToVMAPGroupWmo(FILE* output, bool preciseVectorData) } //------LIQU------------------------ - if (liquflags & 3) + if (LiquEx_size != 0) { - 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" + int LIQU_h[] = {0x5551494C, static_cast(sizeof(WMOLiquidHeader) + LiquEx_size) + hlq->xtiles*hlq->ytiles};// "LIQU" fwrite(LIQU_h, 4, 2, output); + // according to WoW.Dev Wiki: + uint32 liquidEntry; + if (rootWMO->liquidType & 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->liquidType << " group:" << liquidType << ")\n"; llog.close(); */ - 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); - } + fwrite(hlq, sizeof(WMOLiquidHeader), 1, output); + // only need height values, the other values are unknown anyway + for (uint32 i = 0; ixtiles*hlq->ytiles, output); } return nColTriangles; } -uint32 WMOGroup::GetLiquidTypeId(uint32 liquidTypeId) -{ - if (liquidTypeId < 21 && liquidTypeId) - { - switch (((static_cast(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; @@ -482,11 +484,33 @@ WMOGroup::~WMOGroup() delete [] LiquBytes; } -void MapObject::Extract(ADT::MODF const& mapObjDef, char const* WmoInstName, uint32 mapID, uint32 tileX, uint32 tileY, uint32 originalMapId, FILE* pDirfile, std::vector* dirfileCache) +WMOInstance::WMOInstance(MPQFile& f, char const* WmoInstName, uint32 mapID, uint32 tileX, uint32 tileY, uint32 originalMapId, FILE* pDirfile, std::vector* dirfileCache) + : currx(0), curry(0), wmo(nullptr), doodadset(0), pos(), indx(0), id(0) { + 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 ((mapObjDef.Flags & 0x1) != 0) + if ((fflags & 0x01) != 0) return; //-----------add_in _dir_file---------------- @@ -510,41 +534,37 @@ void MapObject::Extract(ADT::MODF const& mapObjDef, char const* WmoInstName, uin if (count != 1 || nVertices == 0) return; - Vec3D position = mapObjDef.Position; - - float x, z; - x = position.x; - z = position.z; - if (x == 0 && z == 0) + float x,z; + x = pos.x; + z = pos.z; + if (x==0 && z == 0) { - position.x = 533.33333f * 32; - position.z = 533.33333f * 32; + pos.x = 533.33333f*32; + pos.z = 533.33333f*32; } - position = fixCoords(position); - AaBox3D bounds; - bounds.min = fixCoords(mapObjDef.Bounds.min); - bounds.max = fixCoords(mapObjDef.Bounds.max); + pos = fixCoords(pos); + pos2 = fixCoords(pos2); + pos3 = fixCoords(pos3); 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, NameSet, UniqueId, Pos, Rot, Scale, Bound_lo, Bound_hi, name + //write mapID, tileX, tileY, Flags, ID, 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(&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(&adtId, sizeof(uint16), 1, pDirfile); + fwrite(&id, sizeof(uint32), 1, pDirfile); + fwrite(&pos, sizeof(float), 3, pDirfile); + fwrite(&rot, sizeof(float), 3, pDirfile); fwrite(&scale, sizeof(float), 1, pDirfile); - fwrite(&bounds, sizeof(AaBox3D), 1, pDirfile); + fwrite(&pos2, sizeof(float), 3, pDirfile); + fwrite(&pos3, sizeof(float), 3, pDirfile); uint32 nlen = strlen(WmoInstName); fwrite(&nlen, sizeof(uint32), 1, pDirfile); fwrite(WmoInstName, sizeof(char), nlen, pDirfile); @@ -555,27 +575,41 @@ void MapObject::Extract(ADT::MODF const& mapObjDef, char const* WmoInstName, uin ADTOutputCache& cacheModelData = dirfileCache->back(); cacheModelData.Flags = flags & ~MOD_PARENT_SPAWN; cacheModelData.Data.resize( - sizeof(uint16) + // mapObjDef.NameSet - sizeof(uint32) + // mapObjDef.UniqueId - sizeof(Vec3D) + // position - sizeof(Vec3D) + // mapObjDef.Rotation + sizeof(uint16) + // adtId + sizeof(uint32) + // id + sizeof(float) * 3 + // pos + sizeof(float) * 3 + // rot sizeof(float) + // scale - sizeof(AaBox3D) + // bounds + sizeof(float) * 3 + // pos2 + sizeof(float) * 3 + // pos3 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(&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(&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(&scale, sizeof(float), 1, cacheData); - CACHE_WRITE(&bounds, sizeof(AaBox3D), 1, cacheData); + CACHE_WRITE(&pos2, sizeof(float), 3, cacheData); + CACHE_WRITE(&pos3, sizeof(float), 3, 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); } diff --git a/src/tools/vmap4_extractor/wmo.h b/src/tools/vmap4_extractor/wmo.h index c2b662a2d1..d85b2fd2af 100644 --- a/src/tools/vmap4_extractor/wmo.h +++ b/src/tools/vmap4_extractor/wmo.h @@ -18,6 +18,8 @@ #ifndef WMO_H #define WMO_H +#define TILESIZE (533.33333f) +#define CHUNKSIZE ((TILESIZE) / 16.0f) #include #include @@ -41,7 +43,6 @@ class WMOInstance; class WMOManager; class MPQFile; 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); } @@ -62,17 +63,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 material; + short type; }; +#pragma pack(push, 1) + struct WMOLiquidVert { uint16 unk1; @@ -106,7 +107,7 @@ public: uint16 moprNItems; uint16 nBatchA; uint16 nBatchB; - uint32 nBatchC, fogIdx, groupLiquid, groupWMOID; + uint32 nBatchC, fogIdx, liquidType, groupWMOID; int mopy_size, moba_size; int LiquEx_size; @@ -117,14 +118,26 @@ public: WMOGroup(std::string const& filename); ~WMOGroup(); - bool open(WMORoot* rootWMO); - int ConvertToVMAPGroupWmo(FILE* output, bool preciseVectorData); - uint32 GetLiquidTypeId(uint32 liquidTypeId); + bool open(); + int ConvertToVMAPGroupWmo(FILE* output, WMORoot* rootWMO, bool preciseVectorData); }; -namespace MapObject +class WMOInstance { - void Extract(ADT::MODF const& mapObjDef, char const* WmoInstName, uint32 mapID, uint32 tileX, uint32 tileY, uint32 originalMapId, FILE* pDirfile, std::vector* dirfileCache); -} + static std::set ids; +public: + std::string MapName; + int currx; + int curry; + WMOGroup* wmo; + int doodadset; + Vec3D pos; + Vec3D pos2, pos3, rot; + uint32 indx, id; + + WMOInstance(MPQFile&f , char const* WmoInstName, uint32 mapID, uint32 tileX, uint32 tileY, uint32 originalMapId, FILE* pDirfile, std::vector* dirfileCache); + + static void reset(); +}; #endif