aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2016-11-19 23:42:21 -0300
committerariel- <ariel-@users.noreply.github.com>2016-11-20 01:46:47 -0300
commit6dc37a9add631888fe5fbcd43d19c2b07bed8a57 (patch)
treef65348c424fd1a63c6e225ec809542a80ab77540 /src
parent5237eda34014ee6d3fa8ca5c52148ff56cba666d (diff)
Core/Auras: Rewritten conditionally applying SPELL_AURA_MOD_WEAPON_CRIT_PERCENT, SPELL_AURA_MOD_DAMAGE_DONE and SPELL_AURA_MOD_DAMAGE_PERCENT_DONE auras
* Now the entire aura is removed when changing equipment * All aura types can now depend on equipped items (cherry picked from commit b9f7b500a362736235fc917ce4f34aa8520eb651)
Diffstat (limited to 'src')
-rw-r--r--src/common/Common.h1
-rw-r--r--src/server/game/Entities/Player/Player.cpp111
-rw-r--r--src/server/game/Entities/Player/Player.h4
-rw-r--r--src/server/game/Entities/Unit/StatSystem.cpp25
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp132
-rw-r--r--src/server/game/Miscellaneous/SharedDefines.h2
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.cpp126
-rw-r--r--src/server/game/Spells/SpellEffects.cpp22
8 files changed, 134 insertions, 289 deletions
diff --git a/src/common/Common.h b/src/common/Common.h
index aa04abacd30..af9b9b17321 100644
--- a/src/common/Common.h
+++ b/src/common/Common.h
@@ -35,6 +35,7 @@
#include <unordered_map>
#include <unordered_set>
#include <vector>
+#include <numeric>
#include <cmath>
#include <cstdio>
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index f4fca5038d2..81c0a1ba2fb 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -7391,15 +7391,13 @@ void Player::_ApplyItemMods(Item* item, uint8 slot, bool apply)
if (proto->Socket[0].Color) //only (un)equipping of items with sockets can influence metagems, so no need to waste time with normal items
CorrectMetaGemEnchants(slot, apply);
- if (attacktype < MAX_ATTACK)
- _ApplyWeaponDependentAuraMods(item, WeaponAttackType(attacktype), apply);
-
_ApplyItemBonuses(proto, slot, apply);
if (slot == EQUIPMENT_SLOT_RANGED)
_ApplyAmmoBonuses();
ApplyItemEquipSpell(item, apply);
+ ApplyItemDependentAuras(item, apply);
ApplyEnchantment(item, apply);
TC_LOG_DEBUG("entities.player.items", "Player::_ApplyItemMods: completed");
@@ -7753,86 +7751,26 @@ void Player::_ApplyWeaponDamage(uint8 slot, ItemTemplate const* proto, ScalingSt
UpdateDamagePhysical(attType);
}
-void Player::_ApplyWeaponDependentAuraMods(Item* item, WeaponAttackType attackType, bool apply)
-{
- AuraEffectList const& auraCritList = GetAuraEffectsByType(SPELL_AURA_MOD_WEAPON_CRIT_PERCENT);
- for (AuraEffectList::const_iterator itr = auraCritList.begin(); itr != auraCritList.end(); ++itr)
- _ApplyWeaponDependentAuraCritMod(item, attackType, *itr, apply);
-
- AuraEffectList const& auraDamageFlatList = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_DONE);
- for (AuraEffectList::const_iterator itr = auraDamageFlatList.begin(); itr != auraDamageFlatList.end(); ++itr)
- _ApplyWeaponDependentAuraDamageMod(item, attackType, *itr, apply);
-
- AuraEffectList const& auraDamagePctList = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE);
- for (AuraEffectList::const_iterator itr = auraDamagePctList.begin(); itr != auraDamagePctList.end(); ++itr)
- _ApplyWeaponDependentAuraDamageMod(item, attackType, *itr, apply);
-}
-
-void Player::_ApplyWeaponDependentAuraCritMod(Item* item, WeaponAttackType attackType, AuraEffect const* aura, bool apply)
+void Player::ApplyItemDependentAuras(Item* item, bool apply)
{
- // don't apply mod if item is broken or cannot be used
- if (item->IsBroken() || !CanUseAttackType(attackType))
- return;
-
- // generic not weapon specific case processes in aura code
- if (aura->GetSpellInfo()->EquippedItemClass == -1)
- return;
-
- BaseModGroup mod;
- switch (attackType)
- {
- case BASE_ATTACK: mod = CRIT_PERCENTAGE; break;
- case OFF_ATTACK: mod = OFFHAND_CRIT_PERCENTAGE;break;
- case RANGED_ATTACK: mod = RANGED_CRIT_PERCENTAGE; break;
- default: return;
- }
-
- if (item->IsFitToSpellRequirements(aura->GetSpellInfo()))
- HandleBaseModValue(mod, FLAT_MOD, float (aura->GetAmount()), apply);
-}
-
-void Player::_ApplyWeaponDependentAuraDamageMod(Item* item, WeaponAttackType attackType, AuraEffect const* aura, bool apply)
-{
- // don't apply mod if item is broken or cannot be used
- if (item->IsBroken() || !CanUseAttackType(attackType))
- return;
-
- // ignore spell mods for not wands
- if ((aura->GetMiscValue() & SPELL_SCHOOL_MASK_MAGIC) && (!(getClassMask() & CLASSMASK_WAND_USERS)))
- return;
-
- // generic not weapon specific case processed in AuraEffect handler
- if (aura->GetSpellInfo()->EquippedItemClass == -1)
- return;
-
- UnitMods unitMod;
- switch (attackType)
+ if (apply)
{
- 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: return;
- }
+ PlayerSpellMap const& spells = GetSpellMap();
+ for (auto itr = spells.begin(); itr != spells.end(); ++itr)
+ {
+ if (itr->second->state == PLAYERSPELL_REMOVED || itr->second->disabled)
+ continue;
- UnitModifierType unitModType;
- switch (aura->GetAuraType())
- {
- case SPELL_AURA_MOD_DAMAGE_DONE: unitModType = TOTAL_VALUE; break;
- case SPELL_AURA_MOD_DAMAGE_PERCENT_DONE: unitModType = TOTAL_PCT; break;
- default: return;
- }
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(itr->first);
+ if (!spellInfo || !spellInfo->IsPassive() || spellInfo->EquippedItemClass < 0)
+ continue;
- if (item->IsFitToSpellRequirements(aura->GetSpellInfo()))
- {
- HandleStatModifier(unitMod, unitModType, float(aura->GetAmount()), apply);
- if (unitModType == TOTAL_VALUE)
- {
- if (aura->GetAmount() > 0)
- ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS, aura->GetAmount(), apply);
- else
- ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG, aura->GetAmount(), apply);
+ if (!HasAura(itr->first) && HasItemFitToSpellRequirements(spellInfo))
+ AddAura(itr->first, this); // no SMSG_SPELL_GO in sniff found
}
}
+ else
+ RemoveItemDependentAurasAndCasts(item);
}
void Player::ApplyItemEquipSpell(Item* item, bool apply, bool form_change)
@@ -8207,10 +8145,7 @@ void Player::_RemoveAllItemMods()
if (!proto)
continue;
- uint32 attacktype = Player::GetAttackBySlot(i);
- if (attacktype < MAX_ATTACK)
- _ApplyWeaponDependentAuraMods(m_items[i], WeaponAttackType(attacktype), false);
-
+ ApplyItemDependentAuras(m_items[i], false);
_ApplyItemBonuses(proto, i, false);
if (i == EQUIPMENT_SLOT_RANGED)
@@ -8237,9 +8172,7 @@ void Player::_ApplyAllItemMods()
continue;
uint32 attacktype = Player::GetAttackBySlot(i);
- if (attacktype < MAX_ATTACK)
- _ApplyWeaponDependentAuraMods(m_items[i], WeaponAttackType(attacktype), true);
-
+ ApplyItemDependentAuras(m_items[i], true);
_ApplyItemBonuses(proto, i, true);
if (i == EQUIPMENT_SLOT_RANGED)
@@ -12230,9 +12163,6 @@ void Player::RemoveItem(uint8 bag, uint8 slot, bool update)
// remove item dependent auras and casts (only weapon and armor slots)
if (slot < EQUIPMENT_SLOT_END)
{
- if (update)
- RemoveItemDependentAurasAndCasts(pItem);
-
// remove held enchantments, update expertise
if (slot == EQUIPMENT_SLOT_MAINHAND)
{
@@ -12383,9 +12313,6 @@ void Player::DestroyItem(uint8 bag, uint8 slot, bool update)
if (slot < EQUIPMENT_SLOT_END)
{
- // remove item dependent auras and casts (only weapon and armor slots)
- RemoveItemDependentAurasAndCasts(pItem);
-
// update expertise and armor penetration - passive auras may need it
switch (slot)
{
@@ -23591,9 +23518,9 @@ void Player::RemoveItemDependentAurasAndCasts(Item* pItem)
{
Aura* aura = itr->second;
- // skip passive (passive item dependent spells work in another way) and not self applied auras
+ // skip not self applied auras
SpellInfo const* spellInfo = aura->GetSpellInfo();
- if (aura->IsPassive() || aura->GetCasterGUID() != GetGUID())
+ if (aura->GetCasterGUID() != GetGUID())
{
++itr;
continue;
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index 565d4f4ac2f..ed5dc7e954f 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -1958,9 +1958,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
void ResetAllPowers();
- void _ApplyWeaponDependentAuraMods(Item* item, WeaponAttackType attackType, bool apply);
- void _ApplyWeaponDependentAuraCritMod(Item* item, WeaponAttackType attackType, AuraEffect const* aura, bool apply);
- void _ApplyWeaponDependentAuraDamageMod(Item* item, WeaponAttackType attackType, AuraEffect const* aura, bool apply);
+ void ApplyItemDependentAuras(Item* item, bool apply);
void _ApplyItemMods(Item* item, uint8 slot, bool apply);
void _RemoveAllItemMods();
diff --git a/src/server/game/Entities/Unit/StatSystem.cpp b/src/server/game/Entities/Unit/StatSystem.cpp
index 699709fabb1..0cad0b2cb05 100644
--- a/src/server/game/Entities/Unit/StatSystem.cpp
+++ b/src/server/game/Entities/Unit/StatSystem.cpp
@@ -184,8 +184,17 @@ void Player::UpdateSpellDamageAndHealingBonus()
// Get healing bonus for all schools
SetStatInt32Value(PLAYER_FIELD_MOD_HEALING_DONE_POS, SpellBaseHealingBonusDone(SPELL_SCHOOL_MASK_ALL));
// Get damage bonus for all schools
- for (int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i)
- SetStatInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS+i, SpellBaseDamageBonusDone(SpellSchoolMask(1 << i)));
+ Unit::AuraEffectList const& modDamageAuras = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_DONE);
+ for (uint16 i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i)
+ {
+ SetInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + i, std::accumulate(modDamageAuras.begin(), modDamageAuras.end(), 0, [i](int32 negativeMod, AuraEffect const* aurEff)
+ {
+ if (aurEff->GetAmount() < 0 && aurEff->GetMiscValue() & (1 << i))
+ negativeMod += aurEff->GetAmount();
+ return negativeMod;
+ }));
+ SetStatInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + i, SpellBaseDamageBonusDone(SpellSchoolMask(1 << i)) - GetInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + i));
+ }
}
bool Player::UpdateAllStats()
@@ -530,9 +539,9 @@ void Player::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bo
break;
}
- float attackSpeedMod = GetAPMultiplier(attType, normalized);
+ float const attackPowerMod = std::max(GetAPMultiplier(attType, normalized), 0.25f);
- float baseValue = GetModifierValue(unitMod, BASE_VALUE) + GetTotalAttackPowerValue(attType) / 14.0f * attackSpeedMod;
+ float baseValue = GetModifierValue(unitMod, BASE_VALUE) + GetTotalAttackPowerValue(attType) / 14.0f * attackPowerMod;
float basePct = GetModifierValue(unitMod, BASE_PCT);
float totalValue = GetModifierValue(unitMod, TOTAL_VALUE);
float totalPct = addTotalPct ? GetModifierValue(unitMod, TOTAL_PCT) : 1.0f;
@@ -546,8 +555,8 @@ void Player::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bo
if (lvl > 60)
lvl = 60;
- weaponMinDamage = lvl * 0.85f * attackSpeedMod;
- weaponMaxDamage = lvl * 1.25f * attackSpeedMod;
+ weaponMinDamage = lvl * 0.85f * attackPowerMod;
+ weaponMaxDamage = lvl * 1.25f * attackPowerMod;
}
else if (!CanUseAttackType(attType)) // check if player not in form but still can't use (disarm case)
{
@@ -563,8 +572,8 @@ void Player::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bo
}
else if (attType == RANGED_ATTACK) // add ammo DPS to ranged damage
{
- weaponMinDamage += GetAmmoDPS() * attackSpeedMod;
- weaponMaxDamage += GetAmmoDPS() * attackSpeedMod;
+ weaponMinDamage += GetAmmoDPS() * attackPowerMod;
+ weaponMaxDamage += GetAmmoDPS() * attackPowerMod;
}
minDamage = ((weaponMinDamage + baseValue) * basePct + totalValue) * totalPct;
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index 46bb247a6e8..b259bd1444f 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -6685,11 +6685,12 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin
// Impurity (dummy effect)
if (GetTypeId() == TYPEID_PLAYER)
{
- PlayerSpellMap playerSpells = ToPlayer()->GetSpellMap();
- for (PlayerSpellMap::const_iterator itr = playerSpells.begin(); itr != playerSpells.end(); ++itr)
+ PlayerSpellMap const& playerSpells = ToPlayer()->GetSpellMap();
+ for (auto itr = playerSpells.begin(); itr != playerSpells.end(); ++itr)
{
if (itr->second->state == PLAYERSPELL_REMOVED || itr->second->disabled)
continue;
+
switch (itr->first)
{
case 49220:
@@ -6698,7 +6699,7 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin
case 49636:
case 49638:
if (SpellInfo const* proto = sSpellMgr->GetSpellInfo(itr->first))
- AddPct(ApCoeffMod, proto->Effects[0].CalcValue());
+ AddPct(ApCoeffMod, proto->Effects[EFFECT_0].CalcValue());
break;
}
}
@@ -6711,14 +6712,14 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin
// Pets just add their bonus damage to their spell damage
// note that their spell damage is just gain of their own auras
if (HasUnitTypeMask(UNIT_MASK_GUARDIAN))
- DoneAdvertisedBenefit += static_cast<Guardian const*>(this)->GetBonusDamage();
+ DoneAdvertisedBenefit += ((Guardian*)this)->GetBonusDamage();
// Check for table values
- float coeff = 0.f;
+ float coeff = 0.0f;
SpellBonusEntry const* bonus = sSpellMgr->GetSpellBonusData(spellProto->Id);
if (bonus)
{
- WeaponAttackType const attType = (spellProto->IsRangedWeaponSpell() && spellProto->DmgClass != SPELL_DAMAGE_CLASS_MELEE) ? RANGED_ATTACK : BASE_ATTACK;
+ WeaponAttackType attType = (spellProto->IsRangedWeaponSpell() && spellProto->DmgClass != SPELL_DAMAGE_CLASS_MELEE) ? RANGED_ATTACK : BASE_ATTACK;
float APbonus = float(victim->GetTotalAuraModifier(attType == BASE_ATTACK ? SPELL_AURA_MELEE_ATTACK_POWER_ATTACKER_BONUS : SPELL_AURA_RANGED_ATTACK_POWER_ATTACKER_BONUS));
APbonus += GetTotalAttackPowerValue(attType);
@@ -6735,6 +6736,7 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin
DoneTotal += int32(bonus->ap_bonus * stack * ApCoeffMod * APbonus);
}
}
+
// Default calculation
if (DoneAdvertisedBenefit)
{
@@ -6788,24 +6790,17 @@ float Unit::SpellDamagePctDone(Unit* victim, SpellInfo const* spellProto, Damage
if (GetTypeId() == TYPEID_UNIT && !IsPet())
DoneTotalMod *= ToCreature()->GetSpellDamageMod(ToCreature()->GetCreatureTemplate()->rank);
- AuraEffectList const& mModDamagePercentDone = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE);
- for (AuraEffect const* aurEff : mModDamagePercentDone)
+ float maxModDamagePercentSchool = 0.0f;
+ if (GetTypeId() == TYPEID_PLAYER)
{
- SpellInfo const* aurSpellInfo = aurEff->GetSpellInfo();
-
- if (spellProto->EquippedItemClass == -1 && aurSpellInfo->EquippedItemClass != -1) // prevent apply mods from weapon specific case to non weapon specific spells (Example: thunder clap and two-handed weapon specialization)
- continue;
-
- if ((aurEff->GetMiscValue() & spellProto->GetSchoolMask()) != 0)
- {
- if (aurSpellInfo->EquippedItemClass == -1)
- AddPct(DoneTotalMod, aurEff->GetAmount());
- else if (!aurSpellInfo->HasAttribute(SPELL_ATTR5_SPECIAL_ITEM_CLASS_CHECK) && (aurSpellInfo->EquippedItemSubClassMask == 0))
- AddPct(DoneTotalMod, aurEff->GetAmount());
- else if (ToPlayer() && ToPlayer()->HasItemFitToSpellRequirements(aurSpellInfo))
- AddPct(DoneTotalMod, aurEff->GetAmount());
- }
+ for (uint32 i = 0; i < MAX_SPELL_SCHOOL; ++i)
+ if (spellProto->GetSchoolMask() & (1 << i))
+ maxModDamagePercentSchool = std::max(maxModDamagePercentSchool, GetFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT + i));
}
+ else
+ maxModDamagePercentSchool = GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE, spellProto->GetSchoolMask());
+
+ DoneTotalMod *= maxModDamagePercentSchool;
uint32 creatureTypeMask = victim->GetCreatureTypeMask();
@@ -7187,14 +7182,8 @@ int32 Unit::SpellBaseDamageBonusDone(SpellSchoolMask schoolMask) const
AuraEffectList const& mDamageDone = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_DONE);
for (AuraEffect const* aurEff : mDamageDone)
- {
- if (!(aurEff->GetMiscValue() & schoolMask))
- continue;
-
- // only apply generic bonus here, weapon requiring mods are not applicable to non-melee spells
- if (aurEff->GetSpellInfo()->EquippedItemClass == -1 && aurEff->GetSpellInfo()->EquippedItemInventoryTypeMask == 0)
+ if (aurEff->GetMiscValue() & schoolMask)
DoneAdvertisedBenefit += aurEff->GetAmount();
- }
if (GetTypeId() == TYPEID_PLAYER)
{
@@ -7215,7 +7204,6 @@ int32 Unit::SpellBaseDamageBonusDone(SpellSchoolMask schoolMask) const
// ... and attack power
DoneAdvertisedBenefit += static_cast<int32>(CalculatePct(GetTotalAttackPowerValue(BASE_ATTACK), GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_SPELL_DAMAGE_OF_ATTACK_POWER, schoolMask)));
-
}
return DoneAdvertisedBenefit;
@@ -8084,35 +8072,22 @@ uint32 Unit::MeleeDamageBonusDone(Unit* victim, uint32 pdamage, WeaponAttackType
float DoneTotalMod = 1.0f;
// Some spells don't benefit from pct done mods
- if (spellProto && !spellProto->HasAttribute(SPELL_ATTR6_NO_DONE_PCT_DAMAGE_MODS))
+ if (spellProto)
{
- AuraEffectList const& mModDamagePercentDone = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE);
- for (AuraEffect const* aurEff : mModDamagePercentDone)
+ // mods for SPELL_SCHOOL_MASK_NORMAL are already factored in base melee damage calculation
+ if (!spellProto->HasAttribute(SPELL_ATTR6_NO_DONE_PCT_DAMAGE_MODS) && !(spellProto->GetSchoolMask() & SPELL_SCHOOL_MASK_NORMAL))
{
- // Apply mod if schoolmask matches...
- if ((aurEff->GetMiscValue() & spellProto->GetSchoolMask()) != 0)
+ float maxModDamagePercentSchool = 0.0f;
+ if (GetTypeId() == TYPEID_PLAYER)
{
- SpellInfo const* aurSpellInfo = aurEff->GetSpellInfo();
-
- // ... but not for SCHOOL_MASK_NORMAL, or generic weapon bonus, or creatures (creatures don't have equiped items check)
- // for these types the damage was already calculated in AuraEffect handler, and stored into TOTAL_PCT
- // if we include them, we'll be multiplying twice (one in Unit::CalculateDamage, the other here)
- if ((aurEff->GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL) && (aurSpellInfo->EquippedItemClass == -1 || GetTypeId() != TYPEID_PLAYER))
- continue;
-
- // generic weapon bonus (magic)
- if (aurSpellInfo->EquippedItemClass == -1)
- AddPct(DoneTotalMod, aurEff->GetAmount());
- // skips subclassmask check/has generic subclassmask set
- else if (!aurSpellInfo->HasAttribute(SPELL_ATTR5_SPECIAL_ITEM_CLASS_CHECK) && (aurSpellInfo->EquippedItemSubClassMask == 0))
- AddPct(DoneTotalMod, aurEff->GetAmount());
-
- // This one is already applied in Player::_ApplyWeaponDependentAuraDamageMod
- /*
- else if (ToPlayer() && ToPlayer()->HasItemFitToSpellRequirements(aurSpellInfo))
- AddPct(DoneTotalMod, aurEff->GetAmount());
- */
+ for (uint32 i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i)
+ if (spellProto->GetSchoolMask() & (1 << i))
+ maxModDamagePercentSchool = std::max(maxModDamagePercentSchool, GetFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT + i));
}
+ else
+ maxModDamagePercentSchool = GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE, spellProto->GetSchoolMask());
+
+ DoneTotalMod *= maxModDamagePercentSchool;
}
}
@@ -8191,7 +8166,6 @@ uint32 Unit::MeleeDamageBonusDone(Unit* victim, uint32 pdamage, WeaponAttackType
// Custom scripted damage
if (spellProto)
- {
switch (spellProto->SpellFamilyName)
{
case SPELLFAMILY_DEATHKNIGHT:
@@ -8200,9 +8174,8 @@ uint32 Unit::MeleeDamageBonusDone(Unit* victim, uint32 pdamage, WeaponAttackType
if (AuraEffect* aurEff = GetDummyAuraEffect(SPELLFAMILY_DEATHKNIGHT, 196, 0))
if (victim->GetDiseasesByCaster(owner->GetGUID()) > 0)
AddPct(DoneTotalMod, aurEff->GetAmount());
- break;
+ break;
}
- }
float tmpDamage = float(int32(pdamage) + DoneFlatBenefit) * DoneTotalMod;
@@ -11467,26 +11440,41 @@ float Unit::CalculateDefaultCoefficient(SpellInfo const* spellInfo, DamageEffect
float Unit::GetAPMultiplier(WeaponAttackType attType, bool normalized)
{
- if (!normalized || GetTypeId() != TYPEID_PLAYER)
- return float(GetAttackTime(attType)) / 1000.0f;
+ if (GetTypeId() != TYPEID_PLAYER)
+ return GetAttackTime(attType) / 1000.0f;
+
+ Item* weapon = ToPlayer()->GetWeaponForAttack(attType, true);
+ if (!weapon)
+ return BASE_ATTACK_TIME / 1000.0f;
- Item* Weapon = ToPlayer()->GetWeaponForAttack(attType, true);
- if (!Weapon)
- return 2.4f; // fist attack
+ if (!normalized)
+ return weapon->GetTemplate()->Delay / 1000.0f;
- switch (Weapon->GetTemplate()->InventoryType)
+ switch (weapon->GetTemplate()->SubClass)
{
- case INVTYPE_2HWEAPON:
+ case ITEM_SUBCLASS_WEAPON_AXE2:
+ case ITEM_SUBCLASS_WEAPON_MACE2:
+ case ITEM_SUBCLASS_WEAPON_POLEARM:
+ case ITEM_SUBCLASS_WEAPON_SWORD2:
+ case ITEM_SUBCLASS_WEAPON_STAFF:
+ case ITEM_SUBCLASS_WEAPON_FISHING_POLE:
return 3.3f;
- case INVTYPE_RANGED:
- case INVTYPE_RANGEDRIGHT:
- case INVTYPE_THROWN:
+ case ITEM_SUBCLASS_WEAPON_BOW:
+ case ITEM_SUBCLASS_WEAPON_GUN:
+ case ITEM_SUBCLASS_WEAPON_CROSSBOW:
+ case ITEM_SUBCLASS_WEAPON_THROWN:
return 2.8f;
- case INVTYPE_WEAPON:
- case INVTYPE_WEAPONMAINHAND:
- case INVTYPE_WEAPONOFFHAND:
+ case ITEM_SUBCLASS_WEAPON_AXE:
+ case ITEM_SUBCLASS_WEAPON_MACE:
+ case ITEM_SUBCLASS_WEAPON_SWORD:
+ case ITEM_SUBCLASS_WEAPON_EXOTIC:
+ case ITEM_SUBCLASS_WEAPON_EXOTIC2:
+ case ITEM_SUBCLASS_WEAPON_FIST:
+ return 2.4f;
+ case ITEM_SUBCLASS_WEAPON_DAGGER:
+ return 1.7f;
default:
- return Weapon->GetTemplate()->SubClass == ITEM_SUBCLASS_WEAPON_DAGGER ? 1.7f : 2.4f;
+ return weapon->GetTemplate()->Delay / 1000.0f;
}
}
diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h
index bc84e3fde29..bf913081fef 100644
--- a/src/server/game/Miscellaneous/SharedDefines.h
+++ b/src/server/game/Miscellaneous/SharedDefines.h
@@ -472,7 +472,7 @@ enum SpellAttr5
SPELL_ATTR5_HASTE_AFFECT_DURATION = 0x00002000, // 13 haste effects decrease duration of this
SPELL_ATTR5_UNK14 = 0x00004000, // 14
SPELL_ATTR5_UNK15 = 0x00008000, // 15 Inflits on multiple targets?
- SPELL_ATTR5_SPECIAL_ITEM_CLASS_CHECK = 0x00010000, // 16 this allows spells with EquippedItemClass to affect spells from other items if the required item is equipped
+ SPELL_ATTR5_UNK16 = 0x00010000, // 16
SPELL_ATTR5_USABLE_WHILE_FEARED = 0x00020000, // 17 usable while feared
SPELL_ATTR5_USABLE_WHILE_CONFUSED = 0x00040000, // 18 usable while confused
SPELL_ATTR5_DONT_TURN_DURING_CAST = 0x00080000, // 19 Blocks caster's turning when casting (client does not automatically turn caster's model to face UNIT_FIELD_TARGET)
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
index 6db6abd5177..2b4e2e4177d 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
@@ -2307,11 +2307,9 @@ void AuraEffect::HandleAuraModDisarm(AuraApplication const* aurApp, uint8 mode,
{
uint8 attacktype = Player::GetAttackBySlot(slot);
+ player->ApplyItemDependentAuras(item, !apply);
if (attacktype < MAX_ATTACK)
- {
player->_ApplyWeaponDamage(slot, item->GetTemplate(), NULL, !apply);
- player->_ApplyWeaponDependentAuraMods(item, WeaponAttackType(attacktype), !apply);
- }
}
}
@@ -3768,29 +3766,14 @@ void AuraEffect::HandleAuraModWeaponCritPercent(AuraApplication const* aurApp, u
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
- Unit* target = aurApp->GetTarget();
+ Player* target = aurApp->GetTarget()->ToPlayer();
- if (target->GetTypeId() != TYPEID_PLAYER)
+ if (!target)
return;
- for (int i = 0; i < MAX_ATTACK; ++i)
- if (Item* pItem = target->ToPlayer()->GetWeaponForAttack(WeaponAttackType(i), true))
- target->ToPlayer()->_ApplyWeaponDependentAuraCritMod(pItem, WeaponAttackType(i), this, apply);
-
- // mods must be applied base at equipped weapon class and subclass comparison
- // with spell->EquippedItemClass and EquippedItemSubClassMask and EquippedItemInventoryTypeMask
- // GetMiscValue() comparison with item generated damage types
-
- if (GetSpellInfo()->EquippedItemClass == -1)
- {
- 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);
- }
- else
- {
- // done in Player::_ApplyWeaponDependentAuraMods
- }
+ 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);
}
void AuraEffect::HandleModHitChance(AuraApplication const* aurApp, uint8 mode, bool apply) const
@@ -4091,6 +4074,7 @@ void AuraEffect::HandleAuraModAttackPowerOfArmor(AuraApplication const* aurApp,
if (target->GetTypeId() == TYPEID_PLAYER)
target->ToPlayer()->UpdateAttackPowerAndDamage(false);
}
+
/********************************/
/*** DAMAGE BONUS ***/
/********************************/
@@ -4101,76 +4085,22 @@ void AuraEffect::HandleModDamageDone(AuraApplication const* aurApp, uint8 mode,
Unit* target = aurApp->GetTarget();
- // apply item specific bonuses for already equipped weapon
- if (target->GetTypeId() == TYPEID_PLAYER)
- {
- for (int i = 0; i < MAX_ATTACK; ++i)
- if (Item* pItem = target->ToPlayer()->GetWeaponForAttack(WeaponAttackType(i), true))
- target->ToPlayer()->_ApplyWeaponDependentAuraDamageMod(pItem, WeaponAttackType(i), this, apply);
- }
-
- // GetMiscValue() is bitmask of spell schools
- // 1 (0-bit) - normal school damage (SPELL_SCHOOL_MASK_NORMAL)
- // 126 - full bitmask all magic damages (SPELL_SCHOOL_MASK_MAGIC) including wands
- // 127 - full bitmask any damages
- //
- // mods must be applied base at equipped weapon class and subclass comparison
- // with spell->EquippedItemClass and EquippedItemSubClassMask and EquippedItemInventoryTypeMask
- // GetMiscValue() comparison with item generated damage types
-
- // apply generic physical damage bonuses including wand case
- if ((GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL) && (GetSpellInfo()->EquippedItemClass == -1 || target->GetTypeId() != TYPEID_PLAYER))
+ 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);
-
- if (target->GetTypeId() == TYPEID_PLAYER)
- {
- if (GetAmount() > 0)
- target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS, GetAmount(), apply);
- else
- target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG, GetAmount(), apply);
- }
}
- else
- {
- // done in Player::_ApplyWeaponDependentAuraMods
- }
-
- // Skip non magic case for speedup
- if ((GetMiscValue() & SPELL_SCHOOL_MASK_MAGIC) == 0)
- return;
-
- if (GetSpellInfo()->EquippedItemClass != -1 || GetSpellInfo()->EquippedItemInventoryTypeMask != 0)
- {
- // wand magic case (skip generic to all item spell bonuses)
- // done in Player::_ApplyWeaponDependentAuraMods
- // Skip item specific requirements for not wand magic damage
- return;
- }
-
- // Magic damage modifiers implemented in Unit::SpellDamageBonus
+ // Magic damage modifiers implemented in Unit::SpellBaseDamageBonusDone
// This information for client side use only
if (target->GetTypeId() == TYPEID_PLAYER)
{
- if (GetAmount() > 0)
- {
- for (int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; i++)
- {
- if ((GetMiscValue() & (1<<i)) != 0)
- target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS+i, GetAmount(), apply);
- }
- }
- else
- {
- for (int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; i++)
- {
- if ((GetMiscValue() & (1<<i)) != 0)
- target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG+i, GetAmount(), apply);
- }
- }
+ uint16 baseField = GetAmount() >= 0 ? PLAYER_FIELD_MOD_DAMAGE_DONE_POS : PLAYER_FIELD_MOD_DAMAGE_DONE_NEG;
+ for (uint16 i = 0; i < MAX_SPELL_SCHOOL; ++i)
+ if (GetMiscValue() & (1 << i))
+ target->ApplyModUInt32Value(baseField + i, GetAmount(), apply);
+
if (Guardian* pet = target->ToPlayer()->GetGuardianPet())
pet->UpdateAttackPowerAndDamage();
}
@@ -4186,14 +4116,7 @@ void AuraEffect::HandleModDamagePercentDone(AuraApplication const* aurApp, uint8
if (abs(spellGroupVal) >= abs(GetAmount()))
return;
- if (target->GetTypeId() == TYPEID_PLAYER)
- {
- for (int i = 0; i < MAX_ATTACK; ++i)
- if (Item* item = target->ToPlayer()->GetWeaponForAttack(WeaponAttackType(i), false))
- target->ToPlayer()->_ApplyWeaponDependentAuraDamageMod(item, WeaponAttackType(i), this, apply);
- }
-
- if ((GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL) && (GetSpellInfo()->EquippedItemClass == -1 || target->GetTypeId() != TYPEID_PLAYER))
+ if (GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL)
{
if (spellGroupVal)
{
@@ -4201,22 +4124,25 @@ void AuraEffect::HandleModDamagePercentDone(AuraApplication const* aurApp, uint8
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);
+ }
- if (Player* player = target->ToPlayer())
+ if (target->GetTypeId() == TYPEID_PLAYER)
+ {
+ for (uint16 i = 0; i < MAX_SPELL_SCHOOL; ++i)
{
- if (spellGroupVal)
- player->ApplyPercentModFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT, float(spellGroupVal), !apply);
+ if (GetMiscValue() & (1 << i))
+ {
+ if (spellGroupVal)
+ target->ApplyPercentModFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT + i, float(spellGroupVal), !apply);
- player->ApplyPercentModFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT, float(GetAmount()), apply);
+ target->ApplyPercentModFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT + i, float(GetAmount()), apply);
+ }
}
}
- else
- {
- // done in Player::_ApplyWeaponDependentAuraMods for SPELL_SCHOOL_MASK_NORMAL && EquippedItemClass != -1 and also for wand case
- }
}
void AuraEffect::HandleModOffhandDamagePercent(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 21950a1385b..7afcf52172a 100644
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -3380,8 +3380,10 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex)
}
}
- // apply to non-weapon bonus weapon total pct effect, weapon total flat effect included in weapon damage
- if (fixed_bonus || spell_bonus)
+ // if (addPctMods) { percent mods are added in Unit::CalculateDamage } else { percent mods are added in Unit::MeleeDamageBonusDone }
+ // this distinction is neccessary to properly inform the client about his autoattack damage values from Script_UnitDamage
+ bool addPctMods = !m_spellInfo->HasAttribute(SPELL_ATTR6_NO_DONE_PCT_DAMAGE_MODS) && (m_spellSchoolMask & SPELL_SCHOOL_MASK_NORMAL);
+ if (addPctMods)
{
UnitMods unitMod;
switch (m_attackType)
@@ -3392,17 +3394,14 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex)
case RANGED_ATTACK: unitMod = UNIT_MOD_DAMAGE_RANGED; break;
}
- float weapon_total_pct = 1.0f;
- if (m_spellInfo->SchoolMask & SPELL_SCHOOL_MASK_NORMAL)
- weapon_total_pct = m_caster->GetModifierValue(unitMod, TOTAL_PCT);
-
+ float weapon_total_pct = m_caster->GetModifierValue(unitMod, TOTAL_PCT);
if (fixed_bonus)
fixed_bonus = int32(fixed_bonus * weapon_total_pct);
if (spell_bonus)
spell_bonus = int32(spell_bonus * weapon_total_pct);
}
- int32 weaponDamage = m_caster->CalculateDamage(m_attackType, normalized, true);
+ int32 weaponDamage = m_caster->CalculateDamage(m_attackType, normalized, addPctMods);
// Sequence is important
for (int j = 0; j < MAX_SPELL_EFFECTS; ++j)
@@ -3417,17 +3416,14 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex)
weaponDamage += fixed_bonus;
break;
case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE:
- weaponDamage = int32(weaponDamage* weaponDamagePercentMod);
+ weaponDamage = int32(weaponDamage * weaponDamagePercentMod);
default:
break; // not weapon damage effect, just skip
}
}
- if (spell_bonus)
- weaponDamage += spell_bonus;
-
- if (totalDamagePercentMod != 1.0f)
- weaponDamage = int32(weaponDamage* totalDamagePercentMod);
+ weaponDamage += spell_bonus;
+ weaponDamage = int32(weaponDamage * totalDamagePercentMod);
// prevent negative damage
uint32 eff_damage(std::max(weaponDamage, 0));