diff --git a/src/server/game/Combat/ThreatManager.cpp b/src/server/game/Combat/ThreatManager.cpp index 366fe3df76..1a34839bb4 100644 --- a/src/server/game/Combat/ThreatManager.cpp +++ b/src/server/game/Combat/ThreatManager.cpp @@ -308,7 +308,7 @@ void ThreatManager::AddThreat(Unit* target, float amount, SpellInfo const* spell { if (spell->HasAttribute(SPELL_ATTR1_NO_THREAT)) return; - if (!_owner->IsEngaged() && spell->HasAttribute(SPELL_ATTR3_NO_INITIAL_AGGRO)) + if (!_owner->IsEngaged() && spell->HasAttribute(SPELL_ATTR2_NO_INITIAL_THREAT)) return; } diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h index 83108a37ed..5dcdde4e78 100644 --- a/src/server/game/Miscellaneous/SharedDefines.h +++ b/src/server/game/Miscellaneous/SharedDefines.h @@ -477,8 +477,8 @@ enum SpellAttr3 SPELL_ATTR3_DONT_DISPLAY_CHANNEL_BAR = 0x00002000, // 13 Clientside attribute - will not display channeling bar SPELL_ATTR3_IS_HONORLESS_TARGET = 0x00004000, // 14 "Honorless Target" only this spells have this flag SPELL_ATTR3_UNK15 = 0x00008000, // 15 Auto Shoot, Shoot, Throw, - this is autoshot flag - SPELL_ATTR3_CANT_TRIGGER_PROC = 0x00010000, // 16 confirmed with many patchnotes - SPELL_ATTR3_NO_INITIAL_AGGRO = 0x00020000, // 17 Soothe Animal, 39758, Mind Soothe + SPELL_ATTR3_CANT_TRIGGER_CASTER_PROCS = 0x00010000, // 16 Suppress Caster Procs + SPELL_ATTR3_CANT_TRIGGER_TARGET_PROCS = 0x00020000, // 17 Suppress Target Procs SPELL_ATTR3_IGNORE_HIT_RESULT = 0x00040000, // 18 Spell should always hit its target SPELL_ATTR3_DISABLE_PROC = 0x00080000, // 19 during aura proc no spells can trigger (20178, 20375) SPELL_ATTR3_DEATH_PERSISTENT = 0x00100000, // 20 Death persistent spells diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index b6477bfc3c..5d241e9f69 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -5760,8 +5760,12 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const caster->DealDamageMods(target, damage, &absorb); // Set trigger flag - uint32 procAttacker = PROC_FLAG_DONE_PERIODIC; - uint32 procVictim = PROC_FLAG_TAKEN_PERIODIC; + uint32 procAttacker = 0, procVictim = 0; + if (!m_spellInfo->HasAttribute(SPELL_ATTR3_CANT_TRIGGER_CASTER_PROCS)) + procAttacker = PROC_FLAG_DONE_PERIODIC; + if (!m_spellInfo->HasAttribute(SPELL_ATTR3_CANT_TRIGGER_TARGET_PROCS)) + procVictim = PROC_FLAG_TAKEN_PERIODIC; + uint32 hitMask = damageInfo.GetHitMask(); if (damage) { @@ -5850,13 +5854,19 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c damage = damageInfo.GetDamage(); // Set trigger flag - uint32 procAttacker = PROC_FLAG_DONE_PERIODIC; - uint32 procVictim = PROC_FLAG_TAKEN_PERIODIC; + uint32 procAttacker = 0, procVictim = 0; + if (!m_spellInfo->HasAttribute(SPELL_ATTR3_CANT_TRIGGER_CASTER_PROCS)) + procAttacker = PROC_FLAG_DONE_PERIODIC; + if (!m_spellInfo->HasAttribute(SPELL_ATTR3_CANT_TRIGGER_TARGET_PROCS)) + procVictim = PROC_FLAG_TAKEN_PERIODIC; + uint32 hitMask = damageInfo.GetHitMask(); if (damage) { hitMask |= crit ? PROC_HIT_CRITICAL : PROC_HIT_NORMAL; - procVictim |= PROC_FLAG_TAKEN_DAMAGE; + + if (!m_spellInfo->HasAttribute(SPELL_ATTR3_CANT_TRIGGER_TARGET_PROCS)) + procVictim |= PROC_FLAG_TAKEN_DAMAGE; } int32 new_damage = caster->DealDamage(target, damage, &cleanDamage, DOT, GetSpellInfo()->GetSchoolMask(), GetSpellInfo(), false); @@ -6020,8 +6030,12 @@ void AuraEffect::HandlePeriodicHealAurasTick(Unit* target, Unit* caster) const if (GetAuraType() == SPELL_AURA_OBS_MOD_HEALTH) return; - uint32 procAttacker = PROC_FLAG_DONE_PERIODIC; - uint32 procVictim = PROC_FLAG_TAKEN_PERIODIC; + uint32 procAttacker = 0, procVictim = 0; + if (!m_spellInfo->HasAttribute(SPELL_ATTR3_CANT_TRIGGER_CASTER_PROCS)) + procAttacker = PROC_FLAG_DONE_PERIODIC; + if (!m_spellInfo->HasAttribute(SPELL_ATTR3_CANT_TRIGGER_TARGET_PROCS)) + procVictim = PROC_FLAG_TAKEN_PERIODIC; + uint32 hitMask = crit ? PROC_HIT_CRITICAL : PROC_HIT_NORMAL; // ignore item heals if (!haveCastItem) @@ -6192,8 +6206,12 @@ void AuraEffect::HandlePeriodicPowerBurnAuraTick(Unit* target, Unit* caster) con caster->SendSpellNonMeleeDamageLog(&damageInfo); // Set trigger flag - uint32 procAttacker = PROC_FLAG_DONE_PERIODIC; - uint32 procVictim = PROC_FLAG_TAKEN_PERIODIC; + uint32 procAttacker = 0, procVictim = 0; + if (!m_spellInfo->HasAttribute(SPELL_ATTR3_CANT_TRIGGER_CASTER_PROCS)) + procAttacker = PROC_FLAG_DONE_PERIODIC; + if (!m_spellInfo->HasAttribute(SPELL_ATTR3_CANT_TRIGGER_TARGET_PROCS)) + procVictim = PROC_FLAG_TAKEN_PERIODIC; + uint32 hitMask = createProcHitMask(&damageInfo, SPELL_MISS_NONE); uint32 spellTypeMask = PROC_SPELL_TYPE_NO_DMG_HEAL; if (damageInfo.damage) diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 0ae9a61aec..117475f4b4 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -2139,6 +2139,12 @@ void Spell::prepareDataForTriggerSystem() m_procAttacker = PROC_FLAG_DONE_PERIODIC; m_procVictim = PROC_FLAG_TAKEN_PERIODIC; } + + // Some spells may not trigger any procs at all. + if (m_spellInfo->HasAttribute(SPELL_ATTR3_CANT_TRIGGER_CASTER_PROCS)) + m_procAttacker = 0; + if (m_spellInfo->HasAttribute(SPELL_ATTR3_CANT_TRIGGER_CASTER_PROCS)) + m_procVictim = 0; } void Spell::CleanupTargetList() @@ -2521,7 +2527,31 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target) m_spellAura = nullptr; // Set aura to null for every target-make sure that pointer is not used for unit without aura applied // Spells with this flag cannot trigger if effect is cast on self - bool const canEffectTrigger = !m_spellInfo->HasAttribute(SPELL_ATTR3_CANT_TRIGGER_PROC) && unitTarget->CanProc() && (CanExecuteTriggersOnHit(mask) || missInfo == SPELL_MISS_IMMUNE || missInfo == SPELL_MISS_IMMUNE2); + bool const canTriggerCasterProcs = [&]() + { + if (m_spellInfo->HasAttribute(SPELL_ATTR3_CANT_TRIGGER_CASTER_PROCS)) + return false; + + if (!unitTarget->CanProc()) + return false; + + if (!(CanExecuteTriggersOnHit(mask) || missInfo == SPELL_MISS_IMMUNE || missInfo == SPELL_MISS_IMMUNE2)) + return false; + + return true; + }(); + + bool const canTriggerTargetProcs = [&]() + { + if (m_spellInfo->HasAttribute(SPELL_ATTR3_CANT_TRIGGER_TARGET_PROCS)) + return false; + + if (!caster->CanProc()) + return false; + + return true; + }(); + Unit* spellHitTarget = nullptr; if (missInfo == SPELL_MISS_NONE) // In case spell hit target, do all effect on that target @@ -2559,7 +2589,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target) m_needComboPoints = false; // Trigger info was not filled in Spell::prepareDataForTriggerSystem - we do it now - if (canEffectTrigger && !procAttacker && !procVictim) + if ((canTriggerCasterProcs || canTriggerTargetProcs) && !procAttacker && !procVictim) { bool positive = true; if (m_damage > 0) @@ -2580,34 +2610,49 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target) } } - switch (m_spellInfo->DmgClass) + if (canTriggerCasterProcs) { - case SPELL_DAMAGE_CLASS_MAGIC: - if (positive) - { - procAttacker |= PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_POS; - procVictim |= PROC_FLAG_TAKEN_SPELL_MAGIC_DMG_CLASS_POS; - } - else - { - procAttacker |= PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_NEG; - procVictim |= PROC_FLAG_TAKEN_SPELL_MAGIC_DMG_CLASS_NEG; - } - break; - case SPELL_DAMAGE_CLASS_NONE: - if (positive) - { - procAttacker |= PROC_FLAG_DONE_SPELL_NONE_DMG_CLASS_POS; - procVictim |= PROC_FLAG_TAKEN_SPELL_NONE_DMG_CLASS_POS; - } - else - { - procAttacker |= PROC_FLAG_DONE_SPELL_NONE_DMG_CLASS_NEG; - procVictim |= PROC_FLAG_TAKEN_SPELL_NONE_DMG_CLASS_NEG; - } - break; + switch (m_spellInfo->DmgClass) + { + case SPELL_DAMAGE_CLASS_MAGIC: + if (positive) + procAttacker |= PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_POS; + else + procAttacker |= PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_NEG; + break; + case SPELL_DAMAGE_CLASS_NONE: + if (positive) + procAttacker |= PROC_FLAG_DONE_SPELL_NONE_DMG_CLASS_POS; + else + procAttacker |= PROC_FLAG_DONE_SPELL_NONE_DMG_CLASS_NEG; + break; + default: + break; + } + } + + if (canTriggerTargetProcs) + { + switch (m_spellInfo->DmgClass) + { + case SPELL_DAMAGE_CLASS_MAGIC: + if (positive) + procVictim |= PROC_FLAG_TAKEN_SPELL_MAGIC_DMG_CLASS_POS; + else + procVictim |= PROC_FLAG_TAKEN_SPELL_MAGIC_DMG_CLASS_NEG; + break; + case SPELL_DAMAGE_CLASS_NONE: + if (positive) + procVictim |= PROC_FLAG_TAKEN_SPELL_NONE_DMG_CLASS_POS; + else + procVictim |= PROC_FLAG_TAKEN_SPELL_NONE_DMG_CLASS_NEG; + break; + default: + break; + } } } + CallScriptOnHitHandlers(); // All calculated do it! @@ -2630,7 +2675,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target) m_healing = healInfo.GetEffectiveHeal(); // Do triggers for unit - if (canEffectTrigger) + if (canTriggerCasterProcs || canTriggerTargetProcs) caster->ProcSkillsAndAuras(unitTarget, procAttacker, procVictim, PROC_SPELL_TYPE_HEAL, PROC_SPELL_PHASE_HIT, hitMask, this, nullptr, &healInfo); } // Do damage and triggers @@ -2676,7 +2721,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target) } // Do triggers for unit - if (canEffectTrigger) + if (canTriggerCasterProcs || canTriggerTargetProcs) { DamageInfo spellDamageInfo(damageInfo, SPELL_DIRECT_DAMAGE, m_attackType, hitMask); caster->ProcSkillsAndAuras(unitTarget, procAttacker, procVictim, PROC_SPELL_TYPE_DAMAGE, PROC_SPELL_PHASE_HIT, hitMask, this, &spellDamageInfo, nullptr); @@ -2698,7 +2743,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target) SpellNonMeleeDamage damageInfo(caster, unitTarget, m_spellInfo->Id, m_spellSchoolMask); hitMask |= createProcHitMask(&damageInfo, missInfo); // Do triggers for unit - if (canEffectTrigger) + if (canTriggerCasterProcs || canTriggerTargetProcs) { DamageInfo spellNoDamageInfo(damageInfo, NODAMAGE, m_attackType, hitMask); caster->ProcSkillsAndAuras(unitTarget, procAttacker, procVictim, PROC_SPELL_TYPE_NO_DMG_HEAL, PROC_SPELL_PHASE_HIT, hitMask, this, &spellNoDamageInfo, nullptr); @@ -2723,7 +2768,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target) if (missInfo != SPELL_MISS_EVADE && spellHitTarget && !m_caster->IsFriendlyTo(unit) && (!m_spellInfo->IsPositive() || m_spellInfo->HasEffect(SPELL_EFFECT_DISPEL))) { if (Unit* unitCaster = m_caster->ToUnit()) - unitCaster->AtTargetAttacked(unit, m_spellInfo->HasInitialAggro() && !unitCaster->IsIgnoringCombat()); + unitCaster->AtTargetAttacked(unit, m_spellInfo->CausesInitialThreat() && !unitCaster->IsIgnoringCombat()); if (!unit->IsStandState()) unit->SetStandState(UNIT_STAND_STATE_STAND); @@ -2820,7 +2865,7 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleA } } - if (m_originalCaster && unit->IsInCombat() && m_spellInfo->HasInitialAggro()) + if (m_originalCaster && unit->IsInCombat() && m_spellInfo->CausesInitialThreat()) { if (m_originalCaster->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED)) // only do explicit combat forwarding for PvP enabled units m_originalCaster->GetCombatManager().InheritCombatStatesFrom(unit); // for creature v creature combat, the threat forward does it for us @@ -3645,7 +3690,7 @@ void Spell::_cast(bool skipCheck) // Handle procs on cast uint32 procAttacker = m_procAttacker; - if (!procAttacker) + if (!procAttacker && !m_spellInfo->HasAttribute(SPELL_ATTR3_CANT_TRIGGER_CASTER_PROCS)) { if (m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_MAGIC) procAttacker = m_spellInfo->IsPositive() ? PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_POS : PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_NEG; @@ -3855,7 +3900,7 @@ void Spell::_handle_finish_phase() return; uint32 procAttacker = m_procAttacker; - if (!procAttacker) + if (!procAttacker && !m_spellInfo->HasAttribute(SPELL_ATTR3_CANT_TRIGGER_CASTER_PROCS)) { if (m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_MAGIC) procAttacker = m_spellInfo->IsPositive() ? PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_POS : PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_NEG; @@ -5291,7 +5336,7 @@ void Spell::HandleThreatSpells() if (m_UniqueTargetInfo.empty()) return; - if (!m_spellInfo->HasInitialAggro()) + if (!m_spellInfo->CausesInitialThreat()) return; float threat = 0.0f; @@ -5302,7 +5347,7 @@ void Spell::HandleThreatSpells() threat += threatEntry->flatMod; } - else if (!m_spellInfo->HasAttribute(SPELL_ATTR0_CU_NO_INITIAL_THREAT) && !m_spellInfo->HasAttribute(SPELL_ATTR2_NO_INITIAL_THREAT)) + else if (!m_spellInfo->HasAttribute(SPELL_ATTR0_CU_NO_INITIAL_THREAT)) threat += m_spellInfo->SpellLevel; // past this point only multiplicative effects occur @@ -7727,7 +7772,7 @@ void Spell::DoAllEffectOnLaunchTarget(TargetInfo& targetInfo, float* multiplier) if (m_originalCaster && targetInfo.missCondition != SPELL_MISS_EVADE && !m_originalCaster->IsFriendlyTo(unit) && (!m_spellInfo->IsPositive() || m_spellInfo->HasEffect(SPELL_EFFECT_DISPEL)) - && (m_spellInfo->HasInitialAggro() || unit->IsEngaged()) + && (m_spellInfo->CausesInitialThreat() || unit->IsEngaged()) && !m_originalCaster->IsIgnoringCombat()) m_originalCaster->SetInCombatWith(unit); diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp index 53b69ea6ec..1d668fc8f7 100644 --- a/src/server/game/Spells/SpellInfo.cpp +++ b/src/server/game/Spells/SpellInfo.cpp @@ -1479,9 +1479,9 @@ bool SpellInfo::IsAutoRepeatRangedSpell() const return HasAttribute(SPELL_ATTR2_AUTOREPEAT_FLAG); } -bool SpellInfo::HasInitialAggro() const +bool SpellInfo::CausesInitialThreat() const { - return !(HasAttribute(SPELL_ATTR1_NO_THREAT) || HasAttribute(SPELL_ATTR3_NO_INITIAL_AGGRO)); + return !(HasAttribute(SPELL_ATTR1_NO_THREAT) || HasAttribute(SPELL_ATTR2_NO_INITIAL_THREAT)); } WeaponAttackType SpellInfo::GetAttackType() const diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h index 95c05536e4..56c7d5152f 100644 --- a/src/server/game/Spells/SpellInfo.h +++ b/src/server/game/Spells/SpellInfo.h @@ -528,7 +528,7 @@ class TC_GAME_API SpellInfo bool IsBreakingStealth() const; bool IsRangedWeaponSpell() const; bool IsAutoRepeatRangedSpell() const; - bool HasInitialAggro() const; + bool CausesInitialThreat() const; WeaponAttackType GetAttackType() const; diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index 66113d98cc..61d4bbac7c 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -3247,7 +3247,7 @@ void SpellMgr::LoadSpellInfoCorrections() // Vampiric Embrace ApplySpellFix({ 15290 }, [](SpellInfo* spellInfo) { - spellInfo->AttributesEx3 |= SPELL_ATTR3_NO_INITIAL_AGGRO; + spellInfo->AttributesEx3 |= SPELL_ATTR2_NO_INITIAL_THREAT; }); // Vampiric Touch (dispel effect) @@ -3763,12 +3763,6 @@ void SpellMgr::LoadSpellInfoCorrections() spellInfo->AttributesEx3 |= SPELL_ATTR3_STACK_FOR_DIFF_CASTERS; }); - // Lock Players and Tap Chest - ApplySpellFix({ 72347 }, [](SpellInfo* spellInfo) - { - spellInfo->AttributesEx3 &= ~SPELL_ATTR3_NO_INITIAL_AGGRO; - }); - // Lock and Load (Rank 1) ApplySpellFix({ 56342 }, [](SpellInfo* spellInfo) { @@ -4578,7 +4572,7 @@ void SpellMgr::LoadSpellInfoCorrections() ApplySpellFix({ 76194, 91042 }, [](SpellInfo* spellInfo) { spellInfo->MaxAffectedTargets = 1; - spellInfo->AttributesEx3 |= SPELL_ATTR3_NO_INITIAL_AGGRO; + spellInfo->AttributesEx3 |= SPELL_ATTR2_NO_INITIAL_THREAT; }); // Shadow Gale @@ -4683,7 +4677,7 @@ void SpellMgr::LoadSpellInfoCorrections() // Destruction Protocoll ApplySpellFix({ 77437 }, [](SpellInfo* spellInfo) { - spellInfo->AttributesEx3 |= SPELL_ATTR3_NO_INITIAL_AGGRO; + spellInfo->AttributesEx3 |= SPELL_ATTR2_NO_INITIAL_THREAT; }); // Crumbling Ruin @@ -4774,7 +4768,7 @@ void SpellMgr::LoadSpellInfoCorrections() // Feral Charge (Cat Form ApplySpellFix({ 49376 }, [](SpellInfo* spellInfo) { - spellInfo->AttributesEx3 &= ~SPELL_ATTR3_CANT_TRIGGER_PROC; + spellInfo->AttributesEx3 &= ~SPELL_ATTR3_CANT_TRIGGER_CASTER_PROCS; }); // @@ -4981,7 +4975,7 @@ void SpellMgr::LoadSpellInfoCorrections() 97352 }, [](SpellInfo* spellInfo) { - spellInfo->AttributesEx3 |= SPELL_ATTR3_NO_INITIAL_AGGRO; + spellInfo->AttributesEx3 |= SPELL_ATTR2_NO_INITIAL_THREAT; }); // Poison Bolt Volley @@ -5165,7 +5159,7 @@ void SpellMgr::LoadSpellInfoCorrections() 93299 }, [](SpellInfo* spellInfo) { - spellInfo->AttributesEx3 |= SPELL_ATTR3_NO_INITIAL_AGGRO; + spellInfo->AttributesEx3 |= SPELL_ATTR2_NO_INITIAL_THREAT; }); // Lightning Clouds @@ -5243,7 +5237,7 @@ void SpellMgr::LoadSpellInfoCorrections() 106464 // Enter the Dream }, [](SpellInfo* spellInfo) { - spellInfo->AttributesEx3 |= SPELL_ATTR3_NO_INITIAL_AGGRO; + spellInfo->AttributesEx3 |= SPELL_ATTR2_NO_INITIAL_THREAT; }); // Root @@ -5532,7 +5526,7 @@ void SpellMgr::LoadSpellInfoCorrections() // Debilitating Slime ApplySpellFix({ 77615 }, [](SpellInfo* spellInfo) { - spellInfo->AttributesEx3 |= SPELL_ATTR3_NO_INITIAL_AGGRO; + spellInfo->AttributesEx3 |= SPELL_ATTR2_NO_INITIAL_THREAT; }); // Dragon Orb @@ -5642,7 +5636,7 @@ void SpellMgr::LoadSpellInfoCorrections() 91884 }, [](SpellInfo* spellInfo) { - spellInfo->AttributesEx3 |= SPELL_ATTR3_NO_INITIAL_AGGRO; + spellInfo->AttributesEx3 |= SPELL_ATTR2_NO_INITIAL_THREAT; spellInfo->Effects[EFFECT_1].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_4_YARDS); });