[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 <dislord@nomail.com>
This commit is contained in:
DiSlord 2009-01-08 01:12:22 +03:00
parent 32a7c35a95
commit c2741b50e7
6 changed files with 352 additions and 346 deletions

View file

@ -337,14 +337,16 @@ pAuraHandler AuraHandler[TOTAL_AURAS]=
}; };
Aura::Aura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target, Unit *caster, Item* castItem) : 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_spellmod(NULL), m_caster_guid(0), m_castItemGuid(castItem?castItem->GetGUID():0), m_target(target),
m_timeCla(1000), m_castItemGuid(castItem?castItem->GetGUID():0), m_auraSlot(MAX_AURAS), m_timeCla(1000), m_periodicTimer(0), m_removeMode(AURA_REMOVE_BY_DEFAULT), m_AuraDRGroup(DIMINISHING_NONE),
m_positive(false), m_permanent(false), m_isPeriodic(false), m_isTrigger(false), m_isAreaAura(false), m_effIndex(eff), m_auraSlot(MAX_AURAS), m_auraFlags(AFLAG_NONE), m_auraLevel(1), m_procCharges(0), m_stackAmount(1),
m_isPersistent(false), m_updated(false), m_removeMode(AURA_REMOVE_BY_DEFAULT), m_isRemovedOnShapeLost(true), m_in_use(false), m_positive(false), m_permanent(false), m_isPeriodic(false), m_isTrigger(false), m_isAreaAura(false), m_isPersistent(false),
m_periodicTimer(0), m_PeriodicEventId(0), m_AuraDRGroup(DIMINISHING_NONE) m_updated(false), m_isRemovedOnShapeLost(true), m_in_use(false)
{ {
assert(target); assert(target);
int32 size = sizeof(Aura);
assert(spellproto && spellproto == sSpellStore.LookupEntry( spellproto->Id ) && "`info` must be pointer to sSpellStore element"); assert(spellproto && spellproto == sSpellStore.LookupEntry( spellproto->Id ) && "`info` must be pointer to sSpellStore element");
m_spellProto = spellproto; m_spellProto = spellproto;
@ -889,12 +891,12 @@ void Aura::_AddAura()
if(!m_target) if(!m_target)
return; return;
// we can found aura in NULL_AURA_SLOT and then need store state instead check slot != NULL_AURA_SLOT // Second aura if some spell
bool samespell = false;
bool secondaura = false; bool secondaura = false;
// Try find slot for aura
uint8 slot = NULL_AURA_SLOT; uint8 slot = NULL_AURA_SLOT;
// Lookup for some spell auras (and get slot from it)
for(uint8 i = 0; i < 3; i++) for(uint8 i = 0; i < m_effIndex; i++)
{ {
Unit::spellEffectPair spair = Unit::spellEffectPair(GetId(), 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) 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 // allow use single slot only by auras from same caster
if(itr->second->GetCasterGUID()==GetCasterGUID()) if(itr->second->GetCasterGUID()==GetCasterGUID())
{ {
samespell = true;
if (m_effIndex > itr->second->GetEffIndex())
secondaura = true;
slot = itr->second->GetAuraSlot(); slot = itr->second->GetAuraSlot();
secondaura = true;
break; break;
} }
} }
if (secondaura)
if(samespell)
break; 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 // not call total regen auras at adding
switch (m_modifier.m_auraname) switch (m_modifier.m_auraname)
{ {
@ -939,59 +953,44 @@ void Aura::_AddAura()
if((!m_isPassive || (caster && caster->GetTypeId() == TYPEID_UNIT && ((Creature*)caster)->isTotem())) && if((!m_isPassive || (caster && caster->GetTypeId() == TYPEID_UNIT && ((Creature*)caster)->isTotem())) &&
(m_spellProto->Effect[GetEffIndex()] != SPELL_EFFECT_APPLY_AREA_AURA_ENEMY || m_target != caster)) (m_spellProto->Effect[GetEffIndex()] != SPELL_EFFECT_APPLY_AREA_AURA_ENEMY || m_target != caster))
{ {
if(!samespell) // new slot need
{
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 ); SetAuraSlot( slot );
if(slot < MAX_AURAS) // slot found send data to client
// Not update fields for not first spell's aura, all data already in fields
if(!secondaura)
{
if(slot < MAX_AURAS) // slot found
{ {
SetAura(false); SetAura(false);
SetAuraFlags((1 << GetEffIndex()) | AFLAG_NOT_CASTER | ((GetAuraMaxDuration() > 0) ? AFLAG_DURATION : AFLAG_NONE) | (IsPositive() ? AFLAG_POSITIVE : AFLAG_NEGATIVE)); 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)); SetAuraLevel(caster ? caster->getLevel() : sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL));
SendAuraUpdate(false); SendAuraUpdate(false);
}
// update for out of range group members //*****************************************************
m_target->UpdateAuraForGroup(slot); // Update target aura state flag (at 1 aura apply)
} // TODO: Make it easer
} //*****************************************************
}
else // use found slot
{
SetAuraSlot( slot );
// Not recalculate stack count for second aura of the same spell
if (!secondaura) if (!secondaura)
UpdateSlotCounterAndDuration(true); {
}
// Update Seals information // Update Seals information
if( IsSealSpell(GetSpellProto()) ) if( IsSealSpell(GetSpellProto()) )
m_target->ModifyAuraState(AURA_STATE_JUDGEMENT, true); m_target->ModifyAuraState(AURA_STATE_JUDGEMENT, true);
// Conflagrate aura state // Conflagrate aura state on Immolate
if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags & 4)) if (m_spellProto->SpellFamilyName == SPELLFAMILY_WARLOCK && m_spellProto->SpellFamilyFlags & 4)
m_target->ModifyAuraState(AURA_STATE_IMMOLATE, true); m_target->ModifyAuraState(AURA_STATE_IMMOLATE, true);
if(GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID // Faerie Fire (druid versions)
&& (GetSpellProto()->SpellFamilyFlags == 0x40 || GetSpellProto()->SpellFamilyFlags == 0x10)) if( m_spellProto->SpellFamilyName == SPELLFAMILY_DRUID && m_spellProto->SpellFamilyFlags & 0x0000000000000400LL)
{ m_target->ModifyAuraState(AURA_STATE_FAERIE_FIRE, true);
// Victorious
if( m_spellProto->SpellFamilyName == SPELLFAMILY_WARRIOR && m_spellProto->SpellFamilyFlags & 0x0004000000000000LL)
m_target->ModifyAuraState(AURA_STATE_WARRIOR_VICTORY_RUSH, true);
// Swiftmend state on Regrowth & Rejuvenation
if(m_spellProto->SpellFamilyName == SPELLFAMILY_DRUID && m_spellProto->SpellFamilyFlags & 0x50 )
m_target->ModifyAuraState(AURA_STATE_SWIFTMEND, true); 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) if(m_target->GetVisibleAura(slot) == 0)
return; return;
bool samespell = false; bool lastaura = true;
bool sameaura = false;
// find other aura in same slot (current already removed from list) // find other aura in same slot (current already removed from list)
for(uint8 i = 0; i < 3; i++) for(uint8 i = 0; i < 3; i++)
@ -1040,30 +1038,30 @@ void Aura::_RemoveAura()
{ {
if(itr->second->GetAuraSlot()==slot) if(itr->second->GetAuraSlot()==slot)
{ {
samespell = true; lastaura = false;
if(GetEffIndex()==i)
sameaura = true;
break; break;
} }
} }
if(samespell) if(!lastaura)
break; break;
} }
// 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 (!samespell) if (lastaura)
{ {
SetAura(true); SetAura(true);
SetAuraFlags(AFLAG_NONE); SetAuraFlags(AFLAG_NONE);
SetAuraLevel(0); SetAuraLevel(0);
SetAuraCharges(0);
SendAuraUpdate(true); SendAuraUpdate(true);
// update for out of range group members // update for out of range group members
m_target->UpdateAuraForGroup(slot); m_target->UpdateAuraForGroup(slot);
//*****************************************************
// Update target aura state flag (at last aura remove)
// TODO: Make it easer
//*****************************************************
// Update Seals information
if( IsSealSpell(GetSpellProto()) ) if( IsSealSpell(GetSpellProto()) )
m_target->ModifyAuraState(AURA_STATE_JUDGEMENT,false); m_target->ModifyAuraState(AURA_STATE_JUDGEMENT,false);
@ -1071,16 +1069,22 @@ void Aura::_RemoveAura()
if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags & 4)) if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags & 4))
m_target->ModifyAuraState(AURA_STATE_IMMOLATE, false); 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 // Swiftmend aura state
if(GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID if(GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID && GetSpellProto()->SpellFamilyFlags & 0x50)
&& (GetSpellProto()->SpellFamilyFlags == 0x40 || GetSpellProto()->SpellFamilyFlags == 0x10))
{ {
bool found = false; bool found = false;
Unit::AuraList const& RejorRegr = m_target->GetAurasByType(SPELL_AURA_PERIODIC_HEAL); Unit::AuraList const& RejorRegr = m_target->GetAurasByType(SPELL_AURA_PERIODIC_HEAL);
for(Unit::AuraList::const_iterator i = RejorRegr.begin(); i != RejorRegr.end(); ++i) for(Unit::AuraList::const_iterator i = RejorRegr.begin(); i != RejorRegr.end(); ++i)
{ {
if((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID if((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID && (*i)->GetSpellProto()->SpellFamilyFlags & 0x50 )
&& ((*i)->GetSpellProto()->SpellFamilyFlags == 0x40 || (*i)->GetSpellProto()->SpellFamilyFlags == 0x10) )
{ {
found = true; found = true;
break; break;
@ -1090,6 +1094,26 @@ void Aura::_RemoveAura()
m_target->ModifyAuraState(AURA_STATE_SWIFTMEND, false); 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 // reset cooldown state for spells
if(caster && caster->GetTypeId() == TYPEID_PLAYER) if(caster && caster->GetTypeId() == TYPEID_PLAYER)
{ {
@ -1097,8 +1121,6 @@ void Aura::_RemoveAura()
((Player*)caster)->SendCooldownEvent(GetSpellProto()); ((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) void Aura::SendAuraUpdate(bool remove)
@ -1117,7 +1139,7 @@ void Aura::SendAuraUpdate(bool remove)
uint8 auraFlags = GetAuraFlags(); uint8 auraFlags = GetAuraFlags();
data << uint8(auraFlags); data << uint8(auraFlags);
data << uint8(GetAuraLevel()); data << uint8(GetAuraLevel());
data << uint8(GetAuraCharges()); data << uint8(m_procCharges ? m_procCharges : m_stackAmount);
if(!(auraFlags & AFLAG_NOT_CASTER)) if(!(auraFlags & AFLAG_NOT_CASTER))
{ {
@ -1133,35 +1155,51 @@ void Aura::SendAuraUpdate(bool remove)
m_target->SendMessageToSet(&data, true); m_target->SendMessageToSet(&data, true);
} }
void Aura::UpdateSlotCounterAndDuration(bool add) void Aura::SetStackAmount(uint8 stackAmount)
{ {
uint8 slot = GetAuraSlot(); if (stackAmount != m_stackAmount)
if(slot >= MAX_AURAS) {
Unit *target = GetTarget();
Unit *caster = GetCaster();
if (!target || !caster)
return; return;
m_stackAmount = stackAmount;
// calculate amount of similar auras by same effect index (similar different spells) int32 amount = m_stackAmount * caster->CalculateSpellDamage(m_spellProto, m_effIndex, m_currentBasePoints, target);
int8 count = 0; // Reapply if amount change
if (amount!=m_modifier.m_amount)
// 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( (*i)->GetId()==GetId() && (*i)->GetEffIndex()==m_effIndex && ApplyModifier(false, true);
(*i)->GetCasterGUID()==GetCasterGUID() ) m_modifier.m_amount = amount;
{ ApplyModifier(true, true);
++count;
if(add)
(*i)->SetAuraDuration(GetAuraDuration());
} }
} }
RefreshAura();
}
// at aura add aura not added yet, at aura remove aura already removed bool Aura::modStackAmount(int32 num)
// in field stored (count-1) {
if(!add) // Can`t mod
--count; 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); SendAuraUpdate(false);
} }
@ -2148,12 +2186,6 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
m_target->RemoveAurasDueToSpell(spellId); m_target->RemoveAurasDueToSpell(spellId);
return; return;
} }
// Victorious
if(GetId()==32216 && m_target->getClass()==CLASS_WARRIOR)
{
m_target->ModifyAuraState(AURA_STATE_WARRIOR_VICTORY_RUSH, apply);
return;
}
//Summon Fire Elemental //Summon Fire Elemental
if (GetId() == 40133 && caster) if (GetId() == 40133 && caster)
{ {
@ -2213,8 +2245,11 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
return; return;
// final heal // final heal
if(m_target->IsInWorld()) if(m_target->IsInWorld() && m_stackAmount > 0)
m_target->CastCustomSpell(m_target,33778,&m_modifier.m_amount,NULL,NULL,true,NULL,this,GetCasterGUID()); {
int32 amount = m_modifier.m_amount / m_stackAmount;
m_target->CastCustomSpell(m_target,33778,&amount,NULL,NULL,true,NULL,this,GetCasterGUID());
}
} }
return; return;
} }
@ -3593,15 +3628,11 @@ void Aura::HandleAuraModSilence(bool apply, bool Real)
return; return;
// Search Mana Tap auras on caster // Search Mana Tap auras on caster
int32 energy = 0; Aura * dummy = caster->GetDummyAura(28734);
Unit::AuraList const& m_dummyAuras = caster->GetAurasByType(SPELL_AURA_DUMMY); if (dummy)
for(Unit::AuraList::const_iterator i = m_dummyAuras.begin(); i != m_dummyAuras.end(); ++i)
if ((*i)->GetId() == 28734)
++energy;
if (energy)
{ {
energy *= 10; int32 bp = dummy->GetStackAmount() * 10;
caster->CastCustomSpell(caster, 25048, &energy, NULL, NULL, true); caster->CastCustomSpell(caster, 25048, &bp, NULL, NULL, true);
caster->RemoveAurasDueToSpell(28734); caster->RemoveAurasDueToSpell(28734);
} }
} }
@ -4089,6 +4120,10 @@ void Aura::HandlePeriodicDamage(bool apply, bool Real)
Unit *caster = GetCaster(); Unit *caster = GetCaster();
// Custom damage calculation after
if (!apply || loading || !caster)
return;
switch (m_spellProto->SpellFamilyName) switch (m_spellProto->SpellFamilyName)
{ {
case SPELLFAMILY_GENERIC: case SPELLFAMILY_GENERIC:
@ -4097,7 +4132,6 @@ void Aura::HandlePeriodicDamage(bool apply, bool Real)
if ( m_spellProto->SpellIconID == 147 && m_spellProto->SpellVisual[0] == 0 ) if ( m_spellProto->SpellIconID == 147 && m_spellProto->SpellVisual[0] == 0 )
{ {
// $AP*0.18/6 bonus per tick // $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; return;
} }
@ -4108,16 +4142,12 @@ void Aura::HandlePeriodicDamage(bool apply, bool Real)
// Rend // Rend
if (m_spellProto->SpellFamilyFlags & 0x0000000000000020LL) if (m_spellProto->SpellFamilyFlags & 0x0000000000000020LL)
{ {
// 0.00743*(($MWB+$mwb)/2+$AP/14*$MWS) bonus per tick // $0.2*(($MWB+$mwb)/2+$AP/14*$MWS) bonus per tick
if (apply && !loading && caster)
{
float ap = caster->GetTotalAttackPowerValue(BASE_ATTACK); float ap = caster->GetTotalAttackPowerValue(BASE_ATTACK);
int32 mws = caster->GetAttackTime(BASE_ATTACK); int32 mws = caster->GetAttackTime(BASE_ATTACK);
float mwb_min = caster->GetWeaponDamageRange(BASE_ATTACK,MINDAMAGE); float mwb_min = caster->GetWeaponDamageRange(BASE_ATTACK,MINDAMAGE);
float mwb_max = caster->GetWeaponDamageRange(BASE_ATTACK,MAXDAMAGE); 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.2f);
m_modifier.m_amount+=int32(((mwb_min+mwb_max)/2+ap*mws/14000)*0.00743f);
}
return; return;
} }
break; break;
@ -4127,25 +4157,24 @@ void Aura::HandlePeriodicDamage(bool apply, bool Real)
// Rake // Rake
if (m_spellProto->SpellFamilyFlags & 0x0000000000001000LL) if (m_spellProto->SpellFamilyFlags & 0x0000000000001000LL)
{ {
// $AP*0.06/3 bonus per tick // $AP*0.06 bonus per tick
if (apply && !loading && caster) m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 6 / 100);
m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 2 / 100);
return; return;
} }
// Lacerate // Lacerate
if (m_spellProto->SpellFamilyFlags & 0x000000010000000000LL) if (m_spellProto->SpellFamilyFlags & 0x000000010000000000LL)
{ {
// $AP*0.05/5 bonus per tick // $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; return;
} }
// Rip // Rip
if (m_spellProto->SpellFamilyFlags & 0x000000000000800000LL) 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] // 0.01*$AP*cp
if (apply && !loading && caster && caster->GetTypeId() == TYPEID_PLAYER) if (caster->GetTypeId() != TYPEID_PLAYER)
{ return;
uint8 cp = ((Player*)caster)->GetComboPoints(); uint8 cp = ((Player*)caster)->GetComboPoints();
// Idol of Feral Shadows. Cant be handled as SpellMod in SpellAura:Dummy due its dependency from CPs // Idol of Feral Shadows. Cant be handled as SpellMod in SpellAura:Dummy due its dependency from CPs
@ -4158,59 +4187,47 @@ void Aura::HandlePeriodicDamage(bool apply, bool Real)
break; 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; return;
} }
break; break;
} }
case SPELLFAMILY_ROGUE: 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 // Rupture
if (m_spellProto->SpellFamilyFlags & 0x000000000000100000LL) 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 (caster->GetTypeId() != TYPEID_PLAYER)
if (apply && !loading && caster && 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(); uint8 cp = ((Player*)caster)->GetComboPoints();
if (cp > 3) cp = 3; if (cp > 5) cp = 5;
m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * cp / 100); m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * AP_per_combo[cp]);
}
return; return;
} }
// Garrote // Garrote
if (m_spellProto->SpellFamilyFlags & 0x000000000000000100LL) if (m_spellProto->SpellFamilyFlags & 0x000000000000000100LL)
{ {
// $AP*0.18/6 bonus per tick // $AP*0.07 bonus per tick
if (apply && !loading && caster) m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 7 / 100);
m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 3 / 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; return;
} }
break; break;
@ -4221,7 +4238,6 @@ void Aura::HandlePeriodicDamage(bool apply, bool Real)
if (m_spellProto->SpellFamilyFlags & 0x0000000000004000LL) if (m_spellProto->SpellFamilyFlags & 0x0000000000004000LL)
{ {
// $RAP*0.1/5 bonus per tick // $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; return;
} }
@ -4229,7 +4245,6 @@ void Aura::HandlePeriodicDamage(bool apply, bool Real)
if (m_spellProto->SpellFamilyFlags & 0x0000000000000004LL && m_spellProto->SpellIconID == 678) if (m_spellProto->SpellFamilyFlags & 0x0000000000000004LL && m_spellProto->SpellIconID == 678)
{ {
// $RAP*0.1/5 bonus per tick // $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; return;
} }
@ -4240,34 +4255,35 @@ void Aura::HandlePeriodicDamage(bool apply, bool Real)
// Consecration // Consecration
if (m_spellProto->SpellFamilyFlags & 0x0000000000000020LL) 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); Unit::AuraList const& classScripts = caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
for(Unit::AuraList::const_iterator k = classScripts.begin(); k != classScripts.end(); ++k) for(Unit::AuraList::const_iterator k = classScripts.begin(); k != classScripts.end(); ++k)
{ {
int32 tickcount = GetSpellDuration(m_spellProto) / m_spellProto->EffectAmplitude[m_effIndex];
switch((*k)->GetModifier()->m_miscvalue) switch((*k)->GetModifier()->m_miscvalue)
{ {
case 5147: // Improved Consecration - Libram of the Eternal Rest case 5147:
{ {
int32 tickcount = GetSpellDuration(m_spellProto) / m_spellProto->EffectAmplitude[m_effIndex];
m_modifier.m_amount += (*k)->GetModifier()->m_amount / tickcount; m_modifier.m_amount += (*k)->GetModifier()->m_amount / tickcount;
break; break;
} }
} }
} }
}
return; 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(m_spellProto->SpellFamilyFlags & 0x0000080000000000LL)
{
if (apply && !loading && caster)
{ {
float ap = caster->GetTotalAttackPowerValue(BASE_ATTACK); float ap = caster->GetTotalAttackPowerValue(BASE_ATTACK);
int32 holy = caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) + int32 holy = caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) +
caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellProto), m_target); caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellProto), m_target);
m_modifier.m_amount += int32(ap * 0.025f) + int32(holy * 13 / 1000); m_modifier.m_amount += int32((0.013f*holy + 0.025f*ap) * GetStackAmount());
}
return; return;
} }
break; break;
@ -4333,14 +4349,6 @@ void Aura::HandleAuraModResistance(bool apply, bool Real)
m_target->ApplyResistanceBuffModsMod(SpellSchools(x),m_positive,m_modifier.m_amount, apply); 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) void Aura::HandleAuraModBaseResistancePCT(bool apply, bool Real)

