diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index fc562b6db..8aae8bcb0 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -15219,15 +15219,22 @@ bool Unit::isFrozen() const struct ProcTriggeredData { - ProcTriggeredData(Aura* _aura) - : aura(_aura) + ProcTriggeredData(Aura* _aura) : aura(_aura) { effMask = 0; spellProcEvent = nullptr; + triggerSpelId.fill(0); } + SpellProcEventEntry const* spellProcEvent; Aura* aura; uint32 effMask; + std::array triggerSpelId; + + bool operator==(const uint32 spellId) const + { + return aura->GetId() == spellId; + } }; typedef std::list< ProcTriggeredData > ProcTriggeredList; @@ -15571,24 +15578,74 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u //bool triggered = !spellProto->HasAttribute(SPELL_ATTR3_CAN_PROC_WITH_TRIGGERED) ? // (procExtra & PROC_EX_INTERNAL_TRIGGERED && !(procFlag & PROC_FLAG_DONE_TRAP_ACTIVATION)) : false; + bool hasTriggeredProc = 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 == nullptr - skip if (!isTriggerAura[aurEff->GetAuraType()] && triggerData.spellProcEvent == nullptr) continue; + + switch (aurEff->GetAuraType()) + { + case SPELL_AURA_PROC_TRIGGER_SPELL: + case SPELL_AURA_MANA_SHIELD: + case SPELL_AURA_DUMMY: + case SPELL_AURA_PROC_TRIGGER_SPELL_WITH_VALUE: + if (uint32 triggerSpellId = aurEff->GetSpellInfo()->Effects[i].TriggerSpell) + { + triggerData.triggerSpelId[i] = triggerSpellId; + hasTriggeredProc = true; + } + break; + default: + break; + } + // Some spells must always trigger //if (isAlwaysTriggeredAura[aurEff->GetAuraType()]) triggerData.effMask |= 1 << i; } } + if (triggerData.effMask) - procTriggered.push_front(triggerData); + { + // If there is aura that triggers another proc aura, make sure that the triggered one is going to be proccessed on top of it + if (hasTriggeredProc) + { + bool proccessed = false; + for (uint8 i = 0; i < EFFECT_ALL; ++i) + { + if (uint32 triggeredSpellId = triggerData.triggerSpelId[i]) + { + auto iter = std::find(procTriggered.begin(), procTriggered.end(), triggeredSpellId); + if (iter != procTriggered.end()) + { + std::advance(iter, 1); + procTriggered.insert(iter, triggerData); + proccessed = true; + break; + } + } + } + + if (!proccessed) + { + procTriggered.push_front(triggerData); + } + } + else + { + procTriggered.push_front(triggerData); + } + } } // Nothing found