mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-03-22 23:30:14 +00:00
feat: resolve item icon paths from ItemDisplayInfo.dbc for Lua API
Add ItemIconPathResolver that lazily loads ItemDisplayInfo.dbc to map displayInfoId → icon texture path. This fixes three Lua API functions that previously returned nil for item icons: - GetItemInfo() field 10 (texture) now returns the icon path - GetActionTexture() for item-type action bar slots now returns icons - GetLootSlotInfo() field 1 (texture) now returns proper item icons instead of incorrectly using the spell icon resolver Follows the same lazy-loading pattern as SpellIconPathResolver. The DBC is loaded once on first query and cached for all subsequent lookups.
This commit is contained in:
parent
e21f808714
commit
7105672f06
3 changed files with 54 additions and 6 deletions
|
|
@ -294,6 +294,13 @@ public:
|
||||||
return spellIconPathResolver_ ? spellIconPathResolver_(spellId) : std::string{};
|
return spellIconPathResolver_ ? spellIconPathResolver_(spellId) : std::string{};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Item icon path resolver: displayInfoId -> texture path (e.g., "Interface\\Icons\\INV_Sword_04")
|
||||||
|
using ItemIconPathResolver = std::function<std::string(uint32_t)>;
|
||||||
|
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")
|
// Random property/suffix name resolver: randomPropertyId -> suffix name (e.g., "of the Eagle")
|
||||||
// Positive IDs → ItemRandomProperties.dbc; negative IDs → ItemRandomSuffix.dbc (abs value)
|
// Positive IDs → ItemRandomProperties.dbc; negative IDs → ItemRandomSuffix.dbc (abs value)
|
||||||
using RandomPropertyNameResolver = std::function<std::string(int32_t)>;
|
using RandomPropertyNameResolver = std::function<std::string(int32_t)>;
|
||||||
|
|
@ -2662,6 +2669,7 @@ private:
|
||||||
AddonChatCallback addonChatCallback_;
|
AddonChatCallback addonChatCallback_;
|
||||||
AddonEventCallback addonEventCallback_;
|
AddonEventCallback addonEventCallback_;
|
||||||
SpellIconPathResolver spellIconPathResolver_;
|
SpellIconPathResolver spellIconPathResolver_;
|
||||||
|
ItemIconPathResolver itemIconPathResolver_;
|
||||||
RandomPropertyNameResolver randomPropertyNameResolver_;
|
RandomPropertyNameResolver randomPropertyNameResolver_;
|
||||||
EmoteAnimCallback emoteAnimCallback_;
|
EmoteAnimCallback emoteAnimCallback_;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -766,7 +766,14 @@ static int lua_GetItemInfo(lua_State* L) {
|
||||||
lua_pushstring(L, ""); // 7: subclass
|
lua_pushstring(L, ""); // 7: subclass
|
||||||
lua_pushnumber(L, info->maxStack > 0 ? info->maxStack : 1); // 8: maxStack
|
lua_pushnumber(L, info->maxStack > 0 ? info->maxStack : 1); // 8: maxStack
|
||||||
lua_pushstring(L, ""); // 9: equipSlot
|
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
|
lua_pushnumber(L, info->sellPrice); // 11: vendorPrice
|
||||||
return 11;
|
return 11;
|
||||||
}
|
}
|
||||||
|
|
@ -1393,11 +1400,10 @@ static int lua_GetLootSlotInfo(lua_State* L) {
|
||||||
const auto& item = loot.items[slot - 1];
|
const auto& item = loot.items[slot - 1];
|
||||||
const auto* info = gh->getItemInfo(item.itemId);
|
const auto* info = gh->getItemInfo(item.itemId);
|
||||||
|
|
||||||
// texture (icon path — nil if not available)
|
// texture (icon path from ItemDisplayInfo.dbc)
|
||||||
std::string icon;
|
std::string icon;
|
||||||
if (info) {
|
if (info && info->displayInfoId != 0) {
|
||||||
// Try spell icon resolver as fallback for item icon
|
icon = gh->getItemIconPath(info->displayInfoId);
|
||||||
icon = gh->getSpellIconPath(item.itemId);
|
|
||||||
}
|
}
|
||||||
if (!icon.empty()) lua_pushstring(L, icon.c_str());
|
if (!icon.empty()) lua_pushstring(L, icon.c_str());
|
||||||
else lua_pushnil(L);
|
else lua_pushnil(L);
|
||||||
|
|
@ -1883,8 +1889,16 @@ static int lua_GetActionTexture(lua_State* L) {
|
||||||
lua_pushstring(L, icon.c_str());
|
lua_pushstring(L, icon.c_str());
|
||||||
return 1;
|
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);
|
lua_pushnil(L);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -413,6 +413,32 @@ bool Application::initialize() {
|
||||||
return pit->second;
|
return pit->second;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
// Wire item icon path resolver: displayInfoId -> "Interface\\Icons\\INV_..."
|
||||||
|
{
|
||||||
|
auto iconNames = std::make_shared<std::unordered_map<uint32_t, std::string>>();
|
||||||
|
auto loaded = std::make_shared<bool>(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
|
// Wire random property/suffix name resolver for item display
|
||||||
{
|
{
|
||||||
auto propNames = std::make_shared<std::unordered_map<int32_t, std::string>>();
|
auto propNames = std::make_shared<std::unordered_map<int32_t, std::string>>();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue