From 5a3cbf063f5d53331eb338af1a8c1ff948d3b21f Mon Sep 17 00:00:00 2001 From: DiSlord Date: Thu, 8 Jan 2009 01:12:22 +0300 Subject: [PATCH] [7049] Work vs Auras Allow stack some auras from some caster in one Move apply/remove aura state on apply/remove aura (on 1 add / on last remove) Correctly fill aura flag and send duration update to client Not use m_procCharges for store satack amount, used m_stackAmount Fixes in HandlePeriodicDamage (use m_stackAmount, fix formulas to 303, optimisation) Fixes in Spell::EffectSchoolDMG (use m_stackAmount, fix formulas to 303) Remove unused uint32 m_PeriodicEventId from aura struct Add Unit::RemoveSingleSpellAurasFromStack for remove one Spell auras from stack Add Aura::RefreshAura() for refresh aura duration Signed-off-by: DiSlord --- src/game/SpellAuras.cpp | 436 +++++++++++++++++++------------------- src/game/SpellAuras.h | 38 ++-- src/game/SpellEffects.cpp | 103 +++++---- src/game/Unit.cpp | 114 +++++----- src/game/Unit.h | 1 + src/shared/revision_nr.h | 2 +- 6 files changed, 350 insertions(+), 344 deletions(-) diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 0f1856d3f90..6581df7aeb8 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -337,14 +337,16 @@ pAuraHandler AuraHandler[TOTAL_AURAS]= }; Aura::Aura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target, Unit *caster, Item* castItem) : -m_procCharges(0), m_spellmod(NULL), m_effIndex(eff), m_caster_guid(0), m_target(target), -m_timeCla(1000), m_castItemGuid(castItem?castItem->GetGUID():0), m_auraSlot(MAX_AURAS), -m_positive(false), m_permanent(false), m_isPeriodic(false), m_isTrigger(false), m_isAreaAura(false), -m_isPersistent(false), m_updated(false), m_removeMode(AURA_REMOVE_BY_DEFAULT), m_isRemovedOnShapeLost(true), m_in_use(false), -m_periodicTimer(0), m_PeriodicEventId(0), m_AuraDRGroup(DIMINISHING_NONE) +m_spellmod(NULL), m_caster_guid(0), m_castItemGuid(castItem?castItem->GetGUID():0), m_target(target), +m_timeCla(1000), m_periodicTimer(0), m_removeMode(AURA_REMOVE_BY_DEFAULT), m_AuraDRGroup(DIMINISHING_NONE), +m_effIndex(eff), m_auraSlot(MAX_AURAS), m_auraFlags(AFLAG_NONE), m_auraLevel(1), m_procCharges(0), m_stackAmount(1), +m_positive(false), m_permanent(false), m_isPeriodic(false), m_isTrigger(false), m_isAreaAura(false), m_isPersistent(false), +m_updated(false), m_isRemovedOnShapeLost(true), m_in_use(false) { assert(target); + int32 size = sizeof(Aura); + assert(spellproto && spellproto == sSpellStore.LookupEntry( spellproto->Id ) && "`info` must be pointer to sSpellStore element"); m_spellProto = spellproto; @@ -889,12 +891,12 @@ void Aura::_AddAura() if(!m_target) return; - // we can found aura in NULL_AURA_SLOT and then need store state instead check slot != NULL_AURA_SLOT - bool samespell = false; + // Second aura if some spell bool secondaura = false; + // Try find slot for aura uint8 slot = NULL_AURA_SLOT; - - for(uint8 i = 0; i < 3; i++) + // Lookup for some spell auras (and get slot from it) + for(uint8 i = 0; i < m_effIndex; i++) { Unit::spellEffectPair spair = Unit::spellEffectPair(GetId(), i); for(Unit::AuraMap::const_iterator itr = m_target->GetAuras().lower_bound(spair); itr != m_target->GetAuras().upper_bound(spair); ++itr) @@ -902,18 +904,30 @@ void Aura::_AddAura() // allow use single slot only by auras from same caster if(itr->second->GetCasterGUID()==GetCasterGUID()) { - samespell = true; - if (m_effIndex > itr->second->GetEffIndex()) - secondaura = true; slot = itr->second->GetAuraSlot(); + secondaura = true; break; } } - - if(samespell) + if (secondaura) break; } - + // Lookup free slot + if (!secondaura && m_target->GetVisibleAurasCount() < MAX_AURAS) + { + Unit::VisibleAuraMap const *visibleAuras = m_target->GetVisibleAuras(); + for(uint8 i = 0; i < MAX_AURAS; ++i) + { + Unit::VisibleAuraMap::const_iterator itr = visibleAuras->find(i); + if(itr == visibleAuras->end()) + { + slot = i; + // update for out of range group members (on 1 slot use) + m_target->UpdateAuraForGroup(slot); + break; + } + } + } // not call total regen auras at adding switch (m_modifier.m_auraname) { @@ -939,59 +953,44 @@ void Aura::_AddAura() if((!m_isPassive || (caster && caster->GetTypeId() == TYPEID_UNIT && ((Creature*)caster)->isTotem())) && (m_spellProto->Effect[GetEffIndex()] != SPELL_EFFECT_APPLY_AREA_AURA_ENEMY || m_target != caster)) { - if(!samespell) // new slot need + SetAuraSlot( slot ); + if(slot < MAX_AURAS) // slot found send data to client { - if(m_target->GetVisibleAurasCount() < MAX_AURAS) - { - Unit::VisibleAuraMap const *visibleAuras = m_target->GetVisibleAuras(); - for(uint8 i = 0; i < MAX_AURAS; ++i) - { - Unit::VisibleAuraMap::const_iterator itr = visibleAuras->find(i); - if(itr == visibleAuras->end()) - { - slot = i; - break; - } - } - } - - SetAuraSlot( slot ); - - // Not update fields for not first spell's aura, all data already in fields - if(!secondaura) - { - if(slot < MAX_AURAS) // slot found - { - SetAura(false); - SetAuraFlags((1 << GetEffIndex()) | AFLAG_NOT_CASTER | ((GetAuraMaxDuration() > 0) ? AFLAG_DURATION : AFLAG_NONE) | (IsPositive() ? AFLAG_POSITIVE : AFLAG_NEGATIVE)); - SetAuraLevel(caster ? caster->getLevel() : sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)); - SendAuraUpdate(false); - - // update for out of range group members - m_target->UpdateAuraForGroup(slot); - } - } + SetAura(false); + SetAuraFlags((1 << GetEffIndex()) | AFLAG_NOT_CASTER | ((GetAuraMaxDuration() > 0) ? AFLAG_DURATION : AFLAG_NONE) | (IsPositive() ? AFLAG_POSITIVE : AFLAG_NEGATIVE)); + SetAuraLevel(caster ? caster->getLevel() : sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)); + SendAuraUpdate(false); } - else // use found slot + + //***************************************************** + // Update target aura state flag (at 1 aura apply) + // TODO: Make it easer + //***************************************************** + if (!secondaura) { - SetAuraSlot( slot ); - // Not recalculate stack count for second aura of the same spell - if (!secondaura) - UpdateSlotCounterAndDuration(true); - } + // Update Seals information + if( IsSealSpell(GetSpellProto()) ) + m_target->ModifyAuraState(AURA_STATE_JUDGEMENT, true); - // Update Seals information - if( IsSealSpell(GetSpellProto()) ) - m_target->ModifyAuraState(AURA_STATE_JUDGEMENT, true); + // Conflagrate aura state on Immolate + if (m_spellProto->SpellFamilyName == SPELLFAMILY_WARLOCK && m_spellProto->SpellFamilyFlags & 4) + m_target->ModifyAuraState(AURA_STATE_IMMOLATE, true); + + // Faerie Fire (druid versions) + if( m_spellProto->SpellFamilyName == SPELLFAMILY_DRUID && m_spellProto->SpellFamilyFlags & 0x0000000000000400LL) + m_target->ModifyAuraState(AURA_STATE_FAERIE_FIRE, true); - // Conflagrate aura state - if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags & 4)) - m_target->ModifyAuraState(AURA_STATE_IMMOLATE, true); + // Victorious + if( m_spellProto->SpellFamilyName == SPELLFAMILY_WARRIOR && m_spellProto->SpellFamilyFlags & 0x0004000000000000LL) + m_target->ModifyAuraState(AURA_STATE_WARRIOR_VICTORY_RUSH, true); - if(GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID - && (GetSpellProto()->SpellFamilyFlags == 0x40 || GetSpellProto()->SpellFamilyFlags == 0x10)) - { - m_target->ModifyAuraState(AURA_STATE_SWIFTMEND, true); + // Swiftmend state on Regrowth & Rejuvenation + if(m_spellProto->SpellFamilyName == SPELLFAMILY_DRUID && m_spellProto->SpellFamilyFlags & 0x50 ) + m_target->ModifyAuraState(AURA_STATE_SWIFTMEND, true); + + // Deadly poison aura state + if(m_spellProto->SpellFamilyName == SPELLFAMILY_ROGUE && m_spellProto->SpellFamilyFlags & 0x10000) + m_target->ModifyAuraState(AURA_STATE_DEADLY_POISON, true); } } } @@ -1029,8 +1028,7 @@ void Aura::_RemoveAura() if(m_target->GetVisibleAura(slot) == 0) return; - bool samespell = false; - bool sameaura = false; + bool lastaura = true; // find other aura in same slot (current already removed from list) for(uint8 i = 0; i < 3; i++) @@ -1040,30 +1038,30 @@ void Aura::_RemoveAura() { if(itr->second->GetAuraSlot()==slot) { - samespell = true; - - if(GetEffIndex()==i) - sameaura = true; - + lastaura = false; break; } } - if(samespell) + if(!lastaura) break; } // only remove icon when the last aura of the spell is removed (current aura already removed from list) - if (!samespell) + if (lastaura) { SetAura(true); SetAuraFlags(AFLAG_NONE); SetAuraLevel(0); - SetAuraCharges(0); SendAuraUpdate(true); // update for out of range group members m_target->UpdateAuraForGroup(slot); + //***************************************************** + // Update target aura state flag (at last aura remove) + // TODO: Make it easer + //***************************************************** + // Update Seals information if( IsSealSpell(GetSpellProto()) ) m_target->ModifyAuraState(AURA_STATE_JUDGEMENT,false); @@ -1071,16 +1069,22 @@ void Aura::_RemoveAura() if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags & 4)) m_target->ModifyAuraState(AURA_STATE_IMMOLATE, false); + // Faerie Fire (druid versions) + if( m_spellProto->SpellFamilyName == SPELLFAMILY_DRUID && m_spellProto->SpellFamilyFlags & 0x0000000000000400LL) + m_target->ModifyAuraState(AURA_STATE_FAERIE_FIRE, false); + + // Victorious + if( m_spellProto->SpellFamilyName == SPELLFAMILY_WARRIOR && m_spellProto->SpellFamilyFlags & 0x0004000000000000LL) + m_target->ModifyAuraState(AURA_STATE_WARRIOR_VICTORY_RUSH, false); + // Swiftmend aura state - if(GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID - && (GetSpellProto()->SpellFamilyFlags == 0x40 || GetSpellProto()->SpellFamilyFlags == 0x10)) + if(GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID && GetSpellProto()->SpellFamilyFlags & 0x50) { bool found = false; Unit::AuraList const& RejorRegr = m_target->GetAurasByType(SPELL_AURA_PERIODIC_HEAL); for(Unit::AuraList::const_iterator i = RejorRegr.begin(); i != RejorRegr.end(); ++i) { - if((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID - && ((*i)->GetSpellProto()->SpellFamilyFlags == 0x40 || (*i)->GetSpellProto()->SpellFamilyFlags == 0x10) ) + if((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID && (*i)->GetSpellProto()->SpellFamilyFlags & 0x50 ) { found = true; break; @@ -1090,6 +1094,26 @@ void Aura::_RemoveAura() m_target->ModifyAuraState(AURA_STATE_SWIFTMEND, false); } + // Deadly poison aura state + if(m_spellProto->SpellFamilyName == SPELLFAMILY_ROGUE && m_spellProto->SpellFamilyFlags & 0x10000) + { + // current aura already removed, search present of another + bool found = false; + Unit::AuraList const& auras = m_target->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE); + for(Unit::AuraList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr) + { + SpellEntry const* itr_spell = (*itr)->GetSpellProto(); + if(itr_spell && itr_spell->SpellFamilyName==SPELLFAMILY_ROGUE && itr_spell->SpellFamilyFlags & 0x10000) + { + found = true; + break; + } + } + // this has been last deadly poison aura + if(!found) + m_target->ModifyAuraState(AURA_STATE_DEADLY_POISON,false); + } + // reset cooldown state for spells if(caster && caster->GetTypeId() == TYPEID_PLAYER) { @@ -1097,8 +1121,6 @@ void Aura::_RemoveAura() ((Player*)caster)->SendCooldownEvent(GetSpellProto()); } } - else if(sameaura) // decrease count for spell, only for same aura effect, or this spell auras in remove process. - UpdateSlotCounterAndDuration(false); } void Aura::SendAuraUpdate(bool remove) @@ -1117,7 +1139,7 @@ void Aura::SendAuraUpdate(bool remove) uint8 auraFlags = GetAuraFlags(); data << uint8(auraFlags); data << uint8(GetAuraLevel()); - data << uint8(GetAuraCharges()); + data << uint8(m_procCharges ? m_procCharges : m_stackAmount); if(!(auraFlags & AFLAG_NOT_CASTER)) { @@ -1133,35 +1155,51 @@ void Aura::SendAuraUpdate(bool remove) m_target->SendMessageToSet(&data, true); } -void Aura::UpdateSlotCounterAndDuration(bool add) +void Aura::SetStackAmount(uint8 stackAmount) { - uint8 slot = GetAuraSlot(); - if(slot >= MAX_AURAS) - return; - - // calculate amount of similar auras by same effect index (similar different spells) - int8 count = 0; - - // calculate auras and update durations in case aura adding - Unit::AuraList const& aura_list = m_target->GetAurasByType(GetModifier()->m_auraname); - for(Unit::AuraList::const_iterator i = aura_list.begin();i != aura_list.end(); ++i) + if (stackAmount != m_stackAmount) { - if( (*i)->GetId()==GetId() && (*i)->GetEffIndex()==m_effIndex && - (*i)->GetCasterGUID()==GetCasterGUID() ) + Unit *target = GetTarget(); + Unit *caster = GetCaster(); + if (!target || !caster) + return; + m_stackAmount = stackAmount; + int32 amount = m_stackAmount * caster->CalculateSpellDamage(m_spellProto, m_effIndex, m_currentBasePoints, target); + // Reapply if amount change + if (amount!=m_modifier.m_amount) { - ++count; - - if(add) - (*i)->SetAuraDuration(GetAuraDuration()); + ApplyModifier(false, true); + m_modifier.m_amount = amount; + ApplyModifier(true, true); } } + RefreshAura(); +} - // at aura add aura not added yet, at aura remove aura already removed - // in field stored (count-1) - if(!add) - --count; +bool Aura::modStackAmount(int32 num) +{ + // Can`t mod + if (!m_spellProto->StackAmount) + return true; - SetAuraCharges(count); + // Modify stack but limit it + int32 stackAmount = m_stackAmount + num; + if (stackAmount > m_spellProto->StackAmount) + stackAmount = m_spellProto->StackAmount; + else if (stackAmount <=0) // Last aura from stack removed + { + m_stackAmount = 0; + return true; // need remove aura + } + + // Update stack amount + SetStackAmount(stackAmount); + return false; +} + +void Aura::RefreshAura() +{ + m_duration = m_maxduration; SendAuraUpdate(false); } @@ -2148,12 +2186,6 @@ void Aura::HandleAuraDummy(bool apply, bool Real) m_target->RemoveAurasDueToSpell(spellId); return; } - // Victorious - if(GetId()==32216 && m_target->getClass()==CLASS_WARRIOR) - { - m_target->ModifyAuraState(AURA_STATE_WARRIOR_VICTORY_RUSH, apply); - return; - } //Summon Fire Elemental if (GetId() == 40133 && caster) { @@ -2213,8 +2245,11 @@ void Aura::HandleAuraDummy(bool apply, bool Real) return; // final heal - if(m_target->IsInWorld()) - m_target->CastCustomSpell(m_target,33778,&m_modifier.m_amount,NULL,NULL,true,NULL,this,GetCasterGUID()); + if(m_target->IsInWorld() && m_stackAmount > 0) + { + int32 amount = m_modifier.m_amount / m_stackAmount; + m_target->CastCustomSpell(m_target,33778,&amount,NULL,NULL,true,NULL,this,GetCasterGUID()); + } } return; } @@ -3593,15 +3628,11 @@ void Aura::HandleAuraModSilence(bool apply, bool Real) return; // Search Mana Tap auras on caster - int32 energy = 0; - Unit::AuraList const& m_dummyAuras = caster->GetAurasByType(SPELL_AURA_DUMMY); - for(Unit::AuraList::const_iterator i = m_dummyAuras.begin(); i != m_dummyAuras.end(); ++i) - if ((*i)->GetId() == 28734) - ++energy; - if (energy) + Aura * dummy = caster->GetDummyAura(28734); + if (dummy) { - energy *= 10; - caster->CastCustomSpell(caster, 25048, &energy, NULL, NULL, true); + int32 bp = dummy->GetStackAmount() * 10; + caster->CastCustomSpell(caster, 25048, &bp, NULL, NULL, true); caster->RemoveAurasDueToSpell(28734); } } @@ -4089,6 +4120,10 @@ void Aura::HandlePeriodicDamage(bool apply, bool Real) Unit *caster = GetCaster(); + // Custom damage calculation after + if (!apply || loading || !caster) + return; + switch (m_spellProto->SpellFamilyName) { case SPELLFAMILY_GENERIC: @@ -4097,8 +4132,7 @@ void Aura::HandlePeriodicDamage(bool apply, bool Real) if ( m_spellProto->SpellIconID == 147 && m_spellProto->SpellVisual[0] == 0 ) { // $AP*0.18/6 bonus per tick - if (apply && !loading && caster) - m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 3 / 100); + m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 3 / 100); return; } break; @@ -4108,16 +4142,12 @@ void Aura::HandlePeriodicDamage(bool apply, bool Real) // Rend if (m_spellProto->SpellFamilyFlags & 0x0000000000000020LL) { - // 0.00743*(($MWB+$mwb)/2+$AP/14*$MWS) bonus per tick - if (apply && !loading && caster) - { - float ap = caster->GetTotalAttackPowerValue(BASE_ATTACK); - int32 mws = caster->GetAttackTime(BASE_ATTACK); - float mwb_min = caster->GetWeaponDamageRange(BASE_ATTACK,MINDAMAGE); - float mwb_max = caster->GetWeaponDamageRange(BASE_ATTACK,MAXDAMAGE); - // WARNING! in 3.0 multiplier 0.00743f change to 0.6 - m_modifier.m_amount+=int32(((mwb_min+mwb_max)/2+ap*mws/14000)*0.00743f); - } + // $0.2*(($MWB+$mwb)/2+$AP/14*$MWS) bonus per tick + float ap = caster->GetTotalAttackPowerValue(BASE_ATTACK); + int32 mws = caster->GetAttackTime(BASE_ATTACK); + float mwb_min = caster->GetWeaponDamageRange(BASE_ATTACK,MINDAMAGE); + float mwb_max = caster->GetWeaponDamageRange(BASE_ATTACK,MAXDAMAGE); + m_modifier.m_amount+=int32(((mwb_min+mwb_max)/2+ap*mws/14000)*0.2f); return; } break; @@ -4127,90 +4157,77 @@ void Aura::HandlePeriodicDamage(bool apply, bool Real) // Rake if (m_spellProto->SpellFamilyFlags & 0x0000000000001000LL) { - // $AP*0.06/3 bonus per tick - if (apply && !loading && caster) - m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 2 / 100); + // $AP*0.06 bonus per tick + m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 6 / 100); return; } // Lacerate if (m_spellProto->SpellFamilyFlags & 0x000000010000000000LL) { // $AP*0.05/5 bonus per tick - if (apply && !loading && caster) - m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100); + m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100); return; } // Rip if (m_spellProto->SpellFamilyFlags & 0x000000000000800000LL) { - // $AP * min(0.06*$cp, 0.24)/6 [Yes, there is no difference, whether 4 or 5 CPs are being used] - if (apply && !loading && caster && caster->GetTypeId() == TYPEID_PLAYER) - { - uint8 cp = ((Player*)caster)->GetComboPoints(); + // 0.01*$AP*cp + if (caster->GetTypeId() != TYPEID_PLAYER) + return; + + uint8 cp = ((Player*)caster)->GetComboPoints(); - // Idol of Feral Shadows. Cant be handled as SpellMod in SpellAura:Dummy due its dependency from CPs - Unit::AuraList const& dummyAuras = caster->GetAurasByType(SPELL_AURA_DUMMY); - for(Unit::AuraList::const_iterator itr = dummyAuras.begin(); itr != dummyAuras.end(); ++itr) + // Idol of Feral Shadows. Cant be handled as SpellMod in SpellAura:Dummy due its dependency from CPs + Unit::AuraList const& dummyAuras = caster->GetAurasByType(SPELL_AURA_DUMMY); + for(Unit::AuraList::const_iterator itr = dummyAuras.begin(); itr != dummyAuras.end(); ++itr) + { + if((*itr)->GetId()==34241) { - if((*itr)->GetId()==34241) - { - m_modifier.m_amount += cp * (*itr)->GetModifier()->m_amount; - break; - } + m_modifier.m_amount += cp * (*itr)->GetModifier()->m_amount; + break; } - - if (cp > 4) cp = 4; - m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * cp / 100); } + m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * cp / 100); + return; + } + // Lock Jaw + if (m_spellProto->SpellFamilyFlags & 0x1000000000000000LL) + { + // 0.15*$AP + m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 15 / 100); return; } break; } case SPELLFAMILY_ROGUE: { - // Deadly poison aura state - if((m_spellProto->SpellFamilyFlags & 0x10000) && m_spellProto->SpellVisual[0]==5100) - { - if(apply) - m_target->ModifyAuraState(AURA_STATE_DEADLY_POISON,true); - else - { - // current aura already removed, search present of another - bool found = false; - Unit::AuraList const& auras = m_target->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE); - for(Unit::AuraList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr) - { - SpellEntry const* itr_spell = (*itr)->GetSpellProto(); - if(itr_spell && itr_spell->SpellFamilyName==SPELLFAMILY_ROGUE && (itr_spell->SpellFamilyFlags & 0x10000) && itr_spell->SpellVisual[0]==5100) - { - found = true; - break; - } - } - // this has been last deadly poison aura - if(!found) - m_target->ModifyAuraState(AURA_STATE_DEADLY_POISON,false); - } - return; - } // Rupture if (m_spellProto->SpellFamilyFlags & 0x000000000000100000LL) { - // Dmg/tick = $AP*min(0.01*$cp, 0.03) [Like Rip: only the first three CP increase the contribution from AP] - if (apply && !loading && caster && caster->GetTypeId() == TYPEID_PLAYER) - { - uint8 cp = ((Player*)caster)->GetComboPoints(); - if (cp > 3) cp = 3; - m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * cp / 100); - } + if (caster->GetTypeId() != TYPEID_PLAYER) + return; + //1 point : ${($m1+$b1*1+0.015*$AP)*4} damage over 8 secs + //2 points: ${($m1+$b1*2+0.024*$AP)*5} damage over 10 secs + //3 points: ${($m1+$b1*3+0.03*$AP)*6} damage over 12 secs + //4 points: ${($m1+$b1*4+0.03428571*$AP)*7} damage over 14 secs + //5 points: ${($m1+$b1*5+0.0375*$AP)*8} damage over 16 secs + float AP_per_combo[] = {0, 0.015f, 0.024, 0.03, 0.03428571, 0.0375}; + uint8 cp = ((Player*)caster)->GetComboPoints(); + if (cp > 5) cp = 5; + m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * AP_per_combo[cp]); return; } // Garrote if (m_spellProto->SpellFamilyFlags & 0x000000000000000100LL) { - // $AP*0.18/6 bonus per tick - if (apply && !loading && caster) - m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 3 / 100); + // $AP*0.07 bonus per tick + m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 7 / 100); + return; + } + if (m_spellProto->SpellFamilyFlags & 0x0000000000010000) + { + // 0.08*$AP / 4 * amount of stack + m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 2 * GetStackAmount() * / 100); return; } break; @@ -4221,16 +4238,14 @@ void Aura::HandlePeriodicDamage(bool apply, bool Real) if (m_spellProto->SpellFamilyFlags & 0x0000000000004000LL) { // $RAP*0.1/5 bonus per tick - if (apply && !loading && caster) - m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 10 / 500); + m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 10 / 500); return; } // Immolation Trap if (m_spellProto->SpellFamilyFlags & 0x0000000000000004LL && m_spellProto->SpellIconID == 678) { // $RAP*0.1/5 bonus per tick - if (apply && !loading && caster) - m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 10 / 500); + m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 10 / 500); return; } break; @@ -4240,34 +4255,35 @@ void Aura::HandlePeriodicDamage(bool apply, bool Real) // Consecration if (m_spellProto->SpellFamilyFlags & 0x0000000000000020LL) { - if (apply && !loading && caster) + // ($m1+0.04*$SPH+0.04*$AP) + float ap = caster->GetTotalAttackPowerValue(BASE_ATTACK); + int32 holy = caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) + + caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellProto), m_target); + m_modifier.m_amount += int32(0.04f*holy + 0.04f*ap); + + // Improved Consecration - Libram of the Eternal Rest + Unit::AuraList const& classScripts = caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); + for(Unit::AuraList::const_iterator k = classScripts.begin(); k != classScripts.end(); ++k) { - Unit::AuraList const& classScripts = caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); - for(Unit::AuraList::const_iterator k = classScripts.begin(); k != classScripts.end(); ++k) + switch((*k)->GetModifier()->m_miscvalue) { - int32 tickcount = GetSpellDuration(m_spellProto) / m_spellProto->EffectAmplitude[m_effIndex]; - switch((*k)->GetModifier()->m_miscvalue) + case 5147: { - case 5147: // Improved Consecration - Libram of the Eternal Rest - { - m_modifier.m_amount += (*k)->GetModifier()->m_amount / tickcount; - break; - } + int32 tickcount = GetSpellDuration(m_spellProto) / m_spellProto->EffectAmplitude[m_effIndex]; + m_modifier.m_amount += (*k)->GetModifier()->m_amount / tickcount; + break; } } } return; } - // Seal of Vengeance 0.013*$SPH+0.025*$AP per tick + // Seal of Vengeance 0.013*$SPH+0.025*$AP per tick (also can stack) if(m_spellProto->SpellFamilyFlags & 0x0000080000000000LL) { - if (apply && !loading && caster) - { - float ap = caster->GetTotalAttackPowerValue(BASE_ATTACK); - int32 holy = caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) + - caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellProto), m_target); - m_modifier.m_amount += int32(ap * 0.025f) + int32(holy * 13 / 1000); - } + float ap = caster->GetTotalAttackPowerValue(BASE_ATTACK); + int32 holy = caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) + + caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellProto), m_target); + m_modifier.m_amount += int32((0.013f*holy + 0.025f*ap) * GetStackAmount()); return; } break; @@ -4333,14 +4349,6 @@ void Aura::HandleAuraModResistance(bool apply, bool Real) m_target->ApplyResistanceBuffModsMod(SpellSchools(x),m_positive,m_modifier.m_amount, apply); } } - - // Faerie Fire (druid versions) - if( m_spellProto->SpellIconID == 109 && - m_spellProto->SpellFamilyName == SPELLFAMILY_DRUID && - m_spellProto->SpellFamilyFlags & 0x0000000000000400LL ) - { - m_target->ModifyAuraState(AURA_STATE_FAERIE_FIRE,apply); - } } void Aura::HandleAuraModBaseResistancePCT(bool apply, bool Real) diff --git a/src/game/SpellAuras.h b/src/game/SpellAuras.h index 0746f0b72ee..b3c7c395d3a 100644 --- a/src/game/SpellAuras.h +++ b/src/game/SpellAuras.h @@ -275,6 +275,11 @@ class MANGOS_DLL_SPEC Aura void SetAura(bool remove) { m_target->SetVisibleAura(m_auraSlot, remove ? 0 : GetId()); } void SendAuraUpdate(bool remove); + int8 GetStackAmount() {return m_stackAmount;} + void SetStackAmount(uint8 num); + bool modStackAmount(int32 num); // return true if last charge dropped + void RefreshAura(); + bool IsPositive() { return m_positive; } void SetNegative() { m_positive = false; } void SetPositive() { m_positive = true; } @@ -320,23 +325,28 @@ class MANGOS_DLL_SPEC Aura Modifier m_modifier; SpellModifier *m_spellmod; - uint32 m_effIndex; + SpellEntry const *m_spellProto; - int32 m_currentBasePoints; // cache SpellEntry::EffectBasePoints and use for set custom base points - uint64 m_caster_guid; Unit* m_target; - int32 m_maxduration; - int32 m_duration; - int32 m_timeCla; + uint64 m_caster_guid; uint64 m_castItemGuid; // it is NOT safe to keep a pointer to the item because it may get deleted time_t m_applyTime; - AuraRemoveMode m_removeMode; + int32 m_currentBasePoints; // cache SpellEntry::EffectBasePoints and use for set custom base points + int32 m_maxduration; // Max aura duration + int32 m_duration; // Current time + int32 m_timeCla; // Timer for power per sec calcultion + int32 m_periodicTimer; // Timer for periodic auras + + AuraRemoveMode m_removeMode:8; // Store info for know remove aura reason + DiminishingGroup m_AuraDRGroup:8; // Diminishing - uint8 m_auraSlot; - uint8 m_auraFlags; - uint8 m_auraLevel; - int8 m_procCharges; + uint8 m_effIndex; // Aura effect index in spell + uint8 m_auraSlot; // Aura slot on unit (for show in client) + uint8 m_auraFlags; // Aura info flag (for send data to client) + uint8 m_auraLevel; // Aura level (store caster level for correct show level dep amount) + uint8 m_procCharges; // Aura charges (0 for infinite) + uint8 m_stackAmount; // Aura stack amount bool m_positive:1; bool m_permanent:1; @@ -347,14 +357,10 @@ class MANGOS_DLL_SPEC Aura bool m_isPersistent:1; bool m_isDeathPersist:1; bool m_isRemovedOnShapeLost:1; - bool m_updated:1; + bool m_updated:1; // Prevent remove aura by stack if set bool m_in_use:1; // true while in Aura::ApplyModifier call - int32 m_periodicTimer; - uint32 m_PeriodicEventId; - DiminishingGroup m_AuraDRGroup; private: - void UpdateSlotCounterAndDuration(bool add); void CleanupTriggeredSpells(); }; diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index afef5ea933f..c4ee30bfee5 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -480,31 +480,29 @@ void Spell::EffectSchoolDMG(uint32 effect_idx) // consume from stack dozes not more that have combo-points if(uint32 combo = ((Player*)m_caster)->GetComboPoints()) { - // count consumed deadly poison doses at target - uint32 doses = 0; - - // remove consumed poison doses + Aura *poison = 0; + // Lookup for Deadly poison (only attacker applied) Unit::AuraList const& auras = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE); for(Unit::AuraList::const_iterator itr = auras.begin(); itr!=auras.end() && combo;) - { - // Deadly poison (only attacker applied) - if( (*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_ROGUE && ((*itr)->GetSpellProto()->SpellFamilyFlags & 0x10000) && - (*itr)->GetSpellProto()->SpellVisual[0]==5100 && (*itr)->GetCasterGUID()==m_caster->GetGUID() ) + if( (*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_ROGUE && + (*itr)->GetSpellProto()->SpellFamilyFlags & 0x10000 && + (*itr)->GetCasterGUID()==m_caster->GetGUID() ) { - --combo; - ++doses; - - unitTarget->RemoveSingleAuraFromStack((*itr)->GetId(), (*itr)->GetEffIndex()); - - itr = auras.begin(); + poison = *itr; + break; } - else - ++itr; + // count consumed deadly poison doses at target + if (poison) + { + uint32 spellId = poison->GetId(); + uint32 doses = poison->GetStackAmount(); + if (doses > combo) + doses = combo; + for (int i=0; i< doses; i++) + unitTarget->RemoveSingleSpellAurasFromStack(spellId); + damage *= doses; + damage += int32(((Player*)m_caster)->GetTotalAttackPowerValue(BASE_ATTACK) * 0.03f * doses); } - - damage *= doses; - damage += int32(((Player*)m_caster)->GetTotalAttackPowerValue(BASE_ATTACK) * 0.03f * doses); - // Eviscerate and Envenom Bonus Damage (item set effect) if(m_caster->GetDummyAura(37169)) damage += ((Player*)m_caster)->GetComboPoints()*40; @@ -572,19 +570,25 @@ void Spell::EffectSchoolDMG(uint32 effect_idx) } case SPELLFAMILY_PALADIN: { - // Judgement of Vengeance + // Judgement of Vengeance ${1+0.22*$SPH+0.14*$AP} + 10% for each application of Holy Vengeance on the target if((m_spellInfo->SpellFamilyFlags & 0x800000000LL) && m_spellInfo->SpellIconID==2292) { + float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK); + int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) + + m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget); + damage+=int32(ap * 0.14f) + int32(holy * 22 / 100); + // Get stack of Holy Vengeance on the target added by caster uint32 stacks = 0; Unit::AuraList const& auras = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE); for(Unit::AuraList::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr) if((*itr)->GetId() == 31803 && (*itr)->GetCasterGUID()==m_caster->GetGUID()) - ++stacks; - if(!stacks) - //No damage if the target isn't affected by this - damage = -1; - else - damage *= stacks; + { + stacks = (*itr)->GetStackAmount(); + break; + } + // + 10% for each application of Holy Vengeance on the target + if(stacks) + damage += damage * stacks * 10 /100; } // Avenger's Shield ($m1+0.07*$SPH+0.07*$AP) else if(m_spellInfo->SpellFamilyFlags & 0x0000000000004000LL) @@ -943,16 +947,12 @@ void Spell::EffectDummy(uint32 i) } case 28730: // Arcane Torrent (Mana) { - int32 count = 0; - Unit::AuraList const& m_dummyAuras = m_caster->GetAurasByType(SPELL_AURA_DUMMY); - for(Unit::AuraList::const_iterator i = m_dummyAuras.begin(); i != m_dummyAuras.end(); ++i) - if ((*i)->GetId() == 28734) - ++count; - if (count) - { - m_caster->RemoveAurasDueToSpell(28734); - int32 bp = damage * count; + Aura * dummy = m_caster->GetDummyAura(28734); + if (dummy) + { + int32 bp = damage * dummy->GetStackAmount(); m_caster->CastCustomSpell(m_caster, 28733, &bp, NULL, NULL, true); + m_caster->RemoveAurasDueToSpell(28734); } return; } @@ -4217,21 +4217,22 @@ void Spell::EffectWeaponDmg(uint32 i) // Devastate bonus and sunder armor refresh else if(m_spellInfo->SpellVisual[0] == 671 && m_spellInfo->SpellIconID == 1508) { - customBonusDamagePercentMod = true; - bonusDamagePercentMod = 0.0f; // only applied if auras found - - Unit::AuraList const& list = unitTarget->GetAurasByType(SPELL_AURA_MOD_RESISTANCE); - for(Unit::AuraList::const_iterator itr=list.begin();itr!=list.end();++itr) + uint32 stack = 0; + // Need refresh all Sunder Armor auras from this caster + Unit::AuraMap& suAuras = unitTarget->GetAuras(); + for(Unit::AuraMap::iterator itr = suAuras.begin(); itr != suAuras.end(); ++itr) { - SpellEntry const *proto = (*itr)->GetSpellProto(); - if(proto->SpellVisual[0] == 406 && proto->SpellIconID == 565) + SpellEntry const *spellInfo = (*itr).second->GetSpellProto(); + if( spellInfo->SpellFamilyName == SPELLFAMILY_WARRIOR && + spellInfo->SpellFamilyFlags & 0x0000000000004000LL && + (*itr).second->GetCasterGUID() == m_caster->GetGUID()) { - int32 duration = GetSpellDuration(proto); - (*itr)->SetAuraDuration(duration); - (*itr)->SendAuraUpdate(false); - bonusDamagePercentMod += 1.0f; // +100% + (*itr).second->RefreshAura(); + stack = (*itr).second->GetStackAmount(); } } + if (stack) + spell_bonus += stack * CalculateDamage(2, unitTarget); } break; } @@ -4644,12 +4645,11 @@ void Spell::EffectScriptEffect(uint32 effIndex) } // Brittle Armor - need remove one 24575 Brittle Armor aura case 24590: - unitTarget->RemoveSingleAuraFromStack(24575, 0); - unitTarget->RemoveSingleAuraFromStack(24575, 1); + unitTarget->RemoveSingleSpellAurasFromStack(24575); return; // Mercurial Shield - need remove one 26464 Mercurial Shield aura case 26465: - unitTarget->RemoveSingleAuraFromStack(26464, 0); + unitTarget->RemoveSingleSpellAurasFromStack(26464); return; // Orb teleport spells case 25140: @@ -4900,8 +4900,7 @@ void Spell::EffectScriptEffect(uint32 effIndex) if (!(familyFlag & 0x000000800000C000LL)) continue; // Refresh aura duration - aura->SetAuraDuration(aura->GetAuraMaxDuration()); - aura->SendAuraUpdate(false); + aura->RefreshAura(); // Serpent Sting - Instantly deals 40% of the damage done by your Serpent Sting. if (familyFlag & 0x0000000000004000LL && aura->GetEffIndex() == 0) diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index e4b8a9729d0..430fe3f130f 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -1131,10 +1131,7 @@ void Unit::DealSpellDamage(SpellNonMeleeDamage *damageInfo, bool durabilityLoss) { SpellEntry const *spellInfo = (*itr).second->GetSpellProto(); if( spellInfo->AttributesEx3 & 0x40000 && spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN && ((*itr).second->GetCasterGUID() == GetGUID())) - { - (*itr).second->SetAuraDuration((*itr).second->GetAuraMaxDuration()); - (*itr).second->SendAuraUpdate(false); - } + (*itr).second->RefreshAura(); } } // Call default DealDamage @@ -1490,10 +1487,7 @@ void Unit::DealMeleeDamage(CalcDamageInfo *damageInfo, bool durabilityLoss) { SpellEntry const *spellInfo = (*itr).second->GetSpellProto(); if( spellInfo->AttributesEx3 & 0x40000 && spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN && ((*itr).second->GetCasterGUID() == GetGUID())) - { - (*itr).second->SetAuraDuration((*itr).second->GetAuraMaxDuration()); - (*itr).second->SendAuraUpdate(false); - } + (*itr).second->RefreshAura(); } } @@ -3195,48 +3189,45 @@ bool Unit::AddAura(Aura *Aur) // passive and persistent auras can stack with themselves any number of times if (!Aur->IsPassive() && !Aur->IsPersistent()) { - // replace aura if next will > spell StackAmount - if(aurSpellInfo->StackAmount) + for(AuraMap::iterator i2 = m_Auras.lower_bound(spair); i2 != m_Auras.upper_bound(spair); ++i2) { - if(m_Auras.count(spair) >= aurSpellInfo->StackAmount) - RemoveAura(i,AURA_REMOVE_BY_STACK); - } - // if StackAmount==0 not allow auras from same caster - else - { - for(AuraMap::iterator i2 = m_Auras.lower_bound(spair); i2 != m_Auras.upper_bound(spair); ++i2) + if(i2->second->GetCasterGUID()==Aur->GetCasterGUID()) { - if(i2->second->GetCasterGUID()==Aur->GetCasterGUID()) - { - // can be only single (this check done at _each_ aura add - RemoveAura(i2,AURA_REMOVE_BY_STACK); - break; - } - - bool stop = false; - switch(aurSpellInfo->EffectApplyAuraName[Aur->GetEffIndex()]) + // Aura can stack on self -> Stack it; + if(aurSpellInfo->StackAmount) { - // DoT/HoT/etc - case SPELL_AURA_PERIODIC_DAMAGE: // allow stack - case SPELL_AURA_PERIODIC_DAMAGE_PERCENT: - case SPELL_AURA_PERIODIC_LEECH: - case SPELL_AURA_PERIODIC_HEAL: - case SPELL_AURA_OBS_MOD_HEALTH: - case SPELL_AURA_PERIODIC_MANA_LEECH: - case SPELL_AURA_PERIODIC_ENERGIZE: - case SPELL_AURA_OBS_MOD_MANA: - case SPELL_AURA_POWER_BURN_MANA: - break; - default: // not allow - // can be only single (this check done at _each_ aura add - RemoveAura(i2,AURA_REMOVE_BY_STACK); - stop = true; - break; + i2->second->modStackAmount(1); + delete Aur; + return false; } + // can be only single (this check done at _each_ aura add + RemoveAura(i2,AURA_REMOVE_BY_STACK); + break; + } - if(stop) + bool stop = false; + switch(aurSpellInfo->EffectApplyAuraName[Aur->GetEffIndex()]) + { + // DoT/HoT/etc + case SPELL_AURA_PERIODIC_DAMAGE: // allow stack + case SPELL_AURA_PERIODIC_DAMAGE_PERCENT: + case SPELL_AURA_PERIODIC_LEECH: + case SPELL_AURA_PERIODIC_HEAL: + case SPELL_AURA_OBS_MOD_HEALTH: + case SPELL_AURA_PERIODIC_MANA_LEECH: + case SPELL_AURA_PERIODIC_ENERGIZE: + case SPELL_AURA_OBS_MOD_MANA: + case SPELL_AURA_POWER_BURN_MANA: + break; + default: // not allow + // can be only single (this check done at _each_ aura add + RemoveAura(i2,AURA_REMOVE_BY_STACK); + stop = true; break; } + + if(stop) + break; } } } @@ -3591,7 +3582,16 @@ void Unit::RemoveSingleAuraFromStack(uint32 spellId, uint32 effindex) { AuraMap::iterator iter = m_Auras.find(spellEffectPair(spellId, effindex)); if(iter != m_Auras.end()) - RemoveAura(iter); + { + if (iter->second->modStackAmount(-1)) + RemoveAura(iter); + } +} + +void Unit::RemoveSingleSpellAurasFromStack(uint32 spellId) +{ + for (int i=0; i<3; ++i) + RemoveSingleAuraFromStack(spellId, i); } void Unit::RemoveAurasDueToSpell(uint32 spellId, Aura* except) @@ -4265,15 +4265,14 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu if (!procSpell || procSpell->Id == 24659) return false; // Need remove one 24659 aura - RemoveSingleAuraFromStack(24659, 0); - RemoveSingleAuraFromStack(24659, 1); + RemoveSingleSpellAurasFromStack(24659); return true; } // Restless Strength case 24661: { // Need remove one 24662 aura - RemoveSingleAuraFromStack(24662, 0); + RemoveSingleSpellAurasFromStack(24662); return true; } // Adaptive Warding (Frostfire Regalia set) @@ -5851,14 +5850,10 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB return false; // stacking CastSpell(this, 37658, true, NULL, triggeredByAura); - // counting - uint32 count = 0; - AuraList const& dummyAura = GetAurasByType(SPELL_AURA_DUMMY); - for(AuraList::const_iterator itr = dummyAura.begin(); itr != dummyAura.end(); ++itr) - if((*itr)->GetId()==37658) - ++count; + + Aura * dummy = GetDummyAura(37658); // release at 3 aura in stack (cont contain in basepoint of trigger aura) - if(count < triggerAmount) + if(!dummy || dummy->GetStackAmount() < triggerAmount) return false; RemoveAurasDueToSpell(37658); @@ -5872,17 +5867,14 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB return false; // stacking CastSpell(this, 54842, true, NULL, triggeredByAura); + // counting - uint32 count = 0; - AuraList const& dummyAura = GetAurasByType(SPELL_AURA_DUMMY); - for(AuraList::const_iterator itr = dummyAura.begin(); itr != dummyAura.end(); ++itr) - if((*itr)->GetId()==54842) - ++count; + Aura * dummy = GetDummyAura(54842); // release at 3 aura in stack (cont contain in basepoint of trigger aura) - if(count < triggerAmount) + if(!dummy || dummy->GetStackAmount() < triggerAmount) return false; - RemoveAurasDueToSpell(54842); + RemoveAurasDueToSpell(54842); trigger_spell_id = 54843; target = pVictim; } diff --git a/src/game/Unit.h b/src/game/Unit.h index 067c73bd92f..cc59b46d5d4 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -1087,6 +1087,7 @@ class MANGOS_DLL_SPEC Unit : public WorldObject void RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode = AURA_REMOVE_BY_DEFAULT); void RemoveAura(uint32 spellId, uint32 effindex, Aura* except = NULL); + void RemoveSingleSpellAurasFromStack(uint32 spellId); void RemoveSingleAuraFromStack(uint32 spellId, uint32 effindex); void RemoveAurasDueToSpell(uint32 spellId, Aura* except = NULL); void RemoveAurasDueToItemSpell(Item* castItem,uint32 spellId); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index c40cac1a844..f77657a8fd1 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 "7048" + #define REVISION_NR "7049" #endif // __REVISION_NR_H__