mirror of
https://github.com/mangosfour/server.git
synced 2025-12-13 13:37:05 +00:00
[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:
parent
7baebcd2de
commit
c8cc9b28f8
6 changed files with 139 additions and 142 deletions
|
|
@ -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_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_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_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);
|
assert(target);
|
||||||
|
|
||||||
|
|
@ -789,12 +789,8 @@ void AreaAura::Update(uint32 diff)
|
||||||
}
|
}
|
||||||
else // aura at non-caster
|
else // aura at non-caster
|
||||||
{
|
{
|
||||||
Unit * tmp_target = m_target;
|
|
||||||
Unit* caster = GetCaster();
|
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);
|
Aura::Update(diff);
|
||||||
|
|
||||||
// remove aura if out-of-range from caster (after teleport for example)
|
// 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
|
// or caster is (no longer) friendly
|
||||||
bool needFriendly = (m_areaAuraType == AREA_AURA_ENEMY ? false : true);
|
bool needFriendly = (m_areaAuraType == AREA_AURA_ENEMY ? false : true);
|
||||||
if( !caster || caster->hasUnitState(UNIT_STAT_ISOLATED) ||
|
if( !caster || caster->hasUnitState(UNIT_STAT_ISOLATED) ||
|
||||||
!caster->IsWithinDistInMap(tmp_target, m_radius) ||
|
!caster->IsWithinDistInMap(m_target, m_radius) ||
|
||||||
!caster->HasAura(tmp_spellId, tmp_effIndex) ||
|
!caster->HasAura(GetId(), GetEffIndex()) ||
|
||||||
caster->IsFriendlyTo(tmp_target) != needFriendly
|
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
|
else if( m_areaAuraType == AREA_AURA_PARTY) // check if in same sub group
|
||||||
{
|
{
|
||||||
// not check group if target == owner or target == pet
|
// 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();
|
Player* check = caster->GetCharmerOrOwnerPlayerOrPlayerItself();
|
||||||
|
|
||||||
Group *pGroup = check ? check->GetGroup() : NULL;
|
Group *pGroup = check ? check->GetGroup() : NULL;
|
||||||
if( pGroup )
|
if( pGroup )
|
||||||
{
|
{
|
||||||
Player* checkTarget = tmp_target->GetCharmerOrOwnerPlayerOrPlayerItself();
|
Player* checkTarget = m_target->GetCharmerOrOwnerPlayerOrPlayerItself();
|
||||||
if(!checkTarget || !pGroup->SameSubGroup(check, checkTarget))
|
if(!checkTarget || !pGroup->SameSubGroup(check, checkTarget))
|
||||||
tmp_target->RemoveAura(tmp_spellId, tmp_effIndex);
|
m_target->RemoveAura(GetId(), GetEffIndex());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
tmp_target->RemoveAura(tmp_spellId, tmp_effIndex);
|
m_target->RemoveAura(GetId(), GetEffIndex());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if( m_areaAuraType == AREA_AURA_RAID) // TODO: fix me!
|
else if( m_areaAuraType == AREA_AURA_RAID) // TODO: fix me!
|
||||||
{
|
{
|
||||||
// not check group if target == owner or target == pet
|
// 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();
|
Player* check = caster->GetCharmerOrOwnerPlayerOrPlayerItself();
|
||||||
|
|
||||||
Group *pGroup = check ? check->GetGroup() : NULL;
|
Group *pGroup = check ? check->GetGroup() : NULL;
|
||||||
if( pGroup )
|
if( pGroup )
|
||||||
{
|
{
|
||||||
Player* checkTarget = tmp_target->GetCharmerOrOwnerPlayerOrPlayerItself();
|
Player* checkTarget = m_target->GetCharmerOrOwnerPlayerOrPlayerItself();
|
||||||
if(!checkTarget)
|
if(!checkTarget)
|
||||||
tmp_target->RemoveAura(tmp_spellId, tmp_effIndex);
|
m_target->RemoveAura(GetId(), GetEffIndex());
|
||||||
}
|
}
|
||||||
else
|
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 )
|
else if( m_areaAuraType == AREA_AURA_PET || m_areaAuraType == AREA_AURA_OWNER )
|
||||||
{
|
{
|
||||||
if( tmp_target->GetGUID() != caster->GetCharmerOrOwnerGUID() )
|
if( m_target->GetGUID() != caster->GetCharmerOrOwnerGUID() )
|
||||||
tmp_target->RemoveAura(tmp_spellId, tmp_effIndex);
|
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
|
// 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
|
// or if the target moves too far from the dynamic object
|
||||||
Unit *caster = GetCaster();
|
if(Unit *caster = GetCaster())
|
||||||
if (caster)
|
|
||||||
{
|
{
|
||||||
DynamicObject *dynObj = caster->GetDynObject(GetId(), GetEffIndex());
|
DynamicObject *dynObj = caster->GetDynObject(GetId(), GetEffIndex());
|
||||||
if (dynObj)
|
if (dynObj)
|
||||||
|
|
@ -874,25 +869,20 @@ void PersistentAreaAura::Update(uint32 diff)
|
||||||
else
|
else
|
||||||
remove = true;
|
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);
|
Aura::Update(diff);
|
||||||
|
|
||||||
if(remove)
|
if(remove)
|
||||||
tmp_target->RemoveAura(tmp_id, tmp_index);
|
m_target->RemoveAura(GetId(), GetEffIndex());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Aura::ApplyModifier(bool apply, bool Real)
|
void Aura::ApplyModifier(bool apply, bool Real)
|
||||||
{
|
{
|
||||||
AuraType aura = m_modifier.m_auraname;
|
AuraType aura = m_modifier.m_auraname;
|
||||||
|
|
||||||
m_in_use = true;
|
SetInUse(true);
|
||||||
if(aura < TOTAL_AURAS)
|
if(aura < TOTAL_AURAS)
|
||||||
(*this.*AuraHandler [aura])(apply, Real);
|
(*this.*AuraHandler [aura])(apply, Real);
|
||||||
m_in_use = false;
|
SetInUse(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Aura::_AddAura()
|
void Aura::_AddAura()
|
||||||
|
|
@ -6109,18 +6099,15 @@ void Aura::PeriodicTick()
|
||||||
SpellPeriodicAuraLogInfo pInfo(this, pdamage, 0, absorb, resist, 0.0f, isCrit);
|
SpellPeriodicAuraLogInfo pInfo(this, pdamage, 0, absorb, resist, 0.0f, isCrit);
|
||||||
m_target->SendPeriodicAuraLog(&pInfo);
|
m_target->SendPeriodicAuraLog(&pInfo);
|
||||||
|
|
||||||
Unit* target = m_target; // aura can be deleted in DealDamage
|
|
||||||
SpellEntry const* spellProto = GetSpellProto();
|
|
||||||
|
|
||||||
// Set trigger flag
|
// Set trigger flag
|
||||||
uint32 procAttacker = PROC_FLAG_ON_DO_PERIODIC; // | PROC_FLAG_SUCCESSFUL_HARMFUL_SPELL_HIT;
|
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;
|
uint32 procVictim = PROC_FLAG_ON_TAKE_PERIODIC;// | PROC_FLAG_TAKEN_HARMFUL_SPELL_HIT;
|
||||||
pdamage = (pdamage <= absorb + resist) ? 0 : (pdamage - absorb - resist);
|
pdamage = (pdamage <= absorb + resist) ? 0 : (pdamage - absorb - resist);
|
||||||
if (pdamage)
|
if (pdamage)
|
||||||
procVictim|=PROC_FLAG_TAKEN_ANY_DAMAGE;
|
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;
|
break;
|
||||||
}
|
}
|
||||||
case SPELL_AURA_PERIODIC_LEECH:
|
case SPELL_AURA_PERIODIC_LEECH:
|
||||||
|
|
@ -6172,10 +6159,7 @@ void Aura::PeriodicTick()
|
||||||
|
|
||||||
pCaster->SendSpellNonMeleeDamageLog(m_target, GetId(), pdamage, GetSpellSchoolMask(GetSpellProto()), absorb, resist, false, 0);
|
pCaster->SendSpellNonMeleeDamageLog(m_target, GetId(), pdamage, GetSpellSchoolMask(GetSpellProto()), absorb, resist, false, 0);
|
||||||
|
|
||||||
Unit* target = m_target; // aura can be deleted in DealDamage
|
float multiplier = GetSpellProto()->EffectMultipleValue[GetEffIndex()] > 0 ? GetSpellProto()->EffectMultipleValue[GetEffIndex()] : 1;
|
||||||
SpellEntry const* spellProto = GetSpellProto();
|
|
||||||
float multiplier = spellProto->EffectMultipleValue[GetEffIndex()] > 0 ? spellProto->EffectMultipleValue[GetEffIndex()] : 1;
|
|
||||||
int32 stackAmount = GetStackAmount();
|
|
||||||
|
|
||||||
// Set trigger flag
|
// Set trigger flag
|
||||||
uint32 procAttacker = PROC_FLAG_ON_DO_PERIODIC; // | PROC_FLAG_SUCCESSFUL_HARMFUL_SPELL_HIT;
|
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);
|
pdamage = (pdamage <= absorb + resist) ? 0 : (pdamage-absorb-resist);
|
||||||
if (pdamage)
|
if (pdamage)
|
||||||
procVictim|=PROC_FLAG_TAKEN_ANY_DAMAGE;
|
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());
|
||||||
int32 new_damage = pCaster->DealDamage(target, pdamage, &cleanDamage, DOT, GetSpellSchoolMask(spellProto), spellProto, false);
|
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)
|
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();
|
pCaster->m_currentSpells[i]->cancel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if(Player *modOwner = pCaster->GetSpellModOwner())
|
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);
|
int32 gain = pCaster->DealHeal(pCaster, heal, GetSpellProto());
|
||||||
pCaster->getHostilRefManager().threatAssist(pCaster, gain * 0.5f, spellProto);
|
pCaster->getHostilRefManager().threatAssist(pCaster, gain * 0.5f, GetSpellProto());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SPELL_AURA_PERIODIC_HEAL:
|
case SPELL_AURA_PERIODIC_HEAL:
|
||||||
|
|
|
||||||
|
|
@ -292,16 +292,24 @@ class MANGOS_DLL_SPEC Aura
|
||||||
bool IsDeathPersistent() const { return m_isDeathPersist; }
|
bool IsDeathPersistent() const { return m_isDeathPersist; }
|
||||||
bool IsRemovedOnShapeLost() const { return m_isRemovedOnShapeLost; }
|
bool IsRemovedOnShapeLost() const { return m_isRemovedOnShapeLost; }
|
||||||
bool IsInUse() const { return m_in_use;}
|
bool IsInUse() const { return m_in_use;}
|
||||||
|
bool IsDeleted() const { return m_deleted;}
|
||||||
|
|
||||||
virtual void Update(uint32 diff);
|
void SetInUse(bool state)
|
||||||
|
{
|
||||||
|
if(state)
|
||||||
|
++m_in_use;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(m_in_use)
|
||||||
|
--m_in_use;
|
||||||
|
}
|
||||||
|
}
|
||||||
void ApplyModifier(bool apply, bool Real = false);
|
void ApplyModifier(bool apply, bool Real = false);
|
||||||
|
|
||||||
|
void UpdateAura(uint32 diff) { SetInUse(true); Update(diff); SetInUse(false); }
|
||||||
void _AddAura();
|
void _AddAura();
|
||||||
bool _RemoveAura();
|
bool _RemoveAura();
|
||||||
|
|
||||||
bool IsUpdated() { return m_updated; }
|
|
||||||
void SetUpdated(bool val) { m_updated = val; }
|
|
||||||
|
|
||||||
bool IsSingleTarget() {return m_isSingleTargetAura;}
|
bool IsSingleTarget() {return m_isSingleTargetAura;}
|
||||||
void SetIsSingleTarget(bool val) { m_isSingleTargetAura = val;}
|
void SetIsSingleTarget(bool val) { m_isSingleTargetAura = val;}
|
||||||
|
|
||||||
|
|
@ -319,14 +327,19 @@ class MANGOS_DLL_SPEC Aura
|
||||||
|
|
||||||
void TriggerSpell();
|
void TriggerSpell();
|
||||||
void TriggerSpellWithValue();
|
void TriggerSpellWithValue();
|
||||||
void PeriodicTick();
|
|
||||||
void PeriodicDummyTick();
|
|
||||||
|
|
||||||
uint32 const *getAuraSpellClassMask() const { return m_spellProto->EffectSpellClassMaskA + m_effIndex * 3; }
|
uint32 const *getAuraSpellClassMask() const { return m_spellProto->EffectSpellClassMaskA + m_effIndex * 3; }
|
||||||
bool isAffectedOnSpell(SpellEntry const *spell) const;
|
bool isAffectedOnSpell(SpellEntry const *spell) const;
|
||||||
protected:
|
protected:
|
||||||
Aura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target, Unit *caster = NULL, Item* castItem = NULL);
|
Aura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target, Unit *caster = NULL, Item* castItem = NULL);
|
||||||
|
|
||||||
|
// must be called only from Aura::UpdateAura
|
||||||
|
virtual void Update(uint32 diff);
|
||||||
|
|
||||||
|
// must be called only from Aura*::Update
|
||||||
|
void PeriodicTick();
|
||||||
|
void PeriodicDummyTick();
|
||||||
|
|
||||||
bool IsCritFromAbilityAura(Unit* caster, uint32& damage);
|
bool IsCritFromAbilityAura(Unit* caster, uint32& damage);
|
||||||
|
|
||||||
Modifier m_modifier;
|
Modifier m_modifier;
|
||||||
|
|
@ -362,10 +375,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; // Prevent remove aura by stack if set
|
bool m_deleted:1; // true if RemoveAura(iterator) called while in Aura::ApplyModifier call (added to Unit::m_deletedAuras)
|
||||||
bool m_in_use:1; // true while in Aura::ApplyModifier call
|
|
||||||
bool m_isSingleTargetAura:1; // true if it's a single target spell and registered at caster - can change at spell steal for example
|
bool m_isSingleTargetAura:1; // true if it's a single target spell and registered at caster - can change at spell steal for example
|
||||||
|
|
||||||
|
uint32 m_in_use; // > 0 while in Aura::ApplyModifier call/Aura::Update/etc
|
||||||
private:
|
private:
|
||||||
void CleanupTriggeredSpells();
|
void CleanupTriggeredSpells();
|
||||||
};
|
};
|
||||||
|
|
@ -375,6 +388,7 @@ class MANGOS_DLL_SPEC AreaAura : public Aura
|
||||||
public:
|
public:
|
||||||
AreaAura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target, Unit *caster = NULL, Item* castItem = NULL);
|
AreaAura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target, Unit *caster = NULL, Item* castItem = NULL);
|
||||||
~AreaAura();
|
~AreaAura();
|
||||||
|
protected:
|
||||||
void Update(uint32 diff);
|
void Update(uint32 diff);
|
||||||
private:
|
private:
|
||||||
float m_radius;
|
float m_radius;
|
||||||
|
|
@ -386,6 +400,7 @@ class MANGOS_DLL_SPEC PersistentAreaAura : public Aura
|
||||||
public:
|
public:
|
||||||
PersistentAreaAura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target, Unit *caster = NULL, Item* castItem = NULL);
|
PersistentAreaAura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target, Unit *caster = NULL, Item* castItem = NULL);
|
||||||
~PersistentAreaAura();
|
~PersistentAreaAura();
|
||||||
|
protected:
|
||||||
void Update(uint32 diff);
|
void Update(uint32 diff);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2413,11 +2413,6 @@ void Spell::EffectApplyAura(uint32 i)
|
||||||
if (!added)
|
if (!added)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// found crash at character loading, broken pointer to Aur...
|
|
||||||
// Aur was deleted in AddAura()...
|
|
||||||
if(!Aur)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Prayer of Mending (jump animation), we need formal caster instead original for correct animation
|
// Prayer of Mending (jump animation), we need formal caster instead original for correct animation
|
||||||
if( m_spellInfo->SpellFamilyName == SPELLFAMILY_PRIEST && (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000002000000000)))
|
if( m_spellInfo->SpellFamilyName == SPELLFAMILY_PRIEST && (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000002000000000)))
|
||||||
m_caster->CastSpell(unitTarget, 41637, true, NULL, Aur, m_originalCasterGUID);
|
m_caster->CastSpell(unitTarget, 41637, true, NULL, Aur, m_originalCasterGUID);
|
||||||
|
|
|
||||||
|
|
@ -102,7 +102,7 @@ Unit::Unit()
|
||||||
//m_Aura = NULL;
|
//m_Aura = NULL;
|
||||||
//m_AurasCheck = 2000;
|
//m_AurasCheck = 2000;
|
||||||
//m_removeAuraTimer = 4;
|
//m_removeAuraTimer = 4;
|
||||||
//tmpAura = NULL;
|
m_AurasUpdateIterator = m_Auras.end();
|
||||||
|
|
||||||
m_Visibility = VISIBILITY_ON;
|
m_Visibility = VISIBILITY_ON;
|
||||||
|
|
||||||
|
|
@ -148,7 +148,6 @@ Unit::Unit()
|
||||||
for (int i = 0; i < MAX_MOVE_TYPE; ++i)
|
for (int i = 0; i < MAX_MOVE_TYPE; ++i)
|
||||||
m_speed_rate[i] = 1.0f;
|
m_speed_rate[i] = 1.0f;
|
||||||
|
|
||||||
m_removedAuras = 0;
|
|
||||||
m_charmInfo = NULL;
|
m_charmInfo = NULL;
|
||||||
|
|
||||||
// remove aurastates allowing special moves
|
// remove aurastates allowing special moves
|
||||||
|
|
@ -192,6 +191,11 @@ void Unit::Update( uint32 p_time )
|
||||||
m_Events.Update( p_time );
|
m_Events.Update( p_time );
|
||||||
_UpdateSpells( p_time );
|
_UpdateSpells( p_time );
|
||||||
|
|
||||||
|
// really delete auras "deleted" while processing its ApplyModify code
|
||||||
|
for(AuraList::const_iterator itr = m_deletedAuras.begin(); itr != m_deletedAuras.begin(); ++itr)
|
||||||
|
delete *itr;
|
||||||
|
m_deletedAuras.clear();
|
||||||
|
|
||||||
// update combat timer only for players and pets
|
// update combat timer only for players and pets
|
||||||
if (isInCombat() && (GetTypeId() == TYPEID_PLAYER || ((Creature*)this)->isPet() || ((Creature*)this)->isCharmed()))
|
if (isInCombat() && (GetTypeId() == TYPEID_PLAYER || ((Creature*)this)->isPet() || ((Creature*)this)->isCharmed()))
|
||||||
{
|
{
|
||||||
|
|
@ -1509,11 +1513,9 @@ void Unit::DealMeleeDamage(CalcDamageInfo *damageInfo, bool durabilityLoss)
|
||||||
|
|
||||||
// victim's damage shield
|
// victim's damage shield
|
||||||
std::set<Aura*> alreadyDone;
|
std::set<Aura*> alreadyDone;
|
||||||
uint32 removedAuras = pVictim->m_removedAuras;
|
|
||||||
AuraList const& vDamageShields = pVictim->GetAurasByType(SPELL_AURA_DAMAGE_SHIELD);
|
AuraList const& vDamageShields = pVictim->GetAurasByType(SPELL_AURA_DAMAGE_SHIELD);
|
||||||
for(AuraList::const_iterator i = vDamageShields.begin(), next = vDamageShields.begin(); i != vDamageShields.end(); i = next)
|
for(AuraList::const_iterator i = vDamageShields.begin(); i != vDamageShields.end();)
|
||||||
{
|
{
|
||||||
next++;
|
|
||||||
if (alreadyDone.find(*i) == alreadyDone.end())
|
if (alreadyDone.find(*i) == alreadyDone.end())
|
||||||
{
|
{
|
||||||
alreadyDone.insert(*i);
|
alreadyDone.insert(*i);
|
||||||
|
|
@ -1540,12 +1542,10 @@ void Unit::DealMeleeDamage(CalcDamageInfo *damageInfo, bool durabilityLoss)
|
||||||
|
|
||||||
pVictim->DealDamage(this, damage, 0, SPELL_DIRECT_DAMAGE, GetSpellSchoolMask(spellProto), spellProto, true);
|
pVictim->DealDamage(this, damage, 0, SPELL_DIRECT_DAMAGE, GetSpellSchoolMask(spellProto), spellProto, true);
|
||||||
|
|
||||||
if (pVictim->m_removedAuras > removedAuras)
|
i = vDamageShields.begin();
|
||||||
{
|
|
||||||
removedAuras = pVictim->m_removedAuras;
|
|
||||||
next = vDamageShields.begin();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
++i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2962,50 +2962,27 @@ void Unit::_UpdateSpells( uint32 time )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Find a better way to prevent crash when multiple auras are removed.
|
// update auras
|
||||||
m_removedAuras = 0;
|
// m_AurasUpdateIterator can be updated in inderect called code at aura remove to skip next planned to update but removed auras
|
||||||
for (AuraMap::iterator i = m_Auras.begin(); i != m_Auras.end(); ++i)
|
for (m_AurasUpdateIterator = m_Auras.begin(); m_AurasUpdateIterator != m_Auras.end();)
|
||||||
if ((*i).second)
|
|
||||||
(*i).second->SetUpdated(false);
|
|
||||||
|
|
||||||
for (AuraMap::iterator i = m_Auras.begin(), next; i != m_Auras.end(); i = next)
|
|
||||||
{
|
{
|
||||||
next = i;
|
Aura* i_aura = m_AurasUpdateIterator->second;
|
||||||
++next;
|
++m_AurasUpdateIterator; // need shift to next for allow update if need into aura update
|
||||||
if ((*i).second)
|
i_aura->UpdateAura(time);
|
||||||
{
|
|
||||||
// prevent double update
|
|
||||||
if ((*i).second->IsUpdated())
|
|
||||||
continue;
|
|
||||||
(*i).second->SetUpdated(true);
|
|
||||||
(*i).second->Update( time );
|
|
||||||
// several auras can be deleted due to update
|
|
||||||
if (m_removedAuras)
|
|
||||||
{
|
|
||||||
if (m_Auras.empty()) break;
|
|
||||||
next = m_Auras.begin();
|
|
||||||
m_removedAuras = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// remove expired auras
|
||||||
for (AuraMap::iterator i = m_Auras.begin(); i != m_Auras.end();)
|
for (AuraMap::iterator i = m_Auras.begin(); i != m_Auras.end();)
|
||||||
{
|
{
|
||||||
if ((*i).second)
|
if ((*i).second)
|
||||||
{
|
{
|
||||||
if ( !(*i).second->GetAuraDuration() && !((*i).second->IsPermanent() || ((*i).second->IsPassive())) )
|
if ( !(*i).second->GetAuraDuration() && !((*i).second->IsPermanent() || ((*i).second->IsPassive())) )
|
||||||
{
|
|
||||||
RemoveAura(i);
|
RemoveAura(i);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
++i;
|
++i;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
|
||||||
++i;
|
++i;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!m_gameObj.empty())
|
if(!m_gameObj.empty())
|
||||||
|
|
@ -3538,6 +3515,11 @@ bool Unit::AddAura(Aura *Aur)
|
||||||
Aur->ApplyModifier(true,true);
|
Aur->ApplyModifier(true,true);
|
||||||
sLog.outDebug("Aura %u now is in use", aurName);
|
sLog.outDebug("Aura %u now is in use", aurName);
|
||||||
|
|
||||||
|
// if aura deleted before boosts apply ignore
|
||||||
|
// this can be possible it it removed indirectly by triggered spell effect at ApplyModifier
|
||||||
|
if (Aur->IsDeleted())
|
||||||
|
return false;
|
||||||
|
|
||||||
if(IsSpellLastAuraEffect(aurSpellInfo,Aur->GetEffIndex()))
|
if(IsSpellLastAuraEffect(aurSpellInfo,Aur->GetEffIndex()))
|
||||||
Aur->HandleSpellSpecificBoosts(true);
|
Aur->HandleSpellSpecificBoosts(true);
|
||||||
|
|
||||||
|
|
@ -3955,10 +3937,16 @@ void Unit::RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode)
|
||||||
|
|
||||||
// Set remove mode
|
// Set remove mode
|
||||||
Aur->SetRemoveMode(mode);
|
Aur->SetRemoveMode(mode);
|
||||||
|
|
||||||
|
// if unit currently update aura list then make safe update iterator shift to next
|
||||||
|
if (m_AurasUpdateIterator == i)
|
||||||
|
++m_AurasUpdateIterator;
|
||||||
|
|
||||||
// some ShapeshiftBoosts at remove trigger removing other auras including parent Shapeshift aura
|
// some ShapeshiftBoosts at remove trigger removing other auras including parent Shapeshift aura
|
||||||
// remove aura from list before to prevent deleting it before
|
// remove aura from list before to prevent deleting it before
|
||||||
m_Auras.erase(i);
|
m_Auras.erase(i);
|
||||||
++m_removedAuras; // internal count used by unit update
|
|
||||||
|
// now aura removed from from list and can't be deleted by indirect call but can be referenced from callers
|
||||||
|
|
||||||
// Statue unsummoned at aura remove
|
// Statue unsummoned at aura remove
|
||||||
Totem* statue = NULL;
|
Totem* statue = NULL;
|
||||||
|
|
@ -3986,7 +3974,12 @@ void Unit::RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode)
|
||||||
Aur->HandleSpellSpecificBoosts(false);
|
Aur->HandleSpellSpecificBoosts(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
delete Aur;
|
// If aura in use (removed from code that plan access to it data after return)
|
||||||
|
// store it in aura list with delayed deletion
|
||||||
|
if (Aur->IsInUse())
|
||||||
|
m_deletedAuras.push_back(Aur);
|
||||||
|
else
|
||||||
|
delete Aur;
|
||||||
|
|
||||||
if(caster_channeled)
|
if(caster_channeled)
|
||||||
RemoveAurasAtChanneledTarget (AurSpellInfo);
|
RemoveAurasAtChanneledTarget (AurSpellInfo);
|
||||||
|
|
@ -10940,6 +10933,7 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag
|
||||||
if(!IsTriggeredAtSpellProcEvent(pTarget, itr->second, procSpell, procFlag, procExtra, attType, isVictim, (damage > 0), spellProcEvent))
|
if(!IsTriggeredAtSpellProcEvent(pTarget, itr->second, procSpell, procFlag, procExtra, attType, isVictim, (damage > 0), spellProcEvent))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
itr->second->SetInUse(true); // prevent aura deletion
|
||||||
procTriggered.push_back( ProcTriggeredData(spellProcEvent, itr->second) );
|
procTriggered.push_back( ProcTriggeredData(spellProcEvent, itr->second) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -10951,33 +10945,11 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag
|
||||||
for(ProcTriggeredList::const_iterator i = procTriggered.begin(); i != procTriggered.end(); ++i)
|
for(ProcTriggeredList::const_iterator i = procTriggered.begin(); i != procTriggered.end(); ++i)
|
||||||
{
|
{
|
||||||
// Some auras can be deleted in function called in this loop (except first, ofc)
|
// Some auras can be deleted in function called in this loop (except first, ofc)
|
||||||
// Until storing auars in std::multimap to hard check deleting by another way
|
Aura *triggeredByAura = i->triggeredByAura;
|
||||||
if(i != procTriggered.begin())
|
if(triggeredByAura->IsDeleted())
|
||||||
{
|
continue;
|
||||||
bool found = false;
|
|
||||||
AuraMap::const_iterator lower = GetAuras().lower_bound(i->triggeredByAura_SpellPair);
|
|
||||||
AuraMap::const_iterator upper = GetAuras().upper_bound(i->triggeredByAura_SpellPair);
|
|
||||||
for(AuraMap::const_iterator itr = lower; itr!= upper; ++itr)
|
|
||||||
{
|
|
||||||
if(itr->second==i->triggeredByAura)
|
|
||||||
{
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(!found)
|
|
||||||
{
|
|
||||||
// sLog.outDebug("Spell aura %u (id:%u effect:%u) has been deleted before call spell proc event handler", i->triggeredByAura->GetModifier()->m_auraname, i->triggeredByAura_SpellPair.first, i->triggeredByAura_SpellPair.second);
|
|
||||||
// sLog.outDebug("It can be deleted one from early proccesed auras:");
|
|
||||||
// for(ProcTriggeredList::const_iterator i2 = procTriggered.begin(); i != i2; ++i2)
|
|
||||||
// sLog.outDebug(" Spell aura %u (id:%u effect:%u)", i->triggeredByAura->GetModifier()->m_auraname,i2->triggeredByAura_SpellPair.first,i2->triggeredByAura_SpellPair.second);
|
|
||||||
// sLog.outDebug(" <end of list>");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SpellProcEventEntry const *spellProcEvent = i->spellProcEvent;
|
SpellProcEventEntry const *spellProcEvent = i->spellProcEvent;
|
||||||
Aura *triggeredByAura = i->triggeredByAura;
|
|
||||||
Modifier *auraModifier = triggeredByAura->GetModifier();
|
Modifier *auraModifier = triggeredByAura->GetModifier();
|
||||||
SpellEntry const *spellInfo = triggeredByAura->GetSpellProto();
|
SpellEntry const *spellInfo = triggeredByAura->GetSpellProto();
|
||||||
bool useCharges = triggeredByAura->GetAuraCharges() > 0;
|
bool useCharges = triggeredByAura->GetAuraCharges() > 0;
|
||||||
|
|
@ -10993,7 +10965,10 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag
|
||||||
sLog.outDebug("ProcDamageAndSpell: casting spell %u (triggered by %s aura of spell %u)", spellInfo->Id,(isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId());
|
sLog.outDebug("ProcDamageAndSpell: casting spell %u (triggered by %s aura of spell %u)", spellInfo->Id,(isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId());
|
||||||
// Don`t drop charge or add cooldown for not started trigger
|
// Don`t drop charge or add cooldown for not started trigger
|
||||||
if (!HandleProcTriggerSpell(pTarget, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown))
|
if (!HandleProcTriggerSpell(pTarget, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown))
|
||||||
|
{
|
||||||
|
triggeredByAura->SetInUse(false);
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SPELL_AURA_PROC_TRIGGER_DAMAGE:
|
case SPELL_AURA_PROC_TRIGGER_DAMAGE:
|
||||||
|
|
@ -11013,21 +10988,30 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag
|
||||||
{
|
{
|
||||||
sLog.outDebug("ProcDamageAndSpell: casting spell id %u (triggered by %s dummy aura of spell %u)", spellInfo->Id,(isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId());
|
sLog.outDebug("ProcDamageAndSpell: casting spell id %u (triggered by %s dummy aura of spell %u)", spellInfo->Id,(isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId());
|
||||||
if (!HandleDummyAuraProc(pTarget, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown))
|
if (!HandleDummyAuraProc(pTarget, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown))
|
||||||
|
{
|
||||||
|
triggeredByAura->SetInUse(false);
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SPELL_AURA_MOD_HASTE:
|
case SPELL_AURA_MOD_HASTE:
|
||||||
{
|
{
|
||||||
sLog.outDebug("ProcDamageAndSpell: casting spell id %u (triggered by %s haste aura of spell %u)", spellInfo->Id,(isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId());
|
sLog.outDebug("ProcDamageAndSpell: casting spell id %u (triggered by %s haste aura of spell %u)", spellInfo->Id,(isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId());
|
||||||
if (!HandleHasteAuraProc(pTarget, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown))
|
if (!HandleHasteAuraProc(pTarget, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown))
|
||||||
|
{
|
||||||
|
triggeredByAura->SetInUse(false);
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SPELL_AURA_OVERRIDE_CLASS_SCRIPTS:
|
case SPELL_AURA_OVERRIDE_CLASS_SCRIPTS:
|
||||||
{
|
{
|
||||||
sLog.outDebug("ProcDamageAndSpell: casting spell id %u (triggered by %s aura of spell %u)", spellInfo->Id,(isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId());
|
sLog.outDebug("ProcDamageAndSpell: casting spell id %u (triggered by %s aura of spell %u)", spellInfo->Id,(isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId());
|
||||||
if (!HandleOverrideClassScriptAuraProc(pTarget, damage, triggeredByAura, procSpell, cooldown))
|
if (!HandleOverrideClassScriptAuraProc(pTarget, damage, triggeredByAura, procSpell, cooldown))
|
||||||
|
{
|
||||||
|
triggeredByAura->SetInUse(false);
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SPELL_AURA_PRAYER_OF_MENDING:
|
case SPELL_AURA_PRAYER_OF_MENDING:
|
||||||
|
|
@ -11043,18 +11027,27 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag
|
||||||
sLog.outDebug("ProcDamageAndSpell: casting spell %u (triggered with value by %s aura of spell %u)", spellInfo->Id,(isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId());
|
sLog.outDebug("ProcDamageAndSpell: casting spell %u (triggered with value by %s aura of spell %u)", spellInfo->Id,(isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId());
|
||||||
|
|
||||||
if (!HandleProcTriggerSpell(pTarget, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown))
|
if (!HandleProcTriggerSpell(pTarget, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown))
|
||||||
|
{
|
||||||
|
triggeredByAura->SetInUse(false);
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SPELL_AURA_MOD_CASTING_SPEED_NOT_STACK:
|
case SPELL_AURA_MOD_CASTING_SPEED_NOT_STACK:
|
||||||
// Skip melee hits or instant cast spells
|
// Skip melee hits or instant cast spells
|
||||||
if (procSpell == NULL || GetSpellCastTime(procSpell) == 0)
|
if (procSpell == NULL || GetSpellCastTime(procSpell) == 0)
|
||||||
|
{
|
||||||
|
triggeredByAura->SetInUse(false);
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case SPELL_AURA_REFLECT_SPELLS_SCHOOL:
|
case SPELL_AURA_REFLECT_SPELLS_SCHOOL:
|
||||||
// Skip Melee hits and spells ws wrong school
|
// Skip Melee hits and spells ws wrong school
|
||||||
if (procSpell == NULL || (auraModifier->m_miscvalue & procSpell->SchoolMask) == 0)
|
if (procSpell == NULL || (auraModifier->m_miscvalue & procSpell->SchoolMask) == 0)
|
||||||
|
{
|
||||||
|
triggeredByAura->SetInUse(false);
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case SPELL_AURA_MOD_POWER_COST_SCHOOL_PCT:
|
case SPELL_AURA_MOD_POWER_COST_SCHOOL_PCT:
|
||||||
case SPELL_AURA_MOD_POWER_COST_SCHOOL:
|
case SPELL_AURA_MOD_POWER_COST_SCHOOL:
|
||||||
|
|
@ -11062,47 +11055,56 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag
|
||||||
if (procSpell == NULL ||
|
if (procSpell == NULL ||
|
||||||
(procSpell->manaCost == 0 && procSpell->ManaCostPercentage == 0) || // Cost check
|
(procSpell->manaCost == 0 && procSpell->ManaCostPercentage == 0) || // Cost check
|
||||||
(auraModifier->m_miscvalue & procSpell->SchoolMask) == 0) // School check
|
(auraModifier->m_miscvalue & procSpell->SchoolMask) == 0) // School check
|
||||||
|
{
|
||||||
|
triggeredByAura->SetInUse(false);
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case SPELL_AURA_MECHANIC_IMMUNITY:
|
case SPELL_AURA_MECHANIC_IMMUNITY:
|
||||||
// Compare mechanic
|
// Compare mechanic
|
||||||
if (procSpell==NULL || procSpell->Mechanic != auraModifier->m_miscvalue)
|
if (procSpell==NULL || procSpell->Mechanic != auraModifier->m_miscvalue)
|
||||||
|
{
|
||||||
|
triggeredByAura->SetInUse(false);
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case SPELL_AURA_MOD_MECHANIC_RESISTANCE:
|
case SPELL_AURA_MOD_MECHANIC_RESISTANCE:
|
||||||
// Compare mechanic
|
// Compare mechanic
|
||||||
if (procSpell==NULL || procSpell->Mechanic != auraModifier->m_miscvalue)
|
if (procSpell==NULL || procSpell->Mechanic != auraModifier->m_miscvalue)
|
||||||
|
{
|
||||||
|
triggeredByAura->SetInUse(false);
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case SPELL_AURA_MOD_DAMAGE_FROM_CASTER:
|
case SPELL_AURA_MOD_DAMAGE_FROM_CASTER:
|
||||||
// Compare casters
|
// Compare casters
|
||||||
if (triggeredByAura->GetCasterGUID() != pTarget->GetGUID())
|
if (triggeredByAura->GetCasterGUID() != pTarget->GetGUID())
|
||||||
|
{
|
||||||
|
triggeredByAura->SetInUse(false);
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case SPELL_AURA_MOD_SPELL_CRIT_CHANCE:
|
case SPELL_AURA_MOD_SPELL_CRIT_CHANCE:
|
||||||
if (!procSpell)
|
if (!procSpell)
|
||||||
|
{
|
||||||
|
triggeredByAura->SetInUse(false);
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
// nothing do, just charges counter
|
// nothing do, just charges counter
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove charge (aura can be removed by triggers)
|
// Remove charge (aura can be removed by triggers)
|
||||||
if(useCharges)
|
if(useCharges && !triggeredByAura->IsDeleted())
|
||||||
{
|
{
|
||||||
// need found aura on drop (can be dropped by triggers)
|
// If last charge dropped add spell to remove list
|
||||||
AuraMap::const_iterator lower = GetAuras().lower_bound(i->triggeredByAura_SpellPair);
|
if(triggeredByAura->DropAuraCharge())
|
||||||
AuraMap::const_iterator upper = GetAuras().upper_bound(i->triggeredByAura_SpellPair);
|
removedSpells.push_back(triggeredByAura->GetId());
|
||||||
for(AuraMap::const_iterator itr = lower; itr!= upper; ++itr)
|
|
||||||
{
|
|
||||||
// If last charge dropped add spell to remove list
|
|
||||||
if(itr->second == i->triggeredByAura && triggeredByAura->DropAuraCharge())
|
|
||||||
{
|
|
||||||
removedSpells.push_back(triggeredByAura->GetId());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
triggeredByAura->SetInUse(false);
|
||||||
}
|
}
|
||||||
if (!removedSpells.empty())
|
if (!removedSpells.empty())
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1514,8 +1514,10 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
|
||||||
DeathState m_deathState;
|
DeathState m_deathState;
|
||||||
|
|
||||||
AuraMap m_Auras;
|
AuraMap m_Auras;
|
||||||
|
AuraMap::iterator m_AurasUpdateIterator; // != end() in Unit::m_Auras update and point to next element
|
||||||
|
AuraList m_deletedAuras; // auras removed while in ApplyModifier and waiting deleted
|
||||||
|
|
||||||
std::list<Aura *> m_scAuras; // casted singlecast auras
|
AuraList m_scAuras; // casted by unit single per-caster auras
|
||||||
|
|
||||||
typedef std::list<uint64> DynObjectGUIDs;
|
typedef std::list<uint64> DynObjectGUIDs;
|
||||||
DynObjectGUIDs m_dynObjGUIDs;
|
DynObjectGUIDs m_dynObjGUIDs;
|
||||||
|
|
@ -1524,7 +1526,6 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
|
||||||
GameObjectList m_gameObj;
|
GameObjectList m_gameObj;
|
||||||
bool m_isSorted;
|
bool m_isSorted;
|
||||||
uint32 m_transform;
|
uint32 m_transform;
|
||||||
uint32 m_removedAuras;
|
|
||||||
|
|
||||||
AuraList m_modAuras[TOTAL_AURAS];
|
AuraList m_modAuras[TOTAL_AURAS];
|
||||||
float m_auraModifiersGroup[UNIT_MOD_END][MODIFIER_TYPE_END];
|
float m_auraModifiersGroup[UNIT_MOD_END][MODIFIER_TYPE_END];
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
#ifndef __REVISION_NR_H__
|
#ifndef __REVISION_NR_H__
|
||||||
#define __REVISION_NR_H__
|
#define __REVISION_NR_H__
|
||||||
#define REVISION_NR "8328"
|
#define REVISION_NR "8329"
|
||||||
#endif // __REVISION_NR_H__
|
#endif // __REVISION_NR_H__
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue