Fix armor stat in character stats panel via UNIT_FIELD_RESISTANCES

The character stats panel was showing Armor: 0 because summing armor
from item query responses is fragile (depends on correct BuyCount/damage
block parsing). Instead, read the server-authoritative total armor
directly from UNIT_FIELD_RESISTANCES (physical resistance, index 0)
in the player entity update fields.

Added UNIT_FIELD_RESISTANCES to the UF enum and all four expansion
JSON files with correct wire indices:
  WotLK 3.3.5a: 99   (NPC_FLAGS=82 + emotestate + stat×5 + posstat×5 + negstat×5)
  TBC 2.4.3:   185   (NPC_FLAGS=168 + same relative layout)
  Classic 1.12: 154  (NPC_FLAGS=147 + emotestate + stat×5, no posstat/negstat)
  Turtle WoW:  154   (same as Classic)

Stats panel uses server armor when > 0, falls back to summed item-query
armor otherwise. Armor rating resets to 0 on world entry and is updated
from both CREATE_OBJECT and VALUES update blocks.
This commit is contained in:
Kelsi 2026-02-19 17:45:09 -08:00
parent 05e2b37894
commit 20cdff0790
10 changed files with 33 additions and 5 deletions

View file

@ -273,6 +273,9 @@ public:
// Money (copper)
uint64_t getMoneyCopper() const { return playerMoneyCopper_; }
// Server-authoritative armor (UNIT_FIELD_RESISTANCES[0])
int32_t getArmorRating() const { return playerArmorRating_; }
// Inventory
Inventory& getInventory() { return inventory; }
const Inventory& getInventory() const { return inventory; }
@ -1435,6 +1438,7 @@ private:
float pendingLootMoneyNotifyTimer_ = 0.0f;
std::unordered_map<uint64_t, float> recentLootMoneyAnnounceCooldowns_;
uint64_t playerMoneyCopper_ = 0;
int32_t playerArmorRating_ = 0;
// Some servers/custom clients shift update field indices. We can auto-detect coinage by correlating
// money-notify deltas with update-field diffs and then overriding UF::PLAYER_FIELD_COINAGE at runtime.
uint32_t pendingMoneyDelta_ = 0;

View file

@ -32,6 +32,7 @@ enum class UF : uint16_t {
UNIT_FIELD_AURAS, // Start of aura spell ID array (48 consecutive uint32 slots, classic/vanilla only)
UNIT_NPC_FLAGS,
UNIT_DYNAMIC_FLAGS,
UNIT_FIELD_RESISTANCES, // Physical armor (index 0 of the resistance array)
UNIT_END,
// Player fields

View file

@ -131,7 +131,7 @@ private:
int bagIndex, float defaultX, float defaultY, uint64_t moneyCopper);
void renderEquipmentPanel(game::Inventory& inventory);
void renderBackpackPanel(game::Inventory& inventory, bool collapseEmptySections = false);
void renderStatsPanel(game::Inventory& inventory, uint32_t playerLevel);
void renderStatsPanel(game::Inventory& inventory, uint32_t playerLevel, int32_t serverArmor = 0);
// Slot rendering with interaction support
enum class SlotKind { BACKPACK, EQUIPMENT };