feat: track and display honor/arena points from update fields

Add PLAYER_FIELD_HONOR_CURRENCY and PLAYER_FIELD_ARENA_CURRENCY to the
update field system for WotLK (indices 1422/1423) and TBC (1505/1506).
Parse values from both CREATE_OBJECT and VALUES update paths, and show
them in the character Stats tab under a PvP Currency section.
This commit is contained in:
Kelsi 2026-03-20 04:36:30 -07:00
parent 0830215b31
commit f88d90ee88
6 changed files with 50 additions and 0 deletions

View file

@ -37,6 +37,8 @@
"PLAYER_FIELD_BANKBAG_SLOT_1": 784,
"PLAYER_SKILL_INFO_START": 928,
"PLAYER_EXPLORED_ZONES_START": 1312,
"PLAYER_FIELD_HONOR_CURRENCY": 1505,
"PLAYER_FIELD_ARENA_CURRENCY": 1506,
"GAMEOBJECT_DISPLAYID": 8,
"ITEM_FIELD_STACK_COUNT": 14,
"ITEM_FIELD_DURABILITY": 60,

View file

@ -49,6 +49,8 @@
"PLAYER_RANGED_CRIT_PERCENTAGE": 1030,
"PLAYER_SPELL_CRIT_PERCENTAGE1": 1032,
"PLAYER_FIELD_COMBAT_RATING_1": 1231,
"PLAYER_FIELD_HONOR_CURRENCY": 1422,
"PLAYER_FIELD_ARENA_CURRENCY": 1423,
"GAMEOBJECT_DISPLAYID": 8,
"ITEM_FIELD_STACK_COUNT": 14,
"ITEM_FIELD_DURABILITY": 60,

View file

@ -299,6 +299,10 @@ public:
// Money (copper)
uint64_t getMoneyCopper() const { return playerMoneyCopper_; }
// PvP currency (TBC/WotLK only)
uint32_t getHonorPoints() const { return playerHonorPoints_; }
uint32_t getArenaPoints() const { return playerArenaPoints_; }
// Server-authoritative armor (UNIT_FIELD_RESISTANCES[0])
int32_t getArmorRating() const { return playerArmorRating_; }
@ -3067,6 +3071,8 @@ private:
float pendingLootMoneyNotifyTimer_ = 0.0f;
std::unordered_map<uint64_t, float> recentLootMoneyAnnounceCooldowns_;
uint64_t playerMoneyCopper_ = 0;
uint32_t playerHonorPoints_ = 0;
uint32_t playerArenaPoints_ = 0;
int32_t playerArmorRating_ = 0;
int32_t playerResistances_[6] = {}; // [0]=Holy,[1]=Fire,[2]=Nature,[3]=Frost,[4]=Shadow,[5]=Arcane
// Server-authoritative primary stats: [0]=STR [1]=AGI [2]=STA [3]=INT [4]=SPI; -1 = not received yet

View file

