diff options
-rw-r--r-- | src/server/game/Entities/Unit/Unit.cpp | 101 | ||||
-rw-r--r-- | src/server/game/Entities/Unit/Unit.h | 2 |
2 files changed, 57 insertions, 46 deletions
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index ce0eb1d503d..cd97d0d4081 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -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; + if (effect->GetMiscValue() == power) + { + uint32 effectAmount = effect->GetAmount(); + uint32 triggerSpell = effect->GetSpellEffectInfo().TriggerSpell; - float oldValueCheck = oldVal; - float newValueCheck = newVal; + float oldValueCheck = oldVal; + float newValueCheck = newVal; - if (effect->GetAuraType() == SPELL_AURA_TRIGGER_SPELL_ON_POWER_PCT) - { - int32 maxPower = GetMaxPower(power); - oldValueCheck = GetPctOf(oldVal, maxPower); - newValueCheck = GetPctOf(newVal, maxPower); - } + 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; - } + 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); + 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) diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index d12fbda04bd..e01d32067e5 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -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); } |