mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-03-24 08:00:14 +00:00
- Fix WDT chunk magic constants to big-endian ASCII (matching ADTLoader) - Add minimum effective size for box area triggers (90 units, like sphere 45-unit radius) - Add areaTriggerSuppressFirst_ flag to prevent portal ping-pong on map transfer - Add WMORenderer::clearAll() to clear models/textures on map change (prevents GPU crash) - Increase WMO texture cache default to 8GB - Fix setMapName called after loadTestTerrain so WMO renderer exists - Save/restore player position around CMSG_AREATRIGGER to prevent bad DB persistence
110 lines
3.6 KiB
C++
110 lines
3.6 KiB
C++
#include "pipeline/wdt_loader.hpp"
|
|
#include "core/logger.hpp"
|
|
#include <cstring>
|
|
|
|
namespace wowee {
|
|
namespace pipeline {
|
|
|
|
namespace {
|
|
|
|
uint32_t readU32(const uint8_t* data, size_t offset) {
|
|
uint32_t v;
|
|
std::memcpy(&v, data + offset, 4);
|
|
return v;
|
|
}
|
|
|
|
uint16_t readU16(const uint8_t* data, size_t offset) {
|
|
uint16_t v;
|
|
std::memcpy(&v, data + offset, 2);
|
|
return v;
|
|
}
|
|
|
|
float readF32(const uint8_t* data, size_t offset) {
|
|
float v;
|
|
std::memcpy(&v, data + offset, 4);
|
|
return v;
|
|
}
|
|
|
|
// Chunk magic constants (big-endian ASCII, same as ADTLoader)
|
|
constexpr uint32_t MVER = 0x4D564552; // "MVER"
|
|
constexpr uint32_t MPHD = 0x4D504844; // "MPHD"
|
|
constexpr uint32_t MAIN = 0x4D41494E; // "MAIN"
|
|
constexpr uint32_t MWMO = 0x4D574D4F; // "MWMO"
|
|
constexpr uint32_t MODF = 0x4D4F4446; // "MODF"
|
|
|
|
} // anonymous namespace
|
|
|
|
WDTInfo parseWDT(const std::vector<uint8_t>& data) {
|
|
WDTInfo info;
|
|
|
|
if (data.size() < 8) {
|
|
LOG_WARNING("WDT data too small (", data.size(), " bytes)");
|
|
return info;
|
|
}
|
|
|
|
size_t offset = 0;
|
|
|
|
while (offset + 8 <= data.size()) {
|
|
uint32_t magic = readU32(data.data(), offset);
|
|
uint32_t chunkSize = readU32(data.data(), offset + 4);
|
|
|
|
if (offset + 8 + chunkSize > data.size()) {
|
|
LOG_WARNING("WDT chunk extends beyond file at offset ", offset);
|
|
break;
|
|
}
|
|
|
|
const uint8_t* chunkData = data.data() + offset + 8;
|
|
|
|
if (magic == MVER) {
|
|
if (chunkSize >= 4) {
|
|
uint32_t version = readU32(chunkData, 0);
|
|
LOG_DEBUG("WDT version: ", version);
|
|
}
|
|
} else if (magic == MPHD) {
|
|
if (chunkSize >= 4) {
|
|
info.mphdFlags = readU32(chunkData, 0);
|
|
LOG_DEBUG("WDT MPHD flags: 0x", std::hex, info.mphdFlags, std::dec);
|
|
}
|
|
} else if (magic == MWMO) {
|
|
// Null-terminated WMO path string(s)
|
|
if (chunkSize > 0) {
|
|
const char* str = reinterpret_cast<const char*>(chunkData);
|
|
size_t len = std::strlen(str);
|
|
if (len > 0) {
|
|
info.rootWMOPath = std::string(str, len);
|
|
LOG_DEBUG("WDT root WMO: ", info.rootWMOPath);
|
|
}
|
|
}
|
|
} else if (magic == MODF) {
|
|
// MODF entry is 64 bytes (same layout as ADT MODF)
|
|
if (chunkSize >= 64) {
|
|
// nameId at offset 0 (unused for WDT — path comes from MWMO)
|
|
// uniqueId at offset 4
|
|
info.position[0] = readF32(chunkData, 8);
|
|
info.position[1] = readF32(chunkData, 12);
|
|
info.position[2] = readF32(chunkData, 16);
|
|
info.rotation[0] = readF32(chunkData, 20);
|
|
info.rotation[1] = readF32(chunkData, 24);
|
|
info.rotation[2] = readF32(chunkData, 28);
|
|
// extents at 32-55
|
|
info.flags = readU16(chunkData, 56);
|
|
info.doodadSet = readU16(chunkData, 58);
|
|
LOG_DEBUG("WDT MODF placement: pos=(", info.position[0], ", ",
|
|
info.position[1], ", ", info.position[2], ") rot=(",
|
|
info.rotation[0], ", ", info.rotation[1], ", ",
|
|
info.rotation[2], ") doodadSet=", info.doodadSet);
|
|
}
|
|
}
|
|
|
|
offset += 8 + chunkSize;
|
|
}
|
|
|
|
LOG_WARNING("WDT parse result: mphdFlags=0x", std::hex, info.mphdFlags, std::dec,
|
|
" isWMOOnly=", info.isWMOOnly(),
|
|
" rootWMO='", info.rootWMOPath, "'");
|
|
|
|
return info;
|
|
}
|
|
|
|
} // namespace pipeline
|
|
} // namespace wowee
|