diff options
Diffstat (limited to 'src')
| -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 | 25 | ||||
| -rw-r--r-- | src/server/game/Entities/Unit/Unit.cpp | 132 | ||||
| -rw-r--r-- | src/server/game/Miscellaneous/SharedDefines.h | 2 | ||||
| -rw-r--r-- | src/server/game/Spells/Auras/SpellAuraEffects.cpp | 126 | ||||
| -rw-r--r-- | src/server/game/Spells/SpellEffects.cpp | 22 |
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)); |
