aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/common/Utilities/Util.h7
-rw-r--r--src/server/game/Entities/Creature/Creature.cpp20
-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/Pet/Pet.cpp12
-rw-r--r--src/server/game/Entities/Player/Player.cpp310
-rw-r--r--src/server/game/Entities/Player/Player.h29
-rw-r--r--src/server/game/Entities/Unit/StatSystem.cpp124
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp289
-rw-r--r--src/server/game/Entities/Unit/Unit.h49
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.cpp327
-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/Northrend/Naxxramas/boss_kelthuzad.cpp18
-rw-r--r--src/server/scripts/Spells/spell_pet.cpp2
15 files changed, 809 insertions, 384 deletions
diff --git a/src/common/Utilities/Util.h b/src/common/Utilities/Util.h
index 20520cb2068..a18fd16ad15 100644
--- a/src/common/Utilities/Util.h
+++ b/src/common/Utilities/Util.h
@@ -63,13 +63,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 748e1ac26ee..4af0dda1212 100644
--- a/src/server/game/Entities/Creature/Creature.cpp
+++ b/src/server/game/Entities/Creature/Creature.cpp
@@ -536,12 +536,12 @@ bool Creature::UpdateEntry(uint32 entry, CreatureData const* data /*= nullptr*/,
UpdateLevelDependantStats(); // We still re-initialize level dependant stats on entry update
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();
@@ -1409,7 +1409,7 @@ void Creature::UpdateLevelDependantStats()
break;
}
- SetModifierValue(UNIT_MOD_HEALTH, BASE_VALUE, (float)health);
+ SetStatFlatModifier(UNIT_MOD_HEALTH, BASE_VALUE, (float)health);
// damage
float basedamage = stats->GenerateBaseDamage(cInfo);
@@ -1426,11 +1426,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 afd07d44053..1be3e00e39a 100644
--- a/src/server/game/Entities/Creature/Creature.h
+++ b/src/server/game/Entities/Creature/Creature.h
@@ -155,7 +155,7 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma
void UpdateMaxPower(Powers power) override;
uint32 GetPowerIndex(Powers power) const 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 056fe78c99d..c91af442cef 100644
--- a/src/server/game/Entities/Creature/TemporarySummon.h
+++ b/src/server/game/Entities/Creature/TemporarySummon.h
@@ -120,6 +120,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/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp
index 7563289b480..2c0c36e908d 100644
--- a/src/server/game/Entities/Pet/Pet.cpp
+++ b/src/server/game/Entities/Pet/Pet.cpp
@@ -794,7 +794,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));
SetBaseAttackTime(BASE_ATTACK, BASE_ATTACK_TIME);
SetBaseAttackTime(OFF_ATTACK, BASE_ATTACK_TIME);
@@ -819,7 +819,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 or Power, Armor
PetLevelInfo const* pInfo = sObjectMgr->GetPetLevelInfo(creature_ID, petlevel);
@@ -829,7 +829,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]));
@@ -875,7 +875,7 @@ bool Guardian::InitStatsForLevel(uint8 petlevel)
SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel - (petlevel / 4)));
SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel + (petlevel / 4)));
- //SetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE, float(cinfo->attackpower));
+ //SetStatFlatModifier(UNIT_MOD_ATTACK_POWER, BASE_VALUE, float(cinfo->attackpower));
break;
}
case HUNTER_PET:
@@ -963,8 +963,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 daeaf3d8877..580f21843d0 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -269,8 +269,8 @@ Player::Player(WorldSession* session) : Unit(true), m_sceneMgr(this)
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++)
@@ -4952,20 +4952,104 @@ void Player::LeaveLFGChannel()
}
}
-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->Effect[i])
+ {
+ case ITEM_ENCHANTMENT_TYPE_DAMAGE:
+ amount += enchantmentEntry->EffectScalingPoints[i];
+ break;
+ case ITEM_ENCHANTMENT_TYPE_TOTEM:
+ if (getClass() == CLASS_SHAMAN)
+ amount += enchantmentEntry->EffectScalingPoints[i] * item->GetTemplate()->GetDelay() / 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;
@@ -4987,10 +5071,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
@@ -5002,10 +5083,7 @@ 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];
}
void Player::GetDodgeFromAgility(float &/*diminishing*/, float &/*nondiminishing*/) const
@@ -5053,7 +5131,7 @@ void Player::GetDodgeFromAgility(float &/*diminishing*/, float &/*nondiminishing
// 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
@@ -5312,7 +5390,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));
}
@@ -7419,7 +7497,13 @@ void Player::_ApplyItemMods(Item* item, uint8 slot, bool apply, bool updateItemA
_ApplyItemBonuses(item, slot, apply);
ApplyItemEquipSpell(item, apply);
if (updateItemAuras)
+ {
ApplyItemDependentAuras(item, apply);
+
+ WeaponAttackType const attackType = Player::GetAttackBySlot(slot, item->GetTemplate()->GetInventoryType());
+ if (attackType != MAX_ATTACK)
+ UpdateWeaponDependentAuras(attackType);
+ }
ApplyArtifactPowers(item, apply);
ApplyAzeritePowers(item, apply);
ApplyEnchantment(item, apply);
@@ -7452,22 +7536,22 @@ void Player::_ApplyItemBonuses(Item* item, 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, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_AGILITY, BASE_PCT_EXCLUDE_CREATE)), 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, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_STRENGTH, BASE_PCT_EXCLUDE_CREATE)), 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, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_INTELLECT, BASE_PCT_EXCLUDE_CREATE)), 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);
@@ -7477,8 +7561,8 @@ void Player::_ApplyItemBonuses(Item* item, uint8 slot, bool apply)
{
if (GtStaminaMultByILvl const* staminaMult = sStaminaMultByILvlGameTable.GetRow(itemLevel))
val = int32(val * GetIlvlStatMultiplier(staminaMult, proto->GetInventoryType()));
- HandleStatModifier(UNIT_MOD_STAT_STAMINA, BASE_VALUE, float(val), apply);
- ApplyStatBuffMod(STAT_STAMINA, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_STAMINA, BASE_PCT_EXCLUDE_CREATE)), apply);
+ HandleStatFlatModifier(UNIT_MOD_STAT_STAMINA, BASE_VALUE, float(val), apply);
+ UpdateStatBuffMod(STAT_STAMINA);
break;
}
case ITEM_MOD_DEFENSE_SKILL_RATING:
@@ -7570,11 +7654,11 @@ void Player::_ApplyItemBonuses(Item* item, uint8 slot, bool apply)
ApplyRatingMod(CR_EXPERTISE, int32(val * combatRatingMultiplier), 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_VERSATILITY:
ApplyRatingMod(CR_VERSATILITY_DAMAGE_DONE, int32(val * combatRatingMultiplier), apply);
@@ -7600,25 +7684,25 @@ void Player::_ApplyItemBonuses(Item* item, uint8 slot, bool apply)
ApplyRatingMod(CR_MASTERY, int32(val * combatRatingMultiplier), apply);
break;
case ITEM_MOD_EXTRA_ARMOR:
- HandleStatModifier(UNIT_MOD_ARMOR, TOTAL_VALUE, float(val), apply);
+ HandleStatFlatModifier(UNIT_MOD_ARMOR, TOTAL_VALUE, float(val), apply);
break;
case ITEM_MOD_FIRE_RESISTANCE:
- HandleStatModifier(UNIT_MOD_RESISTANCE_FIRE, BASE_VALUE, float(val), apply);
+ HandleStatFlatModifier(UNIT_MOD_RESISTANCE_FIRE, BASE_VALUE, float(val), apply);
break;
case ITEM_MOD_FROST_RESISTANCE:
- HandleStatModifier(UNIT_MOD_RESISTANCE_FROST, BASE_VALUE, float(val), apply);
+ HandleStatFlatModifier(UNIT_MOD_RESISTANCE_FROST, BASE_VALUE, float(val), apply);
break;
case ITEM_MOD_HOLY_RESISTANCE:
- HandleStatModifier(UNIT_MOD_RESISTANCE_HOLY, BASE_VALUE, float(val), apply);
+ HandleStatFlatModifier(UNIT_MOD_RESISTANCE_HOLY, BASE_VALUE, float(val), apply);
break;
case ITEM_MOD_SHADOW_RESISTANCE:
- HandleStatModifier(UNIT_MOD_RESISTANCE_SHADOW, BASE_VALUE, float(val), apply);
+ HandleStatFlatModifier(UNIT_MOD_RESISTANCE_SHADOW, BASE_VALUE, float(val), apply);
break;
case ITEM_MOD_NATURE_RESISTANCE:
- HandleStatModifier(UNIT_MOD_RESISTANCE_NATURE, BASE_VALUE, float(val), apply);
+ HandleStatFlatModifier(UNIT_MOD_RESISTANCE_NATURE, BASE_VALUE, float(val), apply);
break;
case ITEM_MOD_ARCANE_RESISTANCE:
- HandleStatModifier(UNIT_MOD_RESISTANCE_ARCANE, BASE_VALUE, float(val), apply);
+ HandleStatFlatModifier(UNIT_MOD_RESISTANCE_ARCANE, BASE_VALUE, float(val), apply);
break;
case ITEM_MOD_PVP_POWER:
ApplyRatingMod(CR_PVP_POWER, int32(val), apply);
@@ -7654,36 +7738,36 @@ void Player::_ApplyItemBonuses(Item* item, uint8 slot, bool apply)
ApplyRatingMod(CR_UNUSED_12, int32(val), apply);
break;
case ITEM_MOD_AGI_STR_INT:
- HandleStatModifier(UNIT_MOD_STAT_AGILITY, BASE_VALUE, float(val), apply);
- HandleStatModifier(UNIT_MOD_STAT_STRENGTH, BASE_VALUE, float(val), apply);
- HandleStatModifier(UNIT_MOD_STAT_INTELLECT, BASE_VALUE, float(val), apply);
- ApplyStatBuffMod(STAT_AGILITY, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_AGILITY, BASE_PCT_EXCLUDE_CREATE)), apply);
- ApplyStatBuffMod(STAT_STRENGTH, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_STRENGTH, BASE_PCT_EXCLUDE_CREATE)), apply);
- ApplyStatBuffMod(STAT_INTELLECT, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_INTELLECT, BASE_PCT_EXCLUDE_CREATE)), apply);
+ HandleStatFlatModifier(UNIT_MOD_STAT_AGILITY, BASE_VALUE, float(val), apply);
+ HandleStatFlatModifier(UNIT_MOD_STAT_STRENGTH, BASE_VALUE, float(val), apply);
+ HandleStatFlatModifier(UNIT_MOD_STAT_INTELLECT, BASE_VALUE, float(val), apply);
+ UpdateStatBuffMod(STAT_AGILITY);
+ UpdateStatBuffMod(STAT_STRENGTH);
+ UpdateStatBuffMod(STAT_INTELLECT);
break;
case ITEM_MOD_AGI_STR:
- HandleStatModifier(UNIT_MOD_STAT_AGILITY, BASE_VALUE, float(val), apply);
- HandleStatModifier(UNIT_MOD_STAT_STRENGTH, BASE_VALUE, float(val), apply);
- ApplyStatBuffMod(STAT_AGILITY, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_AGILITY, BASE_PCT_EXCLUDE_CREATE)), apply);
- ApplyStatBuffMod(STAT_STRENGTH, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_STRENGTH, BASE_PCT_EXCLUDE_CREATE)), apply);
+ HandleStatFlatModifier(UNIT_MOD_STAT_AGILITY, BASE_VALUE, float(val), apply);
+ HandleStatFlatModifier(UNIT_MOD_STAT_STRENGTH, BASE_VALUE, float(val), apply);
+ UpdateStatBuffMod(STAT_AGILITY);
+ UpdateStatBuffMod(STAT_STRENGTH);
break;
case ITEM_MOD_AGI_INT:
- HandleStatModifier(UNIT_MOD_STAT_AGILITY, BASE_VALUE, float(val), apply);
- HandleStatModifier(UNIT_MOD_STAT_INTELLECT, BASE_VALUE, float(val), apply);
- ApplyStatBuffMod(STAT_AGILITY, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_AGILITY, BASE_PCT_EXCLUDE_CREATE)), apply);
- ApplyStatBuffMod(STAT_INTELLECT, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_INTELLECT, BASE_PCT_EXCLUDE_CREATE)), apply);
+ HandleStatFlatModifier(UNIT_MOD_STAT_AGILITY, BASE_VALUE, float(val), apply);
+ HandleStatFlatModifier(UNIT_MOD_STAT_INTELLECT, BASE_VALUE, float(val), apply);
+ UpdateStatBuffMod(STAT_AGILITY);
+ UpdateStatBuffMod(STAT_INTELLECT);
break;
case ITEM_MOD_STR_INT:
- HandleStatModifier(UNIT_MOD_STAT_STRENGTH, BASE_VALUE, float(val), apply);
- HandleStatModifier(UNIT_MOD_STAT_INTELLECT, BASE_VALUE, float(val), apply);
- ApplyStatBuffMod(STAT_STRENGTH, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_STRENGTH, BASE_PCT_EXCLUDE_CREATE)), apply);
- ApplyStatBuffMod(STAT_INTELLECT, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_INTELLECT, BASE_PCT_EXCLUDE_CREATE)), apply);
+ HandleStatFlatModifier(UNIT_MOD_STAT_STRENGTH, BASE_VALUE, float(val), apply);
+ HandleStatFlatModifier(UNIT_MOD_STAT_INTELLECT, BASE_VALUE, float(val), apply);
+ UpdateStatBuffMod(STAT_STRENGTH);
+ UpdateStatBuffMod(STAT_INTELLECT);
break;
}
}
if (uint32 armor = item->GetArmor(this))
- HandleStatModifier(UNIT_MOD_ARMOR, BASE_VALUE, float(armor), apply);
+ HandleStatFlatModifier(UNIT_MOD_ARMOR, BASE_VALUE, float(armor), apply);
WeaponAttackType attType = BASE_ATTACK;
@@ -7775,6 +7859,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)
@@ -8427,6 +8554,10 @@ void Player::_ApplyAllItemMods()
ApplyItemDependentAuras(m_items[i], true);
_ApplyItemBonuses(m_items[i], i, true);
+
+ WeaponAttackType const attackType = Player::GetAttackBySlot(i, m_items[i]->GetTemplate()->GetInventoryType());
+ if (attackType != MAX_ATTACK)
+ UpdateWeaponDependentAuras(attackType);
}
}
@@ -10094,7 +10225,7 @@ Item* Player::GetChildItemByGuid(ObjectGuid guid) const
return nullptr;
}
-uint8 Player::GetAttackBySlot(uint8 slot, InventoryType inventoryType)
+WeaponAttackType Player::GetAttackBySlot(uint8 slot, InventoryType inventoryType)
{
switch (slot)
{
@@ -14124,16 +14255,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)
- {
- if (item->GetTemplate()->GetInventoryType() != INVTYPE_RANGED && item->GetTemplate()->GetInventoryType() != INVTYPE_RANGEDRIGHT)
- HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_VALUE, float(enchant_amount), apply);
- else
- HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_VALUE, float(enchant_amount), apply);
- }
- else if (item->GetSlot() == EQUIPMENT_SLOT_OFFHAND)
- HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_VALUE, float(enchant_amount), apply);
+ {
+ WeaponAttackType const attackType = Player::GetAttackBySlot(item->GetSlot(), item->GetTemplate()->GetInventoryType());
+ if (attackType != MAX_ATTACK)
+ UpdateDamageDoneMods(attackType);
break;
+ }
case ITEM_ENCHANTMENT_TYPE_EQUIP_SPELL:
if (enchant_spell_id)
{
@@ -14163,7 +14290,7 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool
enchant_amount = uint32(pEnchant->EffectScalingPoints[s] * GetSpellScalingColumnForClass(spellScaling, scalingClass));
}
enchant_amount = std::max(enchant_amount, 1u);
- 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:
{
@@ -14193,26 +14320,26 @@ 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);
@@ -14221,8 +14348,8 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool
// 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);
@@ -14330,12 +14457,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_MANA_REGENERATION:
@@ -14359,7 +14486,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_MASTERY_RATING:
@@ -14379,20 +14506,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()->GetDelay() / 1000.0f);
- HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_VALUE, addValue, apply);
- }
- else if (item->GetSlot() == EQUIPMENT_SLOT_OFFHAND)
- {
- addValue = float(enchant_amount * item->GetTemplate()->GetDelay() / 1000.0f);
- HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_VALUE, addValue, apply);
- }
- }
+ WeaponAttackType const attackType = Player::GetAttackBySlot(item->GetSlot(), item->GetTemplate()->GetInventoryType());
+ 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 476aa0d7492..554c9090212 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -1128,8 +1128,8 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
Item* GetWeaponForAttack(WeaponAttackType attackType, bool useable = false) const;
Item* GetShield(bool useable = false) const;
Item* GetChildItemByGuid(ObjectGuid guid) const;
- static uint8 GetAttackBySlot(uint8 slot, InventoryType inventoryType); // MAX_ATTACK if not weapon slot
- std::vector<Item*> &GetItemUpdateQueue() { return m_itemUpdateQueue; }
+ static WeaponAttackType GetAttackBySlot(uint8 slot, InventoryType inventoryType); // 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); }
@@ -1771,6 +1771,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
void ApplyModDamageDonePos(SpellSchools school, int32 mod, bool apply) { ApplyModUpdateFieldValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::ModDamageDonePos, school), mod, apply); }
void ApplyModDamageDoneNeg(SpellSchools school, int32 mod, bool apply) { ApplyModUpdateFieldValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::ModDamageDoneNeg, school), mod, apply); }
void ApplyModDamageDonePercent(SpellSchools school, float pct, bool apply) { ApplyPercentModUpdateFieldValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::ModDamageDonePercent, school), pct, apply); }
+ void SetModDamageDonePercent(uint8 school, float pct) { SetUpdateFieldValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::ModDamageDonePercent, school), pct); }
void ApplyRatingMod(CombatRating cr, int32 value, bool apply);
void UpdateRating(CombatRating cr);
void UpdateAllRatings();
@@ -1779,7 +1780,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
void UpdateHealingDonePercentMod();
bool CanUseMastery() const;
- 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 RecalculateRating(CombatRating cr) { ApplyRatingMod(cr, 0, true);}
void GetDodgeFromAgility(float &diminishing, float &nondiminishing) const;
@@ -2003,11 +2004,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();
@@ -2015,6 +2024,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);
@@ -2651,7 +2665,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_baseManaRegen;
diff --git a/src/server/game/Entities/Unit/StatSystem.cpp b/src/server/game/Entities/Unit/StatSystem.cpp
index e9f1fc359d9..2170ba4d7c7 100644
--- a/src/server/game/Entities/Unit/StatSystem.cpp
+++ b/src/server/game/Entities/Unit/StatSystem.cpp
@@ -200,7 +200,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));
@@ -254,10 +254,10 @@ void Player::UpdateArmor()
{
UnitMods unitMod = UNIT_MOD_ARMOR;
- float value = GetModifierValue(unitMod, BASE_VALUE); // base armor (from items)
+ float value = GetFlatModifierValue(unitMod, BASE_VALUE); // base armor (from items)
float baseValue = value;
- value *= GetModifierValue(unitMod, BASE_PCT); // armor percent from items
- value += GetModifierValue(unitMod, TOTAL_VALUE);
+ value *= GetPctModifierValue(unitMod, BASE_PCT); // armor percent from items
+ value += GetFlatModifierValue(unitMod, TOTAL_VALUE);
//add dynamic flat mods
AuraEffectList const& mResbyIntellect = GetAuraEffectsByType(SPELL_AURA_MOD_RESISTANCE_OF_STAT_PERCENT);
@@ -267,7 +267,7 @@ void Player::UpdateArmor()
value += CalculatePct(GetStat(Stats((*i)->GetMiscValueB())), (*i)->GetAmount());
}
- value *= GetModifierValue(unitMod, TOTAL_PCT);
+ value *= GetPctModifierValue(unitMod, TOTAL_PCT);
SetArmor(int32(baseValue), int32(value - baseValue));
@@ -294,10 +294,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);
}
@@ -315,10 +315,10 @@ void Player::UpdateMaxPower(Powers power)
UnitMods unitMod = UnitMods(UNIT_MOD_POWER_START + power);
- float value = GetModifierValue(unitMod, BASE_VALUE) + GetCreatePowers(power);
- value *= GetModifierValue(unitMod, BASE_PCT);
- value += GetModifierValue(unitMod, TOTAL_VALUE);
- value *= GetModifierValue(unitMod, TOTAL_PCT);
+ float value = GetFlatModifierValue(unitMod, BASE_VALUE) + GetCreatePowers(power);
+ value *= GetPctModifierValue(unitMod, BASE_PCT);
+ value += GetFlatModifierValue(unitMod, TOTAL_VALUE);
+ value *= GetPctModifierValue(unitMod, TOTAL_PCT);
SetMaxPower(power, (int32)std::lroundf(value));
}
@@ -357,11 +357,11 @@ void Player::UpdateAttackPowerAndDamage(bool ranged)
val2 = CalculatePct(float(minSpellPower), *m_activePlayerData->OverrideAPBySpellPowerPercent);
}
- 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 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;
if (ranged)
{
@@ -405,7 +405,7 @@ void Player::UpdateAttackPowerAndDamage(bool ranged)
}
}
-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;
@@ -425,10 +425,10 @@ void Player::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bo
float attackPowerMod = std::max(GetAPMultiplier(attType, normalized), 0.25f);
- float baseValue = GetModifierValue(unitMod, BASE_VALUE) + GetTotalAttackPowerValue(attType) / 3.5f * 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) / 3.5f * 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);
@@ -492,16 +492,16 @@ void Player::UpdateCritPercentage(WeaponAttackType attType)
{
case OFF_ATTACK:
SetUpdateFieldStatValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::OffhandCritPercentage),
- applyCritLimit(GetTotalPercentageModValue(OFFHAND_CRIT_PERCENTAGE) + GetRatingBonusValue(CR_CRIT_MELEE)));
+ applyCritLimit(GetBaseModValue(OFFHAND_CRIT_PERCENTAGE, FLAT_MOD) + GetBaseModValue(OFFHAND_CRIT_PERCENTAGE, PCT_MOD) + GetRatingBonusValue(CR_CRIT_MELEE)));
break;
case RANGED_ATTACK:
SetUpdateFieldStatValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::RangedCritPercentage),
- applyCritLimit(GetTotalPercentageModValue(RANGED_CRIT_PERCENTAGE) + GetRatingBonusValue(CR_CRIT_RANGED)));
+ applyCritLimit(GetBaseModValue(RANGED_CRIT_PERCENTAGE, FLAT_MOD) + GetBaseModValue(RANGED_CRIT_PERCENTAGE, PCT_MOD) + GetRatingBonusValue(CR_CRIT_RANGED)));
break;
case BASE_ATTACK:
default:
SetUpdateFieldStatValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::CritPercentage),
- applyCritLimit(GetTotalPercentageModValue(CRIT_PERCENTAGE) + GetRatingBonusValue(CR_CRIT_MELEE)));
+ applyCritLimit(GetBaseModValue(CRIT_PERCENTAGE, FLAT_MOD) + GetBaseModValue(CRIT_PERCENTAGE, PCT_MOD) + GetRatingBonusValue(CR_CRIT_MELEE)));
break;
}
}
@@ -510,9 +510,9 @@ void Player::UpdateAllCritPercentages()
{
float value = 5.0f;
- 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);
@@ -835,7 +835,7 @@ bool Creature::UpdateAllStats()
void Creature::UpdateArmor()
{
- float baseValue = GetModifierValue(UNIT_MOD_ARMOR, BASE_VALUE);
+ float baseValue = GetFlatModifierValue(UNIT_MOD_ARMOR, BASE_VALUE);
float value = GetTotalAuraModValue(UNIT_MOD_ARMOR);
SetArmor(int32(baseValue), int32(value - baseValue));
}
@@ -864,10 +864,10 @@ void Creature::UpdateMaxPower(Powers power)
UnitMods unitMod = UnitMods(UNIT_MOD_POWER_START + power);
- float value = GetModifierValue(unitMod, BASE_VALUE) + GetCreatePowers(power);
- value *= GetModifierValue(unitMod, BASE_PCT);
- value += GetModifierValue(unitMod, TOTAL_VALUE);
- value *= GetModifierValue(unitMod, TOTAL_PCT);
+ float value = GetFlatModifierValue(unitMod, BASE_VALUE) + GetCreatePowers(power);
+ value *= GetPctModifierValue(unitMod, BASE_PCT);
+ value += GetFlatModifierValue(unitMod, TOTAL_VALUE);
+ value *= GetPctModifierValue(unitMod, TOTAL_PCT);
SetMaxPower(power, (int32)std::lroundf(value));
}
@@ -876,8 +876,8 @@ void Creature::UpdateAttackPowerAndDamage(bool ranged)
{
UnitMods unitMod = ranged ? UNIT_MOD_ATTACK_POWER_RANGED : UNIT_MOD_ATTACK_POWER;
- float baseAttackPower = GetModifierValue(unitMod, BASE_VALUE) * GetModifierValue(unitMod, BASE_PCT);
- float attackPowerMultiplier = GetModifierValue(unitMod, TOTAL_PCT) - 1.0f;
+ float baseAttackPower = GetFlatModifierValue(unitMod, BASE_VALUE) * GetPctModifierValue(unitMod, BASE_PCT);
+ float attackPowerMultiplier = GetPctModifierValue(unitMod, TOTAL_PCT) - 1.0f;
if (ranged)
{
@@ -900,7 +900,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;
@@ -939,10 +939,10 @@ void Creature::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized,
float attackPower = GetTotalAttackPowerValue(attType);
float attackSpeedMulti = GetAPMultiplier(attType, normalized);
- float baseValue = GetModifierValue(unitMod, BASE_VALUE) + (attackPower / 3.5f) * 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 / 3.5f) * 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;
@@ -970,7 +970,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);
+ UpdateStatBuffMod(stat);
float ownersBonus = 0.0f;
Unit* owner = GetOwner();
@@ -1010,7 +1010,7 @@ bool Guardian::UpdateStats(Stats stat)
SetStat(stat, int32(value));
m_statFromOwner[stat] = ownersBonus;
- ApplyStatBuffMod(stat, m_statFromOwner[stat], true);
+ UpdateStatBuffMod(stat);
switch (stat)
{
@@ -1044,7 +1044,7 @@ void Guardian::UpdateResistances(uint32 school)
{
if (school > SPELL_SCHOOL_NORMAL)
{
- float baseValue = GetModifierValue(UnitMods(UNIT_MOD_RESISTANCE_START + school), BASE_VALUE);
+ float baseValue = GetFlatModifierValue(UnitMods(UNIT_MOD_RESISTANCE_START + school), BASE_VALUE);
float bonusValue = GetTotalAuraModValue(UnitMods(UNIT_MOD_RESISTANCE_START + school)) - baseValue;
// hunter and warlock pets gain 40% of owner's resistance
@@ -1074,11 +1074,11 @@ void Guardian::UpdateArmor()
else if (IsPet())
bonus_armor = m_owner->GetArmor();
- value = GetModifierValue(unitMod, BASE_VALUE);
+ value = GetFlatModifierValue(unitMod, BASE_VALUE);
baseValue = value;
- value *= GetModifierValue(unitMod, BASE_PCT);
- value += GetModifierValue(unitMod, TOTAL_VALUE) + bonus_armor;
- value *= GetModifierValue(unitMod, TOTAL_PCT);
+ value *= GetPctModifierValue(unitMod, BASE_PCT);
+ value += GetFlatModifierValue(unitMod, TOTAL_VALUE) + bonus_armor;
+ value *= GetPctModifierValue(unitMod, TOTAL_PCT);
SetArmor(int32(baseValue), int32(value - baseValue));
}
@@ -1100,10 +1100,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);
}
@@ -1115,10 +1115,10 @@ void Guardian::UpdateMaxPower(Powers power)
UnitMods unitMod = UnitMods(UNIT_MOD_POWER_START + power);
- float value = GetModifierValue(unitMod, BASE_VALUE) + GetCreatePowers(power);
- value *= GetModifierValue(unitMod, BASE_PCT);
- value += GetModifierValue(unitMod, TOTAL_VALUE);
- value *= GetModifierValue(unitMod, TOTAL_PCT);
+ float value = GetFlatModifierValue(unitMod, BASE_VALUE) + GetCreatePowers(power);
+ value *= GetPctModifierValue(unitMod, BASE_PCT);
+ value += GetFlatModifierValue(unitMod, TOTAL_VALUE);
+ value *= GetPctModifierValue(unitMod, TOTAL_PCT);
SetMaxPower(power, int32(value));
}
@@ -1178,11 +1178,11 @@ 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 attPowerMultiplier = GetModifierValue(unitMod, TOTAL_PCT) - 1.0f;
+ float base_attPower = GetFlatModifierValue(unitMod, BASE_VALUE) * GetPctModifierValue(unitMod, BASE_PCT);
+ float attPowerMultiplier = GetPctModifierValue(unitMod, TOTAL_PCT) - 1.0f;
SetAttackPower(int32(base_attPower));
SetAttackPowerMultiplier(attPowerMultiplier);
@@ -1219,10 +1219,10 @@ void Guardian::UpdateDamagePhysical(WeaponAttackType attType)
float att_speed = float(GetBaseAttackTime(BASE_ATTACK))/1000.0f;
- float base_value = GetModifierValue(unitMod, BASE_VALUE) + GetTotalAttackPowerValue(attType)/ 3.5f * 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)/ 3.5f * 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 62790919a9c..be6324229d8 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -331,14 +331,14 @@ 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_EXCLUDE_CREATE] = 100.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][BASE_PCT_EXCLUDE_CREATE] = 100.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)
{
@@ -2258,7 +2258,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;
@@ -4892,16 +4892,69 @@ void Unit::InitStatBuffMods()
}
}
-void Unit::ApplyStatBuffMod(Stats stat, float val, bool apply)
+void Unit::UpdateStatBuffMod(Stats stat)
{
- ApplyPercentModFloatVar((val > 0 ? m_floatStatPosBuff[stat] : m_floatStatNegBuff[stat]), val, apply);
- UpdateStatBuffModForClient(stat);
-}
+ float modPos = 0.0f;
+ float modNeg = 0.0f;
+ float factor = 0.0f;
-void Unit::ApplyStatPercentBuffMod(Stats stat, float val, bool apply)
-{
- ApplyPercentModFloatVar(m_floatStatPosBuff[stat], val, apply);
- ApplyPercentModFloatVar(m_floatStatNegBuff[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;
+ }
+
+ // SPELL_AURA_MOD_STAT_BONUS_PCT only affects BASE_VALUE
+ modPos = CalculatePct(modPos, std::max(GetFlatModifierValue(unitMod, BASE_PCT_EXCLUDE_CREATE), -100.0f));
+ modNeg = CalculatePct(modPos, std::max(GetFlatModifierValue(unitMod, BASE_PCT_EXCLUDE_CREATE), -100.0f));
+
+ 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;
+
+ m_floatStatPosBuff[stat] = modPos;
+ m_floatStatNegBuff[stat] = modNeg;
+
+ UpdateStatBuffModForClient(stat);
}
void Unit::UpdateStatBuffModForClient(Stats stat)
@@ -9371,31 +9424,99 @@ bool Unit::IsDisallowedMountForm(uint32 spellId, ShapeshiftForm form, uint32 dis
######## ########
#######################################*/
-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 BASE_PCT_EXCLUDE_CREATE:
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)
{
@@ -9445,37 +9566,109 @@ bool Unit::HandleStatModifier(UnitMods unitMod, UnitModifierType modifierType, f
ASSERT(false, "Not implemented UnitMod %u", unitMod);
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 = CalculatePct(m_auraModifiersGroup[unitMod][BASE_VALUE], std::max(m_auraModifiersGroup[unitMod][BASE_PCT_EXCLUDE_CREATE], -100.0f));
+ float value = CalculatePct(GetFlatModifierValue(unitMod, BASE_VALUE), std::max(GetFlatModifierValue(unitMod, BASE_PCT_EXCLUDE_CREATE), -100.0f));
value += GetCreateStat(stat);
- value *= m_auraModifiersGroup[unitMod][BASE_PCT];
- value += m_auraModifiersGroup[unitMod][TOTAL_VALUE];
- value *= m_auraModifiersGroup[unitMod][TOTAL_PCT];
+ value *= GetPctModifierValue(unitMod, BASE_PCT);
+ value += GetFlatModifierValue(unitMod, TOTAL_VALUE);
+ value *= GetPctModifierValue(unitMod, TOTAL_PCT);
return value;
}
@@ -9488,13 +9681,10 @@ float Unit::GetTotalAuraModValue(UnitMods unitMod) const
return 0.0f;
}
- if (m_auraModifiersGroup[unitMod][TOTAL_PCT] <= 0.0f)
- return 0.0f;
-
- float value = CalculatePct(m_auraModifiersGroup[unitMod][BASE_VALUE], std::max(m_auraModifiersGroup[unitMod][BASE_PCT_EXCLUDE_CREATE], -100.0f));
- value *= m_auraModifiersGroup[unitMod][BASE_PCT];
- value += m_auraModifiersGroup[unitMod][TOTAL_VALUE];
- value *= m_auraModifiersGroup[unitMod][TOTAL_PCT];
+ float value = CalculatePct(GetFlatModifierValue(unitMod, BASE_VALUE), std::max(GetFlatModifierValue(unitMod, BASE_PCT_EXCLUDE_CREATE), -100.0f));
+ value *= GetPctModifierValue(unitMod, BASE_PCT);
+ value += GetFlatModifierValue(unitMod, TOTAL_VALUE);
+ value *= GetPctModifierValue(unitMod, TOTAL_PCT);
return value;
}
@@ -9542,7 +9732,7 @@ void Unit::UpdateResistances(uint32 school)
{
UnitMods unitMod = UnitMods(UNIT_MOD_RESISTANCE_START + school);
- SetResistance(SpellSchools(school), int32(m_auraModifiersGroup[unitMod][BASE_VALUE]));
+ SetResistance(SpellSchools(school), int32(GetFlatModifierValue(unitMod, BASE_VALUE)));
SetBonusResistanceMod(SpellSchools(school), int32(GetTotalAuraModValue(unitMod) - GetResistance(SpellSchools(school))));
}
else
@@ -10734,10 +10924,15 @@ void Unit::UpdateAttackTimeField(WeaponAttackType att)
}
}
+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 remainingTimePct = float(m_attackTimer[att]) / (m_baseAttackSpeed[att] * m_modAttackSpeedPct[att]);
- if (val > 0)
+ if (val > 0.f)
{
ApplyPercentModFloatVar(m_modAttackSpeedPct[att], val, !apply);
@@ -10762,7 +10957,7 @@ void Unit::ApplyAttackTimePercentMod(WeaponAttackType att, float val, bool apply
void Unit::ApplyCastTimePercentMod(float val, bool apply)
{
- if (val > 0)
+ if (val > 0.f)
{
ApplyPercentModUpdateFieldValue(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::ModCastingSpeed), val, !apply);
ApplyPercentModUpdateFieldValue(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::ModSpellHaste), val, !apply);
@@ -10920,7 +11115,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 GetBaseAttackTime(attType) / 1000.0f;
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index 51815fe7eff..0838d2b226b 100644
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -257,14 +257,19 @@ typedef std::vector<DispelableAura> DispelChargesList;
typedef std::unordered_multimap<uint32 /*type*/, uint32 /*spellId*/> SpellImmuneContainer;
-enum UnitModifierType
+enum UnitModifierFlatType
{
BASE_VALUE = 0,
BASE_PCT_EXCLUDE_CREATE = 1, // percent modifier affecting all stat values from auras and gear but not player base for level
- BASE_PCT = 2,
- TOTAL_VALUE = 3,
- TOTAL_PCT = 4,
- MODIFIER_TYPE_END = 5
+ TOTAL_VALUE = 2,
+ MODIFIER_TYPE_FLAT_END = 3
+};
+
+enum UnitModifierPctType
+{
+ BASE_PCT = 0,
+ TOTAL_PCT = 1,
+ MODIFIER_TYPE_PCT_END = 2
};
enum WeaponDamageRange
@@ -1600,8 +1605,7 @@ class TC_GAME_API Unit : public WorldObject
int32 GetMaxNegativeAuraModifierByAffectMask(AuraType auratype, SpellInfo const* affectedSpell) const;
void InitStatBuffMods();
- void ApplyStatBuffMod(Stats stat, float val, bool apply);
- void ApplyStatPercentBuffMod(Stats stat, float val, bool apply);
+ void UpdateStatBuffMod(Stats stat);
void UpdateStatBuffModForClient(Stats stat);
void SetCreateStat(Stats stat, float val) { m_createStats[stat] = val; }
void SetCreateHealth(uint32 val) { SetUpdateFieldValue(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::BaseHealth), val); }
@@ -1685,9 +1689,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;
@@ -1715,9 +1735,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;
@@ -2058,7 +2078,8 @@ class TC_GAME_API Unit : public WorldObject
AuraStateAurasMap m_auraStateAuras; // Used for improve performance of aura state checks on aura apply/remove
std::array<uint32, 2> 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;
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
index 14db03c5b92..cac6834abc5 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
@@ -215,7 +215,7 @@ NonDefaultConstructible<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::HandleUnused, //153 Unused (4.3.4) old SPELL_AURA_SPLIT_DAMAGE_FLAT
@@ -347,7 +347,7 @@ NonDefaultConstructible<pAuraEffectHandler> AuraEffectHandler[TOTAL_AURAS]=
&AuraEffect::HandleNoImmediateEffect, //279 SPELL_AURA_INITIALIZE_IMAGES
&AuraEffect::HandleUnused, //280 unused (4.3.4) old SPELL_AURA_MOD_ARMOR_PENETRATION_PCT
&AuraEffect::HandleNULL, //281 SPELL_AURA_MOD_GUILD_REPUTATION_GAIN_PCT
- &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::HandleAuraLinked, //285 SPELL_AURA_LINKED_2
@@ -2038,7 +2038,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);
}
@@ -2223,11 +2223,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, item->GetTemplate()->GetInventoryType());
+ WeaponAttackType const attackType = Player::GetAttackBySlot(slot, item->GetTemplate()->GetInventoryType());
player->ApplyItemDependentAuras(item, !apply);
- if (attacktype < MAX_ATTACK)
+ if (attackType != MAX_ATTACK)
+ {
player->_ApplyWeaponDamage(slot, item, !apply);
+ if (!apply) // apply case already handled on item dependent aura removal (if any)
+ player->UpdateWeaponDependentAuras(attackType);
+ }
}
}
@@ -2719,9 +2723,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
@@ -3210,9 +3224,9 @@ void AuraEffect::HandleAuraModResistance(AuraApplication const* aurApp, uint8 mo
Unit* target = aurApp->GetTarget();
- for (int8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL; x++)
- if (GetMiscValue() & int32(1<<x))
- target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), TOTAL_VALUE, float(GetAmount()), apply);
+ for (uint8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL; ++x)
+ if (GetMiscValue() & (1 << x))
+ target->HandleStatFlatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), TOTAL_VALUE, float(GetAmount()), apply);
}
void AuraEffect::HandleAuraModBaseResistancePCT(AuraApplication const* aurApp, uint8 mode, bool apply) const
@@ -3227,14 +3241,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);
+ }
+ }
}
}
}
@@ -3245,18 +3275,16 @@ 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);
+ 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->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_PCT, float(GetAmount()), apply);
+ target->SetStatPctModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_PCT, amount);
}
}
}
@@ -3271,15 +3299,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);
}
}
@@ -3323,22 +3351,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));
}
}
}
@@ -3360,10 +3387,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);
+ }
+ }
}
}
@@ -3456,22 +3496,6 @@ void AuraEffect::HandleModTotalPercentStat(AuraApplication const* aurApp, uint8
return;
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();
@@ -3483,30 +3507,29 @@ void AuraEffect::HandleModTotalPercentStat(AuraApplication const* aurApp, uint8
if (target->getDeathState() == CORPSE)
zeroHealth = (target->GetHealth() == 0);
- for (int32 i = STAT_STRENGTH; i < MAX_STATS; i++)
+ for (uint32 i = STAT_STRENGTH; i < MAX_STATS; ++i)
{
if (GetMiscValueB() & 1 << i || !GetMiscValueB()) // 0 is also used for all 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->GetMiscValueB() & 1 << i || !aurEff->GetMiscValueB())
+ return true;
+ return false;
+ });
+
+ if (target->GetPctModifierValue(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_PCT) == amount)
+ continue;
- target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_PCT, float(GetAmount()), apply);
+ 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 (GetMiscValueB() & 1 << STAT_STAMINA && (m_spellInfo->HasAttribute(SPELL_ATTR0_ABILITY)))
+ if ((GetMiscValueB() & 1 << STAT_STAMINA || !GetMiscValueB()) && (m_spellInfo->HasAttribute(SPELL_ATTR0_ABILITY)))
target->SetHealth(std::max<uint32>(CalculatePct(target->GetMaxHealth(), healthPct), (zeroHealth ? 0 : 1)));
}
@@ -3567,8 +3590,8 @@ void AuraEffect::HandleModStatBonusPercent(AuraApplication const* aurApp, uint8
{
if (GetMiscValue() == i || GetMiscValue() == -1)
{
- target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), BASE_PCT_EXCLUDE_CREATE, float(m_amount), apply);
- target->ApplyStatPercentBuffMod(Stats(i), float(m_amount), apply);
+ target->HandleStatFlatModifier(UnitMods(UNIT_MOD_STAT_START + i), BASE_PCT_EXCLUDE_CREATE, float(m_amount), apply);
+ target->UpdateStatBuffMod(Stats(i));
}
}
}
@@ -3623,7 +3646,7 @@ void AuraEffect::HandleAuraModMaxPower(AuraApplication const* aurApp, uint8 mode
Powers power = Powers(GetMiscValue());
UnitMods unitMod = UnitMods(UNIT_MOD_POWER_START + power);
- target->HandleStatModifier(unitMod, TOTAL_VALUE, float(GetAmount()), apply);
+ target->HandleStatFlatModifier(unitMod, TOTAL_VALUE, float(GetAmount()), apply);
}
/********************************/
@@ -3688,7 +3711,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
@@ -3698,7 +3721,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);
}
}
@@ -3711,7 +3734,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)
@@ -3730,7 +3753,7 @@ void AuraEffect::HandleAuraModIncreaseEnergy(AuraApplication const* aurApp, uint
Powers powerType = Powers(GetMiscValue());
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
@@ -3748,7 +3771,26 @@ void AuraEffect::HandleAuraModIncreaseEnergyPercent(AuraApplication const* aurAp
int32 oldMaxPower = target->GetMaxPower(powerType);
// Handle aura effect for max power
- target->HandleStatModifier(unitMod, TOTAL_PCT, float(GetAmount()), apply);
+ if (apply)
+ target->ApplyStatPctModifier(unitMod, TOTAL_PCT, float(GetAmount()));
+ else
+ {
+ float amount = target->GetTotalAuraMultiplier(SPELL_AURA_MOD_INCREASE_ENERGY_PERCENT, [powerType](AuraEffect const* aurEff) -> bool
+ {
+ if (aurEff->GetMiscValue() == powerType)
+ return true;
+ return false;
+ });
+
+ amount *= target->GetTotalAuraMultiplier(SPELL_AURA_MOD_MAX_POWER_PCT, [powerType](AuraEffect const* aurEff) -> bool
+ {
+ if (aurEff->GetMiscValue() == powerType)
+ return true;
+ return false;
+ });
+
+ target->SetStatPctModifier(unitMod, TOTAL_PCT, amount);
+ }
// Calculate the current power change
int32 change = target->GetMaxPower(powerType) - oldMaxPower;
@@ -3765,11 +3807,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);
}
}
@@ -3781,7 +3829,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);
+ }
}
void AuraEffect::HandleAuraModIncreaseBaseManaPercent(AuraApplication const* aurApp, uint8 mode, bool apply) const
@@ -3789,7 +3843,15 @@ void AuraEffect::HandleAuraModIncreaseBaseManaPercent(AuraApplication const* aur
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
- aurApp->GetTarget()->HandleStatModifier(UNIT_MOD_MANA, BASE_PCT, float(GetAmount()), apply);
+ Unit* target = aurApp->GetTarget();
+
+ if (apply)
+ target->ApplyStatPctModifier(UNIT_MOD_MANA, BASE_PCT, float(GetAmount()));
+ else
+ {
+ float amount = target->GetTotalAuraMultiplier(SPELL_AURA_MOD_BASE_MANA_PCT);
+ target->SetStatPctModifier(UNIT_MOD_MANA, BASE_PCT, amount);
+ }
}
void AuraEffect::HandleAuraModPowerDisplay(AuraApplication const* aurApp, uint8 mode, bool apply) const
@@ -3845,7 +3907,26 @@ void AuraEffect::HandleAuraModMaxPowerPct(AuraApplication const* aurApp, uint8 m
int32 oldMaxPower = target->GetMaxPower(powerType);
// Handle aura effect for max power
- target->HandleStatModifier(unitMod, TOTAL_PCT, float(GetAmount()), apply);
+ if (apply)
+ target->ApplyStatPctModifier(unitMod, TOTAL_PCT, float(GetAmount()));
+ else
+ {
+ float amount = target->GetTotalAuraMultiplier(SPELL_AURA_MOD_MAX_POWER_PCT, [powerType](AuraEffect const* aurEff) -> bool
+ {
+ if (aurEff->GetMiscValue() == powerType)
+ return true;
+ return false;
+ });
+
+ amount *= target->GetTotalAuraMultiplier(SPELL_AURA_MOD_INCREASE_ENERGY_PERCENT, [powerType](AuraEffect const* aurEff) -> bool
+ {
+ if (aurEff->GetMiscValue() == powerType)
+ return true;
+ return false;
+ });
+
+ target->SetStatPctModifier(unitMod, TOTAL_PCT, amount);
+ }
// Calculate the current power change
int32 change = target->GetMaxPower(powerType) - oldMaxPower;
@@ -3907,13 +3988,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
@@ -3945,7 +4023,7 @@ void AuraEffect::HandleModSpellHitChance(AuraApplication const* aurApp, uint8 mo
if (target->GetTypeId() == TYPEID_PLAYER)
target->ToPlayer()->UpdateSpellHitChances();
else
- target->m_modSpellHitChance += (apply) ? GetAmount(): (-GetAmount());
+ target->m_modSpellHitChance += (apply) ? GetAmount() : (-GetAmount());
}
void AuraEffect::HandleModSpellCritChance(AuraApplication const* aurApp, uint8 mode, bool apply) const
@@ -3958,7 +4036,7 @@ void AuraEffect::HandleModSpellCritChance(AuraApplication const* aurApp, uint8 m
if (target->GetTypeId() == TYPEID_PLAYER)
target->ToPlayer()->UpdateSpellCritChance();
else
- target->m_baseSpellCritChance += (apply) ? GetAmount():-GetAmount();
+ target->m_baseSpellCritChance += (apply) ? GetAmount() : -GetAmount();
}
void AuraEffect::HandleAuraModCritPct(AuraApplication const* aurApp, uint8 mode, bool apply) const
@@ -3970,13 +4048,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()->UpdateSpellCritChance();
@@ -4136,7 +4212,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
@@ -4149,7 +4225,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
@@ -4160,7 +4236,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
@@ -4174,7 +4256,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);
+ }
}
/********************************/
@@ -4188,11 +4276,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
@@ -4218,34 +4302,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 (Player* thisPlayer = target->ToPlayer())
{
- for (uint16 i = 0; i < MAX_SPELL_SCHOOL; ++i)
+ for (uint8 i = 0; i < MAX_SPELL_SCHOOL; ++i)
{
if (GetMiscValue() & (1 << i))
{
- if (spellGroupVal)
- thisPlayer->ApplyModDamageDonePercent(SpellSchools(i), float(spellGroupVal), !apply);
-
- thisPlayer->ApplyModDamageDonePercent(SpellSchools(i), float(GetAmount()), apply);
+ // only aura type modifying PLAYER_FIELD_MOD_DAMAGE_DONE_PCT
+ float amount = thisPlayer->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE, 1 << i);
+ thisPlayer->SetModDamageDonePercent(i, amount);
}
}
}
@@ -4258,7 +4328,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
@@ -4267,7 +4338,25 @@ void AuraEffect::HandleShieldBlockValue(AuraApplication const* aurApp, uint8 mod
return;
if (Player* player = aurApp->GetTarget()->ToPlayer())
- player->HandleBaseModValue(SHIELD_BLOCK_VALUE, PCT_MOD, float(GetAmount()), apply);
+ player->HandleBaseModFlatValue(SHIELD_BLOCK_VALUE, 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 138ea474e31..7b74320bdef 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.h
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.h
@@ -290,6 +290,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 6acb790d8e8..74148998c51 100644
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -2912,7 +2912,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/Northrend/Naxxramas/boss_kelthuzad.cpp b/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp
index 1d0ef4ccea0..d70f0d07c54 100644
--- a/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp
+++ b/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp
@@ -881,26 +881,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 c0b570cbf46..7aaba87a2da 100644
--- a/src/server/scripts/Spells/spell_pet.cpp
+++ b/src/server/scripts/Spells/spell_pet.cpp
@@ -314,7 +314,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());
}
}