diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index b86d35bc6..37a787240 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -1015,7 +1015,7 @@ void Aura::_AddAura() } } -void Aura::_RemoveAura() +bool Aura::_RemoveAura() { // Remove all triggered by aura spells vs unlimited duration // except same aura replace case @@ -1039,10 +1039,10 @@ void Aura::_RemoveAura() uint8 slot = GetAuraSlot(); if(slot >= MAX_AURAS) // slot not set - return; + return false; if(m_target->GetVisibleAura(slot) == 0) - return; + return false; 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) - 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) - 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) + case SPELLFAMILY_PALADIN: + if (IsSealSpell(m_spellProto)) + removeState = AURA_STATE_JUDGEMENT; // Update Seals information + break; + case SPELLFAMILY_WARLOCK: + // Conflagrate aura state on Immolate and Shadowflame, + if ((m_spellProto->SpellFamilyFlags & UI64LIT(0x0000000000000004)) || + (m_spellProto->SpellFamilyFlags2 & 0x00000002)) { - case SPELLFAMILY_PALADIN: - if (IsSealSpell(m_spellProto)) - removeState = AURA_STATE_JUDGEMENT; // Update Seals information - 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) - + removeFamilyFlag = UI64LIT(0x0000000000000004); + removeFamilyFlag2 = 0x00000002; + removeState = AURA_STATE_CONFLAGRATE; } - // Remove state (but need check other auras for it) - if (removeState) + 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)) { - 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); + 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) - // 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) @@ -5543,6 +5545,107 @@ void Aura::HandleShapeshiftBoosts(bool apply) 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*/) { if(m_target->GetTypeId() != TYPEID_UNIT) @@ -5739,14 +5842,6 @@ void Aura::HandleSpiritOfRedemption( bool apply, bool Real ) 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()]; if(!tSpellId) return; diff --git a/src/game/SpellAuras.h b/src/game/SpellAuras.h index 760145b8d..6fc9d83a9 100644 --- a/src/game/SpellAuras.h +++ b/src/game/SpellAuras.h @@ -297,7 +297,7 @@ class MANGOS_DLL_SPEC Aura void ApplyModifier(bool apply, bool Real = false); void _AddAura(); - void _RemoveAura(); + bool _RemoveAura(); bool IsUpdated() { return m_updated; } 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 void HandleShapeshiftBoosts(bool apply); + void HandleSpellSpecificBoosts(bool apply); // Allow Apply Aura Handler to modify and access m_AuraDRGroup void setDiminishGroup(DiminishingGroup group) { m_AuraDRGroup = group; } diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp index 7e820e4bb..ed8b02634 100644 --- a/src/game/SpellMgr.cpp +++ b/src/game/SpellMgr.cpp @@ -1463,9 +1463,15 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons if( spellInfo_2->SpellFamilyName == SPELLFAMILY_PALADIN ) { // Paladin Seals - if( IsSealSpell(spellInfo_1) && IsSealSpell(spellInfo_2) ) + if (IsSealSpell(spellInfo_1) && IsSealSpell(spellInfo_2)) 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) if( spellInfo_2->Id == 11129 && spellInfo_1->SpellIconID == 33 && spellInfo_1->SpellVisual[0] == 321 ) 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 ) return false; 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: break; } diff --git a/src/game/SpellMgr.h b/src/game/SpellMgr.h index 76c3da926..05ec8dae9 100644 --- a/src/game/SpellMgr.h +++ b/src/game/SpellMgr.h @@ -122,7 +122,7 @@ int32 GetSpellMaxDuration(SpellEntry const *spellInfo); 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) return true; return false; @@ -130,12 +130,20 @@ inline bool IsSpellHaveEffect(SpellEntry const *spellInfo, SpellEffects effect) 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) return true; 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); inline bool IsSealSpell(SpellEntry const *spellInfo) diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index f5c300e79..b1c0786c5 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -3533,6 +3533,10 @@ bool Unit::AddAura(Aura *Aur) Aur->ApplyModifier(true,true); sLog.outDebug("Aura %u now is in use", aurName); + + if(IsSpellLastAuraEffect(aurSpellInfo,Aur->GetEffIndex())) + Aur->HandleSpellSpecificBoosts(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); 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; if(caster_channeled) diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 22b5022ee..21b9406d5 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "8297" + #define REVISION_NR "8298" #endif // __REVISION_NR_H__