diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/server/game/Entities/Unit/Unit.cpp | 371 | ||||
-rw-r--r-- | src/server/game/Entities/Unit/Unit.h | 8 | ||||
-rw-r--r-- | src/server/game/Spells/Auras/SpellAuraEffects.cpp | 161 | ||||
-rw-r--r-- | src/server/game/Spells/Auras/SpellAuraEffects.h | 26 | ||||
-rw-r--r-- | src/server/game/Spells/Auras/SpellAuras.cpp | 238 | ||||
-rw-r--r-- | src/server/game/Spells/Auras/SpellAuras.h | 52 | ||||
-rw-r--r-- | src/server/game/Spells/Spell.cpp | 4 | ||||
-rw-r--r-- | src/server/game/Spells/Spell.h | 10 | ||||
-rw-r--r-- | src/server/game/Spells/SpellEffects.cpp | 400 | ||||
-rw-r--r-- | src/server/game/Spells/SpellInfo.cpp | 425 | ||||
-rw-r--r-- | src/server/game/Spells/SpellInfo.h | 20 |
11 files changed, 810 insertions, 905 deletions
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 89ded594990..d8ba3a8e6d7 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -1427,10 +1427,10 @@ bool Unit::IsDamageReducedByArmor(SpellSchoolMask schoolMask, SpellInfo const* s return false; // bleeding effects are not reduced by armor - if (effIndex != MAX_SPELL_EFFECTS) + if (SpellEffectInfo const* effect = spellInfo->GetEffect(GetMap()->GetDifficulty(), effIndex)) { - if (spellInfo->Effects[effIndex].ApplyAuraName == SPELL_AURA_PERIODIC_DAMAGE || - spellInfo->Effects[effIndex].Effect == SPELL_EFFECT_SCHOOL_DAMAGE) + if (effect->ApplyAuraName == SPELL_AURA_PERIODIC_DAMAGE || + effect->Effect == SPELL_EFFECT_SCHOOL_DAMAGE) if (spellInfo->GetEffectMechanicMask(effIndex) & (1<<MECHANIC_BLEED)) return false; } @@ -1696,7 +1696,7 @@ void Unit::CalcAbsorbResist(Unit* victim, SpellSchoolMask schoolMask, DamageEffe int32 manaReduction = currentAbsorb; // lower absorb amount by talents - if (float manaMultiplier = absorbAurEff->GetSpellInfo()->Effects[absorbAurEff->GetEffIndex()].CalcValueMultiplier(absorbAurEff->GetCaster())) + if (float manaMultiplier = absorbAurEff->GetSpellEffectInfo()->CalcValueMultiplier(absorbAurEff->GetCaster())) manaReduction = int32(float(manaReduction) * manaMultiplier); int32 manaTaken = -victim->ModifyPower(POWER_MANA, -manaReduction); @@ -2166,12 +2166,12 @@ int32 Unit::GetMechanicResistChance(SpellInfo const* spellInfo) const return 0; int32 resistMech = 0; - for (uint8 eff = 0; eff < MAX_SPELL_EFFECTS; ++eff) + for (SpellEffectInfo const* effect : spellInfo->GetEffectsForDifficulty(GetMap()->GetDifficulty())) { - if (!spellInfo->Effects[eff].IsEffect()) + if (!effect || !effect->IsEffect()) break; - int32 effectMech = spellInfo->GetEffectMechanic(eff); + int32 effectMech = spellInfo->GetEffectMechanic(effect->EffectIndex, GetMap()->GetDifficulty()); if (effectMech) { int32 temp = GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_MECHANIC_RESISTANCE, effectMech); @@ -2990,7 +2990,7 @@ void Unit::DeMorph() SetDisplayId(GetNativeDisplayId()); } -Aura* Unit::_TryStackingOrRefreshingExistingAura(SpellInfo const* newAura, uint8 effMask, Unit* caster, int32* baseAmount /*= NULL*/, Item* castItem /*= NULL*/, ObjectGuid casterGUID /*= 0*/) +Aura* Unit::_TryStackingOrRefreshingExistingAura(SpellInfo const* newAura, uint32 effMask, Unit* caster, int32 *baseAmount /*= NULL*/, Item* castItem /*= NULL*/, ObjectGuid casterGUID /*= 0*/) { ASSERT(!casterGUID.IsEmpty() || caster); @@ -3016,25 +3016,25 @@ Aura* Unit::_TryStackingOrRefreshingExistingAura(SpellInfo const* newAura, uint8 return NULL; // update basepoints with new values - effect amount will be recalculated in ModStackAmount - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const* effect : foundAura->GetSpellEffectInfos()) { - if (!foundAura->HasEffect(i)) + if (!effect) continue; int bp; if (baseAmount) - bp = *(baseAmount + i); + bp = *(baseAmount + effect->EffectIndex); else - bp = foundAura->GetSpellInfo()->Effects[i].BasePoints; + bp = effect->BasePoints; - int32* oldBP = const_cast<int32*>(&(foundAura->GetEffect(i)->m_baseAmount)); + int32* oldBP = const_cast<int32*>(&(foundAura->GetEffect(effect->EffectIndex)->GetBaseAmount())); // todo 6.x review GetBaseAmount and GetCastItemGUID in this case *oldBP = bp; } // correct cast item guid if needed if (castItemGUID != foundAura->GetCastItemGUID()) { - ObjectGuid* oldGUID = const_cast<ObjectGuid*>(&foundAura->m_castItemGuid); + ObjectGuid* oldGUID = const_cast<ObjectGuid*>(&foundAura->GetCastItemGUID()); *oldGUID = castItemGUID; } @@ -3087,7 +3087,7 @@ void Unit::_AddAura(UnitAura* aura, Unit* caster) // creates aura application instance and registers it in lists // aura application effects are handled separately to prevent aura list corruption -AuraApplication * Unit::_CreateAuraApplication(Aura* aura, uint8 effMask) +AuraApplication * Unit::_CreateAuraApplication(Aura* aura, uint32 effMask) { // can't apply aura on unit which is going to be deleted - to not create a memory leak ASSERT(!m_cleanupDone); @@ -3278,7 +3278,7 @@ void Unit::_RemoveNoStackAurasDueToAura(Aura* aura) SpellInfo const* spellProto = aura->GetSpellInfo(); // passive spell special case (only non stackable with ranks) - if (spellProto->IsPassiveStackableWithRanks()) + if (spellProto->IsPassiveStackableWithRanks(GetMap()->GetDifficulty())) return; if (!IsHighestExclusiveAura(aura)) @@ -4196,9 +4196,9 @@ bool Unit::HasAuraWithMechanic(uint32 mechanicMask) const if (spellInfo->Mechanic && (mechanicMask & (1 << spellInfo->Mechanic))) return true; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - if (iter->second->HasEffect(i) && spellInfo->Effects[i].Effect && spellInfo->Effects[i].Mechanic) - if (mechanicMask & (1 << spellInfo->Effects[i].Mechanic)) + for (SpellEffectInfo const* effect : iter->second->GetBase()->GetSpellEffectInfos()) + if (effect && effect->Effect && effect->Mechanic) + if (mechanicMask & (1 << effect->Mechanic)) return true; } @@ -4934,13 +4934,17 @@ bool Unit::HandleAuraProcOnPowerAmount(Unit* victim, uint32 /*damage*/, AuraEffe // Get effect index used for the proc uint32 effIndex = triggeredByAura->GetEffIndex(); + SpellEffectInfo const* effect = triggeredByAura->GetSpellEffectInfo(); + if (!effect) + return false; + // Power amount required to proc the spell int32 powerAmountRequired = triggeredByAura->GetAmount(); // Power type required to proc - Powers powerRequired = Powers(auraSpellInfo->Effects[triggeredByAura->GetEffIndex()].MiscValue); + Powers powerRequired = Powers(effect->MiscValue); // Set trigger spell id, target, custom basepoints - uint32 trigger_spell_id = auraSpellInfo->Effects[triggeredByAura->GetEffIndex()].TriggerSpell; + uint32 trigger_spell_id = effect->TriggerSpell; Unit* target = NULL; int32 basepoints0 = 0; @@ -5616,18 +5620,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere triggered_spell_id = 28810; break; } - // Priest T10 Healer 2P Bonus - case 70770: - // Flash Heal - if (procSpell->SpellFamilyFlags[0] & 0x800) - { - triggered_spell_id = 70772; - SpellInfo const* blessHealing = sSpellMgr->GetSpellInfo(triggered_spell_id); - if (!blessHealing) - return false; - basepoints0 = int32(CalculatePct(damage, triggerAmount) / (blessHealing->GetMaxDuration() / blessHealing->Effects[0].ApplyAuraPeriod)); - } - break; + break; } break; } @@ -5745,7 +5738,10 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere SpellInfo const* triggeredSpell = sSpellMgr->GetSpellInfo(triggered_spell_id); if (!triggeredSpell) return false; - basepoints0 = CalculatePct(int32(damage), triggerAmount) / (triggeredSpell->GetMaxDuration() / triggeredSpell->Effects[0].ApplyAuraPeriod); + SpellEffectInfo const* effect = triggeredSpell->GetEffect(DIFFICULTY_NONE, EFFECT_0); + if (!effect) + return false; + basepoints0 = CalculatePct(int32(damage), triggerAmount) / (triggeredSpell->GetMaxDuration() / effect->ApplyAuraPeriod); // Add remaining ticks to damage done basepoints0 += victim->GetRemainingPeriodicAmount(GetGUID(), triggered_spell_id, SPELL_AURA_PERIODIC_DAMAGE); } @@ -6129,7 +6125,8 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere SpellInfo const* triggeredSpell = sSpellMgr->GetSpellInfo(triggered_spell_id); if (!triggeredSpell) return false; - basepoints0 = CalculatePct(int32(damage), triggerAmount) / (triggeredSpell->GetMaxDuration() / triggeredSpell->Effects[0].ApplyAuraPeriod); + if (SpellEffectInfo const* effect = triggeredSpell->GetEffect(DIFFICULTY_NONE, EFFECT_0)) + basepoints0 = CalculatePct(int32(damage), triggerAmount) / (triggeredSpell->GetMaxDuration() / effect->ApplyAuraPeriod); } break; } @@ -6143,9 +6140,12 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere SpellInfo const* triggeredSpell = sSpellMgr->GetSpellInfo(triggered_spell_id); if (!triggeredSpell) return false; - basepoints0 = CalculatePct(int32(damage), triggerAmount) / (triggeredSpell->GetMaxDuration() / triggeredSpell->Effects[0].ApplyAuraPeriod); - // Add remaining ticks to healing done - basepoints0 += GetRemainingPeriodicAmount(GetGUID(), triggered_spell_id, SPELL_AURA_PERIODIC_HEAL); + if (SpellEffectInfo const* effect = triggeredSpell->GetEffect(DIFFICULTY_NONE, EFFECT_0)) + { + basepoints0 = CalculatePct(int32(damage), triggerAmount) / (triggeredSpell->GetMaxDuration() / effect->ApplyAuraPeriod); + // Add remaining ticks to healing done + basepoints0 += GetRemainingPeriodicAmount(GetGUID(), triggered_spell_id, SPELL_AURA_PERIODIC_HEAL); + } } break; } @@ -6187,53 +6187,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere triggered_spell_id = 63685; break; } - // Flametongue Weapon (Passive) - if (dummySpell->SpellFamilyFlags[0] & 0x200000) - { - if (GetTypeId() != TYPEID_PLAYER || !victim || !victim->IsAlive() || !castItem || !castItem->IsEquipped()) - return false; - - WeaponAttackType attType = WeaponAttackType(Player::GetAttackBySlot(castItem->GetSlot())); - if ((attType != BASE_ATTACK && attType != OFF_ATTACK) - || (attType == BASE_ATTACK && procFlag & PROC_FLAG_DONE_OFFHAND_ATTACK) - || (attType == OFF_ATTACK && procFlag & PROC_FLAG_DONE_MAINHAND_ATTACK)) - return false; - - float fire_onhit = float(CalculatePct(dummySpell->Effects[EFFECT_0]. CalcValue(), 1.0f)); - - float add_spellpower = (float)(SpellBaseDamageBonusDone(SPELL_SCHOOL_MASK_FIRE) - + victim->SpellBaseDamageBonusTaken(SPELL_SCHOOL_MASK_FIRE)); - - // 1.3speed = 5%, 2.6speed = 10%, 4.0 speed = 15%, so, 1.0speed = 3.84% - ApplyPct(add_spellpower, 3.84f); - - // Enchant on Off-Hand and ready? - if (castItem->GetSlot() == EQUIPMENT_SLOT_OFFHAND && procFlag & PROC_FLAG_DONE_OFFHAND_ATTACK) - { - float BaseWeaponSpeed = GetAttackTime(OFF_ATTACK) / 1000.0f; - - // Value1: add the tooltip damage by swingspeed + Value2: add spelldmg by swingspeed - basepoints0 = int32((fire_onhit * BaseWeaponSpeed) + (add_spellpower * BaseWeaponSpeed)); - triggered_spell_id = 10444; - } - - // Enchant on Main-Hand and ready? - else if (castItem->GetSlot() == EQUIPMENT_SLOT_MAINHAND && procFlag & PROC_FLAG_DONE_MAINHAND_ATTACK) - { - float BaseWeaponSpeed = GetAttackTime(BASE_ATTACK) / 1000.0f; - - // Value1: add the tooltip damage by swingspeed + Value2: add spelldmg by swingspeed - basepoints0 = int32((fire_onhit * BaseWeaponSpeed) + (add_spellpower * BaseWeaponSpeed)); - triggered_spell_id = 10444; - } - - // If not ready, we should return, shouldn't we?! - else - return false; - - CastCustomSpell(victim, triggered_spell_id, &basepoints0, NULL, NULL, true, castItem, triggeredByAura); - return true; - } // Static Shock if (dummySpell->SpellIconID == 3059) { @@ -6255,15 +6208,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere } case SPELLFAMILY_DEATHKNIGHT: { - // Blood-Caked Blade - if (dummySpell->SpellIconID == 138) - { - if (!target || !target->IsAlive()) - return false; - - triggered_spell_id = dummySpell->Effects[effIndex].TriggerSpell; - break; - } // Dancing Rune Weapon if (dummySpell->Id == 49028) { @@ -6289,24 +6233,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere else return false; } - // Unholy Blight - if (dummySpell->Id == 49194) - { - triggered_spell_id = 50536; - SpellInfo const* unholyBlight = sSpellMgr->GetSpellInfo(triggered_spell_id); - if (!unholyBlight) - return false; - - basepoints0 = CalculatePct(int32(damage), triggerAmount); - - //Glyph of Unholy Blight - if (AuraEffect* glyph=GetAuraEffect(63332, 0)) - AddPct(basepoints0, glyph->GetAmount()); - - basepoints0 = basepoints0 / (unholyBlight->GetMaxDuration() / unholyBlight->Effects[0].ApplyAuraPeriod); - basepoints0 += victim->GetRemainingPeriodicAmount(GetGUID(), triggered_spell_id, SPELL_AURA_PERIODIC_DAMAGE); - break; - } // Threat of Thassarian if (dummySpell->SpellIconID == 2023) { @@ -6347,26 +6273,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere } case SPELLFAMILY_PET: { - switch (dummySpell->SpellIconID) - { - // Guard Dog - case 201: - { - if (!victim) - return false; - - triggered_spell_id = 54445; - target = this; - float addThreat = float(CalculatePct(procSpell->Effects[0].CalcValue(this), triggerAmount)); - victim->AddThreat(this, addThreat); - break; - } - // Silverback - case 1582: - triggered_spell_id = dummySpell->Id == 62765 ? 62801 : 62800; - target = this; - break; - } break; } default: @@ -6375,7 +6281,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere // if not handled by custom case, get triggered spell from dummySpell proto if (!triggered_spell_id) - triggered_spell_id = dummySpell->Effects[triggeredByAura->GetEffIndex()].TriggerSpell; + triggered_spell_id = triggeredByAura->GetSpellEffectInfo()->TriggerSpell; // processed charge only counting case if (!triggered_spell_id) @@ -6459,9 +6365,12 @@ bool Unit::HandleAuraProc(Unit* victim, uint32 /*damage*/, Aura* triggeredByAura // Swift Hand of Justice case 59906: { - int32 bp0 = CalculatePct(GetMaxHealth(), dummySpell->Effects[EFFECT_0]. CalcValue()); - CastCustomSpell(this, 59913, &bp0, NULL, NULL, true); - *handled = true; + if (SpellEffectInfo const* effect = triggeredByAura->GetSpellEffectInfo(EFFECT_0)) + { + int32 bp0 = CalculatePct(GetMaxHealth(), effect->CalcValue()); + CastCustomSpell(this, 59913, &bp0, NULL, NULL, true); + *handled = true; + } break; } } @@ -6476,49 +6385,10 @@ bool Unit::HandleAuraProc(Unit* victim, uint32 /*damage*/, Aura* triggeredByAura CastSpell(victim, 68055, true); return true; } - // Glyph of Divinity - else if (dummySpell->Id == 54939) - { - if (!procSpell) - return false; - *handled = true; - // Check if we are the target and prevent mana gain - if (victim && triggeredByAura->GetCasterGUID() == victim->GetGUID()) - return false; - // Lookup base amount mana restore - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; i++) - { - if (procSpell->Effects[i].Effect == SPELL_EFFECT_ENERGIZE) - { - // value multiplied by 2 because you should get twice amount - int32 mana = procSpell->Effects[i].CalcValue() * 2; - CastCustomSpell(this, 54986, 0, &mana, NULL, true); - } - } - return true; - } break; } case SPELLFAMILY_MAGE: { - switch (dummySpell->Id) - { - // Empowered Fire - case 31656: - case 31657: - case 31658: - { - *handled = true; - - SpellInfo const* spInfo = sSpellMgr->GetSpellInfo(67545); - if (!spInfo) - return false; - - int32 bp0 = int32(CalculatePct(GetCreateMana(), spInfo->Effects[0].CalcValue())); - CastCustomSpell(this, 67545, &bp0, NULL, NULL, true, NULL, triggeredByAura->GetEffect(EFFECT_0), GetGUID()); - return true; - } - } break; } case SPELLFAMILY_DEATHKNIGHT: @@ -6603,8 +6473,11 @@ bool Unit::HandleAuraProc(Unit* victim, uint32 /*damage*/, Aura* triggeredByAura // Item - Warrior T10 Protection 4P Bonus case 70844: { - int32 basepoints0 = CalculatePct(GetMaxHealth(), dummySpell->Effects[EFFECT_1]. CalcValue()); - CastCustomSpell(this, 70845, &basepoints0, NULL, NULL, true); + if (SpellEffectInfo const* effect = triggeredByAura->GetSpellEffectInfo(EFFECT_1)) + { + int32 basepoints0 = CalculatePct(GetMaxHealth(), effect->CalcValue()); + CastCustomSpell(this, 70845, &basepoints0, NULL, NULL, true); + } break; } // Recklessness @@ -6635,7 +6508,7 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg int32 triggerAmount = triggeredByAura->GetAmount(); // Set trigger spell id, target, custom basepoints - uint32 trigger_spell_id = auraSpellInfo->Effects[triggeredByAura->GetEffIndex()].TriggerSpell; + uint32 trigger_spell_id = triggeredByAura->GetSpellEffectInfo()->TriggerSpell; Unit* target = NULL; int32 basepoints0 = 0; @@ -6655,11 +6528,6 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg case SPELLFAMILY_GENERIC: switch (auraSpellInfo->Id) { - case 43820: // Charm of the Witch Doctor (Amani Charm of the Witch Doctor trinket) - // Pct value stored in dummy - basepoints0 = victim->GetCreateHealth() * auraSpellInfo->Effects[1].CalcValue() / 100; - target = victim; - break; case 57345: // Darkmoon Card: Greatness { float stat = 0.0f; @@ -6760,19 +6628,9 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg } case SPELLFAMILY_HUNTER: { - if (auraSpellInfo->SpellIconID == 3247) // Piercing Shots + /*if (auraSpellInfo->SpellIconID == 3247) // Piercing Shots { - switch (auraSpellInfo->Id) - { - case 53234: // Rank 1 - case 53237: // Rank 2 - case 53238: // Rank 3 - trigger_spell_id = 63468; - break; - default: - TC_LOG_ERROR("entities.unit", "Unit::HandleProcTriggerSpell: Spell %u miss posibly Piercing Shots", auraSpellInfo->Id); - return false; - } + trigger_spell_id = 63468; // 6.x missing from dbc but it is in the tooltip SpellInfo const* TriggerPS = sSpellMgr->GetSpellInfo(trigger_spell_id); if (!TriggerPS) return false; @@ -6780,7 +6638,7 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg basepoints0 = CalculatePct(int32(damage), triggerAmount) / (TriggerPS->GetMaxDuration() / TriggerPS->Effects[0].ApplyAuraPeriod); basepoints0 += victim->GetRemainingPeriodicAmount(GetGUID(), trigger_spell_id, SPELL_AURA_PERIODIC_DAMAGE); break; - } + }*/ // Item - Hunter T9 4P Bonus if (auraSpellInfo->Id == 67151) { @@ -6983,10 +6841,9 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg break; } // Decimation - case 63156: - case 63158: + case 108869: // Can proc only if target has hp below 25% - if (!victim || !victim->HealthBelowPct(auraSpellInfo->Effects[EFFECT_1].CalcValue())) + if (!victim || !victim->HealthBelowPct(triggeredByAura->GetSpellEffectInfo()->CalcValue())) return false; break; // Deathbringer Saurfang - Blood Beast's Blood Link @@ -7961,14 +7818,14 @@ void Unit::SetMinion(Minion *minion, bool apply) else if (minion->IsTotem()) { // All summoned by totem minions must disappear when it is removed. - if (SpellInfo const* spInfo = sSpellMgr->GetSpellInfo(minion->ToTotem()->GetSpell())) - for (int i = 0; i < MAX_SPELL_EFFECTS; ++i) - { - if (spInfo->Effects[i].Effect != SPELL_EFFECT_SUMMON) - continue; + if (SpellInfo const* spInfo = sSpellMgr->GetSpellInfo(minion->ToTotem()->GetSpell())) + for (SpellEffectInfo const* effect : spInfo->GetEffectsForDifficulty(DIFFICULTY_NONE)) + { + if (!effect || effect->Effect != SPELL_EFFECT_SUMMON) + continue; - RemoveAllMinionsByEntry(spInfo->Effects[i].MiscValue); - } + RemoveAllMinionsByEntry(effect->MiscValue); + } } if (GetTypeId() == TYPEID_PLAYER) @@ -8462,32 +8319,11 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin } // Custom scripted damage - switch (spellProto->SpellFamilyName) + /*switch (spellProto->SpellFamilyName) { case SPELLFAMILY_DEATHKNIGHT: - // Impurity (dummy effect) - if (GetTypeId() == TYPEID_PLAYER) - { - PlayerSpellMap playerSpells = ToPlayer()->GetSpellMap(); - for (PlayerSpellMap::const_iterator itr = playerSpells.begin(); itr != playerSpells.end(); ++itr) - { - if (itr->second->state == PLAYERSPELL_REMOVED || itr->second->disabled) - continue; - switch (itr->first) - { - case 49220: - case 49633: - case 49635: - case 49636: - case 49638: - if (SpellInfo const* proto = sSpellMgr->GetSpellInfo(itr->first)) - AddPct(ApCoeffMod, proto->Effects[0].CalcValue()); - break; - } - } - } break; - } + }*/ // Done fixed damage bonus auras int32 DoneAdvertisedBenefit = SpellBaseDamageBonusDone(spellProto->GetSchoolMask()); @@ -9236,9 +9072,11 @@ uint32 Unit::SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, ui DoneTotal += int32(DoneAdvertisedBenefit * coeff * factorMod); } - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const* effect : spellProto->GetEffectsForDifficulty(GetMap()->GetDifficulty())) { - switch (spellProto->Effects[i].ApplyAuraName) + if (!effect) + continue; + switch (effect->ApplyAuraName) { // Bonus healing does not apply to these spells case SPELL_AURA_PERIODIC_LEECH: @@ -9246,7 +9084,7 @@ uint32 Unit::SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, ui DoneTotal = 0; break; } - if (spellProto->Effects[i].Effect == SPELL_EFFECT_HEALTH_LEECH) + if (effect->Effect == SPELL_EFFECT_HEALTH_LEECH) DoneTotal = 0; } @@ -9401,17 +9239,19 @@ uint32 Unit::SpellHealingBonusTaken(Unit* caster, SpellInfo const* spellProto, u if (caster->GetGUID() == (*i)->GetCasterGUID() && (*i)->IsAffectingSpell(spellProto)) AddPct(TakenTotalMod, (*i)->GetAmount()); - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const* effect : spellProto->GetEffectsForDifficulty(GetMap()->GetDifficulty())) { - switch (spellProto->Effects[i].ApplyAuraName) + if (!effect) + continue; + switch (effect->ApplyAuraName) { // Bonus healing does not apply to these spells - case SPELL_AURA_PERIODIC_LEECH: - case SPELL_AURA_PERIODIC_HEALTH_FUNNEL: - TakenTotal = 0; - break; + case SPELL_AURA_PERIODIC_LEECH: + case SPELL_AURA_PERIODIC_HEALTH_FUNNEL: + TakenTotal = 0; + break; } - if (spellProto->Effects[i].Effect == SPELL_EFFECT_HEALTH_LEECH) + if (effect->Effect == SPELL_EFFECT_HEALTH_LEECH) TakenTotal = 0; } @@ -9444,7 +9284,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)->GetSpellInfo()->Effects[(*i)->GetEffIndex()].MiscValue); + Stats usedStat = Stats((*i)->GetSpellEffectInfo()->MiscValue); advertisedBenefit += int32(CalculatePct(GetStat(usedStat), (*i)->GetAmount())); } @@ -16693,43 +16533,40 @@ int32 Unit::GetHighestExclusiveSameEffectSpellGroupValue(AuraEffect const* aurEf bool Unit::IsHighestExclusiveAura(Aura const* aura, bool removeOtherAuraApplications /*= false*/) { - for (uint32 i = 0 ; i < MAX_SPELL_EFFECTS; ++i) + for (AuraEffect* aurEff : aura->GetAuraEffects()) { - if (AuraEffect const* aurEff = aura->GetEffect(i)) + AuraType const auraType = AuraType(aurEff->GetSpellEffectInfo()->ApplyAuraName); + AuraEffectList const& auras = GetAuraEffectsByType(auraType); + for (Unit::AuraEffectList::const_iterator itr = auras.begin(); itr != auras.end();) { - AuraType const auraType = AuraType(aura->GetSpellInfo()->Effects[i].ApplyAuraName); - AuraEffectList const& auras = GetAuraEffectsByType(auraType); - for (Unit::AuraEffectList::const_iterator itr = auras.begin(); itr != auras.end();) + AuraEffect const* existingAurEff = (*itr); + ++itr; + + if (sSpellMgr->CheckSpellGroupStackRules(aura->GetSpellInfo(), existingAurEff->GetSpellInfo()) + == SPELL_GROUP_STACK_RULE_EXCLUSIVE_HIGHEST) { - AuraEffect const* existingAurEff = (*itr); - ++itr; + int32 diff = abs(aurEff->GetAmount()) - abs(existingAurEff->GetAmount()); + if (!diff) + diff = int32(aura->GetEffectMask()) - int32(existingAurEff->GetBase()->GetEffectMask()); - if (sSpellMgr->CheckSpellGroupStackRules(aura->GetSpellInfo(), existingAurEff->GetSpellInfo()) - == SPELL_GROUP_STACK_RULE_EXCLUSIVE_HIGHEST) + if (diff > 0) { - int32 diff = abs(aurEff->GetAmount()) - abs(existingAurEff->GetAmount()); - if (!diff) - diff = int32(aura->GetEffectMask()) - int32(existingAurEff->GetBase()->GetEffectMask()); - - if (diff > 0) + Aura const* base = existingAurEff->GetBase(); + // no removing of area auras from the original owner, as that completely cancels them + if (removeOtherAuraApplications && (!base->IsArea() || base->GetOwner() != this)) { - Aura const* base = existingAurEff->GetBase(); - // no removing of area auras from the original owner, as that completely cancels them - if (removeOtherAuraApplications && (!base->IsArea() || base->GetOwner() != this)) + if (AuraApplication* aurApp = existingAurEff->GetBase()->GetApplicationOfTarget(GetGUID())) { - if (AuraApplication* aurApp = existingAurEff->GetBase()->GetApplicationOfTarget(GetGUID())) - { - bool hasMoreThanOneEffect = base->HasMoreThanOneEffectForType(auraType); - uint32 removedAuras = m_removedAurasCount; - RemoveAura(aurApp); - if (hasMoreThanOneEffect || m_removedAurasCount > removedAuras + 1) - itr = auras.begin(); - } + bool hasMoreThanOneEffect = base->HasMoreThanOneEffectForType(auraType); + uint32 removedAuras = m_removedAurasCount; + RemoveAura(aurApp); + if (hasMoreThanOneEffect || m_removedAurasCount > removedAuras + 1) + itr = auras.begin(); } } - else if (diff < 0) - return false; } + else if (diff < 0) + return false; } } } diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index f075578621a..5ff4bede241 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1760,11 +1760,11 @@ class Unit : public WorldObject bool InitTamedPet(Pet* pet, uint8 level, uint32 spell_id); // aura apply/remove helpers - you should better not use these - Aura* _TryStackingOrRefreshingExistingAura(SpellInfo const* newAura, uint8 effMask, Unit* caster, int32* baseAmount = NULL, Item* castItem = NULL, ObjectGuid casterGUID = ObjectGuid::Empty); + Aura* _TryStackingOrRefreshingExistingAura(SpellInfo const* newAura, uint32 effMask, Unit* caster, int32 *baseAmount = NULL, Item* castItem = NULL, ObjectGuid casterGUID = ObjectGuid::Empty); void _AddAura(UnitAura* aura, Unit* caster); - AuraApplication * _CreateAuraApplication(Aura* aura, uint8 effMask); + AuraApplication * _CreateAuraApplication(Aura* aura, uint32 effMask); void _ApplyAuraEffect(Aura* aura, uint8 effIndex); - void _ApplyAura(AuraApplication * aurApp, uint8 effMask); + void _ApplyAura(AuraApplication * aurApp, uint32 effMask); void _UnapplyAura(AuraApplicationMap::iterator &i, AuraRemoveMode removeMode); void _UnapplyAura(AuraApplication * aurApp, AuraRemoveMode removeMode); void _RemoveNoStackAuraApplicationsDueToAura(Aura* aura); @@ -2058,7 +2058,7 @@ class Unit : public WorldObject bool IsImmunedToDamage(SpellInfo const* spellInfo) const; virtual bool IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index) const; // redefined in Creature - static bool IsDamageReducedByArmor(SpellSchoolMask damageSchoolMask, SpellInfo const* spellInfo = NULL, uint8 effIndex = MAX_SPELL_EFFECTS); + bool IsDamageReducedByArmor(SpellSchoolMask damageSchoolMask, SpellInfo const* spellInfo = NULL, uint8 effIndex = MAX_SPELL_EFFECTS); uint32 CalcArmorReducedDamage(Unit* victim, const uint32 damage, SpellInfo const* spellInfo, WeaponAttackType attackType = MAX_ATTACK); uint32 CalcSpellResistance(Unit* victim, SpellSchoolMask schoolMask, SpellInfo const* spellInfo) const; void CalcAbsorbResist(Unit* victim, SpellSchoolMask schoolMask, DamageEffectType damagetype, uint32 const damage, uint32* absorb, uint32* resist, SpellInfo const* spellInfo = NULL); diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index c55c92d296e..10221f61c71 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -431,13 +431,17 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]= &AuraEffect::HandleNULL, //370 SPELL_AURA_SET_FAIR_FAR_CLIP }; -AuraEffect::AuraEffect(Aura* base, uint8 effIndex, int32 *baseAmount, Unit* caster): +AuraEffect::AuraEffect(Aura* base, uint32 effIndex, int32 baseAmount, Unit* caster) : m_base(base), m_spellInfo(base->GetSpellInfo()), -m_baseAmount(baseAmount ? *baseAmount : m_spellInfo->Effects[effIndex].BasePoints), +m_baseAmount(baseAmount), m_damage(0), m_critChance(0.0f), m_donePct(1.0f), m_spellmod(NULL), m_periodicTimer(0), m_tickNumber(0), m_effIndex(effIndex), m_canBeRecalculated(true), m_isPeriodic(false) { + _effectInfo = base->GetSpellEffectInfo(effIndex); + + ASSERT(_effectInfo); + CalculatePeriodic(caster, true, false); m_amount = CalculateAmount(caster); @@ -476,10 +480,10 @@ int32 AuraEffect::CalculateAmount(Unit* caster) // default amount calculation int32 amount = 0; - if (!(m_spellInfo->AttributesEx8 & SPELL_ATTR8_MASTERY_SPECIALIZATION) || G3D::fuzzyEq(m_spellInfo->Effects[m_effIndex].BonusCoefficient, 0.0f)) - amount = m_spellInfo->Effects[m_effIndex].CalcValue(caster, &m_baseAmount, GetBase()->GetOwner()->ToUnit()); + if (!(m_spellInfo->AttributesEx8 & SPELL_ATTR8_MASTERY_SPECIALIZATION) || G3D::fuzzyEq(GetSpellEffectInfo()->BonusCoefficient, 0.0f)) + amount = GetSpellEffectInfo()->CalcValue(caster, &m_baseAmount, GetBase()->GetOwner()->ToUnit()); else if (caster && caster->GetTypeId() == TYPEID_PLAYER) - amount = int32(caster->GetFloatValue(PLAYER_MASTERY) * m_spellInfo->Effects[m_effIndex].BonusCoefficient); + amount = int32(caster->GetFloatValue(PLAYER_MASTERY) * GetSpellEffectInfo()->BonusCoefficient); // check item enchant aura cast if (!amount && caster) @@ -604,7 +608,7 @@ int32 AuraEffect::CalculateAmount(Unit* caster) void AuraEffect::CalculatePeriodic(Unit* caster, bool resetPeriodicTimer /*= true*/, bool load /*= false*/) { - m_period = m_spellInfo->Effects[m_effIndex].ApplyAuraPeriod; + m_period = GetSpellEffectInfo()->ApplyAuraPeriod; // prepare periodics switch (GetAuraType()) @@ -694,7 +698,7 @@ void AuraEffect::CalculateSpellMod() m_spellmod->type = SpellModType(uint32(GetAuraType())); // SpellModType value == spell aura types m_spellmod->spellId = GetId(); - m_spellmod->mask = GetSpellInfo()->Effects[GetEffIndex()].SpellClassMask; + m_spellmod->mask = GetSpellEffectInfo()->SpellClassMask; m_spellmod->charges = GetBase()->GetCharges(); } m_spellmod->value = GetAmount(); @@ -1021,7 +1025,7 @@ bool AuraEffect::IsAffectingSpell(SpellInfo const* spell) const return false; // Check EffectClassMask - if (m_spellInfo->Effects[m_effIndex].SpellClassMask & spell->SpellFamilyFlags) + if (GetSpellEffectInfo()->SpellClassMask & spell->SpellFamilyFlags) return true; return false; } @@ -1114,7 +1118,7 @@ void AuraEffect::HandleProc(AuraApplication* aurApp, ProcEventInfo& eventInfo) void AuraEffect::CleanupTriggeredSpells(Unit* target) { - uint32 tSpellId = m_spellInfo->Effects[GetEffIndex()].TriggerSpell; + uint32 tSpellId = GetSpellEffectInfo()->TriggerSpell; if (!tSpellId) return; @@ -1127,8 +1131,8 @@ void AuraEffect::CleanupTriggeredSpells(Unit* target) // needed for spell 43680, maybe others /// @todo is there a spell flag, which can solve this in a more sophisticated way? - if (m_spellInfo->Effects[GetEffIndex()].ApplyAuraName == SPELL_AURA_PERIODIC_TRIGGER_SPELL && - uint32(m_spellInfo->GetDuration()) == m_spellInfo->Effects[GetEffIndex()].ApplyAuraPeriod) + if (GetSpellEffectInfo()->ApplyAuraName == SPELL_AURA_PERIODIC_TRIGGER_SPELL && + uint32(m_spellInfo->GetDuration()) == GetSpellEffectInfo()->ApplyAuraPeriod) return; target->RemoveAurasDueToSpell(tSpellId, GetCasterGUID()); @@ -1268,30 +1272,6 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const target->CastSpell(target, 24932, true, NULL, this); } - // Heart of the Wild - if (AuraEffect const* heartOfTheWild = target->GetAuraEffectOfRankedSpell(17003, EFFECT_0)) - { - uint32 heartOfTheWildSpellId = 0; - int32 heartOfTheWildAmount = 0; - - switch (GetMiscValue()) - { - case FORM_CAT: - heartOfTheWildSpellId = 24900; - heartOfTheWildAmount = heartOfTheWild->GetSpellInfo()->Effects[EFFECT_1].CalcValue(); - break; - case FORM_BEAR: - heartOfTheWildSpellId = 24899; - heartOfTheWildAmount = heartOfTheWild->GetSpellInfo()->Effects[EFFECT_2].CalcValue(); - break; - default: - break; - } - - if (heartOfTheWildSpellId) - target->CastCustomSpell(target, heartOfTheWildSpellId, &heartOfTheWildAmount, NULL, NULL, true, NULL, this); - } - switch (GetMiscValue()) { case FORM_CAT: @@ -1327,12 +1307,6 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const int32 bp = aurEff->GetAmount(); target->CastCustomSpell(target, 48418, &bp, NULL, NULL, true); } - // Survival of the Fittest - if (AuraEffect const* aurEff = target->GetAuraEffect(SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE, SPELLFAMILY_DRUID, 961, EFFECT_0)) - { - int32 bp = aurEff->GetSpellInfo()->Effects[EFFECT_2].CalcValue(GetCaster()); - target->CastCustomSpell(target, 62069, &bp, NULL, NULL, true, 0, this); - } break; case FORM_MOONKIN: // Master Shapeshifter - Moonkin @@ -2594,9 +2568,8 @@ void AuraEffect::HandleAuraMounted(AuraApplication const* aurApp, uint8 mode, bo vehicleId = creatureInfo->VehicleId; //some spell has one aura of mount and one of vehicle - for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i) - if (GetSpellInfo()->Effects[i].Effect == SPELL_EFFECT_SUMMON - && GetSpellInfo()->Effects[i].MiscValue == GetMiscValue()) + for (SpellEffectInfo const* effect : GetBase()->GetSpellEffectInfos()) + if (effect && effect->Effect == SPELL_EFFECT_SUMMON && effect->MiscValue == GetMiscValue()) displayId = 0; } @@ -4598,8 +4571,9 @@ 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) - mask |= (*i)->m_spellInfo->Effects[(*i)->m_effIndex].SpellClassMask; + for (Unit::AuraEffectList::const_iterator i = noReagent.begin(); i != noReagent.end(); ++i) + if (SpellEffectInfo const* effect = (*i)->GetSpellEffectInfo()) + mask |= effect->SpellClassMask; target->SetUInt32Value(PLAYER_NO_REAGENT_COST_1 , mask[0]); target->SetUInt32Value(PLAYER_NO_REAGENT_COST_1+1, mask[1]); @@ -5021,11 +4995,11 @@ void AuraEffect::HandleChannelDeathItem(AuraApplication const* aurApp, uint8 mod if (GetAmount() <= 0) return; - if (GetSpellInfo()->Effects[m_effIndex].ItemType == 0) + if (GetSpellEffectInfo()->ItemType == 0) return; // Soul Shard - if (GetSpellInfo()->Effects[m_effIndex].ItemType == 6265) + if (GetSpellEffectInfo()->ItemType == 6265) { // Soul Shard only from units that grant XP or honor if (!plCaster->isHonorOrXPTarget(target) || @@ -5038,16 +5012,16 @@ void AuraEffect::HandleChannelDeathItem(AuraApplication const* aurApp, uint8 mod uint32 count = m_amount; ItemPosCountVec dest; - InventoryResult msg = plCaster->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, GetSpellInfo()->Effects[m_effIndex].ItemType, count, &noSpaceForCount); + InventoryResult msg = plCaster->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, GetSpellEffectInfo()->ItemType, count, &noSpaceForCount); if (msg != EQUIP_ERR_OK) { count-=noSpaceForCount; - plCaster->SendEquipError(msg, NULL, NULL, GetSpellInfo()->Effects[m_effIndex].ItemType); + plCaster->SendEquipError(msg, NULL, NULL, GetSpellEffectInfo()->ItemType); if (count == 0) return; } - Item* newitem = plCaster->StoreNewItem(dest, GetSpellInfo()->Effects[m_effIndex].ItemType, true); + Item* newitem = plCaster->StoreNewItem(dest, GetSpellEffectInfo()->ItemType, true); if (!newitem) { plCaster->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL); @@ -5186,19 +5160,19 @@ void AuraEffect::HandleAuraLinked(AuraApplication const* aurApp, uint8 mode, boo { Unit* target = aurApp->GetTarget(); - uint32 triggeredSpellId = sSpellMgr->GetSpellIdForDifficulty(m_spellInfo->Effects[m_effIndex].TriggerSpell, target); + uint32 triggeredSpellId = GetSpellEffectInfo()->TriggerSpell; SpellInfo const* triggeredSpellInfo = sSpellMgr->GetSpellInfo(triggeredSpellId); if (!triggeredSpellInfo) return; + Unit* caster = triggeredSpellInfo->NeedsToBeTriggeredByCaster(m_spellInfo, target->GetMap()->GetDifficulty()) ? GetCaster() : target; + if (!caster) + return; + if (mode & AURA_EFFECT_HANDLE_REAL) { if (apply) { - Unit* caster = triggeredSpellInfo->NeedsToBeTriggeredByCaster(m_spellInfo) ? GetCaster() : target; - - if (!caster) - return; // If amount avalible cast with basepoints (Crypt Fever for example) if (GetAmount()) caster->CastCustomSpell(target, triggeredSpellId, &m_amount, NULL, NULL, true, NULL, this); @@ -5207,13 +5181,13 @@ void AuraEffect::HandleAuraLinked(AuraApplication const* aurApp, uint8 mode, boo } else { - ObjectGuid casterGUID = triggeredSpellInfo->NeedsToBeTriggeredByCaster(m_spellInfo) ? GetCasterGUID() : target->GetGUID(); + ObjectGuid casterGUID = triggeredSpellInfo->NeedsToBeTriggeredByCaster(m_spellInfo, caster->GetMap()->GetDifficulty()) ? GetCasterGUID() : target->GetGUID(); target->RemoveAura(triggeredSpellId, casterGUID, 0, aurApp->GetRemoveMode()); } } else if (mode & AURA_EFFECT_HANDLE_REAPPLY && apply) { - ObjectGuid casterGUID = triggeredSpellInfo->NeedsToBeTriggeredByCaster(m_spellInfo) ? GetCasterGUID() : target->GetGUID(); + ObjectGuid casterGUID = triggeredSpellInfo->NeedsToBeTriggeredByCaster(m_spellInfo, caster->GetMap()->GetDifficulty()) ? GetCasterGUID() : target->GetGUID(); // change the stack amount to be equal to stack amount of our aura if (Aura* triggeredAura = target->GetAura(triggeredSpellId, casterGUID)) triggeredAura->ModStackAmount(GetBase()->GetStackAmount() - triggeredAura->GetStackAmount()); @@ -5384,7 +5358,7 @@ void AuraEffect::HandlePeriodicDummyAuraTick(Unit* target, Unit* caster) const } case 62292: // Blaze (Pool of Tar) // should we use custom damage? - target->CastSpell((Unit*)NULL, m_spellInfo->Effects[m_effIndex].TriggerSpell, true); + target->CastSpell((Unit*)NULL, GetSpellEffectInfo()->TriggerSpell, true); break; case 62399: // Overload Circuit if (target->GetMap()->IsDungeon() && int(target->GetAppliedAuras().count(62399)) >= (target->GetMap()->IsHeroic() ? 4 : 2)) @@ -5408,7 +5382,7 @@ void AuraEffect::HandlePeriodicDummyAuraTick(Unit* target, Unit* caster) const // Mirror Image if (GetId() == 55342) // Set name of summons to name of caster - target->CastSpell((Unit*)NULL, m_spellInfo->Effects[m_effIndex].TriggerSpell, true); + target->CastSpell((Unit*)NULL, GetSpellEffectInfo()->TriggerSpell, true); break; } case SPELLFAMILY_DRUID: @@ -5501,7 +5475,7 @@ void AuraEffect::HandlePeriodicDummyAuraTick(Unit* target, Unit* caster) const void AuraEffect::HandlePeriodicTriggerSpellAuraTick(Unit* target, Unit* caster) const { // generic casting code with custom spells and target/caster customs - uint32 triggerSpellId = GetSpellInfo()->Effects[GetEffIndex()].TriggerSpell; + uint32 triggerSpellId = GetSpellEffectInfo()->TriggerSpell; SpellInfo const* triggeredSpellInfo = sSpellMgr->GetSpellInfo(triggerSpellId); SpellInfo const* auraSpellInfo = GetSpellInfo(); @@ -5765,7 +5739,7 @@ void AuraEffect::HandlePeriodicTriggerSpellAuraTick(Unit* target, Unit* caster) if (triggeredSpellInfo) { - if (Unit* triggerCaster = triggeredSpellInfo->NeedsToBeTriggeredByCaster(m_spellInfo) ? caster : target) + if (Unit* triggerCaster = triggeredSpellInfo->NeedsToBeTriggeredByCaster(m_spellInfo, target->GetMap()->GetDifficulty()) ? caster : target) { triggerCaster->CastSpell(target, triggeredSpellInfo, true, NULL, this); TC_LOG_DEBUG("spells", "AuraEffect::HandlePeriodicTriggerSpellAuraTick: Spell %u Trigger %u", GetId(), triggeredSpellInfo->Id); @@ -5782,10 +5756,10 @@ void AuraEffect::HandlePeriodicTriggerSpellAuraTick(Unit* target, Unit* caster) void AuraEffect::HandlePeriodicTriggerSpellWithValueAuraTick(Unit* target, Unit* caster) const { - uint32 triggerSpellId = GetSpellInfo()->Effects[m_effIndex].TriggerSpell; + uint32 triggerSpellId = GetSpellEffectInfo()->TriggerSpell; if (SpellInfo const* triggeredSpellInfo = sSpellMgr->GetSpellInfo(triggerSpellId)) { - if (Unit* triggerCaster = triggeredSpellInfo->NeedsToBeTriggeredByCaster(m_spellInfo) ? caster : target) + if (Unit* triggerCaster = triggeredSpellInfo->NeedsToBeTriggeredByCaster(m_spellInfo, target->GetMap()->GetDifficulty()) ? caster : target) { int32 basepoints = GetAmount(); triggerCaster->CastCustomSpell(target, triggerSpellId, &basepoints, &basepoints, &basepoints, true, nullptr, this); @@ -5808,7 +5782,7 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const } // Consecrate ticks can miss and will not show up in the combat log - if (GetSpellInfo()->Effects[GetEffIndex()].Effect == SPELL_EFFECT_PERSISTENT_AREA_AURA && + if (GetSpellEffectInfo()->Effect == SPELL_EFFECT_PERSISTENT_AREA_AURA && caster->SpellHitResult(target, GetSpellInfo(), false) != SPELL_MISS_NONE) return; @@ -5827,11 +5801,14 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const break; case 38772: // Grievous Wound { - uint32 percent = GetSpellInfo()->Effects[EFFECT_1].CalcValue(caster); - if (!target->HealthBelowPct(percent)) + if (SpellEffectInfo const* effect = GetSpellInfo()->GetEffect(DIFFICULTY_NONE, EFFECT_1)) { - target->RemoveAurasDueToSpell(GetSpellInfo()->Id); - return; + uint32 percent = effect->CalcValue(caster); + if (!target->HealthBelowPct(percent)) + { + target->RemoveAurasDueToSpell(GetSpellInfo()->Id); + return; + } } break; } @@ -5843,7 +5820,7 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const CleanDamage cleanDamage = CleanDamage(0, 0, BASE_ATTACK, MELEE_HIT_NORMAL); // AOE spells are not affected by the new periodic system. - bool isAreaAura = m_spellInfo->Effects[m_effIndex].IsAreaAuraEffect() || m_spellInfo->Effects[m_effIndex].IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA); + bool isAreaAura = GetSpellEffectInfo()->IsAreaAuraEffect() || GetSpellEffectInfo()->IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA); // ignore negative values (can be result apply spellmods to aura damage uint32 damage = isAreaAura ? std::max(GetAmount(), 0) : m_damage; @@ -5858,7 +5835,7 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const damage = target->SpellDamageBonusTaken(caster, GetSpellInfo(), damage, DOT, GetBase()->GetStackAmount()); // Calculate armor mitigation - if (Unit::IsDamageReducedByArmor(GetSpellInfo()->GetSchoolMask(), GetSpellInfo(), GetEffIndex())) + if (caster->IsDamageReducedByArmor(GetSpellInfo()->GetSchoolMask(), GetSpellInfo(), GetEffIndex())) { uint32 damageReductedArmor = caster->CalcArmorReducedDamage(target, damage, GetSpellInfo()); cleanDamage.mitigated_damage += damage - damageReductedArmor; @@ -5902,7 +5879,7 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const damage = uint32(target->CountPctFromMaxHealth(damage)); if (!(m_spellInfo->AttributesEx4 & SPELL_ATTR4_FIXED_DAMAGE)) - if (m_spellInfo->Effects[m_effIndex].IsTargetingArea() || isAreaAura) + if (GetSpellEffectInfo()->IsTargetingArea() || isAreaAura) { damage = int32(float(damage) * target->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE, m_spellInfo->SchoolMask)); if (caster->GetTypeId() != TYPEID_PLAYER) @@ -5950,6 +5927,18 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const caster->DealDamage(target, damage, &cleanDamage, DOT, GetSpellInfo()->GetSchoolMask(), GetSpellInfo(), true); } +bool AuraEffect::IsAreaAuraEffect() const +{ + if (_effectInfo->Effect == SPELL_EFFECT_APPLY_AREA_AURA_PARTY || + _effectInfo->Effect == SPELL_EFFECT_APPLY_AREA_AURA_RAID || + _effectInfo->Effect == SPELL_EFFECT_APPLY_AREA_AURA_FRIEND || + _effectInfo->Effect == SPELL_EFFECT_APPLY_AREA_AURA_ENEMY || + _effectInfo->Effect == SPELL_EFFECT_APPLY_AREA_AURA_PET || + _effectInfo->Effect == SPELL_EFFECT_APPLY_AREA_AURA_OWNER) + return true; + return false; +} + void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) const { if (!caster || !target->IsAlive()) @@ -5961,7 +5950,7 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c return; } - if (GetSpellInfo()->Effects[GetEffIndex()].Effect == SPELL_EFFECT_PERSISTENT_AREA_AURA && + if (GetSpellEffectInfo()->Effect == SPELL_EFFECT_PERSISTENT_AREA_AURA && caster->SpellHitResult(target, GetSpellInfo(), false) != SPELL_MISS_NONE) return; @@ -5969,7 +5958,7 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c uint32 resist = 0; CleanDamage cleanDamage = CleanDamage(0, 0, BASE_ATTACK, MELEE_HIT_NORMAL); - bool isAreaAura = m_spellInfo->Effects[m_effIndex].IsAreaAuraEffect() || m_spellInfo->Effects[m_effIndex].IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA); + bool isAreaAura = GetSpellEffectInfo()->IsAreaAuraEffect() || GetSpellEffectInfo()->IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA); // ignore negative values (can be result apply spellmods to aura damage uint32 damage = isAreaAura ? std::max(GetAmount(), 0) : m_damage; @@ -5982,7 +5971,7 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c damage = target->SpellDamageBonusTaken(caster, GetSpellInfo(), damage, DOT, GetBase()->GetStackAmount()); // Calculate armor mitigation - if (Unit::IsDamageReducedByArmor(GetSpellInfo()->GetSchoolMask(), GetSpellInfo(), GetEffIndex())) + if (caster->IsDamageReducedByArmor(GetSpellInfo()->GetSchoolMask(), GetSpellInfo(), GetEffIndex())) { uint32 damageReductedArmor = caster->CalcArmorReducedDamage(target, damage, GetSpellInfo()); cleanDamage.mitigated_damage += damage - damageReductedArmor; @@ -5990,7 +5979,7 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c } if (!(m_spellInfo->AttributesEx4 & SPELL_ATTR4_FIXED_DAMAGE)) - if (m_spellInfo->Effects[m_effIndex].IsTargetingArea() || isAreaAura) + if (GetSpellEffectInfo()->IsTargetingArea() || isAreaAura) { damage = int32(float(damage) * target->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE, m_spellInfo->SchoolMask)); if (caster->GetTypeId() != TYPEID_PLAYER) @@ -6032,7 +6021,7 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c int32 new_damage = caster->DealDamage(target, damage, &cleanDamage, DOT, GetSpellInfo()->GetSchoolMask(), GetSpellInfo(), false); if (caster->IsAlive()) { - float gainMultiplier = GetSpellInfo()->Effects[GetEffIndex()].CalcValueMultiplier(caster); + float gainMultiplier = GetSpellEffectInfo()->CalcValueMultiplier(caster); uint32 heal = uint32(caster->SpellHealingBonusDone(caster, GetSpellInfo(), uint32(new_damage * gainMultiplier), DOT, GetBase()->GetStackAmount())); heal = uint32(caster->SpellHealingBonusTaken(caster, GetSpellInfo(), heal, DOT, GetBase()->GetStackAmount())); @@ -6063,7 +6052,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 = GetSpellInfo()->Effects[GetEffIndex()].CalcValueMultiplier(caster); + float gainMultiplier = GetSpellEffectInfo()->CalcValueMultiplier(caster); damage = int32(damage * gainMultiplier); @@ -6089,7 +6078,7 @@ void AuraEffect::HandlePeriodicHealAurasTick(Unit* target, Unit* caster) const if (GetBase()->IsPermanent() && target->IsFullHealth()) return; - bool isAreaAura = m_spellInfo->Effects[m_effIndex].IsAreaAuraEffect() || m_spellInfo->Effects[m_effIndex].IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA); + bool isAreaAura = GetSpellEffectInfo()->IsAreaAuraEffect() || GetSpellEffectInfo()->IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA); // ignore negative values (can be result apply spellmods to aura damage int32 damage = isAreaAura ? std::max(GetAmount(), 0) : m_damage; @@ -6196,7 +6185,7 @@ void AuraEffect::HandlePeriodicManaLeechAuraTick(Unit* target, Unit* caster) con return; } - if (GetSpellInfo()->Effects[GetEffIndex()].Effect == SPELL_EFFECT_PERSISTENT_AREA_AURA && + if (GetSpellEffectInfo()->Effect == SPELL_EFFECT_PERSISTENT_AREA_AURA && caster->SpellHitResult(target, GetSpellInfo(), false) != SPELL_MISS_NONE) return; @@ -6219,7 +6208,7 @@ void AuraEffect::HandlePeriodicManaLeechAuraTick(Unit* target, Unit* caster) con int32 drainedAmount = -target->ModifyPower(powerType, -drainAmount); - float gainMultiplier = GetSpellInfo()->Effects[GetEffIndex()].CalcValueMultiplier(caster); + float gainMultiplier = GetSpellEffectInfo()->CalcValueMultiplier(caster); SpellPeriodicAuraLogInfo pInfo(this, drainedAmount, 0, 0, 0, gainMultiplier, false); target->SendPeriodicAuraLog(&pInfo); @@ -6336,7 +6325,7 @@ void AuraEffect::HandlePeriodicPowerBurnAuraTick(Unit* target, Unit* caster) con uint32 gain = uint32(-target->ModifyPower(powerType, -damage)); - float dmgMultiplier = GetSpellInfo()->Effects[GetEffIndex()].CalcValueMultiplier(caster); + float dmgMultiplier = GetSpellEffectInfo()->CalcValueMultiplier(caster); SpellInfo const* spellProto = GetSpellInfo(); // maybe has to be sent different to client, but not by SMSG_PERIODICAURALOG @@ -6365,7 +6354,7 @@ void AuraEffect::HandleProcTriggerSpellAuraProc(AuraApplication* aurApp, ProcEve Unit* triggerCaster = aurApp->GetTarget(); Unit* triggerTarget = eventInfo.GetProcTarget(); - uint32 triggerSpellId = GetSpellInfo()->Effects[GetEffIndex()].TriggerSpell; + uint32 triggerSpellId = GetSpellEffectInfo()->TriggerSpell; if (SpellInfo const* triggeredSpellInfo = sSpellMgr->GetSpellInfo(triggerSpellId)) { TC_LOG_DEBUG("spells", "AuraEffect::HandleProcTriggerSpellAuraProc: Triggering spell %u from aura %u proc", triggeredSpellInfo->Id, GetId()); @@ -6380,7 +6369,7 @@ void AuraEffect::HandleProcTriggerSpellWithValueAuraProc(AuraApplication* aurApp Unit* triggerCaster = aurApp->GetTarget(); Unit* triggerTarget = eventInfo.GetProcTarget(); - uint32 triggerSpellId = GetSpellInfo()->Effects[m_effIndex].TriggerSpell; + uint32 triggerSpellId = GetSpellEffectInfo()->TriggerSpell; if (SpellInfo const* triggeredSpellInfo = sSpellMgr->GetSpellInfo(triggerSpellId)) { int32 basepoints0 = GetAmount(); @@ -6438,7 +6427,7 @@ void AuraEffect::HandleRaidProcFromChargeAuraProc(AuraApplication* aurApp, ProcE { if (Unit* caster = GetCaster()) { - float radius = GetSpellInfo()->Effects[GetEffIndex()].CalcRadius(caster); + float radius = GetSpellEffectInfo()->CalcRadius(caster); if (Unit* triggerTarget = target->GetNextRandomRaidMemberOrPet(radius)) { @@ -6479,7 +6468,7 @@ void AuraEffect::HandleRaidProcFromChargeWithValueAuraProc(AuraApplication* aurA { if (Unit* caster = GetCaster()) { - float radius = GetSpellInfo()->Effects[GetEffIndex()].CalcRadius(caster); + float radius = GetSpellEffectInfo()->CalcRadius(caster); if (Unit* triggerTarget = target->GetNextRandomRaidMemberOrPet(radius)) { diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.h b/src/server/game/Spells/Auras/SpellAuraEffects.h index 22571f4851e..2c2b0e2646f 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.h +++ b/src/server/game/Spells/Auras/SpellAuraEffects.h @@ -29,13 +29,13 @@ typedef void(AuraEffect::*pAuraEffectHandler)(AuraApplication const* aurApp, uin class AuraEffect { - friend void Aura::_InitEffects(uint8 effMask, Unit* caster, int32 *baseAmount); - friend Aura* Unit::_TryStackingOrRefreshingExistingAura(SpellInfo const* newAura, uint8 effMask, Unit* caster, int32* baseAmount, Item* castItem, ObjectGuid casterGUID); + friend void Aura::_InitEffects(uint32 effMask, Unit* caster, int32 *baseAmount); + friend Aura* Unit::_TryStackingOrRefreshingExistingAura(SpellInfo const* newAura, uint32 effMask, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID); friend Aura::~Aura(); - private: - ~AuraEffect(); - explicit AuraEffect(Aura* base, uint8 effIndex, int32 *baseAmount, Unit* caster); + public: + ~AuraEffect(); + AuraEffect(Aura* base, uint32 effIndex, int32 baseAmount, Unit* caster); Unit* GetCaster() const { return GetBase()->GetCaster(); } ObjectGuid GetCasterGUID() const { return GetBase()->GetCasterGUID(); } Aura* GetBase() const { return m_base; } @@ -49,9 +49,9 @@ class AuraEffect int32 GetBaseAmount() const { return m_baseAmount; } int32 GetPeriod() const { return m_period; } - int32 GetMiscValueB() const { return m_spellInfo->Effects[m_effIndex].MiscValueB; } - int32 GetMiscValue() const { return m_spellInfo->Effects[m_effIndex].MiscValue; } - AuraType GetAuraType() const { return (AuraType)m_spellInfo->Effects[m_effIndex].ApplyAuraName; } + int32 GetMiscValueB() const { return GetSpellEffectInfo()->MiscValueB; } + int32 GetMiscValue() const { return GetSpellEffectInfo()->MiscValue; } + AuraType GetAuraType() const { return (AuraType)GetSpellEffectInfo()->ApplyAuraName; } int32 GetAmount() const { return m_amount; } void SetAmount(int32 amount) { m_amount = amount; m_canBeRecalculated = false;} @@ -87,7 +87,7 @@ class AuraEffect bool IsPeriodic() const { return m_isPeriodic; } void SetPeriodic(bool isPeriodic) { m_isPeriodic = isPeriodic; } bool IsAffectingSpell(SpellInfo const* spell) const; - bool HasSpellClassMask() const { return m_spellInfo->Effects[m_effIndex].SpellClassMask; } + bool HasSpellClassMask() const { return GetSpellEffectInfo()->SpellClassMask; } void SendTickImmune(Unit* target, Unit* caster) const; void PeriodicTick(AuraApplication * aurApp, Unit* caster) const; @@ -98,10 +98,18 @@ class AuraEffect // add/remove SPELL_AURA_MOD_SHAPESHIFT (36) linked auras void HandleShapeshiftBoosts(Unit* target, bool apply) const; + + SpellEffectInfo const* GetSpellEffectInfo() const { return _effectInfo; } + + bool IsEffect() const { return _effectInfo->Effect != 0; } + bool IsEffect(SpellEffectName effectName) const { return _effectInfo->Effect == uint32(effectName); } + bool IsAreaAuraEffect() const; + private: Aura* const m_base; SpellInfo const* const m_spellInfo; + SpellEffectInfo const* _effectInfo; int32 const m_baseAmount; int32 m_amount; diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp index 67df56d892e..c244e7637dd 100644 --- a/src/server/game/Spells/Auras/SpellAuras.cpp +++ b/src/server/game/Spells/Auras/SpellAuras.cpp @@ -37,7 +37,7 @@ #include "Vehicle.h" #include "Config.h" -AuraApplication::AuraApplication(Unit* target, Unit* caster, Aura* aura, uint8 effMask): +AuraApplication::AuraApplication(Unit* target, Unit* caster, Aura* aura, uint32 effMask): _target(target), _base(aura), _removeMode(AURA_REMOVE_NONE), _slot(MAX_AURAS), _flags(AFLAG_NONE), _effectsToApply(effMask), _needClientUpdate(false) { @@ -113,7 +113,7 @@ void AuraApplication::_Remove() } } -void AuraApplication::_InitFlags(Unit* caster, uint8 effMask) +void AuraApplication::_InitFlags(Unit* caster, uint32 effMask) { // mark as selfcast if needed _flags |= (GetBase()->GetCasterGUID() == GetTarget()->GetGUID()) ? AFLAG_CASTER : AFLAG_NONE; @@ -123,9 +123,9 @@ void AuraApplication::_InitFlags(Unit* caster, uint8 effMask) if (IsSelfcast() || !caster || !caster->IsFriendlyTo(GetTarget())) { bool negativeFound = false; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const* effect : GetBase()->GetSpellEffectInfos()) { - if (((1<<i) & effMask) && !GetBase()->GetSpellInfo()->IsPositiveEffect(i)) + if (effect && ((1 << effect->EffectIndex) & effMask) && !GetBase()->GetSpellInfo()->IsPositiveEffect(effect->EffectIndex)) { negativeFound = true; break; @@ -138,9 +138,9 @@ void AuraApplication::_InitFlags(Unit* caster, uint8 effMask) else { bool positiveFound = false; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const* effect : GetBase()->GetSpellEffectInfos()) { - if (((1<<i) & effMask) && GetBase()->GetSpellInfo()->IsPositiveEffect(i)) + if (effect && ((1 << effect->EffectIndex) & effMask) && GetBase()->GetSpellInfo()->IsPositiveEffect(effect->EffectIndex)) { positiveFound = true; break; @@ -212,10 +212,9 @@ void AuraApplication::BuildUpdatePacket(ByteBuffer& data, bool remove) const } if (flags & AFLAG_ANY_EFFECT_AMOUNT_SENT) - for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i) - if (AuraEffect const* eff = aura->GetEffect(i)) - if (HasEffect(i)) // Not all of aura's effects have to be applied on every target - data << int32(eff->GetAmount()); + for (AuraEffect const* effect : GetBase()->GetAuraEffects()) + if (effect && HasEffect(effect->GetEffIndex())) // Not all of aura's effects have to be applied on every target + data << int32(effect->GetAmount()); } void AuraApplication::ClientUpdate(bool remove) @@ -229,26 +228,26 @@ void AuraApplication::ClientUpdate(bool remove) _target->SendMessageToSet(&data, true); } -uint8 Aura::BuildEffectMaskForOwner(SpellInfo const* spellProto, uint8 avalibleEffectMask, WorldObject* owner) +uint32 Aura::BuildEffectMaskForOwner(SpellInfo const* spellProto, uint32 avalibleEffectMask, WorldObject* owner) { ASSERT(spellProto); ASSERT(owner); - uint8 effMask = 0; + uint32 effMask = 0; switch (owner->GetTypeId()) { case TYPEID_UNIT: case TYPEID_PLAYER: - for (uint8 i = 0; i< MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const* effect : spellProto->GetEffectsForDifficulty(owner->GetMap()->GetDifficulty())) { - if (spellProto->Effects[i].IsUnitOwnedAuraEffect()) - effMask |= 1 << i; + if (effect && effect->IsUnitOwnedAuraEffect()) + effMask |= 1 << effect->EffectIndex; } break; case TYPEID_DYNAMICOBJECT: - for (uint8 i = 0; i< MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const* effect : spellProto->GetEffectsForDifficulty(owner->GetMap()->GetDifficulty())) { - if (spellProto->Effects[i].Effect == SPELL_EFFECT_PERSISTENT_AREA_AURA) - effMask |= 1 << i; + if (effect && effect->Effect == SPELL_EFFECT_PERSISTENT_AREA_AURA) + effMask |= 1 << effect->EffectIndex; } break; default: @@ -257,7 +256,7 @@ uint8 Aura::BuildEffectMaskForOwner(SpellInfo const* spellProto, uint8 avalibleE return effMask & avalibleEffectMask; } -Aura* Aura::TryRefreshStackOrCreate(SpellInfo const* spellproto, uint8 tryEffMask, WorldObject* owner, Unit* caster, int32* baseAmount /*= NULL*/, Item* castItem /*= NULL*/, ObjectGuid casterGUID /*= ObjectGuid::Empty*/, bool* refresh /*= NULL*/) +Aura* Aura::TryRefreshStackOrCreate(SpellInfo const* spellproto, uint32 tryEffMask, WorldObject* owner, Unit* caster, int32 *baseAmount /*= NULL*/, Item* castItem /*= NULL*/, ObjectGuid casterGUID /*= ObjectGuid::Empty*/, bool* refresh /*= NULL*/) { ASSERT(spellproto); ASSERT(owner); @@ -283,7 +282,7 @@ Aura* Aura::TryRefreshStackOrCreate(SpellInfo const* spellproto, uint8 tryEffMas return Create(spellproto, effMask, owner, caster, baseAmount, castItem, casterGUID); } -Aura* Aura::TryCreate(SpellInfo const* spellproto, uint8 tryEffMask, WorldObject* owner, Unit* caster, int32* baseAmount /*= NULL*/, Item* castItem /*= NULL*/, ObjectGuid casterGUID /*= ObjectGuid::Empty*/) +Aura* Aura::TryCreate(SpellInfo const* spellproto, uint32 tryEffMask, WorldObject* owner, Unit* caster, int32 *baseAmount /*= NULL*/, Item* castItem /*= NULL*/, ObjectGuid casterGUID /*= ObjectGuid::Empty*/) { ASSERT(spellproto); ASSERT(owner); @@ -295,7 +294,7 @@ Aura* Aura::TryCreate(SpellInfo const* spellproto, uint8 tryEffMask, WorldObject return Create(spellproto, effMask, owner, caster, baseAmount, castItem, casterGUID); } -Aura* Aura::Create(SpellInfo const* spellproto, uint8 effMask, WorldObject* owner, Unit* caster, int32* baseAmount, Item* castItem, ObjectGuid casterGUID) +Aura* Aura::Create(SpellInfo const* spellproto, uint32 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID) { ASSERT(effMask); ASSERT(spellproto); @@ -354,7 +353,6 @@ m_isRemoved(false), m_isSingleTarget(false), m_isUsingCharges(false), m_dropEven m_duration = m_maxDuration; m_procCharges = CalcMaxCharges(caster); m_isUsingCharges = m_procCharges != 0; - memset(m_effects, 0, sizeof(m_effects)); // m_casterLevel = cast item level/caster level, caster level should be saved to db, confirmed with sniffs } @@ -366,15 +364,25 @@ AuraScript* Aura::GetScriptByName(std::string const& scriptName) const return NULL; } -void Aura::_InitEffects(uint8 effMask, Unit* caster, int32 *baseAmount) +SpellEffectInfo const* Aura::GetSpellEffectInfo(uint32 index) const +{ + if (index >= _spelEffectInfos.size()) + return nullptr; + + return _spelEffectInfos[index]; +} + +void Aura::_InitEffects(uint32 effMask, Unit* caster, int32 *baseAmount) { // shouldn't be in constructor - functions in AuraEffect::AuraEffect use polymorphism - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + _spelEffectInfos = m_spellInfo->GetEffectsForDifficulty(GetOwner()->GetMap()->GetDifficulty()); + + ASSERT(!_spelEffectInfos.empty()); + + for (SpellEffectInfo const* effect : GetSpellEffectInfos()) { - if (effMask & (uint8(1) << i)) - m_effects[i] = new AuraEffect(this, i, baseAmount ? baseAmount + i : NULL, caster); - else - m_effects[i] = NULL; + //if (effMask & (uint8(1) << effect->EffectIndex)) + _effects[effect->EffectIndex] = new AuraEffect(this, effect->EffectIndex, baseAmount[effect->EffectIndex], caster); } } @@ -389,9 +397,9 @@ Aura::~Aura() m_loadedScripts.erase(itr); } - // free effects memory - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - delete m_effects[i]; + // free effects memory todo 6.x + //for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + // delete m_effects[i]; ASSERT(m_applications.empty()); _DeleteRemovedApplications(); @@ -407,6 +415,14 @@ Unit* Aura::GetCaster() const return ObjectAccessor::GetUnit(*GetOwner(), GetCasterGUID()); } +AuraEffect* Aura::GetEffect(uint32 index) const +{ + if (index >= _effects.size()) + return nullptr; + + return _effects[index]; +} + AuraObjectType Aura::GetType() const { return (m_owner->GetTypeId() == TYPEID_DYNAMICOBJECT) ? DYNOBJ_AURA_TYPE : UNIT_AURA_TYPE; @@ -674,9 +690,9 @@ void Aura::UpdateOwner(uint32 diff, WorldObject* owner) m_updateTargetMapInterval -= diff; // update aura effects - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - if (m_effects[i]) - m_effects[i]->Update(diff, caster); + for (AuraEffect* effect : GetAuraEffects()) + if (effect) + effect->Update(diff, caster); // remove spellmods after effects update if (modSpell) @@ -880,9 +896,9 @@ void Aura::SetStackAmount(uint8 stackAmount) if (!(*apptItr)->GetRemoveMode()) HandleAuraSpecificMods(*apptItr, caster, false, true); - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - if (HasEffect(i)) - m_effects[i]->ChangeAmount(m_effects[i]->CalculateAmount(caster), false, true); + for (AuraEffect* effect : GetAuraEffects()) + if (effect) + effect->ChangeAmount(effect->CalculateAmount(caster), false, true); for (std::list<AuraApplication*>::const_iterator apptItr = applications.begin(); apptItr != applications.end(); ++apptItr) if (!(*apptItr)->GetRemoveMode()) @@ -945,11 +961,11 @@ void Aura::RefreshSpellMods() player->RestoreAllSpellMods(0, this); } -bool Aura::HasMoreThanOneEffectForType(AuraType auraType) const +bool Aura::HasMoreThanOneEffectForType(AuraType auraType, uint32 difficulty) const { uint32 count = 0; - for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i) - if (HasEffect(i) && AuraType(GetSpellInfo()->Effects[i].ApplyAuraName) == auraType) + for (SpellEffectInfo const* effect : GetSpellEffectInfos()) + if (effect && HasEffect(effect->EffectIndex) && AuraType(effect->ApplyAuraName) == auraType) ++count; return count > 1; @@ -957,8 +973,8 @@ bool Aura::HasMoreThanOneEffectForType(AuraType auraType) const bool Aura::IsArea() const { - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - if (HasEffect(i) && GetSpellInfo()->Effects[i].IsAreaAuraEffect()) + for (SpellEffectInfo const* effect : GetSpellEffectInfos()) + if (effect && HasEffect(effect->EffectIndex) && effect->IsAreaAuraEffect()) return true; return false; @@ -1020,7 +1036,7 @@ bool Aura::CanBeSaved() const bool Aura::CanBeSentToClient() const { - return !IsPassive() || GetSpellInfo()->HasAreaAuraEffect() || HasEffectType(SPELL_AURA_ABILITY_IGNORE_AURASTATE) || HasEffectType(SPELL_AURA_CAST_WHILE_WALKING); + return !IsPassive() || GetSpellInfo()->HasAreaAuraEffect(GetOwner() ? GetOwner()->GetMap()->GetDifficulty() : DIFFICULTY_NONE) || HasEffectType(SPELL_AURA_ABILITY_IGNORE_AURASTATE) || HasEffectType(SPELL_AURA_CAST_WHILE_WALKING); } bool Aura::IsSingleTargetWith(Aura const* aura) const @@ -1080,7 +1096,7 @@ int32 Aura::CalcDispelChance(Unit* auraTarget, bool offensive) const return 100 - resistChance; } -void Aura::SetLoadedState(int32 maxduration, int32 duration, int32 charges, uint8 stackamount, uint8 recalculateMask, int32 * amount) +void Aura::SetLoadedState(int32 maxduration, int32 duration, int32 charges, uint8 stackamount, uint8 recalculateMask, int32 *amount) { m_maxDuration = maxduration; m_duration = duration; @@ -1088,22 +1104,23 @@ void Aura::SetLoadedState(int32 maxduration, int32 duration, int32 charges, uint m_isUsingCharges = m_procCharges != 0; m_stackAmount = stackamount; Unit* caster = GetCaster(); - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - if (m_effects[i]) - { - m_effects[i]->SetAmount(amount[i]); - m_effects[i]->SetCanBeRecalculated((recalculateMask & (1 << i)) != 0); - m_effects[i]->CalculatePeriodic(caster, false, true); - m_effects[i]->CalculateSpellMod(); - m_effects[i]->RecalculateAmount(caster); - } + for (AuraEffect* effect : GetAuraEffects()) + { + if (!effect) + continue; + effect->SetAmount(amount[effect->GetEffIndex()]); + effect->SetCanBeRecalculated((recalculateMask & (1 << effect->GetEffIndex())) != 0); + effect->CalculatePeriodic(caster, false, true); + effect->CalculateSpellMod(); + effect->RecalculateAmount(caster); + } } bool Aura::HasEffectType(AuraType type) const { - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (AuraEffect* effect : GetAuraEffects()) { - if (HasEffect(i) && m_effects[i]->GetAuraType() == type) + if (effect && effect->GetAuraType() == type) return true; } return false; @@ -1113,17 +1130,26 @@ void Aura::RecalculateAmountOfEffects() { ASSERT (!IsRemoved()); Unit* caster = GetCaster(); - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - if (HasEffect(i)) - m_effects[i]->RecalculateAmount(caster); + for (AuraEffect* effect : GetAuraEffects()) + if (effect && !IsRemoved()) + effect->RecalculateAmount(caster); } void Aura::HandleAllEffects(AuraApplication * aurApp, uint8 mode, bool apply) { ASSERT (!IsRemoved()); - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - if (m_effects[i] && !IsRemoved()) - m_effects[i]->HandleEffect(aurApp, mode, apply); + for (AuraEffect* effect : GetAuraEffects()) + if (effect && !IsRemoved()) + effect->HandleEffect(aurApp, mode, apply); +} + +uint32 Aura::GetEffectMask() const +{ + uint32 effMask = 0; + for (AuraEffect* effect : GetAuraEffects()) + if (effect) + effMask |= 1 << effect->GetEffIndex(); + return effMask; } void Aura::GetApplicationList(std::list<AuraApplication*> & applicationList) const @@ -1517,47 +1543,40 @@ void Aura::HandleAuraSpecificPeriodics(AuraApplication const* aurApp, Unit* cast if (!caster || aurApp->GetRemoveMode()) return; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (AuraEffect* effect : GetAuraEffects()) { - if (!HasEffect(i)) - continue; - - if (m_spellInfo->Effects[i].IsAreaAuraEffect() || m_spellInfo->Effects[i].IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA)) + if (!effect || effect->IsAreaAuraEffect() || effect->IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA)) continue; - switch (m_spellInfo->Effects[i].ApplyAuraName) + switch (effect->GetSpellEffectInfo()->ApplyAuraName) { case SPELL_AURA_PERIODIC_DAMAGE: case SPELL_AURA_PERIODIC_DAMAGE_PERCENT: case SPELL_AURA_PERIODIC_LEECH: { - AuraEffect* aurEff = GetEffect(i); - // ignore non positive values (can be result apply spellmods to aura damage - uint32 damage = std::max(aurEff->GetAmount(), 0); + uint32 damage = std::max(effect->GetAmount(), 0); // Script Hook For HandlePeriodicDamageAurasTick -- Allow scripts to change the Damage pre class mitigation calculations sScriptMgr->ModifyPeriodicDamageAurasTick(target, caster, damage); - aurEff->SetDonePct(caster->SpellDamagePctDone(target, m_spellInfo, DOT)); // Calculate done percentage first! - aurEff->SetDamage(caster->SpellDamageBonusDone(target, m_spellInfo, damage, DOT, GetStackAmount()) * aurEff->GetDonePct()); - aurEff->SetCritChance(caster->GetUnitSpellCriticalChance(target, m_spellInfo, m_spellInfo->GetSchoolMask())); + effect->SetDonePct(caster->SpellDamagePctDone(target, m_spellInfo, DOT)); // Calculate done percentage first! + effect->SetDamage(caster->SpellDamageBonusDone(target, m_spellInfo, damage, DOT, GetStackAmount()) * effect->GetDonePct()); + effect->SetCritChance(caster->GetUnitSpellCriticalChance(target, m_spellInfo, m_spellInfo->GetSchoolMask())); break; } case SPELL_AURA_PERIODIC_HEAL: case SPELL_AURA_OBS_MOD_HEALTH: { - AuraEffect* aurEff = GetEffect(i); - // ignore non positive values (can be result apply spellmods to aura damage - uint32 damage = std::max(aurEff->GetAmount(), 0); + uint32 damage = std::max(effect->GetAmount(), 0); // Script Hook For HandlePeriodicDamageAurasTick -- Allow scripts to change the Damage pre class mitigation calculations sScriptMgr->ModifyPeriodicDamageAurasTick(target, caster, damage); - aurEff->SetDonePct(caster->SpellHealingPctDone(target, m_spellInfo)); // Calculate done percentage first! - aurEff->SetDamage(caster->SpellHealingBonusDone(target, m_spellInfo, damage, DOT, GetStackAmount()) * aurEff->GetDonePct()); - aurEff->SetCritChance(caster->GetUnitSpellCriticalChance(target, m_spellInfo, m_spellInfo->GetSchoolMask())); + effect->SetDonePct(caster->SpellHealingPctDone(target, m_spellInfo)); // Calculate done percentage first! + effect->SetDamage(caster->SpellHealingBonusDone(target, m_spellInfo, damage, DOT, GetStackAmount()) * effect->GetDonePct()); + effect->SetCritChance(caster->GetUnitSpellCriticalChance(target, m_spellInfo, m_spellInfo->GetSchoolMask())); break; } default: @@ -1605,12 +1624,17 @@ bool Aura::CanStackWith(Aura const* existingAura) const if (IsPassive() && sameCaster && m_spellInfo->IsDifferentRankOf(existingSpellInfo)) return false; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const* effect : existingAura->GetSpellEffectInfos()) { // prevent remove triggering aura by triggered aura - if (existingSpellInfo->Effects[i].TriggerSpell == GetId() - // prevent remove triggered aura by triggering aura refresh - || m_spellInfo->Effects[i].TriggerSpell == existingAura->GetId()) + if (effect->TriggerSpell == GetId()) + return true; + } + + for (SpellEffectInfo const* effect : GetSpellEffectInfos()) + { + // prevent remove triggered aura by triggering aura refresh + if (effect->TriggerSpell == existingAura->GetId()) return true; } @@ -1620,7 +1644,7 @@ bool Aura::CanStackWith(Aura const* existingAura) const // * The minimap tracking list will only show a check mark next to the last skill activated // Sometimes this bugs out and doesn't switch the check mark. It has no effect on the actual tracking though. // * The minimap dots are yellow for both resources - if (m_spellInfo->HasAura(SPELL_AURA_TRACK_RESOURCES) && existingSpellInfo->HasAura(SPELL_AURA_TRACK_RESOURCES)) + if (m_spellInfo->HasAura(GetOwner()->GetMap()->GetDifficulty(), SPELL_AURA_TRACK_RESOURCES) && existingSpellInfo->HasAura(GetOwner()->GetMap()->GetDifficulty(), SPELL_AURA_TRACK_RESOURCES)) return sWorld->getBoolConfig(CONFIG_ALLOW_TRACK_BOTH_RESOURCES); // check spell specific stack rules @@ -1659,7 +1683,10 @@ bool Aura::CanStackWith(Aura const* existingAura) const // check same periodic auras for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i) { - switch (m_spellInfo->Effects[i].ApplyAuraName) + SpellEffectInfo const* effect = GetSpellEffectInfo(i); + if (!effect) + continue; + switch (effect->ApplyAuraName) { // DOT or HOT from different casters will stack case SPELL_AURA_PERIODIC_DAMAGE: @@ -1673,9 +1700,12 @@ bool Aura::CanStackWith(Aura const* existingAura) const case SPELL_AURA_OBS_MOD_POWER: case SPELL_AURA_OBS_MOD_HEALTH: case SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE: - // periodic auras which target areas are not allowed to stack this way (replenishment for example) - if (m_spellInfo->Effects[i].IsTargetingArea() || existingSpellInfo->Effects[i].IsTargetingArea()) - break; + { + SpellEffectInfo const* existingEffect = GetSpellEffectInfo(i); + // 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; @@ -2246,7 +2276,7 @@ void Aura::CallScriptAfterEffectProcHandlers(AuraEffect const* aurEff, AuraAppli } } -UnitAura::UnitAura(SpellInfo const* spellproto, uint8 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID) +UnitAura::UnitAura(SpellInfo const* spellproto, uint32 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID) : Aura(spellproto, owner, caster, castItem, casterGUID) { m_AuraDRGroup = DIMINISHING_NONE; @@ -2282,29 +2312,29 @@ void UnitAura::Remove(AuraRemoveMode removeMode) void UnitAura::FillTargetMap(std::map<Unit*, uint8> & targets, Unit* caster) { - for (uint8 effIndex = 0; effIndex < MAX_SPELL_EFFECTS; ++effIndex) + for (SpellEffectInfo const* effect : GetSpellEffectInfos()) { - if (!HasEffect(effIndex)) + if (!effect || !HasEffect(effect->EffectIndex)) continue; UnitList targetList; // non-area aura - if (GetSpellInfo()->Effects[effIndex].Effect == SPELL_EFFECT_APPLY_AURA) + if (effect->Effect == SPELL_EFFECT_APPLY_AURA) { targetList.push_back(GetUnitOwner()); } else { - float radius = GetSpellInfo()->Effects[effIndex].CalcRadius(caster); + float radius = effect->CalcRadius(caster); if (!GetUnitOwner()->HasUnitState(UNIT_STATE_ISOLATED)) { - switch (GetSpellInfo()->Effects[effIndex].Effect) + switch (effect->Effect) { case SPELL_EFFECT_APPLY_AREA_AURA_PARTY: case SPELL_EFFECT_APPLY_AREA_AURA_RAID: { targetList.push_back(GetUnitOwner()); - Trinity::AnyGroupedUnitInObjectRangeCheck u_check(GetUnitOwner(), GetUnitOwner(), radius, GetSpellInfo()->Effects[effIndex].Effect == SPELL_EFFECT_APPLY_AREA_AURA_RAID); + Trinity::AnyGroupedUnitInObjectRangeCheck u_check(GetUnitOwner(), GetUnitOwner(), radius, effect->Effect == SPELL_EFFECT_APPLY_AREA_AURA_RAID); Trinity::UnitListSearcher<Trinity::AnyGroupedUnitInObjectRangeCheck> searcher(GetUnitOwner(), targetList, u_check); GetUnitOwner()->VisitNearbyObject(radius, searcher); break; @@ -2342,14 +2372,14 @@ void UnitAura::FillTargetMap(std::map<Unit*, uint8> & targets, Unit* caster) { std::map<Unit*, uint8>::iterator existing = targets.find(*itr); if (existing != targets.end()) - existing->second |= 1<<effIndex; + existing->second |= 1 << effect->EffectIndex; else - targets[*itr] = 1<<effIndex; + targets[*itr] = 1 << effect->EffectIndex; } } } -DynObjAura::DynObjAura(SpellInfo const* spellproto, uint8 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID) +DynObjAura::DynObjAura(SpellInfo const* spellproto, uint32 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID) : Aura(spellproto, owner, caster, castItem, casterGUID) { LoadScripts(); @@ -2379,13 +2409,13 @@ void DynObjAura::FillTargetMap(std::map<Unit*, uint8> & targets, Unit* /*caster* Unit* dynObjOwnerCaster = GetDynobjOwner()->GetCaster(); float radius = GetDynobjOwner()->GetRadius(); - for (uint8 effIndex = 0; effIndex < MAX_SPELL_EFFECTS; ++effIndex) + for (SpellEffectInfo const* effect : GetSpellEffectInfos()) { - if (!HasEffect(effIndex)) + if (!effect || !HasEffect(effect->EffectIndex)) continue; UnitList targetList; - if (GetSpellInfo()->Effects[effIndex].TargetB.GetTarget() == TARGET_DEST_DYNOBJ_ALLY - || GetSpellInfo()->Effects[effIndex].TargetB.GetTarget() == TARGET_UNIT_DEST_AREA_ALLY) + if (effect->TargetB.GetTarget() == TARGET_DEST_DYNOBJ_ALLY + || effect->TargetB.GetTarget() == TARGET_UNIT_DEST_AREA_ALLY) { Trinity::AnyFriendlyUnitInObjectRangeCheck u_check(GetDynobjOwner(), dynObjOwnerCaster, radius); Trinity::UnitListSearcher<Trinity::AnyFriendlyUnitInObjectRangeCheck> searcher(GetDynobjOwner(), targetList, u_check); @@ -2402,9 +2432,9 @@ void DynObjAura::FillTargetMap(std::map<Unit*, uint8> & targets, Unit* /*caster* { std::map<Unit*, uint8>::iterator existing = targets.find(*itr); if (existing != targets.end()) - existing->second |= 1<<effIndex; + existing->second |= 1 << effect->EffectIndex; else - targets[*itr] = 1<<effIndex; + targets[*itr] = 1 << effect->EffectIndex; } } } diff --git a/src/server/game/Spells/Auras/SpellAuras.h b/src/server/game/Spells/Auras/SpellAuras.h index f69d9baafe0..2d40f3aeb8c 100644 --- a/src/server/game/Spells/Auras/SpellAuras.h +++ b/src/server/game/Spells/Auras/SpellAuras.h @@ -41,11 +41,11 @@ class ChargeDropEvent; class AuraApplication { - friend void Unit::_ApplyAura(AuraApplication * aurApp, uint8 effMask); + friend void Unit::_ApplyAura(AuraApplication * aurApp, uint32 effMask); friend void Unit::_UnapplyAura(AuraApplicationMap::iterator &i, AuraRemoveMode removeMode); friend void Unit::_ApplyAuraEffect(Aura* aura, uint8 effIndex); friend void Unit::RemoveAura(AuraApplication * aurApp, AuraRemoveMode mode); - friend AuraApplication * Unit::_CreateAuraApplication(Aura* aura, uint8 effMask); + friend AuraApplication * Unit::_CreateAuraApplication(Aura* aura, uint32 effMask); private: Unit* const _target; Aura* const _base; @@ -55,12 +55,12 @@ class AuraApplication uint8 _effectsToApply; // Used only at spell hit to determine which effect should be applied bool _needClientUpdate:1; - explicit AuraApplication(Unit* target, Unit* caster, Aura* base, uint8 effMask); void _Remove(); private: - void _InitFlags(Unit* caster, uint8 effMask); + void _InitFlags(Unit* caster, uint32 effMask); void _HandleEffect(uint8 effIndex, bool apply); public: + explicit AuraApplication(Unit* target, Unit* caster, Aura* base, uint32 effMask); Unit* GetTarget() const { return _target; } Aura* GetBase() const { return _base; } @@ -84,16 +84,16 @@ class AuraApplication class Aura { - friend Aura* Unit::_TryStackingOrRefreshingExistingAura(SpellInfo const* newAura, uint8 effMask, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID); + friend Aura* Unit::_TryStackingOrRefreshingExistingAura(SpellInfo const* newAura, uint32 effMask, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID); public: typedef std::map<ObjectGuid, AuraApplication*> ApplicationMap; - static uint8 BuildEffectMaskForOwner(SpellInfo const* spellProto, uint8 avalibleEffectMask, WorldObject* owner); - static Aura* TryRefreshStackOrCreate(SpellInfo const* spellproto, uint8 tryEffMask, WorldObject* owner, Unit* caster, int32* baseAmount = NULL, Item* castItem = NULL, ObjectGuid casterGUID = ObjectGuid::Empty, bool* refresh = NULL); - static Aura* TryCreate(SpellInfo const* spellproto, uint8 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount = NULL, Item* castItem = NULL, ObjectGuid casterGUID = ObjectGuid::Empty); - static Aura* Create(SpellInfo const* spellproto, uint8 effMask, WorldObject* owner, Unit* caster, int32* baseAmount, Item* castItem, ObjectGuid casterGUID); + static uint32 BuildEffectMaskForOwner(SpellInfo const* spellProto, uint32 avalibleEffectMask, WorldObject* owner); + static Aura* TryRefreshStackOrCreate(SpellInfo const* spellproto, uint32 tryEffMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem = NULL, ObjectGuid casterGUID = ObjectGuid::Empty, bool* refresh = NULL); + static Aura* TryCreate(SpellInfo const* spellproto, uint32 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem = NULL, ObjectGuid casterGUID = ObjectGuid::Empty); + static Aura* Create(SpellInfo const* spellproto, uint32 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID); explicit Aura(SpellInfo const* spellproto, WorldObject* owner, Unit* caster, Item* castItem, ObjectGuid casterGUID); - void _InitEffects(uint8 effMask, Unit* caster, int32 *baseAmount); + void _InitEffects(uint32 effMask, Unit* caster, int32 *baseAmount); virtual ~Aura(); SpellInfo const* GetSpellInfo() const { return m_spellInfo; } @@ -152,7 +152,7 @@ class Aura uint8 GetCasterLevel() const { return m_casterLevel; } - bool HasMoreThanOneEffectForType(AuraType auraType) const; + bool HasMoreThanOneEffectForType(AuraType auraType, uint32 difficulty) const; bool IsArea() const; bool IsPassive() const; bool IsDeathPersistent() const; @@ -175,13 +175,14 @@ class Aura void UnregisterSingleTarget(); int32 CalcDispelChance(Unit* auraTarget, bool offensive) const; - void SetLoadedState(int32 maxduration, int32 duration, int32 charges, uint8 stackamount, uint8 recalculateMask, int32 * amount); + void SetLoadedState(int32 maxduration, int32 duration, int32 charges, uint8 stackamount, uint8 recalculateMask, int32 *baseAmount); // helpers for aura effects bool HasEffect(uint8 effIndex) const { return GetEffect(effIndex) != NULL; } bool HasEffectType(AuraType type) const; - AuraEffect* GetEffect(uint8 effIndex) const { ASSERT (effIndex < MAX_SPELL_EFFECTS); return m_effects[effIndex]; } - uint8 GetEffectMask() const { uint8 effMask = 0; for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) if (m_effects[i]) effMask |= 1<<i; return effMask; } + //AuraEffect* GetEffect(uint8 effIndex) const { ASSERT (effIndex < MAX_SPELL_EFFECTS); return Effects[effIndex]; } + AuraEffect* GetEffect(uint32 index) const; + uint32 GetEffectMask() const; void RecalculateAmountOfEffects(); void HandleAllEffects(AuraApplication * aurApp, uint8 mode, bool apply); @@ -242,6 +243,12 @@ class Aura AuraScript* GetScriptByName(std::string const& scriptName) const; std::list<AuraScript*> m_loadedScripts; + + AuraEffectVector GetAuraEffects() const { return _effects; } + + SpellEffectInfoVector GetSpellEffectInfos() const { return _spelEffectInfos; } + SpellEffectInfo const* GetSpellEffectInfo(uint32 index) const; + private: void _DeleteRemovedApplications(); protected: @@ -260,7 +267,7 @@ class Aura uint8 m_procCharges; // Aura charges (0 for infinite) uint8 m_stackAmount; // Aura stack amount - AuraEffect* m_effects[3]; + //AuraEffect* m_effects[3]; ApplicationMap m_applications; bool m_isRemoved:1; @@ -271,14 +278,17 @@ class Aura private: Unit::AuraApplicationList m_removedApplications; + + AuraEffectVector _effects; + SpellEffectInfoVector _spelEffectInfos; }; class UnitAura : public Aura { - friend Aura* Aura::Create(SpellInfo const* spellproto, uint8 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID); - protected: - explicit UnitAura(SpellInfo const* spellproto, uint8 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID); + friend Aura* Aura::Create(SpellInfo const* spellproto, uint32 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID); public: + explicit UnitAura(SpellInfo const* spellproto, uint32 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID); + void _ApplyForTarget(Unit* target, Unit* caster, AuraApplication * aurApp) override; void _UnapplyForTarget(Unit* target, Unit* caster, AuraApplication * aurApp) override; @@ -296,10 +306,10 @@ class UnitAura : public Aura class DynObjAura : public Aura { - friend Aura* Aura::Create(SpellInfo const* spellproto, uint8 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID); - protected: - explicit DynObjAura(SpellInfo const* spellproto, uint8 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID); + friend Aura* Aura::Create(SpellInfo const* spellproto, uint32 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID); public: + explicit DynObjAura(SpellInfo const* spellproto, uint32 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID); + void Remove(AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT) override; void FillTargetMap(std::map<Unit*, uint8> & targets, Unit* caster) override; diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 5c247d86fa3..4e3ffd06a64 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -521,7 +521,7 @@ Spell::Spell(Unit* caster, SpellInfo const* info, TriggerCastFlags triggerFlags, m_spellInfo(info), m_caster((info->AttributesEx6 & SPELL_ATTR6_CAST_BY_CHARMER && caster->GetCharmerOrOwner()) ? caster->GetCharmerOrOwner() : caster), m_spellValue(new SpellValue(m_spellInfo)), m_preGeneratedPath(PathGenerator(m_caster)) { - difficultyEffects = info->GetEffectsForDifficulty(caster->GetMap()->GetDifficulty()); + _effects = info->GetEffectsForDifficulty(caster->GetMap()->GetDifficulty()); m_customError = SPELL_CUSTOM_ERROR_NONE; m_skipCheck = skipCheck; @@ -2611,7 +2611,7 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleA { bool refresh = false; m_spellAura = Aura::TryRefreshStackOrCreate(aurSpellInfo, effectMask, unit, - m_originalCaster, (aurSpellInfo == m_spellInfo) ? &m_spellValue->EffectBasePoints[0] : &basePoints[0], m_CastItem, ObjectGuid::Empty, &refresh); + m_originalCaster, (aurSpellInfo == m_spellInfo) ? m_spellValue->EffectBasePoints : basePoints, m_CastItem, ObjectGuid::Empty, &refresh); if (m_spellAura) { // Set aura stack amount to desired value diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h index ee31326808f..612fd18cfda 100644 --- a/src/server/game/Spells/Spell.h +++ b/src/server/game/Spells/Spell.h @@ -192,7 +192,7 @@ class SpellCastTargets struct SpellValue { explicit SpellValue(SpellInfo const* proto); - std::vector<int32> EffectBasePoints; + int32 EffectBasePoints[MAX_SPELL_EFFECTS]; uint32 MaxAffectedTargets; float RadiusMod; uint8 AuraStackAmount; @@ -503,13 +503,13 @@ class Spell void SetSpellValue(SpellValueMod mod, int32 value); - SpellEffectInfoVector GetEffects() const { return difficultyEffects; } + SpellEffectInfoVector GetEffects() const { return _effects; } SpellEffectInfo const* GetEffect(uint32 index) const { - if (index >= difficultyEffects.size()) + if (index >= _effects.size()) return nullptr; - return difficultyEffects[index]; + return _effects[index]; } bool HasEffect(SpellEffectName effect) const; @@ -716,7 +716,7 @@ class Spell Spell(Spell const& right) = delete; Spell& operator=(Spell const& right) = delete; - SpellEffectInfoVector difficultyEffects; + SpellEffectInfoVector _effects; }; namespace Trinity diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index c1e588c7edf..bd577af2b5a 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -284,7 +284,7 @@ void Spell::EffectResurrectNew(SpellEffIndex effIndex) return; uint32 health = damage; - uint32 mana = m_spellInfo->Effects[effIndex].MiscValue; + uint32 mana = GetEffect(effIndex)->MiscValue; ExecuteLogEffectResurrect(effIndex, target); target->SetResurrectRequestData(m_caster, health, mana, 0); SendResurrectRequest(target); @@ -419,23 +419,6 @@ void Spell::EffectSchoolDMG(SpellEffIndex effIndex) } case SPELLFAMILY_PRIEST: { - // Improved Mind Blast (Mind Blast in shadow form bonus) - if (m_caster->GetShapeshiftForm() == FORM_SHADOW && (m_spellInfo->SpellFamilyFlags[0] & 0x00002000)) - { - Unit::AuraEffectList const& ImprMindBlast = m_caster->GetAuraEffectsByType(SPELL_AURA_ADD_FLAT_MODIFIER); - for (Unit::AuraEffectList::const_iterator i = ImprMindBlast.begin(); i != ImprMindBlast.end(); ++i) - { - if ((*i)->GetSpellInfo()->SpellFamilyName == SPELLFAMILY_PRIEST && - ((*i)->GetSpellInfo()->SpellIconID == 95)) - { - int chance = (*i)->GetSpellInfo()->Effects[EFFECT_1].CalcValue(m_caster); - if (roll_chance_i(chance)) - // Mind Trauma - m_caster->CastSpell(unitTarget, 48301, true, nullptr); - break; - } - } - } break; } case SPELLFAMILY_DRUID: @@ -464,31 +447,14 @@ void Spell::EffectSchoolDMG(SpellEffIndex effIndex) if (AuraEffect const* aurEff = unitTarget->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_ROGUE, 0x00010000, 0, 0, m_caster->GetGUID())) { // count consumed deadly poison doses at target - bool needConsume = true; uint32 spellId = aurEff->GetId(); uint32 doses = aurEff->GetBase()->GetStackAmount(); if (doses > combo) doses = combo; - // Master Poisoner - Unit::AuraEffectList const& auraList = player->GetAuraEffectsByType(SPELL_AURA_MOD_AURA_DURATION_BY_DISPEL_NOT_STACK); - for (Unit::AuraEffectList::const_iterator iter = auraList.begin(); iter != auraList.end(); ++iter) - { - if ((*iter)->GetSpellInfo()->SpellFamilyName == SPELLFAMILY_ROGUE && (*iter)->GetSpellInfo()->SpellIconID == 1960) - { - uint32 chance = (*iter)->GetSpellInfo()->Effects[EFFECT_2].CalcValue(m_caster); - - if (chance && roll_chance_i(chance)) - needConsume = false; - - break; - } - } - - if (needConsume) - for (uint32 i = 0; i < doses; ++i) - unitTarget->RemoveAuraFromStack(spellId, m_caster->GetGUID()); + for (uint32 i = 0; i < doses; ++i) + unitTarget->RemoveAuraFromStack(spellId, m_caster->GetGUID()); damage *= doses; damage += int32(player->GetTotalAttackPowerValue(BASE_ATTACK) * 0.09f * combo); @@ -618,10 +584,10 @@ void Spell::EffectTriggerSpell(SpellEffIndex effIndex) && effectHandleMode != SPELL_EFFECT_HANDLE_LAUNCH) return; - uint32 triggered_spell_id = m_spellInfo->Effects[effIndex].TriggerSpell; + uint32 triggered_spell_id = GetEffect(effIndex)->TriggerSpell; /// @todo move those to spell scripts - if (m_spellInfo->Effects[effIndex].Effect == SPELL_EFFECT_TRIGGER_SPELL + if (GetEffect(effIndex)->Effect == SPELL_EFFECT_TRIGGER_SPELL && effectHandleMode == SPELL_EFFECT_HANDLE_LAUNCH_TARGET) { // special cases @@ -718,13 +684,13 @@ void Spell::EffectTriggerSpell(SpellEffIndex effIndex) SpellCastTargets targets; if (effectHandleMode == SPELL_EFFECT_HANDLE_LAUNCH_TARGET) { - if (!spellInfo->NeedsToBeTriggeredByCaster(m_spellInfo)) + if (!spellInfo->NeedsToBeTriggeredByCaster(m_spellInfo, m_caster->GetMap()->GetDifficulty())) return; targets.SetUnitTarget(unitTarget); } else //if (effectHandleMode == SPELL_EFFECT_HANDLE_LAUNCH) { - if (spellInfo->NeedsToBeTriggeredByCaster(m_spellInfo) && (m_spellInfo->Effects[effIndex].GetProvidedTargetMask() & TARGET_FLAG_UNIT_MASK)) + if (spellInfo->NeedsToBeTriggeredByCaster(m_spellInfo, m_caster->GetMap()->GetDifficulty()) && (GetEffect(effIndex)->GetProvidedTargetMask() & TARGET_FLAG_UNIT_MASK)) return; if (spellInfo->GetExplicitTargetMask() & TARGET_FLAG_DEST_LOCATION) @@ -738,7 +704,7 @@ void Spell::EffectTriggerSpell(SpellEffIndex effIndex) CustomSpellValues values; // set basepoints for trigger with value effect - if (m_spellInfo->Effects[effIndex].Effect == SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE) + if (GetEffect(effIndex)->Effect == SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE) { values.AddSpellMod(SPELLVALUE_BASE_POINT0, damage); values.AddSpellMod(SPELLVALUE_BASE_POINT1, damage); @@ -760,7 +726,7 @@ void Spell::EffectTriggerMissileSpell(SpellEffIndex effIndex) && effectHandleMode != SPELL_EFFECT_HANDLE_HIT) return; - uint32 triggered_spell_id = m_spellInfo->Effects[effIndex].TriggerSpell; + uint32 triggered_spell_id = GetEffect(effIndex)->TriggerSpell; // normal case SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(triggered_spell_id); @@ -773,13 +739,13 @@ void Spell::EffectTriggerMissileSpell(SpellEffIndex effIndex) SpellCastTargets targets; if (effectHandleMode == SPELL_EFFECT_HANDLE_HIT_TARGET) { - if (!spellInfo->NeedsToBeTriggeredByCaster(m_spellInfo)) + if (!spellInfo->NeedsToBeTriggeredByCaster(m_spellInfo, m_caster->GetMap()->GetDifficulty())) return; targets.SetUnitTarget(unitTarget); } else //if (effectHandleMode == SPELL_EFFECT_HANDLE_HIT) { - if (spellInfo->NeedsToBeTriggeredByCaster(m_spellInfo) && (m_spellInfo->Effects[effIndex].GetProvidedTargetMask() & TARGET_FLAG_UNIT_MASK)) + if (spellInfo->NeedsToBeTriggeredByCaster(m_spellInfo, m_caster->GetMap()->GetDifficulty()) && (GetEffect(effIndex)->GetProvidedTargetMask() & TARGET_FLAG_UNIT_MASK)) return; if (spellInfo->GetExplicitTargetMask() & TARGET_FLAG_DEST_LOCATION) @@ -790,7 +756,7 @@ void Spell::EffectTriggerMissileSpell(SpellEffIndex effIndex) CustomSpellValues values; // set basepoints for trigger with value effect - if (m_spellInfo->Effects[effIndex].Effect == SPELL_EFFECT_TRIGGER_MISSILE_SPELL_WITH_VALUE) + if (GetEffect(effIndex)->Effect == SPELL_EFFECT_TRIGGER_MISSILE_SPELL_WITH_VALUE) { // maybe need to set value only when basepoints == 0? values.AddSpellMod(SPELLVALUE_BASE_POINT0, damage); @@ -815,7 +781,7 @@ void Spell::EffectForceCast(SpellEffIndex effIndex) if (!unitTarget) return; - uint32 triggered_spell_id = m_spellInfo->Effects[effIndex].TriggerSpell; + uint32 triggered_spell_id = GetEffect(effIndex)->TriggerSpell; // normal case SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(triggered_spell_id); @@ -826,7 +792,7 @@ void Spell::EffectForceCast(SpellEffIndex effIndex) return; } - if (m_spellInfo->Effects[effIndex].Effect == SPELL_EFFECT_FORCE_CAST && damage) + if (GetEffect(effIndex)->Effect == SPELL_EFFECT_FORCE_CAST && damage) { switch (m_spellInfo->Id) { @@ -850,7 +816,7 @@ void Spell::EffectForceCast(SpellEffIndex effIndex) CustomSpellValues values; // set basepoints for trigger with value effect - if (m_spellInfo->Effects[effIndex].Effect == SPELL_EFFECT_FORCE_CAST_WITH_VALUE) + if (GetEffect(effIndex)->Effect == SPELL_EFFECT_FORCE_CAST_WITH_VALUE) { // maybe need to set value only when basepoints == 0? values.AddSpellMod(SPELLVALUE_BASE_POINT0, damage); @@ -869,7 +835,7 @@ void Spell::EffectTriggerRitualOfSummoning(SpellEffIndex effIndex) if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT) return; - uint32 triggered_spell_id = m_spellInfo->Effects[effIndex].TriggerSpell; + uint32 triggered_spell_id = GetEffect(effIndex)->TriggerSpell; SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(triggered_spell_id); if (!spellInfo) @@ -924,12 +890,16 @@ void Spell::EffectJumpDest(SpellEffIndex effIndex) void Spell::CalculateJumpSpeeds(uint8 i, float dist, float & speedXY, float & speedZ) { - if (m_spellInfo->Effects[i].MiscValue) - speedZ = float(m_spellInfo->Effects[i].MiscValue)/10; - else if (m_spellInfo->Effects[i].MiscValueB) - speedZ = float(m_spellInfo->Effects[i].MiscValueB)/10; - else - speedZ = 10.0f; + SpellEffectInfo const* effect = GetEffect(i); + if (effect) + { + if (effect->MiscValue) + speedZ = float(effect->MiscValue) / 10; + else if (effect->MiscValueB) + speedZ = float(effect->MiscValueB) / 10; + else + speedZ = 10.0f; + } speedXY = dist * 10.0f / speedZ; } @@ -1096,7 +1066,7 @@ void Spell::EffectUnlearnSpecialization(SpellEffIndex effIndex) return; Player* player = unitTarget->ToPlayer(); - uint32 spellToUnlearn = m_spellInfo->Effects[effIndex].TriggerSpell; + uint32 spellToUnlearn = GetEffect(effIndex)->TriggerSpell; player->RemoveSpell(spellToUnlearn); @@ -1108,10 +1078,10 @@ void Spell::EffectPowerDrain(SpellEffIndex effIndex) if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET) return; - if (m_spellInfo->Effects[effIndex].MiscValue < 0 || m_spellInfo->Effects[effIndex].MiscValue >= int8(MAX_POWERS)) + if (GetEffect(effIndex)->MiscValue < 0 || GetEffect(effIndex)->MiscValue >= int8(MAX_POWERS)) return; - Powers powerType = Powers(m_spellInfo->Effects[effIndex].MiscValue); + Powers powerType = Powers(GetEffect(effIndex)->MiscValue); if (!unitTarget || !unitTarget->IsAlive() || unitTarget->getPowerType() != powerType || damage < 0) return; @@ -1127,7 +1097,7 @@ void Spell::EffectPowerDrain(SpellEffIndex effIndex) // Don't restore from self drain if (m_caster != unitTarget) { - gainMultiplier = m_spellInfo->Effects[effIndex].CalcValueMultiplier(m_originalCaster, this); + gainMultiplier = GetEffect(effIndex)->CalcValueMultiplier(m_originalCaster, this); int32 gain = int32(newDamage* gainMultiplier); @@ -1159,7 +1129,7 @@ void Spell::EffectSendEvent(SpellEffIndex effIndex) // this check was requested by scripters, but it has some downsides: // now it's impossible to script (using sEventScripts) a cast which misses all targets // or to have an ability to script the moment spell hits dest (in a case when there are object targets present) - if (m_spellInfo->Effects[effIndex].GetProvidedTargetMask() & (TARGET_FLAG_UNIT_MASK | TARGET_FLAG_GAMEOBJECT_MASK)) + if (GetEffect(effIndex)->GetProvidedTargetMask() & (TARGET_FLAG_UNIT_MASK | TARGET_FLAG_GAMEOBJECT_MASK)) return; // some spells have no target entries in dbc and they use focus target if (focusObject) @@ -1167,14 +1137,14 @@ void Spell::EffectSendEvent(SpellEffIndex effIndex) /// @todo there should be a possibility to pass dest target to event script } - TC_LOG_DEBUG("spells", "Spell ScriptStart %u for spellid %u in EffectSendEvent ", m_spellInfo->Effects[effIndex].MiscValue, m_spellInfo->Id); + TC_LOG_DEBUG("spells", "Spell ScriptStart %u for spellid %u in EffectSendEvent ", GetEffect(effIndex)->MiscValue, m_spellInfo->Id); if (ZoneScript* zoneScript = m_caster->GetZoneScript()) - zoneScript->ProcessEvent(target, m_spellInfo->Effects[effIndex].MiscValue); + zoneScript->ProcessEvent(target, GetEffect(effIndex)->MiscValue); else if (InstanceScript* instanceScript = m_caster->GetInstanceScript()) // needed in case Player is the caster - instanceScript->ProcessEvent(target, m_spellInfo->Effects[effIndex].MiscValue); + instanceScript->ProcessEvent(target, GetEffect(effIndex)->MiscValue); - m_caster->GetMap()->ScriptsStart(sEventScripts, m_spellInfo->Effects[effIndex].MiscValue, m_caster, target); + m_caster->GetMap()->ScriptsStart(sEventScripts, GetEffect(effIndex)->MiscValue, m_caster, target); } void Spell::EffectPowerBurn(SpellEffIndex effIndex) @@ -1182,10 +1152,10 @@ void Spell::EffectPowerBurn(SpellEffIndex effIndex) if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET) return; - if (m_spellInfo->Effects[effIndex].MiscValue < 0 || m_spellInfo->Effects[effIndex].MiscValue >= int8(MAX_POWERS)) + if (GetEffect(effIndex)->MiscValue < 0 || GetEffect(effIndex)->MiscValue >= int8(MAX_POWERS)) return; - Powers powerType = Powers(m_spellInfo->Effects[effIndex].MiscValue); + Powers powerType = Powers(GetEffect(effIndex)->MiscValue); if (!unitTarget || !unitTarget->IsAlive() || unitTarget->getPowerType() != powerType || damage < 0) return; @@ -1201,7 +1171,7 @@ void Spell::EffectPowerBurn(SpellEffIndex effIndex) int32 newDamage = -(unitTarget->ModifyPower(powerType, -damage)); // NO - Not a typo - EffectPowerBurn uses effect value multiplier - not effect damage multiplier - float dmgMultiplier = m_spellInfo->Effects[effIndex].CalcValueMultiplier(m_originalCaster, this); + float dmgMultiplier = GetEffect(effIndex)->CalcValueMultiplier(m_originalCaster, this); // add log data before multiplication (need power amount, not damage) ExecuteLogEffectTakeTargetPower(effIndex, unitTarget, powerType, newDamage, 0.0f); @@ -1356,7 +1326,7 @@ void Spell::EffectHealthLeech(SpellEffIndex effIndex) TC_LOG_DEBUG("spells", "HealthLeech :%i", damage); - float healMultiplier = m_spellInfo->Effects[effIndex].CalcValueMultiplier(m_originalCaster, this); + float healMultiplier = GetEffect(effIndex)->CalcValueMultiplier(m_originalCaster, this); m_damage += damage; // get max possible damage, don't count overkill for heal @@ -1491,8 +1461,8 @@ void Spell::EffectCreateItem(SpellEffIndex effIndex) if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET) return; - DoCreateItem(effIndex, m_spellInfo->Effects[effIndex].ItemType); - ExecuteLogEffectCreateItem(effIndex, m_spellInfo->Effects[effIndex].ItemType); + DoCreateItem(effIndex, GetEffect(effIndex)->ItemType); + ExecuteLogEffectCreateItem(effIndex, GetEffect(effIndex)->ItemType); } void Spell::EffectCreateItem2(SpellEffIndex effIndex) @@ -1505,7 +1475,7 @@ void Spell::EffectCreateItem2(SpellEffIndex effIndex) Player* player = unitTarget->ToPlayer(); - uint32 item_id = m_spellInfo->Effects[effIndex].ItemType; + uint32 item_id = GetEffect(effIndex)->ItemType; if (item_id) DoCreateItem(effIndex, item_id); @@ -1553,7 +1523,7 @@ void Spell::EffectPersistentAA(SpellEffIndex effIndex) if (!m_spellAura) { Unit* caster = m_caster->GetEntry() == WORLD_TRIGGER ? m_originalCaster : m_caster; - float radius = m_spellInfo->Effects[effIndex].CalcRadius(caster); + float radius = GetEffect(effIndex)->CalcRadius(caster); // Caster not in world, might be spell triggered from aura removal if (!caster->IsInWorld()) @@ -1588,10 +1558,10 @@ void Spell::EffectEnergize(SpellEffIndex effIndex) if (!unitTarget->IsAlive()) return; - if (m_spellInfo->Effects[effIndex].MiscValue < 0 || m_spellInfo->Effects[effIndex].MiscValue >= int8(MAX_POWERS)) + if (GetEffect(effIndex)->MiscValue < 0 || GetEffect(effIndex)->MiscValue >= int8(MAX_POWERS)) return; - Powers power = Powers(m_spellInfo->Effects[effIndex].MiscValue); + Powers power = Powers(GetEffect(effIndex)->MiscValue); if (unitTarget->GetTypeId() == TYPEID_PLAYER && unitTarget->getPowerType() != power && !(m_spellInfo->AttributesEx7 & SPELL_ATTR7_CAN_RESTORE_SECONDARY_POWER)) return; @@ -1697,10 +1667,10 @@ void Spell::EffectEnergizePct(SpellEffIndex effIndex) if (!unitTarget->IsAlive()) return; - if (m_spellInfo->Effects[effIndex].MiscValue < 0 || m_spellInfo->Effects[effIndex].MiscValue >= int8(MAX_POWERS)) + if (GetEffect(effIndex)->MiscValue < 0 || GetEffect(effIndex)->MiscValue >= int8(MAX_POWERS)) return; - Powers power = Powers(m_spellInfo->Effects[effIndex].MiscValue); + Powers power = Powers(GetEffect(effIndex)->MiscValue); if (unitTarget->GetTypeId() == TYPEID_PLAYER && unitTarget->getPowerType() != power && !(m_spellInfo->AttributesEx7 & SPELL_ATTR7_CAN_RESTORE_SECONDARY_POWER)) return; @@ -1905,7 +1875,7 @@ void Spell::EffectSummonChangeItem(SpellEffIndex effIndex) if (m_CastItem->GetOwnerGUID() != player->GetGUID()) return; - uint32 newitemid = m_spellInfo->Effects[effIndex].ItemType; + uint32 newitemid = GetEffect(effIndex)->ItemType; if (!newitemid) return; @@ -2022,14 +1992,14 @@ void Spell::EffectSummonType(SpellEffIndex effIndex) if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT) return; - uint32 entry = m_spellInfo->Effects[effIndex].MiscValue; + uint32 entry = GetEffect(effIndex)->MiscValue; if (!entry) return; - SummonPropertiesEntry const* properties = sSummonPropertiesStore.LookupEntry(m_spellInfo->Effects[effIndex].MiscValueB); + SummonPropertiesEntry const* properties = sSummonPropertiesStore.LookupEntry(GetEffect(effIndex)->MiscValueB); if (!properties) { - TC_LOG_ERROR("spells", "EffectSummonType: Unhandled summon type %u", m_spellInfo->Effects[effIndex].MiscValueB); + TC_LOG_ERROR("spells", "EffectSummonType: Unhandled summon type %u", GetEffect(effIndex)->MiscValueB); return; } @@ -2130,7 +2100,7 @@ void Spell::EffectSummonType(SpellEffIndex effIndex) } default: { - float radius = m_spellInfo->Effects[effIndex].CalcRadius(); + float radius = GetEffect(effIndex)->CalcRadius(); TempSummonType summonType = (duration == 0) ? TEMPSUMMON_DEAD_DESPAWN : TEMPSUMMON_TIMED_DESPAWN; @@ -2175,8 +2145,8 @@ void Spell::EffectSummonType(SpellEffIndex effIndex) // The spell that this effect will trigger. It has SPELL_AURA_CONTROL_VEHICLE uint32 spellId = VEHICLE_SPELL_RIDE_HARDCODED; - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(m_spellInfo->Effects[effIndex].CalcValue()); - if (spellInfo && spellInfo->HasAura(SPELL_AURA_CONTROL_VEHICLE)) + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(GetEffect(effIndex)->CalcValue()); + if (spellInfo && spellInfo->HasAura(m_originalCaster->GetMap()->GetDifficulty(), SPELL_AURA_CONTROL_VEHICLE)) spellId = spellInfo->Id; // Hard coded enter vehicle spell @@ -2214,7 +2184,7 @@ void Spell::EffectLearnSpell(SpellEffIndex effIndex) Player* player = unitTarget->ToPlayer(); - uint32 spellToLearn = (m_spellInfo->Id == 483 || m_spellInfo->Id == 55884) ? damage : m_spellInfo->Effects[effIndex].TriggerSpell; + uint32 spellToLearn = (m_spellInfo->Id == 483 || m_spellInfo->Id == 55884) ? damage : GetEffect(effIndex)->TriggerSpell; player->LearnSpell(spellToLearn, false); TC_LOG_DEBUG("spells", "Spell: %s has learned spell %u from %s", player->GetGUID().ToString().c_str(), spellToLearn, m_caster->GetGUID().ToString().c_str()); @@ -2229,7 +2199,7 @@ void Spell::EffectDispel(SpellEffIndex effIndex) return; // Create dispel mask by dispel type - uint32 dispel_type = m_spellInfo->Effects[effIndex].MiscValue; + uint32 dispel_type = GetEffect(effIndex)->MiscValue; uint32 dispelMask = SpellInfo::GetDispelMask(DispelType(dispel_type)); DispelChargesList dispel_list; @@ -2316,12 +2286,15 @@ void Spell::EffectDispel(SpellEffIndex effIndex) // Devour Magic if (m_spellInfo->SpellFamilyName == SPELLFAMILY_WARLOCK && m_spellInfo->GetCategory() == SPELLCATEGORY_DEVOUR_MAGIC) { - int32 heal_amount = m_spellInfo->Effects[EFFECT_1].CalcValue(m_caster); - m_caster->CastCustomSpell(m_caster, 19658, &heal_amount, NULL, NULL, true); - // Glyph of Felhunter - if (Unit* owner = m_caster->GetOwner()) + if (SpellEffectInfo const* effect = GetEffect(EFFECT_1)) + { + int32 heal_amount = effect->CalcValue(m_caster); + m_caster->CastCustomSpell(m_caster, 19658, &heal_amount, NULL, NULL, true); + // Glyph of Felhunter + if (Unit* owner = m_caster->GetOwner()) if (owner->GetAura(56249)) owner->CastCustomSpell(owner, 19658, &heal_amount, NULL, NULL, true); + } } } @@ -2384,7 +2357,7 @@ void Spell::EffectAddFarsight(SpellEffIndex effIndex) if (m_caster->GetTypeId() != TYPEID_PLAYER) return; - float radius = m_spellInfo->Effects[effIndex].CalcRadius(); + float radius = GetEffect(effIndex)->CalcRadius(); int32 duration = m_spellInfo->GetDuration(); // Caster not in world, might be spell triggered from aura removal if (!m_caster->IsInWorld()) @@ -2423,7 +2396,7 @@ void Spell::EffectTeleUnitsFaceCaster(SpellEffIndex effIndex) if (unitTarget->IsInFlight()) return; - float dis = m_spellInfo->Effects[effIndex].CalcRadius(m_caster); + float dis = GetEffect(effIndex)->CalcRadius(m_caster); float fx, fy, fz; m_caster->GetClosePoint(fx, fy, fz, unitTarget->GetObjectSize(), dis); @@ -2442,7 +2415,7 @@ void Spell::EffectLearnSkill(SpellEffIndex effIndex) if (damage < 0) return; - uint32 skillid = m_spellInfo->Effects[effIndex].MiscValue; + uint32 skillid = GetEffect(effIndex)->MiscValue; SkillRaceClassInfoEntry const* rcEntry = GetSkillRaceClassInfo(skillid, unitTarget->getRace(), unitTarget->getClass()); if (!rcEntry) return; @@ -2452,7 +2425,7 @@ void Spell::EffectLearnSkill(SpellEffIndex effIndex) return; uint16 skillval = unitTarget->ToPlayer()->GetPureSkillValue(skillid); - unitTarget->ToPlayer()->SetSkill(skillid, m_spellInfo->Effects[effIndex].CalcValue(), std::max<uint16>(skillval, 1), tier->Value[damage - 1]); + unitTarget->ToPlayer()->SetSkill(skillid, GetEffect(effIndex)->CalcValue(), std::max<uint16>(skillval, 1), tier->Value[damage - 1]); } void Spell::EffectPlayMovie(SpellEffIndex effIndex) @@ -2462,12 +2435,14 @@ void Spell::EffectPlayMovie(SpellEffIndex effIndex) if (unitTarget->GetTypeId() != TYPEID_PLAYER) return; + if (SpellEffectInfo const* effect = GetEffect(effIndex)) + { + uint32 movieId = effect->MiscValue; + if (!sMovieStore.LookupEntry(movieId)) + return; - uint32 movieId = GetSpellInfo()->Effects[effIndex].MiscValue; - if (!sMovieStore.LookupEntry(movieId)) - return; - - unitTarget->ToPlayer()->SendMovieStart(movieId); + unitTarget->ToPlayer()->SendMovieStart(movieId); + } } void Spell::EffectTradeSkill(SpellEffIndex /*effIndex*/) @@ -2502,7 +2477,7 @@ void Spell::EffectEnchantItemPerm(SpellEffIndex effIndex) player->DestroyItemCount(itemTarget, count, true); unitTarget = player; // and add a scroll - DoCreateItem(effIndex, m_spellInfo->Effects[effIndex].ItemType); + DoCreateItem(effIndex, GetEffect(effIndex)->ItemType); itemTarget = NULL; m_targets.SetItemTarget(NULL); } @@ -2512,7 +2487,7 @@ void Spell::EffectEnchantItemPerm(SpellEffIndex effIndex) if (!(m_CastItem && m_CastItem->GetTemplate()->Flags[0] & ITEM_PROTO_FLAG_TRIGGERED_CAST)) player->UpdateCraftSkill(m_spellInfo->Id); - uint32 enchant_id = m_spellInfo->Effects[effIndex].MiscValue; + uint32 enchant_id = GetEffect(effIndex)->MiscValue; if (!enchant_id) return; @@ -2558,7 +2533,7 @@ void Spell::EffectEnchantItemPrismatic(SpellEffIndex effIndex) if (!player) return; - uint32 enchantId = m_spellInfo->Effects[effIndex].MiscValue; + uint32 enchantId = GetEffect(effIndex)->MiscValue; if (!enchantId) return; @@ -2622,7 +2597,7 @@ void Spell::EffectEnchantItemTmp(SpellEffIndex effIndex) if (!itemTarget) return; - uint32 enchant_id = m_spellInfo->Effects[effIndex].MiscValue; + uint32 enchant_id = GetEffect(effIndex)->MiscValue; if (!enchant_id) { @@ -2757,7 +2732,7 @@ void Spell::EffectSummonPet(SpellEffIndex effIndex) owner = m_originalCaster->GetCharmerOrOwnerPlayerOrPlayerItself(); } - uint32 petentry = m_spellInfo->Effects[effIndex].MiscValue; + uint32 petentry = GetEffect(effIndex)->MiscValue; if (!owner) { @@ -2843,7 +2818,7 @@ void Spell::EffectLearnPetSpell(SpellEffIndex effIndex) if (!pet) return; - SpellInfo const* learn_spellproto = sSpellMgr->GetSpellInfo(m_spellInfo->Effects[effIndex].TriggerSpell); + SpellInfo const* learn_spellproto = sSpellMgr->GetSpellInfo(GetEffect(effIndex)->TriggerSpell); if (!learn_spellproto) return; @@ -2898,9 +2873,11 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex) // multiple weapon dmg effect workaround // execute only the last weapon damage // and handle all effects at once - for (uint32 j = effIndex + 1; j < MAX_SPELL_EFFECTS; ++j) + for (SpellEffectInfo const* effect : GetEffects()) { - switch (m_spellInfo->Effects[j].Effect) + if (!effect) + continue; + switch (effect->Effect) { case SPELL_EFFECT_WEAPON_DAMAGE: case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL: @@ -2988,48 +2965,14 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex) // Blood Strike if (m_spellInfo->SpellFamilyFlags[0] & 0x400000) { - float bonusPct = m_spellInfo->Effects[EFFECT_2].CalcValue(m_caster) * unitTarget->GetDiseasesByCaster(m_caster->GetGUID()) / 2.0f; - // Death Knight T8 Melee 4P Bonus - if (AuraEffect const* aurEff = m_caster->GetAuraEffect(64736, EFFECT_0)) - AddPct(bonusPct, aurEff->GetAmount()); - AddPct(totalDamagePercentMod, bonusPct); - break; - } - // Death Strike - if (m_spellInfo->SpellFamilyFlags[0] & 0x10) - { - // Glyph of Death Strike - // 2% more damage per 5 runic power, up to a maximum of 40% - if (AuraEffect const* aurEff = m_caster->GetAuraEffect(59336, EFFECT_0)) - if (uint32 runic = std::min<uint32>(uint32(m_caster->GetPower(POWER_RUNIC_POWER) / 2.5f), aurEff->GetSpellInfo()->Effects[EFFECT_1].CalcValue(m_caster))) - AddPct(totalDamagePercentMod, runic); - break; - } - // Obliterate (12.5% more damage per disease) - if (m_spellInfo->SpellFamilyFlags[1] & 0x20000) - { - float bonusPct = m_spellInfo->Effects[EFFECT_2].CalcValue(m_caster) * unitTarget->GetDiseasesByCaster(m_caster->GetGUID(), false) / 2.0f; - // Death Knight T8 Melee 4P Bonus - if (AuraEffect const* aurEff = m_caster->GetAuraEffect(64736, EFFECT_0)) - AddPct(bonusPct, aurEff->GetAmount()); - AddPct(totalDamagePercentMod, bonusPct); - break; - } - // Blood-Caked Strike - Blood-Caked Blade - if (m_spellInfo->SpellIconID == 1736) - { - AddPct(totalDamagePercentMod, unitTarget->GetDiseasesByCaster(m_caster->GetGUID()) * 50.0f); - break; - } - // Heart Strike - if (m_spellInfo->SpellFamilyFlags[0] & 0x1000000) - { - float bonusPct = m_spellInfo->Effects[EFFECT_2].CalcValue(m_caster) * unitTarget->GetDiseasesByCaster(m_caster->GetGUID()); - // Death Knight T8 Melee 4P Bonus - if (AuraEffect const* aurEff = m_caster->GetAuraEffect(64736, EFFECT_0)) - AddPct(bonusPct, aurEff->GetAmount()); - - AddPct(totalDamagePercentMod, bonusPct); + if (SpellEffectInfo const* effect = GetEffect(EFFECT_2)) + { + float bonusPct = effect->CalcValue(m_caster) * unitTarget->GetDiseasesByCaster(m_caster->GetGUID()) / 2.0f; + // Death Knight T8 Melee 4P Bonus + if (AuraEffect const* aurEff = m_caster->GetAuraEffect(64736, EFFECT_0)) + AddPct(bonusPct, aurEff->GetAmount()); + AddPct(totalDamagePercentMod, bonusPct); + } break; } break; @@ -3038,20 +2981,22 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex) bool normalized = false; float weaponDamagePercentMod = 1.0f; - for (int j = 0; j < MAX_SPELL_EFFECTS; ++j) + for (SpellEffectInfo const* effect : GetEffects()) { - switch (m_spellInfo->Effects[j].Effect) + if (!effect) + continue; + switch (effect->Effect) { case SPELL_EFFECT_WEAPON_DAMAGE: case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL: - fixed_bonus += CalculateDamage(j, unitTarget); + fixed_bonus += CalculateDamage(effect->EffectIndex, unitTarget); break; case SPELL_EFFECT_NORMALIZED_WEAPON_DMG: - fixed_bonus += CalculateDamage(j, unitTarget); + fixed_bonus += CalculateDamage(effect->EffectIndex, unitTarget); normalized = true; break; case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE: - ApplyPct(weaponDamagePercentMod, CalculateDamage(j, unitTarget)); + ApplyPct(weaponDamagePercentMod, CalculateDamage(effect->EffectIndex, unitTarget)); break; default: break; // not weapon damage effect, just skip @@ -3083,11 +3028,13 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex) int32 weaponDamage = m_caster->CalculateDamage(m_attackType, normalized, true); // Sequence is important - for (int j = 0; j < MAX_SPELL_EFFECTS; ++j) + for (SpellEffectInfo const* effect : GetEffects()) { + if (!effect) + continue; // We assume that a spell have at most one fixed_bonus // and at most one weaponDamagePercentMod - switch (m_spellInfo->Effects[j].Effect) + switch (effect->Effect) { case SPELL_EFFECT_WEAPON_DAMAGE: case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL: @@ -3189,7 +3136,7 @@ void Spell::EffectSummonObjectWild(SpellEffIndex effIndex) if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT) return; - uint32 gameobject_id = m_spellInfo->Effects[effIndex].MiscValue; + uint32 gameobject_id = GetEffect(effIndex)->MiscValue; GameObject* pGameObj = new GameObject; @@ -3321,7 +3268,7 @@ void Spell::EffectScriptEffect(SpellEffIndex effIndex) case 55693: // Remove Collapsing Cave Aura if (!unitTarget) return; - unitTarget->RemoveAurasDueToSpell(m_spellInfo->Effects[effIndex].CalcValue()); + unitTarget->RemoveAurasDueToSpell(GetEffect(effIndex)->CalcValue()); break; // Bending Shinbone case 8856: @@ -3455,7 +3402,7 @@ void Spell::EffectScriptEffect(SpellEffIndex effIndex) case 45151: { //Workaround for Range ... should be global for every ScriptEffect - float radius = m_spellInfo->Effects[effIndex].CalcRadius(); + float radius = GetEffect(effIndex)->CalcRadius(); if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER && unitTarget->GetDistance(m_caster) >= radius && !unitTarget->HasAura(46394) && unitTarget != m_caster) unitTarget->CastSpell(unitTarget, 46394, true); @@ -3567,7 +3514,7 @@ void Spell::EffectScriptEffect(SpellEffIndex effIndex) return; float x, y, z; - float radius = m_spellInfo->Effects[effIndex].CalcRadius(); + float radius = GetEffect(effIndex)->CalcRadius(); for (uint8 i = 0; i < 15; ++i) { m_caster->GetRandomPoint(*destTarget, radius, x, y, z); @@ -3613,8 +3560,9 @@ void Spell::EffectScriptEffect(SpellEffIndex effIndex) if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER || effIndex != 0) return; - uint32 spellID = m_spellInfo->Effects[EFFECT_0].CalcValue(); - uint32 questID = m_spellInfo->Effects[EFFECT_1].CalcValue(); + // Effects for 58418 and 58420 are all DIFFICULTY_NONE so always valid + uint32 spellID = GetEffect(EFFECT_0)->CalcValue(); + uint32 questID = GetEffect(EFFECT_1)->CalcValue(); if (unitTarget->ToPlayer()->GetQuestStatus(questID) == QUEST_STATUS_COMPLETE) unitTarget->CastSpell(unitTarget, spellID, true); @@ -3664,7 +3612,7 @@ void Spell::EffectScriptEffect(SpellEffIndex effIndex) { /// @todo a hack, range = 11, should after some time cast, otherwise too far m_caster->CastSpell(parent, 62496, true); - unitTarget->CastSpell(parent, m_spellInfo->Effects[EFFECT_0].CalcValue()); + unitTarget->CastSpell(parent, GetEffect(EFFECT_0)->CalcValue()); // DIFFICULTY_NONE, so effect always valid } } } @@ -3856,7 +3804,7 @@ void Spell::EffectDuel(SpellEffIndex effIndex) //CREATE DUEL FLAG OBJECT GameObject* pGameObj = new GameObject; - uint32 gameobject_id = m_spellInfo->Effects[effIndex].MiscValue; + uint32 gameobject_id = GetEffect(effIndex)->MiscValue; Map* map = m_caster->GetMap(); if (!pGameObj->Create(sObjectMgr->GetGenerator<HighGuid::GameObject>()->Generate(), gameobject_id, @@ -3981,7 +3929,7 @@ void Spell::EffectActivateObject(SpellEffIndex /*effIndex*/) ScriptInfo activateCommand; activateCommand.command = SCRIPT_COMMAND_ACTIVATE_OBJECT; - // int32 unk = m_spellInfo->Effects[effIndex].MiscValue; // This is set for EffectActivateObject spells; needs research + // int32 unk = GetEffect(effIndex)->MiscValue; // This is set for EffectActivateObject spells; needs research gameObjTarget->GetMap()->ScriptCommandStart(activateCommand, 0, m_caster, gameObjTarget); } @@ -4020,7 +3968,7 @@ void Spell::EffectApplyGlyph(SpellEffIndex effIndex) } // apply new one - if (uint32 newGlyph = m_spellInfo->Effects[effIndex].MiscValue) + if (uint32 newGlyph = GetEffect(effIndex)->MiscValue) { if (GlyphPropertiesEntry const* newGlyphProperties = sGlyphPropertiesStore.LookupEntry(newGlyph)) { @@ -4078,9 +4026,9 @@ void Spell::EffectEnchantHeldItem(SpellEffIndex effIndex) if (!item->IsEquipped()) return; - if (m_spellInfo->Effects[effIndex].MiscValue) + if (GetEffect(effIndex)->MiscValue) { - uint32 enchant_id = m_spellInfo->Effects[effIndex].MiscValue; + uint32 enchant_id = GetEffect(effIndex)->MiscValue; int32 duration = m_spellInfo->GetDuration(); //Try duration index first .. if (!duration) duration = damage;//+1; //Base points after .. @@ -4174,7 +4122,7 @@ void Spell::EffectFeedPet(SpellEffIndex effIndex) player->DestroyItemCount(foodItem, count, true); /// @todo fix crash when a spell has two effects, both pointed at the same item target - m_caster->CastCustomSpell(pet, m_spellInfo->Effects[effIndex].TriggerSpell, &benefit, NULL, NULL, true); + m_caster->CastCustomSpell(pet, GetEffect(effIndex)->TriggerSpell, &benefit, NULL, NULL, true); } void Spell::EffectDismissPet(SpellEffIndex effIndex) @@ -4196,8 +4144,8 @@ void Spell::EffectSummonObject(SpellEffIndex effIndex) if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT) return; - uint32 go_id = m_spellInfo->Effects[effIndex].MiscValue; - uint8 slot = m_spellInfo->Effects[effIndex].Effect - SPELL_EFFECT_SUMMON_OBJECT_SLOT1; + uint32 go_id = GetEffect(effIndex)->MiscValue; + uint8 slot = GetEffect(effIndex)->Effect - SPELL_EFFECT_SUMMON_OBJECT_SLOT1; ObjectGuid guid = m_caster->m_ObjectSlot[slot]; if (!guid.IsEmpty()) { @@ -4332,7 +4280,7 @@ void Spell::EffectReputation(SpellEffIndex effIndex) int32 repChange = damage; - uint32 factionId = m_spellInfo->Effects[effIndex].MiscValue; + uint32 factionId = GetEffect(effIndex)->MiscValue; FactionEntry const* factionEntry = sFactionStore.LookupEntry(factionId); if (!factionEntry) @@ -4352,7 +4300,7 @@ void Spell::EffectQuestComplete(SpellEffIndex effIndex) return; Player* player = unitTarget->ToPlayer(); - uint32 questId = m_spellInfo->Effects[effIndex].MiscValue; + uint32 questId = GetEffect(effIndex)->MiscValue; if (questId) { Quest const* quest = sObjectMgr->GetQuestTemplate(questId); @@ -4396,7 +4344,7 @@ void Spell::EffectSelfResurrect(SpellEffIndex effIndex) if (damage < 0) { health = uint32(-damage); - mana = m_spellInfo->Effects[effIndex].MiscValue; + mana = GetEffect(effIndex)->MiscValue; } // percent case else @@ -4509,13 +4457,13 @@ void Spell::EffectKnockBack(SpellEffIndex effIndex) unitTarget->InterruptNonMeleeSpells(true); float ratio = 0.1f; - float speedxy = float(m_spellInfo->Effects[effIndex].MiscValue) * ratio; + float speedxy = float(GetEffect(effIndex)->MiscValue) * ratio; float speedz = float(damage) * ratio; if (speedxy < 0.1f && speedz < 0.1f) return; float x, y; - if (m_spellInfo->Effects[effIndex].Effect == SPELL_EFFECT_KNOCK_BACK_DEST) + if (GetEffect(effIndex)->Effect == SPELL_EFFECT_KNOCK_BACK_DEST) { if (m_targets.HasDst()) destTarget->GetPosition(x, y); @@ -4538,7 +4486,7 @@ void Spell::EffectLeapBack(SpellEffIndex effIndex) if (!unitTarget) return; - float speedxy = float(m_spellInfo->Effects[effIndex].MiscValue)/10; + float speedxy = float(GetEffect(effIndex)->MiscValue)/10; float speedz = float(damage/10); //1891: Disengage m_caster->JumpTo(speedxy, speedz, m_spellInfo->SpellIconID != 1891); @@ -4553,7 +4501,7 @@ void Spell::EffectQuestClear(SpellEffIndex effIndex) return; Player* player = unitTarget->ToPlayer(); - uint32 quest_id = m_spellInfo->Effects[effIndex].MiscValue; + uint32 quest_id = GetEffect(effIndex)->MiscValue; Quest const* quest = sObjectMgr->GetQuestTemplate(quest_id); @@ -4595,7 +4543,7 @@ void Spell::EffectSendTaxi(SpellEffIndex effIndex) if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) return; - unitTarget->ToPlayer()->ActivateTaxiPathTo(m_spellInfo->Effects[effIndex].MiscValue, m_spellInfo->Id); + unitTarget->ToPlayer()->ActivateTaxiPathTo(GetEffect(effIndex)->MiscValue, m_spellInfo->Id); } void Spell::EffectPullTowards(SpellEffIndex effIndex) @@ -4607,7 +4555,7 @@ void Spell::EffectPullTowards(SpellEffIndex effIndex) return; Position pos; - if (m_spellInfo->Effects[effIndex].Effect == SPELL_EFFECT_PULL_TOWARDS_DEST) + if (GetEffect(effIndex)->Effect == SPELL_EFFECT_PULL_TOWARDS_DEST) { if (m_targets.HasDst()) pos.Relocate(*destTarget); @@ -4619,7 +4567,7 @@ void Spell::EffectPullTowards(SpellEffIndex effIndex) pos.Relocate(m_caster); } - float speedXY = float(m_spellInfo->Effects[effIndex].MiscValue) * 0.1f; + float speedXY = float(GetEffect(effIndex)->MiscValue) * 0.1f; float speedZ = unitTarget->GetDistance(pos) / speedXY * 0.5f * Movement::gravity; unitTarget->GetMotionMaster()->MoveJump(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), speedXY, speedZ); @@ -4633,7 +4581,7 @@ void Spell::EffectDispelMechanic(SpellEffIndex effIndex) if (!unitTarget) return; - uint32 mechanic = m_spellInfo->Effects[effIndex].MiscValue; + uint32 mechanic = GetEffect(effIndex)->MiscValue; DispelList dispel_list; Unit::AuraMap const& auras = unitTarget->GetOwnedAuras(); for (Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr) @@ -4752,7 +4700,7 @@ void Spell::EffectDurabilityDamage(SpellEffIndex effIndex) if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) return; - int32 slot = m_spellInfo->Effects[effIndex].MiscValue; + int32 slot = GetEffect(effIndex)->MiscValue; // -1 means all player equipped items and -2 all items if (slot < 0) @@ -4781,7 +4729,7 @@ void Spell::EffectDurabilityDamagePCT(SpellEffIndex effIndex) if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) return; - int32 slot = m_spellInfo->Effects[effIndex].MiscValue; + int32 slot = GetEffect(effIndex)->MiscValue; // FIXME: some spells effects have value -1/-2 // Possibly its mean -1 all player equipped items and -2 all items @@ -4818,7 +4766,7 @@ void Spell::EffectTransmitted(SpellEffIndex effIndex) if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT) return; - uint32 name_id = m_spellInfo->Effects[effIndex].MiscValue; + uint32 name_id = GetEffect(effIndex)->MiscValue; GameObjectTemplate const* goinfo = sObjectMgr->GetGameObjectTemplate(name_id); @@ -4833,9 +4781,9 @@ void Spell::EffectTransmitted(SpellEffIndex effIndex) if (m_targets.HasDst()) destTarget->GetPosition(fx, fy, fz); //FIXME: this can be better check for most objects but still hack - else if (m_spellInfo->Effects[effIndex].HasRadius() && m_spellInfo->Speed == 0) + else if (GetEffect(effIndex)->HasRadius() && m_spellInfo->Speed == 0) { - float dis = m_spellInfo->Effects[effIndex].CalcRadius(m_originalCaster); + float dis = GetEffect(effIndex)->CalcRadius(m_originalCaster); m_caster->GetClosePoint(fx, fy, fz, DEFAULT_WORLD_OBJECT_SIZE, dis); } else @@ -5057,7 +5005,7 @@ void Spell::EffectStealBeneficialBuff(SpellEffIndex effIndex) DispelChargesList steal_list; // Create dispel mask by dispel type - uint32 dispelMask = SpellInfo::GetDispelMask(DispelType(m_spellInfo->Effects[effIndex].MiscValue)); + uint32 dispelMask = SpellInfo::GetDispelMask(DispelType(GetEffect(effIndex)->MiscValue)); Unit::AuraMap const& auras = unitTarget->GetOwnedAuras(); for (Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr) { @@ -5157,7 +5105,7 @@ void Spell::EffectKillCreditPersonal(SpellEffIndex effIndex) if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) return; - unitTarget->ToPlayer()->KilledMonsterCredit(m_spellInfo->Effects[effIndex].MiscValue); + unitTarget->ToPlayer()->KilledMonsterCredit(GetEffect(effIndex)->MiscValue); } void Spell::EffectKillCredit(SpellEffIndex effIndex) @@ -5168,7 +5116,7 @@ void Spell::EffectKillCredit(SpellEffIndex effIndex) if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) return; - int32 creatureEntry = m_spellInfo->Effects[effIndex].MiscValue; + int32 creatureEntry = GetEffect(effIndex)->MiscValue; if (!creatureEntry) { if (m_spellInfo->Id == 42793) // Burn Body @@ -5187,7 +5135,7 @@ void Spell::EffectQuestFail(SpellEffIndex effIndex) if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) return; - unitTarget->ToPlayer()->FailQuest(m_spellInfo->Effects[effIndex].MiscValue); + unitTarget->ToPlayer()->FailQuest(GetEffect(effIndex)->MiscValue); } void Spell::EffectQuestStart(SpellEffIndex effIndex) @@ -5202,7 +5150,7 @@ void Spell::EffectQuestStart(SpellEffIndex effIndex) if (!player) return; - if (Quest const* quest = sObjectMgr->GetQuestTemplate(m_spellInfo->Effects[effIndex].MiscValue)) + if (Quest const* quest = sObjectMgr->GetQuestTemplate(GetEffect(effIndex)->MiscValue)) { if (!player->CanTakeQuest(quest, false)) return; @@ -5234,10 +5182,10 @@ void Spell::EffectActivateRune(SpellEffIndex effIndex) if (count == 0) count = 1; for (uint32 j = 0; j < MAX_RUNES && count > 0; ++j) { - if (player->GetRuneCooldown(j) && player->GetCurrentRune(j) == RuneType(m_spellInfo->Effects[effIndex].MiscValue)) + if (player->GetRuneCooldown(j) && player->GetCurrentRune(j) == RuneType(GetEffect(effIndex)->MiscValue)) { if (m_spellInfo->Id == 45529) - if (player->GetBaseRune(j) != RuneType(m_spellInfo->Effects[effIndex].MiscValueB)) + if (player->GetBaseRune(j) != RuneType(GetEffect(effIndex)->MiscValueB)) continue; player->SetRuneCooldown(j, 0); --count; @@ -5250,7 +5198,7 @@ void Spell::EffectActivateRune(SpellEffIndex effIndex) for (uint32 l = 0; l + 1 < MAX_RUNES && count > 0; ++l) { // Check if both runes are on cd as that is the only time when this needs to come into effect - if ((player->GetRuneCooldown(l) && player->GetCurrentRune(l) == RuneType(m_spellInfo->Effects[effIndex].MiscValueB)) && (player->GetRuneCooldown(l+1) && player->GetCurrentRune(l+1) == RuneType(m_spellInfo->Effects[effIndex].MiscValueB))) + if ((player->GetRuneCooldown(l) && player->GetCurrentRune(l) == RuneType(GetEffect(effIndex)->MiscValueB)) && (player->GetRuneCooldown(l+1) && player->GetCurrentRune(l+1) == RuneType(GetEffect(effIndex)->MiscValueB))) { // Should always update the rune with the lowest cd if (l + 1 < MAX_RUNES && player->GetRuneCooldown(l) >= player->GetRuneCooldown(l+1)) @@ -5288,7 +5236,7 @@ void Spell::EffectCreateTamedPet(SpellEffIndex effIndex) if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER || !unitTarget->GetPetGUID().IsEmpty() || unitTarget->getClass() != CLASS_HUNTER) return; - uint32 creatureEntry = m_spellInfo->Effects[effIndex].MiscValue; + uint32 creatureEntry = GetEffect(effIndex)->MiscValue; Pet* pet = unitTarget->CreateTamedPetFrom(creatureEntry, m_spellInfo->Id); if (!pet) return; @@ -5320,7 +5268,7 @@ void Spell::EffectDiscoverTaxi(SpellEffIndex effIndex) if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) return; - uint32 nodeid = m_spellInfo->Effects[effIndex].MiscValue; + uint32 nodeid = GetEffect(effIndex)->MiscValue; if (sTaxiNodesStore.LookupEntry(nodeid)) unitTarget->ToPlayer()->GetSession()->SendDiscoverNewTaxiNode(nodeid); } @@ -5382,7 +5330,7 @@ void Spell::EffectGameObjectSetDestructionState(SpellEffIndex effIndex) return; Player* player = m_originalCaster->GetCharmerOrOwnerPlayerOrPlayerItself(); - gameObjTarget->SetDestructibleState(GameObjectDestructibleState(m_spellInfo->Effects[effIndex].MiscValue), player, true); + gameObjTarget->SetDestructibleState(GameObjectDestructibleState(GetEffect(effIndex)->MiscValue), player, true); } void Spell::SummonGuardian(uint32 i, uint32 entry, SummonPropertiesEntry const* properties, uint32 numGuardians) @@ -5472,7 +5420,7 @@ void Spell::EffectPlayMusic(SpellEffIndex effIndex) if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) return; - uint32 soundid = m_spellInfo->Effects[effIndex].MiscValue; + uint32 soundid = GetEffect(effIndex)->MiscValue; if (!sSoundEntriesStore.LookupEntry(soundid)) { @@ -5529,7 +5477,7 @@ void Spell::EffectPlaySound(SpellEffIndex effIndex) break; } - uint32 soundId = m_spellInfo->Effects[effIndex].MiscValue; + uint32 soundId = GetEffect(effIndex)->MiscValue; if (!sSoundEntriesStore.LookupEntry(soundId)) { @@ -5548,7 +5496,7 @@ void Spell::EffectRemoveAura(SpellEffIndex effIndex) if (!unitTarget) return; // there may be need of specifying casterguid of removed auras - unitTarget->RemoveAurasDueToSpell(m_spellInfo->Effects[effIndex].TriggerSpell); + unitTarget->RemoveAurasDueToSpell(GetEffect(effIndex)->TriggerSpell); } void Spell::EffectDamageFromMaxHealthPCT(SpellEffIndex /*effIndex*/) @@ -5570,7 +5518,7 @@ void Spell::EffectGiveCurrency(SpellEffIndex effIndex) if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) return; - unitTarget->ToPlayer()->ModifyCurrency(m_spellInfo->Effects[effIndex].MiscValue, damage); + unitTarget->ToPlayer()->ModifyCurrency(GetEffect(effIndex)->MiscValue, damage); } void Spell::EffectCastButtons(SpellEffIndex effIndex) @@ -5582,8 +5530,8 @@ void Spell::EffectCastButtons(SpellEffIndex effIndex) return; Player* p_caster = m_caster->ToPlayer(); - uint32 button_id = m_spellInfo->Effects[effIndex].MiscValue + 132; - uint32 n_buttons = m_spellInfo->Effects[effIndex].MiscValueB; + uint32 button_id = GetEffect(effIndex)->MiscValue + 132; + uint32 n_buttons = GetEffect(effIndex)->MiscValueB; for (; n_buttons; --n_buttons, ++button_id) { @@ -5628,21 +5576,23 @@ void Spell::EffectRechargeManaGem(SpellEffIndex /*effIndex*/) if (!player) return; - - uint32 item_id = m_spellInfo->Effects[EFFECT_0].ItemType; - - ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(item_id); - if (!pProto) + if (SpellEffectInfo const* effect = GetEffect(EFFECT_0)) { - player->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL); - return; - } + uint32 item_id = effect->ItemType; - if (Item* pItem = player->GetItemByEntry(item_id)) - { - for (int x = 0; x < pProto->Effects.size(); ++x) - pItem->SetSpellCharges(x, pProto->Effects[x].Charges); - pItem->SetState(ITEM_CHANGED, player); + ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(item_id); + if (!pProto) + { + player->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL); + return; + } + + if (Item* pItem = player->GetItemByEntry(item_id)) + { + for (int x = 0; x < pProto->Effects.size(); ++x) + pItem->SetSpellCharges(x, pProto->Effects[x].Charges); + pItem->SetState(ITEM_CHANGED, player); + } } } @@ -5659,8 +5609,8 @@ void Spell::EffectBind(SpellEffIndex effIndex) WorldLocation homeLoc; uint32 areaId = player->GetAreaId(); - if (m_spellInfo->Effects[effIndex].MiscValue) - areaId = m_spellInfo->Effects[effIndex].MiscValue; + if (GetEffect(effIndex)->MiscValue) + areaId = GetEffect(effIndex)->MiscValue; if (m_targets.HasDst()) homeLoc.WorldRelocate(*destTarget); @@ -5696,7 +5646,7 @@ void Spell::EffectSummonRaFFriend(SpellEffIndex effIndex) if (m_caster->GetTypeId() != TYPEID_PLAYER || !unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) return; - m_caster->CastSpell(unitTarget, m_spellInfo->Effects[effIndex].TriggerSpell, true); + m_caster->CastSpell(unitTarget, GetEffect(effIndex)->TriggerSpell, true); } void Spell::EffectUnlockGuildVaultTab(SpellEffIndex effIndex) @@ -5707,7 +5657,7 @@ void Spell::EffectUnlockGuildVaultTab(SpellEffIndex effIndex) // Safety checks done in Spell::CheckCast Player* caster = m_caster->ToPlayer(); if (Guild* guild = caster->GetGuild()) - guild->HandleBuyBankTab(caster->GetSession(), m_spellInfo->Effects[effIndex].BasePoints - 1); // Bank tabs start at zero internally + guild->HandleBuyBankTab(caster->GetSession(), GetEffect(effIndex)->BasePoints - 1); // Bank tabs start at zero internally } void Spell::EffectResurrectWithAura(SpellEffIndex effIndex) @@ -5731,8 +5681,8 @@ void Spell::EffectResurrectWithAura(SpellEffIndex effIndex) uint32 health = target->CountPctFromMaxHealth(damage); uint32 mana = CalculatePct(target->GetMaxPower(POWER_MANA), damage); uint32 resurrectAura = 0; - if (sSpellMgr->GetSpellInfo(GetSpellInfo()->Effects[effIndex].TriggerSpell)) - resurrectAura = GetSpellInfo()->Effects[effIndex].TriggerSpell; + if (sSpellMgr->GetSpellInfo(GetEffect(effIndex)->TriggerSpell)) + resurrectAura = GetEffect(effIndex)->TriggerSpell; if (resurrectAura && target->HasAura(resurrectAura)) return; @@ -5754,9 +5704,9 @@ void Spell::EffectCreateAreaTrigger(SpellEffIndex effIndex) pos = destTarget->GetPosition(); // trigger entry/miscvalue relation is currently unknown, for now use MiscValue as trigger entry - uint32 triggerEntry = GetSpellInfo()->Effects[effIndex].MiscValue; + uint32 triggerEntry = GetEffect(effIndex)->MiscValue; AreaTrigger * areaTrigger = new AreaTrigger; if (!areaTrigger->CreateAreaTrigger(sObjectMgr->GetGenerator<HighGuid::AreaTrigger>()->Generate(), triggerEntry, GetCaster(), GetSpellInfo(), pos)) delete areaTrigger; -} +}
\ No newline at end of file diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp index 3c4cf37b4e3..17517824709 100644 --- a/src/server/game/Spells/SpellInfo.cpp +++ b/src/server/game/Spells/SpellInfo.cpp @@ -866,7 +866,7 @@ SpellInfo::SpellInfo(SpellEntry const* spellEntry, SpellEffectInfoMap effects) { Id = spellEntry->ID; - Effects = effects; + _effects = effects; SpellName = spellEntry->Name_lang; //Rank = spellEntry->Rank; @@ -1041,9 +1041,9 @@ uint32 SpellInfo::GetCategory() const bool SpellInfo::HasEffect(uint32 difficulty, SpellEffectName effect) const { SpellEffectInfoVector effects = GetEffectsForDifficulty(difficulty); - for (SpellEffectInfoVector::const_iterator itr = effects.begin(); itr != effects.end(); ++itr) + for (SpellEffectInfo const* eff : effects) { - if ((*itr)->IsEffect(effect)) + if (eff && eff->IsEffect(effect)) return true; } return false; @@ -1052,19 +1052,20 @@ bool SpellInfo::HasEffect(uint32 difficulty, SpellEffectName effect) const bool SpellInfo::HasAura(uint32 difficulty, AuraType aura) const { SpellEffectInfoVector effects = GetEffectsForDifficulty(difficulty); - for (SpellEffectInfoVector::const_iterator itr = effects.begin(); itr != effects.end(); ++itr) + for (SpellEffectInfo const* effect : effects) { - if ((*itr)->IsAura(aura)) + if (effect && effect->IsAura(aura)) return true; } + return false; } bool SpellInfo::HasAreaAuraEffect(uint32 difficulty) const { SpellEffectInfoVector effects = GetEffectsForDifficulty(difficulty); - for (SpellEffectInfoVector::const_iterator itr = effects.begin(); itr != effects.end(); ++itr) + for (SpellEffectInfo const* effect : effects) { - if ((*itr)->IsAreaAuraEffect()) + if (effect && effect->IsAreaAuraEffect()) return true; } return false; @@ -1072,33 +1073,38 @@ bool SpellInfo::HasAreaAuraEffect(uint32 difficulty) const bool SpellInfo::IsExplicitDiscovery() const { - return ((Effects[0].Effect == SPELL_EFFECT_CREATE_RANDOM_ITEM - || Effects[0].Effect == SPELL_EFFECT_CREATE_ITEM_2) - && Effects[1].Effect == SPELL_EFFECT_SCRIPT_EFFECT) + SpellEffectInfo const* effect0 = GetEffect(DIFFICULTY_NONE, EFFECT_0); + SpellEffectInfo const* effect1 = GetEffect(DIFFICULTY_NONE, EFFECT_1); + + return ((effect0 && (effect0->Effect == SPELL_EFFECT_CREATE_RANDOM_ITEM || effect0->Effect == SPELL_EFFECT_CREATE_ITEM_2)) + && effect1 && effect1->Effect == SPELL_EFFECT_SCRIPT_EFFECT) || Id == 64323; } bool SpellInfo::IsLootCrafting() const { - return (Effects[0].Effect == SPELL_EFFECT_CREATE_RANDOM_ITEM || + SpellEffectInfo const* effect0 = GetEffect(DIFFICULTY_NONE, EFFECT_0); + return effect0 && (effect0->Effect == SPELL_EFFECT_CREATE_RANDOM_ITEM || // different random cards from Inscription (121==Virtuoso Inking Set category) r without explicit item - (Effects[0].Effect == SPELL_EFFECT_CREATE_ITEM_2 && - ((TotemCategory[0] != 0 || (Totem[0] != 0 && SpellIconID == 1)) || Effects[0].ItemType == 0))); + (effect0->Effect == SPELL_EFFECT_CREATE_ITEM_2 && + ((TotemCategory[0] != 0 || (Totem[0] != 0 && SpellIconID == 1)) || effect0->ItemType == 0))); } bool SpellInfo::IsQuestTame() const { - return Effects[0].Effect == SPELL_EFFECT_THREAT && Effects[1].Effect == SPELL_EFFECT_APPLY_AURA && Effects[1].ApplyAuraName == SPELL_AURA_DUMMY; + SpellEffectInfo const* effect0 = GetEffect(DIFFICULTY_NONE, EFFECT_0); + SpellEffectInfo const* effect1 = GetEffect(DIFFICULTY_NONE, EFFECT_1); + return effect0 && effect1 && effect0->Effect == SPELL_EFFECT_THREAT && effect1->Effect == SPELL_EFFECT_APPLY_AURA && effect1->ApplyAuraName == SPELL_AURA_DUMMY; } bool SpellInfo::IsProfessionOrRiding(uint32 difficulty) const { SpellEffectInfoVector effects = GetEffectsForDifficulty(difficulty); - for (SpellEffectInfoVector::const_iterator itr = effects.begin(); itr != effects.end(); ++itr) + for (SpellEffectInfo const* effect : effects) { - if ((*itr)->Effect == SPELL_EFFECT_SKILL) + if ((effect && effect->Effect == SPELL_EFFECT_SKILL)) { - uint32 skill = (*itr)->MiscValue; + uint32 skill = effect->MiscValue; if (IsProfessionOrRidingSkill(skill)) return true; @@ -1110,11 +1116,11 @@ bool SpellInfo::IsProfessionOrRiding(uint32 difficulty) const bool SpellInfo::IsProfession(uint32 difficulty) const { SpellEffectInfoVector effects = GetEffectsForDifficulty(difficulty); - for (SpellEffectInfoVector::const_iterator itr = effects.begin(); itr != effects.end(); ++itr) + for (SpellEffectInfo const* effect : effects) { - if ((*itr)->Effect == SPELL_EFFECT_SKILL) + if (effect && effect->Effect == SPELL_EFFECT_SKILL) { - uint32 skill = (*itr)->MiscValue; + uint32 skill = effect->MiscValue; if (IsProfessionSkill(skill)) return true; @@ -1126,11 +1132,11 @@ bool SpellInfo::IsProfession(uint32 difficulty) const bool SpellInfo::IsPrimaryProfession(uint32 difficulty) const { SpellEffectInfoVector effects = GetEffectsForDifficulty(difficulty); - for (SpellEffectInfoVector::const_iterator itr = effects.begin(); itr != effects.end(); ++itr) + for(SpellEffectInfo const* effect : effects) { - if ((*itr)->Effect == SPELL_EFFECT_SKILL) + if (effect && effect->Effect == SPELL_EFFECT_SKILL) { - uint32 skill = (*itr)->MiscValue; + uint32 skill = effect->MiscValue; if (IsPrimaryProfessionSkill(skill)) return true; @@ -1175,9 +1181,9 @@ bool SpellInfo::IsAbilityOfSkillType(uint32 skillType) const bool SpellInfo::IsAffectingArea(uint32 difficulty) const { SpellEffectInfoVector effects = GetEffectsForDifficulty(difficulty); - for (SpellEffectInfoVector::const_iterator itr = effects.begin(); itr != effects.end(); ++itr) + for (SpellEffectInfo const* effect : effects) { - if ((*itr)->IsEffect() && ((*itr)->IsTargetingArea() || (*itr)->IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA) || (*itr)->IsAreaAuraEffect())) + if (effect && effect->IsEffect() && (effect->IsTargetingArea() || effect->IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA) || effect->IsAreaAuraEffect())) return true; } return false; @@ -1187,9 +1193,9 @@ bool SpellInfo::IsAffectingArea(uint32 difficulty) const bool SpellInfo::IsTargetingArea(uint32 difficulty) const { SpellEffectInfoVector effects = GetEffectsForDifficulty(difficulty); - for (SpellEffectInfoVector::const_iterator itr = effects.begin(); itr != effects.end(); ++itr) + for (SpellEffectInfo const* effect : effects) { - if ((*itr)->IsEffect() && (*itr)->IsTargetingArea()) + if (effect && effect->IsEffect() && effect->IsTargetingArea()) return true; } return false; @@ -1200,7 +1206,7 @@ bool SpellInfo::NeedsExplicitUnitTarget() const return (GetExplicitTargetMask() & TARGET_FLAG_UNIT_MASK) != 0; } -bool SpellInfo::NeedsToBeTriggeredByCaster(SpellInfo const* triggeringSpell) const +bool SpellInfo::NeedsToBeTriggeredByCaster(SpellInfo const* triggeringSpell, uint32 difficulty) const { if (NeedsExplicitUnitTarget()) return true; @@ -1220,12 +1226,13 @@ bool SpellInfo::NeedsToBeTriggeredByCaster(SpellInfo const* triggeringSpell) con if (triggeringSpell->IsChanneled()) { uint32 mask = 0; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + SpellEffectInfoVector effects = GetEffectsForDifficulty(difficulty); + for (SpellEffectInfo const* effect : effects) { - if (Effects[i].TargetA.GetTarget() != TARGET_UNIT_CASTER && Effects[i].TargetA.GetTarget() != TARGET_DEST_CASTER - && Effects[i].TargetB.GetTarget() != TARGET_UNIT_CASTER && Effects[i].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 |= Effects[i].GetProvidedTargetMask(); + mask |= effect->GetProvidedTargetMask(); } } @@ -1263,19 +1270,20 @@ bool SpellInfo::IsStackableWithRanks() const return false; // All stance spells. if any better way, change it. - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + SpellEffectInfoVector effects = GetEffectsForDifficulty(DIFFICULTY_NONE); + for (SpellEffectInfo const* effect : effects) { switch (SpellFamilyName) { case SPELLFAMILY_PALADIN: // Paladin aura Spell - if (Effects[i].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 (Effects[i].Effect == SPELL_EFFECT_APPLY_AURA && - Effects[i].ApplyAuraName == SPELL_AURA_MOD_SHAPESHIFT) + if (effect->Effect == SPELL_EFFECT_APPLY_AURA && + effect->ApplyAuraName == SPELL_AURA_MOD_SHAPESHIFT) return false; break; } @@ -1283,9 +1291,9 @@ bool SpellInfo::IsStackableWithRanks() const return true; } -bool SpellInfo::IsPassiveStackableWithRanks() const +bool SpellInfo::IsPassiveStackableWithRanks(uint32 difficulty) const { - return IsPassive() && !HasEffect(SPELL_EFFECT_APPLY_AURA); + return IsPassive() && !HasEffect(difficulty, SPELL_EFFECT_APPLY_AURA); } bool SpellInfo::IsMultiSlotAura() const @@ -1665,12 +1673,12 @@ SpellCastResult SpellInfo::CheckLocation(uint32 map_id, uint32 zone_id, uint32 a // aura limitations if (player) { - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const* effect : GetEffectsForDifficulty(player->GetMap()->GetDifficulty())) { - if (!Effects[i].IsAura()) + if (!effect || !effect->IsAura()) continue; - switch (Effects[i].ApplyAuraName) + switch (effect->ApplyAuraName) { case SPELL_AURA_FLY: { @@ -1680,7 +1688,7 @@ SpellCastResult SpellInfo::CheckLocation(uint32 map_id, uint32 zone_id, uint32 a } case SPELL_AURA_MOUNTED: { - if (Effects[i].MiscValueB && !player->GetMountCapability(Effects[i].MiscValueB)) + if (effect->MiscValueB && !player->GetMountCapability(effect->MiscValueB)) return SPELL_FAILED_NOT_HERE; break; } @@ -1829,14 +1837,14 @@ SpellCastResult SpellInfo::CheckTarget(Unit const* caster, WorldObject const* ta return SPELL_FAILED_TARGET_AURASTATE; } - if (TargetAuraSpell && !unitTarget->HasAura(sSpellMgr->GetSpellIdForDifficulty(TargetAuraSpell, caster))) + if (TargetAuraSpell && !unitTarget->HasAura(TargetAuraSpell)) return SPELL_FAILED_TARGET_AURASTATE; - if (ExcludeTargetAuraSpell && unitTarget->HasAura(sSpellMgr->GetSpellIdForDifficulty(ExcludeTargetAuraSpell, caster))) + if (ExcludeTargetAuraSpell && unitTarget->HasAura(ExcludeTargetAuraSpell)) return SPELL_FAILED_TARGET_AURASTATE; if (unitTarget->HasAuraType(SPELL_AURA_PREVENT_RESURRECTION)) - if (HasEffect(SPELL_EFFECT_SELF_RESURRECT) || HasEffect(SPELL_EFFECT_RESURRECT) || HasEffect(SPELL_EFFECT_RESURRECT_NEW)) + if (HasEffect(caster->GetMap()->GetDifficulty(), SPELL_EFFECT_SELF_RESURRECT) || HasEffect(caster->GetMap()->GetDifficulty(), SPELL_EFFECT_RESURRECT) || HasEffect(caster->GetMap()->GetDifficulty(), SPELL_EFFECT_RESURRECT_NEW)) return SPELL_FAILED_TARGET_CANNOT_BE_RESURRECTED; return SPELL_CAST_OK; @@ -1887,18 +1895,18 @@ SpellCastResult SpellInfo::CheckVehicle(Unit const* caster) const if (vehicle) { uint16 checkMask = 0; - for (uint8 effIndex = EFFECT_0; effIndex < MAX_SPELL_EFFECTS; ++effIndex) + for (SpellEffectInfo const* effect : GetEffectsForDifficulty(caster->GetMap()->GetDifficulty())) { - if (Effects[effIndex].ApplyAuraName == SPELL_AURA_MOD_SHAPESHIFT) + if (effect && effect->ApplyAuraName == SPELL_AURA_MOD_SHAPESHIFT) { - SpellShapeshiftFormEntry const* shapeShiftFromEntry = sSpellShapeshiftFormStore.LookupEntry(Effects[effIndex].MiscValue); + SpellShapeshiftFormEntry const* shapeShiftFromEntry = sSpellShapeshiftFormStore.LookupEntry(effect->MiscValue); if (shapeShiftFromEntry && (shapeShiftFromEntry->Flags & 1) == 0) // unk flag checkMask |= VEHICLE_SEAT_FLAG_UNCONTROLLED; break; } } - if (HasAura(SPELL_AURA_MOUNTED)) + if (HasAura(caster->GetMap()->GetDifficulty(), SPELL_AURA_MOUNTED)) checkMask |= VEHICLE_SEAT_FLAG_CAN_CAST_MOUNT_SPELL; if (!checkMask) @@ -1912,12 +1920,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 (uint32 i = EFFECT_0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const* effect : GetEffectsForDifficulty(caster->GetMap()->GetDifficulty())) { - if (Effects[i].Effect != SPELL_EFFECT_SUMMON) + if (!effect || effect->Effect != SPELL_EFFECT_SUMMON) continue; - SummonPropertiesEntry const* props = sSummonPropertiesStore.LookupEntry(Effects[i].MiscValueB); + SummonPropertiesEntry const* props = sSummonPropertiesStore.LookupEntry(effect->MiscValueB); if (props && props->Category != SUMMON_CATEGORY_WILD) return SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW; } @@ -1957,19 +1965,30 @@ uint32 SpellInfo::GetAllEffectsMechanicMask() const uint32 mask = 0; if (Mechanic) mask |= 1 << Mechanic; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - if (Effects[i].IsEffect() && Effects[i].Mechanic) - mask |= 1 << Effects[i].Mechanic; + for (SpellEffectInfoMap::const_iterator itr = _effects.begin(); itr != _effects.end(); ++itr) + { + for (SpellEffectInfo const* effect : itr->second) + { + if (effect && effect->IsEffect() && effect->Mechanic) + mask |= 1 << effect->Mechanic; + } + } return mask; } -uint32 SpellInfo::GetEffectMechanicMask(uint8 effIndex) const +uint32 SpellInfo::GetEffectMechanicMask(uint32 effIndex) const { uint32 mask = 0; if (Mechanic) mask |= 1 << Mechanic; - if (Effects[effIndex].IsEffect() && Effects[effIndex].Mechanic) - mask |= 1 << Effects[effIndex].Mechanic; + for (SpellEffectInfoMap::const_iterator itr = _effects.begin(); itr != _effects.end(); ++itr) + { + for (SpellEffectInfo const* effect : itr->second) + { + if (effect && effect->EffectIndex == effIndex && effect->IsEffect() && effect->Mechanic) + mask |= 1 << effect->Mechanic; + } + } return mask; } @@ -1978,28 +1997,34 @@ uint32 SpellInfo::GetSpellMechanicMaskByEffectMask(uint32 effectMask) const uint32 mask = 0; if (Mechanic) mask |= 1 << Mechanic; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - if ((effectMask & (1 << i)) && Effects[i].Mechanic) - mask |= 1 << Effects[i].Mechanic; + for (SpellEffectInfoMap::const_iterator itr = _effects.begin(); itr != _effects.end(); ++itr) + { + for (SpellEffectInfo const* effect : itr->second) + { + if (effect && (effectMask & (1 << effect->EffectIndex)) && effect->Mechanic) + mask |= 1 << effect->Mechanic; + } + } return mask; } -Mechanics SpellInfo::GetEffectMechanic(uint8 effIndex) const +Mechanics SpellInfo::GetEffectMechanic(uint32 effIndex, uint32 difficulty) const { - if (Effects[effIndex].IsEffect() && Effects[effIndex].Mechanic) - return Mechanics(Effects[effIndex].Mechanic); + SpellEffectInfo const* effect = GetEffect(difficulty, effIndex); + if (effect && effect->IsEffect() && effect->Mechanic) + return Mechanics(effect->Mechanic); if (Mechanic) return Mechanics(Mechanic); return MECHANIC_NONE; } -bool SpellInfo::HasAnyEffectMechanic() const +/*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 { @@ -2020,7 +2045,7 @@ uint32 SpellInfo::GetExplicitTargetMask() const return ExplicitTargetMask; } -AuraStateType SpellInfo::GetAuraState() const +AuraStateType SpellInfo::GetAuraState(uint32 difficulty) const { // Seals if (GetSpellSpecific() == SPELL_SPECIFIC_SEAL) @@ -2063,10 +2088,10 @@ AuraStateType SpellInfo::GetAuraState() const return AURA_STATE_BLEEDING; if (GetSchoolMask() & SPELL_SCHOOL_MASK_FROST) - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - if (Effects[i].IsAura() && (Effects[i].ApplyAuraName == SPELL_AURA_MOD_STUN - || Effects[i].ApplyAuraName == SPELL_AURA_MOD_ROOT)) - return AURA_STATE_FROZEN; + for (SpellEffectInfo const* effect : GetEffectsForDifficulty(difficulty)) + if (effect && effect->IsAura() && (effect->ApplyAuraName == SPELL_AURA_MOD_STUN + || effect->ApplyAuraName == SPELL_AURA_MOD_ROOT)) + return AURA_STATE_FROZEN; switch (Id) { @@ -2091,24 +2116,27 @@ SpellSpecificType SpellInfo::GetSpellSpecific() const { bool food = false; bool drink = false; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfoMap::const_iterator itr = _effects.begin(); itr != _effects.end(); ++itr) { - if (!Effects[i].IsAura()) - continue; - switch (Effects[i].ApplyAuraName) + for (SpellEffectInfo const* effect : itr->second) { - // Food + if (!effect || !effect->IsAura()) + continue; + switch (effect->ApplyAuraName) + { + // Food case SPELL_AURA_MOD_REGEN: case SPELL_AURA_OBS_MOD_HEALTH: food = true; break; - // Drink + // Drink case SPELL_AURA_MOD_POWER_REGEN: case SPELL_AURA_OBS_MOD_POWER: drink = true; break; default: break; + } } } @@ -2148,8 +2176,8 @@ SpellSpecificType SpellInfo::GetSpellSpecific() const // Arcane brillance and Arcane intelect (normal check fails because of flags difference) if (SpellFamilyFlags[0] & 0x400) return SPELL_SPECIFIC_MAGE_ARCANE_BRILLANCE; - - if ((SpellFamilyFlags[0] & 0x1000000) && Effects[0].ApplyAuraName == SPELL_AURA_MOD_CONFUSE) + SpellEffectInfo const* effect = GetEffect(DIFFICULTY_NONE, EFFECT_0); + if (effect && (SpellFamilyFlags[0] & 0x1000000) && effect->ApplyAuraName == SPELL_AURA_MOD_CONFUSE) return SPELL_SPECIFIC_MAGE_POLYMORPH; break; @@ -2235,12 +2263,14 @@ SpellSpecificType SpellInfo::GetSpellSpecific() const break; } - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfoMap::const_iterator itr = _effects.begin(); itr != _effects.end(); ++itr) { - if (Effects[i].Effect == SPELL_EFFECT_APPLY_AURA) + for (SpellEffectInfo const* effect : itr->second) { - switch (Effects[i].ApplyAuraName) + if (effect && effect->Effect == SPELL_EFFECT_APPLY_AURA) { + switch (effect->ApplyAuraName) + { case SPELL_AURA_MOD_CHARM: case SPELL_AURA_MOD_POSSESS_PET: case SPELL_AURA_MOD_POSSESS: @@ -2253,10 +2283,10 @@ SpellSpecificType SpellInfo::GetSpellSpecific() const case SPELL_AURA_TRACK_RESOURCES: case SPELL_AURA_TRACK_STEALTHED: return SPELL_SPECIFIC_TRACKER; + } } } } - return SPELL_SPECIFIC_NORMAL; } @@ -2326,7 +2356,7 @@ uint32 SpellInfo::CalcCastTime(uint8 level, Spell* spell /*= NULL*/) const return (castTime > 0) ? uint32(castTime) : 0; } -uint32 SpellInfo::GetMaxTicks() const +uint32 SpellInfo::GetMaxTicks(uint32 difficulty) const { int32 DotDuration = GetDuration(); if (DotDuration == 0) @@ -2336,16 +2366,16 @@ uint32 SpellInfo::GetMaxTicks() const if (DotDuration > 30000) DotDuration = 30000; - for (uint8 x = 0; x < MAX_SPELL_EFFECTS; x++) + for (SpellEffectInfo const* effect : GetEffectsForDifficulty(difficulty)) { - if (Effects[x].Effect == SPELL_EFFECT_APPLY_AURA) - switch (Effects[x].ApplyAuraName) + if (effect && effect->Effect == SPELL_EFFECT_APPLY_AURA) + switch (effect->ApplyAuraName) { case SPELL_AURA_PERIODIC_DAMAGE: case SPELL_AURA_PERIODIC_HEAL: case SPELL_AURA_PERIODIC_LEECH: - if (Effects[x].ApplyAuraPeriod != 0) - return DotDuration / Effects[x].ApplyAuraPeriod; + if (effect->ApplyAuraPeriod != 0) + return DotDuration / effect->ApplyAuraPeriod; break; } } @@ -2507,13 +2537,13 @@ SpellInfo const* SpellInfo::GetAuraRankForLevel(uint8 level) const return this; bool needRankSelection = false; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const* effect : GetEffectsForDifficulty(DIFFICULTY_NONE)) { - if (IsPositiveEffect(i) && - (Effects[i].Effect == SPELL_EFFECT_APPLY_AURA || - Effects[i].Effect == SPELL_EFFECT_APPLY_AREA_AURA_PARTY || - Effects[i].Effect == SPELL_EFFECT_APPLY_AREA_AURA_RAID) && - !Effects[i].ScalingMultiplier) + if (effect && IsPositiveEffect(effect->Effect) && + (effect->Effect == SPELL_EFFECT_APPLY_AURA || + effect->Effect == SPELL_EFFECT_APPLY_AREA_AURA_PARTY || + effect->Effect == SPELL_EFFECT_APPLY_AREA_AURA_RAID) && + !effect->ScalingMultiplier) { needRankSelection = true; break; @@ -2565,32 +2595,35 @@ void SpellInfo::_InitializeExplicitTargetMask() bool dstSet = false; uint32 targetMask = Targets; // prepare target mask using effect target entries - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfoMap::const_iterator itr = _effects.begin(); itr != _effects.end(); ++itr) { - if (!Effects[i].IsEffect()) - continue; + for (SpellEffectInfo const* effect : itr->second) + { + if (!effect || !effect->IsEffect()) + continue; - targetMask |= Effects[i].TargetA.GetExplicitTargetMask(srcSet, dstSet); - targetMask |= Effects[i].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 (Effects[i].GetImplicitTargetType() != EFFECT_IMPLICIT_TARGET_EXPLICIT) - continue; + // 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) + continue; - // extend explicit target mask only if valid targets for effect could not be provided by target types - uint32 effectTargetMask = Effects[i].GetMissingTargetMask(srcSet, dstSet, targetMask); + // extend explicit target mask only if valid targets for effect could not be provided by target types + 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) - effectTargetMask &= ~(TARGET_FLAG_UNIT_MASK | TARGET_FLAG_GAMEOBJECT | TARGET_FLAG_CORPSE_MASK | TARGET_FLAG_DEST_LOCATION); + // don't add explicit object/dest flags when spell has no max range + if (GetMaxRange(true) == 0.0f && GetMaxRange(false) == 0.0f) + effectTargetMask &= ~(TARGET_FLAG_UNIT_MASK | TARGET_FLAG_GAMEOBJECT | TARGET_FLAG_CORPSE_MASK | TARGET_FLAG_DEST_LOCATION); - targetMask |= effectTargetMask; + targetMask |= effectTargetMask; + } } ExplicitTargetMask = targetMask; } -bool SpellInfo::_IsPositiveEffect(uint8 effIndex, bool deep) const +bool SpellInfo::_IsPositiveEffect(uint32 effIndex, bool deep) const { // not found a single positive spell with this attribute if (Attributes & SPELL_ATTR0_NEGATIVE_1) @@ -2655,40 +2688,50 @@ bool SpellInfo::_IsPositiveEffect(uint8 effIndex, bool deep) const } // Special case: effects which determine positivity of whole spell - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfoMap::const_iterator itr = _effects.begin(); itr != _effects.end(); ++itr) { - if (Effects[i].IsAura() && Effects[i].ApplyAuraName == SPELL_AURA_MOD_STEALTH) - return true; + for (SpellEffectInfo const* effect : itr->second) + { + if (effect && effect->IsAura() && effect->ApplyAuraName == SPELL_AURA_MOD_STEALTH) + return true; + } } - switch (Effects[effIndex].Effect) + for (SpellEffectInfoMap::const_iterator itr = _effects.begin(); itr != _effects.end(); ++itr) { - case SPELL_EFFECT_DUMMY: - // some explicitly required dummy effect sets - switch (Id) + for (SpellEffectInfo const* effect : itr->second) + { + if (!effect || effect->EffectIndex != effIndex) + continue; + + switch (effect->Effect) { + case SPELL_EFFECT_DUMMY: + // some explicitly required dummy effect sets + switch (Id) + { case 28441: return false; // AB Effect 000 default: break; - } - break; - // always positive effects (check before target checks that provided non-positive result in some case for positive effects) - case SPELL_EFFECT_HEAL: - case SPELL_EFFECT_LEARN_SPELL: - case SPELL_EFFECT_SKILL_STEP: - case SPELL_EFFECT_HEAL_PCT: - case SPELL_EFFECT_ENERGIZE_PCT: - return true; - case SPELL_EFFECT_APPLY_AREA_AURA_ENEMY: - return false; + } + break; + // always positive effects (check before target checks that provided non-positive result in some case for positive effects) + case SPELL_EFFECT_HEAL: + case SPELL_EFFECT_LEARN_SPELL: + case SPELL_EFFECT_SKILL_STEP: + case SPELL_EFFECT_HEAL_PCT: + case SPELL_EFFECT_ENERGIZE_PCT: + return true; + case SPELL_EFFECT_APPLY_AREA_AURA_ENEMY: + return false; - // non-positive aura use - case SPELL_EFFECT_APPLY_AURA: - case SPELL_EFFECT_APPLY_AREA_AURA_FRIEND: - { - switch (Effects[effIndex].ApplyAuraName) + // non-positive aura use + case SPELL_EFFECT_APPLY_AURA: + case SPELL_EFFECT_APPLY_AREA_AURA_FRIEND: { + switch (effect->ApplyAuraName) + { case SPELL_AURA_MOD_DAMAGE_DONE: // dependent from bas point sign (negative -> negative) case SPELL_AURA_MOD_STAT: case SPELL_AURA_MOD_SKILL: @@ -2696,16 +2739,16 @@ bool SpellInfo::_IsPositiveEffect(uint8 effIndex, bool deep) const case SPELL_AURA_MOD_HEALING_PCT: case SPELL_AURA_MOD_HEALING_DONE: case SPELL_AURA_MOD_DAMAGE_PERCENT_DONE: - if (Effects[effIndex].CalcValue() < 0) + if (effect->CalcValue() < 0) return false; break; case SPELL_AURA_MOD_DAMAGE_TAKEN: // dependent from bas point sign (positive -> negative) - if (Effects[effIndex].CalcValue() > 0) + if (effect->CalcValue() > 0) return false; break; case SPELL_AURA_MOD_CRIT_PCT: case SPELL_AURA_MOD_SPELL_CRIT_CHANCE: - if (Effects[effIndex].CalcValue() > 0) + if (effect->CalcValue() > 0) return true; // some expected positive spells have SPELL_ATTR1_NEGATIVE break; case SPELL_AURA_ADD_TARGET_TRIGGER: @@ -2714,17 +2757,20 @@ bool SpellInfo::_IsPositiveEffect(uint8 effIndex, bool deep) const case SPELL_AURA_PERIODIC_TRIGGER_SPELL: if (!deep) { - if (SpellInfo const* spellTriggeredProto = sSpellMgr->GetSpellInfo(Effects[effIndex].TriggerSpell)) + if (SpellInfo const* spellTriggeredProto = sSpellMgr->GetSpellInfo(effect->TriggerSpell)) { // negative targets of main spell return early - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfoMap::const_iterator it = spellTriggeredProto->_effects.begin(); it != spellTriggeredProto->_effects.end(); ++it) { - if (!spellTriggeredProto->Effects[i].Effect) - 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->Effects[i].TargetA.GetTarget(), spellTriggeredProto->Effects[i].TargetB.GetTarget()) && !spellTriggeredProto->_IsPositiveEffect(i, true)) - return false; + for (SpellEffectInfo const* eff : itr->second) + { + if (!eff || !eff->Effect) + 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(eff->TargetA.GetTarget(), eff->TargetB.GetTarget()) && !spellTriggeredProto->_IsPositiveEffect(eff->EffectIndex, true)) + return false; + } } } } @@ -2732,9 +2778,23 @@ bool SpellInfo::_IsPositiveEffect(uint8 effIndex, bool deep) const // many positive auras have negative triggered spells at damage for example and this not make it negative (it can be canceled for example) break; case SPELL_AURA_MOD_STUN: //have positive and negative spells, we can't sort its correctly at this moment. - if (effIndex == 0 && Effects[1].Effect == 0 && Effects[2].Effect == 0) + { + bool more = false; + for (SpellEffectInfoMap::const_iterator i = _effects.begin(); i != _effects.end(); ++i) + { + for (SpellEffectInfo const* eff : i->second) + { + if (eff && eff->EffectIndex != 0) + { + more = true; + break; + } + } + } + if (effIndex == 0 && !more) return false; // but all single stun aura spells is negative break; + } case SPELL_AURA_MOD_PACIFY_SILENCE: if (Id == 24740) // Wisp Costume return true; @@ -2749,12 +2809,12 @@ bool SpellInfo::_IsPositiveEffect(uint8 effIndex, bool deep) const return false; case SPELL_AURA_PERIODIC_DAMAGE: // used in positive spells also. // part of negative spell if cast at self (prevent cancel) - if (Effects[effIndex].TargetA.GetTarget() == TARGET_UNIT_CASTER) + if (effect->TargetA.GetTarget() == TARGET_UNIT_CASTER) return false; break; case SPELL_AURA_MOD_DECREASE_SPEED: // used in positive spells also // part of positive spell if cast at self - if (Effects[effIndex].TargetA.GetTarget() != TARGET_UNIT_CASTER) + if (effect->TargetA.GetTarget() != TARGET_UNIT_CASTER) return false; // but not this if this first effect (didn't find better check) if (Attributes & SPELL_ATTR0_NEGATIVE_1 && effIndex == 0) @@ -2763,7 +2823,7 @@ bool SpellInfo::_IsPositiveEffect(uint8 effIndex, bool deep) const case SPELL_AURA_MECHANIC_IMMUNITY: { // non-positive immunities - switch (Effects[effIndex].MiscValue) + switch (effect->MiscValue) { case MECHANIC_BANDAGE: case MECHANIC_SHIELD: @@ -2779,10 +2839,10 @@ bool SpellInfo::_IsPositiveEffect(uint8 effIndex, bool deep) const case SPELL_AURA_ADD_PCT_MODIFIER: { // non-positive mods - switch (Effects[effIndex].MiscValue) + switch (effect->MiscValue) { case SPELLMOD_COST: // dependent from bas point sign (negative -> positive) - if (Effects[effIndex].CalcValue() > 0) + if (effect->CalcValue() > 0) { if (!deep) { @@ -2808,25 +2868,26 @@ bool SpellInfo::_IsPositiveEffect(uint8 effIndex, bool deep) const } default: break; + } + break; + } + default: + break; } - break; - } - default: - break; - } - - // non-positive targets - if (!_IsPositiveTarget(Effects[effIndex].TargetA.GetTarget(), Effects[effIndex].TargetB.GetTarget())) - return false; - // negative spell if triggered spell is negative - if (!deep && !Effects[effIndex].ApplyAuraName && Effects[effIndex].TriggerSpell) - { - if (SpellInfo const* spellTriggeredProto = sSpellMgr->GetSpellInfo(Effects[effIndex].TriggerSpell)) - if (!spellTriggeredProto->_IsPositiveSpell()) + // non-positive targets + if (!_IsPositiveTarget(effect->TargetA.GetTarget(), effect->TargetB.GetTarget())) return false; - } + // negative spell if triggered spell is negative + if (!deep && !effect->ApplyAuraName && effect->TriggerSpell) + { + if (SpellInfo const* spellTriggeredProto = sSpellMgr->GetSpellInfo(effect->TriggerSpell)) + if (!spellTriggeredProto->_IsPositiveSpell()) + return false; + } + } + } // ok, positive return true; } @@ -2948,14 +3009,14 @@ void SpellInfo::_UnloadImplicitTargetConditionLists() // find the same instances of ConditionList and delete them. for (uint32 d = 0; d < DIFFICULTY_MAX; ++d) { - for (uint32 i = 0; i < Effects.size(); ++i) + for (uint32 i = 0; i < _effects.size(); ++i) { if (SpellEffectInfo const* effect = GetEffect(d, i)) { ConditionList* cur = effect->ImplicitTargetConditions; if (!cur) continue; - for (uint8 j = i; j < Effects.size(); ++j) + for (uint8 j = i; j < _effects.size(); ++j) { if (SpellEffectInfo const* eff = GetEffect(d, j)) { @@ -2971,20 +3032,38 @@ void SpellInfo::_UnloadImplicitTargetConditionLists() SpellEffectInfoVector SpellInfo::GetEffectsForDifficulty(uint32 difficulty) const { + SpellEffectInfoVector effList; + + // DIFFICULTY_NONE effects are the default effects, always active if current difficulty's effects don't overwrite + SpellEffectInfoMap::const_iterator itr = _effects.find(DIFFICULTY_NONE); + if (itr != _effects.end()) + effList = itr->second; + // downscale difficulty if original was not found - for (; difficulty >= DIFFICULTY_NONE; --difficulty) + // DIFFICULTY_NONE is already in our list + for (; difficulty > DIFFICULTY_NONE; --difficulty) { - SpellEffectInfoMap::const_iterator itr = Effects.find(difficulty); - if (itr != Effects.end()) - return itr->second; + SpellEffectInfoMap::const_iterator itr = _effects.find(difficulty); + if (itr != _effects.end()) + { + for (SpellEffectInfo const* effect : itr->second) + { + // overwrite any existing effect from DIFFICULTY_NONE + effList[effect->EffectIndex] = effect; + } + // if we found any effect in our difficulty then stop searching + break; + } } - return SpellEffectInfoVector(); + if (effList.empty()) + TC_LOG_ERROR("spells", "GetEffectsForDifficulty did not find any effects for spell %u in difficulty %u", Id, difficulty); + return effList; } SpellEffectInfo const* SpellInfo::GetEffect(uint32 difficulty, uint32 index) const { SpellEffectInfoVector effects = GetEffectsForDifficulty(difficulty); - if (index >= effects.size()) + if (index >= _effects.size()) return nullptr; return effects[index]; diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h index 36c8523dbf2..0383c214944 100644 --- a/src/server/game/Spells/SpellInfo.h +++ b/src/server/game/Spells/SpellInfo.h @@ -302,6 +302,8 @@ private: typedef std::vector<SpellEffectInfo const*> SpellEffectInfoVector; typedef std::unordered_map<uint32, SpellEffectInfoVector> SpellEffectInfoMap; +typedef std::vector<AuraEffect*> AuraEffectVector; + class SpellInfo { public: @@ -448,12 +450,12 @@ public: bool IsAffectingArea(uint32 difficulty) const; bool IsTargetingArea(uint32 difficulty) const; bool NeedsExplicitUnitTarget() const; - bool NeedsToBeTriggeredByCaster(SpellInfo const* triggeringSpell) const; + bool NeedsToBeTriggeredByCaster(SpellInfo const* triggeringSpell, uint32 difficulty) const; bool IsPassive() const; bool IsAutocastable() const; bool IsStackableWithRanks() const; - bool IsPassiveStackableWithRanks() const; + bool IsPassiveStackableWithRanks(uint32 difficulty) const; bool IsMultiSlotAura() const; bool IsStackableOnOneSlotWithDifferentCasters() const; bool IsCooldownStartedOnEvent() const; @@ -488,15 +490,15 @@ public: SpellSchoolMask GetSchoolMask() const; uint32 GetAllEffectsMechanicMask() const; - uint32 GetEffectMechanicMask(uint8 effIndex) const; + uint32 GetEffectMechanicMask(uint32 effIndex) const; uint32 GetSpellMechanicMaskByEffectMask(uint32 effectMask) const; - Mechanics GetEffectMechanic(uint8 effIndex) const; - bool HasAnyEffectMechanic() const; + Mechanics GetEffectMechanic(uint32 effIndex, uint32 difficulty) const; + //bool HasAnyEffectMechanic() const; uint32 GetDispelMask() const; static uint32 GetDispelMask(DispelType type); uint32 GetExplicitTargetMask() const; - AuraStateType GetAuraState() const; + AuraStateType GetAuraState(uint32 difficulty) const; SpellSpecificType GetSpellSpecific() const; float GetMinRange(bool positive = false) const; @@ -505,7 +507,7 @@ public: int32 GetDuration() const; int32 GetMaxDuration() const; - uint32 GetMaxTicks() const; + uint32 GetMaxTicks(uint32 difficulty) const; uint32 CalcCastTime(uint8 level = 0, Spell* spell = NULL) const; uint32 GetRecoveryTime() const; @@ -525,7 +527,7 @@ public: // loading helpers void _InitializeExplicitTargetMask(); - bool _IsPositiveEffect(uint8 effIndex, bool deep) const; + bool _IsPositiveEffect(uint32 effIndex, bool deep) const; bool _IsPositiveSpell() const; static bool _IsPositiveTarget(uint32 targetA, uint32 targetB); @@ -535,7 +537,7 @@ public: SpellEffectInfoVector GetEffectsForDifficulty(uint32 difficulty) const; SpellEffectInfo const* GetEffect(uint32 difficulty, uint32 index) const; - SpellEffectInfoMap Effects; + SpellEffectInfoMap _effects; }; #endif // _SPELLINFO_H |