Core/Spells: Implement Periodic mechanics
Change behaviour of single target periodic aura ticks to be more blizzlike Also add some missing handling of SPELL_AURA_MOD_CREATURE_AOE_DAMAGE_AVOIDANCE Fixes Deep wounds and Chimera Shot Serpent Remove an ancient hack with Drain Soul, spell id 100001 can now be deleted from spell_dbc table Allows Rolling dot mechanics and allows DK's to roll diseases with pestilence, see link for info: http://forums.elitistjerks.com/topic/82503-frost-dps-in-333this-will-be-a-day-long-remembered/page-88
This commit is contained in:
@@ -3385,6 +3385,7 @@ void Unit::_ApplyAura(AuraApplication * aurApp, uint8 effMask)
|
||||
return;
|
||||
|
||||
aura->HandleAuraSpecificMods(aurApp, caster, true, false);
|
||||
aura->HandleAuraSpecificPeriodics(aurApp, caster);
|
||||
|
||||
// apply effects of the aura
|
||||
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
|
||||
@@ -8159,23 +8160,14 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg
|
||||
if (GetTypeId() != TYPEID_PLAYER)
|
||||
return false;
|
||||
|
||||
float averageDmg = 0;
|
||||
// now compute approximate weapon damage by formula from wowwiki.com
|
||||
Item* item = NULL;
|
||||
if (procFlags & PROC_FLAG_DONE_OFFHAND_ATTACK)
|
||||
item = ToPlayer()->GetUseableItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND);
|
||||
averageDmg = (GetFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE) + GetFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE)) / 2;
|
||||
else
|
||||
item = ToPlayer()->GetUseableItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND);
|
||||
averageDmg = (GetFloatValue(UNIT_FIELD_MINDAMAGE) + GetFloatValue(UNIT_FIELD_MAXDAMAGE)) / 2;
|
||||
|
||||
// dunno if it's really needed but will prevent any possible crashes
|
||||
if (!item)
|
||||
return false;
|
||||
|
||||
ItemTemplate const* weapon = item->GetTemplate();
|
||||
|
||||
float weaponDPS = weapon->getDPS();
|
||||
float attackPower = GetTotalAttackPowerValue(BASE_ATTACK) / 14.0f;
|
||||
float weaponSpeed = float(weapon->Delay) / 1000.0f;
|
||||
basepoints0 = int32((weaponDPS + attackPower) * weaponSpeed);
|
||||
basepoints0 = int32(averageDmg);
|
||||
break;
|
||||
}
|
||||
// Persistent Shield (Scarab Brooch trinket)
|
||||
@@ -9853,39 +9845,164 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin
|
||||
if (Unit* owner = GetOwner())
|
||||
return owner->SpellDamageBonusDone(victim, spellProto, pdamage, damagetype);
|
||||
|
||||
// Done total percent damage auras
|
||||
float DoneTotalMod = 1.0f;
|
||||
float ApCoeffMod = 1.0f;
|
||||
int32 DoneTotal = 0;
|
||||
|
||||
uint32 creatureTypeMask = victim->GetCreatureTypeMask();
|
||||
|
||||
// done scripted mod (take it from owner)
|
||||
Unit const* owner = GetOwner() ? GetOwner() : this;
|
||||
AuraEffectList const& mOverrideClassScript = owner->GetAuraEffectsByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
|
||||
for (AuraEffectList::const_iterator i = mOverrideClassScript.begin(); i != mOverrideClassScript.end(); ++i)
|
||||
{
|
||||
if (!(*i)->IsAffectedOnSpell(spellProto))
|
||||
continue;
|
||||
|
||||
switch ((*i)->GetMiscValue())
|
||||
{
|
||||
case 4418: // Increased Shock Damage
|
||||
case 4554: // Increased Lightning Damage
|
||||
case 4555: // Improved Moonfire
|
||||
case 5142: // Increased Lightning Damage
|
||||
case 5147: // Improved Consecration / Libram of Resurgence
|
||||
case 5148: // Idol of the Shooting Star
|
||||
case 6008: // Increased Lightning Damage
|
||||
case 8627: // Totem of Hex
|
||||
{
|
||||
DoneTotal += (*i)->GetAmount();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Custom scripted damage
|
||||
switch (spellProto->SpellFamilyName)
|
||||
{
|
||||
case SPELLFAMILY_DEATHKNIGHT:
|
||||
// Impurity (dummy effect)
|
||||
if (GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
PlayerSpellMap playerSpells = ToPlayer()->GetSpellMap();
|
||||
for (PlayerSpellMap::const_iterator itr = playerSpells.begin(); itr != playerSpells.end(); ++itr)
|
||||
{
|
||||
if (itr->second->state == PLAYERSPELL_REMOVED || itr->second->disabled)
|
||||
continue;
|
||||
switch (itr->first)
|
||||
{
|
||||
case 49220:
|
||||
case 49633:
|
||||
case 49635:
|
||||
case 49636:
|
||||
case 49638:
|
||||
if (SpellInfo const* proto = sSpellMgr->GetSpellInfo(itr->first))
|
||||
AddPct(ApCoeffMod, proto->Effects[0].CalcValue());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Done fixed damage bonus auras
|
||||
int32 DoneAdvertisedBenefit = SpellBaseDamageBonusDone(spellProto->GetSchoolMask());
|
||||
// Pets just add their bonus damage to their spell damage
|
||||
// note that their spell damage is just gain of their own auras
|
||||
if (HasUnitTypeMask(UNIT_MASK_GUARDIAN))
|
||||
DoneAdvertisedBenefit += ((Guardian*)this)->GetBonusDamage();
|
||||
|
||||
// Check for table values
|
||||
float coeff = 0;
|
||||
SpellBonusEntry const* bonus = sSpellMgr->GetSpellBonusData(spellProto->Id);
|
||||
if (bonus)
|
||||
{
|
||||
if (damagetype == DOT)
|
||||
{
|
||||
coeff = bonus->dot_damage;
|
||||
if (bonus->ap_dot_bonus > 0)
|
||||
{
|
||||
WeaponAttackType attType = (spellProto->IsRangedWeaponSpell() && spellProto->DmgClass != SPELL_DAMAGE_CLASS_MELEE) ? RANGED_ATTACK : BASE_ATTACK;
|
||||
float APbonus = float(victim->GetTotalAuraModifier(attType == BASE_ATTACK ? SPELL_AURA_MELEE_ATTACK_POWER_ATTACKER_BONUS : SPELL_AURA_RANGED_ATTACK_POWER_ATTACKER_BONUS));
|
||||
APbonus += GetTotalAttackPowerValue(attType);
|
||||
DoneTotal += int32(bonus->ap_dot_bonus * stack * ApCoeffMod * APbonus);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
coeff = bonus->direct_damage;
|
||||
if (bonus->ap_bonus > 0)
|
||||
{
|
||||
WeaponAttackType attType = (spellProto->IsRangedWeaponSpell() && spellProto->DmgClass != SPELL_DAMAGE_CLASS_MELEE) ? RANGED_ATTACK : BASE_ATTACK;
|
||||
float APbonus = float(victim->GetTotalAuraModifier(attType == BASE_ATTACK ? SPELL_AURA_MELEE_ATTACK_POWER_ATTACKER_BONUS : SPELL_AURA_RANGED_ATTACK_POWER_ATTACKER_BONUS));
|
||||
APbonus += GetTotalAttackPowerValue(attType);
|
||||
DoneTotal += int32(bonus->ap_bonus * stack * ApCoeffMod * APbonus);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Default calculation
|
||||
if (DoneAdvertisedBenefit)
|
||||
{
|
||||
if (!bonus || coeff < 0)
|
||||
coeff = CalculateDefaultCoefficient(spellProto, damagetype) * int32(stack);
|
||||
|
||||
float factorMod = CalculateLevelPenalty(spellProto) * stack;
|
||||
|
||||
if (Player* modOwner = GetSpellModOwner())
|
||||
{
|
||||
coeff *= 100.0f;
|
||||
modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_BONUS_MULTIPLIER, coeff);
|
||||
coeff /= 100.0f;
|
||||
}
|
||||
DoneTotal += int32(DoneAdvertisedBenefit * coeff * factorMod);
|
||||
}
|
||||
|
||||
// Done Percentage for DOT is already calculated, no need to do it again. The percentage mod is applied in Aura::HandleAuraSpecificMods.
|
||||
float tmpDamage = (int32(pdamage) + DoneTotal) * (damagetype == DOT ? 1.0f : SpellDamagePctDone(victim, spellProto, damagetype));
|
||||
// apply spellmod to Done damage (flat and pct)
|
||||
if (Player* modOwner = GetSpellModOwner())
|
||||
modOwner->ApplySpellMod(spellProto->Id, damagetype == DOT ? SPELLMOD_DOT : SPELLMOD_DAMAGE, tmpDamage);
|
||||
|
||||
return uint32(std::max(tmpDamage, 0.0f));
|
||||
}
|
||||
|
||||
float Unit::SpellDamagePctDone(Unit* victim, SpellInfo const* spellProto, DamageEffectType damagetype) const
|
||||
{
|
||||
if (!spellProto || !victim || damagetype == DIRECT_DAMAGE)
|
||||
return 1.0f;
|
||||
|
||||
// Some spells don't benefit from pct done mods
|
||||
if (spellProto->AttributesEx6 & SPELL_ATTR6_NO_DONE_PCT_DAMAGE_MODS)
|
||||
return 1.0f;
|
||||
|
||||
// For totems pct done mods are calculated when its calculation is run on the player in SpellDamageBonusDone.
|
||||
if (GetTypeId() == TYPEID_UNIT && ToCreature()->IsTotem())
|
||||
return 1.0f;
|
||||
|
||||
// Done total percent damage auras
|
||||
float DoneTotalMod = 1.0f;
|
||||
|
||||
// Pet damage?
|
||||
if (GetTypeId() == TYPEID_UNIT && !ToCreature()->IsPet())
|
||||
DoneTotalMod *= ToCreature()->GetSpellDamageMod(ToCreature()->GetCreatureTemplate()->rank);
|
||||
|
||||
// Some spells don't benefit from pct done mods
|
||||
if (!(spellProto->AttributesEx6 & SPELL_ATTR6_NO_DONE_PCT_DAMAGE_MODS))
|
||||
AuraEffectList const& mModDamagePercentDone = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE);
|
||||
for (AuraEffectList::const_iterator i = mModDamagePercentDone.begin(); i != mModDamagePercentDone.end(); ++i)
|
||||
{
|
||||
AuraEffectList const& mModDamagePercentDone = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE);
|
||||
for (AuraEffectList::const_iterator i = mModDamagePercentDone.begin(); i != mModDamagePercentDone.end(); ++i)
|
||||
{
|
||||
if (spellProto->EquippedItemClass == -1 && (*i)->GetSpellInfo()->EquippedItemClass != -1) //prevent apply mods from weapon specific case to non weapon specific spells (Example: thunder clap and two-handed weapon specialization)
|
||||
continue;
|
||||
if (spellProto->EquippedItemClass == -1 && (*i)->GetSpellInfo()->EquippedItemClass != -1) //prevent apply mods from weapon specific case to non weapon specific spells (Example: thunder clap and two-handed weapon specialization)
|
||||
continue;
|
||||
|
||||
if ((*i)->GetMiscValue() & spellProto->GetSchoolMask())
|
||||
{
|
||||
if ((*i)->GetSpellInfo()->EquippedItemClass == -1)
|
||||
AddPct(DoneTotalMod, (*i)->GetAmount());
|
||||
else if (!((*i)->GetSpellInfo()->AttributesEx5 & SPELL_ATTR5_SPECIAL_ITEM_CLASS_CHECK) && ((*i)->GetSpellInfo()->EquippedItemSubClassMask == 0))
|
||||
AddPct(DoneTotalMod, (*i)->GetAmount());
|
||||
else if (ToPlayer() && ToPlayer()->HasItemFitToSpellRequirements((*i)->GetSpellInfo()))
|
||||
AddPct(DoneTotalMod, (*i)->GetAmount());
|
||||
}
|
||||
if ((*i)->GetMiscValue() & spellProto->GetSchoolMask())
|
||||
{
|
||||
if ((*i)->GetSpellInfo()->EquippedItemClass == -1)
|
||||
AddPct(DoneTotalMod, (*i)->GetAmount());
|
||||
else if (!((*i)->GetSpellInfo()->AttributesEx5 & SPELL_ATTR5_SPECIAL_ITEM_CLASS_CHECK) && ((*i)->GetSpellInfo()->EquippedItemSubClassMask == 0))
|
||||
AddPct(DoneTotalMod, (*i)->GetAmount());
|
||||
else if (ToPlayer() && ToPlayer()->HasItemFitToSpellRequirements((*i)->GetSpellInfo()))
|
||||
AddPct(DoneTotalMod, (*i)->GetAmount());
|
||||
}
|
||||
}
|
||||
|
||||
uint32 creatureTypeMask = victim->GetCreatureTypeMask();
|
||||
// Add flat bonus from spell damage versus
|
||||
DoneTotal += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_FLAT_SPELL_DAMAGE_VERSUS, creatureTypeMask);
|
||||
|
||||
AuraEffectList const& mDamageDoneVersus = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_DONE_VERSUS);
|
||||
for (AuraEffectList::const_iterator i = mDamageDoneVersus.begin(); i != mDamageDoneVersus.end(); ++i)
|
||||
if (creatureTypeMask & uint32((*i)->GetMiscValue()))
|
||||
@@ -9899,7 +10016,7 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin
|
||||
|
||||
// done scripted mod (take it from owner)
|
||||
Unit const* owner = GetOwner() ? GetOwner() : this;
|
||||
AuraEffectList const& mOverrideClassScript= owner->GetAuraEffectsByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
|
||||
AuraEffectList const& mOverrideClassScript = owner->GetAuraEffectsByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
|
||||
for (AuraEffectList::const_iterator i = mOverrideClassScript.begin(); i != mOverrideClassScript.end(); ++i)
|
||||
{
|
||||
if (!(*i)->IsAffectedOnSpell(spellProto))
|
||||
@@ -9956,18 +10073,6 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin
|
||||
AddPct(DoneTotalMod, (*i)->GetAmount());
|
||||
break;
|
||||
}
|
||||
case 4418: // Increased Shock Damage
|
||||
case 4554: // Increased Lightning Damage
|
||||
case 4555: // Improved Moonfire
|
||||
case 5142: // Increased Lightning Damage
|
||||
case 5147: // Improved Consecration / Libram of Resurgence
|
||||
case 5148: // Idol of the Shooting Star
|
||||
case 6008: // Increased Lightning Damage
|
||||
case 8627: // Totem of Hex
|
||||
{
|
||||
DoneTotal += (*i)->GetAmount();
|
||||
break;
|
||||
}
|
||||
// Tundra Stalker
|
||||
// Merciless Combat
|
||||
case 7277:
|
||||
@@ -10133,14 +10238,14 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Drain Soul - increased damage for targets under 25 % HP
|
||||
if (spellProto->SpellFamilyFlags[0] & 0x00004000)
|
||||
if (HasAura(100001))
|
||||
DoneTotalMod *= 4;
|
||||
// Shadow Bite (15% increase from each dot)
|
||||
if (spellProto->SpellFamilyFlags[1] & 0x00400000 && IsPet())
|
||||
if (uint8 count = victim->GetDoTsByCaster(GetOwnerGUID()))
|
||||
AddPct(DoneTotalMod, 15 * count);
|
||||
|
||||
// Drain Soul - If the target is at or below 25% health, Drain Soul causes four times the normal damage
|
||||
if (spellProto->SpellFamilyFlags[0] & 0x00004000 && !victim->HealthAbovePct(25))
|
||||
DoneTotalMod *= 4;
|
||||
break;
|
||||
case SPELLFAMILY_HUNTER:
|
||||
// Steady Shot
|
||||
@@ -10155,101 +10260,15 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin
|
||||
if (AuraEffect* aurEff = GetDummyAuraEffect(SPELLFAMILY_DEATHKNIGHT, 2721, 0))
|
||||
AddPct(DoneTotalMod, aurEff->GetAmount());
|
||||
|
||||
// Sigil of the Vengeful Heart
|
||||
if (spellProto->SpellFamilyFlags[0] & 0x2000)
|
||||
if (AuraEffect* aurEff = GetAuraEffect(64962, EFFECT_1))
|
||||
AddPct(DoneTotal, aurEff->GetAmount());
|
||||
|
||||
// Glacier Rot
|
||||
if (spellProto->SpellFamilyFlags[0] & 0x2 || spellProto->SpellFamilyFlags[1] & 0x6)
|
||||
if (AuraEffect* aurEff = GetDummyAuraEffect(SPELLFAMILY_DEATHKNIGHT, 196, 0))
|
||||
if (victim->GetDiseasesByCaster(owner->GetGUID()) > 0)
|
||||
AddPct(DoneTotalMod, aurEff->GetAmount());
|
||||
|
||||
// Impurity (dummy effect)
|
||||
if (GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
PlayerSpellMap playerSpells = ToPlayer()->GetSpellMap();
|
||||
for (PlayerSpellMap::const_iterator itr = playerSpells.begin(); itr != playerSpells.end(); ++itr)
|
||||
{
|
||||
if (itr->second->state == PLAYERSPELL_REMOVED || itr->second->disabled)
|
||||
continue;
|
||||
switch (itr->first)
|
||||
{
|
||||
case 49220:
|
||||
case 49633:
|
||||
case 49635:
|
||||
case 49636:
|
||||
case 49638:
|
||||
{
|
||||
if (SpellInfo const* proto = sSpellMgr->GetSpellInfo(itr->first))
|
||||
AddPct(ApCoeffMod, proto->Effects[0].CalcValue());
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Done fixed damage bonus auras
|
||||
int32 DoneAdvertisedBenefit = SpellBaseDamageBonusDone(spellProto->GetSchoolMask());
|
||||
// Pets just add their bonus damage to their spell damage
|
||||
// note that their spell damage is just gain of their own auras
|
||||
if (HasUnitTypeMask(UNIT_MASK_GUARDIAN))
|
||||
DoneAdvertisedBenefit += ((Guardian*)this)->GetBonusDamage();
|
||||
|
||||
// Check for table values
|
||||
float coeff = 0;
|
||||
SpellBonusEntry const* bonus = sSpellMgr->GetSpellBonusData(spellProto->Id);
|
||||
if (bonus)
|
||||
{
|
||||
if (damagetype == DOT)
|
||||
{
|
||||
coeff = bonus->dot_damage;
|
||||
if (bonus->ap_dot_bonus > 0)
|
||||
{
|
||||
WeaponAttackType attType = (spellProto->IsRangedWeaponSpell() && spellProto->DmgClass != SPELL_DAMAGE_CLASS_MELEE) ? RANGED_ATTACK : BASE_ATTACK;
|
||||
float APbonus = float(victim->GetTotalAuraModifier(attType == BASE_ATTACK ? SPELL_AURA_MELEE_ATTACK_POWER_ATTACKER_BONUS : SPELL_AURA_RANGED_ATTACK_POWER_ATTACKER_BONUS));
|
||||
APbonus += GetTotalAttackPowerValue(attType);
|
||||
DoneTotal += int32(bonus->ap_dot_bonus * stack * ApCoeffMod * APbonus);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
coeff = bonus->direct_damage;
|
||||
if (bonus->ap_bonus > 0)
|
||||
{
|
||||
WeaponAttackType attType = (spellProto->IsRangedWeaponSpell() && spellProto->DmgClass != SPELL_DAMAGE_CLASS_MELEE) ? RANGED_ATTACK : BASE_ATTACK;
|
||||
float APbonus = float(victim->GetTotalAuraModifier(attType == BASE_ATTACK ? SPELL_AURA_MELEE_ATTACK_POWER_ATTACKER_BONUS : SPELL_AURA_RANGED_ATTACK_POWER_ATTACKER_BONUS));
|
||||
APbonus += GetTotalAttackPowerValue(attType);
|
||||
DoneTotal += int32(bonus->ap_bonus * stack * ApCoeffMod * APbonus);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Default calculation
|
||||
if (DoneAdvertisedBenefit)
|
||||
{
|
||||
if (!bonus || coeff < 0)
|
||||
coeff = CalculateDefaultCoefficient(spellProto, damagetype) * int32(stack);
|
||||
|
||||
float factorMod = CalculateLevelPenalty(spellProto) * stack;
|
||||
|
||||
if (Player* modOwner = GetSpellModOwner())
|
||||
{
|
||||
coeff *= 100.0f;
|
||||
modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_BONUS_MULTIPLIER, coeff);
|
||||
coeff /= 100.0f;
|
||||
}
|
||||
DoneTotal += int32(DoneAdvertisedBenefit * coeff * factorMod);
|
||||
}
|
||||
|
||||
float tmpDamage = (int32(pdamage) + DoneTotal) * DoneTotalMod;
|
||||
// apply spellmod to Done damage (flat and pct)
|
||||
if (Player* modOwner = GetSpellModOwner())
|
||||
modOwner->ApplySpellMod(spellProto->Id, damagetype == DOT ? SPELLMOD_DOT : SPELLMOD_DAMAGE, tmpDamage);
|
||||
|
||||
return uint32(std::max(tmpDamage, 0.0f));
|
||||
return DoneTotalMod;
|
||||
}
|
||||
|
||||
uint32 Unit::SpellDamageBonusTaken(Unit* caster, SpellInfo const* spellProto, uint32 pdamage, DamageEffectType damagetype, uint32 stack) const
|
||||
@@ -10407,16 +10426,21 @@ int32 Unit::SpellBaseDamageBonusTaken(SpellSchoolMask schoolMask) const
|
||||
return TakenAdvertisedBenefit;
|
||||
}
|
||||
|
||||
bool Unit::isSpellCrit(Unit* victim, SpellInfo const* spellProto, SpellSchoolMask schoolMask, WeaponAttackType attackType) const
|
||||
bool Unit::IsSpellCrit(Unit* victim, SpellInfo const* spellProto, SpellSchoolMask schoolMask, WeaponAttackType attackType) const
|
||||
{
|
||||
return roll_chance_f(GetUnitSpellCriticalChance(victim, spellProto, schoolMask, attackType));
|
||||
}
|
||||
|
||||
float Unit::GetUnitSpellCriticalChance(Unit* victim, SpellInfo const* spellProto, SpellSchoolMask schoolMask, WeaponAttackType attackType) const
|
||||
{
|
||||
//! Mobs can't crit with spells. Player Totems can
|
||||
//! Fire Elemental (from totem) can too - but this part is a hack and needs more research
|
||||
if (IS_CREATURE_GUID(GetGUID()) && !(IsTotem() && IS_PLAYER_GUID(GetOwnerGUID())) && GetEntry() != 15438)
|
||||
return false;
|
||||
if (IS_CRE_OR_VEH_GUID(GetGUID()) && !(IsTotem() && IS_PLAYER_GUID(GetOwnerGUID())) && GetEntry() != 15438)
|
||||
return 0.0f;
|
||||
|
||||
// not critting spell
|
||||
if ((spellProto->AttributesEx2 & SPELL_ATTR2_CANT_CRIT))
|
||||
return false;
|
||||
return 0.0f;
|
||||
|
||||
float crit_chance = 0.0f;
|
||||
switch (spellProto->DmgClass)
|
||||
@@ -10432,7 +10456,7 @@ bool Unit::isSpellCrit(Unit* victim, SpellInfo const* spellProto, SpellSchoolMas
|
||||
case 71646: // Item - Bauble of True Blood 25m
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
return 0.0f;
|
||||
}
|
||||
// Do not add a break here, case fallthrough is intentional! Adding a break will make above spells unable to crit.
|
||||
case SPELL_DAMAGE_CLASS_MAGIC:
|
||||
@@ -10534,7 +10558,7 @@ bool Unit::isSpellCrit(Unit* victim, SpellInfo const* spellProto, SpellSchoolMas
|
||||
else if (spellProto->GetCategory() == 19)
|
||||
{
|
||||
if (victim->GetCreatureTypeMask() & CREATURE_TYPEMASK_DEMON_OR_UNDEAD)
|
||||
return true;
|
||||
return 100.0f;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@@ -10544,7 +10568,7 @@ bool Unit::isSpellCrit(Unit* victim, SpellInfo const* spellProto, SpellSchoolMas
|
||||
{
|
||||
if (victim->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_SHAMAN, 0x10000000, 0, 0, GetGUID()))
|
||||
if (victim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE) > -100)
|
||||
return true;
|
||||
return 100.0f;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@@ -10592,17 +10616,14 @@ bool Unit::isSpellCrit(Unit* victim, SpellInfo const* spellProto, SpellSchoolMas
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
return 0.0f;
|
||||
}
|
||||
// percent done
|
||||
// only players use intelligence for critical chance computations
|
||||
if (Player* modOwner = GetSpellModOwner())
|
||||
modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_CRITICAL_CHANCE, crit_chance);
|
||||
|
||||
crit_chance = crit_chance > 0.0f ? crit_chance : 0.0f;
|
||||
if (roll_chance_f(crit_chance))
|
||||
return true;
|
||||
return false;
|
||||
return crit_chance > 0.0f ? crit_chance : 0.0f;
|
||||
}
|
||||
|
||||
uint32 Unit::SpellCriticalDamageBonus(SpellInfo const* spellProto, uint32 damage, Unit* victim)
|
||||
@@ -10686,14 +10707,8 @@ uint32 Unit::SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, ui
|
||||
if (spellProto->SpellFamilyName == SPELLFAMILY_POTION)
|
||||
return healamount;
|
||||
|
||||
float DoneTotalMod = 1.0f;
|
||||
int32 DoneTotal = 0;
|
||||
|
||||
// Healing done percent
|
||||
AuraEffectList const& mHealingDonePct = GetAuraEffectsByType(SPELL_AURA_MOD_HEALING_DONE_PERCENT);
|
||||
for (AuraEffectList::const_iterator i = mHealingDonePct.begin(); i != mHealingDonePct.end(); ++i)
|
||||
AddPct(DoneTotalMod, (*i)->GetAmount());
|
||||
|
||||
// done scripted mod (take it from owner)
|
||||
Unit const* owner = GetOwner() ? GetOwner() : this;
|
||||
AuraEffectList const& mOverrideClassScript= owner->GetAuraEffectsByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
|
||||
@@ -10708,43 +10723,6 @@ uint32 Unit::SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, ui
|
||||
case 3736: // Hateful Totem of the Third Wind / Increased Lesser Healing Wave / LK Arena (4/5/6) Totem of the Third Wind / Savage Totem of the Third Wind
|
||||
DoneTotal += (*i)->GetAmount();
|
||||
break;
|
||||
case 21: // Test of Faith
|
||||
case 6935:
|
||||
case 6918:
|
||||
if (victim->HealthBelowPct(50))
|
||||
AddPct(DoneTotalMod, (*i)->GetAmount());
|
||||
break;
|
||||
case 7798: // Glyph of Regrowth
|
||||
{
|
||||
if (victim->GetAuraEffect(SPELL_AURA_PERIODIC_HEAL, SPELLFAMILY_DRUID, 0x40, 0, 0))
|
||||
AddPct(DoneTotalMod, (*i)->GetAmount());
|
||||
break;
|
||||
}
|
||||
case 8477: // Nourish Heal Boost
|
||||
{
|
||||
int32 stepPercent = (*i)->GetAmount();
|
||||
int32 modPercent = 0;
|
||||
AuraApplicationMap const& victimAuras = victim->GetAppliedAuras();
|
||||
for (AuraApplicationMap::const_iterator itr = victimAuras.begin(); itr != victimAuras.end(); ++itr)
|
||||
{
|
||||
Aura const* aura = itr->second->GetBase();
|
||||
if (aura->GetCasterGUID() != GetGUID())
|
||||
continue;
|
||||
SpellInfo const* m_spell = aura->GetSpellInfo();
|
||||
if (m_spell->SpellFamilyName != SPELLFAMILY_DRUID ||
|
||||
!(m_spell->SpellFamilyFlags[1] & 0x00000010 || m_spell->SpellFamilyFlags[0] & 0x50))
|
||||
continue;
|
||||
modPercent += stepPercent * aura->GetStackAmount();
|
||||
}
|
||||
AddPct(DoneTotalMod, modPercent);
|
||||
break;
|
||||
}
|
||||
case 7871: // Glyph of Lesser Healing Wave
|
||||
{
|
||||
if (victim->GetAuraEffect(SPELL_AURA_DUMMY, SPELLFAMILY_SHAMAN, 0, 0x00000400, 0, GetGUID()))
|
||||
AddPct(DoneTotalMod, (*i)->GetAmount());
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -10817,8 +10795,8 @@ uint32 Unit::SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, ui
|
||||
DoneTotal = 0;
|
||||
}
|
||||
|
||||
// use float as more appropriate for negative values and percent applying
|
||||
float heal = float(int32(healamount) + DoneTotal) * DoneTotalMod;
|
||||
// Done Percentage for DOT is already calculated, no need to do it again. The percentage mod is applied in Aura::HandleAuraSpecificMods.
|
||||
float heal = float(int32(healamount) + DoneTotal) * (damagetype == DOT ? 1.0f : SpellHealingPctDone(victim, spellProto));
|
||||
// apply spellmod to Done amount
|
||||
if (Player* modOwner = GetSpellModOwner())
|
||||
modOwner->ApplySpellMod(spellProto->Id, damagetype == DOT ? SPELLMOD_DOT : SPELLMOD_DAMAGE, heal);
|
||||
@@ -10826,6 +10804,78 @@ uint32 Unit::SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, ui
|
||||
return uint32(std::max(heal, 0.0f));
|
||||
}
|
||||
|
||||
float Unit::SpellHealingPctDone(Unit* victim, SpellInfo const* spellProto) const
|
||||
{
|
||||
// For totems pct done mods are calculated when its calculation is run on the player in SpellHealingBonusDone.
|
||||
if (GetTypeId() == TYPEID_UNIT && IsTotem())
|
||||
if (Unit* owner = GetOwner())
|
||||
return 1.0f;
|
||||
|
||||
// No bonus healing for potion spells
|
||||
if (spellProto->SpellFamilyName == SPELLFAMILY_POTION)
|
||||
return 1.0f;
|
||||
|
||||
float DoneTotalMod = 1.0f;
|
||||
|
||||
// Healing done percent
|
||||
AuraEffectList const& mHealingDonePct = GetAuraEffectsByType(SPELL_AURA_MOD_HEALING_DONE_PERCENT);
|
||||
for (AuraEffectList::const_iterator i = mHealingDonePct.begin(); i != mHealingDonePct.end(); ++i)
|
||||
AddPct(DoneTotalMod, (*i)->GetAmount());
|
||||
|
||||
// done scripted mod (take it from owner)
|
||||
Unit const* owner = GetOwner() ? GetOwner() : this;
|
||||
AuraEffectList const& mOverrideClassScript= owner->GetAuraEffectsByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
|
||||
for (AuraEffectList::const_iterator i = mOverrideClassScript.begin(); i != mOverrideClassScript.end(); ++i)
|
||||
{
|
||||
if (!(*i)->IsAffectedOnSpell(spellProto))
|
||||
continue;
|
||||
switch ((*i)->GetMiscValue())
|
||||
{
|
||||
case 21: // Test of Faith
|
||||
case 6935:
|
||||
case 6918:
|
||||
if (victim->HealthBelowPct(50))
|
||||
AddPct(DoneTotalMod, (*i)->GetAmount());
|
||||
break;
|
||||
case 7798: // Glyph of Regrowth
|
||||
{
|
||||
if (victim->GetAuraEffect(SPELL_AURA_PERIODIC_HEAL, SPELLFAMILY_DRUID, 0x40, 0, 0))
|
||||
AddPct(DoneTotalMod, (*i)->GetAmount());
|
||||
break;
|
||||
}
|
||||
case 8477: // Nourish Heal Boost
|
||||
{
|
||||
int32 stepPercent = (*i)->GetAmount();
|
||||
int32 modPercent = 0;
|
||||
AuraApplicationMap const& victimAuras = victim->GetAppliedAuras();
|
||||
for (AuraApplicationMap::const_iterator itr = victimAuras.begin(); itr != victimAuras.end(); ++itr)
|
||||
{
|
||||
Aura const* aura = itr->second->GetBase();
|
||||
if (aura->GetCasterGUID() != GetGUID())
|
||||
continue;
|
||||
SpellInfo const* m_spell = aura->GetSpellInfo();
|
||||
if (m_spell->SpellFamilyName != SPELLFAMILY_DRUID ||
|
||||
!(m_spell->SpellFamilyFlags[1] & 0x00000010 || m_spell->SpellFamilyFlags[0] & 0x50))
|
||||
continue;
|
||||
modPercent += stepPercent * aura->GetStackAmount();
|
||||
}
|
||||
AddPct(DoneTotalMod, modPercent);
|
||||
break;
|
||||
}
|
||||
case 7871: // Glyph of Lesser Healing Wave
|
||||
{
|
||||
if (victim->GetAuraEffect(SPELL_AURA_DUMMY, SPELLFAMILY_SHAMAN, 0, 0x00000400, 0, GetGUID()))
|
||||
AddPct(DoneTotalMod, (*i)->GetAmount());
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return DoneTotalMod;
|
||||
}
|
||||
|
||||
uint32 Unit::SpellHealingBonusTaken(Unit* caster, SpellInfo const* spellProto, uint32 healamount, DamageEffectType damagetype, uint32 stack) const
|
||||
{
|
||||
float TakenTotalMod = 1.0f;
|
||||
@@ -11181,7 +11231,7 @@ uint32 Unit::MeleeDamageBonusDone(Unit* victim, uint32 pdamage, WeaponAttackType
|
||||
|
||||
// Some spells don't benefit from pct done mods
|
||||
if (spellProto)
|
||||
if (!(spellProto->AttributesEx6 & SPELL_ATTR6_NO_DONE_PCT_DAMAGE_MODS) && !spellProto->IsRankOf(sSpellMgr->GetSpellInfo(12162)))
|
||||
if (!(spellProto->AttributesEx6 & SPELL_ATTR6_NO_DONE_PCT_DAMAGE_MODS))
|
||||
{
|
||||
AuraEffectList const& mModDamagePercentDone = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE);
|
||||
for (AuraEffectList::const_iterator i = mModDamagePercentDone.begin(); i != mModDamagePercentDone.end(); ++i)
|
||||
|
||||
@@ -1972,13 +1972,15 @@ class Unit : public WorldObject
|
||||
Unit* GetMagicHitRedirectTarget(Unit* victim, SpellInfo const* spellInfo);
|
||||
Unit* GetMeleeHitRedirectTarget(Unit* victim, SpellInfo const* spellInfo = NULL);
|
||||
|
||||
int32 SpellBaseDamageBonusDone(SpellSchoolMask schoolMask) const;
|
||||
int32 SpellBaseDamageBonusTaken(SpellSchoolMask schoolMask) const;
|
||||
int32 SpellBaseDamageBonusDone(SpellSchoolMask schoolMask) const;
|
||||
int32 SpellBaseDamageBonusTaken(SpellSchoolMask schoolMask) const;
|
||||
uint32 SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uint32 pdamage, DamageEffectType damagetype, uint32 stack = 1) const;
|
||||
float SpellDamagePctDone(Unit* victim, SpellInfo const* spellProto, DamageEffectType damagetype) const;
|
||||
uint32 SpellDamageBonusTaken(Unit* caster, SpellInfo const* spellProto, uint32 pdamage, DamageEffectType damagetype, uint32 stack = 1) const;
|
||||
int32 SpellBaseHealingBonusDone(SpellSchoolMask schoolMask) const;
|
||||
int32 SpellBaseHealingBonusTaken(SpellSchoolMask schoolMask) const;
|
||||
int32 SpellBaseHealingBonusDone(SpellSchoolMask schoolMask) const;
|
||||
int32 SpellBaseHealingBonusTaken(SpellSchoolMask schoolMask) const;
|
||||
uint32 SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, uint32 healamount, DamageEffectType damagetype, uint32 stack = 1) const;
|
||||
float SpellHealingPctDone(Unit* victim, SpellInfo const* spellProto) const;
|
||||
uint32 SpellHealingBonusTaken(Unit* caster, SpellInfo const* spellProto, uint32 healamount, DamageEffectType damagetype, uint32 stack = 1) const;
|
||||
|
||||
uint32 MeleeDamageBonusDone(Unit* pVictim, uint32 damage, WeaponAttackType attType, SpellInfo const* spellProto = NULL);
|
||||
@@ -1986,7 +1988,8 @@ class Unit : public WorldObject
|
||||
|
||||
bool isSpellBlocked(Unit* victim, SpellInfo const* spellProto, WeaponAttackType attackType = BASE_ATTACK);
|
||||
bool isBlockCritical();
|
||||
bool isSpellCrit(Unit* victim, SpellInfo const* spellProto, SpellSchoolMask schoolMask, WeaponAttackType attackType = BASE_ATTACK) const;
|
||||
bool IsSpellCrit(Unit* victim, SpellInfo const* spellProto, SpellSchoolMask schoolMask, WeaponAttackType attackType = BASE_ATTACK) const;
|
||||
float GetUnitSpellCriticalChance(Unit* victim, SpellInfo const* spellProto, SpellSchoolMask schoolMask, WeaponAttackType attackType = BASE_ATTACK) const;
|
||||
uint32 SpellCriticalDamageBonus(SpellInfo const* spellProto, uint32 damage, Unit* victim);
|
||||
uint32 SpellCriticalHealingBonus(SpellInfo const* spellProto, uint32 damage, Unit* victim);
|
||||
|
||||
|
||||
@@ -380,7 +380,7 @@ AuraEffect::AuraEffect(Aura* base, uint8 effIndex, int32 *baseAmount, Unit* cast
|
||||
m_base(base), m_spellInfo(base->GetSpellInfo()),
|
||||
m_baseAmount(baseAmount ? *baseAmount : m_spellInfo->Effects[effIndex].BasePoints),
|
||||
m_spellmod(NULL), m_periodicTimer(0), m_tickNumber(0), m_effIndex(effIndex),
|
||||
m_canBeRecalculated(true), m_isPeriodic(false)
|
||||
m_canBeRecalculated(true), m_isPeriodic(false), m_damage(0), m_critChance(0.0f), m_donePct(1.0f)
|
||||
{
|
||||
CalculatePeriodic(caster, true, false);
|
||||
|
||||
@@ -890,19 +890,15 @@ void AuraEffect::UpdatePeriodic(Unit* caster)
|
||||
GetBase()->CallScriptEffectUpdatePeriodicHandlers(this);
|
||||
}
|
||||
|
||||
bool AuraEffect::IsPeriodicTickCrit(Unit* target, Unit const* caster) const
|
||||
bool AuraEffect::CanPeriodicTickCrit(Unit* target, Unit const* caster) const
|
||||
{
|
||||
ASSERT(caster);
|
||||
Unit::AuraEffectList const& mPeriodicCritAuras= caster->GetAuraEffectsByType(SPELL_AURA_ABILITY_PERIODIC_CRIT);
|
||||
for (Unit::AuraEffectList::const_iterator itr = mPeriodicCritAuras.begin(); itr != mPeriodicCritAuras.end(); ++itr)
|
||||
{
|
||||
if ((*itr)->IsAffectedOnSpell(m_spellInfo) && caster->isSpellCrit(target, m_spellInfo, m_spellInfo->GetSchoolMask()))
|
||||
return true;
|
||||
}
|
||||
if (caster->HasAuraTypeWithAffectMask(SPELL_AURA_ABILITY_PERIODIC_CRIT, m_spellInfo))
|
||||
return true;
|
||||
|
||||
// Rupture - since 3.3.3 can crit
|
||||
if (m_spellInfo->SpellIconID == 500 && m_spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE)
|
||||
return caster->isSpellCrit(target, m_spellInfo, m_spellInfo->GetSchoolMask());
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -5780,15 +5776,19 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const
|
||||
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);
|
||||
// AOE spells are not affected by the new periodic system.
|
||||
bool isAreaAura = m_spellInfo->Effects[m_effIndex].IsAreaAuraEffect() || m_spellInfo->Effects[m_effIndex].IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA);
|
||||
// ignore negative values (can be result apply spellmods to aura damage
|
||||
uint32 damage = isAreaAura ? std::max(GetAmount(), 0) : m_damage;
|
||||
|
||||
// Script Hook For HandlePeriodicDamageAurasTick -- Allow scripts to change the Damage pre class mitigation calculations
|
||||
sScriptMgr->ModifyPeriodicDamageAurasTick(target, caster, damage);
|
||||
if (isAreaAura)
|
||||
sScriptMgr->ModifyPeriodicDamageAurasTick(target, caster, damage);
|
||||
|
||||
if (GetAuraType() == SPELL_AURA_PERIODIC_DAMAGE)
|
||||
{
|
||||
damage = caster->SpellDamageBonusDone(target, GetSpellInfo(), damage, DOT, GetBase()->GetStackAmount());
|
||||
if (isAreaAura)
|
||||
damage = caster->SpellDamageBonusDone(target, GetSpellInfo(), damage, DOT, GetBase()->GetStackAmount()) * caster->SpellDamagePctDone(target, m_spellInfo, DOT);
|
||||
damage = target->SpellDamageBonusTaken(caster, GetSpellInfo(), damage, DOT, GetBase()->GetStackAmount());
|
||||
|
||||
// Calculate armor mitigation
|
||||
@@ -5844,14 +5844,19 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const
|
||||
else
|
||||
damage = uint32(target->CountPctFromMaxHealth(damage));
|
||||
|
||||
if (m_spellInfo->Effects[m_effIndex].IsTargetingArea() || m_spellInfo->Effects[m_effIndex].IsAreaAuraEffect() || m_spellInfo->Effects[m_effIndex].IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA))
|
||||
{
|
||||
damage = int32(float(damage) * target->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE, m_spellInfo->SchoolMask));
|
||||
if (caster->GetTypeId() != TYPEID_PLAYER)
|
||||
damage = int32(float(damage) * target->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_CREATURE_AOE_DAMAGE_AVOIDANCE, m_spellInfo->SchoolMask));
|
||||
}
|
||||
if (!(m_spellInfo->AttributesEx4 & SPELL_ATTR4_FIXED_DAMAGE))
|
||||
if (m_spellInfo->Effects[m_effIndex].IsTargetingArea() || isAreaAura)
|
||||
{
|
||||
damage = int32(float(damage) * target->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE, m_spellInfo->SchoolMask));
|
||||
if (caster->GetTypeId() != TYPEID_PLAYER)
|
||||
damage = int32(float(damage) * target->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_CREATURE_AOE_DAMAGE_AVOIDANCE, m_spellInfo->SchoolMask));
|
||||
}
|
||||
|
||||
bool crit = false;
|
||||
|
||||
if (CanPeriodicTickCrit(target, caster))
|
||||
crit = roll_chance_f(isAreaAura ? caster->GetUnitSpellCriticalChance(target, m_spellInfo, m_spellInfo->GetSchoolMask()) : m_critChance);
|
||||
|
||||
bool crit = IsPeriodicTickCrit(target, caster);
|
||||
if (crit)
|
||||
damage = caster->SpellCriticalDamageBonus(m_spellInfo, damage, target);
|
||||
|
||||
@@ -5906,23 +5911,42 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c
|
||||
uint32 resist = 0;
|
||||
CleanDamage cleanDamage = CleanDamage(0, 0, BASE_ATTACK, MELEE_HIT_NORMAL);
|
||||
|
||||
uint32 damage = std::max(GetAmount(), 0);
|
||||
bool isAreaAura = m_spellInfo->Effects[m_effIndex].IsAreaAuraEffect() || m_spellInfo->Effects[m_effIndex].IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA);
|
||||
// ignore negative values (can be result apply spellmods to aura damage
|
||||
uint32 damage = isAreaAura ? std::max(GetAmount(), 0) : m_damage;
|
||||
|
||||
damage = caster->SpellDamageBonusDone(target, GetSpellInfo(), damage, DOT, GetBase()->GetStackAmount());
|
||||
if (isAreaAura)
|
||||
{
|
||||
// Script Hook For HandlePeriodicDamageAurasTick -- Allow scripts to change the Damage pre class mitigation calculations
|
||||
sScriptMgr->ModifyPeriodicDamageAurasTick(target, caster, damage);
|
||||
damage = caster->SpellDamageBonusDone(target, GetSpellInfo(), damage, DOT, GetBase()->GetStackAmount()) * caster->SpellDamagePctDone(target, m_spellInfo, DOT);
|
||||
}
|
||||
damage = target->SpellDamageBonusTaken(caster, GetSpellInfo(), damage, DOT, GetBase()->GetStackAmount());
|
||||
|
||||
bool crit = IsPeriodicTickCrit(target, caster);
|
||||
if (crit)
|
||||
damage = caster->SpellCriticalDamageBonus(m_spellInfo, damage, target);
|
||||
|
||||
// Calculate armor mitigation
|
||||
if (Unit::IsDamageReducedByArmor(GetSpellInfo()->GetSchoolMask(), GetSpellInfo(), m_effIndex))
|
||||
if (Unit::IsDamageReducedByArmor(GetSpellInfo()->GetSchoolMask(), GetSpellInfo(), GetEffIndex()))
|
||||
{
|
||||
uint32 damageReductedArmor = caster->CalcArmorReducedDamage(target, damage, GetSpellInfo());
|
||||
cleanDamage.mitigated_damage += damage - damageReductedArmor;
|
||||
damage = damageReductedArmor;
|
||||
}
|
||||
|
||||
if (!(m_spellInfo->AttributesEx4 & SPELL_ATTR4_FIXED_DAMAGE))
|
||||
if (m_spellInfo->Effects[m_effIndex].IsTargetingArea() || isAreaAura)
|
||||
{
|
||||
damage = int32(float(damage) * target->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE, m_spellInfo->SchoolMask));
|
||||
if (caster->GetTypeId() != TYPEID_PLAYER)
|
||||
damage = int32(float(damage) * target->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_CREATURE_AOE_DAMAGE_AVOIDANCE, m_spellInfo->SchoolMask));
|
||||
}
|
||||
|
||||
bool crit = false;
|
||||
|
||||
if (CanPeriodicTickCrit(target, caster))
|
||||
crit = roll_chance_f(isAreaAura ? caster->GetUnitSpellCriticalChance(target, m_spellInfo, m_spellInfo->GetSchoolMask()) : m_critChance);
|
||||
|
||||
if (crit)
|
||||
damage = caster->SpellCriticalDamageBonus(m_spellInfo, damage, target);
|
||||
|
||||
int32 dmg = damage;
|
||||
if (!(GetSpellInfo()->AttributesEx4 & SPELL_ATTR4_FIXED_DAMAGE))
|
||||
caster->ApplyResilience(target, NULL, &dmg, crit, CR_CRIT_TAKEN_SPELL);
|
||||
@@ -6007,8 +6031,9 @@ void AuraEffect::HandlePeriodicHealAurasTick(Unit* target, Unit* caster) const
|
||||
if (GetBase()->IsPermanent() && target->IsFullHealth())
|
||||
return;
|
||||
|
||||
bool isAreaAura = m_spellInfo->Effects[m_effIndex].IsAreaAuraEffect() || m_spellInfo->Effects[m_effIndex].IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA);
|
||||
// ignore negative values (can be result apply spellmods to aura damage
|
||||
int32 damage = std::max(m_amount, 0);
|
||||
int32 damage = isAreaAura ? std::max(GetAmount(), 0) : m_damage;
|
||||
|
||||
if (GetAuraType() == SPELL_AURA_OBS_MOD_HEALTH)
|
||||
{
|
||||
@@ -6056,12 +6081,16 @@ void AuraEffect::HandlePeriodicHealAurasTick(Unit* target, Unit* caster) const
|
||||
|
||||
damage += addition;
|
||||
}
|
||||
|
||||
damage = caster->SpellHealingBonusDone(target, GetSpellInfo(), damage, DOT, GetBase()->GetStackAmount());
|
||||
if (isAreaAura)
|
||||
damage = caster->SpellHealingBonusDone(target, GetSpellInfo(), damage, DOT, GetBase()->GetStackAmount()) * caster->SpellHealingPctDone(target, m_spellInfo);
|
||||
damage = target->SpellHealingBonusTaken(caster, GetSpellInfo(), damage, DOT, GetBase()->GetStackAmount());
|
||||
}
|
||||
|
||||
bool crit = IsPeriodicTickCrit(target, caster);
|
||||
bool crit = false;
|
||||
|
||||
if (CanPeriodicTickCrit(target, caster))
|
||||
crit = roll_chance_f(isAreaAura ? caster->GetUnitSpellCriticalChance(target, m_spellInfo, m_spellInfo->GetSchoolMask()) : m_critChance);
|
||||
|
||||
if (crit)
|
||||
damage = caster->SpellCriticalHealingBonus(m_spellInfo, damage, target);
|
||||
|
||||
|
||||
@@ -70,6 +70,13 @@ class AuraEffect
|
||||
void HandleEffect(Unit* target, uint8 mode, bool apply);
|
||||
void ApplySpellMod(Unit* target, bool apply);
|
||||
|
||||
void SetDamage(int32 val) { m_damage = val; }
|
||||
int32 GetDamage() const { return m_damage; }
|
||||
void SetCritChance(float val) { m_critChance = val; }
|
||||
float GetCritChance() const { return m_critChance; }
|
||||
void SetDonePct(float val) { m_donePct = val; }
|
||||
float GetDonePct() const { return m_donePct; }
|
||||
|
||||
void Update(uint32 diff, Unit* caster);
|
||||
void UpdatePeriodic(Unit* caster);
|
||||
|
||||
@@ -98,6 +105,9 @@ class AuraEffect
|
||||
int32 const m_baseAmount;
|
||||
|
||||
int32 m_amount;
|
||||
int32 m_damage;
|
||||
float m_critChance;
|
||||
float m_donePct;
|
||||
|
||||
SpellModifier* m_spellmod;
|
||||
|
||||
@@ -109,7 +119,7 @@ class AuraEffect
|
||||
bool m_canBeRecalculated;
|
||||
bool m_isPeriodic;
|
||||
private:
|
||||
bool IsPeriodicTickCrit(Unit* target, Unit const* caster) const;
|
||||
bool CanPeriodicTickCrit(Unit* target, Unit const* caster) const;
|
||||
|
||||
public:
|
||||
// aura effect apply/remove handlers
|
||||
|
||||
@@ -746,9 +746,20 @@ void Aura::SetDuration(int32 duration, bool withMods)
|
||||
SetNeedClientUpdateForTargets();
|
||||
}
|
||||
|
||||
void Aura::RefreshDuration()
|
||||
void Aura::RefreshDuration(bool withMods)
|
||||
{
|
||||
SetDuration(GetMaxDuration());
|
||||
if (withMods)
|
||||
{
|
||||
int32 duration = m_spellInfo->GetMaxDuration();
|
||||
// Calculate duration of periodics affected by haste.
|
||||
if (GetCaster()->HasAuraTypeWithAffectMask(SPELL_AURA_PERIODIC_HASTE, m_spellInfo) || m_spellInfo->AttributesEx5 & SPELL_ATTR5_HASTE_AFFECT_DURATION)
|
||||
duration = int32(duration * GetCaster()->GetFloatValue(UNIT_MOD_CAST_SPEED));
|
||||
|
||||
SetMaxDuration(duration);
|
||||
SetDuration(duration);
|
||||
}
|
||||
else
|
||||
SetDuration(GetMaxDuration());
|
||||
|
||||
if (m_spellInfo->ManaPerSecond || m_spellInfo->ManaPerSecondPerLevel)
|
||||
m_timeCla = 1 * IN_MILLISECONDS;
|
||||
@@ -825,7 +836,10 @@ void Aura::SetStackAmount(uint8 stackAmount)
|
||||
|
||||
for (std::list<AuraApplication*>::const_iterator apptItr = applications.begin(); apptItr != applications.end(); ++apptItr)
|
||||
if (!(*apptItr)->GetRemoveMode())
|
||||
{
|
||||
HandleAuraSpecificMods(*apptItr, caster, true, true);
|
||||
HandleAuraSpecificPeriodics(*apptItr, caster);
|
||||
}
|
||||
|
||||
SetNeedClientUpdateForTargets();
|
||||
}
|
||||
@@ -1631,26 +1645,62 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SPELLFAMILY_WARLOCK:
|
||||
// Drain Soul - If the target is at or below 25% health, Drain Soul causes four times the normal damage
|
||||
if (GetSpellInfo()->SpellFamilyFlags[0] & 0x00004000)
|
||||
}
|
||||
}
|
||||
|
||||
void Aura::HandleAuraSpecificPeriodics(AuraApplication const* aurApp, Unit* caster)
|
||||
{
|
||||
Unit* target = aurApp->GetTarget();
|
||||
|
||||
if (!caster || aurApp->GetRemoveMode())
|
||||
return;
|
||||
|
||||
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
|
||||
{
|
||||
if (!HasEffect(i))
|
||||
continue;
|
||||
|
||||
if (m_spellInfo->Effects[i].IsAreaAuraEffect() || m_spellInfo->Effects[i].IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA))
|
||||
continue;
|
||||
|
||||
switch (m_spellInfo->Effects[i].ApplyAuraName)
|
||||
{
|
||||
case SPELL_AURA_PERIODIC_DAMAGE:
|
||||
case SPELL_AURA_PERIODIC_DAMAGE_PERCENT:
|
||||
case SPELL_AURA_PERIODIC_LEECH:
|
||||
{
|
||||
if (!caster)
|
||||
break;
|
||||
if (apply)
|
||||
{
|
||||
if (target != caster && !target->HealthAbovePct(25))
|
||||
caster->CastSpell(caster, 100001, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (target != caster)
|
||||
caster->RemoveAurasDueToSpell(GetId());
|
||||
else
|
||||
caster->RemoveAurasDueToSpell(100001);
|
||||
}
|
||||
AuraEffect* aurEff = GetEffect(i);
|
||||
|
||||
// ignore non positive values (can be result apply spellmods to aura damage
|
||||
uint32 damage = std::max(aurEff->GetAmount(), 0);
|
||||
|
||||
// Script Hook For HandlePeriodicDamageAurasTick -- Allow scripts to change the Damage pre class mitigation calculations
|
||||
sScriptMgr->ModifyPeriodicDamageAurasTick(target, caster, damage);
|
||||
|
||||
aurEff->SetDonePct(caster->SpellDamagePctDone(target, m_spellInfo, DOT)); // Calculate done percentage first!
|
||||
aurEff->SetDamage(caster->SpellDamageBonusDone(target, m_spellInfo, damage, DOT, GetStackAmount()) * aurEff->GetDonePct());
|
||||
aurEff->SetCritChance(caster->GetUnitSpellCriticalChance(target, m_spellInfo, m_spellInfo->GetSchoolMask()));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SPELL_AURA_PERIODIC_HEAL:
|
||||
case SPELL_AURA_OBS_MOD_HEALTH:
|
||||
{
|
||||
AuraEffect* aurEff = GetEffect(i);
|
||||
|
||||
// ignore non positive values (can be result apply spellmods to aura damage
|
||||
uint32 damage = std::max(aurEff->GetAmount(), 0);
|
||||
|
||||
// Script Hook For HandlePeriodicDamageAurasTick -- Allow scripts to change the Damage pre class mitigation calculations
|
||||
sScriptMgr->ModifyPeriodicDamageAurasTick(target, caster, damage);
|
||||
|
||||
aurEff->SetDonePct(caster->SpellHealingPctDone(target, m_spellInfo)); // Calculate done percentage first!
|
||||
aurEff->SetDamage(caster->SpellHealingBonusDone(target, m_spellInfo, damage, DOT, GetStackAmount()) * aurEff->GetDonePct());
|
||||
aurEff->SetCritChance(caster->GetUnitSpellCriticalChance(target, m_spellInfo, m_spellInfo->GetSchoolMask()));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -129,7 +129,7 @@ class Aura
|
||||
int32 CalcMaxDuration(Unit* caster) const;
|
||||
int32 GetDuration() const { return m_duration; }
|
||||
void SetDuration(int32 duration, bool withMods = false);
|
||||
void RefreshDuration();
|
||||
void RefreshDuration(bool withMods = false);
|
||||
void RefreshTimers();
|
||||
bool IsExpired() const { return !GetDuration();}
|
||||
bool IsPermanent() const { return GetMaxDuration() == -1; }
|
||||
@@ -190,6 +190,7 @@ class Aura
|
||||
|
||||
void SetNeedClientUpdateForTargets() const;
|
||||
void HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, bool apply, bool onReapply);
|
||||
void HandleAuraSpecificPeriodics(AuraApplication const* aurApp, Unit* caster);
|
||||
bool CanBeAppliedOn(Unit* target);
|
||||
bool CheckAreaTarget(Unit* target);
|
||||
bool CanStackWith(Aura const* existingAura) const;
|
||||
|
||||
@@ -2340,7 +2340,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)
|
||||
// Do healing and triggers
|
||||
if (m_healing > 0)
|
||||
{
|
||||
bool crit = caster->isSpellCrit(unitTarget, m_spellInfo, m_spellSchoolMask);
|
||||
bool crit = caster->IsSpellCrit(unitTarget, m_spellInfo, m_spellSchoolMask);
|
||||
uint32 addhealth = m_healing;
|
||||
if (crit)
|
||||
{
|
||||
@@ -6729,7 +6729,7 @@ void Spell::DoAllEffectOnLaunchTarget(TargetInfo& targetInfo, float* multiplier)
|
||||
}
|
||||
}
|
||||
|
||||
targetInfo.crit = m_caster->isSpellCrit(unit, m_spellInfo, m_spellSchoolMask, m_attackType);
|
||||
targetInfo.crit = m_caster->IsSpellCrit(unit, m_spellInfo, m_spellSchoolMask, m_attackType);
|
||||
}
|
||||
|
||||
SpellCastResult Spell::CanOpenLock(uint32 effIndex, uint32 lockId, SkillType& skillId, int32& reqSkillValue, int32& skillValue)
|
||||
|
||||
@@ -4056,15 +4056,40 @@ void Spell::EffectScriptEffect(SpellEffIndex effIndex)
|
||||
{
|
||||
// Get diseases on target of spell
|
||||
if (m_targets.GetUnitTarget() && // Glyph of Disease - cast on unit target too to refresh aura
|
||||
(m_targets.GetUnitTarget() != unitTarget || m_caster->GetAura(63334)))
|
||||
(m_targets.GetUnitTarget() != unitTarget || m_caster->HasAura(63334)))
|
||||
{
|
||||
// And spread them on target
|
||||
// Blood Plague
|
||||
if (m_targets.GetUnitTarget()->GetAura(55078))
|
||||
if (m_targets.GetUnitTarget()->HasAura(55078))
|
||||
{
|
||||
AuraEffect* aurEffOld = m_targets.GetUnitTarget()->GetAura(55078)->GetEffect(0);
|
||||
float donePct = aurEffOld->GetDonePct();
|
||||
float critChance = aurEffOld->GetCritChance();
|
||||
|
||||
m_caster->CastSpell(unitTarget, 55078, true);
|
||||
|
||||
if (unitTarget->HasAura(55078))
|
||||
if (AuraEffect* aurEffNew = unitTarget->GetAura(55078)->GetEffect(0))
|
||||
{
|
||||
aurEffNew->SetCritChance(critChance); // Blood Plague can crit if caster has T9.
|
||||
aurEffNew->SetDonePct(donePct);
|
||||
aurEffNew->SetDamage(m_caster->SpellDamageBonusDone(unitTarget, aurEffNew->GetSpellInfo(), std::max(aurEffNew->GetAmount(), 0), DOT) * donePct);
|
||||
}
|
||||
}
|
||||
// Frost Fever
|
||||
if (m_targets.GetUnitTarget()->GetAura(55095))
|
||||
if (m_targets.GetUnitTarget()->HasAura(55095))
|
||||
{
|
||||
float donePct = m_targets.GetUnitTarget()->GetAura(55095)->GetEffect(0)->GetDonePct();
|
||||
|
||||
m_caster->CastSpell(unitTarget, 55095, true);
|
||||
|
||||
if (unitTarget->HasAura(55095))
|
||||
if (AuraEffect* aurEffNew = unitTarget->GetAura(55095)->GetEffect(0))
|
||||
{
|
||||
aurEffNew->SetDonePct(donePct);
|
||||
aurEffNew->SetDamage(m_caster->SpellDamageBonusDone(unitTarget, aurEffNew->GetSpellInfo(), std::max(aurEffNew->GetAmount(), 0), DOT) * donePct);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -202,16 +202,21 @@ class spell_hun_chimera_shot : public SpellScriptLoader
|
||||
flag96 familyFlag = aura->GetSpellInfo()->SpellFamilyFlags;
|
||||
if (!(familyFlag[1] & 0x00000080 || familyFlag[0] & 0x0000C000))
|
||||
continue;
|
||||
if (AuraEffect const* aurEff = aura->GetEffect(0))
|
||||
if (AuraEffect* aurEff = aura->GetEffect(0))
|
||||
{
|
||||
// Serpent Sting - Instantly deals 40% of the damage done by your Serpent Sting.
|
||||
if (familyFlag[0] & 0x4000)
|
||||
{
|
||||
int32 TickCount = aurEff->GetTotalTicks();
|
||||
spellId = SPELL_HUNTER_CHIMERA_SHOT_SERPENT;
|
||||
basePoint = caster->SpellDamageBonusDone(unitTarget, aura->GetSpellInfo(), aurEff->GetAmount(), DOT, aura->GetStackAmount());
|
||||
basePoint = aurEff->GetDamage();
|
||||
ApplyPct(basePoint, TickCount * 40);
|
||||
basePoint = unitTarget->SpellDamageBonusTaken(caster, aura->GetSpellInfo(), basePoint, DOT, aura->GetStackAmount());
|
||||
|
||||
// Recalculate bonus damage on roll.
|
||||
uint32 damage = std::max(aurEff->GetAmount(), 0);
|
||||
sScriptMgr->ModifyPeriodicDamageAurasTick(unitTarget, caster, damage);
|
||||
aurEff->SetDamage(caster->SpellDamageBonusDone(unitTarget, aurEff->GetSpellInfo(), damage, DOT) * aurEff->GetDonePct());
|
||||
}
|
||||
// Viper Sting - Instantly restores mana to you equal to 60% of the total amount drained by your Viper Sting.
|
||||
else if (familyFlag[1] & 0x00000080)
|
||||
|
||||
@@ -531,10 +531,17 @@ class spell_pri_pain_and_suffering_proc : public SpellScriptLoader
|
||||
|
||||
void HandleEffectScriptEffect(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
Unit* caster = GetCaster();
|
||||
// Refresh Shadow Word: Pain on target
|
||||
if (Unit* unitTarget = GetHitUnit())
|
||||
if (AuraEffect* aur = unitTarget->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_PRIEST, 0x8000, 0, 0, GetCaster()->GetGUID()))
|
||||
if (Unit* target = GetHitUnit())
|
||||
if (AuraEffect* aur = target->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_PRIEST, 0x8000, 0, 0, caster->GetGUID()))
|
||||
{
|
||||
uint32 damage = std::max(aur->GetAmount(), 0);
|
||||
sScriptMgr->ModifyPeriodicDamageAurasTick(target, caster, damage);
|
||||
aur->SetDamage(caster->SpellDamageBonusDone(target, aur->GetSpellInfo(), damage, DOT) * aur->GetDonePct());
|
||||
aur->CalculatePeriodic(caster, false, false);
|
||||
aur->GetBase()->RefreshDuration();
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
|
||||
@@ -405,10 +405,17 @@ class spell_warl_everlasting_affliction : public SpellScriptLoader
|
||||
|
||||
void HandleScriptEffect(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
if (Unit* unitTarget = GetHitUnit())
|
||||
Unit* caster = GetCaster();
|
||||
if (Unit* target = GetHitUnit())
|
||||
// Refresh corruption on target
|
||||
if (AuraEffect* aur = unitTarget->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_WARLOCK, 0x2, 0, 0, GetCaster()->GetGUID()))
|
||||
aur->GetBase()->RefreshDuration();
|
||||
if (AuraEffect* aur = target->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_WARLOCK, 0x2, 0, 0, caster->GetGUID()))
|
||||
{
|
||||
uint32 damage = std::max(aur->GetAmount(), 0);
|
||||
sScriptMgr->ModifyPeriodicDamageAurasTick(target, caster, damage);
|
||||
aur->SetDamage(caster->SpellDamageBonusDone(target, aur->GetSpellInfo(), damage, DOT) * aur->GetDonePct());
|
||||
aur->CalculatePeriodic(caster, false, false);
|
||||
aur->GetBase()->RefreshDuration(true);
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
|
||||
@@ -36,7 +36,7 @@ enum WarriorSpells
|
||||
SPELL_WARRIOR_DEEP_WOUNDS_RANK_1 = 12162,
|
||||
SPELL_WARRIOR_DEEP_WOUNDS_RANK_2 = 12850,
|
||||
SPELL_WARRIOR_DEEP_WOUNDS_RANK_3 = 12868,
|
||||
SPELL_WARRIOR_DEEP_WOUNDS_RANK_PERIODIC = 12721,
|
||||
SPELL_WARRIOR_DEEP_WOUNDS_PERIODIC = 12721,
|
||||
SPELL_WARRIOR_EXECUTE = 20647,
|
||||
SPELL_WARRIOR_GLYPH_OF_EXECUTION = 58367,
|
||||
SPELL_WARRIOR_GLYPH_OF_VIGILANCE = 63326,
|
||||
@@ -268,23 +268,18 @@ class spell_warr_deep_wounds : public SpellScriptLoader
|
||||
Unit* caster = GetCaster();
|
||||
if (Unit* target = GetHitUnit())
|
||||
{
|
||||
// apply percent damage mods
|
||||
damage = caster->SpellDamageBonusDone(target, GetSpellInfo(), damage, SPELL_DIRECT_DAMAGE);
|
||||
|
||||
ApplyPct(damage, 16 * GetSpellInfo()->GetRank());
|
||||
|
||||
damage = target->SpellDamageBonusTaken(caster, GetSpellInfo(), damage, SPELL_DIRECT_DAMAGE);
|
||||
|
||||
SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(SPELL_WARRIOR_DEEP_WOUNDS_RANK_PERIODIC);
|
||||
SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(SPELL_WARRIOR_DEEP_WOUNDS_PERIODIC);
|
||||
uint32 ticks = spellInfo->GetDuration() / spellInfo->Effects[EFFECT_0].Amplitude;
|
||||
|
||||
// Add remaining ticks to damage done
|
||||
if (AuraEffect const* aurEff = target->GetAuraEffect(SPELL_WARRIOR_DEEP_WOUNDS_RANK_PERIODIC, EFFECT_0, caster->GetGUID()))
|
||||
damage += aurEff->GetAmount() * (ticks - aurEff->GetTickNumber());
|
||||
if (AuraEffect const* aurEff = target->GetAuraEffect(SPELL_WARRIOR_DEEP_WOUNDS_PERIODIC, EFFECT_0, caster->GetGUID()))
|
||||
damage += aurEff->GetDamage() * (ticks - aurEff->GetTickNumber());
|
||||
|
||||
damage /= ticks;
|
||||
|
||||
caster->CastCustomSpell(target, SPELL_WARRIOR_DEEP_WOUNDS_RANK_PERIODIC, &damage, NULL, NULL, true);
|
||||
caster->CastCustomSpell(target, SPELL_WARRIOR_DEEP_WOUNDS_PERIODIC, &damage, NULL, NULL, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user