View file

@ -275,6 +275,11 @@ class MANGOS_DLL_SPEC Aura
void SetAura(bool remove) { m_target->SetVisibleAura(m_auraSlot, remove ? 0 : GetId()); } void SetAura(bool remove) { m_target->SetVisibleAura(m_auraSlot, remove ? 0 : GetId()); }
void SendAuraUpdate(bool remove); 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; } bool IsPositive() { return m_positive; }
void SetNegative() { m_positive = false; } void SetNegative() { m_positive = false; }
void SetPositive() { m_positive = true; } void SetPositive() { m_positive = true; }
@ -320,23 +325,28 @@ class MANGOS_DLL_SPEC Aura
Modifier m_modifier; Modifier m_modifier;
SpellModifier *m_spellmod; SpellModifier *m_spellmod;
uint32 m_effIndex;
SpellEntry const *m_spellProto; SpellEntry const *m_spellProto;
int32 m_currentBasePoints; // cache SpellEntry::EffectBasePoints and use for set custom base points
uint64 m_caster_guid;
Unit* m_target; Unit* m_target;
int32 m_maxduration; uint64 m_caster_guid;
int32 m_duration;
int32 m_timeCla;
uint64 m_castItemGuid; // it is NOT safe to keep a pointer to the item because it may get deleted uint64 m_castItemGuid; // it is NOT safe to keep a pointer to the item because it may get deleted
time_t m_applyTime; 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
uint8 m_auraSlot; AuraRemoveMode m_removeMode:8; // Store info for know remove aura reason
uint8 m_auraFlags; DiminishingGroup m_AuraDRGroup:8; // Diminishing
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_positive:1;
bool m_permanent:1; bool m_permanent:1;
@ -347,14 +357,10 @@ class MANGOS_DLL_SPEC Aura
bool m_isPersistent:1; bool m_isPersistent:1;
bool m_isDeathPersist:1; bool m_isDeathPersist:1;
bool m_isRemovedOnShapeLost: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 bool m_in_use:1; // true while in Aura::ApplyModifier call
int32 m_periodicTimer;
uint32 m_PeriodicEventId;
DiminishingGroup m_AuraDRGroup;
private: private:
void UpdateSlotCounterAndDuration(bool add);
void CleanupTriggeredSpells(); void CleanupTriggeredSpells();
}; };

