diff --git a/include/game/opcodes.hpp b/include/game/opcodes.hpp index 9127c1c7..347eb545 100644 --- a/include/game/opcodes.hpp +++ b/include/game/opcodes.hpp @@ -220,7 +220,8 @@ enum class Opcode : uint16_t { CMSG_QUESTGIVER_REQUEST_REWARD = 0x18C, SMSG_QUESTGIVER_OFFER_REWARD = 0x18D, CMSG_QUESTGIVER_CHOOSE_REWARD = 0x18E, - SMSG_QUESTGIVER_QUEST_COMPLETE = 0x18F, + SMSG_QUESTGIVER_QUEST_INVALID = 0x18F, + SMSG_QUESTGIVER_QUEST_COMPLETE = 0x191, CMSG_QUESTLOG_REMOVE_QUEST = 0x194, // ---- Phase 5: Vendor ---- diff --git a/src/game/game_handler.cpp b/src/game/game_handler.cpp index 7f0d0174..80a175f7 100644 --- a/src/game/game_handler.cpp +++ b/src/game/game_handler.cpp @@ -836,24 +836,31 @@ void GameHandler::handlePacket(network::Packet& packet) { case Opcode::SMSG_QUESTGIVER_QUEST_DETAILS: handleQuestDetails(packet); break; + case Opcode::SMSG_QUESTGIVER_QUEST_INVALID: { + // Quest query failed - parse failure reason + if (packet.getSize() - packet.getReadPos() >= 4) { + uint32_t failReason = packet.readUInt32(); + const char* reasonStr = "Unknown"; + switch (failReason) { + case 0: reasonStr = "Don't have quest"; break; + case 1: reasonStr = "Quest level too low"; break; + case 4: reasonStr = "Insufficient money"; break; + case 5: reasonStr = "Inventory full"; break; + case 13: reasonStr = "Already on that quest"; break; + case 18: reasonStr = "Already completed quest"; break; + case 19: reasonStr = "Can't take any more quests"; break; + } + LOG_WARNING("Quest invalid: reason=", failReason, " (", reasonStr, ")"); + // Show error to user + addSystemChatMessage(std::string("Quest unavailable: ") + reasonStr); + } + break; + } case Opcode::SMSG_QUESTGIVER_QUEST_COMPLETE: { // Mark quest as complete in local log - size_t packetSize = packet.getSize(); - size_t readPos = packet.getReadPos(); - LOG_INFO("SMSG_QUESTGIVER_QUEST_COMPLETE: size=", packetSize, " readPos=", readPos); - - // Dump packet hex for debugging - std::string hexDump; - for (size_t i = readPos; i < std::min(readPos + 32, packetSize); ++i) { - char buf[4]; - snprintf(buf, sizeof(buf), "%02x ", static_cast(packet.getData()[i])); - hexDump += buf; - } - LOG_INFO(" Packet hex: ", hexDump); - if (packet.getSize() - packet.getReadPos() >= 4) { uint32_t questId = packet.readUInt32(); - LOG_INFO(" Read questId: ", questId); + LOG_INFO("Quest completed: questId=", questId); for (auto it = questLog_.begin(); it != questLog_.end(); ++it) { if (it->questId == questId) { questLog_.erase(it);