Add quest details dialog, fix vendor UI, suppress both-button clicks

Parse SMSG_QUESTGIVER_QUEST_DETAILS and show quest text with Accept/
Decline buttons. Vendor window now shows item names with quality colors,
stat tooltips on hover, player money, and closes properly via X button.
Suppress left/right-click targeting and interaction when the other mouse
button is held (both-button run forward).
This commit is contained in:
Kelsi 2026-02-06 11:59:51 -08:00
parent 8b98888dd2
commit f859406671
6 changed files with 227 additions and 5 deletions

View file

@ -322,16 +322,25 @@ public:
void interactWithNpc(uint64_t guid);
void selectGossipOption(uint32_t optionId);
void selectGossipQuest(uint32_t questId);
void acceptQuest();
void declineQuest();
void closeGossip();
bool isGossipWindowOpen() const { return gossipWindowOpen; }
const GossipMessageData& getCurrentGossip() const { return currentGossip; }
bool isQuestDetailsOpen() const { return questDetailsOpen; }
const QuestDetailsData& getQuestDetails() const { return currentQuestDetails; }
// Vendor
void openVendor(uint64_t npcGuid);
void closeVendor();
void buyItem(uint64_t vendorGuid, uint32_t itemId, uint32_t slot, uint8_t count);
void sellItem(uint64_t vendorGuid, uint64_t itemGuid, uint8_t count);
bool isVendorWindowOpen() const { return vendorWindowOpen; }
const ListInventoryData& getVendorItems() const { return currentVendorItems; }
const ItemQueryResponseData* getItemInfo(uint32_t itemId) const {
auto it = itemInfoCache_.find(itemId);
return (it != itemInfoCache_.end()) ? &it->second : nullptr;
}
/**
* Set callbacks
@ -461,6 +470,7 @@ private:
void handleLootRemoved(network::Packet& packet);
void handleGossipMessage(network::Packet& packet);
void handleGossipComplete(network::Packet& packet);
void handleQuestDetails(network::Packet& packet);
void handleListInventory(network::Packet& packet);
LootResponseData generateLocalLoot(uint64_t guid);
void simulateLootResponse(const LootResponseData& data);
@ -602,6 +612,10 @@ private:
bool gossipWindowOpen = false;
GossipMessageData currentGossip;
// Quest details
bool questDetailsOpen = false;
QuestDetailsData currentQuestDetails;
// Vendor
bool vendorWindowOpen = false;
ListInventoryData currentVendorItems;

View file

@ -1182,6 +1182,24 @@ public:
static network::Packet build(uint64_t npcGuid, uint32_t questId);
};
/** SMSG_QUESTGIVER_QUEST_DETAILS data (simplified) */
struct QuestDetailsData {
uint64_t npcGuid = 0;
uint32_t questId = 0;
std::string title;
std::string details; // Quest description text
std::string objectives; // Objectives text
uint32_t suggestedPlayers = 0;
uint32_t rewardMoney = 0;
uint32_t rewardXp = 0;
};
/** SMSG_QUESTGIVER_QUEST_DETAILS parser */
class QuestDetailsParser {
public:
static bool parse(network::Packet& packet, QuestDetailsData& data);
};
// ============================================================
// Phase 5: Vendor
// ============================================================

View file

@ -131,6 +131,7 @@ private:
void renderBuffBar(game::GameHandler& gameHandler);
void renderLootWindow(game::GameHandler& gameHandler);
void renderGossipWindow(game::GameHandler& gameHandler);
void renderQuestDetailsWindow(game::GameHandler& gameHandler);
void renderVendorWindow(game::GameHandler& gameHandler);
void renderTeleporterPanel();
void renderEscapeMenu();