*Re-commit some reverted patch: aura stacking check. By QAston.

--HG--
branch : trunk
This commit is contained in:
megamage
2008-11-20 18:13:10 -06:00
parent e5e6ff9f1b
commit 182c997573
3 changed files with 80 additions and 58 deletions
+66 -13
View File
@@ -99,7 +99,7 @@ bool IsPassiveSpell(uint32 spellId)
return (spellInfo->Attributes & SPELL_ATTR_PASSIVE) != 0;
}
bool IsNoStackAuraDueToAura(uint32 spellId_1, uint32 effIndex_1, uint32 spellId_2, uint32 effIndex_2)
/*bool IsNoStackAuraDueToAura(uint32 spellId_1, uint32 effIndex_1, uint32 spellId_2, uint32 effIndex_2)
{
SpellEntry const *spellInfo_1 = sSpellStore.LookupEntry(spellId_1);
SpellEntry const *spellInfo_2 = sSpellStore.LookupEntry(spellId_2);
@@ -113,7 +113,7 @@ bool IsNoStackAuraDueToAura(uint32 spellId_1, uint32 effIndex_1, uint32 spellId_
return false;
return true;
}
}*/
int32 CompareAuraRanks(uint32 spellId_1, uint32 effIndex_1, uint32 spellId_2, uint32 effIndex_2)
{
@@ -244,14 +244,24 @@ bool IsSingleFromSpellSpecificPerCaster(uint32 spellSpec1,uint32 spellSpec2)
case SPELL_STING:
case SPELL_CURSE:
case SPELL_ASPECT:
case SPELL_POSITIVE_SHOUT:
case SPELL_JUDGEMENT:
case SPELL_WARLOCK_CORRUPTION:
return spellSpec1==spellSpec2;
default:
return false;
}
}
bool IsSingleFromSpellSpecificPerTarget(uint32 spellSpec1,uint32 spellSpec2)
{
switch(spellSpec1)
{
case SPELL_TRACKER:
case SPELL_WARLOCK_ARMOR:
case SPELL_MAGE_ARMOR:
case SPELL_ELEMENTAL_SHIELD:
case SPELL_MAGE_POLYMORPH:
case SPELL_POSITIVE_SHOUT:
case SPELL_JUDGEMENT:
case SPELL_WARLOCK_CORRUPTION:
return spellSpec1==spellSpec2;
case SPELL_BATTLE_ELIXIR:
return spellSpec2==SPELL_BATTLE_ELIXIR
@@ -1030,10 +1040,10 @@ bool SpellMgr::canStackSpellRanks(SpellEntry const *spellInfo)
return true;
}
bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) const
bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2, bool sameCaster) const
{
if(spellId_1 == spellId_2) // auras due to the same spell
return false;
//if(spellId_1 == spellId_2) // auras due to the same spell
// return false;
SpellEntry const *spellInfo_1 = sSpellStore.LookupEntry(spellId_1);
SpellEntry const *spellInfo_2 = sSpellStore.LookupEntry(spellId_2);
@@ -1041,22 +1051,65 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons
if(!spellInfo_1 || !spellInfo_2)
return false;
SpellSpecific spellId_spec_1 = GetSpellSpecific(spellId_1);
SpellSpecific spellId_spec_2 = GetSpellSpecific(spellId_2);
if (spellId_spec_1 && spellId_spec_2)
if (IsSingleFromSpellSpecificPerTarget(spellId_spec_1, spellId_spec_2)
||(IsSingleFromSpellSpecificPerCaster(spellId_spec_1, spellId_spec_2) && sameCaster))
return true;
if(spellInfo_1->SpellFamilyName != spellInfo_2->SpellFamilyName)
return false;
if(!spellInfo_1->SpellFamilyName) // generic spells
// generic spells
if(!spellInfo_1->SpellFamilyName)
{
if(!spellInfo_1->SpellIconID
|| spellInfo_1->SpellIconID != spellInfo_2->SpellIconID)
return false;
}
else if (spellInfo_1->SpellFamilyFlags != spellInfo_2->SpellFamilyFlags)
return false;
// if both elixirs are not battle/guardian/potions/flasks then always stack
else if(spellInfo_1->SpellFamilyName == SPELLFAMILY_POTION)
{
if(spellId_spec_1 || spellId_spec_2))
return false;
}
// check for class spells
else
{
if (spellInfo_1->SpellFamilyFlags != spellInfo_2->SpellFamilyFlags)
return false;
}
for(uint32 i = 0; i < 3; ++i)
{
if(spellInfo_1->Effect[i] != spellInfo_2->Effect[i]
|| spellInfo_1->EffectApplyAuraName[i] != spellInfo_2->EffectApplyAuraName[i])
return false;
|| spellInfo_1->EffectApplyAuraName[i] != spellInfo_2->EffectApplyAuraName[i]
|| spellInfo_1->EffectMiscValue[i] != spellInfo_2->EffectMiscValue[i]) // paladin resist aura
return false; // need itemtype check? need an example to add that check
if(spellInfo_1->EffectApplyAuraName[i] // both spell has the same auras
&& !sameCaster
&& spellInfo_1->Effect[i] != SPELL_EFFECT_APPLY_AREA_AURA_PARTY) // not area auras (shaman totem)
// a better check may be effect == SPELL_EFFECT_APPLY_AURA
{
switch(spellInfo_1->EffectApplyAuraName[i])
{
// DOT or HOT from different casters will stack
case SPELL_AURA_PERIODIC_DAMAGE:
case SPELL_AURA_PERIODIC_HEAL:
case SPELL_AURA_PERIODIC_TRIGGER_SPELL:
case SPELL_AURA_PERIODIC_ENERGIZE:
case SPELL_AURA_PERIODIC_MANA_LEECH:
case SPELL_AURA_PERIODIC_LEECH:
return false;
default:
break;
}
}
}
return true;
}
+4 -3
View File
@@ -284,7 +284,7 @@ inline bool IsSpellHaveEffect(SpellEntry const *spellInfo, SpellEffects effect)
return false;
}
bool IsNoStackAuraDueToAura(uint32 spellId_1, uint32 effIndex_1, uint32 spellId_2, uint32 effIndex_2);
//bool IsNoStackAuraDueToAura(uint32 spellId_1, uint32 effIndex_1, uint32 spellId_2, uint32 effIndex_2);
inline bool IsSealSpell(SpellEntry const *spellInfo)
{
@@ -300,7 +300,8 @@ inline bool IsElementalShield(SpellEntry const *spellInfo)
}
int32 CompareAuraRanks(uint32 spellId_1, uint32 effIndex_1, uint32 spellId_2, uint32 effIndex_2);
bool IsSingleFromSpellSpecificPerCaster(uint32 spellSpec1,uint32 spellSpec2);
bool IsSingleFromSpellSpecificPerCaster(uint32 spellSpec1, uint32 spellSpec2);
bool IsSingleFromSpellSpecificPerTarget(uint32 spellSpec1, uint32 spellSpec2);
bool IsPassiveSpell(uint32 spellId);
inline bool IsDeathPersistentSpell(SpellEntry const *spellInfo)
@@ -768,7 +769,7 @@ class SpellMgr
bool IsRankSpellDueToSpell(SpellEntry const *spellInfo_1,uint32 spellId_2) const;
static bool canStackSpellRanks(SpellEntry const *spellInfo);
bool IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) const;
bool IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2, bool sameCaster) const;
SpellEntry const* SelectAuraRankForPlayerLevel(SpellEntry const* spellInfo, uint32 playerLevel) const;
+10 -42
View File
@@ -3895,16 +3895,17 @@ bool Unit::RemoveNoStackAurasDueToAura(Aura *Aur)
if(!is_triggered_by_spell)
{
SpellSpecific i_spellId_spec = GetSpellSpecific(i_spellId);
bool is_sspc = IsSingleFromSpellSpecificPerCaster(spellId_spec,i_spellId_spec);
if( is_sspc && Aur->GetCasterGUID() == (*i).second->GetCasterGUID() )
bool sameCaster = Aur->GetCasterGUID() == (*i).second->GetCasterGUID();
if( spellmgr.IsNoStackSpellDueToSpell(spellId, i_spellId, sameCaster) )
{
// cannot remove higher rank
if (spellmgr.IsRankSpellDueToSpell(spellProto, i_spellId))
if(CompareAuraRanks(spellId, effIndex, i_spellId, i_effIndex) < 0)
return false;
//some spells should be not removed by lower rank of them
// what is this spell?
if (!sameCaster
&&(spellProto->Effect[effIndex]==SPELL_EFFECT_APPLY_AREA_AURA_PARTY)
&&(spellProto->DurationIndex==21)
&&(spellmgr.IsRankSpellDueToSpell(spellProto, i_spellId))
&&(CompareAuraRanks(spellId, effIndex, i_spellId, i_effIndex) < 0))
return false;
// Its a parent aura (create this aura in ApplyModifier)
if ((*i).second->IsInUse())
@@ -3919,39 +3920,6 @@ bool Unit::RemoveNoStackAurasDueToAura(Aura *Aur)
else
next = m_Auras.begin();
}
else if( !is_sspc && spellmgr.IsNoStackSpellDueToSpell(spellId, i_spellId) )
{
// Its a parent aura (create this aura in ApplyModifier)
if ((*i).second->IsInUse())
{
sLog.outError("Aura (Spell %u Effect %u) is in process but attempt removed at aura (Spell %u Effect %u) adding, need add stack rule for Unit::RemoveNoStackAurasDueToAura", i->second->GetId(), i->second->GetEffIndex(),Aur->GetId(), Aur->GetEffIndex());
continue;
}
RemoveAurasDueToSpell(i_spellId);
if( m_Auras.empty() )
break;
else
next = m_Auras.begin();
}
// Potions stack aura by aura (elixirs/flask already checked)
else if( spellProto->SpellFamilyName == SPELLFAMILY_POTION && i_spellProto->SpellFamilyName == SPELLFAMILY_POTION )
{
if (IsNoStackAuraDueToAura(spellId, effIndex, i_spellId, i_effIndex))
{
if(CompareAuraRanks(spellId, effIndex, i_spellId, i_effIndex) < 0)
return false; // cannot remove higher rank
// Its a parent aura (create this aura in ApplyModifier)
if ((*i).second->IsInUse())
{
sLog.outError("Aura (Spell %u Effect %u) is in process but attempt removed at aura (Spell %u Effect %u) adding, need add stack rule for Unit::RemoveNoStackAurasDueToAura", i->second->GetId(), i->second->GetEffIndex(),Aur->GetId(), Aur->GetEffIndex());
continue;
}
RemoveAura(i);
next = i;
}
}
}
}
return true;