diff --git a/assets/shaders/character.frag.spv b/assets/shaders/character.frag.spv index f970ac7c..43789272 100644 Binary files a/assets/shaders/character.frag.spv and b/assets/shaders/character.frag.spv differ diff --git a/include/game/game_handler.hpp b/include/game/game_handler.hpp index a121d440..8aceba15 100644 --- a/include/game/game_handler.hpp +++ b/include/game/game_handler.hpp @@ -606,7 +606,16 @@ public: bool isAfk() const { return afkStatus_; } bool isDnd() const { return dndStatus_; } void replyToLastWhisper(const std::string& message); - std::string getLastWhisperSender() const { return lastWhisperSender_; } + std::string getLastWhisperSender() const { + if (!lastWhisperSender_.empty()) return lastWhisperSender_; + // Name may not have been cached when whisper arrived — resolve from GUID + if (lastWhisperSenderGuid_ != 0) { + const auto& cache = getPlayerNameCache(); + auto it = cache.find(lastWhisperSenderGuid_); + if (it != cache.end()) return it->second; + } + return ""; + } void setLastWhisperSender(const std::string& name) { lastWhisperSender_ = name; } // Party/Raid management @@ -2436,6 +2445,7 @@ private: std::string afkMessage_; std::string dndMessage_; std::string lastWhisperSender_; + uint64_t lastWhisperSenderGuid_ = 0; // ---- Online item tracking ---- struct OnlineItemInfo { diff --git a/src/game/chat_handler.cpp b/src/game/chat_handler.cpp index ec9d6e46..0c3dcd83 100644 --- a/src/game/chat_handler.cpp +++ b/src/game/chat_handler.cpp @@ -255,15 +255,22 @@ void ChatHandler::handleMessageChat(network::Packet& packet) { } // Track whisper sender for /r command - if (data.type == ChatType::WHISPER && !data.senderName.empty()) { - owner_.lastWhisperSender_ = data.senderName; + if (data.type == ChatType::WHISPER) { + // Always store GUID so getLastWhisperSender() can resolve the name + // from the player name cache even if name wasn't available yet + if (data.senderGuid != 0) + owner_.lastWhisperSenderGuid_ = data.senderGuid; + if (!data.senderName.empty()) + owner_.lastWhisperSender_ = data.senderName; - if (owner_.afkStatus_ && !data.senderName.empty()) { - std::string reply = owner_.afkMessage_.empty() ? "Away from Keyboard" : owner_.afkMessage_; - sendChatMessage(ChatType::WHISPER, " " + reply, data.senderName); - } else if (owner_.dndStatus_ && !data.senderName.empty()) { - std::string reply = owner_.dndMessage_.empty() ? "Do Not Disturb" : owner_.dndMessage_; - sendChatMessage(ChatType::WHISPER, " " + reply, data.senderName); + if (!data.senderName.empty()) { + if (owner_.afkStatus_) { + std::string reply = owner_.afkMessage_.empty() ? "Away from Keyboard" : owner_.afkMessage_; + sendChatMessage(ChatType::WHISPER, " " + reply, data.senderName); + } else if (owner_.dndStatus_) { + std::string reply = owner_.dndMessage_.empty() ? "Do Not Disturb" : owner_.dndMessage_; + sendChatMessage(ChatType::WHISPER, " " + reply, data.senderName); + } } } diff --git a/src/game/entity_controller.cpp b/src/game/entity_controller.cpp index 6a9cc826..f788fca3 100644 --- a/src/game/entity_controller.cpp +++ b/src/game/entity_controller.cpp @@ -1988,6 +1988,11 @@ void EntityController::handleNameQueryResponse(network::Packet& packet) { } } + // Backfill whisper reply target if the name arrived after the whisper. + if (owner_.lastWhisperSenderGuid_ == data.guid && owner_.lastWhisperSender_.empty()) { + owner_.lastWhisperSender_ = data.name; + } + // Backfill mail inbox sender names for (auto& mail : owner_.mailInbox_) { if (mail.messageType == 0 && mail.senderGuid == data.guid) {