Add MCLQ water, TaxiPathNode transports, and vanilla M2 particles

- Parse MCLQ sub-chunks in vanilla ADTs for water rendering (WotLK uses MH2O)
- Load TaxiPathNode.dbc for MO_TRANSPORT world-coordinate paths (vanilla boats)
- Parse data[] from SMSG_GAMEOBJECT_QUERY_RESPONSE (taxiPathId for transports)
- Support vanilla M2 particle emitters (504-byte struct, different from WotLK 476)
- Add character preview texture diagnostic logging
- Fix disconnect handling on character screen (show error only when no chars)
This commit is contained in:
Kelsi 2026-02-14 20:20:43 -08:00
parent cbb3035313
commit bf31da8c13
14 changed files with 556 additions and 55 deletions

View file

@ -205,9 +205,10 @@ bool Application::initialize() {
renderer->getCharacterRenderer()->setAssetManager(assetManager.get());
}
// Load transport paths from TransportAnimation.dbc
// Load transport paths from TransportAnimation.dbc and TaxiPathNode.dbc
if (gameHandler && gameHandler->getTransportManager()) {
gameHandler->getTransportManager()->loadTransportAnimationDBC(assetManager.get());
gameHandler->getTransportManager()->loadTaxiPathNodeDBC(assetManager.get());
}
// Initialize HD texture packs
@ -1487,7 +1488,7 @@ void Application::setupUICallbacks() {
}
// Register the transport with spawn position (prevents rendering at origin until server update)
transportManager->registerTransport(guid, wmoInstanceId, pathId, canonicalSpawnPos);
transportManager->registerTransport(guid, wmoInstanceId, pathId, canonicalSpawnPos, entry);
// Server-authoritative movement - set initial position from spawn data
glm::vec3 canonicalPos(x, y, z);
@ -1502,6 +1503,20 @@ void Application::setupUICallbacks() {
" pos=(", pending.x, ", ", pending.y, ", ", pending.z, ") orientation=", pending.orientation);
pendingTransportMoves_.erase(pendingIt);
}
// For MO_TRANSPORT at (0,0,0): check if GO data is already cached with a taxiPathId
if (glm::length(canonicalSpawnPos) < 1.0f && gameHandler) {
auto goData = gameHandler->getCachedGameObjectInfo(entry);
if (goData && goData->type == 15 && goData->hasData && goData->data[0] != 0) {
uint32_t taxiPathId = goData->data[0];
if (transportManager->hasTaxiPath(taxiPathId)) {
transportManager->assignTaxiPathToTransport(entry, taxiPathId);
LOG_INFO("Assigned cached TaxiPathNode path for MO_TRANSPORT entry=", entry,
" taxiPathId=", taxiPathId);
}
}
}
if (auto* tr = transportManager->getTransport(guid); tr) {
LOG_INFO("Transport registered: guid=0x", std::hex, guid, std::dec,
" entry=", entry, " displayId=", displayId,
@ -1598,7 +1613,7 @@ void Application::setupUICallbacks() {
" displayId=", displayId, " wmoInstance=", wmoInstanceId);
}
transportManager->registerTransport(guid, wmoInstanceId, pathId, canonicalSpawnPos);
transportManager->registerTransport(guid, wmoInstanceId, pathId, canonicalSpawnPos, entry);
} else {
pendingTransportMoves_[guid] = PendingTransportMove{x, y, z, orientation};
LOG_WARNING("Cannot auto-spawn transport 0x", std::hex, guid, std::dec,