[8298] Use new Aura::HandleSpellSpecificBoosts for apply/remove dependent auras.

This provided more clear place where dependent auras can be applied/removed,
if expected manual apply _with_ aura remove at parent aura expire.
This can be used for more cases.

In current state it implement additional effects for
29836 and ranks, 61846 and ranks, 31869, 53379 and ranks, 20254 and ranks,
20138 an ranks, 48263, and 48265.

Signed-off-by: VladimirMangos <vladimir@getmangos.com>
This commit is contained in:
nos4r2zod 2009-08-03 02:17:48 +04:00 committed by VladimirMangos
parent aa56961f94
commit 39eca7d43a
6 changed files with 233 additions and 100 deletions

View file

@ -1015,7 +1015,7 @@ void Aura::_AddAura()
} }
} }
void Aura::_RemoveAura() bool Aura::_RemoveAura()
{ {
// Remove all triggered by aura spells vs unlimited duration // Remove all triggered by aura spells vs unlimited duration
// except same aura replace case // except same aura replace case
@ -1039,10 +1039,10 @@ void Aura::_RemoveAura()
uint8 slot = GetAuraSlot(); uint8 slot = GetAuraSlot();
if(slot >= MAX_AURAS) // slot not set if(slot >= MAX_AURAS) // slot not set
return; return false;
if(m_target->GetVisibleAura(slot) == 0) if(m_target->GetVisibleAura(slot) == 0)
return; return false;
bool lastaura = true; bool lastaura = true;
@ -1063,96 +1063,98 @@ void Aura::_RemoveAura()
} }
// only remove icon when the last aura of the spell is removed (current aura already removed from list) // only remove icon when the last aura of the spell is removed (current aura already removed from list)
if (lastaura) if (!lastaura)
return false;
// unregister aura diminishing (and store last time)
if (getDiminishGroup() != DIMINISHING_NONE )
m_target->ApplyDiminishingAura(getDiminishGroup(), false);
SetAura(true);
SetAuraFlags(AFLAG_NONE);
SetAuraLevel(0);
SendAuraUpdate(true);
// update for out of range group members
m_target->UpdateAuraForGroup(slot);
//*****************************************************
// Update target aura state flag (at last aura remove)
//*****************************************************
// Enrage aura state
if(m_spellProto->Dispel == DISPEL_ENRAGE)
m_target->ModifyAuraState(AURA_STATE_ENRAGE, false);
uint32 removeState = 0;
uint64 removeFamilyFlag = m_spellProto->SpellFamilyFlags;
uint32 removeFamilyFlag2 = m_spellProto->SpellFamilyFlags2;
switch(m_spellProto->SpellFamilyName)
{ {
// unregister aura diminishing (and store last time) case SPELLFAMILY_PALADIN:
if (getDiminishGroup() != DIMINISHING_NONE ) if (IsSealSpell(m_spellProto))
m_target->ApplyDiminishingAura(getDiminishGroup(), false); removeState = AURA_STATE_JUDGEMENT; // Update Seals information
break;
SetAura(true); case SPELLFAMILY_WARLOCK:
SetAuraFlags(AFLAG_NONE); // Conflagrate aura state on Immolate and Shadowflame,
SetAuraLevel(0); if ((m_spellProto->SpellFamilyFlags & UI64LIT(0x0000000000000004)) ||
SendAuraUpdate(true); (m_spellProto->SpellFamilyFlags2 & 0x00000002))
// update for out of range group members
m_target->UpdateAuraForGroup(slot);
//*****************************************************
// Update target aura state flag (at last aura remove)
//*****************************************************
// Enrage aura state
if(m_spellProto->Dispel == DISPEL_ENRAGE)
m_target->ModifyAuraState(AURA_STATE_ENRAGE, false);
uint32 removeState = 0;
uint64 removeFamilyFlag = m_spellProto->SpellFamilyFlags;
uint32 removeFamilyFlag2 = m_spellProto->SpellFamilyFlags2;
switch(m_spellProto->SpellFamilyName)
{ {
case SPELLFAMILY_PALADIN: removeFamilyFlag = UI64LIT(0x0000000000000004);
if (IsSealSpell(m_spellProto)) removeFamilyFlag2 = 0x00000002;
removeState = AURA_STATE_JUDGEMENT; // Update Seals information removeState = AURA_STATE_CONFLAGRATE;
break;
case SPELLFAMILY_WARLOCK:
// Conflagrate aura state on Immolate and Shadowflame,
if ((m_spellProto->SpellFamilyFlags & UI64LIT(0x0000000000000004)) ||
(m_spellProto->SpellFamilyFlags2 & 0x00000002))
{
removeFamilyFlag = UI64LIT(0x0000000000000004);
removeFamilyFlag2 = 0x00000002;
removeState = AURA_STATE_CONFLAGRATE;
}
break;
case SPELLFAMILY_DRUID:
if(m_spellProto->SpellFamilyFlags & UI64LIT(0x0000000000000400))
removeState = AURA_STATE_FAERIE_FIRE; // Faerie Fire (druid versions)
else if(m_spellProto->SpellFamilyFlags & UI64LIT(0x50))
{
removeFamilyFlag = 0x50;
removeState = AURA_STATE_SWIFTMEND; // Swiftmend aura state
}
break;
case SPELLFAMILY_WARRIOR:
if(m_spellProto->SpellFamilyFlags & UI64LIT(0x0004000000000000))
removeState = AURA_STATE_WARRIOR_VICTORY_RUSH; // Victorious
break;
case SPELLFAMILY_ROGUE:
if(m_spellProto->SpellFamilyFlags & UI64LIT(0x10000))
removeState = AURA_STATE_DEADLY_POISON; // Deadly poison aura state
break;
case SPELLFAMILY_HUNTER:
if(m_spellProto->SpellFamilyFlags & UI64LIT(0x1000000000000000))
removeState = AURA_STATE_FAERIE_FIRE; // Sting (hunter versions)
} }
// Remove state (but need check other auras for it) break;
if (removeState) case SPELLFAMILY_DRUID:
if(m_spellProto->SpellFamilyFlags & UI64LIT(0x0000000000000400))
removeState = AURA_STATE_FAERIE_FIRE; // Faerie Fire (druid versions)
else if(m_spellProto->SpellFamilyFlags & UI64LIT(0x50))
{ {
bool found = false; removeFamilyFlag = 0x50;
Unit::AuraMap& Auras = m_target->GetAuras(); removeState = AURA_STATE_SWIFTMEND; // Swiftmend aura state
for(Unit::AuraMap::iterator i = Auras.begin(); i != Auras.end(); ++i)
{
SpellEntry const *auraSpellInfo = (*i).second->GetSpellProto();
if(auraSpellInfo->SpellFamilyName == m_spellProto->SpellFamilyName &&
(auraSpellInfo->SpellFamilyFlags & removeFamilyFlag || auraSpellInfo->SpellFamilyFlags2 & removeFamilyFlag2))
{
found = true;
break;
}
}
// this has been last aura
if(!found)
m_target->ModifyAuraState(AuraState(removeState), false);
} }
break;
case SPELLFAMILY_WARRIOR:
if(m_spellProto->SpellFamilyFlags & UI64LIT(0x0004000000000000))
removeState = AURA_STATE_WARRIOR_VICTORY_RUSH; // Victorious
break;
case SPELLFAMILY_ROGUE:
if(m_spellProto->SpellFamilyFlags & UI64LIT(0x10000))
removeState = AURA_STATE_DEADLY_POISON; // Deadly poison aura state
break;
case SPELLFAMILY_HUNTER:
if(m_spellProto->SpellFamilyFlags & UI64LIT(0x1000000000000000))
removeState = AURA_STATE_FAERIE_FIRE; // Sting (hunter versions)
// reset cooldown state for spells
if(caster && caster->GetTypeId() == TYPEID_PLAYER)
{
if ( GetSpellProto()->Attributes & SPELL_ATTR_DISABLED_WHILE_ACTIVE )
// note: item based cooldowns and cooldown spell mods with charges ignored (unknown existed cases)
((Player*)caster)->SendCooldownEvent(GetSpellProto());
}
} }
// Remove state (but need check other auras for it)
if (removeState)
{
bool found = false;
Unit::AuraMap& Auras = m_target->GetAuras();
for(Unit::AuraMap::iterator i = Auras.begin(); i != Auras.end(); ++i)
{
SpellEntry const *auraSpellInfo = (*i).second->GetSpellProto();
if(auraSpellInfo->SpellFamilyName == m_spellProto->SpellFamilyName &&
(auraSpellInfo->SpellFamilyFlags & removeFamilyFlag || auraSpellInfo->SpellFamilyFlags2 & removeFamilyFlag2))
{
found = true;
break;
}
}
// this has been last aura
if(!found)
m_target->ModifyAuraState(AuraState(removeState), false);
}
// reset cooldown state for spells
if(caster && caster->GetTypeId() == TYPEID_PLAYER)
{
if ( GetSpellProto()->Attributes & SPELL_ATTR_DISABLED_WHILE_ACTIVE )
// note: item based cooldowns and cooldown spell mods with charges ignored (unknown existed cases)
((Player*)caster)->SendCooldownEvent(GetSpellProto());
}
return true;
} }
void Aura::SendAuraUpdate(bool remove) void Aura::SendAuraUpdate(bool remove)
@ -5543,6 +5545,107 @@ void Aura::HandleShapeshiftBoosts(bool apply)
m_target->SetHealth(uint32(ceil((double)m_target->GetMaxHealth() * healthPercentage)));*/ m_target->SetHealth(uint32(ceil((double)m_target->GetMaxHealth() * healthPercentage)));*/
} }
void Aura::HandleSpellSpecificBoosts(bool apply)
{
uint32 spellId1 = 0;
uint32 spellId2 = 0;
uint32 spellId3 = 0;
switch(GetSpellProto()->SpellFamilyName)
{
case SPELLFAMILY_WARRIOR:
{
if(!apply)
{
// Remove Blood Frenzy only if target no longer has any Deep Wound or Rend (applying is handled by procs)
if (GetSpellProto()->Mechanic != MECHANIC_BLEED)
return;
// If target still has one of Warrior's bleeds, do nothing
Unit::AuraList const& PeriodicDamage = m_target->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
for(Unit::AuraList::const_iterator i = PeriodicDamage.begin(); i != PeriodicDamage.end(); ++i)
if( (*i)->GetCasterGUID() == GetCasterGUID() &&
(*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARRIOR &&
(*i)->GetSpellProto()->Mechanic == MECHANIC_BLEED)
return;
spellId1 = 30069;
spellId2 = 30070;
}
break;
}
case SPELLFAMILY_HUNTER:
{
if(GetSpellSpecific(m_spellProto->Id) != SPELL_ASPECT)
return;
// Aspect of the Dragonhawk dodge
if (GetSpellProto()->SpellFamilyFlags2 & 0x00001000)
spellId1 = 61848;
else
return;
break;
}
case SPELLFAMILY_PALADIN:
{
// Only process on player casting paladin aura
// all aura bonuses applied also in aura area effect way to caster
if (GetCasterGUID() != m_target->GetGUID() || !IS_PLAYER_GUID(GetCasterGUID()))
return;
if (GetSpellSpecific(m_spellProto->Id) != SPELL_AURA)
return;
// Sanctified Retribution and Swift Retribution (they share one aura), but not Retribution Aura (already gets modded)
if ((GetSpellProto()->SpellFamilyFlags & UI64LIT(0x0000000000000008))==0)
spellId1 = 63531; // placeholder for talent spell mods
// Improved Concentration Aura (auras bonus)
spellId2 = 63510; // placeholder for talent spell mods
// Improved Devotion Aura (auras bonus)
spellId3 = 63514; // placeholder for talent spell mods
break;
}
case SPELLFAMILY_DEATHKNIGHT:
{
if (GetSpellSpecific(m_spellProto->Id) != SPELL_PRESENCE)
return;
// Frost Presence health
if (GetId() == 48263)
spellId1 = 61261;
// Unholy Presence move speed
else if (GetId() == 48265)
spellId1 = 49772;
else
return;
break;
}
default:
return;
}
if (apply)
{
if (spellId1)
m_target->CastSpell(m_target, spellId1, true, NULL, this);
if (spellId2)
m_target->CastSpell(m_target, spellId2, true, NULL, this);
if (spellId3)
m_target->CastSpell(m_target, spellId3, true, NULL, this);
}
else
{
if (spellId1)
m_target->RemoveAurasByCasterSpell(spellId1, GetCasterGUID());
if (spellId2)
m_target->RemoveAurasByCasterSpell(spellId2, GetCasterGUID());
if (spellId3)
m_target->RemoveAurasByCasterSpell(spellId3, GetCasterGUID());
}
}
void Aura::HandleAuraEmpathy(bool apply, bool /*Real*/) void Aura::HandleAuraEmpathy(bool apply, bool /*Real*/)
{ {
if(m_target->GetTypeId() != TYPEID_UNIT) if(m_target->GetTypeId() != TYPEID_UNIT)
@ -5739,14 +5842,6 @@ void Aura::HandleSpiritOfRedemption( bool apply, bool Real )
void Aura::CleanupTriggeredSpells() void Aura::CleanupTriggeredSpells()
{ {
if (m_spellProto->SpellFamilyName == SPELLFAMILY_WARRIOR && (m_spellProto->SpellFamilyFlags & UI64LIT(0x0000001000000020)))
{
// Blood Frenzy remove
m_target->RemoveAurasDueToSpell(30069);
m_target->RemoveAurasDueToSpell(30070);
return;
}
uint32 tSpellId = m_spellProto->EffectTriggerSpell[GetEffIndex()]; uint32 tSpellId = m_spellProto->EffectTriggerSpell[GetEffIndex()];
if(!tSpellId) if(!tSpellId)
return; return;

View file

@ -297,7 +297,7 @@ class MANGOS_DLL_SPEC Aura
void ApplyModifier(bool apply, bool Real = false); void ApplyModifier(bool apply, bool Real = false);
void _AddAura(); void _AddAura();
void _RemoveAura(); bool _RemoveAura();
bool IsUpdated() { return m_updated; } bool IsUpdated() { return m_updated; }
void SetUpdated(bool val) { m_updated = val; } void SetUpdated(bool val) { m_updated = val; }
@ -311,6 +311,7 @@ class MANGOS_DLL_SPEC Aura
// add/remove SPELL_AURA_MOD_SHAPESHIFT (36) linked auras // add/remove SPELL_AURA_MOD_SHAPESHIFT (36) linked auras
void HandleShapeshiftBoosts(bool apply); void HandleShapeshiftBoosts(bool apply);
void HandleSpellSpecificBoosts(bool apply);
// Allow Apply Aura Handler to modify and access m_AuraDRGroup // Allow Apply Aura Handler to modify and access m_AuraDRGroup
void setDiminishGroup(DiminishingGroup group) { m_AuraDRGroup = group; } void setDiminishGroup(DiminishingGroup group) { m_AuraDRGroup = group; }

View file

@ -1463,9 +1463,15 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons
if( spellInfo_2->SpellFamilyName == SPELLFAMILY_PALADIN ) if( spellInfo_2->SpellFamilyName == SPELLFAMILY_PALADIN )
{ {
// Paladin Seals // Paladin Seals
if( IsSealSpell(spellInfo_1) && IsSealSpell(spellInfo_2) ) if (IsSealSpell(spellInfo_1) && IsSealSpell(spellInfo_2))
return true; return true;
// Swift Retribution / Improved Devotion Aura (talents) and Paladin Auras
if ((spellInfo_1->SpellFamilyFlags2 & 0x00000020) && (spellInfo_2->SpellIconID == 291 || spellInfo_2->SpellIconID == 3028) ||
(spellInfo_2->SpellFamilyFlags2 & 0x00000020) && (spellInfo_1->SpellIconID == 291 || spellInfo_1->SpellIconID == 3028))
return false;
} }
// Combustion and Fire Protection Aura (multi-family check) // Combustion and Fire Protection Aura (multi-family check)
if( spellInfo_2->Id == 11129 && spellInfo_1->SpellIconID == 33 && spellInfo_1->SpellVisual[0] == 321 ) if( spellInfo_2->Id == 11129 && spellInfo_1->SpellIconID == 33 && spellInfo_1->SpellVisual[0] == 321 )
return false; return false;
@ -1494,6 +1500,18 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons
if( spellInfo_1->Id == 2825 && spellInfo_2->SpellIconID == 38 && spellInfo_2->SpellVisual[0] == 0 ) if( spellInfo_1->Id == 2825 && spellInfo_2->SpellIconID == 38 && spellInfo_2->SpellVisual[0] == 0 )
return false; return false;
break; break;
case SPELLFAMILY_DEATHKNIGHT:
if (spellInfo_2->SpellFamilyName == SPELLFAMILY_DEATHKNIGHT)
{
// Frost Presence and Frost Presence (triggered)
if( spellInfo_1->SpellIconID == 2632 && spellInfo_2->SpellIconID == 2632 )
return false;
// Unholy Presence and Unholy Presence (triggered)
if( spellInfo_1->SpellIconID == 2633 && spellInfo_2->SpellIconID == 2633 )
return false;
}
break;
default: default:
break; break;
} }

View file

@ -122,7 +122,7 @@ int32 GetSpellMaxDuration(SpellEntry const *spellInfo);
inline bool IsSpellHaveEffect(SpellEntry const *spellInfo, SpellEffects effect) inline bool IsSpellHaveEffect(SpellEntry const *spellInfo, SpellEffects effect)
{ {
for(int i= 0; i < 3; ++i) for(int i = 0; i < 3; ++i)
if(SpellEffects(spellInfo->Effect[i])==effect) if(SpellEffects(spellInfo->Effect[i])==effect)
return true; return true;
return false; return false;
@ -130,12 +130,20 @@ inline bool IsSpellHaveEffect(SpellEntry const *spellInfo, SpellEffects effect)
inline bool IsSpellHaveAura(SpellEntry const *spellInfo, AuraType aura) inline bool IsSpellHaveAura(SpellEntry const *spellInfo, AuraType aura)
{ {
for(int i= 0; i < 3; ++i) for(int i = 0; i < 3; ++i)
if(AuraType(spellInfo->EffectApplyAuraName[i])==aura) if(AuraType(spellInfo->EffectApplyAuraName[i])==aura)
return true; return true;
return false; return false;
} }
inline bool IsSpellLastAuraEffect(SpellEntry const *spellInfo, int effecIdx)
{
for(int i = effecIdx+1; i < 3; ++i)
if(spellInfo->EffectApplyAuraName[i])
return false;
return true;
}
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) inline bool IsSealSpell(SpellEntry const *spellInfo)

View file

@ -3533,6 +3533,10 @@ bool Unit::AddAura(Aura *Aur)
Aur->ApplyModifier(true,true); Aur->ApplyModifier(true,true);
sLog.outDebug("Aura %u now is in use", aurName); sLog.outDebug("Aura %u now is in use", aurName);
if(IsSpellLastAuraEffect(aurSpellInfo,Aur->GetEffIndex()))
Aur->HandleSpellSpecificBoosts(true);
return true; return true;
} }
@ -3970,7 +3974,14 @@ void Unit::RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode)
sLog.outDebug("Aura %u now is remove mode %d",Aur->GetModifier()->m_auraname, mode); sLog.outDebug("Aura %u now is remove mode %d",Aur->GetModifier()->m_auraname, mode);
Aur->ApplyModifier(false,true); Aur->ApplyModifier(false,true);
Aur->_RemoveAura();
if(Aur->_RemoveAura())
{
// last aura in stack removed
if(IsSpellLastAuraEffect(Aur->GetSpellProto(),Aur->GetEffIndex()))
Aur->HandleSpellSpecificBoosts(false);
}
delete Aur; delete Aur;
if(caster_channeled) if(caster_channeled)

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__ #ifndef __REVISION_NR_H__
#define __REVISION_NR_H__ #define __REVISION_NR_H__
#define REVISION_NR "8297" #define REVISION_NR "8298"
#endif // __REVISION_NR_H__ #endif // __REVISION_NR_H__