Core/Auras: Use std::vector for temporary copies of aura lists

This commit is contained in:
Shauren
2023-06-28 11:45:29 +02:00
parent ef5c7513f4
commit 8c4a966dc0
2 changed files with 58 additions and 47 deletions
+56 -47
View File
@@ -762,6 +762,14 @@ bool Unit::HasBreakableByDamageCrowdControlAura(Unit* excludeCasterChannel) cons
damage *= attacker->GetDamageMultiplierForTarget(victim);
}
/*static*/ AuraEffectVector Unit::CopyAuraEffectList(Unit::AuraEffectList const& list)
{
AuraEffectVector effects;
effects.resize(list.size());
std::copy(list.begin(), list.end(), effects.begin());
return effects;
}
/*static*/ uint32 Unit::DealDamage(Unit* attacker, Unit* victim, uint32 damage, CleanDamage const* cleanDamage, DamageEffectType damagetype, SpellSchoolMask damageSchoolMask, SpellInfo const* spellProto, bool durabilityLoss)
{
uint32 damageDone = damage;
@@ -830,9 +838,9 @@ bool Unit::HasBreakableByDamageCrowdControlAura(Unit* excludeCasterChannel) cons
// We're going to call functions which can modify content of the list during iteration over it's elements
// Let's copy the list so we can prevent iterator invalidation
AuraEffectList vCopyDamageCopy(victim->GetAuraEffectsByType(SPELL_AURA_SHARE_DAMAGE_PCT));
AuraEffectVector vCopyDamageCopy = CopyAuraEffectList(victim->GetAuraEffectsByType(SPELL_AURA_SHARE_DAMAGE_PCT));
// copy damage to casters of this aura
for (AuraEffectList::iterator i = vCopyDamageCopy.begin(); i != vCopyDamageCopy.end(); ++i)
for (auto i = vCopyDamageCopy.begin(); i != vCopyDamageCopy.end(); ++i)
{
// Check if aura was removed during iteration - we don't need to work on such auras
if (!((*i)->GetBase()->IsAppliedOnTarget(victim->GetGUID())))
@@ -941,7 +949,7 @@ bool Unit::HasBreakableByDamageCrowdControlAura(Unit* excludeCasterChannel) cons
if (damagetype != NODAMAGE && damagetype != SELF_DAMAGE && victim->HasAuraType(SPELL_AURA_SCHOOL_ABSORB_OVERKILL))
{
AuraEffectList vAbsorbOverkill = victim->GetAuraEffectsByType(SPELL_AURA_SCHOOL_ABSORB_OVERKILL);
AuraEffectVector vAbsorbOverkill = CopyAuraEffectList(victim->GetAuraEffectsByType(SPELL_AURA_SCHOOL_ABSORB_OVERKILL));
DamageInfo damageInfo = DamageInfo(attacker, victim, damageTaken, spellProto, damageSchoolMask, damagetype,
cleanDamage ? cleanDamage->attackType : BASE_ATTACK);
for (AuraEffect* absorbAurEff : vAbsorbOverkill)
@@ -1535,7 +1543,7 @@ void Unit::DealMeleeDamage(CalcDamageInfo* damageInfo, bool durabilityLoss)
{
// We're going to call functions which can modify content of the list during iteration over it's elements
// Let's copy the list so we can prevent iterator invalidation
AuraEffectList vDamageShieldsCopy(victim->GetAuraEffectsByType(SPELL_AURA_DAMAGE_SHIELD));
AuraEffectVector vDamageShieldsCopy = CopyAuraEffectList(victim->GetAuraEffectsByType(SPELL_AURA_DAMAGE_SHIELD));
for (AuraEffect const* aurEff : vDamageShieldsCopy)
{
SpellInfo const* spellInfo = aurEff->GetSpellInfo();
@@ -1807,11 +1815,11 @@ void Unit::HandleEmoteCommand(Emote emoteId, Player* target /*=nullptr*/, Trinit
// We're going to call functions which can modify content of the list during iteration over it's elements
// Let's copy the list so we can prevent iterator invalidation
AuraEffectList vSchoolAbsorbCopy(damageInfo.GetVictim()->GetAuraEffectsByType(SPELL_AURA_SCHOOL_ABSORB));
vSchoolAbsorbCopy.sort(Trinity::AbsorbAuraOrderPred());
AuraEffectVector vSchoolAbsorbCopy = CopyAuraEffectList(damageInfo.GetVictim()->GetAuraEffectsByType(SPELL_AURA_SCHOOL_ABSORB));
std::sort(vSchoolAbsorbCopy.begin(), vSchoolAbsorbCopy.end(), Trinity::AbsorbAuraOrderPred());
// absorb without mana cost
for (AuraEffectList::iterator itr = vSchoolAbsorbCopy.begin(); (itr != vSchoolAbsorbCopy.end()) && (damageInfo.GetDamage() > 0); ++itr)
for (auto itr = vSchoolAbsorbCopy.begin(); (itr != vSchoolAbsorbCopy.end()) && (damageInfo.GetDamage() > 0); ++itr)
{
AuraEffect* absorbAurEff = *itr;
// Check if aura was removed during iteration - we don't need to work on such auras
@@ -1877,8 +1885,8 @@ void Unit::HandleEmoteCommand(Emote emoteId, Player* target /*=nullptr*/, Trinit
}
// absorb by mana cost
AuraEffectList vManaShieldCopy(damageInfo.GetVictim()->GetAuraEffectsByType(SPELL_AURA_MANA_SHIELD));
for (AuraEffectList::const_iterator itr = vManaShieldCopy.begin(); (itr != vManaShieldCopy.end()) && (damageInfo.GetDamage() > 0); ++itr)
AuraEffectVector vManaShieldCopy = CopyAuraEffectList(damageInfo.GetVictim()->GetAuraEffectsByType(SPELL_AURA_MANA_SHIELD));
for (auto itr = vManaShieldCopy.begin(); (itr != vManaShieldCopy.end()) && (damageInfo.GetDamage() > 0); ++itr)
{
AuraEffect* absorbAurEff = *itr;
// Check if aura was removed during iteration - we don't need to work on such auras
@@ -1958,8 +1966,8 @@ void Unit::HandleEmoteCommand(Emote emoteId, Player* target /*=nullptr*/, Trinit
{
// We're going to call functions which can modify content of the list during iteration over it's elements
// Let's copy the list so we can prevent iterator invalidation
AuraEffectList vSplitDamagePctCopy(damageInfo.GetVictim()->GetAuraEffectsByType(SPELL_AURA_SPLIT_DAMAGE_PCT));
for (AuraEffectList::iterator itr = vSplitDamagePctCopy.begin(); itr != vSplitDamagePctCopy.end() && damageInfo.GetDamage() > 0; ++itr)
AuraEffectVector vSplitDamagePctCopy = CopyAuraEffectList(damageInfo.GetVictim()->GetAuraEffectsByType(SPELL_AURA_SPLIT_DAMAGE_PCT));
for (auto itr = vSplitDamagePctCopy.begin(); itr != vSplitDamagePctCopy.end() && damageInfo.GetDamage() > 0; ++itr)
{
// Check if aura was removed during iteration - we don't need to work on such auras
AuraApplication const* aurApp = (*itr)->GetBase()->GetApplicationOfTarget(damageInfo.GetVictim()->GetGUID());
@@ -2020,8 +2028,7 @@ void Unit::HandleEmoteCommand(Emote emoteId, Player* target /*=nullptr*/, Trinit
if (!healInfo.GetHeal())
return;
std::vector<AuraEffect*> vHealAbsorb(healInfo.GetTarget()->GetAuraEffectsByType(SPELL_AURA_SCHOOL_HEAL_ABSORB).begin(),
healInfo.GetTarget()->GetAuraEffectsByType(SPELL_AURA_SCHOOL_HEAL_ABSORB).end());
AuraEffectVector vHealAbsorb = CopyAuraEffectList(healInfo.GetTarget()->GetAuraEffectsByType(SPELL_AURA_SCHOOL_HEAL_ABSORB));
for (auto i = vHealAbsorb.begin(); i != vHealAbsorb.end() && healInfo.GetHeal() > 0; ++i)
{
AuraEffect* absorbAurEff = *i;
@@ -7892,7 +7899,7 @@ MountCapabilityEntry const* Unit::GetMountCapability(uint32 mountType) const
void Unit::UpdateMountCapability()
{
AuraEffectList mounts = GetAuraEffectsByType(SPELL_AURA_MOUNTED);
AuraEffectVector mounts = CopyAuraEffectList(GetAuraEffectsByType(SPELL_AURA_MOUNTED));
for (AuraEffect* aurEff : mounts)
{
aurEff->RecalculateAmount();
@@ -8074,7 +8081,7 @@ void Unit::TriggerOnHealthChangeAuras(uint64 oldVal, uint64 newVal)
if (!HasAuraType(SPELL_AURA_TRIGGER_SPELL_ON_HEALTH_PCT))
return;
AuraEffectList effects = GetAuraEffectsByType(SPELL_AURA_TRIGGER_SPELL_ON_HEALTH_PCT);
AuraEffectVector effects = CopyAuraEffectList(GetAuraEffectsByType(SPELL_AURA_TRIGGER_SPELL_ON_HEALTH_PCT));
for (AuraEffect const* effect : effects)
{
uint32 triggerHealthPct = effect->GetAmount();
@@ -9264,44 +9271,46 @@ void Unit::SetMaxPower(Powers power, int32 val)
void Unit::TriggerOnPowerChangeAuras(Powers power, int32 oldVal, int32 newVal)
{
AuraEffectList effects = GetAuraEffectsByType(SPELL_AURA_TRIGGER_SPELL_ON_POWER_PCT);
AuraEffectList effectsAmount = GetAuraEffectsByType(SPELL_AURA_TRIGGER_SPELL_ON_POWER_AMOUNT);
effects.splice(effects.end(), effectsAmount);
for (AuraEffect const* effect : effects)
auto processAuras = [&](AuraEffectVector const& effects)
{
if (effect->GetMiscValue() == power)
for (AuraEffect const* effect : effects)
{
uint32 effectAmount = effect->GetAmount();
uint32 triggerSpell = effect->GetSpellEffectInfo().TriggerSpell;
float oldValueCheck = oldVal;
float newValueCheck = newVal;
if (effect->GetAuraType() == SPELL_AURA_TRIGGER_SPELL_ON_POWER_PCT)
if (effect->GetMiscValue() == power)
{
int32 maxPower = GetMaxPower(power);
oldValueCheck = GetPctOf(oldVal, maxPower);
newValueCheck = GetPctOf(newVal, maxPower);
}
uint32 effectAmount = effect->GetAmount();
uint32 triggerSpell = effect->GetSpellEffectInfo().TriggerSpell;
switch (AuraTriggerOnPowerChangeDirection(effect->GetMiscValueB()))
{
case AuraTriggerOnPowerChangeDirection::Gain:
if (oldValueCheck >= effect->GetAmount() || newValueCheck < effectAmount)
continue;
break;
case AuraTriggerOnPowerChangeDirection::Loss:
if (oldValueCheck <= effect->GetAmount() || newValueCheck > effectAmount)
continue;
break;
default:
break;
}
float oldValueCheck = oldVal;
float newValueCheck = newVal;
CastSpell(this, triggerSpell, effect);
if (effect->GetAuraType() == SPELL_AURA_TRIGGER_SPELL_ON_POWER_PCT)
{
int32 maxPower = GetMaxPower(power);
oldValueCheck = GetPctOf(oldVal, maxPower);
newValueCheck = GetPctOf(newVal, maxPower);
}
switch (AuraTriggerOnPowerChangeDirection(effect->GetMiscValueB()))
{
case AuraTriggerOnPowerChangeDirection::Gain:
if (oldValueCheck >= effect->GetAmount() || newValueCheck < effectAmount)
continue;
break;
case AuraTriggerOnPowerChangeDirection::Loss:
if (oldValueCheck <= effect->GetAmount() || newValueCheck > effectAmount)
continue;
break;
default:
break;
}
CastSpell(this, triggerSpell, effect);
}
}
}
};
processAuras(CopyAuraEffectList(GetAuraEffectsByType(SPELL_AURA_TRIGGER_SPELL_ON_POWER_PCT)));
processAuras(CopyAuraEffectList(GetAuraEffectsByType(SPELL_AURA_TRIGGER_SPELL_ON_POWER_AMOUNT)));
}
void Unit::AIUpdateTick(uint32 diff)
+2
View File
@@ -769,6 +769,8 @@ class TC_GAME_API Unit : public WorldObject
struct VisibleAuraSlotCompare { bool operator()(AuraApplication* left, AuraApplication* right) const; };
typedef std::set<AuraApplication*, VisibleAuraSlotCompare> VisibleAuraContainer;
static std::vector<AuraEffect*> CopyAuraEffectList(AuraEffectList const& list);
virtual ~Unit();
bool IsAIEnabled() const { return (i_AI != nullptr); }