View file

@ -480,31 +480,29 @@ void Spell::EffectSchoolDMG(uint32 effect_idx)
// consume from stack dozes not more that have combo-points // consume from stack dozes not more that have combo-points
if(uint32 combo = ((Player*)m_caster)->GetComboPoints()) if(uint32 combo = ((Player*)m_caster)->GetComboPoints())
{ {
// count consumed deadly poison doses at target Aura *poison = 0;
uint32 doses = 0; // Lookup for Deadly poison (only attacker applied)
// remove consumed poison doses
Unit::AuraList const& auras = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE); Unit::AuraList const& auras = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
for(Unit::AuraList::const_iterator itr = auras.begin(); itr!=auras.end() && combo;) for(Unit::AuraList::const_iterator itr = auras.begin(); itr!=auras.end() && combo;)
if( (*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_ROGUE &&
(*itr)->GetSpellProto()->SpellFamilyFlags & 0x10000 &&
(*itr)->GetCasterGUID()==m_caster->GetGUID() )
{ {
// Deadly poison (only attacker applied) poison = *itr;
if( (*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_ROGUE && ((*itr)->GetSpellProto()->SpellFamilyFlags & 0x10000) && break;
(*itr)->GetSpellProto()->SpellVisual[0]==5100 && (*itr)->GetCasterGUID()==m_caster->GetGUID() ) }
// count consumed deadly poison doses at target
if (poison)
{ {
--combo; uint32 spellId = poison->GetId();
++doses; uint32 doses = poison->GetStackAmount();
if (doses > combo)
unitTarget->RemoveSingleAuraFromStack((*itr)->GetId(), (*itr)->GetEffIndex()); doses = combo;
for (int i=0; i< doses; i++)
itr = auras.begin(); unitTarget->RemoveSingleSpellAurasFromStack(spellId);
}
else
++itr;
}
damage *= doses; damage *= doses;
damage += int32(((Player*)m_caster)->GetTotalAttackPowerValue(BASE_ATTACK) * 0.03f * doses); damage += int32(((Player*)m_caster)->GetTotalAttackPowerValue(BASE_ATTACK) * 0.03f * doses);
}
// Eviscerate and Envenom Bonus Damage (item set effect) // Eviscerate and Envenom Bonus Damage (item set effect)
if(m_caster->GetDummyAura(37169)) if(m_caster->GetDummyAura(37169))
damage += ((Player*)m_caster)->GetComboPoints()*40; damage += ((Player*)m_caster)->GetComboPoints()*40;
@ -572,19 +570,25 @@ void Spell::EffectSchoolDMG(uint32 effect_idx)
} }
case SPELLFAMILY_PALADIN: 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) 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; uint32 stacks = 0;
Unit::AuraList const& auras = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE); Unit::AuraList const& auras = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
for(Unit::AuraList::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr) for(Unit::AuraList::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
if((*itr)->GetId() == 31803 && (*itr)->GetCasterGUID()==m_caster->GetGUID()) if((*itr)->GetId() == 31803 && (*itr)->GetCasterGUID()==m_caster->GetGUID())
++stacks; {
if(!stacks) stacks = (*itr)->GetStackAmount();
//No damage if the target isn't affected by this break;
damage = -1; }
else // + 10% for each application of Holy Vengeance on the target
damage *= stacks; if(stacks)
damage += damage * stacks * 10 /100;
} }
// Avenger's Shield ($m1+0.07*$SPH+0.07*$AP) // Avenger's Shield ($m1+0.07*$SPH+0.07*$AP)
else if(m_spellInfo->SpellFamilyFlags & 0x0000000000004000LL) else if(m_spellInfo->SpellFamilyFlags & 0x0000000000004000LL)
@ -943,16 +947,12 @@ void Spell::EffectDummy(uint32 i)
} }
case 28730: // Arcane Torrent (Mana) case 28730: // Arcane Torrent (Mana)
{ {
int32 count = 0; Aura * dummy = m_caster->GetDummyAura(28734);
Unit::AuraList const& m_dummyAuras = m_caster->GetAurasByType(SPELL_AURA_DUMMY); if (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 * dummy->GetStackAmount();
int32 bp = damage * count;
m_caster->CastCustomSpell(m_caster, 28733, &bp, NULL, NULL, true); m_caster->CastCustomSpell(m_caster, 28733, &bp, NULL, NULL, true);
m_caster->RemoveAurasDueToSpell(28734);
} }
return; return;
} }
@ -4217,21 +4217,22 @@ void Spell::EffectWeaponDmg(uint32 i)
// Devastate bonus and sunder armor refresh // Devastate bonus and sunder armor refresh
else if(m_spellInfo->SpellVisual[0] == 671 && m_spellInfo->SpellIconID == 1508) else if(m_spellInfo->SpellVisual[0] == 671 && m_spellInfo->SpellIconID == 1508)
{ {
customBonusDamagePercentMod = true; uint32 stack = 0;
bonusDamagePercentMod = 0.0f; // only applied if auras found // Need refresh all Sunder Armor auras from this caster
Unit::AuraMap& suAuras = unitTarget->GetAuras();
Unit::AuraList const& list = unitTarget->GetAurasByType(SPELL_AURA_MOD_RESISTANCE); for(Unit::AuraMap::iterator itr = suAuras.begin(); itr != suAuras.end(); ++itr)
for(Unit::AuraList::const_iterator itr=list.begin();itr!=list.end();++itr)
{ {
SpellEntry const *proto = (*itr)->GetSpellProto(); SpellEntry const *spellInfo = (*itr).second->GetSpellProto();
if(proto->SpellVisual[0] == 406 && proto->SpellIconID == 565) if( spellInfo->SpellFamilyName == SPELLFAMILY_WARRIOR &&
spellInfo->SpellFamilyFlags & 0x0000000000004000LL &&
(*itr).second->GetCasterGUID() == m_caster->GetGUID())
{ {
int32 duration = GetSpellDuration(proto); (*itr).second->RefreshAura();
(*itr)->SetAuraDuration(duration); stack = (*itr).second->GetStackAmount();
(*itr)->SendAuraUpdate(false);
bonusDamagePercentMod += 1.0f; // +100%
} }
} }
if (stack)
spell_bonus += stack * CalculateDamage(2, unitTarget);
} }
break; break;
} }
@ -4644,12 +4645,11 @@ void Spell::EffectScriptEffect(uint32 effIndex)
} }
// Brittle Armor - need remove one 24575 Brittle Armor aura // Brittle Armor - need remove one 24575 Brittle Armor aura
case 24590: case 24590:
unitTarget->RemoveSingleAuraFromStack(24575, 0); unitTarget->RemoveSingleSpellAurasFromStack(24575);
unitTarget->RemoveSingleAuraFromStack(24575, 1);
return; return;
// Mercurial Shield - need remove one 26464 Mercurial Shield aura // Mercurial Shield - need remove one 26464 Mercurial Shield aura
case 26465: case 26465:
unitTarget->RemoveSingleAuraFromStack(26464, 0); unitTarget->RemoveSingleSpellAurasFromStack(26464);
return; return;
// Orb teleport spells // Orb teleport spells
case 25140: case 25140:
@ -4900,8 +4900,7 @@ void Spell::EffectScriptEffect(uint32 effIndex)
if (!(familyFlag & 0x000000800000C000LL)) if (!(familyFlag & 0x000000800000C000LL))
continue; continue;
// Refresh aura duration // Refresh aura duration
aura->SetAuraDuration(aura->GetAuraMaxDuration()); aura->RefreshAura();
aura->SendAuraUpdate(false);
// Serpent Sting - Instantly deals 40% of the damage done by your Serpent Sting. // Serpent Sting - Instantly deals 40% of the damage done by your Serpent Sting.
if (familyFlag & 0x0000000000004000LL && aura->GetEffIndex() == 0) if (familyFlag & 0x0000000000004000LL && aura->GetEffIndex() == 0)

