diff options
| author | Shauren <shauren.trinity@gmail.com> | 2021-09-04 15:13:15 +0200 |
|---|---|---|
| committer | Shauren <shauren.trinity@gmail.com> | 2021-09-04 15:13:15 +0200 |
| commit | 8a4e1119ac21e2d1112d1717337597fe073e495f (patch) | |
| tree | 34f3215bec2096b59e3d9b2353661e1c137ff8b4 /src/server/game/Spells | |
| parent | 16ed458eeeebe436f05c43686928252992ae2a20 (diff) | |
Core/Spells: Unify spell effect access api in both branches
Diffstat (limited to 'src/server/game/Spells')
| -rw-r--r-- | src/server/game/Spells/Auras/SpellAuraEffects.cpp | 95 | ||||
| -rw-r--r-- | src/server/game/Spells/Auras/SpellAuraEffects.h | 20 | ||||
| -rw-r--r-- | src/server/game/Spells/Auras/SpellAuras.cpp | 145 | ||||
| -rw-r--r-- | src/server/game/Spells/Spell.cpp | 689 | ||||
| -rw-r--r-- | src/server/game/Spells/Spell.h | 52 | ||||
| -rw-r--r-- | src/server/game/Spells/SpellEffects.cpp | 55 | ||||
| -rw-r--r-- | src/server/game/Spells/SpellInfo.cpp | 474 | ||||
| -rw-r--r-- | src/server/game/Spells/SpellInfo.h | 33 | ||||
| -rw-r--r-- | src/server/game/Spells/SpellMgr.cpp | 307 | ||||
| -rw-r--r-- | src/server/game/Spells/SpellScript.cpp | 76 | ||||
| -rw-r--r-- | src/server/game/Spells/SpellScript.h | 5 |
11 files changed, 900 insertions, 1051 deletions
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 159a153ab1f..740e885bd4b 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -575,9 +575,9 @@ NonDefaultConstructible<pAuraEffectHandler> AuraEffectHandler[TOTAL_AURAS]= &AuraEffect::HandleNULL, //503 SPELL_AURA_MOD_PLAYER_CHOICE_REROLLS }; -AuraEffect::AuraEffect(Aura* base, SpellEffectInfo const* spellEfffectInfo, int32 const* baseAmount, Unit* caster) : +AuraEffect::AuraEffect(Aura* base, SpellEffectInfo const& spellEfffectInfo, int32 const* baseAmount, Unit* caster) : m_base(base), m_spellInfo(base->GetSpellInfo()), m_effectInfo(spellEfffectInfo), m_spellmod(nullptr), -m_baseAmount(baseAmount ? *baseAmount : spellEfffectInfo->CalcBaseValue(caster, base->GetType() == UNIT_AURA_TYPE ? base->GetOwner()->ToUnit() : nullptr, base->GetCastItemId(), base->GetCastItemLevel())), +m_baseAmount(baseAmount ? *baseAmount : spellEfffectInfo.CalcBaseValue(caster, base->GetType() == UNIT_AURA_TYPE ? base->GetOwner()->ToUnit() : nullptr, base->GetCastItemId(), base->GetCastItemLevel())), _amount(), _periodicTimer(0), _period(0), _ticksDone(0), m_canBeRecalculated(true), m_isPeriodic(false) { @@ -621,10 +621,10 @@ int32 AuraEffect::CalculateAmount(Unit* caster) // default amount calculation int32 amount = 0; - if (!m_spellInfo->HasAttribute(SPELL_ATTR8_MASTERY_SPECIALIZATION) || G3D::fuzzyEq(GetSpellEffectInfo()->BonusCoefficient, 0.0f)) - amount = GetSpellEffectInfo()->CalcValue(caster, &m_baseAmount, GetBase()->GetOwner()->ToUnit(), nullptr, GetBase()->GetCastItemId(), GetBase()->GetCastItemLevel()); + if (!m_spellInfo->HasAttribute(SPELL_ATTR8_MASTERY_SPECIALIZATION) || G3D::fuzzyEq(GetSpellEffectInfo().BonusCoefficient, 0.0f)) + amount = GetSpellEffectInfo().CalcValue(caster, &m_baseAmount, GetBase()->GetOwner()->ToUnit(), nullptr, GetBase()->GetCastItemId(), GetBase()->GetCastItemLevel()); else if (caster && caster->GetTypeId() == TYPEID_PLAYER) - amount = int32(caster->ToPlayer()->m_activePlayerData->Mastery * GetSpellEffectInfo()->BonusCoefficient); + amount = int32(caster->ToPlayer()->m_activePlayerData->Mastery * GetSpellEffectInfo().BonusCoefficient); // custom amount calculations go here switch (GetAuraType()) @@ -668,12 +668,12 @@ int32 AuraEffect::CalculateAmount(Unit* caster) } GetBase()->CallScriptEffectCalcAmountHandlers(this, amount, m_canBeRecalculated); - if (!GetSpellEffectInfo()->EffectAttributes.HasFlag(SpellEffectAttributes::NoScaleWithStack)) + if (!GetSpellEffectInfo().EffectAttributes.HasFlag(SpellEffectAttributes::NoScaleWithStack)) amount *= GetBase()->GetStackAmount(); if (caster && GetBase()->GetType() == UNIT_AURA_TYPE) { - uint32 stackAmountForBonuses = !GetSpellEffectInfo()->EffectAttributes.HasFlag(SpellEffectAttributes::NoScaleWithStack) ? GetBase()->GetStackAmount() : 1; + uint32 stackAmountForBonuses = !GetSpellEffectInfo().EffectAttributes.HasFlag(SpellEffectAttributes::NoScaleWithStack) ? GetBase()->GetStackAmount() : 1; switch (GetAuraType()) { @@ -719,7 +719,7 @@ void AuraEffect::ResetPeriodic(bool resetPeriodicTimer /*= false*/) void AuraEffect::CalculatePeriodic(Unit* caster, bool resetPeriodicTimer /*= true*/, bool load /*= false*/) { - _period = GetSpellEffectInfo()->ApplyAuraPeriod; + _period = GetSpellEffectInfo().ApplyAuraPeriod; // prepare periodics switch (GetAuraType()) @@ -801,7 +801,7 @@ void AuraEffect::CalculateSpellMod() m_spellmod->type = GetAuraType() == SPELL_AURA_ADD_PCT_MODIFIER ? SPELLMOD_PCT : SPELLMOD_FLAT; m_spellmod->spellId = GetId(); - m_spellmod->mask = GetSpellEffectInfo()->SpellClassMask; + m_spellmod->mask = GetSpellEffectInfo().SpellClassMask; } m_spellmod->value = GetAmount(); break; @@ -1006,7 +1006,7 @@ bool AuraEffect::IsAffectingSpell(SpellInfo const* spell) const return false; // Check family name and EffectClassMask - if (!spell->IsAffected(m_spellInfo->SpellFamilyName, GetSpellEffectInfo()->SpellClassMask)) + if (!spell->IsAffected(m_spellInfo->SpellFamilyName, GetSpellEffectInfo().SpellClassMask)) return false; return true; @@ -1139,7 +1139,7 @@ bool AuraEffect::CheckEffectProc(AuraApplication* aurApp, ProcEventInfo& eventIn case SPELL_AURA_PROC_TRIGGER_SPELL_WITH_VALUE: { // Don't proc extra attacks while already processing extra attack spell - uint32 triggerSpellId = GetSpellEffectInfo()->TriggerSpell; + uint32 triggerSpellId = GetSpellEffectInfo().TriggerSpell; if (SpellInfo const* triggeredSpellInfo = sSpellMgr->GetSpellInfo(triggerSpellId, GetBase()->GetCastDifficulty())) if (aurApp->GetTarget()->m_extraAttacks && triggeredSpellInfo->HasEffect(SPELL_EFFECT_ADD_EXTRA_ATTACKS)) return false; @@ -2527,8 +2527,8 @@ void AuraEffect::HandleAuraMounted(AuraApplication const* aurApp, uint8 mode, bo } //some spell has one aura of mount and one of vehicle - for (SpellEffectInfo const* effect : GetSpellInfo()->GetEffects()) - if (effect && effect->Effect == SPELL_EFFECT_SUMMON && effect->MiscValue == GetMiscValue()) + for (SpellEffectInfo const& effect : GetSpellInfo()->GetEffects()) + if (effect.IsEffect(SPELL_EFFECT_SUMMON) && effect.MiscValue == GetMiscValue()) displayId = 0; } @@ -4382,8 +4382,7 @@ void AuraEffect::HandleNoReagentUseAura(AuraApplication const* aurApp, uint8 mod flag128 mask; Unit::AuraEffectList const& noReagent = target->GetAuraEffectsByType(SPELL_AURA_NO_REAGENT_USE); for (Unit::AuraEffectList::const_iterator i = noReagent.begin(); i != noReagent.end(); ++i) - if (SpellEffectInfo const* effect = (*i)->GetSpellEffectInfo()) - mask |= effect->SpellClassMask; + mask |= (*i)->GetSpellEffectInfo().SpellClassMask; target->ToPlayer()->SetNoRegentCostMask(mask); } @@ -4750,11 +4749,11 @@ void AuraEffect::HandleChannelDeathItem(AuraApplication const* aurApp, uint8 mod if (GetAmount() <= 0) return; - if (GetSpellEffectInfo()->ItemType == 0) + if (GetSpellEffectInfo().ItemType == 0) return; // Soul Shard - if (GetSpellEffectInfo()->ItemType == 6265) + if (GetSpellEffectInfo().ItemType == 6265) { // Soul Shard only from units that grant XP or honor if (!plCaster->isHonorOrXPTarget(target) || @@ -4767,16 +4766,16 @@ void AuraEffect::HandleChannelDeathItem(AuraApplication const* aurApp, uint8 mod uint32 count = GetAmount(); ItemPosCountVec dest; - InventoryResult msg = plCaster->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, GetSpellEffectInfo()->ItemType, count, &noSpaceForCount); + InventoryResult msg = plCaster->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, GetSpellEffectInfo().ItemType, count, &noSpaceForCount); if (msg != EQUIP_ERR_OK) { count -= noSpaceForCount; - plCaster->SendEquipError(msg, nullptr, nullptr, GetSpellEffectInfo()->ItemType); + plCaster->SendEquipError(msg, nullptr, nullptr, GetSpellEffectInfo().ItemType); if (count == 0) return; } - Item* newitem = plCaster->StoreNewItem(dest, GetSpellEffectInfo()->ItemType, true); + Item* newitem = plCaster->StoreNewItem(dest, GetSpellEffectInfo().ItemType, true); if (!newitem) { plCaster->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, nullptr, nullptr); @@ -4902,7 +4901,7 @@ void AuraEffect::HandleAuraLinked(AuraApplication const* aurApp, uint8 mode, boo { Unit* target = aurApp->GetTarget(); - uint32 triggeredSpellId = GetSpellEffectInfo()->TriggerSpell; + uint32 triggeredSpellId = GetSpellEffectInfo().TriggerSpell; SpellInfo const* triggeredSpellInfo = sSpellMgr->GetSpellInfo(triggeredSpellId, GetBase()->GetCastDifficulty()); if (!triggeredSpellInfo) return; @@ -4946,7 +4945,7 @@ void AuraEffect::HandleTriggerSpellOnPowerPercent(AuraApplication const* aurApp, Unit* target = aurApp->GetTarget(); int32 effectAmount = GetAmount(); - uint32 triggerSpell = GetSpellEffectInfo()->TriggerSpell; + uint32 triggerSpell = GetSpellEffectInfo().TriggerSpell; float powerAmountPct = GetPctOf(target->GetPower(Powers(GetMiscValue())), target->GetMaxPower(Powers(GetMiscValue()))); switch (AuraTriggerOnPowerChangeDirection(GetMiscValueB())) @@ -4974,7 +4973,7 @@ void AuraEffect::HandleTriggerSpellOnPowerAmount(AuraApplication const* aurApp, Unit* target = aurApp->GetTarget(); int32 effectAmount = GetAmount(); - uint32 triggerSpell = GetSpellEffectInfo()->TriggerSpell; + uint32 triggerSpell = GetSpellEffectInfo().TriggerSpell; float powerAmount = target->GetPower(Powers(GetMiscValue())); switch (AuraTriggerOnPowerChangeDirection(GetMiscValueB())) @@ -5133,7 +5132,7 @@ void AuraEffect::HandleMastery(AuraApplication const* aurApp, uint8 mode, bool / void AuraEffect::HandlePeriodicTriggerSpellAuraTick(Unit* target, Unit* caster) const { - uint32 triggerSpellId = GetSpellEffectInfo()->TriggerSpell; + uint32 triggerSpellId = GetSpellEffectInfo().TriggerSpell; if (SpellInfo const* triggeredSpellInfo = sSpellMgr->GetSpellInfo(triggerSpellId, GetBase()->GetCastDifficulty())) { if (Unit* triggerCaster = triggeredSpellInfo->NeedsToBeTriggeredByCaster(m_spellInfo) ? caster : target) @@ -5148,7 +5147,7 @@ void AuraEffect::HandlePeriodicTriggerSpellAuraTick(Unit* target, Unit* caster) void AuraEffect::HandlePeriodicTriggerSpellWithValueAuraTick(Unit* target, Unit* caster) const { - uint32 triggerSpellId = GetSpellEffectInfo()->TriggerSpell; + uint32 triggerSpellId = GetSpellEffectInfo().TriggerSpell; if (SpellInfo const* triggeredSpellInfo = sSpellMgr->GetSpellInfo(triggerSpellId, GetBase()->GetCastDifficulty())) { if (Unit* triggerCaster = triggeredSpellInfo->NeedsToBeTriggeredByCaster(m_spellInfo) ? caster : target) @@ -5177,13 +5176,13 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const // Consecrate ticks can miss and will not show up in the combat log // dynobj auras must always have a caster - if (GetSpellEffectInfo()->Effect == SPELL_EFFECT_PERSISTENT_AREA_AURA && + if (GetSpellEffectInfo().IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA) && ASSERT_NOTNULL(caster)->SpellHitResult(target, GetSpellInfo(), false) != SPELL_MISS_NONE) return; CleanDamage cleanDamage = CleanDamage(0, 0, BASE_ATTACK, MELEE_HIT_NORMAL); - uint32 stackAmountForBonuses = !GetSpellEffectInfo()->EffectAttributes.HasFlag(SpellEffectAttributes::NoScaleWithStack) ? GetBase()->GetStackAmount() : 1; + uint32 stackAmountForBonuses = !GetSpellEffectInfo().EffectAttributes.HasFlag(SpellEffectAttributes::NoScaleWithStack) ? GetBase()->GetStackAmount() : 1; // ignore negative values (can be result apply spellmods to aura damage uint32 damage = std::max(GetAmount(), 0); @@ -5248,7 +5247,7 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const damage = Unit::SpellCriticalDamageBonus(caster, m_spellInfo, damage, target); // Calculate armor mitigation - if (Unit::IsDamageReducedByArmor(GetSpellInfo()->GetSchoolMask(), GetSpellInfo(), GetEffIndex())) + if (Unit::IsDamageReducedByArmor(GetSpellInfo()->GetSchoolMask(), GetSpellInfo(), &GetSpellEffectInfo())) { uint32 damageReducedArmor = Unit::CalcArmorReducedDamage(caster, target, damage, GetSpellInfo(), GetSpellInfo()->GetAttackType(), GetBase()->GetCasterLevel()); cleanDamage.mitigated_damage += damage - damageReducedArmor; @@ -5257,7 +5256,7 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const if (!GetSpellInfo()->HasAttribute(SPELL_ATTR4_FIXED_DAMAGE)) { - if (GetSpellEffectInfo()->IsTargetingArea() || GetSpellEffectInfo()->IsAreaAuraEffect() || GetSpellEffectInfo()->Effect == SPELL_EFFECT_PERSISTENT_AREA_AURA) + if (GetSpellEffectInfo().IsTargetingArea() || GetSpellEffectInfo().IsAreaAuraEffect() || GetSpellEffectInfo().IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA)) damage = target->CalculateAOEAvoidance(damage, m_spellInfo->SchoolMask, GetBase()->GetCasterGUID()); } @@ -5302,7 +5301,7 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const bool AuraEffect::IsAreaAuraEffect() const { - return GetSpellEffectInfo()->IsAreaAuraEffect(); + return GetSpellEffectInfo().IsAreaAuraEffect(); } void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) const @@ -5317,13 +5316,13 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c } // dynobj auras must always have a caster - if (GetSpellEffectInfo()->Effect == SPELL_EFFECT_PERSISTENT_AREA_AURA && + if (GetSpellEffectInfo().IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA) && ASSERT_NOTNULL(caster)->SpellHitResult(target, GetSpellInfo(), false) != SPELL_MISS_NONE) return; CleanDamage cleanDamage = CleanDamage(0, 0, GetSpellInfo()->GetAttackType(), MELEE_HIT_NORMAL); - uint32 stackAmountForBonuses = !GetSpellEffectInfo()->EffectAttributes.HasFlag(SpellEffectAttributes::NoScaleWithStack) ? GetBase()->GetStackAmount() : 1; + uint32 stackAmountForBonuses = !GetSpellEffectInfo().EffectAttributes.HasFlag(SpellEffectAttributes::NoScaleWithStack) ? GetBase()->GetStackAmount() : 1; // ignore negative values (can be result apply spellmods to aura damage uint32 damage = std::max(GetAmount(), 0); @@ -5337,7 +5336,7 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c damage = Unit::SpellCriticalDamageBonus(caster, m_spellInfo, damage, target); // Calculate armor mitigation - if (Unit::IsDamageReducedByArmor(GetSpellInfo()->GetSchoolMask(), GetSpellInfo(), GetEffIndex())) + if (Unit::IsDamageReducedByArmor(GetSpellInfo()->GetSchoolMask(), GetSpellInfo(), &GetSpellEffectInfo())) { uint32 damageReducedArmor = Unit::CalcArmorReducedDamage(caster, target, damage, GetSpellInfo(), GetSpellInfo()->GetAttackType(), GetBase()->GetCasterLevel()); cleanDamage.mitigated_damage += damage - damageReducedArmor; @@ -5346,7 +5345,7 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c if (!GetSpellInfo()->HasAttribute(SPELL_ATTR4_FIXED_DAMAGE)) { - if (GetSpellEffectInfo()->IsTargetingArea() || GetSpellEffectInfo()->IsAreaAuraEffect() || GetSpellEffectInfo()->Effect == SPELL_EFFECT_PERSISTENT_AREA_AURA) + if (GetSpellEffectInfo().IsTargetingArea() || GetSpellEffectInfo().IsAreaAuraEffect() || GetSpellEffectInfo().IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA)) damage = target->CalculateAOEAvoidance(damage, m_spellInfo->SchoolMask, GetBase()->GetCasterGUID()); } @@ -5390,7 +5389,7 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c if (!caster || !caster->IsAlive()) return; - float gainMultiplier = GetSpellEffectInfo()->CalcValueMultiplier(caster); + float gainMultiplier = GetSpellEffectInfo().CalcValueMultiplier(caster); uint32 heal = caster->SpellHealingBonusDone(caster, GetSpellInfo(), uint32(new_damage * gainMultiplier), DOT, GetSpellEffectInfo(), stackAmountForBonuses); heal = caster->SpellHealingBonusTaken(caster, GetSpellInfo(), heal, DOT); @@ -5425,7 +5424,7 @@ void AuraEffect::HandlePeriodicHealthFunnelAuraTick(Unit* target, Unit* caster) caster->ModifyHealth(-(int32)damage); TC_LOG_DEBUG("spells", "PeriodicTick: donator %u target %u damage %u.", caster->GetEntry(), target->GetEntry(), damage); - float gainMultiplier = GetSpellEffectInfo()->CalcValueMultiplier(caster); + float gainMultiplier = GetSpellEffectInfo().CalcValueMultiplier(caster); damage = int32(damage * gainMultiplier); @@ -5453,7 +5452,7 @@ void AuraEffect::HandlePeriodicHealAurasTick(Unit* target, Unit* caster) const if (GetBase()->IsPermanent() && target->IsFullHealth()) return; - uint32 stackAmountForBonuses = !GetSpellEffectInfo()->EffectAttributes.HasFlag(SpellEffectAttributes::NoScaleWithStack) ? GetBase()->GetStackAmount() : 1; + uint32 stackAmountForBonuses = !GetSpellEffectInfo().EffectAttributes.HasFlag(SpellEffectAttributes::NoScaleWithStack) ? GetBase()->GetStackAmount() : 1; // ignore negative values (can be result apply spellmods to aura damage uint32 damage = std::max(GetAmount(), 0); @@ -5509,7 +5508,7 @@ void AuraEffect::HandlePeriodicManaLeechAuraTick(Unit* target, Unit* caster) con return; } - if (GetSpellEffectInfo()->Effect == SPELL_EFFECT_PERSISTENT_AREA_AURA && + if (GetSpellEffectInfo().IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA) && caster->SpellHitResult(target, GetSpellInfo(), false) != SPELL_MISS_NONE) return; @@ -5521,7 +5520,7 @@ void AuraEffect::HandlePeriodicManaLeechAuraTick(Unit* target, Unit* caster) con int32 drainedAmount = -target->ModifyPower(powerType, -drainAmount); - float gainMultiplier = GetSpellEffectInfo()->CalcValueMultiplier(caster); + float gainMultiplier = GetSpellEffectInfo().CalcValueMultiplier(caster); SpellPeriodicAuraLogInfo pInfo(this, drainedAmount, drainAmount, 0, 0, 0, gainMultiplier, false); @@ -5638,7 +5637,7 @@ void AuraEffect::HandlePeriodicPowerBurnAuraTick(Unit* target, Unit* caster) con uint32 gain = uint32(-target->ModifyPower(powerType, -damage)); - float dmgMultiplier = GetSpellEffectInfo()->CalcValueMultiplier(caster); + float dmgMultiplier = GetSpellEffectInfo().CalcValueMultiplier(caster); SpellInfo const* spellProto = GetSpellInfo(); // maybe has to be sent different to client, but not by SMSG_PERIODICAURALOG @@ -5703,7 +5702,7 @@ void AuraEffect::HandleProcTriggerSpellAuraProc(AuraApplication* aurApp, ProcEve Unit* triggerCaster = aurApp->GetTarget(); Unit* triggerTarget = eventInfo.GetProcTarget(); - uint32 triggerSpellId = GetSpellEffectInfo()->TriggerSpell; + uint32 triggerSpellId = GetSpellEffectInfo().TriggerSpell; if (SpellInfo const* triggeredSpellInfo = sSpellMgr->GetSpellInfo(triggerSpellId, GetBase()->GetCastDifficulty())) { TC_LOG_DEBUG("spells", "AuraEffect::HandleProcTriggerSpellAuraProc: Triggering spell %u from aura %u proc", triggeredSpellInfo->Id, GetId()); @@ -5718,7 +5717,7 @@ void AuraEffect::HandleProcTriggerSpellWithValueAuraProc(AuraApplication* aurApp Unit* triggerCaster = aurApp->GetTarget(); Unit* triggerTarget = eventInfo.GetProcTarget(); - uint32 triggerSpellId = GetSpellEffectInfo()->TriggerSpell; + uint32 triggerSpellId = GetSpellEffectInfo().TriggerSpell; if (SpellInfo const* triggeredSpellInfo = sSpellMgr->GetSpellInfo(triggerSpellId, GetBase()->GetCastDifficulty())) { CastSpellExtraArgs args(this); @@ -5801,9 +5800,9 @@ void AuraEffect::HandleShowConfirmationPrompt(AuraApplication const* aurApp, uin return; if (apply) - player->AddTemporarySpell(GetSpellEffectInfo()->TriggerSpell); + player->AddTemporarySpell(GetSpellEffectInfo().TriggerSpell); else - player->RemoveTemporarySpell(GetSpellEffectInfo()->TriggerSpell); + player->RemoveTemporarySpell(GetSpellEffectInfo().TriggerSpell); } void AuraEffect::HandleOverridePetSpecs(AuraApplication const* aurApp, uint8 mode, bool apply) const @@ -5897,7 +5896,7 @@ void AuraEffect::HandleLinkedSummon(AuraApplication const* aurApp, uint8 mode, b return; Unit* target = aurApp->GetTarget(); - SpellInfo const* triggerSpellInfo = sSpellMgr->GetSpellInfo(GetSpellEffectInfo()->TriggerSpell, GetBase()->GetCastDifficulty()); + SpellInfo const* triggerSpellInfo = sSpellMgr->GetSpellInfo(GetSpellEffectInfo().TriggerSpell, GetBase()->GetCastDifficulty()); if (!triggerSpellInfo) return; @@ -5914,9 +5913,9 @@ void AuraEffect::HandleLinkedSummon(AuraApplication const* aurApp, uint8 mode, b else { std::vector<uint32> summonedEntries; - for (auto spellEffect : triggerSpellInfo->GetEffects()) - if (spellEffect && spellEffect->Effect == SPELL_EFFECT_SUMMON) - if (uint32 summonEntry = spellEffect->MiscValue) + for (SpellEffectInfo const& spellEffect : triggerSpellInfo->GetEffects()) + if (spellEffect.IsEffect(SPELL_EFFECT_SUMMON)) + if (uint32 summonEntry = spellEffect.MiscValue) summonedEntries.push_back(summonEntry); // we don't know if there can be multiple summons for the same effect, so consider only 1 summon for each effect diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.h b/src/server/game/Spells/Auras/SpellAuraEffects.h index 1a96b81ea68..476be23e451 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.h +++ b/src/server/game/Spells/Auras/SpellAuraEffects.h @@ -33,7 +33,7 @@ class TC_GAME_API AuraEffect private: ~AuraEffect(); - explicit AuraEffect(Aura* base, SpellEffectInfo const* spellEfffectInfo, int32 const* baseAmount, Unit* caster); + explicit AuraEffect(Aura* base, SpellEffectInfo const& spellEfffectInfo, int32 const* baseAmount, Unit* caster); public: Unit* GetCaster() const { return GetBase()->GetCaster(); } @@ -48,13 +48,13 @@ class TC_GAME_API AuraEffect SpellInfo const* GetSpellInfo() const { return m_spellInfo; } uint32 GetId() const { return m_spellInfo->Id; } - uint32 GetEffIndex() const { return m_effectInfo->EffectIndex; } + SpellEffIndex GetEffIndex() const { return m_effectInfo.EffectIndex; } int32 GetBaseAmount() const { return m_baseAmount; } int32 GetPeriod() const { return _period; } - int32 GetMiscValueB() const { return GetSpellEffectInfo()->MiscValueB; } - int32 GetMiscValue() const { return GetSpellEffectInfo()->MiscValue; } - AuraType GetAuraType() const { return (AuraType)GetSpellEffectInfo()->ApplyAuraName; } + int32 GetMiscValueB() const { return GetSpellEffectInfo().MiscValueB; } + int32 GetMiscValue() const { return GetSpellEffectInfo().MiscValue; } + AuraType GetAuraType() const { return GetSpellEffectInfo().ApplyAuraName; } int32 GetAmount() const { return _amount; } void SetAmount(int32 amount) { _amount = amount; m_canBeRecalculated = false; } @@ -86,7 +86,7 @@ class TC_GAME_API AuraEffect bool IsPeriodic() const { return m_isPeriodic; } void SetPeriodic(bool isPeriodic) { m_isPeriodic = isPeriodic; } bool IsAffectingSpell(SpellInfo const* spell) const; - bool HasSpellClassMask() const { return GetSpellEffectInfo()->SpellClassMask; } + bool HasSpellClassMask() const { return GetSpellEffectInfo().SpellClassMask; } void SendTickImmune(Unit* target, Unit* caster) const; void PeriodicTick(AuraApplication* aurApp, Unit* caster) const; @@ -97,17 +97,17 @@ class TC_GAME_API AuraEffect // add/remove SPELL_AURA_MOD_SHAPESHIFT (36) linked auras void HandleShapeshiftBoosts(Unit* target, bool apply) const; - SpellEffectInfo const* GetSpellEffectInfo() const { return m_effectInfo; } + SpellEffectInfo const& GetSpellEffectInfo() const { return m_effectInfo; } - bool IsEffect() const { return m_effectInfo->Effect != 0; } - bool IsEffect(SpellEffectName effectName) const { return m_effectInfo->Effect == uint32(effectName); } + bool IsEffect() const { return m_effectInfo.Effect != 0; } + bool IsEffect(SpellEffectName effectName) const { return m_effectInfo.Effect == effectName; } bool IsAreaAuraEffect() const; private: Aura* const m_base; SpellInfo const* const m_spellInfo; - SpellEffectInfo const* m_effectInfo; + SpellEffectInfo const& m_effectInfo; SpellModifier* m_spellmod; diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp index 881828cbaa5..a6959945d0d 100644 --- a/src/server/game/Spells/Auras/SpellAuras.cpp +++ b/src/server/game/Spells/Auras/SpellAuras.cpp @@ -115,9 +115,9 @@ void AuraApplication::_InitFlags(Unit* caster, uint32 effMask) if (IsSelfcast() || !caster || !caster->IsFriendlyTo(GetTarget())) { bool negativeFound = false; - for (SpellEffectInfo const* effect : GetBase()->GetSpellInfo()->GetEffects()) + for (uint8 i = 0; i < GetBase()->GetSpellInfo()->GetEffects().size(); ++i) { - if (effect && ((1 << effect->EffectIndex) & effMask) && !GetBase()->GetSpellInfo()->IsPositiveEffect(effect->EffectIndex)) + if (((1 << i) & effMask) && !GetBase()->GetSpellInfo()->IsPositiveEffect(i)) { negativeFound = true; break; @@ -130,9 +130,9 @@ void AuraApplication::_InitFlags(Unit* caster, uint32 effMask) else { bool positiveFound = false; - for (SpellEffectInfo const* effect : GetBase()->GetSpellInfo()->GetEffects()) + for (uint8 i = 0; i < GetBase()->GetSpellInfo()->GetEffects().size(); ++i) { - if (effect && ((1 << effect->EffectIndex) & effMask) && GetBase()->GetSpellInfo()->IsPositiveEffect(effect->EffectIndex)) + if (((1 << i) & effMask) && GetBase()->GetSpellInfo()->IsPositiveEffect(i)) { positiveFound = true; break; @@ -300,17 +300,17 @@ uint32 Aura::BuildEffectMaskForOwner(SpellInfo const* spellProto, uint32 availab { case TYPEID_UNIT: case TYPEID_PLAYER: - for (SpellEffectInfo const* effect : spellProto->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : spellProto->GetEffects()) { - if (effect && effect->IsUnitOwnedAuraEffect()) - effMask |= 1 << effect->EffectIndex; + if (spellEffectInfo.IsUnitOwnedAuraEffect()) + effMask |= 1 << spellEffectInfo.EffectIndex; } break; case TYPEID_DYNAMICOBJECT: - for (SpellEffectInfo const* effect : spellProto->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : spellProto->GetEffects()) { - if (effect && effect->Effect == SPELL_EFFECT_PERSISTENT_AREA_AURA) - effMask |= 1 << effect->EffectIndex; + if (spellEffectInfo.IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA)) + effMask |= 1 << spellEffectInfo.EffectIndex; } break; default: @@ -482,9 +482,9 @@ void Aura::_InitEffects(uint32 effMask, Unit* caster, int32 const* baseAmount) // shouldn't be in constructor - functions in AuraEffect::AuraEffect use polymorphism _effects.resize(GetSpellInfo()->GetEffects().size()); - for (SpellEffectInfo const* effect : GetSpellInfo()->GetEffects()) - if (effect && effMask & (1 << effect->EffectIndex)) - _effects[effect->EffectIndex] = new AuraEffect(this, effect, baseAmount ? baseAmount + effect->EffectIndex : nullptr, caster); + for (SpellEffectInfo const& spellEffectInfo : GetSpellInfo()->GetEffects()) + if (effMask & (1 << spellEffectInfo.EffectIndex)) + _effects[spellEffectInfo.EffectIndex] = new AuraEffect(this, spellEffectInfo, baseAmount ? baseAmount + spellEffectInfo.EffectIndex : nullptr, caster); } Aura::~Aura() @@ -643,9 +643,9 @@ void Aura::UpdateTargetMap(Unit* caster, bool apply) { bool addUnit = true; // check target immunities - for (uint8 effIndex = 0; effIndex < MAX_SPELL_EFFECTS; ++effIndex) - if (itr->first->IsImmunedToSpellEffect(GetSpellInfo(), effIndex, caster)) - itr->second &= ~(1 << effIndex); + for (SpellEffectInfo const& spellEffectInfo : GetSpellInfo()->GetEffects()) + if (itr->first->IsImmunedToSpellEffect(GetSpellInfo(), spellEffectInfo, caster)) + itr->second &= ~(1 << spellEffectInfo.EffectIndex); if (!itr->second || itr->first->IsImmunedToSpell(GetSpellInfo(), caster) || !CanBeAppliedOn(itr->first)) addUnit = false; @@ -1071,8 +1071,8 @@ bool Aura::ModStackAmount(int32 num, AuraRemoveMode removeMode /*= AURA_REMOVE_B bool Aura::HasMoreThanOneEffectForType(AuraType auraType) const { uint32 count = 0; - for (SpellEffectInfo const* effect : GetSpellInfo()->GetEffects()) - if (effect && HasEffect(effect->EffectIndex) && AuraType(effect->ApplyAuraName) == auraType) + for (SpellEffectInfo const& spellEffectInfo : GetSpellInfo()->GetEffects()) + if (HasEffect(spellEffectInfo.EffectIndex) && spellEffectInfo.ApplyAuraName == auraType) ++count; return count > 1; @@ -1080,8 +1080,8 @@ bool Aura::HasMoreThanOneEffectForType(AuraType auraType) const bool Aura::IsArea() const { - for (SpellEffectInfo const* effect : GetSpellInfo()->GetEffects()) - if (effect && HasEffect(effect->EffectIndex) && effect->IsAreaAuraEffect()) + for (SpellEffectInfo const& spellEffectInfo : GetSpellInfo()->GetEffects()) + if (HasEffect(spellEffectInfo.EffectIndex) && spellEffectInfo.IsAreaAuraEffect()) return true; return false; @@ -1117,12 +1117,12 @@ bool Aura::CanBeSaved() const if (GetCasterGUID() != GetOwner()->GetGUID()) { // owner == caster for area auras, check for possible bad data in DB - for (SpellEffectInfo const* effect : GetSpellInfo()->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : GetSpellInfo()->GetEffects()) { - if (!effect || !effect->IsEffect()) + if (!spellEffectInfo.IsEffect()) continue; - if (effect->IsTargetingArea() || effect->IsAreaAuraEffect()) + if (spellEffectInfo.IsTargetingArea() || spellEffectInfo.IsAreaAuraEffect()) return false; } @@ -1568,17 +1568,17 @@ bool Aura::CanStackWith(Aura const* existingAura) const if (IsPassive() && sameCaster && (m_spellInfo->IsDifferentRankOf(existingSpellInfo) || (m_spellInfo->Id == existingSpellInfo->Id && m_castItemGuid.IsEmpty()))) return false; - for (SpellEffectInfo const* effect : existingSpellInfo->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : existingSpellInfo->GetEffects()) { // prevent remove triggering aura by triggered aura - if (effect && effect->TriggerSpell == GetId()) + if (spellEffectInfo.TriggerSpell == GetId()) return true; } - for (SpellEffectInfo const* effect : GetSpellInfo()->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : GetSpellInfo()->GetEffects()) { // prevent remove triggered aura by triggering aura refresh - if (effect && effect->TriggerSpell == existingAura->GetId()) + if (spellEffectInfo.TriggerSpell == existingAura->GetId()) return true; } @@ -1625,36 +1625,39 @@ bool Aura::CanStackWith(Aura const* existingAura) const return true; // check same periodic auras - for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i) + auto hasPeriodicNonAreaEffect = [](SpellInfo const* spellInfo) { - SpellEffectInfo const* effect = m_spellInfo->GetEffect(i); - if (!effect) - continue; - switch (effect->ApplyAuraName) + for (SpellEffectInfo const& spellEffectInfo : spellInfo->GetEffects()) { - // DOT or HOT from different casters will stack - case SPELL_AURA_PERIODIC_DAMAGE: - case SPELL_AURA_PERIODIC_DUMMY: - case SPELL_AURA_PERIODIC_HEAL: - case SPELL_AURA_PERIODIC_TRIGGER_SPELL: - case SPELL_AURA_PERIODIC_ENERGIZE: - case SPELL_AURA_PERIODIC_MANA_LEECH: - case SPELL_AURA_PERIODIC_LEECH: - case SPELL_AURA_POWER_BURN: - case SPELL_AURA_OBS_MOD_POWER: - case SPELL_AURA_OBS_MOD_HEALTH: - case SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE: - { - SpellEffectInfo const* existingEffect = m_spellInfo->GetEffect(i); + switch (spellEffectInfo.ApplyAuraName) + { + // DOT or HOT from different casters will stack + case SPELL_AURA_PERIODIC_DAMAGE: + case SPELL_AURA_PERIODIC_WEAPON_PERCENT_DAMAGE: + case SPELL_AURA_PERIODIC_DUMMY: + case SPELL_AURA_PERIODIC_HEAL: + case SPELL_AURA_PERIODIC_TRIGGER_SPELL: + case SPELL_AURA_PERIODIC_ENERGIZE: + case SPELL_AURA_PERIODIC_MANA_LEECH: + case SPELL_AURA_PERIODIC_LEECH: + case SPELL_AURA_POWER_BURN: + case SPELL_AURA_OBS_MOD_POWER: + case SPELL_AURA_OBS_MOD_HEALTH: + case SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE: + case SPELL_AURA_PERIODIC_DAMAGE_PERCENT: // periodic auras which target areas are not allowed to stack this way (replenishment for example) - if (effect->IsTargetingArea() || (existingEffect && existingEffect->IsTargetingArea())) - break; - } - return true; - default: - break; + if (spellEffectInfo.IsTargetingArea()) + return false; + return true; + default: + break; + } } - } + return false; + }; + + if (hasPeriodicNonAreaEffect(m_spellInfo) && hasPeriodicNonAreaEffect(existingSpellInfo)) + return true; } if (HasEffectType(SPELL_AURA_CONTROL_VEHICLE) && existingAura->HasEffectType(SPELL_AURA_CONTROL_VEHICLE)) @@ -2382,13 +2385,13 @@ void UnitAura::FillTargetMap(std::unordered_map<Unit*, uint32>& targets, Unit* c if (Unit* target = ObjectAccessor::GetUnit(*GetUnitOwner(), targetPair.first)) targets.emplace(target, targetPair.second); - for (SpellEffectInfo const* effect : GetSpellInfo()->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : GetSpellInfo()->GetEffects()) { - if (!effect || !HasEffect(effect->EffectIndex)) + if (!HasEffect(spellEffectInfo.EffectIndex)) continue; // area auras only - if (effect->Effect == SPELL_EFFECT_APPLY_AURA) + if (spellEffectInfo.IsEffect(SPELL_EFFECT_APPLY_AURA)) continue; // skip area update if owner is not in world! @@ -2399,11 +2402,11 @@ void UnitAura::FillTargetMap(std::unordered_map<Unit*, uint32>& targets, Unit* c continue; std::vector<Unit*> units; - ConditionContainer* condList = effect->ImplicitTargetConditions; + ConditionContainer* condList = spellEffectInfo.ImplicitTargetConditions; - float radius = effect->CalcRadius(ref); + float radius = spellEffectInfo.CalcRadius(ref); SpellTargetCheckTypes selectionType = TARGET_CHECK_DEFAULT; - switch (effect->Effect) + switch (spellEffectInfo.Effect) { case SPELL_EFFECT_APPLY_AREA_AURA_PARTY: case SPELL_EFFECT_APPLY_AREA_AURA_PARTY_NONRANDOM: @@ -2445,6 +2448,8 @@ void UnitAura::FillTargetMap(std::unordered_map<Unit*, uint32>& targets, Unit* c selectionType = TARGET_CHECK_SUMMONED; break; } + default: + break; } if (selectionType != TARGET_CHECK_DEFAULT) @@ -2458,17 +2463,17 @@ void UnitAura::FillTargetMap(std::unordered_map<Unit*, uint32>& targets, Unit* c } for (Unit* unit : units) - targets[unit] |= 1 << effect->EffectIndex; + targets[unit] |= 1 << spellEffectInfo.EffectIndex; } } void UnitAura::AddStaticApplication(Unit* target, uint32 effMask) { // only valid for non-area auras - for (SpellEffectInfo const* effect : GetSpellInfo()->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : GetSpellInfo()->GetEffects()) { - if (effect && (effMask & (1 << effect->EffectIndex)) && effect->Effect != SPELL_EFFECT_APPLY_AURA) - effMask &= ~(1 << effect->EffectIndex); + if ((effMask & (1 << spellEffectInfo.EffectIndex)) && !spellEffectInfo.IsEffect(SPELL_EFFECT_APPLY_AURA)) + effMask &= ~(1 << spellEffectInfo.EffectIndex); } if (!effMask) @@ -2500,18 +2505,18 @@ void DynObjAura::FillTargetMap(std::unordered_map<Unit*, uint32>& targets, Unit* Unit* dynObjOwnerCaster = GetDynobjOwner()->GetCaster(); float radius = GetDynobjOwner()->GetRadius(); - for (SpellEffectInfo const* effect : GetSpellInfo()->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : GetSpellInfo()->GetEffects()) { - if (!effect || !HasEffect(effect->EffectIndex)) + if (!HasEffect(spellEffectInfo.EffectIndex)) continue; // we can't use effect type like area auras to determine check type, check targets - SpellTargetCheckTypes selectionType = effect->TargetA.GetCheckType(); - if (effect->TargetB.GetReferenceType() == TARGET_REFERENCE_TYPE_DEST) - selectionType = effect->TargetB.GetCheckType(); + SpellTargetCheckTypes selectionType = spellEffectInfo.TargetA.GetCheckType(); + if (spellEffectInfo.TargetB.GetReferenceType() == TARGET_REFERENCE_TYPE_DEST) + selectionType = spellEffectInfo.TargetB.GetCheckType(); std::vector<Unit*> units; - ConditionContainer* condList = effect->ImplicitTargetConditions; + ConditionContainer* condList = spellEffectInfo.ImplicitTargetConditions; Trinity::WorldObjectSpellAreaTargetCheck check(radius, GetDynobjOwner(), dynObjOwnerCaster, dynObjOwnerCaster, m_spellInfo, selectionType, condList, TARGET_OBJECT_TYPE_UNIT); Trinity::UnitListSearcher<Trinity::WorldObjectSpellAreaTargetCheck> searcher(GetDynobjOwner(), units, check); @@ -2521,6 +2526,6 @@ void DynObjAura::FillTargetMap(std::unordered_map<Unit*, uint32>& targets, Unit* units.erase(std::remove_if(units.begin(), units.end(), [this](Unit* unit) { return !unit->IsSelfOrInSameMap(GetDynobjOwner()); }), units.end()); for (Unit* unit : units) - targets[unit] |= 1 << effect->EffectIndex; + targets[unit] |= 1 << spellEffectInfo.EffectIndex; } } diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 66391ecbad2..45b53f6f93b 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -473,9 +473,8 @@ void SpellCastTargets::Update(WorldObject* caster) SpellValue::SpellValue(SpellInfo const* proto, WorldObject const* caster) { memset(EffectBasePoints, 0, sizeof(EffectBasePoints)); - for (SpellEffectInfo const* effect : proto->GetEffects()) - if (effect) - EffectBasePoints[effect->EffectIndex] = effect->CalcBaseValue(caster, nullptr, 0, -1); + for (SpellEffectInfo const& spellEffectInfo : proto->GetEffects()) + EffectBasePoints[spellEffectInfo.EffectIndex] = spellEffectInfo.CalcBaseValue(caster, nullptr, 0, -1); CustomBasePointsMask = 0; MaxAffectedTargets = proto->MaxAffectedTargets; @@ -735,35 +734,32 @@ void Spell::SelectSpellTargets() uint32 processedAreaEffectsMask = 0; - for (SpellEffectInfo const* effect : m_spellInfo->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) { - if (!effect) - continue; - // not call for empty effect. // Also some spells use not used effect targets for store targets for dummy effect in triggered spells - if (!effect->IsEffect()) + if (!spellEffectInfo.IsEffect()) continue; // set expected type of implicit targets to be sent to client - uint32 implicitTargetMask = GetTargetFlagMask(effect->TargetA.GetObjectType()) | GetTargetFlagMask(effect->TargetB.GetObjectType()); + uint32 implicitTargetMask = GetTargetFlagMask(spellEffectInfo.TargetA.GetObjectType()) | GetTargetFlagMask(spellEffectInfo.TargetB.GetObjectType()); if (implicitTargetMask & TARGET_FLAG_UNIT) m_targets.SetTargetFlag(TARGET_FLAG_UNIT); if (implicitTargetMask & (TARGET_FLAG_GAMEOBJECT | TARGET_FLAG_GAMEOBJECT_ITEM)) m_targets.SetTargetFlag(TARGET_FLAG_GAMEOBJECT); - SelectEffectImplicitTargets(SpellEffIndex(effect->EffectIndex), effect->TargetA, processedAreaEffectsMask); - SelectEffectImplicitTargets(SpellEffIndex(effect->EffectIndex), effect->TargetB, processedAreaEffectsMask); + SelectEffectImplicitTargets(spellEffectInfo, spellEffectInfo.TargetA, processedAreaEffectsMask); + SelectEffectImplicitTargets(spellEffectInfo, spellEffectInfo.TargetB, processedAreaEffectsMask); // Select targets of effect based on effect type // those are used when no valid target could be added for spell effect based on spell target type // some spell effects use explicit target as a default target added to target map (like SPELL_EFFECT_LEARN_SPELL) // some spell effects add target to target map only when target type specified (like SPELL_EFFECT_WEAPON) // some spell effects don't add anything to target map (confirmed with sniffs) (like SPELL_EFFECT_DESTROY_ALL_TOTEMS) - SelectEffectTypeImplicitTargets(effect->EffectIndex); + SelectEffectTypeImplicitTargets(spellEffectInfo); if (m_targets.HasDst()) - AddDestTarget(*m_targets.GetDst(), effect->EffectIndex); + AddDestTarget(*m_targets.GetDst(), spellEffectInfo.EffectIndex); if (m_spellInfo->IsChanneled()) { @@ -775,7 +771,7 @@ void Spell::SelectSpellTargets() return; } - uint32 mask = (1 << effect->EffectIndex); + uint32 mask = (1 << spellEffectInfo.EffectIndex); for (auto ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit) { if (ihit->EffectMask & mask) @@ -822,12 +818,12 @@ void Spell::RecalculateDelayMomentForDst() m_caster->m_Events.ModifyEventTime(_spellEvent, GetDelayStart() + m_delayMoment); } -void Spell::SelectEffectImplicitTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, uint32& processedEffectMask) +void Spell::SelectEffectImplicitTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType, uint32& processedEffectMask) { if (!targetType.GetTarget()) return; - uint32 effectMask = 1 << effIndex; + uint32 effectMask = 1 << spellEffectInfo.EffectIndex; // set the same target list for all effects // some spells appear to need this, however this requires more research switch (targetType.GetSelectionCategory()) @@ -836,30 +832,27 @@ void Spell::SelectEffectImplicitTargets(SpellEffIndex effIndex, SpellImplicitTar case TARGET_SELECT_CATEGORY_CONE: case TARGET_SELECT_CATEGORY_AREA: case TARGET_SELECT_CATEGORY_LINE: + { // targets for effect already selected if (effectMask & processedEffectMask) return; - if (SpellEffectInfo const* _effect = m_spellInfo->GetEffect(effIndex)) - { - // choose which targets we can select at once - for (SpellEffectInfo const* effect : m_spellInfo->GetEffects()) + std::vector<SpellEffectInfo> const& effects = GetSpellInfo()->GetEffects(); + // choose which targets we can select at once + for (uint32 j = spellEffectInfo.EffectIndex + 1; j < effects.size(); ++j) + { + if (effects[j].IsEffect() && + spellEffectInfo.TargetA.GetTarget() == effects[j].TargetA.GetTarget() && + spellEffectInfo.TargetB.GetTarget() == effects[j].TargetB.GetTarget() && + spellEffectInfo.ImplicitTargetConditions == effects[j].ImplicitTargetConditions && + spellEffectInfo.CalcRadius(m_caster) == effects[j].CalcRadius(m_caster) && + CheckScriptEffectImplicitTargets(spellEffectInfo.EffectIndex, j)) { - //for (uint32 j = effIndex + 1; j < MAX_SPELL_EFFECTS; ++j) - if (!effect || effect->EffectIndex <= uint32(effIndex)) - continue; - if (effect->IsEffect() && - _effect->TargetA.GetTarget() == effect->TargetA.GetTarget() && - _effect->TargetB.GetTarget() == effect->TargetB.GetTarget() && - _effect->ImplicitTargetConditions == effect->ImplicitTargetConditions && - _effect->CalcRadius(m_caster) == effect->CalcRadius(m_caster) && - CheckScriptEffectImplicitTargets(effIndex, effect->EffectIndex)) - { - effectMask |= 1 << effect->EffectIndex; - } + effectMask |= 1 << j; } } processedEffectMask |= effectMask; break; + } default: break; } @@ -867,25 +860,25 @@ void Spell::SelectEffectImplicitTargets(SpellEffIndex effIndex, SpellImplicitTar switch (targetType.GetSelectionCategory()) { case TARGET_SELECT_CATEGORY_CHANNEL: - SelectImplicitChannelTargets(effIndex, targetType); + SelectImplicitChannelTargets(spellEffectInfo, targetType); break; case TARGET_SELECT_CATEGORY_NEARBY: - SelectImplicitNearbyTargets(effIndex, targetType, effectMask); + SelectImplicitNearbyTargets(spellEffectInfo, targetType, effectMask); break; case TARGET_SELECT_CATEGORY_CONE: - SelectImplicitConeTargets(effIndex, targetType, effectMask); + SelectImplicitConeTargets(spellEffectInfo, targetType, effectMask); break; case TARGET_SELECT_CATEGORY_AREA: - SelectImplicitAreaTargets(effIndex, targetType, effectMask); + SelectImplicitAreaTargets(spellEffectInfo, targetType, effectMask); break; case TARGET_SELECT_CATEGORY_TRAJ: // just in case there is no dest, explanation in SelectImplicitDestDestTargets CheckDst(); - SelectImplicitTrajTargets(effIndex, targetType); + SelectImplicitTrajTargets(spellEffectInfo, targetType); break; case TARGET_SELECT_CATEGORY_LINE: - SelectImplicitLineTargets(effIndex, targetType, effectMask); + SelectImplicitLineTargets(spellEffectInfo, targetType, effectMask); break; case TARGET_SELECT_CATEGORY_DEFAULT: switch (targetType.GetObjectType()) @@ -905,13 +898,13 @@ void Spell::SelectEffectImplicitTargets(SpellEffIndex effIndex, SpellImplicitTar switch (targetType.GetReferenceType()) { case TARGET_REFERENCE_TYPE_CASTER: - SelectImplicitCasterDestTargets(effIndex, targetType); + SelectImplicitCasterDestTargets(spellEffectInfo, targetType); break; case TARGET_REFERENCE_TYPE_TARGET: - SelectImplicitTargetDestTargets(effIndex, targetType); + SelectImplicitTargetDestTargets(spellEffectInfo, targetType); break; case TARGET_REFERENCE_TYPE_DEST: - SelectImplicitDestDestTargets(effIndex, targetType); + SelectImplicitDestDestTargets(spellEffectInfo, targetType); break; default: ASSERT(false && "Spell::SelectEffectImplicitTargets: received not implemented select target reference type for TARGET_TYPE_OBJECT_DEST"); @@ -922,10 +915,10 @@ void Spell::SelectEffectImplicitTargets(SpellEffIndex effIndex, SpellImplicitTar switch (targetType.GetReferenceType()) { case TARGET_REFERENCE_TYPE_CASTER: - SelectImplicitCasterObjectTargets(effIndex, targetType); + SelectImplicitCasterObjectTargets(spellEffectInfo, targetType); break; case TARGET_REFERENCE_TYPE_TARGET: - SelectImplicitTargetObjectTargets(effIndex, targetType); + SelectImplicitTargetObjectTargets(spellEffectInfo, targetType); break; default: ASSERT(false && "Spell::SelectEffectImplicitTargets: received not implemented select target reference type for TARGET_TYPE_OBJECT"); @@ -935,7 +928,7 @@ void Spell::SelectEffectImplicitTargets(SpellEffIndex effIndex, SpellImplicitTar } break; case TARGET_SELECT_CATEGORY_NYI: - TC_LOG_DEBUG("spells", "SPELL: target type %u, found in spellID %u, effect %u is not implemented yet!", m_spellInfo->Id, effIndex, targetType.GetTarget()); + TC_LOG_DEBUG("spells", "SPELL: target type %u, found in spellID %u, effect %u is not implemented yet!", m_spellInfo->Id, uint32(spellEffectInfo.EffectIndex), targetType.GetTarget()); break; default: ASSERT(false && "Spell::SelectEffectImplicitTargets: received not implemented select target category"); @@ -943,7 +936,7 @@ void Spell::SelectEffectImplicitTargets(SpellEffIndex effIndex, SpellImplicitTar } } -void Spell::SelectImplicitChannelTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType) +void Spell::SelectImplicitChannelTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType) { if (targetType.GetReferenceType() != TARGET_REFERENCE_TYPE_CASTER) { @@ -954,7 +947,7 @@ void Spell::SelectImplicitChannelTargets(SpellEffIndex effIndex, SpellImplicitTa Spell* channeledSpell = m_originalCaster->GetCurrentSpell(CURRENT_CHANNELED_SPELL); if (!channeledSpell) { - TC_LOG_DEBUG("spells", "Spell::SelectImplicitChannelTargets: cannot find channel spell for spell ID %u, effect %u", m_spellInfo->Id, effIndex); + TC_LOG_DEBUG("spells", "Spell::SelectImplicitChannelTargets: cannot find channel spell for spell ID %u, effect %u", m_spellInfo->Id, uint32(spellEffectInfo.EffectIndex)); return; } switch (targetType.GetTarget()) @@ -964,13 +957,13 @@ void Spell::SelectImplicitChannelTargets(SpellEffIndex effIndex, SpellImplicitTa for (ObjectGuid const& channelTarget : m_originalCaster->m_unitData->ChannelObjects) { WorldObject* target = ObjectAccessor::GetUnit(*m_caster, channelTarget); - CallScriptObjectTargetSelectHandlers(target, effIndex, targetType); + CallScriptObjectTargetSelectHandlers(target, spellEffectInfo.EffectIndex, targetType); // unit target may be no longer avalible - teleported out of map for example Unit* unitTarget = target ? target->ToUnit() : nullptr; if (unitTarget) - AddUnitTarget(unitTarget, 1 << effIndex); + AddUnitTarget(unitTarget, 1 << spellEffectInfo.EffectIndex); else - TC_LOG_DEBUG("spells", "SPELL: cannot find channel spell target for spell ID %u, effect %u", m_spellInfo->Id, effIndex); + TC_LOG_DEBUG("spells", "SPELL: cannot find channel spell target for spell ID %u, effect %u", m_spellInfo->Id, uint32(spellEffectInfo.EffectIndex)); } break; } @@ -983,22 +976,22 @@ void Spell::SelectImplicitChannelTargets(SpellEffIndex effIndex, SpellImplicitTa WorldObject* target = !channelObjects.empty() ? ObjectAccessor::GetWorldObject(*m_caster, *channelObjects.begin()) : nullptr; if (target) { - CallScriptObjectTargetSelectHandlers(target, effIndex, targetType); + CallScriptObjectTargetSelectHandlers(target, spellEffectInfo.EffectIndex, targetType); if (target) { SpellDestination dest(*target); - CallScriptDestinationTargetSelectHandlers(dest, effIndex, targetType); + CallScriptDestinationTargetSelectHandlers(dest, spellEffectInfo.EffectIndex, targetType); m_targets.SetDst(dest); } } else - TC_LOG_DEBUG("spells", "SPELL: cannot find channel spell destination for spell ID %u, effect %u", m_spellInfo->Id, effIndex); + TC_LOG_DEBUG("spells", "SPELL: cannot find channel spell destination for spell ID %u, effect %u", m_spellInfo->Id, uint32(spellEffectInfo.EffectIndex)); } break; case TARGET_DEST_CHANNEL_CASTER: { SpellDestination dest(*channeledSpell->GetCaster()); - CallScriptDestinationTargetSelectHandlers(dest, effIndex, targetType); + CallScriptDestinationTargetSelectHandlers(dest, spellEffectInfo.EffectIndex, targetType); m_targets.SetDst(dest); break; } @@ -1008,7 +1001,7 @@ void Spell::SelectImplicitChannelTargets(SpellEffIndex effIndex, SpellImplicitTa } } -void Spell::SelectImplicitNearbyTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, uint32 effMask) +void Spell::SelectImplicitNearbyTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType, uint32 effMask) { if (targetType.GetReferenceType() != TARGET_REFERENCE_TYPE_CASTER) { @@ -1016,10 +1009,6 @@ void Spell::SelectImplicitNearbyTargets(SpellEffIndex effIndex, SpellImplicitTar return; } - SpellEffectInfo const* effect = m_spellInfo->GetEffect(effIndex); - if (!effect) - return; - float range = 0.0f; switch (targetType.GetCheckType()) { @@ -1041,12 +1030,12 @@ void Spell::SelectImplicitNearbyTargets(SpellEffIndex effIndex, SpellImplicitTar break; } - ConditionContainer* condList = effect->ImplicitTargetConditions; + ConditionContainer* condList = spellEffectInfo.ImplicitTargetConditions; // handle emergency case - try to use other provided targets if no conditions provided if (targetType.GetCheckType() == TARGET_CHECK_ENTRY && (!condList || condList->empty())) { - TC_LOG_DEBUG("spells", "Spell::SelectImplicitNearbyTargets: no conditions entry for target with TARGET_CHECK_ENTRY of spell ID %u, effect %u - selecting default targets", m_spellInfo->Id, effIndex); + TC_LOG_DEBUG("spells", "Spell::SelectImplicitNearbyTargets: no conditions entry for target with TARGET_CHECK_ENTRY of spell ID %u, effect %u - selecting default targets", m_spellInfo->Id, uint32(spellEffectInfo.EffectIndex)); switch (targetType.GetObjectType()) { case TARGET_OBJECT_TYPE_GOBJ: @@ -1068,7 +1057,7 @@ void Spell::SelectImplicitNearbyTargets(SpellEffIndex effIndex, SpellImplicitTar if (focusObject) { SpellDestination dest(*focusObject); - CallScriptDestinationTargetSelectHandlers(dest, effIndex, targetType); + CallScriptDestinationTargetSelectHandlers(dest, spellEffectInfo.EffectIndex, targetType); m_targets.SetDst(dest); } else @@ -1087,16 +1076,16 @@ void Spell::SelectImplicitNearbyTargets(SpellEffIndex effIndex, SpellImplicitTar WorldObject* target = SearchNearbyTarget(range, targetType.GetObjectType(), targetType.GetCheckType(), condList); if (!target) { - TC_LOG_DEBUG("spells", "Spell::SelectImplicitNearbyTargets: cannot find nearby target for spell ID %u, effect %u", m_spellInfo->Id, effIndex); + TC_LOG_DEBUG("spells", "Spell::SelectImplicitNearbyTargets: cannot find nearby target for spell ID %u, effect %u", m_spellInfo->Id, uint32(spellEffectInfo.EffectIndex)); SendCastResult(SPELL_FAILED_BAD_IMPLICIT_TARGETS); finish(false); return; } - CallScriptObjectTargetSelectHandlers(target, effIndex, targetType); + CallScriptObjectTargetSelectHandlers(target, spellEffectInfo.EffectIndex, targetType); if (!target) { - TC_LOG_DEBUG("spells", "Spell::SelectImplicitNearbyTargets: OnObjectTargetSelect script hook for spell Id %u set NULL target, effect %u", m_spellInfo->Id, effIndex); + TC_LOG_DEBUG("spells", "Spell::SelectImplicitNearbyTargets: OnObjectTargetSelect script hook for spell Id %u set NULL target, effect %u", m_spellInfo->Id, uint32(spellEffectInfo.EffectIndex)); SendCastResult(SPELL_FAILED_BAD_IMPLICIT_TARGETS); finish(false); return; @@ -1129,7 +1118,7 @@ void Spell::SelectImplicitNearbyTargets(SpellEffIndex effIndex, SpellImplicitTar case TARGET_OBJECT_TYPE_DEST: { SpellDestination dest(*target); - CallScriptDestinationTargetSelectHandlers(dest, effIndex, targetType); + CallScriptDestinationTargetSelectHandlers(dest, spellEffectInfo.EffectIndex, targetType); m_targets.SetDst(dest); break; } @@ -1138,10 +1127,10 @@ void Spell::SelectImplicitNearbyTargets(SpellEffIndex effIndex, SpellImplicitTar break; } - SelectImplicitChainTargets(effIndex, targetType, target, effMask); + SelectImplicitChainTargets(spellEffectInfo, targetType, target, effMask); } -void Spell::SelectImplicitConeTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, uint32 effMask) +void Spell::SelectImplicitConeTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType, uint32 effMask) { if (targetType.GetReferenceType() != TARGET_REFERENCE_TYPE_CASTER) { @@ -1151,12 +1140,8 @@ void Spell::SelectImplicitConeTargets(SpellEffIndex effIndex, SpellImplicitTarge std::list<WorldObject*> targets; SpellTargetObjectTypes objectType = targetType.GetObjectType(); SpellTargetCheckTypes selectionType = targetType.GetCheckType(); - SpellEffectInfo const* effect = m_spellInfo->GetEffect(effIndex); - if (!effect) - return; - - ConditionContainer* condList = effect->ImplicitTargetConditions; - float radius = effect->CalcRadius(m_caster) * m_spellValue->RadiusMod; + ConditionContainer* condList = spellEffectInfo.ImplicitTargetConditions; + float radius = spellEffectInfo.CalcRadius(m_caster) * m_spellValue->RadiusMod; if (uint32 containerTypeMask = GetSearcherTypeMask(objectType, condList)) { @@ -1164,7 +1149,7 @@ void Spell::SelectImplicitConeTargets(SpellEffIndex effIndex, SpellImplicitTarge Trinity::WorldObjectListSearcher<Trinity::WorldObjectSpellConeTargetCheck> searcher(m_caster, targets, check, containerTypeMask); SearchTargets<Trinity::WorldObjectListSearcher<Trinity::WorldObjectSpellConeTargetCheck> >(searcher, containerTypeMask, m_caster, m_caster, radius); - CallScriptObjectAreaTargetSelectHandlers(targets, effIndex, targetType); + CallScriptObjectAreaTargetSelectHandlers(targets, spellEffectInfo.EffectIndex, targetType); if (!targets.empty()) { @@ -1183,7 +1168,7 @@ void Spell::SelectImplicitConeTargets(SpellEffIndex effIndex, SpellImplicitTarge } } -void Spell::SelectImplicitAreaTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, uint32 effMask) +void Spell::SelectImplicitAreaTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType, uint32 effMask) { WorldObject* referer = nullptr; switch (targetType.GetReferenceType()) @@ -1201,7 +1186,7 @@ void Spell::SelectImplicitAreaTargets(SpellEffIndex effIndex, SpellImplicitTarge // find last added target for this effect for (auto ihit = m_UniqueTargetInfo.rbegin(); ihit != m_UniqueTargetInfo.rend(); ++ihit) { - if (ihit->EffectMask & (1 << effIndex)) + if (ihit->EffectMask & (1 << spellEffectInfo.EffectIndex)) { referer = ObjectAccessor::GetUnit(*m_caster, ihit->TargetGUID); break; @@ -1237,10 +1222,6 @@ void Spell::SelectImplicitAreaTargets(SpellEffIndex effIndex, SpellImplicitTarge } std::list<WorldObject*> targets; - SpellEffectInfo const* effect = m_spellInfo->GetEffect(effIndex); - if (!effect) - return; - switch (targetType.GetTarget()) { case TARGET_UNIT_TARGET_ALLY_OR_RAID: @@ -1250,7 +1231,7 @@ void Spell::SelectImplicitAreaTargets(SpellEffIndex effIndex, SpellImplicitTarge { targets.push_back(m_targets.GetUnitTarget()); - CallScriptObjectAreaTargetSelectHandlers(targets, effIndex, targetType); + CallScriptObjectAreaTargetSelectHandlers(targets, spellEffectInfo.EffectIndex, targetType); if (!targets.empty()) { @@ -1280,11 +1261,11 @@ void Spell::SelectImplicitAreaTargets(SpellEffIndex effIndex, SpellImplicitTarge break; } - float radius = effect->CalcRadius(m_caster) * m_spellValue->RadiusMod; + float radius = spellEffectInfo.CalcRadius(m_caster) * m_spellValue->RadiusMod; - SearchAreaTargets(targets, radius, center, referer, targetType.GetObjectType(), targetType.GetCheckType(), effect->ImplicitTargetConditions); + SearchAreaTargets(targets, radius, center, referer, targetType.GetObjectType(), targetType.GetCheckType(), spellEffectInfo.ImplicitTargetConditions); - CallScriptObjectAreaTargetSelectHandlers(targets, effIndex, targetType); + CallScriptObjectAreaTargetSelectHandlers(targets, spellEffectInfo.EffectIndex, targetType); if (!targets.empty()) { @@ -1302,7 +1283,7 @@ void Spell::SelectImplicitAreaTargets(SpellEffIndex effIndex, SpellImplicitTarge } } -void Spell::SelectImplicitCasterDestTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType) +void Spell::SelectImplicitCasterDestTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType) { SpellDestination dest(*m_caster); @@ -1315,7 +1296,7 @@ void Spell::SelectImplicitCasterDestTargets(SpellEffIndex effIndex, SpellImplici dest = SpellDestination(playerCaster->m_homebindX, playerCaster->m_homebindY, playerCaster->m_homebindZ, playerCaster->GetOrientation(), playerCaster->m_homebindMapId); break; case TARGET_DEST_DB: - if (SpellTargetPosition const* st = sSpellMgr->GetSpellTargetPosition(m_spellInfo->Id, effIndex)) + if (SpellTargetPosition const* st = sSpellMgr->GetSpellTargetPosition(m_spellInfo->Id, spellEffectInfo.EffectIndex)) { /// @todo fix this check if (m_spellInfo->HasEffect(SPELL_EFFECT_TELEPORT_UNITS) || m_spellInfo->HasEffect(SPELL_EFFECT_BIND)) @@ -1370,7 +1351,7 @@ void Spell::SelectImplicitCasterDestTargets(SpellEffIndex effIndex, SpellImplici if (!unitCaster) break; - float dist = m_spellInfo->GetEffect(effIndex)->CalcRadius(unitCaster); + float dist = spellEffectInfo.CalcRadius(unitCaster); float angle = targetType.CalcDirectionAngle(); Position pos = dest._position; @@ -1405,52 +1386,49 @@ void Spell::SelectImplicitCasterDestTargets(SpellEffIndex effIndex, SpellImplici break; default: { - if (SpellEffectInfo const* effect = m_spellInfo->GetEffect(effIndex)) - { - float dist = effect->CalcRadius(m_caster); - float angle = targetType.CalcDirectionAngle(); - float objSize = m_caster->GetCombatReach(); + float dist = spellEffectInfo.CalcRadius(m_caster); + float angle = targetType.CalcDirectionAngle(); + float objSize = m_caster->GetCombatReach(); - switch (targetType.GetTarget()) + switch (targetType.GetTarget()) + { + case TARGET_DEST_CASTER_SUMMON: + dist = PET_FOLLOW_DIST; + break; + case TARGET_DEST_CASTER_RANDOM: + if (dist > objSize) + dist = objSize + (dist - objSize) * float(rand_norm()); + break; + case TARGET_DEST_CASTER_FRONT_LEFT: + case TARGET_DEST_CASTER_BACK_LEFT: + case TARGET_DEST_CASTER_FRONT_RIGHT: + case TARGET_DEST_CASTER_BACK_RIGHT: { - case TARGET_DEST_CASTER_SUMMON: - dist = PET_FOLLOW_DIST; - break; - case TARGET_DEST_CASTER_RANDOM: - if (dist > objSize) - dist = objSize + (dist - objSize) * float(rand_norm()); - break; - case TARGET_DEST_CASTER_FRONT_LEFT: - case TARGET_DEST_CASTER_BACK_LEFT: - case TARGET_DEST_CASTER_FRONT_RIGHT: - case TARGET_DEST_CASTER_BACK_RIGHT: - { - static float const DefaultTotemDistance = 3.0f; - if (!effect->HasRadius() && !effect->HasMaxRadius()) - dist = DefaultTotemDistance; - break; - } - default: - break; + static float const DefaultTotemDistance = 3.0f; + if (!spellEffectInfo.HasRadius() && !spellEffectInfo.HasMaxRadius()) + dist = DefaultTotemDistance; + break; } + default: + break; + } - if (dist < objSize) - dist = objSize; + if (dist < objSize) + dist = objSize; - Position pos = dest._position; - m_caster->MovePositionToFirstCollision(pos, dist, angle); + Position pos = dest._position; + m_caster->MovePositionToFirstCollision(pos, dist, angle); - dest.Relocate(pos); - } + dest.Relocate(pos); break; } } - CallScriptDestinationTargetSelectHandlers(dest, effIndex, targetType); + CallScriptDestinationTargetSelectHandlers(dest, spellEffectInfo.EffectIndex, targetType); m_targets.SetDst(dest); } -void Spell::SelectImplicitTargetDestTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType) +void Spell::SelectImplicitTargetDestTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType) { ASSERT(m_targets.GetObjectTarget() && "Spell::SelectImplicitTargetDestTargets - no explicit object target available!"); WorldObject* target = m_targets.GetObjectTarget(); @@ -1465,27 +1443,24 @@ void Spell::SelectImplicitTargetDestTargets(SpellEffIndex effIndex, SpellImplici break; default: { - if (SpellEffectInfo const* effect = m_spellInfo->GetEffect(effIndex)) - { - float angle = targetType.CalcDirectionAngle(); - float dist = effect->CalcRadius(nullptr); - if (targetType.GetTarget() == TARGET_DEST_TARGET_RANDOM) - dist *= float(rand_norm()); + float angle = targetType.CalcDirectionAngle(); + float dist = spellEffectInfo.CalcRadius(nullptr); + if (targetType.GetTarget() == TARGET_DEST_TARGET_RANDOM) + dist *= float(rand_norm()); - Position pos = dest._position; - target->MovePositionToFirstCollision(pos, dist, angle); + Position pos = dest._position; + target->MovePositionToFirstCollision(pos, dist, angle); - dest.Relocate(pos); - } + dest.Relocate(pos); break; } } - CallScriptDestinationTargetSelectHandlers(dest, effIndex, targetType); + CallScriptDestinationTargetSelectHandlers(dest, spellEffectInfo.EffectIndex, targetType); m_targets.SetDst(dest); } -void Spell::SelectImplicitDestDestTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType) +void Spell::SelectImplicitDestDestTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType) { // set destination to caster if no dest provided // can only happen if previous destination target could not be set for some reason @@ -1504,27 +1479,24 @@ void Spell::SelectImplicitDestDestTargets(SpellEffIndex effIndex, SpellImplicitT return; default: { - if (SpellEffectInfo const* effect = m_spellInfo->GetEffect(effIndex)) - { - float angle = targetType.CalcDirectionAngle(); - float dist = effect->CalcRadius(m_caster); - if (targetType.GetTarget() == TARGET_DEST_DEST_RANDOM) - dist *= float(rand_norm()); + float angle = targetType.CalcDirectionAngle(); + float dist = spellEffectInfo.CalcRadius(m_caster); + if (targetType.GetTarget() == TARGET_DEST_DEST_RANDOM) + dist *= float(rand_norm()); - Position pos = dest._position; - m_caster->MovePositionToFirstCollision(pos, dist, angle); + Position pos = dest._position; + m_caster->MovePositionToFirstCollision(pos, dist, angle); - dest.Relocate(pos); - } + dest.Relocate(pos); break; } } - CallScriptDestinationTargetSelectHandlers(dest, effIndex, targetType); + CallScriptDestinationTargetSelectHandlers(dest, spellEffectInfo.EffectIndex, targetType); m_targets.ModDst(dest); } -void Spell::SelectImplicitCasterObjectTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType) +void Spell::SelectImplicitCasterObjectTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType) { WorldObject* target = nullptr; bool checkIfValid = true; @@ -1571,63 +1543,59 @@ void Spell::SelectImplicitCasterObjectTargets(SpellEffIndex effIndex, SpellImpli break; } - CallScriptObjectTargetSelectHandlers(target, effIndex, targetType); + CallScriptObjectTargetSelectHandlers(target, spellEffectInfo.EffectIndex, targetType); if (target) { if (Unit* unit = target->ToUnit()) - AddUnitTarget(unit, 1 << effIndex, checkIfValid); + AddUnitTarget(unit, 1 << spellEffectInfo.EffectIndex, checkIfValid); else if (GameObject* go = target->ToGameObject()) - AddGOTarget(go, 1 << effIndex); + AddGOTarget(go, 1 << spellEffectInfo.EffectIndex); } } -void Spell::SelectImplicitTargetObjectTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType) +void Spell::SelectImplicitTargetObjectTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType) { ASSERT((m_targets.GetObjectTarget() || m_targets.GetItemTarget()) && "Spell::SelectImplicitTargetObjectTargets - no explicit object or item target available!"); WorldObject* target = m_targets.GetObjectTarget(); - CallScriptObjectTargetSelectHandlers(target, effIndex, targetType); + CallScriptObjectTargetSelectHandlers(target, spellEffectInfo.EffectIndex, targetType); if (target) { if (Unit* unit = target->ToUnit()) - AddUnitTarget(unit, 1 << effIndex, true, false); + AddUnitTarget(unit, 1 << spellEffectInfo.EffectIndex, true, false); else if (GameObject* gobj = target->ToGameObject()) - AddGOTarget(gobj, 1 << effIndex); + AddGOTarget(gobj, 1 << spellEffectInfo.EffectIndex); - SelectImplicitChainTargets(effIndex, targetType, target, 1 << effIndex); + SelectImplicitChainTargets(spellEffectInfo, targetType, target, 1 << spellEffectInfo.EffectIndex); } // Script hook can remove object target and we would wrongly land here else if (Item* item = m_targets.GetItemTarget()) - AddItemTarget(item, 1 << effIndex); + AddItemTarget(item, 1 << spellEffectInfo.EffectIndex); } -void Spell::SelectImplicitChainTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, WorldObject* target, uint32 effMask) +void Spell::SelectImplicitChainTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType, WorldObject* target, uint32 effMask) { - SpellEffectInfo const* effect = m_spellInfo->GetEffect(effIndex); - if (!effect) - return; - - int32 maxTargets = effect->ChainTargets; + int32 maxTargets = spellEffectInfo.ChainTargets; if (Player* modOwner = m_caster->GetSpellModOwner()) modOwner->ApplySpellMod(m_spellInfo, SpellModOp::ChainTargets, maxTargets, this); if (maxTargets > 1) { // mark damage multipliers as used - for (SpellEffectInfo const* eff : m_spellInfo->GetEffects()) - if (eff && (effMask & (1 << eff->EffectIndex))) - m_damageMultipliers[eff->EffectIndex] = 1.0f; + for (size_t k = spellEffectInfo.EffectIndex; k < m_spellInfo->GetEffects().size(); ++k) + if (effMask & (1 << k)) + m_damageMultipliers[k] = 1.0f; m_applyMultiplierMask |= effMask; std::list<WorldObject*> targets; SearchChainTargets(targets, maxTargets - 1, target, targetType.GetObjectType(), targetType.GetCheckType() - , effect->ImplicitTargetConditions, targetType.GetTarget() == TARGET_UNIT_TARGET_CHAINHEAL_ALLY); + , spellEffectInfo.ImplicitTargetConditions, targetType.GetTarget() == TARGET_UNIT_TARGET_CHAINHEAL_ALLY); // Chain primary target is added earlier - CallScriptObjectAreaTargetSelectHandlers(targets, effIndex, targetType); + CallScriptObjectAreaTargetSelectHandlers(targets, spellEffectInfo.EffectIndex, targetType); for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end(); ++itr) if (Unit* unit = (*itr)->ToUnit()) @@ -1647,7 +1615,7 @@ float tangent(float x) return 0.0f; } -void Spell::SelectImplicitTrajTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType) +void Spell::SelectImplicitTrajTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType) { if (!m_targets.HasTraj()) return; @@ -1660,9 +1628,8 @@ void Spell::SelectImplicitTrajTargets(SpellEffIndex effIndex, SpellImplicitTarge srcPos.SetOrientation(m_caster->GetOrientation()); float srcToDestDelta = m_targets.GetDstPos()->m_positionZ - srcPos.m_positionZ; - SpellEffectInfo const* effect = m_spellInfo->GetEffect(effIndex); std::list<WorldObject*> targets; - Trinity::WorldObjectSpellTrajTargetCheck check(dist2d, &srcPos, m_caster, m_spellInfo, targetType.GetCheckType(), effect->ImplicitTargetConditions, TARGET_OBJECT_TYPE_NONE); + Trinity::WorldObjectSpellTrajTargetCheck check(dist2d, &srcPos, m_caster, m_spellInfo, targetType.GetCheckType(), spellEffectInfo.ImplicitTargetConditions, TARGET_OBJECT_TYPE_NONE); Trinity::WorldObjectListSearcher<Trinity::WorldObjectSpellTrajTargetCheck> searcher(m_caster, targets, check, GRID_MAP_TYPE_MASK_ALL); SearchTargets<Trinity::WorldObjectListSearcher<Trinity::WorldObjectSpellTrajTargetCheck> > (searcher, GRID_MAP_TYPE_MASK_ALL, m_caster, &srcPos, dist2d); if (targets.empty()) @@ -1678,7 +1645,7 @@ void Spell::SelectImplicitTrajTargets(SpellEffIndex effIndex, SpellImplicitTarge // We should check if triggered spell has greater range (which is true in many cases, and initial spell has too short max range) // limit max range to 300 yards, sometimes triggered spells can have 50000yds float bestDist = m_spellInfo->GetMaxRange(false); - if (SpellInfo const* triggerSpellInfo = sSpellMgr->GetSpellInfo(effect->TriggerSpell, GetCastDifficulty())) + if (SpellInfo const* triggerSpellInfo = sSpellMgr->GetSpellInfo(spellEffectInfo.TriggerSpell, GetCastDifficulty())) bestDist = std::min(std::max(bestDist, triggerSpellInfo->GetMaxRange(false)), std::min(dist2d, 300.0f)); // GameObjects don't cast traj @@ -1726,20 +1693,16 @@ void Spell::SelectImplicitTrajTargets(SpellEffIndex effIndex, SpellImplicitTarge float z = m_targets.GetSrcPos()->m_positionZ + bestDist * (a * bestDist + b); SpellDestination dest(x, y, z, unitCaster->GetOrientation()); - CallScriptDestinationTargetSelectHandlers(dest, effIndex, targetType); + CallScriptDestinationTargetSelectHandlers(dest, spellEffectInfo.EffectIndex, targetType); m_targets.ModDst(dest); } } -void Spell::SelectImplicitLineTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, uint32 effMask) +void Spell::SelectImplicitLineTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType, uint32 effMask) { std::list<WorldObject*> targets; SpellTargetObjectTypes objectType = targetType.GetObjectType(); SpellTargetCheckTypes selectionType = targetType.GetCheckType(); - SpellEffectInfo const* effect = m_spellInfo->GetEffect(effIndex); - if (!effect) - return; - Position const* dst = nullptr; switch (targetType.GetReferenceType()) { @@ -1760,8 +1723,8 @@ void Spell::SelectImplicitLineTargets(SpellEffIndex effIndex, SpellImplicitTarge return; } - ConditionContainer* condList = effect->ImplicitTargetConditions; - float radius = effect->CalcRadius(m_caster) * m_spellValue->RadiusMod; + ConditionContainer* condList = spellEffectInfo.ImplicitTargetConditions; + float radius = spellEffectInfo.CalcRadius(m_caster) * m_spellValue->RadiusMod; if (uint32 containerTypeMask = GetSearcherTypeMask(objectType, condList)) { @@ -1769,7 +1732,7 @@ void Spell::SelectImplicitLineTargets(SpellEffIndex effIndex, SpellImplicitTarge Trinity::WorldObjectListSearcher<Trinity::WorldObjectSpellLineTargetCheck> searcher(m_caster, targets, check, containerTypeMask); SearchTargets<Trinity::WorldObjectListSearcher<Trinity::WorldObjectSpellLineTargetCheck>>(searcher, containerTypeMask, m_caster, m_caster, radius); - CallScriptObjectAreaTargetSelectHandlers(targets, effIndex, targetType); + CallScriptObjectAreaTargetSelectHandlers(targets, spellEffectInfo.EffectIndex, targetType); if (!targets.empty()) { @@ -1794,20 +1757,17 @@ void Spell::SelectImplicitLineTargets(SpellEffIndex effIndex, SpellImplicitTarge } } -void Spell::SelectEffectTypeImplicitTargets(uint32 effIndex) +void Spell::SelectEffectTypeImplicitTargets(SpellEffectInfo const& spellEffectInfo) { // special case for SPELL_EFFECT_SUMMON_RAF_FRIEND and SPELL_EFFECT_SUMMON_PLAYER, queue them on map for later execution - SpellEffectInfo const* effect = m_spellInfo->GetEffect(effIndex); - if (!effect) - return; - switch (effect->Effect) + switch (spellEffectInfo.Effect) { case SPELL_EFFECT_SUMMON_RAF_FRIEND: case SPELL_EFFECT_SUMMON_PLAYER: if (m_caster->GetTypeId() == TYPEID_PLAYER && !m_caster->ToPlayer()->GetTarget().IsEmpty()) { WorldObject* target = ObjectAccessor::FindPlayer(m_caster->ToPlayer()->GetTarget()); - CallScriptObjectTargetSelectHandlers(target, SpellEffIndex(effIndex), SpellImplicitTargetInfo()); + CallScriptObjectTargetSelectHandlers(target, spellEffectInfo.EffectIndex, SpellImplicitTargetInfo()); // scripts may modify the target - recheck if (target && target->GetTypeId() == TYPEID_PLAYER) @@ -1816,21 +1776,21 @@ void Spell::SelectEffectTypeImplicitTargets(uint32 effIndex) // since we're completely skipping AddUnitTarget logic, we need to check immunity manually // eg. aura 21546 makes target immune to summons Player* player = target->ToPlayer(); - if (player->IsImmunedToSpellEffect(m_spellInfo, effIndex, nullptr)) + if (player->IsImmunedToSpellEffect(m_spellInfo, spellEffectInfo, nullptr)) return; - target->GetMap()->AddFarSpellCallback(std::bind([](Map* map, Spell* spell, uint8 effIndex, ObjectGuid const& targetGuid) + target->GetMap()->AddFarSpellCallback([spell = this, &spellEffectInfo, targetGuid = target->GetGUID()](Map* map) { Player* player = ObjectAccessor::GetPlayer(map, targetGuid); if (!player) return; // check immunity again in case it changed during update - if (player->IsImmunedToSpellEffect(spell->GetSpellInfo(), effIndex, nullptr)) + if (player->IsImmunedToSpellEffect(spell->GetSpellInfo(), spellEffectInfo, nullptr)) return; - spell->HandleEffects(player, nullptr, nullptr, effIndex, SPELL_EFFECT_HANDLE_HIT_TARGET); - }, std::placeholders::_1, this, effIndex, target->GetGUID())); + spell->HandleEffects(player, nullptr, nullptr, spellEffectInfo, SPELL_EFFECT_HANDLE_HIT_TARGET); + }); } } return; @@ -1839,17 +1799,17 @@ void Spell::SelectEffectTypeImplicitTargets(uint32 effIndex) } // select spell implicit targets based on effect type - if (!effect->GetImplicitTargetType()) + if (!spellEffectInfo.GetImplicitTargetType()) return; - uint32 targetMask = effect->GetMissingTargetMask(); + uint32 targetMask = spellEffectInfo.GetMissingTargetMask(); if (!targetMask) return; WorldObject* target = nullptr; - switch (effect->GetImplicitTargetType()) + switch (spellEffectInfo.GetImplicitTargetType()) { // add explicit object target or self to the target map case EFFECT_IMPLICIT_TARGET_EXPLICIT: @@ -1873,7 +1833,7 @@ void Spell::SelectEffectTypeImplicitTargets(uint32 effIndex) if (targetMask & TARGET_FLAG_ITEM_MASK) { if (Item* item = m_targets.GetItemTarget()) - AddItemTarget(item, 1 << effIndex); + AddItemTarget(item, 1 << spellEffectInfo.EffectIndex); return; } if (targetMask & TARGET_FLAG_GAMEOBJECT_MASK) @@ -1888,14 +1848,14 @@ void Spell::SelectEffectTypeImplicitTargets(uint32 effIndex) break; } - CallScriptObjectTargetSelectHandlers(target, SpellEffIndex(effIndex), SpellImplicitTargetInfo()); + CallScriptObjectTargetSelectHandlers(target, spellEffectInfo.EffectIndex, SpellImplicitTargetInfo()); if (target) { if (target->ToUnit()) - AddUnitTarget(target->ToUnit(), 1 << effIndex, false); + AddUnitTarget(target->ToUnit(), 1 << spellEffectInfo.EffectIndex, false); else if (target->ToGameObject()) - AddGOTarget(target->ToGameObject(), 1 << effIndex); + AddGOTarget(target->ToGameObject(), 1 << spellEffectInfo.EffectIndex); } } @@ -2193,12 +2153,9 @@ class ProcReflectDelayed : public BasicEvent void Spell::AddUnitTarget(Unit* target, uint32 effectMask, bool checkIfValid /*= true*/, bool implicit /*= true*/, Position const* losPosition /*= nullptr*/) { - uint32 validEffectMask = 0; - for (SpellEffectInfo const* effect : m_spellInfo->GetEffects()) - if (effect && (effectMask & (1 << effect->EffectIndex)) != 0 && CheckEffectTarget(target, effect, losPosition)) - validEffectMask |= 1 << effect->EffectIndex; - - effectMask &= validEffectMask; + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) + if (!spellEffectInfo.IsEffect() || !CheckEffectTarget(target, spellEffectInfo, losPosition)) + effectMask &= ~(1 << spellEffectInfo.EffectIndex); // no effects left if (!effectMask) @@ -2209,9 +2166,9 @@ void Spell::AddUnitTarget(Unit* target, uint32 effectMask, bool checkIfValid /*= return; // Check for effect immune skip if immuned - for (SpellEffectInfo const* effect : m_spellInfo->GetEffects()) - if (effect && target->IsImmunedToSpellEffect(m_spellInfo, effect->EffectIndex, m_caster)) - effectMask &= ~(1 << effect->EffectIndex); + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) + if (target->IsImmunedToSpellEffect(m_spellInfo, spellEffectInfo, m_caster)) + effectMask &= ~(1 << spellEffectInfo.EffectIndex); ObjectGuid targetGUID = target->GetGUID(); @@ -2285,12 +2242,9 @@ void Spell::AddUnitTarget(Unit* target, uint32 effectMask, bool checkIfValid /*= void Spell::AddGOTarget(GameObject* go, uint32 effectMask) { - uint32 validEffectMask = 0; - for (SpellEffectInfo const* effect : m_spellInfo->GetEffects()) - if (effect && (effectMask & (1 << effect->EffectIndex)) != 0 && CheckEffectTarget(go, effect)) - validEffectMask |= 1 << effect->EffectIndex; - - effectMask &= validEffectMask; + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) + if (!spellEffectInfo.IsEffect() || !CheckEffectTarget(go, spellEffectInfo)) + effectMask &= ~(1 << spellEffectInfo.EffectIndex); // no effects left if (!effectMask) @@ -2341,12 +2295,9 @@ void Spell::AddGOTarget(GameObject* go, uint32 effectMask) void Spell::AddItemTarget(Item* item, uint32 effectMask) { - uint32 validEffectMask = 0; - for (SpellEffectInfo const* effect : m_spellInfo->GetEffects()) - if (effect && (effectMask & (1 << effect->EffectIndex)) != 0 && CheckEffectTarget(item, effect)) - validEffectMask |= 1 << effect->EffectIndex; - - effectMask &= validEffectMask; + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) + if (!spellEffectInfo.IsEffect() || !CheckEffectTarget(item, spellEffectInfo)) + effectMask &= ~(1 << spellEffectInfo.EffectIndex); // no effects left if (!effectMask) @@ -2442,7 +2393,7 @@ void Spell::TargetInfo::PreprocessTarget(Spell* spell) Healing = spell->m_healing; } -void Spell::TargetInfo::DoTargetSpellHit(Spell* spell, uint8 effIndex) +void Spell::TargetInfo::DoTargetSpellHit(Spell* spell, SpellEffectInfo const& spellEffectInfo) { Unit* unit = spell->m_caster->GetGUID() == TargetGUID ? spell->m_caster->ToUnit() : ObjectAccessor::GetUnit(*spell->m_caster, TargetGUID); if (!unit) @@ -2464,7 +2415,7 @@ void Spell::TargetInfo::DoTargetSpellHit(Spell* spell, uint8 effIndex) return; // No missinfo in that case if (_spellHitTarget) - spell->DoSpellEffectHit(_spellHitTarget, effIndex, *this); + spell->DoSpellEffectHit(_spellHitTarget, spellEffectInfo, *this); // scripts can modify damage/healing for current target, save them Damage = spell->m_damage; @@ -2510,7 +2461,7 @@ void Spell::TargetInfo::DoDamageAndTriggers(Spell* spell) positive = false; else if (!spell->m_healing) { - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (uint8 i = 0; i < spell->m_spellInfo->GetEffects().size(); ++i) { // in case of immunity, check all effects to choose correct procFlags, as none has technically hit if (EffectMask && !(EffectMask & (1 << i))) @@ -2704,7 +2655,7 @@ void Spell::TargetInfo::DoDamageAndTriggers(Spell* spell) spell->CallScriptAfterHitHandlers(); } -void Spell::GOTargetInfo::DoTargetSpellHit(Spell* spell, uint8 effIndex) +void Spell::GOTargetInfo::DoTargetSpellHit(Spell* spell, SpellEffectInfo const& spellEffectInfo) { GameObject* go = spell->m_caster->GetGUID() == TargetGUID ? spell->m_caster->ToGameObject() : ObjectAccessor::GetGameObject(*spell->m_caster, TargetGUID); if (!go) @@ -2712,7 +2663,7 @@ void Spell::GOTargetInfo::DoTargetSpellHit(Spell* spell, uint8 effIndex) spell->CallScriptBeforeHitHandlers(SPELL_MISS_NONE); - spell->HandleEffects(nullptr, nullptr, go, effIndex, SPELL_EFFECT_HANDLE_HIT_TARGET); + spell->HandleEffects(nullptr, nullptr, go, spellEffectInfo, SPELL_EFFECT_HANDLE_HIT_TARGET); //AI functions if (go->AI()) @@ -2732,11 +2683,11 @@ void Spell::GOTargetInfo::DoTargetSpellHit(Spell* spell, uint8 effIndex) spell->CallScriptAfterHitHandlers(); } -void Spell::ItemTargetInfo::DoTargetSpellHit(Spell* spell, uint8 effIndex) +void Spell::ItemTargetInfo::DoTargetSpellHit(Spell* spell, SpellEffectInfo const& spellEffectInfo) { spell->CallScriptBeforeHitHandlers(SPELL_MISS_NONE); - spell->HandleEffects(nullptr, TargetItem, nullptr, effIndex, SPELL_EFFECT_HANDLE_HIT_TARGET); + spell->HandleEffects(nullptr, TargetItem, nullptr, spellEffectInfo, SPELL_EFFECT_HANDLE_HIT_TARGET); spell->CallScriptOnHitHandlers(); spell->CallScriptAfterHitHandlers(); @@ -2812,11 +2763,10 @@ SpellMissInfo Spell::PreprocessSpellHit(Unit* unit, TargetInfo& hitInfo) // check immunity due to diminishing returns if (Aura::BuildEffectMaskForOwner(m_spellInfo, MAX_EFFECT_MASK, unit)) { - for (SpellEffectInfo const* auraSpellEffect : m_spellInfo->GetEffects()) - if (auraSpellEffect) - hitInfo.AuraBasePoints[auraSpellEffect->EffectIndex] = (m_spellValue->CustomBasePointsMask & (1 << auraSpellEffect->EffectIndex)) ? - m_spellValue->EffectBasePoints[auraSpellEffect->EffectIndex] : - auraSpellEffect->CalcBaseValue(m_originalCaster, unit, m_castItemEntry, m_castItemLevel); + for (SpellEffectInfo const& auraSpellEffect : m_spellInfo->GetEffects()) + hitInfo.AuraBasePoints[auraSpellEffect.EffectIndex] = (m_spellValue->CustomBasePointsMask & (1 << auraSpellEffect.EffectIndex)) + ? m_spellValue->EffectBasePoints[auraSpellEffect.EffectIndex] + : auraSpellEffect.CalcBaseValue(m_originalCaster, unit, m_castItemEntry, m_castItemLevel); // Get Data Needed for Diminishing Returns, some effects may have multiple auras, so this must be done on spell hit, not aura add hitInfo.DRGroup = m_spellInfo->GetDiminishingReturnsGroupForSpell(); @@ -2836,13 +2786,12 @@ SpellMissInfo Spell::PreprocessSpellHit(Unit* unit, TargetInfo& hitInfo) hitInfo.Positive = true; if (origCaster == unit || !origCaster->IsFriendlyTo(unit)) { - for (SpellEffectInfo const* effect : m_spellInfo->GetEffects()) + for (SpellEffectInfo const& auraSpellEffect : m_spellInfo->GetEffects()) { // mod duration only for effects applying aura! - if (effect && - hitInfo.EffectMask & (1 << effect->EffectIndex) && - effect->IsUnitOwnedAuraEffect() && - !m_spellInfo->IsPositiveEffect(effect->EffectIndex)) + if (hitInfo.EffectMask & (1 << auraSpellEffect.EffectIndex) && + auraSpellEffect.IsUnitOwnedAuraEffect() && + !m_spellInfo->IsPositiveEffect(auraSpellEffect.EffectIndex)) { hitInfo.Positive = false; break; @@ -2854,16 +2803,16 @@ SpellMissInfo Spell::PreprocessSpellHit(Unit* unit, TargetInfo& hitInfo) // unit is immune to aura if it was diminished to 0 duration if (!hitInfo.Positive && !unit->ApplyDiminishingToDuration(m_spellInfo, hitInfo.AuraDuration, origCaster, diminishLevel)) - if (std::all_of(std::begin(m_spellInfo->GetEffects()), std::end(m_spellInfo->GetEffects()), [](SpellEffectInfo const* effInfo) { return !effInfo || !effInfo->IsEffect() || effInfo->IsEffect(SPELL_EFFECT_APPLY_AURA); })) + if (std::all_of(std::begin(m_spellInfo->GetEffects()), std::end(m_spellInfo->GetEffects()), [](SpellEffectInfo const& effInfo) { return !effInfo.IsEffect() || effInfo.Effect == SPELL_EFFECT_APPLY_AURA; })) return SPELL_MISS_IMMUNE; } return SPELL_MISS_NONE; } -void Spell::DoSpellEffectHit(Unit* unit, uint8 effIndex, TargetInfo& hitInfo) +void Spell::DoSpellEffectHit(Unit* unit, SpellEffectInfo const& spellEffectInfo, TargetInfo& hitInfo) { - if (uint32 aura_effmask = Aura::BuildEffectMaskForOwner(m_spellInfo, 1 << effIndex, unit)) + if (uint32 aura_effmask = Aura::BuildEffectMaskForOwner(m_spellInfo, 1 << spellEffectInfo.EffectIndex, unit)) { WorldObject* caster = m_caster; if (m_originalCaster) @@ -2919,11 +2868,10 @@ void Spell::DoSpellEffectHit(Unit* unit, uint8 effIndex, TargetInfo& hitInfo) { int32 origDuration = hitInfo.AuraDuration; hitInfo.AuraDuration = 0; - for (SpellEffectInfo const* effect : m_spellInfo->GetEffects()) - if (effect) - if (AuraEffect const* eff = _spellAura->GetEffect(effect->EffectIndex)) - if (int32 period = eff->GetPeriod()) // period is hastened by UNIT_MOD_CAST_SPEED - hitInfo.AuraDuration = std::max(std::max(origDuration / period, 1) * period, hitInfo.AuraDuration); + for (AuraEffect const* auraEff : _spellAura->GetAuraEffects()) + if (auraEff) + if (int32 period = auraEff->GetPeriod()) // period is hastened by UNIT_MOD_CAST_SPEED + hitInfo.AuraDuration = std::max(std::max(origDuration / period, 1) * period, hitInfo.AuraDuration); // if there is no periodic effect if (!hitInfo.AuraDuration) @@ -2940,7 +2888,7 @@ void Spell::DoSpellEffectHit(Unit* unit, uint8 effIndex, TargetInfo& hitInfo) } } - HandleEffects(unit, nullptr, nullptr, effIndex, SPELL_EFFECT_HANDLE_HIT_TARGET); + HandleEffects(unit, nullptr, nullptr, spellEffectInfo, SPELL_EFFECT_HANDLE_HIT_TARGET); } void Spell::DoTriggersOnSpellHit(Unit* unit, uint32 effMask) @@ -3000,9 +2948,9 @@ bool Spell::UpdateChanneledTargetList() uint32 channelTargetEffectMask = m_channelTargetEffectMask; uint32 channelAuraMask = 0; - for (SpellEffectInfo const* effect : m_spellInfo->GetEffects()) - if (effect && effect->Effect == SPELL_EFFECT_APPLY_AURA) - channelAuraMask |= 1 << effect->EffectIndex; + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) + if (spellEffectInfo.IsEffect(SPELL_EFFECT_APPLY_AURA)) + channelAuraMask |= 1 << spellEffectInfo.EffectIndex; channelAuraMask &= channelTargetEffectMask; @@ -3397,9 +3345,9 @@ void Spell::_cast(bool skipCheck) if (Unit* target = m_targets.GetUnitTarget()) { uint32 aura_effmask = 0; - for (SpellEffectInfo const* effect : m_spellInfo->GetEffects()) - if (effect && effect->IsUnitOwnedAuraEffect()) - aura_effmask |= 1 << effect->EffectIndex; + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) + if (spellEffectInfo.IsUnitOwnedAuraEffect()) + aura_effmask |= 1 << spellEffectInfo.EffectIndex; if (aura_effmask) { @@ -3586,10 +3534,10 @@ void Spell::DoProcessTargetContainer(Container& targetContainer) for (TargetInfoBase& target : targetContainer) target.PreprocessTarget(this); - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) for (TargetInfoBase& target : targetContainer) - if (target.EffectMask & (1 << i)) - target.DoTargetSpellHit(this, i); + if (target.EffectMask & (1 << spellEffectInfo.EffectIndex)) + target.DoTargetSpellHit(this, spellEffectInfo); for (TargetInfoBase& target : targetContainer) target.DoDamageAndTriggers(this); @@ -3771,14 +3719,14 @@ void Spell::_handle_immediate_phase() HandleThreatSpells(); // handle effects with SPELL_EFFECT_HANDLE_HIT mode - for (SpellEffectInfo const* effect : m_spellInfo->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) { // don't do anything for empty effect - if (!effect || !effect->IsEffect()) + if (!spellEffectInfo.IsEffect()) continue; // call effect handlers to handle destination hit - HandleEffects(nullptr, nullptr, nullptr, effect->EffectIndex, SPELL_EFFECT_HANDLE_HIT); + HandleEffects(nullptr, nullptr, nullptr, spellEffectInfo, SPELL_EFFECT_HANDLE_HIT); } // process items @@ -3852,10 +3800,9 @@ void Spell::update(uint32 difftime) // check if the player caster has moved before the spell finished // with the exception of spells affected with SPELL_AURA_CAST_WHILE_WALKING effect - SpellEffectInfo const* effect = m_spellInfo->GetEffect(EFFECT_0); if ((m_caster->GetTypeId() == TYPEID_PLAYER && m_timer != 0) && m_caster->ToPlayer()->isMoving() && (m_spellInfo->InterruptFlags.HasFlag(SpellInterruptFlags::Movement)) && - ((effect && effect->Effect != SPELL_EFFECT_STUCK) || !m_caster->ToPlayer()->HasUnitMovementFlag(MOVEMENTFLAG_FALLING_FAR)) && + (!m_spellInfo->HasEffect(SPELL_EFFECT_STUCK) || !m_caster->ToPlayer()->HasUnitMovementFlag(MOVEMENTFLAG_FALLING_FAR)) && !m_caster->ToPlayer()->HasAuraTypeWithAffectMask(SPELL_AURA_CAST_WHILE_WALKING, m_spellInfo)) { // don't cancel for melee, autorepeat, triggered and instant spells @@ -4091,9 +4038,15 @@ inline void FillSpellCastFailedArgs(T& packet, ObjectGuid castId, SpellInfo cons else { uint32 item = 0; - for (SpellEffectInfo const* effect : spellInfo->GetEffects()) - if (effect->ItemType) - item = effect->ItemType; + for (SpellEffectInfo const& spellEffectInfo : spellInfo->GetEffects()) + { + if (uint32 itemType = spellEffectInfo.ItemType) + { + item = itemType; + break; + } + } + ItemTemplate const* proto = sObjectMgr->GetItemTemplate(item); if (proto && proto->GetItemLimitCategory()) packet.FailedArg1 = proto->GetItemLimitCategory(); @@ -4755,9 +4708,9 @@ void Spell::SendChannelStart(uint32 duration) explicitTargetEffectMask = explicitTargetItr->EffectMask; } - for (SpellEffectInfo const* effect : m_spellInfo->GetEffects()) - if (effect && effect->Effect == SPELL_EFFECT_APPLY_AURA && (explicitTargetEffectMask & (1u << effect->EffectIndex))) - channelAuraMask |= 1 << effect->EffectIndex; + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) + if (spellEffectInfo.IsEffect(SPELL_EFFECT_APPLY_AURA) && (explicitTargetEffectMask & (1u << spellEffectInfo.EffectIndex))) + channelAuraMask |= 1 << spellEffectInfo.EffectIndex; for (TargetInfo const& target : m_UniqueTargetInfo) { @@ -5093,30 +5046,22 @@ void Spell::HandleThreatSpells() TC_LOG_DEBUG("spells", "Spell %u, added an additional %f threat for %s %u target(s)", m_spellInfo->Id, threat, IsPositive() ? "assisting" : "harming", uint32(m_UniqueTargetInfo.size())); } -void Spell::HandleEffects(Unit* pUnitTarget, Item* pItemTarget, GameObject* pGOTarget, uint32 i, SpellEffectHandleMode mode) +void Spell::HandleEffects(Unit* pUnitTarget, Item* pItemTarget, GameObject* pGOTarget, SpellEffectInfo const& spellEffectInfo, SpellEffectHandleMode mode) { effectHandleMode = mode; unitTarget = pUnitTarget; itemTarget = pItemTarget; gameObjTarget = pGOTarget; - destTarget = &m_destTargets[i]._position; + destTarget = &m_destTargets[spellEffectInfo.EffectIndex]._position; + effectInfo = &spellEffectInfo; unitCaster = m_originalCaster ? m_originalCaster : m_caster->ToUnit(); - effectInfo = m_spellInfo->GetEffect(i); - if (!effectInfo) - { - TC_LOG_ERROR("spells", "Spell: %u HandleEffects at EffectIndex: %u missing effect", m_spellInfo->Id, i); - return; - } - uint32 effect = effectInfo->Effect; - - damage = CalculateDamage(i, unitTarget, &variance); + damage = CalculateDamage(spellEffectInfo, unitTarget, &variance); - SpellEffIndex effIndex = static_cast<SpellEffIndex>(i); - bool preventDefault = CallScriptEffectHandlers(effIndex, mode); + bool preventDefault = CallScriptEffectHandlers(spellEffectInfo.EffectIndex, mode); if (!preventDefault) - (this->*SpellEffectHandlers[effect].Value)(); + (this->*SpellEffectHandlers[spellEffectInfo.Effect].Value)(); } /*static*/ Spell const* Spell::ExtractSpellFromEvent(BasicEvent* event) @@ -5278,8 +5223,7 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint if (unitCaster->GetTypeId() == TYPEID_PLAYER && unitCaster->ToPlayer()->isMoving() && (!unitCaster->IsCharmed() || !unitCaster->GetCharmerGUID().IsCreature()) && !unitCaster->HasAuraTypeWithAffectMask(SPELL_AURA_CAST_WHILE_WALKING, m_spellInfo)) { // skip stuck spell to allow use it in falling case and apply spell limitations at movement - SpellEffectInfo const* effect = m_spellInfo->GetEffect(EFFECT_0); - if ((!unitCaster->HasUnitMovementFlag(MOVEMENTFLAG_FALLING_FAR) || (effect && effect->Effect != SPELL_EFFECT_STUCK)) && + if ((!unitCaster->HasUnitMovementFlag(MOVEMENTFLAG_FALLING_FAR) || !m_spellInfo->HasEffect(SPELL_EFFECT_STUCK)) && (IsAutoRepeat() || m_spellInfo->HasAuraInterruptFlag(SpellAuraInterruptFlags::Standing))) return SPELL_FAILED_MOVING; } @@ -5386,9 +5330,9 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint // check pet presence if (Unit* unitCaster = m_caster->ToUnit()) { - for (SpellEffectInfo const* effect : m_spellInfo->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) { - if (effect && effect->TargetA.GetTarget() == TARGET_UNIT_PET) + if (spellEffectInfo.TargetA.GetTarget() == TARGET_UNIT_PET) { if (!unitCaster->GetGuardianPet()) { @@ -5485,12 +5429,10 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint if (castResult != SPELL_CAST_OK) return castResult; - for (SpellEffectInfo const* effect : m_spellInfo->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) { - if (!effect) - continue; // for effects of spells that have only one target - switch (effect->Effect) + switch (spellEffectInfo.Effect) { case SPELL_EFFECT_DUMMY: { @@ -5514,14 +5456,14 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint } case SPELL_EFFECT_LEARN_SPELL: { - if (effect->TargetA.GetTarget() != TARGET_UNIT_PET) + if (spellEffectInfo.TargetA.GetTarget() != TARGET_UNIT_PET) break; Pet* pet = m_caster->ToPlayer()->GetPet(); if (!pet) return SPELL_FAILED_NO_PET; - SpellInfo const* learn_spellproto = sSpellMgr->GetSpellInfo(effect->TriggerSpell, DIFFICULTY_NONE); + SpellInfo const* learn_spellproto = sSpellMgr->GetSpellInfo(spellEffectInfo.TriggerSpell, DIFFICULTY_NONE); if (!learn_spellproto) return SPELL_FAILED_NOT_KNOWN; @@ -5551,7 +5493,7 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint if (!pet || pet->GetOwner() != m_caster) return SPELL_FAILED_BAD_TARGETS; - SpellInfo const* learn_spellproto = sSpellMgr->GetSpellInfo(effect->TriggerSpell, DIFFICULTY_NONE); + SpellInfo const* learn_spellproto = sSpellMgr->GetSpellInfo(spellEffectInfo.TriggerSpell, DIFFICULTY_NONE); if (!learn_spellproto) return SPELL_FAILED_NOT_KNOWN; @@ -5570,7 +5512,7 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint if (!caster->HasSpell(m_misc.SpellId)) return SPELL_FAILED_NOT_KNOWN; - if (uint32 glyphId = effect->MiscValue) + if (uint32 glyphId = spellEffectInfo.MiscValue) { GlyphPropertiesEntry const* glyphProperties = sGlyphPropertiesStore.LookupEntry(glyphId); if (!glyphProperties) @@ -5713,13 +5655,13 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint } case SPELL_EFFECT_OPEN_LOCK: { - if (effect->TargetA.GetTarget() != TARGET_GAMEOBJECT_TARGET && - effect->TargetA.GetTarget() != TARGET_GAMEOBJECT_ITEM_TARGET) + if (spellEffectInfo.TargetA.GetTarget() != TARGET_GAMEOBJECT_TARGET && + spellEffectInfo.TargetA.GetTarget() != TARGET_GAMEOBJECT_ITEM_TARGET) break; if (m_caster->GetTypeId() != TYPEID_PLAYER // only players can open locks, gather etc. // we need a go target in case of TARGET_GAMEOBJECT_TARGET - || (effect->TargetA.GetTarget() == TARGET_GAMEOBJECT_TARGET && !m_targets.GetGOTarget())) + || (spellEffectInfo.TargetA.GetTarget() == TARGET_GAMEOBJECT_TARGET && !m_targets.GetGOTarget())) return SPELL_FAILED_BAD_TARGETS; Item* pTempItem = nullptr; @@ -5732,7 +5674,7 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint pTempItem = m_caster->ToPlayer()->GetItemByGuid(m_targets.GetItemTargetGUID()); // we need a go target, or an openable item target in case of TARGET_GAMEOBJECT_ITEM_TARGET - if (effect->TargetA.GetTarget() == TARGET_GAMEOBJECT_ITEM_TARGET && + if (spellEffectInfo.TargetA.GetTarget() == TARGET_GAMEOBJECT_ITEM_TARGET && !m_targets.GetGOTarget() && (!pTempItem || !pTempItem->GetTemplate()->GetLockID() || !pTempItem->IsLocked())) return SPELL_FAILED_BAD_TARGETS; @@ -5759,7 +5701,7 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint int32 skillValue = 0; // check lock compatibility - SpellCastResult res = CanOpenLock(*effect, lockId, skillId, reqSkillValue, skillValue); + SpellCastResult res = CanOpenLock(spellEffectInfo, lockId, skillId, reqSkillValue, skillValue); if (res != SPELL_CAST_OK) return res; break; @@ -5782,7 +5724,7 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint if (!unitCaster) break; - SummonPropertiesEntry const* SummonProperties = sSummonPropertiesStore.LookupEntry(effect->MiscValueB); + SummonPropertiesEntry const* SummonProperties = sSummonPropertiesStore.LookupEntry(spellEffectInfo.MiscValueB); if (!SummonProperties) break; @@ -5982,10 +5924,10 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint if (!artifact) return SPELL_FAILED_NO_ARTIFACT_EQUIPPED; - if (effect->Effect == SPELL_EFFECT_GIVE_ARTIFACT_POWER) + if (spellEffectInfo.Effect == SPELL_EFFECT_GIVE_ARTIFACT_POWER) { ArtifactEntry const* artifactEntry = sArtifactStore.LookupEntry(artifact->GetTemplate()->GetArtifactID()); - if (!artifactEntry || artifactEntry->ArtifactCategoryID != effect->MiscValue) + if (!artifactEntry || artifactEntry->ArtifactCategoryID != spellEffectInfo.MiscValue) return SPELL_FAILED_WRONG_ARTIFACT_EQUIPPED; } break; @@ -5995,11 +5937,9 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint } } - for (SpellEffectInfo const* effect : m_spellInfo->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) { - if (!effect) - continue; - switch (effect->ApplyAuraName) + switch (spellEffectInfo.ApplyAuraName) { case SPELL_AURA_MOD_POSSESS_PET: { @@ -6025,8 +5965,8 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint if (!unitCaster->GetCharmerGUID().IsEmpty()) return SPELL_FAILED_CHARMED; - if (effect->ApplyAuraName == SPELL_AURA_MOD_CHARM - || effect->ApplyAuraName == SPELL_AURA_MOD_POSSESS) + if (spellEffectInfo.ApplyAuraName == SPELL_AURA_MOD_CHARM + || spellEffectInfo.ApplyAuraName == SPELL_AURA_MOD_POSSESS) { if (!m_spellInfo->HasAttribute(SPELL_ATTR1_DISMISS_PET) && !unitCaster->GetPetGUID().IsEmpty()) return SPELL_FAILED_ALREADY_HAVE_SUMMON; @@ -6049,7 +5989,7 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint if (target->GetOwner() && target->GetOwner()->GetTypeId() == TYPEID_PLAYER) return SPELL_FAILED_TARGET_IS_PLAYER_CONTROLLED; - int32 value = CalculateDamage(effect->EffectIndex, target); + int32 value = CalculateDamage(spellEffectInfo, target); if (value && int32(target->GetLevelForTarget(m_caster)) > value) return SPELL_FAILED_HIGHLEVEL; } @@ -6106,7 +6046,7 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint } case SPELL_AURA_PERIODIC_MANA_LEECH: { - if (effect->IsTargetingArea()) + if (spellEffectInfo.IsTargetingArea()) break; if (!m_targets.GetUnitTarget()) @@ -6243,7 +6183,7 @@ SpellCastResult Spell::CheckCasterAuras(uint32* param1) const // fill up aura mechanic info to send client proper error message if (param1) { - *param1 = aurEff->GetSpellEffectInfo()->Mechanic; + *param1 = aurEff->GetSpellEffectInfo().Mechanic; if (!*param1) *param1 = aurEff->GetSpellInfo()->Mechanic; } @@ -6336,7 +6276,7 @@ bool Spell::CheckSpellCancelsAuraEffect(AuraType auraType, uint32* param1) const if (param1) { - *param1 = aurEff->GetSpellEffectInfo()->Mechanic; + *param1 = aurEff->GetSpellEffectInfo().Mechanic; if (!*param1) *param1 = aurEff->GetSpellInfo()->Mechanic; } @@ -6418,10 +6358,10 @@ SpellCastResult Spell::CheckArenaAndRatedBattlegroundCastRules() return SPELL_CAST_OK; } -int32 Spell::CalculateDamage(uint8 effIndex, Unit const* target, float* var /*= nullptr*/) const +int32 Spell::CalculateDamage(SpellEffectInfo const& spellEffectInfo, Unit const* target, float* var /*= nullptr*/) const { - bool needRecalculateBasePoints = !(m_spellValue->CustomBasePointsMask & (1 << effIndex)); - return m_caster->CalculateSpellDamage(target, m_spellInfo, effIndex, needRecalculateBasePoints ? nullptr : &m_spellValue->EffectBasePoints[effIndex], var, m_castItemEntry, m_castItemLevel); + bool needRecalculateBasePoints = !(m_spellValue->CustomBasePointsMask & (1 << spellEffectInfo.EffectIndex)); + return m_caster->CalculateSpellDamage(target, spellEffectInfo, needRecalculateBasePoints ? nullptr : &m_spellValue->EffectBasePoints[spellEffectInfo.EffectIndex], var, m_castItemEntry, m_castItemLevel); } bool Spell::CanAutoCast(Unit* target) @@ -6432,15 +6372,12 @@ bool Spell::CanAutoCast(Unit* target) ObjectGuid targetguid = target->GetGUID(); // check if target already has the same or a more powerful aura - for (SpellEffectInfo const* effect : m_spellInfo->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) { - if (!effect) + if (!spellEffectInfo.IsAura()) continue; - if (!effect->IsAura()) - continue; - - AuraType const& auraType = AuraType(effect->ApplyAuraName); + AuraType const& auraType = spellEffectInfo.ApplyAuraName; Unit::AuraEffectList const& auras = target->GetAuraEffectsByType(auraType); for (Unit::AuraEffectList::const_iterator auraIt = auras.begin(); auraIt != auras.end(); ++auraIt) { @@ -6457,7 +6394,7 @@ bool Spell::CanAutoCast(Unit* target) break; case SPELL_GROUP_STACK_RULE_EXCLUSIVE_SAME_EFFECT: // this one has further checks, but i don't think they're necessary for autocast logic case SPELL_GROUP_STACK_RULE_EXCLUSIVE_HIGHEST: - if (abs(effect->BasePoints) <= abs((*auraIt)->GetAmount())) + if (abs(spellEffectInfo.BasePoints) <= abs((*auraIt)->GetAmount())) return false; break; case SPELL_GROUP_STACK_RULE_DEFAULT: @@ -6669,13 +6606,13 @@ SpellCastResult Spell::CheckItems(uint32* param1 /*= nullptr*/, uint32* param2 / { // such items should only fail if there is no suitable effect at all - see Rejuvenation Potions for example SpellCastResult failReason = SPELL_CAST_OK; - for (SpellEffectInfo const* effect : m_spellInfo->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) { // skip check, pet not required like checks, and for TARGET_UNIT_PET m_targets.GetUnitTarget() is not the real target but the caster - if (!effect || effect->TargetA.GetTarget() == TARGET_UNIT_PET) + if (spellEffectInfo.TargetA.GetTarget() == TARGET_UNIT_PET) continue; - if (effect->Effect == SPELL_EFFECT_HEAL) + if (spellEffectInfo.IsEffect(SPELL_EFFECT_HEAL)) { if (m_targets.GetUnitTarget()->IsFullHealth()) { @@ -6690,15 +6627,15 @@ SpellCastResult Spell::CheckItems(uint32* param1 /*= nullptr*/, uint32* param2 / } // Mana Potion, Rage Potion, Thistle Tea(Rogue), ... - if (effect->Effect == SPELL_EFFECT_ENERGIZE) + if (spellEffectInfo.IsEffect(SPELL_EFFECT_ENERGIZE)) { - if (effect->MiscValue < 0 || effect->MiscValue >= int8(MAX_POWERS)) + if (spellEffectInfo.MiscValue < 0 || spellEffectInfo.MiscValue >= int8(MAX_POWERS)) { failReason = SPELL_FAILED_ALREADY_AT_FULL_POWER; continue; } - Powers power = Powers(effect->MiscValue); + Powers power = Powers(spellEffectInfo.MiscValue); if (m_targets.GetUnitTarget()->GetPower(power) == m_targets.GetUnitTarget()->GetMaxPower(power)) { failReason = SPELL_FAILED_ALREADY_AT_FULL_POWER; @@ -6825,29 +6762,26 @@ SpellCastResult Spell::CheckItems(uint32* param1 /*= nullptr*/, uint32* param2 / } // special checks for spell effects - for (SpellEffectInfo const* effect : m_spellInfo->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) { - if (!effect) - continue; - - switch (effect->Effect) + switch (spellEffectInfo.Effect) { case SPELL_EFFECT_CREATE_ITEM: case SPELL_EFFECT_CREATE_LOOT: { // m_targets.GetUnitTarget() means explicit cast, otherwise we dont check for possible equip error Unit* target = m_targets.GetUnitTarget() ? m_targets.GetUnitTarget() : player; - if (target->GetTypeId() == TYPEID_PLAYER && !IsTriggered() && effect->ItemType) + if (target->GetTypeId() == TYPEID_PLAYER && !IsTriggered() && spellEffectInfo.ItemType) { ItemPosCountVec dest; - InventoryResult msg = target->ToPlayer()->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, effect->ItemType, 1); + InventoryResult msg = target->ToPlayer()->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, spellEffectInfo.ItemType, 1); if (msg != EQUIP_ERR_OK) { - ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(effect->ItemType); + ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(spellEffectInfo.ItemType); /// @todo Needs review if (itemTemplate && !(itemTemplate->GetItemLimitCategory())) { - player->SendEquipError(msg, nullptr, nullptr, effect->ItemType); + player->SendEquipError(msg, nullptr, nullptr, spellEffectInfo.ItemType); return SPELL_FAILED_DONT_REPORT; } else @@ -6855,13 +6789,13 @@ SpellCastResult Spell::CheckItems(uint32* param1 /*= nullptr*/, uint32* param2 / // Conjure Food/Water/Refreshment spells if (m_spellInfo->SpellFamilyName != SPELLFAMILY_MAGE || (!(m_spellInfo->SpellFamilyFlags[0] & 0x40000000))) return SPELL_FAILED_TOO_MANY_OF_ITEM; - else if (!(target->ToPlayer()->HasItemCount(effect->ItemType))) + else if (!(target->ToPlayer()->HasItemCount(spellEffectInfo.ItemType))) { - player->SendEquipError(msg, nullptr, nullptr, effect->ItemType); + player->SendEquipError(msg, nullptr, nullptr, spellEffectInfo.ItemType); return SPELL_FAILED_DONT_REPORT; } - else if (SpellEffectInfo const* efi = m_spellInfo->GetEffect(EFFECT_1)) - player->CastSpell(player, efi->CalcValue(), false); // move this to anywhere + else if (m_spellInfo->GetEffects().size() > EFFECT_1) + player->CastSpell(player, m_spellInfo->GetEffect(EFFECT_1).CalcValue(), false); // move this to anywhere return SPELL_FAILED_DONT_REPORT; } } @@ -6869,7 +6803,7 @@ SpellCastResult Spell::CheckItems(uint32* param1 /*= nullptr*/, uint32* param2 / break; } case SPELL_EFFECT_ENCHANT_ITEM: - if (effect->ItemType && m_targets.GetItemTarget() + if (spellEffectInfo.ItemType && m_targets.GetItemTarget() && (m_targets.GetItemTarget()->IsVellum())) { // cannot enchant vellum for other player @@ -6879,10 +6813,10 @@ SpellCastResult Spell::CheckItems(uint32* param1 /*= nullptr*/, uint32* param2 / if (m_CastItem && m_CastItem->GetTemplate()->GetFlags() & ITEM_FLAG_NO_REAGENT_COST) return SPELL_FAILED_TOTEM_CATEGORY; ItemPosCountVec dest; - InventoryResult msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, effect->ItemType, 1); + InventoryResult msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, spellEffectInfo.ItemType, 1); if (msg != EQUIP_ERR_OK) { - player->SendEquipError(msg, nullptr, nullptr, effect->ItemType); + player->SendEquipError(msg, nullptr, nullptr, spellEffectInfo.ItemType); return SPELL_FAILED_DONT_REPORT; } } @@ -6907,7 +6841,7 @@ SpellCastResult Spell::CheckItems(uint32* param1 /*= nullptr*/, uint32* param2 / } } - SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(effect->MiscValue); + SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(spellEffectInfo.MiscValue); // do not allow adding usable enchantments to items that have use effect already if (enchantEntry) { @@ -6952,7 +6886,7 @@ SpellCastResult Spell::CheckItems(uint32* param1 /*= nullptr*/, uint32* param2 / // Not allow enchant in trade slot for some enchant type if (item->GetOwner() != player) { - uint32 enchant_id = effect->MiscValue; + uint32 enchant_id = spellEffectInfo.MiscValue; SpellItemEnchantmentEntry const* pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id); if (!pEnchant) return SPELL_FAILED_ERROR; @@ -7087,7 +7021,7 @@ SpellCastResult Spell::CheckItems(uint32* param1 /*= nullptr*/, uint32* param2 / } case SPELL_EFFECT_RECHARGE_ITEM: { - uint32 itemId = effect->ItemType; + uint32 itemId = spellEffectInfo.ItemType; ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemId); if (!proto) @@ -7300,12 +7234,9 @@ bool Spell::UpdatePointers() WorldObject* transport = nullptr; // update effect destinations (in case of moved transport dest target) - for (SpellEffectInfo const* effect : m_spellInfo->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) { - if (!effect) - continue; - - SpellDestination& dest = m_destTargets[effect->EffectIndex]; + SpellDestination& dest = m_destTargets[spellEffectInfo.EffectIndex]; if (!dest._transportGUID) continue; @@ -7339,12 +7270,9 @@ Difficulty Spell::GetCastDifficulty() const return m_caster->GetMap()->GetDifficultyID(); } -bool Spell::CheckEffectTarget(Unit const* target, SpellEffectInfo const* effect, Position const* losPosition) const +bool Spell::CheckEffectTarget(Unit const* target, SpellEffectInfo const& spellEffectInfo, Position const* losPosition) const { - if (!effect->IsEffect()) - return false; - - switch (effect->ApplyAuraName) + switch (spellEffectInfo.ApplyAuraName) { case SPELL_AURA_MOD_POSSESS: case SPELL_AURA_MOD_CHARM: @@ -7356,7 +7284,7 @@ bool Spell::CheckEffectTarget(Unit const* target, SpellEffectInfo const* effect, return false; if (!target->GetCharmerGUID().IsEmpty()) return false; - if (int32 value = CalculateDamage(effect->EffectIndex, target)) + if (int32 value = CalculateDamage(spellEffectInfo, target)) if ((int32)target->GetLevelForTarget(m_caster) > value) return false; break; @@ -7374,7 +7302,7 @@ bool Spell::CheckEffectTarget(Unit const* target, SpellEffectInfo const* effect, /// @todo shit below shouldn't be here, but it's temporary //Check targets for LOS visibility - switch (effect->Effect) + switch (spellEffectInfo.Effect) { case SPELL_EFFECT_SKIN_PLAYER_CORPSE: { @@ -7422,12 +7350,9 @@ bool Spell::CheckEffectTarget(Unit const* target, SpellEffectInfo const* effect, return true; } -bool Spell::CheckEffectTarget(GameObject const* target, SpellEffectInfo const* effect) const +bool Spell::CheckEffectTarget(GameObject const* target, SpellEffectInfo const& spellEffectInfo) const { - if (!effect->IsEffect()) - return false; - - switch (effect->Effect) + switch (spellEffectInfo.Effect) { case SPELL_EFFECT_GAMEOBJECT_DAMAGE: case SPELL_EFFECT_GAMEOBJECT_REPAIR: @@ -7442,11 +7367,8 @@ bool Spell::CheckEffectTarget(GameObject const* target, SpellEffectInfo const* e return true; } -bool Spell::CheckEffectTarget(Item const* /*target*/, SpellEffectInfo const* effect) const +bool Spell::CheckEffectTarget(Item const* /*target*/, SpellEffectInfo const& /*spellEffectInfo*/) const { - if (!effect->IsEffect()) - return false; - return true; } @@ -7637,40 +7559,37 @@ bool Spell::IsValidDeadOrAliveTarget(Unit const* target) const void Spell::HandleLaunchPhase() { // handle effects with SPELL_EFFECT_HANDLE_LAUNCH mode - for (SpellEffectInfo const* effect : m_spellInfo->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) { // don't do anything for empty effect - if (!effect || !effect->IsEffect()) + if (!spellEffectInfo.IsEffect()) continue; - HandleEffects(nullptr, nullptr, nullptr, effect->EffectIndex, SPELL_EFFECT_HANDLE_LAUNCH); + HandleEffects(nullptr, nullptr, nullptr, spellEffectInfo, SPELL_EFFECT_HANDLE_LAUNCH); } PrepareTargetProcessing(); - for (SpellEffectInfo const* effect : m_spellInfo->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) { - if (!effect) - continue; - float multiplier = 1.0f; - if (m_applyMultiplierMask & (1 << effect->EffectIndex)) - multiplier = effect->CalcDamageMultiplier(m_originalCaster, this); + if (m_applyMultiplierMask & (1 << spellEffectInfo.EffectIndex)) + multiplier = spellEffectInfo.CalcDamageMultiplier(m_originalCaster, this); for (TargetInfo& target : m_UniqueTargetInfo) { uint32 mask = target.EffectMask; - if (!(mask & (1 << effect->EffectIndex))) + if (!(mask & (1 << spellEffectInfo.EffectIndex))) continue; - DoEffectOnLaunchTarget(target, multiplier, effect); + DoEffectOnLaunchTarget(target, multiplier, spellEffectInfo); } } FinishTargetProcessing(); } -void Spell::DoEffectOnLaunchTarget(TargetInfo& targetInfo, float multiplier, SpellEffectInfo const* effect) +void Spell::DoEffectOnLaunchTarget(TargetInfo& targetInfo, float multiplier, SpellEffectInfo const& spellEffectInfo) { Unit* unit = nullptr; // In case spell hit target, do all effect on that target @@ -7690,30 +7609,30 @@ void Spell::DoEffectOnLaunchTarget(TargetInfo& targetInfo, float multiplier, Spe m_damage = 0; m_healing = 0; - HandleEffects(unit, nullptr, nullptr, effect->EffectIndex, SPELL_EFFECT_HANDLE_LAUNCH_TARGET); + HandleEffects(unit, nullptr, nullptr, spellEffectInfo, SPELL_EFFECT_HANDLE_LAUNCH_TARGET); if (m_originalCaster && m_damage > 0) { - if (effect->IsTargetingArea() || effect->IsAreaAuraEffect() || effect->IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA)) + if (spellEffectInfo.IsTargetingArea() || spellEffectInfo.IsAreaAuraEffect() || spellEffectInfo.IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA)) { m_damage = unit->CalculateAOEAvoidance(m_damage, m_spellInfo->SchoolMask, m_originalCaster->GetGUID()); if (m_originalCaster->GetTypeId() == TYPEID_PLAYER) { // cap damage of player AOE - int64 targetAmount = GetUnitTargetCountForEffect(SpellEffIndex(effect->EffectIndex)); + int64 targetAmount = GetUnitTargetCountForEffect(spellEffectInfo.EffectIndex); if (targetAmount > 20) m_damage = m_damage * 20 / targetAmount; } } } - if (m_applyMultiplierMask & (1 << effect->EffectIndex)) + if (m_applyMultiplierMask & (1 << spellEffectInfo.EffectIndex)) { - m_damage = int32(m_damage * m_damageMultipliers[effect->EffectIndex]); - m_healing = int32(m_healing * m_damageMultipliers[effect->EffectIndex]); + m_damage = int32(m_damage * m_damageMultipliers[spellEffectInfo.EffectIndex]); + m_healing = int32(m_healing * m_damageMultipliers[spellEffectInfo.EffectIndex]); - m_damageMultipliers[effect->EffectIndex] *= multiplier; + m_damageMultipliers[spellEffectInfo.EffectIndex] *= multiplier; } targetInfo.Damage += m_damage; @@ -8091,9 +8010,9 @@ bool Spell::CanExecuteTriggersOnHit(uint32 effMask, SpellInfo const* triggeredBy { bool only_on_caster = (triggeredByAura && (triggeredByAura->HasAttribute(SPELL_ATTR4_PROC_ONLY_ON_CASTER))); // If triggeredByAura has SPELL_ATTR4_PROC_ONLY_ON_CASTER then it can only proc on a cast spell with TARGET_UNIT_CASTER - for (SpellEffectInfo const* effect : m_spellInfo->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) { - if (effect && ((effMask & (1 << effect->EffectIndex)) && (!only_on_caster || (effect->TargetA.GetTarget() == TARGET_UNIT_CASTER)))) + if ((effMask & (1 << spellEffectInfo.EffectIndex)) && (!only_on_caster || (spellEffectInfo.TargetA.GetTarget() == TARGET_UNIT_CASTER))) return true; } return false; @@ -8114,13 +8033,13 @@ void Spell::PrepareTriggersExecutedOnHit() if (!aurEff->IsAffectingSpell(m_spellInfo)) continue; - if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(aurEff->GetSpellEffectInfo()->TriggerSpell, GetCastDifficulty())) + if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(aurEff->GetSpellEffectInfo().TriggerSpell, GetCastDifficulty())) { // calculate the chance using spell base amount, because aura amount is not updated on combo-points change // this possibly needs fixing int32 auraBaseAmount = aurEff->GetBaseAmount(); // proc chance is stored in effect amount - int32 chance = unitCaster->CalculateSpellDamage(nullptr, aurEff->GetSpellInfo(), aurEff->GetEffIndex(), &auraBaseAmount); + int32 chance = unitCaster->CalculateSpellDamage(nullptr, aurEff->GetSpellEffectInfo(), &auraBaseAmount); chance *= aurEff->GetBase()->GetStackAmount(); // build trigger and add to the list diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h index 37d6d68a187..b12fa5fd929 100644 --- a/src/server/game/Spells/Spell.h +++ b/src/server/game/Spells/Spell.h @@ -515,21 +515,21 @@ class TC_GAME_API Spell void SelectExplicitTargets(); void SelectSpellTargets(); - void SelectEffectImplicitTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, uint32& processedEffectMask); - void SelectImplicitChannelTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType); - void SelectImplicitNearbyTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, uint32 effMask); - void SelectImplicitConeTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, uint32 effMask); - void SelectImplicitAreaTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, uint32 effMask); - void SelectImplicitCasterDestTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType); - void SelectImplicitTargetDestTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType); - void SelectImplicitDestDestTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType); - void SelectImplicitCasterObjectTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType); - void SelectImplicitTargetObjectTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType); - void SelectImplicitChainTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, WorldObject* target, uint32 effMask); - void SelectImplicitTrajTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType); - void SelectImplicitLineTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, uint32 effMask); - - void SelectEffectTypeImplicitTargets(uint32 effIndex); + void SelectEffectImplicitTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType, uint32& processedEffectMask); + void SelectImplicitChannelTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType); + void SelectImplicitNearbyTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType, uint32 effMask); + void SelectImplicitConeTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType, uint32 effMask); + void SelectImplicitAreaTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType, uint32 effMask); + void SelectImplicitCasterDestTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType); + void SelectImplicitTargetDestTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType); + void SelectImplicitDestDestTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType); + void SelectImplicitCasterObjectTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType); + void SelectImplicitTargetObjectTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType); + void SelectImplicitChainTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType, WorldObject* target, uint32 effMask); + void SelectImplicitTrajTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType); + void SelectImplicitLineTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType, uint32 effMask); + + void SelectEffectTypeImplicitTargets(SpellEffectInfo const& spellEffectInfo); uint32 GetSearcherTypeMask(SpellTargetObjectTypes objType, ConditionContainer* condList); template<class SEARCHER> void SearchTargets(SEARCHER& searcher, uint32 containerMask, WorldObject* referer, Position const* pos, float radius); @@ -577,7 +577,7 @@ class TC_GAME_API Spell bool CheckSpellCancelsConfuse(uint32* param1) const; bool CheckSpellCancelsNoActions(uint32* param1) const; - int32 CalculateDamage(uint8 effIndex, Unit const* target, float* var = nullptr) const; + int32 CalculateDamage(SpellEffectInfo const& spellEffectInfo, Unit const* target, float* var = nullptr) const; void Delayed(); void DelayedChannel(); @@ -586,9 +586,9 @@ class TC_GAME_API Spell void DoCreateItem(uint32 itemId, ItemContext context = ItemContext::NONE, std::vector<int32> const& bonusListIDs = std::vector<int32>()); - bool CheckEffectTarget(Unit const* target, SpellEffectInfo const* effect, Position const* losPosition) const; - bool CheckEffectTarget(GameObject const* target, SpellEffectInfo const* effect) const; - bool CheckEffectTarget(Item const* target, SpellEffectInfo const* effect) const; + bool CheckEffectTarget(Unit const* target, SpellEffectInfo const& spellEffectInfo, Position const* losPosition) const; + bool CheckEffectTarget(GameObject const* target, SpellEffectInfo const& spellEffectInfo) const; + bool CheckEffectTarget(Item const* target, SpellEffectInfo const& spellEffectInfo) const; bool CanAutoCast(Unit* target); void CheckSrc(); void CheckDst(); @@ -626,7 +626,7 @@ class TC_GAME_API Spell void SendChannelStart(uint32 duration); void SendResurrectRequest(Player* target); - void HandleEffects(Unit* pUnitTarget, Item* pItemTarget, GameObject* pGOTarget, uint32 i, SpellEffectHandleMode mode); + void HandleEffects(Unit* pUnitTarget, Item* pItemTarget, GameObject* pGOTarget, SpellEffectInfo const& spellEffectInfo, SpellEffectHandleMode mode); void HandleThreatSpells(); static Spell const* ExtractSpellFromEvent(BasicEvent* event); @@ -818,7 +818,7 @@ class TC_GAME_API Spell struct TargetInfoBase { virtual void PreprocessTarget(Spell* /*spell*/) { } - virtual void DoTargetSpellHit(Spell* spell, uint8 effIndex) = 0; + virtual void DoTargetSpellHit(Spell* spell, SpellEffectInfo const& spellEffectInfo) = 0; virtual void DoDamageAndTriggers(Spell* /*spell*/) { } uint32 EffectMask = 0; @@ -831,7 +831,7 @@ class TC_GAME_API Spell struct TargetInfo : public TargetInfoBase { void PreprocessTarget(Spell* spell) override; - void DoTargetSpellHit(Spell* spell, uint8 effIndex) override; + void DoTargetSpellHit(Spell* spell, SpellEffectInfo const& spellEffectInfo) override; void DoDamageAndTriggers(Spell* spell) override; ObjectGuid TargetGUID; @@ -860,7 +860,7 @@ class TC_GAME_API Spell struct GOTargetInfo : public TargetInfoBase { - void DoTargetSpellHit(Spell* spell, uint8 effIndex) override; + void DoTargetSpellHit(Spell* spell, SpellEffectInfo const& spellEffectInfo) override; ObjectGuid TargetGUID; uint64 TimeDelay = 0ULL; @@ -869,7 +869,7 @@ class TC_GAME_API Spell struct ItemTargetInfo : public TargetInfoBase { - void DoTargetSpellHit(Spell* spell, uint8 effIndex) override; + void DoTargetSpellHit(Spell* spell, SpellEffectInfo const& spellEffectInfo) override; Item* TargetItem = nullptr; }; @@ -886,13 +886,13 @@ class TC_GAME_API Spell void AddDestTarget(SpellDestination const& dest, uint32 effIndex); SpellMissInfo PreprocessSpellHit(Unit* unit, TargetInfo& targetInfo); - void DoSpellEffectHit(Unit* unit, uint8 effIndex, TargetInfo& targetInfo); + void DoSpellEffectHit(Unit* unit, SpellEffectInfo const& spellEffectInfo, TargetInfo& targetInfo); void DoTriggersOnSpellHit(Unit* unit, uint32 effMask); bool UpdateChanneledTargetList(); bool IsValidDeadOrAliveTarget(Unit const* target) const; void HandleLaunchPhase(); - void DoEffectOnLaunchTarget(TargetInfo& targetInfo, float multiplier, SpellEffectInfo const* effect); + void DoEffectOnLaunchTarget(TargetInfo& targetInfo, float multiplier, SpellEffectInfo const& spellEffectInfo); void PrepareTargetProcessing(); void FinishTargetProcessing(); diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 89088dc35d2..f881bf52e15 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -527,7 +527,7 @@ void Spell::EffectSchoolDMG() if (unitCaster && apply_direct_bonus) { - uint32 bonus = unitCaster->SpellDamageBonusDone(unitTarget, m_spellInfo, (uint32)damage, SPELL_DIRECT_DAMAGE, effectInfo); + uint32 bonus = unitCaster->SpellDamageBonusDone(unitTarget, m_spellInfo, (uint32)damage, SPELL_DIRECT_DAMAGE, *effectInfo); damage = bonus + uint32(bonus * variance); damage = unitTarget->SpellDamageBonusTaken(unitCaster, m_spellInfo, (uint32)damage, SPELL_DIRECT_DAMAGE); } @@ -1061,7 +1061,7 @@ void Spell::EffectPowerDrain() // add spell damage bonus if (unitCaster) { - uint32 bonus = unitCaster->SpellDamageBonusDone(unitTarget, m_spellInfo, uint32(damage), SPELL_DIRECT_DAMAGE, effectInfo); + uint32 bonus = unitCaster->SpellDamageBonusDone(unitTarget, m_spellInfo, uint32(damage), SPELL_DIRECT_DAMAGE, *effectInfo); damage = bonus + uint32(bonus * variance); damage = unitTarget->SpellDamageBonusTaken(unitCaster, m_spellInfo, uint32(damage), SPELL_DIRECT_DAMAGE); } @@ -1183,10 +1183,10 @@ void Spell::EffectHeal() } // Death Pact - return pct of max health to caster else if (m_spellInfo->SpellFamilyName == SPELLFAMILY_DEATHKNIGHT && m_spellInfo->SpellFamilyFlags[0] & 0x00080000) - addhealth = unitCaster->SpellHealingBonusDone(unitTarget, m_spellInfo, int32(unitCaster->CountPctFromMaxHealth(damage)), HEAL, effectInfo); + addhealth = unitCaster->SpellHealingBonusDone(unitTarget, m_spellInfo, int32(unitCaster->CountPctFromMaxHealth(damage)), HEAL, *effectInfo); else { - uint32 bonus = unitCaster->SpellHealingBonusDone(unitTarget, m_spellInfo, addhealth, HEAL, effectInfo); + uint32 bonus = unitCaster->SpellHealingBonusDone(unitTarget, m_spellInfo, addhealth, HEAL, *effectInfo); addhealth = bonus + uint32(bonus * variance); } @@ -1210,7 +1210,7 @@ void Spell::EffectHealPct() uint32 heal = unitTarget->CountPctFromMaxHealth(damage); if (unitCaster) { - heal = unitCaster->SpellHealingBonusDone(unitTarget, m_spellInfo, heal, HEAL, effectInfo); + heal = unitCaster->SpellHealingBonusDone(unitTarget, m_spellInfo, heal, HEAL, *effectInfo); heal = unitTarget->SpellHealingBonusTaken(unitCaster, m_spellInfo, heal, HEAL); } @@ -1227,7 +1227,7 @@ void Spell::EffectHealMechanical() uint32 heal = damage; if (unitCaster) - heal = unitCaster->SpellHealingBonusDone(unitTarget, m_spellInfo, heal, HEAL, effectInfo); + heal = unitCaster->SpellHealingBonusDone(unitTarget, m_spellInfo, heal, HEAL, *effectInfo); heal += uint32(heal * variance); if (unitCaster) @@ -1246,7 +1246,7 @@ void Spell::EffectHealthLeech() uint32 bonus = 0; if (unitCaster) - bonus = unitCaster->SpellDamageBonusDone(unitTarget, m_spellInfo, uint32(damage), SPELL_DIRECT_DAMAGE, effectInfo); + bonus = unitCaster->SpellDamageBonusDone(unitTarget, m_spellInfo, uint32(damage), SPELL_DIRECT_DAMAGE, *effectInfo); damage = bonus + uint32(bonus * variance); @@ -1263,7 +1263,7 @@ void Spell::EffectHealthLeech() if (unitCaster && unitCaster->IsAlive()) { - healthGain = unitCaster->SpellHealingBonusDone(unitCaster, m_spellInfo, healthGain, HEAL, effectInfo); + healthGain = unitCaster->SpellHealingBonusDone(unitCaster, m_spellInfo, healthGain, HEAL, *effectInfo); healthGain = unitCaster->SpellHealingBonusTaken(unitCaster, m_spellInfo, healthGain, HEAL); HealInfo healInfo(unitCaster, unitCaster, healthGain, m_spellInfo, m_spellSchoolMask); @@ -1445,10 +1445,9 @@ void Spell::EffectPersistentAA() return; // only handle at last effect - for (uint8 i = effectInfo->EffectIndex + 1; i < MAX_SPELL_EFFECTS; ++i) - if (SpellEffectInfo const* otherEffect = m_spellInfo->GetEffect(i)) - if (otherEffect && otherEffect->IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA)) - return; + for (size_t i = effectInfo->EffectIndex + 1; i < m_spellInfo->GetEffects().size(); ++i) + if (m_spellInfo->GetEffect(SpellEffIndex(i)).IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA)) + return; ASSERT(!_dynObjAura); @@ -2765,17 +2764,15 @@ void Spell::EffectWeaponDmg() // and handle all effects at once for (size_t j = effectInfo->EffectIndex + 1; j < m_spellInfo->GetEffects().size(); ++j) { - SpellEffectInfo const* effect = m_spellInfo->GetEffect(j); - if (!effect) - continue; - switch (effect->Effect) + switch (m_spellInfo->GetEffect(SpellEffIndex(j)).Effect) { case SPELL_EFFECT_WEAPON_DAMAGE: case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL: case SPELL_EFFECT_NORMALIZED_WEAPON_DMG: case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE: return; // we must calculate only at last weapon effect - break; + default: + break; } } @@ -2798,22 +2795,20 @@ void Spell::EffectWeaponDmg() bool normalized = false; float weaponDamagePercentMod = 1.0f; - for (SpellEffectInfo const* effect : m_spellInfo->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) { - if (!effect) - continue; - switch (effect->Effect) + switch (spellEffectInfo.Effect) { case SPELL_EFFECT_WEAPON_DAMAGE: case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL: - fixed_bonus += CalculateDamage(effect->EffectIndex, unitTarget); + fixed_bonus += CalculateDamage(spellEffectInfo, unitTarget); break; case SPELL_EFFECT_NORMALIZED_WEAPON_DMG: - fixed_bonus += CalculateDamage(effect->EffectIndex, unitTarget); + fixed_bonus += CalculateDamage(spellEffectInfo, unitTarget); normalized = true; break; case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE: - ApplyPct(weaponDamagePercentMod, CalculateDamage(effect->EffectIndex, unitTarget)); + ApplyPct(weaponDamagePercentMod, CalculateDamage(spellEffectInfo, unitTarget)); break; default: break; // not weapon damage effect, just skip @@ -2844,13 +2839,11 @@ void Spell::EffectWeaponDmg() int32 weaponDamage = unitCaster->CalculateDamage(m_attackType, normalized, addPctMods); // Sequence is important - for (SpellEffectInfo const* effect : m_spellInfo->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) { - if (!effect) - continue; // We assume that a spell have at most one fixed_bonus // and at most one weaponDamagePercentMod - switch (effect->Effect) + switch (spellEffectInfo.Effect) { case SPELL_EFFECT_WEAPON_DAMAGE: case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL: @@ -3276,8 +3269,8 @@ void Spell::EffectScriptEffect() return; // Effects for 58418 and 58420 are all DIFFICULTY_NONE so always valid - uint32 spellID = m_spellInfo->GetEffect(EFFECT_0)->CalcValue(); - uint32 questID = m_spellInfo->GetEffect(EFFECT_1)->CalcValue(); + uint32 spellID = m_spellInfo->GetEffect(EFFECT_0).CalcValue(); + uint32 questID = m_spellInfo->GetEffect(EFFECT_1).CalcValue(); if (unitTarget->ToPlayer()->GetQuestStatus(questID) == QUEST_STATUS_COMPLETE) unitTarget->CastSpell(unitTarget, spellID, true); @@ -3312,7 +3305,7 @@ void Spell::EffectScriptEffect() { /// @todo a hack, range = 11, should after some time cast, otherwise too far unitCaster->CastSpell(parent, 62496, true); - unitTarget->CastSpell(parent, m_spellInfo->GetEffect(EFFECT_0)->CalcValue()); // DIFFICULTY_NONE, so effect always valid + unitTarget->CastSpell(parent, damage); // DIFFICULTY_NONE, so effect always valid } } } diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp index e343eba170d..db87c917797 100644 --- a/src/server/game/Spells/SpellInfo.cpp +++ b/src/server/game/Spells/SpellInfo.cpp @@ -17,6 +17,7 @@ #include "SpellInfo.h" #include "Battleground.h" +#include "Containers.h" #include "Corpse.h" #include "DB2Stores.h" #include "GameTables.h" @@ -377,9 +378,9 @@ SpellEffectInfo::SpellEffectInfo(SpellInfo const* spellInfo, SpellEffectEntry co ASSERT(spellInfo); _spellInfo = spellInfo; - EffectIndex = _effect.EffectIndex; - Effect = _effect.Effect; - ApplyAuraName = _effect.EffectAura; + EffectIndex = SpellEffIndex(_effect.EffectIndex); + Effect = SpellEffectName(_effect.Effect); + ApplyAuraName = AuraType(_effect.EffectAura); ApplyAuraPeriod = _effect.EffectAuraPeriod; BasePoints = _effect.EffectBasePoints; RealPointsPerLevel = _effect.EffectRealPointsPerLevel; @@ -1088,11 +1089,9 @@ SpellInfo::SpellInfo(SpellNameEntry const* spellName, ::Difficulty difficulty, S if (!spellEffect) continue; - if (uint32(spellEffect->EffectIndex) >= _effects.size()) - _effects.resize(spellEffect->EffectIndex + 1); - - _effects[spellEffect->EffectIndex] = new SpellEffectInfo(this, *spellEffect); + Trinity::Containers::EnsureWritableVectorIndex(_effects, spellEffect->EffectIndex, SpellEffectInfo(this)) = SpellEffectInfo(this, *spellEffect); } + _effects.shrink_to_fit(); SpellName = &spellName->Name; @@ -1272,27 +1271,14 @@ SpellInfo::SpellInfo(SpellNameEntry const* spellName, ::Difficulty difficulty, s _effects.reserve(32); for (SpellEffectEntry const& spellEffect : effects) - { - if (uint32(spellEffect.EffectIndex) >= _effects.size()) - _effects.resize(spellEffect.EffectIndex + 1); + Trinity::Containers::EnsureWritableVectorIndex(_effects, spellEffect.EffectIndex, SpellEffectInfo(this)) = SpellEffectInfo(this, spellEffect); - _effects[spellEffect.EffectIndex] = new SpellEffectInfo(this, spellEffect); - } _effects.shrink_to_fit(); } SpellInfo::~SpellInfo() { _UnloadImplicitTargetConditionLists(); - _UnloadSpellEffects(); -} - -void SpellInfo::_UnloadSpellEffects() -{ - for (SpellEffectInfo const* effect : _effects) - delete effect; - - _effects.clear(); } uint32 SpellInfo::GetCategory() const @@ -1302,8 +1288,8 @@ uint32 SpellInfo::GetCategory() const bool SpellInfo::HasEffect(SpellEffectName effect) const { - for (SpellEffectInfo const* eff : _effects) - if (eff && eff->IsEffect(effect)) + for (SpellEffectInfo const& eff : GetEffects()) + if (eff.IsEffect(effect)) return true; return false; @@ -1311,8 +1297,8 @@ bool SpellInfo::HasEffect(SpellEffectName effect) const bool SpellInfo::HasAura(AuraType aura) const { - for (SpellEffectInfo const* effect : _effects) - if (effect && effect->IsAura(aura)) + for (SpellEffectInfo const& effect : GetEffects()) + if (effect.IsAura(aura)) return true; return false; @@ -1320,8 +1306,8 @@ bool SpellInfo::HasAura(AuraType aura) const bool SpellInfo::HasAreaAuraEffect() const { - for (SpellEffectInfo const* effect : _effects) - if (effect && effect->IsAreaAuraEffect()) + for (SpellEffectInfo const& effect : GetEffects()) + if (effect.IsAreaAuraEffect()) return true; return false; @@ -1329,24 +1315,24 @@ bool SpellInfo::HasAreaAuraEffect() const bool SpellInfo::HasOnlyDamageEffects() const { - for (SpellEffectInfo const* effect : _effects) + for (SpellEffectInfo const& effect : GetEffects()) { - if (!effect) - continue; - - switch (effect->Effect) + if (effect.IsEffect()) { - case SPELL_EFFECT_WEAPON_DAMAGE: - case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL: - case SPELL_EFFECT_NORMALIZED_WEAPON_DMG: - case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE: - case SPELL_EFFECT_SCHOOL_DAMAGE: - case SPELL_EFFECT_ENVIRONMENTAL_DAMAGE: - case SPELL_EFFECT_HEALTH_LEECH: - case SPELL_EFFECT_DAMAGE_FROM_MAX_HEALTH_PCT: - continue; - default: - return false; + switch (effect.Effect) + { + case SPELL_EFFECT_WEAPON_DAMAGE: + case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL: + case SPELL_EFFECT_NORMALIZED_WEAPON_DMG: + case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE: + case SPELL_EFFECT_SCHOOL_DAMAGE: + case SPELL_EFFECT_ENVIRONMENTAL_DAMAGE: + case SPELL_EFFECT_HEALTH_LEECH: + case SPELL_EFFECT_DAMAGE_FROM_MAX_HEALTH_PCT: + continue; + default: + return false; + } } } @@ -1355,8 +1341,8 @@ bool SpellInfo::HasOnlyDamageEffects() const bool SpellInfo::HasTargetType(::Targets target) const { - for (SpellEffectInfo const* effect : _effects) - if (effect && (effect->TargetA.GetTarget() == target || effect->TargetB.GetTarget() == target)) + for (SpellEffectInfo const& effect : GetEffects()) + if (effect.TargetA.GetTarget() == target || effect.TargetB.GetTarget() == target) return true; return false; @@ -1381,11 +1367,12 @@ bool SpellInfo::HasAnyAuraInterruptFlag() const bool SpellInfo::IsExplicitDiscovery() const { - SpellEffectInfo const* effect0 = GetEffect(EFFECT_0); - SpellEffectInfo const* effect1 = GetEffect(EFFECT_1); + if (GetEffects().size() < 2) + return false; - return ((effect0 && (effect0->Effect == SPELL_EFFECT_CREATE_RANDOM_ITEM || effect0->Effect == SPELL_EFFECT_CREATE_LOOT)) - && effect1 && effect1->Effect == SPELL_EFFECT_SCRIPT_EFFECT) + return ((GetEffect(EFFECT_0).Effect == SPELL_EFFECT_CREATE_RANDOM_ITEM + || GetEffect(EFFECT_0).Effect == SPELL_EFFECT_CREATE_LOOT) + && GetEffect(EFFECT_1).Effect == SPELL_EFFECT_SCRIPT_EFFECT) || Id == 64323; } @@ -1396,18 +1383,19 @@ bool SpellInfo::IsLootCrafting() const bool SpellInfo::IsQuestTame() const { - SpellEffectInfo const* effect0 = GetEffect(EFFECT_0); - SpellEffectInfo const* effect1 = GetEffect(EFFECT_1); - return effect0 && effect1 && effect0->Effect == SPELL_EFFECT_THREAT && effect1->Effect == SPELL_EFFECT_APPLY_AURA && effect1->ApplyAuraName == SPELL_AURA_DUMMY; + if (GetEffects().size() < 2) + return false; + + return GetEffect(EFFECT_0).Effect == SPELL_EFFECT_THREAT && GetEffect(EFFECT_1).Effect == SPELL_EFFECT_APPLY_AURA && GetEffect(EFFECT_1).ApplyAuraName == SPELL_AURA_DUMMY; } bool SpellInfo::IsProfession() const { - for (SpellEffectInfo const* effect : _effects) + for (SpellEffectInfo const& effect : GetEffects()) { - if (effect && effect->Effect == SPELL_EFFECT_SKILL) + if (effect.Effect == SPELL_EFFECT_SKILL) { - uint32 skill = effect->MiscValue; + uint32 skill = effect.MiscValue; if (IsProfessionSkill(skill)) return true; @@ -1418,11 +1406,11 @@ bool SpellInfo::IsProfession() const bool SpellInfo::IsPrimaryProfession() const { - for (SpellEffectInfo const* effect : _effects) + for (SpellEffectInfo const& effect : GetEffects()) { - if (effect && effect->Effect == SPELL_EFFECT_SKILL) + if (effect.Effect == SPELL_EFFECT_SKILL) { - uint32 skill = effect->MiscValue; + uint32 skill = effect.MiscValue; if (IsPrimaryProfessionSkill(skill)) return true; @@ -1449,8 +1437,8 @@ bool SpellInfo::IsAbilityOfSkillType(uint32 skillType) const bool SpellInfo::IsAffectingArea() const { - for (SpellEffectInfo const* effect : _effects) - if (effect && effect->IsEffect() && (effect->IsTargetingArea() || effect->IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA) || effect->IsAreaAuraEffect())) + for (SpellEffectInfo const& effect : GetEffects()) + if (effect.IsEffect() && (effect.IsTargetingArea() || effect.IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA) || effect.IsAreaAuraEffect())) return true; return false; @@ -1459,8 +1447,8 @@ bool SpellInfo::IsAffectingArea() const // checks if spell targets are selected from area, doesn't include spell effects in check (like area wide auras for example) bool SpellInfo::IsTargetingArea() const { - for (SpellEffectInfo const* effect : _effects) - if (effect && effect->IsEffect() && effect->IsTargetingArea()) + for (SpellEffectInfo const& effect : GetEffects()) + if (effect.IsEffect() && effect.IsTargetingArea()) return true; return false; @@ -1477,12 +1465,12 @@ bool SpellInfo::NeedsToBeTriggeredByCaster(SpellInfo const* triggeringSpell) con return true; /* - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const& effect : GetEffects()) { - if (Effects[i].IsEffect()) + if (effect.IsEffect()) { - if (Effects[i].TargetA.GetSelectionCategory() == TARGET_SELECT_CATEGORY_CHANNEL - || Effects[i].TargetB.GetSelectionCategory() == TARGET_SELECT_CATEGORY_CHANNEL) + if (effect.TargetA.GetSelectionCategory() == TARGET_SELECT_CATEGORY_CHANNEL + || effect.TargetB.GetSelectionCategory() == TARGET_SELECT_CATEGORY_CHANNEL) return true; } } @@ -1491,15 +1479,12 @@ bool SpellInfo::NeedsToBeTriggeredByCaster(SpellInfo const* triggeringSpell) con if (triggeringSpell->IsChanneled()) { uint32 mask = 0; - for (SpellEffectInfo const* effect : _effects) + for (SpellEffectInfo const& effect : GetEffects()) { - if (!effect) - continue; - - if (effect->TargetA.GetTarget() != TARGET_UNIT_CASTER && effect->TargetA.GetTarget() != TARGET_DEST_CASTER - && effect->TargetB.GetTarget() != TARGET_UNIT_CASTER && effect->TargetB.GetTarget() != TARGET_DEST_CASTER) + if (effect.TargetA.GetTarget() != TARGET_UNIT_CASTER && effect.TargetA.GetTarget() != TARGET_DEST_CASTER + && effect.TargetB.GetTarget() != TARGET_UNIT_CASTER && effect.TargetB.GetTarget() != TARGET_DEST_CASTER) { - mask |= effect->GetProvidedTargetMask(); + mask |= effect.GetProvidedTargetMask(); } } @@ -1530,22 +1515,19 @@ bool SpellInfo::IsStackableWithRanks() const return false; // All stance spells. if any better way, change it. - for (SpellEffectInfo const* effect : _effects) + for (SpellEffectInfo const& effect : GetEffects()) { - if (!effect) - continue; - switch (SpellFamilyName) { case SPELLFAMILY_PALADIN: // Paladin aura Spell - if (effect->Effect == SPELL_EFFECT_APPLY_AREA_AURA_RAID) + if (effect.Effect == SPELL_EFFECT_APPLY_AREA_AURA_RAID) return false; break; case SPELLFAMILY_DRUID: // Druid form Spell - if (effect->Effect == SPELL_EFFECT_APPLY_AURA && - effect->ApplyAuraName == SPELL_AURA_MOD_SHAPESHIFT) + if (effect.Effect == SPELL_EFFECT_APPLY_AURA && + effect.ApplyAuraName == SPELL_AURA_MOD_SHAPESHIFT) return false; break; } @@ -1594,12 +1576,12 @@ bool SpellInfo::IsAllowingDeadTarget() const if (HasAttribute(SPELL_ATTR2_CAN_TARGET_DEAD) || Targets & (TARGET_FLAG_CORPSE_ALLY | TARGET_FLAG_CORPSE_ENEMY | TARGET_FLAG_UNIT_DEAD)) return true; - for (SpellEffectInfo const* effect : _effects) + for (SpellEffectInfo const& effect : GetEffects()) { - if (!effect) + if (!effect.IsEffect()) continue; - if (effect->TargetA.GetObjectType() == TARGET_OBJECT_TYPE_CORPSE || effect->TargetB.GetObjectType() == TARGET_OBJECT_TYPE_CORPSE) + if (effect.TargetA.GetObjectType() == TARGET_OBJECT_TYPE_CORPSE || effect.TargetB.GetObjectType() == TARGET_OBJECT_TYPE_CORPSE) return true; } @@ -1608,12 +1590,9 @@ bool SpellInfo::IsAllowingDeadTarget() const bool SpellInfo::IsGroupBuff() const { - for (SpellEffectInfo const* effect : _effects) + for (SpellEffectInfo const& effect : GetEffects()) { - if (!effect) - continue; - - switch (effect->TargetA.GetCheckType()) + switch (effect.TargetA.GetCheckType()) { case TARGET_CHECK_PARTY: case TARGET_CHECK_RAID: @@ -1880,8 +1859,7 @@ SpellCastResult SpellInfo::CheckShapeshift(uint32 form) const // talents that learn spells can have stance requirements that need ignore // (this requirement only for client-side stance show in talent description) /* TODO: 6.x fix this in proper way (probably spell flags/attributes?) - if (GetTalentSpellCost(Id) > 0 && - (Effects[0].Effect == SPELL_EFFECT_LEARN_SPELL || Effects[1].Effect == SPELL_EFFECT_LEARN_SPELL || Effects[2].Effect == SPELL_EFFECT_LEARN_SPELL)) + if (GetTalentSpellCost(Id) > 0 && HasEffect(SPELL_EFFECT_LEARN_SPELL)) return SPELL_CAST_OK;*/ //if (HasAttribute(SPELL_ATTR13_ACTIVATES_REQUIRED_SHAPESHIFT)) @@ -2063,16 +2041,16 @@ SpellCastResult SpellInfo::CheckLocation(uint32 map_id, uint32 zone_id, uint32 a // aura limitations if (player) { - for (SpellEffectInfo const* effect : _effects) + for (SpellEffectInfo const& effect : GetEffects()) { - if (!effect || !effect->IsAura()) + if (!effect.IsAura()) continue; - switch (effect->ApplyAuraName) + switch (effect.ApplyAuraName) { case SPELL_AURA_MOD_SHAPESHIFT: { - if (SpellShapeshiftFormEntry const* spellShapeshiftForm = sSpellShapeshiftFormStore.LookupEntry(effect->MiscValue)) + if (SpellShapeshiftFormEntry const* spellShapeshiftForm = sSpellShapeshiftFormStore.LookupEntry(effect.MiscValue)) if (uint32 mountType = spellShapeshiftForm->MountTypeID) if (!player->GetMountCapability(mountType)) return SPELL_FAILED_NOT_HERE; @@ -2080,13 +2058,15 @@ SpellCastResult SpellInfo::CheckLocation(uint32 map_id, uint32 zone_id, uint32 a } case SPELL_AURA_MOUNTED: { - uint32 mountType = effect->MiscValueB; + uint32 mountType = effect.MiscValueB; if (MountEntry const* mountEntry = sDB2Manager.GetMount(Id)) mountType = mountEntry->MountTypeID; if (mountType && !player->GetMountCapability(mountType)) return SPELL_FAILED_NOT_HERE; break; } + default: + break; } } } @@ -2294,11 +2274,11 @@ SpellCastResult SpellInfo::CheckVehicle(Unit const* caster) const if (vehicle) { uint16 checkMask = 0; - for (SpellEffectInfo const* effect : _effects) + for (SpellEffectInfo const& effect : GetEffects()) { - if (effect && effect->ApplyAuraName == SPELL_AURA_MOD_SHAPESHIFT) + if (effect.IsAura(SPELL_AURA_MOD_SHAPESHIFT)) { - SpellShapeshiftFormEntry const* shapeShiftFromEntry = sSpellShapeshiftFormStore.LookupEntry(effect->MiscValue); + SpellShapeshiftFormEntry const* shapeShiftFromEntry = sSpellShapeshiftFormStore.LookupEntry(effect.MiscValue); if (shapeShiftFromEntry && (shapeShiftFromEntry->Flags & 1) == 0) // unk flag checkMask |= VEHICLE_SEAT_FLAG_UNCONTROLLED; break; @@ -2319,12 +2299,12 @@ SpellCastResult SpellInfo::CheckVehicle(Unit const* caster) const // Can only summon uncontrolled minions/guardians when on controlled vehicle if (vehicleSeat->Flags & (VEHICLE_SEAT_FLAG_CAN_CONTROL | VEHICLE_SEAT_FLAG_UNK2)) { - for (SpellEffectInfo const* effect : _effects) + for (SpellEffectInfo const& effect : GetEffects()) { - if (!effect || effect->Effect != SPELL_EFFECT_SUMMON) + if (!effect.IsEffect(SPELL_EFFECT_SUMMON)) continue; - SummonPropertiesEntry const* props = sSummonPropertiesStore.LookupEntry(effect->MiscValueB); + SummonPropertiesEntry const* props = sSummonPropertiesStore.LookupEntry(effect.MiscValueB); if (props && props->Control != SUMMON_CATEGORY_WILD) return SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW; } @@ -2365,21 +2345,21 @@ uint32 SpellInfo::GetAllEffectsMechanicMask() const if (Mechanic) mask |= 1 << Mechanic; - for (SpellEffectInfo const* effect : _effects) - if (effect && effect->IsEffect() && effect->Mechanic) - mask |= 1 << effect->Mechanic; + for (SpellEffectInfo const& effect : GetEffects()) + if (effect.IsEffect() && effect.Mechanic) + mask |= 1 << effect.Mechanic; return mask; } -uint32 SpellInfo::GetEffectMechanicMask(uint32 effIndex) const +uint32 SpellInfo::GetEffectMechanicMask(SpellEffIndex effIndex) const { uint32 mask = 0; if (Mechanic) mask |= 1 << Mechanic; - if (effIndex < _effects.size() && _effects[effIndex] && _effects[effIndex]->IsEffect() && _effects[effIndex]->Mechanic) - mask |= 1 << _effects[effIndex]->Mechanic; + if (GetEffect(effIndex).IsEffect() && GetEffect(effIndex).Mechanic) + mask |= 1 << GetEffect(effIndex).Mechanic; return mask; } @@ -2390,18 +2370,17 @@ uint32 SpellInfo::GetSpellMechanicMaskByEffectMask(uint32 effectMask) const if (Mechanic) mask |= 1 << Mechanic; - for (SpellEffectInfo const* effect : _effects) - if (effect && (effectMask & (1 << effect->EffectIndex)) && effect->Mechanic) - mask |= 1 << effect->Mechanic; + for (SpellEffectInfo const& effect : GetEffects()) + if ((effectMask & (1 << effect.EffectIndex)) && effect.Mechanic) + mask |= 1 << effect.Mechanic; return mask; } -Mechanics SpellInfo::GetEffectMechanic(uint32 effIndex) const +Mechanics SpellInfo::GetEffectMechanic(SpellEffIndex effIndex) const { - SpellEffectInfo const* effect = GetEffect(effIndex); - if (effect && effect->IsEffect() && effect->Mechanic) - return Mechanics(effect->Mechanic); + if (GetEffect(effIndex).IsEffect() && GetEffect(effIndex).Mechanic) + return GetEffect(effIndex).Mechanic; if (Mechanic) return Mechanics(Mechanic); @@ -2409,14 +2388,6 @@ Mechanics SpellInfo::GetEffectMechanic(uint32 effIndex) const return MECHANIC_NONE; } -/*bool SpellInfo::HasAnyEffectMechanic() const -{ - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - if (Effects[i].Mechanic) - return true; - return false; -}*/ - uint32 SpellInfo::GetDispelMask() const { return GetDispelMask(DispelType(Dispel)); @@ -2466,8 +2437,8 @@ void SpellInfo::_LoadAuraState() return AURA_STATE_BLEED; if (GetSchoolMask() & SPELL_SCHOOL_MASK_FROST) - for (SpellEffectInfo const* effect : _effects) - if (effect && (effect->IsAura(SPELL_AURA_MOD_STUN) || effect->IsAura(SPELL_AURA_MOD_ROOT))) + for (SpellEffectInfo const& effect : GetEffects()) + if (effect.IsAura(SPELL_AURA_MOD_STUN) || effect.IsAura(SPELL_AURA_MOD_ROOT) || effect.IsAura(SPELL_AURA_MOD_ROOT_2)) return AURA_STATE_FROZEN; switch (Id) @@ -2539,11 +2510,11 @@ void SpellInfo::_LoadSpellSpecific() { bool food = false; bool drink = false; - for (SpellEffectInfo const* effect : _effects) + for (SpellEffectInfo const& effect : GetEffects()) { - if (!effect || !effect->IsAura()) + if (!effect.IsAura()) continue; - switch (effect->ApplyAuraName) + switch (effect.ApplyAuraName) { // Food case SPELL_AURA_MOD_REGEN: @@ -2595,8 +2566,8 @@ void SpellInfo::_LoadSpellSpecific() // Arcane brillance and Arcane intelect (normal check fails because of flags difference) if (SpellFamilyFlags[0] & 0x400) return SPELL_SPECIFIC_MAGE_ARCANE_BRILLANCE; - SpellEffectInfo const* effect = GetEffect(EFFECT_0); - if (effect && (SpellFamilyFlags[0] & 0x1000000) && effect->ApplyAuraName == SPELL_AURA_MOD_CONFUSE) + + if ((SpellFamilyFlags[0] & 0x1000000) && GetEffect(EFFECT_0).IsAura(SPELL_AURA_MOD_CONFUSE)) return SPELL_SPECIFIC_MAGE_POLYMORPH; break; @@ -2690,11 +2661,11 @@ void SpellInfo::_LoadSpellSpecific() break; } - for (SpellEffectInfo const* effect : _effects) + for (SpellEffectInfo const& effect : GetEffects()) { - if (effect && effect->Effect == SPELL_EFFECT_APPLY_AURA) + if (effect.IsEffect(SPELL_EFFECT_APPLY_AURA)) { - switch (effect->ApplyAuraName) + switch (effect.ApplyAuraName) { case SPELL_AURA_MOD_CHARM: case SPELL_AURA_MOD_POSSESS_PET: @@ -2709,6 +2680,8 @@ void SpellInfo::_LoadSpellSpecific() case SPELL_AURA_TRACK_RESOURCES: case SPELL_AURA_TRACK_STEALTHED: return SPELL_SPECIFIC_TRACKER; + default: + break; } } } @@ -3191,7 +3164,7 @@ int32 SpellInfo::GetDiminishingReturnsLimitDuration() const void SpellInfo::_LoadImmunityInfo() { - auto loadImmunityInfoFn = [this](SpellEffectInfo* effectInfo) + for (SpellEffectInfo& effect : _effects) { uint32 schoolImmunityMask = 0; uint32 applyHarmfulAuraImmunityMask = 0; @@ -3199,12 +3172,12 @@ void SpellInfo::_LoadImmunityInfo() uint32 dispelImmunity = 0; uint32 damageImmunityMask = 0; - int32 miscVal = effectInfo->MiscValue; - int32 amount = effectInfo->CalcValue(); + int32 miscVal = effect.MiscValue; + int32 amount = effect.CalcValue(); - ImmunityInfo& immuneInfo = *const_cast<ImmunityInfo*>(effectInfo->GetImmunityInfo()); + ImmunityInfo& immuneInfo = effect._immunityInfo; - switch (effectInfo->ApplyAuraName) + switch (effect.ApplyAuraName) { case SPELL_AURA_MECHANIC_IMMUNITY_MASK: { @@ -3448,14 +3421,6 @@ void SpellInfo::_LoadImmunityInfo() immuneInfo.SpellEffectImmune.shrink_to_fit(); _allowedMechanicMask |= immuneInfo.MechanicImmuneMask; - }; - - for (SpellEffectInfo const* effect : _effects) - { - if (!effect) - continue; - - loadImmunityInfoFn(const_cast<SpellEffectInfo*>(effect)); } if (HasAttribute(SPELL_ATTR5_USABLE_WHILE_STUNNED)) @@ -3496,9 +3461,9 @@ void SpellInfo::_LoadImmunityInfo() } } -void SpellInfo::ApplyAllSpellImmunitiesTo(Unit* target, SpellEffectInfo const* effect, bool apply) const +void SpellInfo::ApplyAllSpellImmunitiesTo(Unit* target, SpellEffectInfo const& spellEffectInfo, bool apply) const { - ImmunityInfo const* immuneInfo = effect->GetImmunityInfo(); + ImmunityInfo const* immuneInfo = spellEffectInfo.GetImmunityInfo(); if (uint32 schoolImmunity = immuneInfo->SchoolImmuneMask) { @@ -3572,12 +3537,12 @@ bool SpellInfo::CanSpellProvideImmunityAgainstAura(SpellInfo const* auraSpellInf if (!auraSpellInfo) return false; - for (SpellEffectInfo const* effectInfo : _effects) + for (SpellEffectInfo const& effectInfo : _effects) { - if (!effectInfo) + if (!effectInfo.IsEffect()) continue; - ImmunityInfo const* immuneInfo = effectInfo->GetImmunityInfo(); + ImmunityInfo const* immuneInfo = effectInfo.GetImmunityInfo(); if (!auraSpellInfo->HasAttribute(SPELL_ATTR1_UNAFFECTED_BY_SCHOOL_IMMUNE) && !auraSpellInfo->HasAttribute(SPELL_ATTR2_UNAFFECTED_BY_AURA_SCHOOL_IMMUNE)) { @@ -3595,23 +3560,19 @@ bool SpellInfo::CanSpellProvideImmunityAgainstAura(SpellInfo const* auraSpellInf return true; bool immuneToAllEffects = true; - for (SpellEffectInfo const* auraSpellEffectInfo : auraSpellInfo->GetEffects()) + for (SpellEffectInfo const& auraSpellEffectInfo : auraSpellInfo->GetEffects()) { - if (!auraSpellEffectInfo) - continue; - - uint32 effectName = auraSpellEffectInfo->Effect; - if (!effectName) + if (!auraSpellEffectInfo.IsEffect()) continue; - auto spellImmuneItr = immuneInfo->SpellEffectImmune.find(static_cast<SpellEffectName>(effectName)); + auto spellImmuneItr = immuneInfo->SpellEffectImmune.find(auraSpellEffectInfo.Effect); if (spellImmuneItr == immuneInfo->SpellEffectImmune.cend()) { immuneToAllEffects = false; break; } - if (uint32 mechanic = auraSpellEffectInfo->Mechanic) + if (uint32 mechanic = auraSpellEffectInfo.Mechanic) { if (!(immuneInfo->MechanicImmuneMask & (1 << mechanic))) { @@ -3622,14 +3583,14 @@ bool SpellInfo::CanSpellProvideImmunityAgainstAura(SpellInfo const* auraSpellInf if (!auraSpellInfo->HasAttribute(SPELL_ATTR3_IGNORE_HIT_RESULT)) { - if (uint32 auraName = auraSpellEffectInfo->ApplyAuraName) + if (AuraType auraName = auraSpellEffectInfo.ApplyAuraName) { bool isImmuneToAuraEffectApply = false; - auto auraImmuneItr = immuneInfo->AuraTypeImmune.find(static_cast<AuraType>(auraName)); + auto auraImmuneItr = immuneInfo->AuraTypeImmune.find(auraName); if (auraImmuneItr != immuneInfo->AuraTypeImmune.cend()) isImmuneToAuraEffectApply = true; - if (!isImmuneToAuraEffectApply && !auraSpellInfo->IsPositiveEffect(auraSpellEffectInfo->EffectIndex) && !auraSpellInfo->HasAttribute(SPELL_ATTR2_UNAFFECTED_BY_AURA_SCHOOL_IMMUNE)) + if (!isImmuneToAuraEffectApply && !auraSpellInfo->IsPositiveEffect(auraSpellEffectInfo.EffectIndex) && !auraSpellInfo->HasAttribute(SPELL_ATTR2_UNAFFECTED_BY_AURA_SCHOOL_IMMUNE)) { if (uint32 applyHarmfulAuraImmunityMask = immuneInfo->ApplyHarmfulAuraImmuneMask) if ((auraSpellInfo->GetSchoolMask() & applyHarmfulAuraImmunityMask) != 0) @@ -3661,19 +3622,16 @@ bool SpellInfo::SpellCancelsAuraEffect(AuraEffect const* aurEff) const if (aurEff->GetSpellInfo()->HasAttribute(SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY)) return false; - for (SpellEffectInfo const* effectInfo : _effects) + for (SpellEffectInfo const& effect : GetEffects()) { - if (!effectInfo) + if (effect.IsEffect(SPELL_EFFECT_APPLY_AURA)) continue; - if (effectInfo->Effect != SPELL_EFFECT_APPLY_AURA) - continue; - - uint32 const miscValue = static_cast<uint32>(effectInfo->MiscValue); - switch (effectInfo->ApplyAuraName) + uint32 const miscValue = static_cast<uint32>(effect.MiscValue); + switch (effect.ApplyAuraName) { case SPELL_AURA_STATE_IMMUNITY: - if (miscValue != aurEff->GetSpellEffectInfo()->ApplyAuraName) + if (miscValue != aurEff->GetAuraType()) continue; break; case SPELL_AURA_SCHOOL_IMMUNITY: @@ -3688,7 +3646,7 @@ bool SpellInfo::SpellCancelsAuraEffect(AuraEffect const* aurEff) const case SPELL_AURA_MECHANIC_IMMUNITY: if (miscValue != aurEff->GetSpellInfo()->Mechanic) { - if (miscValue != aurEff->GetSpellEffectInfo()->Mechanic) + if (miscValue != aurEff->GetSpellEffectInfo().Mechanic) continue; } break; @@ -3774,11 +3732,11 @@ uint32 SpellInfo::GetMaxTicks() const uint32 totalTicks = 0; int32 DotDuration = GetDuration(); - for (SpellEffectInfo const* effect : _effects) + for (SpellEffectInfo const& effect : GetEffects()) { - if (effect && effect->Effect == SPELL_EFFECT_APPLY_AURA) + if (effect.IsEffect(SPELL_EFFECT_APPLY_AURA)) { - switch (effect->ApplyAuraName) + switch (effect.ApplyAuraName) { case SPELL_AURA_PERIODIC_DAMAGE: case SPELL_AURA_PERIODIC_DAMAGE_PERCENT: @@ -3795,13 +3753,15 @@ uint32 SpellInfo::GetMaxTicks() const case SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE: case SPELL_AURA_PERIODIC_HEALTH_FUNNEL: // skip infinite periodics - if (effect->ApplyAuraPeriod > 0 && DotDuration > 0) + if (effect.ApplyAuraPeriod > 0 && DotDuration > 0) { - totalTicks = static_cast<uint32>(DotDuration) / effect->ApplyAuraPeriod; + totalTicks = static_cast<uint32>(DotDuration) / effect.ApplyAuraPeriod; if (HasAttribute(SPELL_ATTR5_START_PERIODIC_AT_APPLY)) ++totalTicks; } break; + default: + break; } } } @@ -4239,13 +4199,13 @@ SpellInfo const* SpellInfo::GetAuraRankForLevel(uint8 level) const return this; bool needRankSelection = false; - for (SpellEffectInfo const* effect : _effects) + for (SpellEffectInfo const& effect : GetEffects()) { - if (effect && IsPositiveEffect(effect->EffectIndex) && - (effect->Effect == SPELL_EFFECT_APPLY_AURA || - effect->Effect == SPELL_EFFECT_APPLY_AREA_AURA_PARTY || - effect->Effect == SPELL_EFFECT_APPLY_AREA_AURA_RAID) && - !effect->Scaling.Coefficient) + if (IsPositiveEffect(effect.EffectIndex) && + (effect.Effect == SPELL_EFFECT_APPLY_AURA || + effect.Effect == SPELL_EFFECT_APPLY_AREA_AURA_PARTY || + effect.Effect == SPELL_EFFECT_APPLY_AREA_AURA_RAID) && + !effect.Scaling.Coefficient) { needRankSelection = true; break; @@ -4322,20 +4282,20 @@ void SpellInfo::_InitializeExplicitTargetMask() bool dstSet = false; uint32 targetMask = Targets; // prepare target mask using effect target entries - for (SpellEffectInfo const* effect : _effects) + for (SpellEffectInfo const& effect : GetEffects()) { - if (!effect || !effect->IsEffect()) + if (!effect.IsEffect()) continue; - targetMask |= effect->TargetA.GetExplicitTargetMask(srcSet, dstSet); - targetMask |= effect->TargetB.GetExplicitTargetMask(srcSet, dstSet); + targetMask |= effect.TargetA.GetExplicitTargetMask(srcSet, dstSet); + targetMask |= effect.TargetB.GetExplicitTargetMask(srcSet, dstSet); // add explicit target flags based on spell effects which have EFFECT_IMPLICIT_TARGET_EXPLICIT and no valid target provided - if (effect->GetImplicitTargetType() != EFFECT_IMPLICIT_TARGET_EXPLICIT) + if (effect.GetImplicitTargetType() != EFFECT_IMPLICIT_TARGET_EXPLICIT) continue; // extend explicit target mask only if valid targets for effect could not be provided by target types - uint32 effectTargetMask = effect->GetMissingTargetMask(srcSet, dstSet, targetMask); + uint32 effectTargetMask = effect.GetMissingTargetMask(srcSet, dstSet, targetMask); // don't add explicit object/dest flags when spell has no max range if (GetMaxRange(true) == 0.0f && GetMaxRange(false) == 0.0f) @@ -4347,24 +4307,22 @@ void SpellInfo::_InitializeExplicitTargetMask() ExplicitTargetMask = targetMask; } -inline bool _isPositiveTarget(SpellInfo const* spellInfo, uint32 effIndex) +inline bool _isPositiveTarget(SpellEffectInfo const& effect) { - SpellEffectInfo const* effect = spellInfo->GetEffect(effIndex); - if (!effect || !effect->IsEffect()) + if (!effect.IsEffect()) return true; - return (effect->TargetA.GetCheckType() != TARGET_CHECK_ENEMY && - effect->TargetB.GetCheckType() != TARGET_CHECK_ENEMY); + return (effect.TargetA.GetCheckType() != TARGET_CHECK_ENEMY && + effect.TargetB.GetCheckType() != TARGET_CHECK_ENEMY); } -bool _isPositiveEffectImpl(SpellInfo const* spellInfo, uint32 effIndex, std::unordered_set<std::pair<SpellInfo const*, uint32>>& visited) +bool _isPositiveEffectImpl(SpellInfo const* spellInfo, SpellEffectInfo const& effect, std::unordered_set<std::pair<SpellInfo const*, SpellEffIndex>>& visited) { - SpellEffectInfo const* effect = spellInfo->GetEffect(effIndex); - if (!effect || !effect->IsEffect()) + if (!effect.IsEffect()) return true; // attribute may be already set in DB - if (!spellInfo->IsPositiveEffect(effIndex)) + if (!spellInfo->IsPositiveEffect(effect.EffectIndex)) return false; // passive auras like talents are all positive @@ -4375,9 +4333,9 @@ bool _isPositiveEffectImpl(SpellInfo const* spellInfo, uint32 effIndex, std::uno if (spellInfo->HasAttribute(SPELL_ATTR0_NEGATIVE_1)) return false; - visited.insert({ spellInfo, effIndex }); + visited.insert({ spellInfo, effect.EffectIndex }); - int32 bp = effect->CalcValue(); + int32 bp = effect.CalcValue(); switch (spellInfo->SpellFamilyName) { case SPELLFAMILY_GENERIC: @@ -4429,17 +4387,14 @@ bool _isPositiveEffectImpl(SpellInfo const* spellInfo, uint32 effIndex, std::uno if (spellInfo->HasAttribute(SPELL_ATTR1_DONT_REFRESH_DURATION_ON_RECAST)) { // check for targets, there seems to be an assortment of dummy triggering spells that should be negative - for (SpellEffectInfo const* otherEffect : spellInfo->GetEffects()) - if (otherEffect && !_isPositiveTarget(spellInfo, otherEffect->EffectIndex)) + for (SpellEffectInfo const& otherEffect : spellInfo->GetEffects()) + if (!_isPositiveTarget(otherEffect)) return false; } - for (SpellEffectInfo const* otherEffect : spellInfo->GetEffects()) + for (SpellEffectInfo const& otherEffect : spellInfo->GetEffects()) { - if (!otherEffect) - continue; - - switch (otherEffect->Effect) + switch (otherEffect.Effect) { case SPELL_EFFECT_HEAL: case SPELL_EFFECT_LEARN_SPELL: @@ -4448,17 +4403,17 @@ bool _isPositiveEffectImpl(SpellInfo const* spellInfo, uint32 effIndex, std::uno case SPELL_EFFECT_ENERGIZE_PCT: return true; case SPELL_EFFECT_INSTAKILL: - if (otherEffect->EffectIndex != effIndex && // for spells like 38044: instakill effect is negative but auras on target must count as buff - otherEffect->TargetA.GetTarget() == effect->TargetA.GetTarget() && - otherEffect->TargetB.GetTarget() == effect->TargetB.GetTarget()) + if (otherEffect.EffectIndex != effect.EffectIndex && // for spells like 38044: instakill effect is negative but auras on target must count as buff + otherEffect.TargetA.GetTarget() == effect.TargetA.GetTarget() && + otherEffect.TargetB.GetTarget() == effect.TargetB.GetTarget()) return false; default: break; } - if (otherEffect->IsAura()) + if (otherEffect.IsAura()) { - switch (otherEffect->ApplyAuraName) + switch (otherEffect.ApplyAuraName) { case SPELL_AURA_MOD_STEALTH: case SPELL_AURA_MOD_UNATTACKABLE: @@ -4473,7 +4428,7 @@ bool _isPositiveEffectImpl(SpellInfo const* spellInfo, uint32 effIndex, std::uno } } - switch (effect->Effect) + switch (effect.Effect) { case SPELL_EFFECT_WEAPON_DAMAGE: case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL: @@ -4506,12 +4461,12 @@ bool _isPositiveEffectImpl(SpellInfo const* spellInfo, uint32 effIndex, std::uno case SPELL_EFFECT_ATTACK_ME: case SPELL_EFFECT_POWER_BURN: // check targets - if (!_isPositiveTarget(spellInfo, effIndex)) + if (!_isPositiveTarget(effect)) return false; break; case SPELL_EFFECT_DISPEL: // non-positive dispel - switch (effect->MiscValue) + switch (effect.MiscValue) { case DISPEL_STEALTH: case DISPEL_INVISIBILITY: @@ -4522,14 +4477,14 @@ bool _isPositiveEffectImpl(SpellInfo const* spellInfo, uint32 effIndex, std::uno } // also check targets - if (!_isPositiveTarget(spellInfo, effIndex)) + if (!_isPositiveTarget(effect)) return false; break; case SPELL_EFFECT_DISPEL_MECHANIC: - if (!_isPositiveTarget(spellInfo, effIndex)) + if (!_isPositiveTarget(effect)) { // non-positive mechanic dispel on negative target - switch (effect->MiscValue) + switch (effect.MiscValue) { case MECHANIC_BANDAGE: case MECHANIC_SHIELD: @@ -4544,17 +4499,17 @@ bool _isPositiveEffectImpl(SpellInfo const* spellInfo, uint32 effIndex, std::uno case SPELL_EFFECT_THREAT: case SPELL_EFFECT_MODIFY_THREAT_PERCENT: // check targets AND basepoints - if (!_isPositiveTarget(spellInfo, effIndex) && bp > 0) + if (!_isPositiveTarget(effect) && bp > 0) return false; break; default: break; } - if (effect->IsAura()) + if (effect.IsAura()) { // non-positive aura use - switch (effect->ApplyAuraName) + switch (effect.ApplyAuraName) { case SPELL_AURA_MOD_DAMAGE_DONE: // dependent from basepoint sign (negative -> negative) case SPELL_AURA_MOD_STAT: @@ -4589,7 +4544,7 @@ bool _isPositiveEffectImpl(SpellInfo const* spellInfo, uint32 effIndex, std::uno case SPELL_AURA_MOD_ATTACK_POWER: case SPELL_AURA_MOD_RANGED_ATTACK_POWER: case SPELL_AURA_MOD_DAMAGE_PERCENT_DONE: - if (!_isPositiveTarget(spellInfo, effIndex) && bp < 0) + if (!_isPositiveTarget(effect) && bp < 0) return false; break; case SPELL_AURA_MOD_DAMAGE_TAKEN: // dependent from basepoint sign (positive -> negative) @@ -4603,33 +4558,30 @@ bool _isPositiveEffectImpl(SpellInfo const* spellInfo, uint32 effIndex, std::uno return false; break; case SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN: // check targets and basepoints (ex Recklessness) - if (!_isPositiveTarget(spellInfo, effIndex) && bp > 0) + if (!_isPositiveTarget(effect) && bp > 0) return false; break; case SPELL_AURA_ADD_TARGET_TRIGGER: return true; case SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE: case SPELL_AURA_PERIODIC_TRIGGER_SPELL: - if (!_isPositiveTarget(spellInfo, effIndex)) + if (!_isPositiveTarget(effect)) { - if (SpellInfo const* spellTriggeredProto = sSpellMgr->GetSpellInfo(effect->TriggerSpell, spellInfo->Difficulty)) + if (SpellInfo const* spellTriggeredProto = sSpellMgr->GetSpellInfo(effect.TriggerSpell, spellInfo->Difficulty)) { // negative targets of main spell return early - for (SpellEffectInfo const* spellTriggeredEffect : spellTriggeredProto->GetEffects()) + for (SpellEffectInfo const& spellTriggeredEffect : spellTriggeredProto->GetEffects()) { - if (!spellTriggeredEffect) - continue; - // already seen this - if (visited.count({ spellTriggeredProto, spellTriggeredEffect->EffectIndex }) > 0) + if (visited.count({ spellTriggeredProto, spellTriggeredEffect.EffectIndex }) > 0) continue; - if (!spellTriggeredEffect->IsEffect()) + if (!spellTriggeredEffect.IsEffect()) continue; // if non-positive trigger cast targeted to positive target this main cast is non-positive // this will place this spell auras as debuffs - if (_isPositiveTarget(spellTriggeredProto, spellTriggeredEffect->EffectIndex) && !_isPositiveEffectImpl(spellTriggeredProto, spellTriggeredEffect->EffectIndex, visited)) + if (_isPositiveTarget(spellTriggeredEffect) && !_isPositiveEffectImpl(spellTriggeredProto, spellTriggeredEffect, visited)) return false; } } @@ -4660,7 +4612,7 @@ bool _isPositiveEffectImpl(SpellInfo const* spellInfo, uint32 effIndex, std::uno case SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_CHANCE: case SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE: // have positive and negative spells, check target - if (!_isPositiveTarget(spellInfo, effIndex)) + if (!_isPositiveTarget(effect)) return false; break; case SPELL_AURA_MOD_CONFUSE: @@ -4682,7 +4634,7 @@ bool _isPositiveEffectImpl(SpellInfo const* spellInfo, uint32 effIndex, std::uno case SPELL_AURA_MECHANIC_IMMUNITY: { // non-positive immunities - switch (effect->MiscValue) + switch (effect.MiscValue) { case MECHANIC_BANDAGE: case MECHANIC_SHIELD: @@ -4699,7 +4651,7 @@ bool _isPositiveEffectImpl(SpellInfo const* spellInfo, uint32 effIndex, std::uno case SPELL_AURA_ADD_FLAT_MODIFIER_BY_SPELL_LABEL: case SPELL_AURA_ADD_PCT_MODIFIER_BY_SPELL_LABEL: { - switch (SpellModOp(effect->MiscValue)) + switch (SpellModOp(effect.MiscValue)) { case SpellModOp::ChangeCastTime: // dependent from basepoint sign (positive -> negative) case SpellModOp::Period: @@ -4745,25 +4697,22 @@ bool _isPositiveEffectImpl(SpellInfo const* spellInfo, uint32 effIndex, std::uno } // negative spell if triggered spell is negative - if (!effect->ApplyAuraName && effect->TriggerSpell) + if (!effect.ApplyAuraName && effect.TriggerSpell) { - if (SpellInfo const* spellTriggeredProto = sSpellMgr->GetSpellInfo(effect->TriggerSpell, spellInfo->Difficulty)) + if (SpellInfo const* spellTriggeredProto = sSpellMgr->GetSpellInfo(effect.TriggerSpell, spellInfo->Difficulty)) { // spells with at least one negative effect are considered negative // some self-applied spells have negative effects but in self casting case negative check ignored. - for (SpellEffectInfo const* spellTriggeredEffect : spellTriggeredProto->GetEffects()) + for (SpellEffectInfo const& spellTriggeredEffect : spellTriggeredProto->GetEffects()) { - if (!spellTriggeredEffect) - continue; - // already seen this - if (visited.count({ spellTriggeredProto, spellTriggeredEffect->EffectIndex }) > 0) + if (visited.count({ spellTriggeredProto, spellTriggeredEffect.EffectIndex }) > 0) continue; - if (!spellTriggeredEffect->IsEffect()) + if (!spellTriggeredEffect.IsEffect()) continue; - if (!_isPositiveEffectImpl(spellTriggeredProto, spellTriggeredEffect->EffectIndex, visited)) + if (!_isPositiveEffectImpl(spellTriggeredProto, spellTriggeredEffect, visited)) return false; } } @@ -4775,19 +4724,19 @@ bool _isPositiveEffectImpl(SpellInfo const* spellInfo, uint32 effIndex, std::uno void SpellInfo::_InitializeSpellPositivity() { - std::unordered_set<std::pair<SpellInfo const*, uint32 /*effIndex*/>> visited; + std::unordered_set<std::pair<SpellInfo const*, SpellEffIndex /*effIndex*/>> visited; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - if (!_isPositiveEffectImpl(this, i, visited)) - NegativeEffects[i] = true; + for (SpellEffectInfo const& effect : GetEffects()) + if (!_isPositiveEffectImpl(this, effect, visited)) + NegativeEffects[effect.EffectIndex] = true; // additional checks after effects marked - for (SpellEffectInfo const* effect : GetEffects()) + for (SpellEffectInfo const& effect : GetEffects()) { - if (!effect || !effect->IsEffect() || !IsPositiveEffect(effect->EffectIndex)) + if (!effect.IsEffect() || !IsPositiveEffect(effect.EffectIndex)) continue; - switch (effect->ApplyAuraName) + switch (effect.ApplyAuraName) { // has other non positive effect? // then it should be marked negative despite of targets (ex 8510, 8511, 8893, 10267) @@ -4798,8 +4747,11 @@ void SpellInfo::_InitializeSpellPositivity() case SPELL_AURA_TRANSFORM: case SPELL_AURA_MOD_ATTACKSPEED: case SPELL_AURA_MOD_DECREASE_SPEED: - if (!IsPositive()) - NegativeEffects[effect->EffectIndex] = true; + for (size_t j = effect.EffectIndex + 1; j < GetEffects().size(); ++j) + if (!IsPositiveEffect(j) + && effect.TargetA.GetTarget() == GetEffect(SpellEffIndex(j)).TargetA.GetTarget() + && effect.TargetB.GetTarget() == GetEffect(SpellEffIndex(j)).TargetB.GetTarget()) + NegativeEffects[effect.EffectIndex] = true; break; default: break; @@ -4810,21 +4762,17 @@ void SpellInfo::_InitializeSpellPositivity() void SpellInfo::_UnloadImplicitTargetConditionLists() { // find the same instances of ConditionList and delete them. - for (uint32 i = 0; i < _effects.size(); ++i) + for (SpellEffectInfo const& effect : _effects) { - if (SpellEffectInfo const* effect = _effects[i]) - { - ConditionContainer* cur = effect->ImplicitTargetConditions; - if (!cur) - continue; + ConditionContainer* cur = effect.ImplicitTargetConditions; + if (!cur) + continue; - for (uint8 j = i; j < _effects.size(); ++j) - if (SpellEffectInfo const* eff = _effects[j]) - if (eff->ImplicitTargetConditions == cur) - const_cast<SpellEffectInfo*>(eff)->ImplicitTargetConditions = nullptr; + for (size_t j = effect.EffectIndex; j < _effects.size(); ++j) + if (_effects[j].ImplicitTargetConditions == cur) + _effects[j].ImplicitTargetConditions = nullptr; - delete cur; - } + delete cur; } } diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h index dfc169ab570..a63d6b2985c 100644 --- a/src/server/game/Spells/SpellInfo.h +++ b/src/server/game/Spells/SpellInfo.h @@ -27,18 +27,18 @@ #include <boost/container/flat_set.hpp> #include <bitset> -class Unit; -class Player; +class AuraEffect; class Item; +class Player; class Spell; class SpellMgr; class SpellInfo; +class Unit; class WorldObject; -class AuraEffect; +struct Condition; struct SpellChainNode; struct SpellModifier; struct SpellTargetPosition; -struct Condition; enum WeaponAttackType : uint8; enum SpellCastTargetFlags : uint32 @@ -262,11 +262,12 @@ struct TC_GAME_API ImmunityInfo class TC_GAME_API SpellEffectInfo { + friend class SpellInfo; SpellInfo const* _spellInfo; public: - uint32 EffectIndex; - uint32 Effect; - uint32 ApplyAuraName; + SpellEffIndex EffectIndex; + SpellEffectName Effect; + AuraType ApplyAuraName; uint32 ApplyAuraPeriod; int32 BasePoints; float RealPointsPerLevel; @@ -298,7 +299,7 @@ public: float ResourceCoefficient; } Scaling; - SpellEffectInfo() : _spellInfo(nullptr), EffectIndex(0), Effect(0), ApplyAuraName(0), ApplyAuraPeriod(0), + SpellEffectInfo(SpellInfo const* spellInfo) : _spellInfo(spellInfo), EffectIndex(EFFECT_0), Effect(SPELL_EFFECT_NONE), ApplyAuraName(AuraType(0)), ApplyAuraPeriod(0), BasePoints(0), RealPointsPerLevel(0), PointsPerResource(0), Amplitude(0), ChainAmplitude(0), BonusCoefficient(0), MiscValue(0), MiscValueB(0), Mechanic(MECHANIC_NONE), PositionFacing(0), RadiusEntry(nullptr), MaxRadiusEntry(nullptr), ChainTargets(0), ItemType(0), TriggerSpell(0), @@ -346,8 +347,6 @@ private: ImmunityInfo _immunityInfo; }; -typedef std::vector<SpellEffectInfo const*> SpellEffectInfoVector; - typedef std::vector<SpellXSpellVisualEntry const*> SpellVisualVector; typedef std::unordered_map<uint32, SpellVisualVector> SpellVisualMap; @@ -571,10 +570,9 @@ class TC_GAME_API SpellInfo SpellSchoolMask GetSchoolMask() const; uint32 GetAllEffectsMechanicMask() const; - uint32 GetEffectMechanicMask(uint32 effIndex) const; + uint32 GetEffectMechanicMask(SpellEffIndex effIndex) const; uint32 GetSpellMechanicMaskByEffectMask(uint32 effectMask) const; - Mechanics GetEffectMechanic(uint32 effIndex) const; - //bool HasAnyEffectMechanic() const; + Mechanics GetEffectMechanic(SpellEffIndex effIndex) const; uint32 GetDispelMask() const; static uint32 GetDispelMask(DispelType type); uint32 GetExplicitTargetMask() const; @@ -614,8 +612,8 @@ class TC_GAME_API SpellInfo uint32 GetSpellXSpellVisualId(WorldObject const* caster = nullptr) const; uint32 GetSpellVisual(WorldObject const* caster = nullptr) const; - SpellEffectInfoVector const& GetEffects() const { return _effects; } - SpellEffectInfo const* GetEffect(uint32 index) const { return index < _effects.size() ? _effects[index] : nullptr; } + std::vector<SpellEffectInfo> const& GetEffects() const { return _effects; } + SpellEffectInfo const& GetEffect(SpellEffIndex index) const { ASSERT(index < _effects.size()); return _effects[index]; } // spell diminishing returns DiminishingGroup GetDiminishingReturnsGroupForSpell() const; @@ -624,7 +622,7 @@ class TC_GAME_API SpellInfo int32 GetDiminishingReturnsLimitDuration() const; // spell immunities - void ApplyAllSpellImmunitiesTo(Unit* target, SpellEffectInfo const* effect, bool apply) const; + void ApplyAllSpellImmunitiesTo(Unit* target, SpellEffectInfo const& spellEffectInfo, bool apply) const; bool CanSpellProvideImmunityAgainstAura(SpellInfo const* auraSpellInfo) const; bool SpellCancelsAuraEffect(AuraEffect const* aurEff) const; @@ -646,10 +644,9 @@ class TC_GAME_API SpellInfo // unloading helpers void _UnloadImplicitTargetConditionLists(); - void _UnloadSpellEffects(); private: - SpellEffectInfoVector _effects; + std::vector<SpellEffectInfo> _effects; SpellVisualVector _visuals; SpellSpecificType _spellSpecific = SPELL_SPECIFIC_NORMAL; AuraStateType _auraState = AURA_STATE_NONE; diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index 1e6d3cbd5f5..472b052a56d 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -146,21 +146,15 @@ bool SpellMgr::IsSpellValid(SpellInfo const* spellInfo, Player* player, bool msg bool needCheckReagents = false; // check effects - for (SpellEffectInfo const* effect : spellInfo->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : spellInfo->GetEffects()) { - if (!effect) - continue; - - switch (effect->Effect) + switch (spellEffectInfo.Effect) { - case 0: - continue; - // craft spell for crafting non-existed item (break client recipes list show) case SPELL_EFFECT_CREATE_ITEM: case SPELL_EFFECT_CREATE_LOOT: { - if (effect->ItemType == 0) + if (spellEffectInfo.ItemType == 0) { // skip auto-loot crafting spells, it does not need explicit item info (but has special fake items sometimes). if (!spellInfo->IsLootCrafting()) @@ -177,14 +171,14 @@ bool SpellMgr::IsSpellValid(SpellInfo const* spellInfo, Player* player, bool msg } // also possible IsLootCrafting case but fake items must exist anyway - else if (!sObjectMgr->GetItemTemplate(effect->ItemType)) + else if (!sObjectMgr->GetItemTemplate(spellEffectInfo.ItemType)) { if (msg) { if (player) - ChatHandler(player->GetSession()).PSendSysMessage("Craft spell %u has created a non-existing in DB item (Entry: %u) and then...", spellInfo->Id, effect->ItemType); + ChatHandler(player->GetSession()).PSendSysMessage("Craft spell %u has created a non-existing in DB item (Entry: %u) and then...", spellInfo->Id, spellEffectInfo.ItemType); else - TC_LOG_ERROR("sql.sql", "Craft spell %u has created a non-existing item in DB item (Entry: %u) and then...", spellInfo->Id, effect->ItemType); + TC_LOG_ERROR("sql.sql", "Craft spell %u has created a non-existing item in DB item (Entry: %u) and then...", spellInfo->Id, spellEffectInfo.ItemType); } return false; } @@ -194,20 +188,22 @@ bool SpellMgr::IsSpellValid(SpellInfo const* spellInfo, Player* player, bool msg } case SPELL_EFFECT_LEARN_SPELL: { - SpellInfo const* spellInfo2 = sSpellMgr->GetSpellInfo(effect->TriggerSpell, DIFFICULTY_NONE); + SpellInfo const* spellInfo2 = sSpellMgr->GetSpellInfo(spellEffectInfo.TriggerSpell, DIFFICULTY_NONE); if (!IsSpellValid(spellInfo2, player, msg)) { if (msg) { if (player) - ChatHandler(player->GetSession()).PSendSysMessage("Spell %u learn to broken spell %u, and then...", spellInfo->Id, effect->TriggerSpell); + ChatHandler(player->GetSession()).PSendSysMessage("Spell %u learn to broken spell %u, and then...", spellInfo->Id, spellEffectInfo.TriggerSpell); else - TC_LOG_ERROR("sql.sql", "Spell %u learn to invalid spell %u, and then...", spellInfo->Id, effect->TriggerSpell); + TC_LOG_ERROR("sql.sql", "Spell %u learn to invalid spell %u, and then...", spellInfo->Id, spellEffectInfo.TriggerSpell); } return false; } break; } + default: + break; } } @@ -980,17 +976,14 @@ void SpellMgr::LoadSpellLearnSkills() if (entry.Difficulty != DIFFICULTY_NONE) continue; - for (SpellEffectInfo const* effect : entry.GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : entry.GetEffects()) { - if (!effect) - continue; - SpellLearnSkillNode dbc_node; - switch (effect->Effect) + switch (spellEffectInfo.Effect) { case SPELL_EFFECT_SKILL: - dbc_node.skill = uint16(effect->MiscValue); - dbc_node.step = uint16(effect->CalcValue()); + dbc_node.skill = uint16(spellEffectInfo.MiscValue); + dbc_node.step = uint16(spellEffectInfo.CalcValue()); if (dbc_node.skill != SKILL_RIDING) dbc_node.value = 1; else @@ -1077,12 +1070,12 @@ void SpellMgr::LoadSpellLearnSpells() if (entry.Difficulty != DIFFICULTY_NONE) continue; - for (SpellEffectInfo const* effect : entry.GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : entry.GetEffects()) { - if (effect && effect->Effect == SPELL_EFFECT_LEARN_SPELL) + if (spellEffectInfo.IsEffect(SPELL_EFFECT_LEARN_SPELL)) { SpellLearnSpellNode dbc_node; - dbc_node.Spell = effect->TriggerSpell; + dbc_node.Spell = spellEffectInfo.TriggerSpell; dbc_node.Active = true; // all dbc based learned spells is active (show in spell book or hide by client itself) dbc_node.OverridesSpell = 0; @@ -1093,7 +1086,7 @@ void SpellMgr::LoadSpellLearnSpells() // talent or passive spells or skill-step spells auto-cast and not need dependent learning, // pet teaching spells must not be dependent learning (cast) // other required explicit dependent learning - dbc_node.AutoLearned = effect->TargetA.GetTarget() == TARGET_UNIT_PET || entry.HasAttribute(SPELL_ATTR0_CU_IS_TALENT) || entry.IsPassive() || entry.HasEffect(SPELL_EFFECT_SKILL_STEP); + dbc_node.AutoLearned = spellEffectInfo.TargetA.GetTarget() == TARGET_UNIT_PET || entry.HasAttribute(SPELL_ATTR0_CU_IS_TALENT) || entry.IsPassive() || entry.HasEffect(SPELL_EFFECT_SKILL_STEP); SpellLearnSpellMapBounds db_node_bounds = dbSpellLearnSpells.equal_range(entry.Id); @@ -1216,20 +1209,19 @@ void SpellMgr::LoadSpellTargetPositions() continue; } - SpellEffectInfo const* effect = spellInfo->GetEffect(effIndex); - if (!effect) + if (effIndex >= spellInfo->GetEffects().size()) { TC_LOG_ERROR("sql.sql", "Spell (Id: %u, EffectIndex: %u) listed in `spell_target_position` does not have an effect at index %u.", spellId, effIndex, effIndex); continue; } // target facing is in degrees for 6484 & 9268... (blizz sucks) - if (effect->PositionFacing > 2 * M_PI) - st.target_Orientation = effect->PositionFacing * float(M_PI) / 180; + if (spellInfo->GetEffect(effIndex).PositionFacing > 2 * M_PI) + st.target_Orientation = spellInfo->GetEffect(effIndex).PositionFacing * float(M_PI) / 180; else - st.target_Orientation = effect->PositionFacing; + st.target_Orientation = spellInfo->GetEffect(effIndex).PositionFacing; - if (effect->TargetA.GetTarget() == TARGET_DEST_DB || effect->TargetB.GetTarget() == TARGET_DEST_DB) + if (spellInfo->GetEffect(effIndex).TargetA.GetTarget() == TARGET_DEST_DB || spellInfo->GetEffect(effIndex).TargetB.GetTarget() == TARGET_DEST_DB) { std::pair<uint32, SpellEffIndex> key = std::make_pair(spellId, effIndex); mSpellTargetPositions[key] = st; @@ -1420,12 +1412,12 @@ void SpellMgr::LoadSpellGroupStackRules() for (uint32 spellId : spellIds) { SpellInfo const* spellInfo = AssertSpellInfo(spellId, DIFFICULTY_NONE); - for (SpellEffectInfo const* effectInfo : spellInfo->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : spellInfo->GetEffects()) { - if (!effectInfo->IsAura()) + if (!spellEffectInfo.IsAura()) continue; - uint32 auraName = effectInfo->ApplyAuraName; + uint32 auraName = spellEffectInfo.ApplyAuraName; for (std::vector<uint32> const& subGroup : SubGroups) { if (std::find(subGroup.begin(), subGroup.end(), auraName) != subGroup.end()) @@ -1616,18 +1608,18 @@ void SpellMgr::LoadSpellProcs() TC_LOG_ERROR("sql.sql", "The `spell_proc` table entry for spellId %u has wrong `HitMask` set: %u", spellInfo->Id, procEntry.HitMask); if (procEntry.HitMask && !(procEntry.ProcFlags & TAKEN_HIT_PROC_FLAG_MASK || (procEntry.ProcFlags & DONE_HIT_PROC_FLAG_MASK && (!procEntry.SpellPhaseMask || procEntry.SpellPhaseMask & (PROC_SPELL_PHASE_HIT | PROC_SPELL_PHASE_FINISH))))) TC_LOG_ERROR("sql.sql", "The `spell_proc` table entry for spellId %u has `HitMask` value defined, but it will not be used for defined `ProcFlags` and `SpellPhaseMask` values.", spellInfo->Id); - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - if ((procEntry.DisableEffectsMask & (1u << i)) && (!spellInfo->GetEffect(i) || !spellInfo->GetEffect(i)->IsAura())) - TC_LOG_ERROR("sql.sql", "The `spell_proc` table entry for spellId %u has DisableEffectsMask with effect %u, but effect %u is not an aura effect", spellInfo->Id, static_cast<uint32>(i), static_cast<uint32>(i)); + for (SpellEffectInfo const& spellEffectInfo : spellInfo->GetEffects()) + if ((procEntry.DisableEffectsMask & (1u << spellEffectInfo.EffectIndex)) && !spellEffectInfo.IsAura()) + TC_LOG_ERROR("sql.sql", "The `spell_proc` table entry for spellId %u has DisableEffectsMask with effect %u, but effect %u is not an aura effect", spellInfo->Id, static_cast<uint32>(spellEffectInfo.EffectIndex), static_cast<uint32>(spellEffectInfo.EffectIndex)); if (procEntry.AttributesMask & PROC_ATTR_REQ_SPELLMOD) { bool found = false; - for (SpellEffectInfo const* effect : spellInfo->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : spellInfo->GetEffects()) { - if (!effect || !effect->IsAura()) + if (!spellEffectInfo.IsAura()) continue; - if (effect->ApplyAuraName == SPELL_AURA_ADD_PCT_MODIFIER || effect->ApplyAuraName == SPELL_AURA_ADD_FLAT_MODIFIER) + if (spellEffectInfo.ApplyAuraName == SPELL_AURA_ADD_PCT_MODIFIER || spellEffectInfo.ApplyAuraName == SPELL_AURA_ADD_FLAT_MODIFIER) { found = true; break; @@ -1761,19 +1753,19 @@ void SpellMgr::LoadSpellProcs() bool addTriggerFlag = false; uint32 procSpellTypeMask = PROC_SPELL_TYPE_NONE; uint32 nonProcMask = 0; - for (SpellEffectInfo const* effect : spellInfo.GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : spellInfo.GetEffects()) { - if (!effect || !effect->IsEffect()) + if (!spellEffectInfo.IsEffect()) continue; - uint32 auraName = effect->ApplyAuraName; + uint32 auraName = spellEffectInfo.ApplyAuraName; if (!auraName) continue; if (!isTriggerAura[auraName]) { // explicitly disable non proccing auras to avoid losing charges on self proc - nonProcMask |= 1 << effect->EffectIndex; + nonProcMask |= 1 << spellEffectInfo.EffectIndex; continue; } @@ -1799,9 +1791,9 @@ void SpellMgr::LoadSpellProcs() if (!procSpellTypeMask) { - for (SpellEffectInfo const* effectInfo : spellInfo.GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : spellInfo.GetEffects()) { - if (effectInfo && effectInfo->IsAura()) + if (spellEffectInfo.IsAura()) { TC_LOG_ERROR("sql.sql", "Spell Id %u has DBC ProcFlags %u, but it's of non-proc aura type, it probably needs an entry in `spell_proc` table to be handled correctly.", spellInfo.Id, spellInfo.ProcFlags); break; @@ -1815,9 +1807,9 @@ void SpellMgr::LoadSpellProcs() procEntry.SchoolMask = 0; procEntry.ProcFlags = spellInfo.ProcFlags; procEntry.SpellFamilyName = 0; - for (SpellEffectInfo const* effect : spellInfo.GetEffects()) - if (effect && effect->IsEffect() && isTriggerAura[effect->ApplyAuraName]) - procEntry.SpellFamilyMask |= effect->SpellClassMask; + for (SpellEffectInfo const& spellEffectInfo : spellInfo.GetEffects()) + if (spellEffectInfo.IsEffect() && isTriggerAura[spellEffectInfo.ApplyAuraName]) + procEntry.SpellFamilyMask |= spellEffectInfo.SpellClassMask; if (procEntry.SpellFamilyMask) procEntry.SpellFamilyName = spellInfo.SpellFamilyName; @@ -1826,12 +1818,12 @@ void SpellMgr::LoadSpellProcs() procEntry.SpellPhaseMask = PROC_SPELL_PHASE_HIT; procEntry.HitMask = PROC_HIT_NONE; // uses default proc @see SpellMgr::CanSpellTriggerProcOnEvent - for (SpellEffectInfo const* effect : spellInfo.GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : spellInfo.GetEffects()) { - if (!effect || !effect->IsAura()) + if (!spellEffectInfo.IsAura()) continue; - switch (effect->ApplyAuraName) + switch (spellEffectInfo.ApplyAuraName) { // Reflect auras should only proc off reflects case SPELL_AURA_REFLECT_SPELLS: @@ -1951,7 +1943,7 @@ void SpellMgr::LoadSpellPetAuras() Field* fields = result->Fetch(); uint32 spell = fields[0].GetUInt32(); - uint8 eff = fields[1].GetUInt8(); + SpellEffIndex eff = SpellEffIndex(fields[1].GetUInt8()); uint32 pet = fields[2].GetUInt32(); uint32 aura = fields[3].GetUInt32(); @@ -1966,18 +1958,17 @@ void SpellMgr::LoadSpellPetAuras() TC_LOG_ERROR("sql.sql", "The spell %u listed in `spell_pet_auras` does not exist.", spell); continue; } - SpellEffectInfo const* effect = spellInfo->GetEffect(eff); - if (!effect) + if (eff >= spellInfo->GetEffects().size()) { TC_LOG_ERROR("spells", "The spell %u listed in `spell_pet_auras` does not have any effect at index %u", spell, uint32(eff)); continue; } - if (effect->Effect != SPELL_EFFECT_DUMMY && - (effect->Effect != SPELL_EFFECT_APPLY_AURA || - effect->ApplyAuraName != SPELL_AURA_DUMMY)) + if (spellInfo->GetEffect(eff).Effect != SPELL_EFFECT_DUMMY && + (spellInfo->GetEffect(eff).Effect != SPELL_EFFECT_APPLY_AURA || + spellInfo->GetEffect(eff).ApplyAuraName != SPELL_AURA_DUMMY)) { - TC_LOG_ERROR("spells", "Spell %u listed in `spell_pet_auras` does not have any dummy aura or dummy effect", spell); + TC_LOG_ERROR("spells", "The spell %u listed in `spell_pet_auras` does not have any dummy aura or dummy effect.", spell); continue; } @@ -1988,7 +1979,7 @@ void SpellMgr::LoadSpellPetAuras() continue; } - PetAura pa(pet, aura, effect->TargetA.GetTarget() == TARGET_UNIT_PET, effect->CalcValue()); + PetAura pa(pet, aura, spellInfo->GetEffect(eff).TargetA.GetTarget() == TARGET_UNIT_PET, spellInfo->GetEffect(eff).CalcValue()); mSpellPetAuraMap[(spell<<8) + eff] = pa; } @@ -2016,11 +2007,11 @@ void SpellMgr::LoadEnchantCustomAttr() if (!spellInfo.HasAttribute(SPELL_ATTR2_PRESERVE_ENCHANT_IN_ARENA) || !spellInfo.HasAttribute(SPELL_ATTR0_NOT_SHAPESHIFT)) continue; - for (SpellEffectInfo const* effect : spellInfo.GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : spellInfo.GetEffects()) { - if (effect && effect->Effect == SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) + if (spellEffectInfo.Effect == SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) { - uint32 enchId = effect->MiscValue; + uint32 enchId = spellEffectInfo.MiscValue; SpellItemEnchantmentEntry const* ench = sSpellItemEnchantmentStore.LookupEntry(enchId); if (!ench) continue; @@ -2108,10 +2099,10 @@ void SpellMgr::LoadSpellLinked() } if (effect >= 0) - for (SpellEffectInfo const* eff : spellInfo->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : spellInfo->GetEffects()) { - if (eff && eff->CalcValue() == abs(effect)) - TC_LOG_ERROR("sql.sql", "The spell %u Effect: %u listed in `spell_linked_spell` has same bp%u like effect (possible hack)", abs(trigger), abs(effect), eff->EffectIndex); + if (spellEffectInfo.CalcValue() == abs(effect)) + TC_LOG_ERROR("sql.sql", "The spell %u Effect: %u listed in `spell_linked_spell` has same bp%u like effect (possible hack).", abs(trigger), abs(effect), uint32(spellEffectInfo.EffectIndex)); } spellInfo = GetSpellInfo(abs(effect), DIFFICULTY_NONE); @@ -2252,11 +2243,11 @@ void SpellMgr::LoadPetDefaultSpells() { if (spellEntry.Difficulty != DIFFICULTY_NONE) - for (SpellEffectInfo const* effect : spellEntry.GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : spellEntry.GetEffects()) { - if (effect && (effect->Effect == SPELL_EFFECT_SUMMON || effect->Effect == SPELL_EFFECT_SUMMON_PET)) + if (spellEffectInfo.IsEffect(SPELL_EFFECT_SUMMON) || spellEffectInfo.IsEffect(SPELL_EFFECT_SUMMON_PET)) { - uint32 creature_id = effect->MiscValue; + uint32 creature_id = spellEffectInfo.MiscValue; CreatureTemplate const* cInfo = sObjectMgr->GetCreatureTemplate(creature_id); if (!cInfo) continue; @@ -2952,12 +2943,9 @@ void SpellMgr::LoadSpellInfoCustomAttributes() for (SpellInfo const& spellInfo : mSpellInfoMap) { SpellInfo* spellInfoMutable = const_cast<SpellInfo*>(&spellInfo); - for (SpellEffectInfo const* effect : spellInfoMutable->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : spellInfoMutable->GetEffects()) { - if (!effect) - continue; - - switch (effect->ApplyAuraName) + switch (spellEffectInfo.ApplyAuraName) { case SPELL_AURA_MOD_POSSESS: case SPELL_AURA_MOD_CONFUSE: @@ -2979,9 +2967,11 @@ void SpellMgr::LoadSpellInfoCustomAttributes() case SPELL_AURA_POWER_BURN: spellInfoMutable->AttributesCu |= SPELL_ATTR0_CU_NO_INITIAL_THREAT; break; + default: + break; } - switch (effect->ApplyAuraName) + switch (spellEffectInfo.ApplyAuraName) { case SPELL_AURA_OPEN_STABLE: // No point in saving this, since the stable dialog can't be open on aura load anyway. // Auras that require both caster & target to be in world cannot be saved @@ -2996,9 +2986,11 @@ void SpellMgr::LoadSpellInfoCustomAttributes() case SPELL_AURA_BATTLEGROUND_PLAYER_POSITION_FACTIONAL: spellInfoMutable->AttributesCu |= SPELL_ATTR0_CU_AURA_CANNOT_BE_SAVED; break; + default: + break; } - switch (effect->Effect) + switch (spellEffectInfo.Effect) { case SPELL_EFFECT_SCHOOL_DAMAGE: case SPELL_EFFECT_HEALTH_LEECH: @@ -3013,9 +3005,11 @@ void SpellMgr::LoadSpellInfoCustomAttributes() case SPELL_EFFECT_DAMAGE_FROM_MAX_HEALTH_PCT: spellInfoMutable->AttributesCu |= SPELL_ATTR0_CU_CAN_CRIT; break; + default: + break; } - switch (effect->Effect) + switch (spellEffectInfo.Effect) { case SPELL_EFFECT_SCHOOL_DAMAGE: case SPELL_EFFECT_WEAPON_DAMAGE: @@ -3053,7 +3047,7 @@ void SpellMgr::LoadSpellInfoCustomAttributes() // only enchanting profession enchantments procs can stack if (IsPartOfSkillLine(SKILL_ENCHANTING, spellInfo.Id)) { - uint32 enchantId = effect->MiscValue; + uint32 enchantId = spellEffectInfo.MiscValue; SpellItemEnchantmentEntry const* enchant = sSpellItemEnchantmentStore.LookupEntry(enchantId); if (!enchant) break; @@ -3077,6 +3071,8 @@ void SpellMgr::LoadSpellInfoCustomAttributes() } break; } + default: + break; } } @@ -3084,67 +3080,64 @@ void SpellMgr::LoadSpellInfoCustomAttributes() if (!spellInfoMutable->HasAttribute(SPELL_ATTR3_IGNORE_HIT_RESULT)) { bool setFlag = false; - for (SpellEffectInfo const* effect : spellInfoMutable->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : spellInfoMutable->GetEffects()) { - if (!effect) - continue; - - if (effect->IsEffect()) + if (spellEffectInfo.IsEffect()) { - switch (effect->Effect) + switch (spellEffectInfo.Effect) { - case SPELL_EFFECT_SCHOOL_DAMAGE: - case SPELL_EFFECT_WEAPON_DAMAGE: - case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL: - case SPELL_EFFECT_NORMALIZED_WEAPON_DMG: - case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE: - case SPELL_EFFECT_TRIGGER_SPELL: - case SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE: - break; - case SPELL_EFFECT_PERSISTENT_AREA_AURA: - case SPELL_EFFECT_APPLY_AURA: - case SPELL_EFFECT_APPLY_AREA_AURA_PARTY: - case SPELL_EFFECT_APPLY_AREA_AURA_RAID: - case SPELL_EFFECT_APPLY_AREA_AURA_FRIEND: - case SPELL_EFFECT_APPLY_AREA_AURA_ENEMY: - case SPELL_EFFECT_APPLY_AREA_AURA_PET: - case SPELL_EFFECT_APPLY_AREA_AURA_OWNER: - case SPELL_EFFECT_APPLY_AURA_ON_PET: - case SPELL_EFFECT_APPLY_AREA_AURA_SUMMONS: - case SPELL_EFFECT_APPLY_AREA_AURA_PARTY_NONRANDOM: - if (effect->ApplyAuraName == SPELL_AURA_PERIODIC_DAMAGE || - effect->ApplyAuraName == SPELL_AURA_PERIODIC_DAMAGE_PERCENT || - effect->ApplyAuraName == SPELL_AURA_DUMMY || - effect->ApplyAuraName == SPELL_AURA_PERIODIC_LEECH || - effect->ApplyAuraName == SPELL_AURA_PERIODIC_HEALTH_FUNNEL || - effect->ApplyAuraName == SPELL_AURA_PERIODIC_DUMMY) - break; - /* fallthrough */ - default: - { - // No value and not interrupt cast or crowd control without SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY flag - if (!effect->CalcValue() && !((effect->Effect == SPELL_EFFECT_INTERRUPT_CAST || spellInfoMutable->HasAttribute(SPELL_ATTR0_CU_AURA_CC)) && !spellInfoMutable->HasAttribute(SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY))) + case SPELL_EFFECT_SCHOOL_DAMAGE: + case SPELL_EFFECT_WEAPON_DAMAGE: + case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL: + case SPELL_EFFECT_NORMALIZED_WEAPON_DMG: + case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE: + case SPELL_EFFECT_TRIGGER_SPELL: + case SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE: break; + case SPELL_EFFECT_PERSISTENT_AREA_AURA: + case SPELL_EFFECT_APPLY_AURA: + case SPELL_EFFECT_APPLY_AREA_AURA_PARTY: + case SPELL_EFFECT_APPLY_AREA_AURA_RAID: + case SPELL_EFFECT_APPLY_AREA_AURA_FRIEND: + case SPELL_EFFECT_APPLY_AREA_AURA_ENEMY: + case SPELL_EFFECT_APPLY_AREA_AURA_PET: + case SPELL_EFFECT_APPLY_AREA_AURA_OWNER: + case SPELL_EFFECT_APPLY_AURA_ON_PET: + case SPELL_EFFECT_APPLY_AREA_AURA_SUMMONS: + case SPELL_EFFECT_APPLY_AREA_AURA_PARTY_NONRANDOM: + if (spellEffectInfo.ApplyAuraName == SPELL_AURA_PERIODIC_DAMAGE || + spellEffectInfo.ApplyAuraName == SPELL_AURA_PERIODIC_DAMAGE_PERCENT || + spellEffectInfo.ApplyAuraName == SPELL_AURA_DUMMY || + spellEffectInfo.ApplyAuraName == SPELL_AURA_PERIODIC_LEECH || + spellEffectInfo.ApplyAuraName == SPELL_AURA_PERIODIC_HEALTH_FUNNEL || + spellEffectInfo.ApplyAuraName == SPELL_AURA_PERIODIC_DUMMY) + break; + /* fallthrough */ + default: + { + // No value and not interrupt cast or crowd control without SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY flag + if (!spellEffectInfo.CalcValue() && !((spellEffectInfo.Effect == SPELL_EFFECT_INTERRUPT_CAST || spellInfoMutable->HasAttribute(SPELL_ATTR0_CU_AURA_CC)) && !spellInfoMutable->HasAttribute(SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY))) + break; - // Sindragosa Frost Breath - if (spellInfoMutable->Id == 69649 || spellInfoMutable->Id == 71056 || spellInfoMutable->Id == 71057 || spellInfoMutable->Id == 71058 || spellInfoMutable->Id == 73061 || spellInfoMutable->Id == 73062 || spellInfoMutable->Id == 73063 || spellInfoMutable->Id == 73064) - break; + // Sindragosa Frost Breath + if (spellInfoMutable->Id == 69649 || spellInfoMutable->Id == 71056 || spellInfoMutable->Id == 71057 || spellInfoMutable->Id == 71058 || spellInfoMutable->Id == 73061 || spellInfoMutable->Id == 73062 || spellInfoMutable->Id == 73063 || spellInfoMutable->Id == 73064) + break; - // Frostbolt - if (spellInfoMutable->SpellFamilyName == SPELLFAMILY_MAGE && (spellInfoMutable->SpellFamilyFlags[0] & 0x20)) - break; + // Frostbolt + if (spellInfoMutable->SpellFamilyName == SPELLFAMILY_MAGE && (spellInfoMutable->SpellFamilyFlags[0] & 0x20)) + break; - // Frost Fever - if (spellInfoMutable->Id == 55095) - break; + // Frost Fever + if (spellInfoMutable->Id == 55095) + break; - // Haunt - if (spellInfoMutable->SpellFamilyName == SPELLFAMILY_WARLOCK && (spellInfoMutable->SpellFamilyFlags[1] & 0x40000)) - break; + // Haunt + if (spellInfoMutable->SpellFamilyName == SPELLFAMILY_WARLOCK && (spellInfoMutable->SpellFamilyFlags[1] & 0x40000)) + break; - setFlag = true; - break; - } + setFlag = true; + break; + } } if (setFlag) @@ -3203,18 +3196,15 @@ void SpellMgr::LoadSpellInfoCustomAttributes() { bool allNonBinary = true; bool overrideAttr = false; - for (SpellEffectInfo const* effect : spellInfoMutable->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : spellInfoMutable->GetEffects()) { - if (!effect) - continue; - - if (effect->IsAura() && effect->TriggerSpell) + if (spellEffectInfo.IsAura() && spellEffectInfo.TriggerSpell) { - switch (effect->ApplyAuraName) + switch (spellEffectInfo.ApplyAuraName) { case SPELL_AURA_PERIODIC_TRIGGER_SPELL: case SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE: - if (SpellInfo const* triggerSpell = sSpellMgr->GetSpellInfo(effect->TriggerSpell, DIFFICULTY_NONE)) + if (SpellInfo const* triggerSpell = sSpellMgr->GetSpellInfo(spellEffectInfo.TriggerSpell, DIFFICULTY_NONE)) { overrideAttr = true; if (triggerSpell->HasAttribute(SPELL_ATTR0_CU_BINARY_SPELL)) @@ -3259,14 +3249,13 @@ inline void ApplySpellFix(std::initializer_list<uint32> spellIds, void(*fix)(Spe inline void ApplySpellEffectFix(SpellInfo* spellInfo, SpellEffIndex effectIndex, void(*fix)(SpellEffectInfo*)) { - SpellEffectInfo const* effect = spellInfo->GetEffect(effectIndex); - if (!effect) + if (spellInfo->GetEffects().size() <= effectIndex) { TC_LOG_ERROR("server.loading", "Spell effect info correction specified for non-existing effect %u of spell %u", uint32(effectIndex), spellInfo->Id); return; } - fix(const_cast<SpellEffectInfo*>(effect)); + fix(const_cast<SpellEffectInfo*>(&spellInfo->GetEffect(effectIndex))); } void SpellMgr::LoadSpellInfoCorrections() @@ -3427,7 +3416,7 @@ void SpellMgr::LoadSpellInfoCorrections() { ApplySpellEffectFix(spellInfo, EFFECT_0, [](SpellEffectInfo* spellEffectInfo) { - spellEffectInfo->Effect = 0; + spellEffectInfo->Effect = SPELL_EFFECT_NONE; }); }); @@ -3765,7 +3754,7 @@ void SpellMgr::LoadSpellInfoCorrections() //! HACK: This spell break quest complete for alliance and on retail not used ApplySpellEffectFix(spellInfo, EFFECT_0, [](SpellEffectInfo* spellEffectInfo) { - spellEffectInfo->Effect = 0; + spellEffectInfo->Effect = SPELL_EFFECT_NONE; }); }); @@ -4056,7 +4045,7 @@ void SpellMgr::LoadSpellInfoCorrections() // this spell initially granted Shadow damage immunity, however it was removed but the data was left in client ApplySpellEffectFix(spellInfo, EFFECT_2, [](SpellEffectInfo* spellEffectInfo) { - spellEffectInfo->Effect = 0; + spellEffectInfo->Effect = SPELL_EFFECT_NONE; }); }); @@ -4098,7 +4087,7 @@ void SpellMgr::LoadSpellInfoCorrections() // THIS IS HERE BECAUSE COOLDOWN ON CREATURE PROCS WERE NOT IMPLEMENTED WHEN THE SCRIPT WAS WRITTEN ApplySpellEffectFix(spellInfo, EFFECT_1, [](SpellEffectInfo* spellEffectInfo) { - spellEffectInfo->Effect = 0; + spellEffectInfo->Effect = SPELL_EFFECT_NONE; }); }); @@ -4477,7 +4466,7 @@ void SpellMgr::LoadSpellInfoCorrections() // Until we figure out what it's actually used for we disable it. ApplySpellEffectFix(spellInfo, EFFECT_2, [](SpellEffectInfo* spellEffectInfo) { - spellEffectInfo->Effect = 0; + spellEffectInfo->Effect = SPELL_EFFECT_NONE; }); }); @@ -4498,26 +4487,24 @@ void SpellMgr::LoadSpellInfoCorrections() if (!spellInfo) continue; - for (SpellEffectInfo const* effect : spellInfo->GetEffects()) + // Fix range for trajectory triggered spell + for (SpellEffectInfo const& spellEffectInfo : spellInfo->GetEffects()) { - if (!effect) - continue; - - if (effect->IsEffect() && (effect->TargetA.GetTarget() == TARGET_DEST_TRAJ || effect->TargetB.GetTarget() == TARGET_DEST_TRAJ)) + if (spellEffectInfo.IsEffect() && (spellEffectInfo.TargetA.GetTarget() == TARGET_DEST_TRAJ || spellEffectInfo.TargetB.GetTarget() == TARGET_DEST_TRAJ)) { // Get triggered spell if any - if (SpellInfo* spellInfoTrigger = const_cast<SpellInfo*>(GetSpellInfo(effect->TriggerSpell, DIFFICULTY_NONE))) + for (SpellInfo const& spellInfoTrigger : _GetSpellInfo(spellEffectInfo.TriggerSpell)) { float maxRangeMain = spellInfo->GetMaxRange(); - float maxRangeTrigger = spellInfoTrigger->GetMaxRange(); + float maxRangeTrigger = spellInfoTrigger.GetMaxRange(); // check if triggered spell has enough max range to cover trajectory if (maxRangeTrigger < maxRangeMain) - spellInfoTrigger->RangeEntry = spellInfo->RangeEntry; + const_cast<SpellInfo&>(spellInfoTrigger).RangeEntry = spellInfo->RangeEntry; } } - switch (effect->Effect) + switch (spellEffectInfo.Effect) { case SPELL_EFFECT_CHARGE: case SPELL_EFFECT_CHARGE_DEST: @@ -4527,17 +4514,19 @@ void SpellMgr::LoadSpellInfoCorrections() if (!spellInfo->Speed && !spellInfo->SpellFamilyName && !spellInfo->HasAttribute(SPELL_ATTR9_SPECIAL_DELAY_CALCULATION)) spellInfo->Speed = SPEED_CHARGE; break; + default: + break; } - if (effect->TargetA.GetSelectionCategory() == TARGET_SELECT_CATEGORY_CONE || effect->TargetB.GetSelectionCategory() == TARGET_SELECT_CATEGORY_CONE) + if (spellEffectInfo.TargetA.GetSelectionCategory() == TARGET_SELECT_CATEGORY_CONE || spellEffectInfo.TargetB.GetSelectionCategory() == TARGET_SELECT_CATEGORY_CONE) if (G3D::fuzzyEq(spellInfo->ConeAngle, 0.f)) spellInfo->ConeAngle = 90.f; // Area auras may not target area (they're self cast) - if (effect->IsAreaAuraEffect() && effect->IsTargetingArea()) + if (spellEffectInfo.IsAreaAuraEffect() && spellEffectInfo.IsTargetingArea()) { - const_cast<SpellEffectInfo*>(effect)->TargetA = SpellImplicitTargetInfo(TARGET_UNIT_CASTER); - const_cast<SpellEffectInfo*>(effect)->TargetB = SpellImplicitTargetInfo(0); + const_cast<SpellEffectInfo&>(spellEffectInfo).TargetA = SpellImplicitTargetInfo(TARGET_UNIT_CASTER); + const_cast<SpellEffectInfo&>(spellEffectInfo).TargetB = SpellImplicitTargetInfo(0); } } diff --git a/src/server/game/Spells/SpellScript.cpp b/src/server/game/Spells/SpellScript.cpp index 3012aeffba5..cc397652093 100644 --- a/src/server/game/Spells/SpellScript.cpp +++ b/src/server/game/Spells/SpellScript.cpp @@ -118,32 +118,25 @@ bool _SpellScript::EffectHook::IsEffectAffected(SpellInfo const* spellEntry, uin std::string _SpellScript::EffectHook::EffIndexToString() const { - switch (effIndex) - { - case EFFECT_ALL: - return "EFFECT_ALL"; - case EFFECT_FIRST_FOUND: - return "EFFECT_FIRST_FOUND"; - case EFFECT_0: - return "EFFECT_0"; - case EFFECT_1: - return "EFFECT_1"; - case EFFECT_2: - return "EFFECT_2"; - } + if (effIndex == EFFECT_ALL) + return "EFFECT_ALL"; + if (effIndex == EFFECT_FIRST_FOUND) + return "EFFECT_FIRST_FOUND"; + if (effIndex < MAX_SPELL_EFFECTS) + return Trinity::StringFormat("EFFECT_%u", uint32(effIndex)); return "Invalid Value"; } bool _SpellScript::EffectNameCheck::Check(SpellInfo const* spellEntry, uint8 effIndex) const { - SpellEffectInfo const* effect = spellEntry->GetEffect(effIndex); - if (!effect) + if (spellEntry->GetEffects().size() <= effIndex) return false; - if (!effect->Effect && !effName) + SpellEffectInfo const& spellEffectInfo = spellEntry->GetEffect(SpellEffIndex(effIndex)); + if (!spellEffectInfo.Effect && !effName) return true; - if (!effect->Effect) + if (!spellEffectInfo.Effect) return false; - return (effName == SPELL_EFFECT_ANY) || (effect->Effect == effName); + return (effName == SPELL_EFFECT_ANY) || (spellEffectInfo.Effect == effName); } std::string _SpellScript::EffectNameCheck::ToString() const @@ -161,14 +154,14 @@ std::string _SpellScript::EffectNameCheck::ToString() const bool _SpellScript::EffectAuraNameCheck::Check(SpellInfo const* spellEntry, uint8 effIndex) const { - SpellEffectInfo const* effect = spellEntry->GetEffect(effIndex); - if (!effect) + if (spellEntry->GetEffects().size() <= effIndex) return false; - if (!effect->ApplyAuraName && !effAurName) + SpellEffectInfo const& spellEffectInfo = spellEntry->GetEffect(SpellEffIndex(effIndex)); + if (!spellEffectInfo.ApplyAuraName && !effAurName) return true; - if (!effect->ApplyAuraName) + if (!spellEffectInfo.ApplyAuraName) return false; - return (effAurName == SPELL_AURA_ANY) || (effect->ApplyAuraName == effAurName); + return (effAurName == SPELL_AURA_ANY) || (spellEffectInfo.ApplyAuraName == effAurName); } std::string _SpellScript::EffectAuraNameCheck::ToString() const @@ -270,12 +263,12 @@ bool SpellScript::TargetHook::CheckEffect(SpellInfo const* spellEntry, uint8 eff if (!targetType) return false; - SpellEffectInfo const* effect = spellEntry->GetEffect(effIndexToCheck); - if (!effect) + if (spellEntry->GetEffects().size() <= effIndexToCheck) return false; - if (effect->TargetA.GetTarget() != targetType && - effect->TargetB.GetTarget() != targetType) + SpellEffectInfo const& spellEffectInfo = spellEntry->GetEffect(SpellEffIndex(effIndexToCheck)); + if (spellEffectInfo.TargetA.GetTarget() != targetType && + spellEffectInfo.TargetB.GetTarget() != targetType) return false; SpellImplicitTargetInfo targetInfo(targetType); @@ -485,6 +478,16 @@ SpellInfo const* SpellScript::GetSpellInfo() const return m_spell->GetSpellInfo(); } +SpellEffectInfo const& SpellScript::GetEffectInfo(SpellEffIndex effIndex) const +{ + return GetSpellInfo()->GetEffect(effIndex); +} + +SpellValue const* SpellScript::GetSpellValue() const +{ + return m_spell->m_spellValue; +} + WorldLocation const* SpellScript::GetExplTargetDest() const { if (m_spell->m_targets.HasDst()) @@ -706,11 +709,11 @@ void SpellScript::PreventHitDefaultEffect(SpellEffIndex effIndex) m_hitPreventDefaultEffectMask |= 1 << effIndex; } -SpellEffectInfo const* SpellScript::GetEffectInfo() const +SpellEffectInfo const& SpellScript::GetEffectInfo() const { ASSERT(IsInEffectHook(), "Script: `%s` Spell: `%u`: function SpellScript::GetEffectInfo was called, but function has no effect in current hook!", m_scriptName->c_str(), m_scriptSpellId); - return m_spell->effectInfo; + return *m_spell->effectInfo; } int32 SpellScript::GetEffectValue() const @@ -772,16 +775,6 @@ Difficulty SpellScript::GetCastDifficulty() const return m_spell->GetCastDifficulty(); } -SpellValue const* SpellScript::GetSpellValue() const -{ - return m_spell->m_spellValue; -} - -SpellEffectInfo const* SpellScript::GetEffectInfo(SpellEffIndex effIndex) const -{ - return GetSpellInfo()->GetEffect(effIndex); -} - bool AuraScript::_Validate(SpellInfo const* entry) { for (auto itr = DoCheckAreaTarget.begin(); itr != DoCheckAreaTarget.end(); ++itr) @@ -1154,6 +1147,11 @@ SpellInfo const* AuraScript::GetSpellInfo() const return m_aura->GetSpellInfo(); } +SpellEffectInfo const& AuraScript::GetEffectInfo(SpellEffIndex effIndex) const +{ + return m_aura->GetSpellInfo()->GetEffect(effIndex); +} + uint32 AuraScript::GetId() const { return m_aura->GetId(); diff --git a/src/server/game/Spells/SpellScript.h b/src/server/game/Spells/SpellScript.h index e4c3cca9387..b217764b552 100644 --- a/src/server/game/Spells/SpellScript.h +++ b/src/server/game/Spells/SpellScript.h @@ -413,8 +413,8 @@ class TC_GAME_API SpellScript : public _SpellScript GameObject* GetGObjCaster() const; Unit* GetOriginalCaster() const; SpellInfo const* GetSpellInfo() const; + SpellEffectInfo const& GetEffectInfo(SpellEffIndex effIndex) const; SpellValue const* GetSpellValue() const; - SpellEffectInfo const* GetEffectInfo(SpellEffIndex effIndex) const; // methods useable after spell is prepared // accessors to the explicit targets of the spell @@ -490,7 +490,7 @@ class TC_GAME_API SpellScript : public _SpellScript void PreventHitDefaultEffect(SpellEffIndex effIndex); // method available only in EffectHandler method - SpellEffectInfo const* GetEffectInfo() const; + SpellEffectInfo const& GetEffectInfo() const; int32 GetEffectValue() const; void SetEffectValue(int32 value); @@ -927,6 +927,7 @@ class TC_GAME_API AuraScript : public _SpellScript // returns proto of the spell SpellInfo const* GetSpellInfo() const; + SpellEffectInfo const& GetEffectInfo(SpellEffIndex effIndex) const; // returns spellid of the spell uint32 GetId() const; |
