aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Spells/SpellInfo.cpp
diff options
context:
space:
mode:
authorRat <gmstreetrat@gmail.com>2014-11-17 20:38:56 +0100
committerRat <gmstreetrat@gmail.com>2014-11-17 20:38:56 +0100
commite9f9719af2bce7f3bcbe9b7e449a50f03b3e0513 (patch)
tree6e09a5aad017a43282f6a2787855c25787251bd5 /src/server/game/Spells/SpellInfo.cpp
parent588143b9b69a81eee69d5fb3b9690c8aafc1a38f (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.cpp425
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];