[8329] Implement aura deleting delay in case aura lock as currently used.

* Use counter for aura uses lock for recursivly mark as used in some cases.
* At aura remove add aura to deleting delayed auras list for aura target.
* Remove now unneeded hacks from aura handlers and aura tick code (maybe not all found yet)
* Use new aura delete locking for simplify proc spell event code.
* Prevent apply aura boost spells if aura deleted while adding to target by triggered spells.
* Re-implement aura list updating at auras update for target to better way skip
  removed from aura list auras while auras update.
This commit is contained in:
VladimirMangos 2009-08-08 11:03:45 +04:00
parent 7baebcd2de
commit c8cc9b28f8
6 changed files with 139 additions and 142 deletions

View file

@ -354,7 +354,7 @@ m_spellmod(NULL), m_caster_guid(0), m_target(target), m_castItemGuid(castItem?ca
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_isAreaAura(false), m_isPersistent(false),
m_isRemovedOnShapeLost(true), m_updated(false), m_in_use(false)
m_isRemovedOnShapeLost(true), m_in_use(0), m_deleted(false)
{
assert(target);
@ -789,12 +789,8 @@ void AreaAura::Update(uint32 diff)
}
else // aura at non-caster
{
Unit * tmp_target = m_target;
Unit* caster = GetCaster();
uint32 tmp_spellId = GetId(), tmp_effIndex = m_effIndex;
// WARNING: the aura may get deleted during the update
// DO NOT access its members after update!
Aura::Update(diff);
// remove aura if out-of-range from caster (after teleport for example)
@ -802,53 +798,53 @@ void AreaAura::Update(uint32 diff)
// or caster is (no longer) friendly
bool needFriendly = (m_areaAuraType == AREA_AURA_ENEMY ? false : true);
if( !caster || caster->hasUnitState(UNIT_STAT_ISOLATED) ||
!caster->IsWithinDistInMap(tmp_target, m_radius) ||
!caster->HasAura(tmp_spellId, tmp_effIndex) ||
caster->IsFriendlyTo(tmp_target) != needFriendly
!caster->IsWithinDistInMap(m_target, m_radius) ||
!caster->HasAura(GetId(), GetEffIndex()) ||
caster->IsFriendlyTo(m_target) != needFriendly
)
{
tmp_target->RemoveAura(tmp_spellId, tmp_effIndex);
m_target->RemoveAura(GetId(), GetEffIndex());
}
else if( m_areaAuraType == AREA_AURA_PARTY) // check if in same sub group
{
// not check group if target == owner or target == pet
if (caster->GetCharmerOrOwnerGUID() != tmp_target->GetGUID() && caster->GetGUID() != tmp_target->GetCharmerOrOwnerGUID())
if (caster->GetCharmerOrOwnerGUID() != m_target->GetGUID() && caster->GetGUID() != m_target->GetCharmerOrOwnerGUID())
{
Player* check = caster->GetCharmerOrOwnerPlayerOrPlayerItself();
Group *pGroup = check ? check->GetGroup() : NULL;
if( pGroup )
{
Player* checkTarget = tmp_target->GetCharmerOrOwnerPlayerOrPlayerItself();
Player* checkTarget = m_target->GetCharmerOrOwnerPlayerOrPlayerItself();
if(!checkTarget || !pGroup->SameSubGroup(check, checkTarget))
tmp_target->RemoveAura(tmp_spellId, tmp_effIndex);
m_target->RemoveAura(GetId(), GetEffIndex());
}
else
tmp_target->RemoveAura(tmp_spellId, tmp_effIndex);
m_target->RemoveAura(GetId(), GetEffIndex());
}
}
else if( m_areaAuraType == AREA_AURA_RAID) // TODO: fix me!
{
// not check group if target == owner or target == pet
if (caster->GetCharmerOrOwnerGUID() != tmp_target->GetGUID() && caster->GetGUID() != tmp_target->GetCharmerOrOwnerGUID())
if (caster->GetCharmerOrOwnerGUID() != m_target->GetGUID() && caster->GetGUID() != m_target->GetCharmerOrOwnerGUID())
{
Player* check = caster->GetCharmerOrOwnerPlayerOrPlayerItself();
Group *pGroup = check ? check->GetGroup() : NULL;
if( pGroup )
{
Player* checkTarget = tmp_target->GetCharmerOrOwnerPlayerOrPlayerItself();
Player* checkTarget = m_target->GetCharmerOrOwnerPlayerOrPlayerItself();
if(!checkTarget)
tmp_target->RemoveAura(tmp_spellId, tmp_effIndex);
m_target->RemoveAura(GetId(), GetEffIndex());
}
else
tmp_target->RemoveAura(tmp_spellId, tmp_effIndex);
m_target->RemoveAura(GetId(), GetEffIndex());
}
}
else if( m_areaAuraType == AREA_AURA_PET || m_areaAuraType == AREA_AURA_OWNER )
{
if( tmp_target->GetGUID() != caster->GetCharmerOrOwnerGUID() )
tmp_target->RemoveAura(tmp_spellId, tmp_effIndex);
if( m_target->GetGUID() != caster->GetCharmerOrOwnerGUID() )
m_target->RemoveAura(GetId(), GetEffIndex());
}
}
}
@ -859,8 +855,7 @@ void PersistentAreaAura::Update(uint32 diff)
// remove the aura if its caster or the dynamic object causing it was removed
// or if the target moves too far from the dynamic object
Unit *caster = GetCaster();
if (caster)
if(Unit *caster = GetCaster())
{
DynamicObject *dynObj = caster->GetDynObject(GetId(), GetEffIndex());
if (dynObj)
@ -874,25 +869,20 @@ void PersistentAreaAura::Update(uint32 diff)
else
remove = true;
Unit *tmp_target = m_target;
uint32 tmp_id = GetId(), tmp_index = GetEffIndex();
// WARNING: the aura may get deleted during the update
// DO NOT access its members after update!
Aura::Update(diff);
if(remove)
tmp_target->RemoveAura(tmp_id, tmp_index);
m_target->RemoveAura(GetId(), GetEffIndex());
}
void Aura::ApplyModifier(bool apply, bool Real)
{
AuraType aura = m_modifier.m_auraname;
m_in_use = true;
SetInUse(true);
if(aura < TOTAL_AURAS)
(*this.*AuraHandler [aura])(apply, Real);
m_in_use = false;
SetInUse(false);
}
void Aura::_AddAura()
@ -6109,18 +6099,15 @@ void Aura::PeriodicTick()
SpellPeriodicAuraLogInfo pInfo(this, pdamage, 0, absorb, resist, 0.0f, isCrit);
m_target->SendPeriodicAuraLog(&pInfo);
Unit* target = m_target; // aura can be deleted in DealDamage
SpellEntry const* spellProto = GetSpellProto();
// Set trigger flag
uint32 procAttacker = PROC_FLAG_ON_DO_PERIODIC; // | PROC_FLAG_SUCCESSFUL_HARMFUL_SPELL_HIT;
uint32 procVictim = PROC_FLAG_ON_TAKE_PERIODIC;// | PROC_FLAG_TAKEN_HARMFUL_SPELL_HIT;
pdamage = (pdamage <= absorb + resist) ? 0 : (pdamage - absorb - resist);
if (pdamage)
procVictim|=PROC_FLAG_TAKEN_ANY_DAMAGE;
pCaster->ProcDamageAndSpell(target, procAttacker, procVictim, PROC_EX_NORMAL_HIT, pdamage, BASE_ATTACK, spellProto);
pCaster->ProcDamageAndSpell(m_target, procAttacker, procVictim, PROC_EX_NORMAL_HIT, pdamage, BASE_ATTACK, GetSpellProto());
pCaster->DealDamage(target, pdamage, &cleanDamage, DOT, GetSpellSchoolMask(spellProto), spellProto, true);
pCaster->DealDamage(m_target, pdamage, &cleanDamage, DOT, GetSpellSchoolMask(GetSpellProto()), GetSpellProto(), true);
break;
}
case SPELL_AURA_PERIODIC_LEECH:
@ -6172,10 +6159,7 @@ void Aura::PeriodicTick()
pCaster->SendSpellNonMeleeDamageLog(m_target, GetId(), pdamage, GetSpellSchoolMask(GetSpellProto()), absorb, resist, false, 0);
Unit* target = m_target; // aura can be deleted in DealDamage
SpellEntry const* spellProto = GetSpellProto();
float multiplier = spellProto->EffectMultipleValue[GetEffIndex()] > 0 ? spellProto->EffectMultipleValue[GetEffIndex()] : 1;
int32 stackAmount = GetStackAmount();
float multiplier = GetSpellProto()->EffectMultipleValue[GetEffIndex()] > 0 ? GetSpellProto()->EffectMultipleValue[GetEffIndex()] : 1;
// Set trigger flag
uint32 procAttacker = PROC_FLAG_ON_DO_PERIODIC; // | PROC_FLAG_SUCCESSFUL_HARMFUL_SPELL_HIT;
@ -6183,26 +6167,26 @@ void Aura::PeriodicTick()
pdamage = (pdamage <= absorb + resist) ? 0 : (pdamage-absorb-resist);
if (pdamage)
procVictim|=PROC_FLAG_TAKEN_ANY_DAMAGE;
pCaster->ProcDamageAndSpell(target, procAttacker, procVictim, PROC_EX_NORMAL_HIT, pdamage, BASE_ATTACK, spellProto);
int32 new_damage = pCaster->DealDamage(target, pdamage, &cleanDamage, DOT, GetSpellSchoolMask(spellProto), spellProto, false);
pCaster->ProcDamageAndSpell(m_target, procAttacker, procVictim, PROC_EX_NORMAL_HIT, pdamage, BASE_ATTACK, GetSpellProto());
int32 new_damage = pCaster->DealDamage(m_target, pdamage, &cleanDamage, DOT, GetSpellSchoolMask(GetSpellProto()), GetSpellProto(), false);
if (!target->isAlive() && pCaster->IsNonMeleeSpellCasted(false))
if (!m_target->isAlive() && pCaster->IsNonMeleeSpellCasted(false))
{
for (uint32 i = CURRENT_FIRST_NON_MELEE_SPELL; i < CURRENT_MAX_SPELL; ++i)
{
if (pCaster->m_currentSpells[i] && pCaster->m_currentSpells[i]->m_spellInfo->Id == spellProto->Id)
if (pCaster->m_currentSpells[i] && pCaster->m_currentSpells[i]->m_spellInfo->Id == GetId())
pCaster->m_currentSpells[i]->cancel();
}
}
if(Player *modOwner = pCaster->GetSpellModOwner())
modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_MULTIPLE_VALUE, multiplier);
modOwner->ApplySpellMod(GetId(), SPELLMOD_MULTIPLE_VALUE, multiplier);
uint32 heal = pCaster->SpellHealingBonus(pCaster, spellProto, uint32(new_damage * multiplier), DOT, stackAmount);
uint32 heal = pCaster->SpellHealingBonus(pCaster, GetSpellProto(), uint32(new_damage * multiplier), DOT, GetStackAmount());
int32 gain = pCaster->DealHeal(pCaster, heal, spellProto);
pCaster->getHostilRefManager().threatAssist(pCaster, gain * 0.5f, spellProto);
int32 gain = pCaster->DealHeal(pCaster, heal, GetSpellProto());
pCaster->getHostilRefManager().threatAssist(pCaster, gain * 0.5f, GetSpellProto());
break;
}
case SPELL_AURA_PERIODIC_HEAL: