Fix item tooltip armor: auto-detect BuyCount in WotLK item query parser

The WotLK item query parser assumed BuyCount is always present as a
separate field (Flags + Flags2 + BuyCount + BuyPrice + SellPrice = 5
fields). Some server variants omit BuyCount, shifting every subsequent
field by 4 bytes and causing armor to be read from the wrong offset.

Now read 5 fields and validate InventoryType (must be 0-28). If it
falls outside that range, rewind and re-parse with 4 fields (no
BuyCount), which recovers correct alignment. Elevated item query log
from DEBUG to INFO so the parsed armor value is visible in output.
This commit is contained in:
Kelsi 2026-02-19 17:54:32 -08:00
parent 208fe0e7e3
commit e92bea747a

View file

@ -2084,14 +2084,27 @@ bool ItemQueryResponseParser::parse(network::Packet& packet, ItemQueryResponseDa
data.displayInfoId = packet.readUInt32();
data.quality = packet.readUInt32();
// WotLK 3.3.5a (TrinityCore/AzerothCore): Flags, Flags2, BuyCount, BuyPrice, SellPrice
// Some server variants omit BuyCount (4 fields instead of 5).
// Read 5 fields and validate InventoryType; if it looks implausible, rewind and try 4.
const size_t postQualityPos = packet.getReadPos();
packet.readUInt32(); // Flags
packet.readUInt32(); // Flags2
packet.readUInt32(); // BuyCount (WotLK: separate from BuyPrice)
packet.readUInt32(); // BuyCount
packet.readUInt32(); // BuyPrice
data.sellPrice = packet.readUInt32(); // SellPrice
data.inventoryType = packet.readUInt32();
if (data.inventoryType > 28) {
// inventoryType out of range — BuyCount probably not present; rewind and try 4 fields
packet.setReadPos(postQualityPos);
packet.readUInt32(); // Flags
packet.readUInt32(); // Flags2
packet.readUInt32(); // BuyPrice
data.sellPrice = packet.readUInt32(); // SellPrice
data.inventoryType = packet.readUInt32();
}
packet.readUInt32(); // AllowableClass
packet.readUInt32(); // AllowableRace
packet.readUInt32(); // ItemLevel
@ -2193,10 +2206,10 @@ bool ItemQueryResponseParser::parse(network::Packet& packet, ItemQueryResponseDa
data.delayMs = chosen->delayMs;
data.valid = !data.name.empty();
LOG_DEBUG("Item query response: ", data.name, " (quality=", data.quality,
" invType=", data.inventoryType, " stack=", data.maxStack,
" class=", data.itemClass, " armor=", data.armor,
" dmgEntries=", chosenDamageEntries, ")");
LOG_INFO("Item query: '", data.name, "' class=", data.itemClass,
" invType=", data.inventoryType, " quality=", data.quality,
" armor=", data.armor, " dmgEntries=", chosenDamageEntries,
" statsCount=", statsCount, " sellPrice=", data.sellPrice);
return true;
}