mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-03-23 07:40:14 +00:00
feat: track and display WotLK server-authoritative combat stats
Adds update field tracking for WotLK secondary combat statistics: - UNIT_FIELD_ATTACK_POWER / RANGED_ATTACK_POWER (fields 123, 126) - PLAYER_DODGE/PARRY/BLOCK/CRIT_PERCENTAGE (fields 1025-1029) - PLAYER_RANGED_CRIT_PERCENTAGE, PLAYER_SPELL_CRIT_PERCENTAGE1 (1030, 1032) - PLAYER_FIELD_COMBAT_RATING_1 (25 slots at 1231, hit/expertise/haste/etc.) Both CREATE_OBJECT and VALUES update paths now populate these fields. The Character screen Stats tab shows them when received from the server, with graceful fallback when not available (Classic/TBC expansions). Field indices verified against AzerothCore 3.3.5a UpdateFields.h.
This commit is contained in:
parent
ea7b276125
commit
c0ffca68f2
7 changed files with 166 additions and 3 deletions
|
|
@ -8195,6 +8195,15 @@ void GameHandler::selectCharacter(uint64_t characterGuid) {
|
|||
playerArmorRating_ = 0;
|
||||
std::fill(std::begin(playerResistances_), std::end(playerResistances_), 0);
|
||||
std::fill(std::begin(playerStats_), std::end(playerStats_), -1);
|
||||
playerMeleeAP_ = -1;
|
||||
playerRangedAP_ = -1;
|
||||
playerDodgePct_ = -1.0f;
|
||||
playerParryPct_ = -1.0f;
|
||||
playerBlockPct_ = -1.0f;
|
||||
playerCritPct_ = -1.0f;
|
||||
playerRangedCritPct_ = -1.0f;
|
||||
std::fill(std::begin(playerSpellCritPct_), std::end(playerSpellCritPct_), -1.0f);
|
||||
std::fill(std::begin(playerCombatRatings_), std::end(playerCombatRatings_), -1);
|
||||
knownSpells.clear();
|
||||
spellCooldowns.clear();
|
||||
spellFlatMods_.clear();
|
||||
|
|
@ -10374,6 +10383,15 @@ void GameHandler::handleUpdateObject(network::Packet& packet) {
|
|||
fieldIndex(UF::UNIT_FIELD_STAT2), fieldIndex(UF::UNIT_FIELD_STAT3),
|
||||
fieldIndex(UF::UNIT_FIELD_STAT4)
|
||||
};
|
||||
const uint16_t ufMeleeAP = fieldIndex(UF::UNIT_FIELD_ATTACK_POWER);
|
||||
const uint16_t ufRangedAP = fieldIndex(UF::UNIT_FIELD_RANGED_ATTACK_POWER);
|
||||
const uint16_t ufBlockPct = fieldIndex(UF::PLAYER_BLOCK_PERCENTAGE);
|
||||
const uint16_t ufDodgePct = fieldIndex(UF::PLAYER_DODGE_PERCENTAGE);
|
||||
const uint16_t ufParryPct = fieldIndex(UF::PLAYER_PARRY_PERCENTAGE);
|
||||
const uint16_t ufCritPct = fieldIndex(UF::PLAYER_CRIT_PERCENTAGE);
|
||||
const uint16_t ufRCritPct = fieldIndex(UF::PLAYER_RANGED_CRIT_PERCENTAGE);
|
||||
const uint16_t ufSCrit1 = fieldIndex(UF::PLAYER_SPELL_CRIT_PERCENTAGE1);
|
||||
const uint16_t ufRating1 = fieldIndex(UF::PLAYER_FIELD_COMBAT_RATING_1);
|
||||
for (const auto& [key, val] : block.fields) {
|
||||
if (key == ufPlayerXp) { playerXp_ = val; }
|
||||
else if (key == ufPlayerNextXp) { playerNextLevelXp_ = val; }
|
||||
|
|
@ -10409,6 +10427,19 @@ void GameHandler::handleUpdateObject(network::Packet& packet) {
|
|||
chosenTitleBit_ = static_cast<int32_t>(val);
|
||||
LOG_DEBUG("PLAYER_CHOSEN_TITLE from update fields: ", chosenTitleBit_);
|
||||
}
|
||||
else if (ufMeleeAP != 0xFFFF && key == ufMeleeAP) { playerMeleeAP_ = static_cast<int32_t>(val); }
|
||||
else if (ufRangedAP != 0xFFFF && key == ufRangedAP) { playerRangedAP_ = static_cast<int32_t>(val); }
|
||||
else if (ufBlockPct != 0xFFFF && key == ufBlockPct) { std::memcpy(&playerBlockPct_, &val, 4); }
|
||||
else if (ufDodgePct != 0xFFFF && key == ufDodgePct) { std::memcpy(&playerDodgePct_, &val, 4); }
|
||||
else if (ufParryPct != 0xFFFF && key == ufParryPct) { std::memcpy(&playerParryPct_, &val, 4); }
|
||||
else if (ufCritPct != 0xFFFF && key == ufCritPct) { std::memcpy(&playerCritPct_, &val, 4); }
|
||||
else if (ufRCritPct != 0xFFFF && key == ufRCritPct) { std::memcpy(&playerRangedCritPct_, &val, 4); }
|
||||
else if (ufSCrit1 != 0xFFFF && key >= ufSCrit1 && key < ufSCrit1 + 7) {
|
||||
std::memcpy(&playerSpellCritPct_[key - ufSCrit1], &val, 4);
|
||||
}
|
||||
else if (ufRating1 != 0xFFFF && key >= ufRating1 && key < ufRating1 + 25) {
|
||||
playerCombatRatings_[key - ufRating1] = static_cast<int32_t>(val);
|
||||
}
|
||||
else {
|
||||
for (int si = 0; si < 5; ++si) {
|
||||
if (ufStats[si] != 0xFFFF && key == ufStats[si]) {
|
||||
|
|
@ -10766,6 +10797,15 @@ void GameHandler::handleUpdateObject(network::Packet& packet) {
|
|||
fieldIndex(UF::UNIT_FIELD_STAT2), fieldIndex(UF::UNIT_FIELD_STAT3),
|
||||
fieldIndex(UF::UNIT_FIELD_STAT4)
|
||||
};
|
||||
const uint16_t ufMeleeAPV = fieldIndex(UF::UNIT_FIELD_ATTACK_POWER);
|
||||
const uint16_t ufRangedAPV = fieldIndex(UF::UNIT_FIELD_RANGED_ATTACK_POWER);
|
||||
const uint16_t ufBlockPctV = fieldIndex(UF::PLAYER_BLOCK_PERCENTAGE);
|
||||
const uint16_t ufDodgePctV = fieldIndex(UF::PLAYER_DODGE_PERCENTAGE);
|
||||
const uint16_t ufParryPctV = fieldIndex(UF::PLAYER_PARRY_PERCENTAGE);
|
||||
const uint16_t ufCritPctV = fieldIndex(UF::PLAYER_CRIT_PERCENTAGE);
|
||||
const uint16_t ufRCritPctV = fieldIndex(UF::PLAYER_RANGED_CRIT_PERCENTAGE);
|
||||
const uint16_t ufSCrit1V = fieldIndex(UF::PLAYER_SPELL_CRIT_PERCENTAGE1);
|
||||
const uint16_t ufRating1V = fieldIndex(UF::PLAYER_FIELD_COMBAT_RATING_1);
|
||||
for (const auto& [key, val] : block.fields) {
|
||||
if (key == ufPlayerXp) {
|
||||
playerXp_ = val;
|
||||
|
|
@ -10830,6 +10870,19 @@ void GameHandler::handleUpdateObject(network::Packet& packet) {
|
|||
if (ghostStateCallback_) ghostStateCallback_(false);
|
||||
}
|
||||
}
|
||||
else if (ufMeleeAPV != 0xFFFF && key == ufMeleeAPV) { playerMeleeAP_ = static_cast<int32_t>(val); }
|
||||
else if (ufRangedAPV != 0xFFFF && key == ufRangedAPV) { playerRangedAP_ = static_cast<int32_t>(val); }
|
||||
else if (ufBlockPctV != 0xFFFF && key == ufBlockPctV) { std::memcpy(&playerBlockPct_, &val, 4); }
|
||||
else if (ufDodgePctV != 0xFFFF && key == ufDodgePctV) { std::memcpy(&playerDodgePct_, &val, 4); }
|
||||
else if (ufParryPctV != 0xFFFF && key == ufParryPctV) { std::memcpy(&playerParryPct_, &val, 4); }
|
||||
else if (ufCritPctV != 0xFFFF && key == ufCritPctV) { std::memcpy(&playerCritPct_, &val, 4); }
|
||||
else if (ufRCritPctV != 0xFFFF && key == ufRCritPctV) { std::memcpy(&playerRangedCritPct_, &val, 4); }
|
||||
else if (ufSCrit1V != 0xFFFF && key >= ufSCrit1V && key < ufSCrit1V + 7) {
|
||||
std::memcpy(&playerSpellCritPct_[key - ufSCrit1V], &val, 4);
|
||||
}
|
||||
else if (ufRating1V != 0xFFFF && key >= ufRating1V && key < ufRating1V + 25) {
|
||||
playerCombatRatings_[key - ufRating1V] = static_cast<int32_t>(val);
|
||||
}
|
||||
else {
|
||||
for (int si = 0; si < 5; ++si) {
|
||||
if (ufStatsV[si] != 0xFFFF && key == ufStatsV[si]) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue