fix(Core/Spells): Ensures that procs triggered by another aura are proccessed in the first place. (#5075)

This commit is contained in:
UltraNix
2021-04-06 14:24:46 +02:00
committed by GitHub
parent c5d4fe20a8
commit 63d78a2f9e

View File

@@ -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<uint32, EFFECT_ALL> 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