mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-03-16 05:55:07 +00:00
refactor(Core/Spells): QAston proc system (#24233)
Co-authored-by: blinkysc <blinkysc@users.noreply.github.com> Co-authored-by: QAston <qaston@gmail.com> Co-authored-by: joschiwald <joschiwald@online.de> Co-authored-by: ariel- <ariel-@users.noreply.github.com> Co-authored-by: Kitzunu <24550914+Kitzunu@users.noreply.github.com> Co-authored-by: blinkysc <your-github-email@example.com> Co-authored-by: Tereneckla <Tereneckla@users.noreply.github.com> Co-authored-by: Andrew <47818697+Nyeriah@users.noreply.github.com>
This commit is contained in:
@@ -2267,7 +2267,7 @@ void Spell::prepareDataForTriggerSystem(AuraEffect const* /*triggeredByAura*/)
|
||||
else if (HasTriggeredCastFlag(TRIGGERED_DISALLOW_PROC_EVENTS))
|
||||
m_procEx |= PROC_EX_INTERNAL_TRIGGERED;
|
||||
}
|
||||
// Totem casts require spellfamilymask defined in spell_proc_event to proc
|
||||
// Totem casts require spellfamilymask defined in spell_proc to proc
|
||||
if (m_originalCaster && m_caster != m_originalCaster && m_caster->IsCreature() && m_caster->ToCreature()->IsTotem() && m_caster->IsControlledByPlayer())
|
||||
m_procEx |= PROC_EX_INTERNAL_REQ_FAMILY;
|
||||
}
|
||||
@@ -2648,7 +2648,6 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)
|
||||
// Fill base trigger info
|
||||
uint32 procAttacker = m_procAttacker;
|
||||
uint32 procVictim = m_procVictim;
|
||||
uint32 procEx = m_procEx;
|
||||
|
||||
// Trigger info was not filled in spell::preparedatafortriggersystem - we do it now
|
||||
if (canEffectTrigger && !procAttacker && !procVictim)
|
||||
@@ -2705,20 +2704,21 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)
|
||||
uint32 addhealth = m_healing;
|
||||
|
||||
if (crit)
|
||||
{
|
||||
procEx |= PROC_EX_CRITICAL_HIT;
|
||||
addhealth = Unit::SpellCriticalHealingBonus(caster, m_spellInfo, addhealth, nullptr);
|
||||
}
|
||||
else
|
||||
procEx |= PROC_EX_NORMAL_HIT;
|
||||
|
||||
HealInfo healInfo(caster, unitTarget, addhealth, m_spellInfo, m_spellInfo->GetSchoolMask());
|
||||
|
||||
// Set hitMask based on crit
|
||||
if (crit)
|
||||
healInfo.AddHitMask(PROC_HIT_CRITICAL);
|
||||
else
|
||||
healInfo.AddHitMask(PROC_HIT_NORMAL);
|
||||
|
||||
// Xinef: override with forced crit, only visual result
|
||||
if (GetSpellValue()->ForcedCritResult)
|
||||
{
|
||||
crit = true;
|
||||
procEx |= PROC_EX_CRITICAL_HIT;
|
||||
healInfo.AddHitMask(PROC_HIT_CRITICAL);
|
||||
}
|
||||
|
||||
int32 gain = caster->HealBySpell(healInfo, crit);
|
||||
@@ -2729,14 +2729,17 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)
|
||||
unitTarget->getHostileRefMgr().threatAssist(caster, threat, m_spellInfo);
|
||||
m_healing = gain;
|
||||
|
||||
// Xinef: if heal acutally healed something, add no overheal flag
|
||||
// Xinef: if heal actually healed something, add no overheal flag
|
||||
if (m_healing)
|
||||
procEx |= PROC_EX_NO_OVERHEAL;
|
||||
healInfo.AddHitMask(PROC_EX_NO_OVERHEAL);
|
||||
|
||||
// Do triggers for unit (reflect triggers passed on hit phase for correct drop charge)
|
||||
if (canEffectTrigger)
|
||||
Unit::ProcDamageAndSpell(caster, unitTarget, procAttacker, procVictim, procEx, addhealth, m_attackType, m_spellInfo, m_triggeredByAuraSpell.spellInfo,
|
||||
{
|
||||
uint32 hitMask = m_procEx | healInfo.GetHitMask();
|
||||
Unit::ProcSkillsAndAuras(caster, unitTarget, procAttacker, procVictim, hitMask, addhealth, m_attackType, m_spellInfo, m_triggeredByAuraSpell.spellInfo,
|
||||
m_triggeredByAuraSpell.effectIndex, this, nullptr, &healInfo);
|
||||
}
|
||||
}
|
||||
// Do damage and triggers
|
||||
else if (m_damage > 0)
|
||||
@@ -2802,7 +2805,6 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)
|
||||
if (reflectedSpell)
|
||||
effectUnit->SendSpellNonMeleeReflectLog(&damageInfo, effectUnit);
|
||||
|
||||
procEx |= createProcExtendMask(&damageInfo, missInfo);
|
||||
procVictim |= PROC_FLAG_TAKEN_DAMAGE;
|
||||
|
||||
caster->DealSpellDamage(&damageInfo, true, this);
|
||||
@@ -2813,13 +2815,14 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)
|
||||
// Do triggers for unit (reflect triggers passed on hit phase for correct drop charge)
|
||||
if (canEffectTrigger)
|
||||
{
|
||||
DamageInfo dmgInfo(damageInfo, SPELL_DIRECT_DAMAGE);
|
||||
Unit::ProcDamageAndSpell(caster, unitTarget, procAttacker, procVictim, procEx, damageInfo.damage, m_attackType, m_spellInfo, m_triggeredByAuraSpell.spellInfo,
|
||||
DamageInfo dmgInfo(damageInfo, SPELL_DIRECT_DAMAGE, m_attackType, missInfo);
|
||||
uint32 hitMask = m_procEx | dmgInfo.GetHitMask();
|
||||
Unit::ProcSkillsAndAuras(caster, unitTarget, procAttacker, procVictim, hitMask, damageInfo.damage, m_attackType, m_spellInfo, m_triggeredByAuraSpell.spellInfo,
|
||||
m_triggeredByAuraSpell.effectIndex, this, &dmgInfo);
|
||||
|
||||
if (caster->IsPlayer() && m_spellInfo->HasAttribute(SPELL_ATTR0_CANCELS_AUTO_ATTACK_COMBAT) == 0 &&
|
||||
m_spellInfo->HasAttribute(SPELL_ATTR4_SUPPRESS_WEAPON_PROCS) == 0 && (m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_MELEE || m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_RANGED))
|
||||
caster->ToPlayer()->CastItemCombatSpell(unitTarget, m_attackType, procVictim, procEx);
|
||||
caster->ToPlayer()->CastItemCombatSpell(unitTarget, m_attackType, procVictim, dmgInfo.GetHitMask());
|
||||
}
|
||||
|
||||
m_damage = damageInfo.damage;
|
||||
@@ -2829,19 +2832,19 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)
|
||||
{
|
||||
// Fill base damage struct (unitTarget - is real spell target)
|
||||
SpellNonMeleeDamage damageInfo(caster, unitTarget, m_spellInfo, m_spellSchoolMask);
|
||||
procEx |= createProcExtendMask(&damageInfo, missInfo);
|
||||
// Do triggers for unit (reflect triggers passed on hit phase for correct drop charge)
|
||||
if (canEffectTrigger)
|
||||
{
|
||||
DamageInfo dmgInfo(damageInfo, NODAMAGE);
|
||||
Unit::ProcDamageAndSpell(caster, unitTarget, procAttacker, procVictim, procEx, 0, m_attackType, m_spellInfo, m_triggeredByAuraSpell.spellInfo,
|
||||
DamageInfo dmgInfo(damageInfo, NODAMAGE, m_attackType, missInfo);
|
||||
uint32 hitMask = m_procEx | dmgInfo.GetHitMask();
|
||||
Unit::ProcSkillsAndAuras(caster, unitTarget, procAttacker, procVictim, hitMask, 0, m_attackType, m_spellInfo, m_triggeredByAuraSpell.spellInfo,
|
||||
m_triggeredByAuraSpell.effectIndex, this, &dmgInfo);
|
||||
|
||||
// Xinef: eg. rogue poisons can proc off cheap shot, etc. so this block should be here also
|
||||
// Xinef: ofc count only spells that HIT the target, little hack used to fool the system
|
||||
if ((procEx & PROC_EX_NORMAL_HIT || procEx & PROC_EX_CRITICAL_HIT) && caster->IsPlayer() && m_spellInfo->HasAttribute(SPELL_ATTR0_CANCELS_AUTO_ATTACK_COMBAT) == 0 &&
|
||||
if ((dmgInfo.GetHitMask() & (PROC_HIT_NORMAL | PROC_HIT_CRITICAL)) && caster->IsPlayer() && m_spellInfo->HasAttribute(SPELL_ATTR0_CANCELS_AUTO_ATTACK_COMBAT) == 0 &&
|
||||
m_spellInfo->HasAttribute(SPELL_ATTR4_SUPPRESS_WEAPON_PROCS) == 0 && (m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_MELEE || m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_RANGED))
|
||||
caster->ToPlayer()->CastItemCombatSpell(unitTarget, m_attackType, procVictim | PROC_FLAG_TAKEN_DAMAGE, procEx);
|
||||
caster->ToPlayer()->CastItemCombatSpell(unitTarget, m_attackType, procVictim | PROC_FLAG_TAKEN_DAMAGE, dmgInfo.GetHitMask());
|
||||
}
|
||||
|
||||
// Failed Pickpocket, reveal rogue
|
||||
@@ -3194,20 +3197,6 @@ void Spell::DoTriggersOnSpellHit(Unit* unit, uint8 effMask)
|
||||
/// @todo: move this code to scripts
|
||||
if (m_preCastSpell)
|
||||
{
|
||||
// Paladin immunity shields
|
||||
if (m_preCastSpell == 61988)
|
||||
{
|
||||
// Cast Forbearance
|
||||
m_caster->CastSpell(unit, 25771, true);
|
||||
// Cast Avenging Wrath Marker
|
||||
unit->CastSpell(unit, 61987, true);
|
||||
}
|
||||
|
||||
// Avenging Wrath
|
||||
if (m_preCastSpell == 61987)
|
||||
// Cast the serverside immunity shield marker
|
||||
m_caster->CastSpell(unit, 61988, true);
|
||||
|
||||
// Fearie Fire (Feral) - damage
|
||||
if (m_preCastSpell == 60089)
|
||||
m_caster->CastSpell(unit, m_preCastSpell, true);
|
||||
@@ -3896,48 +3885,6 @@ void Spell::_cast(bool skipCheck)
|
||||
// we must send smsg_spell_go packet before m_castItem delete in TakeCastItem()...
|
||||
SendSpellGo();
|
||||
|
||||
if (modOwner)
|
||||
modOwner->SetSpellModTakingSpell(this, false);
|
||||
|
||||
if (m_originalCaster)
|
||||
{
|
||||
// Handle procs on cast
|
||||
uint32 procAttacker = m_procAttacker;
|
||||
if (!procAttacker)
|
||||
{
|
||||
bool IsPositive = m_spellInfo->IsPositive();
|
||||
if (m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_MAGIC)
|
||||
{
|
||||
procAttacker = IsPositive ? PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_POS : PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_NEG;
|
||||
}
|
||||
else
|
||||
{
|
||||
procAttacker = IsPositive ? PROC_FLAG_DONE_SPELL_NONE_DMG_CLASS_POS : PROC_FLAG_DONE_SPELL_NONE_DMG_CLASS_NEG;
|
||||
}
|
||||
}
|
||||
|
||||
uint32 procEx = PROC_EX_NORMAL_HIT;
|
||||
|
||||
for (std::list<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
|
||||
{
|
||||
if (ihit->missCondition != SPELL_MISS_NONE)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!ihit->crit)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
procEx |= PROC_EX_CRITICAL_HIT;
|
||||
break;
|
||||
}
|
||||
|
||||
Unit::ProcDamageAndSpell(m_originalCaster, m_originalCaster, procAttacker, PROC_FLAG_NONE, procEx, 1, BASE_ATTACK, m_spellInfo, m_triggeredByAuraSpell.spellInfo,
|
||||
m_triggeredByAuraSpell.effectIndex, this, nullptr, nullptr, PROC_SPELL_PHASE_CAST);
|
||||
}
|
||||
|
||||
if (modOwner)
|
||||
modOwner->SetSpellModTakingSpell(this, true);
|
||||
|
||||
@@ -4012,6 +3959,46 @@ void Spell::_cast(bool skipCheck)
|
||||
if (modOwner)
|
||||
modOwner->SetSpellModTakingSpell(this, false);
|
||||
|
||||
// Handle procs on cast - only for non-triggered spells
|
||||
// Triggered spells (from auras, items, etc.) should not fire CAST phase procs
|
||||
// as they are not player-initiated casts. This prevents issues like Arcane Potency
|
||||
// charges being consumed by periodic damage effects (e.g., Blizzard ticks).
|
||||
// Must be called AFTER handle_immediate() so spell mods (like Missile Barrage's
|
||||
// duration reduction) are applied before the aura is consumed by the proc.
|
||||
if (m_originalCaster && !IsTriggered())
|
||||
{
|
||||
uint32 procAttacker = m_procAttacker;
|
||||
if (!procAttacker)
|
||||
{
|
||||
bool IsPositive = m_spellInfo->IsPositive();
|
||||
if (m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_MAGIC)
|
||||
{
|
||||
procAttacker = IsPositive ? PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_POS : PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_NEG;
|
||||
}
|
||||
else
|
||||
{
|
||||
procAttacker = IsPositive ? PROC_FLAG_DONE_SPELL_NONE_DMG_CLASS_POS : PROC_FLAG_DONE_SPELL_NONE_DMG_CLASS_NEG;
|
||||
}
|
||||
}
|
||||
|
||||
uint32 hitMask = PROC_HIT_NORMAL;
|
||||
|
||||
for (std::list<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
|
||||
{
|
||||
if (ihit->missCondition != SPELL_MISS_NONE)
|
||||
continue;
|
||||
|
||||
if (!ihit->crit)
|
||||
continue;
|
||||
|
||||
hitMask |= PROC_HIT_CRITICAL;
|
||||
break;
|
||||
}
|
||||
|
||||
Unit::ProcSkillsAndAuras(m_originalCaster, m_originalCaster, procAttacker, PROC_FLAG_NONE, hitMask, 1, BASE_ATTACK, m_spellInfo, m_triggeredByAuraSpell.spellInfo,
|
||||
m_triggeredByAuraSpell.effectIndex, this, nullptr, nullptr, PROC_SPELL_PHASE_CAST);
|
||||
}
|
||||
|
||||
if (std::vector<int32> const* spell_triggered = sSpellMgr->GetSpellLinked(m_spellInfo->Id))
|
||||
{
|
||||
for (int32 id : *spell_triggered)
|
||||
@@ -4269,24 +4256,20 @@ void Spell::_handle_finish_phase()
|
||||
}
|
||||
}
|
||||
|
||||
uint32 procEx = PROC_EX_NORMAL_HIT;
|
||||
uint32 hitMask = PROC_HIT_NORMAL;
|
||||
for (std::list<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
|
||||
{
|
||||
if (ihit->missCondition != SPELL_MISS_NONE)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!ihit->crit)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
procEx |= PROC_EX_CRITICAL_HIT;
|
||||
hitMask |= PROC_HIT_CRITICAL;
|
||||
break;
|
||||
}
|
||||
|
||||
Unit::ProcDamageAndSpell(m_originalCaster, m_originalCaster, procAttacker, PROC_FLAG_NONE, procEx, 1, BASE_ATTACK, m_spellInfo, m_triggeredByAuraSpell.spellInfo,
|
||||
Unit::ProcSkillsAndAuras(m_originalCaster, m_originalCaster, procAttacker, PROC_FLAG_NONE, hitMask, 1, BASE_ATTACK, m_spellInfo, m_triggeredByAuraSpell.spellInfo,
|
||||
m_triggeredByAuraSpell.effectIndex, this, nullptr, nullptr, PROC_SPELL_PHASE_FINISH);
|
||||
}
|
||||
}
|
||||
@@ -8209,7 +8192,7 @@ bool ReflectEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
|
||||
{
|
||||
Unit* target = ObjectAccessor::GetUnit(*_caster, _targetGUID);
|
||||
if (target && _caster->IsInMap(target))
|
||||
Unit::ProcDamageAndSpell(_caster, target, PROC_FLAG_NONE, PROC_FLAG_TAKEN_SPELL_MAGIC_DMG_CLASS_NEG, PROC_EX_REFLECT, 1, BASE_ATTACK, _spellInfo);
|
||||
Unit::ProcSkillsAndAuras(_caster, target, PROC_FLAG_NONE, PROC_FLAG_TAKEN_SPELL_MAGIC_DMG_CLASS_NEG, PROC_EX_REFLECT, 1, BASE_ATTACK, _spellInfo);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user