aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/Utilities/Util.h7
-rw-r--r--src/server/game/Entities/Creature/Creature.cpp22
-rw-r--r--src/server/game/Entities/Creature/Creature.h2
-rw-r--r--src/server/game/Entities/Creature/TemporarySummon.h1
-rw-r--r--src/server/game/Entities/Object/Object.cpp7
-rw-r--r--src/server/game/Entities/Object/Object.h1
-rw-r--r--src/server/game/Entities/Pet/Pet.cpp10
-rw-r--r--src/server/game/Entities/Player/Player.cpp300
-rw-r--r--src/server/game/Entities/Player/Player.h28
-rw-r--r--src/server/game/Entities/Unit/StatSystem.cpp118
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp340
-rw-r--r--src/server/game/Entities/Unit/Unit.h55
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.cpp322
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.h1
-rw-r--r--src/server/game/Spells/SpellEffects.cpp2
-rw-r--r--src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp13
-rw-r--r--src/server/scripts/EasternKingdoms/ZulGurub/boss_marli.cpp13
-rw-r--r--src/server/scripts/EasternKingdoms/ZulGurub/boss_thekal.cpp11
-rw-r--r--src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp18
-rw-r--r--src/server/scripts/Spells/spell_pet.cpp2
20 files changed, 825 insertions, 448 deletions
diff --git a/src/common/Utilities/Util.h b/src/common/Utilities/Util.h
index 7b9db849b50..92a2f601c3f 100644
--- a/src/common/Utilities/Util.h
+++ b/src/common/Utilities/Util.h
@@ -78,13 +78,6 @@ TC_COMMON_API std::string secsToTimeString(uint64 timeInSecs, bool shortText = f
TC_COMMON_API uint32 TimeStringToSecs(const std::string& timestring);
TC_COMMON_API std::string TimeToTimestampStr(time_t t);
-inline void ApplyPercentModFloatVar(float& var, float val, bool apply)
-{
- if (val == -100.0f) // prevent set var to zero
- val = -99.99f;
- var *= (apply ? (100.0f + val) / 100.0f : 100.0f / (100.0f + val));
-}
-
// Percentage calculation
template <class T, class U>
inline T CalculatePct(T base, U pct)
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp
index 4d80ca7b855..ce40889bc99 100644
--- a/src/server/game/Entities/Creature/Creature.cpp
+++ b/src/server/game/Entities/Creature/Creature.cpp
@@ -514,12 +514,12 @@ bool Creature::UpdateEntry(uint32 entry, CreatureData const* data /*= nullptr*/,
UpdateLevelDependantStats();
SetMeleeDamageSchool(SpellSchools(cInfo->dmgschool));
- SetModifierValue(UNIT_MOD_RESISTANCE_HOLY, BASE_VALUE, float(cInfo->resistance[SPELL_SCHOOL_HOLY]));
- SetModifierValue(UNIT_MOD_RESISTANCE_FIRE, BASE_VALUE, float(cInfo->resistance[SPELL_SCHOOL_FIRE]));
- SetModifierValue(UNIT_MOD_RESISTANCE_NATURE, BASE_VALUE, float(cInfo->resistance[SPELL_SCHOOL_NATURE]));
- SetModifierValue(UNIT_MOD_RESISTANCE_FROST, BASE_VALUE, float(cInfo->resistance[SPELL_SCHOOL_FROST]));
- SetModifierValue(UNIT_MOD_RESISTANCE_SHADOW, BASE_VALUE, float(cInfo->resistance[SPELL_SCHOOL_SHADOW]));
- SetModifierValue(UNIT_MOD_RESISTANCE_ARCANE, BASE_VALUE, float(cInfo->resistance[SPELL_SCHOOL_ARCANE]));
+ SetStatFlatModifier(UNIT_MOD_RESISTANCE_HOLY, BASE_VALUE, float(cInfo->resistance[SPELL_SCHOOL_HOLY]));
+ SetStatFlatModifier(UNIT_MOD_RESISTANCE_FIRE, BASE_VALUE, float(cInfo->resistance[SPELL_SCHOOL_FIRE]));
+ SetStatFlatModifier(UNIT_MOD_RESISTANCE_NATURE, BASE_VALUE, float(cInfo->resistance[SPELL_SCHOOL_NATURE]));
+ SetStatFlatModifier(UNIT_MOD_RESISTANCE_FROST, BASE_VALUE, float(cInfo->resistance[SPELL_SCHOOL_FROST]));
+ SetStatFlatModifier(UNIT_MOD_RESISTANCE_SHADOW, BASE_VALUE, float(cInfo->resistance[SPELL_SCHOOL_SHADOW]));
+ SetStatFlatModifier(UNIT_MOD_RESISTANCE_ARCANE, BASE_VALUE, float(cInfo->resistance[SPELL_SCHOOL_ARCANE]));
SetCanModifyStats(true);
UpdateAllStats();
@@ -1312,8 +1312,8 @@ void Creature::UpdateLevelDependantStats()
/// @todo set UNIT_FIELD_POWER*, for some creature class case (energy, etc)
- SetModifierValue(UNIT_MOD_HEALTH, BASE_VALUE, (float)health);
- SetModifierValue(UNIT_MOD_MANA, BASE_VALUE, (float)mana);
+ SetStatFlatModifier(UNIT_MOD_HEALTH, BASE_VALUE, (float)health);
+ SetStatFlatModifier(UNIT_MOD_MANA, BASE_VALUE, (float)mana);
// damage
@@ -1331,11 +1331,11 @@ void Creature::UpdateLevelDependantStats()
SetBaseWeaponDamage(RANGED_ATTACK, MINDAMAGE, weaponBaseMinDamage);
SetBaseWeaponDamage(RANGED_ATTACK, MAXDAMAGE, weaponBaseMaxDamage);
- SetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE, stats->AttackPower);
- SetModifierValue(UNIT_MOD_ATTACK_POWER_RANGED, BASE_VALUE, stats->RangedAttackPower);
+ SetStatFlatModifier(UNIT_MOD_ATTACK_POWER, BASE_VALUE, stats->AttackPower);
+ SetStatFlatModifier(UNIT_MOD_ATTACK_POWER_RANGED, BASE_VALUE, stats->RangedAttackPower);
float armor = (float)stats->GenerateArmor(cInfo); /// @todo Why is this treated as uint32 when it's a float?
- SetModifierValue(UNIT_MOD_ARMOR, BASE_VALUE, armor);
+ SetStatFlatModifier(UNIT_MOD_ARMOR, BASE_VALUE, armor);
}
float Creature::_GetHealthMod(int32 Rank)
diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h
index aa9b2466e62..fd00f63635f 100644
--- a/src/server/game/Entities/Creature/Creature.h
+++ b/src/server/game/Entities/Creature/Creature.h
@@ -521,7 +521,7 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma
void UpdateMaxHealth() override;
void UpdateMaxPower(Powers power) override;
void UpdateAttackPowerAndDamage(bool ranged = false) override;
- void CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage) override;
+ void CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage) const override;
void SetCanDualWield(bool value) override;
int8 GetOriginalEquipmentId() const { return m_originalEquipmentId; }
diff --git a/src/server/game/Entities/Creature/TemporarySummon.h b/src/server/game/Entities/Creature/TemporarySummon.h
index 1a68e20d7d8..50f6c592b9e 100644
--- a/src/server/game/Entities/Creature/TemporarySummon.h
+++ b/src/server/game/Entities/Creature/TemporarySummon.h
@@ -100,6 +100,7 @@ class TC_GAME_API Guardian : public Minion
void UpdateDamagePhysical(WeaponAttackType attType) override;
int32 GetBonusDamage() const { return m_bonusSpellDamage; }
+ float GetBonusStatFromOwner(Stats stat) const { return m_statFromOwner[stat]; }
void SetBonusDamage(int32 damage);
protected:
int32 m_bonusSpellDamage;
diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp
index eb6f7388b00..0267229d198 100644
--- a/src/server/game/Entities/Object/Object.cpp
+++ b/src/server/game/Entities/Object/Object.cpp
@@ -806,13 +806,6 @@ void Object::ApplyModSignedFloatValue(uint16 index, float val, bool apply)
SetFloatValue(index, cur);
}
-void Object::ApplyPercentModFloatValue(uint16 index, float val, bool apply)
-{
- float value = GetFloatValue(index);
- ApplyPercentModFloatVar(value, val, apply);
- SetFloatValue(index, value);
-}
-
void Object::ApplyModPositiveFloatValue(uint16 index, float val, bool apply)
{
float cur = GetFloatValue(index);
diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h
index a01e49c33e4..55d3efed548 100644
--- a/src/server/game/Entities/Object/Object.h
+++ b/src/server/game/Entities/Object/Object.h
@@ -149,7 +149,6 @@ class TC_GAME_API Object
void ApplyModUInt64Value(uint16 index, int32 val, bool apply);
void ApplyModPositiveFloatValue(uint16 index, float val, bool apply);
void ApplyModSignedFloatValue(uint16 index, float val, bool apply);
- void ApplyPercentModFloatValue(uint16 index, float val, bool apply);
void SetFlag(uint16 index, uint32 newFlag);
void RemoveFlag(uint16 index, uint32 oldFlag);
diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp
index 3f2723ae03d..bf3fe3c77fc 100644
--- a/src/server/game/Entities/Pet/Pet.cpp
+++ b/src/server/game/Entities/Pet/Pet.cpp
@@ -821,7 +821,7 @@ bool Guardian::InitStatsForLevel(uint8 petlevel)
SetMeleeDamageSchool(SpellSchools(cinfo->dmgschool));
- SetModifierValue(UNIT_MOD_ARMOR, BASE_VALUE, float(petlevel*50));
+ SetStatFlatModifier(UNIT_MOD_ARMOR, BASE_VALUE, float(petlevel * 50));
SetAttackTime(BASE_ATTACK, BASE_ATTACK_TIME);
SetAttackTime(OFF_ATTACK, BASE_ATTACK_TIME);
@@ -848,7 +848,7 @@ bool Guardian::InitStatsForLevel(uint8 petlevel)
// Hunters pet should not inherit resistances from creature_template, they have separate auras for that
if (!IsHunterPet())
for (uint8 i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i)
- SetModifierValue(UnitMods(UNIT_MOD_RESISTANCE_START + i), BASE_VALUE, float(cinfo->resistance[i]));
+ SetStatFlatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), BASE_VALUE, float(cinfo->resistance[i]));
//health, mana, armor and resistance
PetLevelInfo const* pInfo = sObjectMgr->GetPetLevelInfo(creature_ID, petlevel);
@@ -859,7 +859,7 @@ bool Guardian::InitStatsForLevel(uint8 petlevel)
SetCreateMana(pInfo->mana);
if (pInfo->armor > 0)
- SetModifierValue(UNIT_MOD_ARMOR, BASE_VALUE, float(pInfo->armor));
+ SetStatFlatModifier(UNIT_MOD_ARMOR, BASE_VALUE, float(pInfo->armor));
for (uint8 stat = 0; stat < MAX_STATS; ++stat)
SetCreateStat(Stats(stat), float(pInfo->stats[stat]));
@@ -983,8 +983,8 @@ bool Guardian::InitStatsForLevel(uint8 petlevel)
SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float((petlevel * 4 - petlevel)));
SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float((petlevel * 4 + petlevel)));
- SetModifierValue(UNIT_MOD_ARMOR, BASE_VALUE, float(GetOwner()->GetArmor()) * 0.35f); // Bonus Armor (35% of player armor)
- SetModifierValue(UNIT_MOD_STAT_STAMINA, BASE_VALUE, float(GetOwner()->GetStat(STAT_STAMINA)) * 0.3f); // Bonus Stamina (30% of player stamina)
+ SetStatFlatModifier(UNIT_MOD_ARMOR, BASE_VALUE, float(GetOwner()->GetArmor()) * 0.35f); // Bonus Armor (35% of player armor)
+ SetStatFlatModifier(UNIT_MOD_STAT_STAMINA, BASE_VALUE, float(GetOwner()->GetStat(STAT_STAMINA)) * 0.3f); // Bonus Stamina (30% of player stamina)
if (!HasAura(58877))//prevent apply twice for the 2 wolves
AddAura(58877, this);//Spirit Hunt, passive, Spirit Wolves' attacks heal them and their master for 150% of damage done.
break;
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 7725889c875..5d1cfd7d203 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -458,8 +458,8 @@ Player::Player(WorldSession* session): Unit(true)
for (uint8 i = 0; i < BASEMOD_END; ++i)
{
- m_auraBaseMod[i][FLAT_MOD] = 0.0f;
- m_auraBaseMod[i][PCT_MOD] = 1.0f;
+ m_auraBaseFlatMod[i] = 0.0f;
+ m_auraBasePctMod[i] = 1.0f;
}
for (uint8 i = 0; i < MAX_COMBAT_RATING; i++)
@@ -2982,14 +2982,14 @@ void Player::InitStatsForLevel(bool reapplyMods)
// set armor (resistance 0) to original value (create_agility*2)
SetArmor(int32(m_createStats[STAT_AGILITY]*2));
- SetResistanceBuffMods(SPELL_SCHOOL_NORMAL, true, 0.0f);
- SetResistanceBuffMods(SPELL_SCHOOL_NORMAL, false, 0.0f);
+ SetFloatValue(UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE + SPELL_SCHOOL_NORMAL, 0.0f);
+ SetFloatValue(UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE + SPELL_SCHOOL_NORMAL, 0.0f);
// set other resistance to original value (0)
for (uint8 i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i)
{
SetResistance(SpellSchools(i), 0);
- SetResistanceBuffMods(SpellSchools(i), true, 0.0f);
- SetResistanceBuffMods(SpellSchools(i), false, 0.0f);
+ SetFloatValue(UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE + i, 0.0f);
+ SetFloatValue(UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE + i, 0.0f);
}
SetUInt32Value(PLAYER_FIELD_MOD_TARGET_RESISTANCE, 0);
@@ -5303,20 +5303,104 @@ void Player::UpdateDefense()
UpdateDefenseBonusesMod(); // update dependent from defense skill part
}
-void Player::HandleBaseModValue(BaseModGroup modGroup, BaseModType modType, float amount, bool apply)
+void Player::HandleBaseModFlatValue(BaseModGroup modGroup, float amount, bool apply)
{
- if (modGroup >= BASEMOD_END || modType >= MOD_END)
+ if (modGroup >= BASEMOD_END)
{
TC_LOG_ERROR("spells", "Player::HandleBaseModValue: Invalid BaseModGroup/BaseModType (%u/%u) for player '%s' (%s)",
- modGroup, modType, GetName().c_str(), GetGUID().ToString().c_str());
+ modGroup, FLAT_MOD, GetName().c_str(), GetGUID().ToString().c_str());
+ return;
+ }
+
+ m_auraBaseFlatMod[modGroup] += apply ? amount : -amount;
+ UpdateBaseModGroup(modGroup);
+}
+
+void Player::ApplyBaseModPctValue(BaseModGroup modGroup, float pct)
+{
+ if (modGroup >= BASEMOD_END)
+ {
+ TC_LOG_ERROR("spells", "Player::HandleBaseModValue: Invalid BaseModGroup/BaseModType (%u/%u) for player '%s' (%s)",
+ modGroup, FLAT_MOD, GetName().c_str(), GetGUID().ToString().c_str());
+ return;
+ }
+
+ AddPct(m_auraBasePctMod[modGroup], pct);
+ UpdateBaseModGroup(modGroup);
+}
+
+void Player::SetBaseModFlatValue(BaseModGroup modGroup, float val)
+{
+ if (m_auraBaseFlatMod[modGroup] == val)
return;
+
+ m_auraBaseFlatMod[modGroup] = val;
+ UpdateBaseModGroup(modGroup);
+}
+
+void Player::SetBaseModPctValue(BaseModGroup modGroup, float val)
+{
+ if (m_auraBasePctMod[modGroup] == val)
+ return;
+
+ m_auraBasePctMod[modGroup] = val;
+ UpdateBaseModGroup(modGroup);
+}
+
+void Player::UpdateDamageDoneMods(WeaponAttackType attackType)
+{
+ Unit::UpdateDamageDoneMods(attackType);
+
+ UnitMods unitMod;
+ switch (attackType)
+ {
+ case BASE_ATTACK:
+ unitMod = UNIT_MOD_DAMAGE_MAINHAND;
+ break;
+ case OFF_ATTACK:
+ unitMod = UNIT_MOD_DAMAGE_OFFHAND;
+ break;
+ case RANGED_ATTACK:
+ unitMod = UNIT_MOD_DAMAGE_RANGED;
+ break;
+ default:
+ ABORT();
+ break;
+ }
+
+ float amount = 0.0f;
+ Item* item = GetWeaponForAttack(attackType, true);
+ if (!item)
+ return;
+
+ for (uint8 slot = 0; slot < MAX_ENCHANTMENT_SLOT; ++slot)
+ {
+ SpellItemEnchantmentEntry const* enchantmentEntry = sSpellItemEnchantmentStore.LookupEntry(item->GetEnchantmentId(EnchantmentSlot(slot)));
+ if (!enchantmentEntry)
+ continue;
+
+ for (uint8 i = 0; i < MAX_ITEM_ENCHANTMENT_EFFECTS; ++i)
+ {
+ switch (enchantmentEntry->type[i])
+ {
+ case ITEM_ENCHANTMENT_TYPE_DAMAGE:
+ amount += enchantmentEntry->amount[i];
+ break;
+ case ITEM_ENCHANTMENT_TYPE_TOTEM:
+ if (getClass() == CLASS_SHAMAN)
+ amount += enchantmentEntry->amount[i] * item->GetTemplate()->Delay / 1000.0f;
+ break;
+ default:
+ break;
+ }
+ }
}
- if (modType == FLAT_MOD)
- m_auraBaseMod[modGroup][modType] += apply ? amount : -amount;
- else // PCT_MOD
- ApplyPercentModFloatVar(m_auraBaseMod[modGroup][modType], amount, apply);
+ HandleStatFlatModifier(unitMod, TOTAL_VALUE, amount, true);
+}
+void Player::UpdateBaseModGroup(BaseModGroup modGroup)
+{
if (!CanModifyStats())
return;
@@ -5339,10 +5423,7 @@ float Player::GetBaseModValue(BaseModGroup modGroup, BaseModType modType) const
return 0.0f;
}
- if (modType == PCT_MOD && m_auraBaseMod[modGroup][PCT_MOD] <= 0.0f)
- return 0.0f;
-
- return m_auraBaseMod[modGroup][modType];
+ return (modType == FLAT_MOD ? m_auraBaseFlatMod[modGroup] : m_auraBasePctMod[modGroup]);
}
float Player::GetTotalBaseModValue(BaseModGroup modGroup) const
@@ -5354,18 +5435,12 @@ float Player::GetTotalBaseModValue(BaseModGroup modGroup) const
return 0.0f;
}
- if (m_auraBaseMod[modGroup][PCT_MOD] <= 0.0f)
- return 0.0f;
-
- return m_auraBaseMod[modGroup][FLAT_MOD] * m_auraBaseMod[modGroup][PCT_MOD];
+ return m_auraBaseFlatMod[modGroup] * m_auraBasePctMod[modGroup];
}
uint32 Player::GetShieldBlockValue() const
{
- float value = (m_auraBaseMod[SHIELD_BLOCK_VALUE][FLAT_MOD] + GetStat(STAT_STRENGTH) * 0.5f - 10)*m_auraBaseMod[SHIELD_BLOCK_VALUE][PCT_MOD];
-
- value = (value < 0) ? 0 : value;
-
+ float value = std::max(0.f, (m_auraBaseFlatMod[SHIELD_BLOCK_VALUE] + GetStat(STAT_STRENGTH) * 0.5f - 10) * m_auraBasePctMod[SHIELD_BLOCK_VALUE]);
return uint32(value);
}
@@ -5431,7 +5506,7 @@ void Player::GetDodgeFromAgility(float &diminishing, float &nondiminishing) cons
return;
/// @todo research if talents/effects that increase total agility by x% should increase non-diminishing part
- float base_agility = GetCreateStat(STAT_AGILITY) * m_auraModifiersGroup[UNIT_MOD_STAT_START + STAT_AGILITY][BASE_PCT];
+ float base_agility = GetCreateStat(STAT_AGILITY) * GetPctModifierValue(UnitMods(UNIT_MOD_STAT_START + STAT_AGILITY), BASE_PCT);
float bonus_agility = GetStat(STAT_AGILITY) - base_agility;
// calculate diminishing (green in char screen) and non-diminishing (white) contribution
@@ -5654,7 +5729,7 @@ void Player::UpdateRating(CombatRating cr)
void Player::UpdateAllRatings()
{
- for (int cr = 0; cr < MAX_COMBAT_RATING; ++cr)
+ for (uint8 cr = 0; cr < MAX_COMBAT_RATING; ++cr)
UpdateRating(CombatRating(cr));
}
@@ -7365,8 +7440,14 @@ void Player::_ApplyItemMods(Item* item, uint8 slot, bool apply, bool updateItemA
ApplyItemEquipSpell(item, apply);
if (updateItemAuras)
+ {
ApplyItemDependentAuras(item, apply);
+ WeaponAttackType const attackType = Player::GetAttackBySlot(slot);
+ if (attackType != MAX_ATTACK)
+ UpdateWeaponDependentAuras(attackType);
+ }
+
ApplyEnchantment(item, apply);
TC_LOG_DEBUG("entities.player.items", "Player::_ApplyItemMods: completed");
@@ -7416,30 +7497,30 @@ void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply
switch (statType)
{
case ITEM_MOD_MANA:
- HandleStatModifier(UNIT_MOD_MANA, BASE_VALUE, float(val), apply);
+ HandleStatFlatModifier(UNIT_MOD_MANA, BASE_VALUE, float(val), apply);
break;
case ITEM_MOD_HEALTH: // modify HP
- HandleStatModifier(UNIT_MOD_HEALTH, BASE_VALUE, float(val), apply);
+ HandleStatFlatModifier(UNIT_MOD_HEALTH, BASE_VALUE, float(val), apply);
break;
case ITEM_MOD_AGILITY: // modify agility
- HandleStatModifier(UNIT_MOD_STAT_AGILITY, BASE_VALUE, float(val), apply);
- ApplyStatBuffMod(STAT_AGILITY, float(val), apply);
+ HandleStatFlatModifier(UNIT_MOD_STAT_AGILITY, BASE_VALUE, float(val), apply);
+ UpdateStatBuffMod(STAT_AGILITY);
break;
case ITEM_MOD_STRENGTH: //modify strength
- HandleStatModifier(UNIT_MOD_STAT_STRENGTH, BASE_VALUE, float(val), apply);
- ApplyStatBuffMod(STAT_STRENGTH, float(val), apply);
+ HandleStatFlatModifier(UNIT_MOD_STAT_STRENGTH, BASE_VALUE, float(val), apply);
+ UpdateStatBuffMod(STAT_STRENGTH);
break;
case ITEM_MOD_INTELLECT: //modify intellect
- HandleStatModifier(UNIT_MOD_STAT_INTELLECT, BASE_VALUE, float(val), apply);
- ApplyStatBuffMod(STAT_INTELLECT, float(val), apply);
+ HandleStatFlatModifier(UNIT_MOD_STAT_INTELLECT, BASE_VALUE, float(val), apply);
+ UpdateStatBuffMod(STAT_INTELLECT);
break;
case ITEM_MOD_SPIRIT: //modify spirit
- HandleStatModifier(UNIT_MOD_STAT_SPIRIT, BASE_VALUE, float(val), apply);
- ApplyStatBuffMod(STAT_SPIRIT, float(val), apply);
+ HandleStatFlatModifier(UNIT_MOD_STAT_SPIRIT, BASE_VALUE, float(val), apply);
+ UpdateStatBuffMod(STAT_SPIRIT);
break;
case ITEM_MOD_STAMINA: //modify stamina
- HandleStatModifier(UNIT_MOD_STAT_STAMINA, BASE_VALUE, float(val), apply);
- ApplyStatBuffMod(STAT_STAMINA, float(val), apply);
+ HandleStatFlatModifier(UNIT_MOD_STAT_STAMINA, BASE_VALUE, float(val), apply);
+ UpdateStatBuffMod(STAT_STAMINA);
break;
case ITEM_MOD_DEFENSE_SKILL_RATING:
ApplyRatingMod(CR_DEFENSE_SKILL, int32(val), apply);
@@ -7532,11 +7613,11 @@ void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply
ApplyRatingMod(CR_EXPERTISE, int32(val), apply);
break;
case ITEM_MOD_ATTACK_POWER:
- HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, float(val), apply);
- HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(val), apply);
+ HandleStatFlatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, float(val), apply);
+ HandleStatFlatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(val), apply);
break;
case ITEM_MOD_RANGED_ATTACK_POWER:
- HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(val), apply);
+ HandleStatFlatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(val), apply);
break;
// case ITEM_MOD_FERAL_ATTACK_POWER:
// ApplyFeralAPBonus(int32(val), apply);
@@ -7557,7 +7638,7 @@ void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply
ApplySpellPenetrationBonus(val, apply);
break;
case ITEM_MOD_BLOCK_VALUE:
- HandleBaseModValue(SHIELD_BLOCK_VALUE, FLAT_MOD, float(val), apply);
+ HandleBaseModFlatValue(SHIELD_BLOCK_VALUE, float(val), apply);
break;
// deprecated item mods
case ITEM_MOD_SPELL_HEALING_DONE:
@@ -7583,7 +7664,7 @@ void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply
if (armor)
{
- UnitModifierType modType = TOTAL_VALUE;
+ UnitModifierFlatType modType = TOTAL_VALUE;
if (proto->Class == ITEM_CLASS_ARMOR)
{
switch (proto->SubClass)
@@ -7597,33 +7678,33 @@ void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply
break;
}
}
- HandleStatModifier(UNIT_MOD_ARMOR, modType, float(armor), apply);
+ HandleStatFlatModifier(UNIT_MOD_ARMOR, modType, float(armor), apply);
}
// Add armor bonus from ArmorDamageModifier if > 0
if (proto->ArmorDamageModifier > 0)
- HandleStatModifier(UNIT_MOD_ARMOR, TOTAL_VALUE, float(proto->ArmorDamageModifier), apply);
+ HandleStatFlatModifier(UNIT_MOD_ARMOR, TOTAL_VALUE, float(proto->ArmorDamageModifier), apply);
if (proto->Block)
- HandleBaseModValue(SHIELD_BLOCK_VALUE, FLAT_MOD, float(proto->Block), apply);
+ HandleBaseModFlatValue(SHIELD_BLOCK_VALUE, float(proto->Block), apply);
if (proto->HolyRes)
- HandleStatModifier(UNIT_MOD_RESISTANCE_HOLY, BASE_VALUE, float(proto->HolyRes), apply);
+ HandleStatFlatModifier(UNIT_MOD_RESISTANCE_HOLY, BASE_VALUE, float(proto->HolyRes), apply);
if (proto->FireRes)
- HandleStatModifier(UNIT_MOD_RESISTANCE_FIRE, BASE_VALUE, float(proto->FireRes), apply);
+ HandleStatFlatModifier(UNIT_MOD_RESISTANCE_FIRE, BASE_VALUE, float(proto->FireRes), apply);
if (proto->NatureRes)
- HandleStatModifier(UNIT_MOD_RESISTANCE_NATURE, BASE_VALUE, float(proto->NatureRes), apply);
+ HandleStatFlatModifier(UNIT_MOD_RESISTANCE_NATURE, BASE_VALUE, float(proto->NatureRes), apply);
if (proto->FrostRes)
- HandleStatModifier(UNIT_MOD_RESISTANCE_FROST, BASE_VALUE, float(proto->FrostRes), apply);
+ HandleStatFlatModifier(UNIT_MOD_RESISTANCE_FROST, BASE_VALUE, float(proto->FrostRes), apply);
if (proto->ShadowRes)
- HandleStatModifier(UNIT_MOD_RESISTANCE_SHADOW, BASE_VALUE, float(proto->ShadowRes), apply);
+ HandleStatFlatModifier(UNIT_MOD_RESISTANCE_SHADOW, BASE_VALUE, float(proto->ShadowRes), apply);
if (proto->ArcaneRes)
- HandleStatModifier(UNIT_MOD_RESISTANCE_ARCANE, BASE_VALUE, float(proto->ArcaneRes), apply);
+ HandleStatFlatModifier(UNIT_MOD_RESISTANCE_ARCANE, BASE_VALUE, float(proto->ArcaneRes), apply);
WeaponAttackType attType = BASE_ATTACK;
@@ -7760,6 +7841,49 @@ void Player::ApplyItemObtainSpells(Item* item, bool apply)
}
}
+// this one rechecks weapon auras and stores them in BaseModGroup container
+// needed for things like axe specialization applying only to axe weapons in case of dual-wield
+void Player::UpdateWeaponDependentCritAuras(WeaponAttackType attackType)
+{
+ BaseModGroup modGroup;
+ switch (attackType)
+ {
+ case BASE_ATTACK:
+ modGroup = CRIT_PERCENTAGE;
+ break;
+ case OFF_ATTACK:
+ modGroup = OFFHAND_CRIT_PERCENTAGE;
+ break;
+ case RANGED_ATTACK:
+ modGroup = RANGED_CRIT_PERCENTAGE;
+ break;
+ default:
+ ABORT();
+ break;
+ }
+
+ float amount = 0.0f;
+ amount += GetTotalAuraModifier(SPELL_AURA_MOD_WEAPON_CRIT_PERCENT, std::bind(&Unit::CheckAttackFitToAuraRequirement, this, attackType, std::placeholders::_1));
+
+ // these auras don't have item requirement (only Combat Expertise in 3.3.5a)
+ amount += GetTotalAuraModifier(SPELL_AURA_MOD_CRIT_PCT);
+
+ SetBaseModFlatValue(modGroup, amount);
+}
+
+void Player::UpdateAllWeaponDependentCritAuras()
+{
+ for (uint8 i = BASE_ATTACK; i < MAX_ATTACK; ++i)
+ UpdateWeaponDependentCritAuras(WeaponAttackType(i));
+}
+
+void Player::UpdateWeaponDependentAuras(WeaponAttackType attackType)
+{
+ UpdateWeaponDependentCritAuras(attackType);
+ UpdateDamageDoneMods(attackType);
+ UpdateDamagePctDoneMods(attackType);
+}
+
void Player::ApplyItemDependentAuras(Item* item, bool apply)
{
if (apply)
@@ -8202,6 +8326,10 @@ void Player::_ApplyAllItemMods()
ApplyItemDependentAuras(m_items[i], true);
_ApplyItemBonuses(proto, i, true);
+ WeaponAttackType const attackType = Player::GetAttackBySlot(i);
+ if (attackType != MAX_ATTACK)
+ UpdateWeaponDependentAuras(attackType);
+
if (i == EQUIPMENT_SLOT_RANGED)
_ApplyAmmoBonuses();
}
@@ -9916,7 +10044,7 @@ Item* Player::GetShield(bool useable) const
return item;
}
-uint8 Player::GetAttackBySlot(uint8 slot)
+WeaponAttackType Player::GetAttackBySlot(uint8 slot)
{
switch (slot)
{
@@ -13613,7 +13741,7 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool
if (!item->IsBroken())
{
- for (int s = 0; s < MAX_ITEM_ENCHANTMENT_EFFECTS; ++s)
+ for (uint8 s = 0; s < MAX_ITEM_ENCHANTMENT_EFFECTS; ++s)
{
uint32 enchant_display_type = pEnchant->type[s];
uint32 enchant_amount = pEnchant->amount[s];
@@ -13627,13 +13755,12 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool
// processed in Player::CastItemCombatSpell
break;
case ITEM_ENCHANTMENT_TYPE_DAMAGE:
- if (item->GetSlot() == EQUIPMENT_SLOT_MAINHAND)
- HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_VALUE, float(enchant_amount), apply);
- else if (item->GetSlot() == EQUIPMENT_SLOT_OFFHAND)
- HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_VALUE, float(enchant_amount), apply);
- else if (item->GetSlot() == EQUIPMENT_SLOT_RANGED)
- HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_VALUE, float(enchant_amount), apply);
+ {
+ WeaponAttackType const attackType = Player::GetAttackBySlot(item->GetSlot());
+ if (attackType != MAX_ATTACK)
+ UpdateDamageDoneMods(attackType);
break;
+ }
case ITEM_ENCHANTMENT_TYPE_EQUIP_SPELL:
if (enchant_spell_id)
{
@@ -13684,7 +13811,7 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool
}
}
- HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + enchant_spell_id), TOTAL_VALUE, float(enchant_amount), apply);
+ HandleStatFlatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + enchant_spell_id), TOTAL_VALUE, float(enchant_amount), apply);
break;
case ITEM_ENCHANTMENT_TYPE_STAT:
{
@@ -13709,36 +13836,36 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool
{
case ITEM_MOD_MANA:
TC_LOG_DEBUG("entities.player.items", "+ %u MANA", enchant_amount);
- HandleStatModifier(UNIT_MOD_MANA, BASE_VALUE, float(enchant_amount), apply);
+ HandleStatFlatModifier(UNIT_MOD_MANA, BASE_VALUE, float(enchant_amount), apply);
break;
case ITEM_MOD_HEALTH:
TC_LOG_DEBUG("entities.player.items", "+ %u HEALTH", enchant_amount);
- HandleStatModifier(UNIT_MOD_HEALTH, BASE_VALUE, float(enchant_amount), apply);
+ HandleStatFlatModifier(UNIT_MOD_HEALTH, BASE_VALUE, float(enchant_amount), apply);
break;
case ITEM_MOD_AGILITY:
TC_LOG_DEBUG("entities.player.items", "+ %u AGILITY", enchant_amount);
- HandleStatModifier(UNIT_MOD_STAT_AGILITY, TOTAL_VALUE, float(enchant_amount), apply);
- ApplyStatBuffMod(STAT_AGILITY, (float)enchant_amount, apply);
+ HandleStatFlatModifier(UNIT_MOD_STAT_AGILITY, TOTAL_VALUE, float(enchant_amount), apply);
+ UpdateStatBuffMod(STAT_AGILITY);
break;
case ITEM_MOD_STRENGTH:
TC_LOG_DEBUG("entities.player.items", "+ %u STRENGTH", enchant_amount);
- HandleStatModifier(UNIT_MOD_STAT_STRENGTH, TOTAL_VALUE, float(enchant_amount), apply);
- ApplyStatBuffMod(STAT_STRENGTH, (float)enchant_amount, apply);
+ HandleStatFlatModifier(UNIT_MOD_STAT_STRENGTH, TOTAL_VALUE, float(enchant_amount), apply);
+ UpdateStatBuffMod(STAT_STRENGTH);
break;
case ITEM_MOD_INTELLECT:
TC_LOG_DEBUG("entities.player.items", "+ %u INTELLECT", enchant_amount);
- HandleStatModifier(UNIT_MOD_STAT_INTELLECT, TOTAL_VALUE, float(enchant_amount), apply);
- ApplyStatBuffMod(STAT_INTELLECT, (float)enchant_amount, apply);
+ HandleStatFlatModifier(UNIT_MOD_STAT_INTELLECT, TOTAL_VALUE, float(enchant_amount), apply);
+ UpdateStatBuffMod(STAT_INTELLECT);
break;
case ITEM_MOD_SPIRIT:
TC_LOG_DEBUG("entities.player.items", "+ %u SPIRIT", enchant_amount);
- HandleStatModifier(UNIT_MOD_STAT_SPIRIT, TOTAL_VALUE, float(enchant_amount), apply);
- ApplyStatBuffMod(STAT_SPIRIT, (float)enchant_amount, apply);
+ HandleStatFlatModifier(UNIT_MOD_STAT_SPIRIT, TOTAL_VALUE, float(enchant_amount), apply);
+ UpdateStatBuffMod(STAT_SPIRIT);
break;
case ITEM_MOD_STAMINA:
TC_LOG_DEBUG("entities.player.items", "+ %u STAMINA", enchant_amount);
- HandleStatModifier(UNIT_MOD_STAT_STAMINA, TOTAL_VALUE, float(enchant_amount), apply);
- ApplyStatBuffMod(STAT_STAMINA, (float)enchant_amount, apply);
+ HandleStatFlatModifier(UNIT_MOD_STAT_STAMINA, TOTAL_VALUE, float(enchant_amount), apply);
+ UpdateStatBuffMod(STAT_STAMINA);
break;
case ITEM_MOD_DEFENSE_SKILL_RATING:
ApplyRatingMod(CR_DEFENSE_SKILL, enchant_amount, apply);
@@ -13849,12 +13976,12 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool
TC_LOG_DEBUG("entities.player.items", "+ %u EXPERTISE", enchant_amount);
break;
case ITEM_MOD_ATTACK_POWER:
- HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, float(enchant_amount), apply);
- HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(enchant_amount), apply);
+ HandleStatFlatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, float(enchant_amount), apply);
+ HandleStatFlatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(enchant_amount), apply);
TC_LOG_DEBUG("entities.player.items", "+ %u ATTACK_POWER", enchant_amount);
break;
case ITEM_MOD_RANGED_ATTACK_POWER:
- HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(enchant_amount), apply);
+ HandleStatFlatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(enchant_amount), apply);
TC_LOG_DEBUG("entities.player.items", "+ %u RANGED_ATTACK_POWER", enchant_amount);
break;
// case ITEM_MOD_FERAL_ATTACK_POWER:
@@ -13882,7 +14009,7 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool
TC_LOG_DEBUG("entities.player.items", "+ %u SPELL_PENETRATION", enchant_amount);
break;
case ITEM_MOD_BLOCK_VALUE:
- HandleBaseModValue(SHIELD_BLOCK_VALUE, FLAT_MOD, float(enchant_amount), apply);
+ HandleBaseModFlatValue(SHIELD_BLOCK_VALUE, float(enchant_amount), apply);
TC_LOG_DEBUG("entities.player.items", "+ %u BLOCK_VALUE", enchant_amount);
break;
case ITEM_MOD_SPELL_HEALING_DONE: // deprecated
@@ -13894,20 +14021,9 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool
}
case ITEM_ENCHANTMENT_TYPE_TOTEM: // Shaman Rockbiter Weapon
{
- if (getClass() == CLASS_SHAMAN)
- {
- float addValue;
- if (item->GetSlot() == EQUIPMENT_SLOT_MAINHAND)
- {
- addValue = float(enchant_amount * item->GetTemplate()->Delay / 1000.0f);
- HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_VALUE, addValue, apply);
- }
- else if (item->GetSlot() == EQUIPMENT_SLOT_OFFHAND)
- {
- addValue = float(enchant_amount * item->GetTemplate()->Delay / 1000.0f);
- HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_VALUE, addValue, apply);
- }
- }
+ WeaponAttackType const attackType = Player::GetAttackBySlot(item->GetSlot());
+ if (attackType != MAX_ATTACK)
+ UpdateDamageDoneMods(attackType);
break;
}
case ITEM_ENCHANTMENT_TYPE_USE_SPELL:
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index 4e0942425ec..808078d74c0 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -1183,8 +1183,8 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
Bag* GetBagByPos(uint8 slot) const;
Item* GetWeaponForAttack(WeaponAttackType attackType, bool useable = false) const;
Item* GetShield(bool useable = false) const;
- static uint8 GetAttackBySlot(uint8 slot); // MAX_ATTACK if not weapon slot
- std::vector<Item*> &GetItemUpdateQueue() { return m_itemUpdateQueue; }
+ static WeaponAttackType GetAttackBySlot(uint8 slot); // MAX_ATTACK if not weapon slot
+ std::vector<Item*>& GetItemUpdateQueue() { return m_itemUpdateQueue; }
static bool IsInventoryPos(uint16 pos) { return IsInventoryPos(pos >> 8, pos & 255); }
static bool IsInventoryPos(uint8 bag, uint8 slot);
static bool IsEquipmentPos(uint16 pos) { return IsEquipmentPos(pos >> 8, pos & 255); }
@@ -1734,7 +1734,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
void UpdateRating(CombatRating cr);
void UpdateAllRatings();
- void CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage) override;
+ void CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage) const override;
void UpdateDefenseBonusesMod();
void RecalculateRating(CombatRating cr) { ApplyRatingMod(cr, 0, true);}
@@ -1946,11 +1946,19 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
bool CanTameExoticPets() const { return IsGameMaster() || HasAuraType(SPELL_AURA_ALLOW_TAME_PET_TYPE); }
void SetRegularAttackTime();
- void SetBaseModValue(BaseModGroup modGroup, BaseModType modType, float value) { m_auraBaseMod[modGroup][modType] = value; }
- void HandleBaseModValue(BaseModGroup modGroup, BaseModType modType, float amount, bool apply);
+
+ void HandleBaseModFlatValue(BaseModGroup modGroup, float amount, bool apply);
+ void ApplyBaseModPctValue(BaseModGroup modGroup, float pct);
+
+ void SetBaseModFlatValue(BaseModGroup modGroup, float val);
+ void SetBaseModPctValue(BaseModGroup modGroup, float val);
+
+ void UpdateDamageDoneMods(WeaponAttackType attackType) override;
+ void UpdateBaseModGroup(BaseModGroup modGroup);
+
float GetBaseModValue(BaseModGroup modGroup, BaseModType modType) const;
float GetTotalBaseModValue(BaseModGroup modGroup) const;
- float GetTotalPercentageModValue(BaseModGroup modGroup) const { return m_auraBaseMod[modGroup][FLAT_MOD] + m_auraBaseMod[modGroup][PCT_MOD]; }
+
void _ApplyAllStatBonuses();
void _RemoveAllStatBonuses();
@@ -1958,6 +1966,11 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
void CastAllObtainSpells();
void ApplyItemObtainSpells(Item* item, bool apply);
+
+ void UpdateWeaponDependentCritAuras(WeaponAttackType attackType);
+ void UpdateAllWeaponDependentCritAuras();
+
+ void UpdateWeaponDependentAuras(WeaponAttackType attackType);
void ApplyItemDependentAuras(Item* item, bool apply);
void _ApplyItemMods(Item* item, uint8 slot, bool apply, bool updateItemAuras = true);
@@ -2434,7 +2447,8 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
ActionButtonList m_actionButtons;
- float m_auraBaseMod[BASEMOD_END][MOD_END];
+ float m_auraBaseFlatMod[BASEMOD_END];
+ float m_auraBasePctMod[BASEMOD_END];
int16 m_baseRatingValue[MAX_COMBAT_RATING];
uint32 m_baseSpellPower;
uint32 m_baseFeralAP;
diff --git a/src/server/game/Entities/Unit/StatSystem.cpp b/src/server/game/Entities/Unit/StatSystem.cpp
index b18c9fefb90..c48fbd73887 100644
--- a/src/server/game/Entities/Unit/StatSystem.cpp
+++ b/src/server/game/Entities/Unit/StatSystem.cpp
@@ -199,7 +199,7 @@ void Player::UpdateSpellDamageAndHealingBonus()
bool Player::UpdateAllStats()
{
- for (int8 i = STAT_STRENGTH; i < MAX_STATS; ++i)
+ for (uint8 i = STAT_STRENGTH; i < MAX_STATS; ++i)
{
float value = GetTotalStatValue(Stats(i));
SetStat(Stats(i), int32(value));
@@ -253,10 +253,10 @@ void Player::UpdateArmor()
{
UnitMods unitMod = UNIT_MOD_ARMOR;
- float value = GetModifierValue(unitMod, BASE_VALUE); // base armor (from items)
- value *= GetModifierValue(unitMod, BASE_PCT); // armor percent from items
- value += GetStat(STAT_AGILITY) * 2.0f; // armor bonus from stats
- value += GetModifierValue(unitMod, TOTAL_VALUE);
+ float value = GetFlatModifierValue(unitMod, BASE_VALUE); // base armor (from items)
+ value *= GetPctModifierValue(unitMod, BASE_PCT); // armor percent from items
+ value += GetStat(STAT_AGILITY) * 2.0f; // armor bonus from stats
+ value += GetFlatModifierValue(unitMod, TOTAL_VALUE);
//add dynamic flat mods
AuraEffectList const& mResbyIntellect = GetAuraEffectsByType(SPELL_AURA_MOD_RESISTANCE_OF_STAT_PERCENT);
@@ -266,7 +266,7 @@ void Player::UpdateArmor()
value += CalculatePct(GetStat(Stats((*i)->GetMiscValueB())), (*i)->GetAmount());
}
- value *= GetModifierValue(unitMod, TOTAL_PCT);
+ value *= GetPctModifierValue(unitMod, TOTAL_PCT);
SetArmor(int32(value));
@@ -300,10 +300,10 @@ void Player::UpdateMaxHealth()
{
UnitMods unitMod = UNIT_MOD_HEALTH;
- float value = GetModifierValue(unitMod, BASE_VALUE) + GetCreateHealth();
- value *= GetModifierValue(unitMod, BASE_PCT);
- value += GetModifierValue(unitMod, TOTAL_VALUE) + GetHealthBonusFromStamina();
- value *= GetModifierValue(unitMod, TOTAL_PCT);
+ float value = GetFlatModifierValue(unitMod, BASE_VALUE) + GetCreateHealth();
+ value *= GetPctModifierValue(unitMod, BASE_PCT);
+ value += GetFlatModifierValue(unitMod, TOTAL_VALUE) + GetHealthBonusFromStamina();
+ value *= GetPctModifierValue(unitMod, TOTAL_PCT);
SetMaxHealth((uint32)value);
}
@@ -314,10 +314,10 @@ void Player::UpdateMaxPower(Powers power)
float bonusPower = (power == POWER_MANA && GetCreatePowers(power) > 0) ? GetManaBonusFromIntellect() : 0;
- float value = GetModifierValue(unitMod, BASE_VALUE) + GetCreatePowers(power);
- value *= GetModifierValue(unitMod, BASE_PCT);
- value += GetModifierValue(unitMod, TOTAL_VALUE) + bonusPower;
- value *= GetModifierValue(unitMod, TOTAL_PCT);
+ float value = GetFlatModifierValue(unitMod, BASE_VALUE) + GetCreatePowers(power);
+ value *= GetPctModifierValue(unitMod, BASE_PCT);
+ value += GetFlatModifierValue(unitMod, TOTAL_VALUE) + bonusPower;
+ value *= GetPctModifierValue(unitMod, TOTAL_PCT);
SetMaxPower(power, uint32(value));
}
@@ -447,10 +447,10 @@ void Player::UpdateAttackPowerAndDamage(bool ranged)
}
}
- SetModifierValue(unitMod, BASE_VALUE, val2);
+ SetStatFlatModifier(unitMod, BASE_VALUE, val2);
- float base_attPower = GetModifierValue(unitMod, BASE_VALUE) * GetModifierValue(unitMod, BASE_PCT);
- float attPowerMod = GetModifierValue(unitMod, TOTAL_VALUE);
+ float base_attPower = GetFlatModifierValue(unitMod, BASE_VALUE) * GetPctModifierValue(unitMod, BASE_PCT);
+ float attPowerMod = GetFlatModifierValue(unitMod, TOTAL_VALUE);
//add dynamic flat mods
if (ranged)
@@ -474,7 +474,7 @@ void Player::UpdateAttackPowerAndDamage(bool ranged)
attPowerMod += int32(GetArmor() / (*iter)->GetAmount());
}
- float attPowerMultiplier = GetModifierValue(unitMod, TOTAL_PCT) - 1.0f;
+ float attPowerMultiplier = GetPctModifierValue(unitMod, TOTAL_PCT) - 1.0f;
SetInt32Value(index, (uint32)base_attPower); //UNIT_FIELD_(RANGED)_ATTACK_POWER field
SetInt32Value(index_mod, (uint32)attPowerMod); //UNIT_FIELD_(RANGED)_ATTACK_POWER_MODS field
@@ -510,7 +510,7 @@ void Player::UpdateShieldBlockValue()
SetUInt32Value(PLAYER_SHIELD_BLOCK, GetShieldBlockValue());
}
-void Player::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage)
+void Player::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage) const
{
UnitMods unitMod;
@@ -530,10 +530,10 @@ void Player::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bo
float const attackPowerMod = std::max(GetAPMultiplier(attType, normalized), 0.25f);
- float baseValue = GetModifierValue(unitMod, BASE_VALUE) + GetTotalAttackPowerValue(attType) / 14.0f * attackPowerMod;
- float basePct = GetModifierValue(unitMod, BASE_PCT);
- float totalValue = GetModifierValue(unitMod, TOTAL_VALUE);
- float totalPct = addTotalPct ? GetModifierValue(unitMod, TOTAL_PCT) : 1.0f;
+ float baseValue = GetFlatModifierValue(unitMod, BASE_VALUE) + GetTotalAttackPowerValue(attType) / 14.0f * attackPowerMod;
+ float basePct = GetPctModifierValue(unitMod, BASE_PCT);
+ float totalValue = GetFlatModifierValue(unitMod, TOTAL_VALUE);
+ float totalPct = addTotalPct ? GetPctModifierValue(unitMod, TOTAL_PCT) : 1.0f;
float weaponMinDamage = GetWeaponDamageRange(attType, MINDAMAGE);
float weaponMaxDamage = GetWeaponDamageRange(attType, MAXDAMAGE);
@@ -625,14 +625,16 @@ void Player::UpdateCritPercentage(WeaponAttackType attType)
break;
}
- float value = GetTotalPercentageModValue(modGroup) + GetRatingBonusValue(cr);
+ // flat = bonus from crit auras, pct = bonus from agility, combat rating = mods from items
+ float value = GetBaseModValue(modGroup, FLAT_MOD) + GetBaseModValue(modGroup, PCT_MOD) + GetRatingBonusValue(cr);
+
// Modify crit from weapon skill and maximized defense skill of same level victim difference
value += (int32(GetWeaponSkillValue(attType)) - int32(GetMaxSkillValueForLevel())) * 0.04f;
if (sWorld->getBoolConfig(CONFIG_STATS_LIMITS_ENABLE))
value = value > sWorld->getFloatConfig(CONFIG_STATS_LIMITS_CRIT) ? sWorld->getFloatConfig(CONFIG_STATS_LIMITS_CRIT) : value;
- value = value < 0.0f ? 0.0f : value;
+ value = std::max(0.0f, value);
SetStatFloatValue(index, value);
}
@@ -640,9 +642,9 @@ void Player::UpdateAllCritPercentages()
{
float value = GetMeleeCritFromAgility();
- SetBaseModValue(CRIT_PERCENTAGE, PCT_MOD, value);
- SetBaseModValue(OFFHAND_CRIT_PERCENTAGE, PCT_MOD, value);
- SetBaseModValue(RANGED_CRIT_PERCENTAGE, PCT_MOD, value);
+ SetBaseModPctValue(CRIT_PERCENTAGE, value);
+ SetBaseModPctValue(OFFHAND_CRIT_PERCENTAGE, value);
+ SetBaseModPctValue(RANGED_CRIT_PERCENTAGE, value);
UpdateCritPercentage(BASE_ATTACK);
UpdateCritPercentage(OFF_ATTACK);
@@ -1005,9 +1007,9 @@ void Creature::UpdateAttackPowerAndDamage(bool ranged)
indexMulti = UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER;
}
- float baseAttackPower = GetModifierValue(unitMod, BASE_VALUE) * GetModifierValue(unitMod, BASE_PCT);
- float attackPowerMod = GetModifierValue(unitMod, TOTAL_VALUE);
- float attackPowerMultiplier = GetModifierValue(unitMod, TOTAL_PCT) - 1.0f;
+ float baseAttackPower = GetFlatModifierValue(unitMod, BASE_VALUE) * GetPctModifierValue(unitMod, BASE_PCT);
+ float attackPowerMod = GetFlatModifierValue(unitMod, TOTAL_VALUE);
+ float attackPowerMultiplier = GetPctModifierValue(unitMod, TOTAL_PCT) - 1.0f;
SetInt32Value(index, uint32(baseAttackPower)); // UNIT_FIELD_(RANGED)_ATTACK_POWER
SetInt32Value(indexMod, uint32(attackPowerMod)); // UNIT_FIELD_(RANGED)_ATTACK_POWER_MODS
@@ -1023,7 +1025,7 @@ void Creature::UpdateAttackPowerAndDamage(bool ranged)
}
}
-void Creature::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage)
+void Creature::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage) const
{
float variance = 1.0f;
UnitMods unitMod;
@@ -1062,10 +1064,10 @@ void Creature::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized,
float attackPower = GetTotalAttackPowerValue(attType);
float attackSpeedMulti = GetAPMultiplier(attType, normalized);
- float baseValue = GetModifierValue(unitMod, BASE_VALUE) + (attackPower / 14.0f) * variance;
- float basePct = GetModifierValue(unitMod, BASE_PCT) * attackSpeedMulti;
- float totalValue = GetModifierValue(unitMod, TOTAL_VALUE);
- float totalPct = addTotalPct ? GetModifierValue(unitMod, TOTAL_PCT) : 1.0f;
+ float baseValue = GetFlatModifierValue(unitMod, BASE_VALUE) + (attackPower / 14.0f) * variance;
+ float basePct = GetPctModifierValue(unitMod, BASE_PCT) * attackSpeedMulti;
+ float totalValue = GetFlatModifierValue(unitMod, TOTAL_VALUE);
+ float totalPct = addTotalPct ? GetPctModifierValue(unitMod, TOTAL_PCT) : 1.0f;
float dmgMultiplier = GetCreatureTemplate()->ModDamage; // = ModDamage * _GetDamageMod(rank);
minDamage = ((weaponMinDamage + baseValue) * dmgMultiplier * basePct + totalValue) * totalPct;
@@ -1096,7 +1098,7 @@ bool Guardian::UpdateStats(Stats stat)
// value = ((base_value * base_pct) + total_value) * total_pct
float value = GetTotalStatValue(stat);
- ApplyStatBuffMod(stat, m_statFromOwner[stat], false);
+ //ApplyStatBuffMod(stat, m_statFromOwner[stat], false);
float ownersBonus = 0.0f;
Unit* owner = GetOwner();
@@ -1168,7 +1170,7 @@ bool Guardian::UpdateStats(Stats stat)
SetStat(stat, int32(value));
m_statFromOwner[stat] = ownersBonus;
- ApplyStatBuffMod(stat, m_statFromOwner[stat], true);
+ UpdateStatBuffMod(stat);
switch (stat)
{
@@ -1223,11 +1225,11 @@ void Guardian::UpdateArmor()
if (IsPet())
bonus_armor = float(CalculatePct(m_owner->GetArmor(), 35));
- value = GetModifierValue(unitMod, BASE_VALUE);
- value *= GetModifierValue(unitMod, BASE_PCT);
+ value = GetFlatModifierValue(unitMod, BASE_VALUE);
+ value *= GetPctModifierValue(unitMod, BASE_PCT);
value += GetStat(STAT_AGILITY) * 2.0f;
- value += GetModifierValue(unitMod, TOTAL_VALUE) + bonus_armor;
- value *= GetModifierValue(unitMod, TOTAL_PCT);
+ value += GetFlatModifierValue(unitMod, TOTAL_VALUE) + bonus_armor;
+ value *= GetPctModifierValue(unitMod, TOTAL_PCT);
SetArmor(int32(value));
}
@@ -1249,10 +1251,10 @@ void Guardian::UpdateMaxHealth()
default: multiplicator = 10.0f; break;
}
- float value = GetModifierValue(unitMod, BASE_VALUE) + GetCreateHealth();
- value *= GetModifierValue(unitMod, BASE_PCT);
- value += GetModifierValue(unitMod, TOTAL_VALUE) + stamina * multiplicator;
- value *= GetModifierValue(unitMod, TOTAL_PCT);
+ float value = GetFlatModifierValue(unitMod, BASE_VALUE) + GetCreateHealth();
+ value *= GetPctModifierValue(unitMod, BASE_PCT);
+ value += GetFlatModifierValue(unitMod, TOTAL_VALUE) + stamina * multiplicator;
+ value *= GetPctModifierValue(unitMod, TOTAL_PCT);
SetMaxHealth((uint32)value);
}
@@ -1274,10 +1276,10 @@ void Guardian::UpdateMaxPower(Powers power)
default: multiplicator = 15.0f; break;
}
- float value = GetModifierValue(unitMod, BASE_VALUE) + GetCreatePowers(power);
- value *= GetModifierValue(unitMod, BASE_PCT);
- value += GetModifierValue(unitMod, TOTAL_VALUE) + addValue * multiplicator;
- value *= GetModifierValue(unitMod, TOTAL_PCT);
+ float value = GetFlatModifierValue(unitMod, BASE_VALUE) + GetCreatePowers(power);
+ value *= GetPctModifierValue(unitMod, BASE_PCT);
+ value += GetFlatModifierValue(unitMod, TOTAL_VALUE) + addValue * multiplicator;
+ value *= GetPctModifierValue(unitMod, TOTAL_PCT);
SetMaxPower(power, uint32(value));
}
@@ -1357,12 +1359,12 @@ void Guardian::UpdateAttackPowerAndDamage(bool ranged)
}
}
- SetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE, val + bonusAP);
+ SetStatFlatModifier(UNIT_MOD_ATTACK_POWER, BASE_VALUE, val + bonusAP);
//in BASE_VALUE of UNIT_MOD_ATTACK_POWER for creatures we store data of meleeattackpower field in DB
- float base_attPower = GetModifierValue(unitMod, BASE_VALUE) * GetModifierValue(unitMod, BASE_PCT);
- float attPowerMod = GetModifierValue(unitMod, TOTAL_VALUE);
- float attPowerMultiplier = GetModifierValue(unitMod, TOTAL_PCT) - 1.0f;
+ float base_attPower = GetFlatModifierValue(unitMod, BASE_VALUE) * GetPctModifierValue(unitMod, BASE_PCT);
+ float attPowerMod = GetFlatModifierValue(unitMod, TOTAL_VALUE);
+ float attPowerMultiplier = GetPctModifierValue(unitMod, TOTAL_PCT) - 1.0f;
//UNIT_FIELD_(RANGED)_ATTACK_POWER field
SetInt32Value(UNIT_FIELD_ATTACK_POWER, (int32)base_attPower);
@@ -1403,10 +1405,10 @@ void Guardian::UpdateDamagePhysical(WeaponAttackType attType)
float att_speed = float(GetAttackTime(BASE_ATTACK))/1000.0f;
- float base_value = GetModifierValue(unitMod, BASE_VALUE) + GetTotalAttackPowerValue(attType)/ 14.0f * att_speed + bonusDamage;
- float base_pct = GetModifierValue(unitMod, BASE_PCT);
- float total_value = GetModifierValue(unitMod, TOTAL_VALUE);
- float total_pct = GetModifierValue(unitMod, TOTAL_PCT);
+ float base_value = GetFlatModifierValue(unitMod, BASE_VALUE) + GetTotalAttackPowerValue(attType) / 14.0f * att_speed + bonusDamage;
+ float base_pct = GetPctModifierValue(unitMod, BASE_PCT);
+ float total_value = GetFlatModifierValue(unitMod, TOTAL_VALUE);
+ float total_pct = GetPctModifierValue(unitMod, TOTAL_PCT);
float weapon_mindamage = GetWeaponDamageRange(BASE_ATTACK, MINDAMAGE);
float weapon_maxdamage = GetWeaponDamageRange(BASE_ATTACK, MAXDAMAGE);
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index 9bcf71db757..8651d9c24f4 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -307,13 +307,13 @@ Unit::Unit(bool isWorldObject) :
for (uint8 i = 0; i < UNIT_MOD_END; ++i)
{
- m_auraModifiersGroup[i][BASE_VALUE] = 0.0f;
- m_auraModifiersGroup[i][BASE_PCT] = 1.0f;
- m_auraModifiersGroup[i][TOTAL_VALUE] = 0.0f;
- m_auraModifiersGroup[i][TOTAL_PCT] = 1.0f;
+ m_auraFlatModifiersGroup[i][BASE_VALUE] = 0.0f;
+ m_auraFlatModifiersGroup[i][TOTAL_VALUE] = 0.0f;
+ m_auraPctModifiersGroup[i][BASE_PCT] = 1.0f;
+ m_auraPctModifiersGroup[i][TOTAL_PCT] = 1.0f;
}
// implement 50% base damage from offhand
- m_auraModifiersGroup[UNIT_MOD_DAMAGE_OFFHAND][TOTAL_PCT] = 0.5f;
+ m_auraPctModifiersGroup[UNIT_MOD_DAMAGE_OFFHAND][TOTAL_PCT] = 0.5f;
for (uint8 i = 0; i < MAX_ATTACK; ++i)
{
@@ -2313,7 +2313,7 @@ MeleeHitOutcome Unit::RollMeleeOutcomeAgainst(Unit const* victim, WeaponAttackTy
return MELEE_HIT_NORMAL;
}
-uint32 Unit::CalculateDamage(WeaponAttackType attType, bool normalized, bool addTotalPct)
+uint32 Unit::CalculateDamage(WeaponAttackType attType, bool normalized, bool addTotalPct) const
{
float minDamage = 0.0f;
float maxDamage = 0.0f;
@@ -5080,24 +5080,33 @@ int32 Unit::GetMaxNegativeAuraModifierByAffectMask(AuraType auratype, SpellInfo
});
}
-float Unit::GetResistanceBuffMods(SpellSchools school, bool positive) const
+void Unit::UpdateResistanceBuffModsMod(SpellSchools school)
{
- return GetFloatValue(positive ? UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE+school : UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE+school);
-}
+ float modPos = 0.0f;
+ float modNeg = 0.0f;
-void Unit::SetResistanceBuffMods(SpellSchools school, bool positive, float val)
-{
- SetFloatValue(positive ? UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE+school : UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE+school, val);
-}
+ // these auras are always positive
+ modPos = GetMaxPositiveAuraModifierByMiscMask(SPELL_AURA_MOD_RESISTANCE_EXCLUSIVE, 1 << school);
+ modPos += GetTotalAuraModifier(SPELL_AURA_MOD_RESISTANCE, [school](AuraEffect const* aurEff) -> bool
+ {
+ if ((aurEff->GetMiscValue() & (1 << school)) && aurEff->GetAmount() > 0)
+ return true;
+ return false;
+ });
-void Unit::ApplyResistanceBuffModsMod(SpellSchools school, bool positive, float val, bool apply)
-{
- ApplyModSignedFloatValue(positive ? UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE+school : UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE+school, val, apply);
-}
+ modNeg = GetTotalAuraModifier(SPELL_AURA_MOD_RESISTANCE, [school](AuraEffect const* aurEff) -> bool
+ {
+ if ((aurEff->GetMiscValue() & (1 << school)) && aurEff->GetAmount() < 0)
+ return true;
+ return false;
+ });
-void Unit::ApplyResistanceBuffModsPercentMod(SpellSchools school, bool positive, float val, bool apply)
-{
- ApplyPercentModFloatValue(positive ? UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE+school : UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE+school, val, apply);
+ float factor = GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_RESISTANCE_PCT, 1 << school);
+ modPos *= factor;
+ modNeg *= factor;
+
+ SetFloatValue(UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE + school, modPos);
+ SetFloatValue(UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE + school, modNeg);
}
void Unit::InitStatBuffMods()
@@ -5108,15 +5117,63 @@ void Unit::InitStatBuffMods()
SetFloatValue(UNIT_FIELD_NEGSTAT0+i, 0);
}
-void Unit::ApplyStatBuffMod(Stats stat, float val, bool apply)
+void Unit::UpdateStatBuffMod(Stats stat)
{
- ApplyModSignedFloatValue((val > 0 ? UNIT_FIELD_POSSTAT0+stat : UNIT_FIELD_NEGSTAT0+stat), val, apply);
-}
+ float modPos = 0.0f;
+ float modNeg = 0.0f;
+ float factor = 0.0f;
-void Unit::ApplyStatPercentBuffMod(Stats stat, float val, bool apply)
-{
- ApplyPercentModFloatValue(UNIT_FIELD_POSSTAT0+stat, val, apply);
- ApplyPercentModFloatValue(UNIT_FIELD_NEGSTAT0+stat, val, apply);
+ UnitMods const unitMod = static_cast<UnitMods>(UNIT_MOD_STAT_START + stat);
+
+ // includes value from items and enchantments
+ float modValue = GetFlatModifierValue(unitMod, BASE_VALUE);
+ if (modValue > 0.f)
+ modPos += modValue;
+ else
+ modNeg += modValue;
+
+ if (IsGuardian())
+ {
+ modValue = static_cast<Guardian*>(this)->GetBonusStatFromOwner(stat);
+ if (modValue > 0.f)
+ modPos += modValue;
+ else
+ modNeg += modValue;
+ }
+
+ modPos += GetTotalAuraModifier(SPELL_AURA_MOD_STAT, [stat](AuraEffect const* aurEff) -> bool
+ {
+ if ((aurEff->GetMiscValue() < 0 || aurEff->GetMiscValue() == stat) && aurEff->GetAmount() > 0)
+ return true;
+ return false;
+ });
+
+ modNeg += GetTotalAuraModifier(SPELL_AURA_MOD_STAT, [stat](AuraEffect const* aurEff) -> bool
+ {
+ if ((aurEff->GetMiscValue() < 0 || aurEff->GetMiscValue() == stat) && aurEff->GetAmount() < 0)
+ return true;
+ return false;
+ });
+
+ factor = GetTotalAuraMultiplier(SPELL_AURA_MOD_PERCENT_STAT, [stat](AuraEffect const* aurEff) -> bool
+ {
+ if (aurEff->GetMiscValue() == -1 || aurEff->GetMiscValue() == stat)
+ return true;
+ return false;
+ });
+
+ factor *= GetTotalAuraMultiplier(SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE, [stat](AuraEffect const* aurEff) -> bool
+ {
+ if (aurEff->GetMiscValue() == -1 || aurEff->GetMiscValue() == stat)
+ return true;
+ return false;
+ });
+
+ modPos *= factor;
+ modNeg *= factor;
+
+ SetFloatValue(UNIT_FIELD_POSSTAT0 + stat, modPos);
+ SetFloatValue(UNIT_FIELD_NEGSTAT0 + stat, modNeg);
}
void Unit::_RegisterDynObject(DynamicObject* dynObj)
@@ -9068,15 +9125,6 @@ int32 Unit::ModifyPower(Powers power, int32 dVal)
return gain;
}
-// returns negative amount on power reduction
-int32 Unit::ModifyPowerPct(Powers power, float pct, bool apply)
-{
- float amount = (float)GetMaxPower(power);
- ApplyPercentModFloatVar(amount, pct, apply);
-
- return ModifyPower(power, (int32)amount - (int32)GetMaxPower(power));
-}
-
uint32 Unit::GetAttackTime(WeaponAttackType att) const
{
float f_BaseAttackTime = GetFloatValue(UNIT_FIELD_BASEATTACKTIME + att) / m_modAttackSpeedPct[att];
@@ -10072,30 +10120,98 @@ bool Unit::IsInDisallowedMountForm() const
######## ########
#######################################*/
-bool Unit::HandleStatModifier(UnitMods unitMod, UnitModifierType modifierType, float amount, bool apply)
+void Unit::HandleStatFlatModifier(UnitMods unitMod, UnitModifierFlatType modifierType, float amount, bool apply)
{
- if (unitMod >= UNIT_MOD_END || modifierType >= MODIFIER_TYPE_END)
+ if (unitMod >= UNIT_MOD_END || modifierType >= MODIFIER_TYPE_FLAT_END)
{
- TC_LOG_ERROR("entities.unit", "ERROR in HandleStatModifier(): non-existing UnitMods or wrong UnitModifierType!");
- return false;
+ TC_LOG_ERROR("entities.unit", "ERROR in HandleStatFlatModifier(): non-existing UnitMods or wrong UnitModifierType!");
+ return;
}
+ if (!amount)
+ return;
+
switch (modifierType)
{
case BASE_VALUE:
case TOTAL_VALUE:
- m_auraModifiersGroup[unitMod][modifierType] += apply ? amount : -amount;
+ m_auraFlatModifiersGroup[unitMod][modifierType] += apply ? amount : -amount;
+ break;
+ default:
break;
+ }
+
+ UpdateUnitMod(unitMod);
+}
+
+void Unit::ApplyStatPctModifier(UnitMods unitMod, UnitModifierPctType modifierType, float pct)
+{
+ if (unitMod >= UNIT_MOD_END || modifierType >= MODIFIER_TYPE_PCT_END)
+ {
+ TC_LOG_ERROR("entities.unit", "ERROR in ApplyStatPctModifier(): non-existing UnitMods or wrong UnitModifierType!");
+ return;
+ }
+
+ if (!pct)
+ return;
+
+ switch (modifierType)
+ {
case BASE_PCT:
case TOTAL_PCT:
- ApplyPercentModFloatVar(m_auraModifiersGroup[unitMod][modifierType], amount, apply);
+ AddPct(m_auraPctModifiersGroup[unitMod][modifierType], pct);
break;
default:
break;
}
+ UpdateUnitMod(unitMod);
+}
+
+void Unit::SetStatFlatModifier(UnitMods unitMod, UnitModifierFlatType modifierType, float val)
+{
+ if (m_auraFlatModifiersGroup[unitMod][modifierType] == val)
+ return;
+
+ m_auraFlatModifiersGroup[unitMod][modifierType] = val;
+ UpdateUnitMod(unitMod);
+}
+
+void Unit::SetStatPctModifier(UnitMods unitMod, UnitModifierPctType modifierType, float val)
+{
+ if (m_auraPctModifiersGroup[unitMod][modifierType] == val)
+ return;
+
+ m_auraPctModifiersGroup[unitMod][modifierType] = val;
+ UpdateUnitMod(unitMod);
+}
+
+float Unit::GetFlatModifierValue(UnitMods unitMod, UnitModifierFlatType modifierType) const
+{
+ if (unitMod >= UNIT_MOD_END || modifierType >= MODIFIER_TYPE_FLAT_END)
+ {
+ TC_LOG_ERROR("entities.unit", "attempt to access non-existing modifier value from UnitMods!");
+ return 0.0f;
+ }
+
+ return m_auraFlatModifiersGroup[unitMod][modifierType];
+}
+
+float Unit::GetPctModifierValue(UnitMods unitMod, UnitModifierPctType modifierType) const
+{
+ if (unitMod >= UNIT_MOD_END || modifierType >= MODIFIER_TYPE_PCT_END)
+ {
+ TC_LOG_ERROR("entities.unit", "attempt to access non-existing modifier value from UnitMods!");
+ return 0.0f;
+ }
+
+ return m_auraPctModifiersGroup[unitMod][modifierType];
+}
+
+void Unit::UpdateUnitMod(UnitMods unitMod)
+{
if (!CanModifyStats())
- return false;
+ return;
switch (unitMod)
{
@@ -10133,36 +10249,108 @@ bool Unit::HandleStatModifier(UnitMods unitMod, UnitModifierType modifierType, f
default:
break;
}
+}
+
+bool Unit::CheckAttackFitToAuraRequirement(WeaponAttackType attackType, AuraEffect const* aurEff) const
+{
+ // only players have item requirements
+ if (GetTypeId() != TYPEID_PLAYER)
+ return true;
+
+ SpellInfo const* spellInfo = aurEff->GetSpellInfo();
+ if (spellInfo->EquippedItemClass == -1)
+ return true;
+
+ Item* item = ToPlayer()->GetWeaponForAttack(attackType, true);
+ if (!item || !item->IsFitToSpellRequirements(spellInfo))
+ return false;
return true;
}
-float Unit::GetModifierValue(UnitMods unitMod, UnitModifierType modifierType) const
+void Unit::UpdateDamageDoneMods(WeaponAttackType attackType)
{
- if (unitMod >= UNIT_MOD_END || modifierType >= MODIFIER_TYPE_END)
+ UnitMods unitMod;
+ switch (attackType)
{
- TC_LOG_ERROR("entities.unit", "attempt to access non-existing modifier value from UnitMods!");
- return 0.0f;
+ case BASE_ATTACK:
+ unitMod = UNIT_MOD_DAMAGE_MAINHAND;
+ break;
+ case OFF_ATTACK:
+ unitMod = UNIT_MOD_DAMAGE_OFFHAND;
+ break;
+ case RANGED_ATTACK:
+ unitMod = UNIT_MOD_DAMAGE_RANGED;
+ break;
+ default:
+ ABORT();
+ break;
}
- if (modifierType == TOTAL_PCT && m_auraModifiersGroup[unitMod][modifierType] <= 0.0f)
- return 0.0f;
+ float amount = GetTotalAuraModifier(SPELL_AURA_MOD_DAMAGE_DONE, std::bind(&Unit::CheckAttackFitToAuraRequirement, this, attackType, std::placeholders::_1));
+
+ SetStatFlatModifier(unitMod, TOTAL_VALUE, amount);
+}
+
+void Unit::UpdateAllDamageDoneMods()
+{
+ for (uint8 i = BASE_ATTACK; i < MAX_ATTACK; ++i)
+ UpdateDamageDoneMods(WeaponAttackType(i));
+}
+
+void Unit::UpdateDamagePctDoneMods(WeaponAttackType attackType)
+{
+ float factor;
+ UnitMods unitMod;
+ switch (attackType)
+ {
+ case BASE_ATTACK:
+ factor = 1.0f;
+ unitMod = UNIT_MOD_DAMAGE_MAINHAND;
+ break;
+ case OFF_ATTACK:
+ // off hand has 50% penalty
+ factor = 0.5f;
+ unitMod = UNIT_MOD_DAMAGE_OFFHAND;
+ break;
+ case RANGED_ATTACK:
+ factor = 1.0f;
+ unitMod = UNIT_MOD_DAMAGE_RANGED;
+ break;
+ default:
+ ABORT();
+ break;
+ }
- return m_auraModifiersGroup[unitMod][modifierType];
+ factor *= GetTotalAuraMultiplier(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE, [attackType, this](AuraEffect const* aurEff) -> bool
+ {
+ if (!(aurEff->GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL))
+ return false;
+
+ return CheckAttackFitToAuraRequirement(attackType, aurEff);
+ });
+
+ if (attackType == OFF_ATTACK)
+ factor *= GetTotalAuraMultiplier(SPELL_AURA_MOD_OFFHAND_DAMAGE_PCT, std::bind(&Unit::CheckAttackFitToAuraRequirement, this, attackType, std::placeholders::_1));
+
+ SetStatPctModifier(unitMod, TOTAL_PCT, factor);
+}
+
+void Unit::UpdateAllDamagePctDoneMods()
+{
+ for (uint8 i = BASE_ATTACK; i < MAX_ATTACK; ++i)
+ UpdateDamagePctDoneMods(WeaponAttackType(i));
}
float Unit::GetTotalStatValue(Stats stat) const
{
UnitMods unitMod = UnitMods(UNIT_MOD_STAT_START + stat);
- if (m_auraModifiersGroup[unitMod][TOTAL_PCT] <= 0.0f)
- return 0.0f;
-
// value = ((base_value * base_pct) + total_value) * total_pct
- float value = m_auraModifiersGroup[unitMod][BASE_VALUE] + GetCreateStat(stat);
- value *= m_auraModifiersGroup[unitMod][BASE_PCT];
- value += m_auraModifiersGroup[unitMod][TOTAL_VALUE];
- value *= m_auraModifiersGroup[unitMod][TOTAL_PCT];
+ float value = GetFlatModifierValue(unitMod, BASE_VALUE) + GetCreateStat(stat);
+ value *= GetPctModifierValue(unitMod, BASE_PCT);
+ value += GetFlatModifierValue(unitMod, TOTAL_VALUE);
+ value *= GetPctModifierValue(unitMod, TOTAL_PCT);
return value;
}
@@ -10175,13 +10363,10 @@ float Unit::GetTotalAuraModValue(UnitMods unitMod) const
return 0.0f;
}
- if (m_auraModifiersGroup[unitMod][TOTAL_PCT] <= 0.0f)
- return 0.0f;
-
- float value = m_auraModifiersGroup[unitMod][BASE_VALUE];
- value *= m_auraModifiersGroup[unitMod][BASE_PCT];
- value += m_auraModifiersGroup[unitMod][TOTAL_VALUE];
- value *= m_auraModifiersGroup[unitMod][TOTAL_PCT];
+ float value = GetFlatModifierValue(unitMod, BASE_VALUE);
+ value *= GetPctModifierValue(unitMod, BASE_PCT);
+ value += GetFlatModifierValue(unitMod, TOTAL_VALUE);
+ value *= GetPctModifierValue(unitMod, TOTAL_PCT);
return value;
}
@@ -11405,28 +11590,41 @@ Unit* Unit::SelectNearbyTarget(Unit* exclude, float dist) const
return Trinity::Containers::SelectRandomContainerElement(targets);
}
+void ApplyPercentModFloatVar(float& var, float val, bool apply)
+{
+ var *= (apply ? (100.0f + val) / 100.0f : 100.0f / (100.0f + val));
+}
+
void Unit::ApplyAttackTimePercentMod(WeaponAttackType att, float val, bool apply)
{
+ float amount = GetFloatValue(UNIT_FIELD_BASEATTACKTIME + att);
+
float remainingTimePct = (float)m_attackTimer[att] / (GetAttackTime(att) * m_modAttackSpeedPct[att]);
- if (val > 0)
+ if (val > 0.f)
{
ApplyPercentModFloatVar(m_modAttackSpeedPct[att], val, !apply);
- ApplyPercentModFloatValue(UNIT_FIELD_BASEATTACKTIME+att, val, !apply);
+ ApplyPercentModFloatVar(amount, val, !apply);
}
else
{
ApplyPercentModFloatVar(m_modAttackSpeedPct[att], -val, apply);
- ApplyPercentModFloatValue(UNIT_FIELD_BASEATTACKTIME+att, -val, apply);
+ ApplyPercentModFloatVar(amount, -val, apply);
}
+
+ SetFloatValue(UNIT_FIELD_BASEATTACKTIME + att, amount);
m_attackTimer[att] = uint32(GetAttackTime(att) * m_modAttackSpeedPct[att] * remainingTimePct);
}
void Unit::ApplyCastTimePercentMod(float val, bool apply)
{
- if (val > 0)
- ApplyPercentModFloatValue(UNIT_MOD_CAST_SPEED, val, !apply);
+ float amount = GetFloatValue(UNIT_MOD_CAST_SPEED);
+
+ if (val > 0.f)
+ ApplyPercentModFloatVar(amount, val, !apply);
else
- ApplyPercentModFloatValue(UNIT_MOD_CAST_SPEED, -val, apply);
+ ApplyPercentModFloatVar(amount, -val, apply);
+
+ SetFloatValue(UNIT_MOD_CAST_SPEED, amount);
}
uint32 Unit::GetCastingTimeForBonus(SpellInfo const* spellProto, DamageEffectType damagetype, uint32 CastingTime) const
@@ -11581,7 +11779,7 @@ float Unit::CalculateDefaultCoefficient(SpellInfo const* spellInfo, DamageEffect
return (CastingTime / 3500.0f) * DotFactor;
}
-float Unit::GetAPMultiplier(WeaponAttackType attType, bool normalized)
+float Unit::GetAPMultiplier(WeaponAttackType attType, bool normalized) const
{
if (GetTypeId() != TYPEID_PLAYER || (IsInFeralForm() && !normalized))
return GetAttackTime(attType) / 1000.0f;
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index 646595d2808..93dcc590318 100644
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -405,13 +405,18 @@ typedef std::vector<DispelableAura> DispelChargesList;
typedef std::unordered_multimap<uint32 /*type*/, uint32 /*spellId*/> SpellImmuneContainer;
-enum UnitModifierType
+enum UnitModifierFlatType
{
BASE_VALUE = 0,
- BASE_PCT = 1,
- TOTAL_VALUE = 2,
- TOTAL_PCT = 3,
- MODIFIER_TYPE_END = 4
+ TOTAL_VALUE = 1,
+ MODIFIER_TYPE_FLAT_END = 2
+};
+
+enum UnitModifierPctType
+{
+ BASE_PCT = 0,
+ TOTAL_PCT = 1,
+ MODIFIER_TYPE_PCT_END = 2
};
enum WeaponDamageRange
@@ -1408,7 +1413,6 @@ class TC_GAME_API Unit : public WorldObject
void SetMaxPower(Powers power, uint32 val);
// returns the change in power
int32 ModifyPower(Powers power, int32 val);
- int32 ModifyPowerPct(Powers power, float pct, bool apply = true);
uint32 GetAttackTime(WeaponAttackType att) const;
void SetAttackTime(WeaponAttackType att, uint32 val) { SetFloatValue(UNIT_FIELD_BASEATTACKTIME+att, val*m_modAttackSpeedPct[att]); }
@@ -1864,13 +1868,9 @@ class TC_GAME_API Unit : public WorldObject
int32 GetMaxPositiveAuraModifierByAffectMask(AuraType auratype, SpellInfo const* affectedSpell) const;
int32 GetMaxNegativeAuraModifierByAffectMask(AuraType auratype, SpellInfo const* affectedSpell) const;
- float GetResistanceBuffMods(SpellSchools school, bool positive) const;
- void SetResistanceBuffMods(SpellSchools school, bool positive, float val);
- void ApplyResistanceBuffModsMod(SpellSchools school, bool positive, float val, bool apply);
- void ApplyResistanceBuffModsPercentMod(SpellSchools school, bool positive, float val, bool apply);
+ void UpdateResistanceBuffModsMod(SpellSchools school);
void InitStatBuffMods();
- void ApplyStatBuffMod(Stats stat, float val, bool apply);
- void ApplyStatPercentBuffMod(Stats stat, float val, bool apply);
+ void UpdateStatBuffMod(Stats stat);
void SetCreateStat(Stats stat, float val) { m_createStats[stat] = val; }
void SetCreateHealth(uint32 val) { SetUInt32Value(UNIT_FIELD_BASE_HEALTH, val); }
uint32 GetCreateHealth() const { return GetUInt32Value(UNIT_FIELD_BASE_HEALTH); }
@@ -1930,9 +1930,25 @@ class TC_GAME_API Unit : public WorldObject
EventProcessor m_Events;
// stat system
- bool HandleStatModifier(UnitMods unitMod, UnitModifierType modifierType, float amount, bool apply);
- void SetModifierValue(UnitMods unitMod, UnitModifierType modifierType, float value) { m_auraModifiersGroup[unitMod][modifierType] = value; }
- float GetModifierValue(UnitMods unitMod, UnitModifierType modifierType) const;
+ void HandleStatFlatModifier(UnitMods unitMod, UnitModifierFlatType modifierType, float amount, bool apply);
+ void ApplyStatPctModifier(UnitMods unitMod, UnitModifierPctType modifierType, float amount);
+
+ void SetStatFlatModifier(UnitMods unitMod, UnitModifierFlatType modifierType, float val);
+ void SetStatPctModifier(UnitMods unitMod, UnitModifierPctType modifierType, float val);
+
+ float GetFlatModifierValue(UnitMods unitMod, UnitModifierFlatType modifierType) const;
+ float GetPctModifierValue(UnitMods unitMod, UnitModifierPctType modifierType) const;
+
+ void UpdateUnitMod(UnitMods unitMod);
+
+ bool CheckAttackFitToAuraRequirement(WeaponAttackType attackType, AuraEffect const* aurEff) const;
+
+ virtual void UpdateDamageDoneMods(WeaponAttackType attackType);
+ void UpdateAllDamageDoneMods();
+
+ void UpdateDamagePctDoneMods(WeaponAttackType attackType);
+ void UpdateAllDamagePctDoneMods();
+
float GetTotalStatValue(Stats stat) const;
float GetTotalAuraModValue(UnitMods unitMod) const;
SpellSchools GetSpellSchoolByAuraGroup(UnitMods unitMod) const;
@@ -1952,9 +1968,9 @@ class TC_GAME_API Unit : public WorldObject
float GetTotalAttackPowerValue(WeaponAttackType attType) const;
float GetWeaponDamageRange(WeaponAttackType attType, WeaponDamageRange type) const;
void SetBaseWeaponDamage(WeaponAttackType attType, WeaponDamageRange damageRange, float value) { m_weaponDamage[attType][damageRange] = value; }
- virtual void CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage) = 0;
- uint32 CalculateDamage(WeaponAttackType attType, bool normalized, bool addTotalPct);
- float GetAPMultiplier(WeaponAttackType attType, bool normalized);
+ virtual void CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage) const = 0;
+ uint32 CalculateDamage(WeaponAttackType attType, bool normalized, bool addTotalPct) const;
+ float GetAPMultiplier(WeaponAttackType attType, bool normalized) const;
bool isInFrontInMap(Unit const* target, float distance, float arc = float(M_PI)) const;
bool isInBackInMap(Unit const* target, float distance, float arc = float(M_PI)) const;
@@ -2264,7 +2280,8 @@ class TC_GAME_API Unit : public WorldObject
AuraStateAurasMap m_auraStateAuras; // Used for improve performance of aura state checks on aura apply/remove
uint32 m_interruptMask;
- float m_auraModifiersGroup[UNIT_MOD_END][MODIFIER_TYPE_END];
+ float m_auraFlatModifiersGroup[UNIT_MOD_END][MODIFIER_TYPE_FLAT_END];
+ float m_auraPctModifiersGroup[UNIT_MOD_END][MODIFIER_TYPE_PCT_END];
float m_weaponDamage[MAX_ATTACK][2];
bool m_canModifyStats;
VisibleAuraMap m_visibleAuras;
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
index 07180bc8320..d3b40614fcd 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
@@ -207,7 +207,7 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]=
&AuraEffect::HandleModMechanicImmunityMask, //147 SPELL_AURA_MECHANIC_IMMUNITY_MASK
&AuraEffect::HandleAuraRetainComboPoints, //148 SPELL_AURA_RETAIN_COMBO_POINTS
&AuraEffect::HandleNoImmediateEffect, //149 SPELL_AURA_REDUCE_PUSHBACK
- &AuraEffect::HandleShieldBlockValue, //150 SPELL_AURA_MOD_SHIELD_BLOCKVALUE_PCT
+ &AuraEffect::HandleShieldBlockValuePercent, //150 SPELL_AURA_MOD_SHIELD_BLOCKVALUE_PCT
&AuraEffect::HandleAuraTrackStealthed, //151 SPELL_AURA_TRACK_STEALTHED
&AuraEffect::HandleNoImmediateEffect, //152 SPELL_AURA_MOD_DETECTED_RANGE implemented in Creature::GetAttackDistance
&AuraEffect::HandleNoImmediateEffect, //153 SPELL_AURA_SPLIT_DAMAGE_FLAT
@@ -339,7 +339,7 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]=
&AuraEffect::HandleNoImmediateEffect, //279 SPELL_AURA_INITIALIZE_IMAGES
&AuraEffect::HandleNoImmediateEffect, //280 SPELL_AURA_MOD_TARGET_ARMOR_PCT
&AuraEffect::HandleNoImmediateEffect, //281 SPELL_AURA_MOD_HONOR_GAIN_PCT implemented in Player::RewardHonor
- &AuraEffect::HandleAuraIncreaseBaseHealthPercent, //282 SPELL_AURA_INCREASE_BASE_HEALTH_PERCENT
+ &AuraEffect::HandleAuraIncreaseBaseHealthPercent, //282 SPELL_AURA_MOD_BASE_HEALTH_PCT
&AuraEffect::HandleNoImmediateEffect, //283 SPELL_AURA_MOD_HEALING_RECEIVED implemented in Unit::SpellHealingBonus
&AuraEffect::HandleAuraLinked, //284 SPELL_AURA_LINKED
&AuraEffect::HandleAuraModAttackPowerOfArmor, //285 SPELL_AURA_MOD_ATTACK_POWER_OF_ARMOR implemented in Player::UpdateAttackPowerAndDamage
@@ -2129,7 +2129,7 @@ void AuraEffect::HandleAuraModScale(AuraApplication const* aurApp, uint8 mode, b
Unit* target = aurApp->GetTarget();
float scale = target->GetObjectScale();
- ApplyPercentModFloatVar(scale, float(GetAmount()), apply);
+ scale += CalculatePct(1.0f, apply ? GetAmount() : -GetAmount());
target->SetObjectScale(scale);
}
@@ -2306,11 +2306,15 @@ void AuraEffect::HandleAuraModDisarm(AuraApplication const* aurApp, uint8 mode,
Player* player = target->ToPlayer();
if (Item* item = player->GetItemByPos(INVENTORY_SLOT_BAG_0, slot))
{
- uint8 attacktype = Player::GetAttackBySlot(slot);
+ WeaponAttackType const attackType = Player::GetAttackBySlot(slot);
player->ApplyItemDependentAuras(item, !apply);
- if (attacktype < MAX_ATTACK)
+ if (attackType != MAX_ATTACK)
+ {
player->_ApplyWeaponDamage(slot, item->GetTemplate(), NULL, !apply);
+ if (!apply) // apply case already handled on item dependent aura removal (if any)
+ player->UpdateWeaponDependentAuras(attackType);
+ }
}
}
@@ -2716,9 +2720,19 @@ void AuraEffect::HandleModThreat(AuraApplication const* aurApp, uint8 mode, bool
return;
Unit* target = aurApp->GetTarget();
- for (int8 i = 0; i < MAX_SPELL_SCHOOL; ++i)
+ for (uint8 i = 0; i < MAX_SPELL_SCHOOL; ++i)
+ {
if (GetMiscValue() & (1 << i))
- ApplyPercentModFloatVar(target->m_threatModifier[i], float(GetAmount()), apply);
+ {
+ if (apply)
+ AddPct(target->m_threatModifier[i], GetAmount());
+ else
+ {
+ float amount = target->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_THREAT, 1 << i);
+ target->m_threatModifier[i] = amount;
+ }
+ }
+ }
}
void AuraEffect::HandleAuraModTotalThreat(AuraApplication const* aurApp, uint8 mode, bool apply) const
@@ -3189,17 +3203,17 @@ void AuraEffect::HandleAuraModResistanceExclusive(AuraApplication const* aurApp,
Unit* target = aurApp->GetTarget();
- for (int8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL; x++)
+ for (uint8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL; ++x)
{
- if (GetMiscValue() & int32(1<<x))
+ if (GetMiscValue() & (1 << x))
{
- int32 amount = target->GetMaxPositiveAuraModifierByMiscMask(SPELL_AURA_MOD_RESISTANCE_EXCLUSIVE, 1<<x, this);
+ int32 amount = target->GetMaxPositiveAuraModifierByMiscMask(SPELL_AURA_MOD_RESISTANCE_EXCLUSIVE, 1 << x, this);
if (amount < GetAmount())
{
float value = float(GetAmount() - amount);
- target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), BASE_VALUE, value, apply);
- if (target->GetTypeId() == TYPEID_PLAYER)
- target->ApplyResistanceBuffModsMod(SpellSchools(x), aurApp->IsPositive(), value, apply);
+ target->HandleStatFlatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), BASE_VALUE, value, apply);
+ if (target->GetTypeId() == TYPEID_PLAYER || target->IsPet())
+ target->UpdateResistanceBuffModsMod(SpellSchools(x));
}
}
}
@@ -3212,13 +3226,13 @@ void AuraEffect::HandleAuraModResistance(AuraApplication const* aurApp, uint8 mo
Unit* target = aurApp->GetTarget();
- for (int8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL; x++)
+ for (uint8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL; ++x)
{
- if (GetMiscValue() & int32(1<<x))
+ if (GetMiscValue() & (1 << x))
{
- target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), TOTAL_VALUE, float(GetAmount()), apply);
+ target->HandleStatFlatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), TOTAL_VALUE, float(GetAmount()), apply);
if (target->GetTypeId() == TYPEID_PLAYER || target->IsPet())
- target->ApplyResistanceBuffModsMod(SpellSchools(x), GetAmount() > 0, (float)GetAmount(), apply);
+ target->UpdateResistanceBuffModsMod(SpellSchools(x));
}
}
}
@@ -3235,14 +3249,30 @@ void AuraEffect::HandleAuraModBaseResistancePCT(AuraApplication const* aurApp, u
{
//pets only have base armor
if (target->IsPet() && (GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL))
- target->HandleStatModifier(UNIT_MOD_ARMOR, BASE_PCT, float(GetAmount()), apply);
+ {
+ if (apply)
+ target->ApplyStatPctModifier(UNIT_MOD_ARMOR, BASE_PCT, float(GetAmount()));
+ else
+ {
+ float amount = target->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_BASE_RESISTANCE_PCT, SPELL_SCHOOL_MASK_NORMAL);
+ target->SetStatPctModifier(UNIT_MOD_ARMOR, BASE_PCT, amount);
+ }
+ }
}
else
{
- for (int8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL; x++)
+ for (uint8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL; ++x)
{
- if (GetMiscValue() & int32(1<<x))
- target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), BASE_PCT, float(GetAmount()), apply);
+ if (GetMiscValue() & (1 << x))
+ {
+ if (apply)
+ target->ApplyStatPctModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), BASE_PCT, float(GetAmount()));
+ else
+ {
+ float amount = target->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_BASE_RESISTANCE_PCT, 1 << x);
+ target->SetStatPctModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), BASE_PCT, amount);
+ }
+ }
}
}
}
@@ -3253,29 +3283,18 @@ void AuraEffect::HandleModResistancePercent(AuraApplication const* aurApp, uint8
return;
Unit* target = aurApp->GetTarget();
- int32 spellGroupVal = target->GetHighestExclusiveSameEffectSpellGroupValue(this, SPELL_AURA_MOD_RESISTANCE_PCT);
- if (abs(spellGroupVal) >= abs(GetAmount()))
- return;
- for (int8 i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; i++)
+ for (uint8 i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; ++i)
{
- if (GetMiscValue() & int32(1<<i))
+ if (GetMiscValue() & (1 << i))
{
- if (spellGroupVal)
- {
- target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_PCT, (float)spellGroupVal, !apply);
- if (target->GetTypeId() == TYPEID_PLAYER || target->IsPet())
- {
- target->ApplyResistanceBuffModsPercentMod(SpellSchools(i), true, (float)spellGroupVal, !apply);
- target->ApplyResistanceBuffModsPercentMod(SpellSchools(i), false, (float)spellGroupVal, !apply);
- }
- }
- target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_PCT, float(GetAmount()), apply);
+ float amount = target->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_RESISTANCE_PCT, 1 << i);
+ if (target->GetPctModifierValue(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_PCT) == amount)
+ continue;
+
+ target->SetStatPctModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_PCT, amount);
if (target->GetTypeId() == TYPEID_PLAYER || target->IsPet())
- {
- target->ApplyResistanceBuffModsPercentMod(SpellSchools(i), true, (float)GetAmount(), apply);
- target->ApplyResistanceBuffModsPercentMod(SpellSchools(i), false, (float)GetAmount(), apply);
- }
+ target->UpdateResistanceBuffModsMod(SpellSchools(i));
}
}
}
@@ -3290,15 +3309,15 @@ void AuraEffect::HandleModBaseResistance(AuraApplication const* aurApp, uint8 mo
// only players have base stats
if (target->GetTypeId() != TYPEID_PLAYER)
{
- //only pets have base stats
+ //pets only have base armor
if (target->IsPet() && (GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL))
- target->HandleStatModifier(UNIT_MOD_ARMOR, TOTAL_VALUE, float(GetAmount()), apply);
+ target->HandleStatFlatModifier(UNIT_MOD_ARMOR, TOTAL_VALUE, float(GetAmount()), apply);
}
else
{
- for (int i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; i++)
- if (GetMiscValue() & (1<<i))
- target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_VALUE, float(GetAmount()), apply);
+ for (uint8 i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; ++i)
+ if (GetMiscValue() & (1 << i))
+ target->HandleStatFlatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_VALUE, float(GetAmount()), apply);
}
}
@@ -3340,22 +3359,21 @@ void AuraEffect::HandleAuraModStat(AuraApplication const* aurApp, uint8 mode, bo
if (abs(spellGroupVal) >= abs(GetAmount()))
return;
- for (int32 i = STAT_STRENGTH; i < MAX_STATS; i++)
+ for (uint32 i = STAT_STRENGTH; i < MAX_STATS; ++i)
{
// -1 or -2 is all stats (misc < -2 checked in function beginning)
if (GetMiscValue() < 0 || GetMiscValue() == i)
{
if (spellGroupVal)
{
- target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_VALUE, float(spellGroupVal), !apply);
+ target->HandleStatFlatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_VALUE, float(spellGroupVal), !apply);
if (target->GetTypeId() == TYPEID_PLAYER || target->IsPet())
- target->ApplyStatBuffMod(Stats(i), float(spellGroupVal), !apply);
+ target->UpdateStatBuffMod(Stats(i));
}
- //target->ApplyStatMod(Stats(i), m_amount, apply);
- target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_VALUE, float(GetAmount()), apply);
+ target->HandleStatFlatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_VALUE, float(GetAmount()), apply);
if (target->GetTypeId() == TYPEID_PLAYER || target->IsPet())
- target->ApplyStatBuffMod(Stats(i), (float)GetAmount(), apply);
+ target->UpdateStatBuffMod(Stats(i));
}
}
}
@@ -3377,10 +3395,23 @@ void AuraEffect::HandleModPercentStat(AuraApplication const* aurApp, uint8 mode,
if (target->GetTypeId() != TYPEID_PLAYER)
return;
- for (int32 i = STAT_STRENGTH; i < MAX_STATS; ++i)
+ for (uint32 i = STAT_STRENGTH; i < MAX_STATS; ++i)
{
if (GetMiscValue() == i || GetMiscValue() == -1)
- target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), BASE_PCT, float(m_amount), apply);
+ {
+ if (apply)
+ target->ApplyStatPctModifier(UnitMods(UNIT_MOD_STAT_START + i), BASE_PCT, float(m_amount));
+ else
+ {
+ float amount = target->GetTotalAuraMultiplier(SPELL_AURA_MOD_PERCENT_STAT, [i](AuraEffect const* aurEff) -> bool
+ {
+ if (aurEff->GetMiscValue() == i || aurEff->GetMiscValue() == -1)
+ return true;
+ return false;
+ });
+ target->SetStatPctModifier(UnitMods(UNIT_MOD_STAT_START + i), BASE_PCT, amount);
+ }
+ }
}
}
@@ -3470,51 +3501,34 @@ void AuraEffect::HandleModTotalPercentStat(AuraApplication const* aurApp, uint8
}
Unit* target = aurApp->GetTarget();
- int32 spellGroupVal = target->GetHighestExclusiveSameEffectSpellGroupValue(this, SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE, true, -1);
- if (abs(spellGroupVal) >= abs(GetAmount()))
- return;
-
- if (spellGroupVal)
- {
- for (int32 i = STAT_STRENGTH; i < MAX_STATS; i++)
- {
- if (GetMiscValue() == i || GetMiscValue() == -1) // affect the same stats
- {
- target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_PCT, float(spellGroupVal), !apply);
- if (target->GetTypeId() == TYPEID_PLAYER || target->IsPet())
- target->ApplyStatPercentBuffMod(Stats(i), float(spellGroupVal), !apply);
- }
- }
- }
// save current health state
float healthPct = target->GetHealthPct();
bool alive = target->IsAlive();
- for (int32 i = STAT_STRENGTH; i < MAX_STATS; i++)
+ for (uint32 i = STAT_STRENGTH; i < MAX_STATS; ++i)
{
- if (GetMiscValue() == i || GetMiscValue() == -1)
+ if (GetMiscValue() == i || GetMiscValue() == -1) // affect the same stats
{
- int32 spellGroupVal2 = target->GetHighestExclusiveSameEffectSpellGroupValue(this, SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE, true, i);
- if (abs(spellGroupVal2) >= abs(GetAmount()))
- continue;
-
- if (spellGroupVal2)
+ float amount = target->GetTotalAuraMultiplier(SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE, [i](AuraEffect const* aurEff) -> bool
{
- target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_PCT, float(spellGroupVal2), !apply);
- if (target->GetTypeId() == TYPEID_PLAYER || target->IsPet())
- target->ApplyStatPercentBuffMod(Stats(i), float(spellGroupVal2), !apply);
- }
+ if (aurEff->GetMiscValue() == i || aurEff->GetMiscValue() == -1)
+ return true;
+ return false;
+ });
- target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_PCT, float(GetAmount()), apply);
+ if (target->GetPctModifierValue(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_PCT) == amount)
+ continue;
+
+ target->SetStatPctModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_PCT, amount);
if (target->GetTypeId() == TYPEID_PLAYER || target->IsPet())
- target->ApplyStatPercentBuffMod(Stats(i), float(GetAmount()), apply);
+ target->UpdateStatBuffMod(Stats(i));
}
}
- // recalculate current HP/MP after applying aura modifications (only for spells with SPELL_ATTR0_UNK4 0x00000010 flag)
+ // recalculate current HP/MP after applying aura modifications (only for spells with SPELL_ATTR0_ABILITY 0x00000010 flag)
// this check is total bullshit i think
- if (GetMiscValue() == STAT_STAMINA && m_spellInfo->HasAttribute(SPELL_ATTR0_ABILITY))
+ if ((GetMiscValue() == STAT_STAMINA || GetMiscValue() == - 1) && m_spellInfo->HasAttribute(SPELL_ATTR0_ABILITY))
target->SetHealth(std::max<uint32>(uint32(healthPct * target->GetMaxHealth() * 0.01f), (alive ? 1 : 0)));
}
@@ -3603,7 +3617,7 @@ void AuraEffect::HandleAuraModIncreaseHealth(AuraApplication const* aurApp, uint
if (apply)
{
- target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(GetAmount()), apply);
+ target->HandleStatFlatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(GetAmount()), apply);
target->ModifyHealth(GetAmount());
}
else
@@ -3613,7 +3627,7 @@ void AuraEffect::HandleAuraModIncreaseHealth(AuraApplication const* aurApp, uint
int32 value = std::min<int32>(target->GetHealth() - 1, GetAmount());
target->ModifyHealth(-value);
}
- target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(GetAmount()), apply);
+ target->HandleStatFlatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(GetAmount()), apply);
}
}
@@ -3626,7 +3640,7 @@ void AuraEffect::HandleAuraModIncreaseMaxHealth(AuraApplication const* aurApp, u
float percent = target->GetHealthPct();
- target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(GetAmount()), apply);
+ target->HandleStatFlatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(GetAmount()), apply);
// refresh percentage
if (target->GetHealth() > 0)
@@ -3653,7 +3667,7 @@ void AuraEffect::HandleAuraModIncreaseEnergy(AuraApplication const* aurApp, uint
UnitMods unitMod = UnitMods(UNIT_MOD_POWER_START + powerType);
- target->HandleStatModifier(unitMod, TOTAL_VALUE, float(GetAmount()), apply);
+ target->HandleStatFlatModifier(unitMod, TOTAL_VALUE, float(GetAmount()), apply);
}
void AuraEffect::HandleAuraModIncreaseEnergyPercent(AuraApplication const* aurApp, uint8 mode, bool apply) const
@@ -3664,25 +3678,22 @@ void AuraEffect::HandleAuraModIncreaseEnergyPercent(AuraApplication const* aurAp
Unit* target = aurApp->GetTarget();
Powers powerType = Powers(GetMiscValue());
- // do not check power type, we can always modify the maximum
- // as the client will not see any difference
- // also, placing conditions that may change during the aura duration
- // inside effect handlers is not a good idea
- //if (int32(powerType) != GetMiscValue())
- // return;
UnitMods unitMod = UnitMods(UNIT_MOD_POWER_START + powerType);
- float amount = float(GetAmount());
if (apply)
{
- target->HandleStatModifier(unitMod, TOTAL_PCT, amount, apply);
- target->ModifyPowerPct(powerType, amount, apply);
+ float amount = float(GetAmount());
+ target->ApplyStatPctModifier(unitMod, TOTAL_PCT, amount);
+
+ float power = target->GetMaxPower(powerType);
+ AddPct(power, amount);
+ target->ModifyPower(powerType, (int32)power - (int32)target->GetMaxPower(powerType));
}
else
{
- target->ModifyPowerPct(powerType, amount, apply);
- target->HandleStatModifier(unitMod, TOTAL_PCT, amount, apply);
+ float amount = target->GetTotalAuraMultiplierByMiscValue(SPELL_AURA_MOD_INCREASE_ENERGY_PERCENT, GetMiscValue());
+ target->SetStatPctModifier(unitMod, TOTAL_PCT, amount);
}
}
@@ -3695,11 +3706,17 @@ void AuraEffect::HandleAuraModIncreaseHealthPercent(AuraApplication const* aurAp
// Unit will keep hp% after MaxHealth being modified if unit is alive.
float percent = target->GetHealthPct();
- target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_PCT, float(GetAmount()), apply);
+ if (apply)
+ target->ApplyStatPctModifier(UNIT_MOD_HEALTH, TOTAL_PCT, float(GetAmount()));
+ else
+ {
+ float amount = target->GetTotalAuraMultiplier(SPELL_AURA_MOD_INCREASE_HEALTH_PERCENT);
+ target->SetStatPctModifier(UNIT_MOD_HEALTH, TOTAL_PCT, amount);
+ }
if (target->GetHealth() > 0)
{
- uint32 newHealth = std::max<uint32>(target->CountPctFromMaxHealth(int32(percent)), 1);
+ uint32 newHealth = std::max<uint32>(CalculatePct(target->GetMaxHealth(), percent), 1);
target->SetHealth(newHealth);
}
}
@@ -3711,7 +3728,13 @@ void AuraEffect::HandleAuraIncreaseBaseHealthPercent(AuraApplication const* aurA
Unit* target = aurApp->GetTarget();
- target->HandleStatModifier(UNIT_MOD_HEALTH, BASE_PCT, float(GetAmount()), apply);
+ if (apply)
+ target->ApplyStatPctModifier(UNIT_MOD_HEALTH, BASE_PCT, float(GetAmount()));
+ else
+ {
+ float amount = target->GetTotalAuraMultiplier(SPELL_AURA_MOD_BASE_HEALTH_PCT);
+ target->SetStatPctModifier(UNIT_MOD_HEALTH, BASE_PCT, amount);
+ }
}
/********************************/
@@ -3768,13 +3791,10 @@ void AuraEffect::HandleAuraModWeaponCritPercent(AuraApplication const* aurApp, u
return;
Player* target = aurApp->GetTarget()->ToPlayer();
-
if (!target)
return;
- target->HandleBaseModValue(CRIT_PERCENTAGE, FLAT_MOD, float(GetAmount()), apply);
- target->HandleBaseModValue(OFFHAND_CRIT_PERCENTAGE, FLAT_MOD, float(GetAmount()), apply);
- target->HandleBaseModValue(RANGED_CRIT_PERCENTAGE, FLAT_MOD, float(GetAmount()), apply);
+ target->UpdateAllWeaponDependentCritAuras();
}
void AuraEffect::HandleModHitChance(AuraApplication const* aurApp, uint8 mode, bool apply) const
@@ -3819,7 +3839,7 @@ void AuraEffect::HandleModSpellCritChance(AuraApplication const* aurApp, uint8 m
if (target->GetTypeId() == TYPEID_PLAYER)
target->ToPlayer()->UpdateAllSpellCritChances();
else
- target->m_baseSpellCritChance += (apply) ? GetAmount():-GetAmount();
+ target->m_baseSpellCritChance += (apply) ? GetAmount() : -GetAmount();
}
void AuraEffect::HandleModSpellCritChanceShool(AuraApplication const* aurApp, uint8 mode, bool /*apply*/) const
@@ -3846,13 +3866,11 @@ void AuraEffect::HandleAuraModCritPct(AuraApplication const* aurApp, uint8 mode,
if (target->GetTypeId() != TYPEID_PLAYER)
{
- target->m_baseSpellCritChance += (apply) ? GetAmount():-GetAmount();
+ target->m_baseSpellCritChance += (apply) ? GetAmount() : -GetAmount();
return;
}
- target->ToPlayer()->HandleBaseModValue(CRIT_PERCENTAGE, FLAT_MOD, float (GetAmount()), apply);
- target->ToPlayer()->HandleBaseModValue(OFFHAND_CRIT_PERCENTAGE, FLAT_MOD, float (GetAmount()), apply);
- target->ToPlayer()->HandleBaseModValue(RANGED_CRIT_PERCENTAGE, FLAT_MOD, float (GetAmount()), apply);
+ target->ToPlayer()->UpdateAllWeaponDependentCritAuras();
// included in Player::UpdateSpellCritChance calculation
target->ToPlayer()->UpdateAllSpellCritChances();
@@ -4006,7 +4024,7 @@ void AuraEffect::HandleAuraModAttackPower(AuraApplication const* aurApp, uint8 m
Unit* target = aurApp->GetTarget();
- target->HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, float(GetAmount()), apply);
+ target->HandleStatFlatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, float(GetAmount()), apply);
}
void AuraEffect::HandleAuraModRangedAttackPower(AuraApplication const* aurApp, uint8 mode, bool apply) const
@@ -4019,7 +4037,7 @@ void AuraEffect::HandleAuraModRangedAttackPower(AuraApplication const* aurApp, u
if ((target->getClassMask() & CLASSMASK_WAND_USERS) != 0)
return;
- target->HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(GetAmount()), apply);
+ target->HandleStatFlatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(GetAmount()), apply);
}
void AuraEffect::HandleAuraModAttackPowerPercent(AuraApplication const* aurApp, uint8 mode, bool apply) const
@@ -4030,7 +4048,13 @@ void AuraEffect::HandleAuraModAttackPowerPercent(AuraApplication const* aurApp,
Unit* target = aurApp->GetTarget();
//UNIT_FIELD_ATTACK_POWER_MULTIPLIER = multiplier - 1
- target->HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_PCT, float(GetAmount()), apply);
+ if (apply)
+ target->ApplyStatPctModifier(UNIT_MOD_ATTACK_POWER, TOTAL_PCT, float(GetAmount()));
+ else
+ {
+ float amount = target->GetTotalAuraMultiplier(SPELL_AURA_MOD_ATTACK_POWER_PCT);
+ target->SetStatPctModifier(UNIT_MOD_ATTACK_POWER, TOTAL_PCT, amount);
+ }
}
void AuraEffect::HandleAuraModRangedAttackPowerPercent(AuraApplication const* aurApp, uint8 mode, bool apply) const
@@ -4044,7 +4068,13 @@ void AuraEffect::HandleAuraModRangedAttackPowerPercent(AuraApplication const* au
return;
//UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER = multiplier - 1
- target->HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_PCT, float(GetAmount()), apply);
+ if (apply)
+ target->ApplyStatPctModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_PCT, float(GetAmount()));
+ else
+ {
+ float amount = target->GetTotalAuraMultiplier(SPELL_AURA_MOD_RANGED_ATTACK_POWER_PCT);
+ target->SetStatPctModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_PCT, amount);
+ }
}
void AuraEffect::HandleAuraModRangedAttackPowerOfStatPercent(AuraApplication const* aurApp, uint8 mode, bool /*apply*/) const
@@ -4087,11 +4117,7 @@ void AuraEffect::HandleModDamageDone(AuraApplication const* aurApp, uint8 mode,
Unit* target = aurApp->GetTarget();
if (GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL)
- {
- target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_VALUE, float(GetAmount()), apply);
- target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_VALUE, float(GetAmount()), apply);
- target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_VALUE, float(GetAmount()), apply);
- }
+ target->UpdateAllDamageDoneMods();
// Magic damage modifiers implemented in Unit::SpellBaseDamageBonusDone
// This information for client side use only
@@ -4113,34 +4139,20 @@ void AuraEffect::HandleModDamagePercentDone(AuraApplication const* aurApp, uint8
return;
Unit* target = aurApp->GetTarget();
- int32 spellGroupVal = target->GetHighestExclusiveSameEffectSpellGroupValue(this, SPELL_AURA_MOD_DAMAGE_PERCENT_DONE);
- if (abs(spellGroupVal) >= abs(GetAmount()))
- return;
+ // also handles spell group stacks
if (GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL)
- {
- if (spellGroupVal)
- {
- target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, float(spellGroupVal), !apply);
- target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(spellGroupVal), !apply);
- target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_PCT, float(spellGroupVal), !apply);
- }
-
- target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, float(GetAmount()), apply);
- target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(GetAmount()), apply);
- target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_PCT, float(GetAmount()), apply);
- }
+ target->UpdateAllDamagePctDoneMods();
if (target->GetTypeId() == TYPEID_PLAYER)
{
- for (uint16 i = 0; i < MAX_SPELL_SCHOOL; ++i)
+ for (uint8 i = 0; i < MAX_SPELL_SCHOOL; ++i)
{
if (GetMiscValue() & (1 << i))
{
- if (spellGroupVal)
- target->ApplyPercentModFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT + i, float(spellGroupVal), !apply);
-
- target->ApplyPercentModFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT + i, float(GetAmount()), apply);
+ // only aura type modifying PLAYER_FIELD_MOD_DAMAGE_DONE_PCT
+ float amount = target->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE, 1 << i);
+ target->SetFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT + i, amount);
}
}
}
@@ -4153,7 +4165,8 @@ void AuraEffect::HandleModOffhandDamagePercent(AuraApplication const* aurApp, ui
Unit* target = aurApp->GetTarget();
- target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(GetAmount()), apply);
+ // also handles spell group stacks
+ target->UpdateDamagePctDoneMods(OFF_ATTACK);
}
void AuraEffect::HandleShieldBlockValue(AuraApplication const* aurApp, uint8 mode, bool apply) const
@@ -4161,14 +4174,29 @@ void AuraEffect::HandleShieldBlockValue(AuraApplication const* aurApp, uint8 mod
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
- Unit* target = aurApp->GetTarget();
+ Player* target = aurApp->GetTarget()->ToPlayer();
+ if (!target)
+ return;
- BaseModType modType = FLAT_MOD;
- if (GetAuraType() == SPELL_AURA_MOD_SHIELD_BLOCKVALUE_PCT)
- modType = PCT_MOD;
+ target->HandleBaseModFlatValue(SHIELD_BLOCK_VALUE, float(GetAmount()), apply);
+}
- if (target->GetTypeId() == TYPEID_PLAYER)
- target->ToPlayer()->HandleBaseModValue(SHIELD_BLOCK_VALUE, modType, float(GetAmount()), apply);
+void AuraEffect::HandleShieldBlockValuePercent(AuraApplication const* aurApp, uint8 mode, bool apply) const
+{
+ if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
+ return;
+
+ Player* target = aurApp->GetTarget()->ToPlayer();
+ if (!target)
+ return;
+
+ if (apply)
+ target->ApplyBaseModPctValue(SHIELD_BLOCK_VALUE, float(GetAmount()));
+ else
+ {
+ float amount = target->GetTotalAuraMultiplier(SPELL_AURA_MOD_SHIELD_BLOCKVALUE_PCT);
+ target->SetBaseModPctValue(SHIELD_BLOCK_VALUE, amount);
+ }
}
/********************************/
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.h b/src/server/game/Spells/Auras/SpellAuraEffects.h
index e627f4935a0..74b1ae80d71 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.h
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.h
@@ -269,6 +269,7 @@ class TC_GAME_API AuraEffect
void HandleModDamagePercentDone(AuraApplication const* aurApp, uint8 mode, bool apply) const;
void HandleModOffhandDamagePercent(AuraApplication const* aurApp, uint8 mode, bool apply) const;
void HandleShieldBlockValue(AuraApplication const* aurApp, uint8 mode, bool apply) const;
+ void HandleShieldBlockValuePercent(AuraApplication const* aurApp, uint8 mode, bool apply) const;
// power cost
void HandleModPowerCostPCT(AuraApplication const* aurApp, uint8 mode, bool apply) const;
void HandleModPowerCost(AuraApplication const* aurApp, uint8 mode, bool apply) const;
diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp
index 7b17d8d485a..5b414c2073f 100644
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -3349,7 +3349,7 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex)
case RANGED_ATTACK: unitMod = UNIT_MOD_DAMAGE_RANGED; break;
}
- float weapon_total_pct = m_caster->GetModifierValue(unitMod, TOTAL_PCT);
+ float weapon_total_pct = m_caster->GetPctModifierValue(unitMod, TOTAL_PCT);
if (fixed_bonus)
fixed_bonus = int32(fixed_bonus * weapon_total_pct);
if (spell_bonus)
diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp
index 5438014f20d..6a2435e2147 100644
--- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp
+++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp
@@ -86,6 +86,13 @@ Position const PosMoveOnSpawn[1] =
{ -11561.9f, -1627.868f, 41.29941f, 0.0f }
};
+// AWFUL HACK WARNING
+// To whoever reads this: Zul'Gurub needs your love
+// Need to do this calculation to increase/decrease Arlokk's damage by 35% (probably some aura missing)
+// This is only to compile the scripts after the aura calculation revamp
+float const DamageIncrease = 35.0f;
+float const DamageDecrease = 100.f / (1.f + DamageIncrease / 100.f) - 100.f;
+
class boss_arlokk : public CreatureScript
{
public: boss_arlokk() : CreatureScript("boss_arlokk") { }
@@ -106,7 +113,7 @@ class boss_arlokk : public CreatureScript
void Reset() override
{
if (events.IsInPhase(PHASE_TWO))
- me->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, 35.0f, false); // hack
+ me->ApplyStatPctModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, DamageDecrease); // hack
_Reset();
Initialize();
me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(WEAPON_DAGGER));
@@ -267,7 +274,7 @@ class boss_arlokk : public CreatureScript
events.ScheduleEvent(EVENT_RAVAGE, urand(10000, 14000), 0, PHASE_TWO);
events.ScheduleEvent(EVENT_TRANSFORM_BACK, urand(15000, 18000), 0, PHASE_TWO);
events.SetPhase(PHASE_TWO);
- me->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, 35.0f, true); // hack
+ me->ApplyStatPctModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, DamageIncrease); // hack
break;
case EVENT_RAVAGE:
DoCastVictim(SPELL_RAVAGE, true);
@@ -285,7 +292,7 @@ class boss_arlokk : public CreatureScript
me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg));
me->UpdateDamagePhysical(BASE_ATTACK);
*/
- me->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, 35.0f, false); // hack
+ me->ApplyStatPctModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, DamageDecrease); // hack
events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, urand(4000, 7000), 0, PHASE_ONE);
events.ScheduleEvent(EVENT_GOUGE, urand(12000, 15000), 0, PHASE_ONE);
events.ScheduleEvent(EVENT_TRANSFORM, urand(16000, 20000), 0, PHASE_ONE);
diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_marli.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_marli.cpp
index 74ad31c0673..03bc99d177a 100644
--- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_marli.cpp
+++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_marli.cpp
@@ -69,6 +69,13 @@ enum Misc
NPC_SPIDER = 15041
};
+// AWFUL HACK WARNING
+// To whoever reads this: Zul'Gurub needs your love
+// Need to do this calculation to increase/decrease Mar'li's damage by 35% (probably some aura missing)
+// This is only to compile the scripts after the aura calculation revamp
+float const DamageIncrease = 35.0f;
+float const DamageDecrease = 100.f / (1.f + DamageIncrease / 100.f) - 100.f;
+
class boss_marli : public CreatureScript
{
public: boss_marli() : CreatureScript("boss_marli") { }
@@ -80,7 +87,7 @@ class boss_marli : public CreatureScript
void Reset() override
{
if (events.IsInPhase(PHASE_THREE))
- me->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, 35.0f, false); // hack
+ me->ApplyStatPctModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, DamageDecrease); // hack
_Reset();
}
@@ -150,7 +157,7 @@ class boss_marli : public CreatureScript
me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg +((cinfo->maxdmg/100) * 35)));
me->UpdateDamagePhysical(BASE_ATTACK);
*/
- me->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, 35.0f, true); // hack
+ me->ApplyStatPctModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, DamageIncrease); // hack
DoCastVictim(SPELL_ENVOLWINGWEB);
if (DoGetThreat(me->GetVictim()))
DoModifyThreatPercent(me->GetVictim(), -100);
@@ -186,7 +193,7 @@ class boss_marli : public CreatureScript
me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg +((cinfo->maxdmg/100) * 1)));
me->UpdateDamagePhysical(BASE_ATTACK);
*/
- me->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, 35.0f, false); // hack
+ me->ApplyStatPctModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, DamageDecrease); // hack
events.ScheduleEvent(EVENT_ASPECT_OF_MARLI, 12000, 0, PHASE_TWO);
events.ScheduleEvent(EVENT_TRANSFORM, 45000, 0, PHASE_TWO);
events.ScheduleEvent(EVENT_POISON_VOLLEY, 15000);
diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_thekal.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_thekal.cpp
index e468026fcf9..afe5fed0014 100644
--- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_thekal.cpp
+++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_thekal.cpp
@@ -76,6 +76,13 @@ enum Phases
PHASE_TWO = 2
};
+// AWFUL HACK WARNING
+// To whoever reads this: Zul'Gurub needs your love
+// Need to do this calculation to increase/decrease Thekal's damage by 40% (probably some aura missing)
+// This is only to compile the scripts after the aura calculation revamp
+float const DamageIncrease = 40.0f;
+float const DamageDecrease = 100.f / (1.f + DamageIncrease / 100.f) - 100.f;
+
class boss_thekal : public CreatureScript
{
public:
@@ -100,7 +107,7 @@ class boss_thekal : public CreatureScript
void Reset() override
{
if (events.IsInPhase(PHASE_TWO))
- me->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, 35.0f, false); // hack
+ me->ApplyStatPctModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, DamageDecrease); // hack
_Reset();
Initialize();
}
@@ -162,7 +169,7 @@ class boss_thekal : public CreatureScript
me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg +((cinfo->maxdmg/100) * 40)));
me->UpdateDamagePhysical(BASE_ATTACK);
*/
- me->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, 40.0f, true); // hack
+ me->ApplyStatPctModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, DamageIncrease); // hack
DoResetThreat();
events.ScheduleEvent(EVENT_FRENZY, 30000, 0, PHASE_TWO); // Phase 2
events.ScheduleEvent(EVENT_FORCEPUNCH, 4000, 0, PHASE_TWO); // Phase 2
diff --git a/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp b/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp
index 4616f960a5e..6ad3d2257b5 100644
--- a/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp
+++ b/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp
@@ -875,26 +875,20 @@ public:
{
PrepareAuraScript(spell_kelthuzad_chains_AuraScript);
- void HandleApply(AuraEffect const* /*eff*/, AuraEffectHandleModes /*mode*/)
+ void HandleApply(AuraEffect const* aurEff, AuraEffectHandleModes mode)
{
- Unit* target = GetTarget();
- float scale = target->GetObjectScale();
- ApplyPercentModFloatVar(scale, 200.0f, true);
- target->SetObjectScale(scale);
+ aurEff->HandleAuraModScale(GetTargetApplication(), mode, true);
}
- void HandleRemove(AuraEffect const* /*eff*/, AuraEffectHandleModes /*mode*/)
+ void HandleRemove(AuraEffect const* aurEff, AuraEffectHandleModes mode)
{
- Unit* target = GetTarget();
- float scale = target->GetObjectScale();
- ApplyPercentModFloatVar(scale, 200.0f, false);
- target->SetObjectScale(scale);
+ aurEff->HandleAuraModScale(GetTargetApplication(), mode, false);
}
void Register() override
{
- AfterEffectApply += AuraEffectApplyFn(spell_kelthuzad_chains_AuraScript::HandleApply, EFFECT_0, SPELL_AURA_AOE_CHARM, AURA_EFFECT_HANDLE_REAL);
- AfterEffectRemove += AuraEffectApplyFn(spell_kelthuzad_chains_AuraScript::HandleRemove, EFFECT_0, SPELL_AURA_AOE_CHARM, AURA_EFFECT_HANDLE_REAL);
+ AfterEffectApply += AuraEffectApplyFn(spell_kelthuzad_chains_AuraScript::HandleApply, EFFECT_1, SPELL_AURA_MOD_DAMAGE_PERCENT_DONE, AURA_EFFECT_HANDLE_REAL);
+ AfterEffectRemove += AuraEffectApplyFn(spell_kelthuzad_chains_AuraScript::HandleRemove, EFFECT_1, SPELL_AURA_MOD_DAMAGE_PERCENT_DONE, AURA_EFFECT_HANDLE_REAL);
}
};
diff --git a/src/server/scripts/Spells/spell_pet.cpp b/src/server/scripts/Spells/spell_pet.cpp
index 55af7f563cf..abe40cc2c7d 100644
--- a/src/server/scripts/Spells/spell_pet.cpp
+++ b/src/server/scripts/Spells/spell_pet.cpp
@@ -318,7 +318,7 @@ public:
{
if (AuraEffect* /* aurEff */ect = owner->GetAuraEffect(56246, EFFECT_0))
{
- float base_attPower = pet->GetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE) * pet->GetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_PCT);
+ float base_attPower = pet->GetFlatModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE) * pet->GetPctModifierValue(UNIT_MOD_ATTACK_POWER, BASE_PCT);
amount += CalculatePct(amount+base_attPower, /* aurEff */ect->GetAmount());
}
}