diff --git a/src/core/application.cpp b/src/core/application.cpp index 9aa4328c..4d8feec7 100644 --- a/src/core/application.cpp +++ b/src/core/application.cpp @@ -2950,11 +2950,18 @@ std::string Application::getModelPathForDisplayId(uint32_t displayId) const { } if (displayId == 30412) return "Creature\\Gryphon\\Gryphon.m2"; if (displayId == 30413) return "Creature\\Wyvern\\Wyvern.m2"; + LOG_WARNING("No display data for displayId ", displayId, + " (displayDataMap_ has ", displayDataMap_.size(), " entries)"); return ""; } auto itPath = modelIdToPath_.find(itData->second.modelId); - if (itPath == modelIdToPath_.end()) return ""; + if (itPath == modelIdToPath_.end()) { + LOG_WARNING("No model path for modelId ", itData->second.modelId, + " from displayId ", displayId, + " (modelIdToPath_ has ", modelIdToPath_.size(), " entries)"); + return ""; + } return itPath->second; } diff --git a/src/game/game_handler.cpp b/src/game/game_handler.cpp index d73bba0b..d163d1c4 100644 --- a/src/game/game_handler.cpp +++ b/src/game/game_handler.cpp @@ -3436,6 +3436,10 @@ void GameHandler::handleUpdateObject(network::Packet& packet) { unit->setHostile(isHostileFaction(unit->getFactionTemplate())); } // Trigger creature spawn callback for units/players with displayId + if (block.objectType == ObjectType::UNIT && unit->getDisplayId() == 0) { + LOG_INFO("[Spawn] UNIT guid=0x", std::hex, block.guid, std::dec, + " has displayId=0 — no spawn (entry=", unit->getEntry(), ")"); + } if ((block.objectType == ObjectType::UNIT || block.objectType == ObjectType::PLAYER) && unit->getDisplayId() != 0) { if (block.objectType == ObjectType::PLAYER && block.guid == playerGuid) { // Skip local player — spawned separately via spawnPlayerCharacter() @@ -3451,6 +3455,9 @@ void GameHandler::handleUpdateObject(network::Packet& packet) { } } } else if (creatureSpawnCallback_) { + LOG_INFO("[Spawn] UNIT guid=0x", std::hex, block.guid, std::dec, + " displayId=", unit->getDisplayId(), " at (", + unit->getX(), ",", unit->getY(), ",", unit->getZ(), ")"); creatureSpawnCallback_(block.guid, unit->getDisplayId(), unit->getX(), unit->getY(), unit->getZ(), unit->getOrientation()); } diff --git a/src/game/world_packets.cpp b/src/game/world_packets.cpp index 6dff84f6..5d7a00d6 100644 --- a/src/game/world_packets.cpp +++ b/src/game/world_packets.cpp @@ -2931,50 +2931,35 @@ bool QuestRequestItemsParser::parse(network::Packet& packet, QuestRequestItemsDa data.title = packet.readString(); data.completionText = packet.readString(); - LOG_INFO("QRI raw: packetSize=", packet.getSize(), - " posAfterStrings=", packet.getReadPos(), - " remaining=", packet.getSize() - packet.getReadPos()); - - if (packet.getReadPos() + 20 > packet.getSize()) { + if (packet.getReadPos() + 9 > packet.getSize()) { LOG_INFO("Quest request items (short): id=", data.questId, " title='", data.title, "'"); return true; } - // Log each skipped field so we can verify the offset count - uint32_t f1 = packet.readUInt32(); - uint32_t f2 = packet.readUInt32(); - uint32_t f3 = packet.readUInt32(); - uint32_t f4 = packet.readUInt32(); - uint32_t f5 = packet.readUInt32(); - LOG_INFO("QRI fields: f1=", f1, " f2=", f2, " f3=", f3, " f4=", f4, " f5=", f5, - " (emoteDelay/emote/autoClose/flags/suggestedPlayers)"); + // emoteDelay (uint32) + emoteId (uint32) + autoFinish (uint8) = 9 bytes + // (same format in vanilla 1.12 and WotLK 3.3.5a) + /*uint32_t emoteDelay =*/ packet.readUInt32(); + /*uint32_t emoteId =*/ packet.readUInt32(); + /*uint8_t autoFinish =*/ packet.readUInt8(); if (packet.getReadPos() + 4 > packet.getSize()) return true; data.requiredMoney = packet.readUInt32(); - LOG_INFO("QRI requiredMoney=", data.requiredMoney); if (packet.getReadPos() + 4 > packet.getSize()) return true; uint32_t requiredItemCount = packet.readUInt32(); - LOG_INFO("QRI requiredItemCount=", requiredItemCount, - " posBeforeItems=", packet.getReadPos()); for (uint32_t i = 0; i < requiredItemCount && requiredItemCount < 20; ++i) { if (packet.getReadPos() + 12 > packet.getSize()) break; - uint32_t raw0 = packet.readUInt32(); - uint32_t raw1 = packet.readUInt32(); - uint32_t raw2 = packet.readUInt32(); - LOG_INFO("QRI item[", i, "]: raw0=", raw0, " raw1=", raw1, " raw2=", raw2); QuestRewardItem item; - item.itemId = raw0; - item.count = raw1; - item.displayInfoId = raw2; + item.itemId = packet.readUInt32(); + item.count = packet.readUInt32(); + item.displayInfoId = packet.readUInt32(); if (item.itemId > 0) data.requiredItems.push_back(item); } if (packet.getReadPos() + 4 > packet.getSize()) return true; data.completableFlags = packet.readUInt32(); - LOG_INFO("QRI completableFlags=", data.completableFlags); LOG_INFO("Quest request items: id=", data.questId, " title='", data.title, "' items=", data.requiredItems.size(), " completable=", data.isCompletable()); diff --git a/src/pipeline/asset_manager.cpp b/src/pipeline/asset_manager.cpp index 2c6e409a..a231352f 100644 --- a/src/pipeline/asset_manager.cpp +++ b/src/pipeline/asset_manager.cpp @@ -300,7 +300,8 @@ std::shared_ptr AssetManager::loadDBC(const std::string& name) { } LOG_INFO("Binary DBC fallback succeeded: ", name); } else { - LOG_WARNING("No binary DBC fallback available for: ", name); + LOG_ERROR("No binary DBC fallback available for: ", name, " — discarding garbled CSV"); + return nullptr; } } }