aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2016-11-20 00:44:49 +0100
committerShauren <shauren.trinity@gmail.com>2016-11-20 00:44:49 +0100
commitb9f7b500a362736235fc917ce4f34aa8520eb651 (patch)
tree68e867fe3f1d4f8576ecf4e496d573340b901457
parent28fd8a424d828f36a2b05ed016b12c4b8cf2607c (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
-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.cpp15
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp114
-rw-r--r--src/server/game/Miscellaneous/SharedDefines.h2
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.cpp135
-rw-r--r--src/server/game/Spells/SpellEffects.cpp22
8 files changed, 125 insertions, 279 deletions
diff --git a/src/common/Common.h b/src/common/Common.h
index c4180396a28..1034b7731ef 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 88da389f48d..794ca9e9ab8 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -7144,11 +7144,9 @@ void Player::_ApplyItemMods(Item* item, uint8 slot, bool apply)
if (item->GetSocketColor(0)) //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(item, slot, apply);
ApplyItemEquipSpell(item, apply);
+ ApplyItemDependentAuras(item, apply);
ApplyArtifactPowers(item, apply);
ApplyEnchantment(item, apply);
@@ -7477,86 +7475,26 @@ void Player::_ApplyWeaponDamage(uint8 slot, Item* item, bool apply)
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)
-{
- // 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)
+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;
-
- // ignore spell mods for not wands
- if ((aura->GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL) == 0 && (getClassMask() & CLASSMASK_WAND_USERS) == 0)
- return;
-
- // generic not weapon specific case processes in aura code
- 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 formChange /*= false*/)
@@ -8018,10 +7956,7 @@ void Player::_RemoveAllItemMods()
if (m_items[i]->IsBroken() || !CanUseAttackType(Player::GetAttackBySlot(i, m_items[i]->GetTemplate()->GetInventoryType())))
continue;
- uint32 attacktype = Player::GetAttackBySlot(i, m_items[i]->GetTemplate()->GetInventoryType());
- if (attacktype < MAX_ATTACK)
- _ApplyWeaponDependentAuraMods(m_items[i], WeaponAttackType(attacktype), false);
-
+ ApplyItemDependentAuras(m_items[i], false);
_ApplyItemBonuses(m_items[i], i, false);
}
}
@@ -8040,10 +7975,7 @@ void Player::_ApplyAllItemMods()
if (m_items[i]->IsBroken() || !CanUseAttackType(Player::GetAttackBySlot(i, m_items[i]->GetTemplate()->GetInventoryType())))
continue;
- uint32 attacktype = Player::GetAttackBySlot(i, m_items[i]->GetTemplate()->GetInventoryType());
- if (attacktype < MAX_ATTACK)
- _ApplyWeaponDependentAuraMods(m_items[i], WeaponAttackType(attacktype), true);
-
+ ApplyItemDependentAuras(m_items[i], true);
_ApplyItemBonuses(m_items[i], i, true);
}
}
@@ -12011,8 +11943,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)
{
- RemoveItemDependentAurasAndCasts(pItem);
-
// remove held enchantments, update expertise
if (slot == EQUIPMENT_SLOT_MAINHAND)
{
@@ -12161,9 +12091,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)
{
@@ -24171,9 +24098,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 0149922e563..3bd36086101 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -2148,9 +2148,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 04124e71c6e..dac82f8302a 100644
--- a/src/server/game/Entities/Unit/StatSystem.cpp
+++ b/src/server/game/Entities/Unit/StatSystem.cpp
@@ -173,8 +173,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));
+ }
if (HasAuraType(SPELL_AURA_OVERRIDE_ATTACK_POWER_BY_SP_PCT))
{
@@ -410,7 +419,7 @@ void Player::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bo
break;
}
- float attackPowerMod = GetAPMultiplier(attType, normalized);
+ 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);
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index 3767549fa7f..0e083d669cb 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -7879,7 +7879,6 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin
if (Unit* owner = GetOwner())
return owner->SpellDamageBonusDone(victim, spellProto, pdamage, damagetype, effect, stack);
- float ApCoeffMod = 1.0f;
int32 DoneTotal = 0;
// Done fixed damage bonus auras
@@ -7890,16 +7889,24 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin
DoneAdvertisedBenefit += ((Guardian*)this)->GetBonusDamage();
// Check for table values
- float coeff = effect->BonusCoefficient;
- if (effect->BonusCoefficientFromAP > 0)
+ if (effect->BonusCoefficientFromAP > 0.0f)
{
+ float ApCoeffMod = effect->BonusCoefficientFromAP;
+ if (Player* modOwner = GetSpellModOwner())
+ {
+ ApCoeffMod *= 100.0f;
+ modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_BONUS_MULTIPLIER, ApCoeffMod);
+ ApCoeffMod /= 100.0f;
+ }
+
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);
- DoneTotal += int32(effect->BonusCoefficientFromAP * stack * ApCoeffMod * APbonus);
+ DoneTotal += int32(stack * ApCoeffMod * APbonus);
}
// Default calculation
+ float coeff = effect->BonusCoefficient;
if (DoneAdvertisedBenefit)
{
float factorMod = CalculateLevelPenalty(spellProto) * stack;
@@ -7942,22 +7949,12 @@ 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 (AuraEffectList::const_iterator i = mModDamagePercentDone.begin(); i != mModDamagePercentDone.end(); ++i)
- {
- if (spellProto->EquippedItemClass == -1 && (*i)->GetSpellInfo()->EquippedItemClass != -1) //prevent apply mods from weapon specific case to non weapon specific spells (Example: thunder clap and two-handed weapon specialization)
- continue;
+ float maxModDamagePercentSchool = 0.0f;
+ 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));
- if ((*i)->GetMiscValue() & spellProto->GetSchoolMask())
- {
- if ((*i)->GetSpellInfo()->EquippedItemClass == -1)
- AddPct(DoneTotalMod, (*i)->GetAmount());
- else if (!(*i)->GetSpellInfo()->HasAttribute(SPELL_ATTR5_SPECIAL_ITEM_CLASS_CHECK) && ((*i)->GetSpellInfo()->EquippedItemSubClassMask == 0))
- AddPct(DoneTotalMod, (*i)->GetAmount());
- else if (ToPlayer() && ToPlayer()->HasItemFitToSpellRequirements((*i)->GetSpellInfo()))
- AddPct(DoneTotalMod, (*i)->GetAmount());
- }
- }
+ DoneTotalMod *= maxModDamagePercentSchool;
uint32 creatureTypeMask = victim->GetCreatureTypeMask();
@@ -8151,11 +8148,7 @@ int32 Unit::SpellBaseDamageBonusDone(SpellSchoolMask schoolMask) const
AuraEffectList const& mDamageDone = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_DONE);
for (AuraEffectList::const_iterator i = mDamageDone.begin(); i != mDamageDone.end(); ++i)
- if (((*i)->GetMiscValue() & schoolMask) != 0 &&
- (*i)->GetSpellInfo()->EquippedItemClass == -1 &&
- // -1 == any item class (not wand then)
- (*i)->GetSpellInfo()->EquippedItemInventoryTypeMask == 0)
- // 0 == any inventory type (not wand then)
+ if ((*i)->GetMiscValue() & schoolMask)
DoneAdvertisedBenefit += (*i)->GetAmount();
if (GetTypeId() == TYPEID_PLAYER)
@@ -8893,15 +8886,8 @@ uint32 Unit::MeleeDamageBonusDone(Unit* victim, uint32 pdamage, WeaponAttackType
if (APbonus != 0) // Can be negative
{
- bool normalized = false;
- if (spellProto)
- for (SpellEffectInfo const* effect : spellProto->GetEffectsForDifficulty(GetMap()->GetDifficultyID()))
- if (effect && effect->Effect == SPELL_EFFECT_NORMALIZED_WEAPON_DMG)
- {
- normalized = true;
- break;
- }
- DoneFlatBenefit += int32(APbonus/14.0f * GetAPMultiplier(attType, normalized));
+ bool normalized = spellProto && spellProto->HasEffect(GetMap()->GetDifficultyID(), SPELL_EFFECT_NORMALIZED_WEAPON_DMG);
+ DoneFlatBenefit += int32(APbonus / 3.5f * GetAPMultiplier(attType, normalized));
}
// Done total percent damage auras
@@ -8909,22 +8895,18 @@ uint32 Unit::MeleeDamageBonusDone(Unit* victim, uint32 pdamage, WeaponAttackType
// Some spells don't benefit from pct done mods
if (spellProto)
- if (!spellProto->HasAttribute(SPELL_ATTR6_NO_DONE_PCT_DAMAGE_MODS))
+ {
+ // 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))
{
- AuraEffectList const& mModDamagePercentDone = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE);
- for (AuraEffectList::const_iterator i = mModDamagePercentDone.begin(); i != mModDamagePercentDone.end(); ++i)
- {
- if ((*i)->GetMiscValue() & spellProto->GetSchoolMask() && !(spellProto->GetSchoolMask() & SPELL_SCHOOL_MASK_NORMAL))
- {
- if ((*i)->GetSpellInfo()->EquippedItemClass == -1)
- AddPct(DoneTotalMod, (*i)->GetAmount());
- else if (!(*i)->GetSpellInfo()->HasAttribute(SPELL_ATTR5_SPECIAL_ITEM_CLASS_CHECK) && ((*i)->GetSpellInfo()->EquippedItemSubClassMask == 0))
- AddPct(DoneTotalMod, (*i)->GetAmount());
- else if (ToPlayer() && ToPlayer()->HasItemFitToSpellRequirements((*i)->GetSpellInfo()))
- AddPct(DoneTotalMod, (*i)->GetAmount());
- }
- }
+ float maxModDamagePercentSchool = 0.0f;
+ 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));
+
+ DoneTotalMod *= maxModDamagePercentSchool;
}
+ }
AuraEffectList const& mDamageDoneVersus = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_DONE_VERSUS);
for (AuraEffectList::const_iterator i = mDamageDoneVersus.begin(); i != mDamageDoneVersus.end(); ++i)
@@ -12629,25 +12611,35 @@ float Unit::GetAPMultiplier(WeaponAttackType attType, bool normalized)
return GetAttackTime(attType) / 1000.0f;
Item* weapon = ToPlayer()->GetWeaponForAttack(attType, true);
- if (!normalized)
- return (weapon ? weapon->GetTemplate()->GetDelay() : BASE_ATTACK_TIME) / 1000.0f;
-
if (!weapon)
- return 2.4f; // fist attack
+ return 2.0f;
+
+ if (!normalized)
+ return weapon->GetTemplate()->GetDelay() / 1000.0f;
- switch (weapon->GetTemplate()->GetInventoryType())
+ switch (weapon->GetTemplate()->GetSubClass())
{
- 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:
- 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_WARGLAIVES:
+ case ITEM_SUBCLASS_WEAPON_EXOTIC:
+ case ITEM_SUBCLASS_WEAPON_EXOTIC2:
+ case ITEM_SUBCLASS_WEAPON_FIST_WEAPON:
+ return 2.4f;
+ case ITEM_SUBCLASS_WEAPON_DAGGER:
+ return 1.7f;
+ case ITEM_SUBCLASS_WEAPON_THROWN:
+ return 2.0f;
default:
- return weapon->GetTemplate()->GetSubClass() == ITEM_SUBCLASS_WEAPON_DAGGER ? 1.7f : 2.4f;
+ return weapon->GetTemplate()->GetDelay() / 1000.0f;
}
}
diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h
index 438ed91481c..db49ea99f42 100644
--- a/src/server/game/Miscellaneous/SharedDefines.h
+++ b/src/server/game/Miscellaneous/SharedDefines.h
@@ -554,7 +554,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 67764d20f82..db55e86d87a 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
@@ -2359,11 +2359,9 @@ void AuraEffect::HandleAuraModDisarm(AuraApplication const* aurApp, uint8 mode,
{
uint8 attacktype = Player::GetAttackBySlot(slot, item->GetTemplate()->GetInventoryType());
+ player->ApplyItemDependentAuras(item, !apply);
if (attacktype < MAX_ATTACK)
- {
player->_ApplyWeaponDamage(slot, item, !apply);
- player->_ApplyWeaponDependentAuraMods(item, WeaponAttackType(attacktype), !apply);
- }
}
}
@@ -4263,29 +4261,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
@@ -4560,6 +4543,7 @@ void AuraEffect::HandleAuraModAttackPowerOfArmor(AuraApplication const* aurApp,
if (target->GetTypeId() == TYPEID_PLAYER)
target->ToPlayer()->UpdateAttackPowerAndDamage(false);
}
+
/********************************/
/*** DAMAGE BONUS ***/
/********************************/
@@ -4570,79 +4554,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)
+ if (GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL)
{
- 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);
+ 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);
}
- // 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
-
- if ((GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL) != 0)
- {
- // apply generic physical damage bonuses including wand case
- if (GetSpellInfo()->EquippedItemClass == -1 || target->GetTypeId() != TYPEID_PLAYER)
- {
- 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();
}
@@ -4658,14 +4585,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)
{
@@ -4673,22 +4593,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 0ab8a0e5439..b15a83f8f60 100644
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -3012,8 +3012,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)
@@ -3024,17 +3026,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 (SpellEffectInfo const* effect : GetEffects())
@@ -3051,17 +3050,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));