aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Entities
diff options
context:
space:
mode:
authorariel- <ariel-@users.noreply.github.com>2016-09-25 20:47:28 -0300
committerariel- <ariel-@users.noreply.github.com>2016-10-04 20:21:55 -0300
commite641d0c7d71bdb21e443bf52bf508b1581e07839 (patch)
tree764e1afadfa69a8c1d1a9c709498c017d12409b4 /src/server/game/Entities
parent23902ff266c28fa83f3bab5646b3e5b93ab55380 (diff)
Core/Spells: Implementation of QAston proc system
- Move checks from Unit::IsTriggeredAtSpellProcEvent (old system) to Aura::IsProcTriggeredOnEvent (new system) - Templatize SpellModOp param of Player::ApplySpellMod, also killed charge counter from SpellModifier and Player system for handling charges... no point in having 3 different systems doing the same thing - Automatically add default entries to spellProcMap, based on spellinfo (else auras won't proc without an entry) Based on old Unit::ProcDamageAndSpellFor - Old Unit::ProcDamageAndSpellFor renamed to Unit::ProcSkillsAndReactives and made private, will no longer handle auras. - Start making use of HealInfo::AbsorbHeal in unit calculations, add effective healing info to HealInfo struct - Changes in spell reflection system, emulates old behaviour, delaying aura drop - Removed old charge count hacks in SpellMgr::LoadSpellInfoCorrections - Removed bogus error log when procChance is 0: Some auras have initial 0 procChance but modified by SPELLMOD_CHANCE_OF_SUCCESS - Fixed TriggerAurasProcOnEvent logic that tried to trigger twice from actor. - Allow non damaging spells with DamageClass Melee or Ranged to proc character enchants. Ref issue #17034: * http://web.archive.org/web/20110309092008/http://elitistjerks.com/f47/t49865-paladin_retribution_pve/ * When an auto-attack lands (does not dodge/parry/miss) that can proc a seal the of the following things happen independently of each other (see 2 roll system). * 1) A "hidden strike" which uses melee combat mechanics occurs. If it lands it refreshes/stacks SoV DoT. Only white swings can trigger a refresh or stack. (This hidden strike mechanic can also proc things like berserking..) * 2) A weapon damage based proc will occur if you used a special (CS/DS/judge) or if you have a 5 stack (from auto attacks). This attack can not be avoided. * Holy Vengeance is the "hidden strike" it has an apply aura effect and damage class melee. - Fixed Blood Tap interaction with Death Runes (btw, don't know what was going on with those MiscValueB, spell 45529 doesn't have any MiscValueB in SPELL_EFFECT_ACTIVATE_RUNE) - Ported some AuraEffect checks from old Unit.cpp function. added new AuraScript hook to check procs of an specific effect - Allow only AuraEffects that passed the check to proc, this won't block whole aura from proccing (and lose charges) if at least one of the effects procs, though - Changes in spell mod system (for SPELLMOD_CASTING_TIME). fixes #17558. - Added an exception for SPELLMOD_CRITICAL_CHANCE too, fixes #15193
Diffstat (limited to 'src/server/game/Entities')
-rw-r--r--src/server/game/Entities/Player/Player.cpp177
-rw-r--r--src/server/game/Entities/Player/Player.h128
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp3960
-rw-r--r--src/server/game/Entities/Unit/Unit.h303
4 files changed, 529 insertions, 4039 deletions
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index cdd9da88d7b..a00bd9e4d47 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -7923,8 +7923,10 @@ void Player::UpdateEquipSpellsAtFormChange()
}
}
}
-void Player::CastItemCombatSpell(Unit* target, WeaponAttackType attType, uint32 procVictim, uint32 procEx)
+
+void Player::CastItemCombatSpell(DamageInfo const& damageInfo)
{
+ Unit* target = damageInfo.GetVictim();
if (!target || !target->IsAlive() || target == this)
return;
@@ -7932,7 +7934,9 @@ void Player::CastItemCombatSpell(Unit* target, WeaponAttackType attType, uint32
{
// If usable, try to cast item spell
if (Item* item = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
- if (!item->IsBroken() && CanUseAttackType(attType))
+ {
+ if (!item->IsBroken() && CanUseAttackType(damageInfo.GetAttackType()))
+ {
if (ItemTemplate const* proto = item->GetTemplate())
{
// Additional check for weapons
@@ -7940,30 +7944,42 @@ void Player::CastItemCombatSpell(Unit* target, WeaponAttackType attType, uint32
{
// offhand item cannot proc from main hand hit etc
EquipmentSlots slot;
- switch (attType)
+ switch (damageInfo.GetAttackType())
{
- case BASE_ATTACK: slot = EQUIPMENT_SLOT_MAINHAND; break;
- case OFF_ATTACK: slot = EQUIPMENT_SLOT_OFFHAND; break;
- case RANGED_ATTACK: slot = EQUIPMENT_SLOT_RANGED; break;
- default: slot = EQUIPMENT_SLOT_END; break;
+ case BASE_ATTACK:
+ slot = EQUIPMENT_SLOT_MAINHAND;
+ break;
+ case OFF_ATTACK:
+ slot = EQUIPMENT_SLOT_OFFHAND;
+ break;
+ case RANGED_ATTACK:
+ slot = EQUIPMENT_SLOT_RANGED;
+ break;
+ default:
+ slot = EQUIPMENT_SLOT_END;
+ break;
}
if (slot != i)
continue;
// Check if item is useable (forms or disarm)
- if (attType == BASE_ATTACK)
+ if (damageInfo.GetAttackType() == BASE_ATTACK)
if (!IsUseEquipedWeapon(true) && !IsInFeralForm())
continue;
}
- CastItemCombatSpell(target, attType, procVictim, procEx, item, proto);
+
+ CastItemCombatSpell(damageInfo, item, proto);
}
+ }
+ }
}
}
-void Player::CastItemCombatSpell(Unit* target, WeaponAttackType attType, uint32 procVictim, uint32 procEx, Item* item, ItemTemplate const* proto)
+void Player::CastItemCombatSpell(DamageInfo const& damageInfo, Item* item, ItemTemplate const* proto)
{
// Can do effect if any damage done to target
- if (procVictim & PROC_FLAG_TAKEN_DAMAGE)
- //if (damageInfo->procVictim & PROC_FLAG_TAKEN_ANY_DAMAGE)
+ // for done procs allow normal + critical + absorbs by default
+ bool canTrigger = (damageInfo.GetHitMask() & (PROC_HIT_NORMAL | PROC_HIT_CRITICAL | PROC_HIT_ABSORB)) != 0;
+ if (canTrigger)
{
for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i)
{
@@ -7993,14 +8009,14 @@ void Player::CastItemCombatSpell(Unit* target, WeaponAttackType attType, uint32
if (spellData.SpellPPMRate)
{
- uint32 WeaponSpeed = GetAttackTime(attType);
+ uint32 WeaponSpeed = GetAttackTime(damageInfo.GetAttackType());
chance = GetPPMProcChance(WeaponSpeed, spellData.SpellPPMRate, spellInfo);
}
else if (chance > 100.0f)
chance = GetWeaponProcChance();
if (roll_chance_f(chance))
- CastSpell(target, spellInfo->Id, true, item);
+ CastSpell(damageInfo.GetVictim(), spellInfo->Id, true, item);
}
}
@@ -8018,18 +8034,17 @@ void Player::CastItemCombatSpell(Unit* target, WeaponAttackType attType, uint32
continue;
SpellEnchantProcEntry const* entry = sSpellMgr->GetSpellEnchantProcEvent(enchant_id);
-
if (entry && entry->procEx)
{
// Check hit/crit/dodge/parry requirement
- if ((entry->procEx & procEx) == 0)
+ if ((entry->procEx & damageInfo.GetHitMask()) == 0)
continue;
}
else
{
// Can do effect if any damage done to target
- if (!(procVictim & PROC_FLAG_TAKEN_DAMAGE))
- //if (!(damageInfo->procVictim & PROC_FLAG_TAKEN_ANY_DAMAGE))
+ // for done procs allow normal + critical + absorbs by default
+ if (!canTrigger)
continue;
}
@@ -8042,7 +8057,6 @@ void Player::CastItemCombatSpell(Unit* target, WeaponAttackType attType, uint32
}
float chance = pEnchant->amount[s] != 0 ? float(pEnchant->amount[s]) : GetWeaponProcChance();
-
if (entry)
{
if (entry->PPMChance)
@@ -8052,7 +8066,7 @@ void Player::CastItemCombatSpell(Unit* target, WeaponAttackType attType, uint32
}
// Apply spell mods
- ApplySpellMod(pEnchant->spellid[s], SPELLMOD_CHANCE_OF_SUCCESS, chance);
+ ApplySpellMod<SPELLMOD_CHANCE_OF_SUCCESS>(pEnchant->spellid[s], chance);
// Shiv has 100% chance to apply the poison
if (FindCurrentSpellBySpellId(5938) && e_slot == TEMP_ENCHANTMENT_SLOT)
@@ -8063,7 +8077,7 @@ void Player::CastItemCombatSpell(Unit* target, WeaponAttackType attType, uint32
if (spellInfo->IsPositive())
CastSpell(this, spellInfo, true, item);
else
- CastSpell(target, spellInfo, true, item);
+ CastSpell(damageInfo.GetVictim(), spellInfo, true, item);
}
}
}
@@ -20819,13 +20833,13 @@ void Player::SendRemoveControlBar() const
GetSession()->SendPacket(&data);
}
-bool Player::IsAffectedBySpellmod(SpellInfo const* spellInfo, SpellModifier* mod, Spell* spell) const
+bool Player::IsAffectedBySpellmod(SpellInfo const* spellInfo, SpellModifier* mod, Spell* spell)
{
if (!mod || !spellInfo)
return false;
- // Mod out of charges
- if (spell && mod->charges == -1 && spell->m_appliedMods.find(mod->ownerAura) == spell->m_appliedMods.end())
+ // First time this aura applies a mod to us and is out of charges
+ if (spell && mod->ownerAura->IsUsingCharges() && !mod->ownerAura->GetCharges() && !spell->m_appliedMods.count(mod->ownerAura))
return false;
// +duration to infinite duration spells making them limited
@@ -20842,22 +20856,22 @@ void Player::AddSpellMod(SpellModifier* mod, bool apply)
int i = 0;
flag96 _mask = 0;
- for (int eff = 0; eff < 96; ++eff)
+ for (int32 eff = 0; eff < 96; ++eff)
{
- if (eff != 0 && eff%32 == 0)
+ if (eff != 0 && eff % 32 == 0)
_mask[i++] = 0;
- _mask[i] = uint32(1) << (eff-(32*i));
- if (mod->mask & _mask)
+ _mask[i] = uint32(1) << (eff - (32 * i));
+ if ((mod->mask & _mask))
{
int32 val = 0;
- for (SpellModList::iterator itr = m_spellMods[mod->op].begin(); itr != m_spellMods[mod->op].end(); ++itr)
+ for (SpellModifier* spellMod : m_spellMods[mod->op])
{
- if ((*itr)->type == mod->type && (*itr)->mask & _mask)
- val += (*itr)->value;
+ if (spellMod->type == mod->type && (spellMod->mask & _mask))
+ val += spellMod->value;
}
val += apply ? mod->value : -(mod->value);
- WorldPacket data(Opcode, (1+1+4));
+ WorldPacket data(Opcode, (1 + 1 + 4));
data << uint8(eff);
data << uint8(mod->op);
data << int32(val);
@@ -20866,36 +20880,30 @@ void Player::AddSpellMod(SpellModifier* mod, bool apply)
}
if (apply)
- m_spellMods[mod->op].push_back(mod);
+ m_spellMods[mod->op].insert(mod);
else
- {
- m_spellMods[mod->op].remove(mod);
- // mods bound to aura will be removed in AuraEffect::~AuraEffect
- if (!mod->ownerAura)
- delete mod;
- }
+ m_spellMods[mod->op].erase(mod);
}
// Restore spellmods in case of failed cast
-void Player::RestoreSpellMods(Spell* spell, uint32 ownerAuraId, Aura* aura)
+void Player::RestoreSpellMods(Spell* spell, uint32 ownerAuraId /*= 0*/, Aura* aura /*= nullptr*/)
{
if (!spell || spell->m_appliedMods.empty())
return;
std::list<Aura*> aurasQueue;
-
- for (uint8 i=0; i<MAX_SPELLMOD; ++i)
+ for (uint8 i = 0; i < MAX_SPELLMOD; ++i)
{
- for (SpellModList::iterator itr = m_spellMods[i].begin(); itr != m_spellMods[i].end(); ++itr)
+ for (auto itr = m_spellMods[i].begin(); itr != m_spellMods[i].end(); ++itr)
{
SpellModifier* mod = *itr;
- // Spellmods without aura set cannot be charged
- if (!mod->ownerAura || !mod->ownerAura->IsUsingCharges())
+ // Spellmods without charged aura cannot be charged
+ if (!mod->ownerAura->IsUsingCharges())
continue;
// Restore only specific owner aura mods
- if (ownerAuraId && (ownerAuraId != mod->ownerAura->GetSpellInfo()->Id))
+ if (ownerAuraId && mod->spellId != ownerAuraId)
continue;
if (aura && mod->ownerAura != aura)
@@ -20916,84 +20924,33 @@ void Player::RestoreSpellMods(Spell* spell, uint32 ownerAuraId, Aura* aura)
// only see the first of its modifier restored)
aurasQueue.push_back(mod->ownerAura);
- // add mod charges back to mod
- if (mod->charges == -1)
- mod->charges = 1;
- else
- mod->charges++;
-
- // Do not set more spellmods than available
- if (mod->ownerAura->GetCharges() < mod->charges)
- mod->charges = mod->ownerAura->GetCharges();
-
- // Skip this check for now - aura charges may change due to various reason
- /// @todo track these changes correctly
- //ASSERT (mod->ownerAura->GetCharges() <= mod->charges);
+ // add charges back to aura
+ mod->ownerAura->ModCharges(1);
}
}
- for (std::list<Aura*>::iterator itr = aurasQueue.begin(); itr != aurasQueue.end(); ++itr)
- {
- Spell::UsedSpellMods::iterator iterMod = spell->m_appliedMods.find(*itr);
- if (iterMod != spell->m_appliedMods.end())
- spell->m_appliedMods.erase(iterMod);
- }
+ for (Aura* aura : aurasQueue)
+ spell->m_appliedMods.erase(aura);
}
-void Player::RestoreAllSpellMods(uint32 ownerAuraId, Aura* aura)
+void Player::RestoreAllSpellMods(uint32 ownerAuraId /*= 0*/, Aura* aura /*= nullptr*/)
{
for (uint32 i = 0; i < CURRENT_MAX_SPELL; ++i)
- if (m_currentSpells[i])
- RestoreSpellMods(m_currentSpells[i], ownerAuraId, aura);
+ if (Spell* spell = m_currentSpells[i])
+ RestoreSpellMods(spell, ownerAuraId, aura);
}
-void Player::RemoveSpellMods(Spell* spell)
+void Player::ApplyModToSpell(SpellModifier* mod, Spell* spell)
{
if (!spell)
return;
- if (spell->m_appliedMods.empty())
+ // don't do anything with no charges
+ if (mod->ownerAura->IsUsingCharges() && !mod->ownerAura->GetCharges())
return;
- for (uint8 i=0; i<MAX_SPELLMOD; ++i)
- {
- for (SpellModList::const_iterator itr = m_spellMods[i].begin(); itr != m_spellMods[i].end();)
- {
- SpellModifier* mod = *itr;
- ++itr;
-
- // spellmods without aura set cannot be charged
- if (!mod->ownerAura || !mod->ownerAura->IsUsingCharges())
- continue;
-
- // check if mod affected this spell
- Spell::UsedSpellMods::iterator iterMod = spell->m_appliedMods.find(mod->ownerAura);
- if (iterMod == spell->m_appliedMods.end())
- continue;
-
- // remove from list
- spell->m_appliedMods.erase(iterMod);
-
- if (mod->ownerAura->DropCharge(AURA_REMOVE_BY_EXPIRE))
- itr = m_spellMods[i].begin();
- }
- }
-}
-
-void Player::DropModCharge(SpellModifier* mod, Spell* spell)
-{
- // don't handle spells with proc_event entry defined
- // this is a temporary workaround, because all spellmods should be handled like that
- if (sSpellMgr->GetSpellProcEvent(mod->spellId))
- return;
-
- if (spell && mod->ownerAura && mod->charges > 0)
- {
- if (--mod->charges == 0)
- mod->charges = -1;
-
- spell->m_appliedMods.insert(mod->ownerAura);
- }
+ // register inside spell, proc system uses this to drop charges
+ spell->m_appliedMods.insert(mod->ownerAura);
}
void Player::SetSpellModTakingSpell(Spell* spell, bool apply)
@@ -21004,7 +20961,7 @@ void Player::SetSpellModTakingSpell(Spell* spell, bool apply)
if (apply && spell->getState() == SPELL_STATE_FINISHED)
return;
- m_spellModTakingSpell = apply ? spell : NULL;
+ m_spellModTakingSpell = apply ? spell : nullptr;
}
// send Proficiency
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index 269cbb4a9ef..2f580908e2b 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -66,10 +66,10 @@ typedef std::deque<Mail*> PlayerMails;
#define PLAYER_EXPLORED_ZONES_SIZE 128
// Note: SPELLMOD_* values is aura types in fact
-enum SpellModType
+enum SpellModType : uint8
{
- SPELLMOD_FLAT = 107, // SPELL_AURA_ADD_FLAT_MODIFIER
- SPELLMOD_PCT = 108 // SPELL_AURA_ADD_PCT_MODIFIER
+ SPELLMOD_FLAT = SPELL_AURA_ADD_FLAT_MODIFIER,
+ SPELLMOD_PCT = SPELL_AURA_ADD_PCT_MODIFIER
};
// 2^n values, Player::m_isunderwater is a bitmask. These are Trinity internal values, they are never send to any client
@@ -118,10 +118,11 @@ struct PlayerTalent
// Spell modifier (used for modify other spells)
struct SpellModifier
{
- SpellModifier(Aura* _ownerAura = nullptr) : op(SPELLMOD_DAMAGE), type(SPELLMOD_FLAT), charges(0), value(0), mask(), spellId(0), ownerAura(_ownerAura) { }
- SpellModOp op : 8;
- SpellModType type : 8;
- int16 charges : 16;
+ SpellModifier(Aura* _ownerAura) : op(SPELLMOD_DAMAGE), type(SPELLMOD_FLAT), value(0), mask(), spellId(0), ownerAura(_ownerAura) { }
+
+ SpellModOp op;
+ SpellModType type;
+
int32 value;
flag96 mask;
uint32 spellId;
@@ -130,7 +131,7 @@ struct SpellModifier
typedef std::unordered_map<uint32, PlayerTalent*> PlayerTalentMap;
typedef std::unordered_map<uint32, PlayerSpell*> PlayerSpellMap;
-typedef std::list<SpellModifier*> SpellModList;
+typedef std::unordered_set<SpellModifier*> SpellModContainer;
typedef std::unordered_map<uint32 /*instanceId*/, time_t/*releaseTime*/> InstanceTimeMap;
@@ -1602,13 +1603,12 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
PlayerSpellMap & GetSpellMap() { return m_spells; }
void AddSpellMod(SpellModifier* mod, bool apply);
- bool IsAffectedBySpellmod(SpellInfo const* spellInfo, SpellModifier* mod, Spell* spell = nullptr) const;
- template <class T>
- void ApplySpellMod(uint32 spellId, SpellModOp op, T& basevalue, Spell* spell = nullptr);
- void RemoveSpellMods(Spell* spell);
+ static bool IsAffectedBySpellmod(SpellInfo const* spellInfo, SpellModifier* mod, Spell* spell = nullptr);
+ template <SpellModOp op, class T>
+ void ApplySpellMod(uint32 spellId, T& basevalue, Spell* spell = nullptr) const;
void RestoreSpellMods(Spell* spell, uint32 ownerAuraId = 0, Aura* aura = nullptr);
void RestoreAllSpellMods(uint32 ownerAuraId = 0, Aura* aura = nullptr);
- void DropModCharge(SpellModifier* mod, Spell* spell);
+ static void ApplyModToSpell(SpellModifier* mod, Spell* spell);
void SetSpellModTakingSpell(Spell* spell, bool apply);
void RemoveArenaSpellCooldowns(bool removeActivePetCooldowns = false);
@@ -1973,9 +1973,9 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
void ApplyItemEquipSpell(Item* item, bool apply, bool form_change = false);
void ApplyEquipSpell(SpellInfo const* spellInfo, Item* item, bool apply, bool form_change = false);
void UpdateEquipSpellsAtFormChange();
- void CastItemCombatSpell(Unit* target, WeaponAttackType attType, uint32 procVictim, uint32 procEx);
+ void CastItemCombatSpell(DamageInfo const& damageInfo);
+ void CastItemCombatSpell(DamageInfo const& damageInfo, Item* item, ItemTemplate const* proto);
void CastItemUseSpell(Item* item, SpellCastTargets const& targets, uint8 cast_count, uint32 glyphIndex);
- void CastItemCombatSpell(Unit* target, WeaponAttackType attType, uint32 procVictim, uint32 procEx, Item* item, ItemTemplate const* proto);
void SendEquipmentSetList();
void SetEquipmentSet(uint32 index, EquipmentSet eqset);
@@ -2441,7 +2441,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
uint32 m_baseHealthRegen;
int32 m_spellPenetrationItemMod;
- SpellModList m_spellMods[MAX_SPELLMOD];
+ SpellModContainer m_spellMods[MAX_SPELLMOD];
EnchantDurationList m_enchantDuration;
ItemDurationList m_itemDuration;
@@ -2614,8 +2614,8 @@ TC_GAME_API void AddItemsSetItem(Player* player, Item* item);
TC_GAME_API void RemoveItemsSetItem(Player* player, ItemTemplate const* proto);
// "the bodies of template functions must be made available in a header file"
-template <class T>
-void Player::ApplySpellMod(uint32 spellId, SpellModOp op, T& basevalue, Spell* spell /*= nullptr*/)
+template <SpellModOp op, class T>
+void Player::ApplySpellMod(uint32 spellId, T& basevalue, Spell* spell /*= nullptr*/) const
{
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
if (!spellInfo)
@@ -2628,33 +2628,89 @@ void Player::ApplySpellMod(uint32 spellId, SpellModOp op, T& basevalue, Spell* s
if (m_spellModTakingSpell)
spell = m_spellModTakingSpell;
- for (SpellModList::iterator itr = m_spellMods[op].begin(); itr != m_spellMods[op].end(); ++itr)
+ switch (op)
{
- SpellModifier* mod = *itr;
+ // special case, if a mod makes spell instant, only consume that mod
+ case SPELLMOD_CASTING_TIME:
+ {
+ SpellModifier* modInstantSpell = nullptr;
+ for (SpellModifier* mod : m_spellMods[SPELLMOD_CASTING_TIME])
+ {
+ if (!IsAffectedBySpellmod(spellInfo, mod, spell))
+ continue;
+
+ if (mod->type == SPELLMOD_PCT && basevalue < T(10000) && mod->value <= -100)
+ {
+ modInstantSpell = mod;
+ break;
+ }
+ }
- // Charges can be set only for mods with auras
- if (!mod->ownerAura)
- ASSERT(mod->charges == 0);
+ if (modInstantSpell)
+ {
+ Player::ApplyModToSpell(modInstantSpell, spell);
+ basevalue = T(0);
+ return;
+ }
+ break;
+ }
+ // special case if two mods apply 100% critical chance, only consume one
+ case SPELLMOD_CRITICAL_CHANCE:
+ {
+ SpellModifier* modCritical = nullptr;
+ for (SpellModifier* mod : m_spellMods[SPELLMOD_CRITICAL_CHANCE])
+ {
+ if (!IsAffectedBySpellmod(spellInfo, mod, spell))
+ continue;
+
+ if (mod->type == SPELLMOD_FLAT && mod->value >= 100)
+ {
+ modCritical = mod;
+ break;
+ }
+ }
+ if (modCritical)
+ {
+ Player::ApplyModToSpell(modCritical, spell);
+ basevalue = T(100);
+ return;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+
+ for (SpellModifier* mod : m_spellMods[op])
+ {
if (!IsAffectedBySpellmod(spellInfo, mod, spell))
continue;
- if (mod->type == SPELLMOD_FLAT)
- totalflat += mod->value;
- else if (mod->type == SPELLMOD_PCT)
+ switch (mod->type)
{
- // skip percent mods for null basevalue (most important for spell mods with charges)
- if (basevalue == T(0))
- continue;
-
- // special case (skip > 10sec spell casts for instant cast setting)
- if (mod->op == SPELLMOD_CASTING_TIME && basevalue >= T(10000) && mod->value <= -100)
- continue;
-
- totalmul += CalculatePct(1.0f, mod->value);
+ case SPELLMOD_FLAT:
+ totalflat += mod->value;
+ break;
+ case SPELLMOD_PCT:
+ {
+ // skip percent mods for null basevalue (most important for spell mods with charges)
+ if (basevalue == T(0))
+ continue;
+
+ // special case (skip > 10sec spell casts for instant cast setting)
+ if (op == SPELLMOD_CASTING_TIME)
+ {
+ if (mod->value <= -100 && basevalue >= T(10000))
+ continue;
+ }
+
+ totalmul += CalculatePct(1.0f, mod->value);
+ break;
+ }
}
- DropModCharge(mod, spell);
+ Player::ApplyModToSpell(mod, spell);
}
basevalue = T(float(basevalue + totalflat) * totalmul);
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index 2dcac43b828..ea16e542ff7 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -92,17 +92,6 @@ float playerBaseMoveSpeed[MAX_MOVE_TYPE] =
3.14f // MOVE_PITCH_RATE
};
-// Used for prepare can/can`t triggr aura
-static bool InitTriggerAuraData();
-// Define can trigger auras
-static bool isTriggerAura[TOTAL_AURAS];
-// Define can't trigger auras (need for disable second trigger)
-static bool isNonTriggerAura[TOTAL_AURAS];
-// Triggered always, even from triggered spells
-static bool isAlwaysTriggeredAura[TOTAL_AURAS];
-// Prepare lists
-static bool procPrepared = InitTriggerAuraData();
-
DamageInfo::DamageInfo(Unit* attacker, Unit* victim, uint32 damage, SpellInfo const* spellInfo, SpellSchoolMask schoolMask, DamageEffectType damageType, WeaponAttackType attackType)
: m_attacker(attacker), m_victim(victim), m_damage(damage), m_spellInfo(spellInfo), m_schoolMask(schoolMask), m_damageType(damageType), m_attackType(attackType),
m_absorb(0), m_resist(0), m_block(0), m_hitMask(0)
@@ -146,15 +135,23 @@ DamageInfo::DamageInfo(CalcDamageInfo const& dmgInfo)
case MELEE_HIT_EVADE:
m_hitMask |= PROC_HIT_EVADE;
break;
+ case MELEE_HIT_CRUSHING:
+ case MELEE_HIT_GLANCING:
+ case MELEE_HIT_NORMAL:
+ m_hitMask |= PROC_HIT_NORMAL;
+ break;
+ case MELEE_HIT_CRIT:
+ m_hitMask |= PROC_HIT_CRITICAL;
+ break;
default:
break;
}
}
-DamageInfo::DamageInfo(SpellNonMeleeDamage const& spellNonMeleeDamage, DamageEffectType damageType, WeaponAttackType attackType)
+DamageInfo::DamageInfo(SpellNonMeleeDamage const& spellNonMeleeDamage, DamageEffectType damageType, WeaponAttackType attackType, uint32 hitMask)
: m_attacker(spellNonMeleeDamage.attacker), m_victim(spellNonMeleeDamage.target), m_damage(spellNonMeleeDamage.damage),
m_spellInfo(sSpellMgr->GetSpellInfo(spellNonMeleeDamage.SpellID)), m_schoolMask(SpellSchoolMask(spellNonMeleeDamage.schoolMask)), m_damageType(damageType),
- m_attackType(attackType), m_absorb(spellNonMeleeDamage.absorb), m_resist(spellNonMeleeDamage.resist), m_block(spellNonMeleeDamage.blocked), m_hitMask(0)
+ m_attackType(attackType), m_absorb(spellNonMeleeDamage.absorb), m_resist(spellNonMeleeDamage.resist), m_block(spellNonMeleeDamage.blocked), m_hitMask(hitMask)
{
if (spellNonMeleeDamage.blocked)
m_hitMask |= PROC_HIT_BLOCK;
@@ -201,7 +198,7 @@ uint32 DamageInfo::GetHitMask() const
}
HealInfo::HealInfo(Unit* healer, Unit* target, uint32 heal, SpellInfo const* spellInfo, SpellSchoolMask schoolMask)
- : _healer(healer), _target(target), _heal(heal), _absorb(0), _spellInfo(spellInfo), _schoolMask(schoolMask), _hitMask(0)
+ : _healer(healer), _target(target), _heal(heal), _effectiveHeal(0), _absorb(0), _spellInfo(spellInfo), _schoolMask(schoolMask), _hitMask(0)
{
}
@@ -210,6 +207,8 @@ void HealInfo::AbsorbHeal(uint32 amount)
amount = std::min(amount, GetHeal());
_absorb += amount;
_heal -= amount;
+ amount = std::min(amount, GetEffectiveHeal());
+ _effectiveHeal -= amount;
_hitMask |= PROC_HIT_ABSORB;
}
@@ -1118,7 +1117,7 @@ void Unit::CalculateSpellDamageTaken(SpellNonMeleeDamage* damageInfo, int32 dama
uint32 crit_bonus = damage;
// Apply crit_damage bonus for melee spells
if (Player* modOwner = GetSpellModOwner())
- modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_CRIT_DAMAGE_BONUS, crit_bonus);
+ modOwner->ApplySpellMod<SPELLMOD_CRIT_DAMAGE_BONUS>(spellInfo->Id, crit_bonus);
damage += crit_bonus;
// Apply SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE or SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE
@@ -1232,7 +1231,6 @@ void Unit::CalculateMeleeDamage(Unit* victim, uint32 damage, CalcDamageInfo* dam
damageInfo->HitInfo = 0;
damageInfo->procAttacker = PROC_FLAG_NONE;
damageInfo->procVictim = PROC_FLAG_NONE;
- damageInfo->procEx = PROC_EX_NONE;
damageInfo->hitOutCome = MELEE_HIT_EVADE;
if (!victim)
@@ -1263,7 +1261,6 @@ void Unit::CalculateMeleeDamage(Unit* victim, uint32 damage, CalcDamageInfo* dam
damageInfo->HitInfo |= HITINFO_NORMALSWING;
damageInfo->TargetState = VICTIMSTATE_IS_IMMUNE;
- damageInfo->procEx |= PROC_EX_IMMUNE;
damageInfo->damage = 0;
damageInfo->cleanDamage = 0;
return;
@@ -1293,27 +1290,23 @@ void Unit::CalculateMeleeDamage(Unit* victim, uint32 damage, CalcDamageInfo* dam
case MELEE_HIT_EVADE:
damageInfo->HitInfo |= HITINFO_MISS | HITINFO_SWINGNOHITSOUND;
damageInfo->TargetState = VICTIMSTATE_EVADES;
- damageInfo->procEx |= PROC_EX_EVADE;
damageInfo->damage = 0;
damageInfo->cleanDamage = 0;
return;
case MELEE_HIT_MISS:
damageInfo->HitInfo |= HITINFO_MISS;
damageInfo->TargetState = VICTIMSTATE_INTACT;
- damageInfo->procEx |= PROC_EX_MISS;
damageInfo->damage = 0;
damageInfo->cleanDamage = 0;
break;
case MELEE_HIT_NORMAL:
damageInfo->TargetState = VICTIMSTATE_HIT;
- damageInfo->procEx |= PROC_EX_NORMAL_HIT;
break;
case MELEE_HIT_CRIT:
{
damageInfo->HitInfo |= HITINFO_CRITICALHIT;
damageInfo->TargetState = VICTIMSTATE_HIT;
- damageInfo->procEx |= PROC_EX_CRITICAL_HIT;
// Crit bonus calc
damageInfo->damage += damageInfo->damage;
float mod = 0.0f;
@@ -1336,32 +1329,27 @@ void Unit::CalculateMeleeDamage(Unit* victim, uint32 damage, CalcDamageInfo* dam
}
case MELEE_HIT_PARRY:
damageInfo->TargetState = VICTIMSTATE_PARRY;
- damageInfo->procEx |= PROC_EX_PARRY;
damageInfo->cleanDamage += damageInfo->damage;
damageInfo->damage = 0;
break;
case MELEE_HIT_DODGE:
damageInfo->TargetState = VICTIMSTATE_DODGE;
- damageInfo->procEx |= PROC_EX_DODGE;
damageInfo->cleanDamage += damageInfo->damage;
damageInfo->damage = 0;
break;
case MELEE_HIT_BLOCK:
damageInfo->TargetState = VICTIMSTATE_HIT;
damageInfo->HitInfo |= HITINFO_BLOCK;
- damageInfo->procEx |= PROC_EX_BLOCK;
damageInfo->blocked_amount = damageInfo->target->GetShieldBlockValue();
// double blocked amount if block is critical
if (damageInfo->target->isBlockCritical())
- damageInfo->blocked_amount+=damageInfo->blocked_amount;
+ damageInfo->blocked_amount += damageInfo->blocked_amount;
if (damageInfo->blocked_amount >= damageInfo->damage)
{
damageInfo->TargetState = VICTIMSTATE_BLOCKS;
damageInfo->blocked_amount = damageInfo->damage;
- damageInfo->procEx |= PROC_EX_FULL_BLOCK;
}
- else
- damageInfo->procEx |= PROC_EX_NORMAL_HIT;
+
damageInfo->damage -= damageInfo->blocked_amount;
damageInfo->cleanDamage += damageInfo->blocked_amount;
break;
@@ -1369,7 +1357,6 @@ void Unit::CalculateMeleeDamage(Unit* victim, uint32 damage, CalcDamageInfo* dam
{
damageInfo->HitInfo |= HITINFO_GLANCING;
damageInfo->TargetState = VICTIMSTATE_HIT;
- damageInfo->procEx |= PROC_EX_NORMAL_HIT;
int32 leveldif = int32(victim->getLevel()) - int32(getLevel());
if (leveldif > 3)
leveldif = 3;
@@ -1386,7 +1373,6 @@ void Unit::CalculateMeleeDamage(Unit* victim, uint32 damage, CalcDamageInfo* dam
case MELEE_HIT_CRUSHING:
damageInfo->HitInfo |= HITINFO_CRUSHING;
damageInfo->TargetState = VICTIMSTATE_HIT;
- damageInfo->procEx |= PROC_EX_NORMAL_HIT;
// 150% normal damage
damageInfo->damage += (damageInfo->damage / 2);
break;
@@ -1413,10 +1399,7 @@ void Unit::CalculateMeleeDamage(Unit* victim, uint32 damage, CalcDamageInfo* dam
CalcAbsorbResist(damageInfo->target, SpellSchoolMask(damageInfo->damageSchoolMask), DIRECT_DAMAGE, damageInfo->damage, &damageInfo->absorb, &damageInfo->resist);
if (damageInfo->absorb)
- {
damageInfo->HitInfo |= (damageInfo->damage - damageInfo->absorb == 0 ? HITINFO_FULL_ABSORB : HITINFO_PARTIAL_ABSORB);
- damageInfo->procEx |= PROC_EX_ABSORB;
- }
if (damageInfo->resist)
damageInfo->HitInfo |= (damageInfo->damage - damageInfo->resist == 0 ? HITINFO_FULL_RESIST : HITINFO_PARTIAL_RESIST);
@@ -1506,7 +1489,10 @@ void Unit::DealMeleeDamage(CalcDamageInfo* damageInfo, bool durabilityLoss)
}
if (GetTypeId() == TYPEID_PLAYER)
- ToPlayer()->CastItemCombatSpell(victim, damageInfo->attackType, damageInfo->procVictim, damageInfo->procEx);
+ {
+ DamageInfo dmgInfo(*damageInfo);
+ ToPlayer()->CastItemCombatSpell(dmgInfo);
+ }
// Do effect if any damage done to target
if (damageInfo->damage)
@@ -1598,7 +1584,7 @@ uint32 Unit::CalcArmorReducedDamage(Unit* victim, const uint32 damage, SpellInfo
if (spellInfo)
if (Player* modOwner = GetSpellModOwner())
- modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_IGNORE_ARMOR, armor);
+ modOwner->ApplySpellMod<SPELLMOD_IGNORE_ARMOR>(spellInfo->Id, armor);
AuraEffectList const& resIgnoreAurasAb = GetAuraEffectsByType(SPELL_AURA_MOD_ABILITY_IGNORE_TARGET_RESIST);
for (AuraEffectList::const_iterator j = resIgnoreAurasAb.begin(); j != resIgnoreAurasAb.end(); ++j)
@@ -1978,8 +1964,10 @@ void Unit::CalcAbsorbResist(Unit* victim, SpellSchoolMask schoolMask, DamageEffe
CleanDamage cleanDamage = CleanDamage(splitDamage, 0, BASE_ATTACK, MELEE_HIT_NORMAL);
DealDamage(caster, splitDamage, &cleanDamage, DIRECT_DAMAGE, schoolMask, (*itr)->GetSpellInfo(), false);
+
// break 'Fear' and similar auras
- caster->ProcDamageAndSpellFor(true, this, PROC_FLAG_TAKEN_SPELL_MAGIC_DMG_CLASS_NEG, PROC_EX_NORMAL_HIT, BASE_ATTACK, (*itr)->GetSpellInfo(), splitDamage);
+ DamageInfo damageInfo(caster, this, splitDamage, (*itr)->GetSpellInfo(), schoolMask, DIRECT_DAMAGE, BASE_ATTACK);
+ ProcSkillsAndAuras(caster, PROC_FLAG_NONE, PROC_FLAG_TAKEN_SPELL_MAGIC_DMG_CLASS_NEG, PROC_SPELL_TYPE_DAMAGE, PROC_SPELL_PHASE_HIT, PROC_HIT_NONE, nullptr, &damageInfo, nullptr);
}
}
@@ -1987,21 +1975,22 @@ void Unit::CalcAbsorbResist(Unit* victim, SpellSchoolMask schoolMask, DamageEffe
*absorb = dmgInfo.GetAbsorb();
}
-void Unit::CalcHealAbsorb(Unit* victim, SpellInfo const* healSpell, uint32 &healAmount, uint32 &absorb)
+void Unit::CalcHealAbsorb(HealInfo& healInfo)
{
- if (!healAmount)
+ if (!healInfo.GetHeal())
return;
- int32 RemainingHeal = healAmount;
+ int32 const healing = static_cast<int32>(healInfo.GetHeal());
+ int32 absorbAmount = 0;
// Need remove expired auras after
bool existExpired = false;
// absorb without mana cost
- AuraEffectList const& vHealAbsorb = victim->GetAuraEffectsByType(SPELL_AURA_SCHOOL_HEAL_ABSORB);
- for (AuraEffectList::const_iterator i = vHealAbsorb.begin(); i != vHealAbsorb.end() && RemainingHeal > 0; ++i)
+ AuraEffectList const& vHealAbsorb = healInfo.GetTarget()->GetAuraEffectsByType(SPELL_AURA_SCHOOL_HEAL_ABSORB);
+ for (AuraEffectList::const_iterator i = vHealAbsorb.begin(); i != vHealAbsorb.end() && absorbAmount <= healing; ++i)
{
- if (!((*i)->GetMiscValue() & healSpell->SchoolMask))
+ if (!((*i)->GetMiscValue() & healInfo.GetSpellInfo()->SchoolMask))
continue;
// Max Amount can be absorbed by this aura
@@ -2016,10 +2005,10 @@ void Unit::CalcHealAbsorb(Unit* victim, SpellInfo const* healSpell, uint32 &heal
// currentAbsorb - damage can be absorbed by shield
// If need absorb less damage
- if (RemainingHeal < currentAbsorb)
- currentAbsorb = RemainingHeal;
+ if (healing < currentAbsorb + absorbAmount)
+ currentAbsorb = healing - absorbAmount;
- RemainingHeal -= currentAbsorb;
+ absorbAmount += currentAbsorb;
// Reduce shield amount
(*i)->SetAmount((*i)->GetAmount() - currentAbsorb);
@@ -2037,19 +2026,19 @@ void Unit::CalcHealAbsorb(Unit* victim, SpellInfo const* healSpell, uint32 &heal
++i;
if (auraEff->GetAmount() <= 0)
{
- uint32 removedAuras = victim->m_removedAurasCount;
+ uint32 removedAuras = healInfo.GetTarget()->m_removedAurasCount;
auraEff->GetBase()->Remove(AURA_REMOVE_BY_ENEMY_SPELL);
- if (removedAuras+1 < victim->m_removedAurasCount)
+ if (removedAuras + 1 < healInfo.GetTarget()->m_removedAurasCount)
i = vHealAbsorb.begin();
}
}
}
- absorb = RemainingHeal > 0 ? (healAmount - RemainingHeal) : healAmount;
- healAmount = RemainingHeal;
+ if (absorbAmount > 0)
+ healInfo.AbsorbHeal(absorbAmount);
}
-void Unit::AttackerStateUpdate (Unit* victim, WeaponAttackType attType, bool extra)
+void Unit::AttackerStateUpdate(Unit* victim, WeaponAttackType attType, bool extra)
{
if (HasUnitState(UNIT_STATE_CANNOT_AUTOATTACK) || HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED))
return;
@@ -2083,8 +2072,7 @@ void Unit::AttackerStateUpdate (Unit* victim, WeaponAttackType attType, bool ext
DealDamageMods(victim, damageInfo.damage, &damageInfo.absorb);
SendAttackStateUpdate(&damageInfo);
- //TriggerAurasProcOnEvent(damageInfo);
- ProcDamageAndSpell(damageInfo.target, damageInfo.procAttacker, damageInfo.procVictim, damageInfo.procEx, damageInfo.damage, damageInfo.attackType);
+ TriggerAurasProcOnEvent(damageInfo);
DealMeleeDamage(&damageInfo, true);
@@ -2577,7 +2565,7 @@ SpellMissInfo Unit::MagicSpellHitResult(Unit* victim, SpellInfo const* spellInfo
// Spellmod from SPELLMOD_RESIST_MISS_CHANCE
if (Player* modOwner = GetSpellModOwner())
- modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_RESIST_MISS_CHANCE, modHitChance);
+ modOwner->ApplySpellMod<SPELLMOD_RESIST_MISS_CHANCE>(spellInfo->Id, modHitChance);
// Increase from attacker SPELL_AURA_MOD_INCREASES_SPELL_PCT_TO_HIT auras
modHitChance += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_INCREASES_SPELL_PCT_TO_HIT, schoolMask);
@@ -2683,12 +2671,9 @@ SpellMissInfo Unit::SpellHitResult(Unit* victim, SpellInfo const* spellInfo, boo
for (Unit::AuraEffectList::const_iterator i = mReflectSpellsSchool.begin(); i != mReflectSpellsSchool.end(); ++i)
if ((*i)->GetMiscValue() & spellInfo->GetSchoolMask())
reflectchance += (*i)->GetAmount();
+
if (reflectchance > 0 && roll_chance_i(reflectchance))
- {
- // Start triggers for remove charges if need (trigger only for victim, and mark as active spell)
- ProcDamageAndSpell(victim, PROC_FLAG_NONE, PROC_FLAG_TAKEN_SPELL_MAGIC_DMG_CLASS_NEG, PROC_EX_REFLECT, 1, BASE_ATTACK, spellInfo);
return SPELL_MISS_REFLECT;
- }
}
switch (spellInfo->DmgClass)
@@ -5214,15 +5199,16 @@ void Unit::SendSpellNonMeleeDamageLog(Unit* target, uint32 SpellID, uint32 Damag
SendSpellNonMeleeDamageLog(&log);
}
-void Unit::ProcDamageAndSpell(Unit* victim, uint32 procAttacker, uint32 procVictim, uint32 procExtra, uint32 amount, WeaponAttackType attType, SpellInfo const* procSpell, SpellInfo const* procAura)
+void Unit::ProcSkillsAndAuras(Unit* actionTarget, uint32 typeMaskActor, uint32 typeMaskActionTarget, uint32 spellTypeMask, uint32 spellPhaseMask, uint32 hitMask, Spell* spell, DamageInfo* damageInfo, HealInfo* healInfo)
{
- // Not much to do if no flags are set.
- if (procAttacker)
- ProcDamageAndSpellFor(false, victim, procAttacker, procExtra, attType, procSpell, amount, procAura);
- // Now go on with a victim's events'n'auras
- // Not much to do if no flags are set or there is no victim
- if (victim && victim->IsAlive() && procVictim)
- victim->ProcDamageAndSpellFor(true, this, procVictim, procExtra, attType, procSpell, amount, procAura);
+ WeaponAttackType attType = damageInfo ? damageInfo->GetAttackType() : BASE_ATTACK;
+ if (typeMaskActor && CanProc())
+ ProcSkillsAndReactives(false, actionTarget, typeMaskActor, hitMask, attType);
+
+ if (typeMaskActionTarget && actionTarget && actionTarget->CanProc())
+ actionTarget->ProcSkillsAndReactives(true, this, typeMaskActionTarget, hitMask, attType);
+
+ TriggerAurasProcOnEvent(actionTarget, typeMaskActor, typeMaskActionTarget, spellTypeMask, spellPhaseMask, hitMask, spell, damageInfo, healInfo);
}
void Unit::SendPeriodicAuraLog(SpellPeriodicAuraLogInfo* pInfo)
@@ -5384,2970 +5370,6 @@ void Unit::SendAttackStateUpdate(uint32 HitInfo, Unit* target, uint8 /*SwingType
SendAttackStateUpdate(&dmgInfo);
}
-//victim may be NULL
-bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, Milliseconds& cooldown)
-{
- SpellInfo const* dummySpell = triggeredByAura->GetSpellInfo();
- uint32 effIndex = triggeredByAura->GetEffIndex();
- int32 triggerAmount = triggeredByAura->GetAmount();
-
- Item* castItem = triggeredByAura->GetBase()->GetCastItemGUID() && GetTypeId() == TYPEID_PLAYER
- ? ToPlayer()->GetItemByGuid(triggeredByAura->GetBase()->GetCastItemGUID()) : NULL;
-
- uint32 triggered_spell_id = 0;
- Unit* target = victim;
- int32 basepoints0 = 0;
- ObjectGuid originalCaster;
-
- switch (dummySpell->SpellFamilyName)
- {
- case SPELLFAMILY_GENERIC:
- {
- switch (dummySpell->Id)
- {
- // Unstable Power
- case 24658:
- {
- if (!procSpell || procSpell->Id == 24659)
- return false;
- // Need remove one 24659 aura
- RemoveAuraFromStack(24659);
- return true;
- }
- // Restless Strength
- case 24661:
- {
- // Need remove one 24662 aura
- RemoveAuraFromStack(24662);
- return true;
- }
- // Mark of Malice
- case 33493:
- {
- // Cast finish spell at last charge
- if (triggeredByAura->GetBase()->GetCharges() > 1)
- return false;
-
- target = this;
- triggered_spell_id = 33494;
- break;
- }
- // Twisted Reflection (boss spell)
- case 21063:
- triggered_spell_id = 21064;
- break;
- // Vampiric Aura (boss spell)
- case 38196:
- {
- basepoints0 = 3 * damage; // 300%
- if (basepoints0 < 0)
- return false;
-
- triggered_spell_id = 31285;
- target = this;
- break;
- }
- // Aura of Madness (Darkmoon Card: Madness trinket)
- //=====================================================
- // 39511 Sociopath: +35 strength (Paladin, Rogue, Druid, Warrior)
- // 40997 Delusional: +70 attack power (Rogue, Hunter, Paladin, Warrior, Druid)
- // 40998 Kleptomania: +35 agility (Warrior, Rogue, Paladin, Hunter, Druid)
- // 40999 Megalomania: +41 damage/healing (Druid, Shaman, Priest, Warlock, Mage, Paladin)
- // 41002 Paranoia: +35 spell/melee/ranged crit strike rating (All classes)
- // 41005 Manic: +35 haste (spell, melee and ranged) (All classes)
- // 41009 Narcissism: +35 intellect (Druid, Shaman, Priest, Warlock, Mage, Paladin, Hunter)
- // 41011 Martyr Complex: +35 stamina (All classes)
- // 41406 Dementia: Every 5 seconds either gives you +5% damage/healing. (Druid, Shaman, Priest, Warlock, Mage, Paladin)
- // 41409 Dementia: Every 5 seconds either gives you -5% damage/healing. (Druid, Shaman, Priest, Warlock, Mage, Paladin)
- case 39446:
- {
- if (GetTypeId() != TYPEID_PLAYER || !IsAlive())
- return false;
-
- // Select class defined buff
- switch (getClass())
- {
- case CLASS_PALADIN: // 39511, 40997, 40998, 40999, 41002, 41005, 41009, 41011, 41409
- case CLASS_DRUID: // 39511, 40997, 40998, 40999, 41002, 41005, 41009, 41011, 41409
- triggered_spell_id = RAND(39511, 40997, 40998, 40999, 41002, 41005, 41009, 41011, 41409);
- break;
- case CLASS_ROGUE: // 39511, 40997, 40998, 41002, 41005, 41011
- case CLASS_WARRIOR: // 39511, 40997, 40998, 41002, 41005, 41011
- case CLASS_DEATH_KNIGHT:
- triggered_spell_id = RAND(39511, 40997, 40998, 41002, 41005, 41011);
- break;
- case CLASS_PRIEST: // 40999, 41002, 41005, 41009, 41011, 41406, 41409
- case CLASS_SHAMAN: // 40999, 41002, 41005, 41009, 41011, 41406, 41409
- case CLASS_MAGE: // 40999, 41002, 41005, 41009, 41011, 41406, 41409
- case CLASS_WARLOCK: // 40999, 41002, 41005, 41009, 41011, 41406, 41409
- triggered_spell_id = RAND(40999, 41002, 41005, 41009, 41011, 41406, 41409);
- break;
- case CLASS_HUNTER: // 40997, 40999, 41002, 41005, 41009, 41011, 41406, 41409
- triggered_spell_id = RAND(40997, 40999, 41002, 41005, 41009, 41011, 41406, 41409);
- break;
- default:
- return false;
- }
-
- target = this;
- if (roll_chance_i(10))
- ToPlayer()->Say("This is Madness!", LANG_UNIVERSAL); /// @todo It should be moved to database, shouldn't it?
- break;
- }
- // Sunwell Exalted Caster Neck (??? neck)
- // cast ??? Light's Wrath if Exalted by Aldor
- // cast ??? Arcane Bolt if Exalted by Scryers
- case 46569:
- return false; // old unused version
- // Sunwell Exalted Caster Neck (Shattered Sun Pendant of Acumen neck)
- // cast 45479 Light's Wrath if Exalted by Aldor
- // cast 45429 Arcane Bolt if Exalted by Scryers
- case 45481:
- {
- Player* player = ToPlayer();
- if (!player)
- return false;
-
- // Get Aldor reputation rank
- if (player->GetReputationRank(932) == REP_EXALTED)
- {
- target = this;
- triggered_spell_id = 45479;
- break;
- }
- // Get Scryers reputation rank
- if (player->GetReputationRank(934) == REP_EXALTED)
- {
- // triggered at positive/self casts also, current attack target used then
- if (target && IsFriendlyTo(target))
- {
- target = GetVictim();
- if (!target)
- {
- target = player->GetSelectedUnit();
- if (!target)
- return false;
- }
- if (IsFriendlyTo(target))
- return false;
- }
-
- triggered_spell_id = 45429;
- break;
- }
- return false;
- }
- // Sunwell Exalted Melee Neck (Shattered Sun Pendant of Might neck)
- // cast 45480 Light's Strength if Exalted by Aldor
- // cast 45428 Arcane Strike if Exalted by Scryers
- case 45482:
- {
- if (GetTypeId() != TYPEID_PLAYER)
- return false;
-
- // Get Aldor reputation rank
- if (ToPlayer()->GetReputationRank(932) == REP_EXALTED)
- {
- target = this;
- triggered_spell_id = 45480;
- break;
- }
- // Get Scryers reputation rank
- if (ToPlayer()->GetReputationRank(934) == REP_EXALTED)
- {
- triggered_spell_id = 45428;
- break;
- }
- return false;
- }
- // Sunwell Exalted Tank Neck (Shattered Sun Pendant of Resolve neck)
- // cast 45431 Arcane Insight if Exalted by Aldor
- // cast 45432 Light's Ward if Exalted by Scryers
- case 45483:
- {
- if (GetTypeId() != TYPEID_PLAYER)
- return false;
-
- // Get Aldor reputation rank
- if (ToPlayer()->GetReputationRank(932) == REP_EXALTED)
- {
- target = this;
- triggered_spell_id = 45432;
- break;
- }
- // Get Scryers reputation rank
- if (ToPlayer()->GetReputationRank(934) == REP_EXALTED)
- {
- target = this;
- triggered_spell_id = 45431;
- break;
- }
- return false;
- }
- // Sunwell Exalted Healer Neck (Shattered Sun Pendant of Restoration neck)
- // cast 45478 Light's Salvation if Exalted by Aldor
- // cast 45430 Arcane Surge if Exalted by Scryers
- case 45484:
- {
- if (GetTypeId() != TYPEID_PLAYER)
- return false;
-
- // Get Aldor reputation rank
- if (ToPlayer()->GetReputationRank(932) == REP_EXALTED)
- {
- target = this;
- triggered_spell_id = 45478;
- break;
- }
- // Get Scryers reputation rank
- if (ToPlayer()->GetReputationRank(934) == REP_EXALTED)
- {
- triggered_spell_id = 45430;
- break;
- }
- return false;
- }
- // Kill command
- case 58914:
- {
- // Remove aura stack from pet
- RemoveAuraFromStack(58914);
- Unit* owner = GetOwner();
- if (!owner)
- return true;
- // reduce the owner's aura stack
- owner->RemoveAuraFromStack(34027);
- return true;
- }
- // Vampiric Touch (generic, used by some boss)
- case 52723:
- case 60501:
- {
- triggered_spell_id = 52724;
- basepoints0 = damage / 2;
- target = this;
- break;
- }
- // Shadowfiend Death (Gain mana if pet dies with Glyph of Shadowfiend)
- case 57989:
- {
- Unit* owner = GetOwner();
- if (!owner || owner->GetTypeId() != TYPEID_PLAYER)
- return false;
- // Glyph of Shadowfiend (need cast as self cast for owner, no hidden cooldown)
- owner->CastSpell(owner, 58227, true, castItem, triggeredByAura);
- return true;
- }
- // Divine purpose
- case 31871:
- case 31872:
- {
- // Roll chane
- if (!victim || !victim->IsAlive() || !roll_chance_i(triggerAmount))
- return false;
-
- // Remove any stun effect on target
- victim->RemoveAurasWithMechanic(1<<MECHANIC_STUN, AURA_REMOVE_BY_ENEMY_SPELL);
- return true;
- }
- // Glyph of Scourge Strike
- case 58642:
- {
- triggered_spell_id = 69961; // Glyph of Scourge Strike
- break;
- }
- // Glyph of Life Tap
- case 63320:
- {
- triggered_spell_id = 63321; // Life Tap
- break;
- }
- // Purified Shard of the Scale - Onyxia 10 Caster Trinket
- case 69755:
- {
- triggered_spell_id = (procFlag & PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_POS) ? 69733 : 69729;
- break;
- }
- // Shiny Shard of the Scale - Onyxia 25 Caster Trinket
- case 69739:
- {
- triggered_spell_id = (procFlag & PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_POS) ? 69734 : 69730;
- break;
- }
- case 71519: // Deathbringer's Will Normal
- {
- if (GetTypeId() != TYPEID_PLAYER)
- return false;
-
- std::vector<uint32> RandomSpells;
- switch (getClass())
- {
- case CLASS_WARRIOR:
- case CLASS_PALADIN:
- case CLASS_DEATH_KNIGHT:
- RandomSpells.push_back(71484);
- RandomSpells.push_back(71491);
- RandomSpells.push_back(71492);
- break;
- case CLASS_SHAMAN:
- case CLASS_ROGUE:
- RandomSpells.push_back(71486);
- RandomSpells.push_back(71485);
- RandomSpells.push_back(71492);
- break;
- case CLASS_DRUID:
- RandomSpells.push_back(71484);
- RandomSpells.push_back(71485);
- RandomSpells.push_back(71492);
- break;
- case CLASS_HUNTER:
- RandomSpells.push_back(71486);
- RandomSpells.push_back(71491);
- RandomSpells.push_back(71485);
- break;
- default:
- return false;
- }
- if (RandomSpells.empty()) // shouldn't happen
- return false;
-
- uint8 rand_spell = urand(0, (RandomSpells.size() - 1));
- CastSpell(target, RandomSpells[rand_spell], true, castItem, triggeredByAura, originalCaster);
- break;
- }
- case 71562: // Deathbringer's Will Heroic
- {
- if (GetTypeId() != TYPEID_PLAYER)
- return false;
-
- std::vector<uint32> RandomSpells;
- switch (getClass())
- {
- case CLASS_WARRIOR:
- case CLASS_PALADIN:
- case CLASS_DEATH_KNIGHT:
- RandomSpells.push_back(71561);
- RandomSpells.push_back(71559);
- RandomSpells.push_back(71560);
- break;
- case CLASS_SHAMAN:
- case CLASS_ROGUE:
- RandomSpells.push_back(71558);
- RandomSpells.push_back(71556);
- RandomSpells.push_back(71560);
- break;
- case CLASS_DRUID:
- RandomSpells.push_back(71561);
- RandomSpells.push_back(71556);
- RandomSpells.push_back(71560);
- break;
- case CLASS_HUNTER:
- RandomSpells.push_back(71558);
- RandomSpells.push_back(71559);
- RandomSpells.push_back(71556);
- break;
- default:
- return false;
- }
- if (RandomSpells.empty()) // shouldn't happen
- return false;
-
- uint8 rand_spell = urand(0, (RandomSpells.size() - 1));
- CastSpell(target, RandomSpells[rand_spell], true, castItem, triggeredByAura, originalCaster);
- break;
- }
- case 65032: // Boom aura (321 Boombot)
- {
- if (victim->GetEntry() != 33343) // Scrapbot
- return false;
-
- InstanceScript* instance = GetInstanceScript();
- if (!instance)
- return false;
-
- instance->DoCastSpellOnPlayers(65037); // Achievement criteria marker
- break;
- }
- }
- break;
- }
- case SPELLFAMILY_MAGE:
- {
- // Magic Absorption
- if (dummySpell->SpellIconID == 459) // only this spell has SpellIconID == 459 and dummy aura
- {
- if (getPowerType() != POWER_MANA)
- return false;
-
- // mana reward
- basepoints0 = CalculatePct(int32(GetMaxPower(POWER_MANA)), triggerAmount);
- target = this;
- triggered_spell_id = 29442;
- break;
- }
- // Arcane Potency
- if (dummySpell->SpellIconID == 2120)
- {
- if (!procSpell)
- return false;
-
- target = this;
- switch (dummySpell->Id)
- {
- case 31571: triggered_spell_id = 57529; break;
- case 31572: triggered_spell_id = 57531; break;
- default:
- TC_LOG_ERROR("entities.unit", "Unit::HandleDummyAuraProc: non handled spell id: %u", dummySpell->Id);
- return false;
- }
- break;
- }
- // Hot Streak
- if (dummySpell->SpellIconID == 2999)
- {
- if (effIndex != 0)
- return false;
- AuraEffect* counter = triggeredByAura->GetBase()->GetEffect(EFFECT_1);
- if (!counter)
- return true;
-
- // Count spell criticals in a row in second aura
- if (procEx & PROC_EX_CRITICAL_HIT)
- {
- counter->SetAmount(counter->GetAmount() * 2);
- if (counter->GetAmount() < 100) // not enough
- return true;
- // Crititcal counted -> roll chance
- if (roll_chance_i(triggerAmount))
- CastSpell(this, 48108, true, castItem, triggeredByAura);
- }
- counter->SetAmount(25);
- return true;
- }
- // Incanter's Regalia set (add trigger chance to Mana Shield)
- if (dummySpell->SpellFamilyFlags[0] & 0x8000)
- {
- if (GetTypeId() != TYPEID_PLAYER)
- return false;
-
- target = this;
- triggered_spell_id = 37436;
- break;
- }
- switch (dummySpell->Id)
- {
- // Glyph of Polymorph
- case 56375:
- {
- if (!target)
- return false;
- target->RemoveAurasByType(SPELL_AURA_PERIODIC_DAMAGE, ObjectGuid::Empty, target->GetAura(32409)); // SW:D shall not be removed.
- target->RemoveAurasByType(SPELL_AURA_PERIODIC_DAMAGE_PERCENT);
- target->RemoveAurasByType(SPELL_AURA_PERIODIC_LEECH);
- return true;
- }
- // Glyph of Icy Veins
- case 56374:
- {
- RemoveAurasByType(SPELL_AURA_HASTE_SPELLS, ObjectGuid::Empty, 0, true, false);
- RemoveAurasByType(SPELL_AURA_MOD_DECREASE_SPEED);
- return true;
- }
- // Glyph of Ice Block
- case 56372:
- {
- if (GetTypeId() != TYPEID_PLAYER)
- return false;
-
- GetSpellHistory()->ResetCooldowns([](SpellHistory::CooldownStorageType::iterator itr) -> bool
- {
- SpellInfo const* cdSpell = sSpellMgr->GetSpellInfo(itr->first);
- if (!cdSpell || cdSpell->SpellFamilyName != SPELLFAMILY_MAGE
- || !(cdSpell->SpellFamilyFlags[0] & 0x00000040))
- return false;
- return true;
- }, true);
- break;
- }
- case 47020: // Enter vehicle XT-002 (Scrapbot)
- {
- if (GetTypeId() != TYPEID_UNIT)
- return false;
-
- Unit* vehicleBase = GetVehicleBase();
- if (!vehicleBase)
- return false;
-
- /// @todo Check if this amount is blizzlike
- vehicleBase->ModifyHealth(int32(vehicleBase->CountPctFromMaxHealth(1)));
- break;
- }
- }
- break;
- }
- case SPELLFAMILY_WARRIOR:
- {
- switch (dummySpell->Id)
- {
- // Victorious
- case 32216:
- {
- RemoveAura(dummySpell->Id);
- return false;
- }
- // Improved Spell Reflection
- case 59088:
- case 59089:
- {
- triggered_spell_id = 59725;
- target = this;
- break;
- }
- }
- // Second Wind
- if (dummySpell->SpellIconID == 1697)
- {
- // only for spells and hit/crit (trigger start always) and not start from self cast spells (5530 Mace Stun Effect for example)
- if (!procSpell || !(procEx & (PROC_EX_NORMAL_HIT|PROC_EX_CRITICAL_HIT)) || this == victim)
- return false;
- // Need stun or root mechanic
- if (!(procSpell->GetAllEffectsMechanicMask() & ((1<<MECHANIC_ROOT)|(1<<MECHANIC_STUN))))
- return false;
-
- switch (dummySpell->Id)
- {
- case 29838: triggered_spell_id=29842; break;
- case 29834: triggered_spell_id=29841; break;
- case 42770: triggered_spell_id=42771; break;
- default:
- TC_LOG_ERROR("entities.unit", "Unit::HandleDummyAuraProc: non handled spell id: %u (SW)", dummySpell->Id);
- return false;
- }
-
- target = this;
- break;
- }
- // Glyph of Blocking
- if (dummySpell->Id == 58375)
- {
- triggered_spell_id = 58374;
- break;
- }
- break;
- }
- case SPELLFAMILY_WARLOCK:
- {
- // Seed of Corruption
- if (dummySpell->SpellFamilyFlags[1] & 0x00000010)
- {
- if (procSpell && procSpell->SpellFamilyFlags[1] & 0x8000)
- return false;
- // if damage is more than need or target die from damage deal finish spell
- if (triggeredByAura->GetAmount() <= int32(damage) || GetHealth() <= damage)
- {
- // remember caster before aura delete
- Unit* caster = triggeredByAura->GetCaster();
-
- // Remove aura (before cast for prevent infinite loop handlers)
- RemoveAurasDueToSpell(triggeredByAura->GetId());
-
- uint32 spell = sSpellMgr->GetSpellWithRank(27285, dummySpell->GetRank());
-
- // Cast finish spell (triggeredByAura already not exist!)
- if (caster)
- caster->CastSpell(this, spell, true, castItem);
- return true; // no hidden cooldown
- }
-
- // Damage counting
- triggeredByAura->SetAmount(triggeredByAura->GetAmount() - damage);
- return true;
- }
- // Seed of Corruption (Mobs cast) - no die req
- if (dummySpell->SpellFamilyFlags.IsEqual(0, 0, 0) && dummySpell->SpellIconID == 1932)
- {
- // if damage is more than need deal finish spell
- if (triggeredByAura->GetAmount() <= int32(damage))
- {
- // remember caster before aura delete
- Unit* caster = triggeredByAura->GetCaster();
-
- // Remove aura (before cast for prevent infinite loop handlers)
- RemoveAurasDueToSpell(triggeredByAura->GetId());
-
- // Cast finish spell (triggeredByAura already not exist!)
- if (caster)
- caster->CastSpell(this, 32865, true, castItem);
- return true; // no hidden cooldown
- }
- // Damage counting
- triggeredByAura->SetAmount(triggeredByAura->GetAmount() - damage);
- return true;
- }
- switch (dummySpell->Id)
- {
- // Nightfall
- case 18094:
- case 18095:
- // Glyph of corruption
- case 56218:
- {
- target = this;
- triggered_spell_id = 17941;
- break;
- }
- // Soul Leech
- case 30293:
- case 30295:
- case 30296:
- {
- // Improved Soul Leech
- AuraEffectList const& SoulLeechAuras = GetAuraEffectsByType(SPELL_AURA_DUMMY);
- for (Unit::AuraEffectList::const_iterator i = SoulLeechAuras.begin(); i != SoulLeechAuras.end(); ++i)
- {
- if ((*i)->GetId() == 54117 || (*i)->GetId() == 54118)
- {
- if ((*i)->GetEffIndex() != 0)
- continue;
- basepoints0 = int32((*i)->GetAmount());
- target = GetGuardianPet();
- if (target)
- {
- // regen mana for pet
- CastCustomSpell(target, 54607, &basepoints0, NULL, NULL, true, castItem, triggeredByAura);
- }
- // regen mana for caster
- CastCustomSpell(this, 59117, &basepoints0, NULL, NULL, true, castItem, triggeredByAura);
- // Get second aura of spell for replenishment effect on party
- if (AuraEffect const* aurEff = (*i)->GetBase()->GetEffect(EFFECT_1))
- {
- // Replenishment - roll chance
- if (roll_chance_i(aurEff->GetAmount()))
- CastSpell(this, 57669, true, castItem, triggeredByAura);
- }
- break;
- }
- }
- // health
- basepoints0 = CalculatePct(int32(damage), triggerAmount);
- target = this;
- triggered_spell_id = 30294;
- break;
- }
- // Shadowflame (Voidheart Raiment set bonus)
- case 37377:
- {
- triggered_spell_id = 37379;
- break;
- }
- // Pet Healing (Corruptor Raiment or Rift Stalker Armor)
- case 37381:
- {
- target = GetGuardianPet();
- if (!target)
- return false;
-
- // heal amount
- basepoints0 = CalculatePct(int32(damage), triggerAmount);
- triggered_spell_id = 37382;
- break;
- }
- // Shadowflame Hellfire (Voidheart Raiment set bonus)
- case 39437:
- {
- triggered_spell_id = 37378;
- break;
- }
- // Glyph of Succubus
- case 56250:
- {
- if (!target)
- return false;
- target->RemoveAurasByType(SPELL_AURA_PERIODIC_DAMAGE, ObjectGuid::Empty, target->GetAura(32409)); // SW:D shall not be removed.
- target->RemoveAurasByType(SPELL_AURA_PERIODIC_DAMAGE_PERCENT);
- target->RemoveAurasByType(SPELL_AURA_PERIODIC_LEECH);
- return true;
- }
- }
- break;
- }
- case SPELLFAMILY_PRIEST:
- {
- // Vampiric Touch
- if (dummySpell->SpellFamilyFlags[1] & 0x00000400)
- {
- if (!victim || !victim->IsAlive())
- return false;
-
- if (effIndex != 0)
- return false;
-
- // victim is caster of aura
- if (triggeredByAura->GetCasterGUID() != victim->GetGUID())
- return false;
-
- // Energize 0.25% of max. mana
- victim->CastSpell(victim, 57669, true, castItem, triggeredByAura);
- return true; // no hidden cooldown
- }
- // Body and Soul
- if (dummySpell->SpellIconID == 2218)
- {
- // Proc only from Abolish desease on self cast
- if (!procSpell || procSpell->Id != 552 || victim != this || !roll_chance_i(triggerAmount))
- return false;
- triggered_spell_id = 64136;
- target = this;
- break;
- }
- switch (dummySpell->Id)
- {
- // Vampiric Embrace
- case 15286:
- {
- if (!victim || !victim->IsAlive() || !procSpell || procSpell->SpellFamilyFlags[1] & 0x80000)
- return false;
-
- // heal amount
- int32 total = CalculatePct(int32(damage), triggerAmount);
- int32 team = total / 5;
- int32 self = total - team;
- CastCustomSpell(this, 15290, &team, &self, NULL, true, castItem, triggeredByAura);
- return true; // no hidden cooldown
- }
- // Priest Tier 6 Trinket (Ashtongue Talisman of Acumen)
- case 40438:
- {
- // Shadow Word: Pain
- if (!procSpell)
- return false;
- else if (procSpell->SpellFamilyFlags[0] & 0x8000)
- triggered_spell_id = 40441;
- // Renew
- else if (procSpell->SpellFamilyFlags[0] & 0x40)
- triggered_spell_id = 40440;
- else
- return false;
-
- target = this;
- break;
- }
- // Improved Shadowform
- case 47570:
- case 47569:
- {
- if (!roll_chance_i(triggerAmount))
- return false;
-
- RemoveMovementImpairingAuras();
- break;
- }
- // Glyph of Dispel Magic
- case 55677:
- {
- // Dispel Magic shares spellfamilyflag with abolish disease
- if (!procSpell || procSpell->SpellIconID != 74)
- return false;
- if (!target || !target->IsFriendlyTo(this))
- return false;
-
- basepoints0 = int32(target->CountPctFromMaxHealth(triggerAmount));
- triggered_spell_id = 56131;
- break;
- }
- // Oracle Healing Bonus ("Garments of the Oracle" set)
- case 26169:
- {
- // heal amount
- basepoints0 = int32(CalculatePct(damage, 10));
- target = this;
- triggered_spell_id = 26170;
- break;
- }
- // Frozen Shadoweave (Shadow's Embrace set) warning! its not only priest set
- case 39372:
- {
- if (!procSpell || (procSpell->GetSchoolMask() & (SPELL_SCHOOL_MASK_FROST | SPELL_SCHOOL_MASK_SHADOW)) == 0)
- return false;
-
- // heal amount
- basepoints0 = CalculatePct(int32(damage), triggerAmount);
- target = this;
- triggered_spell_id = 39373;
- break;
- }
- // Greater Heal (Vestments of Faith (Priest Tier 3) - 4 pieces bonus)
- case 28809:
- {
- triggered_spell_id = 28810;
- break;
- }
- // Priest T10 Healer 2P Bonus
- case 70770:
- // Flash Heal
- if (procSpell && procSpell->SpellFamilyFlags[0] & 0x800)
- {
- triggered_spell_id = 70772;
- SpellInfo const* blessHealing = sSpellMgr->GetSpellInfo(triggered_spell_id);
- if (!blessHealing)
- return false;
- basepoints0 = int32(CalculatePct(damage, triggerAmount) / (blessHealing->GetMaxDuration() / blessHealing->Effects[0].Amplitude));
- }
- break;
- }
- break;
- }
- case SPELLFAMILY_DRUID:
- {
- switch (dummySpell->Id)
- {
- // Glyph of Innervate
- case 54832:
- {
- if (!procSpell || procSpell->SpellIconID != 62)
- return false;
-
- int32 mana_perc = triggeredByAura->GetSpellInfo()->Effects[triggeredByAura->GetEffIndex()].CalcValue();
- basepoints0 = int32(CalculatePct(GetCreatePowers(POWER_MANA), mana_perc) / 10);
- triggered_spell_id = 54833;
- target = this;
- break;
- }
- // Glyph of Starfire
- case 54845:
- {
- triggered_spell_id = 54846;
- break;
- }
- // Glyph of Shred
- case 54815:
- {
- if (!target)
- return false;
-
- // try to find spell Rip on the target
- if (AuraEffect const* AurEff = target->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_DRUID, 0x00800000, 0x0, 0x0, GetGUID()))
- {
- // Rip's max duration, note: spells which modifies Rip's duration also counted like Glyph of Rip
- uint32 CountMin = AurEff->GetBase()->GetMaxDuration();
-
- // just Rip's max duration without other spells
- uint32 CountMax = AurEff->GetSpellInfo()->GetMaxDuration();
-
- // add possible auras' and Glyph of Shred's max duration
- CountMax += 3 * triggerAmount * IN_MILLISECONDS; // Glyph of Shred -> +6 seconds
- CountMax += HasAura(54818) ? 4 * IN_MILLISECONDS : 0; // Glyph of Rip -> +4 seconds
- CountMax += HasAura(60141) ? 4 * IN_MILLISECONDS : 0; // Rip Duration/Lacerate Damage -> +4 seconds
-
- // if min < max -> that means caster didn't cast 3 shred yet
- // so set Rip's duration and max duration
- if (CountMin < CountMax)
- {
- AurEff->GetBase()->SetDuration(AurEff->GetBase()->GetDuration() + triggerAmount * IN_MILLISECONDS);
- AurEff->GetBase()->SetMaxDuration(CountMin + triggerAmount * IN_MILLISECONDS);
- return true;
- }
- }
- // if not found Rip
- return false;
- }
- // Glyph of Rake
- case 54821:
- {
- if (procSpell && procSpell->SpellVisual[0] == 750 && procSpell->Effects[1].ApplyAuraName == 3)
- {
- if (target && target->GetTypeId() == TYPEID_UNIT)
- {
- triggered_spell_id = 54820;
- break;
- }
- }
- return false;
- }
- // Leader of the Pack
- case 24932:
- {
- if (triggerAmount <= 0)
- return false;
- basepoints0 = int32(CountPctFromMaxHealth(triggerAmount));
- target = this;
- triggered_spell_id = 34299;
- if (triggeredByAura->GetCasterGUID() != GetGUID())
- break;
- int32 basepoints1 = CalculatePct(GetMaxPower(Powers(POWER_MANA)), triggerAmount * 2);
- // Improved Leader of the Pack
- // Check cooldown of heal spell cooldown
- if (!GetSpellHistory()->HasCooldown(34299))
- CastCustomSpell(this, 68285, &basepoints1, 0, 0, true, 0, triggeredByAura);
- break;
- }
- // Healing Touch (Dreamwalker Raiment set)
- case 28719:
- {
- if (procSpell)
- {
- // mana back
- basepoints0 = int32(CalculatePct(procSpell->ManaCost, 30));
- target = this;
- triggered_spell_id = 28742;
- }
- break;
- }
- // Glyph of Rejuvenation
- case 54754:
- {
- if (!victim || !victim->HealthBelowPct(uint32(triggerAmount)))
- return false;
- basepoints0 = CalculatePct(int32(damage), triggerAmount);
- triggered_spell_id = 54755;
- break;
- }
- // Healing Touch Refund (Idol of Longevity trinket)
- case 28847:
- {
- target = this;
- triggered_spell_id = 28848;
- break;
- }
- // Mana Restore (Malorne Raiment set / Malorne Regalia set)
- case 37288:
- case 37295:
- {
- target = this;
- triggered_spell_id = 37238;
- break;
- }
- // Druid Tier 6 Trinket
- case 40442:
- {
- float chance;
-
- if (!procSpell)
- return false;
- // Starfire
- else if (procSpell->SpellFamilyFlags[0] & 0x4)
- {
- triggered_spell_id = 40445;
- chance = 25.0f;
- }
- // Rejuvenation
- else if (procSpell->SpellFamilyFlags[0] & 0x10)
- {
- triggered_spell_id = 40446;
- chance = 25.0f;
- }
- // Mangle (Bear) and Mangle (Cat)
- else if (procSpell->SpellFamilyFlags[1] & 0x00000440)
- {
- triggered_spell_id = 40452;
- chance = 40.0f;
- }
- else
- return false;
-
- if (!roll_chance_f(chance))
- return false;
-
- target = this;
- break;
- }
- // Maim Interrupt
- case 44835:
- {
- // Deadly Interrupt Effect
- triggered_spell_id = 32747;
- break;
- }
- // Item - Druid T10 Balance 4P Bonus
- case 70723:
- {
- // Wrath & Starfire
- if (procSpell && (procSpell->SpellFamilyFlags[0] & 0x5) && (procEx & PROC_EX_CRITICAL_HIT))
- {
- triggered_spell_id = 71023;
- SpellInfo const* triggeredSpell = sSpellMgr->GetSpellInfo(triggered_spell_id);
- if (!triggeredSpell)
- return false;
- basepoints0 = CalculatePct(int32(damage), triggerAmount) / (triggeredSpell->GetMaxDuration() / triggeredSpell->Effects[0].Amplitude);
- // Add remaining ticks to damage done
- basepoints0 += victim->GetRemainingPeriodicAmount(GetGUID(), triggered_spell_id, SPELL_AURA_PERIODIC_DAMAGE);
- }
- break;
- }
- // Item - Druid T10 Restoration 4P Bonus (Rejuvenation)
- case 70664:
- {
- // Proc only from normal Rejuvenation
- if (!procSpell || procSpell->SpellVisual[0] != 32)
- return false;
-
- Player* caster = ToPlayer();
- if (!caster)
- return false;
- if (!caster->GetGroup() && victim == this)
- return false;
-
- CastCustomSpell(70691, SPELLVALUE_BASE_POINT0, damage, victim, true);
- return true;
- }
- }
- break;
- }
- case SPELLFAMILY_ROGUE:
- {
- switch (dummySpell->Id)
- {
- case 56800: // Glyph of Backstab
- {
- triggered_spell_id = 63975;
- break;
- }
- case 32748: // Deadly Throw Interrupt
- {
- // Prevent cast Deadly Throw Interrupt on self from last effect (apply dummy) of Deadly Throw
- if (this == victim)
- return false;
-
- triggered_spell_id = 32747;
- break;
- }
- }
-
- switch (dummySpell->SpellIconID)
- {
- case 2116: // Quick Recovery
- {
- if (!procSpell)
- return false;
-
- // energy cost save
- basepoints0 = CalculatePct(int32(procSpell->ManaCost), triggerAmount);
- if (basepoints0 <= 0)
- return false;
-
- target = this;
- triggered_spell_id = 31663;
- break;
- }
- case 2909: // Cut to the Chase
- {
- // "refresh your Slice and Dice duration to its 5 combo point maximum"
- // lookup Slice and Dice
- if (AuraEffect const* aur = GetAuraEffect(SPELL_AURA_MOD_MELEE_HASTE, SPELLFAMILY_ROGUE, 0x40000, 0, 0))
- {
- aur->GetBase()->SetDuration(aur->GetSpellInfo()->GetMaxDuration(), true);
- return true;
- }
- return false;
- }
- case 2963: // Deadly Brew
- {
- triggered_spell_id = 3409;
- break;
- }
- }
- break;
- }
- case SPELLFAMILY_HUNTER:
- {
- switch (dummySpell->SpellIconID)
- {
- case 2236: // Thrill of the Hunt
- {
- if (!procSpell)
- return false;
-
- Spell* spell = ToPlayer()->m_spellModTakingSpell;
-
- // Disable charge drop because of Lock and Load
- ToPlayer()->SetSpellModTakingSpell(spell, false);
-
- // Explosive Shot
- if (procSpell->SpellFamilyFlags[2] & 0x200)
- {
- if (!victim)
- return false;
- if (AuraEffect const* pEff = victim->GetAuraEffect(SPELL_AURA_PERIODIC_DUMMY, SPELLFAMILY_HUNTER, 0x0, 0x80000000, 0x0, GetGUID()))
- basepoints0 = pEff->GetSpellInfo()->CalcPowerCost(this, SpellSchoolMask(pEff->GetSpellInfo()->SchoolMask)) * 4/10/3;
- }
- else
- basepoints0 = procSpell->CalcPowerCost(this, SpellSchoolMask(procSpell->SchoolMask)) * 4/10;
-
- ToPlayer()->SetSpellModTakingSpell(spell, true);
-
- if (basepoints0 <= 0)
- return false;
-
- target = this;
- triggered_spell_id = 34720;
- break;
- }
- case 3406: // Hunting Party
- {
- triggered_spell_id = 57669;
- target = this;
- break;
- }
- case 3560: // Rapid Recuperation
- {
- // This effect only from Rapid Killing (mana regen)
- if (!procSpell || !(procSpell->SpellFamilyFlags[1] & 0x01000000))
- return false;
-
- target = this;
-
- switch (dummySpell->Id)
- {
- case 53228: // Rank 1
- triggered_spell_id = 56654;
- break;
- case 53232: // Rank 2
- triggered_spell_id = 58882;
- break;
- }
- break;
- }
- }
-
- switch (dummySpell->Id)
- {
- case 57870: // Glyph of Mend Pet
- {
- victim->CastSpell(victim, 57894, true, NULL, NULL, GetGUID());
- return true;
- }
- }
- break;
- }
- case SPELLFAMILY_PALADIN:
- {
- // Judgements of the Wise
- if (dummySpell->SpellIconID == 3017)
- {
- target = this;
- triggered_spell_id = 31930;
- // replenishment
- CastSpell(this, 57669, true, castItem, triggeredByAura);
- break;
- }
- // Righteous Vengeance
- if (dummySpell->SpellIconID == 3025)
- {
- // 4 damage tick
- basepoints0 = triggerAmount * damage / 400;
- triggered_spell_id = 61840;
- // Add remaining ticks to damage done
- basepoints0 += victim->GetRemainingPeriodicAmount(GetGUID(), triggered_spell_id, SPELL_AURA_PERIODIC_DAMAGE);
- break;
- }
- // Sheath of Light
- if (dummySpell->SpellIconID == 3030)
- {
- // 4 healing tick
- basepoints0 = triggerAmount * damage / 400;
- triggered_spell_id = 54203;
- // Add remaining ticks to healing done
- basepoints0 += victim->GetRemainingPeriodicAmount(GetGUID(), triggered_spell_id, SPELL_AURA_PERIODIC_HEAL);
- break;
- }
- switch (dummySpell->Id)
- {
- // Sacred Shield
- case 53601:
- {
- if (procFlag & PROC_FLAG_TAKEN_SPELL_MAGIC_DMG_CLASS_POS)
- return false;
-
- if (damage > 0)
- triggered_spell_id = 58597;
-
- // Item - Paladin T8 Holy 4P Bonus
- if (Unit* caster = triggeredByAura->GetCaster())
- if (AuraEffect const* aurEff = caster->GetAuraEffect(64895, 0))
- cooldown = Milliseconds(aurEff->GetAmount());
-
- target = this;
- break;
- }
- // Heart of the Crusader
- case 20335: // rank 1
- triggered_spell_id = 21183;
- break;
- case 20336: // rank 2
- triggered_spell_id = 54498;
- break;
- case 20337: // rank 3
- triggered_spell_id = 54499;
- break;
- // Judgement of Light
- case 20185:
- {
- if (!victim)
- return false;
-
- // 2% of maximum health
- basepoints0 = int32(victim->CountPctFromMaxHealth(2));
- victim->CastCustomSpell(victim, 20267, &basepoints0, 0, 0, true, 0, triggeredByAura);
- return true;
- }
- // Judgement of Wisdom
- case 20186:
- {
- if (victim && victim->IsAlive() && victim->getPowerType() == POWER_MANA)
- {
- // 2% of base mana
- basepoints0 = int32(CalculatePct(victim->GetCreateMana(), 2));
- victim->CastCustomSpell(victim, 20268, &basepoints0, NULL, NULL, true, 0, triggeredByAura);
- }
- return true;
- }
- // Holy Power (Redemption Armor set)
- case 28789:
- {
- if (!victim)
- return false;
-
- // Set class defined buff
- switch (victim->getClass())
- {
- case CLASS_PALADIN:
- case CLASS_PRIEST:
- case CLASS_SHAMAN:
- case CLASS_DRUID:
- triggered_spell_id = 28795; // Increases the friendly target's mana regeneration by $s1 per 5 sec. for $d.
- break;
- case CLASS_MAGE:
- case CLASS_WARLOCK:
- triggered_spell_id = 28793; // Increases the friendly target's spell damage and healing by up to $s1 for $d.
- break;
- case CLASS_HUNTER:
- case CLASS_ROGUE:
- triggered_spell_id = 28791; // Increases the friendly target's attack power by $s1 for $d.
- break;
- case CLASS_WARRIOR:
- triggered_spell_id = 28790; // Increases the friendly target's armor
- break;
- default:
- return false;
- }
- break;
- }
- // Seal of Vengeance (damage calc on apply aura)
- case 31801:
- {
- if (effIndex != 0) // effect 1, 2 used by seal unleashing code
- return false;
-
- // At melee attack or Hammer of the Righteous spell damage considered as melee attack
- bool stacker = procSpell ? procSpell->Id == 53595 : true;
- // spells with SPELL_DAMAGE_CLASS_MELEE excluding Judgements
- bool damager = procSpell ? (procSpell->EquippedItemClass != -1 || (procSpell->SpellIconID == 243 && procSpell->SpellVisual[0] == 39)) : false;
-
- if (!stacker && !damager)
- return false;
-
- triggered_spell_id = 31803;
-
- // On target with 5 stacks of Holy Vengeance direct damage is done
- if (Aura* aur = victim->GetAura(triggered_spell_id, GetGUID()))
- {
- if (aur->GetStackAmount() == 5)
- {
- if (stacker)
- aur->RefreshDuration();
- CastSpell(victim, 42463, true);
- return true;
- }
- }
-
- if (!stacker)
- return false;
- break;
- }
- // Seal of Corruption
- case 53736:
- {
- if (effIndex != 0) // effect 1, 2 used by seal unleashing code
- return false;
-
- // At melee attack or Hammer of the Righteous spell damage considered as melee attack
- bool stacker = procSpell ? procSpell->Id == 53595 : true;
- // spells with SPELL_DAMAGE_CLASS_MELEE excluding Judgements
- bool damager = procSpell ? (procSpell->EquippedItemClass != -1 || (procSpell->SpellIconID == 243 && procSpell->SpellVisual[0] == 39)) : false;
-
- if (!stacker && !damager)
- return false;
-
- triggered_spell_id = 53742;
-
- // On target with 5 stacks of Blood Corruption direct damage is done
- if (Aura* aur = victim->GetAura(triggered_spell_id, GetGUID()))
- {
- if (aur->GetStackAmount() == 5)
- {
- if (stacker)
- aur->RefreshDuration();
- CastSpell(victim, 53739, true);
- return true;
- }
- }
-
- if (!stacker)
- return false;
- break;
- }
- // Spiritual Attunement
- case 31785:
- case 33776:
- {
- // if healed by another unit (victim)
- if (this == victim)
- return false;
-
- // heal amount
- basepoints0 = int32(CalculatePct(std::min(damage, GetMaxHealth() - GetHealth()), triggerAmount));
- target = this;
-
- if (basepoints0)
- triggered_spell_id = 31786;
- break;
- }
- // Paladin Tier 6 Trinket (Ashtongue Talisman of Zeal)
- case 40470:
- {
- if (!procSpell)
- return false;
-
- float chance;
-
- // Flash of light/Holy light
- if (procSpell->SpellFamilyFlags[0] & 0xC0000000)
- {
- triggered_spell_id = 40471;
- chance = 15.0f;
- }
- // Judgement (any)
- else if (procSpell->GetSpellSpecific() == SPELL_SPECIFIC_JUDGEMENT)
- {
- triggered_spell_id = 40472;
- chance = 50.0f;
- }
- else
- return false;
-
- if (!roll_chance_f(chance))
- return false;
-
- break;
- }
- // Glyph of Holy Light
- case 54937:
- {
- triggered_spell_id = 54968;
- basepoints0 = CalculatePct(int32(damage), triggerAmount);
- break;
- }
- // Item - Paladin T8 Holy 2P Bonus
- case 64890:
- {
- triggered_spell_id = 64891;
- basepoints0 = triggerAmount * damage / 300;
- break;
- }
- case 71406: // Tiny Abomination in a Jar
- case 71545: // Tiny Abomination in a Jar (Heroic)
- {
- if (!victim || !victim->IsAlive())
- return false;
-
- CastSpell(this, 71432, true, NULL, triggeredByAura);
-
- Aura const* dummy = GetAura(71432);
- if (!dummy || dummy->GetStackAmount() < (dummySpell->Id == 71406 ? 8 : 7))
- return false;
-
- RemoveAurasDueToSpell(71432);
- triggered_spell_id = 71433; // default main hand attack
- // roll if offhand
- if (Player const* player = ToPlayer())
- if (player->GetWeaponForAttack(OFF_ATTACK, true) && urand(0, 1))
- triggered_spell_id = 71434;
- target = victim;
- break;
- }
- // Item - Icecrown 25 Normal Dagger Proc
- case 71880:
- {
- switch (getPowerType())
- {
- case POWER_MANA:
- triggered_spell_id = 71881;
- break;
- case POWER_RAGE:
- triggered_spell_id = 71883;
- break;
- case POWER_ENERGY:
- triggered_spell_id = 71882;
- break;
- case POWER_RUNIC_POWER:
- triggered_spell_id = 71884;
- break;
- default:
- return false;
- }
- break;
- }
- // Item - Icecrown 25 Heroic Dagger Proc
- case 71892:
- {
- switch (getPowerType())
- {
- case POWER_MANA:
- triggered_spell_id = 71888;
- break;
- case POWER_RAGE:
- triggered_spell_id = 71886;
- break;
- case POWER_ENERGY:
- triggered_spell_id = 71887;
- break;
- case POWER_RUNIC_POWER:
- triggered_spell_id = 71885;
- break;
- default:
- return false;
- }
- break;
- }
- }
- break;
- }
- case SPELLFAMILY_SHAMAN:
- {
- switch (dummySpell->Id)
- {
- // Tidal Force
- case 55198:
- {
- // Remove aura stack from caster
- RemoveAuraFromStack(55166);
- // drop charges
- return false;
- }
- // Totemic Power (The Earthshatterer set)
- case 28823:
- {
- if (!victim)
- return false;
-
- // Set class defined buff
- switch (victim->getClass())
- {
- case CLASS_PALADIN:
- case CLASS_PRIEST:
- case CLASS_SHAMAN:
- case CLASS_DRUID:
- triggered_spell_id = 28824; // Increases the friendly target's mana regeneration by $s1 per 5 sec. for $d.
- break;
- case CLASS_MAGE:
- case CLASS_WARLOCK:
- triggered_spell_id = 28825; // Increases the friendly target's spell damage and healing by up to $s1 for $d.
- break;
- case CLASS_HUNTER:
- case CLASS_ROGUE:
- triggered_spell_id = 28826; // Increases the friendly target's attack power by $s1 for $d.
- break;
- case CLASS_WARRIOR:
- triggered_spell_id = 28827; // Increases the friendly target's armor
- break;
- default:
- return false;
- }
- break;
- }
- // Lesser Healing Wave (Totem of Flowing Water Relic)
- case 28849:
- {
- target = this;
- triggered_spell_id = 28850;
- break;
- }
- // Windfury Weapon (Passive) 1-8 Ranks
- case 33757:
- {
- Player* player = ToPlayer();
- if (!player || !castItem || !castItem->IsEquipped() || !victim || !victim->IsAlive())
- return false;
-
- if (triggeredByAura->GetBase() && castItem->GetGUID() != triggeredByAura->GetBase()->GetCastItemGUID())
- return false;
-
- WeaponAttackType attType = WeaponAttackType(player->GetAttackBySlot(castItem->GetSlot()));
- if ((attType != BASE_ATTACK && attType != OFF_ATTACK)
- || (attType == BASE_ATTACK && procFlag & PROC_FLAG_DONE_OFFHAND_ATTACK)
- || (attType == OFF_ATTACK && procFlag & PROC_FLAG_DONE_MAINHAND_ATTACK))
- return false;
-
- // Now compute real proc chance...
- uint32 chance = 20;
- player->ApplySpellMod(dummySpell->Id, SPELLMOD_CHANCE_OF_SUCCESS, chance);
-
- Item* addWeapon = player->GetWeaponForAttack(attType == BASE_ATTACK ? OFF_ATTACK : BASE_ATTACK, true);
- uint32 enchant_id_add = addWeapon ? addWeapon->GetEnchantmentId(EnchantmentSlot(TEMP_ENCHANTMENT_SLOT)) : 0;
- SpellItemEnchantmentEntry const* pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id_add);
- if (pEnchant && pEnchant->spellid[0] == dummySpell->Id)
- chance += 14;
-
- if (!roll_chance_i(chance))
- return false;
-
- // Now amount of extra power stored in 1 effect of Enchant spell
- // Get it by item enchant id
- uint32 spellId;
- switch (castItem->GetEnchantmentId(EnchantmentSlot(TEMP_ENCHANTMENT_SLOT)))
- {
- case 283: spellId = 8232; break; // 1 Rank
- case 284: spellId = 8235; break; // 2 Rank
- case 525: spellId = 10486; break; // 3 Rank
- case 1669:spellId = 16362; break; // 4 Rank
- case 2636:spellId = 25505; break; // 5 Rank
- case 3785:spellId = 58801; break; // 6 Rank
- case 3786:spellId = 58803; break; // 7 Rank
- case 3787:spellId = 58804; break; // 8 Rank
- default:
- {
- TC_LOG_ERROR("entities.unit", "Unit::HandleDummyAuraProc: non handled item enchantment (rank?) %u for spell id: %u (Windfury)",
- castItem->GetEnchantmentId(EnchantmentSlot(TEMP_ENCHANTMENT_SLOT)), dummySpell->Id);
- return false;
- }
- }
-
- SpellInfo const* windfurySpellInfo = sSpellMgr->GetSpellInfo(spellId);
- if (!windfurySpellInfo)
- {
- TC_LOG_ERROR("entities.unit", "Unit::HandleDummyAuraProc: non-existing spell id: %u (Windfury)", spellId);
- return false;
- }
-
- int32 extra_attack_power = CalculateSpellDamage(victim, windfurySpellInfo, 1);
-
- // Value gained from additional AP
- basepoints0 = int32(extra_attack_power / 14.0f * GetAttackTime(attType) / 1000);
-
- if (procFlag & PROC_FLAG_DONE_MAINHAND_ATTACK)
- triggered_spell_id = 25504;
-
- if (procFlag & PROC_FLAG_DONE_OFFHAND_ATTACK)
- triggered_spell_id = 33750;
-
- // apply cooldown before cast to prevent processing itself
- triggeredByAura->GetBase()->AddProcCooldown(std::chrono::steady_clock::now() + cooldown);
- cooldown = Milliseconds::zero();
-
- // Attack Twice
- for (uint32 i = 0; i < 2; ++i)
- CastCustomSpell(victim, triggered_spell_id, &basepoints0, NULL, NULL, true, castItem, triggeredByAura);
-
- return true;
- }
- // Shaman Tier 6 Trinket
- case 40463:
- {
- if (!procSpell)
- return false;
-
- float chance;
- if (procSpell->SpellFamilyFlags[0] & 0x1)
- {
- triggered_spell_id = 40465; // Lightning Bolt
- chance = 15.0f;
- }
- else if (procSpell->SpellFamilyFlags[0] & 0x80)
- {
- triggered_spell_id = 40465; // Lesser Healing Wave
- chance = 10.0f;
- }
- else if (procSpell->SpellFamilyFlags[1] & 0x00000010)
- {
- triggered_spell_id = 40466; // Stormstrike
- chance = 50.0f;
- }
- else
- return false;
-
- if (!roll_chance_f(chance))
- return false;
-
- target = this;
- break;
- }
- // Glyph of Healing Wave
- case 55440:
- {
- // Not proc from self heals
- if (this == victim)
- return false;
- basepoints0 = CalculatePct(int32(damage), triggerAmount);
- target = this;
- triggered_spell_id = 55533;
- break;
- }
- // Spirit Hunt
- case 58877:
- {
- // Cast on owner
- target = GetOwner();
- if (!target)
- return false;
- basepoints0 = CalculatePct(int32(damage), triggerAmount);
- triggered_spell_id = 58879;
- // Cast on spirit wolf
- CastCustomSpell(this, triggered_spell_id, &basepoints0, NULL, NULL, true, NULL, triggeredByAura);
- break;
- }
- // Shaman T8 Elemental 4P Bonus
- case 64928:
- {
- basepoints0 = CalculatePct(int32(damage), triggerAmount);
- triggered_spell_id = 64930; // Electrified
- break;
- }
- // Shaman T9 Elemental 4P Bonus
- case 67228:
- {
- // Lava Burst
- if (procSpell && procSpell->SpellFamilyFlags[1] & 0x1000)
- {
- triggered_spell_id = 71824;
- SpellInfo const* triggeredSpell = sSpellMgr->GetSpellInfo(triggered_spell_id);
- if (!triggeredSpell)
- return false;
- basepoints0 = CalculatePct(int32(damage), triggerAmount) / (triggeredSpell->GetMaxDuration() / triggeredSpell->Effects[0].Amplitude);
- }
- break;
- }
- // Item - Shaman T10 Restoration 4P Bonus
- case 70808:
- {
- // Chain Heal
- if (procSpell && (procSpell->SpellFamilyFlags[0] & 0x100) && (procEx & PROC_EX_CRITICAL_HIT))
- {
- triggered_spell_id = 70809;
- SpellInfo const* triggeredSpell = sSpellMgr->GetSpellInfo(triggered_spell_id);
- if (!triggeredSpell)
- return false;
- basepoints0 = CalculatePct(int32(damage), triggerAmount) / (triggeredSpell->GetMaxDuration() / triggeredSpell->Effects[0].Amplitude);
- // Add remaining ticks to healing done
- basepoints0 += GetRemainingPeriodicAmount(GetGUID(), triggered_spell_id, SPELL_AURA_PERIODIC_HEAL);
- }
- break;
- }
- // Item - Shaman T10 Elemental 4P Bonus
- case 70817:
- {
- if (!target)
- return false;
- // try to find spell Flame Shock on the target
- if (AuraEffect const* aurEff = target->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_SHAMAN, 0x10000000, 0x0, 0x0, GetGUID()))
- {
- Aura* flameShock = aurEff->GetBase();
- int32 maxDuration = flameShock->GetMaxDuration();
- int32 newDuration = flameShock->GetDuration() + 2 * aurEff->GetAmplitude();
-
- flameShock->SetDuration(newDuration);
- // is it blizzlike to change max duration for FS?
- if (newDuration > maxDuration)
- flameShock->SetMaxDuration(newDuration);
-
- return true;
- }
- // if not found Flame Shock
- return false;
- }
- case 63280: // Glyph of Totem of Wrath
- {
- if (!procSpell || procSpell->SpellIconID != 2019)
- return false;
-
- if (Creature* totem = GetMap()->GetCreature(m_SummonSlot[1])) // Fire totem summon slot
- {
- if (SpellInfo const* totemSpell = sSpellMgr->GetSpellInfo(totem->m_spells[0]))
- {
- int32 bp0 = CalculatePct(totemSpell->Effects[EFFECT_0].CalcValue(), triggerAmount);
- int32 bp1 = CalculatePct(totemSpell->Effects[EFFECT_1].CalcValue(), triggerAmount);
- CastCustomSpell(this, 63283, &bp0, &bp1, NULL, true);
- return true;
- }
- }
- return false;
- }
- break;
- }
- // Frozen Power
- if (dummySpell->SpellIconID == 3780)
- {
- if (!target)
- return false;
- if (GetDistance(target) < 15.0f)
- return false;
- float chance = (float)triggerAmount;
- if (!roll_chance_f(chance))
- return false;
-
- triggered_spell_id = 63685;
- break;
- }
- // Ancestral Awakening
- if (dummySpell->SpellIconID == 3065)
- {
- triggered_spell_id = 52759;
- basepoints0 = CalculatePct(int32(damage), triggerAmount);
- target = this;
- break;
- }
- // Flametongue Weapon (Passive)
- if (dummySpell->SpellFamilyFlags[0] & 0x200000)
- {
- if (GetTypeId() != TYPEID_PLAYER || !victim || !victim->IsAlive() || !castItem || !castItem->IsEquipped())
- return false;
-
- WeaponAttackType attType = WeaponAttackType(Player::GetAttackBySlot(castItem->GetSlot()));
- if ((attType != BASE_ATTACK && attType != OFF_ATTACK)
- || (attType == BASE_ATTACK && procFlag & PROC_FLAG_DONE_OFFHAND_ATTACK)
- || (attType == OFF_ATTACK && procFlag & PROC_FLAG_DONE_MAINHAND_ATTACK))
- return false;
-
- float fire_onhit = float(CalculatePct(dummySpell->Effects[EFFECT_0]. CalcValue(), 1.0f));
-
- float add_spellpower = (float)(SpellBaseDamageBonusDone(SPELL_SCHOOL_MASK_FIRE)
- + victim->SpellBaseDamageBonusTaken(SPELL_SCHOOL_MASK_FIRE));
-
- // 1.3speed = 5%, 2.6speed = 10%, 4.0 speed = 15%, so, 1.0speed = 3.84%
- ApplyPct(add_spellpower, 3.84f);
-
- // Enchant on Off-Hand and ready?
- if (castItem->GetSlot() == EQUIPMENT_SLOT_OFFHAND && procFlag & PROC_FLAG_DONE_OFFHAND_ATTACK)
- {
- float BaseWeaponSpeed = GetAttackTime(OFF_ATTACK) / 1000.0f;
-
- // Value1: add the tooltip damage by swingspeed + Value2: add spelldmg by swingspeed
- basepoints0 = int32((fire_onhit * BaseWeaponSpeed) + (add_spellpower * BaseWeaponSpeed));
- triggered_spell_id = 10444;
- }
-
- // Enchant on Main-Hand and ready?
- else if (castItem->GetSlot() == EQUIPMENT_SLOT_MAINHAND && procFlag & PROC_FLAG_DONE_MAINHAND_ATTACK)
- {
- float BaseWeaponSpeed = GetAttackTime(BASE_ATTACK) / 1000.0f;
-
- // Value1: add the tooltip damage by swingspeed + Value2: add spelldmg by swingspeed
- basepoints0 = int32((fire_onhit * BaseWeaponSpeed) + (add_spellpower * BaseWeaponSpeed));
- triggered_spell_id = 10444;
- }
-
- // If not ready, we should return, shouldn't we?!
- else
- return false;
-
- CastCustomSpell(victim, triggered_spell_id, &basepoints0, NULL, NULL, true, castItem, triggeredByAura);
- return true;
- }
- // Improved Water Shield
- if (dummySpell->SpellIconID == 2287)
- {
- // Default chance for Healing Wave and Riptide
- float chance = (float)triggeredByAura->GetAmount();
-
- if (!procSpell)
- return false; //This is the same than putting chance *= 0.0f;
- else if (procSpell->SpellFamilyFlags[0] & 0x80)
- // Lesser Healing Wave - 0.6 of default
- chance *= 0.6f;
- else if (procSpell->SpellFamilyFlags[0] & 0x100)
- // Chain heal - 0.3 of default
- chance *= 0.3f;
-
- if (!roll_chance_f(chance))
- return false;
-
- // Water Shield
- if (AuraEffect const* aurEff = GetAuraEffect(SPELL_AURA_PROC_TRIGGER_SPELL, SPELLFAMILY_SHAMAN, 0, 0x00000020, 0))
- {
- uint32 spell = aurEff->GetSpellInfo()->Effects[aurEff->GetEffIndex()].TriggerSpell;
- CastSpell(this, spell, true, castItem, triggeredByAura);
- return true;
- }
- return false;
- }
- // Lightning Overload
- if (dummySpell->SpellIconID == 2018) // only this spell has SpellFamily Shaman SpellIconID == 2018 and dummy aura
- {
- if (!procSpell || GetTypeId() != TYPEID_PLAYER || !victim)
- return false;
-
- uint32 spellId = 0;
- // Every Lightning Bolt and Chain Lightning spell have duplicate vs half damage and zero cost
- switch (procSpell->Id)
- {
- // Lightning Bolt
- case 403: spellId = 45284; break; // Rank 1
- case 529: spellId = 45286; break; // Rank 2
- case 548: spellId = 45287; break; // Rank 3
- case 915: spellId = 45288; break; // Rank 4
- case 943: spellId = 45289; break; // Rank 5
- case 6041: spellId = 45290; break; // Rank 6
- case 10391: spellId = 45291; break; // Rank 7
- case 10392: spellId = 45292; break; // Rank 8
- case 15207: spellId = 45293; break; // Rank 9
- case 15208: spellId = 45294; break; // Rank 10
- case 25448: spellId = 45295; break; // Rank 11
- case 25449: spellId = 45296; break; // Rank 12
- case 49237: spellId = 49239; break; // Rank 13
- case 49238: spellId = 49240; break; // Rank 14
- // Chain Lightning
- case 421: spellId = 45297; break; // Rank 1
- case 930: spellId = 45298; break; // Rank 2
- case 2860: spellId = 45299; break; // Rank 3
- case 10605: spellId = 45300; break; // Rank 4
- case 25439: spellId = 45301; break; // Rank 5
- case 25442: spellId = 45302; break; // Rank 6
- case 49270: spellId = 49268; break; // Rank 7
- case 49271: spellId = 49269; break; // Rank 8
- default:
- TC_LOG_ERROR("entities.unit", "Unit::HandleDummyAuraProc: non handled spell id: %u (LO)", procSpell->Id);
- return false;
- }
-
- // Chain Lightning
- if (procSpell->SpellFamilyFlags[0] & 0x2)
- {
- // Chain lightning has [LightOverload_Proc_Chance] / [Max_Number_of_Targets] chance to proc of each individual target hit.
- // A maxed LO would have a 33% / 3 = 11% chance to proc of each target.
- // LO chance was already "accounted" at the proc chance roll, now need to divide the chance by [Max_Number_of_Targets]
- float chance = 100.0f / procSpell->Effects[effIndex].ChainTarget;
- if (!roll_chance_f(chance))
- return false;
- }
-
- CastSpell(victim, spellId, true, castItem, triggeredByAura);
- return true;
- }
- // Static Shock
- if (dummySpell->SpellIconID == 3059)
- {
- // Lightning Shield
- if (AuraEffect const* aurEff = GetAuraEffect(SPELL_AURA_PROC_TRIGGER_SPELL, SPELLFAMILY_SHAMAN, 0x400, 0, 0))
- {
- uint32 spell = sSpellMgr->GetSpellWithRank(26364, aurEff->GetSpellInfo()->GetRank());
-
- // custom cooldown processing case
- if (GetTypeId() == TYPEID_PLAYER && GetSpellHistory()->HasCooldown(spell))
- GetSpellHistory()->ResetCooldown(spell);
-
- CastSpell(target, spell, true, castItem, triggeredByAura);
- aurEff->GetBase()->DropCharge();
- return true;
- }
- return false;
- }
- break;
- }
- case SPELLFAMILY_DEATHKNIGHT:
- {
- // Blood-Caked Strike - Blood-Caked Blade
- if (dummySpell->SpellIconID == 138)
- {
- if (!target || !target->IsAlive())
- return false;
-
- triggered_spell_id = dummySpell->Effects[effIndex].TriggerSpell;
- break;
- }
- // Improved Blood Presence
- if (dummySpell->SpellIconID == 2636)
- {
- if (GetTypeId() != TYPEID_PLAYER)
- return false;
- basepoints0 = CalculatePct(int32(damage), triggerAmount);
- break;
- }
- // Butchery
- if (dummySpell->SpellIconID == 2664)
- {
- basepoints0 = triggerAmount;
- triggered_spell_id = 50163;
- target = this;
- break;
- }
- // Dancing Rune Weapon
- if (dummySpell->Id == 49028)
- {
- // 1 dummy aura for dismiss rune blade
- if (effIndex != 1)
- return false;
-
- Unit* pPet = NULL;
- for (ControlList::const_iterator itr = m_Controlled.begin(); itr != m_Controlled.end(); ++itr) // Find Rune Weapon
- if ((*itr)->GetEntry() == 27893)
- {
- pPet = *itr;
- break;
- }
-
- if (pPet && pPet->GetVictim() && damage && procSpell)
- {
- uint32 procDmg = damage / 2;
- pPet->SendSpellNonMeleeDamageLog(pPet->GetVictim(), procSpell->Id, procDmg, procSpell->GetSchoolMask(), 0, 0, false, 0, false);
- pPet->DealDamage(pPet->GetVictim(), procDmg, NULL, SPELL_DIRECT_DAMAGE, procSpell->GetSchoolMask(), procSpell, true);
- break;
- }
- else
- return false;
- }
- // Mark of Blood
- if (dummySpell->Id == 49005)
- {
- /// @todo need more info (cooldowns/PPM)
- triggered_spell_id = 61607;
- break;
- }
- // Unholy Blight
- if (dummySpell->Id == 49194)
- {
- triggered_spell_id = 50536;
- SpellInfo const* unholyBlight = sSpellMgr->GetSpellInfo(triggered_spell_id);
- if (!unholyBlight)
- return false;
-
- basepoints0 = CalculatePct(int32(damage), triggerAmount);
-
- //Glyph of Unholy Blight
- if (AuraEffect* glyph=GetAuraEffect(63332, 0))
- AddPct(basepoints0, glyph->GetAmount());
-
- basepoints0 = basepoints0 / (unholyBlight->GetMaxDuration() / unholyBlight->Effects[0].Amplitude);
- basepoints0 += victim->GetRemainingPeriodicAmount(GetGUID(), triggered_spell_id, SPELL_AURA_PERIODIC_DAMAGE);
- break;
- }
- // Vendetta
- if (dummySpell->SpellFamilyFlags[0] & 0x10000)
- {
- basepoints0 = int32(CountPctFromMaxHealth(triggerAmount));
- triggered_spell_id = 50181;
- target = this;
- break;
- }
- // Necrosis
- if (dummySpell->SpellIconID == 2709)
- {
- basepoints0 = CalculatePct(int32(damage), triggerAmount);
- triggered_spell_id = 51460;
- break;
- }
- // Threat of Thassarian
- if (dummySpell->SpellIconID == 2023)
- {
- // Must Dual Wield
- if (!procSpell || !haveOffhandWeapon())
- return false;
- // Chance as basepoints for dummy aura
- if (!roll_chance_i(triggerAmount))
- return false;
-
- switch (procSpell->Id)
- {
- // Obliterate
- case 49020: triggered_spell_id = 66198; break; // Rank 1
- case 51423: triggered_spell_id = 66972; break; // Rank 2
- case 51424: triggered_spell_id = 66973; break; // Rank 3
- case 51425: triggered_spell_id = 66974; break; // Rank 4
-
- // Frost Strike
- case 49143: triggered_spell_id = 66196; break; // Rank 1
- case 51416: triggered_spell_id = 66958; break; // Rank 2
- case 51417: triggered_spell_id = 66959; break; // Rank 3
- case 51418: triggered_spell_id = 66960; break; // Rank 4
- case 51419: triggered_spell_id = 66961; break; // Rank 5
- case 55268: triggered_spell_id = 66962; break; // Rank 6
-
- // Plague Strike
- case 45462: triggered_spell_id = 66216; break; // Rank 1
- case 49917: triggered_spell_id = 66988; break; // Rank 2
- case 49918: triggered_spell_id = 66989; break; // Rank 3
- case 49919: triggered_spell_id = 66990; break; // Rank 4
- case 49920: triggered_spell_id = 66991; break; // Rank 5
- case 49921: triggered_spell_id = 66992; break; // Rank 6
-
- // Death Strike
- case 49998: triggered_spell_id = 66188; break; // Rank 1
- case 49999: triggered_spell_id = 66950; break; // Rank 2
- case 45463: triggered_spell_id = 66951; break; // Rank 3
- case 49923: triggered_spell_id = 66952; break; // Rank 4
- case 49924: triggered_spell_id = 66953; break; // Rank 5
-
- // Rune Strike
- case 56815: triggered_spell_id = 66217; break; // Rank 1
-
- // Blood Strike
- case 45902: triggered_spell_id = 66215; break; // Rank 1
- case 49926: triggered_spell_id = 66975; break; // Rank 2
- case 49927: triggered_spell_id = 66976; break; // Rank 3
- case 49928: triggered_spell_id = 66977; break; // Rank 4
- case 49929: triggered_spell_id = 66978; break; // Rank 5
- case 49930: triggered_spell_id = 66979; break; // Rank 6
- default:
- return false;
- }
- break;
- }
- // Runic Power Back on Snare/Root
- if (dummySpell->Id == 61257)
- {
- // only for spells and hit/crit (trigger start always) and not start from self cast spells
- if (!procSpell || !(procEx & (PROC_EX_NORMAL_HIT|PROC_EX_CRITICAL_HIT)) || this == victim)
- return false;
- // Need snare or root mechanic
- if (!(procSpell->GetAllEffectsMechanicMask() & ((1<<MECHANIC_ROOT)|(1<<MECHANIC_SNARE))))
- return false;
- triggered_spell_id = 61258;
- target = this;
- break;
- }
- // Wandering Plague
- if (dummySpell->SpellIconID == 1614)
- {
- if (!roll_chance_f(GetUnitCriticalChance(BASE_ATTACK, victim)))
- return false;
- basepoints0 = CalculatePct(int32(damage), triggerAmount);
- triggered_spell_id = 50526;
- break;
- }
- // Sudden Doom
- if (dummySpell->SpellIconID == 1939 && GetTypeId() == TYPEID_PLAYER)
- {
- SpellChainNode const* chain = NULL;
- // get highest rank of the Death Coil spell
- PlayerSpellMap const& sp_list = ToPlayer()->GetSpellMap();
- for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
- {
- // check if shown in spell book
- if (!itr->second->active || itr->second->disabled || itr->second->state == PLAYERSPELL_REMOVED)
- continue;
-
- SpellInfo const* spellProto = sSpellMgr->GetSpellInfo(itr->first);
- if (!spellProto)
- continue;
-
- if (spellProto->SpellFamilyName == SPELLFAMILY_DEATHKNIGHT
- && spellProto->SpellFamilyFlags[0] & 0x2000)
- {
- SpellChainNode const* newChain = sSpellMgr->GetSpellChainNode(itr->first);
-
- // No chain entry or entry lower than found entry
- if (!chain || !newChain || (chain->rank < newChain->rank))
- {
- triggered_spell_id = itr->first;
- chain = newChain;
- }
- else
- continue;
- // Found spell is last in chain - do not need to look more
- // Optimisation for most common case
- if (chain && chain->last->Id == itr->first)
- break;
- }
- }
- }
- break;
- }
- case SPELLFAMILY_POTION:
- {
- // alchemist's stone
- if (procSpell && dummySpell->Id == 17619)
- {
- if (procSpell->SpellFamilyName == SPELLFAMILY_POTION)
- {
- for (uint8 i = 0; i < MAX_SPELL_EFFECTS; i++)
- {
- if (procSpell->Effects[i].Effect == SPELL_EFFECT_HEAL)
- {
- triggered_spell_id = 21399;
- }
- else if (procSpell->Effects[i].Effect == SPELL_EFFECT_ENERGIZE)
- {
- triggered_spell_id = 21400;
- }
- else
- continue;
-
- basepoints0 = int32(CalculateSpellDamage(this, procSpell, i) * 0.4f);
- CastCustomSpell(this, triggered_spell_id, &basepoints0, NULL, NULL, true, NULL, triggeredByAura);
- }
- return true;
- }
- }
- break;
- }
- case SPELLFAMILY_PET:
- {
- switch (dummySpell->SpellIconID)
- {
- // Guard Dog
- case 201:
- {
- if (!victim || !procSpell)
- return false;
-
- triggered_spell_id = 54445;
- target = this;
- float addThreat = float(CalculatePct(procSpell->Effects[0].CalcValue(this), triggerAmount));
- victim->AddThreat(this, addThreat);
- break;
- }
- // Silverback
- case 1582:
- triggered_spell_id = dummySpell->Id == 62765 ? 62801 : 62800;
- target = this;
- break;
- }
- break;
- }
- default:
- break;
- }
-
- // if not handled by custom case, get triggered spell from dummySpell proto
- if (!triggered_spell_id)
- triggered_spell_id = dummySpell->Effects[triggeredByAura->GetEffIndex()].TriggerSpell;
-
- // processed charge only counting case
- if (!triggered_spell_id)
- return true;
-
- SpellInfo const* triggerEntry = sSpellMgr->GetSpellInfo(triggered_spell_id);
- if (!triggerEntry)
- {
- TC_LOG_ERROR("entities.unit", "Unit::HandleDummyAuraProc: Spell %u has non-existing triggered spell %u", dummySpell->Id, triggered_spell_id);
- return false;
- }
-
- if (basepoints0)
- CastCustomSpell(target, triggered_spell_id, &basepoints0, NULL, NULL, true, castItem, triggeredByAura, originalCaster);
- else
- CastSpell(target, triggered_spell_id, true, castItem, triggeredByAura, originalCaster);
-
- return true;
-}
-
-// Used in case when access to whole aura is needed
-// All procs should be handled like this...
-bool Unit::HandleAuraProc(Unit* victim, uint32 damage, Aura* triggeredByAura, SpellInfo const* procSpell, uint32 /*procFlag*/, uint32 procEx, bool* handled)
-{
- SpellInfo const* dummySpell = triggeredByAura->GetSpellInfo();
-
- switch (dummySpell->SpellFamilyName)
- {
- case SPELLFAMILY_GENERIC:
- switch (dummySpell->Id)
- {
- // Nevermelting Ice Crystal
- case 71564:
- RemoveAuraFromStack(71564);
- *handled = true;
- break;
- // Gaseous Bloat
- case 70672:
- case 72455:
- case 72832:
- case 72833:
- {
- *handled = true;
- uint32 stack = triggeredByAura->GetStackAmount();
- int32 const mod = (GetMap()->GetSpawnMode() & 1) ? 1500 : 1250;
- int32 dmg = 0;
- for (uint8 i = 1; i <= stack; ++i)
- dmg += mod * i;
- if (Unit* caster = triggeredByAura->GetCaster())
- caster->CastCustomSpell(70701, SPELLVALUE_BASE_POINT0, dmg);
- break;
- }
- // Ball of Flames Proc
- case 71756:
- case 72782:
- case 72783:
- case 72784:
- RemoveAuraFromStack(dummySpell->Id);
- *handled = true;
- break;
- // Discerning Eye of the Beast
- case 59915:
- {
- CastSpell(this, 59914, true); // 59914 already has correct basepoints in DBC, no need for custom bp
- *handled = true;
- break;
- }
- // Swift Hand of Justice
- case 59906:
- {
- int32 bp0 = CalculatePct(GetMaxHealth(), dummySpell->Effects[EFFECT_0]. CalcValue());
- CastCustomSpell(this, 59913, &bp0, NULL, NULL, true);
- *handled = true;
- break;
- }
- }
-
- break;
- case SPELLFAMILY_PALADIN:
- {
- // Infusion of Light
- if (procSpell && dummySpell->SpellIconID == 3021)
- {
- // Flash of Light HoT on Flash of Light when Sacred Shield active
- if (procSpell->SpellFamilyFlags[0] & 0x40000000 && procSpell->SpellIconID == 242)
- {
- *handled = true;
- if (victim && victim->HasAura(53601))
- {
- int32 bp0 = CalculatePct(int32(damage / 12), dummySpell->Effects[EFFECT_2].CalcValue());
- // Item - Paladin T9 Holy 4P Bonus
- if (AuraEffect const* aurEff = GetAuraEffect(67191, 0))
- AddPct(bp0, aurEff->GetAmount());
- CastCustomSpell(victim, 66922, &bp0, NULL, NULL, true);
- return true;
- }
- }
- // but should not proc on non-critical Holy Shocks
- else if ((procSpell->SpellFamilyFlags[0] & 0x200000 || procSpell->SpellFamilyFlags[1] & 0x10000) && !(procEx & PROC_EX_CRITICAL_HIT))
- *handled = true;
- break;
- }
- // Judgements of the Just
- else if (dummySpell->SpellIconID == 3015)
- {
- *handled = true;
- CastSpell(victim, 68055, true);
- return true;
- }
- // Glyph of Divinity
- else if (dummySpell->Id == 54939)
- {
- if (!procSpell)
- return false;
- *handled = true;
- // Check if we are the target and prevent mana gain
- if (victim && triggeredByAura->GetCasterGUID() == victim->GetGUID())
- return false;
- // Lookup base amount mana restore
- for (uint8 i = 0; i < MAX_SPELL_EFFECTS; i++)
- {
- if (procSpell->Effects[i].Effect == SPELL_EFFECT_ENERGIZE)
- {
- // value multiplied by 2 because you should get twice amount
- int32 mana = procSpell->Effects[i].CalcValue() * 2;
- CastCustomSpell(this, 54986, 0, &mana, NULL, true);
- }
- }
- return true;
- }
- break;
- }
- case SPELLFAMILY_MAGE:
- {
- // Combustion
- switch (dummySpell->Id)
- {
- case 11129:
- {
- *handled = true;
- Unit* caster = triggeredByAura->GetCaster();
- if (!caster || !damage)
- return false;
-
- // last charge and crit
- if (triggeredByAura->GetCharges() <= 1 && (procEx & PROC_EX_CRITICAL_HIT))
- return true; // charge counting (will removed)
-
- CastSpell(this, 28682, true);
-
- return (procEx & PROC_EX_CRITICAL_HIT) != 0;
- }
- // Empowered Fire
- case 31656:
- case 31657:
- case 31658:
- {
- *handled = true;
-
- SpellInfo const* spInfo = sSpellMgr->GetSpellInfo(67545);
- if (!spInfo)
- return false;
-
- int32 bp0 = int32(CalculatePct(GetCreateMana(), spInfo->Effects[0].CalcValue()));
- CastCustomSpell(this, 67545, &bp0, NULL, NULL, true, NULL, triggeredByAura->GetEffect(EFFECT_0), GetGUID());
- return true;
- }
- case 44401: //Missile Barrage
- case 48108: //Hot Streak
- case 57761: //Fireball!
- {
- *handled = true;
-
- // Prevent double proc for Arcane missiles
- if (this == victim)
- return false;
-
- if (HasAura(70752)) // Item - Mage T10 2P Bonus
- CastSpell((Unit*)nullptr, 70753, true);
-
- // Proc chance is unknown, we'll just use dummy aura amount
- if (AuraEffect const* aurEff = GetAuraEffect(64869, EFFECT_0)) // Item - Mage T8 4P Bonus
- if (roll_chance_i(aurEff->GetAmount())) // do not proc charges
- return false;
-
- // @workaround: We'll take care of removing the aura on next update tick
- // This is needed for 44401 to affect Arcane Missiles, else the spellmod will not be applied
- // it only works because EventProcessor will always update first scheduled event,
- // as cast is already in progress the SpellEvent for Arcane Missiles is already in queue.
- triggeredByAura->DropChargeDelayed(1);
- return false;
- }
- }
- break;
- }
- case SPELLFAMILY_DEATHKNIGHT:
- {
- // Blood of the North
- // Reaping
- // Death Rune Mastery
- /// @todo move those to spell scripts
- if (dummySpell->SpellIconID == 3041 || (dummySpell->SpellIconID == 22 && dummySpell->Id != 62459) || dummySpell->SpellIconID == 2622)
- {
- *handled = true;
- // Convert recently used Blood Rune to Death Rune
- if (Player* player = ToPlayer())
- {
- if (player->getClass() != CLASS_DEATH_KNIGHT)
- return false;
-
- RuneType rune = ToPlayer()->GetLastUsedRune();
- // can't proc from death rune use
- if (rune == RUNE_DEATH)
- return false;
- AuraEffect* aurEff = triggeredByAura->GetEffect(EFFECT_0);
- if (!aurEff)
- return false;
-
- // Reset amplitude - set death rune remove timer to 30s
- aurEff->ResetPeriodic(true);
- uint32 runesLeft;
-
- if (dummySpell->SpellIconID == 2622)
- runesLeft = 2;
- else
- runesLeft = 1;
-
- for (uint8 i = 0; i < MAX_RUNES && runesLeft; ++i)
- {
- if (dummySpell->SpellIconID == 2622)
- {
- if (player->GetCurrentRune(i) == RUNE_DEATH ||
- player->GetBaseRune(i) == RUNE_BLOOD)
- continue;
- }
- else
- {
- if (player->GetCurrentRune(i) == RUNE_DEATH ||
- player->GetBaseRune(i) != RUNE_BLOOD)
- continue;
- }
- if (player->GetRuneCooldown(i) != (player->GetRuneBaseCooldown(i) - player->GetLastRuneGraceTimer(i)))
- continue;
-
- --runesLeft;
- // Mark aura as used
- player->AddRuneByAuraEffect(i, RUNE_DEATH, aurEff);
- }
- return true;
- }
- return false;
- }
-
- switch (dummySpell->Id)
- {
- // Bone Shield cooldown
- case 49222:
- {
- *handled = true;
- return true;
- }
- // Hungering Cold aura drop
- case 51209:
- *handled = true;
- // Drop only in not disease case
- if (procSpell && procSpell->Dispel == DISPEL_DISEASE)
- return false;
- return true;
- }
- break;
- }
- case SPELLFAMILY_WARRIOR:
- {
- switch (dummySpell->Id)
- {
- // Item - Warrior T10 Protection 4P Bonus
- case 70844:
- {
- int32 basepoints0 = CalculatePct(GetMaxHealth(), dummySpell->Effects[EFFECT_1]. CalcValue());
- CastCustomSpell(this, 70845, &basepoints0, NULL, NULL, true);
- break;
- }
- // Recklessness
- case 1719:
- {
- //! Possible hack alert
- //! Don't drop charges on proc, they will be dropped on SpellMod removal
- //! Before this change, it was dropping two charges per attack, one in ProcDamageAndSpellFor, and one in RemoveSpellMods.
- //! The reason of this behaviour is Recklessness having three auras, 2 of them can not proc (isTriggeredAura array) but the other one can, making the whole spell proc.
- *handled = true;
- break;
- }
- default:
- break;
- }
- break;
- }
- }
- return false;
-}
-
-bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx)
-{
- // Get triggered aura spell info
- SpellInfo const* auraSpellInfo = triggeredByAura->GetSpellInfo();
-
- // Basepoints of trigger aura
- int32 triggerAmount = triggeredByAura->GetAmount();
-
- // Set trigger spell id, target, custom basepoints
- uint32 trigger_spell_id = auraSpellInfo->Effects[triggeredByAura->GetEffIndex()].TriggerSpell;
-
- Unit* target = NULL;
- int32 basepoints0 = 0;
-
- if (triggeredByAura->GetAuraType() == SPELL_AURA_PROC_TRIGGER_SPELL_WITH_VALUE)
- basepoints0 = triggerAmount;
-
- Item* castItem = triggeredByAura->GetBase()->GetCastItemGUID() && GetTypeId() == TYPEID_PLAYER
- ? ToPlayer()->GetItemByGuid(triggeredByAura->GetBase()->GetCastItemGUID()) : NULL;
-
- // Try handle unknown trigger spells
- // triggered spells exists only in serverside spell_dbc
- /// @todo: reverify and move these spells to spellscripts
- {
- switch (auraSpellInfo->SpellFamilyName)
- {
- case SPELLFAMILY_WARLOCK:
- {
- // Drain Soul
- if (auraSpellInfo->SpellFamilyFlags[0] & 0x4000)
- {
- // Improved Drain Soul
- Unit::AuraEffectList const& mAddFlatModifier = GetAuraEffectsByType(SPELL_AURA_DUMMY);
- for (Unit::AuraEffectList::const_iterator i = mAddFlatModifier.begin(); i != mAddFlatModifier.end(); ++i)
- {
- if ((*i)->GetMiscValue() == SPELLMOD_CHANCE_OF_SUCCESS && (*i)->GetSpellInfo()->SpellIconID == 113)
- {
- int32 value2 = CalculateSpellDamage(this, (*i)->GetSpellInfo(), 2);
- basepoints0 = int32(CalculatePct(GetMaxPower(POWER_MANA), value2));
- // Drain Soul
- CastCustomSpell(this, 18371, &basepoints0, NULL, NULL, true, castItem, triggeredByAura);
- break;
- }
- }
- // Not remove charge (aura removed on death in any cases)
- // Need for correct work Drain Soul SPELL_AURA_CHANNEL_DEATH_ITEM aura
- return false;
- }
- }
- default:
- break;
- }
- }
-
- // All ok. Check current trigger spell
- SpellInfo const* triggerEntry = sSpellMgr->GetSpellInfo(trigger_spell_id);
- if (triggerEntry == NULL)
- {
- // Don't cast unknown spell
- TC_LOG_ERROR("entities.unit.handleproctriggerspell", "Unit::HandleProcTriggerSpell: Spell %u (effIndex: %u) has unknown TriggerSpell %u. Unhandled custom case?", auraSpellInfo->Id, triggeredByAura->GetEffIndex(), trigger_spell_id);
- return false;
- }
-
- // not allow proc extra attack spell at extra attack
- if (m_extraAttacks && triggerEntry->HasEffect(SPELL_EFFECT_ADD_EXTRA_ATTACKS))
- return false;
-
- // Custom requirements (not listed in procEx) Warning! damage dealing after this
- // Custom triggered spells
- switch (auraSpellInfo->Id)
- {
- // Deep Wounds
- case 12834:
- case 12849:
- case 12867:
- {
- if (GetTypeId() != TYPEID_PLAYER)
- return false;
-
- float averageDmg = 0;
- // now compute approximate weapon damage by formula from wowwiki.com
- if (procFlag & PROC_FLAG_DONE_OFFHAND_ATTACK)
- averageDmg = (GetFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE) + GetFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE)) / 2.f;
- else
- averageDmg = (GetFloatValue(UNIT_FIELD_MINDAMAGE) + GetFloatValue(UNIT_FIELD_MAXDAMAGE)) / 2.f;
-
- basepoints0 = int32(averageDmg);
- break;
- }
- // Persistent Shield (Scarab Brooch trinket)
- // This spell originally trigger 13567 - Dummy Trigger (vs dummy efect)
- case 26467:
- {
- basepoints0 = int32(CalculatePct(damage, 15));
- target = victim;
- trigger_spell_id = 26470;
- break;
- }
- // Unyielding Knights (item exploit 29108\29109)
- case 38164:
- {
- if (!victim || victim->GetEntry() != 19457) // Proc only if your target is Grillok
- return false;
- break;
- }
- // Deflection
- case 52420:
- {
- if (!HealthBelowPct(35))
- return false;
- break;
- }
-
- // Cheat Death
- case 28845:
- {
- // When your health drops below 20%
- if (HealthBelowPctDamaged(20, damage) || HealthBelowPct(20))
- return false;
- break;
- }
- // Deadly Swiftness (Rank 1)
- case 31255:
- {
- // whenever you deal damage to a target who is below 20% health.
- if (!victim || !victim->IsAlive() || victim->HealthAbovePct(20))
- return false;
-
- target = this;
- trigger_spell_id = 22588;
- }
- // Greater Heal Refund (Avatar Raiment set)
- case 37594:
- {
- if (!victim || !victim->IsAlive())
- return false;
-
- // Doesn't proc if target already has full health
- if (victim->IsFullHealth())
- return false;
- // If your Greater Heal brings the target to full health, you gain $37595s1 mana.
- if (victim->GetHealth() + damage < victim->GetMaxHealth())
- return false;
- break;
- }
- // Bonus Healing (Crystal Spire of Karabor mace)
- case 40971:
- {
- // If your target is below $s1% health
- if (!victim || !victim->IsAlive() || victim->HealthAbovePct(triggerAmount))
- return false;
- break;
- }
- // Rapid Recuperation
- case 53228:
- case 53232:
- {
- // This effect only from Rapid Fire (ability cast)
- if (!procSpell || !(procSpell->SpellFamilyFlags[0] & 0x20))
- return false;
- break;
- }
- // Decimation
- case 63156:
- case 63158:
- // Can proc only if target has hp below 35%
- if (!victim || !victim->HasAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, procSpell, this))
- return false;
- break;
- // Deathbringer Saurfang - Blood Beast's Blood Link
- case 72176:
- basepoints0 = 3;
- break;
- case 15337: // Improved Spirit Tap (Rank 1)
- case 15338: // Improved Spirit Tap (Rank 2)
- {
- if (!procSpell)
- return false;
-
- if (procSpell->SpellFamilyFlags[0] & 0x800000)
- if ((procSpell->Id != 58381) || !roll_chance_i(50))
- return false;
-
- target = victim;
- break;
- }
- // Professor Putricide - Ooze Spell Tank Protection
- case 71770:
- if (victim)
- victim->CastSpell(victim, trigger_spell_id, true); // EffectImplicitTarget is self
- return true;
- case 45057: // Evasive Maneuvers (Commendation of Kael`thas trinket)
- case 71634: // Item - Icecrown 25 Normal Tank Trinket 1
- case 71640: // Item - Icecrown 25 Heroic Tank Trinket 1
- case 75475: // Item - Chamber of Aspects 25 Normal Tank Trinket
- case 75481: // Item - Chamber of Aspects 25 Heroic Tank Trinket
- {
- // Procs only if damage takes health below $s1%
- if (!HealthBelowPctDamaged(triggerAmount, damage))
- return false;
- break;
- }
- default:
- break;
- }
-
- // Blade Barrier
- if (auraSpellInfo->SpellFamilyName == SPELLFAMILY_DEATHKNIGHT && auraSpellInfo->SpellIconID == 85 && procSpell)
- {
- Player* player = ToPlayer();
- if (!player || player->getClass() != CLASS_DEATH_KNIGHT)
- return false;
-
- if (!player->IsBaseRuneSlotsOnCooldown(RUNE_BLOOD))
- return false;
- }
-
- // Rime
- else if (auraSpellInfo->SpellFamilyName == SPELLFAMILY_DEATHKNIGHT && auraSpellInfo->SpellIconID == 56)
- {
- if (GetTypeId() != TYPEID_PLAYER)
- return false;
-
- // Howling Blast
- GetSpellHistory()->ResetCooldowns([](SpellHistory::CooldownStorageType::iterator itr) -> bool
- {
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(itr->first);
- return spellInfo && spellInfo->GetCategory() == 1248;
- }, true);
- }
-
- // Custom basepoints/target for exist spell
- // dummy basepoints or other customs
- switch (trigger_spell_id)
- {
- // Auras which should proc on area aura source (caster in this case):
- // Turn the Tables
- case 52914:
- case 52915:
- case 52910:
- {
- target = triggeredByAura->GetBase()->GetCaster();
- if (!target)
- return false;
-
- target->CastSpell(target, trigger_spell_id, true, castItem, triggeredByAura);
- return true;
- }
- // Cast positive spell on enemy target
- case 7099: // Curse of Mending
- case 39703: // Curse of Mending
- case 29494: // Temptation
- case 20233: // Improved Lay on Hands (cast on target)
- {
- target = victim;
- break;
- }
- // Combo points add triggers (need add combopoint only for main target, and after possible combopoints reset)
- case 15250: // Rogue Setup
- {
- // applied only for main target
- if (!victim || (GetTypeId() == TYPEID_PLAYER && victim != ToPlayer()->GetSelectedUnit()))
- return false;
- break; // continue normal case
- }
- // Finish movies that add combo
- case 14189: // Seal Fate (Netherblade set)
- case 14157: // Ruthlessness
- {
- if (!victim || victim == this)
- return false;
- // Need add combopoint AFTER finish movie (or they dropped in finish phase)
- break;
- }
- // Item - Druid T10 Balance 2P Bonus
- case 16870:
- {
- if (HasAura(70718))
- CastSpell(this, 70721, true);
- break;
- }
- // Shamanistic Rage triggered spell
- case 30824:
- {
- basepoints0 = int32(CalculatePct(GetTotalAttackPowerValue(BASE_ATTACK), triggerAmount));
- break;
- }
- // Enlightenment (trigger only from mana cost spells)
- case 35095:
- {
- if (!procSpell || procSpell->PowerType != POWER_MANA || (procSpell->ManaCost == 0 && procSpell->ManaCostPercentage == 0 && procSpell->ManaCostPerlevel == 0))
- return false;
- break;
- }
- // Demonic Pact
- case 48090:
- {
- // Get talent aura from owner
- if (IsPet())
- if (Unit* owner = GetOwner())
- {
- if (AuraEffect* aurEff = owner->GetDummyAuraEffect(SPELLFAMILY_WARLOCK, 3220, 0))
- {
- basepoints0 = int32((aurEff->GetAmount() * owner->SpellBaseDamageBonusDone(SpellSchoolMask(SPELL_SCHOOL_MASK_MAGIC)) + 100.0f) / 100.0f); /// @todo Is it right?
- CastCustomSpell(this, trigger_spell_id, &basepoints0, &basepoints0, NULL, true, castItem, triggeredByAura);
- return true;
- }
- }
- break;
- }
- case 46916: // Slam! (Bloodsurge proc)
- case 52437: // Sudden Death
- {
- // Item - Warrior T10 Melee 4P Bonus
- if (AuraEffect const* aurEff = GetAuraEffect(70847, 0))
- {
- if (!roll_chance_i(aurEff->GetAmount()))
- break;
- CastSpell(this, 70849, true, castItem, triggeredByAura); // Extra Charge!
- CastSpell(this, 71072, true, castItem, triggeredByAura); // Slam GCD Reduced
- CastSpell(this, 71069, true, castItem, triggeredByAura); // Execute GCD Reduced
- }
- break;
- }
- // Sword and Board
- case 50227:
- {
- // Remove cooldown on Shield Slam
- GetSpellHistory()->ResetCooldowns([](SpellHistory::CooldownStorageType::iterator itr) -> bool
- {
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(itr->first);
- return spellInfo && spellInfo->GetCategory() == 1209;
- }, true);
- break;
- }
- // Maelstrom Weapon
- case 53817:
- {
- // has rank dependant proc chance, ignore too often cases
- // PPM = 2.5 * (rank of talent),
- uint32 rank = auraSpellInfo->GetRank();
- // 5 rank -> 100% 4 rank -> 80% and etc from full rate
- if (!roll_chance_i(20*rank))
- return false;
- // Item - Shaman T10 Enhancement 4P Bonus
- if (AuraEffect const* aurEff = GetAuraEffect(70832, 0))
- if (Aura const* maelstrom = GetAura(53817))
- if ((maelstrom->GetStackAmount() == maelstrom->GetSpellInfo()->StackAmount) && roll_chance_i(aurEff->GetAmount()))
- CastSpell(this, 70831, true, castItem, triggeredByAura);
- break;
- }
- // Astral Shift
- case 52179:
- {
- if (!procSpell || !(procEx & (PROC_EX_NORMAL_HIT|PROC_EX_CRITICAL_HIT)) || this == victim)
- return false;
-
- // Need stun, fear or silence mechanic
- if (!(procSpell->GetAllEffectsMechanicMask() & ((1<<MECHANIC_SILENCE)|(1<<MECHANIC_STUN)|(1<<MECHANIC_FEAR))))
- return false;
- break;
- }
- // Burning Determination
- case 54748:
- {
- if (!procSpell)
- return false;
- // Need Interrupt or Silenced mechanic
- if (!(procSpell->GetAllEffectsMechanicMask() & ((1<<MECHANIC_INTERRUPT)|(1<<MECHANIC_SILENCE))))
- return false;
- break;
- }
- // Glyph of Death's Embrace
- case 58679:
- {
- // Proc only from healing part of Death Coil. Check is essential as all Death Coil spells have 0x2000 mask in SpellFamilyFlags
- if (!procSpell || !(procSpell->SpellFamilyName == SPELLFAMILY_DEATHKNIGHT && procSpell->SpellFamilyFlags[0] == 0x80002000))
- return false;
- break;
- }
- // Glyph of Death Grip
- case 58628:
- {
- // remove cooldown of Death Grip
- GetSpellHistory()->ResetCooldown(49576, true);
- return true;
- }
- // Savage Defense
- case 62606:
- {
- basepoints0 = CalculatePct(triggerAmount, GetTotalAttackPowerValue(BASE_ATTACK));
- break;
- }
- // Body and Soul
- case 64128:
- case 65081:
- {
- // Proc only from PW:S cast
- if (!procSpell || !(procSpell->SpellFamilyFlags[0] & 0x00000001))
- return false;
- break;
- }
- // Culling the Herd
- case 70893:
- {
- if (!procSpell)
- return false;
- // check if we're doing a critical hit
- if (!(procSpell->SpellFamilyFlags[1] & 0x10000000) && (procEx != PROC_EX_CRITICAL_HIT))
- return false;
- // check if we're procced by Claw, Bite or Smack (need to use the spell icon ID to detect it)
- if (!(procSpell->SpellIconID == 262 || procSpell->SpellIconID == 1680 || procSpell->SpellIconID == 473))
- return false;
- break;
- }
- }
-
- // extra attack should hit same target
- if (triggerEntry->HasEffect(SPELL_EFFECT_ADD_EXTRA_ATTACKS))
- target = victim;
-
- // try detect target manually if not set
- if (target == NULL)
- target = !(procFlag & (PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_POS | PROC_FLAG_DONE_SPELL_NONE_DMG_CLASS_POS)) && triggerEntry->IsPositive() ? this : victim;
-
- if (basepoints0)
- CastCustomSpell(target, trigger_spell_id, &basepoints0, NULL, NULL, true, castItem, triggeredByAura);
- else
- CastSpell(target, trigger_spell_id, true, castItem, triggeredByAura);
-
- return true;
-}
-
-bool Unit::HandleOverrideClassScriptAuraProc(Unit* victim, uint32 /*damage*/, AuraEffect* triggeredByAura, SpellInfo const* procSpell)
-{
- int32 scriptId = triggeredByAura->GetMiscValue();
-
- if (!victim || !victim->IsAlive())
- return false;
-
- Item* castItem = triggeredByAura->GetBase()->GetCastItemGUID() && GetTypeId() == TYPEID_PLAYER
- ? ToPlayer()->GetItemByGuid(triggeredByAura->GetBase()->GetCastItemGUID()) : NULL;
-
- uint32 triggered_spell_id = 0;
-
- switch (scriptId)
- {
- case 836: // Improved Blizzard (Rank 1)
- {
- if (!procSpell || procSpell->SpellVisual[0] != 9487)
- return false;
- triggered_spell_id = 12484;
- break;
- }
- case 988: // Improved Blizzard (Rank 2)
- {
- if (!procSpell || procSpell->SpellVisual[0] != 9487)
- return false;
- triggered_spell_id = 12485;
- break;
- }
- case 989: // Improved Blizzard (Rank 3)
- {
- if (!procSpell || procSpell->SpellVisual[0] != 9487)
- return false;
- triggered_spell_id = 12486;
- break;
- }
- case 4533: // Dreamwalker Raiment 2 pieces bonus
- {
- // Chance 50%
- if (!roll_chance_i(50))
- return false;
-
- switch (victim->getPowerType())
- {
- case POWER_MANA: triggered_spell_id = 28722; break;
- case POWER_RAGE: triggered_spell_id = 28723; break;
- case POWER_ENERGY: triggered_spell_id = 28724; break;
- default:
- return false;
- }
- break;
- }
- case 4537: // Dreamwalker Raiment 6 pieces bonus
- triggered_spell_id = 28750; // Blessing of the Claw
- break;
- case 5497: // Improved Mana Gems
- triggered_spell_id = 37445; // Mana Surge
- break;
- case 7010: // Revitalize - can proc on full hp target
- case 7011:
- case 7012:
- {
- if (!roll_chance_i(triggeredByAura->GetAmount()))
- return false;
- switch (victim->getPowerType())
- {
- case POWER_MANA: triggered_spell_id = 48542; break;
- case POWER_RAGE: triggered_spell_id = 48541; break;
- case POWER_ENERGY: triggered_spell_id = 48540; break;
- case POWER_RUNIC_POWER: triggered_spell_id = 48543; break;
- default:
- break;
- }
- break;
- }
- default:
- break;
- }
-
- // not processed
- if (!triggered_spell_id)
- return false;
-
- // standard non-dummy case
- SpellInfo const* triggerEntry = sSpellMgr->GetSpellInfo(triggered_spell_id);
-
- if (!triggerEntry)
- {
- TC_LOG_ERROR("entities.unit", "Unit::HandleOverrideClassScriptAuraProc: Spell %u triggering for class script id %u", triggered_spell_id, scriptId);
- return false;
- }
-
- CastSpell(victim, triggered_spell_id, true, castItem, triggeredByAura);
- return true;
-}
-
void Unit::setPowerType(Powers new_powertype)
{
if (getPowerType() == new_powertype)
@@ -8863,9 +5885,9 @@ uint32 Unit::BuildAuraStateUpdateForTarget(Unit* target) const
{
uint32 auraStates = GetUInt32Value(UNIT_FIELD_AURASTATE) &~(PER_CASTER_AURA_STATE_MASK);
for (AuraStateAurasMap::const_iterator itr = m_auraStateAuras.begin(); itr != m_auraStateAuras.end(); ++itr)
- if ((1<<(itr->first-1)) & PER_CASTER_AURA_STATE_MASK)
+ if ((1 << (itr->first - 1)) & PER_CASTER_AURA_STATE_MASK)
if (itr->second->GetBase()->GetCasterGUID() == target->GetGUID())
- auraStates |= (1<<(itr->first-1));
+ auraStates |= (1 << (itr->first - 1));
return auraStates;
}
@@ -8877,13 +5899,14 @@ bool Unit::HasAuraState(AuraStateType flag, SpellInfo const* spellProto, Unit co
if (spellProto)
{
AuraEffectList const& stateAuras = Caster->GetAuraEffectsByType(SPELL_AURA_ABILITY_IGNORE_AURASTATE);
- for (AuraEffectList::const_iterator j = stateAuras.begin(); j != stateAuras.end(); ++j)
- if ((*j)->IsAffectedOnSpell(spellProto))
+ for (AuraEffect const* aurEff : stateAuras)
+ if (aurEff->IsAffectedOnSpell(spellProto))
return true;
}
+
// Check per caster aura state
// If aura with aurastate by caster not found return false
- if ((1<<(flag-1)) & PER_CASTER_AURA_STATE_MASK)
+ if ((1 << (flag - 1)) & PER_CASTER_AURA_STATE_MASK)
{
AuraStateAurasMapBounds range = m_auraStateAuras.equal_range(flag);
for (AuraStateAurasMap::const_iterator itr = range.first; itr != range.second; ++itr)
@@ -8893,7 +5916,7 @@ bool Unit::HasAuraState(AuraStateType flag, SpellInfo const* spellProto, Unit co
}
}
- return HasFlag(UNIT_FIELD_AURASTATE, 1<<(flag-1));
+ return HasFlag(UNIT_FIELD_AURASTATE, 1 << (flag - 1));
}
void Unit::SetOwnerGUID(ObjectGuid owner)
@@ -9267,9 +6290,11 @@ void Unit::SetCharm(Unit* charm, bool apply)
}
}
-int32 Unit::DealHeal(Unit* victim, uint32 addhealth)
+void Unit::DealHeal(HealInfo& healInfo)
{
int32 gain = 0;
+ Unit* victim = healInfo.GetTarget();
+ uint32 addhealth = healInfo.GetHeal();
if (victim->IsAIEnabled)
victim->GetAI()->HealReceived(this, addhealth);
@@ -9306,7 +6331,8 @@ int32 Unit::DealHeal(Unit* victim, uint32 addhealth)
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEALING_RECEIVED, addhealth);
}
- return gain;
+ if (gain)
+ healInfo.SetEffectiveHeal(gain > 0 ? static_cast<uint32>(gain) : 0UL);
}
bool Unit::IsMagnet() const
@@ -9519,30 +6545,29 @@ void Unit::UnsummonAllTotems()
}
}
-void Unit::SendHealSpellLog(Unit* victim, uint32 SpellID, uint32 Damage, uint32 OverHeal, uint32 Absorb, bool critical)
+void Unit::SendHealSpellLog(HealInfo& healInfo, bool critical /*= false*/)
{
// we guess size
WorldPacket data(SMSG_SPELLHEALLOG, 8 + 8 + 4 + 4 + 4 + 4 + 1 + 1);
- data << victim->GetPackGUID();
+ data << healInfo.GetTarget()->GetPackGUID();
data << GetPackGUID();
- data << uint32(SpellID);
- data << uint32(Damage);
- data << uint32(OverHeal);
- data << uint32(Absorb); // Absorb amount
+ data << uint32(healInfo.GetSpellInfo()->Id);
+ data << uint32(healInfo.GetHeal());
+ data << uint32(healInfo.GetHeal() - healInfo.GetEffectiveHeal());
+ data << uint32(healInfo.GetAbsorb()); // Absorb amount
data << uint8(critical ? 1 : 0);
data << uint8(0); // unused
SendMessageToSet(&data, true);
}
-int32 Unit::HealBySpell(Unit* victim, SpellInfo const* spellInfo, uint32 addHealth, bool critical)
+int32 Unit::HealBySpell(HealInfo& healInfo, bool critical /*= false*/)
{
- uint32 absorb = 0;
// calculate heal absorb and reduce healing
- CalcHealAbsorb(victim, spellInfo, addHealth, absorb);
+ CalcHealAbsorb(healInfo);
- int32 gain = DealHeal(victim, addHealth);
- SendHealSpellLog(victim, spellInfo->Id, addHealth, uint32(addHealth - gain), absorb, critical);
- return gain;
+ DealHeal(healInfo);
+ SendHealSpellLog(healInfo, critical);
+ return healInfo.GetEffectiveHeal();
}
void Unit::SendEnergizeSpellLog(Unit* victim, uint32 spellId, int32 damage, Powers powerType)
@@ -9682,7 +6707,7 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin
if (Player* modOwner = GetSpellModOwner())
{
coeff *= 100.0f;
- modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_BONUS_MULTIPLIER, coeff);
+ modOwner->ApplySpellMod<SPELLMOD_BONUS_MULTIPLIER>(spellProto->Id, coeff);
coeff /= 100.0f;
}
DoneTotal += int32(DoneAdvertisedBenefit * coeff * factorMod);
@@ -9692,7 +6717,12 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin
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);
+ {
+ if (damagetype == DOT)
+ modOwner->ApplySpellMod<SPELLMOD_DOT>(spellProto->Id, tmpDamage);
+ else
+ modOwner->ApplySpellMod<SPELLMOD_DAMAGE>(spellProto->Id, tmpDamage);
+ }
return uint32(std::max(tmpDamage, 0.0f));
}
@@ -10081,7 +7111,7 @@ uint32 Unit::SpellDamageBonusTaken(Unit* caster, SpellInfo const* spellProto, ui
if (Player* modOwner = GetSpellModOwner())
{
coeff *= 100.0f;
- modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_BONUS_MULTIPLIER, coeff);
+ modOwner->ApplySpellMod<SPELLMOD_BONUS_MULTIPLIER>(spellProto->Id, coeff);
coeff /= 100.0f;
}
TakenTotal += int32(TakenAdvertisedBenefit * coeff * factorMod);
@@ -10222,28 +7252,28 @@ float Unit::GetUnitSpellCriticalChance(Unit* victim, SpellInfo const* spellProto
if (!((*i)->IsAffectedOnSpell(spellProto)))
continue;
+ float modChance = 0.f;
switch ((*i)->GetMiscValue())
{
+ case 911: // Shatter (Rank 3)
+ modChance += 16.f;
+ case 910: // Shatter (Rank 2)
+ modChance += 17.f;
case 849: // Shatter (Rank 1)
- if (victim->HasAuraState(AURA_STATE_FROZEN, spellProto, this))
- crit_chance += 17;
+ modChance += 17.f;
+ if (!victim->HasAuraState(AURA_STATE_FROZEN, spellProto, this))
+ break;
+
+ crit_chance += modChance;
break;
- case 910: // Shatter (Rank 2)
- if (victim->HasAuraState(AURA_STATE_FROZEN, spellProto, this))
- crit_chance += 34;
- break;
- case 911: // Shatter (Rank 3)
- if (victim->HasAuraState(AURA_STATE_FROZEN, spellProto, this))
- crit_chance += 50;
- break;
case 7917: // Glyph of Shadowburn
if (victim->HasAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, spellProto, this))
- crit_chance+=(*i)->GetAmount();
+ crit_chance += (*i)->GetAmount();
break;
case 7997: // Renewed Hope
case 7998:
if (victim->HasAura(6788))
- crit_chance+=(*i)->GetAmount();
+ crit_chance += (*i)->GetAmount();
break;
default:
break;
@@ -10358,7 +7388,7 @@ float Unit::GetUnitSpellCriticalChance(Unit* victim, SpellInfo const* spellProto
// percent done
// only players use intelligence for critical chance computations
if (Player* modOwner = GetSpellModOwner())
- modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_CRITICAL_CHANCE, crit_chance);
+ modOwner->ApplySpellMod<SPELLMOD_CRITICAL_CHANCE>(spellProto->Id, crit_chance);
// for this types the bonus was already added in GetUnitCriticalChance, do not add twice
if (spellProto->DmgClass != SPELL_DAMAGE_CLASS_MELEE && spellProto->DmgClass != SPELL_DAMAGE_CLASS_RANGED)
@@ -10408,7 +7438,7 @@ uint32 Unit::SpellCriticalDamageBonus(SpellInfo const* spellProto, uint32 damage
{
// adds additional damage to critBonus (from talents)
if (Player* modOwner = GetSpellModOwner())
- modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_CRIT_DAMAGE_BONUS, crit_bonus);
+ modOwner->ApplySpellMod<SPELLMOD_CRIT_DAMAGE_BONUS>(spellProto->Id, crit_bonus);
}
crit_bonus += damage;
@@ -10520,7 +7550,7 @@ uint32 Unit::SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, ui
if (Player* modOwner = GetSpellModOwner())
{
coeff *= 100.0f;
- modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_BONUS_MULTIPLIER, coeff);
+ modOwner->ApplySpellMod<SPELLMOD_BONUS_MULTIPLIER>(spellProto->Id, coeff);
coeff /= 100.0f;
}
@@ -10549,7 +7579,12 @@ uint32 Unit::SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, ui
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);
+ {
+ if (damagetype == DOT)
+ modOwner->ApplySpellMod<SPELLMOD_DOT>(spellProto->Id, heal);
+ else
+ modOwner->ApplySpellMod<SPELLMOD_DAMAGE>(spellProto->Id, heal);
+ }
return uint32(std::max(heal, 0.0f));
}
@@ -10695,7 +7730,7 @@ uint32 Unit::SpellHealingBonusTaken(Unit* caster, SpellInfo const* spellProto, u
if (Player* modOwner = GetSpellModOwner())
{
coeff *= 100.0f;
- modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_BONUS_MULTIPLIER, coeff);
+ modOwner->ApplySpellMod<SPELLMOD_BONUS_MULTIPLIER>(spellProto->Id, coeff);
coeff /= 100.0f;
}
@@ -11111,7 +8146,7 @@ uint32 Unit::MeleeDamageBonusDone(Unit* victim, uint32 pdamage, WeaponAttackType
// apply spellmod to Done damage
if (spellProto)
if (Player* modOwner = GetSpellModOwner())
- modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_DAMAGE, tmpDamage);
+ modOwner->ApplySpellMod<SPELLMOD_DAMAGE>(spellProto->Id, tmpDamage);
// bonus result can be negative
return uint32(std::max(tmpDamage, 0.0f));
@@ -11314,7 +8349,7 @@ float Unit::GetPPMProcChance(uint32 WeaponSpeed, float PPM, const SpellInfo* spe
// Apply chance modifer aura
if (spellProto)
if (Player* modOwner = GetSpellModOwner())
- modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_PROC_PER_MINUTE, PPM);
+ modOwner->ApplySpellMod<SPELLMOD_PROC_PER_MINUTE>(spellProto->Id, PPM);
return std::floor((WeaponSpeed * PPM) / 600.0f); // result is chance in percents (probability = Speed_in_sec * (PPM / 60))
}
@@ -12494,17 +9529,17 @@ float Unit::ApplyEffectModifiers(SpellInfo const* spellProto, uint8 effect_index
{
if (Player* modOwner = GetSpellModOwner())
{
- modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_ALL_EFFECTS, value);
+ modOwner->ApplySpellMod<SPELLMOD_ALL_EFFECTS>(spellProto->Id, value);
switch (effect_index)
{
- case 0:
- modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_EFFECT1, value);
+ case EFFECT_0:
+ modOwner->ApplySpellMod<SPELLMOD_EFFECT1>(spellProto->Id, value);
break;
- case 1:
- modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_EFFECT2, value);
+ case EFFECT_1:
+ modOwner->ApplySpellMod<SPELLMOD_EFFECT2>(spellProto->Id, value);
break;
- case 2:
- modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_EFFECT3, value);
+ case EFFECT_2:
+ modOwner->ApplySpellMod<SPELLMOD_EFFECT3>(spellProto->Id, value);
break;
}
}
@@ -12647,7 +9682,7 @@ void Unit::ModSpellCastTime(SpellInfo const* spellInfo, int32 & castTime, Spell*
// called from caster
if (Player* modOwner = GetSpellModOwner())
- modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_CASTING_TIME, castTime, spell);
+ modOwner->ApplySpellMod<SPELLMOD_CASTING_TIME>(spellInfo->Id, castTime, spell);
if (!(spellInfo->HasAttribute(SPELL_ATTR0_ABILITY) || spellInfo->HasAttribute(SPELL_ATTR0_TRADESPELL) || spellInfo->HasAttribute(SPELL_ATTR3_NO_DONE_BONUS)) &&
((GetTypeId() == TYPEID_PLAYER && spellInfo->SpellFamilyName) || GetTypeId() == TYPEID_UNIT))
@@ -12668,7 +9703,7 @@ void Unit::ModSpellDurationTime(SpellInfo const* spellInfo, int32 & duration, Sp
// called from caster
if (Player* modOwner = GetSpellModOwner())
- modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_CASTING_TIME, duration, spell);
+ modOwner->ApplySpellMod<SPELLMOD_CASTING_TIME>(spellInfo->Id, duration, spell);
if (!(spellInfo->HasAttribute(SPELL_ATTR0_ABILITY) || spellInfo->HasAttribute(SPELL_ATTR0_TRADESPELL) || spellInfo->HasAttribute(SPELL_ATTR3_NO_DONE_BONUS)) &&
((GetTypeId() == TYPEID_PLAYER && spellInfo->SpellFamilyName) || GetTypeId() == TYPEID_UNIT))
@@ -13709,152 +10744,96 @@ bool Unit::isFrozen() const
return HasAuraState(AURA_STATE_FROZEN);
}
-struct ProcTriggeredData
+uint32 createProcHitMask(SpellNonMeleeDamage* damageInfo, SpellMissInfo missCondition)
{
- ProcTriggeredData(Aura* _aura)
- : aura(_aura)
- {
- effMask = 0;
- spellProcEvent = NULL;
- }
- SpellProcEventEntry const* spellProcEvent;
- Aura* aura;
- uint32 effMask;
-};
-
-typedef std::list< ProcTriggeredData > ProcTriggeredList;
-
-// List of auras that CAN be trigger but may not exist in spell_proc_event
-// in most case need for drop charges
-// in some types of aura need do additional check
-// for example SPELL_AURA_MECHANIC_IMMUNITY - need check for mechanic
-bool InitTriggerAuraData()
-{
- for (uint16 i = 0; i < TOTAL_AURAS; ++i)
- {
- isTriggerAura[i] = false;
- isNonTriggerAura[i] = false;
- isAlwaysTriggeredAura[i] = false;
- }
- isTriggerAura[SPELL_AURA_DUMMY] = true;
- isTriggerAura[SPELL_AURA_MOD_CONFUSE] = true;
- isTriggerAura[SPELL_AURA_MOD_THREAT] = true;
- isTriggerAura[SPELL_AURA_MOD_STUN] = true; // Aura does not have charges but needs to be removed on trigger
- isTriggerAura[SPELL_AURA_MOD_DAMAGE_DONE] = true;
- isTriggerAura[SPELL_AURA_MOD_DAMAGE_TAKEN] = true;
- isTriggerAura[SPELL_AURA_MOD_RESISTANCE] = true;
- isTriggerAura[SPELL_AURA_MOD_STEALTH] = true;
- isTriggerAura[SPELL_AURA_MOD_FEAR] = true; // Aura does not have charges but needs to be removed on trigger
- isTriggerAura[SPELL_AURA_MOD_ROOT] = true;
- isTriggerAura[SPELL_AURA_TRANSFORM] = true;
- isTriggerAura[SPELL_AURA_REFLECT_SPELLS] = true;
- isTriggerAura[SPELL_AURA_DAMAGE_IMMUNITY] = true;
- isTriggerAura[SPELL_AURA_PROC_TRIGGER_SPELL] = true;
- isTriggerAura[SPELL_AURA_PROC_TRIGGER_DAMAGE] = true;
- isTriggerAura[SPELL_AURA_MOD_CASTING_SPEED_NOT_STACK] = true;
- isTriggerAura[SPELL_AURA_SCHOOL_ABSORB] = true; // Savage Defense untested
- isTriggerAura[SPELL_AURA_MOD_POWER_COST_SCHOOL_PCT] = true;
- isTriggerAura[SPELL_AURA_MOD_POWER_COST_SCHOOL] = true;
- isTriggerAura[SPELL_AURA_REFLECT_SPELLS_SCHOOL] = true;
- isTriggerAura[SPELL_AURA_MECHANIC_IMMUNITY] = true;
- isTriggerAura[SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN] = true;
- isTriggerAura[SPELL_AURA_SPELL_MAGNET] = true;
- isTriggerAura[SPELL_AURA_MOD_ATTACK_POWER] = true;
- isTriggerAura[SPELL_AURA_ADD_CASTER_HIT_TRIGGER] = true;
- isTriggerAura[SPELL_AURA_OVERRIDE_CLASS_SCRIPTS] = true;
- isTriggerAura[SPELL_AURA_MOD_MECHANIC_RESISTANCE] = true;
- isTriggerAura[SPELL_AURA_RANGED_ATTACK_POWER_ATTACKER_BONUS] = true;
- isTriggerAura[SPELL_AURA_MOD_MELEE_HASTE] = true;
- isTriggerAura[SPELL_AURA_MOD_ATTACKER_MELEE_HIT_CHANCE] = true;
- isTriggerAura[SPELL_AURA_RAID_PROC_FROM_CHARGE] = true;
- isTriggerAura[SPELL_AURA_RAID_PROC_FROM_CHARGE_WITH_VALUE] = true;
- isTriggerAura[SPELL_AURA_PROC_TRIGGER_SPELL_WITH_VALUE] = true;
- isTriggerAura[SPELL_AURA_MOD_DAMAGE_FROM_CASTER] = true;
- isTriggerAura[SPELL_AURA_MOD_SPELL_CRIT_CHANCE] = true;
- isTriggerAura[SPELL_AURA_ABILITY_IGNORE_AURASTATE] = true;
-
- isNonTriggerAura[SPELL_AURA_MOD_POWER_REGEN] = true;
- isNonTriggerAura[SPELL_AURA_REDUCE_PUSHBACK] = true;
-
- isAlwaysTriggeredAura[SPELL_AURA_OVERRIDE_CLASS_SCRIPTS] = true;
- isAlwaysTriggeredAura[SPELL_AURA_MOD_FEAR] = true;
- isAlwaysTriggeredAura[SPELL_AURA_MOD_ROOT] = true;
- isAlwaysTriggeredAura[SPELL_AURA_MOD_STUN] = true;
- isAlwaysTriggeredAura[SPELL_AURA_TRANSFORM] = true;
- isAlwaysTriggeredAura[SPELL_AURA_SPELL_MAGNET] = true;
- isAlwaysTriggeredAura[SPELL_AURA_SCHOOL_ABSORB] = true;
- isAlwaysTriggeredAura[SPELL_AURA_MOD_STEALTH] = true;
-
- return true;
-}
-
-uint32 createProcExtendMask(SpellNonMeleeDamage* damageInfo, SpellMissInfo missCondition)
-{
- uint32 procEx = PROC_EX_NONE;
+ uint32 hitMask = PROC_HIT_NONE;
// Check victim state
if (missCondition != SPELL_MISS_NONE)
+ {
switch (missCondition)
{
- case SPELL_MISS_MISS: procEx|=PROC_EX_MISS; break;
- case SPELL_MISS_RESIST: procEx|=PROC_EX_RESIST; break;
- case SPELL_MISS_DODGE: procEx|=PROC_EX_DODGE; break;
- case SPELL_MISS_PARRY: procEx|=PROC_EX_PARRY; break;
- case SPELL_MISS_BLOCK: procEx|=PROC_EX_BLOCK; break;
- case SPELL_MISS_EVADE: procEx|=PROC_EX_EVADE; break;
- case SPELL_MISS_IMMUNE: procEx|=PROC_EX_IMMUNE; break;
- case SPELL_MISS_IMMUNE2: procEx|=PROC_EX_IMMUNE; break;
- case SPELL_MISS_DEFLECT: procEx|=PROC_EX_DEFLECT;break;
- case SPELL_MISS_ABSORB: procEx|=PROC_EX_ABSORB; break;
- case SPELL_MISS_REFLECT: procEx|=PROC_EX_REFLECT;break;
+ case SPELL_MISS_MISS:
+ hitMask |= PROC_HIT_MISS;
+ break;
+ case SPELL_MISS_DODGE:
+ hitMask |= PROC_HIT_DODGE;
+ break;
+ case SPELL_MISS_PARRY:
+ hitMask |= PROC_HIT_PARRY;
+ break;
+ case SPELL_MISS_BLOCK:
+ hitMask |= PROC_HIT_BLOCK;
+ break;
+ case SPELL_MISS_EVADE:
+ hitMask |= PROC_HIT_EVADE;
+ break;
+ case SPELL_MISS_IMMUNE:
+ hitMask |= PROC_HIT_IMMUNE;
+ break;
+ case SPELL_MISS_IMMUNE2:
+ hitMask |= PROC_HIT_IMMUNE;
+ break;
+ case SPELL_MISS_DEFLECT:
+ hitMask |= PROC_HIT_DEFLECT;
+ break;
+ case SPELL_MISS_ABSORB:
+ hitMask |= PROC_HIT_ABSORB;
+ break;
+ case SPELL_MISS_REFLECT:
+ hitMask |= PROC_HIT_REFLECT;
+ break;
default:
break;
}
+ }
else
{
// On block
if (damageInfo->blocked)
- procEx|=PROC_EX_BLOCK;
+ hitMask |= PROC_HIT_BLOCK;
// On absorb
if (damageInfo->absorb)
- procEx|=PROC_EX_ABSORB;
+ hitMask |= PROC_HIT_ABSORB;
// On crit
if (damageInfo->HitInfo & SPELL_HIT_TYPE_CRIT)
- procEx|=PROC_EX_CRITICAL_HIT;
+ hitMask |= PROC_HIT_CRITICAL;
else
- procEx|=PROC_EX_NORMAL_HIT;
+ hitMask |= PROC_HIT_NORMAL;
}
- return procEx;
+
+ return hitMask;
}
-void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, SpellInfo const* procSpell, uint32 damage, SpellInfo const* procAura)
+void Unit::ProcSkillsAndReactives(bool isVictim, Unit* procTarget, uint32 typeMask, uint32 hitMask, WeaponAttackType attType)
{
// Player is loaded now - do not allow passive spell casts to proc
if (GetTypeId() == TYPEID_PLAYER && ToPlayer()->GetSession()->PlayerLoading())
return;
+
// For melee/ranged based attack need update skills and set some Aura states if victim present
- if (procFlag & MELEE_BASED_TRIGGER_MASK && target)
+ if (typeMask & MELEE_BASED_TRIGGER_MASK && procTarget)
{
// Update skills here for players
if (GetTypeId() == TYPEID_PLAYER)
{
// On melee based hit/miss/resist need update skill (for victim and attacker)
- if (procExtra & (PROC_EX_NORMAL_HIT|PROC_EX_MISS|PROC_EX_RESIST))
+ if (hitMask & (PROC_HIT_NORMAL | PROC_HIT_MISS | PROC_HIT_FULL_RESIST))
{
- if (target->GetTypeId() != TYPEID_PLAYER && !target->IsCritter())
- ToPlayer()->UpdateCombatSkills(target, attType, isVictim);
+ if (procTarget->GetTypeId() != TYPEID_PLAYER && !procTarget->IsCritter())
+ ToPlayer()->UpdateCombatSkills(procTarget, attType, isVictim);
}
// Update defense if player is victim and parry/dodge/block
- else if (isVictim && procExtra & (PROC_EX_DODGE|PROC_EX_PARRY|PROC_EX_BLOCK))
- ToPlayer()->UpdateCombatSkills(target, attType, true);
+ else if (isVictim && (hitMask & (PROC_HIT_DODGE | PROC_HIT_PARRY | PROC_HIT_BLOCK)))
+ ToPlayer()->UpdateCombatSkills(procTarget, attType, true);
}
// If exist crit/parry/dodge/block need update aura state (for victim and attacker)
- if (procExtra & (PROC_EX_CRITICAL_HIT|PROC_EX_PARRY|PROC_EX_DODGE|PROC_EX_BLOCK))
+ if (hitMask & (PROC_HIT_CRITICAL | PROC_HIT_PARRY | PROC_HIT_DODGE | PROC_HIT_BLOCK))
{
// for victim
if (isVictim)
{
// if victim and dodge attack
- if (procExtra & PROC_EX_DODGE)
+ if (hitMask & PROC_HIT_DODGE)
{
// Update AURA_STATE on dodge
if (getClass() != CLASS_ROGUE) // skip Rogue Riposte
@@ -13864,7 +10843,7 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u
}
}
// if victim and parry attack
- if (procExtra & PROC_EX_PARRY)
+ if (hitMask & PROC_HIT_PARRY)
{
// For Hunters only Counterattack (skip Mongoose bite)
if (getClass() == CLASS_HUNTER)
@@ -13879,7 +10858,7 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u
}
}
// if and victim block attack
- if (procExtra & PROC_EX_BLOCK)
+ if (hitMask & PROC_HIT_BLOCK)
{
ModifyAuraState(AURA_STATE_DEFENSE, true);
StartReactiveTimer(REACTIVE_DEFENSE);
@@ -13888,362 +10867,42 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u
else // For attacker
{
// Overpower on victim dodge
- if (procExtra & PROC_EX_DODGE && GetTypeId() == TYPEID_PLAYER && getClass() == CLASS_WARRIOR)
+ if ((hitMask & PROC_HIT_DODGE) && GetTypeId() == TYPEID_PLAYER && getClass() == CLASS_WARRIOR)
{
- ToPlayer()->AddComboPoints(target, 1);
+ ToPlayer()->AddComboPoints(procTarget, 1);
StartReactiveTimer(REACTIVE_OVERPOWER);
}
}
}
}
-
- Unit* actor = isVictim ? target : this;
- Unit* actionTarget = !isVictim ? target : this;
-
- DamageInfo damageInfo = DamageInfo(actor, actionTarget, damage, procSpell, procSpell ? SpellSchoolMask(procSpell->SchoolMask) : SPELL_SCHOOL_MASK_NORMAL, SPELL_DIRECT_DAMAGE, attType);
- HealInfo healInfo = HealInfo(actor, actionTarget, damage, procSpell, procSpell ? SpellSchoolMask(procSpell->SchoolMask) : SPELL_SCHOOL_MASK_NORMAL);
- ProcEventInfo eventInfo = ProcEventInfo(actor, actionTarget, target, procFlag, 0, 0, procExtra, nullptr, &damageInfo, &healInfo);
-
- std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now();
- ProcTriggeredList procTriggered;
- // Fill procTriggered list
- for (AuraApplicationMap::const_iterator itr = GetAppliedAuras().begin(); itr!= GetAppliedAuras().end(); ++itr)
- {
- // Do not allow auras to proc from effect triggered by itself
- if (procAura && procAura->Id == itr->first)
- continue;
-
- if (itr->second->GetBase()->IsProcOnCooldown(now))
- continue;
-
- ProcTriggeredData triggerData(itr->second->GetBase());
- // Defensive procs are active on absorbs (so absorption effects are not a hindrance)
- bool active = damage || (procExtra & PROC_EX_BLOCK && isVictim);
- if (isVictim)
- procExtra &= ~PROC_EX_INTERNAL_REQ_FAMILY;
-
- SpellInfo const* spellProto = itr->second->GetBase()->GetSpellInfo();
-
- // only auras that has triggered spell should proc from fully absorbed damage
- if (procExtra & PROC_EX_ABSORB && isVictim)
- if (damage || spellProto->Effects[EFFECT_0].TriggerSpell || spellProto->Effects[EFFECT_1].TriggerSpell || spellProto->Effects[EFFECT_2].TriggerSpell)
- active = true;
-
- if (!IsTriggeredAtSpellProcEvent(target, triggerData.aura, procSpell, procFlag, procExtra, attType, isVictim, active, triggerData.spellProcEvent))
- continue;
-
- // do checks using conditions table
- if (!sConditionMgr->IsObjectMeetingNotGroupedConditions(CONDITION_SOURCE_TYPE_SPELL_PROC, spellProto->Id, eventInfo.GetActor(), eventInfo.GetActionTarget()))
- continue;
-
- // AuraScript Hook
- if (!triggerData.aura->CallScriptCheckProcHandlers(itr->second, eventInfo))
- continue;
-
- bool procSuccess = RollProcResult(target, triggerData.aura, attType, isVictim, triggerData.spellProcEvent);
- if (!procSuccess)
- continue;
-
- bool triggeredCanProcAura = true;
- // Additional checks for triggered spells (ignore trap casts)
- if (procExtra & PROC_EX_INTERNAL_TRIGGERED && !(procFlag & PROC_FLAG_DONE_TRAP_ACTIVATION))
- {
- if (!spellProto->HasAttribute(SPELL_ATTR3_CAN_PROC_WITH_TRIGGERED))
- triggeredCanProcAura = false;
- }
-
- for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
- {
- if (itr->second->HasEffect(i))
- {
- AuraEffect* aurEff = itr->second->GetBase()->GetEffect(i);
- // Skip this auras
- if (isNonTriggerAura[aurEff->GetAuraType()])
- continue;
- // If not trigger by default and spellProcEvent == NULL - skip
- if (!isTriggerAura[aurEff->GetAuraType()] && triggerData.spellProcEvent == NULL)
- continue;
- // Some spells must always trigger
- if (triggeredCanProcAura || isAlwaysTriggeredAura[aurEff->GetAuraType()])
- triggerData.effMask |= 1<<i;
- }
- }
- if (triggerData.effMask)
- procTriggered.push_front(triggerData);
- }
-
- // Nothing found
- if (procTriggered.empty())
- return;
-
- // Note: must SetCantProc(false) before return
- if (procExtra & (PROC_EX_INTERNAL_TRIGGERED | PROC_EX_INTERNAL_CANT_PROC))
- SetCantProc(true);
-
- // Handle effects proceed this time
- for (ProcTriggeredList::const_iterator i = procTriggered.begin(); i != procTriggered.end(); ++i)
- {
- // look for aura in auras list, it may be removed while proc event processing
- if (i->aura->IsRemoved())
- continue;
-
- bool useCharges = i->aura->IsUsingCharges();
- // no more charges to use, prevent proc
- if (useCharges && !i->aura->GetCharges())
- continue;
-
- bool takeCharges = false;
- SpellInfo const* spellInfo = i->aura->GetSpellInfo();
- uint32 Id = i->aura->GetId();
-
- AuraApplication* aurApp = i->aura->GetApplicationOfTarget(GetGUID());
-
- bool prepare = i->aura->CallScriptPrepareProcHandlers(aurApp, eventInfo);
-
- Milliseconds cooldown = Milliseconds::zero();
- if (prepare && i->spellProcEvent && i->spellProcEvent->cooldown)
- cooldown = Seconds(i->spellProcEvent->cooldown);
-
- // Note: must SetCantProc(false) before return
- if (spellInfo->HasAttribute(SPELL_ATTR3_DISABLE_PROC))
- SetCantProc(true);
-
- bool handled = i->aura->CallScriptProcHandlers(aurApp, eventInfo);
-
- // "handled" is needed as long as proc can be handled in multiple places
- if (!handled && HandleAuraProc(target, damage, i->aura, procSpell, procFlag, procExtra, &handled))
- {
- TC_LOG_DEBUG("spells", "ProcDamageAndSpell: casting spell %u (triggered with value by %s aura of spell %u)", spellInfo->Id, (isVictim ? "a victim's" : "an attacker's"), Id);
- takeCharges = true;
- }
-
- if (!handled)
- {
- for (uint8 effIndex = 0; effIndex < MAX_SPELL_EFFECTS; ++effIndex)
- {
- if (!(i->effMask & (1 << effIndex)))
- continue;
-
- AuraEffect* triggeredByAura = i->aura->GetEffect(effIndex);
- ASSERT(triggeredByAura);
-
- bool prevented = i->aura->CallScriptEffectProcHandlers(triggeredByAura, aurApp, eventInfo);
- if (prevented)
- {
- takeCharges = true;
- continue;
- }
-
- switch (triggeredByAura->GetAuraType())
- {
- case SPELL_AURA_PROC_TRIGGER_SPELL:
- {
- TC_LOG_DEBUG("spells", "ProcDamageAndSpell: casting spell %u (triggered by %s aura of spell %u)",
- spellInfo->Id, (isVictim ? "a victim's" : "an attacker's"), triggeredByAura->GetId());
- // Don`t drop charge or add cooldown for not started trigger
- if (HandleProcTriggerSpell(target, damage, triggeredByAura, procSpell, procFlag, procExtra))
- takeCharges = true;
- break;
- }
- case SPELL_AURA_PROC_TRIGGER_DAMAGE:
- {
- // target has to be valid
- if (!eventInfo.GetProcTarget())
- break;
-
- triggeredByAura->HandleProcTriggerDamageAuraProc(aurApp, eventInfo); // this function is part of the new proc system
- takeCharges = true;
- break;
- }
- case SPELL_AURA_MANA_SHIELD:
- case SPELL_AURA_DUMMY:
- {
- TC_LOG_DEBUG("spells", "ProcDamageAndSpell: casting spell id %u (triggered by %s dummy aura of spell %u)",
- spellInfo->Id, (isVictim ? "a victim's" : "an attacker's"), triggeredByAura->GetId());
- if (HandleDummyAuraProc(target, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown))
- takeCharges = true;
- break;
- }
- case SPELL_AURA_OBS_MOD_POWER:
- case SPELL_AURA_MOD_SPELL_CRIT_CHANCE:
- case SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN:
- case SPELL_AURA_MOD_MELEE_HASTE:
- TC_LOG_DEBUG("spells", "ProcDamageAndSpell: casting spell id %u (triggered by %s aura of spell %u)",
- spellInfo->Id, isVictim ? "a victim's" : "an attacker's", triggeredByAura->GetId());
- takeCharges = true;
- break;
- case SPELL_AURA_OVERRIDE_CLASS_SCRIPTS:
- {
- TC_LOG_DEBUG("spells", "ProcDamageAndSpell: casting spell id %u (triggered by %s aura of spell %u)",
- spellInfo->Id, (isVictim ? "a victim's" : "an attacker's"), triggeredByAura->GetId());
- if (HandleOverrideClassScriptAuraProc(target, damage, triggeredByAura, procSpell))
- takeCharges = true;
- break;
- }
- case SPELL_AURA_RAID_PROC_FROM_CHARGE_WITH_VALUE:
- {
- TC_LOG_DEBUG("spells", "ProcDamageAndSpell: casting mending (triggered by %s dummy aura of spell %u)",
- (isVictim ? "a victim's" : "an attacker's"), triggeredByAura->GetId());
-
- HandleAuraRaidProcFromChargeWithValue(triggeredByAura);
- takeCharges = true;
- break;
- }
- case SPELL_AURA_RAID_PROC_FROM_CHARGE:
- {
- TC_LOG_DEBUG("spells", "ProcDamageAndSpell: casting mending (triggered by %s dummy aura of spell %u)",
- (isVictim ? "a victim's" : "an attacker's"), triggeredByAura->GetId());
-
- HandleAuraRaidProcFromCharge(triggeredByAura);
- takeCharges = true;
- break;
- }
- case SPELL_AURA_PROC_TRIGGER_SPELL_WITH_VALUE:
- {
- TC_LOG_DEBUG("spells", "ProcDamageAndSpell: casting spell %u (triggered with value by %s aura of spell %u)",
- spellInfo->Id, (isVictim ? "a victim's" : "an attacker's"), triggeredByAura->GetId());
-
- if (HandleProcTriggerSpell(target, damage, triggeredByAura, procSpell, procFlag, procExtra))
- takeCharges = true;
- break;
- }
- case SPELL_AURA_MOD_CASTING_SPEED_NOT_STACK:
- // Skip melee hits or instant cast spells
- if (procSpell && procSpell->CalcCastTime() != 0)
- takeCharges = true;
- break;
- case SPELL_AURA_REFLECT_SPELLS_SCHOOL:
- // Skip Melee hits and spells ws wrong school
- if (procSpell && (triggeredByAura->GetMiscValue() & procSpell->SchoolMask)) // School check
- takeCharges = true;
- break;
- case SPELL_AURA_SPELL_MAGNET:
- // Skip Melee hits and targets with magnet aura
- if (procSpell && (triggeredByAura->GetBase()->GetUnitOwner()->ToUnit() == ToUnit())) // Magnet
- takeCharges = true;
- break;
- case SPELL_AURA_MOD_POWER_COST_SCHOOL_PCT:
- case SPELL_AURA_MOD_POWER_COST_SCHOOL:
- // Skip melee hits and spells ws wrong school or zero cost
- if (procSpell &&
- (procSpell->ManaCost != 0 || procSpell->ManaCostPercentage != 0) && // Cost check
- (triggeredByAura->GetMiscValue() & procSpell->SchoolMask)) // School check
- takeCharges = true;
- break;
- case SPELL_AURA_MECHANIC_IMMUNITY:
- // Compare mechanic
- if (procSpell && procSpell->Mechanic == uint32(triggeredByAura->GetMiscValue()))
- takeCharges = true;
- break;
- case SPELL_AURA_MOD_MECHANIC_RESISTANCE:
- // Compare mechanic
- if (procSpell && procSpell->Mechanic == uint32(triggeredByAura->GetMiscValue()))
- takeCharges = true;
- break;
- case SPELL_AURA_MOD_DAMAGE_FROM_CASTER:
- // Compare casters
- if (triggeredByAura->GetCasterGUID() == target->GetGUID())
- takeCharges = true;
- break;
- // CC Auras which use their amount amount to drop
- // Are there any more auras which need this?
- case SPELL_AURA_MOD_CONFUSE:
- case SPELL_AURA_MOD_FEAR:
- case SPELL_AURA_MOD_STUN:
- case SPELL_AURA_MOD_ROOT:
- case SPELL_AURA_TRANSFORM:
- {
- // chargeable mods are breaking on hit
- if (useCharges)
- takeCharges = true;
- else
- {
- // Spell own direct damage at apply wont break the CC
- if (procSpell && (procSpell->Id == triggeredByAura->GetId()))
- {
- Aura* aura = triggeredByAura->GetBase();
- // called from spellcast, should not have ticked yet
- if (aura->GetDuration() == aura->GetMaxDuration())
- break;
- }
- int32 damageLeft = triggeredByAura->GetAmount();
- // No damage left
- if (damageLeft < int32(damage))
- i->aura->Remove();
- else
- triggeredByAura->SetAmount(damageLeft - damage);
- }
- break;
- }
- //case SPELL_AURA_ADD_FLAT_MODIFIER:
- //case SPELL_AURA_ADD_PCT_MODIFIER:
- // HandleSpellModAuraProc
- //break;
- default:
- // nothing do, just charges counter
- takeCharges = true;
- break;
- } // switch (triggeredByAura->GetAuraType())
- i->aura->CallScriptAfterEffectProcHandlers(triggeredByAura, aurApp, eventInfo);
- } // for (uint8 effIndex = 0; effIndex < MAX_SPELL_EFFECTS; ++effIndex)
- } // if (!handled)
-
- if (prepare && takeCharges && cooldown != Milliseconds::zero())
- i->aura->AddProcCooldown(now + cooldown);
-
- // Remove charge (aura can be removed by triggers)
- if (prepare && useCharges && takeCharges)
- {
- // Set charge drop delay (only for missiles)
- if ((procExtra & PROC_EX_REFLECT) && target && procSpell && procSpell->Speed > 0.0f)
- {
- // Set up missile speed based delay (from Spell.cpp: Spell::AddUnitTarget()::L2237)
- uint32 delay = uint32(std::floor(std::max<float>(target->GetDistance(this), 5.0f) / procSpell->Speed * 1000.0f));
- // Schedule charge drop
- i->aura->DropChargeDelayed(delay);
- }
- else
- i->aura->DropCharge();
- }
-
- i->aura->CallScriptAfterProcHandlers(aurApp, eventInfo);
-
- if (spellInfo->HasAttribute(SPELL_ATTR3_DISABLE_PROC))
- SetCantProc(false);
- }
-
- // Cleanup proc requirements
- if (procExtra & (PROC_EX_INTERNAL_TRIGGERED | PROC_EX_INTERNAL_CANT_PROC))
- SetCantProc(false);
}
-void Unit::GetProcAurasTriggeredOnEvent(std::list<AuraApplication*>& aurasTriggeringProc, std::list<AuraApplication*>* procAuras, ProcEventInfo eventInfo)
+void Unit::GetProcAurasTriggeredOnEvent(AuraApplicationProcContainer& aurasTriggeringProc, AuraApplicationList* procAuras, ProcEventInfo& eventInfo)
{
std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now();
// use provided list of auras which can proc
if (procAuras)
{
- for (std::list<AuraApplication*>::iterator itr = procAuras->begin(); itr!= procAuras->end(); ++itr)
+ for (AuraApplication* aurApp : *procAuras)
{
- ASSERT((*itr)->GetTarget() == this);
- if (!(*itr)->GetRemoveMode())
- if ((*itr)->GetBase()->IsProcTriggeredOnEvent(*itr, eventInfo, now))
- {
- (*itr)->GetBase()->PrepareProcToTrigger(*itr, eventInfo, now);
- aurasTriggeringProc.push_back(*itr);
- }
+ ASSERT(aurApp->GetTarget() == this);
+ if (uint8 procEffectMask = aurApp->GetBase()->IsProcTriggeredOnEvent(aurApp, eventInfo, now))
+ {
+ aurApp->GetBase()->PrepareProcToTrigger(aurApp, eventInfo, now);
+ aurasTriggeringProc.emplace_back(std::make_pair(procEffectMask, aurApp));
+ }
}
}
// or generate one on our own
else
{
- for (AuraApplicationMap::iterator itr = GetAppliedAuras().begin(); itr!= GetAppliedAuras().end(); ++itr)
+ for (AuraApplicationMap::iterator itr = GetAppliedAuras().begin(); itr != GetAppliedAuras().end(); ++itr)
{
- if (itr->second->GetBase()->IsProcTriggeredOnEvent(itr->second, eventInfo, now))
+ if (uint8 procEffectMask = itr->second->GetBase()->IsProcTriggeredOnEvent(itr->second, eventInfo, now))
{
itr->second->GetBase()->PrepareProcToTrigger(itr->second, eventInfo, now);
- aurasTriggeringProc.push_back(itr->second);
+ aurasTriggeringProc.emplace_back(std::make_pair(procEffectMask, itr->second));
}
}
}
@@ -14252,34 +10911,49 @@ void Unit::GetProcAurasTriggeredOnEvent(std::list<AuraApplication*>& aurasTrigge
void Unit::TriggerAurasProcOnEvent(CalcDamageInfo& damageInfo)
{
DamageInfo dmgInfo = DamageInfo(damageInfo);
- TriggerAurasProcOnEvent(NULL, NULL, damageInfo.target, damageInfo.procAttacker, damageInfo.procVictim, 0, 0, damageInfo.procEx, NULL, &dmgInfo, NULL);
+ TriggerAurasProcOnEvent(damageInfo.target, damageInfo.procAttacker, damageInfo.procVictim, PROC_SPELL_TYPE_NONE, PROC_SPELL_PHASE_NONE, dmgInfo.GetHitMask(), nullptr, &dmgInfo, nullptr);
}
-void Unit::TriggerAurasProcOnEvent(std::list<AuraApplication*>* myProcAuras, std::list<AuraApplication*>* targetProcAuras, Unit* actionTarget, uint32 typeMaskActor, uint32 typeMaskActionTarget, uint32 spellTypeMask, uint32 spellPhaseMask, uint32 hitMask, Spell* spell, DamageInfo* damageInfo, HealInfo* healInfo)
+void Unit::TriggerAurasProcOnEvent(Unit* actionTarget, uint32 typeMaskActor, uint32 typeMaskActionTarget, uint32 spellTypeMask, uint32 spellPhaseMask, uint32 hitMask, Spell* spell, DamageInfo* damageInfo, HealInfo* healInfo)
{
// prepare data for self trigger
- ProcEventInfo myProcEventInfo = ProcEventInfo(this, actionTarget, actionTarget, typeMaskActor, spellTypeMask, spellPhaseMask, hitMask, spell, damageInfo, healInfo);
- std::list<AuraApplication*> myAurasTriggeringProc;
- GetProcAurasTriggeredOnEvent(myAurasTriggeringProc, myProcAuras, myProcEventInfo);
+ ProcEventInfo myProcEventInfo(this, actionTarget, actionTarget, typeMaskActor, spellTypeMask, spellPhaseMask, hitMask, spell, damageInfo, healInfo);
+ if (typeMaskActor && CanProc())
+ {
+ AuraApplicationProcContainer myAurasTriggeringProc;
+ GetProcAurasTriggeredOnEvent(myAurasTriggeringProc, nullptr, myProcEventInfo);
+ TriggerAurasProcOnEvent(myProcEventInfo, myAurasTriggeringProc);
+ }
// prepare data for target trigger
- ProcEventInfo targetProcEventInfo = ProcEventInfo(this, actionTarget, this, typeMaskActionTarget, spellTypeMask, spellPhaseMask, hitMask, spell, damageInfo, healInfo);
- std::list<AuraApplication*> targetAurasTriggeringProc;
- if (typeMaskActionTarget)
- GetProcAurasTriggeredOnEvent(targetAurasTriggeringProc, targetProcAuras, targetProcEventInfo);
-
- TriggerAurasProcOnEvent(myProcEventInfo, myAurasTriggeringProc);
-
- if (typeMaskActionTarget)
- TriggerAurasProcOnEvent(targetProcEventInfo, targetAurasTriggeringProc);
+ ProcEventInfo targetProcEventInfo(this, actionTarget, this, typeMaskActionTarget, spellTypeMask, spellPhaseMask, hitMask, spell, damageInfo, healInfo);
+ if (typeMaskActionTarget && actionTarget && actionTarget->CanProc())
+ {
+ AuraApplicationProcContainer targetAurasTriggeringProc;
+ actionTarget->GetProcAurasTriggeredOnEvent(targetAurasTriggeringProc, nullptr, targetProcEventInfo);
+ actionTarget->TriggerAurasProcOnEvent(targetProcEventInfo, targetAurasTriggeringProc);
+ }
}
-void Unit::TriggerAurasProcOnEvent(ProcEventInfo& eventInfo, std::list<AuraApplication*>& aurasTriggeringProc)
+void Unit::TriggerAurasProcOnEvent(ProcEventInfo& eventInfo, AuraApplicationProcContainer& aurasTriggeringProc)
{
- for (std::list<AuraApplication*>::iterator itr = aurasTriggeringProc.begin(); itr != aurasTriggeringProc.end(); ++itr)
+ for (auto const& aurAppProc : aurasTriggeringProc)
{
- if (!(*itr)->GetRemoveMode())
- (*itr)->GetBase()->TriggerProcOnEvent(*itr, eventInfo);
+ AuraApplication* aurApp;
+ uint8 procEffectMask;
+ std::tie(procEffectMask, aurApp) = aurAppProc;
+
+ if (aurApp->GetRemoveMode())
+ continue;
+
+ SpellInfo const* spellInfo = aurApp->GetBase()->GetSpellInfo();
+ if (spellInfo->HasAttribute(SPELL_ATTR3_DISABLE_PROC))
+ SetCantProc(true);
+
+ aurApp->GetBase()->TriggerProcOnEvent(procEffectMask, aurApp, eventInfo);
+
+ if (spellInfo->HasAttribute(SPELL_ATTR3_DISABLE_PROC))
+ SetCantProc(false);
}
}
@@ -14864,203 +11538,6 @@ bool Unit::InitTamedPet(Pet* pet, uint8 level, uint32 spell_id)
return true;
}
-bool Unit::IsTriggeredAtSpellProcEvent(Unit* victim, Aura* aura, SpellInfo const* procSpell, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, bool isVictim, bool active, SpellProcEventEntry const*& spellProcEvent)
-{
- SpellInfo const* spellInfo = aura->GetSpellInfo();
-
- // let the aura be handled by new proc system if it has new entry
- if (sSpellMgr->GetSpellProcEntry(spellInfo->Id))
- return false;
-
- // Get proc Event Entry
- spellProcEvent = sSpellMgr->GetSpellProcEvent(spellInfo->Id);
-
- // Get EventProcFlag
- uint32 EventProcFlag;
- if (spellProcEvent && spellProcEvent->procFlags) // if exist get custom spellProcEvent->procFlags
- EventProcFlag = spellProcEvent->procFlags;
- else
- EventProcFlag = spellInfo->ProcFlags; // else get from spell proto
- // Continue if no trigger exist
- if (!EventProcFlag)
- return false;
-
- // Check spellProcEvent data requirements
- if (!sSpellMgr->IsSpellProcEventCanTriggeredBy(spellInfo, spellProcEvent, EventProcFlag, procSpell, procFlag, procExtra, active))
- return false;
- // In most cases req get honor or XP from kill
- if (EventProcFlag & PROC_FLAG_KILL && GetTypeId() == TYPEID_PLAYER)
- {
- bool allow = false;
-
- if (victim)
- allow = ToPlayer()->isHonorOrXPTarget(victim);
-
- // Shadow Word: Death - can trigger from every kill
- if (aura->GetId() == 32409)
- allow = true;
- if (!allow)
- return false;
- }
- // Aura added by spell can`t trigger from self (prevent drop charges/do triggers)
- // But except periodic and kill triggers (can triggered from self)
- if (procSpell && procSpell->Id == spellInfo->Id
- && !(spellInfo->ProcFlags&(PROC_FLAG_TAKEN_PERIODIC | PROC_FLAG_KILL)))
- return false;
-
- // Check if current equipment allows aura to proc
- if (!isVictim && GetTypeId() == TYPEID_PLAYER)
- {
- Player* player = ToPlayer();
- if (spellInfo->EquippedItemClass == ITEM_CLASS_WEAPON)
- {
- Item* item = NULL;
- if (attType == BASE_ATTACK)
- item = player->GetUseableItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND);
- else if (attType == OFF_ATTACK)
- item = player->GetUseableItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND);
- else
- item = player->GetUseableItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_RANGED);
-
- if (player->IsInFeralForm())
- return false;
-
- if (!item || item->IsBroken() || item->GetTemplate()->Class != ITEM_CLASS_WEAPON || !((1<<item->GetTemplate()->SubClass) & spellInfo->EquippedItemSubClassMask))
- return false;
- }
- else if (spellInfo->EquippedItemClass == ITEM_CLASS_ARMOR)
- {
- // Check if player is wearing shield
- Item* item = player->GetUseableItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND);
- if (!item || item->IsBroken() || item->GetTemplate()->Class != ITEM_CLASS_ARMOR || !((1<<item->GetTemplate()->SubClass) & spellInfo->EquippedItemSubClassMask))
- return false;
- }
- }
-
- return true;
-}
-
-bool Unit::RollProcResult(Unit* victim, Aura* aura, WeaponAttackType attType, bool isVictim, SpellProcEventEntry const* spellProcEvent)
-{
- SpellInfo const* spellInfo = aura->GetSpellInfo();
- // Get chance from spell
- float chance = float(spellInfo->ProcChance);
- // If in spellProcEvent exist custom chance, chance = spellProcEvent->customChance;
- if (spellProcEvent && spellProcEvent->customChance)
- chance = spellProcEvent->customChance;
- // If PPM exist calculate chance from PPM
- if (spellProcEvent && spellProcEvent->ppmRate != 0)
- {
- if (!isVictim)
- {
- uint32 weaponSpeed = GetAttackTime(attType);
- chance = GetPPMProcChance(weaponSpeed, spellProcEvent->ppmRate, spellInfo);
- }
- else if (victim)
- {
- uint32 weaponSpeed = victim->GetAttackTime(attType);
- chance = victim->GetPPMProcChance(weaponSpeed, spellProcEvent->ppmRate, spellInfo);
- }
- }
- // Apply chance modifer aura
- if (Player* modOwner = GetSpellModOwner())
- modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_CHANCE_OF_SUCCESS, chance);
-
- return roll_chance_f(chance);
-}
-
-bool Unit::HandleAuraRaidProcFromChargeWithValue(AuraEffect* triggeredByAura)
-{
- // aura can be deleted at casts
- SpellInfo const* spellProto = triggeredByAura->GetSpellInfo();
- int32 heal = triggeredByAura->GetAmount();
- ObjectGuid caster_guid = triggeredByAura->GetCasterGUID();
-
- // Currently only Prayer of Mending
- if (!(spellProto->SpellFamilyName == SPELLFAMILY_PRIEST && spellProto->SpellFamilyFlags[1] & 0x20))
- {
- TC_LOG_DEBUG("spells", "Unit::HandleAuraRaidProcFromChargeWithValue, received not handled spell: %u", spellProto->Id);
- return false;
- }
-
- // jumps
- int32 jumps = triggeredByAura->GetBase()->GetCharges()-1;
-
- // current aura expire
- triggeredByAura->GetBase()->SetCharges(1); // will removed at next charges decrease
-
- // next target selection
- if (jumps > 0)
- {
- if (Unit* caster = triggeredByAura->GetCaster())
- {
- float radius = triggeredByAura->GetSpellInfo()->Effects[triggeredByAura->GetEffIndex()].CalcRadius(caster);
-
- if (Unit* target = GetNextRandomRaidMemberOrPet(radius))
- {
- CastCustomSpell(target, spellProto->Id, &heal, NULL, NULL, true, NULL, triggeredByAura, caster_guid);
- if (Aura* aura = target->GetAura(spellProto->Id, caster->GetGUID()))
- aura->SetCharges(jumps);
- }
- }
- }
-
- // heal
- CastCustomSpell(this, 33110, &heal, NULL, NULL, true, NULL, NULL, caster_guid);
- return true;
-
-}
-bool Unit::HandleAuraRaidProcFromCharge(AuraEffect* triggeredByAura)
-{
- // aura can be deleted at casts
- SpellInfo const* spellProto = triggeredByAura->GetSpellInfo();
-
- uint32 damageSpellId;
- switch (spellProto->Id)
- {
- case 57949: // shiver
- damageSpellId = 57952;
- //animationSpellId = 57951; dummy effects for jump spell have unknown use (see also 41637)
- break;
- case 59978: // shiver
- damageSpellId = 59979;
- break;
- case 43593: // Cold Stare
- damageSpellId = 43594;
- break;
- default:
- TC_LOG_ERROR("entities.unit", "Unit::HandleAuraRaidProcFromCharge, received unhandled spell: %u", spellProto->Id);
- return false;
- }
-
- ObjectGuid caster_guid = triggeredByAura->GetCasterGUID();
-
- // jumps
- int32 jumps = triggeredByAura->GetBase()->GetCharges()-1;
-
- // current aura expire
- triggeredByAura->GetBase()->SetCharges(1); // will removed at next charges decrease
-
- // next target selection
- if (jumps > 0)
- {
- if (Unit* caster = triggeredByAura->GetCaster())
- {
- float radius = triggeredByAura->GetSpellInfo()->Effects[triggeredByAura->GetEffIndex()].CalcRadius(caster);
- if (Unit* target= GetNextRandomRaidMemberOrPet(radius))
- {
- CastSpell(target, spellProto, true, NULL, triggeredByAura, caster_guid);
- if (Aura* aura = target->GetAura(spellProto->Id, caster->GetGUID()))
- aura->SetCharges(jumps);
- }
- }
- }
-
- CastSpell(this, damageSpellId, true, NULL, triggeredByAura, caster_guid);
-
- return true;
-}
-
void Unit::Kill(Unit* victim, bool durabilityLoss)
{
// Prevent killing unit twice (and giving reward from kill twice)
@@ -15155,14 +11632,17 @@ void Unit::Kill(Unit* victim, bool durabilityLoss)
// Do KILL and KILLED procs. KILL proc is called only for the unit who landed the killing blow (and its owner - for pets and totems) regardless of who tapped the victim
if (IsPet() || IsTotem())
+ {
+ // proc only once for victim
if (Unit* owner = GetOwner())
- owner->ProcDamageAndSpell(victim, PROC_FLAG_KILL, PROC_FLAG_NONE, PROC_EX_NONE, 0);
+ owner->ProcSkillsAndAuras(victim, PROC_FLAG_KILL, PROC_FLAG_NONE, PROC_SPELL_TYPE_MASK_ALL, PROC_SPELL_PHASE_NONE, PROC_HIT_NONE, nullptr, nullptr, nullptr);
+ }
if (!victim->IsCritter())
- ProcDamageAndSpell(victim, PROC_FLAG_KILL, PROC_FLAG_KILLED, PROC_EX_NONE, 0);
+ ProcSkillsAndAuras(victim, PROC_FLAG_KILL, PROC_FLAG_KILLED, PROC_SPELL_TYPE_MASK_ALL, PROC_SPELL_PHASE_NONE, PROC_HIT_NONE, nullptr, nullptr, nullptr);
// Proc auras on death - must be before aura/combat remove
- victim->ProcDamageAndSpell(NULL, PROC_FLAG_DEATH, PROC_FLAG_NONE, PROC_EX_NONE, 0, BASE_ATTACK, 0);
+ victim->ProcSkillsAndAuras(victim, PROC_FLAG_NONE, PROC_FLAG_DEATH, PROC_SPELL_TYPE_MASK_ALL, PROC_SPELL_PHASE_NONE, PROC_HIT_NONE, nullptr, nullptr, nullptr);
// update get killing blow achievements, must be done before setDeathState to be able to require auras on target
// and before Spirit of Redemption as it also removes auras
@@ -16197,7 +12677,7 @@ float Unit::MeleeSpellMissChance(const Unit* victim, WeaponAttackType attType, i
if (spellId)
{
if (Player* modOwner = GetSpellModOwner())
- modOwner->ApplySpellMod(spellId, SPELLMOD_RESIST_MISS_CHANCE, hitChance);
+ modOwner->ApplySpellMod<SPELLMOD_RESIST_MISS_CHANCE>(spellId, hitChance);
}
missChance += hitChance - 100.0f;
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index 1a782c3e89f..b5081fcdab6 100644
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -81,42 +81,42 @@ enum SpellAuraInterruptFlags
AURA_INTERRUPT_FLAG_NOT_VICTIM = (AURA_INTERRUPT_FLAG_HITBYSPELL | AURA_INTERRUPT_FLAG_TAKE_DAMAGE | AURA_INTERRUPT_FLAG_DIRECT_DAMAGE)
};
-enum SpellModOp
-{
- SPELLMOD_DAMAGE = 0,
- SPELLMOD_DURATION = 1,
- SPELLMOD_THREAT = 2,
- SPELLMOD_EFFECT1 = 3,
- SPELLMOD_CHARGES = 4,
- SPELLMOD_RANGE = 5,
- SPELLMOD_RADIUS = 6,
- SPELLMOD_CRITICAL_CHANCE = 7,
- SPELLMOD_ALL_EFFECTS = 8,
- SPELLMOD_NOT_LOSE_CASTING_TIME = 9,
- SPELLMOD_CASTING_TIME = 10,
- SPELLMOD_COOLDOWN = 11,
- SPELLMOD_EFFECT2 = 12,
- SPELLMOD_IGNORE_ARMOR = 13,
- SPELLMOD_COST = 14,
- SPELLMOD_CRIT_DAMAGE_BONUS = 15,
- SPELLMOD_RESIST_MISS_CHANCE = 16,
- SPELLMOD_JUMP_TARGETS = 17,
- SPELLMOD_CHANCE_OF_SUCCESS = 18,
- SPELLMOD_ACTIVATION_TIME = 19,
- SPELLMOD_DAMAGE_MULTIPLIER = 20,
- SPELLMOD_GLOBAL_COOLDOWN = 21,
- SPELLMOD_DOT = 22,
- SPELLMOD_EFFECT3 = 23,
- SPELLMOD_BONUS_MULTIPLIER = 24,
+enum SpellModOp : uint8
+{
+ SPELLMOD_DAMAGE = 0,
+ SPELLMOD_DURATION = 1,
+ SPELLMOD_THREAT = 2,
+ SPELLMOD_EFFECT1 = 3,
+ SPELLMOD_CHARGES = 4,
+ SPELLMOD_RANGE = 5,
+ SPELLMOD_RADIUS = 6,
+ SPELLMOD_CRITICAL_CHANCE = 7,
+ SPELLMOD_ALL_EFFECTS = 8,
+ SPELLMOD_NOT_LOSE_CASTING_TIME = 9,
+ SPELLMOD_CASTING_TIME = 10,
+ SPELLMOD_COOLDOWN = 11,
+ SPELLMOD_EFFECT2 = 12,
+ SPELLMOD_IGNORE_ARMOR = 13,
+ SPELLMOD_COST = 14,
+ SPELLMOD_CRIT_DAMAGE_BONUS = 15,
+ SPELLMOD_RESIST_MISS_CHANCE = 16,
+ SPELLMOD_JUMP_TARGETS = 17,
+ SPELLMOD_CHANCE_OF_SUCCESS = 18,
+ SPELLMOD_ACTIVATION_TIME = 19,
+ SPELLMOD_DAMAGE_MULTIPLIER = 20,
+ SPELLMOD_GLOBAL_COOLDOWN = 21,
+ SPELLMOD_DOT = 22,
+ SPELLMOD_EFFECT3 = 23,
+ SPELLMOD_BONUS_MULTIPLIER = 24,
// spellmod 25
- SPELLMOD_PROC_PER_MINUTE = 26,
- SPELLMOD_VALUE_MULTIPLIER = 27,
- SPELLMOD_RESIST_DISPEL_CHANCE = 28,
- SPELLMOD_CRIT_DAMAGE_BONUS_2 = 29, //one not used spell
- SPELLMOD_SPELL_COST_REFUND_ON_FAIL = 30
-};
+ SPELLMOD_PROC_PER_MINUTE = 26,
+ SPELLMOD_VALUE_MULTIPLIER = 27,
+ SPELLMOD_RESIST_DISPEL_CHANCE = 28,
+ SPELLMOD_CRIT_DAMAGE_BONUS_2 = 29, //one not used spell
+ SPELLMOD_SPELL_COST_REFUND_ON_FAIL = 30,
-#define MAX_SPELLMOD 32
+ MAX_SPELLMOD
+};
enum SpellValueMod
{
@@ -426,7 +426,7 @@ enum TriggerCastFlags
TRIGGERED_IGNORE_CASTER_AURASTATE = 0x00000800, //! Will ignore caster aura states including combat requirements and death state
TRIGGERED_IGNORE_CASTER_MOUNTED_OR_ON_VEHICLE = 0x00002000, //! Will ignore mounted/on vehicle restrictions
TRIGGERED_IGNORE_CASTER_AURAS = 0x00010000, //! Will ignore caster aura restrictions or requirements
- TRIGGERED_DISALLOW_PROC_EVENTS = 0x00020000, //! Disallows proc events from triggered spell (default)
+ // reuse 0x00020000
TRIGGERED_DONT_REPORT_CAST_ERROR = 0x00040000, //! Will return SPELL_FAILED_DONT_REPORT in CheckCast functions
TRIGGERED_IGNORE_EQUIPPED_ITEM_REQUIREMENT = 0x00080000, //! Will ignore equipped item requirements
TRIGGERED_FULL_MASK = 0xFFFFFFFF
@@ -805,13 +805,13 @@ struct DiminishingReturn
: DRGroup(group), stack(0), hitTime(t), hitCount(count)
{ }
- DiminishingGroup DRGroup:16;
- uint16 stack:16;
+ DiminishingGroup DRGroup;
+ uint16 stack;
uint32 hitTime;
uint32 hitCount;
};
-enum MeleeHitOutcome
+enum MeleeHitOutcome : uint8
{
MELEE_HIT_EVADE, MELEE_HIT_MISS, MELEE_HIT_DODGE, MELEE_HIT_BLOCK, MELEE_HIT_PARRY,
MELEE_HIT_GLANCING, MELEE_HIT_CRIT, MELEE_HIT_CRUSHING, MELEE_HIT_NORMAL
@@ -819,21 +819,18 @@ enum MeleeHitOutcome
class DispelInfo
{
-public:
- explicit DispelInfo(Unit* dispeller, uint32 dispellerSpellId, uint8 chargesRemoved) :
- _dispellerUnit(dispeller), _dispellerSpell(dispellerSpellId), _chargesRemoved(chargesRemoved) { }
+ public:
+ explicit DispelInfo(Unit* dispeller, uint32 dispellerSpellId, uint8 chargesRemoved) :
+ _dispellerUnit(dispeller), _dispellerSpell(dispellerSpellId), _chargesRemoved(chargesRemoved) { }
- Unit* GetDispeller() const { return _dispellerUnit; }
- uint32 GetDispellerSpellId() const { return _dispellerSpell; }
- uint8 GetRemovedCharges() const { return _chargesRemoved; }
- void SetRemovedCharges(uint8 amount)
- {
- _chargesRemoved = amount;
- }
-private:
- Unit* _dispellerUnit;
- uint32 _dispellerSpell;
- uint8 _chargesRemoved;
+ Unit* GetDispeller() const { return _dispellerUnit; }
+ uint32 GetDispellerSpellId() const { return _dispellerSpell; }
+ uint8 GetRemovedCharges() const { return _chargesRemoved; }
+ void SetRemovedCharges(uint8 amount) { _chargesRemoved = amount; }
+ private:
+ Unit* _dispellerUnit;
+ uint32 _dispellerSpell;
+ uint8 _chargesRemoved;
};
struct CleanDamage
@@ -849,104 +846,110 @@ struct CleanDamage
};
struct CalcDamageInfo;
+struct SpellNonMeleeDamage;
class TC_GAME_API DamageInfo
{
-private:
- Unit* const m_attacker;
- Unit* const m_victim;
- uint32 m_damage;
- SpellInfo const* const m_spellInfo;
- SpellSchoolMask const m_schoolMask;
- DamageEffectType const m_damageType;
- WeaponAttackType m_attackType;
- uint32 m_absorb;
- uint32 m_resist;
- uint32 m_block;
- uint32 m_hitMask;
-public:
- DamageInfo(Unit* attacker, Unit* victim, uint32 damage, SpellInfo const* spellInfo, SpellSchoolMask schoolMask, DamageEffectType damageType, WeaponAttackType attackType);
- explicit DamageInfo(CalcDamageInfo const& dmgInfo);
- DamageInfo(SpellNonMeleeDamage const& spellNonMeleeDamage, DamageEffectType damageType, WeaponAttackType attackType);
-
- void ModifyDamage(int32 amount);
- void AbsorbDamage(uint32 amount);
- void ResistDamage(uint32 amount);
- void BlockDamage(uint32 amount);
-
- Unit* GetAttacker() const { return m_attacker; }
- Unit* GetVictim() const { return m_victim; }
- SpellInfo const* GetSpellInfo() const { return m_spellInfo; }
- SpellSchoolMask GetSchoolMask() const { return m_schoolMask; }
- DamageEffectType GetDamageType() const { return m_damageType; }
- WeaponAttackType GetAttackType() const { return m_attackType; }
- uint32 GetDamage() const { return m_damage; }
- uint32 GetAbsorb() const { return m_absorb; }
- uint32 GetResist() const { return m_resist; }
- uint32 GetBlock() const { return m_block; }
-
- uint32 GetHitMask() const;
+ private:
+ Unit* const m_attacker;
+ Unit* const m_victim;
+ uint32 m_damage;
+ SpellInfo const* const m_spellInfo;
+ SpellSchoolMask const m_schoolMask;
+ DamageEffectType const m_damageType;
+ WeaponAttackType m_attackType;
+ uint32 m_absorb;
+ uint32 m_resist;
+ uint32 m_block;
+ uint32 m_hitMask;
+ public:
+ DamageInfo(Unit* attacker, Unit* victim, uint32 damage, SpellInfo const* spellInfo, SpellSchoolMask schoolMask, DamageEffectType damageType, WeaponAttackType attackType);
+ explicit DamageInfo(CalcDamageInfo const& dmgInfo);
+ DamageInfo(SpellNonMeleeDamage const& spellNonMeleeDamage, DamageEffectType damageType, WeaponAttackType attackType, uint32 hitMask);
+
+ void ModifyDamage(int32 amount);
+ void AbsorbDamage(uint32 amount);
+ void ResistDamage(uint32 amount);
+ void BlockDamage(uint32 amount);
+
+ Unit* GetAttacker() const { return m_attacker; }
+ Unit* GetVictim() const { return m_victim; }
+ SpellInfo const* GetSpellInfo() const { return m_spellInfo; }
+ SpellSchoolMask GetSchoolMask() const { return m_schoolMask; }
+ DamageEffectType GetDamageType() const { return m_damageType; }
+ WeaponAttackType GetAttackType() const { return m_attackType; }
+ uint32 GetDamage() const { return m_damage; }
+ uint32 GetAbsorb() const { return m_absorb; }
+ uint32 GetResist() const { return m_resist; }
+ uint32 GetBlock() const { return m_block; }
+
+ uint32 GetHitMask() const;
};
class TC_GAME_API HealInfo
{
-private:
- Unit* const _healer;
- Unit* const _target;
- uint32 _heal;
- uint32 _absorb;
- SpellInfo const* const _spellInfo;
- SpellSchoolMask const _schoolMask;
- uint32 _hitMask;
+ private:
+ Unit* const _healer;
+ Unit* const _target;
+ uint32 _heal;
+ uint32 _effectiveHeal;
+ uint32 _absorb;
+ SpellInfo const* const _spellInfo;
+ SpellSchoolMask const _schoolMask;
+ uint32 _hitMask;
-public:
- explicit HealInfo(Unit* healer, Unit* target, uint32 heal, SpellInfo const* spellInfo, SpellSchoolMask schoolMask);
+ public:
+ HealInfo(Unit* healer, Unit* target, uint32 heal, SpellInfo const* spellInfo, SpellSchoolMask schoolMask);
- void AbsorbHeal(uint32 amount);
+ void AbsorbHeal(uint32 amount);
+ void SetEffectiveHeal(uint32 amount) { _effectiveHeal = amount; }
- Unit* GetHealer() const { return _healer; }
- Unit* GetTarget() const { return _target; }
- uint32 GetHeal() const { return _heal; }
- uint32 GetAbsorb() const { return _absorb; }
- SpellInfo const* GetSpellInfo() const { return _spellInfo; };
- SpellSchoolMask GetSchoolMask() const { return _schoolMask; };
+ Unit* GetHealer() const { return _healer; }
+ Unit* GetTarget() const { return _target; }
+ uint32 GetHeal() const { return _heal; }
+ uint32 GetEffectiveHeal() const { return _effectiveHeal; }
+ uint32 GetAbsorb() const { return _absorb; }
+ SpellInfo const* GetSpellInfo() const { return _spellInfo; };
+ SpellSchoolMask GetSchoolMask() const { return _schoolMask; };
- uint32 GetHitMask() const;
+ uint32 GetHitMask() const;
};
class TC_GAME_API ProcEventInfo
{
-public:
- ProcEventInfo(Unit* actor, Unit* actionTarget, Unit* procTarget, uint32 typeMask,
- uint32 spellTypeMask, uint32 spellPhaseMask, uint32 hitMask,
- Spell* spell, DamageInfo* damageInfo, HealInfo* healInfo);
+ public:
+ ProcEventInfo(Unit* actor, Unit* actionTarget, Unit* procTarget, uint32 typeMask,
+ uint32 spellTypeMask, uint32 spellPhaseMask, uint32 hitMask,
+ Spell* spell, DamageInfo* damageInfo, HealInfo* healInfo);
- Unit* GetActor() { return _actor; }
- Unit* GetActionTarget() const { return _actionTarget; }
- Unit* GetProcTarget() const { return _procTarget; }
+ Unit* GetActor() { return _actor; }
+ Unit* GetActionTarget() const { return _actionTarget; }
+ Unit* GetProcTarget() const { return _procTarget; }
- uint32 GetTypeMask() const { return _typeMask; }
- uint32 GetSpellTypeMask() const { return _spellTypeMask; }
- uint32 GetSpellPhaseMask() const { return _spellPhaseMask; }
- uint32 GetHitMask() const { return _hitMask; }
+ uint32 GetTypeMask() const { return _typeMask; }
+ uint32 GetSpellTypeMask() const { return _spellTypeMask; }
+ uint32 GetSpellPhaseMask() const { return _spellPhaseMask; }
+ uint32 GetHitMask() const { return _hitMask; }
- SpellInfo const* GetSpellInfo() const;
- SpellSchoolMask GetSchoolMask() const;
+ SpellInfo const* GetSpellInfo() const;
+ SpellSchoolMask GetSchoolMask() const;
- DamageInfo* GetDamageInfo() const { return _damageInfo; }
- HealInfo* GetHealInfo() const { return _healInfo; }
+ DamageInfo* GetDamageInfo() const { return _damageInfo; }
+ HealInfo* GetHealInfo() const { return _healInfo; }
-private:
- Unit* const _actor;
- Unit* const _actionTarget;
- Unit* const _procTarget;
- uint32 _typeMask;
- uint32 _spellTypeMask;
- uint32 _spellPhaseMask;
- uint32 _hitMask;
- Spell* _spell;
- DamageInfo* _damageInfo;
- HealInfo* _healInfo;
+ Spell const* GetProcSpell() const { return _spell; }
+
+ private:
+ Unit* const _actor;
+ Unit* const _actionTarget;
+ Unit* const _procTarget;
+ uint32 _typeMask;
+ uint32 _spellTypeMask;
+ uint32 _spellPhaseMask;
+ uint32 _hitMask;
+ Spell* _spell;
+ DamageInfo* _damageInfo;
+ HealInfo* _healInfo;
};
// Struct for use in Unit::CalculateMeleeDamage
@@ -966,7 +969,6 @@ struct CalcDamageInfo
WeaponAttackType attackType; //
uint32 procAttacker;
uint32 procVictim;
- uint32 procEx;
uint32 cleanDamage; // Used only for rage calculation
MeleeHitOutcome hitOutCome; /// @todo remove this field (need use TargetState)
};
@@ -1009,7 +1011,7 @@ struct SpellPeriodicAuraLogInfo
bool critical;
};
-uint32 createProcExtendMask(SpellNonMeleeDamage* damageInfo, SpellMissInfo missCondition);
+uint32 createProcHitMask(SpellNonMeleeDamage* damageInfo, SpellMissInfo missCondition);
struct RedirectThreatInfo
{
@@ -1233,8 +1235,6 @@ enum PlayerTotemType
#define ATTACK_DISPLAY_DELAY 200
#define MAX_PLAYER_STEALTH_DETECT_RANGE 30.0f // max distance for detection targets by player
-struct SpellProcEventEntry; // used only privately
-
class TC_GAME_API Unit : public WorldObject
{
public:
@@ -1257,6 +1257,8 @@ class TC_GAME_API Unit : public WorldObject
typedef std::list<AuraApplication *> AuraApplicationList;
typedef std::list<DiminishingReturn> Diminishing;
+ typedef std::deque<std::pair<uint8 /*procEffectMask*/, AuraApplication*>> AuraApplicationProcContainer;
+
typedef std::map<uint8, AuraApplication*> VisibleAuraMap;
virtual ~Unit();
@@ -1430,18 +1432,18 @@ class TC_GAME_API Unit : public WorldObject
uint32 DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDamage = NULL, DamageEffectType damagetype = DIRECT_DAMAGE, SpellSchoolMask damageSchoolMask = SPELL_SCHOOL_MASK_NORMAL, SpellInfo const* spellProto = NULL, bool durabilityLoss = true);
void Kill(Unit* victim, bool durabilityLoss = true);
void KillSelf(bool durabilityLoss = true) { Kill(this, durabilityLoss); }
- int32 DealHeal(Unit* victim, uint32 addhealth);
+ void DealHeal(HealInfo& healInfo);
- void ProcDamageAndSpell(Unit* victim, uint32 procAttacker, uint32 procVictim, uint32 procEx, uint32 amount, WeaponAttackType attType = BASE_ATTACK, SpellInfo const* procSpell = NULL, SpellInfo const* procAura = NULL);
- void ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, SpellInfo const* procSpell, uint32 damage, SpellInfo const* procAura = NULL);
+ void ProcSkillsAndAuras(Unit* actionTarget, uint32 typeMaskActor, uint32 typeMaskActionTarget,
+ uint32 spellTypeMask, uint32 spellPhaseMask, uint32 hitMask, Spell* spell,
+ DamageInfo* damageInfo, HealInfo* healInfo);
- void GetProcAurasTriggeredOnEvent(AuraApplicationList& aurasTriggeringProc, AuraApplicationList* procAuras, ProcEventInfo eventInfo);
+ void GetProcAurasTriggeredOnEvent(AuraApplicationProcContainer& aurasTriggeringProc, AuraApplicationList* procAuras, ProcEventInfo& eventInfo);
void TriggerAurasProcOnEvent(CalcDamageInfo& damageInfo);
- void TriggerAurasProcOnEvent(AuraApplicationList* myProcAuras, AuraApplicationList* targetProcAuras,
- Unit* actionTarget, uint32 typeMaskActor, uint32 typeMaskActionTarget,
+ void TriggerAurasProcOnEvent(Unit* actionTarget, uint32 typeMaskActor, uint32 typeMaskActionTarget,
uint32 spellTypeMask, uint32 spellPhaseMask, uint32 hitMask, Spell* spell,
DamageInfo* damageInfo, HealInfo* healInfo);
- void TriggerAurasProcOnEvent(ProcEventInfo& eventInfo, AuraApplicationList& procAuras);
+ void TriggerAurasProcOnEvent(ProcEventInfo& eventInfo, AuraApplicationProcContainer& procAuras);
void HandleEmoteCommand(uint32 anim_id);
void AttackerStateUpdate (Unit* victim, WeaponAttackType attType = BASE_ATTACK, bool extra = false);
@@ -1548,8 +1550,8 @@ class TC_GAME_API Unit : public WorldObject
virtual void UpdateUnderwaterState(Map* m, float x, float y, float z);
bool isInAccessiblePlaceFor(Creature const* c) const;
- void SendHealSpellLog(Unit* victim, uint32 SpellID, uint32 Damage, uint32 OverHeal, uint32 Absorb, bool critical = false);
- int32 HealBySpell(Unit* victim, SpellInfo const* spellInfo, uint32 addHealth, bool critical = false);
+ void SendHealSpellLog(HealInfo& healInfo, bool critical = false);
+ int32 HealBySpell(HealInfo& healInfo, bool critical = false);
void SendEnergizeSpellLog(Unit* victim, uint32 spellID, int32 damage, Powers powerType);
void EnergizeBySpell(Unit* victim, uint32 SpellID, int32 Damage, Powers powertype);
uint32 SpellNonMeleeDamageLog(Unit* victim, uint32 spellID, uint32 damage);
@@ -2028,7 +2030,7 @@ class TC_GAME_API Unit : public WorldObject
uint32 CalcArmorReducedDamage(Unit* victim, const uint32 damage, SpellInfo const* spellInfo, WeaponAttackType attackType = MAX_ATTACK);
uint32 CalcSpellResistance(Unit* victim, SpellSchoolMask schoolMask, SpellInfo const* spellInfo) const;
void CalcAbsorbResist(Unit* victim, SpellSchoolMask schoolMask, DamageEffectType damagetype, uint32 const damage, uint32* absorb, uint32* resist, SpellInfo const* spellInfo = NULL);
- void CalcHealAbsorb(Unit* victim, SpellInfo const* spellInfo, uint32& healAmount, uint32& absorb);
+ void CalcHealAbsorb(HealInfo& healInfo);
void UpdateSpeed(UnitMoveType mtype);
float GetSpeed(UnitMoveType mtype) const;
@@ -2090,7 +2092,7 @@ class TC_GAME_API Unit : public WorldObject
void UpdateAuraForGroup(uint8 slot);
// proc trigger system
- bool CanProc() const {return !m_procDeep;}
+ bool CanProc() const { return !m_procDeep; }
void SetCantProc(bool apply);
// pet auras
@@ -2261,15 +2263,8 @@ class TC_GAME_API Unit : public WorldObject
bool IsAlwaysDetectableFor(WorldObject const* seer) const override;
void DisableSpline();
+
private:
- bool IsTriggeredAtSpellProcEvent(Unit* victim, Aura* aura, SpellInfo const* procSpell, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, bool isVictim, bool active, SpellProcEventEntry const*& spellProcEvent);
- bool RollProcResult(Unit* victim, Aura* aura, WeaponAttackType attType, bool isVictim, SpellProcEventEntry const* spellProcEvent);
- bool HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, Milliseconds& cooldown);
- bool HandleAuraProc(Unit* victim, uint32 damage, Aura* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, bool* handled);
- bool HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx);
- bool HandleOverrideClassScriptAuraProc(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell);
- bool HandleAuraRaidProcFromChargeWithValue(AuraEffect* triggeredByAura);
- bool HandleAuraRaidProcFromCharge(AuraEffect* triggeredByAura);
void UpdateSplineMovement(uint32 t_diff);
void UpdateSplinePosition();
@@ -2278,6 +2273,8 @@ class TC_GAME_API Unit : public WorldObject
float GetCombatRatingReduction(CombatRating cr) const;
uint32 GetCombatRatingDamageReduction(CombatRating cr, float rate, float cap, uint32 damage) const;
+ void ProcSkillsAndReactives(bool isVictim, Unit* procTarget, uint32 typeMask, uint32 hitMask, WeaponAttackType attType);
+
void SetFeared(bool apply);
void SetConfused(bool apply);
void SetStunned(bool apply);