mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-03-22 23:30:14 +00:00
feat: add spell power and healing bonus to WotLK character stats
Tracks PLAYER_FIELD_MOD_DAMAGE_DONE_POS (7 schools at field 1171) and PLAYER_FIELD_MOD_HEALING_DONE_POS (field 1192) from server update fields. getSpellPower() returns the max damage bonus across magic schools 1-6. getHealingPower() returns the raw healing bonus. Both values displayed in the character screen Combat section alongside the previously added attack power, dodge, parry, crit, and rating fields.
This commit is contained in:
parent
c0ffca68f2
commit
2b79f9d121
6 changed files with 45 additions and 4 deletions
|
|
@ -40,6 +40,8 @@
|
|||
"PLAYER_SKILL_INFO_START": 636,
|
||||
"PLAYER_EXPLORED_ZONES_START": 1041,
|
||||
"PLAYER_CHOSEN_TITLE": 1349,
|
||||
"PLAYER_FIELD_MOD_DAMAGE_DONE_POS": 1171,
|
||||
"PLAYER_FIELD_MOD_HEALING_DONE_POS": 1192,
|
||||
"PLAYER_BLOCK_PERCENTAGE": 1024,
|
||||
"PLAYER_DODGE_PERCENTAGE": 1025,
|
||||
"PLAYER_PARRY_PERCENTAGE": 1026,
|
||||
|
|
|
|||
|
|
@ -314,6 +314,18 @@ public:
|
|||
int32_t getMeleeAttackPower() const { return playerMeleeAP_; }
|
||||
int32_t getRangedAttackPower() const { return playerRangedAP_; }
|
||||
|
||||
// Server-authoritative spell damage / healing bonus (WotLK: PLAYER_FIELD_MOD_*).
|
||||
// getSpellPower returns the max damage bonus across magic schools 1-6 (Holy/Fire/Nature/Frost/Shadow/Arcane).
|
||||
// Returns -1 if not yet received.
|
||||
int32_t getSpellPower() const {
|
||||
int32_t sp = -1;
|
||||
for (int i = 1; i <= 6; ++i) {
|
||||
if (playerSpellDmgBonus_[i] > sp) sp = playerSpellDmgBonus_[i];
|
||||
}
|
||||
return sp;
|
||||
}
|
||||
int32_t getHealingPower() const { return playerHealBonus_; }
|
||||
|
||||
// Server-authoritative combat chance percentages (WotLK: PLAYER_* float fields).
|
||||
// Returns -1.0f if not yet received.
|
||||
float getDodgePct() const { return playerDodgePct_; }
|
||||
|
|
@ -2820,6 +2832,8 @@ private:
|
|||
// WotLK secondary combat stats (-1 = not yet received)
|
||||
int32_t playerMeleeAP_ = -1;
|
||||
int32_t playerRangedAP_ = -1;
|
||||
int32_t playerSpellDmgBonus_[7] = {-1,-1,-1,-1,-1,-1,-1}; // per school 0-6
|
||||
int32_t playerHealBonus_ = -1;
|
||||
float playerDodgePct_ = -1.0f;
|
||||
float playerParryPct_ = -1.0f;
|
||||
float playerBlockPct_ = -1.0f;
|
||||
|
|
|
|||
|
|
@ -63,6 +63,10 @@ enum class UF : uint16_t {
|
|||
PLAYER_EXPLORED_ZONES_START,
|
||||
PLAYER_CHOSEN_TITLE, // Active title index (-1 = no title)
|
||||
|
||||
// Player spell power / healing bonus (WotLK: PRIVATE — int32 per school)
|
||||
PLAYER_FIELD_MOD_DAMAGE_DONE_POS, // Spell damage bonus (first of 7 schools)
|
||||
PLAYER_FIELD_MOD_HEALING_DONE_POS, // Healing bonus
|
||||
|
||||
// Player combat stats (WotLK: PRIVATE — float values)
|
||||
PLAYER_BLOCK_PERCENTAGE, // Block chance %
|
||||
PLAYER_DODGE_PERCENTAGE, // Dodge chance %
|
||||
|
|
|
|||
|
|
@ -8197,6 +8197,8 @@ void GameHandler::selectCharacter(uint64_t characterGuid) {
|
|||
std::fill(std::begin(playerStats_), std::end(playerStats_), -1);
|
||||
playerMeleeAP_ = -1;
|
||||
playerRangedAP_ = -1;
|
||||
std::fill(std::begin(playerSpellDmgBonus_), std::end(playerSpellDmgBonus_), -1);
|
||||
playerHealBonus_ = -1;
|
||||
playerDodgePct_ = -1.0f;
|
||||
playerParryPct_ = -1.0f;
|
||||
playerBlockPct_ = -1.0f;
|
||||
|
|
@ -10385,6 +10387,8 @@ void GameHandler::handleUpdateObject(network::Packet& packet) {
|
|||
};
|
||||
const uint16_t ufMeleeAP = fieldIndex(UF::UNIT_FIELD_ATTACK_POWER);
|
||||
const uint16_t ufRangedAP = fieldIndex(UF::UNIT_FIELD_RANGED_ATTACK_POWER);
|
||||
const uint16_t ufSpDmg1 = fieldIndex(UF::PLAYER_FIELD_MOD_DAMAGE_DONE_POS);
|
||||
const uint16_t ufHealBonus = fieldIndex(UF::PLAYER_FIELD_MOD_HEALING_DONE_POS);
|
||||
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);
|
||||
|
|
@ -10429,6 +10433,10 @@ void GameHandler::handleUpdateObject(network::Packet& packet) {
|
|||
}
|
||||
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 (ufSpDmg1 != 0xFFFF && key >= ufSpDmg1 && key < ufSpDmg1 + 7) {
|
||||
playerSpellDmgBonus_[key - ufSpDmg1] = static_cast<int32_t>(val);
|
||||
}
|
||||
else if (ufHealBonus != 0xFFFF && key == ufHealBonus) { playerHealBonus_ = 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); }
|
||||
|
|
@ -10799,6 +10807,8 @@ void GameHandler::handleUpdateObject(network::Packet& packet) {
|
|||
};
|
||||
const uint16_t ufMeleeAPV = fieldIndex(UF::UNIT_FIELD_ATTACK_POWER);
|
||||
const uint16_t ufRangedAPV = fieldIndex(UF::UNIT_FIELD_RANGED_ATTACK_POWER);
|
||||
const uint16_t ufSpDmg1V = fieldIndex(UF::PLAYER_FIELD_MOD_DAMAGE_DONE_POS);
|
||||
const uint16_t ufHealBonusV= fieldIndex(UF::PLAYER_FIELD_MOD_HEALING_DONE_POS);
|
||||
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);
|
||||
|
|
@ -10872,6 +10882,10 @@ void GameHandler::handleUpdateObject(network::Packet& packet) {
|
|||
}
|
||||
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 (ufSpDmg1V != 0xFFFF && key >= ufSpDmg1V && key < ufSpDmg1V + 7) {
|
||||
playerSpellDmgBonus_[key - ufSpDmg1V] = static_cast<int32_t>(val);
|
||||
}
|
||||
else if (ufHealBonusV != 0xFFFF && key == ufHealBonusV) { playerHealBonus_ = 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); }
|
||||
|
|
|
|||
|
|
@ -64,6 +64,8 @@ static const UFNameEntry kUFNames[] = {
|
|||
{"ITEM_FIELD_MAXDURABILITY", UF::ITEM_FIELD_MAXDURABILITY},
|
||||
{"PLAYER_REST_STATE_EXPERIENCE", UF::PLAYER_REST_STATE_EXPERIENCE},
|
||||
{"PLAYER_CHOSEN_TITLE", UF::PLAYER_CHOSEN_TITLE},
|
||||
{"PLAYER_FIELD_MOD_DAMAGE_DONE_POS", UF::PLAYER_FIELD_MOD_DAMAGE_DONE_POS},
|
||||
{"PLAYER_FIELD_MOD_HEALING_DONE_POS", UF::PLAYER_FIELD_MOD_HEALING_DONE_POS},
|
||||
{"PLAYER_BLOCK_PERCENTAGE", UF::PLAYER_BLOCK_PERCENTAGE},
|
||||
{"PLAYER_DODGE_PERCENTAGE", UF::PLAYER_DODGE_PERCENTAGE},
|
||||
{"PLAYER_PARRY_PERCENTAGE", UF::PLAYER_PARRY_PERCENTAGE},
|
||||
|
|
|
|||
|
|
@ -1782,6 +1782,8 @@ void InventoryScreen::renderStatsPanel(game::Inventory& inventory, uint32_t play
|
|||
if (gh) {
|
||||
int32_t meleeAP = gh->getMeleeAttackPower();
|
||||
int32_t rangedAP = gh->getRangedAttackPower();
|
||||
int32_t spellPow = gh->getSpellPower();
|
||||
int32_t healPow = gh->getHealingPower();
|
||||
float dodgePct = gh->getDodgePct();
|
||||
float parryPct = gh->getParryPct();
|
||||
float blockPct = gh->getBlockPct();
|
||||
|
|
@ -1795,7 +1797,7 @@ void InventoryScreen::renderStatsPanel(game::Inventory& inventory, uint32_t play
|
|||
int32_t armorPenR = gh->getCombatRating(24);
|
||||
int32_t resilR = gh->getCombatRating(14); // CR_CRIT_TAKEN_MELEE = Resilience
|
||||
|
||||
bool hasAny = (meleeAP >= 0 || dodgePct >= 0.0f || parryPct >= 0.0f ||
|
||||
bool hasAny = (meleeAP >= 0 || spellPow >= 0 || dodgePct >= 0.0f || parryPct >= 0.0f ||
|
||||
blockPct >= 0.0f || critPct >= 0.0f || hitRating >= 0);
|
||||
if (hasAny) {
|
||||
ImGui::Spacing();
|
||||
|
|
@ -1805,6 +1807,9 @@ void InventoryScreen::renderStatsPanel(game::Inventory& inventory, uint32_t play
|
|||
if (meleeAP >= 0) ImGui::TextColored(cyan, "Attack Power: %d", meleeAP);
|
||||
if (rangedAP >= 0 && rangedAP != meleeAP)
|
||||
ImGui::TextColored(cyan, "Ranged Attack Power: %d", rangedAP);
|
||||
if (spellPow >= 0) ImGui::TextColored(cyan, "Spell Power: %d", spellPow);
|
||||
if (healPow >= 0 && healPow != spellPow)
|
||||
ImGui::TextColored(cyan, "Healing Power: %d", healPow);
|
||||
if (dodgePct >= 0.0f) ImGui::TextColored(cyan, "Dodge: %.2f%%", dodgePct);
|
||||
if (parryPct >= 0.0f) ImGui::TextColored(cyan, "Parry: %.2f%%", parryPct);
|
||||
if (blockPct >= 0.0f) ImGui::TextColored(cyan, "Block: %.2f%%", blockPct);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue