diff options
author | Shauren <shauren.trinity@gmail.com> | 2016-11-20 00:44:49 +0100 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2016-11-20 00:44:49 +0100 |
commit | b9f7b500a362736235fc917ce4f34aa8520eb651 (patch) | |
tree | 68e867fe3f1d4f8576ecf4e496d573340b901457 | |
parent | 28fd8a424d828f36a2b05ed016b12c4b8cf2607c (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.h | 1 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 111 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.h | 4 | ||||
-rw-r--r-- | src/server/game/Entities/Unit/StatSystem.cpp | 15 | ||||
-rw-r--r-- | src/server/game/Entities/Unit/Unit.cpp | 114 | ||||
-rw-r--r-- | src/server/game/Miscellaneous/SharedDefines.h | 2 | ||||
-rw-r--r-- | src/server/game/Spells/Auras/SpellAuraEffects.cpp | 135 | ||||
-rw-r--r-- | src/server/game/Spells/SpellEffects.cpp | 22 |
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)); |