mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-04-17 17:43:52 +00:00
Add inspect window showing talent summary and gear for inspected players
Store inspect results (talent points, dual-spec state, gear entries) in a new InspectResult struct instead of discarding them as chat messages. Open the inspect window automatically from all Inspect menu items and /inspect.
This commit is contained in:
parent
92db25038c
commit
43de2be1f2
4 changed files with 129 additions and 9 deletions
|
|
@ -332,6 +332,19 @@ public:
|
||||||
// Inspection
|
// Inspection
|
||||||
void inspectTarget();
|
void inspectTarget();
|
||||||
|
|
||||||
|
struct InspectResult {
|
||||||
|
uint64_t guid = 0;
|
||||||
|
std::string playerName;
|
||||||
|
uint32_t totalTalents = 0;
|
||||||
|
uint32_t unspentTalents = 0;
|
||||||
|
uint8_t talentGroups = 0;
|
||||||
|
uint8_t activeTalentGroup = 0;
|
||||||
|
std::array<uint32_t, 19> itemEntries{}; // 0=head…18=ranged
|
||||||
|
};
|
||||||
|
const InspectResult* getInspectResult() const {
|
||||||
|
return inspectResult_.guid ? &inspectResult_ : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
// Server info commands
|
// Server info commands
|
||||||
void queryServerTime();
|
void queryServerTime();
|
||||||
void requestPlayedTime();
|
void requestPlayedTime();
|
||||||
|
|
@ -2019,6 +2032,7 @@ private:
|
||||||
|
|
||||||
// Inspect fallback (when visible item fields are missing/unreliable)
|
// Inspect fallback (when visible item fields are missing/unreliable)
|
||||||
std::unordered_map<uint64_t, std::array<uint32_t, 19>> inspectedPlayerItemEntries_;
|
std::unordered_map<uint64_t, std::array<uint32_t, 19>> inspectedPlayerItemEntries_;
|
||||||
|
InspectResult inspectResult_; // most-recently received inspect response
|
||||||
std::unordered_set<uint64_t> pendingAutoInspect_;
|
std::unordered_set<uint64_t> pendingAutoInspect_;
|
||||||
float inspectRateLimit_ = 0.0f;
|
float inspectRateLimit_ = 0.0f;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -364,6 +364,10 @@ private:
|
||||||
bool showGmTicketWindow_ = false;
|
bool showGmTicketWindow_ = false;
|
||||||
char gmTicketBuf_[2048] = {};
|
char gmTicketBuf_[2048] = {};
|
||||||
void renderGmTicketWindow(game::GameHandler& gameHandler);
|
void renderGmTicketWindow(game::GameHandler& gameHandler);
|
||||||
|
|
||||||
|
// Inspect window
|
||||||
|
bool showInspectWindow_ = false;
|
||||||
|
void renderInspectWindow(game::GameHandler& gameHandler);
|
||||||
uint8_t lfgRoles_ = 0x08; // default: DPS (0x02=tank, 0x04=healer, 0x08=dps)
|
uint8_t lfgRoles_ = 0x08; // default: DPS (0x02=tank, 0x04=healer, 0x08=dps)
|
||||||
uint32_t lfgSelectedDungeon_ = 861; // default: random dungeon (entry 861 = Random Dungeon WotLK)
|
uint32_t lfgSelectedDungeon_ = 861; // default: random dungeon (entry 861 = Random Dungeon WotLK)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11258,16 +11258,21 @@ void GameHandler::handleInspectResults(network::Packet& packet) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Display inspect results
|
// Store inspect result for UI display
|
||||||
std::string msg = "Inspect: " + playerName;
|
inspectResult_.guid = guid;
|
||||||
msg += " - " + std::to_string(totalTalents) + " talent points spent";
|
inspectResult_.playerName = playerName;
|
||||||
if (unspentTalents > 0) {
|
inspectResult_.totalTalents = totalTalents;
|
||||||
msg += ", " + std::to_string(unspentTalents) + " unspent";
|
inspectResult_.unspentTalents = unspentTalents;
|
||||||
|
inspectResult_.talentGroups = talentGroupCount;
|
||||||
|
inspectResult_.activeTalentGroup = activeTalentGroup;
|
||||||
|
|
||||||
|
// Merge any gear we already have from a prior inspect request
|
||||||
|
auto gearIt = inspectedPlayerItemEntries_.find(guid);
|
||||||
|
if (gearIt != inspectedPlayerItemEntries_.end()) {
|
||||||
|
inspectResult_.itemEntries = gearIt->second;
|
||||||
|
} else {
|
||||||
|
inspectResult_.itemEntries = {};
|
||||||
}
|
}
|
||||||
if (talentGroupCount > 1) {
|
|
||||||
msg += " (dual spec, active: " + std::to_string(activeTalentGroup + 1) + ")";
|
|
||||||
}
|
|
||||||
addSystemChatMessage(msg);
|
|
||||||
|
|
||||||
LOG_INFO("Inspect results for ", playerName, ": ", totalTalents, " talents, ",
|
LOG_INFO("Inspect results for ", playerName, ": ", totalTalents, " talents, ",
|
||||||
unspentTalents, " unspent, ", (int)talentGroupCount, " specs");
|
unspentTalents, " unspent, ", (int)talentGroupCount, " specs");
|
||||||
|
|
|
||||||
|
|
@ -499,6 +499,7 @@ void GameScreen::render(game::GameHandler& gameHandler) {
|
||||||
renderInstanceLockouts(gameHandler);
|
renderInstanceLockouts(gameHandler);
|
||||||
renderAchievementWindow(gameHandler);
|
renderAchievementWindow(gameHandler);
|
||||||
renderGmTicketWindow(gameHandler);
|
renderGmTicketWindow(gameHandler);
|
||||||
|
renderInspectWindow(gameHandler);
|
||||||
// renderQuestMarkers(gameHandler); // Disabled - using 3D billboard markers now
|
// renderQuestMarkers(gameHandler); // Disabled - using 3D billboard markers now
|
||||||
if (showMinimap_) {
|
if (showMinimap_) {
|
||||||
renderMinimapMarkers(gameHandler);
|
renderMinimapMarkers(gameHandler);
|
||||||
|
|
@ -2621,6 +2622,7 @@ void GameScreen::renderTargetFrame(game::GameHandler& gameHandler) {
|
||||||
}
|
}
|
||||||
if (ImGui::MenuItem("Inspect")) {
|
if (ImGui::MenuItem("Inspect")) {
|
||||||
gameHandler.inspectTarget();
|
gameHandler.inspectTarget();
|
||||||
|
showInspectWindow_ = true;
|
||||||
}
|
}
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
if (ImGui::MenuItem("Add Friend")) {
|
if (ImGui::MenuItem("Add Friend")) {
|
||||||
|
|
@ -3009,6 +3011,7 @@ void GameScreen::renderFocusFrame(game::GameHandler& gameHandler) {
|
||||||
if (ImGui::MenuItem("Inspect")) {
|
if (ImGui::MenuItem("Inspect")) {
|
||||||
gameHandler.setTarget(fGuid);
|
gameHandler.setTarget(fGuid);
|
||||||
gameHandler.inspectTarget();
|
gameHandler.inspectTarget();
|
||||||
|
showInspectWindow_ = true;
|
||||||
}
|
}
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
if (ImGui::MenuItem("Add Friend"))
|
if (ImGui::MenuItem("Add Friend"))
|
||||||
|
|
@ -3144,6 +3147,7 @@ void GameScreen::sendChatMessage(game::GameHandler& gameHandler) {
|
||||||
// /inspect command
|
// /inspect command
|
||||||
if (cmdLower == "inspect") {
|
if (cmdLower == "inspect") {
|
||||||
gameHandler.inspectTarget();
|
gameHandler.inspectTarget();
|
||||||
|
showInspectWindow_ = true;
|
||||||
chatInputBuffer[0] = '\0';
|
chatInputBuffer[0] = '\0';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -6348,6 +6352,7 @@ void GameScreen::renderPartyFrames(game::GameHandler& gameHandler) {
|
||||||
if (ImGui::MenuItem("Inspect")) {
|
if (ImGui::MenuItem("Inspect")) {
|
||||||
gameHandler.setTarget(m.guid);
|
gameHandler.setTarget(m.guid);
|
||||||
gameHandler.inspectTarget();
|
gameHandler.inspectTarget();
|
||||||
|
showInspectWindow_ = true;
|
||||||
}
|
}
|
||||||
bool isLeader = (partyData.leaderGuid == gameHandler.getPlayerGuid());
|
bool isLeader = (partyData.leaderGuid == gameHandler.getPlayerGuid());
|
||||||
if (isLeader) {
|
if (isLeader) {
|
||||||
|
|
@ -6532,6 +6537,7 @@ void GameScreen::renderPartyFrames(game::GameHandler& gameHandler) {
|
||||||
if (ImGui::MenuItem("Inspect")) {
|
if (ImGui::MenuItem("Inspect")) {
|
||||||
gameHandler.setTarget(member.guid);
|
gameHandler.setTarget(member.guid);
|
||||||
gameHandler.inspectTarget();
|
gameHandler.inspectTarget();
|
||||||
|
showInspectWindow_ = true;
|
||||||
}
|
}
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
if (!member.name.empty()) {
|
if (!member.name.empty()) {
|
||||||
|
|
@ -14484,4 +14490,95 @@ void GameScreen::renderGmTicketWindow(game::GameHandler& gameHandler) {
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ─── Inspect Window ───────────────────────────────────────────────────────────
|
||||||
|
void GameScreen::renderInspectWindow(game::GameHandler& gameHandler) {
|
||||||
|
if (!showInspectWindow_) return;
|
||||||
|
|
||||||
|
// Slot index 0..18 maps to equipment slots 1..19 (WoW convention: slot 0 unused on server)
|
||||||
|
static const char* kSlotNames[19] = {
|
||||||
|
"Head", "Neck", "Shoulder", "Shirt", "Chest",
|
||||||
|
"Waist", "Legs", "Feet", "Wrist", "Hands",
|
||||||
|
"Finger 1", "Finger 2", "Trinket 1", "Trinket 2", "Back",
|
||||||
|
"Main Hand", "Off Hand", "Ranged", "Tabard"
|
||||||
|
};
|
||||||
|
|
||||||
|
ImGui::SetNextWindowSize(ImVec2(360, 440), ImGuiCond_FirstUseEver);
|
||||||
|
ImGui::SetNextWindowPos(ImVec2(350, 120), ImGuiCond_FirstUseEver);
|
||||||
|
|
||||||
|
const game::GameHandler::InspectResult* result = gameHandler.getInspectResult();
|
||||||
|
|
||||||
|
std::string title = result ? ("Inspect: " + result->playerName + "###InspectWin")
|
||||||
|
: "Inspect###InspectWin";
|
||||||
|
if (!ImGui::Begin(title.c_str(), &showInspectWindow_, ImGuiWindowFlags_NoCollapse)) {
|
||||||
|
ImGui::End();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!result) {
|
||||||
|
ImGui::TextDisabled("No inspect data yet. Target a player and use Inspect.");
|
||||||
|
ImGui::End();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Talent summary
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.82f, 0.0f, 1.0f)); // gold
|
||||||
|
ImGui::Text("%s", result->playerName.c_str());
|
||||||
|
ImGui::PopStyleColor();
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::TextDisabled(" %u talent pts", result->totalTalents);
|
||||||
|
if (result->unspentTalents > 0) {
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::TextColored(ImVec4(1.0f, 0.4f, 0.4f, 1.0f), "(%u unspent)", result->unspentTalents);
|
||||||
|
}
|
||||||
|
if (result->talentGroups > 1) {
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::TextDisabled(" Dual spec (active %u)", (unsigned)result->activeTalentGroup + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::Separator();
|
||||||
|
|
||||||
|
// Equipment list
|
||||||
|
bool hasAnyGear = false;
|
||||||
|
for (int s = 0; s < 19; ++s) {
|
||||||
|
if (result->itemEntries[s] != 0) { hasAnyGear = true; break; }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hasAnyGear) {
|
||||||
|
ImGui::TextDisabled("Equipment data not yet available.");
|
||||||
|
ImGui::TextDisabled("(Gear loads after the player is inspected in-range)");
|
||||||
|
} else {
|
||||||
|
if (ImGui::BeginChild("##inspect_gear", ImVec2(0, 0), false)) {
|
||||||
|
for (int s = 0; s < 19; ++s) {
|
||||||
|
uint32_t entry = result->itemEntries[s];
|
||||||
|
if (entry == 0) continue;
|
||||||
|
|
||||||
|
const game::ItemQueryResponseData* info = gameHandler.getItemInfo(entry);
|
||||||
|
if (!info) {
|
||||||
|
gameHandler.ensureItemInfo(entry);
|
||||||
|
ImGui::TextDisabled("[%s] (loading…)", kSlotNames[s]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::TextDisabled("%s", kSlotNames[s]);
|
||||||
|
ImGui::SameLine(90);
|
||||||
|
auto qColor = InventoryScreen::getQualityColor(
|
||||||
|
static_cast<game::ItemQuality>(info->quality));
|
||||||
|
ImGui::TextColored(qColor, "%s", info->name.c_str());
|
||||||
|
if (ImGui::IsItemHovered()) {
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::TextColored(qColor, "%s", info->name.c_str());
|
||||||
|
if (info->itemLevel > 0)
|
||||||
|
ImGui::Text("Item Level %u", info->itemLevel);
|
||||||
|
if (info->armor > 0)
|
||||||
|
ImGui::Text("Armor: %d", info->armor);
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::EndChild();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::End();
|
||||||
|
}
|
||||||
|
|
||||||
}} // namespace wowee::ui
|
}} // namespace wowee::ui
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue