diff --git a/include/game/game_handler.hpp b/include/game/game_handler.hpp index 97dd3103..5208bc53 100644 --- a/include/game/game_handler.hpp +++ b/include/game/game_handler.hpp @@ -294,6 +294,13 @@ public: return spellIconPathResolver_ ? spellIconPathResolver_(spellId) : std::string{}; } + // Item icon path resolver: displayInfoId -> texture path (e.g., "Interface\\Icons\\INV_Sword_04") + using ItemIconPathResolver = std::function; + void setItemIconPathResolver(ItemIconPathResolver r) { itemIconPathResolver_ = std::move(r); } + std::string getItemIconPath(uint32_t displayInfoId) const { + return itemIconPathResolver_ ? itemIconPathResolver_(displayInfoId) : std::string{}; + } + // Random property/suffix name resolver: randomPropertyId -> suffix name (e.g., "of the Eagle") // Positive IDs → ItemRandomProperties.dbc; negative IDs → ItemRandomSuffix.dbc (abs value) using RandomPropertyNameResolver = std::function; @@ -2662,6 +2669,7 @@ private: AddonChatCallback addonChatCallback_; AddonEventCallback addonEventCallback_; SpellIconPathResolver spellIconPathResolver_; + ItemIconPathResolver itemIconPathResolver_; RandomPropertyNameResolver randomPropertyNameResolver_; EmoteAnimCallback emoteAnimCallback_; diff --git a/src/addons/lua_engine.cpp b/src/addons/lua_engine.cpp index 4c87f094..3dad867b 100644 --- a/src/addons/lua_engine.cpp +++ b/src/addons/lua_engine.cpp @@ -766,7 +766,14 @@ static int lua_GetItemInfo(lua_State* L) { lua_pushstring(L, ""); // 7: subclass lua_pushnumber(L, info->maxStack > 0 ? info->maxStack : 1); // 8: maxStack lua_pushstring(L, ""); // 9: equipSlot - lua_pushnil(L); // 10: texture (icon path — no ItemDisplayInfo icon resolver yet) + // 10: texture (icon path from ItemDisplayInfo.dbc) + if (info->displayInfoId != 0) { + std::string iconPath = gh->getItemIconPath(info->displayInfoId); + if (!iconPath.empty()) lua_pushstring(L, iconPath.c_str()); + else lua_pushnil(L); + } else { + lua_pushnil(L); + } lua_pushnumber(L, info->sellPrice); // 11: vendorPrice return 11; } @@ -1393,11 +1400,10 @@ static int lua_GetLootSlotInfo(lua_State* L) { const auto& item = loot.items[slot - 1]; const auto* info = gh->getItemInfo(item.itemId); - // texture (icon path — nil if not available) + // texture (icon path from ItemDisplayInfo.dbc) std::string icon; - if (info) { - // Try spell icon resolver as fallback for item icon - icon = gh->getSpellIconPath(item.itemId); + if (info && info->displayInfoId != 0) { + icon = gh->getItemIconPath(info->displayInfoId); } if (!icon.empty()) lua_pushstring(L, icon.c_str()); else lua_pushnil(L); @@ -1883,8 +1889,16 @@ static int lua_GetActionTexture(lua_State* L) { lua_pushstring(L, icon.c_str()); return 1; } + } else if (action.type == game::ActionBarSlot::ITEM && action.id != 0) { + const auto* info = gh->getItemInfo(action.id); + if (info && info->displayInfoId != 0) { + std::string icon = gh->getItemIconPath(info->displayInfoId); + if (!icon.empty()) { + lua_pushstring(L, icon.c_str()); + return 1; + } + } } - // For items we don't have icon resolution yet (needs ItemDisplayInfo DBC) lua_pushnil(L); return 1; } diff --git a/src/core/application.cpp b/src/core/application.cpp index 91d6d619..c007c09c 100644 --- a/src/core/application.cpp +++ b/src/core/application.cpp @@ -413,6 +413,32 @@ bool Application::initialize() { return pit->second; }); } + // Wire item icon path resolver: displayInfoId -> "Interface\\Icons\\INV_..." + { + auto iconNames = std::make_shared>(); + auto loaded = std::make_shared(false); + auto* am = assetManager.get(); + gameHandler->setItemIconPathResolver([iconNames, loaded, am](uint32_t displayInfoId) -> std::string { + if (!am || displayInfoId == 0) return {}; + if (!*loaded) { + *loaded = true; + auto dbc = am->loadDBC("ItemDisplayInfo.dbc"); + const auto* dispL = pipeline::getActiveDBCLayout() ? pipeline::getActiveDBCLayout()->getLayout("ItemDisplayInfo") : nullptr; + if (dbc && dbc->isLoaded()) { + uint32_t iconField = dispL ? (*dispL)["InventoryIcon"] : 5; + for (uint32_t i = 0; i < dbc->getRecordCount(); i++) { + uint32_t id = dbc->getUInt32(i, 0); // field 0 = ID + std::string name = dbc->getString(i, iconField); + if (id > 0 && !name.empty()) (*iconNames)[id] = name; + } + LOG_INFO("Loaded ", iconNames->size(), " item icon names from ItemDisplayInfo.dbc"); + } + } + auto it = iconNames->find(displayInfoId); + if (it == iconNames->end()) return {}; + return "Interface\\Icons\\" + it->second; + }); + } // Wire random property/suffix name resolver for item display { auto propNames = std::make_shared>();