From 8963006729674211b69bad0948b2de8d82078d62 Mon Sep 17 00:00:00 2001 From: QAston Date: Fri, 13 Mar 2009 20:24:40 +0100 Subject: [PATCH] *More strict for auras to put in visible slots. *Do linked auras triggers only on first/last aura change. *Fixed issues with auras applied for slots which did not fit to visible aura slots. *Fix guardian spirit buff remove. --HG-- branch : trunk --- src/game/SpellAuras.cpp | 148 +++++++++++++++++++++++++--------------- src/game/Unit.cpp | 47 +------------ src/game/Unit.h | 4 +- 3 files changed, 98 insertions(+), 101 deletions(-) diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index c016d9ca98..ad00013bbb 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -797,7 +797,7 @@ void Aura::_AddAura() // passive auras (except totem auras) do not get placed in the slots // area auras with SPELL_AURA_NONE are not shown on target // all further code applies only to active spells - if(!((m_spellProto->Attributes & 0x80 || !m_isPassive || (caster && caster->GetTypeId() == TYPEID_UNIT && ((Creature*)caster)->isTotem())) && + if(!(((m_spellProto->Attributes & 0x80 && GetTalentSpellPos(GetId())) || !m_isPassive || (caster && caster->GetTypeId() == TYPEID_UNIT && ((Creature*)caster)->isTotem())) && (m_spellProto->Effect[GetEffIndex()] != SPELL_EFFECT_APPLY_AREA_AURA_ENEMY || m_target != caster))) return; @@ -815,8 +815,6 @@ void Aura::_AddAura() if(itr->second->GetCasterGUID()==GetCasterGUID()) { slot = itr->second->GetAuraSlot(); - if(slot >= MAX_AURAS) - return; secondaura = true; break; } @@ -825,46 +823,48 @@ void Aura::_AddAura() break; } - // Lookup free slot - if (!secondaura) + Unit::VisibleAuraMap const *visibleAuras = m_target->GetVisibleAuras(); + if(visibleAuras->size() < MAX_AURAS || slot < MAX_AURAS) // got free slot { - Unit::VisibleAuraMap const *visibleAuras = m_target->GetVisibleAuras(); - if(visibleAuras->size() >= MAX_AURAS) // no free slot - return; - - Unit::VisibleAuraMap::const_iterator itr = visibleAuras->begin(); - for(int freeSlot = 0; freeSlot < MAX_AURAS; ++itr, ++freeSlot) + // Lookup free slot + if (!secondaura) { - if(itr == visibleAuras->end() || itr->first != freeSlot) + Unit::VisibleAuraMap::const_iterator itr = visibleAuras->begin(); + for(int freeSlot = 0; freeSlot < MAX_AURAS; ++itr, ++freeSlot) { - slot = freeSlot; - break; + if(itr == visibleAuras->end() || itr->first != freeSlot) + { + slot = freeSlot; + break; + } } + assert(slot < MAX_AURAS); // assert that we find a slot and it is valid + + AuraSlotEntry t_entry; + t_entry.m_Flags=(IsPositive() ? AFLAG_POSITIVE : AFLAG_NEGATIVE) | AFLAG_NOT_CASTER | ((GetAuraMaxDuration() > 0) ? AFLAG_DURATION : AFLAG_NONE); + t_entry.m_Level=(caster ? caster->getLevel() : sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)); + t_entry.m_spellId = GetId(); + //init pointers-prevent unexpected behaviour + for(uint8 i = 0; i < 3; i++) + t_entry.m_slotAuras[i]=NULL; + + m_target->SetVisibleAura(slot, t_entry); } - assert(slot < MAX_AURAS); // assert that we find a slot and it is valid - AuraSlotEntry t_entry; - t_entry.m_Flags=(IsPositive() ? AFLAG_POSITIVE : AFLAG_NEGATIVE) | AFLAG_NOT_CASTER | ((GetAuraMaxDuration() > 0) ? AFLAG_DURATION : AFLAG_NONE); - t_entry.m_Level=(caster ? caster->getLevel() : sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)); + if(AuraSlotEntry *entry = m_target->GetVisibleAura(slot)) + { + entry->m_Flags |= (1 << GetEffIndex()); + entry->m_slotAuras[GetEffIndex()]=this; - //init pointers-prevent unexpected behaviour - for(uint8 i = 0; i < 3; i++) - t_entry.m_slotAuras[i]=NULL; + SetAuraSlot( slot ); - m_target->SetVisibleAura(slot, t_entry); + // update for out of range group members (on 1 slot use) + m_target->UpdateAuraForGroup(slot); + sLog.outDebug("Aura: %u Effect: %d put to unit visible auras slot: %u",GetId(), GetEffIndex(), slot); + } } - - AuraSlotEntry *entry = m_target->GetVisibleAura(slot); - if(!entry) - return; - - entry->m_Flags |= (1 << GetEffIndex()); - entry->m_slotAuras[GetEffIndex()]=this; - - SetAuraSlot( slot ); - - // update for out of range group members (on 1 slot use) - m_target->UpdateAuraForGroup(slot); + else + sLog.outDebug("Aura: %u Effect: %d could not find empty unit visible slot",GetId(), GetEffIndex()); //***************************************************** // Update target aura state flag @@ -880,6 +880,18 @@ void Aura::_AddAura() // register aura diminishing on apply if (getDiminishGroup() != DIMINISHING_NONE ) m_target->ApplyDiminishingAura(getDiminishGroup(),true); + + // Apply linked auras (On first aura apply) + uint32 id = GetId(); + if(spellmgr.GetSpellCustomAttr(id) & SPELL_ATTR_CU_LINK_AURA) + { + if(const std::vector *spell_triggered = spellmgr.GetSpellLinked(id + SPELL_LINK_AURA)) + for(std::vector::const_iterator itr = spell_triggered->begin(); itr != spell_triggered->end(); ++itr) + if(*itr < 0) + m_target->ApplySpellImmune(id, IMMUNITY_ID, *itr, m_target); + else if(Unit* caster = GetCaster()) + m_target->AddAura(*itr, m_target); + } } // Update Seals information @@ -930,39 +942,44 @@ void Aura::_RemoveAura() // return; uint8 slot = GetAuraSlot(); - if(slot >= MAX_AURAS) // slot not set - return; - - bool lastaura=true; - - AuraSlotEntry *entry = m_target->GetVisibleAura(slot); - if (entry) + if(slot < MAX_AURAS) // slot not set { - // we have more auras, do not clear slot - if (entry->m_slotAuras[GetEffIndex()]==this) + if (AuraSlotEntry *entry = m_target->GetVisibleAura(slot)) { - entry->m_slotAuras[GetEffIndex()]=NULL; //unregister aura - for(uint8 i = 0; i < 3; ++i) //check slot for more auras of the spell + // we have more auras, do not clear slot + if (entry->m_slotAuras[GetEffIndex()]==this) { - if(entry->m_slotAuras[i]) - { - lastaura = false; - break; - } + entry->m_slotAuras[GetEffIndex()]=NULL; //unregister aura } } } - // only remove icon when the last aura of the spell is removed (current aura already removed from list) - if(lastaura) + bool lastaura=true; + for(uint8 i = 0; i < 3; 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) + { + if(itr->second->GetCasterGUID()==GetCasterGUID()) + { + lastaura = false; + break; + } + } + if(!lastaura) + break; + } + + if (lastaura) + { + // update for out of range group members + if (slot < MAX_AURAS) + m_target->UpdateAuraForGroup(slot); + // unregister aura diminishing (and store last time) if (getDiminishGroup() != DIMINISHING_NONE ) m_target->ApplyDiminishingAura(getDiminishGroup(),false); - // update for out of range group members - m_target->UpdateAuraForGroup(slot); - // Check needed only if aura applies aurastate if(GetAuraStateMask()) { @@ -986,6 +1003,27 @@ void Aura::_RemoveAura() // note: item based cooldowns and cooldown spell mods with charges ignored (unknown existed cases) ((Player*)caster)->SendCooldownEvent(GetSpellProto()); } + + // Remove Linked Auras (on last aura remove) + uint32 id = GetId(); + if(spellmgr.GetSpellCustomAttr(id) & SPELL_ATTR_CU_LINK_REMOVE) + { + if(const std::vector *spell_triggered = spellmgr.GetSpellLinked(-(int32)id)) + for(std::vector::const_iterator itr = spell_triggered->begin(); itr != spell_triggered->end(); ++itr) + if(*itr < 0) + m_target->RemoveAurasDueToSpell(-(*itr)); + else if(Unit* caster = GetCaster()) + m_target->CastSpell(m_target, *itr, true, 0, 0, caster->GetGUID()); + } + if(spellmgr.GetSpellCustomAttr(id) & SPELL_ATTR_CU_LINK_AURA) + { + if(const std::vector *spell_triggered = spellmgr.GetSpellLinked(id + SPELL_LINK_AURA)) + for(std::vector::const_iterator itr = spell_triggered->begin(); itr != spell_triggered->end(); ++itr) + if(*itr < 0) + m_target->ApplySpellImmune(id, IMMUNITY_ID, *itr, false); + else + m_target->RemoveAurasDueToSpell(*itr); + } } } diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 52b7b4f511..26b3d7ce7a 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -2013,10 +2013,9 @@ void Unit::CalcAbsorbResist(Unit *pVictim,SpellSchoolMask schoolMask, DamageEffe healAmount = pVictim->GetMaxHealth()/2; healCaster = pVictim; healSpell = 48153; - currentAbsorb = mod->m_amount; + mod->m_amount=0; RemainingDamage=0; } - else continue; } @@ -3895,17 +3894,6 @@ bool Unit::AddAura(Aura *Aur) Aur->ApplyModifier(true,true); - uint32 id = Aur->GetId(); - if(spellmgr.GetSpellCustomAttr(id) & SPELL_ATTR_CU_LINK_AURA) - { - if(const std::vector *spell_triggered = spellmgr.GetSpellLinked(id + SPELL_LINK_AURA)) - for(std::vector::const_iterator itr = spell_triggered->begin(); itr != spell_triggered->end(); ++itr) - if(*itr < 0) - ApplySpellImmune(id, IMMUNITY_ID, *itr, true); - else if(Unit* caster = Aur->GetCaster()) - caster->AddAura(*itr, this); - } - sLog.outDebug("Aura %u now is in use", Aur->GetModifier()->m_auraname); return true; } @@ -4360,40 +4348,10 @@ void Unit::RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode) Aur->ApplyModifier(false,true); Aur->_RemoveAura(); - bool stack = false; - spellEffectPair spair = spellEffectPair(Aur->GetId(), Aur->GetEffIndex()); - for(AuraMap::const_iterator itr = GetAuras().lower_bound(spair); itr != GetAuras().upper_bound(spair); ++itr) - { - if (itr->second->GetCasterGUID()==GetGUID()) - { - stack = true; - } - } - if (!stack) + //if (mode!=AURA_REMOVE_BY_REPLACE) { // Remove all triggered by aura spells vs unlimited duration Aur->CleanupTriggeredSpells(); - - // Remove Linked Auras - uint32 id = Aur->GetId(); - if(spellmgr.GetSpellCustomAttr(id) & SPELL_ATTR_CU_LINK_REMOVE) - { - if(const std::vector *spell_triggered = spellmgr.GetSpellLinked(-(int32)id)) - for(std::vector::const_iterator itr = spell_triggered->begin(); itr != spell_triggered->end(); ++itr) - if(*itr < 0) - RemoveAurasDueToSpell(-(*itr)); - else if(Unit* caster = Aur->GetCaster()) - CastSpell(this, *itr, true, 0, 0, caster->GetGUID()); - } - if(spellmgr.GetSpellCustomAttr(id) & SPELL_ATTR_CU_LINK_AURA) - { - if(const std::vector *spell_triggered = spellmgr.GetSpellLinked(id + SPELL_LINK_AURA)) - for(std::vector::const_iterator itr = spell_triggered->begin(); itr != spell_triggered->end(); ++itr) - if(*itr < 0) - ApplySpellImmune(id, IMMUNITY_ID, *itr, false); - else - RemoveAurasDueToSpell(*itr); - } } delete Aur; @@ -13379,6 +13337,7 @@ void Unit::SendAuraUpdate(uint8 slot) if(!ptr) { + sLog.outDebug("Aura %u removed slot %u",entry->m_spellId, slot); RemoveVisibleAura(slot); SendMessageToSet(&data, true); return; diff --git a/src/game/Unit.h b/src/game/Unit.h index 19e188922e..1f199445f1 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -325,8 +325,8 @@ enum DamageTypeToSchool enum AuraRemoveMode { AURA_REMOVE_BY_DEFAULT, - AURA_REMOVE_BY_STACK, // at replace by semillar aura - AURA_REMOVE_BY_CANCEL, + AURA_REMOVE_BY_STACK, // at replace by semillar aura + AURA_REMOVE_BY_CANCEL, // single target aura remove is considered as cancel AURA_REMOVE_BY_DISPEL, AURA_REMOVE_BY_DEATH };