Index: game/SpellAuras.cpp =================================================================== --- game/SpellAuras.cpp (revision 5306) +++ game/SpellAuras.cpp (working copy) @@ -394,6 +394,11 @@ else m_procCharges = -1; + // count from 1 + m_stackAmmount = 1; + // give it some damage + m_stackDamage = damage; + m_isRemovedOnShapeLost = (m_caster_guid==m_target->GetGUID() && m_spellProto->Stances && !(m_spellProto->AttributesEx2 & 0x80000) && !(m_spellProto->Attributes & 0x10000)); } @@ -741,20 +746,8 @@ if(!m_target) return; - bool samespell = false; uint8 slot = 0xFF; - for(uint8 i = 0; i < 3; i++) - { - Aura* aura = m_target->GetAura(m_spellId, i); - if(aura) - { - samespell = true; - slot = aura->GetAuraSlot(); - break; - } - } - //if(m_spellId == 23333 || m_spellId == 23335) // for BG // m_positive = true; @@ -776,56 +769,49 @@ // passive auras (except totem auras) do not get placed in the slots if(!m_isPassive || (caster && caster->GetTypeId() == TYPEID_UNIT && ((Creature*)caster)->isTotem())) { - if(!samespell) + if (IsPositive()) { - if (IsPositive()) + for (uint8 i = 0; i < MAX_POSITIVE_AURAS; i++) { - for (uint8 i = 0; i < MAX_POSITIVE_AURAS; i++) + if (m_target->GetUInt32Value((uint16)(UNIT_FIELD_AURA + i)) == 0) { - if (m_target->GetUInt32Value((uint16)(UNIT_FIELD_AURA + i)) == 0) - { - slot = i; - break; - } + slot = i; + break; } } - else + } + else + { + for (uint8 i = MAX_POSITIVE_AURAS; i < MAX_AURAS; i++) { - for (uint8 i = MAX_POSITIVE_AURAS; i < MAX_AURAS; i++) + if (m_target->GetUInt32Value((uint16)(UNIT_FIELD_AURA + i)) == 0) { - if (m_target->GetUInt32Value((uint16)(UNIT_FIELD_AURA + i)) == 0) - { - slot = i; - break; - } + slot = i; + break; } } + } - if(slot < MAX_AURAS) - { - m_target->SetUInt32Value((uint16)(UNIT_FIELD_AURA + slot), GetId()); + if(slot < MAX_AURAS) + { + m_target->SetUInt32Value((uint16)(UNIT_FIELD_AURA + slot), GetId()); - uint8 flagslot = slot >> 2; - uint32 value = m_target->GetUInt32Value((uint16)(UNIT_FIELD_AURAFLAGS + flagslot)); + uint8 flagslot = slot >> 2; + uint32 value = m_target->GetUInt32Value((uint16)(UNIT_FIELD_AURAFLAGS + flagslot)); + + uint8 value1 = (slot & 3) << 3; - uint8 value1 = (slot & 3) << 3; + value &= ~((uint32)AFLAG_MASK << value1); + if (IsPositive()) + value |= ((uint32)AFLAG_POSITIVE << value1); + else + value |= ((uint32)AFLAG_NEGATIVE << value1); + m_target->SetUInt32Value((uint16)(UNIT_FIELD_AURAFLAGS + flagslot), value); + } - value &= ~((uint32)AFLAG_MASK << value1); - if (IsPositive()) - value |= ((uint32)AFLAG_POSITIVE << value1); - else - value |= ((uint32)AFLAG_NEGATIVE << value1); - m_target->SetUInt32Value((uint16)(UNIT_FIELD_AURAFLAGS + flagslot), value); - } + SetAuraSlot( slot ); + UpdateAuraDuration(); - SetAuraSlot( slot ); - UpdateAuraDuration(); - } - else - { - SetAuraSlot( slot ); - UpdateSlotCounterAndDuration(true); - } // Update Seals information if( IsSealSpell(GetId()) ) @@ -878,93 +864,90 @@ if(m_target->GetUInt32Value((uint16)(UNIT_FIELD_AURA + slot)) == 0) return; - bool samespell = false; + m_target->SetUInt32Value((uint16)(UNIT_FIELD_AURA + slot), 0); - for(uint8 i = 0; i < 3; i++) - { - Aura* aura = m_target->GetAura(m_spellId, i); - if(aura) - { - samespell = true; - break; - } - } + uint8 flagslot = slot >> 2; - // only remove icon when the last aura of the spell is removed (current aura already removed from list) - if (!samespell) - { - m_target->SetUInt32Value((uint16)(UNIT_FIELD_AURA + slot), 0); + uint32 value = m_target->GetUInt32Value((uint16)(UNIT_FIELD_AURAFLAGS + flagslot)); - uint8 flagslot = slot >> 2; + uint8 aurapos = (slot & 3) << 3; + value &= ~((uint32)AFLAG_MASK << aurapos ); - uint32 value = m_target->GetUInt32Value((uint16)(UNIT_FIELD_AURAFLAGS + flagslot)); + m_target->SetUInt32Value((uint16)(UNIT_FIELD_AURAFLAGS + flagslot), value); + if( IsSealSpell(GetId()) ) + m_target->ModifyAuraState(AURA_STATE_JUDGEMENT,false); - uint8 aurapos = (slot & 3) << 3; - value &= ~((uint32)AFLAG_MASK << aurapos ); + // Conflagrate aura state + if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags & 4)) + m_target->ModifyAuraState(AURA_STATE_IMMOLATE, false); - m_target->SetUInt32Value((uint16)(UNIT_FIELD_AURAFLAGS + flagslot), value); - if( IsSealSpell(GetId()) ) - m_target->ModifyAuraState(AURA_STATE_JUDGEMENT,false); - - // Conflagrate aura state - if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags & 4)) - m_target->ModifyAuraState(AURA_STATE_IMMOLATE, false); - - // Swiftmend aura state - if(GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID - && (GetSpellProto()->SpellFamilyFlags == 0x40 || GetSpellProto()->SpellFamilyFlags == 0x10)) + // Swiftmend aura state + if(GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID + && (GetSpellProto()->SpellFamilyFlags == 0x40 || GetSpellProto()->SpellFamilyFlags == 0x10)) + { + 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) { - 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 == 0x40 || (*i)->GetSpellProto()->SpellFamilyFlags == 0x10) ) - { - found = true; - break; - } + found = true; + break; } - if(!found) - m_target->ModifyAuraState(AURA_STATE_SWIFTMEND, false); } - - // reset cooldown state for spells infinity/long aura (it's all self applied (?)) - int32 duration = GetDuration(GetSpellProto()); - if( caster==m_target && ( duration < 0 || uint32(duration) > GetRecoveryTime(GetSpellProto()) )) - SendCoolDownEvent(); + if(!found) + m_target->ModifyAuraState(AURA_STATE_SWIFTMEND, false); } - else // decrease count for spell - UpdateSlotCounterAndDuration(false); + + // reset cooldown state for spells infinity/long aura (it's all self applied (?)) + int32 duration = GetDuration(GetSpellProto()); + if( caster==m_target && ( duration < 0 || uint32(duration) > GetRecoveryTime(GetSpellProto()) )) + SendCoolDownEvent(); + } -void Aura::UpdateSlotCounterAndDuration(bool add) +void Aura::ModStackAmmount(int32 val) { + // Already Full + if( (m_stackAmmount + val) > m_spellProto->StackAmount ) + { + val = m_spellProto->StackAmount - m_stackAmmount; + // nothing to change + if ( val == 0 ) + return; + } + + m_stackAmmount += val; + + // remove if empty + if ( m_stackAmmount <= 0 ) + { + m_target->RemoveAura(m_spellId, m_effIndex); + return; + } + // modify damage + m_modifier.m_amount += m_stackDamage * val; + +} + +void Aura::UpdateStackableAura(Unit* caster) +{ uint8 slot = GetAuraSlot(); if(slot >= MAX_AURAS) return; - // calculate amount of similar auras by same effect index (similar different spells) - int8 count = 0; + SetAuraDuration(caster->CalculateSpellDuration(m_spellProto)); - // 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)->m_spellId==m_spellId && (*i)->m_effIndex==m_effIndex) - { - ++count; - - if(add) - (*i)->SetAuraDuration(GetAuraDuration()); - } + // If not full yet + if ( m_stackAmmount < m_spellProto->StackAmount ) + { + m_stackAmmount++; + // recalculate damage + m_stackDamage = caster->CalculateSpellDamage(m_spellProto,m_effIndex,m_currentBasePoints,m_target); + m_modifier.m_amount = m_stackDamage*m_stackAmmount; } - // at aura add aura not added yet, at aura remove aura already removed - // in field stored (count-1) - if(!add) - --count; - uint32 index = slot / 4; uint32 byte = slot % 4; uint32 val = m_target->GetUInt32Value(UNIT_FIELD_AURAAPPLICATIONS+index); @@ -972,7 +955,7 @@ uint32 byte_bitpos = byte * 8; uint32 byte_mask = 0xFF << (byte * 8); - val = (val & ~byte_mask) | (count << byte_bitpos); + val = (val & ~byte_mask) | (m_stackAmmount << byte_bitpos); m_target->SetUInt32Value(UNIT_FIELD_AURAAPPLICATIONS+index, val); Index: game/SpellAuras.h =================================================================== --- game/SpellAuras.h (revision 5306) +++ game/SpellAuras.h (working copy) @@ -259,6 +259,10 @@ void SetUpdated(bool val) { m_updated = val; } void SetRemoveOnDeath(bool rod) { m_removeOnDeath = rod; } + void UpdateStackableAura(Unit* caster); + uint32 GetStackAmmount( void ) { return m_stackAmmount; } + void ModStackAmmount(int32 val); + int32 m_procCharges; // add/remove SPELL_AURA_MOD_SHAPESHIFT (36) linked auras @@ -295,8 +299,10 @@ uint32 m_PeriodicEventId; bool m_updated; bool m_removeOnDeath; + + uint32 m_stackAmmount; + int32 m_stackDamage; private: - void UpdateSlotCounterAndDuration(bool add); void CleanupTriggeredSpells(); float m_fearMoveAngle; Index: game/SpellEffects.cpp =================================================================== --- game/SpellEffects.cpp (revision 5306) +++ game/SpellEffects.cpp (working copy) @@ -342,20 +342,23 @@ // remove consumed poison doses 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();++itr) { // Deadly poison if((*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_ROGUE && ((*itr)->GetSpellProto()->SpellFamilyFlags & 0x10000) && (*itr)->GetSpellProto()->SpellVisual==5100) { - --combo; - ++doses; - unitTarget->RemoveSingleAuraFromStack((*itr)->GetId(), (*itr)->GetEffIndex()); + if ( combo > (*itr)->GetStackAmmount()) + combo = (*itr)->GetStackAmmount(); - itr = auras.begin(); + doses = (*itr)->GetStackAmmount(); + + if ( doses > combo) + doses = combo; + + (*itr)->ModStackAmmount(combo*(-1)); + break; } - else - ++itr; } damage *= doses; @@ -421,8 +424,13 @@ 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) - stacks++; + { + stacks=(*itr)->GetStackAmmount(); + break; + } + } if(!stacks) //No damage if the target isn't affected by this damage = -1; @@ -3229,7 +3237,8 @@ int32 duration = GetDuration(proto); (*itr)->SetAuraDuration(duration); (*itr)->UpdateAuraDuration(); - sunder_stacks++; + sunder_stacks=(*itr)->GetStackAmmount(); + break; } } Index: game/Unit.cpp =================================================================== --- game/Unit.cpp (revision 5306) +++ game/Unit.cpp (working copy) @@ -3435,14 +3435,14 @@ // take out same spell if (i != m_Auras.end()) { - /*(*i).second->SetAuraDuration(Aur->GetAuraDuration()); - if ((*i).second->GetTarget()) - if ((*i).second->GetTarget()->GetTypeId() == TYPEID_PLAYER ) - (*i).second->UpdateAuraDuration(); - delete Aur; - return false;*/ + if ( Aur->GetSpellProto()->StackAmount) + { + Aur->UpdateStackableAura(this); + delete Aur; + return false; + } // passive and persistent auras can stack with themselves any number of times - if (!Aur->IsPassive() && !Aur->IsPersistent() && m_Auras.count(spellEffectPair(Aur->GetId(), Aur->GetEffIndex())) >= Aur->GetSpellProto()->StackAmount) + if (!Aur->IsPassive() && !Aur->IsPersistent()) RemoveAura(i); } @@ -3739,13 +3739,6 @@ RemoveAura(iter); } -void Unit::RemoveSingleAuraFromStack(uint32 spellId, uint32 effindex) -{ - AuraMap::iterator iter = m_Auras.find(spellEffectPair(spellId, effindex)); - if(iter != m_Auras.end()) - RemoveAura(iter); -} - void Unit::RemoveAurasDueToSpell(uint32 spellId) { for (int i = 0; i < 3; ++i) Index: game/Unit.h =================================================================== --- game/Unit.h (revision 5306) +++ game/Unit.h (working copy) @@ -810,7 +810,6 @@ bool RemoveFirstAuraByDispel(uint32 dispel_type, Unit *pCaster); void RemoveAura(AuraMap::iterator &i, bool onDeath = false); void RemoveAura(uint32 spellId, uint32 effindex); - void RemoveSingleAuraFromStack(uint32 spellId, uint32 effindex); void RemoveAurasDueToSpell(uint32 spellId); void RemoveAurasDueToItem(Item* castItem); void RemoveSpellsCausingAura(AuraType auraType);