@ -77,6 +77,10 @@ enum class UF : uint16_t {
PLAYER_SPELL_CRIT_PERCENTAGE1, // Spell crit chance % (first school; 7 consecutive float fields)
PLAYER_FIELD_COMBAT_RATING_1, // First of 25 int32 combat rating slots (CR_* indices)
// Player PvP currency (TBC/WotLK only — Classic uses the old weekly honor system)
PLAYER_FIELD_HONOR_CURRENCY, // Accumulated honor points (uint32)
PLAYER_FIELD_ARENA_CURRENCY, // Accumulated arena points (uint32)
// GameObject fields
GAMEOBJECT_DISPLAYID,

View file

@ -11781,6 +11781,8 @@ void GameHandler::applyUpdateObjectBlock(const UpdateBlock& block, bool& newItem
const uint16_t ufPlayerRestedXp = fieldIndex(UF::PLAYER_REST_STATE_EXPERIENCE);
const uint16_t ufPlayerLevel = fieldIndex(UF::UNIT_FIELD_LEVEL);
const uint16_t ufCoinage = fieldIndex(UF::PLAYER_FIELD_COINAGE);
const uint16_t ufHonor = fieldIndex(UF::PLAYER_FIELD_HONOR_CURRENCY);
const uint16_t ufArena = fieldIndex(UF::PLAYER_FIELD_ARENA_CURRENCY);
const uint16_t ufArmor = fieldIndex(UF::UNIT_FIELD_RESISTANCES);
const uint16_t ufPBytes2 = fieldIndex(UF::PLAYER_BYTES_2);
const uint16_t ufChosenTitle = fieldIndex(UF::PLAYER_CHOSEN_TITLE);
@ -11814,6 +11816,14 @@ void GameHandler::applyUpdateObjectBlock(const UpdateBlock& block, bool& newItem
playerMoneyCopper_ = val;
LOG_DEBUG("Money set from update fields: ", val, " copper");
}
else if (ufHonor != 0xFFFF && key == ufHonor) {
playerHonorPoints_ = val;
LOG_DEBUG("Honor points from update fields: ", val);
}
else if (ufArena != 0xFFFF && key == ufArena) {
playerArenaPoints_ = val;
LOG_DEBUG("Arena points from update fields: ", val);
}
else if (ufArmor != 0xFFFF && key == ufArmor) {
playerArmorRating_ = static_cast<int32_t>(val);
LOG_DEBUG("Armor rating from update fields: ", playerArmorRating_);
@ -12207,6 +12217,8 @@ void GameHandler::applyUpdateObjectBlock(const UpdateBlock& block, bool& newItem
const uint16_t ufPlayerRestedXpV = fieldIndex(UF::PLAYER_REST_STATE_EXPERIENCE);
const uint16_t ufPlayerLevel = fieldIndex(UF::UNIT_FIELD_LEVEL);
const uint16_t ufCoinage = fieldIndex(UF::PLAYER_FIELD_COINAGE);
const uint16_t ufHonorV = fieldIndex(UF::PLAYER_FIELD_HONOR_CURRENCY);
const uint16_t ufArenaV = fieldIndex(UF::PLAYER_FIELD_ARENA_CURRENCY);
const uint16_t ufPlayerFlags = fieldIndex(UF::PLAYER_FLAGS);
const uint16_t ufArmor = fieldIndex(UF::UNIT_FIELD_RESISTANCES);
const uint16_t ufPBytesV = fieldIndex(UF::PLAYER_BYTES);
@ -12254,6 +12266,14 @@ void GameHandler::applyUpdateObjectBlock(const UpdateBlock& block, bool& newItem
playerMoneyCopper_ = val;
LOG_DEBUG("Money updated via VALUES: ", val, " copper");
}
else if (ufHonorV != 0xFFFF && key == ufHonorV) {
playerHonorPoints_ = val;
LOG_DEBUG("Honor points updated: ", val);
}
else if (ufArenaV != 0xFFFF && key == ufArenaV) {
playerArenaPoints_ = val;
LOG_DEBUG("Arena points updated: ", val);
}
else if (ufArmor != 0xFFFF && key == ufArmor) {
playerArmorRating_ = static_cast<int32_t>(val);
}

View file

@ -1249,6 +1249,22 @@ void InventoryScreen::renderCharacterScreen(game::GameHandler& gameHandler) {
ImGui::Text("%s", fmtTime(levelSec).c_str()); ImGui::NextColumn();
ImGui::Columns(1);
}
// PvP Currency (TBC/WotLK only)
uint32_t honor = gameHandler.getHonorPoints();
uint32_t arena = gameHandler.getArenaPoints();
if (honor > 0 || arena > 0) {
ImGui::Separator();
ImGui::TextDisabled("PvP Currency");
ImGui::Columns(2, "##pvpcurrency", false);
ImGui::SetColumnWidth(0, 130);
ImGui::Text("Honor Points:"); ImGui::NextColumn();
ImGui::TextColored(ImVec4(0.9f, 0.75f, 0.2f, 1.0f), "%u", honor); ImGui::NextColumn();
ImGui::Text("Arena Points:"); ImGui::NextColumn();
ImGui::TextColored(ImVec4(0.9f, 0.75f, 0.2f, 1.0f), "%u", arena); ImGui::NextColumn();
ImGui::Columns(1);
}
ImGui::EndTabItem();
}