[9798] Implement basic splitting for caster/target part damage/heal bonus calculations, periodic damage/heal over time auras will now store m_amount with caster side bonuses applied and calculate target part on each tick. Currently critical chance/bonus calculations are not affected by this change

This commit is contained in:
Laise 2010-04-27 13:12:44 +03:00
parent bb95e4a868
commit 471af8fb27
6 changed files with 580 additions and 318 deletions

View file

@ -1217,7 +1217,8 @@ void Unit::CalculateSpellDamage(SpellNonMeleeDamage *damageInfo, int32 damage, S
case SPELL_DAMAGE_CLASS_MELEE:
{
//Calculate damage bonus
damage = MeleeDamageBonus(pVictim, damage, attackType, spellInfo, SPELL_DIRECT_DAMAGE);
damage = MeleeDamageBonusDone(pVictim, damage, attackType, spellInfo, SPELL_DIRECT_DAMAGE);
damage = pVictim->MeleeDamageBonusTaken(this, damage, attackType, spellInfo, SPELL_DIRECT_DAMAGE);
// if crit add critical bonus
if (crit)
@ -1238,7 +1239,9 @@ void Unit::CalculateSpellDamage(SpellNonMeleeDamage *damageInfo, int32 damage, S
case SPELL_DAMAGE_CLASS_MAGIC:
{
// Calculate damage bonus
damage = SpellDamageBonus(pVictim, spellInfo, damage, SPELL_DIRECT_DAMAGE);
damage = SpellDamageBonusDone(pVictim, spellInfo, damage, SPELL_DIRECT_DAMAGE);
damage = pVictim->SpellDamageBonusTaken(this, spellInfo, damage, SPELL_DIRECT_DAMAGE);
// If crit add critical bonus
if (crit)
{
@ -1368,7 +1371,8 @@ void Unit::CalculateMeleeDamage(Unit *pVictim, uint32 damage, CalcDamageInfo *da
}
damage += CalculateDamage (damageInfo->attackType, false);
// Add melee damage bonus
damage = MeleeDamageBonus(damageInfo->target, damage, damageInfo->attackType);
damage = MeleeDamageBonusDone(damageInfo->target, damage, damageInfo->attackType);
damage = damageInfo->target->MeleeDamageBonusTaken(this, damage, damageInfo->attackType);
// Calculate armor reduction
uint32 armor_affected_damage = CalcNotIgnoreDamageRedunction(damage,damageInfo->damageSchoolMask);
@ -4243,7 +4247,9 @@ void Unit::RemoveSingleAuraDueToSpellByDispel(uint32 spellId, uint64 casterGUID,
if(Unit* caster = dot->GetCaster())
{
int32 bp0 = dot->GetModifier()->m_amount;
bp0 = 8 * caster->SpellDamageBonus(this, spellEntry, bp0, DOT, 1);
uint32 bonusDamage = caster->SpellDamageBonusDone(this, spellEntry, bp0, DOT);
bonusDamage = SpellDamageBonusTaken(caster, spellEntry, bonusDamage, DOT);
bp0 = 8 * bonusDamage;
// Remove spell auras from stack
RemoveSingleSpellAurasByCasterSpell(spellId, casterGUID, AURA_REMOVE_BY_DISPEL);
@ -5899,7 +5905,9 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
if (!healingAura)
return false;
int32 healingfromticks = SpellHealingBonus(pVictim, procSpell, (healingAura->GetModifier()->m_amount* GetSpellAuraMaxTicks(procSpell)), DOT);
int32 healingfromticks = healingAura->GetModifier()->m_amount * GetSpellAuraMaxTicks(procSpell);
healingfromticks = pVictim->SpellHealingBonusTaken(this, procSpell, healingfromticks, DOT);
basepoints[0] = healingfromticks * triggerAmount / 100;
triggered_spell_id = 63544;
break;
@ -5914,7 +5922,8 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
if (!leachAura)
return false;
int32 damagefromticks = SpellDamageBonus(pVictim, procSpell, (leachAura->GetModifier()->m_amount* GetSpellAuraMaxTicks(procSpell)), DOT);
int32 damagefromticks = leachAura->GetModifier()->m_amount * GetSpellAuraMaxTicks(procSpell);
damagefromticks = pVictim->SpellDamageBonusTaken(this, procSpell, damagefromticks, DOT);
basepoints[0] = damagefromticks * triggerAmount / 100;
triggered_spell_id = 63675;
break;
@ -6295,8 +6304,8 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
{
triggered_spell_id = 25742;
float ap = GetTotalAttackPowerValue(BASE_ATTACK);
int32 holy = SpellBaseDamageBonus(SPELL_SCHOOL_MASK_HOLY) +
SpellBaseDamageBonusForVictim(SPELL_SCHOOL_MASK_HOLY, pVictim);
int32 holy = SpellBaseDamageBonusDone(SPELL_SCHOOL_MASK_HOLY) +
pVictim->SpellBaseDamageBonusTaken(SPELL_SCHOOL_MASK_HOLY);
basepoints[0] = GetAttackTime(BASE_ATTACK) * int32(ap*0.022f + 0.044f * holy) / 1000;
break;
}
@ -7807,7 +7816,7 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB
int32 curBonus = 0;
if (Aura* aur = owner->GetAura(48090, EFFECT_INDEX_0))
curBonus = aur->GetModifier()->m_amount;
int32 spellDamage = owner->SpellBaseDamageBonus(SPELL_SCHOOL_MASK_MAGIC) - curBonus;
int32 spellDamage = owner->SpellBaseDamageBonusDone(SPELL_SCHOOL_MASK_MAGIC) - curBonus;
if(spellDamage <= 0)
return false;
@ -8867,7 +8876,11 @@ void Unit::EnergizeBySpell(Unit *pVictim, uint32 SpellID, uint32 Damage, Powers
pVictim->ModifyPower(powertype, Damage);
}
uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint32 pdamage, DamageEffectType damagetype, uint32 stack)
/**
* Calculates caster part of spell damage bonuses,
* also includes different bonuses dependent from target auras
*/
uint32 Unit::SpellDamageBonusDone(Unit *pVictim, SpellEntry const *spellProto, uint32 pdamage, DamageEffectType damagetype, uint32 stack)
{
if(!spellProto || !pVictim || damagetype==DIRECT_DAMAGE )
return pdamage;
@ -8876,16 +8889,12 @@ uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint3
if( GetTypeId()==TYPEID_UNIT && ((Creature*)this)->isTotem() && ((Totem*)this)->GetTotemType()!=TOTEM_STATUE)
{
if(Unit* owner = GetOwner())
return owner->SpellDamageBonus(pVictim, spellProto, pdamage, damagetype);
return owner->SpellDamageBonusDone(pVictim, spellProto, pdamage, damagetype);
}
// Taken/Done total percent damage auras
float DoneTotalMod = 1.0f;
float TakenTotalMod = 1.0f;
int32 DoneTotal = 0;
int32 TakenTotal = 0;
// ..done
// Creature damage
if( GetTypeId() == TYPEID_UNIT && !((Creature*)this)->isPet() )
DoneTotalMod *= ((Creature*)this)->GetSpellDamageMod(((Creature*)this)->GetCreatureInfo()->rank);
@ -8914,6 +8923,13 @@ uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint3
if(creatureTypeMask & uint32((*i)->GetModifier()->m_miscvalue))
DoneTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f;
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))
DoneTotalMod += ((*i)->GetModifier()->m_amount+100.0f)/100.0f;
}
// done scripted mod (take it from owner)
Unit *owner = GetOwner();
if (!owner) owner = this;
@ -9030,7 +9046,7 @@ uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint3
}
}
// Custom scripted damage
// Custom scripted damage
switch(spellProto->SpellFamilyName)
{
case SPELLFAMILY_MAGE:
@ -9074,7 +9090,7 @@ uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint3
if (spellProto->SpellFamilyFlags & UI64LIT(0x0000000000004000))
{
if (pVictim->GetHealth() * 100 / pVictim->GetMaxHealth() <= 25)
DoneTotalMod *= 4;
DoneTotalMod *= 4;
}
break;
}
@ -9147,50 +9163,8 @@ uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint3
break;
}
// ..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 & GetSpellSchoolMask(spellProto))
TakenTotalMod *= ((*i)->GetModifier()->m_amount + 100.0f) / 100.0f;
}
// .. taken pct: dummy auras
if (pVictim->GetTypeId() == TYPEID_PLAYER)
{
//Cheat Death
if (Aura *dummy = pVictim->GetDummyAura(45182))
{
float mod = -((Player*)pVictim)->GetRatingBonusValue(CR_CRIT_TAKEN_SPELL)*2*4;
if (mod < float(dummy->GetModifier()->m_amount))
mod = float(dummy->GetModifier()->m_amount);
TakenTotalMod *= (mod+100.0f)/100.0f;
}
}
// From caster spells
AuraList const& mOwnerTaken = pVictim->GetAurasByType(SPELL_AURA_MOD_DAMAGE_FROM_CASTER);
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;
}
// Mod damage from spell mechanic
TakenTotalMod *= pVictim->GetTotalAuraMultiplierByMiscValueForMask(SPELL_AURA_MOD_MECHANIC_DAMAGE_TAKEN_PERCENT,GetAllSpellMechanicMask(spellProto));
// Mod damage taken from AoE spells
if(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;
}
// Taken/Done fixed damage bonus auras
int32 DoneAdvertisedBenefit = SpellBaseDamageBonus(GetSpellSchoolMask(spellProto));
int32 TakenAdvertisedBenefit = SpellBaseDamageBonusForVictim(GetSpellSchoolMask(spellProto), pVictim);
// Done fixed damage bonus auras
int32 DoneAdvertisedBenefit = SpellBaseDamageBonusDone(GetSpellSchoolMask(spellProto));
// Pets just add their bonus damage to their spell damage
// note that their spell damage is just gain of their own auras
@ -9209,18 +9183,17 @@ uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint3
{
float coeff;
if (damagetype == DOT)
coeff = bonus->dot_damage * LvlPenalty * stack;
coeff = bonus->dot_damage * LvlPenalty;
else
coeff = bonus->direct_damage * LvlPenalty * stack;
coeff = bonus->direct_damage * LvlPenalty;
if (bonus->ap_bonus)
DoneTotal += int32(bonus->ap_bonus * GetTotalAttackPowerValue(BASE_ATTACK) * stack);
DoneTotal += int32(bonus->ap_bonus * GetTotalAttackPowerValue(BASE_ATTACK));
DoneTotal += int32(DoneAdvertisedBenefit * coeff * SpellModSpellDamage);
TakenTotal += int32(TakenAdvertisedBenefit * coeff);
}
// Default calculation
else if (DoneAdvertisedBenefit || TakenAdvertisedBenefit)
else if (DoneAdvertisedBenefit)
{
// Damage over Time spells bonus calculation
float DotFactor = 1.0f;
@ -9230,10 +9203,7 @@ uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint3
DotFactor = GetSpellDuration(spellProto) / 15000.0f;
if (uint16 DotTicks = GetSpellAuraMaxTicks(spellProto))
{
DoneAdvertisedBenefit = DoneAdvertisedBenefit * int32(stack) / DotTicks;
TakenAdvertisedBenefit = TakenAdvertisedBenefit * int32(stack) / DotTicks;
}
DoneAdvertisedBenefit = DoneAdvertisedBenefit / DotTicks;
}
// Distribute Damage over multiple effects, reduce by AoE
uint32 CastingTime = !IsChanneledSpell(spellProto) ? GetSpellCastTime(spellProto) : GetSpellDuration(spellProto);
@ -9250,20 +9220,121 @@ uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint3
}
}
DoneTotal += int32(DoneAdvertisedBenefit * (CastingTime / 3500.0f) * DotFactor * LvlPenalty * SpellModSpellDamage);
TakenTotal+= int32(TakenAdvertisedBenefit * (CastingTime / 3500.0f) * DotFactor * LvlPenalty);
}
float tmpDamage = (pdamage + DoneTotal) * DoneTotalMod;
float tmpDamage = (pdamage + DoneTotal * stack) * DoneTotalMod;
// apply spellmod to Done damage (flat and pct)
if(Player* modOwner = GetSpellModOwner())
modOwner->ApplySpellMod(spellProto->Id, damagetype == DOT ? SPELLMOD_DOT : SPELLMOD_DAMAGE, tmpDamage);
tmpDamage = (tmpDamage + TakenTotal) * TakenTotalMod;
return tmpDamage > 0 ? uint32(tmpDamage) : 0;
}
/**
* Calculates target part of spell damage bonuses,
* will be called on each tick for periodic damage over time auras
*/
uint32 Unit::SpellDamageBonusTaken(Unit *pCaster, SpellEntry const *spellProto, uint32 pdamage, DamageEffectType damagetype, uint32 stack)
{
if(!spellProto || !pCaster || damagetype==DIRECT_DAMAGE )
return pdamage;
// Taken total percent damage auras
float TakenTotalMod = 1.0f;
int32 TakenTotal = 0;
// ..taken
AuraList const& mModDamagePercentTaken = GetAurasByType(SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN);
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;
}
// .. taken pct: dummy auras
if (GetTypeId() == TYPEID_PLAYER)
{
//Cheat Death
if (Aura *dummy = GetDummyAura(45182))
{
float mod = -((Player*)this)->GetRatingBonusValue(CR_CRIT_TAKEN_SPELL)*2*4;
if (mod < float(dummy->GetModifier()->m_amount))
mod = float(dummy->GetModifier()->m_amount);
TakenTotalMod *= (mod+100.0f)/100.0f;
}
}
// From caster spells
AuraList const& mOwnerTaken = GetAurasByType(SPELL_AURA_MOD_DAMAGE_FROM_CASTER);
for(AuraList::const_iterator i = mOwnerTaken.begin(); i != mOwnerTaken.end(); ++i)
{
if ((*i)->GetCasterGUID() == pCaster->GetGUID() && (*i)->isAffectedOnSpell(spellProto))
TakenTotalMod *= ((*i)->GetModifier()->m_amount + 100.0f) / 100.0f;
}
// Mod damage from spell mechanic
TakenTotalMod *= GetTotalAuraMultiplierByMiscValueForMask(SPELL_AURA_MOD_MECHANIC_DAMAGE_TAKEN_PERCENT,GetAllSpellMechanicMask(spellProto));
// Mod damage taken from AoE spells
if(IsAreaOfEffectSpell(spellProto))
{
AuraList const& avoidAuras = 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;
}
// Taken fixed damage bonus auras
int32 TakenAdvertisedBenefit = SpellBaseDamageBonusTaken(GetSpellSchoolMask(spellProto));
float LvlPenalty = CalculateLevelPenalty(spellProto);
// Check for table values
if (SpellBonusEntry const* bonus = sSpellMgr.GetSpellBonusData(spellProto->Id))
{
float coeff;
if (damagetype == DOT)
coeff = bonus->dot_damage * LvlPenalty;
else
coeff = bonus->direct_damage * LvlPenalty;
TakenTotal += int32(TakenAdvertisedBenefit * coeff);
}
// Default calculation
else if (TakenAdvertisedBenefit)
{
// Damage over Time spells bonus calculation
float DotFactor = 1.0f;
if (damagetype == DOT)
{
if (!IsChanneledSpell(spellProto))
DotFactor = GetSpellDuration(spellProto) / 15000.0f;
if (uint16 DotTicks = GetSpellAuraMaxTicks(spellProto))
TakenAdvertisedBenefit = TakenAdvertisedBenefit / DotTicks;
}
// Distribute Damage over multiple effects, reduce by AoE
uint32 CastingTime = !IsChanneledSpell(spellProto) ? GetSpellCastTime(spellProto) : GetSpellDuration(spellProto);
CastingTime = pCaster->GetCastingTimeForBonus( spellProto, damagetype, CastingTime );
// 50% for damage and healing spells for leech spells from damage bonus and 0% from healing
for(int j = 0; j < MAX_EFFECT_INDEX; ++j)
{
if (spellProto->Effect[j] == SPELL_EFFECT_HEALTH_LEECH ||
(spellProto->Effect[j] == SPELL_EFFECT_APPLY_AURA &&
spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_LEECH))
{
CastingTime /= 2;
break;
}
}
TakenTotal+= int32(TakenAdvertisedBenefit * (CastingTime / 3500.0f) * DotFactor * LvlPenalty);
}
float tmpDamage = (pdamage + TakenTotal * stack) * TakenTotalMod;
return tmpDamage > 0 ? uint32(tmpDamage) : 0;
}
int32 Unit::SpellBaseDamageBonus(SpellSchoolMask schoolMask)
int32 Unit::SpellBaseDamageBonusDone(SpellSchoolMask schoolMask)
{
int32 DoneAdvertisedBenefit = 0;
@ -9305,21 +9376,12 @@ int32 Unit::SpellBaseDamageBonus(SpellSchoolMask schoolMask)
return DoneAdvertisedBenefit;
}
int32 Unit::SpellBaseDamageBonusForVictim(SpellSchoolMask schoolMask, Unit *pVictim)
int32 Unit::SpellBaseDamageBonusTaken(SpellSchoolMask schoolMask)
{
uint32 creatureTypeMask = pVictim->GetCreatureTypeMask();
int32 TakenAdvertisedBenefit = 0;
// ..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))
TakenAdvertisedBenefit += (*i)->GetModifier()->m_amount;
}
// ..taken
AuraList const& mDamageTaken = pVictim->GetAurasByType(SPELL_AURA_MOD_DAMAGE_TAKEN);
AuraList const& mDamageTaken = GetAurasByType(SPELL_AURA_MOD_DAMAGE_TAKEN);
for(AuraList::const_iterator i = mDamageTaken.begin();i != mDamageTaken.end(); ++i)
{
if(((*i)->GetModifier()->m_miscvalue & schoolMask) != 0)
@ -9559,36 +9621,25 @@ uint32 Unit::SpellCriticalHealingBonus(SpellEntry const *spellProto, uint32 dama
return damage;
}
int32 Unit::SpellHealingBonus(Unit *pVictim, SpellEntry const *spellProto, int32 healamount, DamageEffectType damagetype, uint32 stack)
/**
* Calculates caster part of healing spell bonuses,
* also includes different bonuses dependent from target auras
*/
uint32 Unit::SpellHealingBonusDone(Unit *pVictim, SpellEntry const *spellProto, int32 healamount, DamageEffectType damagetype, uint32 stack)
{
// For totems get healing bonus from owner (statue isn't totem in fact)
// For totems get healing bonus from owner (statue isn't totem in fact)
if( GetTypeId()==TYPEID_UNIT && ((Creature*)this)->isTotem() && ((Totem*)this)->GetTotemType()!=TOTEM_STATUE)
if(Unit* owner = GetOwner())
return owner->SpellHealingBonus(pVictim, spellProto, healamount, damagetype, stack);
float TakenTotalMod = 1.0f;
// Healing taken percent
float minval = float(pVictim->GetMaxNegativeAuraModifier(SPELL_AURA_MOD_HEALING_PCT));
if(minval)
TakenTotalMod *= (100.0f + minval) / 100.0f;
float maxval = float(pVictim->GetMaxPositiveAuraModifier(SPELL_AURA_MOD_HEALING_PCT));
if(maxval)
TakenTotalMod *= (100.0f + maxval) / 100.0f;
return owner->SpellHealingBonusDone(pVictim, spellProto, healamount, damagetype, stack);
// No heal amount for this class spells
if (spellProto->DmgClass == SPELL_DAMAGE_CLASS_NONE)
{
healamount = int32(healamount * TakenTotalMod);
return healamount < 0 ? 0 : healamount;
}
// Healing Done
// Taken/Done total percent damage auras
// Done total percent damage auras
float DoneTotalMod = 1.0f;
int32 DoneTotal = 0;
int32 TakenTotal = 0;
// Healing done percent
AuraList const& mHealingDonePct = GetAurasByType(SPELL_AURA_MOD_HEALING_DONE_PERCENT);
@ -9640,7 +9691,7 @@ int32 Unit::SpellHealingBonus(Unit *pVictim, SpellEntry const *spellProto, int32
++ownHotCount;
if (ownHotCount)
TakenTotalMod *= (stepPercent * ownHotCount + 100.0f) / 100.0f;
DoneTotalMod *= (stepPercent * ownHotCount + 100.0f) / 100.0f;
break;
}
case 7871: // Glyph of Lesser Healing Wave
@ -9654,9 +9705,27 @@ int32 Unit::SpellHealingBonus(Unit *pVictim, SpellEntry const *spellProto, int32
}
}
// Taken/Done fixed damage bonus auras
int32 DoneAdvertisedBenefit = SpellBaseHealingBonus(GetSpellSchoolMask(spellProto));
int32 TakenAdvertisedBenefit = SpellBaseHealingBonusForVictim(GetSpellSchoolMask(spellProto), pVictim);
// Nourish 20% of heal increase if target is affected by Druids HOTs
if (spellProto->SpellFamilyName == SPELLFAMILY_DRUID && (spellProto->SpellFamilyFlags & UI64LIT(0x0200000000000000)))
{
int ownHotCount = 0; // counted HoT types amount, not stacks
Unit::AuraList const& RejorRegr = pVictim->GetAurasByType(SPELL_AURA_PERIODIC_HEAL);
for(Unit::AuraList::const_iterator i = RejorRegr.begin(); i != RejorRegr.end(); ++i)
if ((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID &&
(*i)->GetCasterGUID() == GetGUID())
++ownHotCount;
if (ownHotCount)
{
DoneTotalMod *= 1.2f; // base bonus at HoTs
if (Aura* glyph = GetAura(62971, EFFECT_INDEX_0))// Glyph of Nourish
DoneTotalMod *= (glyph->GetModifier()->m_amount * ownHotCount + 100.0f) / 100.0f;
}
}
// Done fixed damage bonus auras
int32 DoneAdvertisedBenefit = SpellBaseHealingBonusDone(GetSpellSchoolMask(spellProto));
float LvlPenalty = CalculateLevelPenalty(spellProto);
// Spellmod SpellDamage
@ -9671,18 +9740,17 @@ int32 Unit::SpellHealingBonus(Unit *pVictim, SpellEntry const *spellProto, int32
{
float coeff;
if (damagetype == DOT)
coeff = bonus->dot_damage * LvlPenalty * stack;
coeff = bonus->dot_damage * LvlPenalty;
else
coeff = bonus->direct_damage * LvlPenalty * stack;
coeff = bonus->direct_damage * LvlPenalty;
if (bonus->ap_bonus)
DoneTotal += int32(bonus->ap_bonus * GetTotalAttackPowerValue(BASE_ATTACK) * stack);
DoneTotal += int32(bonus->ap_bonus * GetTotalAttackPowerValue(BASE_ATTACK));
DoneTotal += int32(DoneAdvertisedBenefit * coeff * SpellModSpellDamage);
TakenTotal += int32(TakenAdvertisedBenefit * coeff);
}
// Default calculation
else if (DoneAdvertisedBenefit || TakenAdvertisedBenefit)
else if (DoneAdvertisedBenefit)
{
// Damage over Time spells bonus calculation
float DotFactor = 1.0f;
@ -9692,10 +9760,7 @@ int32 Unit::SpellHealingBonus(Unit *pVictim, SpellEntry const *spellProto, int32
DotFactor = GetSpellDuration(spellProto) / 15000.0f;
uint16 DotTicks = GetSpellAuraMaxTicks(spellProto);
if(DotTicks)
{
DoneAdvertisedBenefit = DoneAdvertisedBenefit * int32(stack) / DotTicks;
TakenAdvertisedBenefit = TakenAdvertisedBenefit * int32(stack) / DotTicks;
}
DoneAdvertisedBenefit = DoneAdvertisedBenefit / DotTicks;
}
// Distribute Damage over multiple effects, reduce by AoE
uint32 CastingTime = !IsChanneledSpell(spellProto) ? GetSpellCastTime(spellProto) : GetSpellDuration(spellProto);
@ -9711,56 +9776,103 @@ int32 Unit::SpellHealingBonus(Unit *pVictim, SpellEntry const *spellProto, int32
}
}
DoneTotal += int32(DoneAdvertisedBenefit * (CastingTime / 3500.0f) * DotFactor * LvlPenalty * SpellModSpellDamage * 1.88f);
TakenTotal += int32(TakenAdvertisedBenefit * (CastingTime / 3500.0f) * DotFactor * LvlPenalty * 1.88f);
}
// use float as more appropriate for negative values and percent applying
float heal = (healamount + DoneTotal)*DoneTotalMod;
float heal = (healamount + DoneTotal * stack)*DoneTotalMod;
// apply spellmod to Done amount
if(Player* modOwner = GetSpellModOwner())
modOwner->ApplySpellMod(spellProto->Id, damagetype == DOT ? SPELLMOD_DOT : SPELLMOD_DAMAGE, heal);
// Taken mods
// Healing Wave cast
if (spellProto->SpellFamilyName == SPELLFAMILY_SHAMAN && (spellProto->SpellFamilyFlags & UI64LIT(0x0000000000000040)))
{
// Search for Healing Way on Victim
Unit::AuraList const& auraDummy = pVictim->GetAurasByType(SPELL_AURA_DUMMY);
for(Unit::AuraList::const_iterator itr = auraDummy.begin(); itr!=auraDummy.end(); ++itr)
if((*itr)->GetId() == 29203)
TakenTotalMod *= ((*itr)->GetModifier()->m_amount+100.0f) / 100.0f;
}
// Nourish 20% of heal increase if target is affected by Druids HOTs
else if (spellProto->SpellFamilyName == SPELLFAMILY_DRUID && (spellProto->SpellFamilyFlags & UI64LIT(0x0200000000000000)))
{
int ownHotCount = 0; // counted HoT types amount, not stacks
Unit::AuraList const& RejorRegr = pVictim->GetAurasByType(SPELL_AURA_PERIODIC_HEAL);
for(Unit::AuraList::const_iterator i = RejorRegr.begin(); i != RejorRegr.end(); ++i)
if ((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID &&
(*i)->GetCasterGUID() == GetGUID())
++ownHotCount;
return heal < 0 ? 0 : uint32(heal);
}
if (ownHotCount)
/**
* Calculates target part of healing spell bonuses,
* will be called on each tick for periodic damage over time auras
*/
uint32 Unit::SpellHealingBonusTaken(Unit *pCaster, SpellEntry const *spellProto, int32 healamount, DamageEffectType damagetype, uint32 stack)
{
float TakenTotalMod = 1.0f;
// Healing taken percent
float minval = float(GetMaxNegativeAuraModifier(SPELL_AURA_MOD_HEALING_PCT));
if(minval)
TakenTotalMod *= (100.0f + minval) / 100.0f;
float maxval = float(GetMaxPositiveAuraModifier(SPELL_AURA_MOD_HEALING_PCT));
if(maxval)
TakenTotalMod *= (100.0f + maxval) / 100.0f;
// No heal amount for this class spells
if (spellProto->DmgClass == SPELL_DAMAGE_CLASS_NONE)
{
healamount = int32(healamount * TakenTotalMod);
return healamount < 0 ? 0 : healamount;
}
// Healing Done
// Done total percent damage auras
int32 TakenTotal = 0;
// Taken fixed damage bonus auras
int32 TakenAdvertisedBenefit = SpellBaseHealingBonusTaken(GetSpellSchoolMask(spellProto));
float LvlPenalty = CalculateLevelPenalty(spellProto);
// Check for table values
SpellBonusEntry const* bonus = sSpellMgr.GetSpellBonusData(spellProto->Id);
if (bonus)
{
float coeff;
if (damagetype == DOT)
coeff = bonus->dot_damage * LvlPenalty;
else
coeff = bonus->direct_damage * LvlPenalty;
TakenTotal += int32(TakenAdvertisedBenefit * coeff);
}
// Default calculation
else if (TakenAdvertisedBenefit)
{
// Damage over Time spells bonus calculation
float DotFactor = 1.0f;
if(damagetype == DOT)
{
TakenTotalMod *= 1.2f; // base bonus at HoTs
if (Aura* glyph = GetAura(62971, EFFECT_INDEX_0))// Glyph of Nourish
TakenTotalMod *= (glyph->GetModifier()->m_amount * ownHotCount + 100.0f) / 100.0f;
if(!IsChanneledSpell(spellProto))
DotFactor = GetSpellDuration(spellProto) / 15000.0f;
uint16 DotTicks = GetSpellAuraMaxTicks(spellProto);
if(DotTicks)
TakenAdvertisedBenefit = TakenAdvertisedBenefit / DotTicks;
}
// Distribute Damage over multiple effects, reduce by AoE
uint32 CastingTime = !IsChanneledSpell(spellProto) ? GetSpellCastTime(spellProto) : GetSpellDuration(spellProto);
CastingTime = pCaster->GetCastingTimeForBonus( spellProto, damagetype, CastingTime );
// 50% for damage and healing spells for leech spells from damage bonus and 0% from healing
for(int j = 0; j < MAX_EFFECT_INDEX; ++j)
{
if( spellProto->Effect[j] == SPELL_EFFECT_HEALTH_LEECH ||
spellProto->Effect[j] == SPELL_EFFECT_APPLY_AURA && spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_LEECH )
{
CastingTime /= 2;
break;
}
}
TakenTotal += int32(TakenAdvertisedBenefit * (CastingTime / 3500.0f) * DotFactor * LvlPenalty * 1.88f);
}
AuraList const& mHealingGet= pVictim->GetAurasByType(SPELL_AURA_MOD_HEALING_RECEIVED);
AuraList const& mHealingGet= GetAurasByType(SPELL_AURA_MOD_HEALING_RECEIVED);
for(AuraList::const_iterator i = mHealingGet.begin(); i != mHealingGet.end(); ++i)
if ((*i)->isAffectedOnSpell(spellProto))
TakenTotalMod *= ((*i)->GetModifier()->m_amount + 100.0f) / 100.0f;
heal = (heal + TakenTotal) * TakenTotalMod;
// use float as more appropriate for negative values and percent applying
float heal = (healamount + TakenTotal * stack) * TakenTotalMod;
return heal < 0 ? 0 : uint32(heal);
}
int32 Unit::SpellBaseHealingBonus(SpellSchoolMask schoolMask)
int32 Unit::SpellBaseHealingBonusDone(SpellSchoolMask schoolMask)
{
int32 AdvertisedBenefit = 0;
@ -9793,10 +9905,10 @@ int32 Unit::SpellBaseHealingBonus(SpellSchoolMask schoolMask)
return AdvertisedBenefit;
}
int32 Unit::SpellBaseHealingBonusForVictim(SpellSchoolMask schoolMask, Unit *pVictim)
int32 Unit::SpellBaseHealingBonusTaken(SpellSchoolMask schoolMask)
{
int32 AdvertisedBenefit = 0;
AuraList const& mDamageTaken = pVictim->GetAurasByType(SPELL_AURA_MOD_HEALING);
AuraList const& mDamageTaken = GetAurasByType(SPELL_AURA_MOD_HEALING);
for(AuraList::const_iterator i = mDamageTaken.begin();i != mDamageTaken.end(); ++i)
if ((*i)->GetModifier()->m_miscvalue & schoolMask)
AdvertisedBenefit += (*i)->GetModifier()->m_amount;
@ -9917,7 +10029,11 @@ bool Unit::IsDamageToThreatSpell(SpellEntry const * spellInfo) const
return false;
}
uint32 Unit::MeleeDamageBonus(Unit *pVictim, uint32 pdamage,WeaponAttackType attType, SpellEntry const *spellProto, DamageEffectType damagetype, uint32 stack)
/**
* Calculates caster part of melee damage bonuses,
* also includes different bonuses dependent from target auras
*/
uint32 Unit::MeleeDamageBonusDone(Unit *pVictim, uint32 pdamage,WeaponAttackType attType, SpellEntry const *spellProto, DamageEffectType damagetype, uint32 stack)
{
if (!pVictim)
return pdamage;
@ -9940,7 +10056,6 @@ uint32 Unit::MeleeDamageBonus(Unit *pVictim, uint32 pdamage,WeaponAttackType att
// FLAT damage bonus auras
// =======================
int32 DoneFlat = 0;
int32 TakenFlat = 0;
int32 APbonus = 0;
// ..done flat, already included in wepon damage based spells
@ -9971,22 +10086,16 @@ uint32 Unit::MeleeDamageBonus(Unit *pVictim, uint32 pdamage,WeaponAttackType att
{
APbonus += pVictim->GetTotalAuraModifier(SPELL_AURA_RANGED_ATTACK_POWER_ATTACKER_BONUS);
APbonus += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_RANGED_ATTACK_POWER_VERSUS, creatureTypeMask);
TakenFlat += pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN);
}
else
{
APbonus += pVictim->GetTotalAuraModifier(SPELL_AURA_MELEE_ATTACK_POWER_ATTACKER_BONUS);
APbonus += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_MELEE_ATTACK_POWER_VERSUS, creatureTypeMask);
TakenFlat += pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_MELEE_DAMAGE_TAKEN);
}
// ..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)
@ -10010,23 +10119,6 @@ uint32 Unit::MeleeDamageBonus(Unit *pVictim, uint32 pdamage,WeaponAttackType att
// ..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->GetTotalAuraMultiplierByMiscValueForMask(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();
@ -10084,30 +10176,7 @@ uint32 Unit::MeleeDamageBonus(Unit *pVictim, uint32 pdamage,WeaponAttackType att
}
}
// .. taken (dummy auras)
AuraList const& mDummyAuras = pVictim->GetAurasByType(SPELL_AURA_DUMMY);
for(AuraList::const_iterator i = mDummyAuras.begin(); i != mDummyAuras.end(); ++i)
{
switch((*i)->GetSpellProto()->SpellIconID)
{
//Cheat Death
case 2109:
if((*i)->GetModifier()->m_miscvalue & SPELL_SCHOOL_MASK_NORMAL)
{
if(pVictim->GetTypeId() != TYPEID_PLAYER)
continue;
float mod = ((Player*)pVictim)->GetRatingBonusValue(CR_CRIT_TAKEN_MELEE)*(-8.0f);
if (mod < float((*i)->GetModifier()->m_amount))
mod = float((*i)->GetModifier()->m_amount);
TakenPercent *= (mod + 100.0f) / 100.0f;
}
break;
}
}
// .. taken (class scripts)
// .. done (class scripts)
AuraList const& mclassScritAuras = GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
for(AuraList::const_iterator i = mclassScritAuras.begin(); i != mclassScritAuras.end(); ++i)
{
@ -10126,7 +10195,7 @@ uint32 Unit::MeleeDamageBonus(Unit *pVictim, uint32 pdamage,WeaponAttackType att
}
// effect 0 have expected value but in negative state
TakenPercent *= (-eff0->GetModifier()->m_amount + 100.0f) / 100.0f;
DonePercent *= (-eff0->GetModifier()->m_amount + 100.0f) / 100.0f;
}
break;
}
@ -10146,18 +10215,17 @@ uint32 Unit::MeleeDamageBonus(Unit *pVictim, uint32 pdamage,WeaponAttackType att
{
float coeff;
if (damagetype == DOT)
coeff = bonus->dot_damage * LvlPenalty * stack;
coeff = bonus->dot_damage * LvlPenalty;
else
coeff = bonus->direct_damage * LvlPenalty * stack;
coeff = bonus->direct_damage * LvlPenalty;
if (bonus->ap_bonus)
DoneFlat += bonus->ap_bonus * (GetTotalAttackPowerValue(BASE_ATTACK) + APbonus) * stack;
DoneFlat += bonus->ap_bonus * (GetTotalAttackPowerValue(BASE_ATTACK) + APbonus);
DoneFlat *= coeff;
TakenFlat *= coeff;
}
// Default calculation
else if (DoneFlat || TakenFlat)
else if (DoneFlat)
{
// Damage over Time spells bonus calculation
float DotFactor = 1.0f;
@ -10167,16 +10235,12 @@ uint32 Unit::MeleeDamageBonus(Unit *pVictim, uint32 pdamage,WeaponAttackType att
DotFactor = GetSpellDuration(spellProto) / 15000.0f;
uint16 DotTicks = GetSpellAuraMaxTicks(spellProto);
if(DotTicks)
{
DoneFlat = DoneFlat * int32(stack) / DotTicks;
TakenFlat = TakenFlat * int32(stack) / DotTicks;
}
DoneFlat = DoneFlat / 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
@ -10200,7 +10264,7 @@ uint32 Unit::MeleeDamageBonus(Unit *pVictim, uint32 pdamage,WeaponAttackType att
DoneFlat *= GetModifierValue(unitMod, TOTAL_PCT);
}
float tmpDamage = float(int32(pdamage) + DoneFlat) * DonePercent;
float tmpDamage = float(int32(pdamage) + DoneFlat * stack) * DonePercent;
// apply spellmod to Done damage
if(spellProto)
@ -10209,7 +10273,132 @@ uint32 Unit::MeleeDamageBonus(Unit *pVictim, uint32 pdamage,WeaponAttackType att
modOwner->ApplySpellMod(spellProto->Id, damagetype == DOT ? SPELLMOD_DOT : SPELLMOD_DAMAGE, tmpDamage);
}
tmpDamage = (tmpDamage + TakenFlat) * TakenPercent;
// bonus result can be negative
return tmpDamage > 0 ? uint32(tmpDamage) : 0;
}
/**
* Calculates target part of melee damage bonuses,
* will be called on each tick for periodic damage over time auras
*/
uint32 Unit::MeleeDamageBonusTaken(Unit *pCaster, uint32 pdamage,WeaponAttackType attType, SpellEntry const *spellProto, DamageEffectType damagetype, uint32 stack)
{
if (!pCaster)
return pdamage;
if (pdamage == 0)
return pdamage;
// differentiate for weapon damage based spells
bool isWeaponDamageBasedSpell = !(spellProto && (damagetype == DOT || IsSpellHaveEffect(spellProto, SPELL_EFFECT_SCHOOL_DAMAGE)));
uint32 schoolMask = spellProto ? spellProto->SchoolMask : GetMeleeDamageSchoolMask();
uint32 mechanicMask = spellProto ? GetAllSpellMechanicMask(spellProto) : 0;
// Shred also have bonus as MECHANIC_BLEED damages
if (spellProto && spellProto->SpellFamilyName==SPELLFAMILY_DRUID && spellProto->SpellFamilyFlags & UI64LIT(0x00008000))
mechanicMask |= (1 << (MECHANIC_BLEED-1));
// FLAT damage bonus auras
// =======================
int32 TakenFlat = 0;
// ..taken flat (base at attack power for marked target and base at attack power for creature type)
if (attType == RANGED_ATTACK)
TakenFlat += GetTotalAuraModifier(SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN);
else
TakenFlat += GetTotalAuraModifier(SPELL_AURA_MOD_MELEE_DAMAGE_TAKEN);
// ..taken flat (by school mask)
TakenFlat += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_DAMAGE_TAKEN, schoolMask);
// PERCENT damage auras
// ====================
float TakenPercent = 1.0f;
// ..taken pct (by school mask)
TakenPercent *= GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, schoolMask);
// ..taken pct (by mechanic mask)
TakenPercent *= GetTotalAuraMultiplierByMiscValueForMask(SPELL_AURA_MOD_MECHANIC_DAMAGE_TAKEN_PERCENT,mechanicMask);
// ..taken pct (melee/ranged)
if(attType == RANGED_ATTACK)
TakenPercent *= GetTotalAuraMultiplier(SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN_PCT);
else
TakenPercent *= GetTotalAuraMultiplier(SPELL_AURA_MOD_MELEE_DAMAGE_TAKEN_PCT);
// ..taken pct (aoe avoidance)
if(spellProto && IsAreaOfEffectSpell(spellProto))
TakenPercent *= GetTotalAuraMultiplier(SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE);
// special dummys/class scripts and other effects
// =============================================
// .. taken (dummy auras)
AuraList const& mDummyAuras = GetAurasByType(SPELL_AURA_DUMMY);
for(AuraList::const_iterator i = mDummyAuras.begin(); i != mDummyAuras.end(); ++i)
{
switch((*i)->GetSpellProto()->SpellIconID)
{
//Cheat Death
case 2109:
if((*i)->GetModifier()->m_miscvalue & SPELL_SCHOOL_MASK_NORMAL)
{
if(GetTypeId() != TYPEID_PLAYER)
continue;
float mod = ((Player*)this)->GetRatingBonusValue(CR_CRIT_TAKEN_MELEE)*(-8.0f);
if (mod < float((*i)->GetModifier()->m_amount))
mod = float((*i)->GetModifier()->m_amount);
TakenPercent *= (mod + 100.0f) / 100.0f;
}
break;
}
}
// final calculation
// =================
// scaling of non weapon based spells
if (!isWeaponDamageBasedSpell)
{
float LvlPenalty = CalculateLevelPenalty(spellProto);
// Check for table values
if (SpellBonusEntry const* bonus = sSpellMgr.GetSpellBonusData(spellProto->Id))
{
float coeff;
if (damagetype == DOT)
coeff = bonus->dot_damage * LvlPenalty;
else
coeff = bonus->direct_damage * LvlPenalty;
TakenFlat *= coeff;
}
// Default calculation
else if (TakenFlat)
{
// Damage over Time spells bonus calculation
float DotFactor = 1.0f;
if(damagetype == DOT)
{
if(!IsChanneledSpell(spellProto))
DotFactor = GetSpellDuration(spellProto) / 15000.0f;
uint16 DotTicks = GetSpellAuraMaxTicks(spellProto);
if(DotTicks)
TakenFlat = TakenFlat / DotTicks;
}
// Distribute Damage over multiple effects, reduce by AoE
uint32 CastingTime = !IsChanneledSpell(spellProto) ? GetSpellCastTime(spellProto) : GetSpellDuration(spellProto);
CastingTime = pCaster->GetCastingTimeForBonus( spellProto, damagetype, CastingTime );
TakenFlat*= (CastingTime / 3500.0f) * DotFactor * LvlPenalty;
}
}
float tmpDamage = float(int32(pdamage) + TakenFlat * stack) * TakenPercent;
// bonus result can be negative
return tmpDamage > 0 ? uint32(tmpDamage) : 0;