mirror of
https://github.com/mangosfour/server.git
synced 2025-12-13 22:37:03 +00:00
[8635] Rewrote bonus damage claculation
* calculation depends on the damageClass now ->SPELL_DAMAGE_CLASS_RANGED & SPELL_DAMAGE_CLASS_MELEE use MeleeDamageBonus() ->SPELL_DAMAGE_CLASS_MAGIC & SPELL_DAMAGE_CLASS_RANGED use SpellDamageBonus() * changes/improvements in MeleeDamageBonus: -> improved criterions to apply bonuses -> implemented scaling of FLAT damage Bonus for non weapon damage based spells -> support of DOT's -> added pet's bonus damage for non weapon based spells * general cleanup in CalculateSpellDamage() and MeleeDamageBonus() * implemented global helper functions GetWeaponAttackType() and GetAuraTicks() in SpellMgr Signed-off-by: ApoC <apoc@nymfe.net>
This commit is contained in:
parent
29fde5f671
commit
c47cf7bd61
9 changed files with 414 additions and 290 deletions
|
|
@ -1004,6 +1004,15 @@ enum SpellImmunity
|
||||||
|
|
||||||
#define MAX_SPELL_IMMUNITY 6
|
#define MAX_SPELL_IMMUNITY 6
|
||||||
|
|
||||||
|
enum WeaponAttackType
|
||||||
|
{
|
||||||
|
BASE_ATTACK = 0,
|
||||||
|
OFF_ATTACK = 1,
|
||||||
|
RANGED_ATTACK = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
#define MAX_ATTACK 3
|
||||||
|
|
||||||
enum Targets
|
enum Targets
|
||||||
{
|
{
|
||||||
TARGET_SELF = 1,
|
TARGET_SELF = 1,
|
||||||
|
|
|
||||||
|
|
@ -351,25 +351,7 @@ Spell::Spell( Unit* Caster, SpellEntry const *info, bool triggered, uint64 origi
|
||||||
m_applyMultiplierMask = 0;
|
m_applyMultiplierMask = 0;
|
||||||
|
|
||||||
// Get data for type of attack
|
// Get data for type of attack
|
||||||
switch (m_spellInfo->DmgClass)
|
m_attackType = GetWeaponAttackType(m_spellInfo);
|
||||||
{
|
|
||||||
case SPELL_DAMAGE_CLASS_MELEE:
|
|
||||||
if (m_spellInfo->AttributesEx3 & SPELL_ATTR_EX3_REQ_OFFHAND)
|
|
||||||
m_attackType = OFF_ATTACK;
|
|
||||||
else
|
|
||||||
m_attackType = BASE_ATTACK;
|
|
||||||
break;
|
|
||||||
case SPELL_DAMAGE_CLASS_RANGED:
|
|
||||||
m_attackType = RANGED_ATTACK;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// Wands
|
|
||||||
if (m_spellInfo->AttributesEx2 & SPELL_ATTR_EX2_AUTOREPEAT_FLAG)
|
|
||||||
m_attackType = RANGED_ATTACK;
|
|
||||||
else
|
|
||||||
m_attackType = BASE_ATTACK;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_spellSchoolMask = GetSpellSchoolMask(info); // Can be override for some spell (wand shoot for example)
|
m_spellSchoolMask = GetSpellSchoolMask(info); // Can be override for some spell (wand shoot for example)
|
||||||
|
|
||||||
|
|
@ -997,7 +979,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo *target)
|
||||||
SpellNonMeleeDamage damageInfo(caster, unitTarget, m_spellInfo->Id, m_spellSchoolMask);
|
SpellNonMeleeDamage damageInfo(caster, unitTarget, m_spellInfo->Id, m_spellSchoolMask);
|
||||||
|
|
||||||
// Add bonuses and fill damageInfo struct
|
// Add bonuses and fill damageInfo struct
|
||||||
caster->CalculateSpellDamage(&damageInfo, m_damage, m_spellInfo);
|
caster->CalculateSpellDamage(&damageInfo, m_damage, m_spellInfo, m_attackType);
|
||||||
caster->DealDamageMods(damageInfo.target, damageInfo.damage, &damageInfo.absorb);
|
caster->DealDamageMods(damageInfo.target, damageInfo.damage, &damageInfo.absorb);
|
||||||
|
|
||||||
// Send log damage message to client
|
// Send log damage message to client
|
||||||
|
|
|
||||||
|
|
@ -6281,9 +6281,19 @@ void Aura::PeriodicTick()
|
||||||
{
|
{
|
||||||
pdamage = amount;
|
pdamage = amount;
|
||||||
|
|
||||||
|
// SpellDamageBonus for magic spells
|
||||||
|
if(GetSpellProto()->DmgClass == SPELL_DAMAGE_CLASS_NONE || GetSpellProto()->DmgClass == SPELL_DAMAGE_CLASS_MAGIC)
|
||||||
|
pdamage = pCaster->SpellDamageBonus(m_target, GetSpellProto(), pdamage, DOT, GetStackAmount());
|
||||||
|
// MeleeDamagebonus for weapon based spells
|
||||||
|
else
|
||||||
|
{
|
||||||
|
WeaponAttackType attackType = GetWeaponAttackType(GetSpellProto());
|
||||||
|
pdamage = pCaster->MeleeDamageBonus(m_target, pdamage, attackType, GetSpellProto(), DOT, GetStackAmount());
|
||||||
|
}
|
||||||
|
|
||||||
// Calculate armor mitigation if it is a physical spell
|
// Calculate armor mitigation if it is a physical spell
|
||||||
// But not for bleed mechanic spells
|
// But not for bleed mechanic spells
|
||||||
if ( GetSpellSchoolMask(GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL &&
|
if (GetSpellSchoolMask(GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL &&
|
||||||
GetEffectMechanic(GetSpellProto(), m_effIndex) != MECHANIC_BLEED)
|
GetEffectMechanic(GetSpellProto(), m_effIndex) != MECHANIC_BLEED)
|
||||||
{
|
{
|
||||||
uint32 pdamageReductedArmor = pCaster->CalcArmorReducedDamage(m_target, pdamage);
|
uint32 pdamageReductedArmor = pCaster->CalcArmorReducedDamage(m_target, pdamage);
|
||||||
|
|
@ -6291,8 +6301,6 @@ void Aura::PeriodicTick()
|
||||||
pdamage = pdamageReductedArmor;
|
pdamage = pdamageReductedArmor;
|
||||||
}
|
}
|
||||||
|
|
||||||
pdamage = pCaster->SpellDamageBonus(m_target, GetSpellProto(), pdamage, DOT, GetStackAmount());
|
|
||||||
|
|
||||||
// Curse of Agony damage-per-tick calculation
|
// Curse of Agony damage-per-tick calculation
|
||||||
if (GetSpellProto()->SpellFamilyName==SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags & UI64LIT(0x0000000000000400)) && GetSpellProto()->SpellIconID==544)
|
if (GetSpellProto()->SpellFamilyName==SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags & UI64LIT(0x0000000000000400)) && GetSpellProto()->SpellIconID==544)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -4609,11 +4609,7 @@ void Spell::EffectWeaponDmg(uint32 i)
|
||||||
bonus = int32(bonus*totalDamagePercentMod);
|
bonus = int32(bonus*totalDamagePercentMod);
|
||||||
|
|
||||||
// prevent negative damage
|
// prevent negative damage
|
||||||
uint32 eff_damage = uint32(bonus > 0 ? bonus : 0);
|
m_damage+= uint32(bonus > 0 ? bonus : 0);
|
||||||
|
|
||||||
// Add melee damage bonuses (also check for negative)
|
|
||||||
m_caster->MeleeDamageBonus(unitTarget, &eff_damage, m_attackType, m_spellInfo);
|
|
||||||
m_damage+= eff_damage;
|
|
||||||
|
|
||||||
// Hemorrhage
|
// Hemorrhage
|
||||||
if (m_spellInfo->SpellFamilyName==SPELLFAMILY_ROGUE && (m_spellInfo->SpellFamilyFlags & UI64LIT(0x2000000)))
|
if (m_spellInfo->SpellFamilyName==SPELLFAMILY_ROGUE && (m_spellInfo->SpellFamilyFlags & UI64LIT(0x2000000)))
|
||||||
|
|
|
||||||
|
|
@ -90,6 +90,60 @@ uint32 GetSpellCastTime(SpellEntry const* spellInfo, Spell const* spell)
|
||||||
return (castTime > 0) ? uint32(castTime) : 0;
|
return (castTime > 0) ? uint32(castTime) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint16 GetSpellAuraMaxTicks(SpellEntry const* spellInfo)
|
||||||
|
{
|
||||||
|
int32 DotDuration = GetSpellDuration(spellInfo);
|
||||||
|
if(DotDuration == 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
// 200% limit
|
||||||
|
if(DotDuration > 30000)
|
||||||
|
DotDuration = 30000;
|
||||||
|
|
||||||
|
int j = 0;
|
||||||
|
for( ; j < 3; j++)
|
||||||
|
{
|
||||||
|
if( spellInfo->Effect[j] == SPELL_EFFECT_APPLY_AURA && (
|
||||||
|
spellInfo->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_DAMAGE ||
|
||||||
|
spellInfo->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_HEAL ||
|
||||||
|
spellInfo->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_LEECH) )
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(spellInfo->EffectAmplitude[j] != 0)
|
||||||
|
return DotDuration / spellInfo->EffectAmplitude[j];
|
||||||
|
|
||||||
|
return 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
WeaponAttackType GetWeaponAttackType(SpellEntry const *spellInfo)
|
||||||
|
{
|
||||||
|
if(!spellInfo)
|
||||||
|
return BASE_ATTACK;
|
||||||
|
|
||||||
|
switch (spellInfo->DmgClass)
|
||||||
|
{
|
||||||
|
case SPELL_DAMAGE_CLASS_MELEE:
|
||||||
|
if (spellInfo->AttributesEx3 & SPELL_ATTR_EX3_REQ_OFFHAND)
|
||||||
|
return OFF_ATTACK;
|
||||||
|
else
|
||||||
|
return BASE_ATTACK;
|
||||||
|
break;
|
||||||
|
case SPELL_DAMAGE_CLASS_RANGED:
|
||||||
|
return RANGED_ATTACK;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Wands
|
||||||
|
if (spellInfo->AttributesEx2 & SPELL_ATTR_EX2_AUTOREPEAT_FLAG)
|
||||||
|
return RANGED_ATTACK;
|
||||||
|
else
|
||||||
|
return BASE_ATTACK;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool IsPassiveSpell(uint32 spellId)
|
bool IsPassiveSpell(uint32 spellId)
|
||||||
{
|
{
|
||||||
SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId);
|
SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId);
|
||||||
|
|
|
||||||
|
|
@ -125,6 +125,8 @@ inline float GetSpellMaxRange(SpellRangeEntry const *range, bool friendly = fals
|
||||||
inline uint32 GetSpellRecoveryTime(SpellEntry const *spellInfo) { return spellInfo->RecoveryTime > spellInfo->CategoryRecoveryTime ? spellInfo->RecoveryTime : spellInfo->CategoryRecoveryTime; }
|
inline uint32 GetSpellRecoveryTime(SpellEntry const *spellInfo) { return spellInfo->RecoveryTime > spellInfo->CategoryRecoveryTime ? spellInfo->RecoveryTime : spellInfo->CategoryRecoveryTime; }
|
||||||
int32 GetSpellDuration(SpellEntry const *spellInfo);
|
int32 GetSpellDuration(SpellEntry const *spellInfo);
|
||||||
int32 GetSpellMaxDuration(SpellEntry const *spellInfo);
|
int32 GetSpellMaxDuration(SpellEntry const *spellInfo);
|
||||||
|
uint16 GetSpellAuraMaxTicks(SpellEntry const* spellInfo);
|
||||||
|
WeaponAttackType GetWeaponAttackType(SpellEntry const *spellInfo);
|
||||||
|
|
||||||
inline bool IsSpellHaveEffect(SpellEntry const *spellInfo, SpellEffects effect)
|
inline bool IsSpellHaveEffect(SpellEntry const *spellInfo, SpellEffects effect)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1040,65 +1040,28 @@ void Unit::CalculateSpellDamage(SpellNonMeleeDamage *damageInfo, int32 damage, S
|
||||||
// Check spell crit chance
|
// Check spell crit chance
|
||||||
bool crit = isSpellCrit(pVictim, spellInfo, damageSchoolMask, attackType);
|
bool crit = isSpellCrit(pVictim, spellInfo, damageSchoolMask, attackType);
|
||||||
bool blocked = false;
|
bool blocked = false;
|
||||||
// Per-school calc
|
|
||||||
|
// damage bonus (per damage class)
|
||||||
switch (spellInfo->DmgClass)
|
switch (spellInfo->DmgClass)
|
||||||
{
|
{
|
||||||
// Melee and Ranged Spells
|
// Melee and Ranged Spells
|
||||||
case SPELL_DAMAGE_CLASS_RANGED:
|
case SPELL_DAMAGE_CLASS_RANGED:
|
||||||
case SPELL_DAMAGE_CLASS_MELEE:
|
case SPELL_DAMAGE_CLASS_MELEE:
|
||||||
{
|
{
|
||||||
// Physical Damage
|
//Calculate damage bonus
|
||||||
if ( damageSchoolMask & SPELL_SCHOOL_MASK_NORMAL )
|
damage = MeleeDamageBonus(pVictim, damage, attackType, spellInfo, SPELL_DIRECT_DAMAGE);
|
||||||
{
|
|
||||||
//Calculate armor mitigation
|
|
||||||
damage = CalcArmorReducedDamage(pVictim, damage);
|
|
||||||
// Get blocked status
|
// Get blocked status
|
||||||
blocked = isSpellBlocked(pVictim, spellInfo, attackType);
|
blocked = isSpellBlocked(pVictim, spellInfo, attackType);
|
||||||
}
|
|
||||||
// Magical Damage
|
// if crit add critical bonus
|
||||||
else
|
|
||||||
{
|
|
||||||
// Calculate damage bonus
|
|
||||||
damage = SpellDamageBonus(pVictim, spellInfo, damage, SPELL_DIRECT_DAMAGE);
|
|
||||||
}
|
|
||||||
if (crit)
|
if (crit)
|
||||||
{
|
{
|
||||||
damageInfo->HitInfo|= SPELL_HIT_TYPE_CRIT;
|
damageInfo->HitInfo|= SPELL_HIT_TYPE_CRIT;
|
||||||
|
damage = SpellCriticalDamageBonus(spellInfo, damage, pVictim);
|
||||||
// Calculate crit bonus
|
|
||||||
uint32 crit_bonus = damage;
|
|
||||||
// Apply crit_damage bonus for melee spells
|
|
||||||
if(Player* modOwner = GetSpellModOwner())
|
|
||||||
modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_CRIT_DAMAGE_BONUS, crit_bonus);
|
|
||||||
damage += crit_bonus;
|
|
||||||
|
|
||||||
// Apply SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE or SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE
|
|
||||||
int32 critPctDamageMod=0;
|
|
||||||
if(attackType == RANGED_ATTACK)
|
|
||||||
critPctDamageMod += pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
critPctDamageMod += pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE);
|
|
||||||
critPctDamageMod += GetTotalAuraModifier(SPELL_AURA_MOD_CRIT_DAMAGE_BONUS_MELEE);
|
|
||||||
}
|
|
||||||
// Increase crit damage from SPELL_AURA_MOD_CRIT_PERCENT_VERSUS
|
|
||||||
critPctDamageMod += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_CRIT_PERCENT_VERSUS, crTypeMask);
|
|
||||||
|
|
||||||
if (critPctDamageMod!=0)
|
|
||||||
damage = int32((damage) * float((100.0f + critPctDamageMod)/100.0f));
|
|
||||||
|
|
||||||
// Resilience - reduce crit damage
|
// Resilience - reduce crit damage
|
||||||
if (pVictim->GetTypeId()==TYPEID_PLAYER)
|
if (pVictim->GetTypeId()==TYPEID_PLAYER)
|
||||||
damage -= ((Player*)pVictim)->GetMeleeCritDamageReduction(damage);
|
damage -= ((Player*)pVictim)->GetMeleeCritDamageReduction(damage);
|
||||||
}
|
}
|
||||||
// Spell weapon based damage CAN BE crit & blocked at same time
|
|
||||||
if (blocked)
|
|
||||||
{
|
|
||||||
damageInfo->blocked = uint32(pVictim->GetShieldBlockValue());
|
|
||||||
if (damage < damageInfo->blocked)
|
|
||||||
damageInfo->blocked = damage;
|
|
||||||
damage-=damageInfo->blocked;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
// Magical Attacks
|
// Magical Attacks
|
||||||
|
|
@ -1123,10 +1086,23 @@ void Unit::CalculateSpellDamage(SpellNonMeleeDamage *damageInfo, int32 damage, S
|
||||||
if (GetTypeId() == TYPEID_PLAYER && pVictim->GetTypeId() == TYPEID_PLAYER)
|
if (GetTypeId() == TYPEID_PLAYER && pVictim->GetTypeId() == TYPEID_PLAYER)
|
||||||
damage -= ((Player*)pVictim)->GetSpellDamageReduction(damage);
|
damage -= ((Player*)pVictim)->GetSpellDamageReduction(damage);
|
||||||
|
|
||||||
// Calculate absorb resist
|
// damage mitigation
|
||||||
if(damage > 0)
|
if(damage > 0)
|
||||||
{
|
{
|
||||||
// lookup absorb/resist ignore auras on caster for spell
|
// physical damage => armor
|
||||||
|
if ( damageSchoolMask & SPELL_SCHOOL_MASK_NORMAL )
|
||||||
|
damage = CalcArmorReducedDamage(pVictim, damage);
|
||||||
|
|
||||||
|
// block (only for damage class ranged and -melee, also non-physical damage possible)
|
||||||
|
if (blocked)
|
||||||
|
{
|
||||||
|
damageInfo->blocked = uint32(pVictim->GetShieldBlockValue());
|
||||||
|
if (damage < damageInfo->blocked)
|
||||||
|
damageInfo->blocked = damage;
|
||||||
|
damage-=damageInfo->blocked;
|
||||||
|
}
|
||||||
|
|
||||||
|
// absorb/resist: lookup ignore auras on caster for spell
|
||||||
bool ignore = false;
|
bool ignore = false;
|
||||||
Unit::AuraList const& ignoreAbsorb = GetAurasByType(SPELL_AURA_MOD_IGNORE_ABSORB_FOR_SPELL);
|
Unit::AuraList const& ignoreAbsorb = GetAurasByType(SPELL_AURA_MOD_IGNORE_ABSORB_FOR_SPELL);
|
||||||
for(Unit::AuraList::const_iterator i = ignoreAbsorb.begin(); i != ignoreAbsorb.end(); ++i)
|
for(Unit::AuraList::const_iterator i = ignoreAbsorb.begin(); i != ignoreAbsorb.end(); ++i)
|
||||||
|
|
@ -1241,7 +1217,7 @@ void Unit::CalculateMeleeDamage(Unit *pVictim, uint32 damage, CalcDamageInfo *da
|
||||||
}
|
}
|
||||||
damage += CalculateDamage (damageInfo->attackType, false);
|
damage += CalculateDamage (damageInfo->attackType, false);
|
||||||
// Add melee damage bonus
|
// Add melee damage bonus
|
||||||
MeleeDamageBonus(damageInfo->target, &damage, damageInfo->attackType);
|
damage = MeleeDamageBonus(damageInfo->target, damage, damageInfo->attackType);
|
||||||
// Calculate armor reduction
|
// Calculate armor reduction
|
||||||
damageInfo->damage = CalcArmorReducedDamage(damageInfo->target, damage);
|
damageInfo->damage = CalcArmorReducedDamage(damageInfo->target, damage);
|
||||||
damageInfo->cleanDamage += damage - damageInfo->damage;
|
damageInfo->cleanDamage += damage - damageInfo->damage;
|
||||||
|
|
@ -3307,6 +3283,9 @@ int32 Unit::GetMaxNegativeAuraModifier(AuraType auratype) const
|
||||||
|
|
||||||
int32 Unit::GetTotalAuraModifierByMiscMask(AuraType auratype, uint32 misc_mask) const
|
int32 Unit::GetTotalAuraModifierByMiscMask(AuraType auratype, uint32 misc_mask) const
|
||||||
{
|
{
|
||||||
|
if(!misc_mask)
|
||||||
|
return 0;
|
||||||
|
|
||||||
int32 modifier = 0;
|
int32 modifier = 0;
|
||||||
|
|
||||||
AuraList const& mTotalAuraList = GetAurasByType(auratype);
|
AuraList const& mTotalAuraList = GetAurasByType(auratype);
|
||||||
|
|
@ -3321,6 +3300,9 @@ int32 Unit::GetTotalAuraModifierByMiscMask(AuraType auratype, uint32 misc_mask)
|
||||||
|
|
||||||
float Unit::GetTotalAuraMultiplierByMiscMask(AuraType auratype, uint32 misc_mask) const
|
float Unit::GetTotalAuraMultiplierByMiscMask(AuraType auratype, uint32 misc_mask) const
|
||||||
{
|
{
|
||||||
|
if(!misc_mask)
|
||||||
|
return 1.0f;
|
||||||
|
|
||||||
float multiplier = 1.0f;
|
float multiplier = 1.0f;
|
||||||
|
|
||||||
AuraList const& mTotalAuraList = GetAurasByType(auratype);
|
AuraList const& mTotalAuraList = GetAurasByType(auratype);
|
||||||
|
|
@ -3335,6 +3317,9 @@ float Unit::GetTotalAuraMultiplierByMiscMask(AuraType auratype, uint32 misc_mask
|
||||||
|
|
||||||
int32 Unit::GetMaxPositiveAuraModifierByMiscMask(AuraType auratype, uint32 misc_mask) const
|
int32 Unit::GetMaxPositiveAuraModifierByMiscMask(AuraType auratype, uint32 misc_mask) const
|
||||||
{
|
{
|
||||||
|
if(!misc_mask)
|
||||||
|
return 0;
|
||||||
|
|
||||||
int32 modifier = 0;
|
int32 modifier = 0;
|
||||||
|
|
||||||
AuraList const& mTotalAuraList = GetAurasByType(auratype);
|
AuraList const& mTotalAuraList = GetAurasByType(auratype);
|
||||||
|
|
@ -3350,6 +3335,9 @@ int32 Unit::GetMaxPositiveAuraModifierByMiscMask(AuraType auratype, uint32 misc_
|
||||||
|
|
||||||
int32 Unit::GetMaxNegativeAuraModifierByMiscMask(AuraType auratype, uint32 misc_mask) const
|
int32 Unit::GetMaxNegativeAuraModifierByMiscMask(AuraType auratype, uint32 misc_mask) const
|
||||||
{
|
{
|
||||||
|
if(!misc_mask)
|
||||||
|
return 0;
|
||||||
|
|
||||||
int32 modifier = 0;
|
int32 modifier = 0;
|
||||||
|
|
||||||
AuraList const& mTotalAuraList = GetAurasByType(auratype);
|
AuraList const& mTotalAuraList = GetAurasByType(auratype);
|
||||||
|
|
@ -8128,20 +8116,20 @@ uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint3
|
||||||
int32 TakenTotal = 0;
|
int32 TakenTotal = 0;
|
||||||
|
|
||||||
// ..done
|
// ..done
|
||||||
// Pet damage
|
// Creature damage
|
||||||
if( GetTypeId() == TYPEID_UNIT && !((Creature*)this)->isPet() )
|
if( GetTypeId() == TYPEID_UNIT && !((Creature*)this)->isPet() )
|
||||||
DoneTotalMod *= ((Creature*)this)->GetSpellDamageMod(((Creature*)this)->GetCreatureInfo()->rank);
|
DoneTotalMod *= ((Creature*)this)->GetSpellDamageMod(((Creature*)this)->GetCreatureInfo()->rank);
|
||||||
|
|
||||||
AuraList const& mModDamagePercentDone = GetAurasByType(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE);
|
AuraList const& mModDamagePercentDone = GetAurasByType(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE);
|
||||||
for(AuraList::const_iterator i = mModDamagePercentDone.begin(); i != mModDamagePercentDone.end(); ++i)
|
for(AuraList::const_iterator i = mModDamagePercentDone.begin(); i != mModDamagePercentDone.end(); ++i)
|
||||||
{
|
{
|
||||||
if( ((*i)->GetModifier()->m_miscvalue & GetSpellSchoolMask(spellProto)) &&
|
if (((*i)->GetModifier()->m_miscvalue & GetSpellSchoolMask(spellProto)) &&
|
||||||
(*i)->GetSpellProto()->EquippedItemClass == -1 &&
|
(*i)->GetSpellProto()->EquippedItemClass == -1 &&
|
||||||
// -1 == any item class (not wand then)
|
// -1 == any item class (not wand then)
|
||||||
(*i)->GetSpellProto()->EquippedItemInventoryTypeMask == 0 )
|
(*i)->GetSpellProto()->EquippedItemInventoryTypeMask == 0)
|
||||||
// 0 == any inventory type (not wand then)
|
// 0 == any inventory type (not wand then)
|
||||||
{
|
{
|
||||||
DoneTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f;
|
DoneTotalMod *= ((*i)->GetModifier()->m_amount + 100.0f) / 100.0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -8346,8 +8334,10 @@ uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint3
|
||||||
// ..taken
|
// ..taken
|
||||||
AuraList const& mModDamagePercentTaken = pVictim->GetAurasByType(SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN);
|
AuraList const& mModDamagePercentTaken = pVictim->GetAurasByType(SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN);
|
||||||
for(AuraList::const_iterator i = mModDamagePercentTaken.begin(); i != mModDamagePercentTaken.end(); ++i)
|
for(AuraList::const_iterator i = mModDamagePercentTaken.begin(); i != mModDamagePercentTaken.end(); ++i)
|
||||||
if( (*i)->GetModifier()->m_miscvalue & GetSpellSchoolMask(spellProto) )
|
{
|
||||||
TakenTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f;
|
if ((*i)->GetModifier()->m_miscvalue & GetSpellSchoolMask(spellProto))
|
||||||
|
TakenTotalMod *= ((*i)->GetModifier()->m_amount + 100.0f) / 100.0f;
|
||||||
|
}
|
||||||
|
|
||||||
// .. taken pct: dummy auras
|
// .. taken pct: dummy auras
|
||||||
if (pVictim->GetTypeId() == TYPEID_PLAYER)
|
if (pVictim->GetTypeId() == TYPEID_PLAYER)
|
||||||
|
|
@ -8365,16 +8355,20 @@ uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint3
|
||||||
// From caster spells
|
// From caster spells
|
||||||
AuraList const& mOwnerTaken = pVictim->GetAurasByType(SPELL_AURA_MOD_DAMAGE_FROM_CASTER);
|
AuraList const& mOwnerTaken = pVictim->GetAurasByType(SPELL_AURA_MOD_DAMAGE_FROM_CASTER);
|
||||||
for(AuraList::const_iterator i = mOwnerTaken.begin(); i != mOwnerTaken.end(); ++i)
|
for(AuraList::const_iterator i = mOwnerTaken.begin(); i != mOwnerTaken.end(); ++i)
|
||||||
if( (*i)->GetCasterGUID() == GetGUID() && (*i)->isAffectedOnSpell(spellProto))
|
{
|
||||||
TakenTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f;
|
if ((*i)->GetCasterGUID() == GetGUID() && (*i)->isAffectedOnSpell(spellProto))
|
||||||
|
TakenTotalMod *= ((*i)->GetModifier()->m_amount + 100.0f) / 100.0f;
|
||||||
|
}
|
||||||
|
|
||||||
// Mod damage from spell mechanic
|
// Mod damage from spell mechanic
|
||||||
if (uint32 mechanicMask = GetAllSpellMechanicMask(spellProto))
|
if (uint32 mechanicMask = GetAllSpellMechanicMask(spellProto))
|
||||||
{
|
{
|
||||||
AuraList const& mDamageDoneMechanic = pVictim->GetAurasByType(SPELL_AURA_MOD_MECHANIC_DAMAGE_TAKEN_PERCENT);
|
AuraList const& mDamageDoneMechanic = pVictim->GetAurasByType(SPELL_AURA_MOD_MECHANIC_DAMAGE_TAKEN_PERCENT);
|
||||||
for(AuraList::const_iterator i = mDamageDoneMechanic.begin();i != mDamageDoneMechanic.end(); ++i)
|
for(AuraList::const_iterator i = mDamageDoneMechanic.begin();i != mDamageDoneMechanic.end(); ++i)
|
||||||
if(mechanicMask & uint32(1<<((*i)->GetModifier()->m_miscvalue)))
|
{
|
||||||
TakenTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f;
|
if (mechanicMask & uint32(1 << ((*i)->GetModifier()->m_miscvalue)))
|
||||||
|
TakenTotalMod *= ((*i)->GetModifier()->m_amount + 100.0f) / 100.0f;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mod damage taken from AoE spells
|
// Mod damage taken from AoE spells
|
||||||
|
|
@ -8382,7 +8376,7 @@ uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint3
|
||||||
{
|
{
|
||||||
AuraList const& avoidAuras = pVictim->GetAurasByType(SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE);
|
AuraList const& avoidAuras = pVictim->GetAurasByType(SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE);
|
||||||
for(AuraList::const_iterator itr = avoidAuras.begin(); itr != avoidAuras.end(); ++itr)
|
for(AuraList::const_iterator itr = avoidAuras.begin(); itr != avoidAuras.end(); ++itr)
|
||||||
TakenTotalMod *= ((*itr)->GetModifier()->m_amount+100.0f)/100.0f;
|
TakenTotalMod *= ((*itr)->GetModifier()->m_amount + 100.0f) / 100.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Taken/Done fixed damage bonus auras
|
// Taken/Done fixed damage bonus auras
|
||||||
|
|
@ -8402,8 +8396,7 @@ uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint3
|
||||||
SpellModSpellDamage /= 100.0f;
|
SpellModSpellDamage /= 100.0f;
|
||||||
|
|
||||||
// Check for table values
|
// Check for table values
|
||||||
SpellBonusEntry const* bonus = spellmgr.GetSpellBonusData(spellProto->Id);
|
if (SpellBonusEntry const* bonus = spellmgr.GetSpellBonusData(spellProto->Id))
|
||||||
if (bonus)
|
|
||||||
{
|
{
|
||||||
float coeff;
|
float coeff;
|
||||||
if (damagetype == DOT)
|
if (damagetype == DOT)
|
||||||
|
|
@ -8420,46 +8413,28 @@ uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint3
|
||||||
// Default calculation
|
// Default calculation
|
||||||
else if (DoneAdvertisedBenefit || TakenAdvertisedBenefit)
|
else if (DoneAdvertisedBenefit || TakenAdvertisedBenefit)
|
||||||
{
|
{
|
||||||
// Damage Done from spell damage bonus
|
|
||||||
uint32 CastingTime = !IsChanneledSpell(spellProto) ? GetSpellCastTime(spellProto) : GetSpellDuration(spellProto);
|
|
||||||
// Damage over Time spells bonus calculation
|
// Damage over Time spells bonus calculation
|
||||||
float DotFactor = 1.0f;
|
float DotFactor = 1.0f;
|
||||||
if(damagetype == DOT)
|
if (damagetype == DOT)
|
||||||
{
|
{
|
||||||
int32 DotDuration = GetSpellDuration(spellProto);
|
if (!IsChanneledSpell(spellProto))
|
||||||
// 200% limit
|
DotFactor = GetSpellDuration(spellProto) / 15000.0f;
|
||||||
if(DotDuration > 0)
|
|
||||||
{
|
if (uint16 DotTicks = GetSpellAuraMaxTicks(spellProto))
|
||||||
if(DotDuration > 30000) DotDuration = 30000;
|
|
||||||
if(!IsChanneledSpell(spellProto)) DotFactor = DotDuration / 15000.0f;
|
|
||||||
int x = 0;
|
|
||||||
for(int j = 0; j < 3; j++)
|
|
||||||
{
|
|
||||||
if( spellProto->Effect[j] == SPELL_EFFECT_APPLY_AURA && (
|
|
||||||
spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_DAMAGE ||
|
|
||||||
spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_LEECH) )
|
|
||||||
{
|
|
||||||
x = j;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
int32 DotTicks = 6;
|
|
||||||
if(spellProto->EffectAmplitude[x] != 0)
|
|
||||||
DotTicks = DotDuration / spellProto->EffectAmplitude[x];
|
|
||||||
if(DotTicks)
|
|
||||||
{
|
{
|
||||||
DoneAdvertisedBenefit = DoneAdvertisedBenefit * int32(stack) / DotTicks;
|
DoneAdvertisedBenefit = DoneAdvertisedBenefit * int32(stack) / DotTicks;
|
||||||
TakenAdvertisedBenefit = TakenAdvertisedBenefit * int32(stack) / DotTicks;
|
TakenAdvertisedBenefit = TakenAdvertisedBenefit * int32(stack) / DotTicks;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// Distribute Damage over multiple effects, reduce by AoE
|
// Distribute Damage over multiple effects, reduce by AoE
|
||||||
|
uint32 CastingTime = !IsChanneledSpell(spellProto) ? GetSpellCastTime(spellProto) : GetSpellDuration(spellProto);
|
||||||
CastingTime = GetCastingTimeForBonus( spellProto, damagetype, CastingTime );
|
CastingTime = GetCastingTimeForBonus( spellProto, damagetype, CastingTime );
|
||||||
// 50% for damage and healing spells for leech spells from damage bonus and 0% from healing
|
// 50% for damage and healing spells for leech spells from damage bonus and 0% from healing
|
||||||
for(int j = 0; j < 3; ++j)
|
for(int j = 0; j < 3; ++j)
|
||||||
{
|
{
|
||||||
if( spellProto->Effect[j] == SPELL_EFFECT_HEALTH_LEECH ||
|
if (spellProto->Effect[j] == SPELL_EFFECT_HEALTH_LEECH ||
|
||||||
spellProto->Effect[j] == SPELL_EFFECT_APPLY_AURA && spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_LEECH )
|
(spellProto->Effect[j] == SPELL_EFFECT_APPLY_AURA &&
|
||||||
|
spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_LEECH))
|
||||||
{
|
{
|
||||||
CastingTime /= 2;
|
CastingTime /= 2;
|
||||||
break;
|
break;
|
||||||
|
|
@ -8486,12 +8461,12 @@ int32 Unit::SpellBaseDamageBonus(SpellSchoolMask schoolMask)
|
||||||
// ..done
|
// ..done
|
||||||
AuraList const& mDamageDone = GetAurasByType(SPELL_AURA_MOD_DAMAGE_DONE);
|
AuraList const& mDamageDone = GetAurasByType(SPELL_AURA_MOD_DAMAGE_DONE);
|
||||||
for(AuraList::const_iterator i = mDamageDone.begin();i != mDamageDone.end(); ++i)
|
for(AuraList::const_iterator i = mDamageDone.begin();i != mDamageDone.end(); ++i)
|
||||||
if(((*i)->GetModifier()->m_miscvalue & schoolMask) != 0 &&
|
{
|
||||||
(*i)->GetSpellProto()->EquippedItemClass == -1 &&
|
if (((*i)->GetModifier()->m_miscvalue & schoolMask) != 0 &&
|
||||||
// -1 == any item class (not wand then)
|
(*i)->GetSpellProto()->EquippedItemClass == -1 && // -1 == any item class (not wand then)
|
||||||
(*i)->GetSpellProto()->EquippedItemInventoryTypeMask == 0 )
|
(*i)->GetSpellProto()->EquippedItemInventoryTypeMask == 0) // 0 == any inventory type (not wand then)
|
||||||
// 0 == any inventory type (not wand then)
|
|
||||||
DoneAdvertisedBenefit += (*i)->GetModifier()->m_amount;
|
DoneAdvertisedBenefit += (*i)->GetModifier()->m_amount;
|
||||||
|
}
|
||||||
|
|
||||||
if (GetTypeId() == TYPEID_PLAYER)
|
if (GetTypeId() == TYPEID_PLAYER)
|
||||||
{
|
{
|
||||||
|
|
@ -8512,8 +8487,10 @@ int32 Unit::SpellBaseDamageBonus(SpellSchoolMask schoolMask)
|
||||||
// ... and attack power
|
// ... and attack power
|
||||||
AuraList const& mDamageDonebyAP = GetAurasByType(SPELL_AURA_MOD_SPELL_DAMAGE_OF_ATTACK_POWER);
|
AuraList const& mDamageDonebyAP = GetAurasByType(SPELL_AURA_MOD_SPELL_DAMAGE_OF_ATTACK_POWER);
|
||||||
for(AuraList::const_iterator i =mDamageDonebyAP.begin();i != mDamageDonebyAP.end(); ++i)
|
for(AuraList::const_iterator i =mDamageDonebyAP.begin();i != mDamageDonebyAP.end(); ++i)
|
||||||
|
{
|
||||||
if ((*i)->GetModifier()->m_miscvalue & schoolMask)
|
if ((*i)->GetModifier()->m_miscvalue & schoolMask)
|
||||||
DoneAdvertisedBenefit += int32(GetTotalAttackPowerValue(BASE_ATTACK) * (*i)->GetModifier()->m_amount / 100.0f);
|
DoneAdvertisedBenefit += int32(GetTotalAttackPowerValue(BASE_ATTACK) * (*i)->GetModifier()->m_amount / 100.0f);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return DoneAdvertisedBenefit;
|
return DoneAdvertisedBenefit;
|
||||||
|
|
@ -8527,14 +8504,18 @@ int32 Unit::SpellBaseDamageBonusForVictim(SpellSchoolMask schoolMask, Unit *pVic
|
||||||
// ..done (for creature type by mask) in taken
|
// ..done (for creature type by mask) in taken
|
||||||
AuraList const& mDamageDoneCreature = GetAurasByType(SPELL_AURA_MOD_DAMAGE_DONE_CREATURE);
|
AuraList const& mDamageDoneCreature = GetAurasByType(SPELL_AURA_MOD_DAMAGE_DONE_CREATURE);
|
||||||
for(AuraList::const_iterator i = mDamageDoneCreature.begin();i != mDamageDoneCreature.end(); ++i)
|
for(AuraList::const_iterator i = mDamageDoneCreature.begin();i != mDamageDoneCreature.end(); ++i)
|
||||||
|
{
|
||||||
if(creatureTypeMask & uint32((*i)->GetModifier()->m_miscvalue))
|
if(creatureTypeMask & uint32((*i)->GetModifier()->m_miscvalue))
|
||||||
TakenAdvertisedBenefit += (*i)->GetModifier()->m_amount;
|
TakenAdvertisedBenefit += (*i)->GetModifier()->m_amount;
|
||||||
|
}
|
||||||
|
|
||||||
// ..taken
|
// ..taken
|
||||||
AuraList const& mDamageTaken = pVictim->GetAurasByType(SPELL_AURA_MOD_DAMAGE_TAKEN);
|
AuraList const& mDamageTaken = pVictim->GetAurasByType(SPELL_AURA_MOD_DAMAGE_TAKEN);
|
||||||
for(AuraList::const_iterator i = mDamageTaken.begin();i != mDamageTaken.end(); ++i)
|
for(AuraList::const_iterator i = mDamageTaken.begin();i != mDamageTaken.end(); ++i)
|
||||||
|
{
|
||||||
if(((*i)->GetModifier()->m_miscvalue & schoolMask) != 0)
|
if(((*i)->GetModifier()->m_miscvalue & schoolMask) != 0)
|
||||||
TakenAdvertisedBenefit += (*i)->GetModifier()->m_amount;
|
TakenAdvertisedBenefit += (*i)->GetModifier()->m_amount;
|
||||||
|
}
|
||||||
|
|
||||||
return TakenAdvertisedBenefit;
|
return TakenAdvertisedBenefit;
|
||||||
}
|
}
|
||||||
|
|
@ -8698,7 +8679,6 @@ uint32 Unit::SpellCriticalDamageBonus(SpellEntry const *spellProto, uint32 damag
|
||||||
{
|
{
|
||||||
case SPELL_DAMAGE_CLASS_MELEE: // for melee based spells is 100%
|
case SPELL_DAMAGE_CLASS_MELEE: // for melee based spells is 100%
|
||||||
case SPELL_DAMAGE_CLASS_RANGED:
|
case SPELL_DAMAGE_CLASS_RANGED:
|
||||||
// TODO: write here full calculation for melee/ranged spells
|
|
||||||
crit_bonus = damage;
|
crit_bonus = damage;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
@ -8710,11 +8690,25 @@ uint32 Unit::SpellCriticalDamageBonus(SpellEntry const *spellProto, uint32 damag
|
||||||
if(Player* modOwner = GetSpellModOwner())
|
if(Player* modOwner = GetSpellModOwner())
|
||||||
modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_CRIT_DAMAGE_BONUS, crit_bonus);
|
modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_CRIT_DAMAGE_BONUS, crit_bonus);
|
||||||
|
|
||||||
if(pVictim)
|
if(!pVictim)
|
||||||
|
return damage += crit_bonus;
|
||||||
|
|
||||||
|
int32 critPctDamageMod = 0;
|
||||||
|
if(spellProto->DmgClass >= SPELL_DAMAGE_CLASS_MELEE)
|
||||||
{
|
{
|
||||||
uint32 creatureTypeMask = pVictim->GetCreatureTypeMask();
|
if(GetWeaponAttackType(spellProto) == RANGED_ATTACK)
|
||||||
crit_bonus = int32(crit_bonus * GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_CRIT_PERCENT_VERSUS, creatureTypeMask));
|
critPctDamageMod += pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
critPctDamageMod += pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE);
|
||||||
|
critPctDamageMod += GetTotalAuraModifier(SPELL_AURA_MOD_CRIT_DAMAGE_BONUS_MELEE);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
uint32 creatureTypeMask = pVictim->GetCreatureTypeMask();
|
||||||
|
critPctDamageMod += GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_CRIT_PERCENT_VERSUS, creatureTypeMask);
|
||||||
|
|
||||||
|
if(critPctDamageMod!=0)
|
||||||
|
crit_bonus = int32(crit_bonus * float((100.0f + critPctDamageMod)/100.0f));
|
||||||
|
|
||||||
if(crit_bonus > 0)
|
if(crit_bonus > 0)
|
||||||
damage += crit_bonus;
|
damage += crit_bonus;
|
||||||
|
|
@ -8866,40 +8860,21 @@ uint32 Unit::SpellHealingBonus(Unit *pVictim, SpellEntry const *spellProto, uint
|
||||||
// Default calculation
|
// Default calculation
|
||||||
else if (DoneAdvertisedBenefit || TakenAdvertisedBenefit)
|
else if (DoneAdvertisedBenefit || TakenAdvertisedBenefit)
|
||||||
{
|
{
|
||||||
// Damage Done from spell damage bonus
|
|
||||||
uint32 CastingTime = !IsChanneledSpell(spellProto) ? GetSpellCastTime(spellProto) : GetSpellDuration(spellProto);
|
|
||||||
// Damage over Time spells bonus calculation
|
// Damage over Time spells bonus calculation
|
||||||
float DotFactor = 1.0f;
|
float DotFactor = 1.0f;
|
||||||
if(damagetype == DOT)
|
if(damagetype == DOT)
|
||||||
{
|
{
|
||||||
int32 DotDuration = GetSpellDuration(spellProto);
|
if(!IsChanneledSpell(spellProto))
|
||||||
// 200% limit
|
DotFactor = GetSpellDuration(spellProto) / 15000.0f;
|
||||||
if(DotDuration > 0)
|
uint16 DotTicks = GetSpellAuraMaxTicks(spellProto);
|
||||||
{
|
|
||||||
if(DotDuration > 30000) DotDuration = 30000;
|
|
||||||
if(!IsChanneledSpell(spellProto)) DotFactor = DotDuration / 15000.0f;
|
|
||||||
int x = 0;
|
|
||||||
for(int j = 0; j < 3; j++)
|
|
||||||
{
|
|
||||||
if( spellProto->Effect[j] == SPELL_EFFECT_APPLY_AURA && (
|
|
||||||
spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_DAMAGE ||
|
|
||||||
spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_LEECH) )
|
|
||||||
{
|
|
||||||
x = j;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
int32 DotTicks = 6;
|
|
||||||
if(spellProto->EffectAmplitude[x] != 0)
|
|
||||||
DotTicks = DotDuration / spellProto->EffectAmplitude[x];
|
|
||||||
if(DotTicks)
|
if(DotTicks)
|
||||||
{
|
{
|
||||||
DoneAdvertisedBenefit = DoneAdvertisedBenefit * int32(stack) / DotTicks;
|
DoneAdvertisedBenefit = DoneAdvertisedBenefit * int32(stack) / DotTicks;
|
||||||
TakenAdvertisedBenefit = TakenAdvertisedBenefit * int32(stack) / DotTicks;
|
TakenAdvertisedBenefit = TakenAdvertisedBenefit * int32(stack) / DotTicks;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// Distribute Damage over multiple effects, reduce by AoE
|
// Distribute Damage over multiple effects, reduce by AoE
|
||||||
|
uint32 CastingTime = !IsChanneledSpell(spellProto) ? GetSpellCastTime(spellProto) : GetSpellDuration(spellProto);
|
||||||
CastingTime = GetCastingTimeForBonus( spellProto, damagetype, CastingTime );
|
CastingTime = GetCastingTimeForBonus( spellProto, damagetype, CastingTime );
|
||||||
// 50% for damage and healing spells for leech spells from damage bonus and 0% from healing
|
// 50% for damage and healing spells for leech spells from damage bonus and 0% from healing
|
||||||
for(int j = 0; j < 3; ++j)
|
for(int j = 0; j < 3; ++j)
|
||||||
|
|
@ -9097,120 +9072,174 @@ bool Unit::IsDamageToThreatSpell(SpellEntry const * spellInfo) const
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Unit::MeleeDamageBonus(Unit *pVictim, uint32 *pdamage,WeaponAttackType attType, SpellEntry const *spellProto)
|
uint32 Unit::MeleeDamageBonus(Unit *pVictim, uint32 pdamage,WeaponAttackType attType, SpellEntry const *spellProto, DamageEffectType damagetype, uint32 stack)
|
||||||
{
|
{
|
||||||
if(!pVictim)
|
if(!pVictim)
|
||||||
return;
|
return pdamage;
|
||||||
|
|
||||||
if(*pdamage == 0)
|
if(pdamage == 0)
|
||||||
return;
|
return pdamage;
|
||||||
|
|
||||||
|
// differentiate for weapon damage based spells
|
||||||
|
bool isWeaponDamageBasedSpell = !(spellProto && (damagetype == DOT || IsSpellHaveEffect(spellProto, SPELL_EFFECT_SCHOOL_DAMAGE)));
|
||||||
|
Item* pWeapon = GetTypeId() == TYPEID_PLAYER ? ((Player*)this)->GetWeaponForAttack(attType) : NULL;
|
||||||
uint32 creatureTypeMask = pVictim->GetCreatureTypeMask();
|
uint32 creatureTypeMask = pVictim->GetCreatureTypeMask();
|
||||||
|
uint32 schoolMask = spellProto ? spellProto->SchoolMask : GetMeleeDamageSchoolMask();
|
||||||
|
uint32 mechanicMask = spellProto ? GetAllSpellMechanicMask(spellProto) : 0;
|
||||||
|
|
||||||
// Taken/Done fixed damage bonus auras
|
// Shred also have bonus as MECHANIC_BLEED damages
|
||||||
int32 DoneFlatBenefit = 0;
|
if (spellProto && spellProto->SpellFamilyName==SPELLFAMILY_DRUID && spellProto->SpellFamilyFlags & UI64LIT(0x00008000))
|
||||||
int32 TakenFlatBenefit = 0;
|
mechanicMask |= (1 << MECHANIC_BLEED);
|
||||||
|
|
||||||
// ..done (for creature type by mask) in taken
|
|
||||||
AuraList const& mDamageDoneCreature = GetAurasByType(SPELL_AURA_MOD_DAMAGE_DONE_CREATURE);
|
|
||||||
for(AuraList::const_iterator i = mDamageDoneCreature.begin();i != mDamageDoneCreature.end(); ++i)
|
|
||||||
if(creatureTypeMask & uint32((*i)->GetModifier()->m_miscvalue))
|
|
||||||
DoneFlatBenefit += (*i)->GetModifier()->m_amount;
|
|
||||||
|
|
||||||
// ..done
|
// FLAT damage bonus auras
|
||||||
// SPELL_AURA_MOD_DAMAGE_DONE included in weapon damage
|
// =======================
|
||||||
|
int32 DoneFlat = 0;
|
||||||
// ..done (base at attack power for marked target and base at attack power for creature type)
|
int32 TakenFlat = 0;
|
||||||
int32 APbonus = 0;
|
int32 APbonus = 0;
|
||||||
if(attType == RANGED_ATTACK)
|
|
||||||
|
// ..done flat, already included in wepon damage based spells
|
||||||
|
if (!isWeaponDamageBasedSpell)
|
||||||
|
{
|
||||||
|
AuraList const& mModDamageDone = GetAurasByType(SPELL_AURA_MOD_DAMAGE_DONE);
|
||||||
|
for(AuraList::const_iterator i = mModDamageDone.begin(); i != mModDamageDone.end(); ++i)
|
||||||
|
{
|
||||||
|
if ((*i)->GetModifier()->m_miscvalue & schoolMask && // schoolmask has to fit with the intrinsic spell school
|
||||||
|
(*i)->GetModifier()->m_miscvalue & GetMeleeDamageSchoolMask() && // AND schoolmask has to fit with weapon damage school (essential for non-physical spells)
|
||||||
|
((*i)->GetSpellProto()->EquippedItemClass == -1 || // general, weapon independent
|
||||||
|
pWeapon && pWeapon->IsFitToSpellRequirements((*i)->GetSpellProto()))) // OR used weapon fits aura requirements
|
||||||
|
{
|
||||||
|
DoneFlat += (*i)->GetModifier()->m_amount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pets just add their bonus damage to their melee damage
|
||||||
|
if (GetTypeId() == TYPEID_UNIT && ((Creature*)this)->isPet())
|
||||||
|
DoneFlat += ((Pet*)this)->GetBonusDamage();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ..done flat (by creature type mask)
|
||||||
|
DoneFlat += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_DAMAGE_DONE_CREATURE, creatureTypeMask);
|
||||||
|
|
||||||
|
// ..done flat (base at attack power for marked target and base at attack power for creature type)
|
||||||
|
if (attType == RANGED_ATTACK)
|
||||||
{
|
{
|
||||||
APbonus += pVictim->GetTotalAuraModifier(SPELL_AURA_RANGED_ATTACK_POWER_ATTACKER_BONUS);
|
APbonus += pVictim->GetTotalAuraModifier(SPELL_AURA_RANGED_ATTACK_POWER_ATTACKER_BONUS);
|
||||||
|
APbonus += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_RANGED_ATTACK_POWER_VERSUS, creatureTypeMask);
|
||||||
// ..done (base at attack power and creature type)
|
TakenFlat += pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN);
|
||||||
AuraList const& mCreatureAttackPower = GetAurasByType(SPELL_AURA_MOD_RANGED_ATTACK_POWER_VERSUS);
|
|
||||||
for(AuraList::const_iterator i = mCreatureAttackPower.begin();i != mCreatureAttackPower.end(); ++i)
|
|
||||||
if(creatureTypeMask & uint32((*i)->GetModifier()->m_miscvalue))
|
|
||||||
APbonus += (*i)->GetModifier()->m_amount;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
APbonus += pVictim->GetTotalAuraModifier(SPELL_AURA_MELEE_ATTACK_POWER_ATTACKER_BONUS);
|
APbonus += pVictim->GetTotalAuraModifier(SPELL_AURA_MELEE_ATTACK_POWER_ATTACKER_BONUS);
|
||||||
|
APbonus += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_MELEE_ATTACK_POWER_VERSUS, creatureTypeMask);
|
||||||
// ..done (base at attack power and creature type)
|
TakenFlat += pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_MELEE_DAMAGE_TAKEN);
|
||||||
AuraList const& mCreatureAttackPower = GetAurasByType(SPELL_AURA_MOD_MELEE_ATTACK_POWER_VERSUS);
|
|
||||||
for(AuraList::const_iterator i = mCreatureAttackPower.begin();i != mCreatureAttackPower.end(); ++i)
|
|
||||||
if(creatureTypeMask & uint32((*i)->GetModifier()->m_miscvalue))
|
|
||||||
APbonus += (*i)->GetModifier()->m_amount;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (APbonus!=0) // Can be negative
|
// ..taken flat (by school mask)
|
||||||
|
TakenFlat += pVictim->GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_DAMAGE_TAKEN, schoolMask);
|
||||||
|
|
||||||
|
// PERCENT damage auras
|
||||||
|
// ====================
|
||||||
|
float DonePercent = 1.0f;
|
||||||
|
float TakenPercent = 1.0f;
|
||||||
|
|
||||||
|
// ..done pct, already included in weapon damage based spells
|
||||||
|
if(!isWeaponDamageBasedSpell)
|
||||||
{
|
{
|
||||||
bool normalized = false;
|
AuraList const& mModDamagePercentDone = GetAurasByType(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE);
|
||||||
|
for(AuraList::const_iterator i = mModDamagePercentDone.begin(); i != mModDamagePercentDone.end(); ++i)
|
||||||
|
{
|
||||||
|
if ((*i)->GetModifier()->m_miscvalue & schoolMask && // schoolmask has to fit with the intrinsic spell school
|
||||||
|
(*i)->GetModifier()->m_miscvalue & GetMeleeDamageSchoolMask() && // AND schoolmask has to fit with weapon damage school (essential for non-physical spells)
|
||||||
|
((*i)->GetSpellProto()->EquippedItemClass == -1 || // general, weapon independent
|
||||||
|
pWeapon && pWeapon->IsFitToSpellRequirements((*i)->GetSpellProto()))) // OR used weapon fits aura requirements
|
||||||
|
{
|
||||||
|
DonePercent *= ((*i)->GetModifier()->m_amount+100.0f) / 100.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attType == OFF_ATTACK)
|
||||||
|
DonePercent *= GetModifierValue(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT); // no school check required
|
||||||
|
}
|
||||||
|
|
||||||
|
// ..done pct (by creature type mask)
|
||||||
|
DonePercent *= GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_DAMAGE_DONE_VERSUS, creatureTypeMask);
|
||||||
|
|
||||||
|
// ..taken pct (by school mask)
|
||||||
|
TakenPercent *= pVictim->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, schoolMask);
|
||||||
|
|
||||||
|
// ..taken pct (by mechanic mask)
|
||||||
|
TakenPercent *= pVictim->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_MECHANIC_DAMAGE_TAKEN_PERCENT, mechanicMask);
|
||||||
|
|
||||||
|
// ..taken pct (melee/ranged)
|
||||||
|
if(attType == RANGED_ATTACK)
|
||||||
|
TakenPercent *= pVictim->GetTotalAuraMultiplier(SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN_PCT);
|
||||||
|
else
|
||||||
|
TakenPercent *= pVictim->GetTotalAuraMultiplier(SPELL_AURA_MOD_MELEE_DAMAGE_TAKEN_PCT);
|
||||||
|
|
||||||
|
// ..taken pct (aoe avoidance)
|
||||||
|
if(spellProto && IsAreaOfEffectSpell(spellProto))
|
||||||
|
TakenPercent *= pVictim->GetTotalAuraMultiplier(SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE);
|
||||||
|
|
||||||
|
|
||||||
|
// special dummys/class sripts and other effects
|
||||||
|
// =============================================
|
||||||
|
Unit *owner = GetOwner();
|
||||||
|
if (!owner)
|
||||||
|
owner = this;
|
||||||
|
|
||||||
|
// ..done (class scripts)
|
||||||
if(spellProto)
|
if(spellProto)
|
||||||
{
|
{
|
||||||
for (uint8 i = 0; i<3;++i)
|
AuraList const& mOverrideClassScript= owner->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
|
||||||
|
for(AuraList::const_iterator i = mOverrideClassScript.begin(); i != mOverrideClassScript.end(); ++i)
|
||||||
{
|
{
|
||||||
if (spellProto->Effect[i] == SPELL_EFFECT_NORMALIZED_WEAPON_DMG)
|
if (!(*i)->isAffectedOnSpell(spellProto))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
switch((*i)->GetModifier()->m_miscvalue)
|
||||||
{
|
{
|
||||||
normalized = true;
|
// Tundra Stalker
|
||||||
|
// Merciless Combat
|
||||||
|
case 7277:
|
||||||
|
{
|
||||||
|
// Merciless Combat
|
||||||
|
if ((*i)->GetSpellProto()->SpellIconID == 2656)
|
||||||
|
{
|
||||||
|
if(pVictim->HasAuraState(AURA_STATE_HEALTHLESS_35_PERCENT))
|
||||||
|
DonePercent *= (100.0f+(*i)->GetModifier()->m_amount)/100.0f;
|
||||||
|
}
|
||||||
|
else // Tundra Stalker
|
||||||
|
{
|
||||||
|
// Frost Fever (target debuff)
|
||||||
|
if (pVictim->GetAura(SPELL_AURA_MOD_HASTE, SPELLFAMILY_DEATHKNIGHT, UI64LIT(0x0000000000000000), 0x00000002))
|
||||||
|
DonePercent *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 7293: // Rage of Rivendare
|
||||||
|
{
|
||||||
|
if (pVictim->GetAura(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_DEATHKNIGHT, UI64LIT(0x0200000000000000)))
|
||||||
|
DonePercent *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Marked for Death
|
||||||
|
case 7598:
|
||||||
|
case 7599:
|
||||||
|
case 7600:
|
||||||
|
case 7601:
|
||||||
|
case 7602:
|
||||||
|
{
|
||||||
|
if (pVictim->GetAura(SPELL_AURA_MOD_STALKED, SPELLFAMILY_HUNTER, UI64LIT(0x0000000000000400)))
|
||||||
|
DonePercent *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DoneFlatBenefit += int32(APbonus/14.0f * GetAPMultiplier(attType,normalized));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ..taken
|
// .. taken (dummy auras)
|
||||||
AuraList const& mDamageTaken = pVictim->GetAurasByType(SPELL_AURA_MOD_DAMAGE_TAKEN);
|
|
||||||
for(AuraList::const_iterator i = mDamageTaken.begin();i != mDamageTaken.end(); ++i)
|
|
||||||
if((*i)->GetModifier()->m_miscvalue & GetMeleeDamageSchoolMask())
|
|
||||||
TakenFlatBenefit += (*i)->GetModifier()->m_amount;
|
|
||||||
|
|
||||||
if(attType!=RANGED_ATTACK)
|
|
||||||
TakenFlatBenefit += pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_MELEE_DAMAGE_TAKEN);
|
|
||||||
else
|
|
||||||
TakenFlatBenefit += pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN);
|
|
||||||
|
|
||||||
// Done/Taken total percent damage auras
|
|
||||||
float DoneTotalMod = 1.0f;
|
|
||||||
float TakenTotalMod = 1.0f;
|
|
||||||
|
|
||||||
// ..done
|
|
||||||
// SPELL_AURA_MOD_DAMAGE_PERCENT_DONE included in weapon damage
|
|
||||||
// SPELL_AURA_MOD_OFFHAND_DAMAGE_PCT included in weapon damage
|
|
||||||
|
|
||||||
AuraList const& mDamageDoneVersus = GetAurasByType(SPELL_AURA_MOD_DAMAGE_DONE_VERSUS);
|
|
||||||
for(AuraList::const_iterator i = mDamageDoneVersus.begin();i != mDamageDoneVersus.end(); ++i)
|
|
||||||
if(creatureTypeMask & uint32((*i)->GetModifier()->m_miscvalue))
|
|
||||||
DoneTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f;
|
|
||||||
|
|
||||||
// ..taken
|
|
||||||
AuraList const& mModDamagePercentTaken = pVictim->GetAurasByType(SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN);
|
|
||||||
for(AuraList::const_iterator i = mModDamagePercentTaken.begin(); i != mModDamagePercentTaken.end(); ++i)
|
|
||||||
if((*i)->GetModifier()->m_miscvalue & GetMeleeDamageSchoolMask())
|
|
||||||
TakenTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f;
|
|
||||||
|
|
||||||
// .. taken pct (special attacks)
|
|
||||||
if (spellProto)
|
|
||||||
{
|
|
||||||
uint32 mechanicMask = GetAllSpellMechanicMask(spellProto);
|
|
||||||
|
|
||||||
// Shred also have bonus as MECHANIC_BLEED damages
|
|
||||||
if(spellProto->SpellFamilyName==SPELLFAMILY_DRUID && (spellProto->SpellFamilyFlags & UI64LIT(0x00008000)))
|
|
||||||
mechanicMask |= (1 << MECHANIC_BLEED);
|
|
||||||
|
|
||||||
// Mod damage from spell mechanic
|
|
||||||
if (mechanicMask)
|
|
||||||
{
|
|
||||||
AuraList const& mDamageDoneMechanic = pVictim->GetAurasByType(SPELL_AURA_MOD_MECHANIC_DAMAGE_TAKEN_PERCENT);
|
|
||||||
for(AuraList::const_iterator i = mDamageDoneMechanic.begin();i != mDamageDoneMechanic.end(); ++i)
|
|
||||||
if(mechanicMask & uint32(1<<((*i)->GetModifier()->m_miscvalue)))
|
|
||||||
TakenTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// .. taken pct: dummy auras
|
|
||||||
AuraList const& mDummyAuras = pVictim->GetAurasByType(SPELL_AURA_DUMMY);
|
AuraList const& mDummyAuras = pVictim->GetAurasByType(SPELL_AURA_DUMMY);
|
||||||
for(AuraList::const_iterator i = mDummyAuras.begin(); i != mDummyAuras.end(); ++i)
|
for(AuraList::const_iterator i = mDummyAuras.begin(); i != mDummyAuras.end(); ++i)
|
||||||
{
|
{
|
||||||
|
|
@ -9222,72 +9251,123 @@ void Unit::MeleeDamageBonus(Unit *pVictim, uint32 *pdamage,WeaponAttackType attT
|
||||||
{
|
{
|
||||||
if(pVictim->GetTypeId() != TYPEID_PLAYER)
|
if(pVictim->GetTypeId() != TYPEID_PLAYER)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
float mod = ((Player*)pVictim)->GetRatingBonusValue(CR_CRIT_TAKEN_MELEE)*(-8.0f);
|
float mod = ((Player*)pVictim)->GetRatingBonusValue(CR_CRIT_TAKEN_MELEE)*(-8.0f);
|
||||||
if (mod < (*i)->GetModifier()->m_amount)
|
if (mod < (*i)->GetModifier()->m_amount)
|
||||||
mod = (*i)->GetModifier()->m_amount;
|
mod = (*i)->GetModifier()->m_amount;
|
||||||
TakenTotalMod *= (mod+100.0f)/100.0f;
|
|
||||||
|
TakenPercent *= (mod + 100.0f) / 100.0f;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// .. taken pct: class scripts
|
// .. taken (class scripts)
|
||||||
AuraList const& mclassScritAuras = GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
|
AuraList const& mclassScritAuras = GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
|
||||||
for(AuraList::const_iterator i = mclassScritAuras.begin(); i != mclassScritAuras.end(); ++i)
|
for(AuraList::const_iterator i = mclassScritAuras.begin(); i != mclassScritAuras.end(); ++i)
|
||||||
{
|
{
|
||||||
switch((*i)->GetMiscValue())
|
switch((*i)->GetMiscValue())
|
||||||
{
|
{
|
||||||
case 6427: case 6428: // Dirty Deeds
|
// Dirty Deeds
|
||||||
|
case 6427:
|
||||||
|
case 6428:
|
||||||
if(pVictim->HasAuraState(AURA_STATE_HEALTHLESS_35_PERCENT))
|
if(pVictim->HasAuraState(AURA_STATE_HEALTHLESS_35_PERCENT))
|
||||||
{
|
{
|
||||||
Aura* eff0 = GetAura((*i)->GetId(),0);
|
Aura* eff0 = GetAura((*i)->GetId(), 0);
|
||||||
if(!eff0 || (*i)->GetEffIndex()!=1)
|
if (!eff0 || (*i)->GetEffIndex() != 1)
|
||||||
{
|
{
|
||||||
sLog.outError("Spell structure of DD (%u) changed.",(*i)->GetId());
|
sLog.outError("Spell structure of DD (%u) changed.",(*i)->GetId());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// effect 0 have expected value but in negative state
|
// effect 0 have expected value but in negative state
|
||||||
TakenTotalMod *= (-eff0->GetModifier()->m_amount+100.0f)/100.0f;
|
TakenPercent *= (-eff0->GetModifier()->m_amount + 100.0f) / 100.0f;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(attType != RANGED_ATTACK)
|
|
||||||
|
// final calculation
|
||||||
|
// =================
|
||||||
|
|
||||||
|
// scaling of non weapon based spells
|
||||||
|
if (!isWeaponDamageBasedSpell)
|
||||||
{
|
{
|
||||||
AuraList const& mModMeleeDamageTakenPercent = pVictim->GetAurasByType(SPELL_AURA_MOD_MELEE_DAMAGE_TAKEN_PCT);
|
float LvlPenalty = CalculateLevelPenalty(spellProto);
|
||||||
for(AuraList::const_iterator i = mModMeleeDamageTakenPercent.begin(); i != mModMeleeDamageTakenPercent.end(); ++i)
|
|
||||||
TakenTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f;
|
// Check for table values
|
||||||
}
|
if (SpellBonusEntry const* bonus = spellmgr.GetSpellBonusData(spellProto->Id))
|
||||||
|
{
|
||||||
|
float coeff;
|
||||||
|
if (damagetype == DOT)
|
||||||
|
coeff = bonus->dot_damage * LvlPenalty * stack;
|
||||||
else
|
else
|
||||||
|
coeff = bonus->direct_damage * LvlPenalty * stack;
|
||||||
|
|
||||||
|
if (bonus->ap_bonus)
|
||||||
|
DoneFlat += bonus->ap_bonus * (GetTotalAttackPowerValue(BASE_ATTACK) + APbonus) * stack;
|
||||||
|
|
||||||
|
DoneFlat *= coeff;
|
||||||
|
TakenFlat *= coeff;
|
||||||
|
}
|
||||||
|
// Default calculation
|
||||||
|
else if (DoneFlat || TakenFlat)
|
||||||
{
|
{
|
||||||
AuraList const& mModRangedDamageTakenPercent = pVictim->GetAurasByType(SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN_PCT);
|
// Damage over Time spells bonus calculation
|
||||||
for(AuraList::const_iterator i = mModRangedDamageTakenPercent.begin(); i != mModRangedDamageTakenPercent.end(); ++i)
|
float DotFactor = 1.0f;
|
||||||
TakenTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f;
|
if(damagetype == DOT)
|
||||||
|
{
|
||||||
|
if(!IsChanneledSpell(spellProto))
|
||||||
|
DotFactor = GetSpellDuration(spellProto) / 15000.0f;
|
||||||
|
uint16 DotTicks = GetSpellAuraMaxTicks(spellProto);
|
||||||
|
if(DotTicks)
|
||||||
|
{
|
||||||
|
DoneFlat = DoneFlat * int32(stack) / DotTicks;
|
||||||
|
TakenFlat = TakenFlat * int32(stack) / DotTicks;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Distribute Damage over multiple effects, reduce by AoE
|
||||||
|
uint32 CastingTime = !IsChanneledSpell(spellProto) ? GetSpellCastTime(spellProto) : GetSpellDuration(spellProto);
|
||||||
|
CastingTime = GetCastingTimeForBonus( spellProto, damagetype, CastingTime );
|
||||||
|
DoneFlat *= (CastingTime / 3500.0f) * DotFactor * LvlPenalty;
|
||||||
|
TakenFlat*= (CastingTime / 3500.0f) * DotFactor * LvlPenalty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// weapon damage based spells
|
||||||
|
else if( APbonus || DoneFlat )
|
||||||
|
{
|
||||||
|
bool normalized = spellProto ? IsSpellHaveEffect(spellProto, SPELL_EFFECT_NORMALIZED_WEAPON_DMG) : false;
|
||||||
|
DoneFlat += int32(APbonus / 14.0f * GetAPMultiplier(attType,normalized));
|
||||||
|
|
||||||
|
// for weapon damage based spells we still have to apply damage done percent mods
|
||||||
|
// (that are already included into pdamage) to not-yet included DoneFlat
|
||||||
|
// e.g. from doneVersusCreature, apBonusVs...
|
||||||
|
UnitMods unitMod;
|
||||||
|
switch(attType)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mod damage taken from AoE spells
|
DoneFlat *= GetModifierValue(unitMod, TOTAL_PCT);
|
||||||
if(spellProto && IsAreaOfEffectSpell(spellProto))
|
|
||||||
{
|
|
||||||
AuraList const& avoidAuras = pVictim->GetAurasByType(SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE);
|
|
||||||
for(AuraList::const_iterator itr = avoidAuras.begin(); itr != avoidAuras.end(); ++itr)
|
|
||||||
TakenTotalMod *= ((*itr)->GetModifier()->m_amount+100.0f)/100.0f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float tmpDamage = float(int32(*pdamage) + DoneFlatBenefit) * DoneTotalMod;
|
float tmpDamage = float(int32(pdamage) + DoneFlat) * DonePercent;
|
||||||
|
|
||||||
// apply spellmod to Done damage
|
// apply spellmod to Done damage
|
||||||
if(spellProto)
|
if(spellProto)
|
||||||
{
|
{
|
||||||
if(Player* modOwner = GetSpellModOwner())
|
if(Player* modOwner = GetSpellModOwner())
|
||||||
modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_DAMAGE, tmpDamage);
|
modOwner->ApplySpellMod(spellProto->Id, damagetype == DOT ? SPELLMOD_DOT : SPELLMOD_DAMAGE, tmpDamage);
|
||||||
}
|
}
|
||||||
|
|
||||||
tmpDamage = (tmpDamage + TakenFlatBenefit)*TakenTotalMod;
|
tmpDamage = (tmpDamage + TakenFlat) * TakenPercent;
|
||||||
|
|
||||||
// bonus result can be negative
|
// bonus result can be negative
|
||||||
*pdamage = tmpDamage > 0 ? uint32(tmpDamage) : 0;
|
return tmpDamage > 0 ? uint32(tmpDamage) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Unit::ApplySpellImmune(uint32 spellId, uint32 op, uint32 type, bool apply)
|
void Unit::ApplySpellImmune(uint32 spellId, uint32 op, uint32 type, bool apply)
|
||||||
|
|
@ -9334,17 +9414,18 @@ float Unit::GetWeaponProcChance() const
|
||||||
{
|
{
|
||||||
// normalized proc chance for weapon attack speed
|
// normalized proc chance for weapon attack speed
|
||||||
// (odd formula...)
|
// (odd formula...)
|
||||||
if(isAttackReady(BASE_ATTACK))
|
if (isAttackReady(BASE_ATTACK))
|
||||||
return (GetAttackTime(BASE_ATTACK) * 1.8f / 1000.0f);
|
return (GetAttackTime(BASE_ATTACK) * 1.8f / 1000.0f);
|
||||||
else if (haveOffhandWeapon() && isAttackReady(OFF_ATTACK))
|
else if (haveOffhandWeapon() && isAttackReady(OFF_ATTACK))
|
||||||
return (GetAttackTime(OFF_ATTACK) * 1.6f / 1000.0f);
|
return (GetAttackTime(OFF_ATTACK) * 1.6f / 1000.0f);
|
||||||
return 0;
|
|
||||||
|
return 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
float Unit::GetPPMProcChance(uint32 WeaponSpeed, float PPM) const
|
float Unit::GetPPMProcChance(uint32 WeaponSpeed, float PPM) const
|
||||||
{
|
{
|
||||||
// proc per minute chance calculation
|
// proc per minute chance calculation
|
||||||
if (PPM <= 0) return 0.0f;
|
if (PPM <= 0.0f) return 0.0f;
|
||||||
return WeaponSpeed * PPM / 600.0f; // result is chance in percents (probability = Speed_in_sec * (PPM / 60))
|
return WeaponSpeed * PPM / 600.0f; // result is chance in percents (probability = Speed_in_sec * (PPM / 60))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -9366,7 +9447,7 @@ void Unit::Mount(uint32 mount)
|
||||||
|
|
||||||
void Unit::Unmount()
|
void Unit::Unmount()
|
||||||
{
|
{
|
||||||
if(!IsMounted())
|
if (!IsMounted())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_NOT_MOUNTED);
|
RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_NOT_MOUNTED);
|
||||||
|
|
@ -9384,14 +9465,14 @@ void Unit::Unmount()
|
||||||
void Unit::SetInCombatWith(Unit* enemy)
|
void Unit::SetInCombatWith(Unit* enemy)
|
||||||
{
|
{
|
||||||
Unit* eOwner = enemy->GetCharmerOrOwnerOrSelf();
|
Unit* eOwner = enemy->GetCharmerOrOwnerOrSelf();
|
||||||
if(eOwner->IsPvP())
|
if (eOwner->IsPvP())
|
||||||
{
|
{
|
||||||
SetInCombatState(true,enemy);
|
SetInCombatState(true,enemy);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//check for duel
|
//check for duel
|
||||||
if(eOwner->GetTypeId() == TYPEID_PLAYER && ((Player*)eOwner)->duel)
|
if (eOwner->GetTypeId() == TYPEID_PLAYER && ((Player*)eOwner)->duel)
|
||||||
{
|
{
|
||||||
Unit const* myOwner = GetCharmerOrOwnerOrSelf();
|
Unit const* myOwner = GetCharmerOrOwnerOrSelf();
|
||||||
if(((Player const*)eOwner)->duel->opponent == myOwner)
|
if(((Player const*)eOwner)->duel->opponent == myOwner)
|
||||||
|
|
@ -9400,23 +9481,24 @@ void Unit::SetInCombatWith(Unit* enemy)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SetInCombatState(false,enemy);
|
SetInCombatState(false,enemy);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Unit::SetInCombatState(bool PvP, Unit* enemy)
|
void Unit::SetInCombatState(bool PvP, Unit* enemy)
|
||||||
{
|
{
|
||||||
// only alive units can be in combat
|
// only alive units can be in combat
|
||||||
if(!isAlive())
|
if (!isAlive())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(PvP)
|
if (PvP)
|
||||||
m_CombatTimer = 5000;
|
m_CombatTimer = 5000;
|
||||||
|
|
||||||
bool creatureNotInCombat = GetTypeId()==TYPEID_UNIT && !HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT);
|
bool creatureNotInCombat = GetTypeId()==TYPEID_UNIT && !HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT);
|
||||||
|
|
||||||
SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT);
|
SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT);
|
||||||
|
|
||||||
if(isCharmed() || (GetTypeId()!=TYPEID_PLAYER && ((Creature*)this)->isPet()))
|
if (isCharmed() || (GetTypeId()!=TYPEID_PLAYER && ((Creature*)this)->isPet()))
|
||||||
SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PET_IN_COMBAT);
|
SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PET_IN_COMBAT);
|
||||||
|
|
||||||
if (creatureNotInCombat)
|
if (creatureNotInCombat)
|
||||||
|
|
|
||||||
|
|
@ -428,15 +428,6 @@ enum UnitMoveType
|
||||||
|
|
||||||
extern float baseMoveSpeed[MAX_MOVE_TYPE];
|
extern float baseMoveSpeed[MAX_MOVE_TYPE];
|
||||||
|
|
||||||
enum WeaponAttackType
|
|
||||||
{
|
|
||||||
BASE_ATTACK = 0,
|
|
||||||
OFF_ATTACK = 1,
|
|
||||||
RANGED_ATTACK = 2
|
|
||||||
};
|
|
||||||
|
|
||||||
#define MAX_ATTACK 3
|
|
||||||
|
|
||||||
enum CombatRating
|
enum CombatRating
|
||||||
{
|
{
|
||||||
CR_WEAPON_SKILL = 0,
|
CR_WEAPON_SKILL = 0,
|
||||||
|
|
@ -1448,7 +1439,7 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
|
||||||
|
|
||||||
void SetContestedPvP(Player *attackedPlayer = NULL);
|
void SetContestedPvP(Player *attackedPlayer = NULL);
|
||||||
|
|
||||||
void MeleeDamageBonus(Unit *pVictim, uint32 *damage, WeaponAttackType attType, SpellEntry const *spellProto = NULL);
|
uint32 MeleeDamageBonus(Unit *pVictim, uint32 damage, WeaponAttackType attType, SpellEntry const *spellProto = NULL, DamageEffectType damagetype = DIRECT_DAMAGE, uint32 stack =1);
|
||||||
uint32 GetCastingTimeForBonus( SpellEntry const *spellProto, DamageEffectType damagetype, uint32 CastingTime );
|
uint32 GetCastingTimeForBonus( SpellEntry const *spellProto, DamageEffectType damagetype, uint32 CastingTime );
|
||||||
|
|
||||||
void ApplySpellImmune(uint32 spellId, uint32 op, uint32 type, bool apply);
|
void ApplySpellImmune(uint32 spellId, uint32 op, uint32 type, bool apply);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
#ifndef __REVISION_NR_H__
|
#ifndef __REVISION_NR_H__
|
||||||
#define __REVISION_NR_H__
|
#define __REVISION_NR_H__
|
||||||
#define REVISION_NR "8634"
|
#define REVISION_NR "8635"
|
||||||
#endif // __REVISION_NR_H__
|
#endif // __REVISION_NR_H__
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue