diff options
author | Shauren <shauren.trinity@gmail.com> | 2021-09-04 15:13:15 +0200 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2021-09-04 15:13:15 +0200 |
commit | 8a4e1119ac21e2d1112d1717337597fe073e495f (patch) | |
tree | 34f3215bec2096b59e3d9b2353661e1c137ff8b4 | |
parent | 16ed458eeeebe436f05c43686928252992ae2a20 (diff) |
Core/Spells: Unify spell effect access api in both branches
90 files changed, 1482 insertions, 1672 deletions
diff --git a/src/server/game/AI/CoreAI/UnitAI.cpp b/src/server/game/AI/CoreAI/UnitAI.cpp index f44742419e5..2665379e779 100644 --- a/src/server/game/AI/CoreAI/UnitAI.cpp +++ b/src/server/game/AI/CoreAI/UnitAI.cpp @@ -202,12 +202,9 @@ void UnitAI::FillAISpellInfo() UPDATE_TARGET(AITARGET_SELF) else { - for (SpellEffectInfo const* effect : spellInfo->GetEffects()) + for (SpellEffectInfo const& effect : spellInfo->GetEffects()) { - if (!effect) - continue; - - uint32 targetType = effect->TargetA.GetTarget(); + uint32 targetType = effect.TargetA.GetTarget(); if (targetType == TARGET_UNIT_TARGET_ENEMY || targetType == TARGET_DEST_TARGET_ENEMY) @@ -215,7 +212,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) @@ -230,73 +227,70 @@ void UnitAI::FillAISpellInfo() AIInfo->Effects = 0; AIInfo->Targets = 0; - for (SpellEffectInfo const* effect : spellInfo->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : spellInfo->GetEffects()) { - if (!effect) - continue; - // Spell targets self. - if (effect->TargetA.GetTarget() == TARGET_UNIT_CASTER) + if (spellEffectInfo.TargetA.GetTarget() == TARGET_UNIT_CASTER) AIInfo->Targets |= 1 << (SELECT_TARGET_SELF - 1); // Spell targets a single enemy. - if (effect->TargetA.GetTarget() == TARGET_UNIT_TARGET_ENEMY || - effect->TargetA.GetTarget() == TARGET_DEST_TARGET_ENEMY) + if (spellEffectInfo.TargetA.GetTarget() == TARGET_UNIT_TARGET_ENEMY || + spellEffectInfo.TargetA.GetTarget() == TARGET_DEST_TARGET_ENEMY) AIInfo->Targets |= 1 << (SELECT_TARGET_SINGLE_ENEMY - 1); // Spell targets AoE at enemy. - if (effect->TargetA.GetTarget() == TARGET_UNIT_SRC_AREA_ENEMY || - effect->TargetA.GetTarget() == TARGET_UNIT_DEST_AREA_ENEMY || - effect->TargetA.GetTarget() == TARGET_SRC_CASTER || - effect->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_SRC_CASTER || + spellEffectInfo.TargetA.GetTarget() == TARGET_DEST_DYNOBJ_ENEMY) AIInfo->Targets |= 1 << (SELECT_TARGET_AOE_ENEMY - 1); // Spell targets an enemy. - if (effect->TargetA.GetTarget() == TARGET_UNIT_TARGET_ENEMY || - effect->TargetA.GetTarget() == TARGET_DEST_TARGET_ENEMY || - effect->TargetA.GetTarget() == TARGET_UNIT_SRC_AREA_ENEMY || - effect->TargetA.GetTarget() == TARGET_UNIT_DEST_AREA_ENEMY || - effect->TargetA.GetTarget() == TARGET_SRC_CASTER || - effect->TargetA.GetTarget() == TARGET_DEST_DYNOBJ_ENEMY) + if (spellEffectInfo.TargetA.GetTarget() == TARGET_UNIT_TARGET_ENEMY || + spellEffectInfo.TargetA.GetTarget() == TARGET_DEST_TARGET_ENEMY || + spellEffectInfo.TargetA.GetTarget() == TARGET_UNIT_SRC_AREA_ENEMY || + spellEffectInfo.TargetA.GetTarget() == TARGET_UNIT_DEST_AREA_ENEMY || + spellEffectInfo.TargetA.GetTarget() == TARGET_SRC_CASTER || + spellEffectInfo.TargetA.GetTarget() == TARGET_DEST_DYNOBJ_ENEMY) AIInfo->Targets |= 1 << (SELECT_TARGET_ANY_ENEMY - 1); // Spell targets a single friend (or self). - if (effect->TargetA.GetTarget() == TARGET_UNIT_CASTER || - effect->TargetA.GetTarget() == TARGET_UNIT_TARGET_ALLY || - effect->TargetA.GetTarget() == TARGET_UNIT_TARGET_PARTY) + if (spellEffectInfo.TargetA.GetTarget() == TARGET_UNIT_CASTER || + spellEffectInfo.TargetA.GetTarget() == TARGET_UNIT_TARGET_ALLY || + spellEffectInfo.TargetA.GetTarget() == TARGET_UNIT_TARGET_PARTY) AIInfo->Targets |= 1 << (SELECT_TARGET_SINGLE_FRIEND - 1); // Spell targets AoE friends. - if (effect->TargetA.GetTarget() == TARGET_UNIT_CASTER_AREA_PARTY || - effect->TargetA.GetTarget() == TARGET_UNIT_LASTTARGET_AREA_PARTY || - effect->TargetA.GetTarget() == TARGET_SRC_CASTER) + if (spellEffectInfo.TargetA.GetTarget() == TARGET_UNIT_CASTER_AREA_PARTY || + spellEffectInfo.TargetA.GetTarget() == TARGET_UNIT_LASTTARGET_AREA_PARTY || + spellEffectInfo.TargetA.GetTarget() == TARGET_SRC_CASTER) AIInfo->Targets |= 1 << (SELECT_TARGET_AOE_FRIEND - 1); // Spell targets any friend (or self). - if (effect->TargetA.GetTarget() == TARGET_UNIT_CASTER || - effect->TargetA.GetTarget() == TARGET_UNIT_TARGET_ALLY || - effect->TargetA.GetTarget() == TARGET_UNIT_TARGET_PARTY || - effect->TargetA.GetTarget() == TARGET_UNIT_CASTER_AREA_PARTY || - effect->TargetA.GetTarget() == TARGET_UNIT_LASTTARGET_AREA_PARTY || - effect->TargetA.GetTarget() == TARGET_SRC_CASTER) + if (spellEffectInfo.TargetA.GetTarget() == TARGET_UNIT_CASTER || + spellEffectInfo.TargetA.GetTarget() == TARGET_UNIT_TARGET_ALLY || + spellEffectInfo.TargetA.GetTarget() == TARGET_UNIT_TARGET_PARTY || + spellEffectInfo.TargetA.GetTarget() == TARGET_UNIT_CASTER_AREA_PARTY || + spellEffectInfo.TargetA.GetTarget() == TARGET_UNIT_LASTTARGET_AREA_PARTY || + spellEffectInfo.TargetA.GetTarget() == TARGET_SRC_CASTER) AIInfo->Targets |= 1 << (SELECT_TARGET_ANY_FRIEND - 1); // Make sure that this spell includes a damage effect. - if (effect->Effect == SPELL_EFFECT_SCHOOL_DAMAGE || - effect->Effect == SPELL_EFFECT_INSTAKILL || - effect->Effect == SPELL_EFFECT_ENVIRONMENTAL_DAMAGE || - effect->Effect == SPELL_EFFECT_HEALTH_LEECH) + if (spellEffectInfo.Effect == SPELL_EFFECT_SCHOOL_DAMAGE || + spellEffectInfo.Effect == SPELL_EFFECT_INSTAKILL || + spellEffectInfo.Effect == SPELL_EFFECT_ENVIRONMENTAL_DAMAGE || + spellEffectInfo.Effect == SPELL_EFFECT_HEALTH_LEECH) AIInfo->Effects |= 1 << (SELECT_EFFECT_DAMAGE - 1); // Make sure that this spell includes a healing effect (or an apply aura with a periodic heal). - if (effect->Effect == SPELL_EFFECT_HEAL || - effect->Effect == SPELL_EFFECT_HEAL_MAX_HEALTH || - effect->Effect == SPELL_EFFECT_HEAL_MECHANICAL || - (effect->Effect == SPELL_EFFECT_APPLY_AURA && effect->ApplyAuraName == 8)) + if (spellEffectInfo.Effect == SPELL_EFFECT_HEAL || + spellEffectInfo.Effect == SPELL_EFFECT_HEAL_MAX_HEALTH || + spellEffectInfo.Effect == SPELL_EFFECT_HEAL_MECHANICAL || + (spellEffectInfo.Effect == SPELL_EFFECT_APPLY_AURA && spellEffectInfo.ApplyAuraName == 8)) AIInfo->Effects |= 1 << (SELECT_EFFECT_HEALING - 1); // Make sure that this spell applies an aura. - if (effect->Effect == SPELL_EFFECT_APPLY_AURA) + if (spellEffectInfo.Effect == SPELL_EFFECT_APPLY_AURA) AIInfo->Effects |= 1 << (SELECT_EFFECT_AURA - 1); } }); diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp index f70b00e539b..266cfd08c56 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp @@ -1265,14 +1265,13 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) if (!IsSpellValid(e, e.action.cast.spell)) return false; - SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(e.action.cast.spell, DIFFICULTY_NONE); - for (SpellEffectInfo const* effect : spellInfo->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : sSpellMgr->AssertSpellInfo(e.action.cast.spell, DIFFICULTY_NONE)->GetEffects()) { - if (effect && (effect->IsEffect(SPELL_EFFECT_KILL_CREDIT) || effect->IsEffect(SPELL_EFFECT_KILL_CREDIT2))) + if (spellEffectInfo.IsEffect(SPELL_EFFECT_KILL_CREDIT) || spellEffectInfo.IsEffect(SPELL_EFFECT_KILL_CREDIT2)) { - if (effect->TargetA.GetTarget() == TARGET_UNIT_CASTER) + if (spellEffectInfo.TargetA.GetTarget() == TARGET_UNIT_CASTER) TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u Effect: SPELL_EFFECT_KILL_CREDIT: (SpellId: %u targetA: %u - targetB: %u) has invalid target for this Action", - e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.cast.spell, effect->TargetA.GetTarget(), effect->TargetB.GetTarget()); + e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.cast.spell, spellEffectInfo.TargetA.GetTarget(), spellEffectInfo.TargetB.GetTarget()); } } break; @@ -1821,19 +1820,16 @@ void SmartAIMgr::LoadHelperStores() sSpellMgr->ForEachSpellInfo([this](SpellInfo const* spellInfo) { - for (SpellEffectInfo const* effect : spellInfo->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : spellInfo->GetEffects()) { - if (!effect) - continue; - - if (effect->IsEffect(SPELL_EFFECT_SUMMON)) - SummonCreatureSpellStore.insert(std::make_pair(uint32(effect->MiscValue), std::make_pair(spellInfo->Id, SpellEffIndex(effect->EffectIndex)))); - else if (effect->IsEffect(SPELL_EFFECT_SUMMON_OBJECT_WILD)) - SummonGameObjectSpellStore.insert(std::make_pair(uint32(effect->MiscValue), std::make_pair(spellInfo->Id, SpellEffIndex(effect->EffectIndex)))); - else if (effect->IsEffect(SPELL_EFFECT_KILL_CREDIT) || effect->IsEffect(SPELL_EFFECT_KILL_CREDIT2)) - KillCreditSpellStore.insert(std::make_pair(uint32(effect->MiscValue), std::make_pair(spellInfo->Id, SpellEffIndex(effect->EffectIndex)))); - else if (effect->IsEffect(SPELL_EFFECT_CREATE_ITEM)) - CreateItemSpellStore.insert(std::make_pair(uint32(effect->ItemType), std::make_pair(spellInfo->Id, SpellEffIndex(effect->EffectIndex)))); + if (spellEffectInfo.IsEffect(SPELL_EFFECT_SUMMON)) + SummonCreatureSpellStore.insert(std::make_pair(uint32(spellEffectInfo.MiscValue), std::make_pair(spellInfo->Id, spellEffectInfo.EffectIndex))); + else if (spellEffectInfo.IsEffect(SPELL_EFFECT_SUMMON_OBJECT_WILD)) + SummonGameObjectSpellStore.insert(std::make_pair(uint32(spellEffectInfo.MiscValue), std::make_pair(spellInfo->Id, spellEffectInfo.EffectIndex))); + else if (spellEffectInfo.IsEffect(SPELL_EFFECT_KILL_CREDIT) || spellEffectInfo.IsEffect(SPELL_EFFECT_KILL_CREDIT2)) + KillCreditSpellStore.insert(std::make_pair(uint32(spellEffectInfo.MiscValue), std::make_pair(spellInfo->Id, spellEffectInfo.EffectIndex))); + else if (spellEffectInfo.IsEffect(SPELL_EFFECT_CREATE_ITEM)) + CreateItemSpellStore.insert(std::make_pair(uint32(spellEffectInfo.ItemType), std::make_pair(spellInfo->Id, spellEffectInfo.EffectIndex))); } }); diff --git a/src/server/game/Achievements/CriteriaHandler.cpp b/src/server/game/Achievements/CriteriaHandler.cpp index 6dcbf2a7164..d750d16cea9 100644 --- a/src/server/game/Achievements/CriteriaHandler.cpp +++ b/src/server/game/Achievements/CriteriaHandler.cpp @@ -147,14 +147,13 @@ bool CriteriaData::IsValid(Criteria const* criteria) criteria->ID, criteria->Entry->Type, (DataType == CRITERIA_DATA_TYPE_S_AURA ? "CRITERIA_DATA_TYPE_S_AURA" : "CRITERIA_DATA_TYPE_T_AURA"), DataType, Aura.SpellId); return false; } - SpellEffectInfo const* effect = spellEntry->GetEffect(Aura.EffectIndex); - if (!effect) + if (spellEntry->GetEffects().size() <= Aura.EffectIndex) { TC_LOG_ERROR("sql.sql", "Table `criteria_data` (Entry: %u Type: %u) for data type %s (%u) contains a wrong spell effect index in value2 (%u), ignored.", criteria->ID, criteria->Entry->Type, (DataType == CRITERIA_DATA_TYPE_S_AURA ? "CRITERIA_DATA_TYPE_S_AURA" : "CRITERIA_DATA_TYPE_T_AURA"), DataType, Aura.EffectIndex); return false; } - if (!effect->ApplyAuraName) + if (!spellEntry->GetEffect(SpellEffIndex(Aura.EffectIndex)).ApplyAuraName) { TC_LOG_ERROR("sql.sql", "Table `criteria_data` (Entry: %u Type: %u) for data type %s (%u) contains a non-aura spell effect (ID: %u Effect: %u), ignored.", criteria->ID, criteria->Entry->Type, (DataType == CRITERIA_DATA_TYPE_S_AURA ? "CRITERIA_DATA_TYPE_S_AURA" : "CRITERIA_DATA_TYPE_T_AURA"), DataType, Aura.SpellId, Aura.EffectIndex); diff --git a/src/server/game/Conditions/ConditionMgr.cpp b/src/server/game/Conditions/ConditionMgr.cpp index c516594763e..6a6e936bba4 100644 --- a/src/server/game/Conditions/ConditionMgr.cpp +++ b/src/server/game/Conditions/ConditionMgr.cpp @@ -1372,38 +1372,34 @@ bool ConditionMgr::addToSpellImplicitTargetConditions(Condition* cond) const { uint32 conditionEffMask = cond->SourceGroup; std::list<uint32> sharedMasks; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const& spellEffectInfo : spellInfo->GetEffects()) { - SpellEffectInfo const* effect = spellInfo->GetEffect(i); - if (!effect) - continue; - // 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(effect->TargetA.GetObjectType()) | GetTargetFlagMask(effect->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; } 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; } 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; } break; @@ -1414,22 +1410,16 @@ 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 = effect->ImplicitTargetConditions; - for (uint8 effIndex = i + 1; effIndex < MAX_SPELL_EFFECTS; ++effIndex) - { - SpellEffectInfo const* inner = spellInfo->GetEffect(effIndex); - if (!inner) - continue; - - if (inner->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); } @@ -1439,20 +1429,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; - SpellEffectInfo const* effect = spellInfo->GetEffect(firstEffIndex); - if (!effect) - continue; - // get shared data - ConditionContainer* sharedList = effect->ImplicitTargetConditions; + ConditionContainer* sharedList = spellInfo->GetEffect(SpellEffIndex(firstEffIndex)).ImplicitTargetConditions; // there's already data entry for that sharedMask if (sharedList) @@ -1472,15 +1458,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) { - SpellEffectInfo const* eff = spellInfo->GetEffect(i); - if (!eff) - continue; - if ((1 << i) & commonMask) { - const_cast<SpellEffectInfo*>(eff)->ImplicitTargetConditions = sharedList; + const_cast<SpellEffectInfo&>(spellInfo->GetEffect(SpellEffIndex(i))).ImplicitTargetConditions = sharedList; assigned = true; } } @@ -1767,19 +1749,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)) - continue; - - SpellEffectInfo const* effect = spellInfo->GetEffect(i); - if (!effect) + if (!((1 << spellEffectInfo.EffectIndex) & cond->SourceGroup)) continue; - if (effect->ChainTargets > 0) + if (spellEffectInfo.ChainTargets > 0) continue; - switch (effect->TargetA.GetSelectionCategory()) + switch (spellEffectInfo.TargetA.GetSelectionCategory()) { case TARGET_SELECT_CATEGORY_NEARBY: case TARGET_SELECT_CATEGORY_CONE: @@ -1791,7 +1769,7 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) const break; } - switch (effect->TargetB.GetSelectionCategory()) + switch (spellEffectInfo.TargetB.GetSelectionCategory()) { case TARGET_SELECT_CATEGORY_NEARBY: case TARGET_SELECT_CATEGORY_CONE: @@ -1803,8 +1781,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 f59f4e48b6a..b7d72e49c10 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -2361,12 +2361,9 @@ bool Creature::IsImmunedToSpell(SpellInfo const* spellInfo, WorldObject const* c return false; bool immunedToAllEffects = true; - for (SpellEffectInfo const* effect : spellInfo->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : spellInfo->GetEffects()) { - if (!effect || !effect->IsEffect()) - continue; - - if (!IsImmunedToSpellEffect(spellInfo, effect->EffectIndex, caster)) + if (spellEffectInfo.IsEffect() && !IsImmunedToSpellEffect(spellInfo, spellEffectInfo, caster)) { immunedToAllEffects = false; break; @@ -2379,16 +2376,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 { - SpellEffectInfo const* effect = spellInfo->GetEffect(index); - if (!effect) - return true; - - if (GetCreatureTemplate()->type == CREATURE_TYPE_MECHANICAL && effect->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 1463e1b6975..1add6c4d146 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -128,7 +128,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/Creature/GossipDef.cpp b/src/server/game/Entities/Creature/GossipDef.cpp index 9df67435686..3c67229aab4 100644 --- a/src/server/game/Entities/Creature/GossipDef.cpp +++ b/src/server/game/Entities/Creature/GossipDef.cpp @@ -442,9 +442,9 @@ void PlayerMenu::SendQuestGiverQuestDetails(Quest const* quest, ObjectGuid npcGU // RewardSpell can teach multiple spells in trigger spell effects. But not all effects must be SPELL_EFFECT_LEARN_SPELL. See example spell 33950 if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(quest->GetRewSpell(), DIFFICULTY_NONE)) - for (SpellEffectInfo const* effect : spellInfo->GetEffects()) - if (effect->IsEffect(SPELL_EFFECT_LEARN_SPELL)) - packet.LearnSpells.push_back(effect->TriggerSpell); + for (SpellEffectInfo const& spellEffectInfo : spellInfo->GetEffects()) + if (spellEffectInfo.IsEffect(SPELL_EFFECT_LEARN_SPELL)) + packet.LearnSpells.push_back(spellEffectInfo.TriggerSpell); quest->BuildQuestRewards(packet.Rewards, _session->GetPlayer()); diff --git a/src/server/game/Entities/Creature/Trainer.cpp b/src/server/game/Entities/Creature/Trainer.cpp index ed2d2a9cf3e..3f5294b069d 100644 --- a/src/server/game/Entities/Creature/Trainer.cpp +++ b/src/server/game/Entities/Creature/Trainer.cpp @@ -142,13 +142,13 @@ namespace Trainer // check ranks bool hasLearnSpellEffect = false; bool knowsAllLearnedSpells = true; - for (SpellEffectInfo const* spellEffect : sSpellMgr->AssertSpellInfo(trainerSpell->SpellId, DIFFICULTY_NONE)->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : sSpellMgr->AssertSpellInfo(trainerSpell->SpellId, DIFFICULTY_NONE)->GetEffects()) { - if (!spellEffect || !spellEffect->IsEffect(SPELL_EFFECT_LEARN_SPELL)) + if (!spellEffectInfo.IsEffect(SPELL_EFFECT_LEARN_SPELL)) continue; hasLearnSpellEffect = true; - if (!player->HasSpell(spellEffect->TriggerSpell)) + if (!player->HasSpell(spellEffectInfo.TriggerSpell)) knowsAllLearnedSpells = false; } diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index a2b4067291d..bb2fddd6ad0 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -2094,13 +2094,12 @@ Player* WorldObject::GetSpellModOwner() const } // function uses real base points (typically value - 1) -int32 WorldObject::CalculateSpellDamage(Unit const* target, SpellInfo const* spellProto, uint8 effIndex, int32 const* basePoints /*= nullptr*/, float* variance /*= nullptr*/, uint32 castItemId /*= 0*/, int32 itemLevel /*= -1*/) const +int32 WorldObject::CalculateSpellDamage(Unit const* target, SpellEffectInfo const& spellEffectInfo, int32 const* basePoints /*= nullptr*/, float* variance /*= nullptr*/, uint32 castItemId /*= 0*/, int32 itemLevel /*= -1*/) const { - SpellEffectInfo const* effect = spellProto->GetEffect(effIndex); if (variance) *variance = 0.0f; - return effect ? effect->CalcValue(this, basePoints, target, variance, castItemId, itemLevel) : 0; + return spellEffectInfo.CalcValue(this, basePoints, target, variance, castItemId, itemLevel); } float WorldObject::GetSpellMaxRangeForTarget(Unit const* target, SpellInfo const* spellInfo) const @@ -2231,8 +2230,8 @@ int32 WorldObject::ModSpellDuration(SpellInfo const* spellInfo, WorldObject cons sSpellMgr->IsSpellMemberOfSpellGroup(spellInfo->Id, SPELL_GROUP_ELIXIR_BATTLE) || sSpellMgr->IsSpellMemberOfSpellGroup(spellInfo->Id, SPELL_GROUP_ELIXIR_GUARDIAN))) { - SpellEffectInfo const* effect = spellInfo->GetEffect(EFFECT_0); - if (unitTarget->HasAura(53042) && effect && unitTarget->HasSpell(effect->TriggerSpell)) + SpellEffectInfo const& effect = spellInfo->GetEffect(EFFECT_0); + if (unitTarget->HasAura(53042) && unitTarget->HasSpell(effect.TriggerSpell)) duration *= 2; } } diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h index 4e0d9005b07..974c74a02bd 100644 --- a/src/server/game/Entities/Object/Object.h +++ b/src/server/game/Entities/Object/Object.h @@ -50,6 +50,7 @@ class Player; class Scenario; class Spell; class SpellCastTargets; +class SpellEffectInfo; class SpellInfo; class TempSummon; class Transport; @@ -564,7 +565,7 @@ class TC_GAME_API WorldObject : public Object, public WorldLocation Player* GetAffectingPlayer() const; Player* GetSpellModOwner() const; - int32 CalculateSpellDamage(Unit const* target, SpellInfo const* spellInfo, uint8 effIndex, int32 const* basePoints = nullptr, float* variance = nullptr, uint32 castItemId = 0, int32 itemLevel = -1) const; + int32 CalculateSpellDamage(Unit const* target, SpellEffectInfo const& spellEffectInfo, int32 const* basePoints = nullptr, float* variance = nullptr, uint32 castItemId = 0, int32 itemLevel = -1) const; // target dependent range checks float GetSpellMaxRangeForTarget(Unit const* target, SpellInfo const* spellInfo) const; diff --git a/src/server/game/Entities/Object/Updates/ViewerDependentValues.h b/src/server/game/Entities/Object/Updates/ViewerDependentValues.h index db15672ce97..e5cd00485da 100644 --- a/src/server/game/Entities/Object/Updates/ViewerDependentValues.h +++ b/src/server/game/Entities/Object/Updates/ViewerDependentValues.h @@ -116,13 +116,19 @@ public: // this also applies for transform auras if (SpellInfo const* transform = sSpellMgr->GetSpellInfo(unit->getTransForm(), unit->GetMap()->GetDifficultyID())) - for (SpellEffectInfo const* effect : transform->GetEffects()) - if (effect && effect->IsAura(SPELL_AURA_TRANSFORM)) - if (CreatureTemplate const* transformInfo = sObjectMgr->GetCreatureTemplate(effect->MiscValue)) + { + for (SpellEffectInfo const& spellEffectInfo : transform->GetEffects()) + { + if (spellEffectInfo.IsAura(SPELL_AURA_TRANSFORM)) + { + if (CreatureTemplate const* transformInfo = sObjectMgr->GetCreatureTemplate(spellEffectInfo.MiscValue)) { cinfo = transformInfo; break; } + } + } + } if (cinfo->flags_extra & CREATURE_FLAG_EXTRA_TRIGGER) if (receiver->IsGameMaster()) diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 57a1d0b2b5c..bd783df2295 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -1663,19 +1663,15 @@ void Player::SetObjectScale(float scale) SendMovementSetCollisionHeight(scale * GetCollisionHeight(), WorldPackets::Movement::UpdateCollisionHeightReason::Scale); } -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 { - SpellEffectInfo const* effect = spellInfo->GetEffect(index); - if (!effect || !effect->IsEffect()) - return false; - // players are immune to taunt (the aura and the spell effect). - if (effect->IsAura(SPELL_AURA_MOD_TAUNT)) + if (spellEffectInfo.IsAura(SPELL_AURA_MOD_TAUNT)) return true; - if (effect->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() @@ -2724,9 +2720,9 @@ void Player::RemoveTalent(TalentEntry const* talent) RemoveSpell(talent->SpellID, true); // search for spells that the talent teaches and unlearn them - for (SpellEffectInfo const* effect : spellInfo->GetEffects()) - if (effect && effect->TriggerSpell > 0 && effect->Effect == SPELL_EFFECT_LEARN_SPELL) - RemoveSpell(effect->TriggerSpell, true); + for (SpellEffectInfo const& spellEffectInfo : spellInfo->GetEffects()) + if (spellEffectInfo.IsEffect(SPELL_EFFECT_LEARN_SPELL) && spellEffectInfo.TriggerSpell > 0) + RemoveSpell(spellEffectInfo.TriggerSpell, true); if (talent->OverridesSpellID) RemoveOverrideSpell(talent->OverridesSpellID, talent->SpellID); @@ -3123,13 +3119,15 @@ bool Player::HandlePassiveSpellLearn(SpellInfo const* spellInfo) // passive spells which apply aura and have an item requirement are to be added manually, instead of casted if (spellInfo->EquippedItemClass >= 0) { - for (SpellEffectInfo const* effectInfo : spellInfo->GetEffects()) - if (effectInfo && effectInfo->IsAura()) + for (SpellEffectInfo const& spellEffectInfo : spellInfo->GetEffects()) + { + if (spellEffectInfo.IsAura()) { if (!HasAura(spellInfo->Id) && HasItemFitToSpellRequirements(spellInfo)) AddAura(spellInfo->Id, this); return false; } + } } //Check CasterAuraStates @@ -8096,7 +8094,7 @@ void Player::ApplyArtifactPowerRank(Item* artifact, ArtifactPowerRankEntry const continue; if (powerAura->HasEffect(auraEffect->GetEffIndex())) - auraEffect->ChangeAmount(artifactPowerRank->AuraPointsOverride ? artifactPowerRank->AuraPointsOverride : auraEffect->GetSpellEffectInfo()->CalcValue()); + auraEffect->ChangeAmount(artifactPowerRank->AuraPointsOverride ? artifactPowerRank->AuraPointsOverride : auraEffect->GetSpellEffectInfo().CalcValue()); } } else @@ -8108,9 +8106,8 @@ void Player::ApplyArtifactPowerRank(Item* artifact, ArtifactPowerRankEntry const args.TriggerFlags = TRIGGERED_FULL_MASK; args.CastItem = artifact; if (artifactPowerRank->AuraPointsOverride) - for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i) - if (spellInfo->GetEffect(i)) - args.AddSpellMod(SpellValueMod(SPELLVALUE_BASE_POINT0 + i), artifactPowerRank->AuraPointsOverride); + for (SpellEffectInfo const& spellEffectInfo : spellInfo->GetEffects()) + args.AddSpellMod(SpellValueMod(SPELLVALUE_BASE_POINT0 + spellEffectInfo.EffectIndex), artifactPowerRank->AuraPointsOverride); CastSpell(this, artifactPowerRank->SpellID, args); } @@ -8409,11 +8406,9 @@ void Player::CastItemCombatSpell(DamageInfo const& damageInfo, Item* item, ItemT int32 const effectPct = std::max(0, 100 - (lvlDifference * lvlPenaltyFactor)); - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - { - if (spellInfo->GetEffect(i)->IsEffect()) - args.AddSpellMod(static_cast<SpellValueMod>(SPELLVALUE_BASE_POINT0 + i), CalculatePct(spellInfo->GetEffect(i)->CalcValue(this), effectPct)); - } + for (SpellEffectInfo const& spellEffectInfo : spellInfo->GetEffects()) + if (spellEffectInfo.IsEffect()) + args.AddSpellMod(static_cast<SpellValueMod>(SPELLVALUE_BASE_POINT0 + spellEffectInfo.EffectIndex), CalculatePct(spellEffectInfo.CalcValue(this), effectPct)); } CastSpell(target, spellInfo->Id, args); } @@ -24560,9 +24555,9 @@ void Player::LearnQuestRewardedSpells(Quest const* quest) // check learned spells state bool found = false; - for (SpellEffectInfo const* effect : spellInfo->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : spellInfo->GetEffects()) { - if (effect && effect->Effect == SPELL_EFFECT_LEARN_SPELL && !HasSpell(effect->TriggerSpell)) + if (spellEffectInfo.IsEffect(SPELL_EFFECT_LEARN_SPELL) && !HasSpell(spellEffectInfo.TriggerSpell)) { found = true; break; @@ -24573,11 +24568,11 @@ void Player::LearnQuestRewardedSpells(Quest const* quest) if (!found) return; - SpellEffectInfo const* effect = spellInfo->GetEffect(EFFECT_0); - if (!effect) + if (spellInfo->GetEffects().empty()) return; - uint32 learned_0 = effect->TriggerSpell; + SpellEffectInfo const& effect = spellInfo->GetEffect(EFFECT_0); + uint32 learned_0 = effect.TriggerSpell; if (!HasSpell(learned_0)) { found = false; @@ -25264,11 +25259,9 @@ bool Player::HasItemFitToSpellRequirements(SpellInfo const* spellInfo, Item cons // special check to filter things like Shield Wall, the aura is not permanent and must stay even without required item if (!spellInfo->IsPassive()) - { - for (SpellEffectInfo const* effect : spellInfo->GetEffects()) - if (effect && effect->IsAura()) + for (SpellEffectInfo const& spellEffectInfo : spellInfo->GetEffects()) + if (spellEffectInfo.IsAura()) return true; - } } // tabard not have dependent spells @@ -27461,9 +27454,9 @@ void Player::ActivateTalentGroup(ChrSpecializationEntry const* spec) RemoveSpell(talentInfo->SpellID, true); // search for spells that the talent teaches and unlearn them - for (SpellEffectInfo const* effect : spellInfo->GetEffects()) - if (effect && effect->TriggerSpell > 0 && effect->Effect == SPELL_EFFECT_LEARN_SPELL) - RemoveSpell(effect->TriggerSpell, true); + for (SpellEffectInfo const& spellEffectInfo : spellInfo->GetEffects()) + if (spellEffectInfo.IsEffect(SPELL_EFFECT_LEARN_SPELL) && spellEffectInfo.TriggerSpell > 0) + RemoveSpell(spellEffectInfo.TriggerSpell, true); if (talentInfo->OverridesSpellID) RemoveOverrideSpell(talentInfo->OverridesSpellID, talentInfo->SpellID); @@ -27482,9 +27475,9 @@ void Player::ActivateTalentGroup(ChrSpecializationEntry const* spec) RemoveSpell(talentInfo->SpellID, true); // search for spells that the talent teaches and unlearn them - for (SpellEffectInfo const* effect : spellInfo->GetEffects()) - if (effect && effect->TriggerSpell > 0 && effect->Effect == SPELL_EFFECT_LEARN_SPELL) - RemoveSpell(effect->TriggerSpell, true); + for (SpellEffectInfo const& spellEffectInfo : spellInfo->GetEffects()) + if (spellEffectInfo.IsEffect(SPELL_EFFECT_LEARN_SPELL) && spellEffectInfo.TriggerSpell > 0) + RemoveSpell(spellEffectInfo.TriggerSpell, true); if (talentInfo->OverridesSpellID) RemoveOverrideSpell(talentInfo->OverridesSpellID, talentInfo->SpellID); diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 0fd50b7b5f9..35cd545fe26 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -1085,7 +1085,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player> void Update(uint32 time) 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; void SetInWater(bool inWater) override; diff --git a/src/server/game/Entities/Totem/Totem.cpp b/src/server/game/Entities/Totem/Totem.cpp index 38f30551a63..a5271ed9378 100644 --- a/src/server/game/Entities/Totem/Totem.cpp +++ b/src/server/game/Entities/Totem/Totem.cpp @@ -137,26 +137,22 @@ 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 { /// @todo possibly all negative auras immune? if (GetEntry() == 5925) return false; - if (SpellEffectInfo const* effect = spellInfo->GetEffect(index)) + + switch (spellEffectInfo.ApplyAuraName) { - switch (effect->ApplyAuraName) - { - case SPELL_AURA_PERIODIC_DAMAGE: - case SPELL_AURA_PERIODIC_LEECH: - case SPELL_AURA_MOD_FEAR: - case SPELL_AURA_TRANSFORM: - return true; - default: - break; - } + case SPELL_AURA_PERIODIC_DAMAGE: + case SPELL_AURA_PERIODIC_LEECH: + case SPELL_AURA_MOD_FEAR: + case SPELL_AURA_TRANSFORM: + return true; + default: + break; } - else - return true; - 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 54fc53a09d0..36919f20eb8 100644 --- a/src/server/game/Entities/Totem/Totem.h +++ b/src/server/game/Entities/Totem/Totem.h @@ -50,7 +50,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 05b85293d0d..501060b954b 100644 --- a/src/server/game/Entities/Unit/StatSystem.cpp +++ b/src/server/game/Entities/Unit/StatSystem.cpp @@ -538,20 +538,20 @@ void Player::UpdateMastery() if (!chrSpec) return; - for (uint32 i = 0; i < MAX_MASTERY_SPELLS; ++i) + for (int32 masterySpellId : chrSpec->MasterySpellID) { - if (Aura* aura = GetAura(chrSpec->MasterySpellID[i])) + if (Aura* aura = GetAura(masterySpellId)) { - for (SpellEffectInfo const* effect : aura->GetSpellInfo()->GetEffects()) + for (AuraEffect* auraEff : aura->GetAuraEffects()) { - if (!effect) + if (!auraEff) continue; - float mult = effect->BonusCoefficient; + float mult = auraEff->GetSpellEffectInfo().BonusCoefficient; if (G3D::fuzzyEq(mult, 0.0f)) continue; - aura->GetEffect(effect->EffectIndex)->ChangeAmount(int32(value * mult)); + auraEff->ChangeAmount(int32(value * mult)); } } } diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index e7b9366722c..e03a84cc057 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -1507,7 +1507,7 @@ void Unit::HandleEmoteCommand(uint32 anim_id, Trinity::IteratorPair<int32 const* SendMessageToSet(packet.Write(), true); } -/*static*/ bool Unit::IsDamageReducedByArmor(SpellSchoolMask schoolMask, SpellInfo const* spellInfo /*= nullptr*/, int8 effIndex /*= -1*/) +/*static*/ bool Unit::IsDamageReducedByArmor(SpellSchoolMask schoolMask, SpellInfo const* spellInfo /*= nullptr*/, SpellEffectInfo const* spellEffectInfo /*= nullptr*/) { // only physical spells damage gets reduced by armor if ((schoolMask & SPELL_SCHOOL_MASK_NORMAL) == 0) @@ -1519,16 +1519,12 @@ void Unit::HandleEmoteCommand(uint32 anim_id, Trinity::IteratorPair<int32 const* return false; // bleeding effects are not reduced by armor - if (effIndex != -1) + if (spellEffectInfo) { - // bleeding effects are not reduced by armor - if (SpellEffectInfo const* effect = spellInfo->GetEffect(effIndex)) - { - if (effect->ApplyAuraName == SPELL_AURA_PERIODIC_DAMAGE || - effect->Effect == SPELL_EFFECT_SCHOOL_DAMAGE) - if (spellInfo->GetEffectMechanicMask(effIndex) & (1 << MECHANIC_BLEED)) - return false; - } + if (spellEffectInfo->ApplyAuraName == SPELL_AURA_PERIODIC_DAMAGE || + spellEffectInfo->Effect == SPELL_EFFECT_SCHOOL_DAMAGE) + if (spellInfo->GetEffectMechanicMask(spellEffectInfo->EffectIndex) & (1 << MECHANIC_BLEED)) + return false; } } return true; @@ -1834,7 +1830,7 @@ void Unit::HandleEmoteCommand(uint32 anim_id, Trinity::IteratorPair<int32 const* int32 manaReduction = currentAbsorb; // lower absorb amount by talents - if (float manaMultiplier = absorbAurEff->GetSpellEffectInfo()->CalcValueMultiplier(absorbAurEff->GetCaster())) + if (float manaMultiplier = absorbAurEff->GetSpellEffectInfo().CalcValueMultiplier(absorbAurEff->GetCaster())) manaReduction = int32(float(manaReduction) * manaMultiplier); int32 manaTaken = -damageInfo.GetVictim()->ModifyPower(POWER_MANA, -manaReduction); @@ -2020,19 +2016,19 @@ void Unit::AttackerStateUpdate(Unit* victim, WeaponAttackType attType, bool extr if (!meleeAttackOverrides.empty()) { meleeAttackAuraEffect = meleeAttackOverrides.front(); - meleeAttackSpellId = meleeAttackAuraEffect->GetSpellEffectInfo()->TriggerSpell; + meleeAttackSpellId = meleeAttackAuraEffect->GetSpellEffectInfo().TriggerSpell; } } else { auto itr = std::find_if(meleeAttackOverrides.begin(), meleeAttackOverrides.end(), [&](AuraEffect const* aurEff) { - return aurEff->GetSpellEffectInfo()->MiscValue != 0; + return aurEff->GetSpellEffectInfo().MiscValue != 0; }); if (itr != meleeAttackOverrides.end()) { meleeAttackAuraEffect = *itr; - meleeAttackSpellId = meleeAttackAuraEffect->GetSpellEffectInfo()->MiscValue; + meleeAttackSpellId = meleeAttackAuraEffect->GetSpellEffectInfo().MiscValue; } } @@ -2338,12 +2334,12 @@ int32 Unit::GetMechanicResistChance(SpellInfo const* spellInfo) const return 0; int32 resistMech = 0; - for (SpellEffectInfo const* effect : spellInfo->GetEffects()) + for (SpellEffectInfo const& effect : spellInfo->GetEffects()) { - if (!effect || !effect->IsEffect()) + if (!effect.IsEffect()) break; - int32 effectMech = spellInfo->GetEffectMechanic(effect->EffectIndex); + int32 effectMech = spellInfo->GetEffectMechanic(effect.EffectIndex); if (effectMech) { int32 temp = GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_MECHANIC_RESISTANCE, effectMech); @@ -3107,22 +3103,19 @@ Aura* Unit::_TryStackingOrRefreshingExistingAura(AuraCreateInfo& createInfo) return nullptr; // update basepoints with new values - effect amount will be recalculated in ModStackAmount - for (SpellEffectInfo const* effect : createInfo.GetSpellInfo()->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : createInfo.GetSpellInfo()->GetEffects()) { - if (!effect) - continue; - - AuraEffect const* eff = foundAura->GetEffect(effect->EffectIndex); - if (!eff) + AuraEffect const* auraEff = foundAura->GetEffect(spellEffectInfo.EffectIndex); + if (!auraEff) continue; int32 bp; if (createInfo.BaseAmount) - bp = *(createInfo.BaseAmount + effect->EffectIndex); + bp = *(createInfo.BaseAmount + spellEffectInfo.EffectIndex); else - bp = effect->BasePoints; + bp = spellEffectInfo.BasePoints; - int32* oldBP = const_cast<int32*>(&(foundAura->GetEffect(effect->EffectIndex)->m_baseAmount)); // todo 6.x review GetBaseAmount and GetCastItemGUID in this case + int32* oldBP = const_cast<int32*>(&(auraEff->m_baseAmount)); // todo 6.x review GetBaseAmount and GetCastItemGUID in this case *oldBP = bp; } @@ -3978,9 +3971,9 @@ void Unit::RemoveMovementImpairingAuras(bool withRoot) } // turn off snare auras by setting amount to 0 - for (SpellEffectInfo const* spellEffectInfo : aura->GetSpellInfo()->GetEffects()) - if (spellEffectInfo && iter->second->HasEffect(spellEffectInfo->EffectIndex) && spellEffectInfo->Mechanic == MECHANIC_SNARE) - aura->GetEffect(spellEffectInfo->EffectIndex)->ChangeAmount(0); + for (SpellEffectInfo const& spellEffectInfo : aura->GetSpellInfo()->GetEffects()) + if (iter->second->HasEffect(spellEffectInfo.EffectIndex) && spellEffectInfo.Mechanic == MECHANIC_SNARE) + aura->GetEffect(spellEffectInfo.EffectIndex)->ChangeAmount(0); ++iter; } @@ -4498,9 +4491,9 @@ bool Unit::HasAuraWithMechanic(uint32 mechanicMask) const if (spellInfo->Mechanic && (mechanicMask & (1 << spellInfo->Mechanic))) return true; - for (SpellEffectInfo const* spellEffectInfo : spellInfo->GetEffects()) - if (spellEffectInfo && iter->second->HasEffect(spellEffectInfo->EffectIndex) && spellEffectInfo->IsEffect() && spellEffectInfo->Mechanic) - if (mechanicMask & (1 << spellEffectInfo->Mechanic)) + for (SpellEffectInfo const& spellEffectInfo : spellInfo->GetEffects()) + if (iter->second->HasEffect(spellEffectInfo.EffectIndex) && spellEffectInfo.IsEffect() && spellEffectInfo.Mechanic) + if (mechanicMask & (1 << spellEffectInfo.Mechanic)) return true; } @@ -5908,13 +5901,15 @@ void Unit::SetMinion(Minion *minion, bool apply) { // All summoned by totem minions must disappear when it is removed. if (SpellInfo const* spInfo = sSpellMgr->GetSpellInfo(minion->ToTotem()->GetSpell(), GetMap()->GetDifficultyID())) - for (SpellEffectInfo const* effect : spInfo->GetEffects()) - { - if (!effect || effect->Effect != SPELL_EFFECT_SUMMON) - continue; + { + for (SpellEffectInfo const& spellEffectInfo : spInfo->GetEffects()) + { + if (!spellEffectInfo.IsEffect(SPELL_EFFECT_SUMMON)) + continue; - RemoveAllMinionsByEntry(effect->MiscValue); - } + RemoveAllMinionsByEntry(spellEffectInfo.MiscValue); + } + } } SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(minion->m_unitData->CreatedBySpell, GetMap()->GetDifficultyID()); @@ -6352,7 +6347,7 @@ void Unit::EnergizeBySpell(Unit* victim, SpellInfo const* spellInfo, int32 damag SendEnergizeSpellLog(victim, spellInfo->Id, gain, overEnergize, powerType); } -uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uint32 pdamage, DamageEffectType damagetype, SpellEffectInfo const* effect, uint32 stack /*= 1*/) const +uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uint32 pdamage, DamageEffectType damagetype, SpellEffectInfo const& spellEffectInfo, uint32 stack /*= 1*/) const { if (!spellProto || !victim || damagetype == DIRECT_DAMAGE) return pdamage; @@ -6364,7 +6359,7 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin // For totems get damage bonus from owner if (GetTypeId() == TYPEID_UNIT && IsTotem()) if (Unit* owner = GetOwner()) - return owner->SpellDamageBonusDone(victim, spellProto, pdamage, damagetype, effect, stack); + return owner->SpellDamageBonusDone(victim, spellProto, pdamage, damagetype, spellEffectInfo, stack); int32 DoneTotal = 0; float DoneTotalMod = SpellDamagePctDone(victim, spellProto, damagetype); @@ -6380,9 +6375,9 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin DoneAdvertisedBenefit += static_cast<Guardian const*>(this)->GetBonusDamage(); // Check for table values - if (effect->BonusCoefficientFromAP > 0.0f) + if (spellEffectInfo.BonusCoefficientFromAP > 0.0f) { - float ApCoeffMod = effect->BonusCoefficientFromAP; + float ApCoeffMod = spellEffectInfo.BonusCoefficientFromAP; if (Player* modOwner = GetSpellModOwner()) { ApCoeffMod *= 100.0f; @@ -6412,7 +6407,7 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin } // Default calculation - float coeff = effect->BonusCoefficient; + float coeff = spellEffectInfo.BonusCoefficient; if (DoneAdvertisedBenefit) { if (Player* modOwner = GetSpellModOwner()) @@ -6839,12 +6834,12 @@ float Unit::SpellCritChanceTaken(Unit const* caster, Spell* spell, AuraEffect co return damage; } -uint32 Unit::SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, uint32 healamount, DamageEffectType damagetype, SpellEffectInfo const* spellEffect, uint32 stack /*= 1*/) const +uint32 Unit::SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, uint32 healamount, DamageEffectType damagetype, SpellEffectInfo const& spellEffectInfo, uint32 stack /*= 1*/) const { // For totems get healing bonus from owner (statue isn't totem in fact) if (GetTypeId() == TYPEID_UNIT && IsTotem()) if (Unit* owner = GetOwner()) - return owner->SpellHealingBonusDone(victim, spellProto, healamount, damagetype, spellEffect, stack); + return owner->SpellHealingBonusDone(victim, spellProto, healamount, damagetype, spellEffectInfo, stack); // No bonus healing for potion spells if (spellProto->SpellFamilyName == SPELLFAMILY_POTION) @@ -6882,14 +6877,14 @@ uint32 Unit::SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, ui DoneAdvertisedBenefit += static_cast<Guardian const*>(this)->GetBonusDamage(); // Check for table values - float coeff = spellEffect->BonusCoefficient; - if (spellEffect->BonusCoefficientFromAP > 0.0f) + float coeff = spellEffectInfo.BonusCoefficient; + if (spellEffectInfo.BonusCoefficientFromAP > 0.0f) { WeaponAttackType const attType = (spellProto->IsRangedWeaponSpell() && spellProto->DmgClass != SPELL_DAMAGE_CLASS_MELEE) ? RANGED_ATTACK : BASE_ATTACK; float APbonus = float(victim->GetTotalAuraModifier(attType == BASE_ATTACK ? SPELL_AURA_MELEE_ATTACK_POWER_ATTACKER_BONUS : SPELL_AURA_RANGED_ATTACK_POWER_ATTACKER_BONUS)); APbonus += GetTotalAttackPowerValue(attType); - DoneTotal += int32(spellEffect->BonusCoefficientFromAP * stack * APbonus); + DoneTotal += int32(spellEffectInfo.BonusCoefficientFromAP * stack * APbonus); } else if (coeff <= 0.0f) // no AP and no SP coefs, skip { @@ -6911,19 +6906,19 @@ uint32 Unit::SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, ui DoneTotal += int32(DoneAdvertisedBenefit * coeff * stack); } - for (SpellEffectInfo const* effect : spellProto->GetEffects()) + for (SpellEffectInfo const& otherSpellEffect : spellProto->GetEffects()) { - if (!effect) - continue; - switch (effect->ApplyAuraName) + switch (otherSpellEffect.ApplyAuraName) { // Bonus healing does not apply to these spells case SPELL_AURA_PERIODIC_LEECH: case SPELL_AURA_PERIODIC_HEALTH_FUNNEL: DoneTotal = 0; break; + default: + break; } - if (effect->Effect == SPELL_EFFECT_HEALTH_LEECH) + if (otherSpellEffect.IsEffect(SPELL_EFFECT_HEALTH_LEECH)) DoneTotal = 0; } @@ -7071,7 +7066,7 @@ int32 Unit::SpellBaseHealingBonusDone(SpellSchoolMask schoolMask) const for (AuraEffectList::const_iterator i = mHealingDoneOfStatPercent.begin(); i != mHealingDoneOfStatPercent.end(); ++i) { // stat used dependent from misc value (stat index) - Stats usedStat = Stats((*i)->GetSpellEffectInfo()->MiscValue); + Stats usedStat = Stats((*i)->GetSpellEffectInfo().MiscValue); advertisedBenefit += int32(CalculatePct(GetStat(usedStat), (*i)->GetAmount())); } } @@ -7159,13 +7154,13 @@ bool Unit::IsImmunedToSpell(SpellInfo const* spellInfo, WorldObject const* caste } bool immuneToAllEffects = true; - for (SpellEffectInfo const* effect : spellInfo->GetEffects()) + 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 (!effect || !effect->IsEffect()) + if (!spellEffectInfo.IsEffect()) continue; - if (!IsImmunedToSpellEffect(spellInfo, effect->EffectIndex, caster)) + if (!IsImmunedToSpellEffect(spellInfo, spellEffectInfo, caster)) { immuneToAllEffects = false; break; @@ -7226,25 +7221,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) return false; - SpellEffectInfo const* effect = spellInfo->GetEffect(index); - if (!effect) - return false; - if (spellInfo->HasAttribute(SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY)) return false; // If m_immuneToEffect type contain this effect type, IMMUNE effect. - uint32 eff = effect->Effect; auto const& effectList = m_spellImmune[IMMUNITY_EFFECT]; - if (effectList.count(eff) > 0) + if (effectList.count(spellEffectInfo.Effect) > 0) return true; - if (uint32 mechanic = effect->Mechanic) + if (uint32 mechanic = spellEffectInfo.Mechanic) { SpellImmuneContainer const& mechanicList = m_spellImmune[IMMUNITY_MECHANIC]; if (mechanicList.count(mechanic) > 0) @@ -7253,7 +7243,7 @@ bool Unit::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index, Worl if (!spellInfo->HasAttribute(SPELL_ATTR3_IGNORE_HIT_RESULT)) { - if (uint32 aura = effect->ApplyAuraName) + if (AuraType aura = spellEffectInfo.ApplyAuraName) { SpellImmuneContainer const& list = m_spellImmune[IMMUNITY_STATE]; if (list.count(aura) > 0) @@ -7265,7 +7255,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; } } @@ -9044,7 +9034,7 @@ void Unit::TriggerOnPowerChangeAuras(Powers power, int32 oldVal, int32 newVal) if (effect->GetMiscValue() == power) { uint32 effectAmount = effect->GetAmount(); - uint32 triggerSpell = effect->GetSpellEffectInfo()->TriggerSpell; + uint32 triggerSpell = effect->GetSpellEffectInfo().TriggerSpell; float oldValueCheck = oldVal; float newValueCheck = newVal; @@ -11337,13 +11327,13 @@ Aura* Unit::AddAura(SpellInfo const* spellInfo, uint32 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) @@ -11779,12 +11769,9 @@ void Unit::HandleSpellClick(Unit* clicker, int8 seatId /*= -1*/) { uint8 i = 0; bool valid = false; - for (SpellEffectInfo const* effect : spellEntry->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : spellEntry->GetEffects()) { - if (!effect) - continue; - - if (effect->ApplyAuraName == SPELL_AURA_CONTROL_VEHICLE) + if (spellEffectInfo.ApplyAuraName == SPELL_AURA_CONTROL_VEHICLE) { valid = true; break; @@ -11808,9 +11795,8 @@ void Unit::HandleSpellClick(Unit* clicker, int8 seatId /*= -1*/) else // This can happen during Player::_LoadAuras { int32 bp[MAX_SPELL_EFFECTS] = { }; - for (SpellEffectInfo const* effect : spellEntry->GetEffects()) - if (effect) - bp[effect->EffectIndex] = effect->BasePoints; + for (SpellEffectInfo const& spellEffectInfo : spellEntry->GetEffects()) + bp[spellEffectInfo.EffectIndex] = spellEffectInfo.BasePoints; bp[i] = seatId; @@ -13057,11 +13043,11 @@ int32 Unit::GetHighestExclusiveSameEffectSpellGroupValue(AuraEffect const* aurEf bool Unit::IsHighestExclusiveAura(Aura const* aura, bool removeOtherAuraApplications /*= false*/) { - for (AuraEffect* aurEff : aura->GetAuraEffects()) + for (AuraEffect const* aurEff : aura->GetAuraEffects()) { if (!aurEff) continue; - AuraType const auraType = AuraType(aurEff->GetSpellEffectInfo()->ApplyAuraName); + AuraType const auraType = aurEff->GetSpellEffectInfo().ApplyAuraName; AuraEffectList const& auras = GetAuraEffectsByType(auraType); for (Unit::AuraEffectList::const_iterator itr = auras.begin(); itr != auras.end();) { diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 063e22ab1d3..a11aa499f41 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1646,11 +1646,11 @@ class TC_GAME_API Unit : public WorldObject Unit* GetMeleeHitRedirectTarget(Unit* victim, SpellInfo const* spellInfo = nullptr); int32 SpellBaseDamageBonusDone(SpellSchoolMask schoolMask) const; - uint32 SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uint32 pdamage, DamageEffectType damagetype, SpellEffectInfo const* effect, uint32 stack = 1) const; + uint32 SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uint32 pdamage, DamageEffectType damagetype, SpellEffectInfo const& spellEffectInfo, uint32 stack = 1) const; float SpellDamagePctDone(Unit* victim, SpellInfo const* spellProto, DamageEffectType damagetype) const; uint32 SpellDamageBonusTaken(Unit* caster, SpellInfo const* spellProto, uint32 pdamage, DamageEffectType damagetype) const; int32 SpellBaseHealingBonusDone(SpellSchoolMask schoolMask) const; - uint32 SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, uint32 healamount, DamageEffectType damagetype, SpellEffectInfo const* effect, uint32 stack = 1) const; + uint32 SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, uint32 healamount, DamageEffectType damagetype, SpellEffectInfo const& spellEffectInfo, uint32 stack = 1) const; float SpellHealingPctDone(Unit* victim, SpellInfo const* spellProto) const; uint32 SpellHealingBonusTaken(Unit* caster, SpellInfo const* spellProto, uint32 healamount, DamageEffectType damagetype) const; @@ -1674,9 +1674,9 @@ 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, int8 effIndex = -1); + static bool IsDamageReducedByArmor(SpellSchoolMask damageSchoolMask, SpellInfo const* spellInfo = nullptr, SpellEffectInfo const* spellEffectInfo = nullptr); static uint32 CalcArmorReducedDamage(Unit const* attacker, Unit* victim, uint32 damage, SpellInfo const* spellInfo, WeaponAttackType attackType = MAX_ATTACK, uint8 attackerLevel = 0); static uint32 CalcSpellResistedDamage(Unit const* attacker, Unit* victim, uint32 damage, SpellSchoolMask schoolMask, SpellInfo const* spellInfo); static void CalcAbsorbResist(DamageInfo& damageInfo); diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index e341794b7a3..20a5454d184 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -4939,12 +4939,12 @@ void ObjectMgr::LoadQuests() if (!spellInfo) continue; - for (SpellEffectInfo const* effect : spellInfo->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : spellInfo->GetEffects()) { - if (!effect || effect->Effect != SPELL_EFFECT_QUEST_COMPLETE) + if (spellEffectInfo.Effect != SPELL_EFFECT_QUEST_COMPLETE) continue; - uint32 quest_id = effect->MiscValue; + uint32 quest_id = spellEffectInfo.MiscValue; Quest const* quest = GetQuestTemplate(quest_id); @@ -5506,11 +5506,16 @@ void ObjectMgr::LoadSpellScripts() continue; } - uint8 i = (uint8)((uint32(itr->first) >> 24) & 0x000000FF); + SpellEffIndex i = SpellEffIndex((uint32(itr->first) >> 24) & 0x000000FF); + if (uint32(i) >= spellInfo->GetEffects().size()) + { + TC_LOG_ERROR("sql.sql", "Table `spell_scripts` has too high effect index %u for spell (Id: %u) as script id", uint32(i), spellId); + continue; + } + //check for correct spellEffect - SpellEffectInfo const* effect = spellInfo->GetEffect(i); - if (effect && (!effect->Effect || (effect->Effect != SPELL_EFFECT_SCRIPT_EFFECT && effect->Effect != SPELL_EFFECT_DUMMY))) - TC_LOG_ERROR("sql.sql", "Table `spell_scripts` - spell %u effect %u is not SPELL_EFFECT_SCRIPT_EFFECT or SPELL_EFFECT_DUMMY", spellId, i); + if (!spellInfo->GetEffect(i).Effect || (spellInfo->GetEffect(i).Effect != SPELL_EFFECT_SCRIPT_EFFECT && spellInfo->GetEffect(i).Effect != SPELL_EFFECT_DUMMY)) + TC_LOG_ERROR("sql.sql", "Table `spell_scripts` - spell %u effect %u is not SPELL_EFFECT_SCRIPT_EFFECT or SPELL_EFFECT_DUMMY", spellId, uint32(i)); } } @@ -5527,10 +5532,10 @@ void ObjectMgr::LoadEventScripts() // Load all possible script entries from spells for (SpellNameEntry const* spellNameEntry : sSpellNameStore) if (SpellInfo const* spell = sSpellMgr->GetSpellInfo(spellNameEntry->ID, DIFFICULTY_NONE)) - for (SpellEffectInfo const* effect : spell->GetEffects()) - if (effect && effect->Effect == SPELL_EFFECT_SEND_EVENT) - if (effect->MiscValue) - evt_scripts.insert(effect->MiscValue); + for (SpellEffectInfo const& spellEffectInfo : spell->GetEffects()) + if (spellEffectInfo.IsEffect(SPELL_EFFECT_SEND_EVENT)) + if (spellEffectInfo.MiscValue) + evt_scripts.insert(spellEffectInfo.MiscValue); for (size_t path_idx = 0; path_idx < sTaxiPathNodesByPath.size(); ++path_idx) { diff --git a/src/server/game/Handlers/PetHandler.cpp b/src/server/game/Handlers/PetHandler.cpp index c38a63201b1..bb5e3323b11 100644 --- a/src/server/game/Handlers/PetHandler.cpp +++ b/src/server/game/Handlers/PetHandler.cpp @@ -305,9 +305,9 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spe return; } - for (SpellEffectInfo const* effect: spellInfo->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : spellInfo->GetEffects()) { - if (effect && (effect->TargetA.GetTarget() == TARGET_UNIT_SRC_AREA_ENEMY || effect->TargetA.GetTarget() == TARGET_UNIT_DEST_AREA_ENEMY || effect->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/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h index 49a9d48cbe7..63733a8b220 100644 --- a/src/server/game/Miscellaneous/SharedDefines.h +++ b/src/server/game/Miscellaneous/SharedDefines.h @@ -1089,6 +1089,7 @@ enum Team enum SpellEffectName { + SPELL_EFFECT_NONE = 0, SPELL_EFFECT_INSTAKILL = 1, SPELL_EFFECT_SCHOOL_DAMAGE = 2, SPELL_EFFECT_DUMMY = 3, diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 159a153ab1f..740e885bd4b 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -575,9 +575,9 @@ NonDefaultConstructible<pAuraEffectHandler> AuraEffectHandler[TOTAL_AURAS]= &AuraEffect::HandleNULL, //503 SPELL_AURA_MOD_PLAYER_CHOICE_REROLLS }; -AuraEffect::AuraEffect(Aura* base, SpellEffectInfo const* spellEfffectInfo, int32 const* baseAmount, Unit* caster) : +AuraEffect::AuraEffect(Aura* base, SpellEffectInfo const& spellEfffectInfo, int32 const* baseAmount, Unit* caster) : m_base(base), m_spellInfo(base->GetSpellInfo()), m_effectInfo(spellEfffectInfo), m_spellmod(nullptr), -m_baseAmount(baseAmount ? *baseAmount : spellEfffectInfo->CalcBaseValue(caster, base->GetType() == UNIT_AURA_TYPE ? base->GetOwner()->ToUnit() : nullptr, base->GetCastItemId(), base->GetCastItemLevel())), +m_baseAmount(baseAmount ? *baseAmount : spellEfffectInfo.CalcBaseValue(caster, base->GetType() == UNIT_AURA_TYPE ? base->GetOwner()->ToUnit() : nullptr, base->GetCastItemId(), base->GetCastItemLevel())), _amount(), _periodicTimer(0), _period(0), _ticksDone(0), m_canBeRecalculated(true), m_isPeriodic(false) { @@ -621,10 +621,10 @@ int32 AuraEffect::CalculateAmount(Unit* caster) // default amount calculation int32 amount = 0; - if (!m_spellInfo->HasAttribute(SPELL_ATTR8_MASTERY_SPECIALIZATION) || G3D::fuzzyEq(GetSpellEffectInfo()->BonusCoefficient, 0.0f)) - amount = GetSpellEffectInfo()->CalcValue(caster, &m_baseAmount, GetBase()->GetOwner()->ToUnit(), nullptr, GetBase()->GetCastItemId(), GetBase()->GetCastItemLevel()); + if (!m_spellInfo->HasAttribute(SPELL_ATTR8_MASTERY_SPECIALIZATION) || G3D::fuzzyEq(GetSpellEffectInfo().BonusCoefficient, 0.0f)) + amount = GetSpellEffectInfo().CalcValue(caster, &m_baseAmount, GetBase()->GetOwner()->ToUnit(), nullptr, GetBase()->GetCastItemId(), GetBase()->GetCastItemLevel()); else if (caster && caster->GetTypeId() == TYPEID_PLAYER) - amount = int32(caster->ToPlayer()->m_activePlayerData->Mastery * GetSpellEffectInfo()->BonusCoefficient); + amount = int32(caster->ToPlayer()->m_activePlayerData->Mastery * GetSpellEffectInfo().BonusCoefficient); // custom amount calculations go here switch (GetAuraType()) @@ -668,12 +668,12 @@ int32 AuraEffect::CalculateAmount(Unit* caster) } GetBase()->CallScriptEffectCalcAmountHandlers(this, amount, m_canBeRecalculated); - if (!GetSpellEffectInfo()->EffectAttributes.HasFlag(SpellEffectAttributes::NoScaleWithStack)) + if (!GetSpellEffectInfo().EffectAttributes.HasFlag(SpellEffectAttributes::NoScaleWithStack)) amount *= GetBase()->GetStackAmount(); if (caster && GetBase()->GetType() == UNIT_AURA_TYPE) { - uint32 stackAmountForBonuses = !GetSpellEffectInfo()->EffectAttributes.HasFlag(SpellEffectAttributes::NoScaleWithStack) ? GetBase()->GetStackAmount() : 1; + uint32 stackAmountForBonuses = !GetSpellEffectInfo().EffectAttributes.HasFlag(SpellEffectAttributes::NoScaleWithStack) ? GetBase()->GetStackAmount() : 1; switch (GetAuraType()) { @@ -719,7 +719,7 @@ void AuraEffect::ResetPeriodic(bool resetPeriodicTimer /*= false*/) void AuraEffect::CalculatePeriodic(Unit* caster, bool resetPeriodicTimer /*= true*/, bool load /*= false*/) { - _period = GetSpellEffectInfo()->ApplyAuraPeriod; + _period = GetSpellEffectInfo().ApplyAuraPeriod; // prepare periodics switch (GetAuraType()) @@ -801,7 +801,7 @@ void AuraEffect::CalculateSpellMod() m_spellmod->type = GetAuraType() == SPELL_AURA_ADD_PCT_MODIFIER ? SPELLMOD_PCT : SPELLMOD_FLAT; m_spellmod->spellId = GetId(); - m_spellmod->mask = GetSpellEffectInfo()->SpellClassMask; + m_spellmod->mask = GetSpellEffectInfo().SpellClassMask; } m_spellmod->value = GetAmount(); break; @@ -1006,7 +1006,7 @@ bool AuraEffect::IsAffectingSpell(SpellInfo const* spell) const return false; // Check family name and EffectClassMask - if (!spell->IsAffected(m_spellInfo->SpellFamilyName, GetSpellEffectInfo()->SpellClassMask)) + if (!spell->IsAffected(m_spellInfo->SpellFamilyName, GetSpellEffectInfo().SpellClassMask)) return false; return true; @@ -1139,7 +1139,7 @@ bool AuraEffect::CheckEffectProc(AuraApplication* aurApp, ProcEventInfo& eventIn case SPELL_AURA_PROC_TRIGGER_SPELL_WITH_VALUE: { // Don't proc extra attacks while already processing extra attack spell - uint32 triggerSpellId = GetSpellEffectInfo()->TriggerSpell; + uint32 triggerSpellId = GetSpellEffectInfo().TriggerSpell; if (SpellInfo const* triggeredSpellInfo = sSpellMgr->GetSpellInfo(triggerSpellId, GetBase()->GetCastDifficulty())) if (aurApp->GetTarget()->m_extraAttacks && triggeredSpellInfo->HasEffect(SPELL_EFFECT_ADD_EXTRA_ATTACKS)) return false; @@ -2527,8 +2527,8 @@ void AuraEffect::HandleAuraMounted(AuraApplication const* aurApp, uint8 mode, bo } //some spell has one aura of mount and one of vehicle - for (SpellEffectInfo const* effect : GetSpellInfo()->GetEffects()) - if (effect && effect->Effect == SPELL_EFFECT_SUMMON && effect->MiscValue == GetMiscValue()) + for (SpellEffectInfo const& effect : GetSpellInfo()->GetEffects()) + if (effect.IsEffect(SPELL_EFFECT_SUMMON) && effect.MiscValue == GetMiscValue()) displayId = 0; } @@ -4382,8 +4382,7 @@ void AuraEffect::HandleNoReagentUseAura(AuraApplication const* aurApp, uint8 mod flag128 mask; Unit::AuraEffectList const& noReagent = target->GetAuraEffectsByType(SPELL_AURA_NO_REAGENT_USE); for (Unit::AuraEffectList::const_iterator i = noReagent.begin(); i != noReagent.end(); ++i) - if (SpellEffectInfo const* effect = (*i)->GetSpellEffectInfo()) - mask |= effect->SpellClassMask; + mask |= (*i)->GetSpellEffectInfo().SpellClassMask; target->ToPlayer()->SetNoRegentCostMask(mask); } @@ -4750,11 +4749,11 @@ void AuraEffect::HandleChannelDeathItem(AuraApplication const* aurApp, uint8 mod if (GetAmount() <= 0) return; - if (GetSpellEffectInfo()->ItemType == 0) + if (GetSpellEffectInfo().ItemType == 0) return; // Soul Shard - if (GetSpellEffectInfo()->ItemType == 6265) + if (GetSpellEffectInfo().ItemType == 6265) { // Soul Shard only from units that grant XP or honor if (!plCaster->isHonorOrXPTarget(target) || @@ -4767,16 +4766,16 @@ void AuraEffect::HandleChannelDeathItem(AuraApplication const* aurApp, uint8 mod uint32 count = GetAmount(); ItemPosCountVec dest; - InventoryResult msg = plCaster->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, GetSpellEffectInfo()->ItemType, count, &noSpaceForCount); + InventoryResult msg = plCaster->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, GetSpellEffectInfo().ItemType, count, &noSpaceForCount); if (msg != EQUIP_ERR_OK) { count -= noSpaceForCount; - plCaster->SendEquipError(msg, nullptr, nullptr, GetSpellEffectInfo()->ItemType); + plCaster->SendEquipError(msg, nullptr, nullptr, GetSpellEffectInfo().ItemType); if (count == 0) return; } - Item* newitem = plCaster->StoreNewItem(dest, GetSpellEffectInfo()->ItemType, true); + Item* newitem = plCaster->StoreNewItem(dest, GetSpellEffectInfo().ItemType, true); if (!newitem) { plCaster->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, nullptr, nullptr); @@ -4902,7 +4901,7 @@ void AuraEffect::HandleAuraLinked(AuraApplication const* aurApp, uint8 mode, boo { Unit* target = aurApp->GetTarget(); - uint32 triggeredSpellId = GetSpellEffectInfo()->TriggerSpell; + uint32 triggeredSpellId = GetSpellEffectInfo().TriggerSpell; SpellInfo const* triggeredSpellInfo = sSpellMgr->GetSpellInfo(triggeredSpellId, GetBase()->GetCastDifficulty()); if (!triggeredSpellInfo) return; @@ -4946,7 +4945,7 @@ void AuraEffect::HandleTriggerSpellOnPowerPercent(AuraApplication const* aurApp, Unit* target = aurApp->GetTarget(); int32 effectAmount = GetAmount(); - uint32 triggerSpell = GetSpellEffectInfo()->TriggerSpell; + uint32 triggerSpell = GetSpellEffectInfo().TriggerSpell; float powerAmountPct = GetPctOf(target->GetPower(Powers(GetMiscValue())), target->GetMaxPower(Powers(GetMiscValue()))); switch (AuraTriggerOnPowerChangeDirection(GetMiscValueB())) @@ -4974,7 +4973,7 @@ void AuraEffect::HandleTriggerSpellOnPowerAmount(AuraApplication const* aurApp, Unit* target = aurApp->GetTarget(); int32 effectAmount = GetAmount(); - uint32 triggerSpell = GetSpellEffectInfo()->TriggerSpell; + uint32 triggerSpell = GetSpellEffectInfo().TriggerSpell; float powerAmount = target->GetPower(Powers(GetMiscValue())); switch (AuraTriggerOnPowerChangeDirection(GetMiscValueB())) @@ -5133,7 +5132,7 @@ void AuraEffect::HandleMastery(AuraApplication const* aurApp, uint8 mode, bool / void AuraEffect::HandlePeriodicTriggerSpellAuraTick(Unit* target, Unit* caster) const { - uint32 triggerSpellId = GetSpellEffectInfo()->TriggerSpell; + uint32 triggerSpellId = GetSpellEffectInfo().TriggerSpell; if (SpellInfo const* triggeredSpellInfo = sSpellMgr->GetSpellInfo(triggerSpellId, GetBase()->GetCastDifficulty())) { if (Unit* triggerCaster = triggeredSpellInfo->NeedsToBeTriggeredByCaster(m_spellInfo) ? caster : target) @@ -5148,7 +5147,7 @@ void AuraEffect::HandlePeriodicTriggerSpellAuraTick(Unit* target, Unit* caster) void AuraEffect::HandlePeriodicTriggerSpellWithValueAuraTick(Unit* target, Unit* caster) const { - uint32 triggerSpellId = GetSpellEffectInfo()->TriggerSpell; + uint32 triggerSpellId = GetSpellEffectInfo().TriggerSpell; if (SpellInfo const* triggeredSpellInfo = sSpellMgr->GetSpellInfo(triggerSpellId, GetBase()->GetCastDifficulty())) { if (Unit* triggerCaster = triggeredSpellInfo->NeedsToBeTriggeredByCaster(m_spellInfo) ? caster : target) @@ -5177,13 +5176,13 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const // Consecrate ticks can miss and will not show up in the combat log // dynobj auras must always have a caster - if (GetSpellEffectInfo()->Effect == SPELL_EFFECT_PERSISTENT_AREA_AURA && + if (GetSpellEffectInfo().IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA) && ASSERT_NOTNULL(caster)->SpellHitResult(target, GetSpellInfo(), false) != SPELL_MISS_NONE) return; CleanDamage cleanDamage = CleanDamage(0, 0, BASE_ATTACK, MELEE_HIT_NORMAL); - uint32 stackAmountForBonuses = !GetSpellEffectInfo()->EffectAttributes.HasFlag(SpellEffectAttributes::NoScaleWithStack) ? GetBase()->GetStackAmount() : 1; + uint32 stackAmountForBonuses = !GetSpellEffectInfo().EffectAttributes.HasFlag(SpellEffectAttributes::NoScaleWithStack) ? GetBase()->GetStackAmount() : 1; // ignore negative values (can be result apply spellmods to aura damage uint32 damage = std::max(GetAmount(), 0); @@ -5248,7 +5247,7 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const damage = Unit::SpellCriticalDamageBonus(caster, m_spellInfo, damage, target); // Calculate armor mitigation - if (Unit::IsDamageReducedByArmor(GetSpellInfo()->GetSchoolMask(), GetSpellInfo(), GetEffIndex())) + if (Unit::IsDamageReducedByArmor(GetSpellInfo()->GetSchoolMask(), GetSpellInfo(), &GetSpellEffectInfo())) { uint32 damageReducedArmor = Unit::CalcArmorReducedDamage(caster, target, damage, GetSpellInfo(), GetSpellInfo()->GetAttackType(), GetBase()->GetCasterLevel()); cleanDamage.mitigated_damage += damage - damageReducedArmor; @@ -5257,7 +5256,7 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const if (!GetSpellInfo()->HasAttribute(SPELL_ATTR4_FIXED_DAMAGE)) { - if (GetSpellEffectInfo()->IsTargetingArea() || GetSpellEffectInfo()->IsAreaAuraEffect() || GetSpellEffectInfo()->Effect == SPELL_EFFECT_PERSISTENT_AREA_AURA) + if (GetSpellEffectInfo().IsTargetingArea() || GetSpellEffectInfo().IsAreaAuraEffect() || GetSpellEffectInfo().IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA)) damage = target->CalculateAOEAvoidance(damage, m_spellInfo->SchoolMask, GetBase()->GetCasterGUID()); } @@ -5302,7 +5301,7 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const bool AuraEffect::IsAreaAuraEffect() const { - return GetSpellEffectInfo()->IsAreaAuraEffect(); + return GetSpellEffectInfo().IsAreaAuraEffect(); } void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) const @@ -5317,13 +5316,13 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c } // dynobj auras must always have a caster - if (GetSpellEffectInfo()->Effect == SPELL_EFFECT_PERSISTENT_AREA_AURA && + if (GetSpellEffectInfo().IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA) && ASSERT_NOTNULL(caster)->SpellHitResult(target, GetSpellInfo(), false) != SPELL_MISS_NONE) return; CleanDamage cleanDamage = CleanDamage(0, 0, GetSpellInfo()->GetAttackType(), MELEE_HIT_NORMAL); - uint32 stackAmountForBonuses = !GetSpellEffectInfo()->EffectAttributes.HasFlag(SpellEffectAttributes::NoScaleWithStack) ? GetBase()->GetStackAmount() : 1; + uint32 stackAmountForBonuses = !GetSpellEffectInfo().EffectAttributes.HasFlag(SpellEffectAttributes::NoScaleWithStack) ? GetBase()->GetStackAmount() : 1; // ignore negative values (can be result apply spellmods to aura damage uint32 damage = std::max(GetAmount(), 0); @@ -5337,7 +5336,7 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c damage = Unit::SpellCriticalDamageBonus(caster, m_spellInfo, damage, target); // Calculate armor mitigation - if (Unit::IsDamageReducedByArmor(GetSpellInfo()->GetSchoolMask(), GetSpellInfo(), GetEffIndex())) + if (Unit::IsDamageReducedByArmor(GetSpellInfo()->GetSchoolMask(), GetSpellInfo(), &GetSpellEffectInfo())) { uint32 damageReducedArmor = Unit::CalcArmorReducedDamage(caster, target, damage, GetSpellInfo(), GetSpellInfo()->GetAttackType(), GetBase()->GetCasterLevel()); cleanDamage.mitigated_damage += damage - damageReducedArmor; @@ -5346,7 +5345,7 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c if (!GetSpellInfo()->HasAttribute(SPELL_ATTR4_FIXED_DAMAGE)) { - if (GetSpellEffectInfo()->IsTargetingArea() || GetSpellEffectInfo()->IsAreaAuraEffect() || GetSpellEffectInfo()->Effect == SPELL_EFFECT_PERSISTENT_AREA_AURA) + if (GetSpellEffectInfo().IsTargetingArea() || GetSpellEffectInfo().IsAreaAuraEffect() || GetSpellEffectInfo().IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA)) damage = target->CalculateAOEAvoidance(damage, m_spellInfo->SchoolMask, GetBase()->GetCasterGUID()); } @@ -5390,7 +5389,7 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c if (!caster || !caster->IsAlive()) return; - float gainMultiplier = GetSpellEffectInfo()->CalcValueMultiplier(caster); + float gainMultiplier = GetSpellEffectInfo().CalcValueMultiplier(caster); uint32 heal = caster->SpellHealingBonusDone(caster, GetSpellInfo(), uint32(new_damage * gainMultiplier), DOT, GetSpellEffectInfo(), stackAmountForBonuses); heal = caster->SpellHealingBonusTaken(caster, GetSpellInfo(), heal, DOT); @@ -5425,7 +5424,7 @@ void AuraEffect::HandlePeriodicHealthFunnelAuraTick(Unit* target, Unit* caster) caster->ModifyHealth(-(int32)damage); TC_LOG_DEBUG("spells", "PeriodicTick: donator %u target %u damage %u.", caster->GetEntry(), target->GetEntry(), damage); - float gainMultiplier = GetSpellEffectInfo()->CalcValueMultiplier(caster); + float gainMultiplier = GetSpellEffectInfo().CalcValueMultiplier(caster); damage = int32(damage * gainMultiplier); @@ -5453,7 +5452,7 @@ void AuraEffect::HandlePeriodicHealAurasTick(Unit* target, Unit* caster) const if (GetBase()->IsPermanent() && target->IsFullHealth()) return; - uint32 stackAmountForBonuses = !GetSpellEffectInfo()->EffectAttributes.HasFlag(SpellEffectAttributes::NoScaleWithStack) ? GetBase()->GetStackAmount() : 1; + uint32 stackAmountForBonuses = !GetSpellEffectInfo().EffectAttributes.HasFlag(SpellEffectAttributes::NoScaleWithStack) ? GetBase()->GetStackAmount() : 1; // ignore negative values (can be result apply spellmods to aura damage uint32 damage = std::max(GetAmount(), 0); @@ -5509,7 +5508,7 @@ void AuraEffect::HandlePeriodicManaLeechAuraTick(Unit* target, Unit* caster) con return; } - if (GetSpellEffectInfo()->Effect == SPELL_EFFECT_PERSISTENT_AREA_AURA && + if (GetSpellEffectInfo().IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA) && caster->SpellHitResult(target, GetSpellInfo(), false) != SPELL_MISS_NONE) return; @@ -5521,7 +5520,7 @@ void AuraEffect::HandlePeriodicManaLeechAuraTick(Unit* target, Unit* caster) con int32 drainedAmount = -target->ModifyPower(powerType, -drainAmount); - float gainMultiplier = GetSpellEffectInfo()->CalcValueMultiplier(caster); + float gainMultiplier = GetSpellEffectInfo().CalcValueMultiplier(caster); SpellPeriodicAuraLogInfo pInfo(this, drainedAmount, drainAmount, 0, 0, 0, gainMultiplier, false); @@ -5638,7 +5637,7 @@ void AuraEffect::HandlePeriodicPowerBurnAuraTick(Unit* target, Unit* caster) con uint32 gain = uint32(-target->ModifyPower(powerType, -damage)); - float dmgMultiplier = GetSpellEffectInfo()->CalcValueMultiplier(caster); + float dmgMultiplier = GetSpellEffectInfo().CalcValueMultiplier(caster); SpellInfo const* spellProto = GetSpellInfo(); // maybe has to be sent different to client, but not by SMSG_PERIODICAURALOG @@ -5703,7 +5702,7 @@ void AuraEffect::HandleProcTriggerSpellAuraProc(AuraApplication* aurApp, ProcEve Unit* triggerCaster = aurApp->GetTarget(); Unit* triggerTarget = eventInfo.GetProcTarget(); - uint32 triggerSpellId = GetSpellEffectInfo()->TriggerSpell; + uint32 triggerSpellId = GetSpellEffectInfo().TriggerSpell; if (SpellInfo const* triggeredSpellInfo = sSpellMgr->GetSpellInfo(triggerSpellId, GetBase()->GetCastDifficulty())) { TC_LOG_DEBUG("spells", "AuraEffect::HandleProcTriggerSpellAuraProc: Triggering spell %u from aura %u proc", triggeredSpellInfo->Id, GetId()); @@ -5718,7 +5717,7 @@ void AuraEffect::HandleProcTriggerSpellWithValueAuraProc(AuraApplication* aurApp Unit* triggerCaster = aurApp->GetTarget(); Unit* triggerTarget = eventInfo.GetProcTarget(); - uint32 triggerSpellId = GetSpellEffectInfo()->TriggerSpell; + uint32 triggerSpellId = GetSpellEffectInfo().TriggerSpell; if (SpellInfo const* triggeredSpellInfo = sSpellMgr->GetSpellInfo(triggerSpellId, GetBase()->GetCastDifficulty())) { CastSpellExtraArgs args(this); @@ -5801,9 +5800,9 @@ void AuraEffect::HandleShowConfirmationPrompt(AuraApplication const* aurApp, uin return; if (apply) - player->AddTemporarySpell(GetSpellEffectInfo()->TriggerSpell); + player->AddTemporarySpell(GetSpellEffectInfo().TriggerSpell); else - player->RemoveTemporarySpell(GetSpellEffectInfo()->TriggerSpell); + player->RemoveTemporarySpell(GetSpellEffectInfo().TriggerSpell); } void AuraEffect::HandleOverridePetSpecs(AuraApplication const* aurApp, uint8 mode, bool apply) const @@ -5897,7 +5896,7 @@ void AuraEffect::HandleLinkedSummon(AuraApplication const* aurApp, uint8 mode, b return; Unit* target = aurApp->GetTarget(); - SpellInfo const* triggerSpellInfo = sSpellMgr->GetSpellInfo(GetSpellEffectInfo()->TriggerSpell, GetBase()->GetCastDifficulty()); + SpellInfo const* triggerSpellInfo = sSpellMgr->GetSpellInfo(GetSpellEffectInfo().TriggerSpell, GetBase()->GetCastDifficulty()); if (!triggerSpellInfo) return; @@ -5914,9 +5913,9 @@ void AuraEffect::HandleLinkedSummon(AuraApplication const* aurApp, uint8 mode, b else { std::vector<uint32> summonedEntries; - for (auto spellEffect : triggerSpellInfo->GetEffects()) - if (spellEffect && spellEffect->Effect == SPELL_EFFECT_SUMMON) - if (uint32 summonEntry = spellEffect->MiscValue) + for (SpellEffectInfo const& spellEffect : triggerSpellInfo->GetEffects()) + if (spellEffect.IsEffect(SPELL_EFFECT_SUMMON)) + if (uint32 summonEntry = spellEffect.MiscValue) summonedEntries.push_back(summonEntry); // we don't know if there can be multiple summons for the same effect, so consider only 1 summon for each effect diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.h b/src/server/game/Spells/Auras/SpellAuraEffects.h index 1a96b81ea68..476be23e451 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.h +++ b/src/server/game/Spells/Auras/SpellAuraEffects.h @@ -33,7 +33,7 @@ class TC_GAME_API AuraEffect private: ~AuraEffect(); - explicit AuraEffect(Aura* base, SpellEffectInfo const* spellEfffectInfo, int32 const* baseAmount, Unit* caster); + explicit AuraEffect(Aura* base, SpellEffectInfo const& spellEfffectInfo, int32 const* baseAmount, Unit* caster); public: Unit* GetCaster() const { return GetBase()->GetCaster(); } @@ -48,13 +48,13 @@ class TC_GAME_API AuraEffect SpellInfo const* GetSpellInfo() const { return m_spellInfo; } uint32 GetId() const { return m_spellInfo->Id; } - uint32 GetEffIndex() const { return m_effectInfo->EffectIndex; } + SpellEffIndex GetEffIndex() const { return m_effectInfo.EffectIndex; } int32 GetBaseAmount() const { return m_baseAmount; } int32 GetPeriod() const { return _period; } - int32 GetMiscValueB() const { return GetSpellEffectInfo()->MiscValueB; } - int32 GetMiscValue() const { return GetSpellEffectInfo()->MiscValue; } - AuraType GetAuraType() const { return (AuraType)GetSpellEffectInfo()->ApplyAuraName; } + int32 GetMiscValueB() const { return GetSpellEffectInfo().MiscValueB; } + int32 GetMiscValue() const { return GetSpellEffectInfo().MiscValue; } + AuraType GetAuraType() const { return GetSpellEffectInfo().ApplyAuraName; } int32 GetAmount() const { return _amount; } void SetAmount(int32 amount) { _amount = amount; m_canBeRecalculated = false; } @@ -86,7 +86,7 @@ class TC_GAME_API AuraEffect bool IsPeriodic() const { return m_isPeriodic; } void SetPeriodic(bool isPeriodic) { m_isPeriodic = isPeriodic; } bool IsAffectingSpell(SpellInfo const* spell) const; - bool HasSpellClassMask() const { return GetSpellEffectInfo()->SpellClassMask; } + bool HasSpellClassMask() const { return GetSpellEffectInfo().SpellClassMask; } void SendTickImmune(Unit* target, Unit* caster) const; void PeriodicTick(AuraApplication* aurApp, Unit* caster) const; @@ -97,17 +97,17 @@ class TC_GAME_API AuraEffect // add/remove SPELL_AURA_MOD_SHAPESHIFT (36) linked auras void HandleShapeshiftBoosts(Unit* target, bool apply) const; - SpellEffectInfo const* GetSpellEffectInfo() const { return m_effectInfo; } + SpellEffectInfo const& GetSpellEffectInfo() const { return m_effectInfo; } - bool IsEffect() const { return m_effectInfo->Effect != 0; } - bool IsEffect(SpellEffectName effectName) const { return m_effectInfo->Effect == uint32(effectName); } + bool IsEffect() const { return m_effectInfo.Effect != 0; } + bool IsEffect(SpellEffectName effectName) const { return m_effectInfo.Effect == effectName; } bool IsAreaAuraEffect() const; private: Aura* const m_base; SpellInfo const* const m_spellInfo; - SpellEffectInfo const* m_effectInfo; + SpellEffectInfo const& m_effectInfo; SpellModifier* m_spellmod; diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp index 881828cbaa5..a6959945d0d 100644 --- a/src/server/game/Spells/Auras/SpellAuras.cpp +++ b/src/server/game/Spells/Auras/SpellAuras.cpp @@ -115,9 +115,9 @@ void AuraApplication::_InitFlags(Unit* caster, uint32 effMask) if (IsSelfcast() || !caster || !caster->IsFriendlyTo(GetTarget())) { bool negativeFound = false; - for (SpellEffectInfo const* effect : GetBase()->GetSpellInfo()->GetEffects()) + for (uint8 i = 0; i < GetBase()->GetSpellInfo()->GetEffects().size(); ++i) { - if (effect && ((1 << effect->EffectIndex) & effMask) && !GetBase()->GetSpellInfo()->IsPositiveEffect(effect->EffectIndex)) + if (((1 << i) & effMask) && !GetBase()->GetSpellInfo()->IsPositiveEffect(i)) { negativeFound = true; break; @@ -130,9 +130,9 @@ void AuraApplication::_InitFlags(Unit* caster, uint32 effMask) else { bool positiveFound = false; - for (SpellEffectInfo const* effect : GetBase()->GetSpellInfo()->GetEffects()) + for (uint8 i = 0; i < GetBase()->GetSpellInfo()->GetEffects().size(); ++i) { - if (effect && ((1 << effect->EffectIndex) & effMask) && GetBase()->GetSpellInfo()->IsPositiveEffect(effect->EffectIndex)) + if (((1 << i) & effMask) && GetBase()->GetSpellInfo()->IsPositiveEffect(i)) { positiveFound = true; break; @@ -300,17 +300,17 @@ uint32 Aura::BuildEffectMaskForOwner(SpellInfo const* spellProto, uint32 availab { case TYPEID_UNIT: case TYPEID_PLAYER: - for (SpellEffectInfo const* effect : spellProto->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : spellProto->GetEffects()) { - if (effect && effect->IsUnitOwnedAuraEffect()) - effMask |= 1 << effect->EffectIndex; + if (spellEffectInfo.IsUnitOwnedAuraEffect()) + effMask |= 1 << spellEffectInfo.EffectIndex; } break; case TYPEID_DYNAMICOBJECT: - for (SpellEffectInfo const* effect : spellProto->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : spellProto->GetEffects()) { - if (effect && effect->Effect == SPELL_EFFECT_PERSISTENT_AREA_AURA) - effMask |= 1 << effect->EffectIndex; + if (spellEffectInfo.IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA)) + effMask |= 1 << spellEffectInfo.EffectIndex; } break; default: @@ -482,9 +482,9 @@ void Aura::_InitEffects(uint32 effMask, Unit* caster, int32 const* baseAmount) // shouldn't be in constructor - functions in AuraEffect::AuraEffect use polymorphism _effects.resize(GetSpellInfo()->GetEffects().size()); - for (SpellEffectInfo const* effect : GetSpellInfo()->GetEffects()) - if (effect && effMask & (1 << effect->EffectIndex)) - _effects[effect->EffectIndex] = new AuraEffect(this, effect, baseAmount ? baseAmount + effect->EffectIndex : nullptr, caster); + for (SpellEffectInfo const& spellEffectInfo : GetSpellInfo()->GetEffects()) + if (effMask & (1 << spellEffectInfo.EffectIndex)) + _effects[spellEffectInfo.EffectIndex] = new AuraEffect(this, spellEffectInfo, baseAmount ? baseAmount + spellEffectInfo.EffectIndex : nullptr, caster); } Aura::~Aura() @@ -643,9 +643,9 @@ void Aura::UpdateTargetMap(Unit* caster, bool apply) { bool addUnit = true; // check target immunities - for (uint8 effIndex = 0; effIndex < MAX_SPELL_EFFECTS; ++effIndex) - if (itr->first->IsImmunedToSpellEffect(GetSpellInfo(), effIndex, caster)) - itr->second &= ~(1 << effIndex); + for (SpellEffectInfo const& spellEffectInfo : GetSpellInfo()->GetEffects()) + if (itr->first->IsImmunedToSpellEffect(GetSpellInfo(), spellEffectInfo, caster)) + itr->second &= ~(1 << spellEffectInfo.EffectIndex); if (!itr->second || itr->first->IsImmunedToSpell(GetSpellInfo(), caster) || !CanBeAppliedOn(itr->first)) addUnit = false; @@ -1071,8 +1071,8 @@ bool Aura::ModStackAmount(int32 num, AuraRemoveMode removeMode /*= AURA_REMOVE_B bool Aura::HasMoreThanOneEffectForType(AuraType auraType) const { uint32 count = 0; - for (SpellEffectInfo const* effect : GetSpellInfo()->GetEffects()) - if (effect && HasEffect(effect->EffectIndex) && AuraType(effect->ApplyAuraName) == auraType) + for (SpellEffectInfo const& spellEffectInfo : GetSpellInfo()->GetEffects()) + if (HasEffect(spellEffectInfo.EffectIndex) && spellEffectInfo.ApplyAuraName == auraType) ++count; return count > 1; @@ -1080,8 +1080,8 @@ bool Aura::HasMoreThanOneEffectForType(AuraType auraType) const bool Aura::IsArea() const { - for (SpellEffectInfo const* effect : GetSpellInfo()->GetEffects()) - if (effect && HasEffect(effect->EffectIndex) && effect->IsAreaAuraEffect()) + for (SpellEffectInfo const& spellEffectInfo : GetSpellInfo()->GetEffects()) + if (HasEffect(spellEffectInfo.EffectIndex) && spellEffectInfo.IsAreaAuraEffect()) return true; return false; @@ -1117,12 +1117,12 @@ bool Aura::CanBeSaved() const if (GetCasterGUID() != GetOwner()->GetGUID()) { // owner == caster for area auras, check for possible bad data in DB - for (SpellEffectInfo const* effect : GetSpellInfo()->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : GetSpellInfo()->GetEffects()) { - if (!effect || !effect->IsEffect()) + if (!spellEffectInfo.IsEffect()) continue; - if (effect->IsTargetingArea() || effect->IsAreaAuraEffect()) + if (spellEffectInfo.IsTargetingArea() || spellEffectInfo.IsAreaAuraEffect()) return false; } @@ -1568,17 +1568,17 @@ bool Aura::CanStackWith(Aura const* existingAura) const if (IsPassive() && sameCaster && (m_spellInfo->IsDifferentRankOf(existingSpellInfo) || (m_spellInfo->Id == existingSpellInfo->Id && m_castItemGuid.IsEmpty()))) return false; - for (SpellEffectInfo const* effect : existingSpellInfo->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : existingSpellInfo->GetEffects()) { // prevent remove triggering aura by triggered aura - if (effect && effect->TriggerSpell == GetId()) + if (spellEffectInfo.TriggerSpell == GetId()) return true; } - for (SpellEffectInfo const* effect : GetSpellInfo()->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : GetSpellInfo()->GetEffects()) { // prevent remove triggered aura by triggering aura refresh - if (effect && effect->TriggerSpell == existingAura->GetId()) + if (spellEffectInfo.TriggerSpell == existingAura->GetId()) return true; } @@ -1625,36 +1625,39 @@ bool Aura::CanStackWith(Aura const* existingAura) const return true; // check same periodic auras - for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i) + auto hasPeriodicNonAreaEffect = [](SpellInfo const* spellInfo) { - SpellEffectInfo const* effect = m_spellInfo->GetEffect(i); - if (!effect) - continue; - switch (effect->ApplyAuraName) + for (SpellEffectInfo const& spellEffectInfo : spellInfo->GetEffects()) { - // DOT or HOT from different casters will stack - case SPELL_AURA_PERIODIC_DAMAGE: - case SPELL_AURA_PERIODIC_DUMMY: - case SPELL_AURA_PERIODIC_HEAL: - case SPELL_AURA_PERIODIC_TRIGGER_SPELL: - case SPELL_AURA_PERIODIC_ENERGIZE: - case SPELL_AURA_PERIODIC_MANA_LEECH: - case SPELL_AURA_PERIODIC_LEECH: - case SPELL_AURA_POWER_BURN: - case SPELL_AURA_OBS_MOD_POWER: - case SPELL_AURA_OBS_MOD_HEALTH: - case SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE: - { - SpellEffectInfo const* existingEffect = m_spellInfo->GetEffect(i); + switch (spellEffectInfo.ApplyAuraName) + { + // DOT or HOT from different casters will stack + case SPELL_AURA_PERIODIC_DAMAGE: + case SPELL_AURA_PERIODIC_WEAPON_PERCENT_DAMAGE: + case SPELL_AURA_PERIODIC_DUMMY: + case SPELL_AURA_PERIODIC_HEAL: + case SPELL_AURA_PERIODIC_TRIGGER_SPELL: + case SPELL_AURA_PERIODIC_ENERGIZE: + case SPELL_AURA_PERIODIC_MANA_LEECH: + case SPELL_AURA_PERIODIC_LEECH: + case SPELL_AURA_POWER_BURN: + case SPELL_AURA_OBS_MOD_POWER: + case SPELL_AURA_OBS_MOD_HEALTH: + case SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE: + case SPELL_AURA_PERIODIC_DAMAGE_PERCENT: // periodic auras which target areas are not allowed to stack this way (replenishment for example) - if (effect->IsTargetingArea() || (existingEffect && existingEffect->IsTargetingArea())) - break; - } - return true; - default: - break; + if (spellEffectInfo.IsTargetingArea()) + return false; + return true; + default: + break; + } } - } + return false; + }; + + if (hasPeriodicNonAreaEffect(m_spellInfo) && hasPeriodicNonAreaEffect(existingSpellInfo)) + return true; } if (HasEffectType(SPELL_AURA_CONTROL_VEHICLE) && existingAura->HasEffectType(SPELL_AURA_CONTROL_VEHICLE)) @@ -2382,13 +2385,13 @@ void UnitAura::FillTargetMap(std::unordered_map<Unit*, uint32>& targets, Unit* c if (Unit* target = ObjectAccessor::GetUnit(*GetUnitOwner(), targetPair.first)) targets.emplace(target, targetPair.second); - for (SpellEffectInfo const* effect : GetSpellInfo()->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : GetSpellInfo()->GetEffects()) { - if (!effect || !HasEffect(effect->EffectIndex)) + if (!HasEffect(spellEffectInfo.EffectIndex)) continue; // area auras only - if (effect->Effect == SPELL_EFFECT_APPLY_AURA) + if (spellEffectInfo.IsEffect(SPELL_EFFECT_APPLY_AURA)) continue; // skip area update if owner is not in world! @@ -2399,11 +2402,11 @@ void UnitAura::FillTargetMap(std::unordered_map<Unit*, uint32>& targets, Unit* c continue; std::vector<Unit*> units; - ConditionContainer* condList = effect->ImplicitTargetConditions; + ConditionContainer* condList = spellEffectInfo.ImplicitTargetConditions; - float radius = effect->CalcRadius(ref); + float radius = spellEffectInfo.CalcRadius(ref); SpellTargetCheckTypes selectionType = TARGET_CHECK_DEFAULT; - switch (effect->Effect) + switch (spellEffectInfo.Effect) { case SPELL_EFFECT_APPLY_AREA_AURA_PARTY: case SPELL_EFFECT_APPLY_AREA_AURA_PARTY_NONRANDOM: @@ -2445,6 +2448,8 @@ void UnitAura::FillTargetMap(std::unordered_map<Unit*, uint32>& targets, Unit* c selectionType = TARGET_CHECK_SUMMONED; break; } + default: + break; } if (selectionType != TARGET_CHECK_DEFAULT) @@ -2458,17 +2463,17 @@ void UnitAura::FillTargetMap(std::unordered_map<Unit*, uint32>& targets, Unit* c } for (Unit* unit : units) - targets[unit] |= 1 << effect->EffectIndex; + targets[unit] |= 1 << spellEffectInfo.EffectIndex; } } void UnitAura::AddStaticApplication(Unit* target, uint32 effMask) { // only valid for non-area auras - for (SpellEffectInfo const* effect : GetSpellInfo()->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : GetSpellInfo()->GetEffects()) { - if (effect && (effMask & (1 << effect->EffectIndex)) && effect->Effect != SPELL_EFFECT_APPLY_AURA) - effMask &= ~(1 << effect->EffectIndex); + if ((effMask & (1 << spellEffectInfo.EffectIndex)) && !spellEffectInfo.IsEffect(SPELL_EFFECT_APPLY_AURA)) + effMask &= ~(1 << spellEffectInfo.EffectIndex); } if (!effMask) @@ -2500,18 +2505,18 @@ void DynObjAura::FillTargetMap(std::unordered_map<Unit*, uint32>& targets, Unit* Unit* dynObjOwnerCaster = GetDynobjOwner()->GetCaster(); float radius = GetDynobjOwner()->GetRadius(); - for (SpellEffectInfo const* effect : GetSpellInfo()->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : GetSpellInfo()->GetEffects()) { - if (!effect || !HasEffect(effect->EffectIndex)) + if (!HasEffect(spellEffectInfo.EffectIndex)) continue; // we can't use effect type like area auras to determine check type, check targets - SpellTargetCheckTypes selectionType = effect->TargetA.GetCheckType(); - if (effect->TargetB.GetReferenceType() == TARGET_REFERENCE_TYPE_DEST) - selectionType = effect->TargetB.GetCheckType(); + SpellTargetCheckTypes selectionType = spellEffectInfo.TargetA.GetCheckType(); + if (spellEffectInfo.TargetB.GetReferenceType() == TARGET_REFERENCE_TYPE_DEST) + selectionType = spellEffectInfo.TargetB.GetCheckType(); std::vector<Unit*> units; - ConditionContainer* condList = effect->ImplicitTargetConditions; + ConditionContainer* condList = spellEffectInfo.ImplicitTargetConditions; Trinity::WorldObjectSpellAreaTargetCheck check(radius, GetDynobjOwner(), dynObjOwnerCaster, dynObjOwnerCaster, m_spellInfo, selectionType, condList, TARGET_OBJECT_TYPE_UNIT); Trinity::UnitListSearcher<Trinity::WorldObjectSpellAreaTargetCheck> searcher(GetDynobjOwner(), units, check); @@ -2521,6 +2526,6 @@ void DynObjAura::FillTargetMap(std::unordered_map<Unit*, uint32>& targets, Unit* units.erase(std::remove_if(units.begin(), units.end(), [this](Unit* unit) { return !unit->IsSelfOrInSameMap(GetDynobjOwner()); }), units.end()); for (Unit* unit : units) - targets[unit] |= 1 << effect->EffectIndex; + targets[unit] |= 1 << spellEffectInfo.EffectIndex; } } diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 66391ecbad2..45b53f6f93b 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -473,9 +473,8 @@ void SpellCastTargets::Update(WorldObject* caster) SpellValue::SpellValue(SpellInfo const* proto, WorldObject const* caster) { memset(EffectBasePoints, 0, sizeof(EffectBasePoints)); - for (SpellEffectInfo const* effect : proto->GetEffects()) - if (effect) - EffectBasePoints[effect->EffectIndex] = effect->CalcBaseValue(caster, nullptr, 0, -1); + for (SpellEffectInfo const& spellEffectInfo : proto->GetEffects()) + EffectBasePoints[spellEffectInfo.EffectIndex] = spellEffectInfo.CalcBaseValue(caster, nullptr, 0, -1); CustomBasePointsMask = 0; MaxAffectedTargets = proto->MaxAffectedTargets; @@ -735,35 +734,32 @@ void Spell::SelectSpellTargets() uint32 processedAreaEffectsMask = 0; - for (SpellEffectInfo const* effect : m_spellInfo->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) { - if (!effect) - continue; - // not call for empty effect. // Also some spells use not used effect targets for store targets for dummy effect in triggered spells - if (!effect->IsEffect()) + if (!spellEffectInfo.IsEffect()) continue; // set expected type of implicit targets to be sent to client - uint32 implicitTargetMask = GetTargetFlagMask(effect->TargetA.GetObjectType()) | GetTargetFlagMask(effect->TargetB.GetObjectType()); + uint32 implicitTargetMask = GetTargetFlagMask(spellEffectInfo.TargetA.GetObjectType()) | GetTargetFlagMask(spellEffectInfo.TargetB.GetObjectType()); if (implicitTargetMask & TARGET_FLAG_UNIT) m_targets.SetTargetFlag(TARGET_FLAG_UNIT); if (implicitTargetMask & (TARGET_FLAG_GAMEOBJECT | TARGET_FLAG_GAMEOBJECT_ITEM)) m_targets.SetTargetFlag(TARGET_FLAG_GAMEOBJECT); - SelectEffectImplicitTargets(SpellEffIndex(effect->EffectIndex), effect->TargetA, processedAreaEffectsMask); - SelectEffectImplicitTargets(SpellEffIndex(effect->EffectIndex), effect->TargetB, processedAreaEffectsMask); + SelectEffectImplicitTargets(spellEffectInfo, spellEffectInfo.TargetA, processedAreaEffectsMask); + SelectEffectImplicitTargets(spellEffectInfo, spellEffectInfo.TargetB, processedAreaEffectsMask); // Select targets of effect based on effect type // those are used when no valid target could be added for spell effect based on spell target type // some spell effects use explicit target as a default target added to target map (like SPELL_EFFECT_LEARN_SPELL) // some spell effects add target to target map only when target type specified (like SPELL_EFFECT_WEAPON) // some spell effects don't add anything to target map (confirmed with sniffs) (like SPELL_EFFECT_DESTROY_ALL_TOTEMS) - SelectEffectTypeImplicitTargets(effect->EffectIndex); + SelectEffectTypeImplicitTargets(spellEffectInfo); if (m_targets.HasDst()) - AddDestTarget(*m_targets.GetDst(), effect->EffectIndex); + AddDestTarget(*m_targets.GetDst(), spellEffectInfo.EffectIndex); if (m_spellInfo->IsChanneled()) { @@ -775,7 +771,7 @@ void Spell::SelectSpellTargets() return; } - uint32 mask = (1 << effect->EffectIndex); + uint32 mask = (1 << spellEffectInfo.EffectIndex); for (auto ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit) { if (ihit->EffectMask & mask) @@ -822,12 +818,12 @@ void Spell::RecalculateDelayMomentForDst() m_caster->m_Events.ModifyEventTime(_spellEvent, GetDelayStart() + m_delayMoment); } -void Spell::SelectEffectImplicitTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, uint32& processedEffectMask) +void Spell::SelectEffectImplicitTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType, uint32& processedEffectMask) { if (!targetType.GetTarget()) return; - uint32 effectMask = 1 << effIndex; + uint32 effectMask = 1 << spellEffectInfo.EffectIndex; // set the same target list for all effects // some spells appear to need this, however this requires more research switch (targetType.GetSelectionCategory()) @@ -836,30 +832,27 @@ void Spell::SelectEffectImplicitTargets(SpellEffIndex effIndex, SpellImplicitTar case TARGET_SELECT_CATEGORY_CONE: case TARGET_SELECT_CATEGORY_AREA: case TARGET_SELECT_CATEGORY_LINE: + { // targets for effect already selected if (effectMask & processedEffectMask) return; - if (SpellEffectInfo const* _effect = m_spellInfo->GetEffect(effIndex)) - { - // choose which targets we can select at once - for (SpellEffectInfo const* effect : m_spellInfo->GetEffects()) + std::vector<SpellEffectInfo> const& effects = GetSpellInfo()->GetEffects(); + // choose which targets we can select at once + for (uint32 j = spellEffectInfo.EffectIndex + 1; j < effects.size(); ++j) + { + if (effects[j].IsEffect() && + spellEffectInfo.TargetA.GetTarget() == effects[j].TargetA.GetTarget() && + spellEffectInfo.TargetB.GetTarget() == effects[j].TargetB.GetTarget() && + spellEffectInfo.ImplicitTargetConditions == effects[j].ImplicitTargetConditions && + spellEffectInfo.CalcRadius(m_caster) == effects[j].CalcRadius(m_caster) && + CheckScriptEffectImplicitTargets(spellEffectInfo.EffectIndex, j)) { - //for (uint32 j = effIndex + 1; j < MAX_SPELL_EFFECTS; ++j) - if (!effect || effect->EffectIndex <= uint32(effIndex)) - continue; - if (effect->IsEffect() && - _effect->TargetA.GetTarget() == effect->TargetA.GetTarget() && - _effect->TargetB.GetTarget() == effect->TargetB.GetTarget() && - _effect->ImplicitTargetConditions == effect->ImplicitTargetConditions && - _effect->CalcRadius(m_caster) == effect->CalcRadius(m_caster) && - CheckScriptEffectImplicitTargets(effIndex, effect->EffectIndex)) - { - effectMask |= 1 << effect->EffectIndex; - } + effectMask |= 1 << j; } } processedEffectMask |= effectMask; break; + } default: break; } @@ -867,25 +860,25 @@ void Spell::SelectEffectImplicitTargets(SpellEffIndex effIndex, SpellImplicitTar switch (targetType.GetSelectionCategory()) { case TARGET_SELECT_CATEGORY_CHANNEL: - SelectImplicitChannelTargets(effIndex, targetType); + SelectImplicitChannelTargets(spellEffectInfo, targetType); break; case TARGET_SELECT_CATEGORY_NEARBY: - SelectImplicitNearbyTargets(effIndex, targetType, effectMask); + SelectImplicitNearbyTargets(spellEffectInfo, targetType, effectMask); break; case TARGET_SELECT_CATEGORY_CONE: - SelectImplicitConeTargets(effIndex, targetType, effectMask); + SelectImplicitConeTargets(spellEffectInfo, targetType, effectMask); break; case TARGET_SELECT_CATEGORY_AREA: - SelectImplicitAreaTargets(effIndex, targetType, effectMask); + SelectImplicitAreaTargets(spellEffectInfo, targetType, effectMask); break; case TARGET_SELECT_CATEGORY_TRAJ: // just in case there is no dest, explanation in SelectImplicitDestDestTargets CheckDst(); - SelectImplicitTrajTargets(effIndex, targetType); + SelectImplicitTrajTargets(spellEffectInfo, targetType); break; case TARGET_SELECT_CATEGORY_LINE: - SelectImplicitLineTargets(effIndex, targetType, effectMask); + SelectImplicitLineTargets(spellEffectInfo, targetType, effectMask); break; case TARGET_SELECT_CATEGORY_DEFAULT: switch (targetType.GetObjectType()) @@ -905,13 +898,13 @@ void Spell::SelectEffectImplicitTargets(SpellEffIndex effIndex, SpellImplicitTar switch (targetType.GetReferenceType()) { case TARGET_REFERENCE_TYPE_CASTER: - SelectImplicitCasterDestTargets(effIndex, targetType); + SelectImplicitCasterDestTargets(spellEffectInfo, targetType); break; case TARGET_REFERENCE_TYPE_TARGET: - SelectImplicitTargetDestTargets(effIndex, targetType); + SelectImplicitTargetDestTargets(spellEffectInfo, targetType); break; case TARGET_REFERENCE_TYPE_DEST: - SelectImplicitDestDestTargets(effIndex, targetType); + SelectImplicitDestDestTargets(spellEffectInfo, targetType); break; default: ASSERT(false && "Spell::SelectEffectImplicitTargets: received not implemented select target reference type for TARGET_TYPE_OBJECT_DEST"); @@ -922,10 +915,10 @@ void Spell::SelectEffectImplicitTargets(SpellEffIndex effIndex, SpellImplicitTar switch (targetType.GetReferenceType()) { case TARGET_REFERENCE_TYPE_CASTER: - SelectImplicitCasterObjectTargets(effIndex, targetType); + SelectImplicitCasterObjectTargets(spellEffectInfo, targetType); break; case TARGET_REFERENCE_TYPE_TARGET: - SelectImplicitTargetObjectTargets(effIndex, targetType); + SelectImplicitTargetObjectTargets(spellEffectInfo, targetType); break; default: ASSERT(false && "Spell::SelectEffectImplicitTargets: received not implemented select target reference type for TARGET_TYPE_OBJECT"); @@ -935,7 +928,7 @@ void Spell::SelectEffectImplicitTargets(SpellEffIndex effIndex, SpellImplicitTar } break; case TARGET_SELECT_CATEGORY_NYI: - TC_LOG_DEBUG("spells", "SPELL: target type %u, found in spellID %u, effect %u is not implemented yet!", m_spellInfo->Id, effIndex, targetType.GetTarget()); + TC_LOG_DEBUG("spells", "SPELL: target type %u, found in spellID %u, effect %u is not implemented yet!", m_spellInfo->Id, uint32(spellEffectInfo.EffectIndex), targetType.GetTarget()); break; default: ASSERT(false && "Spell::SelectEffectImplicitTargets: received not implemented select target category"); @@ -943,7 +936,7 @@ void Spell::SelectEffectImplicitTargets(SpellEffIndex effIndex, SpellImplicitTar } } -void Spell::SelectImplicitChannelTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType) +void Spell::SelectImplicitChannelTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType) { if (targetType.GetReferenceType() != TARGET_REFERENCE_TYPE_CASTER) { @@ -954,7 +947,7 @@ void Spell::SelectImplicitChannelTargets(SpellEffIndex effIndex, SpellImplicitTa Spell* channeledSpell = m_originalCaster->GetCurrentSpell(CURRENT_CHANNELED_SPELL); if (!channeledSpell) { - TC_LOG_DEBUG("spells", "Spell::SelectImplicitChannelTargets: cannot find channel spell for spell ID %u, effect %u", m_spellInfo->Id, effIndex); + TC_LOG_DEBUG("spells", "Spell::SelectImplicitChannelTargets: cannot find channel spell for spell ID %u, effect %u", m_spellInfo->Id, uint32(spellEffectInfo.EffectIndex)); return; } switch (targetType.GetTarget()) @@ -964,13 +957,13 @@ void Spell::SelectImplicitChannelTargets(SpellEffIndex effIndex, SpellImplicitTa for (ObjectGuid const& channelTarget : m_originalCaster->m_unitData->ChannelObjects) { WorldObject* target = ObjectAccessor::GetUnit(*m_caster, channelTarget); - CallScriptObjectTargetSelectHandlers(target, effIndex, targetType); + CallScriptObjectTargetSelectHandlers(target, spellEffectInfo.EffectIndex, targetType); // unit target may be no longer avalible - teleported out of map for example Unit* unitTarget = target ? target->ToUnit() : nullptr; if (unitTarget) - AddUnitTarget(unitTarget, 1 << effIndex); + AddUnitTarget(unitTarget, 1 << spellEffectInfo.EffectIndex); else - TC_LOG_DEBUG("spells", "SPELL: cannot find channel spell target for spell ID %u, effect %u", m_spellInfo->Id, effIndex); + TC_LOG_DEBUG("spells", "SPELL: cannot find channel spell target for spell ID %u, effect %u", m_spellInfo->Id, uint32(spellEffectInfo.EffectIndex)); } break; } @@ -983,22 +976,22 @@ void Spell::SelectImplicitChannelTargets(SpellEffIndex effIndex, SpellImplicitTa WorldObject* target = !channelObjects.empty() ? ObjectAccessor::GetWorldObject(*m_caster, *channelObjects.begin()) : nullptr; if (target) { - CallScriptObjectTargetSelectHandlers(target, effIndex, targetType); + CallScriptObjectTargetSelectHandlers(target, spellEffectInfo.EffectIndex, targetType); if (target) { SpellDestination dest(*target); - CallScriptDestinationTargetSelectHandlers(dest, effIndex, targetType); + CallScriptDestinationTargetSelectHandlers(dest, spellEffectInfo.EffectIndex, targetType); m_targets.SetDst(dest); } } else - TC_LOG_DEBUG("spells", "SPELL: cannot find channel spell destination for spell ID %u, effect %u", m_spellInfo->Id, effIndex); + TC_LOG_DEBUG("spells", "SPELL: cannot find channel spell destination for spell ID %u, effect %u", m_spellInfo->Id, uint32(spellEffectInfo.EffectIndex)); } break; case TARGET_DEST_CHANNEL_CASTER: { SpellDestination dest(*channeledSpell->GetCaster()); - CallScriptDestinationTargetSelectHandlers(dest, effIndex, targetType); + CallScriptDestinationTargetSelectHandlers(dest, spellEffectInfo.EffectIndex, targetType); m_targets.SetDst(dest); break; } @@ -1008,7 +1001,7 @@ void Spell::SelectImplicitChannelTargets(SpellEffIndex effIndex, SpellImplicitTa } } -void Spell::SelectImplicitNearbyTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, uint32 effMask) +void Spell::SelectImplicitNearbyTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType, uint32 effMask) { if (targetType.GetReferenceType() != TARGET_REFERENCE_TYPE_CASTER) { @@ -1016,10 +1009,6 @@ void Spell::SelectImplicitNearbyTargets(SpellEffIndex effIndex, SpellImplicitTar return; } - SpellEffectInfo const* effect = m_spellInfo->GetEffect(effIndex); - if (!effect) - return; - float range = 0.0f; switch (targetType.GetCheckType()) { @@ -1041,12 +1030,12 @@ void Spell::SelectImplicitNearbyTargets(SpellEffIndex effIndex, SpellImplicitTar break; } - ConditionContainer* condList = effect->ImplicitTargetConditions; + ConditionContainer* condList = spellEffectInfo.ImplicitTargetConditions; // handle emergency case - try to use other provided targets if no conditions provided if (targetType.GetCheckType() == TARGET_CHECK_ENTRY && (!condList || condList->empty())) { - TC_LOG_DEBUG("spells", "Spell::SelectImplicitNearbyTargets: no conditions entry for target with TARGET_CHECK_ENTRY of spell ID %u, effect %u - selecting default targets", m_spellInfo->Id, effIndex); + TC_LOG_DEBUG("spells", "Spell::SelectImplicitNearbyTargets: no conditions entry for target with TARGET_CHECK_ENTRY of spell ID %u, effect %u - selecting default targets", m_spellInfo->Id, uint32(spellEffectInfo.EffectIndex)); switch (targetType.GetObjectType()) { case TARGET_OBJECT_TYPE_GOBJ: @@ -1068,7 +1057,7 @@ void Spell::SelectImplicitNearbyTargets(SpellEffIndex effIndex, SpellImplicitTar if (focusObject) { SpellDestination dest(*focusObject); - CallScriptDestinationTargetSelectHandlers(dest, effIndex, targetType); + CallScriptDestinationTargetSelectHandlers(dest, spellEffectInfo.EffectIndex, targetType); m_targets.SetDst(dest); } else @@ -1087,16 +1076,16 @@ void Spell::SelectImplicitNearbyTargets(SpellEffIndex effIndex, SpellImplicitTar WorldObject* target = SearchNearbyTarget(range, targetType.GetObjectType(), targetType.GetCheckType(), condList); if (!target) { - TC_LOG_DEBUG("spells", "Spell::SelectImplicitNearbyTargets: cannot find nearby target for spell ID %u, effect %u", m_spellInfo->Id, effIndex); + TC_LOG_DEBUG("spells", "Spell::SelectImplicitNearbyTargets: cannot find nearby target for spell ID %u, effect %u", m_spellInfo->Id, uint32(spellEffectInfo.EffectIndex)); SendCastResult(SPELL_FAILED_BAD_IMPLICIT_TARGETS); finish(false); return; } - CallScriptObjectTargetSelectHandlers(target, effIndex, targetType); + CallScriptObjectTargetSelectHandlers(target, spellEffectInfo.EffectIndex, targetType); if (!target) { - TC_LOG_DEBUG("spells", "Spell::SelectImplicitNearbyTargets: OnObjectTargetSelect script hook for spell Id %u set NULL target, effect %u", m_spellInfo->Id, effIndex); + TC_LOG_DEBUG("spells", "Spell::SelectImplicitNearbyTargets: OnObjectTargetSelect script hook for spell Id %u set NULL target, effect %u", m_spellInfo->Id, uint32(spellEffectInfo.EffectIndex)); SendCastResult(SPELL_FAILED_BAD_IMPLICIT_TARGETS); finish(false); return; @@ -1129,7 +1118,7 @@ void Spell::SelectImplicitNearbyTargets(SpellEffIndex effIndex, SpellImplicitTar case TARGET_OBJECT_TYPE_DEST: { SpellDestination dest(*target); - CallScriptDestinationTargetSelectHandlers(dest, effIndex, targetType); + CallScriptDestinationTargetSelectHandlers(dest, spellEffectInfo.EffectIndex, targetType); m_targets.SetDst(dest); break; } @@ -1138,10 +1127,10 @@ void Spell::SelectImplicitNearbyTargets(SpellEffIndex effIndex, SpellImplicitTar break; } - SelectImplicitChainTargets(effIndex, targetType, target, effMask); + SelectImplicitChainTargets(spellEffectInfo, targetType, target, effMask); } -void Spell::SelectImplicitConeTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, uint32 effMask) +void Spell::SelectImplicitConeTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType, uint32 effMask) { if (targetType.GetReferenceType() != TARGET_REFERENCE_TYPE_CASTER) { @@ -1151,12 +1140,8 @@ void Spell::SelectImplicitConeTargets(SpellEffIndex effIndex, SpellImplicitTarge std::list<WorldObject*> targets; SpellTargetObjectTypes objectType = targetType.GetObjectType(); SpellTargetCheckTypes selectionType = targetType.GetCheckType(); - SpellEffectInfo const* effect = m_spellInfo->GetEffect(effIndex); - if (!effect) - return; - - ConditionContainer* condList = effect->ImplicitTargetConditions; - float radius = effect->CalcRadius(m_caster) * m_spellValue->RadiusMod; + ConditionContainer* condList = spellEffectInfo.ImplicitTargetConditions; + float radius = spellEffectInfo.CalcRadius(m_caster) * m_spellValue->RadiusMod; if (uint32 containerTypeMask = GetSearcherTypeMask(objectType, condList)) { @@ -1164,7 +1149,7 @@ void Spell::SelectImplicitConeTargets(SpellEffIndex effIndex, SpellImplicitTarge Trinity::WorldObjectListSearcher<Trinity::WorldObjectSpellConeTargetCheck> searcher(m_caster, targets, check, containerTypeMask); SearchTargets<Trinity::WorldObjectListSearcher<Trinity::WorldObjectSpellConeTargetCheck> >(searcher, containerTypeMask, m_caster, m_caster, radius); - CallScriptObjectAreaTargetSelectHandlers(targets, effIndex, targetType); + CallScriptObjectAreaTargetSelectHandlers(targets, spellEffectInfo.EffectIndex, targetType); if (!targets.empty()) { @@ -1183,7 +1168,7 @@ void Spell::SelectImplicitConeTargets(SpellEffIndex effIndex, SpellImplicitTarge } } -void Spell::SelectImplicitAreaTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, uint32 effMask) +void Spell::SelectImplicitAreaTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType, uint32 effMask) { WorldObject* referer = nullptr; switch (targetType.GetReferenceType()) @@ -1201,7 +1186,7 @@ void Spell::SelectImplicitAreaTargets(SpellEffIndex effIndex, SpellImplicitTarge // find last added target for this effect for (auto ihit = m_UniqueTargetInfo.rbegin(); ihit != m_UniqueTargetInfo.rend(); ++ihit) { - if (ihit->EffectMask & (1 << effIndex)) + if (ihit->EffectMask & (1 << spellEffectInfo.EffectIndex)) { referer = ObjectAccessor::GetUnit(*m_caster, ihit->TargetGUID); break; @@ -1237,10 +1222,6 @@ void Spell::SelectImplicitAreaTargets(SpellEffIndex effIndex, SpellImplicitTarge } std::list<WorldObject*> targets; - SpellEffectInfo const* effect = m_spellInfo->GetEffect(effIndex); - if (!effect) - return; - switch (targetType.GetTarget()) { case TARGET_UNIT_TARGET_ALLY_OR_RAID: @@ -1250,7 +1231,7 @@ void Spell::SelectImplicitAreaTargets(SpellEffIndex effIndex, SpellImplicitTarge { targets.push_back(m_targets.GetUnitTarget()); - CallScriptObjectAreaTargetSelectHandlers(targets, effIndex, targetType); + CallScriptObjectAreaTargetSelectHandlers(targets, spellEffectInfo.EffectIndex, targetType); if (!targets.empty()) { @@ -1280,11 +1261,11 @@ void Spell::SelectImplicitAreaTargets(SpellEffIndex effIndex, SpellImplicitTarge break; } - float radius = effect->CalcRadius(m_caster) * m_spellValue->RadiusMod; + float radius = spellEffectInfo.CalcRadius(m_caster) * m_spellValue->RadiusMod; - SearchAreaTargets(targets, radius, center, referer, targetType.GetObjectType(), targetType.GetCheckType(), effect->ImplicitTargetConditions); + SearchAreaTargets(targets, radius, center, referer, targetType.GetObjectType(), targetType.GetCheckType(), spellEffectInfo.ImplicitTargetConditions); - CallScriptObjectAreaTargetSelectHandlers(targets, effIndex, targetType); + CallScriptObjectAreaTargetSelectHandlers(targets, spellEffectInfo.EffectIndex, targetType); if (!targets.empty()) { @@ -1302,7 +1283,7 @@ void Spell::SelectImplicitAreaTargets(SpellEffIndex effIndex, SpellImplicitTarge } } -void Spell::SelectImplicitCasterDestTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType) +void Spell::SelectImplicitCasterDestTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType) { SpellDestination dest(*m_caster); @@ -1315,7 +1296,7 @@ void Spell::SelectImplicitCasterDestTargets(SpellEffIndex effIndex, SpellImplici dest = SpellDestination(playerCaster->m_homebindX, playerCaster->m_homebindY, playerCaster->m_homebindZ, playerCaster->GetOrientation(), playerCaster->m_homebindMapId); break; case TARGET_DEST_DB: - if (SpellTargetPosition const* st = sSpellMgr->GetSpellTargetPosition(m_spellInfo->Id, effIndex)) + if (SpellTargetPosition const* st = sSpellMgr->GetSpellTargetPosition(m_spellInfo->Id, spellEffectInfo.EffectIndex)) { /// @todo fix this check if (m_spellInfo->HasEffect(SPELL_EFFECT_TELEPORT_UNITS) || m_spellInfo->HasEffect(SPELL_EFFECT_BIND)) @@ -1370,7 +1351,7 @@ void Spell::SelectImplicitCasterDestTargets(SpellEffIndex effIndex, SpellImplici if (!unitCaster) break; - float dist = m_spellInfo->GetEffect(effIndex)->CalcRadius(unitCaster); + float dist = spellEffectInfo.CalcRadius(unitCaster); float angle = targetType.CalcDirectionAngle(); Position pos = dest._position; @@ -1405,52 +1386,49 @@ void Spell::SelectImplicitCasterDestTargets(SpellEffIndex effIndex, SpellImplici break; default: { - if (SpellEffectInfo const* effect = m_spellInfo->GetEffect(effIndex)) - { - float dist = effect->CalcRadius(m_caster); - float angle = targetType.CalcDirectionAngle(); - float objSize = m_caster->GetCombatReach(); + float dist = spellEffectInfo.CalcRadius(m_caster); + float angle = targetType.CalcDirectionAngle(); + float objSize = m_caster->GetCombatReach(); - switch (targetType.GetTarget()) + switch (targetType.GetTarget()) + { + case TARGET_DEST_CASTER_SUMMON: + dist = PET_FOLLOW_DIST; + break; + case TARGET_DEST_CASTER_RANDOM: + if (dist > objSize) + dist = objSize + (dist - objSize) * float(rand_norm()); + break; + case TARGET_DEST_CASTER_FRONT_LEFT: + case TARGET_DEST_CASTER_BACK_LEFT: + case TARGET_DEST_CASTER_FRONT_RIGHT: + case TARGET_DEST_CASTER_BACK_RIGHT: { - case TARGET_DEST_CASTER_SUMMON: - dist = PET_FOLLOW_DIST; - break; - case TARGET_DEST_CASTER_RANDOM: - if (dist > objSize) - dist = objSize + (dist - objSize) * float(rand_norm()); - break; - case TARGET_DEST_CASTER_FRONT_LEFT: - case TARGET_DEST_CASTER_BACK_LEFT: - case TARGET_DEST_CASTER_FRONT_RIGHT: - case TARGET_DEST_CASTER_BACK_RIGHT: - { - static float const DefaultTotemDistance = 3.0f; - if (!effect->HasRadius() && !effect->HasMaxRadius()) - dist = DefaultTotemDistance; - break; - } - default: - break; + static float const DefaultTotemDistance = 3.0f; + if (!spellEffectInfo.HasRadius() && !spellEffectInfo.HasMaxRadius()) + dist = DefaultTotemDistance; + break; } + default: + break; + } - if (dist < objSize) - dist = objSize; + if (dist < objSize) + dist = objSize; - Position pos = dest._position; - m_caster->MovePositionToFirstCollision(pos, dist, angle); + Position pos = dest._position; + m_caster->MovePositionToFirstCollision(pos, dist, angle); - dest.Relocate(pos); - } + dest.Relocate(pos); break; } } - CallScriptDestinationTargetSelectHandlers(dest, effIndex, targetType); + CallScriptDestinationTargetSelectHandlers(dest, spellEffectInfo.EffectIndex, targetType); m_targets.SetDst(dest); } -void Spell::SelectImplicitTargetDestTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType) +void Spell::SelectImplicitTargetDestTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType) { ASSERT(m_targets.GetObjectTarget() && "Spell::SelectImplicitTargetDestTargets - no explicit object target available!"); WorldObject* target = m_targets.GetObjectTarget(); @@ -1465,27 +1443,24 @@ void Spell::SelectImplicitTargetDestTargets(SpellEffIndex effIndex, SpellImplici break; default: { - if (SpellEffectInfo const* effect = m_spellInfo->GetEffect(effIndex)) - { - float angle = targetType.CalcDirectionAngle(); - float dist = effect->CalcRadius(nullptr); - if (targetType.GetTarget() == TARGET_DEST_TARGET_RANDOM) - dist *= float(rand_norm()); + float angle = targetType.CalcDirectionAngle(); + float dist = spellEffectInfo.CalcRadius(nullptr); + if (targetType.GetTarget() == TARGET_DEST_TARGET_RANDOM) + dist *= float(rand_norm()); - Position pos = dest._position; - target->MovePositionToFirstCollision(pos, dist, angle); + Position pos = dest._position; + target->MovePositionToFirstCollision(pos, dist, angle); - dest.Relocate(pos); - } + dest.Relocate(pos); break; } } - CallScriptDestinationTargetSelectHandlers(dest, effIndex, targetType); + CallScriptDestinationTargetSelectHandlers(dest, spellEffectInfo.EffectIndex, targetType); m_targets.SetDst(dest); } -void Spell::SelectImplicitDestDestTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType) +void Spell::SelectImplicitDestDestTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType) { // set destination to caster if no dest provided // can only happen if previous destination target could not be set for some reason @@ -1504,27 +1479,24 @@ void Spell::SelectImplicitDestDestTargets(SpellEffIndex effIndex, SpellImplicitT return; default: { - if (SpellEffectInfo const* effect = m_spellInfo->GetEffect(effIndex)) - { - float angle = targetType.CalcDirectionAngle(); - float dist = effect->CalcRadius(m_caster); - if (targetType.GetTarget() == TARGET_DEST_DEST_RANDOM) - dist *= float(rand_norm()); + float angle = targetType.CalcDirectionAngle(); + float dist = spellEffectInfo.CalcRadius(m_caster); + if (targetType.GetTarget() == TARGET_DEST_DEST_RANDOM) + dist *= float(rand_norm()); - Position pos = dest._position; - m_caster->MovePositionToFirstCollision(pos, dist, angle); + Position pos = dest._position; + m_caster->MovePositionToFirstCollision(pos, dist, angle); - dest.Relocate(pos); - } + dest.Relocate(pos); break; } } - CallScriptDestinationTargetSelectHandlers(dest, effIndex, targetType); + CallScriptDestinationTargetSelectHandlers(dest, spellEffectInfo.EffectIndex, targetType); m_targets.ModDst(dest); } -void Spell::SelectImplicitCasterObjectTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType) +void Spell::SelectImplicitCasterObjectTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType) { WorldObject* target = nullptr; bool checkIfValid = true; @@ -1571,63 +1543,59 @@ void Spell::SelectImplicitCasterObjectTargets(SpellEffIndex effIndex, SpellImpli break; } - CallScriptObjectTargetSelectHandlers(target, effIndex, targetType); + CallScriptObjectTargetSelectHandlers(target, spellEffectInfo.EffectIndex, targetType); if (target) { if (Unit* unit = target->ToUnit()) - AddUnitTarget(unit, 1 << effIndex, checkIfValid); + AddUnitTarget(unit, 1 << spellEffectInfo.EffectIndex, checkIfValid); else if (GameObject* go = target->ToGameObject()) - AddGOTarget(go, 1 << effIndex); + AddGOTarget(go, 1 << spellEffectInfo.EffectIndex); } } -void Spell::SelectImplicitTargetObjectTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType) +void Spell::SelectImplicitTargetObjectTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType) { ASSERT((m_targets.GetObjectTarget() || m_targets.GetItemTarget()) && "Spell::SelectImplicitTargetObjectTargets - no explicit object or item target available!"); WorldObject* target = m_targets.GetObjectTarget(); - CallScriptObjectTargetSelectHandlers(target, effIndex, targetType); + CallScriptObjectTargetSelectHandlers(target, spellEffectInfo.EffectIndex, targetType); if (target) { if (Unit* unit = target->ToUnit()) - AddUnitTarget(unit, 1 << effIndex, true, false); + AddUnitTarget(unit, 1 << spellEffectInfo.EffectIndex, true, false); else if (GameObject* gobj = target->ToGameObject()) - AddGOTarget(gobj, 1 << effIndex); + AddGOTarget(gobj, 1 << spellEffectInfo.EffectIndex); - SelectImplicitChainTargets(effIndex, targetType, target, 1 << effIndex); + SelectImplicitChainTargets(spellEffectInfo, targetType, target, 1 << spellEffectInfo.EffectIndex); } // Script hook can remove object target and we would wrongly land here else if (Item* item = m_targets.GetItemTarget()) - AddItemTarget(item, 1 << effIndex); + AddItemTarget(item, 1 << spellEffectInfo.EffectIndex); } -void Spell::SelectImplicitChainTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, WorldObject* target, uint32 effMask) +void Spell::SelectImplicitChainTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType, WorldObject* target, uint32 effMask) { - SpellEffectInfo const* effect = m_spellInfo->GetEffect(effIndex); - if (!effect) - return; - - int32 maxTargets = effect->ChainTargets; + int32 maxTargets = spellEffectInfo.ChainTargets; if (Player* modOwner = m_caster->GetSpellModOwner()) modOwner->ApplySpellMod(m_spellInfo, SpellModOp::ChainTargets, maxTargets, this); if (maxTargets > 1) { // mark damage multipliers as used - for (SpellEffectInfo const* eff : m_spellInfo->GetEffects()) - if (eff && (effMask & (1 << eff->EffectIndex))) - m_damageMultipliers[eff->EffectIndex] = 1.0f; + for (size_t k = spellEffectInfo.EffectIndex; k < m_spellInfo->GetEffects().size(); ++k) + if (effMask & (1 << k)) + m_damageMultipliers[k] = 1.0f; m_applyMultiplierMask |= effMask; std::list<WorldObject*> targets; SearchChainTargets(targets, maxTargets - 1, target, targetType.GetObjectType(), targetType.GetCheckType() - , effect->ImplicitTargetConditions, targetType.GetTarget() == TARGET_UNIT_TARGET_CHAINHEAL_ALLY); + , spellEffectInfo.ImplicitTargetConditions, targetType.GetTarget() == TARGET_UNIT_TARGET_CHAINHEAL_ALLY); // Chain primary target is added earlier - CallScriptObjectAreaTargetSelectHandlers(targets, effIndex, targetType); + CallScriptObjectAreaTargetSelectHandlers(targets, spellEffectInfo.EffectIndex, targetType); for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end(); ++itr) if (Unit* unit = (*itr)->ToUnit()) @@ -1647,7 +1615,7 @@ float tangent(float x) return 0.0f; } -void Spell::SelectImplicitTrajTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType) +void Spell::SelectImplicitTrajTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType) { if (!m_targets.HasTraj()) return; @@ -1660,9 +1628,8 @@ void Spell::SelectImplicitTrajTargets(SpellEffIndex effIndex, SpellImplicitTarge srcPos.SetOrientation(m_caster->GetOrientation()); float srcToDestDelta = m_targets.GetDstPos()->m_positionZ - srcPos.m_positionZ; - SpellEffectInfo const* effect = m_spellInfo->GetEffect(effIndex); std::list<WorldObject*> targets; - Trinity::WorldObjectSpellTrajTargetCheck check(dist2d, &srcPos, m_caster, m_spellInfo, targetType.GetCheckType(), effect->ImplicitTargetConditions, TARGET_OBJECT_TYPE_NONE); + Trinity::WorldObjectSpellTrajTargetCheck check(dist2d, &srcPos, m_caster, m_spellInfo, targetType.GetCheckType(), spellEffectInfo.ImplicitTargetConditions, TARGET_OBJECT_TYPE_NONE); Trinity::WorldObjectListSearcher<Trinity::WorldObjectSpellTrajTargetCheck> searcher(m_caster, targets, check, GRID_MAP_TYPE_MASK_ALL); SearchTargets<Trinity::WorldObjectListSearcher<Trinity::WorldObjectSpellTrajTargetCheck> > (searcher, GRID_MAP_TYPE_MASK_ALL, m_caster, &srcPos, dist2d); if (targets.empty()) @@ -1678,7 +1645,7 @@ void Spell::SelectImplicitTrajTargets(SpellEffIndex effIndex, SpellImplicitTarge // We should check if triggered spell has greater range (which is true in many cases, and initial spell has too short max range) // limit max range to 300 yards, sometimes triggered spells can have 50000yds float bestDist = m_spellInfo->GetMaxRange(false); - if (SpellInfo const* triggerSpellInfo = sSpellMgr->GetSpellInfo(effect->TriggerSpell, GetCastDifficulty())) + if (SpellInfo const* triggerSpellInfo = sSpellMgr->GetSpellInfo(spellEffectInfo.TriggerSpell, GetCastDifficulty())) bestDist = std::min(std::max(bestDist, triggerSpellInfo->GetMaxRange(false)), std::min(dist2d, 300.0f)); // GameObjects don't cast traj @@ -1726,20 +1693,16 @@ void Spell::SelectImplicitTrajTargets(SpellEffIndex effIndex, SpellImplicitTarge float z = m_targets.GetSrcPos()->m_positionZ + bestDist * (a * bestDist + b); SpellDestination dest(x, y, z, unitCaster->GetOrientation()); - CallScriptDestinationTargetSelectHandlers(dest, effIndex, targetType); + CallScriptDestinationTargetSelectHandlers(dest, spellEffectInfo.EffectIndex, targetType); m_targets.ModDst(dest); } } -void Spell::SelectImplicitLineTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, uint32 effMask) +void Spell::SelectImplicitLineTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType, uint32 effMask) { std::list<WorldObject*> targets; SpellTargetObjectTypes objectType = targetType.GetObjectType(); SpellTargetCheckTypes selectionType = targetType.GetCheckType(); - SpellEffectInfo const* effect = m_spellInfo->GetEffect(effIndex); - if (!effect) - return; - Position const* dst = nullptr; switch (targetType.GetReferenceType()) { @@ -1760,8 +1723,8 @@ void Spell::SelectImplicitLineTargets(SpellEffIndex effIndex, SpellImplicitTarge return; } - ConditionContainer* condList = effect->ImplicitTargetConditions; - float radius = effect->CalcRadius(m_caster) * m_spellValue->RadiusMod; + ConditionContainer* condList = spellEffectInfo.ImplicitTargetConditions; + float radius = spellEffectInfo.CalcRadius(m_caster) * m_spellValue->RadiusMod; if (uint32 containerTypeMask = GetSearcherTypeMask(objectType, condList)) { @@ -1769,7 +1732,7 @@ void Spell::SelectImplicitLineTargets(SpellEffIndex effIndex, SpellImplicitTarge Trinity::WorldObjectListSearcher<Trinity::WorldObjectSpellLineTargetCheck> searcher(m_caster, targets, check, containerTypeMask); SearchTargets<Trinity::WorldObjectListSearcher<Trinity::WorldObjectSpellLineTargetCheck>>(searcher, containerTypeMask, m_caster, m_caster, radius); - CallScriptObjectAreaTargetSelectHandlers(targets, effIndex, targetType); + CallScriptObjectAreaTargetSelectHandlers(targets, spellEffectInfo.EffectIndex, targetType); if (!targets.empty()) { @@ -1794,20 +1757,17 @@ void Spell::SelectImplicitLineTargets(SpellEffIndex effIndex, SpellImplicitTarge } } -void Spell::SelectEffectTypeImplicitTargets(uint32 effIndex) +void Spell::SelectEffectTypeImplicitTargets(SpellEffectInfo const& spellEffectInfo) { // special case for SPELL_EFFECT_SUMMON_RAF_FRIEND and SPELL_EFFECT_SUMMON_PLAYER, queue them on map for later execution - SpellEffectInfo const* effect = m_spellInfo->GetEffect(effIndex); - if (!effect) - return; - switch (effect->Effect) + switch (spellEffectInfo.Effect) { case SPELL_EFFECT_SUMMON_RAF_FRIEND: case SPELL_EFFECT_SUMMON_PLAYER: if (m_caster->GetTypeId() == TYPEID_PLAYER && !m_caster->ToPlayer()->GetTarget().IsEmpty()) { WorldObject* target = ObjectAccessor::FindPlayer(m_caster->ToPlayer()->GetTarget()); - CallScriptObjectTargetSelectHandlers(target, SpellEffIndex(effIndex), SpellImplicitTargetInfo()); + CallScriptObjectTargetSelectHandlers(target, spellEffectInfo.EffectIndex, SpellImplicitTargetInfo()); // scripts may modify the target - recheck if (target && target->GetTypeId() == TYPEID_PLAYER) @@ -1816,21 +1776,21 @@ void Spell::SelectEffectTypeImplicitTargets(uint32 effIndex) // since we're completely skipping AddUnitTarget logic, we need to check immunity manually // eg. aura 21546 makes target immune to summons Player* player = target->ToPlayer(); - if (player->IsImmunedToSpellEffect(m_spellInfo, effIndex, nullptr)) + if (player->IsImmunedToSpellEffect(m_spellInfo, spellEffectInfo, nullptr)) return; - target->GetMap()->AddFarSpellCallback(std::bind([](Map* map, Spell* spell, uint8 effIndex, ObjectGuid const& targetGuid) + target->GetMap()->AddFarSpellCallback([spell = this, &spellEffectInfo, targetGuid = target->GetGUID()](Map* map) { Player* player = ObjectAccessor::GetPlayer(map, targetGuid); if (!player) return; // check immunity again in case it changed during update - if (player->IsImmunedToSpellEffect(spell->GetSpellInfo(), effIndex, nullptr)) + if (player->IsImmunedToSpellEffect(spell->GetSpellInfo(), spellEffectInfo, nullptr)) return; - spell->HandleEffects(player, nullptr, nullptr, effIndex, SPELL_EFFECT_HANDLE_HIT_TARGET); - }, std::placeholders::_1, this, effIndex, target->GetGUID())); + spell->HandleEffects(player, nullptr, nullptr, spellEffectInfo, SPELL_EFFECT_HANDLE_HIT_TARGET); + }); } } return; @@ -1839,17 +1799,17 @@ void Spell::SelectEffectTypeImplicitTargets(uint32 effIndex) } // select spell implicit targets based on effect type - if (!effect->GetImplicitTargetType()) + if (!spellEffectInfo.GetImplicitTargetType()) return; - uint32 targetMask = effect->GetMissingTargetMask(); + uint32 targetMask = spellEffectInfo.GetMissingTargetMask(); if (!targetMask) return; WorldObject* target = nullptr; - switch (effect->GetImplicitTargetType()) + switch (spellEffectInfo.GetImplicitTargetType()) { // add explicit object target or self to the target map case EFFECT_IMPLICIT_TARGET_EXPLICIT: @@ -1873,7 +1833,7 @@ void Spell::SelectEffectTypeImplicitTargets(uint32 effIndex) if (targetMask & TARGET_FLAG_ITEM_MASK) { if (Item* item = m_targets.GetItemTarget()) - AddItemTarget(item, 1 << effIndex); + AddItemTarget(item, 1 << spellEffectInfo.EffectIndex); return; } if (targetMask & TARGET_FLAG_GAMEOBJECT_MASK) @@ -1888,14 +1848,14 @@ void Spell::SelectEffectTypeImplicitTargets(uint32 effIndex) break; } - CallScriptObjectTargetSelectHandlers(target, SpellEffIndex(effIndex), SpellImplicitTargetInfo()); + CallScriptObjectTargetSelectHandlers(target, spellEffectInfo.EffectIndex, SpellImplicitTargetInfo()); if (target) { if (target->ToUnit()) - AddUnitTarget(target->ToUnit(), 1 << effIndex, false); + AddUnitTarget(target->ToUnit(), 1 << spellEffectInfo.EffectIndex, false); else if (target->ToGameObject()) - AddGOTarget(target->ToGameObject(), 1 << effIndex); + AddGOTarget(target->ToGameObject(), 1 << spellEffectInfo.EffectIndex); } } @@ -2193,12 +2153,9 @@ class ProcReflectDelayed : public BasicEvent void Spell::AddUnitTarget(Unit* target, uint32 effectMask, bool checkIfValid /*= true*/, bool implicit /*= true*/, Position const* losPosition /*= nullptr*/) { - uint32 validEffectMask = 0; - for (SpellEffectInfo const* effect : m_spellInfo->GetEffects()) - if (effect && (effectMask & (1 << effect->EffectIndex)) != 0 && CheckEffectTarget(target, effect, losPosition)) - validEffectMask |= 1 << effect->EffectIndex; - - effectMask &= validEffectMask; + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) + if (!spellEffectInfo.IsEffect() || !CheckEffectTarget(target, spellEffectInfo, losPosition)) + effectMask &= ~(1 << spellEffectInfo.EffectIndex); // no effects left if (!effectMask) @@ -2209,9 +2166,9 @@ void Spell::AddUnitTarget(Unit* target, uint32 effectMask, bool checkIfValid /*= return; // Check for effect immune skip if immuned - for (SpellEffectInfo const* effect : m_spellInfo->GetEffects()) - if (effect && target->IsImmunedToSpellEffect(m_spellInfo, effect->EffectIndex, m_caster)) - effectMask &= ~(1 << effect->EffectIndex); + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) + if (target->IsImmunedToSpellEffect(m_spellInfo, spellEffectInfo, m_caster)) + effectMask &= ~(1 << spellEffectInfo.EffectIndex); ObjectGuid targetGUID = target->GetGUID(); @@ -2285,12 +2242,9 @@ void Spell::AddUnitTarget(Unit* target, uint32 effectMask, bool checkIfValid /*= void Spell::AddGOTarget(GameObject* go, uint32 effectMask) { - uint32 validEffectMask = 0; - for (SpellEffectInfo const* effect : m_spellInfo->GetEffects()) - if (effect && (effectMask & (1 << effect->EffectIndex)) != 0 && CheckEffectTarget(go, effect)) - validEffectMask |= 1 << effect->EffectIndex; - - effectMask &= validEffectMask; + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) + if (!spellEffectInfo.IsEffect() || !CheckEffectTarget(go, spellEffectInfo)) + effectMask &= ~(1 << spellEffectInfo.EffectIndex); // no effects left if (!effectMask) @@ -2341,12 +2295,9 @@ void Spell::AddGOTarget(GameObject* go, uint32 effectMask) void Spell::AddItemTarget(Item* item, uint32 effectMask) { - uint32 validEffectMask = 0; - for (SpellEffectInfo const* effect : m_spellInfo->GetEffects()) - if (effect && (effectMask & (1 << effect->EffectIndex)) != 0 && CheckEffectTarget(item, effect)) - validEffectMask |= 1 << effect->EffectIndex; - - effectMask &= validEffectMask; + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) + if (!spellEffectInfo.IsEffect() || !CheckEffectTarget(item, spellEffectInfo)) + effectMask &= ~(1 << spellEffectInfo.EffectIndex); // no effects left if (!effectMask) @@ -2442,7 +2393,7 @@ void Spell::TargetInfo::PreprocessTarget(Spell* spell) Healing = spell->m_healing; } -void Spell::TargetInfo::DoTargetSpellHit(Spell* spell, uint8 effIndex) +void Spell::TargetInfo::DoTargetSpellHit(Spell* spell, SpellEffectInfo const& spellEffectInfo) { Unit* unit = spell->m_caster->GetGUID() == TargetGUID ? spell->m_caster->ToUnit() : ObjectAccessor::GetUnit(*spell->m_caster, TargetGUID); if (!unit) @@ -2464,7 +2415,7 @@ void Spell::TargetInfo::DoTargetSpellHit(Spell* spell, uint8 effIndex) return; // No missinfo in that case if (_spellHitTarget) - spell->DoSpellEffectHit(_spellHitTarget, effIndex, *this); + spell->DoSpellEffectHit(_spellHitTarget, spellEffectInfo, *this); // scripts can modify damage/healing for current target, save them Damage = spell->m_damage; @@ -2510,7 +2461,7 @@ void Spell::TargetInfo::DoDamageAndTriggers(Spell* spell) positive = false; else if (!spell->m_healing) { - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (uint8 i = 0; i < spell->m_spellInfo->GetEffects().size(); ++i) { // in case of immunity, check all effects to choose correct procFlags, as none has technically hit if (EffectMask && !(EffectMask & (1 << i))) @@ -2704,7 +2655,7 @@ void Spell::TargetInfo::DoDamageAndTriggers(Spell* spell) spell->CallScriptAfterHitHandlers(); } -void Spell::GOTargetInfo::DoTargetSpellHit(Spell* spell, uint8 effIndex) +void Spell::GOTargetInfo::DoTargetSpellHit(Spell* spell, SpellEffectInfo const& spellEffectInfo) { GameObject* go = spell->m_caster->GetGUID() == TargetGUID ? spell->m_caster->ToGameObject() : ObjectAccessor::GetGameObject(*spell->m_caster, TargetGUID); if (!go) @@ -2712,7 +2663,7 @@ void Spell::GOTargetInfo::DoTargetSpellHit(Spell* spell, uint8 effIndex) spell->CallScriptBeforeHitHandlers(SPELL_MISS_NONE); - spell->HandleEffects(nullptr, nullptr, go, effIndex, SPELL_EFFECT_HANDLE_HIT_TARGET); + spell->HandleEffects(nullptr, nullptr, go, spellEffectInfo, SPELL_EFFECT_HANDLE_HIT_TARGET); //AI functions if (go->AI()) @@ -2732,11 +2683,11 @@ void Spell::GOTargetInfo::DoTargetSpellHit(Spell* spell, uint8 effIndex) spell->CallScriptAfterHitHandlers(); } -void Spell::ItemTargetInfo::DoTargetSpellHit(Spell* spell, uint8 effIndex) +void Spell::ItemTargetInfo::DoTargetSpellHit(Spell* spell, SpellEffectInfo const& spellEffectInfo) { spell->CallScriptBeforeHitHandlers(SPELL_MISS_NONE); - spell->HandleEffects(nullptr, TargetItem, nullptr, effIndex, SPELL_EFFECT_HANDLE_HIT_TARGET); + spell->HandleEffects(nullptr, TargetItem, nullptr, spellEffectInfo, SPELL_EFFECT_HANDLE_HIT_TARGET); spell->CallScriptOnHitHandlers(); spell->CallScriptAfterHitHandlers(); @@ -2812,11 +2763,10 @@ SpellMissInfo Spell::PreprocessSpellHit(Unit* unit, TargetInfo& hitInfo) // check immunity due to diminishing returns if (Aura::BuildEffectMaskForOwner(m_spellInfo, MAX_EFFECT_MASK, unit)) { - for (SpellEffectInfo const* auraSpellEffect : m_spellInfo->GetEffects()) - if (auraSpellEffect) - hitInfo.AuraBasePoints[auraSpellEffect->EffectIndex] = (m_spellValue->CustomBasePointsMask & (1 << auraSpellEffect->EffectIndex)) ? - m_spellValue->EffectBasePoints[auraSpellEffect->EffectIndex] : - auraSpellEffect->CalcBaseValue(m_originalCaster, unit, m_castItemEntry, m_castItemLevel); + for (SpellEffectInfo const& auraSpellEffect : m_spellInfo->GetEffects()) + hitInfo.AuraBasePoints[auraSpellEffect.EffectIndex] = (m_spellValue->CustomBasePointsMask & (1 << auraSpellEffect.EffectIndex)) + ? m_spellValue->EffectBasePoints[auraSpellEffect.EffectIndex] + : auraSpellEffect.CalcBaseValue(m_originalCaster, unit, m_castItemEntry, m_castItemLevel); // Get Data Needed for Diminishing Returns, some effects may have multiple auras, so this must be done on spell hit, not aura add hitInfo.DRGroup = m_spellInfo->GetDiminishingReturnsGroupForSpell(); @@ -2836,13 +2786,12 @@ SpellMissInfo Spell::PreprocessSpellHit(Unit* unit, TargetInfo& hitInfo) hitInfo.Positive = true; if (origCaster == unit || !origCaster->IsFriendlyTo(unit)) { - for (SpellEffectInfo const* effect : m_spellInfo->GetEffects()) + for (SpellEffectInfo const& auraSpellEffect : m_spellInfo->GetEffects()) { // mod duration only for effects applying aura! - if (effect && - hitInfo.EffectMask & (1 << effect->EffectIndex) && - effect->IsUnitOwnedAuraEffect() && - !m_spellInfo->IsPositiveEffect(effect->EffectIndex)) + if (hitInfo.EffectMask & (1 << auraSpellEffect.EffectIndex) && + auraSpellEffect.IsUnitOwnedAuraEffect() && + !m_spellInfo->IsPositiveEffect(auraSpellEffect.EffectIndex)) { hitInfo.Positive = false; break; @@ -2854,16 +2803,16 @@ SpellMissInfo Spell::PreprocessSpellHit(Unit* unit, TargetInfo& hitInfo) // unit is immune to aura if it was diminished to 0 duration if (!hitInfo.Positive && !unit->ApplyDiminishingToDuration(m_spellInfo, hitInfo.AuraDuration, origCaster, diminishLevel)) - if (std::all_of(std::begin(m_spellInfo->GetEffects()), std::end(m_spellInfo->GetEffects()), [](SpellEffectInfo const* effInfo) { return !effInfo || !effInfo->IsEffect() || effInfo->IsEffect(SPELL_EFFECT_APPLY_AURA); })) + if (std::all_of(std::begin(m_spellInfo->GetEffects()), std::end(m_spellInfo->GetEffects()), [](SpellEffectInfo const& effInfo) { return !effInfo.IsEffect() || effInfo.Effect == SPELL_EFFECT_APPLY_AURA; })) return SPELL_MISS_IMMUNE; } return SPELL_MISS_NONE; } -void Spell::DoSpellEffectHit(Unit* unit, uint8 effIndex, TargetInfo& hitInfo) +void Spell::DoSpellEffectHit(Unit* unit, SpellEffectInfo const& spellEffectInfo, TargetInfo& hitInfo) { - if (uint32 aura_effmask = Aura::BuildEffectMaskForOwner(m_spellInfo, 1 << effIndex, unit)) + if (uint32 aura_effmask = Aura::BuildEffectMaskForOwner(m_spellInfo, 1 << spellEffectInfo.EffectIndex, unit)) { WorldObject* caster = m_caster; if (m_originalCaster) @@ -2919,11 +2868,10 @@ void Spell::DoSpellEffectHit(Unit* unit, uint8 effIndex, TargetInfo& hitInfo) { int32 origDuration = hitInfo.AuraDuration; hitInfo.AuraDuration = 0; - for (SpellEffectInfo const* effect : m_spellInfo->GetEffects()) - if (effect) - if (AuraEffect const* eff = _spellAura->GetEffect(effect->EffectIndex)) - if (int32 period = eff->GetPeriod()) // period is hastened by UNIT_MOD_CAST_SPEED - hitInfo.AuraDuration = std::max(std::max(origDuration / period, 1) * period, hitInfo.AuraDuration); + for (AuraEffect const* auraEff : _spellAura->GetAuraEffects()) + if (auraEff) + if (int32 period = auraEff->GetPeriod()) // period is hastened by UNIT_MOD_CAST_SPEED + hitInfo.AuraDuration = std::max(std::max(origDuration / period, 1) * period, hitInfo.AuraDuration); // if there is no periodic effect if (!hitInfo.AuraDuration) @@ -2940,7 +2888,7 @@ void Spell::DoSpellEffectHit(Unit* unit, uint8 effIndex, TargetInfo& hitInfo) } } - HandleEffects(unit, nullptr, nullptr, effIndex, SPELL_EFFECT_HANDLE_HIT_TARGET); + HandleEffects(unit, nullptr, nullptr, spellEffectInfo, SPELL_EFFECT_HANDLE_HIT_TARGET); } void Spell::DoTriggersOnSpellHit(Unit* unit, uint32 effMask) @@ -3000,9 +2948,9 @@ bool Spell::UpdateChanneledTargetList() uint32 channelTargetEffectMask = m_channelTargetEffectMask; uint32 channelAuraMask = 0; - for (SpellEffectInfo const* effect : m_spellInfo->GetEffects()) - if (effect && effect->Effect == SPELL_EFFECT_APPLY_AURA) - channelAuraMask |= 1 << effect->EffectIndex; + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) + if (spellEffectInfo.IsEffect(SPELL_EFFECT_APPLY_AURA)) + channelAuraMask |= 1 << spellEffectInfo.EffectIndex; channelAuraMask &= channelTargetEffectMask; @@ -3397,9 +3345,9 @@ void Spell::_cast(bool skipCheck) if (Unit* target = m_targets.GetUnitTarget()) { uint32 aura_effmask = 0; - for (SpellEffectInfo const* effect : m_spellInfo->GetEffects()) - if (effect && effect->IsUnitOwnedAuraEffect()) - aura_effmask |= 1 << effect->EffectIndex; + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) + if (spellEffectInfo.IsUnitOwnedAuraEffect()) + aura_effmask |= 1 << spellEffectInfo.EffectIndex; if (aura_effmask) { @@ -3586,10 +3534,10 @@ void Spell::DoProcessTargetContainer(Container& targetContainer) for (TargetInfoBase& target : targetContainer) target.PreprocessTarget(this); - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) for (TargetInfoBase& target : targetContainer) - if (target.EffectMask & (1 << i)) - target.DoTargetSpellHit(this, i); + if (target.EffectMask & (1 << spellEffectInfo.EffectIndex)) + target.DoTargetSpellHit(this, spellEffectInfo); for (TargetInfoBase& target : targetContainer) target.DoDamageAndTriggers(this); @@ -3771,14 +3719,14 @@ void Spell::_handle_immediate_phase() HandleThreatSpells(); // handle effects with SPELL_EFFECT_HANDLE_HIT mode - for (SpellEffectInfo const* effect : m_spellInfo->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) { // don't do anything for empty effect - if (!effect || !effect->IsEffect()) + if (!spellEffectInfo.IsEffect()) continue; // call effect handlers to handle destination hit - HandleEffects(nullptr, nullptr, nullptr, effect->EffectIndex, SPELL_EFFECT_HANDLE_HIT); + HandleEffects(nullptr, nullptr, nullptr, spellEffectInfo, SPELL_EFFECT_HANDLE_HIT); } // process items @@ -3852,10 +3800,9 @@ void Spell::update(uint32 difftime) // check if the player caster has moved before the spell finished // with the exception of spells affected with SPELL_AURA_CAST_WHILE_WALKING effect - SpellEffectInfo const* effect = m_spellInfo->GetEffect(EFFECT_0); if ((m_caster->GetTypeId() == TYPEID_PLAYER && m_timer != 0) && m_caster->ToPlayer()->isMoving() && (m_spellInfo->InterruptFlags.HasFlag(SpellInterruptFlags::Movement)) && - ((effect && effect->Effect != SPELL_EFFECT_STUCK) || !m_caster->ToPlayer()->HasUnitMovementFlag(MOVEMENTFLAG_FALLING_FAR)) && + (!m_spellInfo->HasEffect(SPELL_EFFECT_STUCK) || !m_caster->ToPlayer()->HasUnitMovementFlag(MOVEMENTFLAG_FALLING_FAR)) && !m_caster->ToPlayer()->HasAuraTypeWithAffectMask(SPELL_AURA_CAST_WHILE_WALKING, m_spellInfo)) { // don't cancel for melee, autorepeat, triggered and instant spells @@ -4091,9 +4038,15 @@ inline void FillSpellCastFailedArgs(T& packet, ObjectGuid castId, SpellInfo cons else { uint32 item = 0; - for (SpellEffectInfo const* effect : spellInfo->GetEffects()) - if (effect->ItemType) - item = effect->ItemType; + for (SpellEffectInfo const& spellEffectInfo : spellInfo->GetEffects()) + { + if (uint32 itemType = spellEffectInfo.ItemType) + { + item = itemType; + break; + } + } + ItemTemplate const* proto = sObjectMgr->GetItemTemplate(item); if (proto && proto->GetItemLimitCategory()) packet.FailedArg1 = proto->GetItemLimitCategory(); @@ -4755,9 +4708,9 @@ void Spell::SendChannelStart(uint32 duration) explicitTargetEffectMask = explicitTargetItr->EffectMask; } - for (SpellEffectInfo const* effect : m_spellInfo->GetEffects()) - if (effect && effect->Effect == SPELL_EFFECT_APPLY_AURA && (explicitTargetEffectMask & (1u << effect->EffectIndex))) - channelAuraMask |= 1 << effect->EffectIndex; + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) + if (spellEffectInfo.IsEffect(SPELL_EFFECT_APPLY_AURA) && (explicitTargetEffectMask & (1u << spellEffectInfo.EffectIndex))) + channelAuraMask |= 1 << spellEffectInfo.EffectIndex; for (TargetInfo const& target : m_UniqueTargetInfo) { @@ -5093,30 +5046,22 @@ void Spell::HandleThreatSpells() TC_LOG_DEBUG("spells", "Spell %u, added an additional %f threat for %s %u target(s)", m_spellInfo->Id, threat, IsPositive() ? "assisting" : "harming", uint32(m_UniqueTargetInfo.size())); } -void Spell::HandleEffects(Unit* pUnitTarget, Item* pItemTarget, GameObject* pGOTarget, uint32 i, SpellEffectHandleMode mode) +void Spell::HandleEffects(Unit* pUnitTarget, Item* pItemTarget, GameObject* pGOTarget, SpellEffectInfo const& spellEffectInfo, SpellEffectHandleMode mode) { effectHandleMode = mode; unitTarget = pUnitTarget; itemTarget = pItemTarget; gameObjTarget = pGOTarget; - destTarget = &m_destTargets[i]._position; + destTarget = &m_destTargets[spellEffectInfo.EffectIndex]._position; + effectInfo = &spellEffectInfo; unitCaster = m_originalCaster ? m_originalCaster : m_caster->ToUnit(); - effectInfo = m_spellInfo->GetEffect(i); - if (!effectInfo) - { - TC_LOG_ERROR("spells", "Spell: %u HandleEffects at EffectIndex: %u missing effect", m_spellInfo->Id, i); - return; - } - uint32 effect = effectInfo->Effect; - - damage = CalculateDamage(i, unitTarget, &variance); + damage = CalculateDamage(spellEffectInfo, unitTarget, &variance); - SpellEffIndex effIndex = static_cast<SpellEffIndex>(i); - bool preventDefault = CallScriptEffectHandlers(effIndex, mode); + bool preventDefault = CallScriptEffectHandlers(spellEffectInfo.EffectIndex, mode); if (!preventDefault) - (this->*SpellEffectHandlers[effect].Value)(); + (this->*SpellEffectHandlers[spellEffectInfo.Effect].Value)(); } /*static*/ Spell const* Spell::ExtractSpellFromEvent(BasicEvent* event) @@ -5278,8 +5223,7 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint if (unitCaster->GetTypeId() == TYPEID_PLAYER && unitCaster->ToPlayer()->isMoving() && (!unitCaster->IsCharmed() || !unitCaster->GetCharmerGUID().IsCreature()) && !unitCaster->HasAuraTypeWithAffectMask(SPELL_AURA_CAST_WHILE_WALKING, m_spellInfo)) { // skip stuck spell to allow use it in falling case and apply spell limitations at movement - SpellEffectInfo const* effect = m_spellInfo->GetEffect(EFFECT_0); - if ((!unitCaster->HasUnitMovementFlag(MOVEMENTFLAG_FALLING_FAR) || (effect && effect->Effect != SPELL_EFFECT_STUCK)) && + if ((!unitCaster->HasUnitMovementFlag(MOVEMENTFLAG_FALLING_FAR) || !m_spellInfo->HasEffect(SPELL_EFFECT_STUCK)) && (IsAutoRepeat() || m_spellInfo->HasAuraInterruptFlag(SpellAuraInterruptFlags::Standing))) return SPELL_FAILED_MOVING; } @@ -5386,9 +5330,9 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint // check pet presence if (Unit* unitCaster = m_caster->ToUnit()) { - for (SpellEffectInfo const* effect : m_spellInfo->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) { - if (effect && effect->TargetA.GetTarget() == TARGET_UNIT_PET) + if (spellEffectInfo.TargetA.GetTarget() == TARGET_UNIT_PET) { if (!unitCaster->GetGuardianPet()) { @@ -5485,12 +5429,10 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint if (castResult != SPELL_CAST_OK) return castResult; - for (SpellEffectInfo const* effect : m_spellInfo->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) { - if (!effect) - continue; // for effects of spells that have only one target - switch (effect->Effect) + switch (spellEffectInfo.Effect) { case SPELL_EFFECT_DUMMY: { @@ -5514,14 +5456,14 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint } case SPELL_EFFECT_LEARN_SPELL: { - if (effect->TargetA.GetTarget() != TARGET_UNIT_PET) + if (spellEffectInfo.TargetA.GetTarget() != TARGET_UNIT_PET) break; Pet* pet = m_caster->ToPlayer()->GetPet(); if (!pet) return SPELL_FAILED_NO_PET; - SpellInfo const* learn_spellproto = sSpellMgr->GetSpellInfo(effect->TriggerSpell, DIFFICULTY_NONE); + SpellInfo const* learn_spellproto = sSpellMgr->GetSpellInfo(spellEffectInfo.TriggerSpell, DIFFICULTY_NONE); if (!learn_spellproto) return SPELL_FAILED_NOT_KNOWN; @@ -5551,7 +5493,7 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint if (!pet || pet->GetOwner() != m_caster) return SPELL_FAILED_BAD_TARGETS; - SpellInfo const* learn_spellproto = sSpellMgr->GetSpellInfo(effect->TriggerSpell, DIFFICULTY_NONE); + SpellInfo const* learn_spellproto = sSpellMgr->GetSpellInfo(spellEffectInfo.TriggerSpell, DIFFICULTY_NONE); if (!learn_spellproto) return SPELL_FAILED_NOT_KNOWN; @@ -5570,7 +5512,7 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint if (!caster->HasSpell(m_misc.SpellId)) return SPELL_FAILED_NOT_KNOWN; - if (uint32 glyphId = effect->MiscValue) + if (uint32 glyphId = spellEffectInfo.MiscValue) { GlyphPropertiesEntry const* glyphProperties = sGlyphPropertiesStore.LookupEntry(glyphId); if (!glyphProperties) @@ -5713,13 +5655,13 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint } case SPELL_EFFECT_OPEN_LOCK: { - if (effect->TargetA.GetTarget() != TARGET_GAMEOBJECT_TARGET && - effect->TargetA.GetTarget() != TARGET_GAMEOBJECT_ITEM_TARGET) + if (spellEffectInfo.TargetA.GetTarget() != TARGET_GAMEOBJECT_TARGET && + spellEffectInfo.TargetA.GetTarget() != TARGET_GAMEOBJECT_ITEM_TARGET) break; if (m_caster->GetTypeId() != TYPEID_PLAYER // only players can open locks, gather etc. // we need a go target in case of TARGET_GAMEOBJECT_TARGET - || (effect->TargetA.GetTarget() == TARGET_GAMEOBJECT_TARGET && !m_targets.GetGOTarget())) + || (spellEffectInfo.TargetA.GetTarget() == TARGET_GAMEOBJECT_TARGET && !m_targets.GetGOTarget())) return SPELL_FAILED_BAD_TARGETS; Item* pTempItem = nullptr; @@ -5732,7 +5674,7 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint pTempItem = m_caster->ToPlayer()->GetItemByGuid(m_targets.GetItemTargetGUID()); // we need a go target, or an openable item target in case of TARGET_GAMEOBJECT_ITEM_TARGET - if (effect->TargetA.GetTarget() == TARGET_GAMEOBJECT_ITEM_TARGET && + if (spellEffectInfo.TargetA.GetTarget() == TARGET_GAMEOBJECT_ITEM_TARGET && !m_targets.GetGOTarget() && (!pTempItem || !pTempItem->GetTemplate()->GetLockID() || !pTempItem->IsLocked())) return SPELL_FAILED_BAD_TARGETS; @@ -5759,7 +5701,7 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint int32 skillValue = 0; // check lock compatibility - SpellCastResult res = CanOpenLock(*effect, lockId, skillId, reqSkillValue, skillValue); + SpellCastResult res = CanOpenLock(spellEffectInfo, lockId, skillId, reqSkillValue, skillValue); if (res != SPELL_CAST_OK) return res; break; @@ -5782,7 +5724,7 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint if (!unitCaster) break; - SummonPropertiesEntry const* SummonProperties = sSummonPropertiesStore.LookupEntry(effect->MiscValueB); + SummonPropertiesEntry const* SummonProperties = sSummonPropertiesStore.LookupEntry(spellEffectInfo.MiscValueB); if (!SummonProperties) break; @@ -5982,10 +5924,10 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint if (!artifact) return SPELL_FAILED_NO_ARTIFACT_EQUIPPED; - if (effect->Effect == SPELL_EFFECT_GIVE_ARTIFACT_POWER) + if (spellEffectInfo.Effect == SPELL_EFFECT_GIVE_ARTIFACT_POWER) { ArtifactEntry const* artifactEntry = sArtifactStore.LookupEntry(artifact->GetTemplate()->GetArtifactID()); - if (!artifactEntry || artifactEntry->ArtifactCategoryID != effect->MiscValue) + if (!artifactEntry || artifactEntry->ArtifactCategoryID != spellEffectInfo.MiscValue) return SPELL_FAILED_WRONG_ARTIFACT_EQUIPPED; } break; @@ -5995,11 +5937,9 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint } } - for (SpellEffectInfo const* effect : m_spellInfo->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) { - if (!effect) - continue; - switch (effect->ApplyAuraName) + switch (spellEffectInfo.ApplyAuraName) { case SPELL_AURA_MOD_POSSESS_PET: { @@ -6025,8 +5965,8 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint if (!unitCaster->GetCharmerGUID().IsEmpty()) return SPELL_FAILED_CHARMED; - if (effect->ApplyAuraName == SPELL_AURA_MOD_CHARM - || effect->ApplyAuraName == SPELL_AURA_MOD_POSSESS) + if (spellEffectInfo.ApplyAuraName == SPELL_AURA_MOD_CHARM + || spellEffectInfo.ApplyAuraName == SPELL_AURA_MOD_POSSESS) { if (!m_spellInfo->HasAttribute(SPELL_ATTR1_DISMISS_PET) && !unitCaster->GetPetGUID().IsEmpty()) return SPELL_FAILED_ALREADY_HAVE_SUMMON; @@ -6049,7 +5989,7 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint if (target->GetOwner() && target->GetOwner()->GetTypeId() == TYPEID_PLAYER) return SPELL_FAILED_TARGET_IS_PLAYER_CONTROLLED; - int32 value = CalculateDamage(effect->EffectIndex, target); + int32 value = CalculateDamage(spellEffectInfo, target); if (value && int32(target->GetLevelForTarget(m_caster)) > value) return SPELL_FAILED_HIGHLEVEL; } @@ -6106,7 +6046,7 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint } case SPELL_AURA_PERIODIC_MANA_LEECH: { - if (effect->IsTargetingArea()) + if (spellEffectInfo.IsTargetingArea()) break; if (!m_targets.GetUnitTarget()) @@ -6243,7 +6183,7 @@ SpellCastResult Spell::CheckCasterAuras(uint32* param1) const // fill up aura mechanic info to send client proper error message if (param1) { - *param1 = aurEff->GetSpellEffectInfo()->Mechanic; + *param1 = aurEff->GetSpellEffectInfo().Mechanic; if (!*param1) *param1 = aurEff->GetSpellInfo()->Mechanic; } @@ -6336,7 +6276,7 @@ bool Spell::CheckSpellCancelsAuraEffect(AuraType auraType, uint32* param1) const if (param1) { - *param1 = aurEff->GetSpellEffectInfo()->Mechanic; + *param1 = aurEff->GetSpellEffectInfo().Mechanic; if (!*param1) *param1 = aurEff->GetSpellInfo()->Mechanic; } @@ -6418,10 +6358,10 @@ SpellCastResult Spell::CheckArenaAndRatedBattlegroundCastRules() return SPELL_CAST_OK; } -int32 Spell::CalculateDamage(uint8 effIndex, Unit const* target, float* var /*= nullptr*/) const +int32 Spell::CalculateDamage(SpellEffectInfo const& spellEffectInfo, Unit const* target, float* var /*= nullptr*/) const { - bool needRecalculateBasePoints = !(m_spellValue->CustomBasePointsMask & (1 << effIndex)); - return m_caster->CalculateSpellDamage(target, m_spellInfo, effIndex, needRecalculateBasePoints ? nullptr : &m_spellValue->EffectBasePoints[effIndex], var, m_castItemEntry, m_castItemLevel); + bool needRecalculateBasePoints = !(m_spellValue->CustomBasePointsMask & (1 << spellEffectInfo.EffectIndex)); + return m_caster->CalculateSpellDamage(target, spellEffectInfo, needRecalculateBasePoints ? nullptr : &m_spellValue->EffectBasePoints[spellEffectInfo.EffectIndex], var, m_castItemEntry, m_castItemLevel); } bool Spell::CanAutoCast(Unit* target) @@ -6432,15 +6372,12 @@ bool Spell::CanAutoCast(Unit* target) ObjectGuid targetguid = target->GetGUID(); // check if target already has the same or a more powerful aura - for (SpellEffectInfo const* effect : m_spellInfo->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) { - if (!effect) + if (!spellEffectInfo.IsAura()) continue; - if (!effect->IsAura()) - continue; - - AuraType const& auraType = AuraType(effect->ApplyAuraName); + AuraType const& auraType = spellEffectInfo.ApplyAuraName; Unit::AuraEffectList const& auras = target->GetAuraEffectsByType(auraType); for (Unit::AuraEffectList::const_iterator auraIt = auras.begin(); auraIt != auras.end(); ++auraIt) { @@ -6457,7 +6394,7 @@ bool Spell::CanAutoCast(Unit* target) break; case SPELL_GROUP_STACK_RULE_EXCLUSIVE_SAME_EFFECT: // this one has further checks, but i don't think they're necessary for autocast logic case SPELL_GROUP_STACK_RULE_EXCLUSIVE_HIGHEST: - if (abs(effect->BasePoints) <= abs((*auraIt)->GetAmount())) + if (abs(spellEffectInfo.BasePoints) <= abs((*auraIt)->GetAmount())) return false; break; case SPELL_GROUP_STACK_RULE_DEFAULT: @@ -6669,13 +6606,13 @@ SpellCastResult Spell::CheckItems(uint32* param1 /*= nullptr*/, uint32* param2 / { // such items should only fail if there is no suitable effect at all - see Rejuvenation Potions for example SpellCastResult failReason = SPELL_CAST_OK; - for (SpellEffectInfo const* effect : m_spellInfo->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) { // skip check, pet not required like checks, and for TARGET_UNIT_PET m_targets.GetUnitTarget() is not the real target but the caster - if (!effect || effect->TargetA.GetTarget() == TARGET_UNIT_PET) + if (spellEffectInfo.TargetA.GetTarget() == TARGET_UNIT_PET) continue; - if (effect->Effect == SPELL_EFFECT_HEAL) + if (spellEffectInfo.IsEffect(SPELL_EFFECT_HEAL)) { if (m_targets.GetUnitTarget()->IsFullHealth()) { @@ -6690,15 +6627,15 @@ SpellCastResult Spell::CheckItems(uint32* param1 /*= nullptr*/, uint32* param2 / } // Mana Potion, Rage Potion, Thistle Tea(Rogue), ... - if (effect->Effect == SPELL_EFFECT_ENERGIZE) + if (spellEffectInfo.IsEffect(SPELL_EFFECT_ENERGIZE)) { - if (effect->MiscValue < 0 || effect->MiscValue >= int8(MAX_POWERS)) + if (spellEffectInfo.MiscValue < 0 || spellEffectInfo.MiscValue >= int8(MAX_POWERS)) { failReason = SPELL_FAILED_ALREADY_AT_FULL_POWER; continue; } - Powers power = Powers(effect->MiscValue); + Powers power = Powers(spellEffectInfo.MiscValue); if (m_targets.GetUnitTarget()->GetPower(power) == m_targets.GetUnitTarget()->GetMaxPower(power)) { failReason = SPELL_FAILED_ALREADY_AT_FULL_POWER; @@ -6825,29 +6762,26 @@ SpellCastResult Spell::CheckItems(uint32* param1 /*= nullptr*/, uint32* param2 / } // special checks for spell effects - for (SpellEffectInfo const* effect : m_spellInfo->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) { - if (!effect) - continue; - - switch (effect->Effect) + switch (spellEffectInfo.Effect) { case SPELL_EFFECT_CREATE_ITEM: case SPELL_EFFECT_CREATE_LOOT: { // m_targets.GetUnitTarget() means explicit cast, otherwise we dont check for possible equip error Unit* target = m_targets.GetUnitTarget() ? m_targets.GetUnitTarget() : player; - if (target->GetTypeId() == TYPEID_PLAYER && !IsTriggered() && effect->ItemType) + if (target->GetTypeId() == TYPEID_PLAYER && !IsTriggered() && spellEffectInfo.ItemType) { ItemPosCountVec dest; - InventoryResult msg = target->ToPlayer()->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, effect->ItemType, 1); + InventoryResult msg = target->ToPlayer()->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, spellEffectInfo.ItemType, 1); if (msg != EQUIP_ERR_OK) { - ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(effect->ItemType); + ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(spellEffectInfo.ItemType); /// @todo Needs review if (itemTemplate && !(itemTemplate->GetItemLimitCategory())) { - player->SendEquipError(msg, nullptr, nullptr, effect->ItemType); + player->SendEquipError(msg, nullptr, nullptr, spellEffectInfo.ItemType); return SPELL_FAILED_DONT_REPORT; } else @@ -6855,13 +6789,13 @@ SpellCastResult Spell::CheckItems(uint32* param1 /*= nullptr*/, uint32* param2 / // Conjure Food/Water/Refreshment spells if (m_spellInfo->SpellFamilyName != SPELLFAMILY_MAGE || (!(m_spellInfo->SpellFamilyFlags[0] & 0x40000000))) return SPELL_FAILED_TOO_MANY_OF_ITEM; - else if (!(target->ToPlayer()->HasItemCount(effect->ItemType))) + else if (!(target->ToPlayer()->HasItemCount(spellEffectInfo.ItemType))) { - player->SendEquipError(msg, nullptr, nullptr, effect->ItemType); + player->SendEquipError(msg, nullptr, nullptr, spellEffectInfo.ItemType); return SPELL_FAILED_DONT_REPORT; } - else if (SpellEffectInfo const* efi = m_spellInfo->GetEffect(EFFECT_1)) - player->CastSpell(player, efi->CalcValue(), false); // move this to anywhere + else if (m_spellInfo->GetEffects().size() > EFFECT_1) + player->CastSpell(player, m_spellInfo->GetEffect(EFFECT_1).CalcValue(), false); // move this to anywhere return SPELL_FAILED_DONT_REPORT; } } @@ -6869,7 +6803,7 @@ SpellCastResult Spell::CheckItems(uint32* param1 /*= nullptr*/, uint32* param2 / break; } case SPELL_EFFECT_ENCHANT_ITEM: - if (effect->ItemType && m_targets.GetItemTarget() + if (spellEffectInfo.ItemType && m_targets.GetItemTarget() && (m_targets.GetItemTarget()->IsVellum())) { // cannot enchant vellum for other player @@ -6879,10 +6813,10 @@ SpellCastResult Spell::CheckItems(uint32* param1 /*= nullptr*/, uint32* param2 / if (m_CastItem && m_CastItem->GetTemplate()->GetFlags() & ITEM_FLAG_NO_REAGENT_COST) return SPELL_FAILED_TOTEM_CATEGORY; ItemPosCountVec dest; - InventoryResult msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, effect->ItemType, 1); + InventoryResult msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, spellEffectInfo.ItemType, 1); if (msg != EQUIP_ERR_OK) { - player->SendEquipError(msg, nullptr, nullptr, effect->ItemType); + player->SendEquipError(msg, nullptr, nullptr, spellEffectInfo.ItemType); return SPELL_FAILED_DONT_REPORT; } } @@ -6907,7 +6841,7 @@ SpellCastResult Spell::CheckItems(uint32* param1 /*= nullptr*/, uint32* param2 / } } - SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(effect->MiscValue); + SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(spellEffectInfo.MiscValue); // do not allow adding usable enchantments to items that have use effect already if (enchantEntry) { @@ -6952,7 +6886,7 @@ SpellCastResult Spell::CheckItems(uint32* param1 /*= nullptr*/, uint32* param2 / // Not allow enchant in trade slot for some enchant type if (item->GetOwner() != player) { - uint32 enchant_id = effect->MiscValue; + uint32 enchant_id = spellEffectInfo.MiscValue; SpellItemEnchantmentEntry const* pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id); if (!pEnchant) return SPELL_FAILED_ERROR; @@ -7087,7 +7021,7 @@ SpellCastResult Spell::CheckItems(uint32* param1 /*= nullptr*/, uint32* param2 / } case SPELL_EFFECT_RECHARGE_ITEM: { - uint32 itemId = effect->ItemType; + uint32 itemId = spellEffectInfo.ItemType; ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemId); if (!proto) @@ -7300,12 +7234,9 @@ bool Spell::UpdatePointers() WorldObject* transport = nullptr; // update effect destinations (in case of moved transport dest target) - for (SpellEffectInfo const* effect : m_spellInfo->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) { - if (!effect) - continue; - - SpellDestination& dest = m_destTargets[effect->EffectIndex]; + SpellDestination& dest = m_destTargets[spellEffectInfo.EffectIndex]; if (!dest._transportGUID) continue; @@ -7339,12 +7270,9 @@ Difficulty Spell::GetCastDifficulty() const return m_caster->GetMap()->GetDifficultyID(); } -bool Spell::CheckEffectTarget(Unit const* target, SpellEffectInfo const* effect, Position const* losPosition) const +bool Spell::CheckEffectTarget(Unit const* target, SpellEffectInfo const& spellEffectInfo, Position const* losPosition) const { - if (!effect->IsEffect()) - return false; - - switch (effect->ApplyAuraName) + switch (spellEffectInfo.ApplyAuraName) { case SPELL_AURA_MOD_POSSESS: case SPELL_AURA_MOD_CHARM: @@ -7356,7 +7284,7 @@ bool Spell::CheckEffectTarget(Unit const* target, SpellEffectInfo const* effect, return false; if (!target->GetCharmerGUID().IsEmpty()) return false; - if (int32 value = CalculateDamage(effect->EffectIndex, target)) + if (int32 value = CalculateDamage(spellEffectInfo, target)) if ((int32)target->GetLevelForTarget(m_caster) > value) return false; break; @@ -7374,7 +7302,7 @@ bool Spell::CheckEffectTarget(Unit const* target, SpellEffectInfo const* effect, /// @todo shit below shouldn't be here, but it's temporary //Check targets for LOS visibility - switch (effect->Effect) + switch (spellEffectInfo.Effect) { case SPELL_EFFECT_SKIN_PLAYER_CORPSE: { @@ -7422,12 +7350,9 @@ bool Spell::CheckEffectTarget(Unit const* target, SpellEffectInfo const* effect, return true; } -bool Spell::CheckEffectTarget(GameObject const* target, SpellEffectInfo const* effect) const +bool Spell::CheckEffectTarget(GameObject const* target, SpellEffectInfo const& spellEffectInfo) const { - if (!effect->IsEffect()) - return false; - - switch (effect->Effect) + switch (spellEffectInfo.Effect) { case SPELL_EFFECT_GAMEOBJECT_DAMAGE: case SPELL_EFFECT_GAMEOBJECT_REPAIR: @@ -7442,11 +7367,8 @@ bool Spell::CheckEffectTarget(GameObject const* target, SpellEffectInfo const* e return true; } -bool Spell::CheckEffectTarget(Item const* /*target*/, SpellEffectInfo const* effect) const +bool Spell::CheckEffectTarget(Item const* /*target*/, SpellEffectInfo const& /*spellEffectInfo*/) const { - if (!effect->IsEffect()) - return false; - return true; } @@ -7637,40 +7559,37 @@ bool Spell::IsValidDeadOrAliveTarget(Unit const* target) const void Spell::HandleLaunchPhase() { // handle effects with SPELL_EFFECT_HANDLE_LAUNCH mode - for (SpellEffectInfo const* effect : m_spellInfo->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) { // don't do anything for empty effect - if (!effect || !effect->IsEffect()) + if (!spellEffectInfo.IsEffect()) continue; - HandleEffects(nullptr, nullptr, nullptr, effect->EffectIndex, SPELL_EFFECT_HANDLE_LAUNCH); + HandleEffects(nullptr, nullptr, nullptr, spellEffectInfo, SPELL_EFFECT_HANDLE_LAUNCH); } PrepareTargetProcessing(); - for (SpellEffectInfo const* effect : m_spellInfo->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) { - if (!effect) - continue; - float multiplier = 1.0f; - if (m_applyMultiplierMask & (1 << effect->EffectIndex)) - multiplier = effect->CalcDamageMultiplier(m_originalCaster, this); + if (m_applyMultiplierMask & (1 << spellEffectInfo.EffectIndex)) + multiplier = spellEffectInfo.CalcDamageMultiplier(m_originalCaster, this); for (TargetInfo& target : m_UniqueTargetInfo) { uint32 mask = target.EffectMask; - if (!(mask & (1 << effect->EffectIndex))) + if (!(mask & (1 << spellEffectInfo.EffectIndex))) continue; - DoEffectOnLaunchTarget(target, multiplier, effect); + DoEffectOnLaunchTarget(target, multiplier, spellEffectInfo); } } FinishTargetProcessing(); } -void Spell::DoEffectOnLaunchTarget(TargetInfo& targetInfo, float multiplier, SpellEffectInfo const* effect) +void Spell::DoEffectOnLaunchTarget(TargetInfo& targetInfo, float multiplier, SpellEffectInfo const& spellEffectInfo) { Unit* unit = nullptr; // In case spell hit target, do all effect on that target @@ -7690,30 +7609,30 @@ void Spell::DoEffectOnLaunchTarget(TargetInfo& targetInfo, float multiplier, Spe m_damage = 0; m_healing = 0; - HandleEffects(unit, nullptr, nullptr, effect->EffectIndex, SPELL_EFFECT_HANDLE_LAUNCH_TARGET); + HandleEffects(unit, nullptr, nullptr, spellEffectInfo, SPELL_EFFECT_HANDLE_LAUNCH_TARGET); if (m_originalCaster && m_damage > 0) { - if (effect->IsTargetingArea() || effect->IsAreaAuraEffect() || effect->IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA)) + if (spellEffectInfo.IsTargetingArea() || spellEffectInfo.IsAreaAuraEffect() || spellEffectInfo.IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA)) { m_damage = unit->CalculateAOEAvoidance(m_damage, m_spellInfo->SchoolMask, m_originalCaster->GetGUID()); if (m_originalCaster->GetTypeId() == TYPEID_PLAYER) { // cap damage of player AOE - int64 targetAmount = GetUnitTargetCountForEffect(SpellEffIndex(effect->EffectIndex)); + int64 targetAmount = GetUnitTargetCountForEffect(spellEffectInfo.EffectIndex); if (targetAmount > 20) m_damage = m_damage * 20 / targetAmount; } } } - if (m_applyMultiplierMask & (1 << effect->EffectIndex)) + if (m_applyMultiplierMask & (1 << spellEffectInfo.EffectIndex)) { - m_damage = int32(m_damage * m_damageMultipliers[effect->EffectIndex]); - m_healing = int32(m_healing * m_damageMultipliers[effect->EffectIndex]); + m_damage = int32(m_damage * m_damageMultipliers[spellEffectInfo.EffectIndex]); + m_healing = int32(m_healing * m_damageMultipliers[spellEffectInfo.EffectIndex]); - m_damageMultipliers[effect->EffectIndex] *= multiplier; + m_damageMultipliers[spellEffectInfo.EffectIndex] *= multiplier; } targetInfo.Damage += m_damage; @@ -8091,9 +8010,9 @@ bool Spell::CanExecuteTriggersOnHit(uint32 effMask, SpellInfo const* triggeredBy { bool only_on_caster = (triggeredByAura && (triggeredByAura->HasAttribute(SPELL_ATTR4_PROC_ONLY_ON_CASTER))); // If triggeredByAura has SPELL_ATTR4_PROC_ONLY_ON_CASTER then it can only proc on a cast spell with TARGET_UNIT_CASTER - for (SpellEffectInfo const* effect : m_spellInfo->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) { - if (effect && ((effMask & (1 << effect->EffectIndex)) && (!only_on_caster || (effect->TargetA.GetTarget() == TARGET_UNIT_CASTER)))) + if ((effMask & (1 << spellEffectInfo.EffectIndex)) && (!only_on_caster || (spellEffectInfo.TargetA.GetTarget() == TARGET_UNIT_CASTER))) return true; } return false; @@ -8114,13 +8033,13 @@ void Spell::PrepareTriggersExecutedOnHit() if (!aurEff->IsAffectingSpell(m_spellInfo)) continue; - if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(aurEff->GetSpellEffectInfo()->TriggerSpell, GetCastDifficulty())) + if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(aurEff->GetSpellEffectInfo().TriggerSpell, GetCastDifficulty())) { // calculate the chance using spell base amount, because aura amount is not updated on combo-points change // this possibly needs fixing int32 auraBaseAmount = aurEff->GetBaseAmount(); // proc chance is stored in effect amount - int32 chance = unitCaster->CalculateSpellDamage(nullptr, aurEff->GetSpellInfo(), aurEff->GetEffIndex(), &auraBaseAmount); + int32 chance = unitCaster->CalculateSpellDamage(nullptr, aurEff->GetSpellEffectInfo(), &auraBaseAmount); chance *= aurEff->GetBase()->GetStackAmount(); // build trigger and add to the list diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h index 37d6d68a187..b12fa5fd929 100644 --- a/src/server/game/Spells/Spell.h +++ b/src/server/game/Spells/Spell.h @@ -515,21 +515,21 @@ class TC_GAME_API Spell void SelectExplicitTargets(); void SelectSpellTargets(); - void SelectEffectImplicitTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, uint32& processedEffectMask); - void SelectImplicitChannelTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType); - void SelectImplicitNearbyTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, uint32 effMask); - void SelectImplicitConeTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, uint32 effMask); - void SelectImplicitAreaTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, uint32 effMask); - void SelectImplicitCasterDestTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType); - void SelectImplicitTargetDestTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType); - void SelectImplicitDestDestTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType); - void SelectImplicitCasterObjectTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType); - void SelectImplicitTargetObjectTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType); - void SelectImplicitChainTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, WorldObject* target, uint32 effMask); - void SelectImplicitTrajTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType); - void SelectImplicitLineTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, uint32 effMask); - - void SelectEffectTypeImplicitTargets(uint32 effIndex); + void SelectEffectImplicitTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType, uint32& processedEffectMask); + void SelectImplicitChannelTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType); + void SelectImplicitNearbyTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType, uint32 effMask); + void SelectImplicitConeTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType, uint32 effMask); + void SelectImplicitAreaTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType, uint32 effMask); + void SelectImplicitCasterDestTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType); + void SelectImplicitTargetDestTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType); + void SelectImplicitDestDestTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType); + void SelectImplicitCasterObjectTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType); + void SelectImplicitTargetObjectTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType); + void SelectImplicitChainTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType, WorldObject* target, uint32 effMask); + void SelectImplicitTrajTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType); + void SelectImplicitLineTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType, uint32 effMask); + + void SelectEffectTypeImplicitTargets(SpellEffectInfo const& spellEffectInfo); uint32 GetSearcherTypeMask(SpellTargetObjectTypes objType, ConditionContainer* condList); template<class SEARCHER> void SearchTargets(SEARCHER& searcher, uint32 containerMask, WorldObject* referer, Position const* pos, float radius); @@ -577,7 +577,7 @@ class TC_GAME_API Spell bool CheckSpellCancelsConfuse(uint32* param1) const; bool CheckSpellCancelsNoActions(uint32* param1) const; - int32 CalculateDamage(uint8 effIndex, Unit const* target, float* var = nullptr) const; + int32 CalculateDamage(SpellEffectInfo const& spellEffectInfo, Unit const* target, float* var = nullptr) const; void Delayed(); void DelayedChannel(); @@ -586,9 +586,9 @@ class TC_GAME_API Spell void DoCreateItem(uint32 itemId, ItemContext context = ItemContext::NONE, std::vector<int32> const& bonusListIDs = std::vector<int32>()); - bool CheckEffectTarget(Unit const* target, SpellEffectInfo const* effect, Position const* losPosition) const; - bool CheckEffectTarget(GameObject const* target, SpellEffectInfo const* effect) const; - bool CheckEffectTarget(Item const* target, SpellEffectInfo const* effect) const; + bool CheckEffectTarget(Unit const* target, SpellEffectInfo const& spellEffectInfo, Position const* losPosition) const; + bool CheckEffectTarget(GameObject const* target, SpellEffectInfo const& spellEffectInfo) const; + bool CheckEffectTarget(Item const* target, SpellEffectInfo const& spellEffectInfo) const; bool CanAutoCast(Unit* target); void CheckSrc(); void CheckDst(); @@ -626,7 +626,7 @@ class TC_GAME_API Spell void SendChannelStart(uint32 duration); void SendResurrectRequest(Player* target); - void HandleEffects(Unit* pUnitTarget, Item* pItemTarget, GameObject* pGOTarget, uint32 i, SpellEffectHandleMode mode); + void HandleEffects(Unit* pUnitTarget, Item* pItemTarget, GameObject* pGOTarget, SpellEffectInfo const& spellEffectInfo, SpellEffectHandleMode mode); void HandleThreatSpells(); static Spell const* ExtractSpellFromEvent(BasicEvent* event); @@ -818,7 +818,7 @@ class TC_GAME_API Spell struct TargetInfoBase { virtual void PreprocessTarget(Spell* /*spell*/) { } - virtual void DoTargetSpellHit(Spell* spell, uint8 effIndex) = 0; + virtual void DoTargetSpellHit(Spell* spell, SpellEffectInfo const& spellEffectInfo) = 0; virtual void DoDamageAndTriggers(Spell* /*spell*/) { } uint32 EffectMask = 0; @@ -831,7 +831,7 @@ class TC_GAME_API Spell struct TargetInfo : public TargetInfoBase { void PreprocessTarget(Spell* spell) override; - void DoTargetSpellHit(Spell* spell, uint8 effIndex) override; + void DoTargetSpellHit(Spell* spell, SpellEffectInfo const& spellEffectInfo) override; void DoDamageAndTriggers(Spell* spell) override; ObjectGuid TargetGUID; @@ -860,7 +860,7 @@ class TC_GAME_API Spell struct GOTargetInfo : public TargetInfoBase { - void DoTargetSpellHit(Spell* spell, uint8 effIndex) override; + void DoTargetSpellHit(Spell* spell, SpellEffectInfo const& spellEffectInfo) override; ObjectGuid TargetGUID; uint64 TimeDelay = 0ULL; @@ -869,7 +869,7 @@ class TC_GAME_API Spell struct ItemTargetInfo : public TargetInfoBase { - void DoTargetSpellHit(Spell* spell, uint8 effIndex) override; + void DoTargetSpellHit(Spell* spell, SpellEffectInfo const& spellEffectInfo) override; Item* TargetItem = nullptr; }; @@ -886,13 +886,13 @@ class TC_GAME_API Spell void AddDestTarget(SpellDestination const& dest, uint32 effIndex); SpellMissInfo PreprocessSpellHit(Unit* unit, TargetInfo& targetInfo); - void DoSpellEffectHit(Unit* unit, uint8 effIndex, TargetInfo& targetInfo); + void DoSpellEffectHit(Unit* unit, SpellEffectInfo const& spellEffectInfo, TargetInfo& targetInfo); void DoTriggersOnSpellHit(Unit* unit, uint32 effMask); bool UpdateChanneledTargetList(); bool IsValidDeadOrAliveTarget(Unit const* target) const; void HandleLaunchPhase(); - void DoEffectOnLaunchTarget(TargetInfo& targetInfo, float multiplier, SpellEffectInfo const* effect); + void DoEffectOnLaunchTarget(TargetInfo& targetInfo, float multiplier, SpellEffectInfo const& spellEffectInfo); void PrepareTargetProcessing(); void FinishTargetProcessing(); diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 89088dc35d2..f881bf52e15 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -527,7 +527,7 @@ void Spell::EffectSchoolDMG() if (unitCaster && apply_direct_bonus) { - uint32 bonus = unitCaster->SpellDamageBonusDone(unitTarget, m_spellInfo, (uint32)damage, SPELL_DIRECT_DAMAGE, effectInfo); + uint32 bonus = unitCaster->SpellDamageBonusDone(unitTarget, m_spellInfo, (uint32)damage, SPELL_DIRECT_DAMAGE, *effectInfo); damage = bonus + uint32(bonus * variance); damage = unitTarget->SpellDamageBonusTaken(unitCaster, m_spellInfo, (uint32)damage, SPELL_DIRECT_DAMAGE); } @@ -1061,7 +1061,7 @@ void Spell::EffectPowerDrain() // add spell damage bonus if (unitCaster) { - uint32 bonus = unitCaster->SpellDamageBonusDone(unitTarget, m_spellInfo, uint32(damage), SPELL_DIRECT_DAMAGE, effectInfo); + uint32 bonus = unitCaster->SpellDamageBonusDone(unitTarget, m_spellInfo, uint32(damage), SPELL_DIRECT_DAMAGE, *effectInfo); damage = bonus + uint32(bonus * variance); damage = unitTarget->SpellDamageBonusTaken(unitCaster, m_spellInfo, uint32(damage), SPELL_DIRECT_DAMAGE); } @@ -1183,10 +1183,10 @@ void Spell::EffectHeal() } // Death Pact - return pct of max health to caster else if (m_spellInfo->SpellFamilyName == SPELLFAMILY_DEATHKNIGHT && m_spellInfo->SpellFamilyFlags[0] & 0x00080000) - addhealth = unitCaster->SpellHealingBonusDone(unitTarget, m_spellInfo, int32(unitCaster->CountPctFromMaxHealth(damage)), HEAL, effectInfo); + addhealth = unitCaster->SpellHealingBonusDone(unitTarget, m_spellInfo, int32(unitCaster->CountPctFromMaxHealth(damage)), HEAL, *effectInfo); else { - uint32 bonus = unitCaster->SpellHealingBonusDone(unitTarget, m_spellInfo, addhealth, HEAL, effectInfo); + uint32 bonus = unitCaster->SpellHealingBonusDone(unitTarget, m_spellInfo, addhealth, HEAL, *effectInfo); addhealth = bonus + uint32(bonus * variance); } @@ -1210,7 +1210,7 @@ void Spell::EffectHealPct() uint32 heal = unitTarget->CountPctFromMaxHealth(damage); if (unitCaster) { - heal = unitCaster->SpellHealingBonusDone(unitTarget, m_spellInfo, heal, HEAL, effectInfo); + heal = unitCaster->SpellHealingBonusDone(unitTarget, m_spellInfo, heal, HEAL, *effectInfo); heal = unitTarget->SpellHealingBonusTaken(unitCaster, m_spellInfo, heal, HEAL); } @@ -1227,7 +1227,7 @@ void Spell::EffectHealMechanical() uint32 heal = damage; if (unitCaster) - heal = unitCaster->SpellHealingBonusDone(unitTarget, m_spellInfo, heal, HEAL, effectInfo); + heal = unitCaster->SpellHealingBonusDone(unitTarget, m_spellInfo, heal, HEAL, *effectInfo); heal += uint32(heal * variance); if (unitCaster) @@ -1246,7 +1246,7 @@ void Spell::EffectHealthLeech() uint32 bonus = 0; if (unitCaster) - bonus = unitCaster->SpellDamageBonusDone(unitTarget, m_spellInfo, uint32(damage), SPELL_DIRECT_DAMAGE, effectInfo); + bonus = unitCaster->SpellDamageBonusDone(unitTarget, m_spellInfo, uint32(damage), SPELL_DIRECT_DAMAGE, *effectInfo); damage = bonus + uint32(bonus * variance); @@ -1263,7 +1263,7 @@ void Spell::EffectHealthLeech() if (unitCaster && unitCaster->IsAlive()) { - healthGain = unitCaster->SpellHealingBonusDone(unitCaster, m_spellInfo, healthGain, HEAL, effectInfo); + healthGain = unitCaster->SpellHealingBonusDone(unitCaster, m_spellInfo, healthGain, HEAL, *effectInfo); healthGain = unitCaster->SpellHealingBonusTaken(unitCaster, m_spellInfo, healthGain, HEAL); HealInfo healInfo(unitCaster, unitCaster, healthGain, m_spellInfo, m_spellSchoolMask); @@ -1445,10 +1445,9 @@ void Spell::EffectPersistentAA() return; // only handle at last effect - for (uint8 i = effectInfo->EffectIndex + 1; i < MAX_SPELL_EFFECTS; ++i) - if (SpellEffectInfo const* otherEffect = m_spellInfo->GetEffect(i)) - if (otherEffect && otherEffect->IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA)) - return; + for (size_t i = effectInfo->EffectIndex + 1; i < m_spellInfo->GetEffects().size(); ++i) + if (m_spellInfo->GetEffect(SpellEffIndex(i)).IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA)) + return; ASSERT(!_dynObjAura); @@ -2765,17 +2764,15 @@ void Spell::EffectWeaponDmg() // and handle all effects at once for (size_t j = effectInfo->EffectIndex + 1; j < m_spellInfo->GetEffects().size(); ++j) { - SpellEffectInfo const* effect = m_spellInfo->GetEffect(j); - if (!effect) - continue; - switch (effect->Effect) + switch (m_spellInfo->GetEffect(SpellEffIndex(j)).Effect) { case SPELL_EFFECT_WEAPON_DAMAGE: case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL: case SPELL_EFFECT_NORMALIZED_WEAPON_DMG: case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE: return; // we must calculate only at last weapon effect - break; + default: + break; } } @@ -2798,22 +2795,20 @@ void Spell::EffectWeaponDmg() bool normalized = false; float weaponDamagePercentMod = 1.0f; - for (SpellEffectInfo const* effect : m_spellInfo->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) { - if (!effect) - continue; - switch (effect->Effect) + switch (spellEffectInfo.Effect) { case SPELL_EFFECT_WEAPON_DAMAGE: case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL: - fixed_bonus += CalculateDamage(effect->EffectIndex, unitTarget); + fixed_bonus += CalculateDamage(spellEffectInfo, unitTarget); break; case SPELL_EFFECT_NORMALIZED_WEAPON_DMG: - fixed_bonus += CalculateDamage(effect->EffectIndex, unitTarget); + fixed_bonus += CalculateDamage(spellEffectInfo, unitTarget); normalized = true; break; case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE: - ApplyPct(weaponDamagePercentMod, CalculateDamage(effect->EffectIndex, unitTarget)); + ApplyPct(weaponDamagePercentMod, CalculateDamage(spellEffectInfo, unitTarget)); break; default: break; // not weapon damage effect, just skip @@ -2844,13 +2839,11 @@ void Spell::EffectWeaponDmg() int32 weaponDamage = unitCaster->CalculateDamage(m_attackType, normalized, addPctMods); // Sequence is important - for (SpellEffectInfo const* effect : m_spellInfo->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) { - if (!effect) - continue; // We assume that a spell have at most one fixed_bonus // and at most one weaponDamagePercentMod - switch (effect->Effect) + switch (spellEffectInfo.Effect) { case SPELL_EFFECT_WEAPON_DAMAGE: case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL: @@ -3276,8 +3269,8 @@ void Spell::EffectScriptEffect() return; // Effects for 58418 and 58420 are all DIFFICULTY_NONE so always valid - uint32 spellID = m_spellInfo->GetEffect(EFFECT_0)->CalcValue(); - uint32 questID = m_spellInfo->GetEffect(EFFECT_1)->CalcValue(); + uint32 spellID = m_spellInfo->GetEffect(EFFECT_0).CalcValue(); + uint32 questID = m_spellInfo->GetEffect(EFFECT_1).CalcValue(); if (unitTarget->ToPlayer()->GetQuestStatus(questID) == QUEST_STATUS_COMPLETE) unitTarget->CastSpell(unitTarget, spellID, true); @@ -3312,7 +3305,7 @@ void Spell::EffectScriptEffect() { /// @todo a hack, range = 11, should after some time cast, otherwise too far unitCaster->CastSpell(parent, 62496, true); - unitTarget->CastSpell(parent, m_spellInfo->GetEffect(EFFECT_0)->CalcValue()); // DIFFICULTY_NONE, so effect always valid + unitTarget->CastSpell(parent, damage); // DIFFICULTY_NONE, so effect always valid } } } diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp index e343eba170d..db87c917797 100644 --- a/src/server/game/Spells/SpellInfo.cpp +++ b/src/server/game/Spells/SpellInfo.cpp @@ -17,6 +17,7 @@ #include "SpellInfo.h" #include "Battleground.h" +#include "Containers.h" #include "Corpse.h" #include "DB2Stores.h" #include "GameTables.h" @@ -377,9 +378,9 @@ SpellEffectInfo::SpellEffectInfo(SpellInfo const* spellInfo, SpellEffectEntry co ASSERT(spellInfo); _spellInfo = spellInfo; - EffectIndex = _effect.EffectIndex; - Effect = _effect.Effect; - ApplyAuraName = _effect.EffectAura; + EffectIndex = SpellEffIndex(_effect.EffectIndex); + Effect = SpellEffectName(_effect.Effect); + ApplyAuraName = AuraType(_effect.EffectAura); ApplyAuraPeriod = _effect.EffectAuraPeriod; BasePoints = _effect.EffectBasePoints; RealPointsPerLevel = _effect.EffectRealPointsPerLevel; @@ -1088,11 +1089,9 @@ SpellInfo::SpellInfo(SpellNameEntry const* spellName, ::Difficulty difficulty, S if (!spellEffect) continue; - if (uint32(spellEffect->EffectIndex) >= _effects.size()) - _effects.resize(spellEffect->EffectIndex + 1); - - _effects[spellEffect->EffectIndex] = new SpellEffectInfo(this, *spellEffect); + Trinity::Containers::EnsureWritableVectorIndex(_effects, spellEffect->EffectIndex, SpellEffectInfo(this)) = SpellEffectInfo(this, *spellEffect); } + _effects.shrink_to_fit(); SpellName = &spellName->Name; @@ -1272,27 +1271,14 @@ SpellInfo::SpellInfo(SpellNameEntry const* spellName, ::Difficulty difficulty, s _effects.reserve(32); for (SpellEffectEntry const& spellEffect : effects) - { - if (uint32(spellEffect.EffectIndex) >= _effects.size()) - _effects.resize(spellEffect.EffectIndex + 1); + Trinity::Containers::EnsureWritableVectorIndex(_effects, spellEffect.EffectIndex, SpellEffectInfo(this)) = SpellEffectInfo(this, spellEffect); - _effects[spellEffect.EffectIndex] = new SpellEffectInfo(this, spellEffect); - } _effects.shrink_to_fit(); } SpellInfo::~SpellInfo() { _UnloadImplicitTargetConditionLists(); - _UnloadSpellEffects(); -} - -void SpellInfo::_UnloadSpellEffects() -{ - for (SpellEffectInfo const* effect : _effects) - delete effect; - - _effects.clear(); } uint32 SpellInfo::GetCategory() const @@ -1302,8 +1288,8 @@ uint32 SpellInfo::GetCategory() const bool SpellInfo::HasEffect(SpellEffectName effect) const { - for (SpellEffectInfo const* eff : _effects) - if (eff && eff->IsEffect(effect)) + for (SpellEffectInfo const& eff : GetEffects()) + if (eff.IsEffect(effect)) return true; return false; @@ -1311,8 +1297,8 @@ bool SpellInfo::HasEffect(SpellEffectName effect) const bool SpellInfo::HasAura(AuraType aura) const { - for (SpellEffectInfo const* effect : _effects) - if (effect && effect->IsAura(aura)) + for (SpellEffectInfo const& effect : GetEffects()) + if (effect.IsAura(aura)) return true; return false; @@ -1320,8 +1306,8 @@ bool SpellInfo::HasAura(AuraType aura) const bool SpellInfo::HasAreaAuraEffect() const { - for (SpellEffectInfo const* effect : _effects) - if (effect && effect->IsAreaAuraEffect()) + for (SpellEffectInfo const& effect : GetEffects()) + if (effect.IsAreaAuraEffect()) return true; return false; @@ -1329,24 +1315,24 @@ bool SpellInfo::HasAreaAuraEffect() const bool SpellInfo::HasOnlyDamageEffects() const { - for (SpellEffectInfo const* effect : _effects) + for (SpellEffectInfo const& effect : GetEffects()) { - if (!effect) - continue; - - switch (effect->Effect) + if (effect.IsEffect()) { - case SPELL_EFFECT_WEAPON_DAMAGE: - case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL: - case SPELL_EFFECT_NORMALIZED_WEAPON_DMG: - case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE: - case SPELL_EFFECT_SCHOOL_DAMAGE: - case SPELL_EFFECT_ENVIRONMENTAL_DAMAGE: - case SPELL_EFFECT_HEALTH_LEECH: - case SPELL_EFFECT_DAMAGE_FROM_MAX_HEALTH_PCT: - continue; - default: - return false; + switch (effect.Effect) + { + case SPELL_EFFECT_WEAPON_DAMAGE: + case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL: + case SPELL_EFFECT_NORMALIZED_WEAPON_DMG: + case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE: + case SPELL_EFFECT_SCHOOL_DAMAGE: + case SPELL_EFFECT_ENVIRONMENTAL_DAMAGE: + case SPELL_EFFECT_HEALTH_LEECH: + case SPELL_EFFECT_DAMAGE_FROM_MAX_HEALTH_PCT: + continue; + default: + return false; + } } } @@ -1355,8 +1341,8 @@ bool SpellInfo::HasOnlyDamageEffects() const bool SpellInfo::HasTargetType(::Targets target) const { - for (SpellEffectInfo const* effect : _effects) - if (effect && (effect->TargetA.GetTarget() == target || effect->TargetB.GetTarget() == target)) + for (SpellEffectInfo const& effect : GetEffects()) + if (effect.TargetA.GetTarget() == target || effect.TargetB.GetTarget() == target) return true; return false; @@ -1381,11 +1367,12 @@ bool SpellInfo::HasAnyAuraInterruptFlag() const bool SpellInfo::IsExplicitDiscovery() const { - SpellEffectInfo const* effect0 = GetEffect(EFFECT_0); - SpellEffectInfo const* effect1 = GetEffect(EFFECT_1); + if (GetEffects().size() < 2) + return false; - return ((effect0 && (effect0->Effect == SPELL_EFFECT_CREATE_RANDOM_ITEM || effect0->Effect == SPELL_EFFECT_CREATE_LOOT)) - && effect1 && effect1->Effect == SPELL_EFFECT_SCRIPT_EFFECT) + return ((GetEffect(EFFECT_0).Effect == SPELL_EFFECT_CREATE_RANDOM_ITEM + || GetEffect(EFFECT_0).Effect == SPELL_EFFECT_CREATE_LOOT) + && GetEffect(EFFECT_1).Effect == SPELL_EFFECT_SCRIPT_EFFECT) || Id == 64323; } @@ -1396,18 +1383,19 @@ bool SpellInfo::IsLootCrafting() const bool SpellInfo::IsQuestTame() const { - SpellEffectInfo const* effect0 = GetEffect(EFFECT_0); - SpellEffectInfo const* effect1 = GetEffect(EFFECT_1); - return effect0 && effect1 && effect0->Effect == SPELL_EFFECT_THREAT && effect1->Effect == SPELL_EFFECT_APPLY_AURA && effect1->ApplyAuraName == SPELL_AURA_DUMMY; + if (GetEffects().size() < 2) + return false; + + return GetEffect(EFFECT_0).Effect == SPELL_EFFECT_THREAT && GetEffect(EFFECT_1).Effect == SPELL_EFFECT_APPLY_AURA && GetEffect(EFFECT_1).ApplyAuraName == SPELL_AURA_DUMMY; } bool SpellInfo::IsProfession() const { - for (SpellEffectInfo const* effect : _effects) + for (SpellEffectInfo const& effect : GetEffects()) { - if (effect && effect->Effect == SPELL_EFFECT_SKILL) + if (effect.Effect == SPELL_EFFECT_SKILL) { - uint32 skill = effect->MiscValue; + uint32 skill = effect.MiscValue; if (IsProfessionSkill(skill)) return true; @@ -1418,11 +1406,11 @@ bool SpellInfo::IsProfession() const bool SpellInfo::IsPrimaryProfession() const { - for (SpellEffectInfo const* effect : _effects) + for (SpellEffectInfo const& effect : GetEffects()) { - if (effect && effect->Effect == SPELL_EFFECT_SKILL) + if (effect.Effect == SPELL_EFFECT_SKILL) { - uint32 skill = effect->MiscValue; + uint32 skill = effect.MiscValue; if (IsPrimaryProfessionSkill(skill)) return true; @@ -1449,8 +1437,8 @@ bool SpellInfo::IsAbilityOfSkillType(uint32 skillType) const bool SpellInfo::IsAffectingArea() const { - for (SpellEffectInfo const* effect : _effects) - if (effect && effect->IsEffect() && (effect->IsTargetingArea() || effect->IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA) || effect->IsAreaAuraEffect())) + for (SpellEffectInfo const& effect : GetEffects()) + if (effect.IsEffect() && (effect.IsTargetingArea() || effect.IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA) || effect.IsAreaAuraEffect())) return true; return false; @@ -1459,8 +1447,8 @@ bool SpellInfo::IsAffectingArea() const // checks if spell targets are selected from area, doesn't include spell effects in check (like area wide auras for example) bool SpellInfo::IsTargetingArea() const { - for (SpellEffectInfo const* effect : _effects) - if (effect && effect->IsEffect() && effect->IsTargetingArea()) + for (SpellEffectInfo const& effect : GetEffects()) + if (effect.IsEffect() && effect.IsTargetingArea()) return true; return false; @@ -1477,12 +1465,12 @@ bool SpellInfo::NeedsToBeTriggeredByCaster(SpellInfo const* triggeringSpell) con return true; /* - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const& effect : GetEffects()) { - if (Effects[i].IsEffect()) + if (effect.IsEffect()) { - if (Effects[i].TargetA.GetSelectionCategory() == TARGET_SELECT_CATEGORY_CHANNEL - || Effects[i].TargetB.GetSelectionCategory() == TARGET_SELECT_CATEGORY_CHANNEL) + if (effect.TargetA.GetSelectionCategory() == TARGET_SELECT_CATEGORY_CHANNEL + || effect.TargetB.GetSelectionCategory() == TARGET_SELECT_CATEGORY_CHANNEL) return true; } } @@ -1491,15 +1479,12 @@ bool SpellInfo::NeedsToBeTriggeredByCaster(SpellInfo const* triggeringSpell) con if (triggeringSpell->IsChanneled()) { uint32 mask = 0; - for (SpellEffectInfo const* effect : _effects) + for (SpellEffectInfo const& effect : GetEffects()) { - if (!effect) - continue; - - if (effect->TargetA.GetTarget() != TARGET_UNIT_CASTER && effect->TargetA.GetTarget() != TARGET_DEST_CASTER - && effect->TargetB.GetTarget() != TARGET_UNIT_CASTER && effect->TargetB.GetTarget() != TARGET_DEST_CASTER) + if (effect.TargetA.GetTarget() != TARGET_UNIT_CASTER && effect.TargetA.GetTarget() != TARGET_DEST_CASTER + && effect.TargetB.GetTarget() != TARGET_UNIT_CASTER && effect.TargetB.GetTarget() != TARGET_DEST_CASTER) { - mask |= effect->GetProvidedTargetMask(); + mask |= effect.GetProvidedTargetMask(); } } @@ -1530,22 +1515,19 @@ bool SpellInfo::IsStackableWithRanks() const return false; // All stance spells. if any better way, change it. - for (SpellEffectInfo const* effect : _effects) + for (SpellEffectInfo const& effect : GetEffects()) { - if (!effect) - continue; - switch (SpellFamilyName) { case SPELLFAMILY_PALADIN: // Paladin aura Spell - if (effect->Effect == SPELL_EFFECT_APPLY_AREA_AURA_RAID) + if (effect.Effect == SPELL_EFFECT_APPLY_AREA_AURA_RAID) return false; break; case SPELLFAMILY_DRUID: // Druid form Spell - if (effect->Effect == SPELL_EFFECT_APPLY_AURA && - effect->ApplyAuraName == SPELL_AURA_MOD_SHAPESHIFT) + if (effect.Effect == SPELL_EFFECT_APPLY_AURA && + effect.ApplyAuraName == SPELL_AURA_MOD_SHAPESHIFT) return false; break; } @@ -1594,12 +1576,12 @@ bool SpellInfo::IsAllowingDeadTarget() const if (HasAttribute(SPELL_ATTR2_CAN_TARGET_DEAD) || Targets & (TARGET_FLAG_CORPSE_ALLY | TARGET_FLAG_CORPSE_ENEMY | TARGET_FLAG_UNIT_DEAD)) return true; - for (SpellEffectInfo const* effect : _effects) + for (SpellEffectInfo const& effect : GetEffects()) { - if (!effect) + if (!effect.IsEffect()) continue; - if (effect->TargetA.GetObjectType() == TARGET_OBJECT_TYPE_CORPSE || effect->TargetB.GetObjectType() == TARGET_OBJECT_TYPE_CORPSE) + if (effect.TargetA.GetObjectType() == TARGET_OBJECT_TYPE_CORPSE || effect.TargetB.GetObjectType() == TARGET_OBJECT_TYPE_CORPSE) return true; } @@ -1608,12 +1590,9 @@ bool SpellInfo::IsAllowingDeadTarget() const bool SpellInfo::IsGroupBuff() const { - for (SpellEffectInfo const* effect : _effects) + for (SpellEffectInfo const& effect : GetEffects()) { - if (!effect) - continue; - - switch (effect->TargetA.GetCheckType()) + switch (effect.TargetA.GetCheckType()) { case TARGET_CHECK_PARTY: case TARGET_CHECK_RAID: @@ -1880,8 +1859,7 @@ SpellCastResult SpellInfo::CheckShapeshift(uint32 form) const // talents that learn spells can have stance requirements that need ignore // (this requirement only for client-side stance show in talent description) /* TODO: 6.x fix this in proper way (probably spell flags/attributes?) - if (GetTalentSpellCost(Id) > 0 && - (Effects[0].Effect == SPELL_EFFECT_LEARN_SPELL || Effects[1].Effect == SPELL_EFFECT_LEARN_SPELL || Effects[2].Effect == SPELL_EFFECT_LEARN_SPELL)) + if (GetTalentSpellCost(Id) > 0 && HasEffect(SPELL_EFFECT_LEARN_SPELL)) return SPELL_CAST_OK;*/ //if (HasAttribute(SPELL_ATTR13_ACTIVATES_REQUIRED_SHAPESHIFT)) @@ -2063,16 +2041,16 @@ SpellCastResult SpellInfo::CheckLocation(uint32 map_id, uint32 zone_id, uint32 a // aura limitations if (player) { - for (SpellEffectInfo const* effect : _effects) + for (SpellEffectInfo const& effect : GetEffects()) { - if (!effect || !effect->IsAura()) + if (!effect.IsAura()) continue; - switch (effect->ApplyAuraName) + switch (effect.ApplyAuraName) { case SPELL_AURA_MOD_SHAPESHIFT: { - if (SpellShapeshiftFormEntry const* spellShapeshiftForm = sSpellShapeshiftFormStore.LookupEntry(effect->MiscValue)) + if (SpellShapeshiftFormEntry const* spellShapeshiftForm = sSpellShapeshiftFormStore.LookupEntry(effect.MiscValue)) if (uint32 mountType = spellShapeshiftForm->MountTypeID) if (!player->GetMountCapability(mountType)) return SPELL_FAILED_NOT_HERE; @@ -2080,13 +2058,15 @@ SpellCastResult SpellInfo::CheckLocation(uint32 map_id, uint32 zone_id, uint32 a } case SPELL_AURA_MOUNTED: { - uint32 mountType = effect->MiscValueB; + uint32 mountType = effect.MiscValueB; if (MountEntry const* mountEntry = sDB2Manager.GetMount(Id)) mountType = mountEntry->MountTypeID; if (mountType && !player->GetMountCapability(mountType)) return SPELL_FAILED_NOT_HERE; break; } + default: + break; } } } @@ -2294,11 +2274,11 @@ SpellCastResult SpellInfo::CheckVehicle(Unit const* caster) const if (vehicle) { uint16 checkMask = 0; - for (SpellEffectInfo const* effect : _effects) + for (SpellEffectInfo const& effect : GetEffects()) { - if (effect && effect->ApplyAuraName == SPELL_AURA_MOD_SHAPESHIFT) + if (effect.IsAura(SPELL_AURA_MOD_SHAPESHIFT)) { - SpellShapeshiftFormEntry const* shapeShiftFromEntry = sSpellShapeshiftFormStore.LookupEntry(effect->MiscValue); + SpellShapeshiftFormEntry const* shapeShiftFromEntry = sSpellShapeshiftFormStore.LookupEntry(effect.MiscValue); if (shapeShiftFromEntry && (shapeShiftFromEntry->Flags & 1) == 0) // unk flag checkMask |= VEHICLE_SEAT_FLAG_UNCONTROLLED; break; @@ -2319,12 +2299,12 @@ SpellCastResult SpellInfo::CheckVehicle(Unit const* caster) const // Can only summon uncontrolled minions/guardians when on controlled vehicle if (vehicleSeat->Flags & (VEHICLE_SEAT_FLAG_CAN_CONTROL | VEHICLE_SEAT_FLAG_UNK2)) { - for (SpellEffectInfo const* effect : _effects) + for (SpellEffectInfo const& effect : GetEffects()) { - if (!effect || effect->Effect != SPELL_EFFECT_SUMMON) + if (!effect.IsEffect(SPELL_EFFECT_SUMMON)) continue; - SummonPropertiesEntry const* props = sSummonPropertiesStore.LookupEntry(effect->MiscValueB); + SummonPropertiesEntry const* props = sSummonPropertiesStore.LookupEntry(effect.MiscValueB); if (props && props->Control != SUMMON_CATEGORY_WILD) return SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW; } @@ -2365,21 +2345,21 @@ uint32 SpellInfo::GetAllEffectsMechanicMask() const if (Mechanic) mask |= 1 << Mechanic; - for (SpellEffectInfo const* effect : _effects) - if (effect && effect->IsEffect() && effect->Mechanic) - mask |= 1 << effect->Mechanic; + for (SpellEffectInfo const& effect : GetEffects()) + if (effect.IsEffect() && effect.Mechanic) + mask |= 1 << effect.Mechanic; return mask; } -uint32 SpellInfo::GetEffectMechanicMask(uint32 effIndex) const +uint32 SpellInfo::GetEffectMechanicMask(SpellEffIndex effIndex) const { uint32 mask = 0; if (Mechanic) mask |= 1 << Mechanic; - if (effIndex < _effects.size() && _effects[effIndex] && _effects[effIndex]->IsEffect() && _effects[effIndex]->Mechanic) - mask |= 1 << _effects[effIndex]->Mechanic; + if (GetEffect(effIndex).IsEffect() && GetEffect(effIndex).Mechanic) + mask |= 1 << GetEffect(effIndex).Mechanic; return mask; } @@ -2390,18 +2370,17 @@ uint32 SpellInfo::GetSpellMechanicMaskByEffectMask(uint32 effectMask) const if (Mechanic) mask |= 1 << Mechanic; - for (SpellEffectInfo const* effect : _effects) - if (effect && (effectMask & (1 << effect->EffectIndex)) && effect->Mechanic) - mask |= 1 << effect->Mechanic; + for (SpellEffectInfo const& effect : GetEffects()) + if ((effectMask & (1 << effect.EffectIndex)) && effect.Mechanic) + mask |= 1 << effect.Mechanic; return mask; } -Mechanics SpellInfo::GetEffectMechanic(uint32 effIndex) const +Mechanics SpellInfo::GetEffectMechanic(SpellEffIndex effIndex) const { - SpellEffectInfo const* effect = GetEffect(effIndex); - if (effect && effect->IsEffect() && effect->Mechanic) - return Mechanics(effect->Mechanic); + if (GetEffect(effIndex).IsEffect() && GetEffect(effIndex).Mechanic) + return GetEffect(effIndex).Mechanic; if (Mechanic) return Mechanics(Mechanic); @@ -2409,14 +2388,6 @@ Mechanics SpellInfo::GetEffectMechanic(uint32 effIndex) const return MECHANIC_NONE; } -/*bool SpellInfo::HasAnyEffectMechanic() const -{ - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - if (Effects[i].Mechanic) - return true; - return false; -}*/ - uint32 SpellInfo::GetDispelMask() const { return GetDispelMask(DispelType(Dispel)); @@ -2466,8 +2437,8 @@ void SpellInfo::_LoadAuraState() return AURA_STATE_BLEED; if (GetSchoolMask() & SPELL_SCHOOL_MASK_FROST) - for (SpellEffectInfo const* effect : _effects) - if (effect && (effect->IsAura(SPELL_AURA_MOD_STUN) || effect->IsAura(SPELL_AURA_MOD_ROOT))) + for (SpellEffectInfo const& effect : GetEffects()) + if (effect.IsAura(SPELL_AURA_MOD_STUN) || effect.IsAura(SPELL_AURA_MOD_ROOT) || effect.IsAura(SPELL_AURA_MOD_ROOT_2)) return AURA_STATE_FROZEN; switch (Id) @@ -2539,11 +2510,11 @@ void SpellInfo::_LoadSpellSpecific() { bool food = false; bool drink = false; - for (SpellEffectInfo const* effect : _effects) + for (SpellEffectInfo const& effect : GetEffects()) { - if (!effect || !effect->IsAura()) + if (!effect.IsAura()) continue; - switch (effect->ApplyAuraName) + switch (effect.ApplyAuraName) { // Food case SPELL_AURA_MOD_REGEN: @@ -2595,8 +2566,8 @@ void SpellInfo::_LoadSpellSpecific() // Arcane brillance and Arcane intelect (normal check fails because of flags difference) if (SpellFamilyFlags[0] & 0x400) return SPELL_SPECIFIC_MAGE_ARCANE_BRILLANCE; - SpellEffectInfo const* effect = GetEffect(EFFECT_0); - if (effect && (SpellFamilyFlags[0] & 0x1000000) && effect->ApplyAuraName == SPELL_AURA_MOD_CONFUSE) + + if ((SpellFamilyFlags[0] & 0x1000000) && GetEffect(EFFECT_0).IsAura(SPELL_AURA_MOD_CONFUSE)) return SPELL_SPECIFIC_MAGE_POLYMORPH; break; @@ -2690,11 +2661,11 @@ void SpellInfo::_LoadSpellSpecific() break; } - for (SpellEffectInfo const* effect : _effects) + for (SpellEffectInfo const& effect : GetEffects()) { - if (effect && effect->Effect == SPELL_EFFECT_APPLY_AURA) + if (effect.IsEffect(SPELL_EFFECT_APPLY_AURA)) { - switch (effect->ApplyAuraName) + switch (effect.ApplyAuraName) { case SPELL_AURA_MOD_CHARM: case SPELL_AURA_MOD_POSSESS_PET: @@ -2709,6 +2680,8 @@ void SpellInfo::_LoadSpellSpecific() case SPELL_AURA_TRACK_RESOURCES: case SPELL_AURA_TRACK_STEALTHED: return SPELL_SPECIFIC_TRACKER; + default: + break; } } } @@ -3191,7 +3164,7 @@ int32 SpellInfo::GetDiminishingReturnsLimitDuration() const void SpellInfo::_LoadImmunityInfo() { - auto loadImmunityInfoFn = [this](SpellEffectInfo* effectInfo) + for (SpellEffectInfo& effect : _effects) { uint32 schoolImmunityMask = 0; uint32 applyHarmfulAuraImmunityMask = 0; @@ -3199,12 +3172,12 @@ void SpellInfo::_LoadImmunityInfo() uint32 dispelImmunity = 0; uint32 damageImmunityMask = 0; - int32 miscVal = effectInfo->MiscValue; - int32 amount = effectInfo->CalcValue(); + int32 miscVal = effect.MiscValue; + int32 amount = effect.CalcValue(); - ImmunityInfo& immuneInfo = *const_cast<ImmunityInfo*>(effectInfo->GetImmunityInfo()); + ImmunityInfo& immuneInfo = effect._immunityInfo; - switch (effectInfo->ApplyAuraName) + switch (effect.ApplyAuraName) { case SPELL_AURA_MECHANIC_IMMUNITY_MASK: { @@ -3448,14 +3421,6 @@ void SpellInfo::_LoadImmunityInfo() immuneInfo.SpellEffectImmune.shrink_to_fit(); _allowedMechanicMask |= immuneInfo.MechanicImmuneMask; - }; - - for (SpellEffectInfo const* effect : _effects) - { - if (!effect) - continue; - - loadImmunityInfoFn(const_cast<SpellEffectInfo*>(effect)); } if (HasAttribute(SPELL_ATTR5_USABLE_WHILE_STUNNED)) @@ -3496,9 +3461,9 @@ void SpellInfo::_LoadImmunityInfo() } } -void SpellInfo::ApplyAllSpellImmunitiesTo(Unit* target, SpellEffectInfo const* effect, bool apply) const +void SpellInfo::ApplyAllSpellImmunitiesTo(Unit* target, SpellEffectInfo const& spellEffectInfo, bool apply) const { - ImmunityInfo const* immuneInfo = effect->GetImmunityInfo(); + ImmunityInfo const* immuneInfo = spellEffectInfo.GetImmunityInfo(); if (uint32 schoolImmunity = immuneInfo->SchoolImmuneMask) { @@ -3572,12 +3537,12 @@ bool SpellInfo::CanSpellProvideImmunityAgainstAura(SpellInfo const* auraSpellInf if (!auraSpellInfo) return false; - for (SpellEffectInfo const* effectInfo : _effects) + for (SpellEffectInfo const& effectInfo : _effects) { - if (!effectInfo) + if (!effectInfo.IsEffect()) continue; - ImmunityInfo const* immuneInfo = effectInfo->GetImmunityInfo(); + ImmunityInfo const* immuneInfo = effectInfo.GetImmunityInfo(); if (!auraSpellInfo->HasAttribute(SPELL_ATTR1_UNAFFECTED_BY_SCHOOL_IMMUNE) && !auraSpellInfo->HasAttribute(SPELL_ATTR2_UNAFFECTED_BY_AURA_SCHOOL_IMMUNE)) { @@ -3595,23 +3560,19 @@ bool SpellInfo::CanSpellProvideImmunityAgainstAura(SpellInfo const* auraSpellInf return true; bool immuneToAllEffects = true; - for (SpellEffectInfo const* auraSpellEffectInfo : auraSpellInfo->GetEffects()) + for (SpellEffectInfo const& auraSpellEffectInfo : auraSpellInfo->GetEffects()) { - if (!auraSpellEffectInfo) - continue; - - uint32 effectName = auraSpellEffectInfo->Effect; - if (!effectName) + if (!auraSpellEffectInfo.IsEffect()) continue; - auto spellImmuneItr = immuneInfo->SpellEffectImmune.find(static_cast<SpellEffectName>(effectName)); + auto spellImmuneItr = immuneInfo->SpellEffectImmune.find(auraSpellEffectInfo.Effect); if (spellImmuneItr == immuneInfo->SpellEffectImmune.cend()) { immuneToAllEffects = false; break; } - if (uint32 mechanic = auraSpellEffectInfo->Mechanic) + if (uint32 mechanic = auraSpellEffectInfo.Mechanic) { if (!(immuneInfo->MechanicImmuneMask & (1 << mechanic))) { @@ -3622,14 +3583,14 @@ bool SpellInfo::CanSpellProvideImmunityAgainstAura(SpellInfo const* auraSpellInf if (!auraSpellInfo->HasAttribute(SPELL_ATTR3_IGNORE_HIT_RESULT)) { - if (uint32 auraName = auraSpellEffectInfo->ApplyAuraName) + if (AuraType auraName = auraSpellEffectInfo.ApplyAuraName) { bool isImmuneToAuraEffectApply = false; - auto auraImmuneItr = immuneInfo->AuraTypeImmune.find(static_cast<AuraType>(auraName)); + auto auraImmuneItr = immuneInfo->AuraTypeImmune.find(auraName); if (auraImmuneItr != immuneInfo->AuraTypeImmune.cend()) isImmuneToAuraEffectApply = true; - if (!isImmuneToAuraEffectApply && !auraSpellInfo->IsPositiveEffect(auraSpellEffectInfo->EffectIndex) && !auraSpellInfo->HasAttribute(SPELL_ATTR2_UNAFFECTED_BY_AURA_SCHOOL_IMMUNE)) + if (!isImmuneToAuraEffectApply && !auraSpellInfo->IsPositiveEffect(auraSpellEffectInfo.EffectIndex) && !auraSpellInfo->HasAttribute(SPELL_ATTR2_UNAFFECTED_BY_AURA_SCHOOL_IMMUNE)) { if (uint32 applyHarmfulAuraImmunityMask = immuneInfo->ApplyHarmfulAuraImmuneMask) if ((auraSpellInfo->GetSchoolMask() & applyHarmfulAuraImmunityMask) != 0) @@ -3661,19 +3622,16 @@ bool SpellInfo::SpellCancelsAuraEffect(AuraEffect const* aurEff) const if (aurEff->GetSpellInfo()->HasAttribute(SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY)) return false; - for (SpellEffectInfo const* effectInfo : _effects) + for (SpellEffectInfo const& effect : GetEffects()) { - if (!effectInfo) + if (effect.IsEffect(SPELL_EFFECT_APPLY_AURA)) continue; - if (effectInfo->Effect != SPELL_EFFECT_APPLY_AURA) - continue; - - uint32 const miscValue = static_cast<uint32>(effectInfo->MiscValue); - switch (effectInfo->ApplyAuraName) + uint32 const miscValue = static_cast<uint32>(effect.MiscValue); + switch (effect.ApplyAuraName) { case SPELL_AURA_STATE_IMMUNITY: - if (miscValue != aurEff->GetSpellEffectInfo()->ApplyAuraName) + if (miscValue != aurEff->GetAuraType()) continue; break; case SPELL_AURA_SCHOOL_IMMUNITY: @@ -3688,7 +3646,7 @@ bool SpellInfo::SpellCancelsAuraEffect(AuraEffect const* aurEff) const case SPELL_AURA_MECHANIC_IMMUNITY: if (miscValue != aurEff->GetSpellInfo()->Mechanic) { - if (miscValue != aurEff->GetSpellEffectInfo()->Mechanic) + if (miscValue != aurEff->GetSpellEffectInfo().Mechanic) continue; } break; @@ -3774,11 +3732,11 @@ uint32 SpellInfo::GetMaxTicks() const uint32 totalTicks = 0; int32 DotDuration = GetDuration(); - for (SpellEffectInfo const* effect : _effects) + for (SpellEffectInfo const& effect : GetEffects()) { - if (effect && effect->Effect == SPELL_EFFECT_APPLY_AURA) + if (effect.IsEffect(SPELL_EFFECT_APPLY_AURA)) { - switch (effect->ApplyAuraName) + switch (effect.ApplyAuraName) { case SPELL_AURA_PERIODIC_DAMAGE: case SPELL_AURA_PERIODIC_DAMAGE_PERCENT: @@ -3795,13 +3753,15 @@ uint32 SpellInfo::GetMaxTicks() const case SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE: case SPELL_AURA_PERIODIC_HEALTH_FUNNEL: // skip infinite periodics - if (effect->ApplyAuraPeriod > 0 && DotDuration > 0) + if (effect.ApplyAuraPeriod > 0 && DotDuration > 0) { - totalTicks = static_cast<uint32>(DotDuration) / effect->ApplyAuraPeriod; + totalTicks = static_cast<uint32>(DotDuration) / effect.ApplyAuraPeriod; if (HasAttribute(SPELL_ATTR5_START_PERIODIC_AT_APPLY)) ++totalTicks; } break; + default: + break; } } } @@ -4239,13 +4199,13 @@ SpellInfo const* SpellInfo::GetAuraRankForLevel(uint8 level) const return this; bool needRankSelection = false; - for (SpellEffectInfo const* effect : _effects) + for (SpellEffectInfo const& effect : GetEffects()) { - if (effect && IsPositiveEffect(effect->EffectIndex) && - (effect->Effect == SPELL_EFFECT_APPLY_AURA || - effect->Effect == SPELL_EFFECT_APPLY_AREA_AURA_PARTY || - effect->Effect == SPELL_EFFECT_APPLY_AREA_AURA_RAID) && - !effect->Scaling.Coefficient) + if (IsPositiveEffect(effect.EffectIndex) && + (effect.Effect == SPELL_EFFECT_APPLY_AURA || + effect.Effect == SPELL_EFFECT_APPLY_AREA_AURA_PARTY || + effect.Effect == SPELL_EFFECT_APPLY_AREA_AURA_RAID) && + !effect.Scaling.Coefficient) { needRankSelection = true; break; @@ -4322,20 +4282,20 @@ void SpellInfo::_InitializeExplicitTargetMask() bool dstSet = false; uint32 targetMask = Targets; // prepare target mask using effect target entries - for (SpellEffectInfo const* effect : _effects) + for (SpellEffectInfo const& effect : GetEffects()) { - if (!effect || !effect->IsEffect()) + if (!effect.IsEffect()) continue; - targetMask |= effect->TargetA.GetExplicitTargetMask(srcSet, dstSet); - targetMask |= effect->TargetB.GetExplicitTargetMask(srcSet, dstSet); + targetMask |= effect.TargetA.GetExplicitTargetMask(srcSet, dstSet); + targetMask |= effect.TargetB.GetExplicitTargetMask(srcSet, dstSet); // add explicit target flags based on spell effects which have EFFECT_IMPLICIT_TARGET_EXPLICIT and no valid target provided - if (effect->GetImplicitTargetType() != EFFECT_IMPLICIT_TARGET_EXPLICIT) + if (effect.GetImplicitTargetType() != EFFECT_IMPLICIT_TARGET_EXPLICIT) continue; // extend explicit target mask only if valid targets for effect could not be provided by target types - uint32 effectTargetMask = effect->GetMissingTargetMask(srcSet, dstSet, targetMask); + uint32 effectTargetMask = effect.GetMissingTargetMask(srcSet, dstSet, targetMask); // don't add explicit object/dest flags when spell has no max range if (GetMaxRange(true) == 0.0f && GetMaxRange(false) == 0.0f) @@ -4347,24 +4307,22 @@ void SpellInfo::_InitializeExplicitTargetMask() ExplicitTargetMask = targetMask; } -inline bool _isPositiveTarget(SpellInfo const* spellInfo, uint32 effIndex) +inline bool _isPositiveTarget(SpellEffectInfo const& effect) { - SpellEffectInfo const* effect = spellInfo->GetEffect(effIndex); - if (!effect || !effect->IsEffect()) + if (!effect.IsEffect()) return true; - return (effect->TargetA.GetCheckType() != TARGET_CHECK_ENEMY && - effect->TargetB.GetCheckType() != TARGET_CHECK_ENEMY); + return (effect.TargetA.GetCheckType() != TARGET_CHECK_ENEMY && + effect.TargetB.GetCheckType() != TARGET_CHECK_ENEMY); } -bool _isPositiveEffectImpl(SpellInfo const* spellInfo, uint32 effIndex, std::unordered_set<std::pair<SpellInfo const*, uint32>>& visited) +bool _isPositiveEffectImpl(SpellInfo const* spellInfo, SpellEffectInfo const& effect, std::unordered_set<std::pair<SpellInfo const*, SpellEffIndex>>& visited) { - SpellEffectInfo const* effect = spellInfo->GetEffect(effIndex); - if (!effect || !effect->IsEffect()) + if (!effect.IsEffect()) return true; // attribute may be already set in DB - if (!spellInfo->IsPositiveEffect(effIndex)) + if (!spellInfo->IsPositiveEffect(effect.EffectIndex)) return false; // passive auras like talents are all positive @@ -4375,9 +4333,9 @@ bool _isPositiveEffectImpl(SpellInfo const* spellInfo, uint32 effIndex, std::uno if (spellInfo->HasAttribute(SPELL_ATTR0_NEGATIVE_1)) return false; - visited.insert({ spellInfo, effIndex }); + visited.insert({ spellInfo, effect.EffectIndex }); - int32 bp = effect->CalcValue(); + int32 bp = effect.CalcValue(); switch (spellInfo->SpellFamilyName) { case SPELLFAMILY_GENERIC: @@ -4429,17 +4387,14 @@ bool _isPositiveEffectImpl(SpellInfo const* spellInfo, uint32 effIndex, std::uno if (spellInfo->HasAttribute(SPELL_ATTR1_DONT_REFRESH_DURATION_ON_RECAST)) { // check for targets, there seems to be an assortment of dummy triggering spells that should be negative - for (SpellEffectInfo const* otherEffect : spellInfo->GetEffects()) - if (otherEffect && !_isPositiveTarget(spellInfo, otherEffect->EffectIndex)) + for (SpellEffectInfo const& otherEffect : spellInfo->GetEffects()) + if (!_isPositiveTarget(otherEffect)) return false; } - for (SpellEffectInfo const* otherEffect : spellInfo->GetEffects()) + for (SpellEffectInfo const& otherEffect : spellInfo->GetEffects()) { - if (!otherEffect) - continue; - - switch (otherEffect->Effect) + switch (otherEffect.Effect) { case SPELL_EFFECT_HEAL: case SPELL_EFFECT_LEARN_SPELL: @@ -4448,17 +4403,17 @@ bool _isPositiveEffectImpl(SpellInfo const* spellInfo, uint32 effIndex, std::uno case SPELL_EFFECT_ENERGIZE_PCT: return true; case SPELL_EFFECT_INSTAKILL: - if (otherEffect->EffectIndex != effIndex && // for spells like 38044: instakill effect is negative but auras on target must count as buff - otherEffect->TargetA.GetTarget() == effect->TargetA.GetTarget() && - otherEffect->TargetB.GetTarget() == effect->TargetB.GetTarget()) + if (otherEffect.EffectIndex != effect.EffectIndex && // for spells like 38044: instakill effect is negative but auras on target must count as buff + otherEffect.TargetA.GetTarget() == effect.TargetA.GetTarget() && + otherEffect.TargetB.GetTarget() == effect.TargetB.GetTarget()) return false; default: break; } - if (otherEffect->IsAura()) + if (otherEffect.IsAura()) { - switch (otherEffect->ApplyAuraName) + switch (otherEffect.ApplyAuraName) { case SPELL_AURA_MOD_STEALTH: case SPELL_AURA_MOD_UNATTACKABLE: @@ -4473,7 +4428,7 @@ bool _isPositiveEffectImpl(SpellInfo const* spellInfo, uint32 effIndex, std::uno } } - switch (effect->Effect) + switch (effect.Effect) { case SPELL_EFFECT_WEAPON_DAMAGE: case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL: @@ -4506,12 +4461,12 @@ bool _isPositiveEffectImpl(SpellInfo const* spellInfo, uint32 effIndex, std::uno case SPELL_EFFECT_ATTACK_ME: case SPELL_EFFECT_POWER_BURN: // check targets - if (!_isPositiveTarget(spellInfo, effIndex)) + if (!_isPositiveTarget(effect)) return false; break; case SPELL_EFFECT_DISPEL: // non-positive dispel - switch (effect->MiscValue) + switch (effect.MiscValue) { case DISPEL_STEALTH: case DISPEL_INVISIBILITY: @@ -4522,14 +4477,14 @@ bool _isPositiveEffectImpl(SpellInfo const* spellInfo, uint32 effIndex, std::uno } // also check targets - if (!_isPositiveTarget(spellInfo, effIndex)) + if (!_isPositiveTarget(effect)) return false; break; case SPELL_EFFECT_DISPEL_MECHANIC: - if (!_isPositiveTarget(spellInfo, effIndex)) + if (!_isPositiveTarget(effect)) { // non-positive mechanic dispel on negative target - switch (effect->MiscValue) + switch (effect.MiscValue) { case MECHANIC_BANDAGE: case MECHANIC_SHIELD: @@ -4544,17 +4499,17 @@ bool _isPositiveEffectImpl(SpellInfo const* spellInfo, uint32 effIndex, std::uno case SPELL_EFFECT_THREAT: case SPELL_EFFECT_MODIFY_THREAT_PERCENT: // check targets AND basepoints - if (!_isPositiveTarget(spellInfo, effIndex) && bp > 0) + if (!_isPositiveTarget(effect) && bp > 0) return false; break; default: break; } - if (effect->IsAura()) + if (effect.IsAura()) { // non-positive aura use - switch (effect->ApplyAuraName) + switch (effect.ApplyAuraName) { case SPELL_AURA_MOD_DAMAGE_DONE: // dependent from basepoint sign (negative -> negative) case SPELL_AURA_MOD_STAT: @@ -4589,7 +4544,7 @@ bool _isPositiveEffectImpl(SpellInfo const* spellInfo, uint32 effIndex, std::uno case SPELL_AURA_MOD_ATTACK_POWER: case SPELL_AURA_MOD_RANGED_ATTACK_POWER: case SPELL_AURA_MOD_DAMAGE_PERCENT_DONE: - if (!_isPositiveTarget(spellInfo, effIndex) && bp < 0) + if (!_isPositiveTarget(effect) && bp < 0) return false; break; case SPELL_AURA_MOD_DAMAGE_TAKEN: // dependent from basepoint sign (positive -> negative) @@ -4603,33 +4558,30 @@ bool _isPositiveEffectImpl(SpellInfo const* spellInfo, uint32 effIndex, std::uno return false; break; case SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN: // check targets and basepoints (ex Recklessness) - if (!_isPositiveTarget(spellInfo, effIndex) && bp > 0) + if (!_isPositiveTarget(effect) && bp > 0) return false; break; case SPELL_AURA_ADD_TARGET_TRIGGER: return true; case SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE: case SPELL_AURA_PERIODIC_TRIGGER_SPELL: - if (!_isPositiveTarget(spellInfo, effIndex)) + if (!_isPositiveTarget(effect)) { - if (SpellInfo const* spellTriggeredProto = sSpellMgr->GetSpellInfo(effect->TriggerSpell, spellInfo->Difficulty)) + if (SpellInfo const* spellTriggeredProto = sSpellMgr->GetSpellInfo(effect.TriggerSpell, spellInfo->Difficulty)) { // negative targets of main spell return early - for (SpellEffectInfo const* spellTriggeredEffect : spellTriggeredProto->GetEffects()) + for (SpellEffectInfo const& spellTriggeredEffect : spellTriggeredProto->GetEffects()) { - if (!spellTriggeredEffect) - continue; - // already seen this - if (visited.count({ spellTriggeredProto, spellTriggeredEffect->EffectIndex }) > 0) + if (visited.count({ spellTriggeredProto, spellTriggeredEffect.EffectIndex }) > 0) continue; - if (!spellTriggeredEffect->IsEffect()) + if (!spellTriggeredEffect.IsEffect()) continue; // if non-positive trigger cast targeted to positive target this main cast is non-positive // this will place this spell auras as debuffs - if (_isPositiveTarget(spellTriggeredProto, spellTriggeredEffect->EffectIndex) && !_isPositiveEffectImpl(spellTriggeredProto, spellTriggeredEffect->EffectIndex, visited)) + if (_isPositiveTarget(spellTriggeredEffect) && !_isPositiveEffectImpl(spellTriggeredProto, spellTriggeredEffect, visited)) return false; } } @@ -4660,7 +4612,7 @@ bool _isPositiveEffectImpl(SpellInfo const* spellInfo, uint32 effIndex, std::uno case SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_CHANCE: case SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE: // have positive and negative spells, check target - if (!_isPositiveTarget(spellInfo, effIndex)) + if (!_isPositiveTarget(effect)) return false; break; case SPELL_AURA_MOD_CONFUSE: @@ -4682,7 +4634,7 @@ bool _isPositiveEffectImpl(SpellInfo const* spellInfo, uint32 effIndex, std::uno case SPELL_AURA_MECHANIC_IMMUNITY: { // non-positive immunities - switch (effect->MiscValue) + switch (effect.MiscValue) { case MECHANIC_BANDAGE: case MECHANIC_SHIELD: @@ -4699,7 +4651,7 @@ bool _isPositiveEffectImpl(SpellInfo const* spellInfo, uint32 effIndex, std::uno case SPELL_AURA_ADD_FLAT_MODIFIER_BY_SPELL_LABEL: case SPELL_AURA_ADD_PCT_MODIFIER_BY_SPELL_LABEL: { - switch (SpellModOp(effect->MiscValue)) + switch (SpellModOp(effect.MiscValue)) { case SpellModOp::ChangeCastTime: // dependent from basepoint sign (positive -> negative) case SpellModOp::Period: @@ -4745,25 +4697,22 @@ bool _isPositiveEffectImpl(SpellInfo const* spellInfo, uint32 effIndex, std::uno } // negative spell if triggered spell is negative - if (!effect->ApplyAuraName && effect->TriggerSpell) + if (!effect.ApplyAuraName && effect.TriggerSpell) { - if (SpellInfo const* spellTriggeredProto = sSpellMgr->GetSpellInfo(effect->TriggerSpell, spellInfo->Difficulty)) + if (SpellInfo const* spellTriggeredProto = sSpellMgr->GetSpellInfo(effect.TriggerSpell, spellInfo->Difficulty)) { // spells with at least one negative effect are considered negative // some self-applied spells have negative effects but in self casting case negative check ignored. - for (SpellEffectInfo const* spellTriggeredEffect : spellTriggeredProto->GetEffects()) + for (SpellEffectInfo const& spellTriggeredEffect : spellTriggeredProto->GetEffects()) { - if (!spellTriggeredEffect) - continue; - // already seen this - if (visited.count({ spellTriggeredProto, spellTriggeredEffect->EffectIndex }) > 0) + if (visited.count({ spellTriggeredProto, spellTriggeredEffect.EffectIndex }) > 0) continue; - if (!spellTriggeredEffect->IsEffect()) + if (!spellTriggeredEffect.IsEffect()) continue; - if (!_isPositiveEffectImpl(spellTriggeredProto, spellTriggeredEffect->EffectIndex, visited)) + if (!_isPositiveEffectImpl(spellTriggeredProto, spellTriggeredEffect, visited)) return false; } } @@ -4775,19 +4724,19 @@ bool _isPositiveEffectImpl(SpellInfo const* spellInfo, uint32 effIndex, std::uno void SpellInfo::_InitializeSpellPositivity() { - std::unordered_set<std::pair<SpellInfo const*, uint32 /*effIndex*/>> visited; + std::unordered_set<std::pair<SpellInfo const*, SpellEffIndex /*effIndex*/>> visited; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - if (!_isPositiveEffectImpl(this, i, visited)) - NegativeEffects[i] = true; + for (SpellEffectInfo const& effect : GetEffects()) + if (!_isPositiveEffectImpl(this, effect, visited)) + NegativeEffects[effect.EffectIndex] = true; // additional checks after effects marked - for (SpellEffectInfo const* effect : GetEffects()) + for (SpellEffectInfo const& effect : GetEffects()) { - if (!effect || !effect->IsEffect() || !IsPositiveEffect(effect->EffectIndex)) + if (!effect.IsEffect() || !IsPositiveEffect(effect.EffectIndex)) continue; - switch (effect->ApplyAuraName) + switch (effect.ApplyAuraName) { // has other non positive effect? // then it should be marked negative despite of targets (ex 8510, 8511, 8893, 10267) @@ -4798,8 +4747,11 @@ void SpellInfo::_InitializeSpellPositivity() case SPELL_AURA_TRANSFORM: case SPELL_AURA_MOD_ATTACKSPEED: case SPELL_AURA_MOD_DECREASE_SPEED: - if (!IsPositive()) - NegativeEffects[effect->EffectIndex] = true; + for (size_t j = effect.EffectIndex + 1; j < GetEffects().size(); ++j) + if (!IsPositiveEffect(j) + && effect.TargetA.GetTarget() == GetEffect(SpellEffIndex(j)).TargetA.GetTarget() + && effect.TargetB.GetTarget() == GetEffect(SpellEffIndex(j)).TargetB.GetTarget()) + NegativeEffects[effect.EffectIndex] = true; break; default: break; @@ -4810,21 +4762,17 @@ void SpellInfo::_InitializeSpellPositivity() void SpellInfo::_UnloadImplicitTargetConditionLists() { // find the same instances of ConditionList and delete them. - for (uint32 i = 0; i < _effects.size(); ++i) + for (SpellEffectInfo const& effect : _effects) { - if (SpellEffectInfo const* effect = _effects[i]) - { - ConditionContainer* cur = effect->ImplicitTargetConditions; - if (!cur) - continue; + ConditionContainer* cur = effect.ImplicitTargetConditions; + if (!cur) + continue; - for (uint8 j = i; j < _effects.size(); ++j) - if (SpellEffectInfo const* eff = _effects[j]) - if (eff->ImplicitTargetConditions == cur) - const_cast<SpellEffectInfo*>(eff)->ImplicitTargetConditions = nullptr; + for (size_t j = effect.EffectIndex; j < _effects.size(); ++j) + if (_effects[j].ImplicitTargetConditions == cur) + _effects[j].ImplicitTargetConditions = nullptr; - delete cur; - } + delete cur; } } diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h index dfc169ab570..a63d6b2985c 100644 --- a/src/server/game/Spells/SpellInfo.h +++ b/src/server/game/Spells/SpellInfo.h @@ -27,18 +27,18 @@ #include <boost/container/flat_set.hpp> #include <bitset> -class Unit; -class Player; +class AuraEffect; class Item; +class Player; class Spell; class SpellMgr; class SpellInfo; +class Unit; class WorldObject; -class AuraEffect; +struct Condition; struct SpellChainNode; struct SpellModifier; struct SpellTargetPosition; -struct Condition; enum WeaponAttackType : uint8; enum SpellCastTargetFlags : uint32 @@ -262,11 +262,12 @@ struct TC_GAME_API ImmunityInfo class TC_GAME_API SpellEffectInfo { + friend class SpellInfo; SpellInfo const* _spellInfo; public: - uint32 EffectIndex; - uint32 Effect; - uint32 ApplyAuraName; + SpellEffIndex EffectIndex; + SpellEffectName Effect; + AuraType ApplyAuraName; uint32 ApplyAuraPeriod; int32 BasePoints; float RealPointsPerLevel; @@ -298,7 +299,7 @@ public: float ResourceCoefficient; } Scaling; - SpellEffectInfo() : _spellInfo(nullptr), EffectIndex(0), Effect(0), ApplyAuraName(0), ApplyAuraPeriod(0), + SpellEffectInfo(SpellInfo const* spellInfo) : _spellInfo(spellInfo), EffectIndex(EFFECT_0), Effect(SPELL_EFFECT_NONE), ApplyAuraName(AuraType(0)), ApplyAuraPeriod(0), BasePoints(0), RealPointsPerLevel(0), PointsPerResource(0), Amplitude(0), ChainAmplitude(0), BonusCoefficient(0), MiscValue(0), MiscValueB(0), Mechanic(MECHANIC_NONE), PositionFacing(0), RadiusEntry(nullptr), MaxRadiusEntry(nullptr), ChainTargets(0), ItemType(0), TriggerSpell(0), @@ -346,8 +347,6 @@ private: ImmunityInfo _immunityInfo; }; -typedef std::vector<SpellEffectInfo const*> SpellEffectInfoVector; - typedef std::vector<SpellXSpellVisualEntry const*> SpellVisualVector; typedef std::unordered_map<uint32, SpellVisualVector> SpellVisualMap; @@ -571,10 +570,9 @@ class TC_GAME_API SpellInfo SpellSchoolMask GetSchoolMask() const; uint32 GetAllEffectsMechanicMask() const; - uint32 GetEffectMechanicMask(uint32 effIndex) const; + uint32 GetEffectMechanicMask(SpellEffIndex effIndex) const; uint32 GetSpellMechanicMaskByEffectMask(uint32 effectMask) const; - Mechanics GetEffectMechanic(uint32 effIndex) const; - //bool HasAnyEffectMechanic() const; + Mechanics GetEffectMechanic(SpellEffIndex effIndex) const; uint32 GetDispelMask() const; static uint32 GetDispelMask(DispelType type); uint32 GetExplicitTargetMask() const; @@ -614,8 +612,8 @@ class TC_GAME_API SpellInfo uint32 GetSpellXSpellVisualId(WorldObject const* caster = nullptr) const; uint32 GetSpellVisual(WorldObject const* caster = nullptr) const; - SpellEffectInfoVector const& GetEffects() const { return _effects; } - SpellEffectInfo const* GetEffect(uint32 index) const { return index < _effects.size() ? _effects[index] : nullptr; } + std::vector<SpellEffectInfo> const& GetEffects() const { return _effects; } + SpellEffectInfo const& GetEffect(SpellEffIndex index) const { ASSERT(index < _effects.size()); return _effects[index]; } // spell diminishing returns DiminishingGroup GetDiminishingReturnsGroupForSpell() const; @@ -624,7 +622,7 @@ class TC_GAME_API SpellInfo int32 GetDiminishingReturnsLimitDuration() const; // spell immunities - void ApplyAllSpellImmunitiesTo(Unit* target, SpellEffectInfo const* effect, bool apply) const; + void ApplyAllSpellImmunitiesTo(Unit* target, SpellEffectInfo const& spellEffectInfo, bool apply) const; bool CanSpellProvideImmunityAgainstAura(SpellInfo const* auraSpellInfo) const; bool SpellCancelsAuraEffect(AuraEffect const* aurEff) const; @@ -646,10 +644,9 @@ class TC_GAME_API SpellInfo // unloading helpers void _UnloadImplicitTargetConditionLists(); - void _UnloadSpellEffects(); private: - SpellEffectInfoVector _effects; + std::vector<SpellEffectInfo> _effects; SpellVisualVector _visuals; SpellSpecificType _spellSpecific = SPELL_SPECIFIC_NORMAL; AuraStateType _auraState = AURA_STATE_NONE; diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index 1e6d3cbd5f5..472b052a56d 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -146,21 +146,15 @@ bool SpellMgr::IsSpellValid(SpellInfo const* spellInfo, Player* player, bool msg bool needCheckReagents = false; // check effects - for (SpellEffectInfo const* effect : spellInfo->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : spellInfo->GetEffects()) { - if (!effect) - continue; - - switch (effect->Effect) + switch (spellEffectInfo.Effect) { - case 0: - continue; - // craft spell for crafting non-existed item (break client recipes list show) case SPELL_EFFECT_CREATE_ITEM: case SPELL_EFFECT_CREATE_LOOT: { - if (effect->ItemType == 0) + if (spellEffectInfo.ItemType == 0) { // skip auto-loot crafting spells, it does not need explicit item info (but has special fake items sometimes). if (!spellInfo->IsLootCrafting()) @@ -177,14 +171,14 @@ bool SpellMgr::IsSpellValid(SpellInfo const* spellInfo, Player* player, bool msg } // also possible IsLootCrafting case but fake items must exist anyway - else if (!sObjectMgr->GetItemTemplate(effect->ItemType)) + else if (!sObjectMgr->GetItemTemplate(spellEffectInfo.ItemType)) { if (msg) { if (player) - ChatHandler(player->GetSession()).PSendSysMessage("Craft spell %u has created a non-existing in DB item (Entry: %u) and then...", spellInfo->Id, effect->ItemType); + ChatHandler(player->GetSession()).PSendSysMessage("Craft spell %u has created a non-existing in DB item (Entry: %u) and then...", spellInfo->Id, spellEffectInfo.ItemType); else - TC_LOG_ERROR("sql.sql", "Craft spell %u has created a non-existing item in DB item (Entry: %u) and then...", spellInfo->Id, effect->ItemType); + TC_LOG_ERROR("sql.sql", "Craft spell %u has created a non-existing item in DB item (Entry: %u) and then...", spellInfo->Id, spellEffectInfo.ItemType); } return false; } @@ -194,20 +188,22 @@ bool SpellMgr::IsSpellValid(SpellInfo const* spellInfo, Player* player, bool msg } case SPELL_EFFECT_LEARN_SPELL: { - SpellInfo const* spellInfo2 = sSpellMgr->GetSpellInfo(effect->TriggerSpell, DIFFICULTY_NONE); + SpellInfo const* spellInfo2 = sSpellMgr->GetSpellInfo(spellEffectInfo.TriggerSpell, DIFFICULTY_NONE); if (!IsSpellValid(spellInfo2, player, msg)) { if (msg) { if (player) - ChatHandler(player->GetSession()).PSendSysMessage("Spell %u learn to broken spell %u, and then...", spellInfo->Id, effect->TriggerSpell); + ChatHandler(player->GetSession()).PSendSysMessage("Spell %u learn to broken spell %u, and then...", spellInfo->Id, spellEffectInfo.TriggerSpell); else - TC_LOG_ERROR("sql.sql", "Spell %u learn to invalid spell %u, and then...", spellInfo->Id, effect->TriggerSpell); + TC_LOG_ERROR("sql.sql", "Spell %u learn to invalid spell %u, and then...", spellInfo->Id, spellEffectInfo.TriggerSpell); } return false; } break; } + default: + break; } } @@ -980,17 +976,14 @@ void SpellMgr::LoadSpellLearnSkills() if (entry.Difficulty != DIFFICULTY_NONE) continue; - for (SpellEffectInfo const* effect : entry.GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : entry.GetEffects()) { - if (!effect) - continue; - SpellLearnSkillNode dbc_node; - switch (effect->Effect) + switch (spellEffectInfo.Effect) { case SPELL_EFFECT_SKILL: - dbc_node.skill = uint16(effect->MiscValue); - dbc_node.step = uint16(effect->CalcValue()); + dbc_node.skill = uint16(spellEffectInfo.MiscValue); + dbc_node.step = uint16(spellEffectInfo.CalcValue()); if (dbc_node.skill != SKILL_RIDING) dbc_node.value = 1; else @@ -1077,12 +1070,12 @@ void SpellMgr::LoadSpellLearnSpells() if (entry.Difficulty != DIFFICULTY_NONE) continue; - for (SpellEffectInfo const* effect : entry.GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : entry.GetEffects()) { - if (effect && effect->Effect == SPELL_EFFECT_LEARN_SPELL) + if (spellEffectInfo.IsEffect(SPELL_EFFECT_LEARN_SPELL)) { SpellLearnSpellNode dbc_node; - dbc_node.Spell = effect->TriggerSpell; + dbc_node.Spell = spellEffectInfo.TriggerSpell; dbc_node.Active = true; // all dbc based learned spells is active (show in spell book or hide by client itself) dbc_node.OverridesSpell = 0; @@ -1093,7 +1086,7 @@ void SpellMgr::LoadSpellLearnSpells() // talent or passive spells or skill-step spells auto-cast and not need dependent learning, // pet teaching spells must not be dependent learning (cast) // other required explicit dependent learning - dbc_node.AutoLearned = effect->TargetA.GetTarget() == TARGET_UNIT_PET || entry.HasAttribute(SPELL_ATTR0_CU_IS_TALENT) || entry.IsPassive() || entry.HasEffect(SPELL_EFFECT_SKILL_STEP); + dbc_node.AutoLearned = spellEffectInfo.TargetA.GetTarget() == TARGET_UNIT_PET || entry.HasAttribute(SPELL_ATTR0_CU_IS_TALENT) || entry.IsPassive() || entry.HasEffect(SPELL_EFFECT_SKILL_STEP); SpellLearnSpellMapBounds db_node_bounds = dbSpellLearnSpells.equal_range(entry.Id); @@ -1216,20 +1209,19 @@ void SpellMgr::LoadSpellTargetPositions() continue; } - SpellEffectInfo const* effect = spellInfo->GetEffect(effIndex); - if (!effect) + if (effIndex >= spellInfo->GetEffects().size()) { TC_LOG_ERROR("sql.sql", "Spell (Id: %u, EffectIndex: %u) listed in `spell_target_position` does not have an effect at index %u.", spellId, effIndex, effIndex); continue; } // target facing is in degrees for 6484 & 9268... (blizz sucks) - if (effect->PositionFacing > 2 * M_PI) - st.target_Orientation = effect->PositionFacing * float(M_PI) / 180; + if (spellInfo->GetEffect(effIndex).PositionFacing > 2 * M_PI) + st.target_Orientation = spellInfo->GetEffect(effIndex).PositionFacing * float(M_PI) / 180; else - st.target_Orientation = effect->PositionFacing; + st.target_Orientation = spellInfo->GetEffect(effIndex).PositionFacing; - if (effect->TargetA.GetTarget() == TARGET_DEST_DB || effect->TargetB.GetTarget() == TARGET_DEST_DB) + if (spellInfo->GetEffect(effIndex).TargetA.GetTarget() == TARGET_DEST_DB || spellInfo->GetEffect(effIndex).TargetB.GetTarget() == TARGET_DEST_DB) { std::pair<uint32, SpellEffIndex> key = std::make_pair(spellId, effIndex); mSpellTargetPositions[key] = st; @@ -1420,12 +1412,12 @@ void SpellMgr::LoadSpellGroupStackRules() for (uint32 spellId : spellIds) { SpellInfo const* spellInfo = AssertSpellInfo(spellId, DIFFICULTY_NONE); - for (SpellEffectInfo const* effectInfo : spellInfo->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : spellInfo->GetEffects()) { - if (!effectInfo->IsAura()) + if (!spellEffectInfo.IsAura()) continue; - uint32 auraName = effectInfo->ApplyAuraName; + uint32 auraName = spellEffectInfo.ApplyAuraName; for (std::vector<uint32> const& subGroup : SubGroups) { if (std::find(subGroup.begin(), subGroup.end(), auraName) != subGroup.end()) @@ -1616,18 +1608,18 @@ void SpellMgr::LoadSpellProcs() TC_LOG_ERROR("sql.sql", "The `spell_proc` table entry for spellId %u has wrong `HitMask` set: %u", spellInfo->Id, procEntry.HitMask); if (procEntry.HitMask && !(procEntry.ProcFlags & TAKEN_HIT_PROC_FLAG_MASK || (procEntry.ProcFlags & DONE_HIT_PROC_FLAG_MASK && (!procEntry.SpellPhaseMask || procEntry.SpellPhaseMask & (PROC_SPELL_PHASE_HIT | PROC_SPELL_PHASE_FINISH))))) TC_LOG_ERROR("sql.sql", "The `spell_proc` table entry for spellId %u has `HitMask` value defined, but it will not be used for defined `ProcFlags` and `SpellPhaseMask` values.", spellInfo->Id); - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - if ((procEntry.DisableEffectsMask & (1u << i)) && (!spellInfo->GetEffect(i) || !spellInfo->GetEffect(i)->IsAura())) - TC_LOG_ERROR("sql.sql", "The `spell_proc` table entry for spellId %u has DisableEffectsMask with effect %u, but effect %u is not an aura effect", spellInfo->Id, static_cast<uint32>(i), static_cast<uint32>(i)); + for (SpellEffectInfo const& spellEffectInfo : spellInfo->GetEffects()) + if ((procEntry.DisableEffectsMask & (1u << spellEffectInfo.EffectIndex)) && !spellEffectInfo.IsAura()) + TC_LOG_ERROR("sql.sql", "The `spell_proc` table entry for spellId %u has DisableEffectsMask with effect %u, but effect %u is not an aura effect", spellInfo->Id, static_cast<uint32>(spellEffectInfo.EffectIndex), static_cast<uint32>(spellEffectInfo.EffectIndex)); if (procEntry.AttributesMask & PROC_ATTR_REQ_SPELLMOD) { bool found = false; - for (SpellEffectInfo const* effect : spellInfo->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : spellInfo->GetEffects()) { - if (!effect || !effect->IsAura()) + if (!spellEffectInfo.IsAura()) continue; - if (effect->ApplyAuraName == SPELL_AURA_ADD_PCT_MODIFIER || effect->ApplyAuraName == SPELL_AURA_ADD_FLAT_MODIFIER) + if (spellEffectInfo.ApplyAuraName == SPELL_AURA_ADD_PCT_MODIFIER || spellEffectInfo.ApplyAuraName == SPELL_AURA_ADD_FLAT_MODIFIER) { found = true; break; @@ -1761,19 +1753,19 @@ void SpellMgr::LoadSpellProcs() bool addTriggerFlag = false; uint32 procSpellTypeMask = PROC_SPELL_TYPE_NONE; uint32 nonProcMask = 0; - for (SpellEffectInfo const* effect : spellInfo.GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : spellInfo.GetEffects()) { - if (!effect || !effect->IsEffect()) + if (!spellEffectInfo.IsEffect()) continue; - uint32 auraName = effect->ApplyAuraName; + uint32 auraName = spellEffectInfo.ApplyAuraName; if (!auraName) continue; if (!isTriggerAura[auraName]) { // explicitly disable non proccing auras to avoid losing charges on self proc - nonProcMask |= 1 << effect->EffectIndex; + nonProcMask |= 1 << spellEffectInfo.EffectIndex; continue; } @@ -1799,9 +1791,9 @@ void SpellMgr::LoadSpellProcs() if (!procSpellTypeMask) { - for (SpellEffectInfo const* effectInfo : spellInfo.GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : spellInfo.GetEffects()) { - if (effectInfo && effectInfo->IsAura()) + if (spellEffectInfo.IsAura()) { TC_LOG_ERROR("sql.sql", "Spell Id %u has DBC ProcFlags %u, but it's of non-proc aura type, it probably needs an entry in `spell_proc` table to be handled correctly.", spellInfo.Id, spellInfo.ProcFlags); break; @@ -1815,9 +1807,9 @@ void SpellMgr::LoadSpellProcs() procEntry.SchoolMask = 0; procEntry.ProcFlags = spellInfo.ProcFlags; procEntry.SpellFamilyName = 0; - for (SpellEffectInfo const* effect : spellInfo.GetEffects()) - if (effect && effect->IsEffect() && isTriggerAura[effect->ApplyAuraName]) - procEntry.SpellFamilyMask |= effect->SpellClassMask; + for (SpellEffectInfo const& spellEffectInfo : spellInfo.GetEffects()) + if (spellEffectInfo.IsEffect() && isTriggerAura[spellEffectInfo.ApplyAuraName]) + procEntry.SpellFamilyMask |= spellEffectInfo.SpellClassMask; if (procEntry.SpellFamilyMask) procEntry.SpellFamilyName = spellInfo.SpellFamilyName; @@ -1826,12 +1818,12 @@ void SpellMgr::LoadSpellProcs() procEntry.SpellPhaseMask = PROC_SPELL_PHASE_HIT; procEntry.HitMask = PROC_HIT_NONE; // uses default proc @see SpellMgr::CanSpellTriggerProcOnEvent - for (SpellEffectInfo const* effect : spellInfo.GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : spellInfo.GetEffects()) { - if (!effect || !effect->IsAura()) + if (!spellEffectInfo.IsAura()) continue; - switch (effect->ApplyAuraName) + switch (spellEffectInfo.ApplyAuraName) { // Reflect auras should only proc off reflects case SPELL_AURA_REFLECT_SPELLS: @@ -1951,7 +1943,7 @@ void SpellMgr::LoadSpellPetAuras() Field* fields = result->Fetch(); uint32 spell = fields[0].GetUInt32(); - uint8 eff = fields[1].GetUInt8(); + SpellEffIndex eff = SpellEffIndex(fields[1].GetUInt8()); uint32 pet = fields[2].GetUInt32(); uint32 aura = fields[3].GetUInt32(); @@ -1966,18 +1958,17 @@ void SpellMgr::LoadSpellPetAuras() TC_LOG_ERROR("sql.sql", "The spell %u listed in `spell_pet_auras` does not exist.", spell); continue; } - SpellEffectInfo const* effect = spellInfo->GetEffect(eff); - if (!effect) + if (eff >= spellInfo->GetEffects().size()) { TC_LOG_ERROR("spells", "The spell %u listed in `spell_pet_auras` does not have any effect at index %u", spell, uint32(eff)); continue; } - if (effect->Effect != SPELL_EFFECT_DUMMY && - (effect->Effect != SPELL_EFFECT_APPLY_AURA || - effect->ApplyAuraName != SPELL_AURA_DUMMY)) + if (spellInfo->GetEffect(eff).Effect != SPELL_EFFECT_DUMMY && + (spellInfo->GetEffect(eff).Effect != SPELL_EFFECT_APPLY_AURA || + spellInfo->GetEffect(eff).ApplyAuraName != SPELL_AURA_DUMMY)) { - TC_LOG_ERROR("spells", "Spell %u listed in `spell_pet_auras` does not have any dummy aura or dummy effect", spell); + TC_LOG_ERROR("spells", "The spell %u listed in `spell_pet_auras` does not have any dummy aura or dummy effect.", spell); continue; } @@ -1988,7 +1979,7 @@ void SpellMgr::LoadSpellPetAuras() continue; } - PetAura pa(pet, aura, effect->TargetA.GetTarget() == TARGET_UNIT_PET, effect->CalcValue()); + PetAura pa(pet, aura, spellInfo->GetEffect(eff).TargetA.GetTarget() == TARGET_UNIT_PET, spellInfo->GetEffect(eff).CalcValue()); mSpellPetAuraMap[(spell<<8) + eff] = pa; } @@ -2016,11 +2007,11 @@ void SpellMgr::LoadEnchantCustomAttr() if (!spellInfo.HasAttribute(SPELL_ATTR2_PRESERVE_ENCHANT_IN_ARENA) || !spellInfo.HasAttribute(SPELL_ATTR0_NOT_SHAPESHIFT)) continue; - for (SpellEffectInfo const* effect : spellInfo.GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : spellInfo.GetEffects()) { - if (effect && effect->Effect == SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) + if (spellEffectInfo.Effect == SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) { - uint32 enchId = effect->MiscValue; + uint32 enchId = spellEffectInfo.MiscValue; SpellItemEnchantmentEntry const* ench = sSpellItemEnchantmentStore.LookupEntry(enchId); if (!ench) continue; @@ -2108,10 +2099,10 @@ void SpellMgr::LoadSpellLinked() } if (effect >= 0) - for (SpellEffectInfo const* eff : spellInfo->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : spellInfo->GetEffects()) { - if (eff && eff->CalcValue() == abs(effect)) - TC_LOG_ERROR("sql.sql", "The spell %u Effect: %u listed in `spell_linked_spell` has same bp%u like effect (possible hack)", abs(trigger), abs(effect), eff->EffectIndex); + if (spellEffectInfo.CalcValue() == abs(effect)) + TC_LOG_ERROR("sql.sql", "The spell %u Effect: %u listed in `spell_linked_spell` has same bp%u like effect (possible hack).", abs(trigger), abs(effect), uint32(spellEffectInfo.EffectIndex)); } spellInfo = GetSpellInfo(abs(effect), DIFFICULTY_NONE); @@ -2252,11 +2243,11 @@ void SpellMgr::LoadPetDefaultSpells() { if (spellEntry.Difficulty != DIFFICULTY_NONE) - for (SpellEffectInfo const* effect : spellEntry.GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : spellEntry.GetEffects()) { - if (effect && (effect->Effect == SPELL_EFFECT_SUMMON || effect->Effect == SPELL_EFFECT_SUMMON_PET)) + if (spellEffectInfo.IsEffect(SPELL_EFFECT_SUMMON) || spellEffectInfo.IsEffect(SPELL_EFFECT_SUMMON_PET)) { - uint32 creature_id = effect->MiscValue; + uint32 creature_id = spellEffectInfo.MiscValue; CreatureTemplate const* cInfo = sObjectMgr->GetCreatureTemplate(creature_id); if (!cInfo) continue; @@ -2952,12 +2943,9 @@ void SpellMgr::LoadSpellInfoCustomAttributes() for (SpellInfo const& spellInfo : mSpellInfoMap) { SpellInfo* spellInfoMutable = const_cast<SpellInfo*>(&spellInfo); - for (SpellEffectInfo const* effect : spellInfoMutable->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : spellInfoMutable->GetEffects()) { - if (!effect) - continue; - - switch (effect->ApplyAuraName) + switch (spellEffectInfo.ApplyAuraName) { case SPELL_AURA_MOD_POSSESS: case SPELL_AURA_MOD_CONFUSE: @@ -2979,9 +2967,11 @@ void SpellMgr::LoadSpellInfoCustomAttributes() case SPELL_AURA_POWER_BURN: spellInfoMutable->AttributesCu |= SPELL_ATTR0_CU_NO_INITIAL_THREAT; break; + default: + break; } - switch (effect->ApplyAuraName) + switch (spellEffectInfo.ApplyAuraName) { case SPELL_AURA_OPEN_STABLE: // No point in saving this, since the stable dialog can't be open on aura load anyway. // Auras that require both caster & target to be in world cannot be saved @@ -2996,9 +2986,11 @@ void SpellMgr::LoadSpellInfoCustomAttributes() case SPELL_AURA_BATTLEGROUND_PLAYER_POSITION_FACTIONAL: spellInfoMutable->AttributesCu |= SPELL_ATTR0_CU_AURA_CANNOT_BE_SAVED; break; + default: + break; } - switch (effect->Effect) + switch (spellEffectInfo.Effect) { case SPELL_EFFECT_SCHOOL_DAMAGE: case SPELL_EFFECT_HEALTH_LEECH: @@ -3013,9 +3005,11 @@ void SpellMgr::LoadSpellInfoCustomAttributes() case SPELL_EFFECT_DAMAGE_FROM_MAX_HEALTH_PCT: spellInfoMutable->AttributesCu |= SPELL_ATTR0_CU_CAN_CRIT; break; + default: + break; } - switch (effect->Effect) + switch (spellEffectInfo.Effect) { case SPELL_EFFECT_SCHOOL_DAMAGE: case SPELL_EFFECT_WEAPON_DAMAGE: @@ -3053,7 +3047,7 @@ void SpellMgr::LoadSpellInfoCustomAttributes() // only enchanting profession enchantments procs can stack if (IsPartOfSkillLine(SKILL_ENCHANTING, spellInfo.Id)) { - uint32 enchantId = effect->MiscValue; + uint32 enchantId = spellEffectInfo.MiscValue; SpellItemEnchantmentEntry const* enchant = sSpellItemEnchantmentStore.LookupEntry(enchantId); if (!enchant) break; @@ -3077,6 +3071,8 @@ void SpellMgr::LoadSpellInfoCustomAttributes() } break; } + default: + break; } } @@ -3084,67 +3080,64 @@ void SpellMgr::LoadSpellInfoCustomAttributes() if (!spellInfoMutable->HasAttribute(SPELL_ATTR3_IGNORE_HIT_RESULT)) { bool setFlag = false; - for (SpellEffectInfo const* effect : spellInfoMutable->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : spellInfoMutable->GetEffects()) { - if (!effect) - continue; - - if (effect->IsEffect()) + if (spellEffectInfo.IsEffect()) { - switch (effect->Effect) + switch (spellEffectInfo.Effect) { - case SPELL_EFFECT_SCHOOL_DAMAGE: - case SPELL_EFFECT_WEAPON_DAMAGE: - case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL: - case SPELL_EFFECT_NORMALIZED_WEAPON_DMG: - case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE: - case SPELL_EFFECT_TRIGGER_SPELL: - case SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE: - break; - case SPELL_EFFECT_PERSISTENT_AREA_AURA: - case SPELL_EFFECT_APPLY_AURA: - case SPELL_EFFECT_APPLY_AREA_AURA_PARTY: - case SPELL_EFFECT_APPLY_AREA_AURA_RAID: - case SPELL_EFFECT_APPLY_AREA_AURA_FRIEND: - case SPELL_EFFECT_APPLY_AREA_AURA_ENEMY: - case SPELL_EFFECT_APPLY_AREA_AURA_PET: - case SPELL_EFFECT_APPLY_AREA_AURA_OWNER: - case SPELL_EFFECT_APPLY_AURA_ON_PET: - case SPELL_EFFECT_APPLY_AREA_AURA_SUMMONS: - case SPELL_EFFECT_APPLY_AREA_AURA_PARTY_NONRANDOM: - if (effect->ApplyAuraName == SPELL_AURA_PERIODIC_DAMAGE || - effect->ApplyAuraName == SPELL_AURA_PERIODIC_DAMAGE_PERCENT || - effect->ApplyAuraName == SPELL_AURA_DUMMY || - effect->ApplyAuraName == SPELL_AURA_PERIODIC_LEECH || - effect->ApplyAuraName == SPELL_AURA_PERIODIC_HEALTH_FUNNEL || - effect->ApplyAuraName == SPELL_AURA_PERIODIC_DUMMY) - break; - /* fallthrough */ - default: - { - // No value and not interrupt cast or crowd control without SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY flag - if (!effect->CalcValue() && !((effect->Effect == SPELL_EFFECT_INTERRUPT_CAST || spellInfoMutable->HasAttribute(SPELL_ATTR0_CU_AURA_CC)) && !spellInfoMutable->HasAttribute(SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY))) + case SPELL_EFFECT_SCHOOL_DAMAGE: + case SPELL_EFFECT_WEAPON_DAMAGE: + case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL: + case SPELL_EFFECT_NORMALIZED_WEAPON_DMG: + case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE: + case SPELL_EFFECT_TRIGGER_SPELL: + case SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE: break; + case SPELL_EFFECT_PERSISTENT_AREA_AURA: + case SPELL_EFFECT_APPLY_AURA: + case SPELL_EFFECT_APPLY_AREA_AURA_PARTY: + case SPELL_EFFECT_APPLY_AREA_AURA_RAID: + case SPELL_EFFECT_APPLY_AREA_AURA_FRIEND: + case SPELL_EFFECT_APPLY_AREA_AURA_ENEMY: + case SPELL_EFFECT_APPLY_AREA_AURA_PET: + case SPELL_EFFECT_APPLY_AREA_AURA_OWNER: + case SPELL_EFFECT_APPLY_AURA_ON_PET: + case SPELL_EFFECT_APPLY_AREA_AURA_SUMMONS: + case SPELL_EFFECT_APPLY_AREA_AURA_PARTY_NONRANDOM: + if (spellEffectInfo.ApplyAuraName == SPELL_AURA_PERIODIC_DAMAGE || + spellEffectInfo.ApplyAuraName == SPELL_AURA_PERIODIC_DAMAGE_PERCENT || + spellEffectInfo.ApplyAuraName == SPELL_AURA_DUMMY || + spellEffectInfo.ApplyAuraName == SPELL_AURA_PERIODIC_LEECH || + spellEffectInfo.ApplyAuraName == SPELL_AURA_PERIODIC_HEALTH_FUNNEL || + spellEffectInfo.ApplyAuraName == SPELL_AURA_PERIODIC_DUMMY) + break; + /* fallthrough */ + default: + { + // No value and not interrupt cast or crowd control without SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY flag + if (!spellEffectInfo.CalcValue() && !((spellEffectInfo.Effect == SPELL_EFFECT_INTERRUPT_CAST || spellInfoMutable->HasAttribute(SPELL_ATTR0_CU_AURA_CC)) && !spellInfoMutable->HasAttribute(SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY))) + break; - // Sindragosa Frost Breath - if (spellInfoMutable->Id == 69649 || spellInfoMutable->Id == 71056 || spellInfoMutable->Id == 71057 || spellInfoMutable->Id == 71058 || spellInfoMutable->Id == 73061 || spellInfoMutable->Id == 73062 || spellInfoMutable->Id == 73063 || spellInfoMutable->Id == 73064) - break; + // Sindragosa Frost Breath + if (spellInfoMutable->Id == 69649 || spellInfoMutable->Id == 71056 || spellInfoMutable->Id == 71057 || spellInfoMutable->Id == 71058 || spellInfoMutable->Id == 73061 || spellInfoMutable->Id == 73062 || spellInfoMutable->Id == 73063 || spellInfoMutable->Id == 73064) + break; - // Frostbolt - if (spellInfoMutable->SpellFamilyName == SPELLFAMILY_MAGE && (spellInfoMutable->SpellFamilyFlags[0] & 0x20)) - break; + // Frostbolt + if (spellInfoMutable->SpellFamilyName == SPELLFAMILY_MAGE && (spellInfoMutable->SpellFamilyFlags[0] & 0x20)) + break; - // Frost Fever - if (spellInfoMutable->Id == 55095) - break; + // Frost Fever + if (spellInfoMutable->Id == 55095) + break; - // Haunt - if (spellInfoMutable->SpellFamilyName == SPELLFAMILY_WARLOCK && (spellInfoMutable->SpellFamilyFlags[1] & 0x40000)) - break; + // Haunt + if (spellInfoMutable->SpellFamilyName == SPELLFAMILY_WARLOCK && (spellInfoMutable->SpellFamilyFlags[1] & 0x40000)) + break; - setFlag = true; - break; - } + setFlag = true; + break; + } } if (setFlag) @@ -3203,18 +3196,15 @@ void SpellMgr::LoadSpellInfoCustomAttributes() { bool allNonBinary = true; bool overrideAttr = false; - for (SpellEffectInfo const* effect : spellInfoMutable->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : spellInfoMutable->GetEffects()) { - if (!effect) - continue; - - if (effect->IsAura() && effect->TriggerSpell) + if (spellEffectInfo.IsAura() && spellEffectInfo.TriggerSpell) { - switch (effect->ApplyAuraName) + switch (spellEffectInfo.ApplyAuraName) { case SPELL_AURA_PERIODIC_TRIGGER_SPELL: case SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE: - if (SpellInfo const* triggerSpell = sSpellMgr->GetSpellInfo(effect->TriggerSpell, DIFFICULTY_NONE)) + if (SpellInfo const* triggerSpell = sSpellMgr->GetSpellInfo(spellEffectInfo.TriggerSpell, DIFFICULTY_NONE)) { overrideAttr = true; if (triggerSpell->HasAttribute(SPELL_ATTR0_CU_BINARY_SPELL)) @@ -3259,14 +3249,13 @@ inline void ApplySpellFix(std::initializer_list<uint32> spellIds, void(*fix)(Spe inline void ApplySpellEffectFix(SpellInfo* spellInfo, SpellEffIndex effectIndex, void(*fix)(SpellEffectInfo*)) { - SpellEffectInfo const* effect = spellInfo->GetEffect(effectIndex); - if (!effect) + if (spellInfo->GetEffects().size() <= effectIndex) { TC_LOG_ERROR("server.loading", "Spell effect info correction specified for non-existing effect %u of spell %u", uint32(effectIndex), spellInfo->Id); return; } - fix(const_cast<SpellEffectInfo*>(effect)); + fix(const_cast<SpellEffectInfo*>(&spellInfo->GetEffect(effectIndex))); } void SpellMgr::LoadSpellInfoCorrections() @@ -3427,7 +3416,7 @@ void SpellMgr::LoadSpellInfoCorrections() { ApplySpellEffectFix(spellInfo, EFFECT_0, [](SpellEffectInfo* spellEffectInfo) { - spellEffectInfo->Effect = 0; + spellEffectInfo->Effect = SPELL_EFFECT_NONE; }); }); @@ -3765,7 +3754,7 @@ void SpellMgr::LoadSpellInfoCorrections() //! HACK: This spell break quest complete for alliance and on retail not used ApplySpellEffectFix(spellInfo, EFFECT_0, [](SpellEffectInfo* spellEffectInfo) { - spellEffectInfo->Effect = 0; + spellEffectInfo->Effect = SPELL_EFFECT_NONE; }); }); @@ -4056,7 +4045,7 @@ void SpellMgr::LoadSpellInfoCorrections() // this spell initially granted Shadow damage immunity, however it was removed but the data was left in client ApplySpellEffectFix(spellInfo, EFFECT_2, [](SpellEffectInfo* spellEffectInfo) { - spellEffectInfo->Effect = 0; + spellEffectInfo->Effect = SPELL_EFFECT_NONE; }); }); @@ -4098,7 +4087,7 @@ void SpellMgr::LoadSpellInfoCorrections() // THIS IS HERE BECAUSE COOLDOWN ON CREATURE PROCS WERE NOT IMPLEMENTED WHEN THE SCRIPT WAS WRITTEN ApplySpellEffectFix(spellInfo, EFFECT_1, [](SpellEffectInfo* spellEffectInfo) { - spellEffectInfo->Effect = 0; + spellEffectInfo->Effect = SPELL_EFFECT_NONE; }); }); @@ -4477,7 +4466,7 @@ void SpellMgr::LoadSpellInfoCorrections() // Until we figure out what it's actually used for we disable it. ApplySpellEffectFix(spellInfo, EFFECT_2, [](SpellEffectInfo* spellEffectInfo) { - spellEffectInfo->Effect = 0; + spellEffectInfo->Effect = SPELL_EFFECT_NONE; }); }); @@ -4498,26 +4487,24 @@ void SpellMgr::LoadSpellInfoCorrections() if (!spellInfo) continue; - for (SpellEffectInfo const* effect : spellInfo->GetEffects()) + // Fix range for trajectory triggered spell + for (SpellEffectInfo const& spellEffectInfo : spellInfo->GetEffects()) { - if (!effect) - continue; - - if (effect->IsEffect() && (effect->TargetA.GetTarget() == TARGET_DEST_TRAJ || effect->TargetB.GetTarget() == TARGET_DEST_TRAJ)) + if (spellEffectInfo.IsEffect() && (spellEffectInfo.TargetA.GetTarget() == TARGET_DEST_TRAJ || spellEffectInfo.TargetB.GetTarget() == TARGET_DEST_TRAJ)) { // Get triggered spell if any - if (SpellInfo* spellInfoTrigger = const_cast<SpellInfo*>(GetSpellInfo(effect->TriggerSpell, DIFFICULTY_NONE))) + for (SpellInfo const& spellInfoTrigger : _GetSpellInfo(spellEffectInfo.TriggerSpell)) { float maxRangeMain = spellInfo->GetMaxRange(); - float maxRangeTrigger = spellInfoTrigger->GetMaxRange(); + float maxRangeTrigger = spellInfoTrigger.GetMaxRange(); // check if triggered spell has enough max range to cover trajectory if (maxRangeTrigger < maxRangeMain) - spellInfoTrigger->RangeEntry = spellInfo->RangeEntry; + const_cast<SpellInfo&>(spellInfoTrigger).RangeEntry = spellInfo->RangeEntry; } } - switch (effect->Effect) + switch (spellEffectInfo.Effect) { case SPELL_EFFECT_CHARGE: case SPELL_EFFECT_CHARGE_DEST: @@ -4527,17 +4514,19 @@ void SpellMgr::LoadSpellInfoCorrections() if (!spellInfo->Speed && !spellInfo->SpellFamilyName && !spellInfo->HasAttribute(SPELL_ATTR9_SPECIAL_DELAY_CALCULATION)) spellInfo->Speed = SPEED_CHARGE; break; + default: + break; } - if (effect->TargetA.GetSelectionCategory() == TARGET_SELECT_CATEGORY_CONE || effect->TargetB.GetSelectionCategory() == TARGET_SELECT_CATEGORY_CONE) + if (spellEffectInfo.TargetA.GetSelectionCategory() == TARGET_SELECT_CATEGORY_CONE || spellEffectInfo.TargetB.GetSelectionCategory() == TARGET_SELECT_CATEGORY_CONE) if (G3D::fuzzyEq(spellInfo->ConeAngle, 0.f)) spellInfo->ConeAngle = 90.f; // Area auras may not target area (they're self cast) - if (effect->IsAreaAuraEffect() && effect->IsTargetingArea()) + if (spellEffectInfo.IsAreaAuraEffect() && spellEffectInfo.IsTargetingArea()) { - const_cast<SpellEffectInfo*>(effect)->TargetA = SpellImplicitTargetInfo(TARGET_UNIT_CASTER); - const_cast<SpellEffectInfo*>(effect)->TargetB = SpellImplicitTargetInfo(0); + const_cast<SpellEffectInfo&>(spellEffectInfo).TargetA = SpellImplicitTargetInfo(TARGET_UNIT_CASTER); + const_cast<SpellEffectInfo&>(spellEffectInfo).TargetB = SpellImplicitTargetInfo(0); } } diff --git a/src/server/game/Spells/SpellScript.cpp b/src/server/game/Spells/SpellScript.cpp index 3012aeffba5..cc397652093 100644 --- a/src/server/game/Spells/SpellScript.cpp +++ b/src/server/game/Spells/SpellScript.cpp @@ -118,32 +118,25 @@ bool _SpellScript::EffectHook::IsEffectAffected(SpellInfo const* spellEntry, uin std::string _SpellScript::EffectHook::EffIndexToString() const { - switch (effIndex) - { - case EFFECT_ALL: - return "EFFECT_ALL"; - case EFFECT_FIRST_FOUND: - return "EFFECT_FIRST_FOUND"; - case EFFECT_0: - return "EFFECT_0"; - case EFFECT_1: - return "EFFECT_1"; - case EFFECT_2: - return "EFFECT_2"; - } + if (effIndex == EFFECT_ALL) + return "EFFECT_ALL"; + if (effIndex == EFFECT_FIRST_FOUND) + return "EFFECT_FIRST_FOUND"; + if (effIndex < MAX_SPELL_EFFECTS) + return Trinity::StringFormat("EFFECT_%u", uint32(effIndex)); return "Invalid Value"; } bool _SpellScript::EffectNameCheck::Check(SpellInfo const* spellEntry, uint8 effIndex) const { - SpellEffectInfo const* effect = spellEntry->GetEffect(effIndex); - if (!effect) + if (spellEntry->GetEffects().size() <= effIndex) return false; - if (!effect->Effect && !effName) + SpellEffectInfo const& spellEffectInfo = spellEntry->GetEffect(SpellEffIndex(effIndex)); + if (!spellEffectInfo.Effect && !effName) return true; - if (!effect->Effect) + if (!spellEffectInfo.Effect) return false; - return (effName == SPELL_EFFECT_ANY) || (effect->Effect == effName); + return (effName == SPELL_EFFECT_ANY) || (spellEffectInfo.Effect == effName); } std::string _SpellScript::EffectNameCheck::ToString() const @@ -161,14 +154,14 @@ std::string _SpellScript::EffectNameCheck::ToString() const bool _SpellScript::EffectAuraNameCheck::Check(SpellInfo const* spellEntry, uint8 effIndex) const { - SpellEffectInfo const* effect = spellEntry->GetEffect(effIndex); - if (!effect) + if (spellEntry->GetEffects().size() <= effIndex) return false; - if (!effect->ApplyAuraName && !effAurName) + SpellEffectInfo const& spellEffectInfo = spellEntry->GetEffect(SpellEffIndex(effIndex)); + if (!spellEffectInfo.ApplyAuraName && !effAurName) return true; - if (!effect->ApplyAuraName) + if (!spellEffectInfo.ApplyAuraName) return false; - return (effAurName == SPELL_AURA_ANY) || (effect->ApplyAuraName == effAurName); + return (effAurName == SPELL_AURA_ANY) || (spellEffectInfo.ApplyAuraName == effAurName); } std::string _SpellScript::EffectAuraNameCheck::ToString() const @@ -270,12 +263,12 @@ bool SpellScript::TargetHook::CheckEffect(SpellInfo const* spellEntry, uint8 eff if (!targetType) return false; - SpellEffectInfo const* effect = spellEntry->GetEffect(effIndexToCheck); - if (!effect) + if (spellEntry->GetEffects().size() <= effIndexToCheck) return false; - if (effect->TargetA.GetTarget() != targetType && - effect->TargetB.GetTarget() != targetType) + SpellEffectInfo const& spellEffectInfo = spellEntry->GetEffect(SpellEffIndex(effIndexToCheck)); + if (spellEffectInfo.TargetA.GetTarget() != targetType && + spellEffectInfo.TargetB.GetTarget() != targetType) return false; SpellImplicitTargetInfo targetInfo(targetType); @@ -485,6 +478,16 @@ SpellInfo const* SpellScript::GetSpellInfo() const return m_spell->GetSpellInfo(); } +SpellEffectInfo const& SpellScript::GetEffectInfo(SpellEffIndex effIndex) const +{ + return GetSpellInfo()->GetEffect(effIndex); +} + +SpellValue const* SpellScript::GetSpellValue() const +{ + return m_spell->m_spellValue; +} + WorldLocation const* SpellScript::GetExplTargetDest() const { if (m_spell->m_targets.HasDst()) @@ -706,11 +709,11 @@ void SpellScript::PreventHitDefaultEffect(SpellEffIndex effIndex) m_hitPreventDefaultEffectMask |= 1 << effIndex; } -SpellEffectInfo const* SpellScript::GetEffectInfo() const +SpellEffectInfo const& SpellScript::GetEffectInfo() const { ASSERT(IsInEffectHook(), "Script: `%s` Spell: `%u`: function SpellScript::GetEffectInfo was called, but function has no effect in current hook!", m_scriptName->c_str(), m_scriptSpellId); - return m_spell->effectInfo; + return *m_spell->effectInfo; } int32 SpellScript::GetEffectValue() const @@ -772,16 +775,6 @@ Difficulty SpellScript::GetCastDifficulty() const return m_spell->GetCastDifficulty(); } -SpellValue const* SpellScript::GetSpellValue() const -{ - return m_spell->m_spellValue; -} - -SpellEffectInfo const* SpellScript::GetEffectInfo(SpellEffIndex effIndex) const -{ - return GetSpellInfo()->GetEffect(effIndex); -} - bool AuraScript::_Validate(SpellInfo const* entry) { for (auto itr = DoCheckAreaTarget.begin(); itr != DoCheckAreaTarget.end(); ++itr) @@ -1154,6 +1147,11 @@ SpellInfo const* AuraScript::GetSpellInfo() const return m_aura->GetSpellInfo(); } +SpellEffectInfo const& AuraScript::GetEffectInfo(SpellEffIndex effIndex) const +{ + return m_aura->GetSpellInfo()->GetEffect(effIndex); +} + uint32 AuraScript::GetId() const { return m_aura->GetId(); diff --git a/src/server/game/Spells/SpellScript.h b/src/server/game/Spells/SpellScript.h index e4c3cca9387..b217764b552 100644 --- a/src/server/game/Spells/SpellScript.h +++ b/src/server/game/Spells/SpellScript.h @@ -413,8 +413,8 @@ class TC_GAME_API SpellScript : public _SpellScript GameObject* GetGObjCaster() const; Unit* GetOriginalCaster() const; SpellInfo const* GetSpellInfo() const; + SpellEffectInfo const& GetEffectInfo(SpellEffIndex effIndex) const; SpellValue const* GetSpellValue() const; - SpellEffectInfo const* GetEffectInfo(SpellEffIndex effIndex) const; // methods useable after spell is prepared // accessors to the explicit targets of the spell @@ -490,7 +490,7 @@ class TC_GAME_API SpellScript : public _SpellScript void PreventHitDefaultEffect(SpellEffIndex effIndex); // method available only in EffectHandler method - SpellEffectInfo const* GetEffectInfo() const; + SpellEffectInfo const& GetEffectInfo() const; int32 GetEffectValue() const; void SetEffectValue(int32 value); @@ -927,6 +927,7 @@ class TC_GAME_API AuraScript : public _SpellScript // returns proto of the spell SpellInfo const* GetSpellInfo() const; + SpellEffectInfo const& GetEffectInfo(SpellEffIndex effIndex) const; // returns spellid of the spell uint32 GetId() const; diff --git a/src/server/scripts/Argus/AntorusTheBurningThrone/boss_garothi_worldbreaker.cpp b/src/server/scripts/Argus/AntorusTheBurningThrone/boss_garothi_worldbreaker.cpp index cd0049eb169..e0603d9880c 100644 --- a/src/server/scripts/Argus/AntorusTheBurningThrone/boss_garothi_worldbreaker.cpp +++ b/src/server/scripts/Argus/AntorusTheBurningThrone/boss_garothi_worldbreaker.cpp @@ -604,13 +604,13 @@ class spell_garothi_fel_bombardment_periodic : public AuraScript bool Validate(SpellInfo const* spellInfo) override { - return ValidateSpellInfo({ uint32(spellInfo->GetEffect(EFFECT_0)->BasePoints) }); + return !spellInfo->GetEffects().empty() && ValidateSpellInfo({ uint32(spellInfo->GetEffect(EFFECT_0).CalcValue()) }); } - void HandlePeriodic(AuraEffect const* /*aurEff*/) + void HandlePeriodic(AuraEffect const* aurEff) { if (Unit* caster = GetCaster()) - caster->CastSpell(GetTarget(), uint32(GetSpellInfo()->GetEffect(EFFECT_0)->BasePoints), true); + caster->CastSpell(GetTarget(), uint32(aurEff->GetSpellEffectInfo().CalcValue(caster)), true); } void Register() override @@ -757,13 +757,13 @@ class spell_garothi_annihilation_selector : public SpellScript bool Validate(SpellInfo const* spellInfo) override { - return ValidateSpellInfo({ uint32(spellInfo->GetEffect(EFFECT_0)->BasePoints) }); + return !spellInfo->GetEffects().empty() && ValidateSpellInfo({ uint32(spellInfo->GetEffect(EFFECT_0).CalcValue()) }); } - void HandleHit(SpellEffIndex effIndex) + void HandleHit(SpellEffIndex /*effIndex*/) { if (Unit* caster = GetCaster()) - caster->CastSpell(GetHitUnit(), uint32(GetSpellInfo()->GetEffect(effIndex)->BasePoints), true); + caster->CastSpell(GetHitUnit(), uint32(GetEffectInfo().CalcValue(caster)), true); } void Register() override diff --git a/src/server/scripts/Commands/cs_lookup.cpp b/src/server/scripts/Commands/cs_lookup.cpp index 8ea4aa3dc27..2481abbdffc 100644 --- a/src/server/scripts/Commands/cs_lookup.cpp +++ b/src/server/scripts/Commands/cs_lookup.cpp @@ -886,10 +886,10 @@ public: bool known = target && target->HasSpell(spellInfo->Id); - SpellEffectInfo const* effect = spellInfo->GetEffect(EFFECT_0); - bool learn = effect ? (effect->Effect == SPELL_EFFECT_LEARN_SPELL) : false; + SpellEffectInfo const& spellEffectInfo = spellInfo->GetEffect(EFFECT_0); + bool learn = spellEffectInfo.IsEffect(SPELL_EFFECT_LEARN_SPELL); - SpellInfo const* learnSpellInfo = effect ? sSpellMgr->GetSpellInfo(effect->TriggerSpell, spellInfo->Difficulty) : nullptr; + SpellInfo const* learnSpellInfo = sSpellMgr->GetSpellInfo(spellEffectInfo.TriggerSpell, spellInfo->Difficulty); bool talent = spellInfo->HasAttribute(SPELL_ATTR0_CU_IS_TALENT); bool passive = spellInfo->IsPassive(); @@ -959,10 +959,10 @@ public: bool known = target && target->HasSpell(id); - SpellEffectInfo const* effect = spellInfo->GetEffect(EFFECT_0); - bool learn = effect? (effect->Effect == SPELL_EFFECT_LEARN_SPELL) : false; + SpellEffectInfo const& spellEffectInfo = spellInfo->GetEffect(EFFECT_0); + bool learn = spellEffectInfo.IsEffect(SPELL_EFFECT_LEARN_SPELL); - SpellInfo const* learnSpellInfo = effect ? sSpellMgr->GetSpellInfo(effect->TriggerSpell, DIFFICULTY_NONE) : nullptr; + SpellInfo const* learnSpellInfo = sSpellMgr->GetSpellInfo(spellEffectInfo.TriggerSpell, DIFFICULTY_NONE); bool talent = spellInfo->HasAttribute(SPELL_ATTR0_CU_IS_TALENT); bool passive = spellInfo->IsPassive(); diff --git a/src/server/scripts/EasternKingdoms/BaradinHold/boss_occuthar.cpp b/src/server/scripts/EasternKingdoms/BaradinHold/boss_occuthar.cpp index f2c8ef442ea..aaa627f79ec 100644 --- a/src/server/scripts/EasternKingdoms/BaradinHold/boss_occuthar.cpp +++ b/src/server/scripts/EasternKingdoms/BaradinHold/boss_occuthar.cpp @@ -270,7 +270,7 @@ class spell_occuthar_eyes_of_occuthar : public SpellScriptLoader bool Validate(SpellInfo const* spellInfo) override { - return ValidateSpellInfo({ uint32(spellInfo->GetEffect(EFFECT_0)->CalcValue()) }); + return !spellInfo->GetEffects().empty() && ValidateSpellInfo({ uint32(spellInfo->GetEffect(EFFECT_0).CalcValue()) }); } bool Load() override diff --git a/src/server/scripts/EasternKingdoms/Karazhan/boss_shade_of_aran.cpp b/src/server/scripts/EasternKingdoms/Karazhan/boss_shade_of_aran.cpp index cbdc82d355e..b797436b3bd 100644 --- a/src/server/scripts/EasternKingdoms/Karazhan/boss_shade_of_aran.cpp +++ b/src/server/scripts/EasternKingdoms/Karazhan/boss_shade_of_aran.cpp @@ -500,21 +500,21 @@ public: void SpellHit(Unit* /*caster*/, SpellInfo const* spellInfo) override { - // We only care about interrupt effects and only if they are durring a spell currently being cast - if (spellInfo->HasEffect(SPELL_EFFECT_INTERRUPT_CAST) && me->IsNonMeleeSpellCast(false)) - { - // Interrupt effect - me->InterruptNonMeleeSpells(false); + //We only care about interrupt effects and only if they are durring a spell currently being cast + if (!spellInfo->HasEffect(SPELL_EFFECT_INTERRUPT_CAST) || !me->IsNonMeleeSpellCast(false)) + return; - // Normally we would set the cooldown equal to the spell duration - // but we do not have access to the DurationStore + //Interrupt effect + me->InterruptNonMeleeSpells(false); - switch (CurrentNormalSpell) - { - case SPELL_ARCMISSLE: ArcaneCooldown = 5000; break; - case SPELL_FIREBALL: FireCooldown = 5000; break; - case SPELL_FROSTBOLT: FrostCooldown = 5000; break; - } + //Normally we would set the cooldown equal to the spell duration + //but we do not have access to the DurationStore + + switch (CurrentNormalSpell) + { + case SPELL_ARCMISSLE: ArcaneCooldown = 5000; break; + case SPELL_FIREBALL: FireCooldown = 5000; break; + case SPELL_FROSTBOLT: FrostCooldown = 5000; break; } } diff --git a/src/server/scripts/EasternKingdoms/Scholomance/boss_darkmaster_gandling.cpp b/src/server/scripts/EasternKingdoms/Scholomance/boss_darkmaster_gandling.cpp index 3ef5498e7a7..fef3f9ea821 100644 --- a/src/server/scripts/EasternKingdoms/Scholomance/boss_darkmaster_gandling.cpp +++ b/src/server/scripts/EasternKingdoms/Scholomance/boss_darkmaster_gandling.cpp @@ -299,7 +299,7 @@ class spell_shadow_portal_rooms : public SpellScriptLoader return InstanceHasScript(GetCaster(), ScholomanceScriptName); } - void HandleSendEvent(SpellEffIndex effIndex) + void HandleSendEvent(SpellEffIndex /*effIndex*/) { // If only one player in threat list fail spell @@ -309,7 +309,7 @@ class spell_shadow_portal_rooms : public SpellScriptLoader int8 phase_to_set = 0; int32 gate_to_close = 0; - switch (GetSpellInfo()->GetEffect(effIndex)->MiscValue) + switch (GetEffectInfo().MiscValue) { case SPELL_EVENT_HALLOFSECRETS: pos_to_summon = 0; // Not yet spawned diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kalecgos.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kalecgos.cpp index ef29d76972b..71cd87f9b8a 100644 --- a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kalecgos.cpp +++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kalecgos.cpp @@ -603,12 +603,12 @@ class spell_kalecgos_tap_check : public SpellScript bool Validate(SpellInfo const* spellInfo) override { - return spellInfo->GetEffect(EFFECT_0) && ValidateSpellInfo({ uint32(spellInfo->GetEffect(EFFECT_0)->CalcValue()) }); + return !spellInfo->GetEffects().empty() && ValidateSpellInfo({ uint32(spellInfo->GetEffect(EFFECT_0).CalcValue()) }); } void HandleDummy(SpellEffIndex /*effIndex*/) { - GetHitUnit()->CastSpell(GetCaster(), (uint32)GetEffectInfo(EFFECT_0)->CalcValue(), true); + GetHitUnit()->CastSpell(GetCaster(), GetEffectInfo().CalcValue(), true); } void Register() override diff --git a/src/server/scripts/EasternKingdoms/zone_dun_morogh_area_coldridge_valley.cpp b/src/server/scripts/EasternKingdoms/zone_dun_morogh_area_coldridge_valley.cpp index ed287bbe846..9b0d1220ebe 100644 --- a/src/server/scripts/EasternKingdoms/zone_dun_morogh_area_coldridge_valley.cpp +++ b/src/server/scripts/EasternKingdoms/zone_dun_morogh_area_coldridge_valley.cpp @@ -380,7 +380,7 @@ public: void HandleForceCast(SpellEffIndex effIndex) { PreventHitDefaultEffect(effIndex); - GetHitUnit()->CastSpell(GetHitUnit(), GetSpellInfo()->GetEffect(effIndex)->TriggerSpell, true); + GetHitUnit()->CastSpell(GetHitUnit(), GetEffectInfo().TriggerSpell, true); } void Register() override @@ -412,7 +412,7 @@ public: void HandleForceCast(SpellEffIndex effIndex) { PreventHitDefaultEffect(effIndex); - GetHitUnit()->CastSpell(GetHitUnit(), GetSpellInfo()->GetEffect(effIndex)->TriggerSpell, true); + GetHitUnit()->CastSpell(GetHitUnit(), GetEffectInfo().TriggerSpell, true); } void Register() override diff --git a/src/server/scripts/Kalimdor/Firelands/boss_baleroc.cpp b/src/server/scripts/Kalimdor/Firelands/boss_baleroc.cpp index 7699375c69a..2307954145d 100644 --- a/src/server/scripts/Kalimdor/Firelands/boss_baleroc.cpp +++ b/src/server/scripts/Kalimdor/Firelands/boss_baleroc.cpp @@ -417,16 +417,16 @@ class spell_baleroc_decimating_strike : public SpellScript bool Validate(SpellInfo const* spellInfo) override { - if (!spellInfo->GetEffect(EFFECT_0)) + if (spellInfo->GetEffects().size() <= EFFECT_2) return false; - SpellEffectInfo const* spellEffectInfo = spellInfo->GetEffect(EFFECT_2); - return spellEffectInfo && ValidateSpellInfo({ uint32(spellEffectInfo->BasePoints) }); + SpellEffectInfo const& spellEffectInfo = spellInfo->GetEffect(EFFECT_2); + return ValidateSpellInfo({ uint32(spellEffectInfo.CalcValue()) }); } void ChangeDamage() { - int32 healthPctDmg = GetHitUnit()->CountPctFromMaxHealth(GetSpellInfo()->GetEffect(EFFECT_0)->BasePoints); - int32 flatDmg = GetSpellInfo()->GetEffect(EFFECT_2)->BasePoints; + int32 healthPctDmg = GetHitUnit()->CountPctFromMaxHealth(GetEffectInfo(EFFECT_0).CalcValue(GetCaster())); + int32 flatDmg = GetEffectInfo(EFFECT_2).CalcValue(GetCaster()); SetHitDamage(healthPctDmg < flatDmg ? flatDmg : healthPctDmg); } @@ -800,7 +800,8 @@ class spell_baleroc_vital_flame : public AuraScript bool Validate(SpellInfo const* /*spellInfo*/) override { - return ValidateSpellInfo({ SPELL_VITAL_SPARK }); + return ValidateSpellInfo({ SPELL_VITAL_SPARK }) + && !sSpellMgr->AssertSpellInfo(SPELL_VITAL_SPARK, DIFFICULTY_NONE)->GetEffects().empty(); } void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) @@ -812,7 +813,7 @@ class spell_baleroc_vital_flame : public AuraScript } stacks = GetCaster()->GetAuraCount(SPELL_VITAL_SPARK); - int32 healingPct = sSpellMgr->AssertSpellInfo(SPELL_VITAL_SPARK, GetCastDifficulty())->GetEffect(EFFECT_0)->BasePoints * stacks; + int32 healingPct = sSpellMgr->AssertSpellInfo(SPELL_VITAL_SPARK, GetCastDifficulty())->GetEffect(EFFECT_0).CalcValue(GetCaster()) * stacks; if (GetAura()->GetEffect(EFFECT_0)->GetAmount() < healingPct) GetAura()->GetEffect(EFFECT_0)->SetAmount(healingPct); diff --git a/src/server/scripts/Kalimdor/HallsOfOrigination/boss_anraphet.cpp b/src/server/scripts/Kalimdor/HallsOfOrigination/boss_anraphet.cpp index 907ccb7abb2..d92b75fa020 100644 --- a/src/server/scripts/Kalimdor/HallsOfOrigination/boss_anraphet.cpp +++ b/src/server/scripts/Kalimdor/HallsOfOrigination/boss_anraphet.cpp @@ -540,7 +540,7 @@ public: /// TODO: Remove this once we find a general rule for WorldObject::MovePosition (this spell shouldn't take the Z change into consideration) Unit* caster = GetCaster(); float angle = float(rand_norm()) * static_cast<float>(2 * M_PI); - uint32 dist = caster->GetCombatReach() + GetSpellInfo()->GetEffect(EFFECT_0)->CalcRadius(caster) * (float)rand_norm(); + uint32 dist = caster->GetCombatReach() + GetSpellInfo()->GetEffect(EFFECT_0).CalcRadius(caster) * (float)rand_norm(); float x = caster->GetPositionX() + dist * std::cos(angle); float y = caster->GetPositionY() + dist * std::sin(angle); diff --git a/src/server/scripts/Kalimdor/HallsOfOrigination/boss_temple_guardian_anhuur.cpp b/src/server/scripts/Kalimdor/HallsOfOrigination/boss_temple_guardian_anhuur.cpp index e125af5d46b..7adb716efb4 100644 --- a/src/server/scripts/Kalimdor/HallsOfOrigination/boss_temple_guardian_anhuur.cpp +++ b/src/server/scripts/Kalimdor/HallsOfOrigination/boss_temple_guardian_anhuur.cpp @@ -387,7 +387,7 @@ public: { CastSpellExtraArgs args; args.AddSpellMod(SPELLVALUE_BASE_POINT0, aurEff->GetAmount()); - caster->CastSpell(GetTarget(), aurEff->GetSpellEffectInfo()->TriggerSpell, args); + caster->CastSpell(GetTarget(), aurEff->GetSpellEffectInfo().TriggerSpell, args); } } diff --git a/src/server/scripts/Kalimdor/zone_dustwallow_marsh.cpp b/src/server/scripts/Kalimdor/zone_dustwallow_marsh.cpp index c5cf1f86109..392706bcc5f 100644 --- a/src/server/scripts/Kalimdor/zone_dustwallow_marsh.cpp +++ b/src/server/scripts/Kalimdor/zone_dustwallow_marsh.cpp @@ -242,14 +242,14 @@ class spell_ooze_zap : public SpellScriptLoader { PrepareSpellScript(spell_ooze_zap_SpellScript); - bool Validate(SpellInfo const* /*spellInfo*/) override + bool Validate(SpellInfo const* spellInfo) override { - return ValidateSpellInfo({ SPELL_OOZE_ZAP }); + return spellInfo->GetEffects().size() > EFFECT_1 && ValidateSpellInfo({ SPELL_OOZE_ZAP }); } SpellCastResult CheckRequirement() { - if (!GetCaster()->HasAura(GetSpellInfo()->GetEffect(EFFECT_1)->CalcValue())) + if (!GetCaster()->HasAura(GetEffectInfo(EFFECT_1).CalcValue())) return SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW; // This is actually correct if (!GetExplTargetUnit()) @@ -330,7 +330,7 @@ class spell_energize_aoe : public SpellScriptLoader { for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end();) { - if ((*itr)->GetTypeId() == TYPEID_PLAYER && (*itr)->ToPlayer()->GetQuestStatus(GetSpellInfo()->GetEffect(EFFECT_1)->CalcValue()) == QUEST_STATUS_INCOMPLETE) + if ((*itr)->GetTypeId() == TYPEID_PLAYER && (*itr)->ToPlayer()->GetQuestStatus(GetEffectInfo(EFFECT_1).CalcValue()) == QUEST_STATUS_INCOMPLETE) ++itr; else targets.erase(itr++); diff --git a/src/server/scripts/Kalimdor/zone_silithus.cpp b/src/server/scripts/Kalimdor/zone_silithus.cpp index 5f7c1745a22..16398d42ee3 100644 --- a/src/server/scripts/Kalimdor/zone_silithus.cpp +++ b/src/server/scripts/Kalimdor/zone_silithus.cpp @@ -1409,7 +1409,7 @@ class spell_silithus_summon_cultist_periodic : public AuraScript bool Validate(SpellInfo const* spellInfo) override { - return ValidateSpellInfo({ spellInfo->GetEffect(EFFECT_0)->TriggerSpell }); + return !spellInfo->GetEffects().empty() && ValidateSpellInfo({ spellInfo->GetEffect(EFFECT_0).TriggerSpell }); } void PeriodicTick(AuraEffect const* aurEff) @@ -1419,7 +1419,7 @@ class spell_silithus_summon_cultist_periodic : public AuraScript // All these spells trigger a spell that requires reagents; if the // triggered spell is cast as "triggered", reagents are not consumed if (Unit* caster = GetCaster()) - caster->CastSpell(nullptr, GetSpellInfo()->GetEffect(aurEff->GetEffIndex())->TriggerSpell, CastSpellExtraArgs(TriggerCastFlags(TRIGGERED_FULL_MASK & ~TRIGGERED_IGNORE_POWER_AND_REAGENT_COST)).SetTriggeringAura(aurEff)); + caster->CastSpell(nullptr, aurEff->GetSpellEffectInfo().TriggerSpell, CastSpellExtraArgs(TriggerCastFlags(TRIGGERED_FULL_MASK & ~TRIGGERED_IGNORE_POWER_AND_REAGENT_COST)).SetTriggeringAura(aurEff)); } void Register() override diff --git a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_herald_volazj.cpp b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_herald_volazj.cpp index 5e896f3b462..3b6c5828ac5 100644 --- a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_herald_volazj.cpp +++ b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_herald_volazj.cpp @@ -148,7 +148,7 @@ public: // clone player->CastSpell(summon, SPELL_CLONE_PLAYER, true); // phase the summon - PhasingHandler::AddPhase(summon, spellInfo->GetEffect(EFFECT_0)->MiscValueB, true); + PhasingHandler::AddPhase(summon, spellInfo->GetEffect(EFFECT_0).MiscValueB, true); } } ++insanityHandled; diff --git a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp index 1356b00a181..c12fbab7b88 100644 --- a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp +++ b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp @@ -1500,7 +1500,7 @@ class spell_halion_combustion_consumption_periodic : public SpellScriptLoader bool Validate(SpellInfo const* spellInfo) override { - return ValidateSpellInfo({ spellInfo->GetEffect(EFFECT_0)->TriggerSpell }); + return !spellInfo->GetEffects().empty() && ValidateSpellInfo({ spellInfo->GetEffect(EFFECT_0).TriggerSpell }); } void HandleTick(AuraEffect const* aurEff) @@ -1510,7 +1510,7 @@ class spell_halion_combustion_consumption_periodic : public SpellScriptLoader if (!caster) return; - uint32 triggerSpell = aurEff->GetSpellEffectInfo()->TriggerSpell; + uint32 triggerSpell = aurEff->GetSpellEffectInfo().TriggerSpell; int32 radius = caster->GetObjectScale() * M_PI * 10000 / 3; CastSpellExtraArgs args(aurEff); @@ -1606,8 +1606,8 @@ class spell_halion_damage_aoe_summon : public SpellScriptLoader { PreventHitDefaultEffect(effIndex); Unit* caster = GetCaster(); - uint32 entry = uint32(GetSpellInfo()->GetEffect(effIndex)->MiscValue); - SummonPropertiesEntry const* properties = sSummonPropertiesStore.LookupEntry(uint32(GetSpellInfo()->GetEffect(effIndex)->MiscValueB)); + uint32 entry = uint32(GetEffectInfo().MiscValue); + SummonPropertiesEntry const* properties = sSummonPropertiesStore.LookupEntry(uint32(GetEffectInfo().MiscValueB)); uint32 duration = uint32(GetSpellInfo()->GetDuration()); Position pos = caster->GetPosition(); @@ -1707,10 +1707,10 @@ class spell_halion_clear_debuffs : public SpellScriptLoader return ValidateSpellInfo({ SPELL_CLEAR_DEBUFFS, SPELL_TWILIGHT_REALM }); } - void HandleScript(SpellEffIndex effIndex) + void HandleScript(SpellEffIndex /*effIndex*/) { - if (GetHitUnit()->HasAura(GetSpellInfo()->GetEffect(effIndex)->CalcValue())) - GetHitUnit()->RemoveAurasDueToSpell(GetSpellInfo()->GetEffect(effIndex)->CalcValue()); + if (GetHitUnit()->HasAura(GetEffectInfo().CalcValue())) + GetHitUnit()->RemoveAurasDueToSpell(GetEffectInfo().CalcValue()); } void Register() override @@ -1891,7 +1891,7 @@ class spell_halion_blazing_aura : public SpellScriptLoader void HandleScript(SpellEffIndex effIndex) { PreventHitDefaultEffect(effIndex); - GetHitUnit()->CastSpell(GetHitUnit(), GetSpellInfo()->GetEffect(EFFECT_1)->TriggerSpell); + GetHitUnit()->CastSpell(GetHitUnit(), GetEffectInfo().TriggerSpell); } void Register() override diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp index 747546b9d12..8b341661df4 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp @@ -499,8 +499,7 @@ class spell_mistress_kiss_area : public SpellScript bool Validate(SpellInfo const* spellInfo) override { - SpellEffectInfo const* effect0 = spellInfo->GetEffect(EFFECT_0); - return effect0 && ValidateSpellInfo({ static_cast<uint32>(effect0->CalcValue()) }); + return !spellInfo->GetEffects().empty() && ValidateSpellInfo({ static_cast<uint32>(spellInfo->GetEffect(EFFECT_0).CalcValue()) }); } void FilterTargets(std::list<WorldObject*>& targets) @@ -538,8 +537,7 @@ class spell_fel_streak_visual : public SpellScript bool Validate(SpellInfo const* spellInfo) override { - SpellEffectInfo const* effect0 = spellInfo->GetEffect(EFFECT_0); - return effect0 && ValidateSpellInfo({ static_cast<uint32>(effect0->CalcValue()) }); + return !spellInfo->GetEffects().empty() && ValidateSpellInfo({ static_cast<uint32>(spellInfo->GetEffect(EFFECT_0).CalcValue()) }); } void HandleScript(SpellEffIndex /*effIndex*/) diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp index 5a067e8aad3..b2658110776 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp @@ -1189,7 +1189,7 @@ class spell_jormungars_slime_pool : public AuraScript bool Validate(SpellInfo const* spellInfo) override { - return ValidateSpellInfo({ spellInfo->GetEffect(EFFECT_0)->TriggerSpell }); + return !spellInfo->GetEffects().empty() && ValidateSpellInfo({ spellInfo->GetEffect(EFFECT_0).TriggerSpell }); } void PeriodicTick(AuraEffect const* aurEff) @@ -1199,7 +1199,7 @@ class spell_jormungars_slime_pool : public AuraScript int32 const radius = static_cast<int32>(((aurEff->GetTickNumber() / 60.f) * 0.9f + 0.1f) * 10000.f * 2.f / 3.f); CastSpellExtraArgs args(aurEff); args.AddSpellMod(SPELLVALUE_RADIUS_MOD, radius); - GetTarget()->CastSpell(nullptr, GetSpellInfo()->GetEffect(aurEff->GetEffIndex())->TriggerSpell, args); + GetTarget()->CastSpell(nullptr, aurEff->GetSpellEffectInfo().TriggerSpell, args); } void Register() override @@ -1277,12 +1277,12 @@ class spell_icehowl_arctic_breath : public SpellScript bool Validate(SpellInfo const* spellInfo) override { - return ValidateSpellInfo({ static_cast<uint32>(spellInfo->GetEffect(EFFECT_0)->CalcValue()) }); + return !spellInfo->GetEffects().empty() && ValidateSpellInfo({ static_cast<uint32>(spellInfo->GetEffect(EFFECT_0).CalcValue()) }); } - void HandleScriptEffect(SpellEffIndex effIndex) + void HandleScriptEffect(SpellEffIndex /*effIndex*/) { - uint32 spellId = GetSpellInfo()->GetEffect(effIndex)->CalcValue(); + uint32 spellId = GetEffectInfo().CalcValue(); GetCaster()->CastSpell(GetHitUnit(), spellId, true); } diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp index e70810e6182..06c786ff2ab 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp @@ -811,7 +811,7 @@ class spell_valkyr_essences : public SpellScriptLoader GetTarget()->CastSpell(GetTarget(), SPELL_SURGE_OF_SPEED, true); // Twin Vortex part - int32 stacksCount = dmgInfo.GetSpellInfo()->GetEffect(EFFECT_0)->CalcValue() / 1000 - 1; + int32 stacksCount = dmgInfo.GetSpellInfo()->GetEffect(EFFECT_0).CalcValue() / 1000 - 1; if (stacksCount) { diff --git a/src/server/scripts/Northrend/DraktharonKeep/boss_trollgore.cpp b/src/server/scripts/Northrend/DraktharonKeep/boss_trollgore.cpp index d05bff6386b..cbb468ad3dd 100644 --- a/src/server/scripts/Northrend/DraktharonKeep/boss_trollgore.cpp +++ b/src/server/scripts/Northrend/DraktharonKeep/boss_trollgore.cpp @@ -311,7 +311,7 @@ class spell_trollgore_invader_taunt : public SpellScriptLoader bool Validate(SpellInfo const* spellInfo) override { - return spellInfo->GetEffect(EFFECT_0) && ValidateSpellInfo({ static_cast<uint32>(spellInfo->GetEffect(EFFECT_0)->CalcValue()) }); + return !spellInfo->GetEffects().empty() && ValidateSpellInfo({ static_cast<uint32>(spellInfo->GetEffect(EFFECT_0).CalcValue()) }); } void HandleTaunt(SpellEffIndex /*effIndex*/) diff --git a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp index 84688b9a380..7cc0f87bd51 100644 --- a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp @@ -2791,7 +2791,7 @@ class spell_hor_evasion : public SpellScriptLoader return; float angle = pos.GetAngle(&home); - float dist = GetSpellInfo()->GetEffect(EFFECT_0)->CalcRadius(GetCaster()); + float dist = GetEffectInfo().CalcRadius(GetCaster()); target->MovePosition(pos, dist, angle); dest.Relocate(pos); @@ -2849,7 +2849,7 @@ class spell_hor_quel_delars_will : public SpellScript bool Validate(SpellInfo const* spellInfo) override { - return ValidateSpellInfo({ spellInfo->GetEffect(EFFECT_0)->TriggerSpell }); + return !spellInfo->GetEffects().empty() && ValidateSpellInfo({ spellInfo->GetEffect(EFFECT_0).TriggerSpell }); } void HandleReagent(SpellEffIndex effIndex) @@ -2857,7 +2857,7 @@ class spell_hor_quel_delars_will : public SpellScript PreventHitDefaultEffect(effIndex); // dummy spell consumes reagent, don't ignore it - GetHitUnit()->CastSpell(GetCaster(), GetSpellInfo()->GetEffect(effIndex)->TriggerSpell, TriggerCastFlags(TRIGGERED_FULL_MASK & ~TRIGGERED_IGNORE_POWER_AND_REAGENT_COST)); + GetHitUnit()->CastSpell(GetCaster(), GetEffectInfo().TriggerSpell, TriggerCastFlags(TRIGGERED_FULL_MASK & ~TRIGGERED_IGNORE_POWER_AND_REAGENT_COST)); } void Register() override diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp index a8bf0718f8b..515501dafcf 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp @@ -813,7 +813,7 @@ class spell_blood_queen_pact_of_the_darkfallen_dmg : public SpellScriptLoader void PeriodicTick(AuraEffect const* aurEff) { SpellInfo const* damageSpell = sSpellMgr->AssertSpellInfo(SPELL_PACT_OF_THE_DARKFALLEN_DAMAGE, GetCastDifficulty()); - int32 damage = damageSpell->GetEffect(EFFECT_0)->CalcValue(); + int32 damage = damageSpell->GetEffect(EFFECT_0).CalcValue(); float multiplier = 0.3375f + 0.1f * uint32(aurEff->GetTickNumber() / 10); // do not convert to 0.01f - we need tick number/10 as INT (damage increases every 10 ticks) damage = int32(damage * multiplier); diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp index c29683fa748..092cd40bf29 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp @@ -1829,7 +1829,8 @@ class spell_igb_rocket_pack : public SpellScriptLoader bool Validate(SpellInfo const* /*spellInfo*/) override { - return ValidateSpellInfo({ SPELL_ROCKET_PACK_DAMAGE, SPELL_ROCKET_BURST }); + return ValidateSpellInfo({ SPELL_ROCKET_PACK_DAMAGE, SPELL_ROCKET_BURST }) + && !sSpellMgr->AssertSpellInfo(SPELL_ROCKET_PACK_DAMAGE, DIFFICULTY_NONE)->GetEffects().empty(); } void HandlePeriodic(AuraEffect const* /*aurEff*/) @@ -1843,7 +1844,7 @@ class spell_igb_rocket_pack : public SpellScriptLoader SpellInfo const* damageInfo = sSpellMgr->AssertSpellInfo(SPELL_ROCKET_PACK_DAMAGE, GetCastDifficulty()); CastSpellExtraArgs args(TRIGGERED_FULL_MASK); args.CastDifficulty = GetCastDifficulty(); - args.AddSpellBP0(2 * (damageInfo->GetEffect(EFFECT_0)->CalcValue() + aurEff->GetTickNumber() * aurEff->GetPeriod())); + args.AddSpellBP0(2 * (damageInfo->GetEffect(EFFECT_0).CalcValue() + aurEff->GetTickNumber() * aurEff->GetPeriod())); GetTarget()->CastSpell(nullptr, SPELL_ROCKET_PACK_DAMAGE, args); GetTarget()->CastSpell(nullptr, SPELL_ROCKET_BURST, TRIGGERED_FULL_MASK); } @@ -1971,10 +1972,10 @@ class spell_igb_periodic_trigger_with_power_cost : public SpellScriptLoader { PrepareAuraScript(spell_igb_periodic_trigger_with_power_cost_AuraScript); - void HandlePeriodicTick(AuraEffect const* /*aurEff*/) + void HandlePeriodicTick(AuraEffect const* aurEff) { PreventDefaultAction(); - GetTarget()->CastSpell(GetTarget(), GetSpellInfo()->GetEffect(EFFECT_0)->TriggerSpell, TriggerCastFlags(TRIGGERED_FULL_MASK & ~TRIGGERED_IGNORE_POWER_AND_REAGENT_COST)); + GetTarget()->CastSpell(GetTarget(), aurEff->GetSpellEffectInfo().TriggerSpell, TriggerCastFlags(TRIGGERED_FULL_MASK & ~TRIGGERED_IGNORE_POWER_AND_REAGENT_COST)); } void Register() override diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp index 8be4018532d..ddec000524b 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp @@ -582,9 +582,8 @@ class spell_marrowgar_coldflame_damage : public SpellScriptLoader if (target->HasAura(SPELL_IMPALED)) return false; - if (SpellEffectInfo const* effect = GetSpellInfo()->GetEffect(EFFECT_0)) - if (target->GetExactDist2d(GetOwner()) > effect->CalcRadius()) - return false; + if (target->GetExactDist2d(GetOwner()) > GetEffectInfo(EFFECT_0).CalcRadius()) + return false; if (Aura* aur = target->GetAura(GetId())) if (aur->GetOwner() != GetOwner()) diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp index 233c1f35644..d09530233f7 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp @@ -1057,7 +1057,7 @@ class spell_putricide_unstable_experiment : public SpellScriptLoader break; } - GetCaster()->CastSpell(target, uint32(GetSpellInfo()->GetEffect(stage)->CalcValue()), true); + GetCaster()->CastSpell(target, uint32(GetEffectInfo(SpellEffIndex(stage)).CalcValue()), true); } void Register() override @@ -1114,9 +1114,8 @@ class spell_putricide_ooze_tank_protection : public SpellScriptLoader bool Validate(SpellInfo const* spellInfo) override { - SpellEffectInfo const* effect0 = spellInfo->GetEffect(EFFECT_0); - SpellEffectInfo const* effect1 = spellInfo->GetEffect(EFFECT_1); - return effect0 && effect1 && ValidateSpellInfo({ effect0->TriggerSpell, effect1->TriggerSpell }); + return spellInfo->GetEffects().size() > EFFECT_1 + && ValidateSpellInfo({ spellInfo->GetEffect(EFFECT_0).TriggerSpell, spellInfo->GetEffect(EFFECT_1).TriggerSpell }); } void HandleProc(AuraEffect* aurEff, ProcEventInfo& eventInfo) @@ -1124,7 +1123,7 @@ class spell_putricide_ooze_tank_protection : public SpellScriptLoader PreventDefaultAction(); Unit* actionTarget = eventInfo.GetActionTarget(); - actionTarget->CastSpell(nullptr, aurEff->GetSpellEffectInfo()->TriggerSpell, aurEff); + actionTarget->CastSpell(nullptr, aurEff->GetSpellEffectInfo().TriggerSpell, aurEff); } void Register() override @@ -1152,12 +1151,12 @@ class spell_putricide_choking_gas_bomb : public SpellScriptLoader void HandleScript(SpellEffIndex /*effIndex*/) { uint32 skipIndex = urand(0, 2); - for (SpellEffectInfo const* effect : GetSpellInfo()->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : GetSpellInfo()->GetEffects()) { - if (!effect || effect->EffectIndex == skipIndex) + if (spellEffectInfo.EffectIndex == skipIndex) continue; - uint32 spellId = uint32(effect->CalcValue()); + uint32 spellId = uint32(spellEffectInfo.CalcValue()); GetCaster()->CastSpell(GetCaster(), spellId, GetCaster()->GetGUID()); } } @@ -1314,10 +1313,10 @@ class spell_putricide_mutated_plague : public SpellScriptLoader if (!caster) return; - uint32 triggerSpell = aurEff->GetSpellEffectInfo()->TriggerSpell; + uint32 triggerSpell = aurEff->GetSpellEffectInfo().TriggerSpell; SpellInfo const* spell = sSpellMgr->AssertSpellInfo(triggerSpell, GetCastDifficulty()); - int32 damage = spell->GetEffect(EFFECT_0)->CalcValue(caster); + int32 damage = spell->GetEffect(EFFECT_0).CalcValue(caster); float multiplier = 2.0f; if (GetTarget()->GetMap()->Is25ManRaid()) multiplier = 3.0f; @@ -1331,15 +1330,15 @@ class spell_putricide_mutated_plague : public SpellScriptLoader GetTarget()->CastSpell(GetTarget(), triggerSpell, args); } - void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + void OnRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) { - uint32 healSpell = uint32(GetSpellInfo()->GetEffect(EFFECT_0)->CalcValue()); + uint32 healSpell = uint32(aurEff->GetSpellEffectInfo().CalcValue()); SpellInfo const* healSpellInfo = sSpellMgr->GetSpellInfo(healSpell, GetCastDifficulty()); if (!healSpellInfo) return; - int32 heal = healSpellInfo->GetEffect(EFFECT_0)->CalcValue() * GetStackAmount(); + int32 heal = healSpellInfo->GetEffect(EFFECT_0).CalcValue() * GetStackAmount(); CastSpellExtraArgs args(GetCasterGUID()); args.AddSpellBP0(heal); GetTarget()->CastSpell(GetTarget(), healSpell, args); @@ -1505,8 +1504,8 @@ class spell_putricide_mutated_transformation : public SpellScriptLoader return; } - uint32 entry = uint32(GetSpellInfo()->GetEffect(effIndex)->MiscValue); - SummonPropertiesEntry const* properties = sSummonPropertiesStore.LookupEntry(uint32(GetSpellInfo()->GetEffect(effIndex)->MiscValueB)); + uint32 entry = uint32(GetEffectInfo().MiscValue); + SummonPropertiesEntry const* properties = sSummonPropertiesStore.LookupEntry(uint32(GetEffectInfo().MiscValueB)); uint32 duration = uint32(GetSpellInfo()->GetDuration()); Position pos = caster->GetPosition(); diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_rotface.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_rotface.cpp index f15e751157d..94bc9d0310d 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_rotface.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_rotface.cpp @@ -550,14 +550,13 @@ class spell_rotface_mutated_infection : public SpellScriptLoader bool Validate(SpellInfo const* spellInfo) override { - SpellEffectInfo const* effect = spellInfo->GetEffect(EFFECT_2); - return effect && ValidateSpellInfo({ uint32(effect->CalcValue()) }); + return spellInfo->GetEffects().size() > EFFECT_2 && ValidateSpellInfo({ uint32(spellInfo->GetEffect(EFFECT_2).CalcValue()) }); } void HandleEffectRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) { Unit* target = GetTarget(); - target->CastSpell(target, uint32(GetSpellInfo()->GetEffect(EFFECT_2)->CalcValue()), { aurEff, GetCasterGUID() }); + target->CastSpell(target, uint32(GetEffectInfo(EFFECT_2).CalcValue()), { aurEff, GetCasterGUID() }); } void Register() override @@ -776,11 +775,11 @@ class spell_rotface_unstable_ooze_explosion : public SpellScriptLoader void CheckTarget(SpellEffIndex effIndex) { - PreventHitDefaultEffect(EFFECT_0); + PreventHitDefaultEffect(effIndex); if (!GetExplTargetDest()) return; - uint32 triggered_spell_id = GetSpellInfo()->GetEffect(effIndex)->TriggerSpell; + uint32 triggered_spell_id = GetEffectInfo().TriggerSpell; float x, y, z; GetExplTargetDest()->GetPosition(x, y, z); diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp index 158b63ab4f2..6d249e6ce16 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp @@ -1571,14 +1571,17 @@ class spell_frostwarden_handler_focus_fire : public SpellScriptLoader { PrepareAuraScript(spell_frostwarden_handler_focus_fire_AuraScript); + bool Validate(SpellInfo const* spellInfo) override + { + return spellInfo->GetEffects().size() > EFFECT_1; + } + void PeriodicTick(AuraEffect const* /*aurEff*/) { PreventDefaultAction(); if (Unit* caster = GetCaster()) { - if (SpellEffectInfo const* effect = GetSpellInfo()->GetEffect(EFFECT_1)) - caster->GetThreatManager().AddThreat(GetTarget(), -float(effect->CalcValue()), GetSpellInfo(), true, true); - + caster->GetThreatManager().AddThreat(GetTarget(), -float(GetEffectInfo(EFFECT_1).CalcValue()), GetSpellInfo(), true, true); caster->GetAI()->SetData(DATA_WHELP_MARKER, 0); } } diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp index 54605a25996..9b33c7b53ae 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp @@ -2494,14 +2494,14 @@ class spell_the_lich_king_summon_into_air : public SpellScriptLoader { PrepareSpellScript(spell_the_lich_king_summon_into_air_SpellScript); - void ModDestHeight(SpellEffIndex effIndex) + void ModDestHeight(SpellEffIndex /*effIndex*/) { static Position const offset = {0.0f, 0.0f, 15.0f, 0.0f}; WorldLocation* dest = const_cast<WorldLocation*>(GetExplTargetDest()); dest->RelocateOffset(offset); GetHitDest()->RelocateOffset(offset); // spirit bombs get higher - if (GetSpellInfo()->GetEffect(effIndex)->MiscValue == NPC_SPIRIT_BOMB) + if (GetEffectInfo().MiscValue == NPC_SPIRIT_BOMB) { static Position const offsetExtra = { 0.0f, 0.0f, 5.0f, 0.0f }; dest->RelocateOffset(offsetExtra); @@ -2695,7 +2695,7 @@ class spell_the_lich_king_vile_spirits : public SpellScriptLoader void OnPeriodic(AuraEffect const* aurEff) { if (_is25Man || ((aurEff->GetTickNumber() - 1) % 5)) - GetTarget()->CastSpell(nullptr, aurEff->GetSpellEffectInfo()->TriggerSpell, { aurEff, GetCasterGUID() }); + GetTarget()->CastSpell(nullptr, aurEff->GetSpellEffectInfo().TriggerSpell, { aurEff, GetCasterGUID() }); } void Register() override diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp index bbd04e7890b..baec83a7608 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp @@ -248,7 +248,7 @@ class ValithriaDespawner : public BasicEvent default: return; } - + creature->DespawnOrUnsummon(0, 10s); } @@ -1235,7 +1235,7 @@ class spell_dreamwalker_summoner : public SpellScriptLoader if (!GetHitUnit()) return; - GetHitUnit()->CastSpell(GetCaster(), GetSpellInfo()->GetEffect(effIndex)->TriggerSpell, GetCaster()->GetInstanceScript()->GetGuidData(DATA_VALITHRIA_LICH_KING)); + GetHitUnit()->CastSpell(GetCaster(), GetEffectInfo().TriggerSpell, GetCaster()->GetInstanceScript()->GetGuidData(DATA_VALITHRIA_LICH_KING)); } void Register() override @@ -1326,7 +1326,7 @@ class spell_dreamwalker_summon_suppresser_effect : public SpellScriptLoader if (!GetHitUnit()) return; - GetHitUnit()->CastSpell(GetCaster(), GetSpellInfo()->GetEffect(effIndex)->TriggerSpell, GetCaster()->GetInstanceScript()->GetGuidData(DATA_VALITHRIA_LICH_KING)); + GetHitUnit()->CastSpell(GetCaster(), GetEffectInfo().TriggerSpell, GetCaster()->GetInstanceScript()->GetGuidData(DATA_VALITHRIA_LICH_KING)); } void Register() override @@ -1462,7 +1462,7 @@ class spell_dreamwalker_twisted_nightmares : public SpellScriptLoader // return; if (InstanceScript* instance = GetHitUnit()->GetInstanceScript()) - GetHitUnit()->CastSpell(nullptr, GetSpellInfo()->GetEffect(effIndex)->TriggerSpell, instance->GetGuidData(DATA_VALITHRIA_DREAMWALKER)); + GetHitUnit()->CastSpell(nullptr, GetEffectInfo().TriggerSpell, instance->GetGuidData(DATA_VALITHRIA_DREAMWALKER)); } void Register() override diff --git a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp index a1b4698a37c..1500349fd50 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp @@ -1847,7 +1847,7 @@ class spell_icc_sprit_alarm : public SpellScriptLoader { PreventHitDefaultEffect(effIndex); uint32 trapId = 0; - switch (GetSpellInfo()->GetEffect(effIndex)->MiscValue) + switch (GetEffectInfo().MiscValue) { case EVENT_AWAKEN_WARD_1: trapId = GO_SPIRIT_ALARM_1; diff --git a/src/server/scripts/Northrend/Naxxramas/boss_grobbulus.cpp b/src/server/scripts/Northrend/Naxxramas/boss_grobbulus.cpp index c529a580917..33ba844ca4a 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_grobbulus.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_grobbulus.cpp @@ -193,8 +193,8 @@ class spell_grobbulus_poison_cloud : public SpellScriptLoader bool Validate(SpellInfo const* spellInfo) override { - SpellEffectInfo const* effect0 = spellInfo->GetEffect(EFFECT_0); - return effect0 && ValidateSpellInfo({ effect0->TriggerSpell }); + return !spellInfo->GetEffects().empty() + && ValidateSpellInfo({ spellInfo->GetEffect(EFFECT_0).TriggerSpell }); } void PeriodicTick(AuraEffect const* aurEff) @@ -203,7 +203,7 @@ class spell_grobbulus_poison_cloud : public SpellScriptLoader if (!aurEff->GetTotalTicks()) return; - uint32 triggerSpell = aurEff->GetSpellEffectInfo()->TriggerSpell; + uint32 triggerSpell = aurEff->GetSpellEffectInfo().TriggerSpell; int32 mod = int32(((float(aurEff->GetTickNumber()) / aurEff->GetTotalTicks()) * 0.9f + 0.1f) * 10000 * 2 / 3); CastSpellExtraArgs args(aurEff); diff --git a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp index 60152408e4c..aa31ee41ea6 100644 --- a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp +++ b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp @@ -1899,7 +1899,7 @@ class spell_arcane_overload : public SpellScriptLoader { Creature* arcaneOverload = GetCaster()->ToCreature(); targets.remove_if(ExactDistanceCheck(arcaneOverload, - GetSpellInfo()->GetEffect(EFFECT_0)->CalcRadius(arcaneOverload) * arcaneOverload->GetObjectScale())); + GetEffectInfo(EFFECT_0).CalcRadius(arcaneOverload) * arcaneOverload->GetObjectScale())); } void Register() override diff --git a/src/server/scripts/Northrend/Nexus/Oculus/oculus.cpp b/src/server/scripts/Northrend/Nexus/Oculus/oculus.cpp index f61ab9bf2b3..a87a11e9076 100644 --- a/src/server/scripts/Northrend/Nexus/Oculus/oculus.cpp +++ b/src/server/scripts/Northrend/Nexus/Oculus/oculus.cpp @@ -453,7 +453,7 @@ class spell_oculus_ride_ruby_emerald_amber_drake_que : public SpellScriptLoader // caster of the triggered spell is wrong for an unknown reason, handle it here correctly PreventDefaultAction(); if (Unit* caster = GetCaster()) - GetTarget()->CastSpell(caster, aurEff->GetSpellEffectInfo()->TriggerSpell, true); + GetTarget()->CastSpell(caster, aurEff->GetSpellEffectInfo().TriggerSpell, true); } void Register() override diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_krystallus.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_krystallus.cpp index a8f0924c9e4..59ca0c6e0f9 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_krystallus.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_krystallus.cpp @@ -181,12 +181,17 @@ class spell_krystallus_shatter_effect : public SpellScriptLoader { PrepareSpellScript(spell_krystallus_shatter_effect_SpellScript); + bool Validate(SpellInfo const* spellInfo) override + { + return !spellInfo->GetEffects().empty(); + } + void CalculateDamage() { if (!GetHitUnit()) return; - float radius = GetSpellInfo()->GetEffect(EFFECT_0)->CalcRadius(GetCaster()); + float radius = GetSpellInfo()->GetEffect(EFFECT_0).CalcRadius(GetCaster()); if (!radius) return; diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp index 6db930756a2..c704265493a 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp @@ -1526,13 +1526,13 @@ class spell_tar_blaze : public AuraScript bool Validate(SpellInfo const* spellInfo) override { - return ValidateSpellInfo({ spellInfo->GetEffect(EFFECT_0)->TriggerSpell }); + return !spellInfo->GetEffects().empty() && ValidateSpellInfo({ spellInfo->GetEffect(EFFECT_0).TriggerSpell }); } void PeriodicTick(AuraEffect const* aurEff) { // should we use custom damage? - GetTarget()->CastSpell(nullptr, GetSpellInfo()->GetEffect(aurEff->GetEffIndex())->TriggerSpell, true); + GetTarget()->CastSpell(nullptr, aurEff->GetSpellEffectInfo().TriggerSpell, true); } void Register() override @@ -1792,7 +1792,7 @@ class spell_vehicle_throw_passenger : public SpellScriptLoader class spell_vehicle_throw_passenger_SpellScript : public SpellScript { PrepareSpellScript(spell_vehicle_throw_passenger_SpellScript); - void HandleScript(SpellEffIndex effIndex) + void HandleScript(SpellEffIndex /*effIndex*/) { Spell* baseSpell = GetSpell(); SpellCastTargets targets = baseSpell->m_targets; @@ -1825,7 +1825,7 @@ class spell_vehicle_throw_passenger : public SpellScriptLoader } } } - if (target && target->IsWithinDist2d(targets.GetDstPos(), GetSpellInfo()->GetEffect(effIndex)->CalcRadius() * 2)) // now we use *2 because the location of the seat is not correct + if (target && target->IsWithinDist2d(targets.GetDstPos(), GetEffectInfo().CalcRadius() * 2)) // now we use *2 because the location of the seat is not correct passenger->EnterVehicle(target, 0); else { diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp index 083c37d4763..a0f3d711bee 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp @@ -1583,7 +1583,7 @@ class spell_freya_iron_roots : public SpellScriptLoader void HandleSummon(SpellEffIndex effIndex) { PreventHitDefaultEffect(effIndex); - uint32 entry = uint32(GetSpellInfo()->GetEffect(effIndex)->MiscValue); + uint32 entry = uint32(GetEffectInfo().MiscValue); Position pos = GetCaster()->GetPosition(); // Not good at all, but this prevents having roots in a different position then player diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_kologarn.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_kologarn.cpp index e1c81c0a286..9d234ce1888 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_kologarn.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_kologarn.cpp @@ -448,23 +448,22 @@ class spell_ulduar_cancel_stone_grip : public SpellScriptLoader { PrepareSpellScript(spell_ulduar_cancel_stone_gripSpellScript); + bool Validate(SpellInfo const* spellInfo) override + { + return spellInfo->GetEffects().size() > EFFECT_1; + } + void HandleScript(SpellEffIndex /*effIndex*/) { Unit* target = GetHitUnit(); if (!target || !target->GetVehicle()) return; - switch (target->GetMap()->GetDifficultyID()) - { - case DIFFICULTY_10_N: - target->RemoveAura(GetSpellInfo()->GetEffect(EFFECT_0)->CalcValue()); - break; - case DIFFICULTY_25_N: - target->RemoveAura(GetSpellInfo()->GetEffect(EFFECT_1)->CalcValue()); - break; - default: - break; - } + SpellEffIndex effectIndexToCancel = EFFECT_0; + if (target->GetMap()->Is25ManRaid()) + effectIndexToCancel = EFFECT_1; + + target->RemoveAura(GetEffectInfo(effectIndexToCancel).CalcValue()); } void Register() override @@ -647,7 +646,7 @@ class spell_kologarn_summon_focused_eyebeam : public SpellScriptLoader void HandleForceCast(SpellEffIndex effIndex) { PreventHitDefaultEffect(effIndex); - GetCaster()->CastSpell(GetCaster(), GetSpellInfo()->GetEffect(effIndex)->TriggerSpell, true); + GetCaster()->CastSpell(GetCaster(), GetEffectInfo().TriggerSpell, true); } void Register() override diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_thorim.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_thorim.cpp index 66f2eae6fe0..e72c83742e1 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_thorim.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_thorim.cpp @@ -959,13 +959,13 @@ struct npc_thorim_trashAI : public ScriptedAI static uint32 GetTotalHeal(SpellInfo const* spellInfo, Unit const* caster) { uint32 heal = 0; - for (SpellEffectInfo const* effect : spellInfo->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : spellInfo->GetEffects()) { - if (effect->IsEffect(SPELL_EFFECT_HEAL)) - heal += effect->CalcValue(caster); + if (spellEffectInfo.IsEffect(SPELL_EFFECT_HEAL)) + heal += spellEffectInfo.CalcValue(caster); - if (effect->IsEffect(SPELL_EFFECT_APPLY_AURA) && effect->IsAura(SPELL_AURA_PERIODIC_HEAL)) - heal += spellInfo->GetMaxTicks() * effect->CalcValue(caster); + if (spellEffectInfo.IsEffect(SPELL_EFFECT_APPLY_AURA) && spellEffectInfo.IsAura(SPELL_AURA_PERIODIC_HEAL)) + heal += spellInfo->GetMaxTicks() * spellEffectInfo.CalcValue(caster); } return heal; } diff --git a/src/server/scripts/Northrend/VioletHold/boss_moragg.cpp b/src/server/scripts/Northrend/VioletHold/boss_moragg.cpp index db2946ce825..2a2737bd127 100644 --- a/src/server/scripts/Northrend/VioletHold/boss_moragg.cpp +++ b/src/server/scripts/Northrend/VioletHold/boss_moragg.cpp @@ -108,7 +108,7 @@ class spell_moragg_ray : public SpellScriptLoader if (Unit* target = GetTarget()->GetAI()->SelectTarget(SELECT_TARGET_RANDOM, 0, 45.0f, true)) { - uint32 triggerSpell = aurEff->GetSpellEffectInfo()->TriggerSpell; + uint32 triggerSpell = aurEff->GetSpellEffectInfo().TriggerSpell; GetTarget()->CastSpell(target, triggerSpell, aurEff); } } diff --git a/src/server/scripts/Northrend/zone_storm_peaks.cpp b/src/server/scripts/Northrend/zone_storm_peaks.cpp index 4beecee5eed..e581a8d742d 100644 --- a/src/server/scripts/Northrend/zone_storm_peaks.cpp +++ b/src/server/scripts/Northrend/zone_storm_peaks.cpp @@ -1327,7 +1327,7 @@ public: bool Validate(SpellInfo const* spellInfo) override { - return ValidateSpellInfo({ uint32(spellInfo->GetEffect(EFFECT_0)->CalcValue()) }); + return !spellInfo->GetEffects().empty() && ValidateSpellInfo({ static_cast<uint32>(spellInfo->GetEffect(EFFECT_0).CalcValue()) }); } void HandleScript(SpellEffIndex /*effIndex*/) diff --git a/src/server/scripts/Northrend/zone_wintergrasp.cpp b/src/server/scripts/Northrend/zone_wintergrasp.cpp index a7db09490ad..0924cdf16cf 100644 --- a/src/server/scripts/Northrend/zone_wintergrasp.cpp +++ b/src/server/scripts/Northrend/zone_wintergrasp.cpp @@ -590,10 +590,9 @@ class spell_wintergrasp_tenacity_refresh : public AuraScript bool Validate(SpellInfo const* spellInfo) override { - SpellEffectInfo const* effect2 = spellInfo->GetEffect(EFFECT_2); - if (!effect2) + if (spellInfo->GetEffects().size() <= EFFECT_2) return false; - uint32 triggeredSpellId = effect2->CalcValue(); + uint32 triggeredSpellId = spellInfo->GetEffect(EFFECT_2).CalcValue(); return !triggeredSpellId || ValidateSpellInfo({ triggeredSpellId }); } @@ -601,7 +600,7 @@ class spell_wintergrasp_tenacity_refresh : public AuraScript { PreventDefaultAction(); - if (uint32 triggeredSpellId = aurEff->GetSpellEffectInfo()->CalcValue()) + if (uint32 triggeredSpellId = aurEff->GetSpellEffectInfo().CalcValue()) { int32 bp = 0; if (AuraEffect const* healEffect = GetEffect(EFFECT_0)) @@ -619,7 +618,7 @@ class spell_wintergrasp_tenacity_refresh : public AuraScript void OnRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) { - if (uint32 triggeredSpellId = aurEff->GetSpellEffectInfo()->CalcValue()) + if (uint32 triggeredSpellId = aurEff->GetSpellEffectInfo().CalcValue()) GetTarget()->RemoveAurasDueToSpell(triggeredSpellId); } diff --git a/src/server/scripts/Outland/BlackTemple/boss_mother_shahraz.cpp b/src/server/scripts/Outland/BlackTemple/boss_mother_shahraz.cpp index f5b8418fd11..0e88b976fe1 100644 --- a/src/server/scripts/Outland/BlackTemple/boss_mother_shahraz.cpp +++ b/src/server/scripts/Outland/BlackTemple/boss_mother_shahraz.cpp @@ -262,14 +262,15 @@ class spell_mother_shahraz_saber_lash : public AuraScript bool Validate(SpellInfo const* spellInfo) override { - return ValidateSpellInfo({ spellInfo->GetEffect(EFFECT_1)->TriggerSpell }); + return spellInfo->GetEffects().size() > EFFECT_1 + && ValidateSpellInfo({ spellInfo->GetEffect(EFFECT_1).TriggerSpell }); } void OnTrigger(AuraEffect const* aurEff) { PreventDefaultAction(); - uint32 triggerSpell = aurEff->GetSpellEffectInfo()->TriggerSpell; + uint32 triggerSpell = aurEff->GetSpellEffectInfo().TriggerSpell; if (Unit* target = GetUnitOwner()->GetAI()->SelectTarget(SELECT_TARGET_RANDOM, 0)) GetUnitOwner()->CastSpell(target, triggerSpell, true); } @@ -290,14 +291,15 @@ class spell_mother_shahraz_generic_periodic : public AuraScript bool Validate(SpellInfo const* spellInfo) override { - return ValidateSpellInfo({ spellInfo->GetEffect(EFFECT_0)->TriggerSpell }); + return !spellInfo->GetEffects().empty() + && ValidateSpellInfo({ spellInfo->GetEffect(EFFECT_0).TriggerSpell }); } void OnTrigger(AuraEffect const* aurEff) { PreventDefaultAction(); - uint32 triggerSpell = aurEff->GetSpellEffectInfo()->TriggerSpell; + uint32 triggerSpell = aurEff->GetSpellEffectInfo().TriggerSpell; if (Unit* target = GetUnitOwner()->GetAI()->SelectTarget(SELECT_TARGET_RANDOM, 0)) GetUnitOwner()->CastSpell(target, triggerSpell, true); } diff --git a/src/server/scripts/Outland/GruulsLair/boss_gruul.cpp b/src/server/scripts/Outland/GruulsLair/boss_gruul.cpp index f050c1d9e39..fae7d777b32 100644 --- a/src/server/scripts/Outland/GruulsLair/boss_gruul.cpp +++ b/src/server/scripts/Outland/GruulsLair/boss_gruul.cpp @@ -309,12 +309,17 @@ class spell_gruul_shatter_effect : public SpellScriptLoader { PrepareSpellScript(spell_gruul_shatter_effect_SpellScript); + bool Validate(SpellInfo const* spellInfo) override + { + return !spellInfo->GetEffects().empty(); + } + void CalculateDamage() { if (!GetHitUnit()) return; - float radius = GetSpellInfo()->GetEffect(EFFECT_0)->CalcRadius(GetCaster()); + float radius = GetEffectInfo(EFFECT_0).CalcRadius(GetCaster()); if (!radius) return; diff --git a/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/boss_broggok.cpp b/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/boss_broggok.cpp index 334e7335ccd..23100fea7c5 100644 --- a/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/boss_broggok.cpp +++ b/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/boss_broggok.cpp @@ -171,8 +171,7 @@ class spell_broggok_poison_cloud : public SpellScriptLoader bool Validate(SpellInfo const* spellInfo) override { - SpellEffectInfo const* effect0 = spellInfo->GetEffect(EFFECT_0); - return effect0 && ValidateSpellInfo({ effect0->TriggerSpell }); + return !spellInfo->GetEffects().empty() && ValidateSpellInfo({ spellInfo->GetEffect(EFFECT_0).TriggerSpell }); } void PeriodicTick(AuraEffect const* aurEff) @@ -181,7 +180,7 @@ class spell_broggok_poison_cloud : public SpellScriptLoader if (!aurEff->GetTotalTicks()) return; - uint32 triggerSpell = aurEff->GetSpellEffectInfo()->TriggerSpell; + uint32 triggerSpell = aurEff->GetSpellEffectInfo().TriggerSpell; int32 mod = int32(((float(aurEff->GetTickNumber()) / aurEff->GetTotalTicks()) * 0.9f + 0.1f) * 10000 * 2 / 3); GetTarget()->CastSpell(nullptr, triggerSpell, CastSpellExtraArgs(aurEff).AddSpellMod(SPELLVALUE_RADIUS_MOD, mod)); } diff --git a/src/server/scripts/Outland/TempestKeep/Eye/boss_astromancer.cpp b/src/server/scripts/Outland/TempestKeep/Eye/boss_astromancer.cpp index f7874b392f7..b3a4ae4144c 100644 --- a/src/server/scripts/Outland/TempestKeep/Eye/boss_astromancer.cpp +++ b/src/server/scripts/Outland/TempestKeep/Eye/boss_astromancer.cpp @@ -512,9 +512,10 @@ class spell_astromancer_wrath_of_the_astromancer : public SpellScriptLoader { PrepareAuraScript(spell_astromancer_wrath_of_the_astromancer_AuraScript); - bool Validate(SpellInfo const* /*spellInfo*/) override + bool Validate(SpellInfo const* spellInfo) override { - return ValidateSpellInfo({ SPELL_WRATH_OF_THE_ASTROMANCER_DOT }); + return ValidateSpellInfo({ SPELL_WRATH_OF_THE_ASTROMANCER_DOT }) + && spellInfo->GetEffects().size() > EFFECT_1; } void AfterRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) @@ -524,7 +525,7 @@ class spell_astromancer_wrath_of_the_astromancer : public SpellScriptLoader return; Unit* target = GetUnitOwner(); - target->CastSpell(target, GetSpellInfo()->GetEffect(EFFECT_1)->CalcValue(), false); + target->CastSpell(target, GetEffectInfo(EFFECT_1).CalcValue(), false); } void Register() override diff --git a/src/server/scripts/Spells/spell_dk.cpp b/src/server/scripts/Spells/spell_dk.cpp index fb46a1ee3e3..3f61ed7058c 100644 --- a/src/server/scripts/Spells/spell_dk.cpp +++ b/src/server/scripts/Spells/spell_dk.cpp @@ -120,14 +120,14 @@ public: absorbedAmount = 0; } - bool Validate(SpellInfo const* /*spellInfo*/) override + bool Validate(SpellInfo const* spellInfo) override { - return ValidateSpellInfo({ SPELL_DK_RUNIC_POWER_ENERGIZE, SPELL_DK_VOLATILE_SHIELDING }); + return ValidateSpellInfo({ SPELL_DK_RUNIC_POWER_ENERGIZE, SPELL_DK_VOLATILE_SHIELDING }) && spellInfo->GetEffects().size() > EFFECT_1; } bool Load() override { - absorbPct = GetSpellInfo()->GetEffect(EFFECT_1)->CalcValue(GetCaster()); + absorbPct = GetEffectInfo(EFFECT_1).CalcValue(GetCaster()); maxHealth = GetCaster()->GetMaxHealth(); absorbedAmount = 0; return true; @@ -465,8 +465,7 @@ class spell_dk_death_strike : public SpellScript SPELL_DK_FROST, SPELL_DK_DEATH_STRIKE_OFFHAND }) - && spellInfo->GetEffect(EFFECT_1) - && spellInfo->GetEffect(EFFECT_2); + && spellInfo->GetEffects().size() > EFFECT_2; } void HandleDummy(SpellEffIndex /*effIndex*/) @@ -475,12 +474,10 @@ class spell_dk_death_strike : public SpellScript if (AuraEffect* enabler = caster->GetAuraEffect(SPELL_DK_DEATH_STRIKE_ENABLER, EFFECT_0, GetCaster()->GetGUID())) { - SpellInfo const* spellInfo = GetSpellInfo(); - // Heals you for 25% of all damage taken in the last 5 sec, - int32 heal = CalculatePct(enabler->CalculateAmount(GetCaster()), spellInfo->GetEffect(EFFECT_1)->CalcValue(GetCaster())); + int32 heal = CalculatePct(enabler->CalculateAmount(GetCaster()), GetEffectInfo(EFFECT_1).CalcValue(GetCaster())); // minimum 7.0% of maximum health. - int32 pctOfMaxHealth = CalculatePct(spellInfo->GetEffect(EFFECT_2)->CalcValue(GetCaster()), caster->GetMaxHealth()); + int32 pctOfMaxHealth = CalculatePct(GetEffectInfo(EFFECT_2).CalcValue(GetCaster()), caster->GetMaxHealth()); heal = std::max(heal, pctOfMaxHealth); caster->CastSpell(caster, SPELL_DK_DEATH_STRIKE_HEAL, CastSpellExtraArgs(TRIGGERED_FULL_MASK).AddSpellMod(SPELLVALUE_BASE_POINT0, heal)); @@ -574,14 +571,14 @@ class spell_dk_ghoul_explode : public SpellScript { PrepareSpellScript(spell_dk_ghoul_explode); - bool Validate(SpellInfo const* /*spellInfo*/) override + bool Validate(SpellInfo const* spellInfo) override { - return ValidateSpellInfo({ SPELL_DK_CORPSE_EXPLOSION_TRIGGERED }); + return ValidateSpellInfo({ SPELL_DK_CORPSE_EXPLOSION_TRIGGERED }) && spellInfo->GetEffects().size() > EFFECT_2; } void HandleDamage(SpellEffIndex /*effIndex*/) { - SetHitDamage(GetCaster()->CountPctFromMaxHealth(GetEffectInfo(EFFECT_2)->CalcValue(GetCaster()))); + SetHitDamage(GetCaster()->CountPctFromMaxHealth(GetEffectInfo(EFFECT_2).CalcValue(GetCaster()))); } void Suicide(SpellEffIndex /*effIndex*/) diff --git a/src/server/scripts/Spells/spell_druid.cpp b/src/server/scripts/Spells/spell_druid.cpp index 9fadf1612f3..06b197b4c7b 100644 --- a/src/server/scripts/Spells/spell_druid.cpp +++ b/src/server/scripts/Spells/spell_druid.cpp @@ -472,7 +472,7 @@ class spell_dru_ferocious_bite : public SpellScript bool Validate(SpellInfo const* /*spellInfo*/) override { return ValidateSpellInfo({ SPELL_DRUID_INCARNATION_KING_OF_THE_JUNGLE }) - && sSpellMgr->AssertSpellInfo(SPELL_DRUID_INCARNATION_KING_OF_THE_JUNGLE, DIFFICULTY_NONE)->GetEffect(EFFECT_1); + && sSpellMgr->AssertSpellInfo(SPELL_DRUID_INCARNATION_KING_OF_THE_JUNGLE, DIFFICULTY_NONE)->GetEffects().size() > EFFECT_1; } void HandleHitTargetBurn(SpellEffIndex /*effIndex*/) @@ -709,7 +709,7 @@ public: spellMod->op = SpellModOp::PeriodicHealingAndDamage; spellMod->type = SPELLMOD_FLAT; spellMod->spellId = GetId(); - spellMod->mask = aurEff->GetSpellEffectInfo()->SpellClassMask; + spellMod->mask = aurEff->GetSpellEffectInfo().SpellClassMask; } spellMod->value = aurEff->GetAmount() / 7; } @@ -1959,8 +1959,7 @@ public: bool Validate(SpellInfo const* spellInfo) override { - SpellEffectInfo const* effect2 = spellInfo->GetEffect(EFFECT_2); - if (!effect2 || effect2->IsEffect() || effect2->CalcValue() <= 0) + if (spellInfo->GetEffects().size() <= EFFECT_2 || spellInfo->GetEffect(EFFECT_2).IsEffect() || spellInfo->GetEffect(EFFECT_2).CalcValue() <= 0) return false; return true; } @@ -1969,7 +1968,7 @@ public: { targets.remove_if(RaidCheck(GetCaster())); - uint32 const maxTargets = uint32(GetSpellInfo()->GetEffect(EFFECT_2)->CalcValue(GetCaster())); + uint32 const maxTargets = uint32(GetEffectInfo(EFFECT_2).CalcValue(GetCaster())); if (targets.size() > maxTargets) { @@ -2010,7 +2009,7 @@ public: return; // calculate from base damage, not from aurEff->GetAmount() (already modified) - float damage = caster->CalculateSpellDamage(GetUnitOwner(), GetSpellInfo(), aurEff->GetEffIndex()); + float damage = caster->CalculateSpellDamage(GetUnitOwner(), aurEff->GetSpellEffectInfo()); // Wild Growth = first tick gains a 6% bonus, reduced by 2% each tick float reduction = 2.f; diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp index 7875e4522aa..9971cc20d4c 100644 --- a/src/server/scripts/Spells/spell_generic.cpp +++ b/src/server/scripts/Spells/spell_generic.cpp @@ -52,7 +52,7 @@ class spell_gen_absorb0_hitlimit1 : public AuraScript bool Load() override { // Max absorb stored in 1 dummy effect - limit = GetSpellInfo()->GetEffect(EFFECT_1)->CalcValue(); + limit = GetSpellInfo()->GetEffect(EFFECT_1).CalcValue(); return true; } @@ -229,7 +229,7 @@ class spell_gen_arena_drink : public AuraScript bool Validate(SpellInfo const* spellInfo) override { - if (!spellInfo->GetEffect(EFFECT_0)->IsAura() || spellInfo->GetEffect(EFFECT_0)->ApplyAuraName != SPELL_AURA_MOD_POWER_REGEN) + if (spellInfo->GetEffects().empty() || !spellInfo->GetEffect(EFFECT_0).IsAura(SPELL_AURA_MOD_POWER_REGEN)) { TC_LOG_ERROR("spells", "Aura %d structure has been changed - first aura is no longer SPELL_AURA_MOD_POWER_REGEN", GetId()); return false; @@ -328,7 +328,7 @@ class spell_gen_aura_of_fear : public AuraScript bool Validate(SpellInfo const* spellInfo) override { - return ValidateSpellInfo({ spellInfo->GetEffect(EFFECT_0)->TriggerSpell }); + return !spellInfo->GetEffects().empty() && ValidateSpellInfo({ spellInfo->GetEffect(EFFECT_0).TriggerSpell }); } void PeriodicTick(AuraEffect const* aurEff) @@ -337,7 +337,7 @@ class spell_gen_aura_of_fear : public AuraScript if (!roll_chance_i(GetSpellInfo()->ProcChance)) return; - GetTarget()->CastSpell(nullptr, GetSpellInfo()->GetEffect(aurEff->GetEffIndex())->TriggerSpell, true); + GetTarget()->CastSpell(nullptr, aurEff->GetSpellEffectInfo().TriggerSpell, true); } void Register() override @@ -676,18 +676,18 @@ class spell_gen_burning_depths_necrolyte_image : public AuraScript bool Validate(SpellInfo const* spellInfo) override { - return ValidateSpellInfo({ static_cast<uint32>(spellInfo->GetEffect(EFFECT_2)->CalcValue()) }); + return spellInfo->GetEffects().size() > EFFECT_2 && ValidateSpellInfo({ static_cast<uint32>(spellInfo->GetEffect(EFFECT_2).CalcValue()) }); } void HandleApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) { if (Unit* caster = GetCaster()) - caster->CastSpell(GetTarget(), uint32(GetSpellInfo()->GetEffect(EFFECT_2)->CalcValue())); + caster->CastSpell(GetTarget(), uint32(GetEffectInfo(EFFECT_2).CalcValue())); } void HandleRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) { - GetTarget()->RemoveAurasDueToSpell(uint32(GetSpellInfo()->GetEffect(EFFECT_2)->CalcValue()), GetCasterGUID()); + GetTarget()->RemoveAurasDueToSpell(uint32(GetEffectInfo(EFFECT_2).CalcValue()), GetCasterGUID()); } void Register() override @@ -1344,7 +1344,7 @@ class spell_gen_despawn_self : public SpellScript void HandleDummy(SpellEffIndex /*effIndex*/) { - if (GetEffectInfo()->IsEffect(SPELL_EFFECT_DUMMY) || GetEffectInfo()->IsEffect(SPELL_EFFECT_SCRIPT_EFFECT)) + if (GetEffectInfo().IsEffect(SPELL_EFFECT_DUMMY) || GetEffectInfo().IsEffect(SPELL_EFFECT_SCRIPT_EFFECT)) GetCaster()->ToCreature()->DespawnOrUnsummon(); } @@ -1594,18 +1594,20 @@ class spell_gen_gift_of_naaru : public AuraScript { PrepareAuraScript(spell_gen_gift_of_naaru); + bool Validate(SpellInfo const* spellInfo) override + { + return spellInfo->GetEffects().size() > EFFECT_1; + } + void CalculateAmount(AuraEffect const* aurEff, int32& amount, bool& /*canBeRecalculated*/) { if (!GetCaster() || !aurEff->GetTotalTicks()) return; - if (SpellEffectInfo const* eff1 = GetSpellInfo()->GetEffect(EFFECT_1)) - { - float healPct = eff1->CalcValue() / 100.0f; - float heal = healPct * GetCaster()->GetMaxHealth(); - int32 healTick = std::floor(heal / aurEff->GetTotalTicks()); - amount += healTick; - } + float healPct = GetEffectInfo(EFFECT_1).CalcValue() / 100.0f; + float heal = healPct * GetCaster()->GetMaxHealth(); + int32 healTick = std::floor(heal / aurEff->GetTotalTicks()); + amount += healTick; } void Register() override @@ -1906,7 +1908,7 @@ class spell_gen_mounted_charge : public SpellScript if (spell->HasEffect(SPELL_EFFECT_SCRIPT_EFFECT)) OnEffectHitTarget += SpellEffectFn(spell_gen_mounted_charge::HandleScriptEffect, EFFECT_FIRST_FOUND, SPELL_EFFECT_SCRIPT_EFFECT); - if (spell->GetEffect(EFFECT_0)->Effect == SPELL_EFFECT_CHARGE) + if (spell->GetEffect(EFFECT_0).IsEffect(SPELL_EFFECT_CHARGE)) OnEffectHitTarget += SpellEffectFn(spell_gen_mounted_charge::HandleChargeEffect, EFFECT_0, SPELL_EFFECT_CHARGE); } }; @@ -1946,7 +1948,7 @@ class spell_gen_negative_energy_periodic : public AuraScript bool Validate(SpellInfo const* spellInfo) override { - return ValidateSpellInfo({ spellInfo->GetEffect(EFFECT_0)->TriggerSpell }); + return !spellInfo->GetEffects().empty() && ValidateSpellInfo({ spellInfo->GetEffect(EFFECT_0).TriggerSpell }); } void PeriodicTick(AuraEffect const* aurEff) @@ -1955,7 +1957,7 @@ class spell_gen_negative_energy_periodic : public AuraScript CastSpellExtraArgs args(aurEff); args.AddSpellMod(SPELLVALUE_MAX_TARGETS, aurEff->GetTickNumber() / 10 + 1); - GetTarget()->CastSpell(nullptr, GetSpellInfo()->GetEffect(aurEff->GetEffIndex())->TriggerSpell, args); + GetTarget()->CastSpell(nullptr, aurEff->GetSpellEffectInfo().TriggerSpell, args); } void Register() override @@ -2147,16 +2149,21 @@ class spell_gen_oracle_wolvar_reputation : public SpellScript { PrepareSpellScript(spell_gen_oracle_wolvar_reputation); + bool Validate(SpellInfo const* spellInfo) override + { + return spellInfo->GetEffects().size() > EFFECT_1; + } + bool Load() override { return GetCaster()->GetTypeId() == TYPEID_PLAYER; } - void HandleDummy(SpellEffIndex effIndex) + void HandleDummy(SpellEffIndex /*effIndex*/) { Player* player = GetCaster()->ToPlayer(); - uint32 factionId = GetEffectInfo(effIndex)->CalcValue(); - int32 repChange = GetEffectInfo(EFFECT_1)->CalcValue(); + uint32 factionId = GetEffectInfo().CalcValue(); + int32 repChange = GetEffectInfo(EFFECT_1).CalcValue(); FactionEntry const* factionEntry = sFactionStore.LookupEntry(factionId); if (!factionEntry) @@ -2260,7 +2267,7 @@ class spell_gen_proc_below_pct_damaged : public SpellScriptLoader if (!damageInfo || !damageInfo->GetDamage()) return false; - int32 pct = GetSpellInfo()->GetEffect(EFFECT_0)->CalcValue(); + int32 pct = GetSpellInfo()->GetEffect(EFFECT_0).CalcValue(); if (eventInfo.GetActionTarget()->HealthBelowPctDamaged(pct, damageInfo->GetDamage())) return true; @@ -2513,11 +2520,16 @@ class spell_gen_remove_on_health_pct : public AuraScript { PrepareAuraScript(spell_gen_remove_on_health_pct); + bool Validate(SpellInfo const* spellInfo) override + { + return spellInfo->GetEffects().size() > EFFECT_1; + } + void PeriodicTick(AuraEffect const* /*aurEff*/) { // they apply damage so no need to check for ticks here - if (GetTarget()->HealthAbovePct(GetSpellInfo()->GetEffect(EFFECT_1)->CalcValue())) + if (GetTarget()->HealthAbovePct(GetEffectInfo(EFFECT_1).CalcValue())) { Remove(AURA_REMOVE_BY_ENEMY_SPELL); PreventDefaultAction(); @@ -2542,7 +2554,7 @@ class spell_gen_remove_on_full_health : public AuraScript void PeriodicTick(AuraEffect const* aurEff) { // if it has only periodic effect, allow 1 tick - bool onlyEffect = (GetSpellInfo()->GetEffects().size() == 1); + bool onlyEffect = GetSpellInfo()->GetEffects().size() == 1; if (onlyEffect && aurEff->GetTickNumber() <= 1) return; @@ -3379,8 +3391,9 @@ class spell_gen_eject_passenger : public SpellScript bool Validate(SpellInfo const* spellInfo) override { - SpellEffectInfo const* effect = spellInfo->GetEffect(EFFECT_0); - if (!effect || effect->CalcValue() < 1) + if (spellInfo->GetEffects().empty()) + return false; + if (spellInfo->GetEffect(EFFECT_0).CalcValue() < 1) return false; return true; } @@ -3572,9 +3585,9 @@ class spell_gen_mixology_bonus : public AuraScript { PrepareAuraScript(spell_gen_mixology_bonus); - bool Validate(SpellInfo const* /*spellInfo*/) override + bool Validate(SpellInfo const* spellInfo) override { - return ValidateSpellInfo({ SPELL_MIXOLOGY }); + return ValidateSpellInfo({ SPELL_MIXOLOGY }) && !spellInfo->GetEffects().empty(); } bool Load() override @@ -3590,7 +3603,7 @@ class spell_gen_mixology_bonus : public AuraScript void CalculateAmount(AuraEffect const* aurEff, int32& amount, bool& /*canBeRecalculated*/) { - if (GetCaster()->HasAura(SPELL_MIXOLOGY) && GetCaster()->HasSpell(GetSpellInfo()->GetEffect(EFFECT_0)->TriggerSpell)) + if (GetCaster()->HasAura(SPELL_MIXOLOGY) && GetCaster()->HasSpell(GetEffectInfo(EFFECT_0).TriggerSpell)) { switch (GetId()) { @@ -3973,14 +3986,14 @@ class spell_gen_face_rage : public AuraScript { PrepareAuraScript(spell_gen_face_rage); - bool Validate(SpellInfo const* /*spell*/) override + bool Validate(SpellInfo const* spellInfo) override { - return ValidateSpellInfo({ SPELL_FACE_RAGE }); + return ValidateSpellInfo({ SPELL_FACE_RAGE }) && spellInfo->GetEffects().size() > EFFECT_2; } void OnRemove(AuraEffect const* /*effect*/, AuraEffectHandleModes /*mode*/) { - GetTarget()->RemoveAurasDueToSpell(GetSpellInfo()->GetEffect(EFFECT_2)->TriggerSpell); + GetTarget()->RemoveAurasDueToSpell(GetEffectInfo(EFFECT_2).TriggerSpell); } void Register() override @@ -4001,7 +4014,7 @@ class spell_gen_impatient_mind : public AuraScript void OnRemove(AuraEffect const* effect, AuraEffectHandleModes /*mode*/) { - GetTarget()->RemoveAurasDueToSpell(effect->GetSpellEffectInfo()->TriggerSpell); + GetTarget()->RemoveAurasDueToSpell(effect->GetSpellEffectInfo().TriggerSpell); } void Register() override diff --git a/src/server/scripts/Spells/spell_holiday.cpp b/src/server/scripts/Spells/spell_holiday.cpp index 3d947c59db5..c046ce12c14 100644 --- a/src/server/scripts/Spells/spell_holiday.cpp +++ b/src/server/scripts/Spells/spell_holiday.cpp @@ -28,6 +28,7 @@ #include "Player.h" #include "ScriptedCreature.h" #include "SpellAuraEffects.h" +#include "SpellMgr.h" #include "SpellScript.h" #include "Vehicle.h" #include "World.h" @@ -539,6 +540,13 @@ class spell_pilgrims_bounty_feast_on : public SpellScriptLoader { PrepareSpellScript(spell_pilgrims_bounty_feast_on_SpellScript); + bool Validate(SpellInfo const* spellInfo) override + { + return !spellInfo->GetEffects().empty() + && ValidateSpellInfo({ uint32(spellInfo->GetEffect(EFFECT_0).CalcValue()) }) + && !sSpellMgr->AssertSpellInfo(spellInfo->GetEffect(EFFECT_0).CalcValue(), DIFFICULTY_NONE)->GetEffects().empty(); + } + void HandleDummy(SpellEffIndex /*effIndex*/) { Unit* caster = GetCaster(); @@ -576,8 +584,7 @@ class spell_pilgrims_bounty_feast_on : public SpellScriptLoader if (Aura* aura = caster->GetAura(GetEffectValue())) { if (aura->GetStackAmount() == 1) - if (SpellEffectInfo const* effect = aura->GetSpellInfo()->GetEffect(EFFECT_0)) - caster->RemoveAurasDueToSpell(effect->CalcValue()); + caster->RemoveAurasDueToSpell(aura->GetSpellInfo()->GetEffect(EFFECT_0).CalcValue()); aura->ModStackAmount(-1); } } @@ -1328,7 +1335,7 @@ class spell_brewfest_relay_race_intro_force_player_to_throw : public SpellScript PreventHitDefaultEffect(effIndex); // All this spells trigger a spell that requires reagents; if the // triggered spell is cast as "triggered", reagents are not consumed - GetHitUnit()->CastSpell(nullptr, GetEffectInfo()->TriggerSpell, TriggerCastFlags(TRIGGERED_FULL_MASK & ~TRIGGERED_IGNORE_POWER_AND_REAGENT_COST)); + GetHitUnit()->CastSpell(nullptr, GetEffectInfo().TriggerSpell, TriggerCastFlags(TRIGGERED_FULL_MASK & ~TRIGGERED_IGNORE_POWER_AND_REAGENT_COST)); } void Register() override diff --git a/src/server/scripts/Spells/spell_hunter.cpp b/src/server/scripts/Spells/spell_hunter.cpp index c36f78d76dd..1e2c6b382b9 100644 --- a/src/server/scripts/Spells/spell_hunter.cpp +++ b/src/server/scripts/Spells/spell_hunter.cpp @@ -211,7 +211,8 @@ class spell_hun_masters_call : public SpellScriptLoader bool Validate(SpellInfo const* spellInfo) override { - return spellInfo->GetEffect(EFFECT_0) && ValidateSpellInfo({ SPELL_HUNTER_MASTERS_CALL_TRIGGERED, uint32(spellInfo->GetEffect(EFFECT_0)->CalcValue()) }); + return !spellInfo->GetEffects().empty() + && ValidateSpellInfo({ SPELL_HUNTER_MASTERS_CALL_TRIGGERED, uint32(spellInfo->GetEffect(EFFECT_0).CalcValue()) }); } bool Load() override diff --git a/src/server/scripts/Spells/spell_item.cpp b/src/server/scripts/Spells/spell_item.cpp index b9f15cf20df..33f61663b07 100644 --- a/src/server/scripts/Spells/spell_item.cpp +++ b/src/server/scripts/Spells/spell_item.cpp @@ -1121,12 +1121,12 @@ class spell_item_crystal_spire_of_karabor : public AuraScript bool Validate(SpellInfo const* spellInfo) override { - return spellInfo->GetEffect(EFFECT_0) != nullptr; + return !spellInfo->GetEffects().empty(); } bool CheckProc(ProcEventInfo& eventInfo) { - int32 pct = GetSpellInfo()->GetEffect(EFFECT_0)->CalcValue(); + int32 pct = GetSpellInfo()->GetEffect(EFFECT_0).CalcValue(); if (HealInfo* healInfo = eventInfo.GetHealInfo()) if (Unit* healTarget = healInfo->GetTarget()) if (healTarget->GetHealth() - healInfo->GetEffectiveHeal() <= healTarget->CountPctFromMaxHealth(pct)) @@ -3765,7 +3765,7 @@ class spell_item_artifical_stamina : public AuraScript bool Validate(SpellInfo const* spellInfo) override { - return spellInfo->GetEffect(EFFECT_1) != nullptr; + return spellInfo->GetEffects().size() > EFFECT_1; } bool Load() override @@ -3776,7 +3776,7 @@ class spell_item_artifical_stamina : public AuraScript void CalculateAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/) { if (Item* artifact = GetOwner()->ToPlayer()->GetItemByGuid(GetAura()->GetCastItemGUID())) - amount = GetSpellInfo()->GetEffect(EFFECT_1)->BasePoints * artifact->GetTotalPurchasedArtifactPowers() / 100; + amount = GetEffectInfo(EFFECT_1).BasePoints * artifact->GetTotalPurchasedArtifactPowers() / 100; } void Register() override @@ -3791,7 +3791,7 @@ class spell_item_artifical_damage : public AuraScript bool Validate(SpellInfo const* spellInfo) override { - return spellInfo->GetEffect(EFFECT_1) != nullptr; + return spellInfo->GetEffects().size() > EFFECT_1; } bool Load() override @@ -3802,7 +3802,7 @@ class spell_item_artifical_damage : public AuraScript void CalculateAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/) { if (Item* artifact = GetOwner()->ToPlayer()->GetItemByGuid(GetAura()->GetCastItemGUID())) - amount = GetSpellInfo()->GetEffect(EFFECT_1)->BasePoints * artifact->GetTotalPurchasedArtifactPowers() / 100; + amount = GetSpellInfo()->GetEffect(EFFECT_1).BasePoints * artifact->GetTotalPurchasedArtifactPowers() / 100; } void Register() override @@ -3817,11 +3817,6 @@ enum AuraProcRemoveSpells SPELL_JOM_GABBAR = 29602, SPELL_BATTLE_TRANCE = 45040, SPELL_WORLD_QUELLER_FOCUS = 90900, - SPELL_AZURE_WATER_STRIDER = 118089, - SPELL_CRIMSON_WATER_STRIDER = 127271, - SPELL_ORANGE_WATER_STRIDER = 127272, - SPELL_JADE_WATER_STRIDER = 127274, - SPELL_GOLDEN_WATER_STRIDER = 127278, SPELL_BRUTAL_KINSHIP_1 = 144671, SPELL_BRUTAL_KINSHIP_2 = 145738 }; @@ -3838,7 +3833,7 @@ class spell_item_talisman_of_ascendance : public AuraScript void OnRemove(AuraEffect const* effect, AuraEffectHandleModes /*mode*/) { - GetTarget()->RemoveAurasDueToSpell(effect->GetSpellEffectInfo()->TriggerSpell); + GetTarget()->RemoveAurasDueToSpell(effect->GetSpellEffectInfo().TriggerSpell); } void Register() override @@ -3859,7 +3854,7 @@ class spell_item_jom_gabbar : public AuraScript void OnRemove(AuraEffect const* effect, AuraEffectHandleModes /*mode*/) { - GetTarget()->RemoveAurasDueToSpell(effect->GetSpellEffectInfo()->TriggerSpell); + GetTarget()->RemoveAurasDueToSpell(effect->GetSpellEffectInfo().TriggerSpell); } void Register() override @@ -3880,7 +3875,7 @@ class spell_item_battle_trance : public AuraScript void OnRemove(AuraEffect const* effect, AuraEffectHandleModes /*mode*/) { - GetTarget()->RemoveAurasDueToSpell(effect->GetSpellEffectInfo()->TriggerSpell); + GetTarget()->RemoveAurasDueToSpell(effect->GetSpellEffectInfo().TriggerSpell); } void Register() override @@ -3901,7 +3896,7 @@ class spell_item_world_queller_focus : public AuraScript void OnRemove(AuraEffect const* effect, AuraEffectHandleModes /*mode*/) { - GetTarget()->RemoveAurasDueToSpell(effect->GetSpellEffectInfo()->TriggerSpell); + GetTarget()->RemoveAurasDueToSpell(effect->GetSpellEffectInfo().TriggerSpell); } void Register() override @@ -3919,21 +3914,14 @@ class spell_item_water_strider : public AuraScript { PrepareAuraScript(spell_item_water_strider); - bool Validate(SpellInfo const* /*spell*/) override + bool Validate(SpellInfo const* spellInfo) override { - return ValidateSpellInfo( - { - SPELL_AZURE_WATER_STRIDER, - SPELL_CRIMSON_WATER_STRIDER, - SPELL_ORANGE_WATER_STRIDER, - SPELL_JADE_WATER_STRIDER, - SPELL_GOLDEN_WATER_STRIDER - }); + return spellInfo->GetEffects().size() > EFFECT_1; } void OnRemove(AuraEffect const* /*effect*/, AuraEffectHandleModes /*mode*/) { - GetTarget()->RemoveAurasDueToSpell(GetSpellInfo()->GetEffect(EFFECT_1)->TriggerSpell); + GetTarget()->RemoveAurasDueToSpell(GetSpellInfo()->GetEffect(EFFECT_1).TriggerSpell); } void Register() override @@ -3955,7 +3943,7 @@ class spell_item_brutal_kinship : public AuraScript void OnRemove(AuraEffect const* effect, AuraEffectHandleModes /*mode*/) { - GetTarget()->RemoveAurasDueToSpell(effect->GetSpellEffectInfo()->TriggerSpell); + GetTarget()->RemoveAurasDueToSpell(effect->GetSpellEffectInfo().TriggerSpell); } void Register() override diff --git a/src/server/scripts/Spells/spell_mage.cpp b/src/server/scripts/Spells/spell_mage.cpp index 60203a08c5b..b0dfaa38a73 100644 --- a/src/server/scripts/Spells/spell_mage.cpp +++ b/src/server/scripts/Spells/spell_mage.cpp @@ -172,7 +172,7 @@ class spell_mage_arcane_barrage : public SpellScript bool Validate(SpellInfo const* spellInfo) override { return ValidateSpellInfo({ SPELL_MAGE_ARCANE_BARRAGE_R3, SPELL_MAGE_ARCANE_BARRAGE_ENERGIZE }) - && spellInfo->GetEffect(EFFECT_1); + && spellInfo->GetEffects().size() > EFFECT_1; } void ConsumeArcaneCharges() @@ -188,7 +188,7 @@ class spell_mage_arcane_barrage : public SpellScript void HandleEffectHitTarget(SpellEffIndex /*effIndex*/) { if (GetHitUnit()->GetGUID() != _primaryTarget) - SetHitDamage(CalculatePct(GetHitDamage(), GetEffectInfo(EFFECT_1)->CalcValue(GetCaster()))); + SetHitDamage(CalculatePct(GetHitDamage(), GetEffectInfo(EFFECT_1).CalcValue(GetCaster()))); } void MarkPrimaryTarget(SpellEffIndex /*effIndex*/) @@ -237,8 +237,10 @@ class spell_mage_arcane_explosion : public SpellScript if (!ValidateSpellInfo({ SPELL_MAGE_ARCANE_MAGE, SPELL_MAGE_REVERBERATE })) return false; - SpellEffectInfo const* damageEffect = spellInfo->GetEffect(EFFECT_1); - return damageEffect && damageEffect->IsEffect(SPELL_EFFECT_SCHOOL_DAMAGE); + if (spellInfo->GetEffects().size() <= EFFECT_1) + return false; + + return spellInfo->GetEffect(EFFECT_1).IsEffect(SPELL_EFFECT_SCHOOL_DAMAGE); } void CheckRequiredAuraForBaselineEnergize(SpellEffIndex effIndex) @@ -350,11 +352,11 @@ class spell_mage_cauterize_AuraScript : public AuraScript bool Validate(SpellInfo const* spellInfo) override { - return spellInfo->GetEffect(EFFECT_2) && ValidateSpellInfo + return spellInfo->GetEffects().size() > EFFECT_2 && ValidateSpellInfo ({ SPELL_MAGE_CAUTERIZE_DOT, SPELL_MAGE_CAUTERIZED, - spellInfo->GetEffect(EFFECT_2)->TriggerSpell + spellInfo->GetEffect(EFFECT_2).TriggerSpell }); } @@ -372,7 +374,7 @@ class spell_mage_cauterize_AuraScript : public AuraScript } GetTarget()->SetHealth(GetTarget()->CountPctFromMaxHealth(effect1->GetAmount())); - GetTarget()->CastSpell(GetTarget(), GetSpellInfo()->GetEffect(EFFECT_2)->TriggerSpell, TRIGGERED_FULL_MASK); + GetTarget()->CastSpell(GetTarget(), GetEffectInfo(EFFECT_2).TriggerSpell, TRIGGERED_FULL_MASK); GetTarget()->CastSpell(GetTarget(), SPELL_MAGE_CAUTERIZE_DOT, TRIGGERED_FULL_MASK); GetTarget()->CastSpell(GetTarget(), SPELL_MAGE_CAUTERIZED, TRIGGERED_FULL_MASK); } @@ -583,9 +585,9 @@ class spell_mage_ice_lance : public SpellScript { // Thermal Void if (Aura const* thermalVoid = caster->GetAura(SPELL_MAGE_THERMAL_VOID)) - if (SpellEffectInfo const* thermalVoidEffect = thermalVoid->GetSpellInfo()->GetEffect(EFFECT_0)) + if (!thermalVoid->GetSpellInfo()->GetEffects().empty()) if (Aura* icyVeins = caster->GetAura(SPELL_MAGE_ICY_VEINS)) - icyVeins->SetDuration(icyVeins->GetDuration() + thermalVoidEffect->CalcValue(caster) * IN_MILLISECONDS); + icyVeins->SetDuration(icyVeins->GetDuration() + thermalVoid->GetSpellInfo()->GetEffect(EFFECT_0).CalcValue(caster) * IN_MILLISECONDS); // Chain Reaction if (caster->HasAura(SPELL_MAGE_CHAIN_REACTION_DUMMY)) @@ -620,7 +622,7 @@ class spell_mage_ice_lance_damage : public SpellScript { int32 originalDamage = GetHitDamage(); float targetIndex = float(spellValue->EffectBasePoints[EFFECT_1]); - float multiplier = std::pow(GetEffectInfo()->CalcDamageMultiplier(GetCaster(), GetSpell()), targetIndex); + float multiplier = std::pow(GetEffectInfo().CalcDamageMultiplier(GetCaster(), GetSpell()), targetIndex); SetHitDamage(int32(originalDamage * multiplier)); } } @@ -834,7 +836,8 @@ class spell_mage_ring_of_frost : public AuraScript bool Validate(SpellInfo const* /*spellInfo*/) override { - return ValidateSpellInfo({ SPELL_MAGE_RING_OF_FROST_SUMMON, SPELL_MAGE_RING_OF_FROST_FREEZE }); + return ValidateSpellInfo({ SPELL_MAGE_RING_OF_FROST_SUMMON, SPELL_MAGE_RING_OF_FROST_FREEZE }) + && !sSpellMgr->AssertSpellInfo(SPELL_MAGE_RING_OF_FROST_SUMMON, GetCastDifficulty())->GetEffects().empty(); } void HandleEffectPeriodic(AuraEffect const* /*aurEff*/) @@ -846,7 +849,7 @@ class spell_mage_ring_of_frost : public AuraScript void Apply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) { std::list<TempSummon*> minions; - GetTarget()->GetAllMinionsByEntry(minions, sSpellMgr->AssertSpellInfo(SPELL_MAGE_RING_OF_FROST_SUMMON, GetCastDifficulty())->GetEffect(EFFECT_0)->MiscValue); + GetTarget()->GetAllMinionsByEntry(minions, sSpellMgr->AssertSpellInfo(SPELL_MAGE_RING_OF_FROST_SUMMON, GetCastDifficulty())->GetEffect(EFFECT_0).MiscValue); // Get the last summoned RoF, save it and despawn older ones for (TempSummon* summon : minions) @@ -890,13 +893,14 @@ class spell_mage_ring_of_frost_freeze : public SpellScript bool Validate(SpellInfo const* /*spellInfo*/) override { - return ValidateSpellInfo({ SPELL_MAGE_RING_OF_FROST_SUMMON, SPELL_MAGE_RING_OF_FROST_FREEZE }); + return ValidateSpellInfo({ SPELL_MAGE_RING_OF_FROST_SUMMON, SPELL_MAGE_RING_OF_FROST_FREEZE }) + && !sSpellMgr->AssertSpellInfo(SPELL_MAGE_RING_OF_FROST_SUMMON, GetCastDifficulty())->GetEffects().empty(); } void FilterTargets(std::list<WorldObject*>& targets) { WorldLocation const* dest = GetExplTargetDest(); - float outRadius = sSpellMgr->AssertSpellInfo(SPELL_MAGE_RING_OF_FROST_SUMMON, GetCastDifficulty())->GetEffect(EFFECT_0)->CalcRadius(); + float outRadius = sSpellMgr->AssertSpellInfo(SPELL_MAGE_RING_OF_FROST_SUMMON, GetCastDifficulty())->GetEffect(EFFECT_0).CalcRadius(); float inRadius = 6.5f; targets.remove_if([dest, outRadius, inRadius](WorldObject* target) diff --git a/src/server/scripts/Spells/spell_monk.cpp b/src/server/scripts/Spells/spell_monk.cpp index 721ca1f829e..07072cbff43 100644 --- a/src/server/scripts/Spells/spell_monk.cpp +++ b/src/server/scripts/Spells/spell_monk.cpp @@ -326,14 +326,15 @@ class spell_monk_stagger_debuff_aura : public AuraScript { PrepareAuraScript(spell_monk_stagger_debuff_aura); - bool Load() override + bool Validate(SpellInfo const* /*spellInfo*/) override { - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(SPELL_MONK_STAGGER_DAMAGE_AURA, GetCastDifficulty()); - SpellEffectInfo const* effInfo = !spellInfo ? nullptr : spellInfo->GetEffect(EFFECT_0); - if (!effInfo) - return false; + return ValidateSpellInfo({ SPELL_MONK_STAGGER_DAMAGE_AURA }) + && !sSpellMgr->GetSpellInfo(SPELL_MONK_STAGGER_DAMAGE_AURA, DIFFICULTY_NONE)->GetEffects().empty(); + } - _period = float(effInfo->ApplyAuraPeriod); + bool Load() override + { + _period = float(sSpellMgr->AssertSpellInfo(SPELL_MONK_STAGGER_DAMAGE_AURA, GetCastDifficulty())->GetEffect(EFFECT_0).ApplyAuraPeriod); return true; } diff --git a/src/server/scripts/Spells/spell_pet.cpp b/src/server/scripts/Spells/spell_pet.cpp index e8743fa35fc..fa9acf4087f 100644 --- a/src/server/scripts/Spells/spell_pet.cpp +++ b/src/server/scripts/Spells/spell_pet.cpp @@ -898,7 +898,7 @@ public: if (itr != pet->ToPet()->m_spells.end()) // If pet has Wild Hunt { SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(itr->first, GetCastDifficulty()); // Then get the SpellProto and add the dummy effect value - AddPct(mod, spellInfo->GetEffect(EFFECT_0)->CalcValue()); + AddPct(mod, spellInfo->GetEffect(EFFECT_0).CalcValue()); } int32 const ownerBonus = owner->GetStat(STAT_STAMINA) * mod; @@ -940,7 +940,7 @@ public: if (itr != pet->ToPet()->m_spells.end()) // If pet has Wild Hunt { SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(itr->first, GetCastDifficulty()); // Then get the SpellProto and add the dummy effect value - mod += CalculatePct(1.0f, spellInfo->GetEffect(EFFECT_1)->CalcValue()); + mod += CalculatePct(1.0f, spellInfo->GetEffect(EFFECT_1).CalcValue()); } bonusAP = owner->GetTotalAttackPowerValue(RANGED_ATTACK) * 0.22f * mod; @@ -970,7 +970,7 @@ public: if (itr != pet->ToPet()->m_spells.end()) // If pet has Wild Hunt { SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(itr->first, GetCastDifficulty()); // Then get the SpellProto and add the dummy effect value - mod += CalculatePct(1.0f, spellInfo->GetEffect(EFFECT_1)->CalcValue()); + mod += CalculatePct(1.0f, spellInfo->GetEffect(EFFECT_1).CalcValue()); } bonusDamage = owner->GetTotalAttackPowerValue(RANGED_ATTACK) * 0.1287f * mod; @@ -1410,7 +1410,7 @@ public: amount = -90; // Night of the dead else if (Aura* aur = owner->GetAuraOfRankedSpell(SPELL_NIGHT_OF_THE_DEAD)) - amount = aur->GetSpellInfo()->GetEffect(EFFECT_2)->CalcValue(); + amount = aur->GetSpellInfo()->GetEffect(EFFECT_2).CalcValue(); } } } diff --git a/src/server/scripts/Spells/spell_priest.cpp b/src/server/scripts/Spells/spell_priest.cpp index 9efb49d5935..42546ba3cfe 100644 --- a/src/server/scripts/Spells/spell_priest.cpp +++ b/src/server/scripts/Spells/spell_priest.cpp @@ -174,9 +174,9 @@ public: { PrepareAuraScript(spell_pri_atonement_AuraScript); - bool Validate(SpellInfo const* /*spellInfo*/) override + bool Validate(SpellInfo const* spellInfo) override { - return ValidateSpellInfo({ SPELL_PRIEST_ATONEMENT_HEAL }); + return ValidateSpellInfo({ SPELL_PRIEST_ATONEMENT_HEAL }) && spellInfo->GetEffects().size() > EFFECT_1; } bool CheckProc(ProcEventInfo& eventInfo) @@ -193,7 +193,7 @@ public: { if (Unit* target = ObjectAccessor::GetUnit(*GetTarget(), targetGuid)) { - if (target->GetExactDist(GetTarget()) < GetSpellInfo()->GetEffect(EFFECT_1)->CalcValue()) + if (target->GetExactDist(GetTarget()) < GetEffectInfo(EFFECT_1).CalcValue()) GetTarget()->CastSpell(target, SPELL_PRIEST_ATONEMENT_HEAL, args); return false; @@ -325,14 +325,14 @@ class spell_pri_guardian_spirit : public SpellScriptLoader uint32 healPct = 0; - bool Validate(SpellInfo const* /*spellInfo*/) override + bool Validate(SpellInfo const* spellInfo) override { - return ValidateSpellInfo({ SPELL_PRIEST_GUARDIAN_SPIRIT_HEAL }); + return ValidateSpellInfo({ SPELL_PRIEST_GUARDIAN_SPIRIT_HEAL }) && spellInfo->GetEffects().size() > EFFECT_1; } bool Load() override { - healPct = GetSpellInfo()->GetEffect(EFFECT_1)->CalcValue(); + healPct = GetEffectInfo(EFFECT_1).CalcValue(); return true; } @@ -387,11 +387,10 @@ class spell_pri_holy_words : public AuraScript SPELL_PRIEST_HOLY_WORD_CHASTISE, SPELL_PRIEST_HOLY_WORD_SANCTIFY, SPELL_PRIEST_HOLY_WORD_SERENITY - }) - && sSpellMgr->AssertSpellInfo(SPELL_PRIEST_HOLY_WORD_SERENITY, DIFFICULTY_NONE)->GetEffect(EFFECT_1) - && sSpellMgr->AssertSpellInfo(SPELL_PRIEST_HOLY_WORD_SANCTIFY, DIFFICULTY_NONE)->GetEffect(EFFECT_2) - && sSpellMgr->AssertSpellInfo(SPELL_PRIEST_HOLY_WORD_SANCTIFY, DIFFICULTY_NONE)->GetEffect(EFFECT_3) - && sSpellMgr->AssertSpellInfo(SPELL_PRIEST_HOLY_WORD_CHASTISE, DIFFICULTY_NONE)->GetEffect(EFFECT_1); + }) + && sSpellMgr->AssertSpellInfo(SPELL_PRIEST_HOLY_WORD_SERENITY, DIFFICULTY_NONE)->GetEffects().size() > EFFECT_1 + && sSpellMgr->AssertSpellInfo(SPELL_PRIEST_HOLY_WORD_SANCTIFY, DIFFICULTY_NONE)->GetEffects().size() > EFFECT_3 + && sSpellMgr->AssertSpellInfo(SPELL_PRIEST_HOLY_WORD_CHASTISE, DIFFICULTY_NONE)->GetEffects().size() > EFFECT_1; } void HandleProc(AuraEffect* /*aurEff*/, ProcEventInfo& eventInfo) @@ -428,7 +427,7 @@ class spell_pri_holy_words : public AuraScript } SpellInfo const* targetSpellInfo = sSpellMgr->AssertSpellInfo(targetSpellId, GetCastDifficulty()); - int32 cdReduction = targetSpellInfo->GetEffect(cdReductionEffIndex)->CalcValue(GetTarget()); + int32 cdReduction = targetSpellInfo->GetEffect(cdReductionEffIndex).CalcValue(GetTarget()); GetTarget()->GetSpellHistory()->ModifyCooldown(targetSpellInfo, Seconds(-cdReduction)); } @@ -632,18 +631,15 @@ class spell_pri_power_word_radiance : public SpellScript { PrepareSpellScript(spell_pri_power_word_radiance); - bool Validate(SpellInfo const* /*spellInfo*/) override + bool Validate(SpellInfo const* spellInfo) override { - return ValidateSpellInfo({ SPELL_PRIEST_ATONEMENT, SPELL_PRIEST_ATONEMENT_TRIGGERED, SPELL_PRIEST_TRINITY }); + return ValidateSpellInfo({ SPELL_PRIEST_ATONEMENT, SPELL_PRIEST_ATONEMENT_TRIGGERED, SPELL_PRIEST_TRINITY }) + && spellInfo->GetEffects().size() > EFFECT_3; } void OnTargetSelect(std::list<WorldObject*>& targets) { - SpellEffectInfo const* eff2 = GetEffectInfo(EFFECT_2); - if (!eff2) - return; - - uint32 maxTargets = eff2->CalcValue(GetCaster()) + 1; // adding 1 for explicit target unit + uint32 maxTargets = GetEffectInfo(EFFECT_2).CalcValue(GetCaster()) + 1; // adding 1 for explicit target unit if (targets.size() > maxTargets) { Unit* explTarget = GetExplTargetUnit(); @@ -669,11 +665,7 @@ class spell_pri_power_word_radiance : public SpellScript if (caster->HasAura(SPELL_PRIEST_TRINITY)) return; - SpellEffectInfo const* effect3 = GetEffectInfo(EFFECT_3); - if (!effect3) - return; - - uint32 durationPct = effect3->CalcValue(caster); + uint32 durationPct = GetEffectInfo(EFFECT_3).CalcValue(caster); if (caster->HasAura(SPELL_PRIEST_ATONEMENT)) caster->CastSpell(GetHitUnit(), SPELL_PRIEST_ATONEMENT_TRIGGERED, CastSpellExtraArgs(SPELLVALUE_DURATION_PCT, durationPct).SetTriggerFlags(TRIGGERED_FULL_MASK)); } @@ -799,19 +791,19 @@ public: bool Validate(SpellInfo const* /*spellInfo*/) override { return ValidateSpellInfo({ SPELL_PRIEST_PRAYER_OF_MENDING_HEAL, SPELL_PRIEST_PRAYER_OF_MENDING_AURA }) - && sSpellMgr->AssertSpellInfo(SPELL_PRIEST_PRAYER_OF_MENDING_HEAL, DIFFICULTY_NONE)->GetEffect(EFFECT_0); + && !sSpellMgr->AssertSpellInfo(SPELL_PRIEST_PRAYER_OF_MENDING_HEAL, DIFFICULTY_NONE)->GetEffects().empty(); } bool Load() override { _spellInfoHeal = sSpellMgr->AssertSpellInfo(SPELL_PRIEST_PRAYER_OF_MENDING_HEAL, DIFFICULTY_NONE); - _healEffectDummy = _spellInfoHeal->GetEffect(EFFECT_0); + _healEffectDummy = &_spellInfoHeal->GetEffect(EFFECT_0); return true; } void CastPrayerOfMendingAura(Unit* caster, Unit* target, uint8 stack) { - uint32 basePoints = caster->SpellHealingBonusDone(target, _spellInfoHeal, _healEffectDummy->CalcValue(caster), HEAL, _healEffectDummy); + uint32 basePoints = caster->SpellHealingBonusDone(target, _spellInfoHeal, _healEffectDummy->CalcValue(caster), HEAL, *_healEffectDummy); CastSpellExtraArgs args; args.TriggerFlags = TRIGGERED_FULL_MASK; args.AddSpellMod(SPELLVALUE_AURA_STACK, stack); @@ -1264,7 +1256,7 @@ class spell_pri_angelic_feather_trigger : public SpellScriptLoader void HandleEffectDummy(SpellEffIndex /*effIndex*/) { Position destPos = GetHitDest()->GetPosition(); - float radius = GetEffectInfo()->CalcRadius(); + float radius = GetEffectInfo().CalcRadius(); // Caster is prioritary if (GetCaster()->IsWithinDist2d(&destPos, radius)) diff --git a/src/server/scripts/Spells/spell_quest.cpp b/src/server/scripts/Spells/spell_quest.cpp index 23bc128890a..17beea16514 100644 --- a/src/server/scripts/Spells/spell_quest.cpp +++ b/src/server/scripts/Spells/spell_quest.cpp @@ -634,14 +634,19 @@ class spell_q12683_take_sputum_sample : public SpellScriptLoader { PrepareSpellScript(spell_q12683_take_sputum_sample_SpellScript); + bool Validate(SpellInfo const* spellInfo) override + { + return spellInfo->GetEffects().size() > EFFECT_1; + } + void HandleDummy(SpellEffIndex /*effIndex*/) { - uint32 reqAuraId = GetSpellInfo()->GetEffect(EFFECT_1)->CalcValue(); + uint32 reqAuraId = GetEffectInfo(EFFECT_1).CalcValue(); Unit* caster = GetCaster(); if (caster->HasAuraEffect(reqAuraId, 0)) { - uint32 spellId = GetSpellInfo()->GetEffect(EFFECT_0)->CalcValue(); + uint32 spellId = GetEffectInfo().CalcValue(); caster->CastSpell(caster, spellId, true); } } @@ -1916,7 +1921,8 @@ class spell_q13086_cannons_target : public SpellScriptLoader bool Validate(SpellInfo const* spellInfo) override { - return ValidateSpellInfo({ static_cast<uint32>(spellInfo->GetEffect(EFFECT_0)->CalcValue()) }); + return !spellInfo->GetEffects().empty() + && ValidateSpellInfo({ static_cast<uint32>(spellInfo->GetEffect(EFFECT_0).CalcValue()) }); } void HandleEffectDummy(SpellEffIndex /*effIndex*/) @@ -2160,7 +2166,7 @@ class spell_q12308_escape_from_silverbrook_summon_worgen : public SpellScriptLoa void ModDest(SpellDestination& dest) { - float dist = GetSpellInfo()->GetEffect(EFFECT_0)->CalcRadius(GetCaster()); + float dist = GetEffectInfo(EFFECT_0).CalcRadius(GetCaster()); float angle = frand(0.75f, 1.25f) * float(M_PI); Position pos = GetCaster()->GetNearPosition(dist, angle); @@ -2301,7 +2307,7 @@ class spell_q12619_emblazon_runeblade : public SpellScriptLoader { PreventDefaultAction(); if (Unit* caster = GetCaster()) - caster->CastSpell(caster, aurEff->GetSpellEffectInfo()->TriggerSpell, aurEff); + caster->CastSpell(caster, aurEff->GetSpellEffectInfo().TriggerSpell, aurEff); } void Register() override diff --git a/src/server/scripts/Spells/spell_warlock.cpp b/src/server/scripts/Spells/spell_warlock.cpp index 737012cf41f..a5728438912 100644 --- a/src/server/scripts/Spells/spell_warlock.cpp +++ b/src/server/scripts/Spells/spell_warlock.cpp @@ -270,27 +270,25 @@ class spell_warl_devour_magic : public SpellScriptLoader { PrepareSpellScript(spell_warl_devour_magic_SpellScript); - bool Validate(SpellInfo const* /*spellInfo*/) override + bool Validate(SpellInfo const* spellInfo) override { - return ValidateSpellInfo({ SPELL_WARLOCK_GLYPH_OF_DEMON_TRAINING, SPELL_WARLOCK_DEVOUR_MAGIC_HEAL }); + return ValidateSpellInfo({ SPELL_WARLOCK_GLYPH_OF_DEMON_TRAINING, SPELL_WARLOCK_DEVOUR_MAGIC_HEAL }) + && spellInfo->GetEffects().size() > EFFECT_1; } void OnSuccessfulDispel(SpellEffIndex /*effIndex*/) { - if (SpellEffectInfo const* effect = GetSpellInfo()->GetEffect(EFFECT_1)) - { - Unit* caster = GetCaster(); - CastSpellExtraArgs args; - args.TriggerFlags = TRIGGERED_FULL_MASK; - args.AddSpellBP0(effect->CalcValue(caster)); + Unit* caster = GetCaster(); + CastSpellExtraArgs args; + args.TriggerFlags = TRIGGERED_FULL_MASK; + args.AddSpellBP0(GetEffectInfo(EFFECT_1).CalcValue(caster)); - caster->CastSpell(caster, SPELL_WARLOCK_DEVOUR_MAGIC_HEAL, args); + caster->CastSpell(caster, SPELL_WARLOCK_DEVOUR_MAGIC_HEAL, args); - // Glyph of Felhunter - if (Unit* owner = caster->GetOwner()) - if (owner->GetAura(SPELL_WARLOCK_GLYPH_OF_DEMON_TRAINING)) - owner->CastSpell(owner, SPELL_WARLOCK_DEVOUR_MAGIC_HEAL, args); - } + // Glyph of Felhunter + if (Unit* owner = caster->GetOwner()) + if (owner->GetAura(SPELL_WARLOCK_GLYPH_OF_DEMON_TRAINING)) + owner->CastSpell(owner, SPELL_WARLOCK_DEVOUR_MAGIC_HEAL, args); } void Register() override @@ -517,7 +515,7 @@ class spell_warl_seed_of_corruption_dummy : public SpellScriptLoader if (!caster) return; - amount = caster->SpellBaseDamageBonusDone(GetSpellInfo()->GetSchoolMask()) * ASSERT_NOTNULL(GetSpellInfo()->GetEffect(EFFECT_0))->CalcValue(caster) / 100; + amount = caster->SpellBaseDamageBonusDone(GetSpellInfo()->GetSchoolMask()) * GetEffectInfo(EFFECT_0).CalcValue(caster) / 100; } void HandleProc(AuraEffect* aurEff, ProcEventInfo& eventInfo) @@ -711,7 +709,7 @@ class spell_warl_soul_swap_dot_marker : public SpellScriptLoader if (!swapSpellScript) return; - flag128 classMask = GetEffectInfo()->SpellClassMask; + flag128 classMask = GetEffectInfo().SpellClassMask; for (Unit::AuraApplicationMap::const_iterator itr = appliedAuras.begin(); itr != appliedAuras.end(); ++itr) { diff --git a/src/server/scripts/Spells/spell_warrior.cpp b/src/server/scripts/Spells/spell_warrior.cpp index 6cba63461fb..af1604ff994 100644 --- a/src/server/scripts/Spells/spell_warrior.cpp +++ b/src/server/scripts/Spells/spell_warrior.cpp @@ -437,9 +437,10 @@ class spell_warr_item_t10_prot_4p_bonus : public SpellScriptLoader { PrepareAuraScript(spell_warr_item_t10_prot_4p_bonus_AuraScript); - bool Validate(SpellInfo const* /*spellInfo*/) override + bool Validate(SpellInfo const* spellInfo) override { - return ValidateSpellInfo({ SPELL_WARRIOR_STOICISM }); + return ValidateSpellInfo({ SPELL_WARRIOR_STOICISM }) + && spellInfo->GetEffects().size() > EFFECT_1; } void HandleProc(ProcEventInfo& eventInfo) @@ -447,7 +448,7 @@ class spell_warr_item_t10_prot_4p_bonus : public SpellScriptLoader PreventDefaultAction(); Unit* target = eventInfo.GetActionTarget(); - int32 bp0 = CalculatePct(target->GetMaxHealth(), GetSpellInfo()->GetEffect(EFFECT_1)->CalcValue()); + int32 bp0 = CalculatePct(target->GetMaxHealth(), GetEffectInfo(EFFECT_1).CalcValue()); CastSpellExtraArgs args(TRIGGERED_FULL_MASK); args.AddSpellBP0(bp0); target->CastSpell(nullptr, SPELL_WARRIOR_STOICISM, args); @@ -553,7 +554,7 @@ public: if (!ValidateSpellInfo({ SPELL_WARRIOR_SHOCKWAVE, SPELL_WARRIOR_SHOCKWAVE_STUN })) return false; - return spellInfo->GetEffect(EFFECT_0) && spellInfo->GetEffect(EFFECT_3); + return spellInfo->GetEffects().size() > EFFECT_3; } bool Load() override @@ -570,8 +571,8 @@ public: // Cooldown reduced by 20 sec if it strikes at least 3 targets. void HandleAfterCast() { - if (_targetCount >= uint32(GetSpellInfo()->GetEffect(EFFECT_0)->CalcValue())) - GetCaster()->ToPlayer()->GetSpellHistory()->ModifyCooldown(GetSpellInfo()->Id, Seconds(-GetSpellInfo()->GetEffect(EFFECT_3)->CalcValue())); + if (_targetCount >= uint32(GetEffectInfo(EFFECT_0).CalcValue())) + GetCaster()->ToPlayer()->GetSpellHistory()->ModifyCooldown(GetSpellInfo()->Id, Seconds(-GetEffectInfo(EFFECT_3).CalcValue())); } void Register() override diff --git a/src/server/scripts/World/npc_professions.cpp b/src/server/scripts/World/npc_professions.cpp index c7635efcef3..f49d7e92db0 100644 --- a/src/server/scripts/World/npc_professions.cpp +++ b/src/server/scripts/World/npc_professions.cpp @@ -286,12 +286,9 @@ bool EquippedOk(Player* player, uint32 spellId) if (!spell) return false; - for (SpellEffectInfo const* effect : spell->GetEffects()) + for (SpellEffectInfo const& spellEffectInfo : spell->GetEffects()) { - if (!effect) - continue; - - uint32 reqSpell = effect->TriggerSpell; + uint32 reqSpell = spellEffectInfo.TriggerSpell; if (!reqSpell) continue; diff --git a/src/server/scripts/World/npcs_special.cpp b/src/server/scripts/World/npcs_special.cpp index 0e0cf7a1d85..f51f9b70cd5 100644 --- a/src/server/scripts/World/npcs_special.cpp +++ b/src/server/scripts/World/npcs_special.cpp @@ -2220,10 +2220,10 @@ public: break; } - if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId, DIFFICULTY_NONE)) - if (SpellEffectInfo const* effect0 = spellInfo->GetEffect(EFFECT_0)) - if (effect0->Effect == SPELL_EFFECT_SUMMON_OBJECT_WILD) - return effect0->MiscValue; + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId, DIFFICULTY_NONE); + + if (spellInfo && spellInfo->GetEffect(EFFECT_0).Effect == SPELL_EFFECT_SUMMON_OBJECT_WILD) + return spellInfo->GetEffect(EFFECT_0).MiscValue; return 0; } |