diff options
| author | Rat <gmstreetrat@gmail.com> | 2014-11-17 20:38:56 +0100 |
|---|---|---|
| committer | Rat <gmstreetrat@gmail.com> | 2014-11-17 20:38:56 +0100 |
| commit | e9f9719af2bce7f3bcbe9b7e449a50f03b3e0513 (patch) | |
| tree | 6e09a5aad017a43282f6a2787855c25787251bd5 /src/server/game/Spells/SpellInfo.cpp | |
| parent | 588143b9b69a81eee69d5fb3b9690c8aafc1a38f (diff) | |
Core/Spells: spell system updates (no-compile-version_2)
Diffstat (limited to 'src/server/game/Spells/SpellInfo.cpp')
| -rw-r--r-- | src/server/game/Spells/SpellInfo.cpp | 425 |
1 files changed, 252 insertions, 173 deletions
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]; |
