mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-03-22 23:30:14 +00:00
Refine bag UI layout and add shift-hover item compare
This commit is contained in:
parent
fc0ac6dd0f
commit
b3ea6d8e81
3 changed files with 242 additions and 25 deletions
|
|
@ -37,6 +37,10 @@ public:
|
|||
void closeAllBags();
|
||||
void setSeparateBags(bool sep) { separateBags_ = sep; }
|
||||
bool isSeparateBags() const { return separateBags_; }
|
||||
void toggleCompactBags() { compactBags_ = !compactBags_; }
|
||||
bool isCompactBags() const { return compactBags_; }
|
||||
bool isBackpackOpen() const { return backpackOpen_; }
|
||||
bool isBagOpen(int idx) const { return idx >= 0 && idx < 4 ? bagOpen_[idx] : false; }
|
||||
|
||||
bool isCharacterOpen() const { return characterOpen; }
|
||||
void toggleCharacter() { characterOpen = !characterOpen; }
|
||||
|
|
@ -74,6 +78,7 @@ private:
|
|||
bool characterOpen = false;
|
||||
bool bKeyWasDown = false;
|
||||
bool separateBags_ = true;
|
||||
bool compactBags_ = false;
|
||||
bool backpackOpen_ = false;
|
||||
std::array<bool, 4> bagOpen_{};
|
||||
bool cKeyWasDown = false;
|
||||
|
|
@ -125,7 +130,7 @@ private:
|
|||
void renderBagWindow(const char* title, bool& isOpen, game::Inventory& inventory,
|
||||
int bagIndex, float defaultX, float defaultY, uint64_t moneyCopper);
|
||||
void renderEquipmentPanel(game::Inventory& inventory);
|
||||
void renderBackpackPanel(game::Inventory& inventory);
|
||||
void renderBackpackPanel(game::Inventory& inventory, bool collapseEmptySections = false);
|
||||
void renderStatsPanel(game::Inventory& inventory, uint32_t playerLevel);
|
||||
|
||||
// Slot rendering with interaction support
|
||||
|
|
@ -135,7 +140,7 @@ private:
|
|||
SlotKind kind, int backpackIndex,
|
||||
game::EquipSlot equipSlot,
|
||||
int bagIndex = -1, int bagSlotIndex = -1);
|
||||
void renderItemTooltip(const game::ItemDef& item);
|
||||
void renderItemTooltip(const game::ItemDef& item, const game::Inventory* inventory = nullptr);
|
||||
|
||||
// Held item helpers
|
||||
void pickupFromBackpack(game::Inventory& inv, int index);
|
||||
|
|
@ -147,6 +152,7 @@ private:
|
|||
void cancelPickup(game::Inventory& inv);
|
||||
game::EquipSlot getEquipSlotForType(uint8_t inventoryType, game::Inventory& inv);
|
||||
void renderHeldItem();
|
||||
bool bagHasAnyItems(const game::Inventory& inventory, int bagIndex) const;
|
||||
|
||||
// Drop confirmation
|
||||
bool dropConfirmOpen_ = false;
|
||||
|
|
|
|||
|
|
@ -663,6 +663,55 @@ void GameScreen::renderChatWindow(game::GameHandler& gameHandler) {
|
|||
auto renderItemLinkTooltip = [&](uint32_t itemEntry) {
|
||||
const auto* info = gameHandler.getItemInfo(itemEntry);
|
||||
if (!info || !info->valid) return;
|
||||
auto findComparableEquipped = [&](uint8_t inventoryType) -> const game::ItemSlot* {
|
||||
using ES = game::EquipSlot;
|
||||
const auto& inv = gameHandler.getInventory();
|
||||
auto slotPtr = [&](ES slot) -> const game::ItemSlot* {
|
||||
const auto& s = inv.getEquipSlot(slot);
|
||||
return s.empty() ? nullptr : &s;
|
||||
};
|
||||
switch (inventoryType) {
|
||||
case 1: return slotPtr(ES::HEAD);
|
||||
case 2: return slotPtr(ES::NECK);
|
||||
case 3: return slotPtr(ES::SHOULDERS);
|
||||
case 4: return slotPtr(ES::SHIRT);
|
||||
case 5:
|
||||
case 20: return slotPtr(ES::CHEST);
|
||||
case 6: return slotPtr(ES::WAIST);
|
||||
case 7: return slotPtr(ES::LEGS);
|
||||
case 8: return slotPtr(ES::FEET);
|
||||
case 9: return slotPtr(ES::WRISTS);
|
||||
case 10: return slotPtr(ES::HANDS);
|
||||
case 11: {
|
||||
if (auto* s = slotPtr(ES::RING1)) return s;
|
||||
return slotPtr(ES::RING2);
|
||||
}
|
||||
case 12: {
|
||||
if (auto* s = slotPtr(ES::TRINKET1)) return s;
|
||||
return slotPtr(ES::TRINKET2);
|
||||
}
|
||||
case 13:
|
||||
if (auto* s = slotPtr(ES::MAIN_HAND)) return s;
|
||||
return slotPtr(ES::OFF_HAND);
|
||||
case 14:
|
||||
case 22:
|
||||
case 23: return slotPtr(ES::OFF_HAND);
|
||||
case 15:
|
||||
case 25:
|
||||
case 26: return slotPtr(ES::RANGED);
|
||||
case 16: return slotPtr(ES::BACK);
|
||||
case 17:
|
||||
case 21: return slotPtr(ES::MAIN_HAND);
|
||||
case 18:
|
||||
for (int i = 0; i < game::Inventory::NUM_BAG_SLOTS; ++i) {
|
||||
auto slot = static_cast<ES>(static_cast<int>(ES::BAG1) + i);
|
||||
if (auto* s = slotPtr(slot)) return s;
|
||||
}
|
||||
return nullptr;
|
||||
case 19: return slotPtr(ES::TABARD);
|
||||
default: return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
ImGui::BeginTooltip();
|
||||
// Quality color for name
|
||||
|
|
@ -741,6 +790,28 @@ void GameScreen::renderChatWindow(game::GameHandler& gameHandler) {
|
|||
ImGui::Separator();
|
||||
ImGui::TextColored(ImVec4(1.0f, 0.84f, 0.0f, 1.0f), "Sell Price: %ug %us %uc", g, s, c);
|
||||
}
|
||||
|
||||
if (ImGui::GetIO().KeyShift && info->inventoryType > 0) {
|
||||
if (const auto* eq = findComparableEquipped(static_cast<uint8_t>(info->inventoryType))) {
|
||||
ImGui::Separator();
|
||||
ImGui::TextDisabled("Equipped:");
|
||||
GLuint eqIcon = inventoryScreen.getItemIcon(eq->item.displayInfoId);
|
||||
if (eqIcon) {
|
||||
ImGui::Image((ImTextureID)(uintptr_t)eqIcon, ImVec2(18.0f, 18.0f));
|
||||
ImGui::SameLine();
|
||||
}
|
||||
ImGui::TextColored(InventoryScreen::getQualityColor(eq->item.quality), "%s", eq->item.name.c_str());
|
||||
if (eq->item.damageMax > 0.0f) {
|
||||
ImGui::Text("%.0f - %.0f Damage", eq->item.damageMin, eq->item.damageMax);
|
||||
}
|
||||
if (eq->item.armor > 0) ImGui::Text("%d Armor", eq->item.armor);
|
||||
renderStat(eq->item.stamina, "Stamina");
|
||||
renderStat(eq->item.strength, "Strength");
|
||||
renderStat(eq->item.agility, "Agility");
|
||||
renderStat(eq->item.intellect, "Intellect");
|
||||
renderStat(eq->item.spirit, "Spirit");
|
||||
}
|
||||
}
|
||||
ImGui::EndTooltip();
|
||||
};
|
||||
|
||||
|
|
@ -3504,6 +3575,14 @@ void GameScreen::renderBagBar(game::GameHandler& gameHandler) {
|
|||
}
|
||||
}
|
||||
|
||||
if (inventoryScreen.isSeparateBags() &&
|
||||
inventoryScreen.isBagOpen(i)) {
|
||||
ImDrawList* dl = ImGui::GetWindowDrawList();
|
||||
ImVec2 r0 = ImGui::GetItemRectMin();
|
||||
ImVec2 r1 = ImGui::GetItemRectMax();
|
||||
dl->AddRect(r0, r1, IM_COL32(255, 255, 255, 255), 3.0f, 0, 2.0f);
|
||||
}
|
||||
|
||||
// Accept dragged item from inventory
|
||||
if (ImGui::IsItemHovered() && inventoryScreen.isHoldingItem()) {
|
||||
const auto& heldItem = inventoryScreen.getHeldItem();
|
||||
|
|
@ -3544,7 +3623,15 @@ void GameScreen::renderBagBar(game::GameHandler& gameHandler) {
|
|||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Backpack");
|
||||
}
|
||||
if (inventoryScreen.isSeparateBags() &&
|
||||
inventoryScreen.isBackpackOpen()) {
|
||||
ImDrawList* dl = ImGui::GetWindowDrawList();
|
||||
ImVec2 r0 = ImGui::GetItemRectMin();
|
||||
ImVec2 r1 = ImGui::GetItemRectMax();
|
||||
dl->AddRect(r0, r1, IM_COL32(255, 255, 255, 255), 3.0f, 0, 2.0f);
|
||||
}
|
||||
ImGui::PopID();
|
||||
|
||||
}
|
||||
ImGui::End();
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,58 @@
|
|||
namespace wowee {
|
||||
namespace ui {
|
||||
|
||||
namespace {
|
||||
const game::ItemSlot* findComparableEquipped(const game::Inventory& inventory, uint8_t inventoryType) {
|
||||
using ES = game::EquipSlot;
|
||||
auto slotPtr = [&](ES slot) -> const game::ItemSlot* {
|
||||
const auto& s = inventory.getEquipSlot(slot);
|
||||
return s.empty() ? nullptr : &s;
|
||||
};
|
||||
|
||||
switch (inventoryType) {
|
||||
case 1: return slotPtr(ES::HEAD);
|
||||
case 2: return slotPtr(ES::NECK);
|
||||
case 3: return slotPtr(ES::SHOULDERS);
|
||||
case 4: return slotPtr(ES::SHIRT);
|
||||
case 5:
|
||||
case 20: return slotPtr(ES::CHEST);
|
||||
case 6: return slotPtr(ES::WAIST);
|
||||
case 7: return slotPtr(ES::LEGS);
|
||||
case 8: return slotPtr(ES::FEET);
|
||||
case 9: return slotPtr(ES::WRISTS);
|
||||
case 10: return slotPtr(ES::HANDS);
|
||||
case 11: {
|
||||
if (auto* s = slotPtr(ES::RING1)) return s;
|
||||
return slotPtr(ES::RING2);
|
||||
}
|
||||
case 12: {
|
||||
if (auto* s = slotPtr(ES::TRINKET1)) return s;
|
||||
return slotPtr(ES::TRINKET2);
|
||||
}
|
||||
case 13: // One-hand
|
||||
if (auto* s = slotPtr(ES::MAIN_HAND)) return s;
|
||||
return slotPtr(ES::OFF_HAND);
|
||||
case 14:
|
||||
case 22:
|
||||
case 23: return slotPtr(ES::OFF_HAND);
|
||||
case 15:
|
||||
case 25:
|
||||
case 26: return slotPtr(ES::RANGED);
|
||||
case 16: return slotPtr(ES::BACK);
|
||||
case 17:
|
||||
case 21: return slotPtr(ES::MAIN_HAND);
|
||||
case 18: // bag
|
||||
for (int i = 0; i < game::Inventory::NUM_BAG_SLOTS; ++i) {
|
||||
auto slot = static_cast<ES>(static_cast<int>(ES::BAG1) + i);
|
||||
if (auto* s = slotPtr(slot)) return s;
|
||||
}
|
||||
return nullptr;
|
||||
case 19: return slotPtr(ES::TABARD);
|
||||
default: return nullptr;
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
InventoryScreen::~InventoryScreen() {
|
||||
// Clean up icon textures
|
||||
for (auto& [id, tex] : iconCache_) {
|
||||
|
|
@ -614,8 +666,13 @@ void InventoryScreen::toggleBackpack() {
|
|||
}
|
||||
|
||||
void InventoryScreen::toggleBag(int idx) {
|
||||
if (idx >= 0 && idx < 4)
|
||||
if (idx >= 0 && idx < 4) {
|
||||
bagOpen_[idx] = !bagOpen_[idx];
|
||||
if (bagOpen_[idx]) {
|
||||
// Keep backpack as the anchor window at the bottom of the stack.
|
||||
backpackOpen_ = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InventoryScreen::openAllBags() {
|
||||
|
|
@ -628,6 +685,15 @@ void InventoryScreen::closeAllBags() {
|
|||
for (auto& b : bagOpen_) b = false;
|
||||
}
|
||||
|
||||
bool InventoryScreen::bagHasAnyItems(const game::Inventory& inventory, int bagIndex) const {
|
||||
int bagSize = inventory.getBagSize(bagIndex);
|
||||
if (bagSize <= 0) return false;
|
||||
for (int i = 0; i < bagSize; ++i) {
|
||||
if (!inventory.getBagSlot(bagIndex, i).empty()) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void InventoryScreen::render(game::Inventory& inventory, uint64_t moneyCopper) {
|
||||
// B key toggle (edge-triggered)
|
||||
bool wantsTextInput = ImGui::GetIO().WantTextInput;
|
||||
|
|
@ -724,13 +790,14 @@ void InventoryScreen::renderAggregateBags(game::Inventory& inventory, uint64_t m
|
|||
float screenH = io.DisplaySize.y;
|
||||
|
||||
constexpr float slotSize = 40.0f;
|
||||
constexpr int columns = 4;
|
||||
constexpr int columns = 6;
|
||||
int rows = (inventory.getBackpackSize() + columns - 1) / columns;
|
||||
float bagContentH = rows * (slotSize + 4.0f) + 40.0f;
|
||||
|
||||
for (int bag = 0; bag < game::Inventory::NUM_BAG_SLOTS; bag++) {
|
||||
int bagSize = inventory.getBagSize(bag);
|
||||
if (bagSize <= 0) continue;
|
||||
if (compactBags_ && !bagHasAnyItems(inventory, bag)) continue;
|
||||
int bagRows = (bagSize + columns - 1) / columns;
|
||||
bagContentH += bagRows * (slotSize + 4.0f) + 30.0f;
|
||||
}
|
||||
|
|
@ -750,7 +817,7 @@ void InventoryScreen::renderAggregateBags(game::Inventory& inventory, uint64_t m
|
|||
return;
|
||||
}
|
||||
|
||||
renderBackpackPanel(inventory);
|
||||
renderBackpackPanel(inventory, compactBags_);
|
||||
|
||||
ImGui::Spacing();
|
||||
uint64_t gold = moneyCopper / 10000;
|
||||
|
|
@ -760,6 +827,18 @@ void InventoryScreen::renderAggregateBags(game::Inventory& inventory, uint64_t m
|
|||
static_cast<unsigned long long>(gold),
|
||||
static_cast<unsigned long long>(silver),
|
||||
static_cast<unsigned long long>(copper));
|
||||
ImGui::SameLine();
|
||||
const char* collapseLabel = compactBags_ ? "Expand Empty" : "Collapse Empty";
|
||||
const float btnW = 92.0f;
|
||||
const float rightMargin = 8.0f;
|
||||
float rightX = ImGui::GetWindowContentRegionMax().x - btnW - rightMargin;
|
||||
if (rightX > ImGui::GetCursorPosX()) ImGui::SetCursorPosX(rightX);
|
||||
if (ImGui::SmallButton(collapseLabel)) {
|
||||
compactBags_ = !compactBags_;
|
||||
}
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Toggle empty bag section visibility");
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
|
|
@ -773,31 +852,47 @@ void InventoryScreen::renderSeparateBags(game::Inventory& inventory, uint64_t mo
|
|||
float screenH = io.DisplaySize.y;
|
||||
|
||||
constexpr float slotSize = 40.0f;
|
||||
constexpr int columns = 4;
|
||||
constexpr int columns = 6;
|
||||
constexpr float baseWindowW = columns * (slotSize + 4.0f) + 30.0f;
|
||||
|
||||
// Backpack window (rightmost, bottom-right)
|
||||
bool anyBagOpen = std::any_of(bagOpen_.begin(), bagOpen_.end(), [](bool b) { return b; });
|
||||
if (anyBagOpen && !backpackOpen_) {
|
||||
// Enforce backpack as the bottom-most stack window when any bag is open.
|
||||
backpackOpen_ = true;
|
||||
}
|
||||
|
||||
// Anchor stack to the bag bar (bottom-right), opening upward.
|
||||
const float bagBarTop = screenH - (42.0f + 12.0f) - 10.0f;
|
||||
const float stackGap = 8.0f;
|
||||
float stackBottom = bagBarTop - stackGap;
|
||||
float stackX = screenW - baseWindowW - 10.0f;
|
||||
|
||||
// Backpack window (bottom of stack)
|
||||
if (backpackOpen_) {
|
||||
int bpRows = (inventory.getBackpackSize() + columns - 1) / columns;
|
||||
float bpH = bpRows * (slotSize + 4.0f) + 80.0f; // header + money + padding
|
||||
float defaultX = screenW - baseWindowW - 10.0f;
|
||||
float defaultY = screenH - bpH - 60.0f;
|
||||
renderBagWindow("Backpack", backpackOpen_, inventory, -1, defaultX, defaultY, moneyCopper);
|
||||
float defaultY = stackBottom - bpH;
|
||||
renderBagWindow("Backpack", backpackOpen_, inventory, -1, stackX, defaultY, moneyCopper);
|
||||
stackBottom = defaultY - stackGap;
|
||||
}
|
||||
|
||||
// Extra bag windows (stacked to the left of backpack)
|
||||
for (int bag = 0; bag < game::Inventory::NUM_BAG_SLOTS; bag++) {
|
||||
// Extra bag windows in right-to-left bag-bar order (closest to backpack first).
|
||||
constexpr int kBagOrder[game::Inventory::NUM_BAG_SLOTS] = {3, 2, 1, 0};
|
||||
for (int ord = 0; ord < game::Inventory::NUM_BAG_SLOTS; ++ord) {
|
||||
int bag = kBagOrder[ord];
|
||||
if (!bagOpen_[bag]) continue;
|
||||
int bagSize = inventory.getBagSize(bag);
|
||||
if (bagSize <= 0) {
|
||||
bagOpen_[bag] = false;
|
||||
continue;
|
||||
}
|
||||
// In separate-bag mode, never auto-hide empty bags. Players still need
|
||||
// to open empty bags to move items into them.
|
||||
|
||||
int bagRows = (bagSize + columns - 1) / columns;
|
||||
float bagH = bagRows * (slotSize + 4.0f) + 60.0f;
|
||||
float defaultX = screenW - (baseWindowW + 10.0f) * (bag + 2) - 10.0f;
|
||||
float defaultY = screenH - bagH - 60.0f;
|
||||
float defaultY = stackBottom - bagH;
|
||||
stackBottom = defaultY - stackGap;
|
||||
|
||||
// Build title from equipped bag item name
|
||||
char title[64];
|
||||
|
|
@ -806,10 +901,10 @@ void InventoryScreen::renderSeparateBags(game::Inventory& inventory, uint64_t mo
|
|||
if (!bagItem.empty() && !bagItem.item.name.empty()) {
|
||||
snprintf(title, sizeof(title), "%s##bag%d", bagItem.item.name.c_str(), bag);
|
||||
} else {
|
||||
snprintf(title, sizeof(title), "Bag %d##bag%d", bag + 1, bag);
|
||||
snprintf(title, sizeof(title), "Bag Slot %d##bag%d", bag + 1, bag);
|
||||
}
|
||||
|
||||
renderBagWindow(title, bagOpen_[bag], inventory, bag, defaultX, defaultY, 0);
|
||||
renderBagWindow(title, bagOpen_[bag], inventory, bag, stackX, defaultY, 0);
|
||||
}
|
||||
|
||||
// Update open state based on individual windows
|
||||
|
|
@ -820,7 +915,7 @@ void InventoryScreen::renderBagWindow(const char* title, bool& isOpen,
|
|||
game::Inventory& inventory, int bagIndex,
|
||||
float defaultX, float defaultY, uint64_t moneyCopper) {
|
||||
constexpr float slotSize = 40.0f;
|
||||
constexpr int columns = 4;
|
||||
constexpr int columns = 6;
|
||||
|
||||
int numSlots = (bagIndex < 0) ? inventory.getBackpackSize() : inventory.getBagSize(bagIndex);
|
||||
if (numSlots <= 0) return;
|
||||
|
|
@ -836,7 +931,8 @@ void InventoryScreen::renderBagWindow(const char* title, bool& isOpen,
|
|||
float windowW = std::max(gridW, titleW);
|
||||
float windowH = contentH + 40.0f; // title bar + padding
|
||||
|
||||
ImGui::SetNextWindowPos(ImVec2(defaultX, defaultY), ImGuiCond_FirstUseEver);
|
||||
// Keep separate bag windows anchored to the bag-bar stack.
|
||||
ImGui::SetNextWindowPos(ImVec2(defaultX, defaultY), ImGuiCond_Always);
|
||||
ImGui::SetNextWindowSize(ImVec2(windowW, windowH), ImGuiCond_Always);
|
||||
|
||||
ImGuiWindowFlags flags = ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize;
|
||||
|
|
@ -1197,12 +1293,12 @@ void InventoryScreen::renderStatsPanel(game::Inventory& inventory, uint32_t play
|
|||
renderStat("Spirit", totalSpi);
|
||||
}
|
||||
|
||||
void InventoryScreen::renderBackpackPanel(game::Inventory& inventory) {
|
||||
void InventoryScreen::renderBackpackPanel(game::Inventory& inventory, bool collapseEmptySections) {
|
||||
ImGui::TextColored(ImVec4(1.0f, 0.84f, 0.0f, 1.0f), "Backpack");
|
||||
ImGui::Separator();
|
||||
|
||||
constexpr float slotSize = 40.0f;
|
||||
constexpr int columns = 4;
|
||||
constexpr int columns = 6;
|
||||
|
||||
for (int i = 0; i < inventory.getBackpackSize(); i++) {
|
||||
if (i % columns != 0) ImGui::SameLine();
|
||||
|
|
@ -1220,12 +1316,16 @@ void InventoryScreen::renderBackpackPanel(game::Inventory& inventory) {
|
|||
for (int bag = 0; bag < game::Inventory::NUM_BAG_SLOTS; bag++) {
|
||||
int bagSize = inventory.getBagSize(bag);
|
||||
if (bagSize <= 0) continue;
|
||||
if (collapseEmptySections && !bagHasAnyItems(inventory, bag)) continue;
|
||||
|
||||
ImGui::Spacing();
|
||||
ImGui::Separator();
|
||||
char bagLabel[32];
|
||||
snprintf(bagLabel, sizeof(bagLabel), "Bag %d", bag + 1);
|
||||
ImGui::TextColored(ImVec4(0.8f, 0.8f, 0.0f, 1.0f), "%s", bagLabel);
|
||||
game::EquipSlot bagSlot = static_cast<game::EquipSlot>(static_cast<int>(game::EquipSlot::BAG1) + bag);
|
||||
const auto& bagItem = inventory.getEquipSlot(bagSlot);
|
||||
std::string bagLabel = (!bagItem.empty() && !bagItem.item.name.empty())
|
||||
? bagItem.item.name
|
||||
: ("Bag Slot " + std::to_string(bag + 1));
|
||||
ImGui::TextColored(ImVec4(0.8f, 0.8f, 0.0f, 1.0f), "%s", bagLabel.c_str());
|
||||
|
||||
for (int s = 0; s < bagSize; s++) {
|
||||
if (s % columns != 0) ImGui::SameLine();
|
||||
|
|
@ -1400,12 +1500,12 @@ void InventoryScreen::renderItemSlot(game::Inventory& inventory, const game::Ite
|
|||
}
|
||||
|
||||
if (ImGui::IsItemHovered() && !holdingItem) {
|
||||
renderItemTooltip(item);
|
||||
renderItemTooltip(item, &inventory);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InventoryScreen::renderItemTooltip(const game::ItemDef& item) {
|
||||
void InventoryScreen::renderItemTooltip(const game::ItemDef& item, const game::Inventory* inventory) {
|
||||
ImGui::BeginTooltip();
|
||||
|
||||
ImVec4 qColor = getQualityColor(item.quality);
|
||||
|
|
@ -1518,6 +1618,30 @@ void InventoryScreen::renderItemTooltip(const game::ItemDef& item) {
|
|||
ImGui::TextColored(ImVec4(1.0f, 0.84f, 0.0f, 1.0f), "Sell Price: %ug %us %uc", g, s, c);
|
||||
}
|
||||
|
||||
// Shift-hover comparison with currently equipped equivalent.
|
||||
if (inventory && ImGui::GetIO().KeyShift && item.inventoryType > 0) {
|
||||
if (const game::ItemSlot* eq = findComparableEquipped(*inventory, item.inventoryType)) {
|
||||
ImGui::Separator();
|
||||
ImGui::TextDisabled("Equipped:");
|
||||
GLuint eqIcon = getItemIcon(eq->item.displayInfoId);
|
||||
if (eqIcon) {
|
||||
ImGui::Image((ImTextureID)(uintptr_t)eqIcon, ImVec2(18.0f, 18.0f));
|
||||
ImGui::SameLine();
|
||||
}
|
||||
ImGui::TextColored(getQualityColor(eq->item.quality), "%s", eq->item.name.c_str());
|
||||
|
||||
if (eq->item.damageMax > 0.0f) {
|
||||
ImGui::Text("%.0f - %.0f Damage", eq->item.damageMin, eq->item.damageMax);
|
||||
}
|
||||
if (eq->item.armor > 0) ImGui::Text("%d Armor", eq->item.armor);
|
||||
renderStat(eq->item.stamina, "Stamina");
|
||||
renderStat(eq->item.strength, "Strength");
|
||||
renderStat(eq->item.agility, "Agility");
|
||||
renderStat(eq->item.intellect, "Intellect");
|
||||
renderStat(eq->item.spirit, "Spirit");
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue