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

@ -1066,7 +1066,7 @@ void InventoryScreen::renderCharacterScreen(game::GameHandler& gameHandler) {
if (ImGui::BeginTabItem("Stats")) {
ImGui::Spacing();
renderStatsPanel(inventory, gameHandler.getPlayerLevel());
renderStatsPanel(inventory, gameHandler.getPlayerLevel(), gameHandler.getArmorRating());
ImGui::EndTabItem();
}
@ -1269,15 +1269,13 @@ void InventoryScreen::renderEquipmentPanel(game::Inventory& inventory) {
// Stats Panel
// ============================================================
void InventoryScreen::renderStatsPanel(game::Inventory& inventory, uint32_t playerLevel) {
void InventoryScreen::renderStatsPanel(game::Inventory& inventory, uint32_t playerLevel, int32_t serverArmor) {
// Sum equipment stats
int32_t totalArmor = 0;
int32_t totalStr = 0, totalAgi = 0, totalSta = 0, totalInt = 0, totalSpi = 0;
for (int s = 0; s < game::Inventory::NUM_EQUIP_SLOTS; s++) {
const auto& slot = inventory.getEquipSlot(static_cast<game::EquipSlot>(s));
if (slot.empty()) continue;
totalArmor += slot.item.armor;
totalStr += slot.item.strength;
totalAgi += slot.item.agility;
totalSta += slot.item.stamina;
@ -1285,6 +1283,15 @@ void InventoryScreen::renderStatsPanel(game::Inventory& inventory, uint32_t play
totalSpi += slot.item.spirit;
}
// Use server-authoritative armor from UNIT_FIELD_RESISTANCES when available.
// Falls back to summing item query armors if server armor wasn't received yet.
int32_t itemQueryArmor = 0;
for (int s = 0; s < game::Inventory::NUM_EQUIP_SLOTS; s++) {
const auto& slot = inventory.getEquipSlot(static_cast<game::EquipSlot>(s));
if (!slot.empty()) itemQueryArmor += slot.item.armor;
}
int32_t totalArmor = (serverArmor > 0) ? serverArmor : itemQueryArmor;
// Base stats: 20 + level
int32_t baseStat = 20 + static_cast<int32_t>(playerLevel);