diff options
26 files changed, 465 insertions, 470 deletions
diff --git a/src/server/game/AI/CoreAI/UnitAI.cpp b/src/server/game/AI/CoreAI/UnitAI.cpp index f98e9581591..79d847cfe41 100644 --- a/src/server/game/AI/CoreAI/UnitAI.cpp +++ b/src/server/game/AI/CoreAI/UnitAI.cpp @@ -209,9 +209,9 @@ void UnitAI::FillAISpellInfo() if (spellInfo->GetMaxRange(false)) { - for (SpellEffectInfo const& Effect : spellInfo->Effects) + for (SpellEffectInfo const& effect : spellInfo->GetEffects()) { - uint32 targetType = Effect.TargetA.GetTarget(); + uint32 targetType = effect.TargetA.GetTarget(); if (targetType == TARGET_UNIT_TARGET_ENEMY || targetType == TARGET_DEST_TARGET_ENEMY) @@ -219,7 +219,7 @@ void UnitAI::FillAISpellInfo() else if (targetType == TARGET_UNIT_DEST_AREA_ENEMY) UPDATE_TARGET(AITARGET_ENEMY) - if (Effect.Effect == SPELL_EFFECT_APPLY_AURA) + if (effect.Effect == SPELL_EFFECT_APPLY_AURA) { if (targetType == TARGET_UNIT_TARGET_ENEMY) UPDATE_TARGET(AITARGET_DEBUFF) diff --git a/src/server/game/Chat/HyperlinkTags.cpp b/src/server/game/Chat/HyperlinkTags.cpp index acc9139f9f7..5c343a9abe9 100644 --- a/src/server/game/Chat/HyperlinkTags.cpp +++ b/src/server/game/Chat/HyperlinkTags.cpp @@ -225,6 +225,6 @@ bool Trinity::Hyperlinks::LinkTags::trade::StoreTo(TradeskillLinkData& val, std: if (!t.TryConsumeTo(spellId)) return false; val.Spell = sSpellMgr->GetSpellInfo(spellId); - return (val.Spell && val.Spell->Effects[0].Effect == SPELL_EFFECT_TRADE_SKILL && t.TryConsumeTo(val.CurValue) && + return (val.Spell && val.Spell->GetEffect(EFFECT_0).Effect == SPELL_EFFECT_TRADE_SKILL && t.TryConsumeTo(val.CurValue) && t.TryConsumeTo(val.MaxValue) && t.TryConsumeTo(val.Owner) && t.TryConsumeTo(val.KnownRecipes) && t.IsEmpty()); } diff --git a/src/server/game/Conditions/ConditionMgr.cpp b/src/server/game/Conditions/ConditionMgr.cpp index 5a5b66b9b30..eb81bcba8cb 100644 --- a/src/server/game/Conditions/ConditionMgr.cpp +++ b/src/server/game/Conditions/ConditionMgr.cpp @@ -1360,34 +1360,34 @@ bool ConditionMgr::addToSpellImplicitTargetConditions(Condition* cond) const uint32 conditionEffMask = cond->SourceGroup; SpellInfo* spellInfo = const_cast<SpellInfo*>(sSpellMgr->AssertSpellInfo(cond->SourceEntry)); std::list<uint32> sharedMasks; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const& spellEffectInfo : spellInfo->GetEffects()) { // additional checks by condition type - if (conditionEffMask & (1 << i)) + if (conditionEffMask & (1 << spellEffectInfo.EffectIndex)) { switch (cond->ConditionType) { case CONDITION_OBJECT_ENTRY_GUID: { - uint32 implicitTargetMask = GetTargetFlagMask(spellInfo->Effects[i].TargetA.GetObjectType()) | GetTargetFlagMask(spellInfo->Effects[i].TargetB.GetObjectType()); + uint32 implicitTargetMask = GetTargetFlagMask(spellEffectInfo.TargetA.GetObjectType()) | GetTargetFlagMask(spellEffectInfo.TargetB.GetObjectType()); if ((implicitTargetMask & TARGET_FLAG_UNIT_MASK) && cond->ConditionValue1 != TYPEID_UNIT && cond->ConditionValue1 != TYPEID_PLAYER) { TC_LOG_ERROR("sql.sql", "%s in `condition` table - spell %u EFFECT_%u - " - "target requires ConditionValue1 to be either TYPEID_UNIT (%u) or TYPEID_PLAYER (%u)", cond->ToString().c_str(), spellInfo->Id, uint32(i), uint32(TYPEID_UNIT), uint32(TYPEID_PLAYER)); + "target requires ConditionValue1 to be either TYPEID_UNIT (%u) or TYPEID_PLAYER (%u)", cond->ToString().c_str(), spellInfo->Id, uint32(spellEffectInfo.EffectIndex), uint32(TYPEID_UNIT), uint32(TYPEID_PLAYER)); return false; } if ((implicitTargetMask & TARGET_FLAG_GAMEOBJECT_MASK) && cond->ConditionValue1 != TYPEID_GAMEOBJECT) { TC_LOG_ERROR("sql.sql", "%s in `condition` table - spell %u EFFECT_%u - " - "target requires ConditionValue1 to be TYPEID_GAMEOBJECT (%u)", cond->ToString().c_str(), spellInfo->Id, uint32(i), uint32(TYPEID_GAMEOBJECT)); + "target requires ConditionValue1 to be TYPEID_GAMEOBJECT (%u)", cond->ToString().c_str(), spellInfo->Id, uint32(spellEffectInfo.EffectIndex), uint32(TYPEID_GAMEOBJECT)); return false; } if ((implicitTargetMask & TARGET_FLAG_CORPSE_MASK) && cond->ConditionValue1 != TYPEID_CORPSE) { TC_LOG_ERROR("sql.sql", "%s in `condition` table - spell %u EFFECT_%u - " - "target requires ConditionValue1 to be TYPEID_CORPSE (%u)", cond->ToString().c_str(), spellInfo->Id, uint32(i), uint32(TYPEID_CORPSE)); + "target requires ConditionValue1 to be TYPEID_CORPSE (%u)", cond->ToString().c_str(), spellInfo->Id, uint32(spellEffectInfo.EffectIndex), uint32(TYPEID_CORPSE)); return false; } break; @@ -1398,18 +1398,17 @@ bool ConditionMgr::addToSpellImplicitTargetConditions(Condition* cond) const } // check if effect is already a part of some shared mask - auto itr = std::find_if(sharedMasks.begin(), sharedMasks.end(), [i](uint32 mask) { return !!(mask & (1 << i)); }); + auto itr = std::find_if(sharedMasks.begin(), sharedMasks.end(), [&](uint32 mask) { return !!(mask & (1 << spellEffectInfo.EffectIndex)); }); if (itr != sharedMasks.end()) continue; // build new shared mask with found effect - uint32 sharedMask = 1 << i; - ConditionContainer* cmp = spellInfo->Effects[i].ImplicitTargetConditions; - for (uint8 effIndex = i + 1; effIndex < MAX_SPELL_EFFECTS; ++effIndex) - { - if (spellInfo->Effects[effIndex].ImplicitTargetConditions == cmp) + uint32 sharedMask = 1 << spellEffectInfo.EffectIndex; + ConditionContainer* cmp = spellEffectInfo.ImplicitTargetConditions; + for (size_t effIndex = spellEffectInfo.EffectIndex + 1; effIndex < spellInfo->GetEffects().size(); ++effIndex) + if (spellInfo->GetEffect(SpellEffIndex(effIndex)).ImplicitTargetConditions == cmp) sharedMask |= 1 << effIndex; - } + sharedMasks.push_back(sharedMask); } @@ -1418,16 +1417,16 @@ bool ConditionMgr::addToSpellImplicitTargetConditions(Condition* cond) const // some effect indexes should have same data if (uint32 commonMask = effectMask & conditionEffMask) { - uint8 firstEffIndex = 0; - for (; firstEffIndex < MAX_SPELL_EFFECTS; ++firstEffIndex) + size_t firstEffIndex = 0; + for (; firstEffIndex < spellInfo->GetEffects().size(); ++firstEffIndex) if ((1 << firstEffIndex) & effectMask) break; - if (firstEffIndex >= MAX_SPELL_EFFECTS) + if (firstEffIndex >= spellInfo->GetEffects().size()) return false; // get shared data - ConditionContainer* sharedList = spellInfo->Effects[firstEffIndex].ImplicitTargetConditions; + ConditionContainer* sharedList = spellInfo->GetEffect(SpellEffIndex(firstEffIndex)).ImplicitTargetConditions; // there's already data entry for that sharedMask if (sharedList) @@ -1446,11 +1445,11 @@ bool ConditionMgr::addToSpellImplicitTargetConditions(Condition* cond) const // add new list, create new shared mask sharedList = new ConditionContainer(); bool assigned = false; - for (uint8 i = firstEffIndex; i < MAX_SPELL_EFFECTS; ++i) + for (size_t i = firstEffIndex; i < spellInfo->GetEffects().size(); ++i) { if ((1 << i) & commonMask) { - spellInfo->Effects[i].ImplicitTargetConditions = sharedList; + const_cast<SpellEffectInfo&>(spellInfo->GetEffect(SpellEffIndex(i))).ImplicitTargetConditions = sharedList; assigned = true; } } @@ -1699,15 +1698,15 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) const uint32 origGroup = cond->SourceGroup; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const& spellEffectInfo : spellInfo->GetEffects()) { - if (!((1 << i) & cond->SourceGroup)) + if (!((1 << spellEffectInfo.EffectIndex) & cond->SourceGroup)) continue; - if (spellInfo->Effects[i].ChainTarget > 0) + if (spellEffectInfo.ChainTarget > 0) continue; - switch (spellInfo->Effects[i].TargetA.GetSelectionCategory()) + switch (spellEffectInfo.TargetA.GetSelectionCategory()) { case TARGET_SELECT_CATEGORY_NEARBY: case TARGET_SELECT_CATEGORY_CONE: @@ -1718,7 +1717,7 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) const break; } - switch (spellInfo->Effects[i].TargetB.GetSelectionCategory()) + switch (spellEffectInfo.TargetB.GetSelectionCategory()) { case TARGET_SELECT_CATEGORY_NEARBY: case TARGET_SELECT_CATEGORY_CONE: @@ -1729,8 +1728,8 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) const break; } - TC_LOG_ERROR("sql.sql", "SourceEntry %u SourceGroup %u in `condition` table - spell %u does not have implicit targets of types: _AREA_, _CONE_, _NEARBY_, __CHAIN__ for effect %u, SourceGroup needs correction, ignoring.", cond->SourceEntry, origGroup, cond->SourceEntry, uint32(i)); - cond->SourceGroup &= ~(1 << i); + TC_LOG_ERROR("sql.sql", "SourceEntry %u SourceGroup %u in `condition` table - spell %u does not have implicit targets of types: _AREA_, _CONE_, _NEARBY_, __CHAIN__ for effect %u, SourceGroup needs correction, ignoring.", cond->SourceEntry, origGroup, cond->SourceEntry, uint32(spellEffectInfo.EffectIndex)); + cond->SourceGroup &= ~(1 << spellEffectInfo.EffectIndex); } // all effects were removed, no need to add the condition at all if (!cond->SourceGroup) diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 502d214e7eb..9a7ec7c8727 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -2209,9 +2209,9 @@ bool Creature::IsImmunedToSpell(SpellInfo const* spellInfo, WorldObject const* c return false; bool immunedToAllEffects = true; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const& spellEffectInfo : spellInfo->GetEffects()) { - if (spellInfo->Effects[i].IsEffect() && !IsImmunedToSpellEffect(spellInfo, i, caster)) + if (spellEffectInfo.IsEffect() && !IsImmunedToSpellEffect(spellInfo, spellEffectInfo, caster)) { immunedToAllEffects = false; break; @@ -2224,12 +2224,12 @@ bool Creature::IsImmunedToSpell(SpellInfo const* spellInfo, WorldObject const* c return Unit::IsImmunedToSpell(spellInfo, caster); } -bool Creature::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index, WorldObject const* caster) const +bool Creature::IsImmunedToSpellEffect(SpellInfo const* spellInfo, SpellEffectInfo const& spellEffectInfo, WorldObject const* caster) const { - if (GetCreatureTemplate()->type == CREATURE_TYPE_MECHANICAL && spellInfo->Effects[index].Effect == SPELL_EFFECT_HEAL) + if (GetCreatureTemplate()->type == CREATURE_TYPE_MECHANICAL && spellEffectInfo.IsEffect(SPELL_EFFECT_HEAL)) return true; - return Unit::IsImmunedToSpellEffect(spellInfo, index, caster); + return Unit::IsImmunedToSpellEffect(spellInfo, spellEffectInfo, caster); } bool Creature::isElite() const diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index b64e09ec1bf..de1df1829fc 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -137,7 +137,7 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma bool CanCreatureAttack(Unit const* victim, bool force = true) const; void LoadTemplateImmunities(); bool IsImmunedToSpell(SpellInfo const* spellInfo, WorldObject const* caster) const override; - bool IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index, WorldObject const* caster) const override; + bool IsImmunedToSpellEffect(SpellInfo const* spellInfo, SpellEffectInfo const& spellEffectInfo, WorldObject const* caster) const override; bool isElite() const; bool isWorldBoss() const; diff --git a/src/server/game/Entities/Item/ItemTemplate.cpp b/src/server/game/Entities/Item/ItemTemplate.cpp index 8c70a624936..a55a90ed77c 100644 --- a/src/server/game/Entities/Item/ItemTemplate.cpp +++ b/src/server/game/Entities/Item/ItemTemplate.cpp @@ -148,9 +148,9 @@ void ItemTemplate::_LoadTotalAP() for (uint32 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i) if (Spells[i].SpellId > 0 && Spells[i].SpellTrigger == ITEM_SPELLTRIGGER_ON_EQUIP) if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(Spells[i].SpellId)) - for (uint8 j = 0; j < MAX_SPELL_EFFECTS; ++j) - if (spellInfo->Effects[j].IsAura(SPELL_AURA_MOD_ATTACK_POWER)) - totalAP += spellInfo->Effects[j].CalcValue(); + for (SpellEffectInfo const& effect : spellInfo->GetEffects()) + if (effect.IsAura(SPELL_AURA_MOD_ATTACK_POWER)) + totalAP += effect.CalcValue(); _totalAP = totalAP; } diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index 95f25061d05..4e5dbebc8ac 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -2228,9 +2228,9 @@ Player* WorldObject::GetSpellModOwner() const } // function uses real base points (typically value - 1) -int32 WorldObject::CalculateSpellDamage(SpellInfo const* spellInfo, uint8 effIndex, int32 const* basePoints /*= nullptr*/) const +int32 WorldObject::CalculateSpellDamage(SpellEffectInfo const& spellEffectInfo, int32 const* basePoints /*= nullptr*/) const { - return spellInfo->Effects[effIndex].CalcValue(this, basePoints); + return spellEffectInfo.CalcValue(this, basePoints); } float WorldObject::GetSpellMaxRangeForTarget(Unit const* target, SpellInfo const* spellInfo) const diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h index 30df1d97fdc..907e7b47f35 100644 --- a/src/server/game/Entities/Object/Object.h +++ b/src/server/game/Entities/Object/Object.h @@ -45,6 +45,7 @@ class Map; class Player; class Spell; class SpellCastTargets; +class SpellEffectInfo; class SpellInfo; class TempSummon; class Transport; @@ -413,7 +414,7 @@ class TC_GAME_API WorldObject : public Object, public WorldLocation Player* GetAffectingPlayer() const; Player* GetSpellModOwner() const; - int32 CalculateSpellDamage(SpellInfo const* spellInfo, uint8 effIndex, int32 const* basePoints = nullptr) const; + int32 CalculateSpellDamage(SpellEffectInfo const& spellEffectInfo, int32 const* basePoints = nullptr) const; // target dependent range checks float GetSpellMaxRangeForTarget(Unit const* target, SpellInfo const* spellInfo) const; diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 7d7f39ed840..9402f1904df 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -1977,15 +1977,15 @@ void Player::SetObjectScale(float scale) SetFloatValue(UNIT_FIELD_COMBATREACH, scale * DEFAULT_PLAYER_COMBAT_REACH); } -bool Player::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index, WorldObject const* caster) const +bool Player::IsImmunedToSpellEffect(SpellInfo const* spellInfo, SpellEffectInfo const& spellEffectInfo, WorldObject const* caster) const { // players are immune to taunt (the aura and the spell effect) - if (spellInfo->Effects[index].IsAura(SPELL_AURA_MOD_TAUNT)) + if (spellEffectInfo.IsAura(SPELL_AURA_MOD_TAUNT)) return true; - if (spellInfo->Effects[index].IsEffect(SPELL_EFFECT_ATTACK_ME)) + if (spellEffectInfo.IsEffect(SPELL_EFFECT_ATTACK_ME)) return true; - return Unit::IsImmunedToSpellEffect(spellInfo, index, caster); + return Unit::IsImmunedToSpellEffect(spellInfo, spellEffectInfo, caster); } void Player::RegenerateAll() diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 69fc386e4d0..b0ceb39ef1f 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -914,7 +914,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player> static bool BuildEnumData(PreparedQueryResult result, WorldPacket* data); - bool IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index, WorldObject const* caster) const override; + bool IsImmunedToSpellEffect(SpellInfo const* spellInfo, SpellEffectInfo const& spellEffectInfo, WorldObject const* caster) const override; void SetInWater(bool apply); diff --git a/src/server/game/Entities/Totem/Totem.cpp b/src/server/game/Entities/Totem/Totem.cpp index 5c86d3371d4..4cc7e6df3aa 100644 --- a/src/server/game/Entities/Totem/Totem.cpp +++ b/src/server/game/Entities/Totem/Totem.cpp @@ -155,17 +155,17 @@ void Totem::UnSummon(uint32 msTime) AddObjectToRemoveList(); } -bool Totem::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index, WorldObject const* caster) const +bool Totem::IsImmunedToSpellEffect(SpellInfo const* spellInfo, SpellEffectInfo const& spellEffectInfo, WorldObject const* caster) const { // immune to all positive spells, except of stoneclaw totem absorb and sentry totem bind sight // totems positive spells have unit_caster target - if (spellInfo->Effects[index].Effect != SPELL_EFFECT_DUMMY && - spellInfo->Effects[index].Effect != SPELL_EFFECT_SCRIPT_EFFECT && - spellInfo->IsPositive() && spellInfo->Effects[index].TargetA.GetTarget() != TARGET_UNIT_CASTER && - spellInfo->Effects[index].TargetA.GetCheckType() != TARGET_CHECK_ENTRY && spellInfo->Id != SENTRY_STONECLAW_SPELLID && spellInfo->Id != SENTRY_BIND_SIGHT_SPELLID) + if (spellEffectInfo.Effect != SPELL_EFFECT_DUMMY && + spellEffectInfo.Effect != SPELL_EFFECT_SCRIPT_EFFECT && + spellInfo->IsPositive() && spellEffectInfo.TargetA.GetTarget() != TARGET_UNIT_CASTER && + spellEffectInfo.TargetA.GetCheckType() != TARGET_CHECK_ENTRY && spellInfo->Id != SENTRY_STONECLAW_SPELLID && spellInfo->Id != SENTRY_BIND_SIGHT_SPELLID) return true; - switch (spellInfo->Effects[index].ApplyAuraName) + switch (spellEffectInfo.ApplyAuraName) { case SPELL_AURA_PERIODIC_DAMAGE: case SPELL_AURA_PERIODIC_LEECH: @@ -176,5 +176,5 @@ bool Totem::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index, Wor break; } - return Creature::IsImmunedToSpellEffect(spellInfo, index, caster); + return Creature::IsImmunedToSpellEffect(spellInfo, spellEffectInfo, caster); } diff --git a/src/server/game/Entities/Totem/Totem.h b/src/server/game/Entities/Totem/Totem.h index 123f7cb8720..b94299c843c 100644 --- a/src/server/game/Entities/Totem/Totem.h +++ b/src/server/game/Entities/Totem/Totem.h @@ -58,7 +58,7 @@ class TC_GAME_API Totem : public Minion void UpdateAttackPowerAndDamage(bool /*ranged*/) override { } void UpdateDamagePhysical(WeaponAttackType /*attType*/) override { } - bool IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index, WorldObject const* caster) const override; + bool IsImmunedToSpellEffect(SpellInfo const* spellInfo, SpellEffectInfo const& spellEffectInfo, WorldObject const* caster) const override; protected: TotemType m_type; diff --git a/src/server/game/Entities/Unit/StatSystem.cpp b/src/server/game/Entities/Unit/StatSystem.cpp index 0458f14bcfb..c1939f60dd5 100644 --- a/src/server/game/Entities/Unit/StatSystem.cpp +++ b/src/server/game/Entities/Unit/StatSystem.cpp @@ -1170,8 +1170,8 @@ bool Guardian::UpdateStats(Stats stat) AuraEffect const* aurEff = owner->GetAuraEffect(SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE, SPELLFAMILY_DEATHKNIGHT, 3010, 0); if (aurEff) { - SpellInfo const* spellInfo = aurEff->GetSpellInfo(); // Then get the SpellProto and add the dummy effect value - AddPct(mod, spellInfo->Effects[EFFECT_1].CalcValue()); // Ravenous Dead edits the original scale + SpellInfo const* spellInfo = aurEff->GetSpellInfo(); // Then get the SpellProto and add the dummy effect value + AddPct(mod, spellInfo->GetEffect(EFFECT_1).CalcValue()); // Ravenous Dead edits the original scale } // Glyph of the Ghoul aurEff = owner->GetAuraEffect(58686, 0); @@ -1199,7 +1199,7 @@ bool Guardian::UpdateStats(Stats stat) if (itr != ToPet()->m_spells.end()) // If pet has Wild Hunt { SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(itr->first); // Then get the SpellProto and add the dummy effect value - AddPct(mod, spellInfo->Effects[EFFECT_0].CalcValue()); + AddPct(mod, spellInfo->GetEffect(EFFECT_0).CalcValue()); } } ownersBonus = float(owner->GetStat(stat)) * mod; @@ -1370,7 +1370,7 @@ void Guardian::UpdateAttackPowerAndDamage(bool ranged) if (itr != ToPet()->m_spells.end()) // If pet has Wild Hunt { SpellInfo const* sProto = sSpellMgr->AssertSpellInfo(itr->first); // Then get the SpellProto and add the dummy effect value - mod += CalculatePct(1.0f, sProto->Effects[1].CalcValue()); + mod += CalculatePct(1.0f, sProto->GetEffect(EFFECT_1).CalcValue()); } } diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 68608d94742..2a19ba8a501 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -6653,7 +6653,7 @@ float Unit::SpellDamagePctDone(Unit* victim, SpellInfo const* spellProto, Damage // effect 1 m_amount int32 maxPercent = (*i)->GetAmount(); // effect 0 m_amount - int32 stepPercent = CalculateSpellDamage((*i)->GetSpellInfo(), EFFECT_0); + int32 stepPercent = CalculateSpellDamage((*i)->GetSpellInfo()->GetEffect(EFFECT_0)); // count affliction effects and calc additional damage in percentage int32 modPercent = 0; AuraApplicationMap const& victimAuras = victim->GetAppliedAuras(); @@ -7689,14 +7689,14 @@ bool Unit::IsImmunedToSpell(SpellInfo const* spellInfo, WorldObject const* caste } bool immuneToAllEffects = true; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const& spellEffectInfo : spellInfo->GetEffects()) { // State/effect immunities applied by aura expect full spell immunity // Ignore effects with mechanic, they are supposed to be checked separately - if (!spellInfo->Effects[i].IsEffect()) + if (!spellEffectInfo.IsEffect()) continue; - if (!IsImmunedToSpellEffect(spellInfo, i, caster)) + if (!IsImmunedToSpellEffect(spellInfo, spellEffectInfo, caster)) { immuneToAllEffects = false; break; @@ -7760,21 +7760,20 @@ uint32 Unit::GetMechanicImmunityMask() const return mask; } -bool Unit::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index, WorldObject const* caster) const +bool Unit::IsImmunedToSpellEffect(SpellInfo const* spellInfo, SpellEffectInfo const& spellEffectInfo, WorldObject const* caster) const { - if (!spellInfo || !spellInfo->Effects[index].IsEffect()) + if (!spellInfo || !spellEffectInfo.IsEffect()) return false; if (spellInfo->HasAttribute(SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY)) return false; // If m_immuneToEffect type contain this effect type, IMMUNE effect. - uint32 effect = spellInfo->Effects[index].Effect; SpellImmuneContainer const& effectList = m_spellImmune[IMMUNITY_EFFECT]; - if (effectList.count(effect) > 0) + if (effectList.count(spellEffectInfo.Effect) > 0) return true; - if (uint32 mechanic = spellInfo->Effects[index].Mechanic) + if (uint32 mechanic = spellEffectInfo.Mechanic) { SpellImmuneContainer const& mechanicList = m_spellImmune[IMMUNITY_MECHANIC]; if (mechanicList.count(mechanic) > 0) @@ -7783,7 +7782,7 @@ bool Unit::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index, Worl if (!spellInfo->HasAttribute(SPELL_ATTR3_IGNORE_HIT_RESULT)) { - if (uint32 aura = spellInfo->Effects[index].ApplyAuraName) + if (AuraType aura = spellEffectInfo.ApplyAuraName) { SpellImmuneContainer const& list = m_spellImmune[IMMUNITY_STATE]; if (list.count(aura) > 0) @@ -7795,7 +7794,7 @@ bool Unit::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index, Worl AuraEffectList const& immuneAuraApply = GetAuraEffectsByType(SPELL_AURA_MOD_IMMUNE_AURA_APPLY_SCHOOL); for (AuraEffectList::const_iterator iter = immuneAuraApply.begin(); iter != immuneAuraApply.end(); ++iter) if (((*iter)->GetMiscValue() & spellInfo->GetSchoolMask()) && // Check school - ((caster && !IsFriendlyTo(caster)) || !spellInfo->IsPositiveEffect(index))) // Harmful + ((caster && !IsFriendlyTo(caster)) || !spellInfo->IsPositiveEffect(spellEffectInfo.EffectIndex))) // Harmful return true; } } @@ -11927,13 +11926,13 @@ Aura* Unit::AddAura(SpellInfo const* spellInfo, uint8 effMask, Unit* target) if (target->IsImmunedToSpell(spellInfo, this)) return nullptr; - for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const& spellEffectInfo : spellInfo->GetEffects()) { - if (!(effMask & (1 << i))) + if (!(effMask & (1 << spellEffectInfo.EffectIndex))) continue; - if (target->IsImmunedToSpellEffect(spellInfo, i, this)) - effMask &= ~(1 << i); + if (target->IsImmunedToSpellEffect(spellInfo, spellEffectInfo, this)) + effMask &= ~(1 << spellEffectInfo.EffectIndex); } if (!effMask) diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 0d3e1f69309..9a07cca1e3e 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -82,6 +82,7 @@ class Pet; class PetAura; class Spell; class SpellCastTargets; +class SpellEffectInfo; class SpellHistory; class SpellInfo; class Totem; @@ -1566,7 +1567,7 @@ class TC_GAME_API Unit : public WorldObject bool IsImmunedToDamage(SpellSchoolMask meleeSchoolMask) const; bool IsImmunedToDamage(SpellInfo const* spellInfo) const; - virtual bool IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index, WorldObject const* caster) const; + virtual bool IsImmunedToSpellEffect(SpellInfo const* spellInfo, SpellEffectInfo const& spellEffectInfo, WorldObject const* caster) const; static bool IsDamageReducedByArmor(SpellSchoolMask damageSchoolMask, SpellInfo const* spellInfo = nullptr); static uint32 CalcArmorReducedDamage(Unit const* attacker, Unit* victim, uint32 damage, SpellInfo const* spellInfo, WeaponAttackType attackType = MAX_ATTACK, uint8 attackerLevel = 0); diff --git a/src/server/game/Handlers/PetHandler.cpp b/src/server/game/Handlers/PetHandler.cpp index de4f5f13078..95409b0a88d 100644 --- a/src/server/game/Handlers/PetHandler.cpp +++ b/src/server/game/Handlers/PetHandler.cpp @@ -287,9 +287,9 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spe return; } - for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const& spellEffectInfo : spellInfo->GetEffects()) { - if (spellInfo->Effects[i].TargetA.GetTarget() == TARGET_UNIT_SRC_AREA_ENEMY || spellInfo->Effects[i].TargetA.GetTarget() == TARGET_UNIT_DEST_AREA_ENEMY || spellInfo->Effects[i].TargetA.GetTarget() == TARGET_DEST_DYNOBJ_ENEMY) + if (spellEffectInfo.TargetA.GetTarget() == TARGET_UNIT_SRC_AREA_ENEMY || spellEffectInfo.TargetA.GetTarget() == TARGET_UNIT_DEST_AREA_ENEMY || spellEffectInfo.TargetA.GetTarget() == TARGET_DEST_DYNOBJ_ENEMY) return; } diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 914e2a5f079..280dcc26d14 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -378,10 +378,10 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]= &AuraEffect::HandleNoImmediateEffect, //316 SPELL_AURA_PERIODIC_HASTE implemented in AuraEffect::CalculatePeriodic }; -AuraEffect::AuraEffect(Aura* base, uint8 effIndex, int32 const* baseAmount, Unit* caster): -m_base(base), m_spellInfo(base->GetSpellInfo()), -m_baseAmount(baseAmount ? *baseAmount : m_spellInfo->Effects[effIndex].BasePoints), -_amount(), m_spellmod(nullptr), _periodicTimer(0), _amplitude(0), _ticksDone(0), m_effIndex(effIndex), +AuraEffect::AuraEffect(Aura* base, SpellEffectInfo const& spellEfffectInfo, int32 const* baseAmount, Unit* caster): +m_base(base), m_spellInfo(base->GetSpellInfo()), m_spellEffectInfo(spellEfffectInfo), +m_baseAmount(baseAmount ? *baseAmount : spellEfffectInfo.BasePoints), +_amount(), m_spellmod(nullptr), _periodicTimer(0), _amplitude(0), _ticksDone(0), m_canBeRecalculated(true), m_isPeriodic(false) { CalculatePeriodic(caster, true, false); @@ -422,7 +422,7 @@ void AuraEffect::GetApplicationList(Container& applicationContainer) const int32 AuraEffect::CalculateAmount(Unit* caster) { // default amount calculation - int32 amount = m_spellInfo->Effects[m_effIndex].CalcValue(caster, &m_baseAmount); + int32 amount = GetSpellEffectInfo().CalcValue(caster, &m_baseAmount); // check item enchant aura cast if (!amount && caster) @@ -561,7 +561,7 @@ void AuraEffect::ResetPeriodic(bool resetPeriodicTimer /*= false*/) void AuraEffect::CalculatePeriodic(Unit* caster, bool resetPeriodicTimer /*= true*/, bool load /*= false*/) { - _amplitude = m_spellInfo->Effects[m_effIndex].Amplitude; + _amplitude = GetSpellEffectInfo().Amplitude; // prepare periodics switch (GetAuraType()) @@ -848,7 +848,7 @@ bool AuraEffect::IsAffectedOnSpell(SpellInfo const* spell) const return false; // Check family name and EffectClassMask - if (!spell->IsAffected(m_spellInfo->SpellFamilyName, m_spellInfo->Effects[m_effIndex].SpellClassMask)) + if (!spell->IsAffected(m_spellInfo->SpellFamilyName, GetSpellEffectInfo().SpellClassMask)) return false; return true; @@ -1848,7 +1848,7 @@ void AuraEffect::HandleAuraModShapeshift(AuraApplication const* aurApp, uint8 mo SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(itr->first); if (spellInfo && spellInfo->SpellFamilyName == SPELLFAMILY_WARRIOR && spellInfo->SpellIconID == 139) - Rage_val += target->CalculateSpellDamage(spellInfo, EFFECT_0) * 10; + Rage_val += target->CalculateSpellDamage(spellInfo->GetEffect(EFFECT_0)) * 10; } } if (target->GetPower(POWER_RAGE) > Rage_val) @@ -4298,7 +4298,7 @@ void AuraEffect::HandleNoReagentUseAura(AuraApplication const* aurApp, uint8 mod flag96 mask; Unit::AuraEffectList const& noReagent = target->GetAuraEffectsByType(SPELL_AURA_NO_REAGENT_USE); for (Unit::AuraEffectList::const_iterator i = noReagent.begin(); i != noReagent.end(); ++i) - mask |= (*i)->m_spellInfo->Effects[(*i)->m_effIndex].SpellClassMask; + mask |= (*i)->GetSpellEffectInfo().SpellClassMask; target->SetUInt32Value(PLAYER_NO_REAGENT_COST_1 , mask[0]); target->SetUInt32Value(PLAYER_NO_REAGENT_COST_1+1, mask[1]); @@ -4337,7 +4337,7 @@ void AuraEffect::HandleAuraDummy(AuraApplication const* aurApp, uint8 mode, bool // pet auras if (target->GetTypeId() == TYPEID_PLAYER && (mode & AURA_EFFECT_HANDLE_REAL)) { - if (PetAura const* petSpell = sSpellMgr->GetPetAura(GetId(), m_effIndex)) + if (PetAura const* petSpell = sSpellMgr->GetPetAura(GetId(), GetEffIndex())) { if (apply) target->ToPlayer()->AddPetAura(petSpell); @@ -4706,11 +4706,11 @@ void AuraEffect::HandleChannelDeathItem(AuraApplication const* aurApp, uint8 mod if (GetAmount() <= 0) return; - if (GetSpellInfo()->Effects[m_effIndex].ItemType == 0) + if (GetSpellEffectInfo().ItemType == 0) return; // Soul Shard - if (GetSpellInfo()->Effects[m_effIndex].ItemType == 6265) + if (GetSpellEffectInfo().ItemType == 6265) { // Soul Shard only from units that grant XP or honor if (!plCaster->isHonorOrXPTarget(target) || @@ -4732,16 +4732,16 @@ void AuraEffect::HandleChannelDeathItem(AuraApplication const* aurApp, uint8 mod uint32 count = GetAmount(); ItemPosCountVec dest; - InventoryResult msg = plCaster->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, GetSpellInfo()->Effects[m_effIndex].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, GetSpellInfo()->Effects[m_effIndex].ItemType); + plCaster->SendEquipError(msg, nullptr, nullptr, GetSpellEffectInfo().ItemType); if (count == 0) return; } - Item* newitem = plCaster->StoreNewItem(dest, GetSpellInfo()->Effects[m_effIndex].ItemType, true); + Item* newitem = plCaster->StoreNewItem(dest, GetSpellEffectInfo().ItemType, true); if (!newitem) { plCaster->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, nullptr, nullptr); @@ -4880,7 +4880,7 @@ void AuraEffect::HandleAuraLinked(AuraApplication const* aurApp, uint8 mode, boo { Unit* target = aurApp->GetTarget(); - uint32 triggeredSpellId = sSpellMgr->GetSpellIdForDifficulty(m_spellInfo->Effects[m_effIndex].TriggerSpell, target); + uint32 triggeredSpellId = sSpellMgr->GetSpellIdForDifficulty(GetSpellEffectInfo().TriggerSpell, target); SpellInfo const* triggeredSpellInfo = sSpellMgr->GetSpellInfo(triggeredSpellId); if (!triggeredSpellInfo) return; @@ -5072,7 +5072,7 @@ void AuraEffect::HandlePeriodicTriggerSpellAuraTick(Unit* target, Unit* caster) void AuraEffect::HandlePeriodicTriggerSpellWithValueAuraTick(Unit* target, Unit* caster) const { - uint32 triggerSpellId = GetSpellInfo()->Effects[m_effIndex].TriggerSpell; + uint32 triggerSpellId = GetSpellEffectInfo().TriggerSpell; if (triggerSpellId == 0) { TC_LOG_WARN("spells.aura.effect.nospell", "AuraEffect::HandlePeriodicTriggerSpellWithValueAuraTick: Spell %u [EffectIndex: %u] does not have triggered spell.", GetId(), GetEffIndex()); @@ -5618,7 +5618,7 @@ void AuraEffect::HandlePeriodicPowerBurnAuraTick(Unit* target, Unit* caster) con void AuraEffect::HandleModAttackPowerOfArmorAuraTick(Unit* target, Unit* caster) const { - int32 const armorMod = m_spellInfo->Effects[m_effIndex].CalcValue(caster, &m_baseAmount); + int32 const armorMod = GetSpellEffectInfo().CalcValue(caster, &m_baseAmount); const_cast<AuraEffect*>(this)->SetAmount(target->GetArmor() / armorMod); target->UpdateAttackPowerAndDamage(false); diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.h b/src/server/game/Spells/Auras/SpellAuraEffects.h index a87cb89a544..6a50956f81d 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, uint8 effIndex, 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,7 +48,7 @@ class TC_GAME_API AuraEffect SpellInfo const* GetSpellInfo() const { return m_spellInfo; } uint32 GetId() const { return m_spellInfo->Id; } - uint32 GetEffIndex() const { return m_effIndex; } + SpellEffIndex GetEffIndex() const { return m_spellEffectInfo.EffectIndex; } int32 GetBaseAmount() const { return m_baseAmount; } int32 GetAmplitude() const { return _amplitude; } @@ -97,12 +97,13 @@ 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_spellInfo->Effects[m_effIndex]; } + SpellEffectInfo const& GetSpellEffectInfo() const { return m_spellEffectInfo; } private: Aura* const m_base; SpellInfo const* const m_spellInfo; + SpellEffectInfo const& m_spellEffectInfo; int32 const m_baseAmount; int32 _amount; @@ -114,7 +115,6 @@ class TC_GAME_API AuraEffect int32 _amplitude; // time between consecutive ticks uint32 _ticksDone; // ticks counter - uint8 const m_effIndex; bool m_canBeRecalculated; bool m_isPeriodic; diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp index 723d84ccc55..433e0ef1384 100644 --- a/src/server/game/Spells/Auras/SpellAuras.cpp +++ b/src/server/game/Spells/Auras/SpellAuras.cpp @@ -463,13 +463,9 @@ AuraScript* Aura::GetScriptByName(std::string const& scriptName) const void Aura::_InitEffects(uint8 effMask, Unit* caster, int32 const* baseAmount) { // shouldn't be in constructor - functions in AuraEffect::AuraEffect use polymorphism - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - { - if (effMask & (uint8(1) << i)) - m_effects[i] = new AuraEffect(this, i, baseAmount ? baseAmount + i : nullptr, caster); - else - m_effects[i] = nullptr; - } + for (SpellEffectInfo const& spellEffectInfo : GetSpellInfo()->GetEffects()) + if (effMask & (uint8(1) << spellEffectInfo.EffectIndex)) + m_effects[spellEffectInfo.EffectIndex] = new AuraEffect(this, spellEffectInfo, baseAmount ? baseAmount + spellEffectInfo.EffectIndex : nullptr, caster); } bool Aura::CanPeriodicTickCrit(Unit const* caster) const @@ -677,9 +673,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; diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 46e0000bb78..d5987de4654 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -498,8 +498,8 @@ void SpellCastTargets::Update(WorldObject* caster) SpellValue::SpellValue(SpellInfo const* proto) { - for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i) - EffectBasePoints[i] = proto->Effects[i].BasePoints; + for (SpellEffectInfo const& spellEffectInfo : proto->GetEffects()) + EffectBasePoints[spellEffectInfo.EffectIndex] = spellEffectInfo.BasePoints; MaxAffectedTargets = proto->MaxAffectedTargets; RadiusMod = 1.0f; AuraStackAmount = 1; @@ -752,32 +752,32 @@ void Spell::SelectSpellTargets() SelectExplicitTargets(); uint32 processedAreaEffectsMask = 0; - for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) { // not call for empty effect. // Also some spells use not used effect targets for store targets for dummy effect in triggered spells - if (!m_spellInfo->Effects[i].IsEffect()) + if (!spellEffectInfo.IsEffect()) continue; // set expected type of implicit targets to be sent to client - uint32 implicitTargetMask = GetTargetFlagMask(m_spellInfo->Effects[i].TargetA.GetObjectType()) | GetTargetFlagMask(m_spellInfo->Effects[i].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(i), m_spellInfo->Effects[i].TargetA, processedAreaEffectsMask); - SelectEffectImplicitTargets(SpellEffIndex(i), m_spellInfo->Effects[i].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(i); + SelectEffectTypeImplicitTargets(spellEffectInfo); if (m_targets.HasDst()) - AddDestTarget(*m_targets.GetDst(), i); + AddDestTarget(*m_targets.GetDst(), spellEffectInfo.EffectIndex); if (m_spellInfo->IsChanneled()) { @@ -789,7 +789,7 @@ void Spell::SelectSpellTargets() return; } - uint8 mask = (1 << i); + uint8 mask = (1 << spellEffectInfo.EffectIndex); for (auto ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit) { if (ihit->EffectMask & mask) @@ -854,12 +854,12 @@ void Spell::RecalculateDelayMomentForDst() m_caster->m_Events.ModifyEventTime(_spellEvent, Milliseconds(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()) @@ -871,16 +871,16 @@ void Spell::SelectEffectImplicitTargets(SpellEffIndex effIndex, SpellImplicitTar // targets for effect already selected if (effectMask & processedEffectMask) return; - std::array<SpellEffectInfo, MAX_SPELL_EFFECTS> const& effects = GetSpellInfo()->Effects; + std::array<SpellEffectInfo, MAX_SPELL_EFFECTS> const& effects = GetSpellInfo()->GetEffects(); // choose which targets we can select at once - for (uint32 j = effIndex + 1; j < effects.size(); ++j) + for (uint32 j = spellEffectInfo.EffectIndex + 1; j < effects.size(); ++j) { if (effects[j].IsEffect() && - effects[effIndex].TargetA.GetTarget() == effects[j].TargetA.GetTarget() && - effects[effIndex].TargetB.GetTarget() == effects[j].TargetB.GetTarget() && - effects[effIndex].ImplicitTargetConditions == effects[j].ImplicitTargetConditions && - effects[effIndex].CalcRadius(m_caster) == effects[j].CalcRadius(m_caster) && - CheckScriptEffectImplicitTargets(effIndex, j)) + 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)) { effectMask |= 1 << j; } @@ -895,22 +895,22 @@ 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_DEFAULT: switch (targetType.GetObjectType()) @@ -930,13 +930,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: ABORT_MSG("Spell::SelectEffectImplicitTargets: received not implemented select target reference type for TARGET_TYPE_OBJECT_DEST"); @@ -947,10 +947,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: ABORT_MSG("Spell::SelectEffectImplicitTargets: received not implemented select target reference type for TARGET_TYPE_OBJECT"); @@ -960,7 +960,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: ABORT_MSG("Spell::SelectEffectImplicitTargets: received not implemented select target category"); @@ -968,7 +968,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) { @@ -979,7 +979,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()) @@ -987,12 +987,12 @@ void Spell::SelectImplicitChannelTargets(SpellEffIndex effIndex, SpellImplicitTa case TARGET_UNIT_CHANNEL_TARGET: { WorldObject* target = ObjectAccessor::GetUnit(*m_caster, m_originalCaster->GetChannelObjectGuid()); - CallScriptObjectTargetSelectHandlers(target, effIndex, targetType); + CallScriptObjectTargetSelectHandlers(target, spellEffectInfo.EffectIndex, targetType); // unit target may be no longer avalible - teleported out of map for example if (target && target->ToUnit()) - AddUnitTarget(target->ToUnit(), 1 << effIndex); + AddUnitTarget(target->ToUnit(), 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; } case TARGET_DEST_CHANNEL_TARGET: @@ -1000,21 +1000,21 @@ void Spell::SelectImplicitChannelTargets(SpellEffIndex effIndex, SpellImplicitTa m_targets.SetDst(channeledSpell->m_targets); else if (WorldObject* target = ObjectAccessor::GetWorldObject(*m_caster, m_originalCaster->GetChannelObjectGuid())) { - 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; } @@ -1024,7 +1024,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) { @@ -1053,12 +1053,12 @@ void Spell::SelectImplicitNearbyTargets(SpellEffIndex effIndex, SpellImplicitTar break; } - ConditionContainer* condList = m_spellInfo->Effects[effIndex].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: @@ -1080,7 +1080,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 @@ -1099,16 +1099,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; @@ -1152,7 +1152,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; } @@ -1161,10 +1161,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) { @@ -1174,13 +1174,13 @@ void Spell::SelectImplicitConeTargets(SpellEffIndex effIndex, SpellImplicitTarge std::list<WorldObject*> targets; SpellTargetObjectTypes objectType = targetType.GetObjectType(); SpellTargetCheckTypes selectionType = targetType.GetCheckType(); - ConditionContainer* condList = m_spellInfo->Effects[effIndex].ImplicitTargetConditions; + ConditionContainer* condList = spellEffectInfo.ImplicitTargetConditions; float coneAngle = float(M_PI) / 2.f; - float radius = m_spellInfo->Effects[effIndex].CalcRadius(m_caster); + float radius = spellEffectInfo.CalcRadius(m_caster); // Workaround for some spells that don't have RadiusEntry set in dbc (but SpellRange instead) if (G3D::fuzzyEq(radius, 0.f)) - radius = m_spellInfo->GetMaxRange(m_spellInfo->IsPositiveEffect(effIndex), m_caster, this); + radius = m_spellInfo->GetMaxRange(m_spellInfo->IsPositiveEffect(spellEffectInfo.EffectIndex), m_caster, this); radius *= m_spellValue->RadiusMod; @@ -1190,7 +1190,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()) { @@ -1215,7 +1215,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()) @@ -1233,7 +1233,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; @@ -1267,16 +1267,16 @@ void Spell::SelectImplicitAreaTargets(SpellEffIndex effIndex, SpellImplicitTarge return; } std::list<WorldObject*> targets; - float radius = m_spellInfo->Effects[effIndex].CalcRadius(m_caster); + float radius = spellEffectInfo.CalcRadius(m_caster); // Workaround for some spells that don't have RadiusEntry set in dbc (but SpellRange instead) if (G3D::fuzzyEq(radius, 0.f)) - radius = m_spellInfo->GetMaxRange(m_spellInfo->IsPositiveEffect(effIndex), m_caster, this); + radius = m_spellInfo->GetMaxRange(m_spellInfo->IsPositiveEffect(spellEffectInfo.EffectIndex), m_caster, this); radius *= m_spellValue->RadiusMod; - SearchAreaTargets(targets, radius, center, referer, targetType.GetObjectType(), targetType.GetCheckType(), m_spellInfo->Effects[effIndex].ImplicitTargetConditions); + SearchAreaTargets(targets, radius, center, referer, targetType.GetObjectType(), targetType.GetCheckType(), spellEffectInfo.ImplicitTargetConditions); - CallScriptObjectAreaTargetSelectHandlers(targets, effIndex, targetType); + CallScriptObjectAreaTargetSelectHandlers(targets, spellEffectInfo.EffectIndex, targetType); if (!targets.empty()) { @@ -1300,7 +1300,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); @@ -1313,7 +1313,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)) @@ -1368,7 +1368,7 @@ void Spell::SelectImplicitCasterDestTargets(SpellEffIndex effIndex, SpellImplici if (!unitCaster) break; - float dist = m_spellInfo->Effects[effIndex].CalcRadius(unitCaster); + float dist = spellEffectInfo.CalcRadius(unitCaster); float angle = targetType.CalcDirectionAngle(); Position pos = dest._position; @@ -1379,7 +1379,7 @@ void Spell::SelectImplicitCasterDestTargets(SpellEffIndex effIndex, SpellImplici } default: { - float dist = m_spellInfo->Effects[effIndex].CalcRadius(m_caster); + float dist = spellEffectInfo.CalcRadius(m_caster); float angle = targetType.CalcDirectionAngle(); float objSize = m_caster->GetCombatReach(); @@ -1398,7 +1398,7 @@ void Spell::SelectImplicitCasterDestTargets(SpellEffIndex effIndex, SpellImplici case TARGET_DEST_CASTER_BACK_RIGHT: { static float const DefaultTotemDistance = 3.0f; - if (!m_spellInfo->Effects[effIndex].HasRadius()) + if (!spellEffectInfo.HasRadius()) dist = DefaultTotemDistance; break; } @@ -1417,11 +1417,11 @@ void Spell::SelectImplicitCasterDestTargets(SpellEffIndex effIndex, SpellImplici } } - 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(); @@ -1436,7 +1436,7 @@ void Spell::SelectImplicitTargetDestTargets(SpellEffIndex effIndex, SpellImplici default: { float angle = targetType.CalcDirectionAngle(); - float dist = m_spellInfo->Effects[effIndex].CalcRadius(nullptr); + float dist = spellEffectInfo.CalcRadius(nullptr); if (targetType.GetTarget() == TARGET_DEST_TARGET_RANDOM) dist *= float(rand_norm()); @@ -1448,11 +1448,11 @@ void Spell::SelectImplicitTargetDestTargets(SpellEffIndex effIndex, SpellImplici } } - 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 @@ -1472,7 +1472,7 @@ void Spell::SelectImplicitDestDestTargets(SpellEffIndex effIndex, SpellImplicitT default: { float angle = targetType.CalcDirectionAngle(); - float dist = m_spellInfo->Effects[effIndex].CalcRadius(m_caster); + float dist = spellEffectInfo.CalcRadius(m_caster); if (targetType.GetTarget() == TARGET_DEST_DEST_RANDOM) dist *= float(rand_norm()); @@ -1484,11 +1484,11 @@ void Spell::SelectImplicitDestDestTargets(SpellEffIndex effIndex, SpellImplicitT } } - 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; @@ -1531,61 +1531,61 @@ 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); else if (Corpse* corpse = target->ToCorpse()) - AddCorpseTarget(corpse, 1 << effIndex); + AddCorpseTarget(corpse, 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) { - uint32 maxTargets = m_spellInfo->Effects[effIndex].ChainTarget; + uint32 maxTargets = spellEffectInfo.ChainTarget; if (Player* modOwner = m_caster->GetSpellModOwner()) modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_JUMP_TARGETS, maxTargets, this); if (maxTargets > 1) { // mark damage multipliers as used - for (uint32 k = effIndex; k < MAX_SPELL_EFFECTS; ++k) + 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() - , m_spellInfo->Effects[effIndex].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()) @@ -1605,7 +1605,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; @@ -1619,7 +1619,7 @@ void Spell::SelectImplicitTrajTargets(SpellEffIndex effIndex, SpellImplicitTarge float srcToDestDelta = m_targets.GetDstPos()->m_positionZ - srcPos.m_positionZ; std::list<WorldObject*> targets; - Trinity::WorldObjectSpellTrajTargetCheck check(dist2d, &srcPos, m_caster, m_spellInfo, targetType.GetCheckType(), m_spellInfo->Effects[effIndex].ImplicitTargetConditions); + Trinity::WorldObjectSpellTrajTargetCheck check(dist2d, &srcPos, m_caster, m_spellInfo, targetType.GetCheckType(), spellEffectInfo.ImplicitTargetConditions); 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()) @@ -1635,7 +1635,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(m_spellInfo->Effects[effIndex].TriggerSpell)) + if (SpellInfo const* triggerSpellInfo = sSpellMgr->GetSpellInfo(spellEffectInfo.TriggerSpell)) bestDist = std::min(std::max(bestDist, triggerSpellInfo->GetMaxRange(false)), std::min(dist2d, 300.0f)); // GameObjects don't cast traj @@ -1683,22 +1683,22 @@ 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::SelectEffectTypeImplicitTargets(uint8 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 - switch (m_spellInfo->Effects[effIndex].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()) { 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) @@ -1707,21 +1707,21 @@ void Spell::SelectEffectTypeImplicitTargets(uint8 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, nullptr, effIndex, SPELL_EFFECT_HANDLE_HIT_TARGET); - }, std::placeholders::_1, this, effIndex, target->GetGUID())); + spell->HandleEffects(player, nullptr, nullptr, nullptr, spellEffectInfo, SPELL_EFFECT_HANDLE_HIT_TARGET); + }); } } return; @@ -1730,17 +1730,17 @@ void Spell::SelectEffectTypeImplicitTargets(uint8 effIndex) } // select spell implicit targets based on effect type - if (!m_spellInfo->Effects[effIndex].GetImplicitTargetType()) + if (!spellEffectInfo.GetImplicitTargetType()) return; - uint32 targetMask = m_spellInfo->Effects[effIndex].GetMissingTargetMask(); + uint32 targetMask = spellEffectInfo.GetMissingTargetMask(); if (!targetMask) return; WorldObject* target = nullptr; - switch (m_spellInfo->Effects[effIndex].GetImplicitTargetType()) + switch (spellEffectInfo.GetImplicitTargetType()) { // add explicit object target or self to the target map case EFFECT_IMPLICIT_TARGET_EXPLICIT: @@ -1760,7 +1760,7 @@ void Spell::SelectEffectTypeImplicitTargets(uint8 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) @@ -1775,16 +1775,16 @@ void Spell::SelectEffectTypeImplicitTargets(uint8 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); else if (target->ToCorpse()) - AddCorpseTarget(target->ToCorpse(), 1 << effIndex); + AddCorpseTarget(target->ToCorpse(), 1 << spellEffectInfo.EffectIndex); } } @@ -2076,9 +2076,9 @@ class ProcReflectDelayed : public BasicEvent void Spell::AddUnitTarget(Unit* target, uint32 effectMask, bool checkIfValid /*= true*/, bool implicit /*= true*/, Position const* losPosition /*= nullptr*/) { - for (uint32 effIndex = 0; effIndex < MAX_SPELL_EFFECTS; ++effIndex) - if (!m_spellInfo->Effects[effIndex].IsEffect() || !CheckEffectTarget(target, effIndex, losPosition)) - effectMask &= ~(1 << effIndex); + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) + if (!spellEffectInfo.IsEffect() || !CheckEffectTarget(target, spellEffectInfo, losPosition)) + effectMask &= ~(1 << spellEffectInfo.EffectIndex); // no effects left if (!effectMask) @@ -2089,9 +2089,9 @@ void Spell::AddUnitTarget(Unit* target, uint32 effectMask, bool checkIfValid /*= return; // Check for effect immune skip if immuned - for (uint32 effIndex = 0; effIndex < MAX_SPELL_EFFECTS; ++effIndex) - if (target->IsImmunedToSpellEffect(m_spellInfo, effIndex, m_caster)) - effectMask &= ~(1 << effIndex); + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) + if (target->IsImmunedToSpellEffect(m_spellInfo, spellEffectInfo, m_caster)) + effectMask &= ~(1 << spellEffectInfo.EffectIndex); ObjectGuid targetGUID = target->GetGUID(); @@ -2174,19 +2174,19 @@ void Spell::AddUnitTarget(Unit* target, uint32 effectMask, bool checkIfValid /*= void Spell::AddGOTarget(GameObject* go, uint32 effectMask) { - for (uint32 effIndex = 0; effIndex < MAX_SPELL_EFFECTS; ++effIndex) + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) { - if (!m_spellInfo->Effects[effIndex].IsEffect()) - effectMask &= ~(1 << effIndex); + if (!spellEffectInfo.IsEffect()) + effectMask &= ~(1 << spellEffectInfo.EffectIndex); else { - switch (m_spellInfo->Effects[effIndex].Effect) + switch (spellEffectInfo.Effect) { case SPELL_EFFECT_GAMEOBJECT_DAMAGE: case SPELL_EFFECT_GAMEOBJECT_REPAIR: case SPELL_EFFECT_GAMEOBJECT_SET_DESTRUCTION_STATE: if (go->GetGoType() != GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING) - effectMask &= ~(1 << effIndex); + effectMask &= ~(1 << spellEffectInfo.EffectIndex); break; default: break; @@ -2234,9 +2234,9 @@ void Spell::AddGOTarget(GameObject* go, uint32 effectMask) void Spell::AddItemTarget(Item* item, uint32 effectMask) { - for (uint32 effIndex = 0; effIndex < MAX_SPELL_EFFECTS; ++effIndex) - if (!m_spellInfo->Effects[effIndex].IsEffect()) - effectMask &= ~(1 << effIndex); + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) + if (!spellEffectInfo.IsEffect()) + effectMask &= ~(1 << spellEffectInfo.EffectIndex); // no effects left if (!effectMask) @@ -2262,50 +2262,48 @@ void Spell::AddItemTarget(Item* item, uint32 effectMask) void Spell::AddCorpseTarget(Corpse* corpse, uint32 effectMask) { - { - for (uint32 effIndex = 0; effIndex < MAX_SPELL_EFFECTS; ++effIndex) - if (!m_spellInfo->Effects[effIndex].IsEffect()) - effectMask &= ~(1 << effIndex); + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) + if (!spellEffectInfo.IsEffect()) + effectMask &= ~(1 << spellEffectInfo.EffectIndex); - if (!effectMask) - return; + if (!effectMask) + return; - ObjectGuid targetGUID = corpse->GetGUID(); + ObjectGuid targetGUID = corpse->GetGUID(); - // Lookup target in already in list - for (CorpseTargetInfo ihit : m_UniqueCorpseTargetInfo) + // Lookup target in already in list + for (CorpseTargetInfo ihit : m_UniqueCorpseTargetInfo) + { + if (targetGUID == ihit.TargetGUID) // Found in list { - if (targetGUID == ihit.TargetGUID) // Found in list - { - ihit.EffectMask |= effectMask; // Add only effect mask - return; - } + ihit.EffectMask |= effectMask; // Add only effect mask + return; } + } - // This is new target calculate data for him - CorpseTargetInfo target; - target.TargetGUID = targetGUID; - target.EffectMask = effectMask; + // This is new target calculate data for him + CorpseTargetInfo target; + target.TargetGUID = targetGUID; + target.EffectMask = effectMask; - // Spell have speed - need calculate incoming time - if (m_spellInfo->Speed > 0.0f) - { - // calculate spell incoming interval - float dist = m_caster->GetDistance(corpse->GetPositionX(), corpse->GetPositionY(), corpse->GetPositionZ()); - if (dist < 5.0f) - dist = 5.0f; + // Spell have speed - need calculate incoming time + if (m_spellInfo->Speed > 0.0f) + { + // calculate spell incoming interval + float dist = m_caster->GetDistance(corpse->GetPositionX(), corpse->GetPositionY(), corpse->GetPositionZ()); + if (dist < 5.0f) + dist = 5.0f; - target.TimeDelay = uint64(floor(dist / m_spellInfo->Speed * 1000.0f)); + target.TimeDelay = uint64(floor(dist / m_spellInfo->Speed * 1000.0f)); - if (!m_delayMoment || m_delayMoment > target.TimeDelay) - m_delayMoment = target.TimeDelay; - } - else - target.TimeDelay = 0LL; - - // Add target to list - m_UniqueCorpseTargetInfo.push_back(target); + if (!m_delayMoment || m_delayMoment > target.TimeDelay) + m_delayMoment = target.TimeDelay; } + else + target.TimeDelay = 0LL; + + // Add target to list + m_UniqueCorpseTargetInfo.push_back(target); } void Spell::AddDestTarget(SpellDestination const& dest, uint32 effIndex) @@ -2363,7 +2361,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) @@ -2385,7 +2383,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; @@ -2431,7 +2429,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))) @@ -2614,7 +2612,7 @@ void Spell::TargetInfo::DoDamageAndTriggers(Spell* spell) { // only apply unapplied effects (for reapply case) uint8 effMask = EffectMask & aurApp->GetEffectsToApply(); - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (uint8 i = 0; i < spell->m_spellInfo->GetEffects().size(); ++i) if ((effMask & (1 << i)) && aurApp->HasEffect(i)) effMask &= ~(1 << i); @@ -2635,7 +2633,7 @@ void Spell::TargetInfo::DoDamageAndTriggers(Spell* spell) spell->_spellAura = nullptr; } -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) @@ -2643,7 +2641,7 @@ void Spell::GOTargetInfo::DoTargetSpellHit(Spell* spell, uint8 effIndex) spell->CallScriptBeforeHitHandlers(SPELL_MISS_NONE); - spell->HandleEffects(nullptr, nullptr, go, nullptr, effIndex, SPELL_EFFECT_HANDLE_HIT_TARGET); + spell->HandleEffects(nullptr, nullptr, go, nullptr, spellEffectInfo, SPELL_EFFECT_HANDLE_HIT_TARGET); // AI functions if (go->AI()) @@ -2658,17 +2656,17 @@ 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, nullptr, effIndex, SPELL_EFFECT_HANDLE_HIT_TARGET); + spell->HandleEffects(nullptr, TargetItem, nullptr, nullptr, spellEffectInfo, SPELL_EFFECT_HANDLE_HIT_TARGET); spell->CallScriptOnHitHandlers(); spell->CallScriptAfterHitHandlers(); } -void Spell::CorpseTargetInfo::DoTargetSpellHit(Spell* spell, uint8 effIndex) +void Spell::CorpseTargetInfo::DoTargetSpellHit(Spell* spell, SpellEffectInfo const& spellEffectInfo) { Corpse* corpse = ObjectAccessor::GetCorpse(*spell->m_caster, TargetGUID); if (!corpse) @@ -2676,7 +2674,7 @@ void Spell::CorpseTargetInfo::DoTargetSpellHit(Spell* spell, uint8 effIndex) spell->CallScriptBeforeHitHandlers(SPELL_MISS_NONE); - spell->HandleEffects(nullptr, nullptr, nullptr, corpse, effIndex, SPELL_EFFECT_HANDLE_HIT_TARGET); + spell->HandleEffects(nullptr, nullptr, nullptr, corpse, spellEffectInfo, SPELL_EFFECT_HANDLE_HIT_TARGET); spell->CallScriptOnHitHandlers(); spell->CallScriptAfterHitHandlers(); @@ -2758,10 +2756,10 @@ SpellMissInfo Spell::PreprocessSpellHit(Unit* unit, bool scaleAura, TargetInfo& if (SpellInfo const* actualSpellInfo = m_spellInfo->GetAuraRankForLevel(unitTarget->GetLevel())) hitInfo.AuraSpellInfo = actualSpellInfo; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const& auraEffectInfo : hitInfo.AuraSpellInfo->GetEffects()) { - hitInfo.AuraBasePoints[i] = hitInfo.AuraSpellInfo->Effects[i].BasePoints; - if (m_spellInfo->Effects[i].Effect != hitInfo.AuraSpellInfo->Effects[i].Effect) + hitInfo.AuraBasePoints[auraEffectInfo.EffectIndex] = auraEffectInfo.BasePoints; + if (m_spellInfo->GetEffect(auraEffectInfo.EffectIndex).Effect != auraEffectInfo.Effect) { hitInfo.AuraSpellInfo = m_spellInfo; break; @@ -2788,12 +2786,12 @@ SpellMissInfo Spell::PreprocessSpellHit(Unit* unit, bool scaleAura, TargetInfo& hitInfo.Positive = true; if (origCaster == unit || !origCaster->IsFriendlyTo(unit)) { - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const& auraSpellEffect : hitInfo.AuraSpellInfo->GetEffects()) { // mod duration only for effects applying aura! - if (hitInfo.EffectMask & (1 << i) && - hitInfo.AuraSpellInfo->Effects[i].IsUnitOwnedAuraEffect() && - !hitInfo.AuraSpellInfo->IsPositiveEffect(i)) + if (hitInfo.EffectMask & (1 << auraSpellEffect.EffectIndex) && + auraSpellEffect.IsUnitOwnedAuraEffect() && + !hitInfo.AuraSpellInfo->IsPositiveEffect(auraSpellEffect.EffectIndex)) { hitInfo.Positive = false; break; @@ -2805,16 +2803,16 @@ SpellMissInfo Spell::PreprocessSpellHit(Unit* unit, bool scaleAura, TargetInfo& // unit is immune to aura if it was diminished to 0 duration if (!hitInfo.Positive && !unit->ApplyDiminishingToDuration(hitInfo.AuraSpellInfo, triggered, hitInfo.AuraDuration, origCaster, diminishLevel)) - if (std::all_of(std::begin(hitInfo.AuraSpellInfo->Effects), std::end(hitInfo.AuraSpellInfo->Effects), [](SpellEffectInfo const& effInfo) { return !effInfo.IsEffect() || effInfo.Effect == SPELL_EFFECT_APPLY_AURA; })) + if (std::all_of(std::begin(hitInfo.AuraSpellInfo->GetEffects()), std::end(hitInfo.AuraSpellInfo->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 (uint8 aura_effmask = Aura::BuildEffectMaskForOwner(m_spellInfo, 1 << effIndex, unit)) + if (uint8 aura_effmask = Aura::BuildEffectMaskForOwner(m_spellInfo, 1 << spellEffectInfo.EffectIndex, unit)) { WorldObject* caster = m_caster; if (m_originalCaster) @@ -2881,7 +2879,7 @@ void Spell::DoSpellEffectHit(Unit* unit, uint8 effIndex, TargetInfo& hitInfo) } _spellAura = hitInfo.HitAura; - HandleEffects(unit, nullptr, nullptr, nullptr, effIndex, SPELL_EFFECT_HANDLE_HIT_TARGET); + HandleEffects(unit, nullptr, nullptr, nullptr, spellEffectInfo, SPELL_EFFECT_HANDLE_HIT_TARGET); _spellAura = nullptr; } @@ -2942,9 +2940,9 @@ bool Spell::UpdateChanneledTargetList() uint8 channelTargetEffectMask = m_channelTargetEffectMask; uint8 channelAuraMask = 0; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - if (m_spellInfo->Effects[i].Effect == SPELL_EFFECT_APPLY_AURA) - channelAuraMask |= 1 << i; + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) + if (spellEffectInfo.IsEffect(SPELL_EFFECT_APPLY_AURA)) + channelAuraMask |= 1 << spellEffectInfo.EffectIndex; channelAuraMask &= channelTargetEffectMask; @@ -3013,15 +3011,15 @@ SpellCastResult Spell::prepare(SpellCastTargets const& targets, AuraEffect const { if (unitCaster->IsControlledByPlayer() && !m_spellInfo->IsPassive() && m_spellInfo->SpellLevel && !m_spellInfo->IsChanneled() && !(_triggeredCastFlags & TRIGGERED_IGNORE_AURA_SCALING)) { - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) { - if (m_spellInfo->Effects[i].Effect == SPELL_EFFECT_APPLY_AURA) + if (spellEffectInfo.IsEffect(SPELL_EFFECT_APPLY_AURA)) { // Change aura with ranks only if basepoints are taken from spellInfo and aura is positive - if (m_spellInfo->IsPositiveEffect(i)) + if (m_spellInfo->IsPositiveEffect(spellEffectInfo.EffectIndex)) { - m_auraScaleMask |= (1 << i); - if (m_spellValue->EffectBasePoints[i] != m_spellInfo->Effects[i].BasePoints) + m_auraScaleMask |= (1 << spellEffectInfo.EffectIndex); + if (m_spellValue->EffectBasePoints[spellEffectInfo.EffectIndex] != spellEffectInfo.BasePoints) { m_auraScaleMask = 0; break; @@ -3149,9 +3147,9 @@ SpellCastResult Spell::prepare(SpellCastTargets const& targets, AuraEffect const if (!(_triggeredCastFlags & TRIGGERED_IGNORE_AURA_INTERRUPT_FLAGS) && m_spellInfo->IsBreakingStealth()) { unitCaster->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_CAST); - for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) { - if (m_spellInfo->Effects[i].GetUsedTargetObjectType() == TARGET_OBJECT_TYPE_UNIT) + if (spellEffectInfo.GetUsedTargetObjectType() == TARGET_OBJECT_TYPE_UNIT) { unitCaster->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_SPELL_ATTACK); break; @@ -3341,9 +3339,9 @@ void Spell::_cast(bool skipCheck) if (Unit* target = m_targets.GetUnitTarget()) { uint8 aura_effmask = 0; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - if (m_spellInfo->Effects[i].IsUnitOwnedAuraEffect()) - aura_effmask |= 1 << i; + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) + if (spellEffectInfo.IsUnitOwnedAuraEffect()) + aura_effmask |= 1 << spellEffectInfo.EffectIndex; if (aura_effmask) { @@ -3516,10 +3514,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); @@ -3680,14 +3678,14 @@ void Spell::_handle_immediate_phase() HandleThreatSpells(); // handle effects with SPELL_EFFECT_HANDLE_HIT mode - for (uint32 j = 0; j < MAX_SPELL_EFFECTS; ++j) + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) { // don't do anything for empty effect - if (!m_spellInfo->Effects[j].IsEffect()) + if (!spellEffectInfo.IsEffect()) continue; // call effect handlers to handle destination hit - HandleEffects(nullptr, nullptr, nullptr, nullptr, j, SPELL_EFFECT_HANDLE_HIT); + HandleEffects(nullptr, nullptr, nullptr, nullptr, spellEffectInfo, SPELL_EFFECT_HANDLE_HIT); } // process items @@ -3765,7 +3763,7 @@ void Spell::update(uint32 difftime) // check if the player caster has moved before the spell finished if (m_caster->GetTypeId() == TYPEID_PLAYER && m_timer != 0 && m_caster->ToPlayer()->isMoving() && m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_MOVEMENT && - (m_spellInfo->Effects[EFFECT_0].Effect != SPELL_EFFECT_STUCK || !m_caster->ToPlayer()->HasUnitMovementFlag(MOVEMENTFLAG_FALLING_FAR))) + (!m_spellInfo->HasEffect(SPELL_EFFECT_STUCK) || !m_caster->ToPlayer()->HasUnitMovementFlag(MOVEMENTFLAG_FALLING_FAR))) { // don't cancel for melee, autorepeat, triggered and instant spells if (!m_spellInfo->IsNextMeleeSwingSpell() && !IsAutoRepeat() && !IsTriggered() && !(IsChannelActive() && m_spellInfo->IsMoveAllowedChannel())) @@ -4011,9 +4009,14 @@ void Spell::WriteCastResultInfo(WorldPacket& data, Player* caster, SpellInfo con else { uint32 item = 0; - for (uint8 effIndex = 0; effIndex < MAX_SPELL_EFFECTS && !item; ++effIndex) - if (uint32 itemType = spellInfo->Effects[effIndex].ItemType) + for (SpellEffectInfo const& spellEffectInfo : spellInfo->GetEffects()) + { + if (uint32 itemType = spellEffectInfo.ItemType) + { item = itemType; + break; + } + } ItemTemplate const* proto = sObjectMgr->GetItemTemplate(item); if (proto && proto->ItemLimitCategory) @@ -4490,17 +4493,17 @@ void Spell::SendLogExecute() return; data << uint32(effCount); - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) { - if (!m_effectExecuteData[i]) + if (!m_effectExecuteData[spellEffectInfo.EffectIndex]) continue; - data << uint32(m_spellInfo->Effects[i].Effect); // spell effect + data << uint32(spellEffectInfo.Effect); // spell effect - data.append(*m_effectExecuteData[i]); + data.append(*m_effectExecuteData[spellEffectInfo.EffectIndex]); - delete m_effectExecuteData[i]; - m_effectExecuteData[i] = nullptr; + delete m_effectExecuteData[spellEffectInfo.EffectIndex]; + m_effectExecuteData[spellEffectInfo.EffectIndex] = nullptr; } m_caster->SendMessageToSet(&data, true); } @@ -5070,26 +5073,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, Corpse* pCorpseTarget, uint32 i, SpellEffectHandleMode mode) +void Spell::HandleEffects(Unit* pUnitTarget, Item* pItemTarget, GameObject* pGoTarget, Corpse* pCorpseTarget, SpellEffectInfo const& spellEffectInfo, SpellEffectHandleMode mode) { effectHandleMode = mode; unitTarget = pUnitTarget; itemTarget = pItemTarget; gameObjTarget = pGoTarget; m_corpseTarget = pCorpseTarget; - destTarget = &m_destTargets[i]._position; - - uint8 effect = m_spellInfo->Effects[i].Effect; - ASSERT(effect < TOTAL_SPELL_EFFECTS); // checked at startup + destTarget = &m_destTargets[spellEffectInfo.EffectIndex]._position; // we do not need DamageMultiplier here. - damage = CalculateDamage(i); + damage = CalculateDamage(spellEffectInfo); - SpellEffIndex effIndex = static_cast<SpellEffIndex>(i); - bool preventDefault = CallScriptEffectHandlers(effIndex, mode); + bool preventDefault = CallScriptEffectHandlers(spellEffectInfo.EffectIndex, mode); if (!preventDefault) - (this->*SpellEffectHandlers[effect])(effIndex); + (this->*SpellEffectHandlers[effectInfo->Effect])(spellEffectInfo.EffectIndex); } SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint32* param2 /*= nullptr*/) @@ -5227,7 +5226,7 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint if (unitCaster->GetTypeId() == TYPEID_PLAYER && unitCaster->ToPlayer()->isMoving() && (!unitCaster->IsCharmed() || !unitCaster->GetCharmerGUID().IsCreature())) { // skip stuck spell to allow use it in falling case and apply spell limitations at movement - if ((!unitCaster->HasUnitMovementFlag(MOVEMENTFLAG_FALLING_FAR) || m_spellInfo->Effects[EFFECT_0].Effect != SPELL_EFFECT_STUCK) && + if ((!unitCaster->HasUnitMovementFlag(MOVEMENTFLAG_FALLING_FAR) || !m_spellInfo->HasEffect(SPELL_EFFECT_STUCK)) && (IsAutoRepeat() || (m_spellInfo->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) != 0)) return SPELL_FAILED_MOVING; } @@ -5321,9 +5320,9 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint // check pet presence if (Unit* unitCaster = m_caster->ToUnit()) { - for (uint8 j = EFFECT_0; j < MAX_SPELL_EFFECTS; ++j) + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) { - if (m_spellInfo->Effects[j].TargetA.GetTarget() == TARGET_UNIT_PET) + if (spellEffectInfo.TargetA.GetTarget() == TARGET_UNIT_PET) { if (!unitCaster->GetGuardianPet()) { @@ -5420,19 +5419,19 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint bool hasDispellableAura = false; bool hasNonDispelEffect = false; uint32 dispelMask = 0; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) { - if (m_spellInfo->Effects[i].Effect == SPELL_EFFECT_DISPEL) + if (spellEffectInfo.Effect == SPELL_EFFECT_DISPEL) { - if (m_spellInfo->Effects[i].IsTargetingArea() || m_spellInfo->HasAttribute(SPELL_ATTR1_MELEE_COMBAT_START)) + if (spellEffectInfo.IsTargetingArea() || m_spellInfo->HasAttribute(SPELL_ATTR1_MELEE_COMBAT_START)) { hasDispellableAura = true; break; } - dispelMask |= SpellInfo::GetDispelMask(DispelType(m_spellInfo->Effects[i].MiscValue)); + dispelMask |= SpellInfo::GetDispelMask(DispelType(spellEffectInfo.MiscValue)); } - else if (m_spellInfo->Effects[i].IsEffect()) + else if (spellEffectInfo.IsEffect()) { hasNonDispelEffect = true; break; @@ -5467,24 +5466,24 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint uint8 approximateAuraEffectMask = 0; uint8 nonAuraEffectMask = 0; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) { // for effects of spells that have only one target - switch (m_spellInfo->Effects[i].Effect) + switch (spellEffectInfo.Effect) { case SPELL_EFFECT_LEARN_SPELL: { if (m_caster->GetTypeId() != TYPEID_PLAYER) return SPELL_FAILED_BAD_TARGETS; - if (m_spellInfo->Effects[i].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(m_spellInfo->Effects[i].TriggerSpell); + SpellInfo const* learn_spellproto = sSpellMgr->GetSpellInfo(spellEffectInfo.TriggerSpell); if (!learn_spellproto) return SPELL_FAILED_NOT_KNOWN; @@ -5505,7 +5504,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(m_spellInfo->Effects[i].TriggerSpell); + SpellInfo const* learn_spellproto = sSpellMgr->GetSpellInfo(spellEffectInfo.TriggerSpell); if (!learn_spellproto) return SPELL_FAILED_NOT_KNOWN; @@ -5520,7 +5519,7 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint if (m_caster->GetTypeId() != TYPEID_PLAYER) return SPELL_FAILED_BAD_TARGETS; - uint32 glyphId = m_spellInfo->Effects[i].MiscValue; + uint32 glyphId = spellEffectInfo.MiscValue; if (GlyphPropertiesEntry const* gp = sGlyphPropertiesStore.LookupEntry(glyphId)) if (m_caster->ToPlayer()->HasAura(gp->SpellID)) return SPELL_FAILED_UNIQUE_GLYPH; @@ -5556,7 +5555,7 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint // Can be area effect, Check only for players and not check if target - caster (spell can have multiply drain/burn effects) if (m_caster->GetTypeId() == TYPEID_PLAYER) if (Unit* target = m_targets.GetUnitTarget()) - if (target != m_caster && target->GetPowerType() != Powers(m_spellInfo->Effects[i].MiscValue)) + if (target != m_caster && target->GetPowerType() != Powers(spellEffectInfo.MiscValue)) return SPELL_FAILED_BAD_TARGETS; break; } @@ -5629,13 +5628,13 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint } case SPELL_EFFECT_OPEN_LOCK: { - if (m_spellInfo->Effects[i].TargetA.GetTarget() != TARGET_GAMEOBJECT_TARGET && - m_spellInfo->Effects[i].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 - || (m_spellInfo->Effects[i].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; @@ -5648,7 +5647,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 (m_spellInfo->Effects[i].TargetA.GetTarget() == TARGET_GAMEOBJECT_ITEM_TARGET && + if (spellEffectInfo.TargetA.GetTarget() == TARGET_GAMEOBJECT_ITEM_TARGET && !m_targets.GetGOTarget() && (!pTempItem || !pTempItem->GetTemplate()->LockID || !pTempItem->IsLocked())) return SPELL_FAILED_BAD_TARGETS; @@ -5675,7 +5674,7 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint int32 skillValue = 0; // check lock compatibility - SpellCastResult res = CanOpenLock(i, lockId, skillId, reqSkillValue, skillValue); + SpellCastResult res = CanOpenLock(spellEffectInfo, lockId, skillId, reqSkillValue, skillValue); if (res != SPELL_CAST_OK) return res; @@ -5709,7 +5708,7 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint if (!unitCaster) break; - SummonPropertiesEntry const* SummonProperties = sSummonPropertiesStore.LookupEntry(m_spellInfo->Effects[i].MiscValueB); + SummonPropertiesEntry const* SummonProperties = sSummonPropertiesStore.LookupEntry(spellEffectInfo.MiscValueB); if (!SummonProperties) break; @@ -5761,7 +5760,7 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint Player* playerCaster = unitCaster->ToPlayer(); if (playerCaster && playerCaster->GetPetStable()) { - std::pair<PetStable::PetInfo const*, PetSaveMode> info = Pet::GetLoadPetInfo(*playerCaster->GetPetStable(), m_spellInfo->Effects[i].MiscValue, 0, false); + std::pair<PetStable::PetInfo const*, PetSaveMode> info = Pet::GetLoadPetInfo(*playerCaster->GetPetStable(), spellEffectInfo.MiscValue, 0, false); if (info.first) { if (info.first->Type == HUNTER_PET) @@ -5785,7 +5784,7 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint } } } - else if (!m_spellInfo->Effects[i].MiscValue) // when miscvalue is present it is allowed to create new pets + else if (!spellEffectInfo.MiscValue) // when miscvalue is present it is allowed to create new pets { playerCaster->SendTameFailure(PETTAME_NOPETAVAILABLE); return SPELL_FAILED_DONT_REPORT; @@ -5860,7 +5859,7 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint if (!m_targets.GetUnitTarget() || m_targets.GetUnitTarget() == m_caster) return SPELL_FAILED_BAD_TARGETS; - dispelMask = SpellInfo::GetDispelMask(DispelType(m_spellInfo->Effects[i].MiscValue)); + dispelMask = SpellInfo::GetDispelMask(DispelType(spellEffectInfo.MiscValue)); bool hasStealableAura = false; Unit::VisibleAuraMap const* visibleAuras = m_targets.GetUnitTarget()->GetVisibleAuras(); for (Unit::VisibleAuraMap::const_iterator itr = visibleAuras->begin(); itr != visibleAuras->end(); ++itr) @@ -5921,15 +5920,15 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint break; } - if (m_spellInfo->Effects[i].IsAura()) - approximateAuraEffectMask |= 1 << i; - else if (m_spellInfo->Effects[i].IsEffect()) - nonAuraEffectMask |= 1 << i; + if (spellEffectInfo.IsAura()) + approximateAuraEffectMask |= 1 << spellEffectInfo.EffectIndex; + else if (spellEffectInfo.IsEffect()) + nonAuraEffectMask |= 1 << spellEffectInfo.EffectIndex; } - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) { - switch (m_spellInfo->Effects[i].ApplyAuraName) + switch (spellEffectInfo.ApplyAuraName) { case SPELL_AURA_MOD_POSSESS_PET: { @@ -5955,8 +5954,8 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint if (unitCaster->GetCharmerGUID()) return SPELL_FAILED_CHARMED; - if (m_spellInfo->Effects[i].ApplyAuraName == SPELL_AURA_MOD_CHARM - || m_spellInfo->Effects[i].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()) return SPELL_FAILED_ALREADY_HAVE_SUMMON; @@ -5979,7 +5978,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(i); + int32 value = CalculateDamage(spellEffectInfo); if (value && int32(target->GetLevel()) > value) return SPELL_FAILED_HIGHLEVEL; } @@ -6036,7 +6035,7 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint } case SPELL_AURA_PERIODIC_MANA_LEECH: { - if (m_spellInfo->Effects[i].IsTargetingArea()) + if (spellEffectInfo.IsTargetingArea()) break; if (!m_targets.GetUnitTarget()) @@ -6054,10 +6053,10 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint } // check if target already has the same type, but more powerful aura - if (!nonAuraEffectMask && (approximateAuraEffectMask & (1 << i)) && !m_spellInfo->IsTargetingArea()) + if (!nonAuraEffectMask && (approximateAuraEffectMask & (1 << spellEffectInfo.EffectIndex)) && !m_spellInfo->IsTargetingArea()) if (Unit* target = m_targets.GetUnitTarget()) - if (!target->IsHighestExclusiveAuraEffect(m_spellInfo, AuraType(m_spellInfo->Effects[i].ApplyAuraName), - m_spellInfo->Effects[i].CalcValue(m_caster, &m_spellValue->EffectBasePoints[i]), approximateAuraEffectMask, false)) + if (!target->IsHighestExclusiveAuraEffect(m_spellInfo, AuraType(spellEffectInfo.ApplyAuraName), + spellEffectInfo.CalcValue(m_caster, &m_spellValue->EffectBasePoints[spellEffectInfo.EffectIndex]), approximateAuraEffectMask, false)) return SPELL_FAILED_AURA_BOUNCED; } @@ -6206,7 +6205,7 @@ SpellCastResult Spell::CheckCasterAuras(uint32* param1) const // fill up aura mechanic info to send client proper error message if (param1) { - *param1 = aurEff->GetSpellInfo()->Effects[aurEff->GetEffIndex()].Mechanic; + *param1 = aurEff->GetSpellEffectInfo().Mechanic; if (!*param1) *param1 = aurEff->GetSpellInfo()->Mechanic; } @@ -6300,7 +6299,7 @@ bool Spell::CheckSpellCancelsAuraEffect(AuraType auraType, uint32* param1) const if (param1) { - *param1 = auraInfo->Effects[aurEff->GetEffIndex()].Mechanic; + *param1 = aurEff->GetSpellEffectInfo().Mechanic; if (!*param1) *param1 = auraInfo->Mechanic; } @@ -6346,9 +6345,9 @@ bool Spell::CheckSpellCancelsConfuse(uint32* param1) const return CheckSpellCancelsAuraEffect(SPELL_AURA_MOD_CONFUSE, param1); } -int32 Spell::CalculateDamage(uint8 effIndex) const +int32 Spell::CalculateDamage(SpellEffectInfo const& spellEffectInfo) const { - return m_caster->CalculateSpellDamage(m_spellInfo, effIndex, m_spellValue->EffectBasePoints + effIndex); + return m_caster->CalculateSpellDamage(spellEffectInfo, m_spellValue->EffectBasePoints + spellEffectInfo.EffectIndex); } bool Spell::CanAutoCast(Unit* target) @@ -6359,12 +6358,12 @@ bool Spell::CanAutoCast(Unit* target) ObjectGuid targetguid = target->GetGUID(); // check if target already has the same or a more powerful aura - for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) { - if (!GetSpellInfo()->Effects[i].IsAura()) + if (!spellEffectInfo.IsAura()) continue; - AuraType const& auraType = AuraType(GetSpellInfo()->Effects[i].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) { @@ -6381,7 +6380,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(GetSpellInfo()->Effects[i].BasePoints) <= abs((*auraIt)->GetAmount())) + if (abs(spellEffectInfo.BasePoints) <= abs((*auraIt)->GetAmount())) return false; break; case SPELL_GROUP_STACK_RULE_DEFAULT: @@ -6596,13 +6595,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 (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + 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 (m_spellInfo->Effects[i].TargetA.GetTarget() == TARGET_UNIT_PET) + if (spellEffectInfo.TargetA.GetTarget() == TARGET_UNIT_PET) continue; - if (m_spellInfo->Effects[i].Effect == SPELL_EFFECT_HEAL) + if (spellEffectInfo.IsEffect(SPELL_EFFECT_HEAL)) { if (m_targets.GetUnitTarget()->IsFullHealth()) { @@ -6617,15 +6616,15 @@ SpellCastResult Spell::CheckItems(uint32* param1 /*= nullptr*/, uint32* param2 / } // Mana Potion, Rage Potion, Thistle Tea(Rogue), ... - if (m_spellInfo->Effects[i].Effect == SPELL_EFFECT_ENERGIZE) + if (spellEffectInfo.IsEffect(SPELL_EFFECT_ENERGIZE)) { - if (m_spellInfo->Effects[i].MiscValue < 0 || m_spellInfo->Effects[i].MiscValue >= int8(MAX_POWERS)) + if (spellEffectInfo.MiscValue < 0 || spellEffectInfo.MiscValue >= int8(MAX_POWERS)) { failReason = SPELL_FAILED_ALREADY_AT_FULL_POWER; continue; } - Powers power = Powers(m_spellInfo->Effects[i].MiscValue); + Powers power = Powers(spellEffectInfo.MiscValue); if (m_targets.GetUnitTarget()->GetPower(power) == m_targets.GetUnitTarget()->GetMaxPower(power)) { failReason = SPELL_FAILED_ALREADY_AT_FULL_POWER; @@ -6746,9 +6745,9 @@ SpellCastResult Spell::CheckItems(uint32* param1 /*= nullptr*/, uint32* param2 / } // special checks for spell effects - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) { - switch (m_spellInfo->Effects[i].Effect) + switch (spellEffectInfo.Effect) { case SPELL_EFFECT_CREATE_ITEM: case SPELL_EFFECT_CREATE_ITEM_2: @@ -6759,28 +6758,28 @@ SpellCastResult Spell::CheckItems(uint32* param1 /*= nullptr*/, uint32* param2 / { // SPELL_EFFECT_CREATE_ITEM_2 differs from SPELL_EFFECT_CREATE_ITEM in that it picks the random item to create from a pool of potential items, // so we need to make sure there is at least one free space in the player's inventory - if (m_spellInfo->Effects[i].Effect == SPELL_EFFECT_CREATE_ITEM_2) + if (spellEffectInfo.IsEffect(SPELL_EFFECT_CREATE_ITEM_2)) if (target->ToPlayer()->GetFreeInventorySpace() == 0) { - player->SendEquipError(EQUIP_ERR_INVENTORY_FULL, nullptr, nullptr, m_spellInfo->Effects[i].ItemType); + player->SendEquipError(EQUIP_ERR_INVENTORY_FULL, nullptr, nullptr, spellEffectInfo.ItemType); return SPELL_FAILED_DONT_REPORT; } - if (m_spellInfo->Effects[i].ItemType) + if (spellEffectInfo.ItemType) { - ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(m_spellInfo->Effects[i].ItemType); + ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(spellEffectInfo.ItemType); if (!itemTemplate) return SPELL_FAILED_ITEM_NOT_FOUND; - uint32 createCount = std::clamp<uint32>(m_spellInfo->Effects[i].CalcValue(), 1u, itemTemplate->GetMaxStackSize()); + uint32 createCount = std::clamp<uint32>(spellEffectInfo.CalcValue(), 1u, itemTemplate->GetMaxStackSize()); ItemPosCountVec dest; - InventoryResult msg = target->ToPlayer()->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, m_spellInfo->Effects[i].ItemType, createCount); + InventoryResult msg = target->ToPlayer()->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, spellEffectInfo.ItemType, createCount); if (msg != EQUIP_ERR_OK) { /// @todo Needs review if (!itemTemplate->ItemLimitCategory) { - player->SendEquipError(msg, nullptr, nullptr, m_spellInfo->Effects[i].ItemType); + player->SendEquipError(msg, nullptr, nullptr, spellEffectInfo.ItemType); return SPELL_FAILED_DONT_REPORT; } else @@ -6788,13 +6787,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(m_spellInfo->Effects[i].ItemType))) + else if (!(target->ToPlayer()->HasItemCount(spellEffectInfo.ItemType))) { - player->SendEquipError(msg, nullptr, nullptr, m_spellInfo->Effects[i].ItemType); + player->SendEquipError(msg, nullptr, nullptr, spellEffectInfo.ItemType); return SPELL_FAILED_DONT_REPORT; } else - player->CastSpell(player, m_spellInfo->Effects[EFFECT_1].CalcValue(), false); // move this to anywhere + player->CastSpell(player, m_spellInfo->GetEffect(EFFECT_1).CalcValue(), false); // move this to anywhere return SPELL_FAILED_DONT_REPORT; } } @@ -6803,7 +6802,7 @@ SpellCastResult Spell::CheckItems(uint32* param1 /*= nullptr*/, uint32* param2 / break; } case SPELL_EFFECT_ENCHANT_ITEM: - if (m_spellInfo->Effects[i].ItemType && m_targets.GetItemTarget() + if (spellEffectInfo.ItemType && m_targets.GetItemTarget() && (m_targets.GetItemTarget()->IsWeaponVellum() || m_targets.GetItemTarget()->IsArmorVellum())) { // cannot enchant vellum for other player @@ -6813,10 +6812,10 @@ SpellCastResult Spell::CheckItems(uint32* param1 /*= nullptr*/, uint32* param2 / if (m_CastItem && m_CastItem->GetTemplate()->HasFlag(ITEM_FLAG_NO_REAGENT_COST)) return SPELL_FAILED_TOTEM_CATEGORY; ItemPosCountVec dest; - InventoryResult msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, m_spellInfo->Effects[i].ItemType, 1); + InventoryResult msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, spellEffectInfo.ItemType, 1); if (msg != EQUIP_ERR_OK) { - player->SendEquipError(msg, nullptr, nullptr, m_spellInfo->Effects[i].ItemType); + player->SendEquipError(msg, nullptr, nullptr, spellEffectInfo.ItemType); return SPELL_FAILED_DONT_REPORT; } } @@ -6844,7 +6843,7 @@ SpellCastResult Spell::CheckItems(uint32* param1 /*= nullptr*/, uint32* param2 / } } - SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(m_spellInfo->Effects[i].MiscValue); + SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(spellEffectInfo.MiscValue); // do not allow adding usable enchantments to items that have use effect already if (enchantEntry) { @@ -6889,7 +6888,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 = m_spellInfo->Effects[i].MiscValue; + uint32 enchant_id = spellEffectInfo.MiscValue; SpellItemEnchantmentEntry const* pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id); if (!pEnchant) return SPELL_FAILED_ERROR; @@ -7072,7 +7071,7 @@ SpellCastResult Spell::CheckItems(uint32* param1 /*= nullptr*/, uint32* param2 / } case SPELL_EFFECT_CREATE_MANA_GEM: { - uint32 item_id = m_spellInfo->Effects[i].ItemType; + uint32 item_id = spellEffectInfo.ItemType; ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(item_id); if (!pProto) @@ -7249,9 +7248,9 @@ bool Spell::UpdatePointers() WorldObject* transport = nullptr; // update effect destinations (in case of moved transport dest target) - for (uint8 effIndex = 0; effIndex < MAX_SPELL_EFFECTS; ++effIndex) + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) { - SpellDestination& dest = m_destTargets[effIndex]; + SpellDestination& dest = m_destTargets[spellEffectInfo.EffectIndex]; if (!dest._transportGUID) continue; @@ -7280,9 +7279,9 @@ CurrentSpellTypes Spell::GetCurrentContainer() const return CURRENT_GENERIC_SPELL; } -bool Spell::CheckEffectTarget(Unit const* target, uint32 eff, Position const* losPosition) const +bool Spell::CheckEffectTarget(Unit const* target, SpellEffectInfo const& spellEffectInfo, Position const* losPosition) const { - switch (m_spellInfo->Effects[eff].ApplyAuraName) + switch (spellEffectInfo.ApplyAuraName) { case SPELL_AURA_MOD_POSSESS: case SPELL_AURA_MOD_CHARM: @@ -7294,7 +7293,7 @@ bool Spell::CheckEffectTarget(Unit const* target, uint32 eff, Position const* lo return false; if (target->GetCharmerGUID()) return false; - if (int32 value = CalculateDamage(eff)) + if (int32 value = CalculateDamage(spellEffectInfo)) if ((int32)target->GetLevel() > value) return false; break; @@ -7317,7 +7316,7 @@ bool Spell::CheckEffectTarget(Unit const* target, uint32 eff, Position const* lo /// @todo shit below shouldn't be here, but it's temporary //Check targets for LOS visibility (except spells without range limitations) - switch (m_spellInfo->Effects[eff].Effect) + switch (spellEffectInfo.Effect) { case SPELL_EFFECT_RESURRECT_NEW: // player far away, maybe his corpse near? @@ -7573,13 +7572,13 @@ bool Spell::IsValidDeadOrAliveTarget(Unit const* target) const void Spell::HandleLaunchPhase() { // handle effects with SPELL_EFFECT_HANDLE_LAUNCH mode - for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) { // don't do anything for empty effect - if (!m_spellInfo->Effects[i].IsEffect()) + if (!spellEffectInfo.IsEffect()) continue; - HandleEffects(nullptr, nullptr, nullptr, nullptr, i, SPELL_EFFECT_HANDLE_LAUNCH); + HandleEffects(nullptr, nullptr, nullptr, nullptr, spellEffectInfo, SPELL_EFFECT_HANDLE_LAUNCH); } PrepareTargetProcessing(); @@ -7599,26 +7598,26 @@ void Spell::HandleLaunchPhase() TakeAmmo(); } - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) { float multiplier = 1.0f; - if (m_applyMultiplierMask & (1 << i)) - multiplier = m_spellInfo->Effects[i].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 << i))) + if (!(mask & (1 << spellEffectInfo.EffectIndex))) continue; - DoEffectOnLaunchTarget(target, multiplier, i); + DoEffectOnLaunchTarget(target, multiplier, spellEffectInfo); } } FinishTargetProcessing(); } -void Spell::DoEffectOnLaunchTarget(TargetInfo& targetInfo, float multiplier, uint8 effIndex) +void Spell::DoEffectOnLaunchTarget(TargetInfo& targetInfo, float multiplier, SpellEffectInfo const& spellEffectInfo) { Unit* unit = nullptr; // In case spell hit target, do all effect on that target @@ -7638,11 +7637,11 @@ void Spell::DoEffectOnLaunchTarget(TargetInfo& targetInfo, float multiplier, uin m_damage = 0; m_healing = 0; - HandleEffects(unit, nullptr, nullptr, nullptr, effIndex, SPELL_EFFECT_HANDLE_LAUNCH_TARGET); + HandleEffects(unit, nullptr, nullptr, nullptr, spellEffectInfo, SPELL_EFFECT_HANDLE_LAUNCH_TARGET); if (m_originalCaster && m_damage > 0) { - if (m_spellInfo->Effects[effIndex].IsTargetingArea() || m_spellInfo->Effects[effIndex].IsAreaAuraEffect() || m_spellInfo->Effects[effIndex].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()); @@ -7656,12 +7655,12 @@ void Spell::DoEffectOnLaunchTarget(TargetInfo& targetInfo, float multiplier, uin } } - if (m_applyMultiplierMask & (1 << effIndex)) + if (m_applyMultiplierMask & (1 << spellEffectInfo.EffectIndex)) { - m_damage = int32(m_damage * m_damageMultipliers[effIndex]); - m_healing = int32(m_healing * m_damageMultipliers[effIndex]); + m_damage = int32(m_damage * m_damageMultipliers[spellEffectInfo.EffectIndex]); + m_healing = int32(m_healing * m_damageMultipliers[spellEffectInfo.EffectIndex]); - m_damageMultipliers[effIndex] *= multiplier; + m_damageMultipliers[spellEffectInfo.EffectIndex] *= multiplier; } targetInfo.Damage += m_damage; @@ -7678,7 +7677,7 @@ void Spell::DoEffectOnLaunchTarget(TargetInfo& targetInfo, float multiplier, uin targetInfo.IsCrit = roll_chance_f(critChance); } -SpellCastResult Spell::CanOpenLock(uint32 effIndex, uint32 lockId, SkillType& skillId, int32& reqSkillValue, int32& skillValue) +SpellCastResult Spell::CanOpenLock(SpellEffectInfo const& spellEffectInfo, uint32 lockId, SkillType& skillId, int32& reqSkillValue, int32& skillValue) { if (!lockId) // possible case for GO and maybe for items. return SPELL_CAST_OK; @@ -7707,7 +7706,7 @@ SpellCastResult Spell::CanOpenLock(uint32 effIndex, uint32 lockId, SkillType& sk reqKey = true; // wrong locktype, skip - if (uint32(m_spellInfo->Effects[effIndex].MiscValue) != lockInfo->Index[j]) + if (uint32(spellEffectInfo.MiscValue) != lockInfo->Index[j]) continue; skillId = SkillByLockType(LockType(lockInfo->Index[j])); @@ -7722,8 +7721,8 @@ SpellCastResult Spell::CanOpenLock(uint32 effIndex, uint32 lockId, SkillType& sk // skill bonus provided by casting spell (mostly item spells) // add the effect base points modifier from the spell cast (cheat lock / skeleton key etc.) - if (m_spellInfo->Effects[effIndex].TargetA.GetTarget() == TARGET_GAMEOBJECT_ITEM_TARGET || m_spellInfo->Effects[effIndex].TargetB.GetTarget() == TARGET_GAMEOBJECT_ITEM_TARGET) - skillValue += m_spellInfo->Effects[effIndex].CalcValue(); + if (spellEffectInfo.TargetA.GetTarget() == TARGET_GAMEOBJECT_ITEM_TARGET || spellEffectInfo.TargetB.GetTarget() == TARGET_GAMEOBJECT_ITEM_TARGET) + skillValue += spellEffectInfo.CalcValue(); if (skillValue < reqSkillValue) return SPELL_FAILED_LOW_CASTLEVEL; @@ -7750,13 +7749,13 @@ void Spell::SetSpellValue(SpellValueMod mod, int32 value) switch (mod) { case SPELLVALUE_BASE_POINT0: - m_spellValue->EffectBasePoints[0] = m_spellInfo->Effects[EFFECT_0].CalcBaseValue(value); + m_spellValue->EffectBasePoints[0] = m_spellInfo->GetEffect(EFFECT_0).CalcBaseValue(value); break; case SPELLVALUE_BASE_POINT1: - m_spellValue->EffectBasePoints[1] = m_spellInfo->Effects[EFFECT_1].CalcBaseValue(value); + m_spellValue->EffectBasePoints[1] = m_spellInfo->GetEffect(EFFECT_1).CalcBaseValue(value); break; case SPELLVALUE_BASE_POINT2: - m_spellValue->EffectBasePoints[2] = m_spellInfo->Effects[EFFECT_2].CalcBaseValue(value); + m_spellValue->EffectBasePoints[2] = m_spellInfo->GetEffect(EFFECT_2).CalcBaseValue(value); break; case SPELLVALUE_RADIUS_MOD: m_spellValue->RadiusMod = (float)value / 10000; @@ -8046,9 +8045,9 @@ bool Spell::CanExecuteTriggersOnHit(uint8 effMask, SpellInfo const* triggeredByA { 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 (uint8 i = 0;i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) { - if ((effMask & (1 << i)) && (!only_on_caster || (m_spellInfo->Effects[i].TargetA.GetTarget() == TARGET_UNIT_CASTER))) + if ((effMask & (1 << spellEffectInfo.EffectIndex)) && (!only_on_caster || (spellEffectInfo.TargetA.GetTarget() == TARGET_UNIT_CASTER))) return true; } return false; @@ -8070,14 +8069,13 @@ void Spell::PrepareTriggersExecutedOnHit() continue; SpellInfo const* auraSpellInfo = aurEff->GetSpellInfo(); - uint32 auraSpellIdx = aurEff->GetEffIndex(); - if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(auraSpellInfo->Effects[auraSpellIdx].TriggerSpell)) + if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(aurEff->GetSpellEffectInfo().TriggerSpell)) { // 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(auraSpellInfo, auraSpellIdx, &auraBaseAmount); + int32 chance = unitCaster->CalculateSpellDamage(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 e78bbcbfffe..0ef88399b20 100644 --- a/src/server/game/Spells/Spell.h +++ b/src/server/game/Spells/Spell.h @@ -46,6 +46,7 @@ class Item; class Object; class PathGenerator; class Player; +class SpellEffectInfo; class SpellEvent; class SpellImplicitTargetInfo; class SpellInfo; @@ -399,20 +400,20 @@ 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 SelectEffectTypeImplicitTargets(uint8 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 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); @@ -459,7 +460,7 @@ class TC_GAME_API Spell bool CheckSpellCancelsFear(uint32* param1) const; bool CheckSpellCancelsConfuse(uint32* param1) const; - int32 CalculateDamage(uint8 effIndex) const; + int32 CalculateDamage(SpellEffectInfo const& spellEffectInfo) const; void Delayed(); void DelayedChannel(); @@ -470,7 +471,7 @@ class TC_GAME_API Spell void UpdateSpellCastDataTargets(WorldPackets::Spells::SpellCastData& data); void UpdateSpellCastDataAmmo(WorldPackets::Spells::SpellAmmo& data); - bool CheckEffectTarget(Unit const* target, uint32 eff, Position const* losPosition) const; + bool CheckEffectTarget(Unit const* target, SpellEffectInfo const& spellEffectInfo, Position const* losPosition) const; bool CanAutoCast(Unit* target); void CheckSrc(); void CheckDst(); @@ -499,7 +500,7 @@ class TC_GAME_API Spell void SendChannelStart(uint32 duration); void SendResurrectRequest(Player* target); - void HandleEffects(Unit* pUnitTarget, Item* pItemTarget, GameObject* pGoTarget, Corpse* pCorpseTarget, uint32 i, SpellEffectHandleMode mode); + void HandleEffects(Unit* pUnitTarget, Item* pItemTarget, GameObject* pGoTarget, Corpse* pCorpseTarget, SpellEffectInfo const& spellEffectInfo, SpellEffectHandleMode mode); void HandleThreatSpells(); SpellInfo const* const m_spellInfo; @@ -657,7 +658,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*/) { } uint8 EffectMask = 0; @@ -670,7 +671,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; @@ -702,7 +703,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; @@ -711,7 +712,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; }; @@ -719,7 +720,7 @@ class TC_GAME_API Spell struct CorpseTargetInfo : public TargetInfoBase { - void DoTargetSpellHit(Spell* spell, uint8 effIndex) override; + void DoTargetSpellHit(Spell* spell, SpellEffectInfo const& spellEffectInfo) override; ObjectGuid TargetGUID; uint64 TimeDelay = 0ULL; @@ -738,13 +739,13 @@ class TC_GAME_API Spell void AddDestTarget(SpellDestination const& dest, uint32 effIndex); SpellMissInfo PreprocessSpellHit(Unit* unit, bool scaleAura, TargetInfo& targetInfo); - void DoSpellEffectHit(Unit* unit, uint8 effIndex, TargetInfo& targetInfo); + void DoSpellEffectHit(Unit* unit, SpellEffectInfo const& spellEffectInfo, TargetInfo& targetInfo); void DoTriggersOnSpellHit(Unit* unit, uint8 effMask); bool UpdateChanneledTargetList(); bool IsValidDeadOrAliveTarget(Unit const* target) const; void HandleLaunchPhase(); - void DoEffectOnLaunchTarget(TargetInfo& targetInfo, float multiplier, uint8 effIndex); + void DoEffectOnLaunchTarget(TargetInfo& targetInfo, float multiplier, SpellEffectInfo const& spellEffectInfo); void PrepareTargetProcessing(); void FinishTargetProcessing(); @@ -790,7 +791,7 @@ class TC_GAME_API Spell void SummonGuardian(uint32 i, uint32 entry, SummonPropertiesEntry const* properties, uint32 numSummons); void CalculateJumpSpeeds(SpellInfo const* spellInfo, uint8 i, float dist, float& speedXY, float& speedZ); - SpellCastResult CanOpenLock(uint32 effIndex, uint32 lockid, SkillType& skillid, int32& reqSkillValue, int32& skillValue); + SpellCastResult CanOpenLock(SpellEffectInfo const& spellEffectInfo, uint32 lockid, SkillType& skillid, int32& reqSkillValue, int32& skillValue); // ------------------------------------------- uint32 m_spellState; diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index cfe1096930a..fa4b8ea9a4a 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -367,7 +367,7 @@ void Spell::EffectSchoolDMG(SpellEffIndex effIndex) // Shockwave else if (m_spellInfo->Id == 46968) { - int32 pct = unitCaster->CalculateSpellDamage(m_spellInfo, EFFECT_2); + int32 pct = unitCaster->CalculateSpellDamage(m_spellInfo->GetEffect(EFFECT_2)); if (pct > 0) damage += int32(CalculatePct(unitCaster->GetTotalAttackPowerValue(BASE_ATTACK), pct)); break; @@ -425,10 +425,10 @@ void Spell::EffectSchoolDMG(SpellEffIndex effIndex) // And multiply by amount of ticks to get damage potential pdamage *= aura->GetSpellInfo()->GetMaxTicks(); - int32 pct_dir = unitCaster->CalculateSpellDamage(m_spellInfo, EFFECT_1); + int32 pct_dir = unitCaster->CalculateSpellDamage(m_spellInfo->GetEffect(EFFECT_1)); damage += CalculatePct(pdamage, pct_dir); - int32 pct_dot = unitCaster->CalculateSpellDamage(m_spellInfo, EFFECT_2); + int32 pct_dot = unitCaster->CalculateSpellDamage(m_spellInfo->GetEffect(EFFECT_2)); int32 const dotBasePoints = CalculatePct(pdamage, pct_dot); ASSERT(m_spellInfo->GetMaxTicks() > 0); @@ -652,7 +652,7 @@ void Spell::EffectSchoolDMG(SpellEffIndex effIndex) float average = (minTotal + maxTotal) / 2; // Add main hand dps * effect[2] amount - int32 count = unitCaster->CalculateSpellDamage(m_spellInfo, EFFECT_2); + int32 count = unitCaster->CalculateSpellDamage(m_spellInfo->GetEffect(EFFECT_2)); damage += count * int32(average * IN_MILLISECONDS) / unitCaster->GetAttackTime(BASE_ATTACK); break; } @@ -1847,7 +1847,7 @@ void Spell::EffectOpenLock(SpellEffIndex effIndex) int32 reqSkillValue = 0; int32 skillValue; - SpellCastResult res = CanOpenLock(effIndex, lockId, skillId, reqSkillValue, skillValue); + SpellCastResult res = CanOpenLock(m_spellInfo->GetEffect(effIndex), lockId, skillId, reqSkillValue, skillValue); if (res != SPELL_CAST_OK) { SendCastResult(res); @@ -3039,11 +3039,11 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex) unitCaster->CastSpell(unitTarget, 58567, true); if (Aura* aur = unitTarget->GetAura(58567, unitCaster->GetGUID())) - fixed_bonus += (aur->GetStackAmount() - 1) * CalculateDamage(EFFECT_2); // subtract 1 so fixed bonus is not applied twice + fixed_bonus += (aur->GetStackAmount() - 1) * CalculateDamage(m_spellInfo->GetEffect(EFFECT_2)); // subtract 1 so fixed bonus is not applied twice } else if (m_spellInfo->SpellFamilyFlags[0] & 0x8000000) // Mocking Blow { - if (unitTarget->IsImmunedToSpellEffect(m_spellInfo, EFFECT_1, unitCaster) || unitTarget->GetTypeId() == TYPEID_PLAYER) + if (unitTarget->IsImmunedToSpellEffect(m_spellInfo, m_spellInfo->GetEffect(EFFECT_1), unitCaster) || unitTarget->GetTypeId() == TYPEID_PLAYER) { m_damage = 0; return; @@ -3206,20 +3206,20 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex) bool normalized = false; float weaponDamagePercentMod = 1.0f; - for (uint8 j = 0; j < MAX_SPELL_EFFECTS; ++j) + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) { - switch (m_spellInfo->Effects[j].Effect) + switch (spellEffectInfo.Effect) { case SPELL_EFFECT_WEAPON_DAMAGE: case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL: - fixed_bonus += CalculateDamage(j); + fixed_bonus += CalculateDamage(spellEffectInfo); break; case SPELL_EFFECT_NORMALIZED_WEAPON_DMG: - fixed_bonus += CalculateDamage(j); + fixed_bonus += CalculateDamage(spellEffectInfo); normalized = true; break; case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE: - ApplyPct(weaponDamagePercentMod, CalculateDamage(j)); + ApplyPct(weaponDamagePercentMod, CalculateDamage(spellEffectInfo)); break; default: break; // not weapon damage effect, just skip diff --git a/src/server/scripts/Spells/spell_dk.cpp b/src/server/scripts/Spells/spell_dk.cpp index f396c45d8b9..b5f0a6de54a 100644 --- a/src/server/scripts/Spells/spell_dk.cpp +++ b/src/server/scripts/Spells/spell_dk.cpp @@ -587,11 +587,11 @@ class spell_dk_corpse_explosion : public SpellScript if (effIndex == EFFECT_0) { args.AddSpellBP0(GetEffectValue()); - GetCaster()->CastSpell(target, GetSpellInfo()->Effects[EFFECT_1].CalcValue(), args); + GetCaster()->CastSpell(target, GetSpellInfo()->GetEffect(EFFECT_1).CalcValue(), args); } else if (effIndex == EFFECT_1) { - args.AddSpellBP0(GetSpell()->CalculateDamage(EFFECT_0)); + args.AddSpellBP0(GetSpell()->CalculateDamage(GetSpellInfo()->GetEffect(EFFECT_0))); GetCaster()->CastSpell(target, GetEffectValue(), args); } } @@ -896,7 +896,7 @@ class spell_dk_death_strike : public SpellScript int32 bp = int32(count * caster->CountPctFromMaxHealth(int32(GetSpellInfo()->Effects[EFFECT_0].DamageMultiplier))); // Improved Death Strike if (AuraEffect const* aurEff = caster->GetAuraEffect(SPELL_AURA_ADD_PCT_MODIFIER, SPELLFAMILY_DEATHKNIGHT, DK_ICON_ID_IMPROVED_DEATH_STRIKE, 0)) - AddPct(bp, caster->CalculateSpellDamage(aurEff->GetSpellInfo(), EFFECT_2)); + AddPct(bp, caster->CalculateSpellDamage(aurEff->GetSpellInfo()->GetEffect(EFFECT_2))); // @todo castspell refactor note: this is not triggered - is this intended?? CastSpellExtraArgs args; @@ -1040,7 +1040,7 @@ class spell_dk_hysteria : public AuraScript void PeriodicTick(AuraEffect const* aurEff) { - uint32 const damage = GetTarget()->CountPctFromMaxHealth(GetTarget()->CalculateSpellDamage(GetSpellInfo(), aurEff->GetEffIndex())); + uint32 const damage = GetTarget()->CountPctFromMaxHealth(GetTarget()->CalculateSpellDamage(aurEff->GetSpellEffectInfo())); Unit::DealDamage(GetTarget(), GetTarget(), damage, nullptr, SELF_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false); } diff --git a/src/server/scripts/Spells/spell_druid.cpp b/src/server/scripts/Spells/spell_druid.cpp index e112f224272..c3d1eb7a772 100644 --- a/src/server/scripts/Spells/spell_druid.cpp +++ b/src/server/scripts/Spells/spell_druid.cpp @@ -457,7 +457,7 @@ class spell_dru_frenzied_regeneration : public AuraScript return; int32 const mod = std::min(static_cast<int32>(rage), 100); - int32 const regen = CalculatePct(GetTarget()->GetMaxHealth(), GetTarget()->CalculateSpellDamage(GetSpellInfo(), EFFECT_1) * mod / 100.f); + int32 const regen = CalculatePct(GetTarget()->GetMaxHealth(), GetTarget()->CalculateSpellDamage(GetSpellInfo()->GetEffect(EFFECT_1)) * mod / 100.f); CastSpellExtraArgs args(aurEff); args.AddSpellBP0(regen); GetTarget()->CastSpell(nullptr, SPELL_DRUID_FRENZIED_REGENERATION_HEAL, args); diff --git a/src/server/scripts/Spells/spell_hunter.cpp b/src/server/scripts/Spells/spell_hunter.cpp index 9273cf24b82..6cdbca548f3 100644 --- a/src/server/scripts/Spells/spell_hunter.cpp +++ b/src/server/scripts/Spells/spell_hunter.cpp @@ -939,7 +939,7 @@ class spell_hun_rapid_recuperation : public AuraScript Unit* target = GetTarget(); CastSpellExtraArgs args(aurEff); args.AddSpellBP0(CalculatePct(target->GetMaxPower(POWER_MANA), aurEff->GetAmount())); - target->CastSpell(target, GetSpellInfo()->Effects[aurEff->GetEffIndex()].TriggerSpell, args); + target->CastSpell(target, aurEff->GetSpellEffectInfo().TriggerSpell, args); } void Register() override @@ -1114,7 +1114,7 @@ class spell_hun_sniper_training : public AuraScript if (Player* playerTarget = GetUnitOwner()->ToPlayer()) { int32 baseAmount = aurEff->GetBaseAmount(); - int32 amount = playerTarget->CalculateSpellDamage(GetSpellInfo(), aurEff->GetEffIndex(), &baseAmount); + int32 amount = playerTarget->CalculateSpellDamage(aurEff->GetSpellEffectInfo(), &baseAmount); GetEffect(EFFECT_0)->SetAmount(amount); } } @@ -1126,7 +1126,7 @@ class spell_hun_sniper_training : public AuraScript { int32 baseAmount = aurEff->GetBaseAmount(); int32 amount = playerTarget->isMoving() ? - playerTarget->CalculateSpellDamage(GetSpellInfo(), aurEff->GetEffIndex(), &baseAmount) : + playerTarget->CalculateSpellDamage(aurEff->GetSpellEffectInfo(), &baseAmount) : aurEff->GetAmount() - 1; aurEff->SetAmount(amount); } diff --git a/src/server/scripts/Spells/spell_warlock.cpp b/src/server/scripts/Spells/spell_warlock.cpp index 290f75546b3..9cd62c00232 100644 --- a/src/server/scripts/Spells/spell_warlock.cpp +++ b/src/server/scripts/Spells/spell_warlock.cpp @@ -398,7 +398,7 @@ class spell_warl_demonic_empowerment : public SpellScript case CREATURE_FAMILY_VOIDWALKER: { SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(SPELL_WARLOCK_DEMONIC_EMPOWERMENT_VOIDWALKER); - int32 hp = targetCreature->CountPctFromMaxHealth(GetCaster()->CalculateSpellDamage(spellInfo, EFFECT_0)); + int32 hp = targetCreature->CountPctFromMaxHealth(GetCaster()->CalculateSpellDamage(spellInfo->GetEffect(EFFECT_0))); CastSpellExtraArgs args(TRIGGERED_FULL_MASK); args.AddSpellBP0(hp); targetCreature->CastSpell(targetCreature, SPELL_WARLOCK_DEMONIC_EMPOWERMENT_VOIDWALKER, args); |