mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-03-22 23:30:14 +00:00
Fix NPC chat showing only name without message text
Two bugs in SMSG_MESSAGECHAT parser for MONSTER_SAY/YELL/EMOTE: 1. Sender name included trailing null byte from server (nameLen includes null terminator). The embedded null in std::string caused ImGui to truncate the concatenated display string at the NPC name, hiding " says: <message>" entirely. 2. Missing NamedGuid receiver name for non-player/non-pet targets. When the receiver GUID is a creature, the server writes an additional SizedCString (target name) that we weren't reading, shifting all subsequent field reads. Also adds MONSTER_WHISPER, MONSTER_PARTY, RAID_BOSS_EMOTE, RAID_BOSS_WHISPER chat types with proper parsing and display formatting (says/yells/whispers).
This commit is contained in:
parent
f1caf8c03e
commit
b948720ec3
4 changed files with 41 additions and 6 deletions
|
|
@ -605,7 +605,11 @@ enum class ChatType : uint8_t {
|
|||
RAID_LEADER = 27,
|
||||
RAID_WARNING = 28,
|
||||
ACHIEVEMENT = 29,
|
||||
GUILD_ACHIEVEMENT = 30
|
||||
GUILD_ACHIEVEMENT = 30,
|
||||
MONSTER_WHISPER = 42,
|
||||
RAID_BOSS_WHISPER = 43,
|
||||
RAID_BOSS_EMOTE = 44,
|
||||
MONSTER_PARTY = 50
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -5967,7 +5967,8 @@ void GameHandler::handleMessageChat(network::Packet& packet) {
|
|||
// Trigger chat bubble for SAY/YELL messages from others
|
||||
if (chatBubbleCallback_ && data.senderGuid != 0) {
|
||||
if (data.type == ChatType::SAY || data.type == ChatType::YELL ||
|
||||
data.type == ChatType::MONSTER_SAY || data.type == ChatType::MONSTER_YELL) {
|
||||
data.type == ChatType::MONSTER_SAY || data.type == ChatType::MONSTER_YELL ||
|
||||
data.type == ChatType::MONSTER_PARTY) {
|
||||
bool isYell = (data.type == ChatType::YELL || data.type == ChatType::MONSTER_YELL);
|
||||
chatBubbleCallback_(data.senderGuid, data.message, isYell);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1370,17 +1370,38 @@ bool MessageChatParser::parse(network::Packet& packet, MessageChatData& data) {
|
|||
switch (data.type) {
|
||||
case ChatType::MONSTER_SAY:
|
||||
case ChatType::MONSTER_YELL:
|
||||
case ChatType::MONSTER_EMOTE: {
|
||||
// Read sender name length + name
|
||||
case ChatType::MONSTER_EMOTE:
|
||||
case ChatType::MONSTER_WHISPER:
|
||||
case ChatType::MONSTER_PARTY:
|
||||
case ChatType::RAID_BOSS_EMOTE:
|
||||
case ChatType::RAID_BOSS_WHISPER: {
|
||||
// Read sender name (SizedCString: uint32 len including null + chars)
|
||||
uint32_t nameLen = packet.readUInt32();
|
||||
if (nameLen > 0 && nameLen < 256) {
|
||||
data.senderName.resize(nameLen);
|
||||
for (uint32_t i = 0; i < nameLen; ++i) {
|
||||
data.senderName[i] = static_cast<char>(packet.readUInt8());
|
||||
}
|
||||
// Strip trailing null (server includes it in nameLen)
|
||||
if (!data.senderName.empty() && data.senderName.back() == '\0') {
|
||||
data.senderName.pop_back();
|
||||
}
|
||||
}
|
||||
// Read receiver GUID
|
||||
// Read receiver GUID (NamedGuid: guid + optional name for non-player targets)
|
||||
data.receiverGuid = packet.readUInt64();
|
||||
if (data.receiverGuid != 0) {
|
||||
// Non-player, non-pet GUIDs have high type bits set (0xF1xx/0xF0xx range)
|
||||
uint16_t highGuid = static_cast<uint16_t>(data.receiverGuid >> 48);
|
||||
bool isPlayer = (highGuid == 0x0000);
|
||||
bool isPet = ((highGuid & 0xF0FF) == 0xF040) || ((highGuid & 0xF0FF) == 0xF014);
|
||||
if (!isPlayer && !isPet) {
|
||||
// Read receiver name (SizedCString)
|
||||
uint32_t recvNameLen = packet.readUInt32();
|
||||
if (recvNameLen > 0 && recvNameLen < 256) {
|
||||
packet.setReadPos(packet.getReadPos() + recvNameLen);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1120,9 +1120,18 @@ void GameScreen::renderChatWindow(game::GameHandler& gameHandler) {
|
|||
} else if (msg.type == game::ChatType::TEXT_EMOTE) {
|
||||
renderTextWithLinks(tsPrefix + processedMessage, color);
|
||||
} else if (!msg.senderName.empty()) {
|
||||
if (msg.type == game::ChatType::MONSTER_SAY || msg.type == game::ChatType::MONSTER_YELL) {
|
||||
if (msg.type == game::ChatType::MONSTER_SAY || msg.type == game::ChatType::MONSTER_PARTY) {
|
||||
std::string fullMsg = tsPrefix + msg.senderName + " says: " + processedMessage;
|
||||
renderTextWithLinks(fullMsg, color);
|
||||
} else if (msg.type == game::ChatType::MONSTER_YELL) {
|
||||
std::string fullMsg = tsPrefix + msg.senderName + " yells: " + processedMessage;
|
||||
renderTextWithLinks(fullMsg, color);
|
||||
} else if (msg.type == game::ChatType::MONSTER_WHISPER || msg.type == game::ChatType::RAID_BOSS_WHISPER) {
|
||||
std::string fullMsg = tsPrefix + msg.senderName + " whispers: " + processedMessage;
|
||||
renderTextWithLinks(fullMsg, color);
|
||||
} else if (msg.type == game::ChatType::MONSTER_EMOTE || msg.type == game::ChatType::RAID_BOSS_EMOTE) {
|
||||
std::string fullMsg = tsPrefix + msg.senderName + " " + processedMessage;
|
||||
renderTextWithLinks(fullMsg, color);
|
||||
} else if (msg.type == game::ChatType::CHANNEL && !msg.channelName.empty()) {
|
||||
int chIdx = gameHandler.getChannelIndex(msg.channelName);
|
||||
std::string chDisplay = chIdx > 0
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue