mirror of
https://github.com/brues-code/ClassicAPI.git
synced 2026-11-10 20:07:37 +00:00
item: decorate C_Item.GetItemName location form with random suffix
The location form of C_Item.GetItemName points at a real item instance,
so its name should carry random-suffix decoration ("... of the Owl") the
way modern WoW does -- but we were reading m_name[0] off the itemID-keyed
ItemStats_C cache, which only holds the base name.
Resolve the location to its CGItem and build the name via the engine's
own per-instance name builder (FUN_005D8BC0): it reads the suffix ID off
the descriptor (+0x98) and formats base + ItemRandomProperties localized
suffix through the engine's ITEM_SUFFIX_TEMPLATE. This is the same
builder FUN_GAMETOOLTIP_BUILD_ITEM_LINK wraps in brackets, so the output
now matches GetItemLink's bracketed name and modern C_Item.GetItemName
exactly (verified in-game: "Iridium Chain of the Owl"). Falls back to the
base ItemStats name (and warms the cache) when the instance build yields
nothing.
GetItemNameByID is unchanged -- an itemID has no instance, so base name
only is correct.
This commit is contained in:
@@ -287,6 +287,18 @@ enum Offsets {
|
||||
// the item isn't in the player's bag/equipment.
|
||||
FUN_GAMETOOLTIP_BUILD_ITEM_LINK = 0x0052AE00,
|
||||
|
||||
// CGItem → decorated instance display name. __thiscall(ecx = CGItem *,
|
||||
// char *outBuf, uint outSize). Reads the instance's random-suffix ID
|
||||
// off the descriptor (+0x98, gated on the broken flag) and writes the
|
||||
// plain — uncolored, unbracketed — display name into outBuf:
|
||||
// "Ethereum Torque of the Sorcerer" when a suffix is present, the base
|
||||
// ItemStats name otherwise (via the item cache + ItemRandomProperties
|
||||
// localized suffix at record +0x1c). This is the inner name builder
|
||||
// FUN_GAMETOOLTIP_BUILD_ITEM_LINK wraps in brackets, so the name it
|
||||
// produces matches GetItemLink's bracketed name and modern
|
||||
// C_Item.GetItemName exactly. Inner formatter FUN_005D8B00.
|
||||
FUN_ITEM_BUILD_INSTANCE_NAME = 0x005D8BC0,
|
||||
|
||||
// Engine's inventory swap-and-send. Same primitive
|
||||
// `Script_EquipCursorItem` (0x00489660) uses after the cursor's
|
||||
// source location has been resolved. Sends opcode 0x10D
|
||||
|
||||
+38
-5
@@ -56,18 +56,51 @@ int PushNameForItemID(void *L, int itemID) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Engine's per-instance item-name builder: `__thiscall(CGItem *this,
|
||||
// char *outBuf, uint outSize)`. Reads the instance's random-suffix ID off
|
||||
// the descriptor (+0x98) and writes the decorated display name
|
||||
// ("Ethereum Torque of the Sorcerer"), or the base name when there's no
|
||||
// suffix. Same builder the item-link builder uses for the bracketed name,
|
||||
// so this matches `GetItemLink`'s name and modern `C_Item.GetItemName`.
|
||||
using BuildInstanceName_t = void(__thiscall *)(const void *cgItem, char *out,
|
||||
unsigned outSize);
|
||||
|
||||
// Pushes the suffix-decorated display name for a resolved `CGItem`.
|
||||
// Returns 0 (pushes nothing) for a null item or an empty build result,
|
||||
// so the caller can fall back to the base-name-by-itemID path.
|
||||
int PushInstanceName(void *L, const uint8_t *cgItem) {
|
||||
if (cgItem == nullptr)
|
||||
return 0;
|
||||
char buf[128];
|
||||
buf[0] = '\0';
|
||||
auto fn = reinterpret_cast<BuildInstanceName_t>(
|
||||
Offsets::FUN_ITEM_BUILD_INSTANCE_NAME);
|
||||
fn(cgItem, buf, sizeof(buf));
|
||||
if (buf[0] == '\0')
|
||||
return 0;
|
||||
Game::Lua::PushString(L, buf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// `C_Item.GetItemName(itemLocation)` — returns the cached display name
|
||||
// of the item at the location, or nil for empty / uncached / invalid
|
||||
// inputs. Reads `m_name[0]` straight off `ItemStats_C` — no engine
|
||||
// round-trip, no `GetItemInfo` chaining.
|
||||
// `C_Item.GetItemName(itemLocation)` — returns the display name of the
|
||||
// item at the location, or nil for empty / uncached / invalid inputs.
|
||||
// The location points at a real item instance, so the name carries any
|
||||
// random-suffix decoration ("... of the Sorcerer") — built off the
|
||||
// CGItem via the engine's own name builder, matching modern WoW and
|
||||
// `C_Item.GetItemLink`'s bracketed name. Falls back to the base
|
||||
// `ItemStats_C` name (and warms the cache) if the instance build yields
|
||||
// nothing.
|
||||
static int __fastcall Script_C_Item_GetItemName(void *L) {
|
||||
if (!Item::Location::IsLocationArg(L, 1)) {
|
||||
Game::Lua::Error(L, "Usage: C_Item.GetItemName(itemLocation)");
|
||||
return 0;
|
||||
}
|
||||
return PushNameForItemID(L, Item::ID::FromCGItem(Item::Location::Resolve(L, 1)));
|
||||
const uint8_t *cgItem = Item::Location::Resolve(L, 1);
|
||||
if (int pushed = PushInstanceName(L, cgItem))
|
||||
return pushed;
|
||||
return PushNameForItemID(L, Item::ID::FromCGItem(cgItem));
|
||||
}
|
||||
|
||||
// `C_Item.GetItemNameByID(itemInfo)` — returns the cached display name
|
||||
|
||||
Reference in New Issue
Block a user