*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
This commit is contained in:
QAston
2009-03-13 20:24:40 +01:00
parent 7fd6d97e0f
commit 8963006729
3 changed files with 98 additions and 101 deletions
+93 -55
View File
@@ -797,7 +797,7 @@ void Aura::_AddAura()
// passive auras (except totem auras) do not get placed in the slots // passive auras (except totem auras) do not get placed in the slots
// area auras with SPELL_AURA_NONE are not shown on target // area auras with SPELL_AURA_NONE are not shown on target
// all further code applies only to active spells // 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))) (m_spellProto->Effect[GetEffIndex()] != SPELL_EFFECT_APPLY_AREA_AURA_ENEMY || m_target != caster)))
return; return;
@@ -815,8 +815,6 @@ void Aura::_AddAura()
if(itr->second->GetCasterGUID()==GetCasterGUID()) if(itr->second->GetCasterGUID()==GetCasterGUID())
{ {
slot = itr->second->GetAuraSlot(); slot = itr->second->GetAuraSlot();
if(slot >= MAX_AURAS)
return;
secondaura = true; secondaura = true;
break; break;
} }
@@ -825,46 +823,48 @@ void Aura::_AddAura()
break; break;
} }
// Lookup free slot Unit::VisibleAuraMap const *visibleAuras = m_target->GetVisibleAuras();
if (!secondaura) if(visibleAuras->size() < MAX_AURAS || slot < MAX_AURAS) // got free slot
{ {
Unit::VisibleAuraMap const *visibleAuras = m_target->GetVisibleAuras(); // Lookup free slot
if(visibleAuras->size() >= MAX_AURAS) // no free slot if (!secondaura)
return;
Unit::VisibleAuraMap::const_iterator itr = visibleAuras->begin();
for(int freeSlot = 0; freeSlot < MAX_AURAS; ++itr, ++freeSlot)
{ {
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; if(itr == visibleAuras->end() || itr->first != freeSlot)
break; {
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; if(AuraSlotEntry *entry = m_target->GetVisibleAura(slot))
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)); entry->m_Flags |= (1 << GetEffIndex());
entry->m_slotAuras[GetEffIndex()]=this;
//init pointers-prevent unexpected behaviour SetAuraSlot( slot );
for(uint8 i = 0; i < 3; i++)
t_entry.m_slotAuras[i]=NULL;
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);
}
} }
else
AuraSlotEntry *entry = m_target->GetVisibleAura(slot); sLog.outDebug("Aura: %u Effect: %d could not find empty unit visible slot",GetId(), GetEffIndex());
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);
//***************************************************** //*****************************************************
// Update target aura state flag // Update target aura state flag
@@ -880,6 +880,18 @@ void Aura::_AddAura()
// register aura diminishing on apply // register aura diminishing on apply
if (getDiminishGroup() != DIMINISHING_NONE ) if (getDiminishGroup() != DIMINISHING_NONE )
m_target->ApplyDiminishingAura(getDiminishGroup(),true); 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<int32> *spell_triggered = spellmgr.GetSpellLinked(id + SPELL_LINK_AURA))
for(std::vector<int32>::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 // Update Seals information
@@ -930,39 +942,44 @@ void Aura::_RemoveAura()
// return; // return;
uint8 slot = GetAuraSlot(); uint8 slot = GetAuraSlot();
if(slot >= MAX_AURAS) // slot not set if(slot < MAX_AURAS) // slot not set
return;
bool lastaura=true;
AuraSlotEntry *entry = m_target->GetVisibleAura(slot);
if (entry)
{ {
// we have more auras, do not clear slot if (AuraSlotEntry *entry = m_target->GetVisibleAura(slot))
if (entry->m_slotAuras[GetEffIndex()]==this)
{ {
entry->m_slotAuras[GetEffIndex()]=NULL; //unregister aura // we have more auras, do not clear slot
for(uint8 i = 0; i < 3; ++i) //check slot for more auras of the spell if (entry->m_slotAuras[GetEffIndex()]==this)
{ {
if(entry->m_slotAuras[i]) entry->m_slotAuras[GetEffIndex()]=NULL; //unregister aura
{
lastaura = false;
break;
}
} }
} }
} }
// only remove icon when the last aura of the spell is removed (current aura already removed from list) bool lastaura=true;
if(lastaura) 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) // unregister aura diminishing (and store last time)
if (getDiminishGroup() != DIMINISHING_NONE ) if (getDiminishGroup() != DIMINISHING_NONE )
m_target->ApplyDiminishingAura(getDiminishGroup(),false); m_target->ApplyDiminishingAura(getDiminishGroup(),false);
// update for out of range group members
m_target->UpdateAuraForGroup(slot);
// Check needed only if aura applies aurastate // Check needed only if aura applies aurastate
if(GetAuraStateMask()) if(GetAuraStateMask())
{ {
@@ -986,6 +1003,27 @@ void Aura::_RemoveAura()
// note: item based cooldowns and cooldown spell mods with charges ignored (unknown existed cases) // note: item based cooldowns and cooldown spell mods with charges ignored (unknown existed cases)
((Player*)caster)->SendCooldownEvent(GetSpellProto()); ((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<int32> *spell_triggered = spellmgr.GetSpellLinked(-(int32)id))
for(std::vector<int32>::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<int32> *spell_triggered = spellmgr.GetSpellLinked(id + SPELL_LINK_AURA))
for(std::vector<int32>::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);
}
} }
} }
+3 -44
View File
@@ -2013,10 +2013,9 @@ void Unit::CalcAbsorbResist(Unit *pVictim,SpellSchoolMask schoolMask, DamageEffe
healAmount = pVictim->GetMaxHealth()/2; healAmount = pVictim->GetMaxHealth()/2;
healCaster = pVictim; healCaster = pVictim;
healSpell = 48153; healSpell = 48153;
currentAbsorb = mod->m_amount; mod->m_amount=0;
RemainingDamage=0; RemainingDamage=0;
} }
else
continue; continue;
} }
@@ -3895,17 +3894,6 @@ bool Unit::AddAura(Aura *Aur)
Aur->ApplyModifier(true,true); Aur->ApplyModifier(true,true);
uint32 id = Aur->GetId();
if(spellmgr.GetSpellCustomAttr(id) & SPELL_ATTR_CU_LINK_AURA)
{
if(const std::vector<int32> *spell_triggered = spellmgr.GetSpellLinked(id + SPELL_LINK_AURA))
for(std::vector<int32>::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); sLog.outDebug("Aura %u now is in use", Aur->GetModifier()->m_auraname);
return true; return true;
} }
@@ -4360,40 +4348,10 @@ void Unit::RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode)
Aur->ApplyModifier(false,true); Aur->ApplyModifier(false,true);
Aur->_RemoveAura(); Aur->_RemoveAura();
bool stack = false; //if (mode!=AURA_REMOVE_BY_REPLACE)
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)
{ {
// Remove all triggered by aura spells vs unlimited duration // Remove all triggered by aura spells vs unlimited duration
Aur->CleanupTriggeredSpells(); Aur->CleanupTriggeredSpells();
// Remove Linked Auras
uint32 id = Aur->GetId();
if(spellmgr.GetSpellCustomAttr(id) & SPELL_ATTR_CU_LINK_REMOVE)
{
if(const std::vector<int32> *spell_triggered = spellmgr.GetSpellLinked(-(int32)id))
for(std::vector<int32>::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<int32> *spell_triggered = spellmgr.GetSpellLinked(id + SPELL_LINK_AURA))
for(std::vector<int32>::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; delete Aur;
@@ -13379,6 +13337,7 @@ void Unit::SendAuraUpdate(uint8 slot)
if(!ptr) if(!ptr)
{ {
sLog.outDebug("Aura %u removed slot %u",entry->m_spellId, slot);
RemoveVisibleAura(slot); RemoveVisibleAura(slot);
SendMessageToSet(&data, true); SendMessageToSet(&data, true);
return; return;
+2 -2
View File
@@ -325,8 +325,8 @@ enum DamageTypeToSchool
enum AuraRemoveMode enum AuraRemoveMode
{ {
AURA_REMOVE_BY_DEFAULT, AURA_REMOVE_BY_DEFAULT,
AURA_REMOVE_BY_STACK, // at replace by semillar aura AURA_REMOVE_BY_STACK, // at replace by semillar aura
AURA_REMOVE_BY_CANCEL, AURA_REMOVE_BY_CANCEL, // single target aura remove is considered as cancel
AURA_REMOVE_BY_DISPEL, AURA_REMOVE_BY_DISPEL,
AURA_REMOVE_BY_DEATH AURA_REMOVE_BY_DEATH
}; };