aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xsrc/server/game/Spells/Auras/SpellAuraEffects.cpp2296
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.h21
2 files changed, 1105 insertions, 1212 deletions
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
index 8a6e8f5b8df..e63d0dfda03 100755
--- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
@@ -42,7 +42,7 @@ class Aura;
//
// in aura handler there should be check for modes:
// AURA_EFFECT_HANDLE_REAL set
-// AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK set
+// AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK set
// AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK set - aura is recalculated or is just applied/removed - need to redo all things related to m_amount
// AURA_EFFECT_HANDLE_CHANGE_AMOUNT_SEND_FOR_CLIENT_MASK - logical or of above conditions
// AURA_EFFECT_HANDLE_STAT - set when stats are reapplied
@@ -850,7 +850,7 @@ void AuraEffect::CalculatePeriodic(Unit* caster, bool create, bool load)
// reset periodic timer on aura create or on reapply when aura isn't dot
// possibly we should not reset periodic timers only when aura is triggered by proc
// or maybe there's a spell attribute somewhere
- bool resetPeriodicTimer = create
+ bool resetPeriodicTimer = create
|| ((GetAuraType() != SPELL_AURA_PERIODIC_DAMAGE) && (GetAuraType() != SPELL_AURA_PERIODIC_DAMAGE_PERCENT));
if (resetPeriodicTimer)
@@ -1279,1236 +1279,51 @@ void AuraEffect::PeriodicTick(AuraApplication * aurApp, Unit* caster) const
switch(GetAuraType())
{
+ case SPELL_AURA_PERIODIC_DUMMY:
+ HandlePeriodicDummyAuraTick(target, caster);
+ break;
+ case SPELL_AURA_PERIODIC_TRIGGER_SPELL:
+ HandlePeriodicTriggerSpellAuraTick(target, caster);
+ break;
+ case SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE:
+ HandlePeriodicTriggerSpellWithValueAuraTick(target, caster);
+ break;
case SPELL_AURA_PERIODIC_DAMAGE:
case SPELL_AURA_PERIODIC_DAMAGE_PERCENT:
- {
- if (!caster)
- break;
-
- if (!target->isAlive())
- return;
-
- if (target->HasUnitState(UNIT_STAT_ISOLATED))
- {
- SendTickImmune(target, caster);
- return;
- }
-
- // Consecrate ticks can miss and will not show up in the combat log
- if (GetSpellProto()->Effect[GetEffIndex()] == SPELL_EFFECT_PERSISTENT_AREA_AURA &&
- caster->SpellHitResult(target, GetSpellProto(), false) != SPELL_MISS_NONE)
- break;
-
- // Check for immune (not use charges)
- if (target->IsImmunedToDamage(GetSpellProto()))
- {
- SendTickImmune(target, caster);
- break;
- }
-
- // some auras remove at specific health level or more
- if (GetAuraType() == SPELL_AURA_PERIODIC_DAMAGE)
- {
- switch (GetId())
- {
- case 43093: case 31956: case 38801: // Grievous Wound
- case 35321: case 38363: case 39215: // Gushing Wound
- if (target->IsFullHealth())
- {
- target->RemoveAurasDueToSpell(GetId());
- return;
- }
- break;
- case 38772: // Grievous Wound
- {
- uint32 percent =
- GetEffIndex() < 2 && GetSpellProto()->Effect[GetEffIndex()] == SPELL_EFFECT_DUMMY ?
- caster->CalculateSpellDamage(target, GetSpellProto(), GetEffIndex()+1) :
- 100;
- if (!target->HealthBelowPct(percent))
- {
- target->RemoveAurasDueToSpell(GetId());
- return;
- }
- break;
- }
- }
- }
-
- uint32 absorb=0;
- uint32 resist=0;
- CleanDamage cleanDamage = CleanDamage(0, 0, BASE_ATTACK, MELEE_HIT_NORMAL);
-
- // ignore non positive values (can be result apply spellmods to aura damage
- uint32 damage = GetAmount() > 0 ? GetAmount() : 0;
-
- if (GetAuraType() == SPELL_AURA_PERIODIC_DAMAGE)
- {
- damage = caster->SpellDamageBonus(target, GetSpellProto(), damage, DOT, GetBase()->GetStackAmount());
-
- // Calculate armor mitigation
- if (Unit::IsDamageReducedByArmor(GetSpellSchoolMask(GetSpellProto()), GetSpellProto(), m_effIndex))
- {
- uint32 damageReductedArmor = caster->CalcArmorReducedDamage(target, damage, GetSpellProto());
- cleanDamage.mitigated_damage += damage - damageReductedArmor;
- damage = damageReductedArmor;
- }
-
- // Curse of Agony damage-per-tick calculation
- if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags[0] & 0x400) && GetSpellProto()->SpellIconID == 544)
- {
- uint32 totalTick = GetTotalTicks();
- // 1..4 ticks, 1/2 from normal tick damage
- if (m_tickNumber <= totalTick / 3)
- damage = damage/2;
- // 9..12 ticks, 3/2 from normal tick damage
- else if (m_tickNumber > totalTick * 2 / 3)
- damage += (damage+1)/2; // +1 prevent 0.5 damage possible lost at 1..4 ticks
- // 5..8 ticks have normal tick damage
- }
- // There is a Chance to make a Soul Shard when Drain soul does damage
- if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags[0] & 0x00004000))
- {
- if (caster->GetTypeId() == TYPEID_PLAYER && caster->ToPlayer()->isHonorOrXPTarget(target))
- {
- if (roll_chance_i(20))
- {
- caster->CastSpell(caster, 43836, true, 0, this);
- // Glyph of Drain Soul - chance to create an additional Soul Shard
- if (AuraEffect *aur = caster->GetAuraEffect(58070, 0))
- if (roll_chance_i(aur->GetMiscValue()))
- caster->CastSpell(caster, 58068, true, 0, aur);
- }
- }
- }
- if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_GENERIC)
- {
- switch (GetId())
- {
- case 70911: // Unbound Plague
- case 72854: // Unbound Plague
- case 72855: // Unbound Plague
- case 72856: // Unbound Plague
- damage *= uint32(pow(1.25f, int32(m_tickNumber)));
- break;
- default:
- break;
- }
- }
- }
- else
- damage = uint32(target->CountPctFromMaxHealth(damage));
-
- bool crit = IsPeriodicTickCrit(target, caster);
- if (crit)
- damage = caster->SpellCriticalDamageBonus(m_spellProto, damage, target);
-
- int32 dmg = damage;
- caster->ApplyResilience(target, NULL, &dmg, crit, CR_CRIT_TAKEN_SPELL);
- damage = dmg;
-
- caster->CalcAbsorbResist(target, GetSpellSchoolMask(GetSpellProto()), DOT, damage, &absorb, &resist, m_spellProto);
-
- sLog->outDetail("PeriodicTick: %u (TypeId: %u) attacked %u (TypeId: %u) for %u dmg inflicted by %u abs is %u",
- GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), target->GetGUIDLow(), target->GetTypeId(), damage, GetId(), absorb);
-
- caster->DealDamageMods(target, damage, &absorb);
-
- // Set trigger flag
- uint32 procAttacker = PROC_FLAG_DONE_PERIODIC;
- uint32 procVictim = PROC_FLAG_TAKEN_PERIODIC;
- uint32 procEx = (crit ? PROC_EX_CRITICAL_HIT : PROC_EX_NORMAL_HIT) | PROC_EX_INTERNAL_DOT;
- damage = (damage <= absorb+resist) ? 0 : (damage-absorb-resist);
- if (damage)
- procVictim|=PROC_FLAG_TAKEN_DAMAGE;
-
- int32 overkill = damage - target->GetHealth();
- if (overkill < 0)
- overkill = 0;
-
- SpellPeriodicAuraLogInfo pInfo(this, damage, overkill, absorb, resist, 0.0f, crit);
- target->SendPeriodicAuraLog(&pInfo);
-
- caster->ProcDamageAndSpell(target, procAttacker, procVictim, procEx, damage, BASE_ATTACK, GetSpellProto());
-
- caster->DealDamage(target, damage, &cleanDamage, DOT, GetSpellSchoolMask(GetSpellProto()), GetSpellProto(), true);
+ HandlePeriodicDamageAurasTick(target, caster);
break;
- }
case SPELL_AURA_PERIODIC_LEECH:
- {
- if (!caster)
- return;
-
- if (!caster->isAlive())
- return;
-
- if (!target->isAlive())
- return;
-
- if (target->HasUnitState(UNIT_STAT_ISOLATED))
- {
- SendTickImmune(target, caster);
- return;
- }
-
- if (GetSpellProto()->Effect[GetEffIndex()] == SPELL_EFFECT_PERSISTENT_AREA_AURA &&
- caster->SpellHitResult(target, GetSpellProto(), false) != SPELL_MISS_NONE)
- return;
-
- // Check for immune
- if (target->IsImmunedToDamage(GetSpellProto()))
- {
- SendTickImmune(target, caster);
- return;
- }
-
- uint32 absorb=0;
- uint32 resist=0;
- CleanDamage cleanDamage = CleanDamage(0, 0, BASE_ATTACK, MELEE_HIT_NORMAL);
-
- //uint32 damage = GetModifierValuePerStack() > 0 ? GetModifierValuePerStack() : 0;
- uint32 damage = GetAmount() > 0 ? GetAmount() : 0;
- damage = caster->SpellDamageBonus(target, GetSpellProto(), damage, DOT, GetBase()->GetStackAmount());
-
- bool crit = IsPeriodicTickCrit(target, caster);
- if (crit)
- damage = caster->SpellCriticalDamageBonus(m_spellProto, damage, target);
-
- // Calculate armor mitigation
- if (Unit::IsDamageReducedByArmor(GetSpellSchoolMask(GetSpellProto()), GetSpellProto(), m_effIndex))
- {
- uint32 damageReductedArmor = caster->CalcArmorReducedDamage(target, damage, GetSpellProto());
- cleanDamage.mitigated_damage += damage - damageReductedArmor;
- damage = damageReductedArmor;
- }
-
- int32 dmg = damage;
- caster->ApplyResilience(target, NULL, &dmg, crit, CR_CRIT_TAKEN_SPELL);
- damage = dmg;
-
- caster->CalcAbsorbResist(target, GetSpellSchoolMask(GetSpellProto()), DOT, damage, &absorb, &resist, m_spellProto);
-
- if (target->GetHealth() < damage)
- damage = uint32(target->GetHealth());
-
- sLog->outDetail("PeriodicTick: %u (TypeId: %u) health leech of %u (TypeId: %u) for %u dmg inflicted by %u abs is %u",
- GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), target->GetGUIDLow(), target->GetTypeId(), damage, GetId(), absorb);
-
- caster->SendSpellNonMeleeDamageLog(target, GetId(), damage, GetSpellSchoolMask(GetSpellProto()), absorb, resist, false, 0, crit);
-
- // Set trigger flag
- uint32 procAttacker = PROC_FLAG_DONE_PERIODIC;
- uint32 procVictim = PROC_FLAG_TAKEN_PERIODIC;
- uint32 procEx = (crit ? PROC_EX_CRITICAL_HIT : PROC_EX_NORMAL_HIT) | PROC_EX_INTERNAL_DOT;
- damage = (damage <= absorb+resist) ? 0 : (damage-absorb-resist);
- if (damage)
- procVictim|=PROC_FLAG_TAKEN_DAMAGE;
- caster->ProcDamageAndSpell(target, procAttacker, procVictim, procEx, damage, BASE_ATTACK, GetSpellProto());
- int32 new_damage = caster->DealDamage(target, damage, &cleanDamage, DOT, GetSpellSchoolMask(GetSpellProto()), GetSpellProto(), false);
-
- if (!target->isAlive() && caster->IsNonMeleeSpellCasted(false))
- for (uint32 i = CURRENT_FIRST_NON_MELEE_SPELL; i < CURRENT_MAX_SPELL; ++i)
- if (Spell* spell = caster->GetCurrentSpell(CurrentSpellTypes(i)))
- if (spell->m_spellInfo->Id == GetId())
- spell->cancel();
-
- float gainMultiplier = SpellMgr::CalculateSpellEffectValueMultiplier(GetSpellProto(), GetEffIndex(), caster);
-
- uint32 heal = uint32(caster->SpellHealingBonus(caster, GetSpellProto(), uint32(new_damage * gainMultiplier), DOT, GetBase()->GetStackAmount()));
-
- int32 gain = caster->HealBySpell(caster, GetSpellProto(), heal);
- caster->getHostileRefManager().threatAssist(caster, gain * 0.5f, GetSpellProto());
+ HandlePeriodicHealthLeechAuraTick(target, caster);
break;
- }
- case SPELL_AURA_PERIODIC_HEALTH_FUNNEL: // only three spells
- {
- if (!caster || !caster->GetHealth())
- break;
-
- if (!target->isAlive())
- return;
-
- if (target->HasUnitState(UNIT_STAT_ISOLATED))
- {
- SendTickImmune(target, caster);
- return;
- }
-
- uint32 damage = GetAmount();
- // do not kill health donator
- if (caster->GetHealth() < damage)
- damage = caster->GetHealth() - 1;
- if (!damage)
- break;
-
- //donator->SendSpellNonMeleeDamageLog(donator, GetId(), damage, GetSpellSchoolMask(spellProto), 0, 0, false, 0);
- caster->ModifyHealth(-(int32)damage);
- sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "PeriodicTick: donator %u target %u damage %u.", target->GetEntry(), target->GetEntry(), damage);
-
- float gainMultiplier = SpellMgr::CalculateSpellEffectValueMultiplier(GetSpellProto(), GetEffIndex(), caster);
-
- damage = int32(damage * gainMultiplier);
-
- caster->HealBySpell(target, GetSpellProto(), damage);
+ case SPELL_AURA_PERIODIC_HEALTH_FUNNEL:
+ HandlePeriodicHealthFunnelAuraTick(target, caster);
break;
- }
case SPELL_AURA_PERIODIC_HEAL:
case SPELL_AURA_OBS_MOD_HEALTH:
- {
- if (!caster)
- break;
-
- if (!target->isAlive())
- return;
-
- if (target->HasUnitState(UNIT_STAT_ISOLATED))
- {
- SendTickImmune(target, caster);
- return;
- }
-
- // heal for caster damage (must be alive)
- if (target != caster && GetSpellProto()->AttributesEx2 & SPELL_ATTR2_HEALTH_FUNNEL && !caster->isAlive())
- break;
-
- if (GetBase()->GetDuration() == -1 && target->IsFullHealth())
- break;
-
- // ignore non positive values (can be result apply spellmods to aura damage
- int32 damage = m_amount > 0 ? m_amount : 0;
-
- if (GetAuraType() == SPELL_AURA_OBS_MOD_HEALTH)
- {
- // Taken mods
- float TakenTotalMod = 1.0f;
-
- // Tenacity increase healing % taken
- if (AuraEffect const* Tenacity = target->GetAuraEffect(58549, 0))
- AddPctN(TakenTotalMod, Tenacity->GetAmount());
-
- // Healing taken percent
- float minval = (float)target->GetMaxNegativeAuraModifier(SPELL_AURA_MOD_HEALING_PCT);
- if (minval)
- AddPctF(TakenTotalMod, minval);
-
- float maxval = (float)target->GetMaxPositiveAuraModifier(SPELL_AURA_MOD_HEALING_PCT);
- if (maxval)
- AddPctF(TakenTotalMod, maxval);
-
- // Healing over time taken percent
- float minval_hot = (float)target->GetMaxNegativeAuraModifier(SPELL_AURA_MOD_HOT_PCT);
- if (minval_hot)
- AddPctF(TakenTotalMod, minval_hot);
-
- float maxval_hot = (float)target->GetMaxPositiveAuraModifier(SPELL_AURA_MOD_HOT_PCT);
- if (maxval_hot)
- AddPctF(TakenTotalMod, maxval_hot);
-
- TakenTotalMod = std::max(TakenTotalMod, 0.0f);
-
- damage = uint32(target->CountPctFromMaxHealth(damage));
- damage = uint32(damage * TakenTotalMod);
- }
- else
- {
- // Wild Growth = amount + (6 - 2*doneTicks) * ticks* amount / 100
- if (m_spellProto->SpellFamilyName == SPELLFAMILY_DRUID && m_spellProto->SpellIconID == 2864)
- {
- int32 addition = int32(float(damage * GetTotalTicks()) * ((6-float(2*(GetTickNumber()-1)))/100));
-
- // Item - Druid T10 Restoration 2P Bonus
- if (AuraEffect* aurEff = caster->GetAuraEffect(70658, 0))
- // divided by 50 instead of 100 because calculated as for every 2 tick
- addition += abs(int32((addition * aurEff->GetAmount()) / 50));
-
- damage += addition;
- }
-
- damage = caster->SpellHealingBonus(target, GetSpellProto(), damage, DOT, GetBase()->GetStackAmount());
- }
-
- bool crit = IsPeriodicTickCrit(target, caster);
- if (crit)
- damage = caster->SpellCriticalHealingBonus(m_spellProto, damage, target);
-
- sLog->outDetail("PeriodicTick: %u (TypeId: %u) heal of %u (TypeId: %u) for %u health inflicted by %u",
- GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), target->GetGUIDLow(), target->GetTypeId(), damage, GetId());
-
- uint32 absorb = 0;
- uint32 heal = uint32(damage);
- caster->CalcHealAbsorb(target, GetSpellProto(), heal, absorb);
- int32 gain = caster->DealHeal(target, heal);
-
- SpellPeriodicAuraLogInfo pInfo(this, damage, damage - gain, absorb, 0, 0.0f, crit);
- target->SendPeriodicAuraLog(&pInfo);
-
- target->getHostileRefManager().threatAssist(caster, float(gain) * 0.5f, GetSpellProto());
-
- bool haveCastItem = GetBase()->GetCastItemGUID() != 0;
-
- // Health Funnel
- // damage caster for heal amount
- if (target != caster && GetSpellProto()->AttributesEx2 & SPELL_ATTR2_HEALTH_FUNNEL)
- {
- uint32 damage = SpellMgr::CalculateSpellEffectAmount(GetSpellProto(), 0); // damage is not affected by spell power
- if ((int32)damage > gain)
- damage = gain;
- uint32 absorb = 0;
- caster->DealDamageMods(caster, damage, &absorb);
- caster->SendSpellNonMeleeDamageLog(caster, GetId(), damage, GetSpellSchoolMask(GetSpellProto()), absorb, 0, false, 0, false);
-
- CleanDamage cleanDamage = CleanDamage(0, 0, BASE_ATTACK, MELEE_HIT_NORMAL);
- caster->DealDamage(caster, damage, &cleanDamage, NODAMAGE, GetSpellSchoolMask(GetSpellProto()), GetSpellProto(), true);
- }
-
- uint32 procAttacker = PROC_FLAG_DONE_PERIODIC;
- uint32 procVictim = PROC_FLAG_TAKEN_PERIODIC;
- uint32 procEx = (crit ? PROC_EX_CRITICAL_HIT : PROC_EX_NORMAL_HIT) | PROC_EX_INTERNAL_HOT;
- // ignore item heals
- if (!haveCastItem)
- caster->ProcDamageAndSpell(target, procAttacker, procVictim, procEx, damage, BASE_ATTACK, GetSpellProto());
+ HandlePeriodicHealAurasTick(target, caster);
break;
- }
case SPELL_AURA_PERIODIC_MANA_LEECH:
- {
- if (GetMiscValue() < 0 || GetMiscValue() >= int8(MAX_POWERS))
- break;
-
- if (!target->isAlive())
- return;
-
- if (target->HasUnitState(UNIT_STAT_ISOLATED))
- {
- SendTickImmune(target, caster);
- return;
- }
-
- Powers power = Powers(GetMiscValue());
-
- // power type might have changed between aura applying and tick (druid's shapeshift)
- if (target->getPowerType() != power)
- break;
-
- if (!caster || !caster->isAlive())
- break;
-
- if (GetSpellProto()->Effect[GetEffIndex()] == SPELL_EFFECT_PERSISTENT_AREA_AURA &&
- caster->SpellHitResult(target, GetSpellProto(), false) != SPELL_MISS_NONE)
- break;
-
- // Check for immune (not use charges)
- if (target->IsImmunedToDamage(GetSpellProto()))
- {
- SendTickImmune(target, caster);
- break;
- }
-
- // ignore non positive values (can be result apply spellmods to aura damage
- uint32 damage = m_amount > 0 ? m_amount : 0;
-
- // Special case: draining x% of mana (up to a maximum of 2*x% of the caster's maximum mana)
- // It's mana percent cost spells, m_amount is percent drain from target
- if (m_spellProto->ManaCostPercentage)
- {
- // max value
- uint32 maxmana = CalculatePctF(caster->GetMaxPower(power), damage * 2.0f);
- ApplyPctU(damage, target->GetMaxPower(power));
- if (damage > maxmana)
- damage = maxmana;
- }
-
- sLog->outDetail("PeriodicTick: %u (TypeId: %u) power leech of %u (TypeId: %u) for %u dmg inflicted by %u",
- GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), target->GetGUIDLow(), target->GetTypeId(), damage, GetId());
-
- int32 drain_amount = std::min(target->GetPower(power), damage);
-
- // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
- if (power == POWER_MANA)
- drain_amount -= target->GetSpellCritDamageReduction(drain_amount);
-
- target->ModifyPower(power, -drain_amount);
-
- float gain_multiplier = 0.0f;
-
- if (caster->GetMaxPower(power) > 0)
- gain_multiplier = SpellMgr::CalculateSpellEffectValueMultiplier(GetSpellProto(), GetEffIndex(), caster);
-
- SpellPeriodicAuraLogInfo pInfo(this, drain_amount, 0, 0, 0, gain_multiplier, false);
- target->SendPeriodicAuraLog(&pInfo);
-
- int32 gain_amount = int32(drain_amount * gain_multiplier);
-
- if (gain_amount)
- {
- int32 gain = caster->ModifyPower(power, gain_amount);
- target->AddThreat(caster, float(gain) * 0.5f, GetSpellSchoolMask(GetSpellProto()), GetSpellProto());
- }
-
- switch(GetId())
- {
- case 31447: // Mark of Kaz'rogal
- if (target->GetPower(power) == 0)
- {
- target->CastSpell(target, 31463, true, 0, this);
- // Remove aura
- GetBase()->SetDuration(0);
- }
- break;
-
- case 32960: // Mark of Kazzak
- int32 modifier = int32(target->GetPower(power) * 0.05f);
- target->ModifyPower(power, -modifier);
-
- if (target->GetPower(power) == 0)
- {
- target->CastSpell(target, 32961, true, 0, this);
- // Remove aura
- GetBase()->SetDuration(0);
- }
- }
- // Drain Mana
- if (m_spellProto->SpellFamilyName == SPELLFAMILY_WARLOCK
- && m_spellProto->SpellFamilyFlags[0] & 0x00000010)
- {
- int32 manaFeedVal = 0;
- if (AuraEffect const* aurEff = GetBase()->GetEffect(1))
- manaFeedVal = aurEff->GetAmount();
- // Mana Feed - Drain Mana
- if (manaFeedVal > 0)
- {
- ApplyPctN(manaFeedVal, gain_amount);
- caster->CastCustomSpell(caster, 32554, &manaFeedVal, NULL, NULL, true, NULL, this);
- }
- }
+ HandlePeriodicManaLeechAuraTick(target, caster);
break;
- }
case SPELL_AURA_OBS_MOD_POWER:
- {
- if (GetMiscValue() < 0)
- return;
-
- if (!target->isAlive())
- return;
-
- if (target->HasUnitState(UNIT_STAT_ISOLATED))
- {
- SendTickImmune(target, caster);
- return;
- }
-
- Powers power;
- if (GetMiscValue() == POWER_ALL)
- power = target->getPowerType();
- else
- power = Powers(GetMiscValue());
-
- if (target->GetMaxPower(power) == 0)
- return;
-
- if (GetBase()->GetDuration() == -1 && target->GetPower(power) == target->GetMaxPower(power))
- return;
-
- uint32 amount = m_amount * target->GetMaxPower(power) /100;
- sLog->outDetail("PeriodicTick: %u (TypeId: %u) energize %u (TypeId: %u) for %u dmg inflicted by %u",
- GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), target->GetGUIDLow(), target->GetTypeId(), amount, GetId());
-
- SpellPeriodicAuraLogInfo pInfo(this, amount, 0, 0, 0, 0.0f, false);
- target->SendPeriodicAuraLog(&pInfo);
-
- int32 gain = target->ModifyPower(power, amount);
-
- if (caster)
- target->getHostileRefManager().threatAssist(caster, float(gain) * 0.5f, GetSpellProto());
+ HandleObsModPowerAuraTick(target, caster);
break;
- }
case SPELL_AURA_PERIODIC_ENERGIZE:
- {
- // ignore non positive values (can be result apply spellmods to aura damage
- if (m_amount < 0 || GetMiscValue() >= int8(MAX_POWERS))
- return;
-
- if (!target->isAlive())
- return;
-
- if (target->HasUnitState(UNIT_STAT_ISOLATED))
- {
- SendTickImmune(target, caster);
- return;
- }
-
- Powers power = Powers(GetMiscValue());
-
- if (target->GetMaxPower(power) == 0)
- return;
-
- if (GetBase()->GetDuration() == -1 && target->GetPower(power) == target->GetMaxPower(power))
- return;
-
- uint32 amount = m_amount;
-
- SpellPeriodicAuraLogInfo pInfo(this, amount, 0, 0, 0, 0.0f, false);
- target->SendPeriodicAuraLog(&pInfo);
-
- sLog->outDetail("PeriodicTick: %u (TypeId: %u) energize %u (TypeId: %u) for %u dmg inflicted by %u",
- GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), target->GetGUIDLow(), target->GetTypeId(), amount, GetId());
-
- int32 gain = target->ModifyPower(power, amount);
-
- if (caster)
- target->getHostileRefManager().threatAssist(caster, float(gain) * 0.5f, GetSpellProto());
+ HandlePeriodicEnergizeAuraTick(target, caster);
break;
- }
case SPELL_AURA_POWER_BURN_MANA:
- {
- if (!caster)
- return;
-
- if (!target->isAlive())
- return;
-
- if (target->HasUnitState(UNIT_STAT_ISOLATED))
- {
- SendTickImmune(target, caster);
- return;
- }
-
- // Check for immune (not use charges)
- if (target->IsImmunedToDamage(GetSpellProto()))
- {
- SendTickImmune(target, caster);
- return;
- }
-
- int32 damage = m_amount > 0 ? m_amount : 0;
-
- Powers powerType = Powers(GetMiscValue());
-
- if (!target->isAlive() || target->getPowerType() != powerType)
- return;
-
- // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
- if (powerType == POWER_MANA)
- damage -= target->GetSpellCritDamageReduction(damage);
-
- uint32 gain = uint32(-target->ModifyPower(powerType, -damage));
-
- float dmgMultiplier = SpellMgr::CalculateSpellEffectValueMultiplier(GetSpellProto(), GetEffIndex(), caster);
-
- SpellEntry const* spellProto = GetSpellProto();
- //maybe has to be sent different to client, but not by SMSG_PERIODICAURALOG
- SpellNonMeleeDamage damageInfo(caster, target, spellProto->Id, spellProto->SchoolMask);
- //no SpellDamageBonus for burn mana
- caster->CalculateSpellDamageTaken(&damageInfo, int32(gain * dmgMultiplier), spellProto);
-
- caster->DealDamageMods(damageInfo.target, damageInfo.damage, &damageInfo.absorb);
-
- caster->SendSpellNonMeleeDamageLog(&damageInfo);
-
- // Set trigger flag
- uint32 procAttacker = PROC_FLAG_DONE_PERIODIC;
- uint32 procVictim = PROC_FLAG_TAKEN_PERIODIC;
- uint32 procEx = createProcExtendMask(&damageInfo, SPELL_MISS_NONE) | PROC_EX_INTERNAL_DOT;
- if (damageInfo.damage)
- procVictim|=PROC_FLAG_TAKEN_DAMAGE;
-
- caster->ProcDamageAndSpell(damageInfo.target, procAttacker, procVictim, procEx, damageInfo.damage, BASE_ATTACK, spellProto);
-
- caster->DealSpellDamage(&damageInfo, true);
+ HandlePeriodicPowerBurnManaAuraTick(target, caster);
break;
- }
case SPELL_AURA_DUMMY:
// Haunting Spirits
if (GetId() == 7057)
target->CastSpell((Unit*)NULL , GetAmount(), true);
break;
- case SPELL_AURA_PERIODIC_DUMMY:
- PeriodicDummyTick(target, caster);
- break;
- case SPELL_AURA_PERIODIC_TRIGGER_SPELL:
- TriggerSpell(target, caster);
- break;
- case SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE:
- TriggerSpellWithValue(target, caster);
- break;
- default:
- break;
- }
-}
-
-void AuraEffect::PeriodicDummyTick(Unit* target, Unit* caster) const
-{
- switch (GetSpellProto()->SpellFamilyName)
- {
- case SPELLFAMILY_GENERIC:
- switch (GetId())
- {
- // Forsaken Skills
- case 7054:
- {
- // Possibly need cast one of them (but
- // 7038 Forsaken Skill: Swords
- // 7039 Forsaken Skill: Axes
- // 7040 Forsaken Skill: Daggers
- // 7041 Forsaken Skill: Maces
- // 7042 Forsaken Skill: Staves
- // 7043 Forsaken Skill: Bows
- // 7044 Forsaken Skill: Guns
- // 7045 Forsaken Skill: 2H Axes
- // 7046 Forsaken Skill: 2H Maces
- // 7047 Forsaken Skill: 2H Swords
- // 7048 Forsaken Skill: Defense
- // 7049 Forsaken Skill: Fire
- // 7050 Forsaken Skill: Frost
- // 7051 Forsaken Skill: Holy
- // 7053 Forsaken Skill: Shadow
- return;
- }
- case 54798: // FLAMING Arrow Triggered Effect
- {
- if (!target || !target->ToCreature() || !caster->IsVehicle())
- return;
-
- Unit *rider = caster->GetVehicleKit()->GetPassenger(0);
- if (!rider)
- return;
-
- // set ablaze
- if (target->HasAuraEffect(54683, EFFECT_0))
- return;
- else
- target->CastSpell(target, 54683, true);
-
- // Credit Frostworgs
- if (target->GetEntry() == 29358)
- rider->CastSpell(rider, 54896, true);
- // Credit Frost Giants
- else if (target->GetEntry() == 29351)
- rider->CastSpell(rider, 54893, true);
-
- break;
- }
- case 62292: // Blaze (Pool of Tar)
- // should we use custom damage?
- target->CastSpell((Unit*)NULL, m_spellProto->EffectTriggerSpell[m_effIndex], true);
- break;
- case 62399: // Overload Circuit
- if (target->GetMap()->IsDungeon() && int(target->GetAppliedAuras().count(62399)) >= (target->GetMap()->IsHeroic() ? 4 : 2))
- {
- target->CastSpell(target, 62475, true); // System Shutdown
- if (Unit *veh = target->GetVehicleBase())
- veh->CastSpell(target, 62475, true);
- }
- break;
- case 64821: // Fuse Armor (Razorscale)
- if (GetBase()->GetStackAmount() == GetSpellProto()->StackAmount)
- {
- target->CastSpell(target, 64774, true, NULL, NULL, GetCasterGUID());
- target->RemoveAura(64821);
- }
- break;
- }
- break;
- case SPELLFAMILY_MAGE:
- {
- // Mirror Image
- if (GetId() == 55342)
- // Set name of summons to name of caster
- target->CastSpell((Unit *)NULL, m_spellProto->EffectTriggerSpell[m_effIndex], true);
- break;
- }
- case SPELLFAMILY_WARLOCK:
- {
- switch (GetSpellProto()->Id)
- {
- // Demonic Circle
- case 48018:
- if (GameObject* obj = target->GetGameObject(GetSpellProto()->Id))
- {
- if (target->IsWithinDist(obj, GetSpellMaxRange(48020, true)))
- {
- if (!target->HasAura(62388))
- target->CastSpell(target, 62388, true);
- }
- else
- target->RemoveAura(62388);
- }
- break;
- }
- break;
- }
- case SPELLFAMILY_DRUID:
- {
- switch (GetSpellProto()->Id)
- {
- // Frenzied Regeneration
- case 22842:
- {
- // Converts up to 10 rage per second into health for $d. Each point of rage is converted into ${$m2/10}.1% of max health.
- // Should be manauser
- if (target->getPowerType() != POWER_RAGE)
- break;
- uint32 rage = target->GetPower(POWER_RAGE);
- // Nothing todo
- if (rage == 0)
- break;
- int32 mod = (rage < 100) ? rage : 100;
- int32 points = target->CalculateSpellDamage(target, GetSpellProto(), 1);
- int32 regen = target->GetMaxHealth() * (mod * points / 10) / 1000;
- target->CastCustomSpell(target, 22845, &regen, 0, 0, true, 0, this);
- target->SetPower(POWER_RAGE, rage-mod);
- break;
- }
- // Force of Nature
- case 33831:
- break;
- }
- break;
- }
- case SPELLFAMILY_ROGUE:
- {
- switch (GetSpellProto()->Id)
- {
- // Master of Subtlety
- case 31666:
- if (!target->HasAuraType(SPELL_AURA_MOD_STEALTH))
- target->RemoveAurasDueToSpell(31665);
- break;
- // Killing Spree
- case 51690:
- {
- // TODO: this should use effect[1] of 51690
- UnitList targets;
- {
- // eff_radius == 0
- float radius = GetSpellMaxRange(GetSpellProto(), false);
-
- CellPair p(Trinity::ComputeCellPair(caster->GetPositionX(), caster->GetPositionY()));
- Cell cell(p);
- cell.data.Part.reserved = ALL_DISTRICT;
-
- Trinity::AnyUnfriendlyVisibleUnitInObjectRangeCheck u_check(caster, caster, radius);
- Trinity::UnitListSearcher<Trinity::AnyUnfriendlyVisibleUnitInObjectRangeCheck> checker(caster, targets, u_check);
-
- TypeContainerVisitor<Trinity::UnitListSearcher<Trinity::AnyUnfriendlyVisibleUnitInObjectRangeCheck>, GridTypeMapContainer > grid_object_checker(checker);
- TypeContainerVisitor<Trinity::UnitListSearcher<Trinity::AnyUnfriendlyVisibleUnitInObjectRangeCheck>, WorldTypeMapContainer > world_object_checker(checker);
-
- cell.Visit(p, grid_object_checker, *GetBase()->GetOwner()->GetMap(), *caster, radius);
- cell.Visit(p, world_object_checker, *GetBase()->GetOwner()->GetMap(), *caster, radius);
- }
-
- if (targets.empty())
- return;
-
- UnitList::const_iterator itr = targets.begin();
- std::advance(itr, rand()%targets.size());
- Unit* spellTarget = *itr;
-
- target->CastSpell(spellTarget, 57840, true);
- target->CastSpell(spellTarget, 57841, true);
- break;
- }
- // Overkill
- case 58428:
- if (!target->HasAuraType(SPELL_AURA_MOD_STEALTH))
- target->RemoveAurasDueToSpell(58427);
- break;
- }
- break;
- }
- case SPELLFAMILY_HUNTER:
- {
- // Explosive Shot
- if (GetSpellProto()->SpellFamilyFlags[1] & 0x80000000)
- {
- if (caster)
- caster->CastCustomSpell(53352, SPELLVALUE_BASE_POINT0, m_amount, target, true, NULL, this);
- break;
- }
- switch (GetSpellProto()->Id)
- {
- // Feeding Frenzy Rank 1
- case 53511:
- if (target->getVictim() && target->getVictim()->HealthBelowPct(35))
- target->CastSpell(target, 60096, true, 0, this);
- return;
- // Feeding Frenzy Rank 2
- case 53512:
- if (target->getVictim() && target->getVictim()->HealthBelowPct(35))
- target->CastSpell(target, 60097, true, 0, this);
- return;
- default:
- break;
- }
- break;
- }
- case SPELLFAMILY_SHAMAN:
- if (GetId() == 52179) // Astral Shift
- {
- // Periodic need for remove visual on stun/fear/silence lost
- if (!(target->GetUInt32Value(UNIT_FIELD_FLAGS)&(UNIT_FLAG_STUNNED|UNIT_FLAG_FLEEING|UNIT_FLAG_SILENCED)))
- target->RemoveAurasDueToSpell(52179);
- break;
- }
- break;
- case SPELLFAMILY_DEATHKNIGHT:
- switch (GetId())
- {
- case 49016: // Hysteria
- uint32 damage = uint32(target->CountPctFromMaxHealth(1));
- target->DealDamage(target, damage, NULL, NODAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
- break;
- }
- // Death and Decay
- if (GetSpellProto()->SpellFamilyFlags[0] & 0x20)
- {
- if (caster)
- caster->CastCustomSpell(target, 52212, &m_amount, NULL, NULL, true, 0, this);
- break;
- }
- // Blood of the North
- // Reaping
- // Death Rune Mastery
- if (GetSpellProto()->SpellIconID == 3041 || GetSpellProto()->SpellIconID == 22 || GetSpellProto()->SpellIconID == 2622)
- {
- if (target->GetTypeId() != TYPEID_PLAYER)
- return;
- if (target->ToPlayer()->getClass() != CLASS_DEATH_KNIGHT)
- return;
-
- // timer expired - remove death runes
- target->ToPlayer()->RemoveRunesByAuraEffect(this);
- }
- break;
default:
break;
}
}
-void AuraEffect::TriggerSpell(Unit* target, Unit* caster) const
-{
- if (!caster || !target)
- return;
-
- Unit* triggerTarget = target;
-
- // generic casting code with custom spells and target/caster customs
- uint32 triggerSpellId = GetSpellProto()->EffectTriggerSpell[GetEffIndex()];
-
- SpellEntry const *triggeredSpellInfo = sSpellStore.LookupEntry(triggerSpellId);
- SpellEntry const *auraSpellInfo = GetSpellProto();
- uint32 auraId = auraSpellInfo->Id;
-
- // specific code for cases with no trigger spell provided in field
- if (triggeredSpellInfo == NULL)
- {
- switch (auraSpellInfo->SpellFamilyName)
- {
- case SPELLFAMILY_GENERIC:
- {
- switch (auraId)
- {
- // Thaumaturgy Channel
- case 9712:
- triggerSpellId = 21029;
- break;
- // Brood Affliction: Bronze
- case 23170:
- triggerSpellId = 23171;
- return;
- // Restoration
- case 24379:
- case 23493:
- {
- int32 heal = caster->CountPctFromMaxHealth(10);
- caster->HealBySpell(target, auraSpellInfo, heal);
-
- int32 mana = caster->GetMaxPower(POWER_MANA);
- if (mana)
- {
- mana /= 10;
- caster->EnergizeBySpell(caster, 23493, mana, POWER_MANA);
- }
- return;
- }
- // Nitrous Boost
- case 27746:
- if (target->GetPower(POWER_MANA) >= 10)
- {
- target->ModifyPower(POWER_MANA, -10);
- target->SendEnergizeSpellLog(caster, 27746, 10, POWER_MANA);
- }
- else
- target->RemoveAurasDueToSpell(27746);
- return;
- // Frost Blast
- case 27808:
- caster->CastCustomSpell(29879, SPELLVALUE_BASE_POINT0, int32(target->CountPctFromMaxHealth(21)), target, true, NULL, this);
- return;
- // Detonate Mana
- case 27819:
- if (int32 mana = (int32)(target->GetMaxPower(POWER_MANA) / 10))
- {
- mana = target->ModifyPower(POWER_MANA, -mana);
- target->CastCustomSpell(27820, SPELLVALUE_BASE_POINT0, -mana*10, target, true, NULL, this);
- }
- return;
- // Inoculate Nestlewood Owlkin
- case 29528:
- if (triggerTarget->GetTypeId() != TYPEID_UNIT)// prevent error reports in case ignored player target
- return;
- break;
- // Feed Captured Animal
- case 29917:
- triggerSpellId = 29916;
- break;
- // Extract Gas
- case 30427:
- {
- // move loot to player inventory and despawn target
- if (caster->GetTypeId() == TYPEID_PLAYER &&
- triggerTarget->GetTypeId() == TYPEID_UNIT &&
- triggerTarget->ToCreature()->GetCreatureInfo()->type == CREATURE_TYPE_GAS_CLOUD)
- {
- Player* player = (Player*)caster;
- Creature* creature = triggerTarget->ToCreature();
- // missing lootid has been reported on startup - just return
- if (!creature->GetCreatureInfo()->SkinLootId)
- return;
-
- player->AutoStoreLoot(creature->GetCreatureInfo()->SkinLootId, LootTemplates_Skinning, true);
-
- creature->DespawnOrUnsummon();
- }
- return;
- }
- // Quake
- case 30576: triggerSpellId = 30571; break;
- // Doom
- // TODO: effect trigger spell may be independant on spell targets, and executed in spell finish phase
- // so instakill will be naturally done before trigger spell
- case 31347:
- {
- target->CastSpell(target, 31350, true, NULL, this);
- target->Kill(target);
- return;
- }
- // Spellcloth
- case 31373:
- {
- // Summon Elemental after create item
- target->SummonCreature(17870, 0, 0, 0, target->GetOrientation(), TEMPSUMMON_DEAD_DESPAWN, 0);
- return;
- }
- // Flame Quills
- case 34229:
- {
- // cast 24 spells 34269-34289, 34314-34316
- for (uint32 spell_id = 34269; spell_id != 34290; ++spell_id)
- caster->CastSpell(target, spell_id, true, NULL, this);
- for (uint32 spell_id = 34314; spell_id != 34317; ++spell_id)
- caster->CastSpell(target, spell_id, true, NULL, this);
- return;
- }
- // Remote Toy
- case 37027: triggerSpellId = 37029; break;
- // Eye of Grillok
- case 38495:
- {
- target->CastSpell(target, 38530, true, NULL, this);
- return;
- }
- // Absorb Eye of Grillok (Zezzak's Shard)
- case 38554:
- {
- if (target->GetTypeId() != TYPEID_UNIT)
- return;
-
- caster->CastSpell(caster, 38495, true, NULL, this);
-
- Creature* creatureTarget = target->ToCreature();
-
- creatureTarget->DespawnOrUnsummon();
- return;
- }
- // Tear of Azzinoth Summon Channel - it's not really supposed to do anything, and this only prevents the console spam
- case 39857:
- triggerSpellId = 39856;
- break;
- // Personalized Weather
- case 46736:
- triggerSpellId = 46737;
- break;
- // Shield Level 1
- case 63130:
- // Shield Level 2
- case 63131:
- // Shield Level 3
- case 63132:
- // Ball of Flames Visual
- case 71706:
- return;
- }
- break;
- }
- case SPELLFAMILY_MAGE:
- {
- switch(auraId)
- {
- // Invisibility
- case 66:
- // Here need periodic triger reducing threat spell (or do it manually)
- return;
- }
- break;
- }
- case SPELLFAMILY_DRUID:
- {
- switch(auraId)
- {
- // Cat Form
- // triggerSpellId not set and unknown effect triggered in this case, ignoring for while
- case 768:
- return;
- }
- break;
- }
- case SPELLFAMILY_SHAMAN:
- {
- switch(auraId)
- {
- // Lightning Shield (The Earthshatterer set trigger after cast Lighting Shield)
- case 28820:
- {
- // Need remove self if Lightning Shield not active
- if (!target->GetAuraEffect(SPELL_AURA_PROC_TRIGGER_SPELL, SPELLFAMILY_SHAMAN, 0x400))
- target->RemoveAurasDueToSpell(28820);
- return;
- }
- // Totemic Mastery (Skyshatter Regalia (Shaman Tier 6) - bonus)
- case 38443:
- {
- bool all = true;
- for (int i = SUMMON_SLOT_TOTEM; i < MAX_TOTEM_SLOT; ++i)
- {
- if (!target->m_SummonSlot[i])
- {
- all = false;
- break;
- }
- }
-
- if (all)
- caster->CastSpell(target, 38437, true, NULL, this);
- else
- target->RemoveAurasDueToSpell(38437);
- return;
- }
- }
- break;
- }
- default:
- break;
- }
- }
- else
- {
- // Spell exist but require custom code
- switch (auraId)
- {
- // Pursuing Spikes (Anub'arak)
- case 65920:
- case 65922:
- case 65923:
- {
- Unit *permafrostCaster = NULL;
- if (caster->HasAura(66193)) permafrostCaster = caster->GetAura(66193)->GetCaster();
- if (caster->HasAura(67855)) permafrostCaster = caster->GetAura(67855)->GetCaster();
- if (caster->HasAura(67856)) permafrostCaster = caster->GetAura(67856)->GetCaster();
- if (caster->HasAura(67857)) permafrostCaster = caster->GetAura(67857)->GetCaster();
-
- if (permafrostCaster)
- {
- if (Creature *permafrostCasterAsCreature = permafrostCaster->ToCreature())
- permafrostCasterAsCreature->DespawnOrUnsummon(3000);
-
- caster->CastSpell(caster, 66181, false);
- caster->RemoveAllAuras();
- if (Creature *casterAsCreature = caster->ToCreature())
- casterAsCreature->DisappearAndDie();
- }
- }
- break;
- // Mana Tide
- case 16191:
- target->CastCustomSpell(triggerTarget, triggerSpellId, &m_amount, NULL, NULL, true, NULL, this);
- return;
- // Negative Energy Periodic
- case 46284:
- caster->CastCustomSpell(triggerSpellId, SPELLVALUE_MAX_TARGETS, m_tickNumber / 10 + 1, NULL, true, NULL, this);
- return;
- // Poison (Grobbulus)
- case 28158:
- case 54362:
- // Slime Pool (Dreadscale & Acidmaw)
- case 66882:
- target->CastCustomSpell(triggerSpellId, SPELLVALUE_RADIUS_MOD, (int32)((((float)m_tickNumber / 60) * 0.9f + 0.1f) * 10000 * 2 / 3), NULL, true, NULL, this);
- return;
- // Beacon of Light
- case 53563:
- {
- Unit* triggerCaster = (Unit *)(GetBase()->GetOwner());
- triggerCaster->CastSpell(triggerTarget, triggeredSpellInfo, true, 0, this, triggerCaster->GetGUID());
- return;
- }
- // Slime Spray - temporary here until preventing default effect works again
- // added on 9.10.2010
- case 69508:
- {
- caster->CastSpell(triggerTarget, triggerSpellId, true, NULL, NULL, caster->GetGUID());
- return;
- }
- }
- }
-
- // Reget trigger spell proto
- triggeredSpellInfo = sSpellStore.LookupEntry(triggerSpellId);
-
- if (triggeredSpellInfo)
- {
- Unit* triggerCaster = GetTriggeredSpellCaster(triggeredSpellInfo, caster, triggerTarget);
- triggerCaster->CastSpell(triggerTarget, triggeredSpellInfo, true, NULL, this);
- sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "AuraEffect::TriggerSpell: Spell %u Trigger %u", GetId(), triggeredSpellInfo->Id);
- }
- else
- {
- Creature* c = triggerTarget->ToCreature();
- if (!c || (c && !sScriptMgr->OnDummyEffect(caster, GetId(), SpellEffIndex(GetEffIndex()), triggerTarget->ToCreature())) ||
- (c && !c->AI()->sOnDummyEffect(caster, GetId(), SpellEffIndex(GetEffIndex()))))
- sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "AuraEffect::TriggerSpell: Spell %u has non-existent spell %u in EffectTriggered[%d] and is therefor not triggered.", GetId(), triggerSpellId, GetEffIndex());
- }
-}
-
-void AuraEffect::TriggerSpellWithValue(Unit* target, Unit* caster) const
-{
- if (!caster || !target)
- return;
-
- Unit* triggerTarget = target;
-
- uint32 triggerSpellId = GetSpellProto()->EffectTriggerSpell[m_effIndex];
- SpellEntry const *triggeredSpellInfo = sSpellStore.LookupEntry(triggerSpellId);
- if (triggeredSpellInfo)
- {
- Unit* triggerCaster = GetTriggeredSpellCaster(triggeredSpellInfo, caster, triggerTarget);
-
- // generic casting code with custom spells and target/caster customs
- int32 basepoints0 = GetAmount();
- triggerCaster->CastCustomSpell(triggerTarget, triggerSpellId, &basepoints0, 0, 0, true, 0, this);
- }
- else
- sLog->outError("AuraEffect::TriggerSpellWithValue: Spell %u has value 0 in EffectTriggered[%d] and is therefor not handled. Define as custom case?", GetId(), GetEffIndex());
-}
-
bool AuraEffect::IsAffectedOnSpell(SpellEntry const *spell) const
{
if (!spell)
@@ -6594,7 +5409,7 @@ void AuraEffect::HandleAuraLinked(AuraApplication const* aurApp, uint8 mode, boo
else if (mode & AURA_EFFECT_HANDLE_REAPPLY && apply)
{
uint64 casterGUID = IsSpellRequiringFocusedTarget(GetSpellProto()) ? GetCasterGUID() : target->GetGUID();
-
+
// change the stack amount to be equal to stack amount of our aura
if (Aura* triggeredAura = target->GetAura(triggeredSpellId, casterGUID))
triggeredAura->ModStackAmount(GetBase()->GetStackAmount() - triggeredAura->GetStackAmount());
@@ -6719,3 +5534,1072 @@ void AuraEffect::HandleAuraSetVehicle(AuraApplication const* aurApp, uint8 mode,
target->ToPlayer()->GetSession()->SendPacket(&data);
}
}
+
+void AuraEffect::HandlePeriodicDummyAuraTick(Unit* target, Unit* caster) const
+{
+ switch (GetSpellProto()->SpellFamilyName)
+ {
+ case SPELLFAMILY_GENERIC:
+ switch (GetId())
+ {
+ case 54798: // FLAMING Arrow Triggered Effect
+ {
+ if (!caster || !target || !target->ToCreature() || !caster->IsVehicle() || target->HasAura(54683))
+ break;
+
+ if (Unit* rider = caster->GetVehicleKit()->GetPassenger(0))
+ {
+ target->CastSpell(target, 54683, true);
+
+ // Credit Frostworgs
+ if (target->GetEntry() == 29358)
+ rider->CastSpell(rider, 54896, true);
+ // Credit Frost Giants
+ else if (target->GetEntry() == 29351)
+ rider->CastSpell(rider, 54893, true);
+ }
+ break;
+ }
+ case 62292: // Blaze (Pool of Tar)
+ // should we use custom damage?
+ target->CastSpell((Unit*)NULL, m_spellProto->EffectTriggerSpell[m_effIndex], true);
+ break;
+ case 62399: // Overload Circuit
+ if (target->GetMap()->IsDungeon() && int(target->GetAppliedAuras().count(62399)) >= (target->GetMap()->IsHeroic() ? 4 : 2))
+ {
+ target->CastSpell(target, 62475, true); // System Shutdown
+ if (Unit *veh = target->GetVehicleBase())
+ veh->CastSpell(target, 62475, true);
+ }
+ break;
+ case 64821: // Fuse Armor (Razorscale)
+ if (GetBase()->GetStackAmount() == GetSpellProto()->StackAmount)
+ {
+ target->CastSpell(target, 64774, true, NULL, NULL, GetCasterGUID());
+ target->RemoveAura(64821);
+ }
+ break;
+ }
+ break;
+ case SPELLFAMILY_MAGE:
+ {
+ // Mirror Image
+ if (GetId() == 55342)
+ // Set name of summons to name of caster
+ target->CastSpell((Unit *)NULL, m_spellProto->EffectTriggerSpell[m_effIndex], true);
+ break;
+ }
+ case SPELLFAMILY_WARLOCK:
+ {
+ switch (GetSpellProto()->Id)
+ {
+ // Demonic Circle
+ case 48018:
+ if (GameObject* obj = target->GetGameObject(GetSpellProto()->Id))
+ {
+ if (target->IsWithinDist(obj, GetSpellMaxRange(48020, true)))
+ {
+ if (!target->HasAura(62388))
+ target->CastSpell(target, 62388, true);
+ }
+ else
+ target->RemoveAura(62388);
+ }
+ break;
+ }
+ break;
+ }
+ case SPELLFAMILY_DRUID:
+ {
+ switch (GetSpellProto()->Id)
+ {
+ // Frenzied Regeneration
+ case 22842:
+ {
+ // Converts up to 10 rage per second into health for $d. Each point of rage is converted into ${$m2/10}.1% of max health.
+ // Should be manauser
+ if (target->getPowerType() != POWER_RAGE)
+ break;
+ uint32 rage = target->GetPower(POWER_RAGE);
+ // Nothing todo
+ if (rage == 0)
+ break;
+ int32 mod = (rage < 100) ? rage : 100;
+ int32 points = target->CalculateSpellDamage(target, GetSpellProto(), 1);
+ int32 regen = target->GetMaxHealth() * (mod * points / 10) / 1000;
+ target->CastCustomSpell(target, 22845, &regen, 0, 0, true, 0, this);
+ target->SetPower(POWER_RAGE, rage-mod);
+ break;
+ }
+ }
+ break;
+ }
+ case SPELLFAMILY_ROGUE:
+ {
+ switch (GetSpellProto()->Id)
+ {
+ // Master of Subtlety
+ case 31666:
+ if (!target->HasAuraType(SPELL_AURA_MOD_STEALTH))
+ target->RemoveAurasDueToSpell(31665);
+ break;
+ // Killing Spree
+ case 51690:
+ {
+ // TODO: this should use effect[1] of 51690
+ UnitList targets;
+ {
+ // eff_radius == 0
+ float radius = GetSpellMaxRange(GetSpellProto(), false);
+
+ CellPair p(Trinity::ComputeCellPair(target->GetPositionX(), target->GetPositionY()));
+ Cell cell(p);
+ cell.data.Part.reserved = ALL_DISTRICT;
+
+ Trinity::AnyUnfriendlyVisibleUnitInObjectRangeCheck u_check(target, target, radius);
+ Trinity::UnitListSearcher<Trinity::AnyUnfriendlyVisibleUnitInObjectRangeCheck> checker(target, targets, u_check);
+
+ TypeContainerVisitor<Trinity::UnitListSearcher<Trinity::AnyUnfriendlyVisibleUnitInObjectRangeCheck>, GridTypeMapContainer > grid_object_checker(checker);
+ TypeContainerVisitor<Trinity::UnitListSearcher<Trinity::AnyUnfriendlyVisibleUnitInObjectRangeCheck>, WorldTypeMapContainer > world_object_checker(checker);
+
+ cell.Visit(p, grid_object_checker, *GetBase()->GetOwner()->GetMap(), *target, radius);
+ cell.Visit(p, world_object_checker, *GetBase()->GetOwner()->GetMap(), *target, radius);
+ }
+
+ if (targets.empty())
+ return;
+
+ UnitList::const_iterator itr = targets.begin();
+ std::advance(itr, rand()%targets.size());
+ Unit* spellTarget = *itr;
+
+ target->CastSpell(spellTarget, 57840, true);
+ target->CastSpell(spellTarget, 57841, true);
+ break;
+ }
+ // Overkill
+ case 58428:
+ if (!target->HasAuraType(SPELL_AURA_MOD_STEALTH))
+ target->RemoveAurasDueToSpell(58427);
+ break;
+ }
+ break;
+ }
+ case SPELLFAMILY_HUNTER:
+ {
+ // Explosive Shot
+ if (GetSpellProto()->SpellFamilyFlags[1] & 0x80000000)
+ {
+ if (caster)
+ caster->CastCustomSpell(53352, SPELLVALUE_BASE_POINT0, m_amount, target, true, NULL, this);
+ break;
+ }
+ switch (GetSpellProto()->Id)
+ {
+ // Feeding Frenzy Rank 1
+ case 53511:
+ if (target->getVictim() && target->getVictim()->HealthBelowPct(35))
+ target->CastSpell(target, 60096, true, 0, this);
+ return;
+ // Feeding Frenzy Rank 2
+ case 53512:
+ if (target->getVictim() && target->getVictim()->HealthBelowPct(35))
+ target->CastSpell(target, 60097, true, 0, this);
+ return;
+ default:
+ break;
+ }
+ break;
+ }
+ case SPELLFAMILY_SHAMAN:
+ if (GetId() == 52179) // Astral Shift
+ {
+ // Periodic need for remove visual on stun/fear/silence lost
+ if (!(target->GetUInt32Value(UNIT_FIELD_FLAGS)&(UNIT_FLAG_STUNNED|UNIT_FLAG_FLEEING|UNIT_FLAG_SILENCED)))
+ target->RemoveAurasDueToSpell(52179);
+ break;
+ }
+ break;
+ case SPELLFAMILY_DEATHKNIGHT:
+ switch (GetId())
+ {
+ case 49016: // Hysteria
+ uint32 damage = uint32(target->CountPctFromMaxHealth(1));
+ target->DealDamage(target, damage, NULL, NODAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
+ break;
+ }
+ // Death and Decay
+ if (GetSpellProto()->SpellFamilyFlags[0] & 0x20)
+ {
+ if (caster)
+ caster->CastCustomSpell(target, 52212, &m_amount, NULL, NULL, true, 0, this);
+ break;
+ }
+ // Blood of the North
+ // Reaping
+ // Death Rune Mastery
+ if (GetSpellProto()->SpellIconID == 3041 || GetSpellProto()->SpellIconID == 22 || GetSpellProto()->SpellIconID == 2622)
+ {
+ if (target->GetTypeId() != TYPEID_PLAYER)
+ return;
+ if (target->ToPlayer()->getClass() != CLASS_DEATH_KNIGHT)
+ return;
+
+ // timer expired - remove death runes
+ target->ToPlayer()->RemoveRunesByAuraEffect(this);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+void AuraEffect::HandlePeriodicTriggerSpellAuraTick(Unit* target, Unit* caster) const
+{
+ // generic casting code with custom spells and target/caster customs
+ uint32 triggerSpellId = GetSpellProto()->EffectTriggerSpell[GetEffIndex()];
+
+ SpellEntry const* triggeredSpellInfo = sSpellStore.LookupEntry(triggerSpellId);
+ SpellEntry const* auraSpellInfo = GetSpellProto();
+ uint32 auraId = auraSpellInfo->Id;
+
+ // specific code for cases with no trigger spell provided in field
+ if (triggeredSpellInfo == NULL)
+ {
+ switch (auraSpellInfo->SpellFamilyName)
+ {
+ case SPELLFAMILY_GENERIC:
+ {
+ switch (auraId)
+ {
+ // Thaumaturgy Channel
+ case 9712:
+ triggerSpellId = 21029;
+ break;
+ // Brood Affliction: Bronze
+ case 23170:
+ triggerSpellId = 23171;
+ break;
+ // Restoration
+ case 24379:
+ case 23493:
+ {
+ if (caster)
+ {
+ int32 heal = caster->CountPctFromMaxHealth(10);
+ caster->HealBySpell(target, auraSpellInfo, heal);
+
+ if (int32 mana = caster->GetMaxPower(POWER_MANA))
+ {
+ mana /= 10;
+ caster->EnergizeBySpell(caster, 23493, mana, POWER_MANA);
+ }
+ }
+ return;
+ }
+ // Nitrous Boost
+ case 27746:
+ if (caster && target->GetPower(POWER_MANA) >= 10)
+ {
+ target->ModifyPower(POWER_MANA, -10);
+ target->SendEnergizeSpellLog(caster, 27746, 10, POWER_MANA);
+ }
+ else
+ target->RemoveAurasDueToSpell(27746);
+ return;
+ // Frost Blast
+ case 27808:
+ if (caster)
+ caster->CastCustomSpell(29879, SPELLVALUE_BASE_POINT0, int32(target->CountPctFromMaxHealth(21)), target, true, NULL, this);
+ return;
+ // Detonate Mana
+ case 27819:
+ if (int32 mana = (int32)(target->GetMaxPower(POWER_MANA) / 10))
+ {
+ mana = target->ModifyPower(POWER_MANA, -mana);
+ target->CastCustomSpell(27820, SPELLVALUE_BASE_POINT0, -mana*10, target, true, NULL, this);
+ }
+ return;
+ // Inoculate Nestlewood Owlkin
+ case 29528:
+ if (target->GetTypeId() != TYPEID_UNIT) // prevent error reports in case ignored player target
+ return;
+ break;
+ // Feed Captured Animal
+ case 29917:
+ triggerSpellId = 29916;
+ break;
+ // Extract Gas
+ case 30427:
+ {
+ // move loot to player inventory and despawn target
+ if (caster && caster->GetTypeId() == TYPEID_PLAYER &&
+ target->GetTypeId() == TYPEID_UNIT &&
+ target->ToCreature()->GetCreatureInfo()->type == CREATURE_TYPE_GAS_CLOUD)
+ {
+ Player* player = caster->ToPlayer();
+ Creature* creature = target->ToCreature();
+ // missing lootid has been reported on startup - just return
+ if (!creature->GetCreatureInfo()->SkinLootId)
+ return;
+
+ player->AutoStoreLoot(creature->GetCreatureInfo()->SkinLootId, LootTemplates_Skinning, true);
+
+ creature->DespawnOrUnsummon();
+ }
+ return;
+ }
+ // Quake
+ case 30576:
+ triggerSpellId = 30571;
+ break;
+ // Doom
+ // TODO: effect trigger spell may be independant on spell targets, and executed in spell finish phase
+ // so instakill will be naturally done before trigger spell
+ case 31347:
+ {
+ target->CastSpell(target, 31350, true, NULL, this);
+ target->Kill(target);
+ return;
+ }
+ // Spellcloth
+ case 31373:
+ {
+ // Summon Elemental after create item
+ target->SummonCreature(17870, 0, 0, 0, target->GetOrientation(), TEMPSUMMON_DEAD_DESPAWN, 0);
+ return;
+ }
+ // Flame Quills
+ case 34229:
+ {
+ // cast 24 spells 34269-34289, 34314-34316
+ for (uint32 spell_id = 34269; spell_id != 34290; ++spell_id)
+ target->CastSpell(target, spell_id, true, NULL, this);
+ for (uint32 spell_id = 34314; spell_id != 34317; ++spell_id)
+ target->CastSpell(target, spell_id, true, NULL, this);
+ return;
+ }
+ // Remote Toy
+ case 37027: triggerSpellId = 37029; break;
+ // Eye of Grillok
+ case 38495:
+ {
+ target->CastSpell(target, 38530, true, NULL, this);
+ return;
+ }
+ // Absorb Eye of Grillok (Zezzak's Shard)
+ case 38554:
+ {
+ if (!caster || target->GetTypeId() != TYPEID_UNIT)
+ return;
+
+ caster->CastSpell(caster, 38495, true, NULL, this);
+
+ Creature* creatureTarget = target->ToCreature();
+
+ creatureTarget->DespawnOrUnsummon();
+ return;
+ }
+ // Tear of Azzinoth Summon Channel - it's not really supposed to do anything, and this only prevents the console spam
+ case 39857:
+ triggerSpellId = 39856;
+ break;
+ // Personalized Weather
+ case 46736:
+ triggerSpellId = 46737;
+ break;
+ }
+ break;
+ }
+ case SPELLFAMILY_SHAMAN:
+ {
+ switch(auraId)
+ {
+ // Lightning Shield (The Earthshatterer set trigger after cast Lighting Shield)
+ case 28820:
+ {
+ // Need remove self if Lightning Shield not active
+ if (!target->GetAuraEffect(SPELL_AURA_PROC_TRIGGER_SPELL, SPELLFAMILY_SHAMAN, 0x400))
+ target->RemoveAurasDueToSpell(28820);
+ return;
+ }
+ // Totemic Mastery (Skyshatter Regalia (Shaman Tier 6) - bonus)
+ case 38443:
+ {
+ bool all = true;
+ for (int i = SUMMON_SLOT_TOTEM; i < MAX_TOTEM_SLOT; ++i)
+ {
+ if (!target->m_SummonSlot[i])
+ {
+ all = false;
+ break;
+ }
+ }
+
+ if (all)
+ target->CastSpell(target, 38437, true, NULL, this);
+ else
+ target->RemoveAurasDueToSpell(38437);
+ return;
+ }
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ else
+ {
+ // Spell exist but require custom code
+ switch (auraId)
+ {
+ // Pursuing Spikes (Anub'arak)
+ case 65920:
+ case 65922:
+ case 65923:
+ {
+ Unit* permafrostCaster = NULL;
+ Aura* permafrostAura = NULL;
+ if (permafrostAura = target->GetAura(66193))
+ permafrostCaster = permafrostAura->GetCaster();
+ else if (permafrostAura = target->GetAura(67855))
+ permafrostCaster = permafrostAura->GetCaster();
+ else if (permafrostAura = target->GetAura(67856))
+ permafrostCaster = permafrostAura->GetCaster();
+ else if (permafrostAura = target->GetAura(67857))
+ permafrostCaster = permafrostAura->GetCaster();
+
+ if (permafrostCaster)
+ {
+ if (Creature* permafrostCasterCreature = permafrostCaster->ToCreature())
+ permafrostCasterCreature->DespawnOrUnsummon(3000);
+
+ target->CastSpell(target, 66181, false);
+ target->RemoveAllAuras();
+ if (Creature* targetCreature = target->ToCreature())
+ targetCreature->DisappearAndDie();
+ }
+ }
+ break;
+ // Mana Tide
+ case 16191:
+ target->CastCustomSpell(target, triggerSpellId, &m_amount, NULL, NULL, true, NULL, this);
+ return;
+ // Negative Energy Periodic
+ case 46284:
+ target->CastCustomSpell(triggerSpellId, SPELLVALUE_MAX_TARGETS, m_tickNumber / 10 + 1, NULL, true, NULL, this);
+ return;
+ // Poison (Grobbulus)
+ case 28158:
+ case 54362:
+ // Slime Pool (Dreadscale & Acidmaw)
+ case 66882:
+ target->CastCustomSpell(triggerSpellId, SPELLVALUE_RADIUS_MOD, (int32)((((float)m_tickNumber / 60) * 0.9f + 0.1f) * 10000 * 2 / 3), NULL, true, NULL, this);
+ return;
+ // Beacon of Light
+ case 53563:
+ {
+ // area aura owner casts the spell
+ GetBase()->GetUnitOwner()->CastSpell(target, triggeredSpellInfo, true, 0, this, GetBase()->GetUnitOwner()->GetGUID());
+ return;
+ }
+ // Slime Spray - temporary here until preventing default effect works again
+ // added on 9.10.2010
+ case 69508:
+ {
+ if (caster)
+ caster->CastSpell(target, triggerSpellId, true, NULL, NULL, caster->GetGUID());
+ return;
+ }
+ }
+ }
+
+ // Reget trigger spell proto
+ if (triggeredSpellInfo = sSpellStore.LookupEntry(triggerSpellId))
+ {
+ if (Unit* triggerCaster = GetTriggeredSpellCaster(triggeredSpellInfo, caster, target))
+ {
+ triggerCaster->CastSpell(target, triggeredSpellInfo, true, NULL, this);
+ sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "AuraEffect::HandlePeriodicTriggerSpellAuraTick: Spell %u Trigger %u", GetId(), triggeredSpellInfo->Id);
+ }
+ }
+ else
+ {
+ Creature* c = target->ToCreature();
+ if (!c || (c && !sScriptMgr->OnDummyEffect(caster, GetId(), SpellEffIndex(GetEffIndex()), target->ToCreature())) ||
+ (c && !c->AI()->sOnDummyEffect(caster, GetId(), SpellEffIndex(GetEffIndex()))))
+ sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "AuraEffect::HandlePeriodicTriggerSpellAuraTick: Spell %u has non-existent spell %u in EffectTriggered[%d] and is therefor not triggered.", GetId(), triggerSpellId, GetEffIndex());
+ }
+}
+
+void AuraEffect::HandlePeriodicTriggerSpellWithValueAuraTick(Unit* target, Unit* caster) const
+{
+ uint32 triggerSpellId = GetSpellProto()->EffectTriggerSpell[m_effIndex];
+ if (SpellEntry const *triggeredSpellInfo = sSpellStore.LookupEntry(triggerSpellId))
+ {
+ if (Unit* triggerCaster = GetTriggeredSpellCaster(triggeredSpellInfo, caster, target))
+ {
+ int32 basepoints0 = GetAmount();
+ triggerCaster->CastCustomSpell(target, triggerSpellId, &basepoints0, 0, 0, true, 0, this);
+ sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "AuraEffect::HandlePeriodicTriggerSpellWithValueAuraTick: Spell %u Trigger %u", GetId(), triggeredSpellInfo->Id);
+ }
+ }
+ else
+ sLog->outDebug(LOG_FILTER_SPELLS_AURAS,"AuraEffect::HandlePeriodicTriggerSpellWithValueAuraTick: Spell %u has non-existent spell %u in EffectTriggered[%d] and is therefor not triggered.", GetId(), triggerSpellId, GetEffIndex());
+}
+
+void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const
+{
+ if (!caster || !target->isAlive())
+ return;
+
+ if (target->HasUnitState(UNIT_STAT_ISOLATED) || target->IsImmunedToDamage(GetSpellProto()))
+ {
+ SendTickImmune(target, caster);
+ return;
+ }
+
+ // Consecrate ticks can miss and will not show up in the combat log
+ if (GetSpellProto()->Effect[GetEffIndex()] == SPELL_EFFECT_PERSISTENT_AREA_AURA &&
+ caster->SpellHitResult(target, GetSpellProto(), false) != SPELL_MISS_NONE)
+ return;
+
+ // some auras remove at specific health level or more
+ if (GetAuraType() == SPELL_AURA_PERIODIC_DAMAGE)
+ {
+ switch (GetId())
+ {
+ case 43093: case 31956: case 38801: // Grievous Wound
+ case 35321: case 38363: case 39215: // Gushing Wound
+ if (target->IsFullHealth())
+ {
+ target->RemoveAurasDueToSpell(GetId());
+ return;
+ }
+ break;
+ case 38772: // Grievous Wound
+ {
+ uint32 percent = SpellMgr::CalculateSpellEffectAmount(GetSpellProto(), 1, caster);
+ if (!target->HealthBelowPct(percent))
+ {
+ target->RemoveAurasDueToSpell(GetId());
+ return;
+ }
+ break;
+ }
+ }
+ }
+
+ uint32 absorb = 0;
+ uint32 resist = 0;
+ CleanDamage cleanDamage = CleanDamage(0, 0, BASE_ATTACK, MELEE_HIT_NORMAL);
+
+ // ignore non positive values (can be result apply spellmods to aura damage
+ uint32 damage = std::max(GetAmount(), 0);
+
+ if (GetAuraType() == SPELL_AURA_PERIODIC_DAMAGE)
+ {
+ damage = caster->SpellDamageBonus(target, GetSpellProto(), damage, DOT, GetBase()->GetStackAmount());
+
+ // Calculate armor mitigation
+ if (Unit::IsDamageReducedByArmor(GetSpellSchoolMask(GetSpellProto()), GetSpellProto(), m_effIndex))
+ {
+ uint32 damageReductedArmor = caster->CalcArmorReducedDamage(target, damage, GetSpellProto());
+ cleanDamage.mitigated_damage += damage - damageReductedArmor;
+ damage = damageReductedArmor;
+ }
+
+ // Curse of Agony damage-per-tick calculation
+ if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags[0] & 0x400) && GetSpellProto()->SpellIconID == 544)
+ {
+ uint32 totalTick = GetTotalTicks();
+ // 1..4 ticks, 1/2 from normal tick damage
+ if (m_tickNumber <= totalTick / 3)
+ damage = damage/2;
+ // 9..12 ticks, 3/2 from normal tick damage
+ else if (m_tickNumber > totalTick * 2 / 3)
+ damage += (damage+1)/2; // +1 prevent 0.5 damage possible lost at 1..4 ticks
+ // 5..8 ticks have normal tick damage
+ }
+ // There is a Chance to make a Soul Shard when Drain soul does damage
+ if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags[0] & 0x00004000))
+ {
+ if (caster->GetTypeId() == TYPEID_PLAYER && caster->ToPlayer()->isHonorOrXPTarget(target))
+ {
+ if (roll_chance_i(20))
+ {
+ caster->CastSpell(caster, 43836, true, 0, this);
+ // Glyph of Drain Soul - chance to create an additional Soul Shard
+ if (AuraEffect *aur = caster->GetAuraEffect(58070, 0))
+ if (roll_chance_i(aur->GetMiscValue()))
+ caster->CastSpell(caster, 58068, true, 0, aur);
+ }
+ }
+ }
+ if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_GENERIC)
+ {
+ switch (GetId())
+ {
+ case 70911: // Unbound Plague
+ case 72854: // Unbound Plague
+ case 72855: // Unbound Plague
+ case 72856: // Unbound Plague
+ damage *= uint32(pow(1.25f, int32(m_tickNumber)));
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ else
+ damage = uint32(target->CountPctFromMaxHealth(damage));
+
+ bool crit = IsPeriodicTickCrit(target, caster);
+ if (crit)
+ damage = caster->SpellCriticalDamageBonus(m_spellProto, damage, target);
+
+ int32 dmg = damage;
+ caster->ApplyResilience(target, NULL, &dmg, crit, CR_CRIT_TAKEN_SPELL);
+ damage = dmg;
+
+ caster->CalcAbsorbResist(target, GetSpellSchoolMask(GetSpellProto()), DOT, damage, &absorb, &resist, m_spellProto);
+
+ sLog->outDetail("PeriodicTick: %u (TypeId: %u) attacked %u (TypeId: %u) for %u dmg inflicted by %u abs is %u",
+ GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), target->GetGUIDLow(), target->GetTypeId(), damage, GetId(), absorb);
+
+ caster->DealDamageMods(target, damage, &absorb);
+
+ // Set trigger flag
+ uint32 procAttacker = PROC_FLAG_DONE_PERIODIC;
+ uint32 procVictim = PROC_FLAG_TAKEN_PERIODIC;
+ uint32 procEx = (crit ? PROC_EX_CRITICAL_HIT : PROC_EX_NORMAL_HIT) | PROC_EX_INTERNAL_DOT;
+ damage = (damage <= absorb+resist) ? 0 : (damage-absorb-resist);
+ if (damage)
+ procVictim |= PROC_FLAG_TAKEN_DAMAGE;
+
+ int32 overkill = damage - target->GetHealth();
+ if (overkill < 0)
+ overkill = 0;
+
+ SpellPeriodicAuraLogInfo pInfo(this, damage, overkill, absorb, resist, 0.0f, crit);
+ target->SendPeriodicAuraLog(&pInfo);
+
+ caster->ProcDamageAndSpell(target, procAttacker, procVictim, procEx, damage, BASE_ATTACK, GetSpellProto());
+
+ caster->DealDamage(target, damage, &cleanDamage, DOT, GetSpellSchoolMask(GetSpellProto()), GetSpellProto(), true);
+}
+
+void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) const
+{
+ if (!caster || !caster->isAlive() || !target->isAlive())
+ return;
+
+ if (target->HasUnitState(UNIT_STAT_ISOLATED) || target->IsImmunedToDamage(GetSpellProto()))
+ {
+ SendTickImmune(target, caster);
+ return;
+ }
+
+ if (GetSpellProto()->Effect[GetEffIndex()] == SPELL_EFFECT_PERSISTENT_AREA_AURA &&
+ caster->SpellHitResult(target, GetSpellProto(), false) != SPELL_MISS_NONE)
+ return;
+
+ uint32 absorb = 0;
+ uint32 resist = 0;
+ CleanDamage cleanDamage = CleanDamage(0, 0, BASE_ATTACK, MELEE_HIT_NORMAL);
+
+ uint32 damage = std::max(GetAmount(), 0);
+ damage = caster->SpellDamageBonus(target, GetSpellProto(), damage, DOT, GetBase()->GetStackAmount());
+
+ bool crit = IsPeriodicTickCrit(target, caster);
+ if (crit)
+ damage = caster->SpellCriticalDamageBonus(m_spellProto, damage, target);
+
+ // Calculate armor mitigation
+ if (Unit::IsDamageReducedByArmor(GetSpellSchoolMask(GetSpellProto()), GetSpellProto(), m_effIndex))
+ {
+ uint32 damageReductedArmor = caster->CalcArmorReducedDamage(target, damage, GetSpellProto());
+ cleanDamage.mitigated_damage += damage - damageReductedArmor;
+ damage = damageReductedArmor;
+ }
+
+ int32 dmg = damage;
+ caster->ApplyResilience(target, NULL, &dmg, crit, CR_CRIT_TAKEN_SPELL);
+ damage = dmg;
+
+ caster->CalcAbsorbResist(target, GetSpellSchoolMask(GetSpellProto()), DOT, damage, &absorb, &resist, m_spellProto);
+
+ if (target->GetHealth() < damage)
+ damage = uint32(target->GetHealth());
+
+ sLog->outDetail("PeriodicTick: %u (TypeId: %u) health leech of %u (TypeId: %u) for %u dmg inflicted by %u abs is %u",
+ GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), target->GetGUIDLow(), target->GetTypeId(), damage, GetId(), absorb);
+
+ caster->SendSpellNonMeleeDamageLog(target, GetId(), damage, GetSpellSchoolMask(GetSpellProto()), absorb, resist, false, 0, crit);
+
+ // Set trigger flag
+ uint32 procAttacker = PROC_FLAG_DONE_PERIODIC;
+ uint32 procVictim = PROC_FLAG_TAKEN_PERIODIC;
+ uint32 procEx = (crit ? PROC_EX_CRITICAL_HIT : PROC_EX_NORMAL_HIT) | PROC_EX_INTERNAL_DOT;
+ damage = (damage <= absorb+resist) ? 0 : (damage-absorb-resist);
+ if (damage)
+ procVictim |= PROC_FLAG_TAKEN_DAMAGE;
+ caster->ProcDamageAndSpell(target, procAttacker, procVictim, procEx, damage, BASE_ATTACK, GetSpellProto());
+ int32 new_damage = caster->DealDamage(target, damage, &cleanDamage, DOT, GetSpellSchoolMask(GetSpellProto()), GetSpellProto(), false);
+
+ float gainMultiplier = SpellMgr::CalculateSpellEffectValueMultiplier(GetSpellProto(), GetEffIndex(), caster);
+
+ uint32 heal = uint32(caster->SpellHealingBonus(caster, GetSpellProto(), uint32(new_damage * gainMultiplier), DOT, GetBase()->GetStackAmount()));
+
+ int32 gain = caster->HealBySpell(caster, GetSpellProto(), heal);
+ caster->getHostileRefManager().threatAssist(caster, gain * 0.5f, GetSpellProto());
+}
+
+void AuraEffect::HandlePeriodicHealthFunnelAuraTick(Unit* target, Unit* caster) const
+{
+ if (!caster || !caster->isAlive() || !target->isAlive())
+ return;
+
+ if (target->HasUnitState(UNIT_STAT_ISOLATED))
+ {
+ SendTickImmune(target, caster);
+ return;
+ }
+
+ uint32 damage = std::max(GetAmount(), 0);
+ // do not kill health donator
+ if (caster->GetHealth() < damage)
+ damage = caster->GetHealth() - 1;
+ if (!damage)
+ return;
+
+ caster->ModifyHealth(-(int32)damage);
+ sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "PeriodicTick: donator %u target %u damage %u.", caster->GetEntry(), target->GetEntry(), damage);
+
+ float gainMultiplier = SpellMgr::CalculateSpellEffectValueMultiplier(GetSpellProto(), GetEffIndex(), caster);
+
+ damage = int32(damage * gainMultiplier);
+
+ caster->HealBySpell(target, GetSpellProto(), damage);
+}
+
+void AuraEffect::HandlePeriodicHealAurasTick(Unit* target, Unit* caster) const
+{
+ if (!caster || !target->isAlive())
+ return;
+
+ if (target->HasUnitState(UNIT_STAT_ISOLATED))
+ {
+ SendTickImmune(target, caster);
+ return;
+ }
+
+ // heal for caster damage (must be alive)
+ if (target != caster && GetSpellProto()->AttributesEx2 & SPELL_ATTR2_HEALTH_FUNNEL && !caster->isAlive())
+ return;
+
+ // don't regen when permanent aura target has full power
+ if (GetBase()->IsPermanent() && target->IsFullHealth())
+ return;
+
+ // ignore negative values (can be result apply spellmods to aura damage
+ int32 damage = std::max(m_amount, 0);
+
+ if (GetAuraType() == SPELL_AURA_OBS_MOD_HEALTH)
+ {
+ // Taken mods
+ float TakenTotalMod = 1.0f;
+
+ // Tenacity increase healing % taken
+ if (AuraEffect const* Tenacity = target->GetAuraEffect(58549, 0))
+ AddPctN(TakenTotalMod, Tenacity->GetAmount());
+
+ // Healing taken percent
+ float minval = (float)target->GetMaxNegativeAuraModifier(SPELL_AURA_MOD_HEALING_PCT);
+ if (minval)
+ AddPctF(TakenTotalMod, minval);
+
+ float maxval = (float)target->GetMaxPositiveAuraModifier(SPELL_AURA_MOD_HEALING_PCT);
+ if (maxval)
+ AddPctF(TakenTotalMod, maxval);
+
+ // Healing over time taken percent
+ float minval_hot = (float)target->GetMaxNegativeAuraModifier(SPELL_AURA_MOD_HOT_PCT);
+ if (minval_hot)
+ AddPctF(TakenTotalMod, minval_hot);
+
+ float maxval_hot = (float)target->GetMaxPositiveAuraModifier(SPELL_AURA_MOD_HOT_PCT);
+ if (maxval_hot)
+ AddPctF(TakenTotalMod, maxval_hot);
+
+ TakenTotalMod = std::max(TakenTotalMod, 0.0f);
+
+ damage = uint32(target->CountPctFromMaxHealth(damage));
+ damage = uint32(damage * TakenTotalMod);
+ }
+ else
+ {
+ // Wild Growth = amount + (6 - 2*doneTicks) * ticks* amount / 100
+ if (m_spellProto->SpellFamilyName == SPELLFAMILY_DRUID && m_spellProto->SpellIconID == 2864)
+ {
+ int32 addition = int32(float(damage * GetTotalTicks()) * ((6-float(2*(GetTickNumber()-1)))/100));
+
+ // Item - Druid T10 Restoration 2P Bonus
+ if (AuraEffect* aurEff = caster->GetAuraEffect(70658, 0))
+ // divided by 50 instead of 100 because calculated as for every 2 tick
+ addition += abs(int32((addition * aurEff->GetAmount()) / 50));
+
+ damage += addition;
+ }
+
+ damage = caster->SpellHealingBonus(target, GetSpellProto(), damage, DOT, GetBase()->GetStackAmount());
+ }
+
+ bool crit = IsPeriodicTickCrit(target, caster);
+ if (crit)
+ damage = caster->SpellCriticalHealingBonus(m_spellProto, damage, target);
+
+ sLog->outDetail("PeriodicTick: %u (TypeId: %u) heal of %u (TypeId: %u) for %u health inflicted by %u",
+ GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), target->GetGUIDLow(), target->GetTypeId(), damage, GetId());
+
+ uint32 absorb = 0;
+ uint32 heal = uint32(damage);
+ caster->CalcHealAbsorb(target, GetSpellProto(), heal, absorb);
+ int32 gain = caster->DealHeal(target, heal);
+
+ SpellPeriodicAuraLogInfo pInfo(this, damage, damage - gain, absorb, 0, 0.0f, crit);
+ target->SendPeriodicAuraLog(&pInfo);
+
+ target->getHostileRefManager().threatAssist(caster, float(gain) * 0.5f, GetSpellProto());
+
+ bool haveCastItem = GetBase()->GetCastItemGUID() != 0;
+
+ // Health Funnel
+ // damage caster for heal amount
+ if (target != caster && GetSpellProto()->AttributesEx2 & SPELL_ATTR2_HEALTH_FUNNEL)
+ {
+ uint32 damage = SpellMgr::CalculateSpellEffectAmount(GetSpellProto(), 0); // damage is not affected by spell power
+ if ((int32)damage > gain)
+ damage = gain;
+ uint32 absorb = 0;
+ caster->DealDamageMods(caster, damage, &absorb);
+ caster->SendSpellNonMeleeDamageLog(caster, GetId(), damage, GetSpellSchoolMask(GetSpellProto()), absorb, 0, false, 0, false);
+
+ CleanDamage cleanDamage = CleanDamage(0, 0, BASE_ATTACK, MELEE_HIT_NORMAL);
+ caster->DealDamage(caster, damage, &cleanDamage, NODAMAGE, GetSpellSchoolMask(GetSpellProto()), GetSpellProto(), true);
+ }
+
+ uint32 procAttacker = PROC_FLAG_DONE_PERIODIC;
+ uint32 procVictim = PROC_FLAG_TAKEN_PERIODIC;
+ uint32 procEx = (crit ? PROC_EX_CRITICAL_HIT : PROC_EX_NORMAL_HIT) | PROC_EX_INTERNAL_HOT;
+ // ignore item heals
+ if (!haveCastItem)
+ caster->ProcDamageAndSpell(target, procAttacker, procVictim, procEx, damage, BASE_ATTACK, GetSpellProto());
+}
+
+void AuraEffect::HandlePeriodicManaLeechAuraTick(Unit* target, Unit* caster) const
+{
+ Powers powerType = Powers(GetMiscValue());
+
+ if (!caster || !caster->isAlive() || !target->isAlive() || target->getPowerType() != powerType)
+ return;
+
+ if (target->HasUnitState(UNIT_STAT_ISOLATED) || target->IsImmunedToDamage(GetSpellProto()))
+ {
+ SendTickImmune(target, caster);
+ return;
+ }
+
+ if (GetSpellProto()->Effect[GetEffIndex()] == SPELL_EFFECT_PERSISTENT_AREA_AURA &&
+ caster->SpellHitResult(target, GetSpellProto(), false) != SPELL_MISS_NONE)
+ return;
+
+ // ignore negative values (can be result apply spellmods to aura damage
+ int32 drainAmount = std::max(m_amount, 0);
+
+ // Special case: draining x% of mana (up to a maximum of 2*x% of the caster's maximum mana)
+ // It's mana percent cost spells, m_amount is percent drain from target
+ if (m_spellProto->ManaCostPercentage)
+ {
+ // max value
+ int32 maxmana = CalculatePctF(caster->GetMaxPower(powerType), drainAmount * 2.0f);
+ ApplyPctU(drainAmount, target->GetMaxPower(powerType));
+ if (drainAmount > maxmana)
+ drainAmount = maxmana;
+ }
+
+ sLog->outDetail("PeriodicTick: %u (TypeId: %u) power leech of %u (TypeId: %u) for %u dmg inflicted by %u",
+ GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), target->GetGUIDLow(), target->GetTypeId(), drainAmount, GetId());
+
+ // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
+ if (powerType == POWER_MANA)
+ drainAmount -= target->GetSpellCritDamageReduction(drainAmount);
+
+ int32 drainedAmount = target->ModifyPower(powerType, -drainAmount);
+
+ float gainMultiplier = SpellMgr::CalculateSpellEffectValueMultiplier(GetSpellProto(), GetEffIndex(), caster);
+
+ SpellPeriodicAuraLogInfo pInfo(this, drainedAmount, 0, 0, 0, gainMultiplier, false);
+ target->SendPeriodicAuraLog(&pInfo);
+
+ int32 gainAmount = int32(drainedAmount * gainMultiplier);
+ int32 gainedAmount = caster->ModifyPower(powerType, gainAmount);
+
+ target->AddThreat(caster, float(gainedAmount) * 0.5f, GetSpellSchoolMask(GetSpellProto()), GetSpellProto());
+
+ // spell-specific code
+ switch(GetId())
+ {
+ case 31447: // Mark of Kaz'rogal
+ if (target->GetPower(powerType) == 0)
+ {
+ target->CastSpell(target, 31463, true, 0, this);
+ // Remove aura
+ GetBase()->SetDuration(0);
+ }
+ break;
+ case 32960: // Mark of Kazzak
+ {
+ int32 modifier = int32(target->GetPower(powerType) * 0.05f);
+ target->ModifyPower(powerType, -modifier);
+
+ if (target->GetPower(powerType) == 0)
+ {
+ target->CastSpell(target, 32961, true, 0, this);
+ // Remove aura
+ GetBase()->SetDuration(0);
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ // Drain Mana
+ if (m_spellProto->SpellFamilyName == SPELLFAMILY_WARLOCK
+ && m_spellProto->SpellFamilyFlags[0] & 0x00000010)
+ {
+ int32 manaFeedVal = 0;
+ if (AuraEffect const* aurEff = GetBase()->GetEffect(1))
+ manaFeedVal = aurEff->GetAmount();
+ // Mana Feed - Drain Mana
+ if (manaFeedVal > 0)
+ {
+ int32 feedAmount = CalculatePctN(gainedAmount, manaFeedVal);
+ caster->CastCustomSpell(caster, 32554, &feedAmount, NULL, NULL, true, NULL, this);
+ }
+ }
+}
+
+void AuraEffect::HandleObsModPowerAuraTick(Unit* target, Unit* caster) const
+{
+ Powers powerType;
+ if (GetMiscValue() == POWER_ALL)
+ powerType = target->getPowerType();
+ else
+ powerType = Powers(GetMiscValue());
+
+ if (!target->isAlive() || target->GetMaxPower(powerType) == 0)
+ return;
+
+ if (target->HasUnitState(UNIT_STAT_ISOLATED))
+ {
+ SendTickImmune(target, caster);
+ return;
+ }
+
+ // don't regen when permanent aura target has full power
+ if (GetBase()->IsPermanent() && target->GetPower(powerType) == target->GetMaxPower(powerType))
+ return;
+
+ // ignore negative values (can be result apply spellmods to aura damage
+ uint32 amount = std::max(m_amount, 0) * target->GetMaxPower(powerType) /100;
+ sLog->outDetail("PeriodicTick: %u (TypeId: %u) energize %u (TypeId: %u) for %u dmg inflicted by %u",
+ GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), target->GetGUIDLow(), target->GetTypeId(), amount, GetId());
+
+ SpellPeriodicAuraLogInfo pInfo(this, amount, 0, 0, 0, 0.0f, false);
+ target->SendPeriodicAuraLog(&pInfo);
+
+ int32 gain = target->ModifyPower(powerType, amount);
+
+ if (caster)
+ target->getHostileRefManager().threatAssist(caster, float(gain) * 0.5f, GetSpellProto());
+}
+
+void AuraEffect::HandlePeriodicEnergizeAuraTick(Unit* target, Unit* caster) const
+{
+ Powers powerType = Powers(GetMiscValue());
+
+ if (!target->isAlive() || target->GetMaxPower(powerType) == 0)
+ return;
+
+ if (target->HasUnitState(UNIT_STAT_ISOLATED))
+ {
+ SendTickImmune(target, caster);
+ return;
+ }
+
+ // don't regen when permanent aura target has full power
+ if (GetBase()->IsPermanent() && target->GetPower(powerType) == target->GetMaxPower(powerType))
+ return;
+
+ // ignore negative values (can be result apply spellmods to aura damage
+ int32 amount = std::max(m_amount, 0);
+
+ SpellPeriodicAuraLogInfo pInfo(this, amount, 0, 0, 0, 0.0f, false);
+ target->SendPeriodicAuraLog(&pInfo);
+
+ sLog->outDetail("PeriodicTick: %u (TypeId: %u) energize %u (TypeId: %u) for %u dmg inflicted by %u",
+ GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), target->GetGUIDLow(), target->GetTypeId(), amount, GetId());
+
+ int32 gain = target->ModifyPower(powerType, amount);
+
+ if (caster)
+ target->getHostileRefManager().threatAssist(caster, float(gain) * 0.5f, GetSpellProto());
+}
+
+void AuraEffect::HandlePeriodicPowerBurnManaAuraTick(Unit* target, Unit* caster) const
+{
+ Powers powerType = Powers(GetMiscValue());
+
+ if (!caster || !target->isAlive() || target->getPowerType() != powerType)
+ return;
+
+ if (target->HasUnitState(UNIT_STAT_ISOLATED) || target->IsImmunedToDamage(GetSpellProto()))
+ {
+ SendTickImmune(target, caster);
+ return;
+ }
+
+ // ignore negative values (can be result apply spellmods to aura damage
+ int32 damage = std::max(m_amount, 0);
+
+ // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
+ if (powerType == POWER_MANA)
+ damage -= target->GetSpellCritDamageReduction(damage);
+
+ uint32 gain = uint32(-target->ModifyPower(powerType, -damage));
+
+ float dmgMultiplier = SpellMgr::CalculateSpellEffectValueMultiplier(GetSpellProto(), GetEffIndex(), caster);
+
+ SpellEntry const* spellProto = GetSpellProto();
+ // maybe has to be sent different to client, but not by SMSG_PERIODICAURALOG
+ SpellNonMeleeDamage damageInfo(caster, target, spellProto->Id, spellProto->SchoolMask);
+ // no SpellDamageBonus for burn mana
+ caster->CalculateSpellDamageTaken(&damageInfo, int32(gain * dmgMultiplier), spellProto);
+
+ caster->DealDamageMods(damageInfo.target, damageInfo.damage, &damageInfo.absorb);
+
+ caster->SendSpellNonMeleeDamageLog(&damageInfo);
+
+ // Set trigger flag
+ uint32 procAttacker = PROC_FLAG_DONE_PERIODIC;
+ uint32 procVictim = PROC_FLAG_TAKEN_PERIODIC;
+ uint32 procEx = createProcExtendMask(&damageInfo, SPELL_MISS_NONE) | PROC_EX_INTERNAL_DOT;
+ if (damageInfo.damage)
+ procVictim |= PROC_FLAG_TAKEN_DAMAGE;
+
+ caster->ProcDamageAndSpell(damageInfo.target, procAttacker, procVictim, procEx, damageInfo.damage, BASE_ATTACK, spellProto);
+
+ caster->DealSpellDamage(&damageInfo, true);
+}
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.h b/src/server/game/Spells/Auras/SpellAuraEffects.h
index 45b4d86c35b..2f1bab3f9fc 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.h
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.h
@@ -65,11 +65,7 @@ class AuraEffect
bool IsAffectedOnSpell(SpellEntry const *spell) const;
void SendTickImmune(Unit* target, Unit *caster) const;
-
void PeriodicTick(AuraApplication * aurApp, Unit* caster) const;
- void PeriodicDummyTick(Unit* target, Unit* caster) const;
- void TriggerSpell(Unit* target, Unit* caster) const;
- void TriggerSpellWithValue(Unit* target, Unit* caster) const;
void CleanupTriggeredSpells(Unit* target);
@@ -95,7 +91,7 @@ class AuraEffect
bool IsPeriodicTickCrit(Unit* target, Unit const* caster) const;
public:
- // aura effect handlers
+ // aura effect apply/remove handlers
void HandleNULL(AuraApplication const* /*aurApp*/, uint8 /*mode*/, bool /*apply*/) const
{
// not implemented
@@ -259,9 +255,22 @@ class AuraEffect
void HandleAuraConvertRune(AuraApplication const* aurApp, uint8 mode, bool apply) const;
void HandleAuraLinked(AuraApplication const* aurApp, uint8 mode, bool apply) const;
void HandleAuraOpenStable(AuraApplication const* aurApp, uint8 mode, bool apply) const;
+ void HandleAuraModFakeInebriation(AuraApplication const* aurApp, uint8 mode, bool apply) const;
void HandleAuraOverrideSpells(AuraApplication const* aurApp, uint8 mode, bool apply) const;
void HandleAuraSetVehicle(AuraApplication const* aurApp, uint8 mode, bool apply) const;
- void HandleAuraModFakeInebriation(AuraApplication const* aurApp, uint8 mode, bool apply) const;
+
+ // aura effect periodic tick handlers
+ void HandlePeriodicDummyAuraTick(Unit* target, Unit* caster) const;
+ void HandlePeriodicTriggerSpellAuraTick(Unit* target, Unit* caster) const;
+ void HandlePeriodicTriggerSpellWithValueAuraTick(Unit* target, Unit* caster) const;
+ void HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const;
+ void HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) const;
+ void HandlePeriodicHealthFunnelAuraTick(Unit* target, Unit* caster) const;
+ void HandlePeriodicHealAurasTick(Unit* target, Unit* caster) const;
+ void HandlePeriodicManaLeechAuraTick(Unit* target, Unit* caster) const;
+ void HandleObsModPowerAuraTick(Unit* target, Unit* caster) const;
+ void HandlePeriodicEnergizeAuraTick(Unit* target, Unit* caster) const;
+ void HandlePeriodicPowerBurnManaAuraTick(Unit* target, Unit* caster) const;
};
namespace Trinity