View file

@ -1131,10 +1131,7 @@ void Unit::DealSpellDamage(SpellNonMeleeDamage *damageInfo, bool durabilityLoss)
{ {
SpellEntry const *spellInfo = (*itr).second->GetSpellProto(); SpellEntry const *spellInfo = (*itr).second->GetSpellProto();
if( spellInfo->AttributesEx3 & 0x40000 && spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN && ((*itr).second->GetCasterGUID() == GetGUID())) if( spellInfo->AttributesEx3 & 0x40000 && spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN && ((*itr).second->GetCasterGUID() == GetGUID()))
{ (*itr).second->RefreshAura();
(*itr).second->SetAuraDuration((*itr).second->GetAuraMaxDuration());
(*itr).second->SendAuraUpdate(false);
}
} }
} }
// Call default DealDamage // Call default DealDamage
@ -1490,10 +1487,7 @@ void Unit::DealMeleeDamage(CalcDamageInfo *damageInfo, bool durabilityLoss)
{ {
SpellEntry const *spellInfo = (*itr).second->GetSpellProto(); SpellEntry const *spellInfo = (*itr).second->GetSpellProto();
if( spellInfo->AttributesEx3 & 0x40000 && spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN && ((*itr).second->GetCasterGUID() == GetGUID())) if( spellInfo->AttributesEx3 & 0x40000 && spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN && ((*itr).second->GetCasterGUID() == GetGUID()))
{ (*itr).second->RefreshAura();
(*itr).second->SetAuraDuration((*itr).second->GetAuraMaxDuration());
(*itr).second->SendAuraUpdate(false);
}
} }
} }
@ -3194,20 +3188,18 @@ bool Unit::AddAura(Aura *Aur)
{ {
// passive and persistent auras can stack with themselves any number of times // passive and persistent auras can stack with themselves any number of times
if (!Aur->IsPassive() && !Aur->IsPersistent()) if (!Aur->IsPassive() && !Aur->IsPersistent())
{
// replace aura if next will > spell StackAmount
if(aurSpellInfo->StackAmount)
{
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) 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())
{ {
// Aura can stack on self -> Stack it;
if(aurSpellInfo->StackAmount)
{
i2->second->modStackAmount(1);
delete Aur;
return false;
}
// can be only single (this check done at _each_ aura add // can be only single (this check done at _each_ aura add
RemoveAura(i2,AURA_REMOVE_BY_STACK); RemoveAura(i2,AURA_REMOVE_BY_STACK);
break; break;
@ -3239,7 +3231,6 @@ bool Unit::AddAura(Aura *Aur)
} }
} }
} }
}
// passive auras not stacable with other ranks // passive auras not stacable with other ranks
if (!IsPassiveSpellStackableWithRanks(aurSpellInfo)) if (!IsPassiveSpellStackableWithRanks(aurSpellInfo))
@ -3591,8 +3582,17 @@ void Unit::RemoveSingleAuraFromStack(uint32 spellId, uint32 effindex)
{ {
AuraMap::iterator iter = m_Auras.find(spellEffectPair(spellId, effindex)); AuraMap::iterator iter = m_Auras.find(spellEffectPair(spellId, effindex));
if(iter != m_Auras.end()) if(iter != m_Auras.end())
{
if (iter->second->modStackAmount(-1))
RemoveAura(iter); RemoveAura(iter);
} }
}
void Unit::RemoveSingleSpellAurasFromStack(uint32 spellId)
{
for (int i=0; i<3; ++i)
RemoveSingleAuraFromStack(spellId, i);
}
void Unit::RemoveAurasDueToSpell(uint32 spellId, Aura* except) 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) if (!procSpell || procSpell->Id == 24659)
return false; return false;
// Need remove one 24659 aura // Need remove one 24659 aura
RemoveSingleAuraFromStack(24659, 0); RemoveSingleSpellAurasFromStack(24659);
RemoveSingleAuraFromStack(24659, 1);
return true; return true;
} }
// Restless Strength // Restless Strength
case 24661: case 24661:
{ {
// Need remove one 24662 aura // Need remove one 24662 aura
RemoveSingleAuraFromStack(24662, 0); RemoveSingleSpellAurasFromStack(24662);
return true; return true;
} }
// Adaptive Warding (Frostfire Regalia set) // Adaptive Warding (Frostfire Regalia set)
@ -5851,14 +5850,10 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB
return false; return false;
// stacking // stacking
CastSpell(this, 37658, true, NULL, triggeredByAura); CastSpell(this, 37658, true, NULL, triggeredByAura);
// counting
uint32 count = 0; Aura * dummy = GetDummyAura(37658);
AuraList const& dummyAura = GetAurasByType(SPELL_AURA_DUMMY);
for(AuraList::const_iterator itr = dummyAura.begin(); itr != dummyAura.end(); ++itr)
if((*itr)->GetId()==37658)
++count;
// release at 3 aura in stack (cont contain in basepoint of trigger aura) // release at 3 aura in stack (cont contain in basepoint of trigger aura)
if(count < triggerAmount) if(!dummy || dummy->GetStackAmount() < triggerAmount)
return false; return false;
RemoveAurasDueToSpell(37658); RemoveAurasDueToSpell(37658);
@ -5872,14 +5867,11 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB
return false; return false;
// stacking // stacking
CastSpell(this, 54842, true, NULL, triggeredByAura); CastSpell(this, 54842, true, NULL, triggeredByAura);
// counting // counting
uint32 count = 0; Aura * dummy = GetDummyAura(54842);
AuraList const& dummyAura = GetAurasByType(SPELL_AURA_DUMMY);
for(AuraList::const_iterator itr = dummyAura.begin(); itr != dummyAura.end(); ++itr)
if((*itr)->GetId()==54842)
++count;
// release at 3 aura in stack (cont contain in basepoint of trigger aura) // release at 3 aura in stack (cont contain in basepoint of trigger aura)
if(count < triggerAmount) if(!dummy || dummy->GetStackAmount() < triggerAmount)
return false; return false;
RemoveAurasDueToSpell(54842); RemoveAurasDueToSpell(54842);

View file

@ -1087,6 +1087,7 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
void RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode = AURA_REMOVE_BY_DEFAULT); void RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode = AURA_REMOVE_BY_DEFAULT);
void RemoveAura(uint32 spellId, uint32 effindex, Aura* except = NULL); void RemoveAura(uint32 spellId, uint32 effindex, Aura* except = NULL);
void RemoveSingleSpellAurasFromStack(uint32 spellId);
void RemoveSingleAuraFromStack(uint32 spellId, uint32 effindex); void RemoveSingleAuraFromStack(uint32 spellId, uint32 effindex);
void RemoveAurasDueToSpell(uint32 spellId, Aura* except = NULL); void RemoveAurasDueToSpell(uint32 spellId, Aura* except = NULL);
void RemoveAurasDueToItemSpell(Item* castItem,uint32 spellId); void RemoveAurasDueToItemSpell(Item* castItem,uint32 spellId);

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 "7048" #define REVISION_NR "7049"
#endif // __REVISION_NR_H__ #endif // __REVISION_NR_H__