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 /src/server/game/Entities | |
| 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
Diffstat (limited to 'src/server/game/Entities')
| -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 |
4 files changed, 85 insertions, 159 deletions
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; } } |
