aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Miscellaneous/SharedDefines.h2
-rw-r--r--src/server/game/Spells/SpellInfo.cpp308
-rw-r--r--src/server/game/Spells/SpellInfo.h189
-rw-r--r--src/server/game/Spells/SpellMgr.cpp270
-rw-r--r--src/server/game/Spells/SpellMgr.h1
-rw-r--r--src/server/game/World/World.cpp3
6 files changed, 532 insertions, 241 deletions
diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h
index e91dbcc6e67..12746ad6b81 100644
--- a/src/server/game/Miscellaneous/SharedDefines.h
+++ b/src/server/game/Miscellaneous/SharedDefines.h
@@ -1262,7 +1262,7 @@ enum SpellEffectName
SPELL_EFFECT_LEARN_GARRISON_BUILDING = 210,
SPELL_EFFECT_LEARN_GARRISON_SPECIALIZATION = 211,
SPELL_EFFECT_REMOVE_AURA_BY_SPELL_LABEL = 212,
- SPELL_EFFECT_JUMP_DEST_2 = 213,
+ SPELL_EFFECT_JUMP_DEST_2 = 213,
SPELL_EFFECT_CREATE_GARRISON = 214,
SPELL_EFFECT_UPGRADE_CHARACTER_SPELLS = 215, // Unlocks boosted players' spells (ChrUpgrade*.db2)
SPELL_EFFECT_CREATE_SHIPMENT = 216,
diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp
index 2e6c6acb76f..53a732c1390 100644
--- a/src/server/game/Spells/SpellInfo.cpp
+++ b/src/server/game/Spells/SpellInfo.cpp
@@ -371,41 +371,40 @@ SpellImplicitTargetInfo::StaticData SpellImplicitTargetInfo::_data[TOTAL_SPELL_
{TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_AREA, TARGET_CHECK_ENEMY, TARGET_DIR_NONE}, // 151
};
-SpellEffectInfo::SpellEffectInfo(SpellInfo const* spellInfo, SpellEffectEntry const* _effect)
+SpellEffectInfo::SpellEffectInfo(SpellInfo const* spellInfo, SpellEffectEntry const& _effect)
: EffectAttributes(SpellEffectAttributes::None)
{
ASSERT(spellInfo);
- ASSERT(_effect);
_spellInfo = spellInfo;
- EffectIndex = _effect->EffectIndex;
- Effect = _effect->Effect;
- ApplyAuraName = _effect->EffectAura;
- ApplyAuraPeriod = _effect->EffectAuraPeriod;
- RealPointsPerLevel = _effect->EffectRealPointsPerLevel;
- BasePoints = _effect->EffectBasePoints;
- PointsPerResource = _effect->EffectPointsPerResource;
- Amplitude = _effect->EffectAmplitude;
- ChainAmplitude = _effect->EffectChainAmplitude;
- BonusCoefficient = _effect->EffectBonusCoefficient;
- MiscValue = _effect->EffectMiscValue[0];
- MiscValueB = _effect->EffectMiscValue[1];
- Mechanic = Mechanics(_effect->EffectMechanic);
- PositionFacing = _effect->EffectPosFacing;
- TargetA = SpellImplicitTargetInfo(_effect->ImplicitTarget[0]);
- TargetB = SpellImplicitTargetInfo(_effect->ImplicitTarget[1]);
- RadiusEntry = sSpellRadiusStore.LookupEntry(_effect->EffectRadiusIndex[0]);
- MaxRadiusEntry = sSpellRadiusStore.LookupEntry(_effect->EffectRadiusIndex[1]);
- ChainTargets = _effect->EffectChainTargets;
- ItemType = _effect->EffectItemType;
- TriggerSpell = _effect->EffectTriggerSpell;
- SpellClassMask = _effect->EffectSpellClassMask;
- BonusCoefficientFromAP = _effect->BonusCoefficientFromAP;
- Scaling.Coefficient = _effect->Coefficient;
- Scaling.Variance = _effect->Variance;
- Scaling.ResourceCoefficient = _effect->ResourceCoefficient;
+ EffectIndex = _effect.EffectIndex;
+ Effect = _effect.Effect;
+ ApplyAuraName = _effect.EffectAura;
+ ApplyAuraPeriod = _effect.EffectAuraPeriod;
+ BasePoints = _effect.EffectBasePoints;
+ RealPointsPerLevel = _effect.EffectRealPointsPerLevel;
+ PointsPerResource = _effect.EffectPointsPerResource;
+ Amplitude = _effect.EffectAmplitude;
+ ChainAmplitude = _effect.EffectChainAmplitude;
+ BonusCoefficient = _effect.EffectBonusCoefficient;
+ MiscValue = _effect.EffectMiscValue[0];
+ MiscValueB = _effect.EffectMiscValue[1];
+ Mechanic = Mechanics(_effect.EffectMechanic);
+ PositionFacing = _effect.EffectPosFacing;
+ TargetA = SpellImplicitTargetInfo(_effect.ImplicitTarget[0]);
+ TargetB = SpellImplicitTargetInfo(_effect.ImplicitTarget[1]);
+ RadiusEntry = sSpellRadiusStore.LookupEntry(_effect.EffectRadiusIndex[0]);
+ MaxRadiusEntry = sSpellRadiusStore.LookupEntry(_effect.EffectRadiusIndex[1]);
+ ChainTargets = _effect.EffectChainTargets;
+ ItemType = _effect.EffectItemType;
+ TriggerSpell = _effect.EffectTriggerSpell;
+ SpellClassMask = _effect.EffectSpellClassMask;
+ BonusCoefficientFromAP = _effect.BonusCoefficientFromAP;
+ Scaling.Coefficient = _effect.Coefficient;
+ Scaling.Variance = _effect.Variance;
+ Scaling.ResourceCoefficient = _effect.ResourceCoefficient;
ImplicitTargetConditions = nullptr;
- EffectAttributes = _effect->GetEffectAttributes();
+ EffectAttributes = _effect.GetEffectAttributes();
}
bool SpellEffectInfo::IsEffect() const
@@ -1081,10 +1080,8 @@ SpellEffectInfo::StaticData SpellEffectInfo::_data[TOTAL_SPELL_EFFECTS] =
};
SpellInfo::SpellInfo(SpellNameEntry const* spellName, ::Difficulty difficulty, SpellInfoLoadHelper const& data, SpellVisualVector&& visuals)
+ : Id(spellName->ID), Difficulty(difficulty)
{
- Id = spellName->ID;
- Difficulty = difficulty;
-
_effects.reserve(32);
for (SpellEffectEntry const* spellEffect : data.Effects)
{
@@ -1094,106 +1091,123 @@ SpellInfo::SpellInfo(SpellNameEntry const* spellName, ::Difficulty difficulty, S
if (uint32(spellEffect->EffectIndex) >= _effects.size())
_effects.resize(spellEffect->EffectIndex + 1);
- _effects[spellEffect->EffectIndex] = new SpellEffectInfo(this, spellEffect);
+ _effects[spellEffect->EffectIndex] = new SpellEffectInfo(this, *spellEffect);
}
_effects.shrink_to_fit();
SpellName = &spellName->Name;
// SpellMiscEntry
- SpellMiscEntry const* _misc = data.Misc;
- Attributes = _misc ? _misc->Attributes[0] : 0;
- AttributesEx = _misc ? _misc->Attributes[1] : 0;
- AttributesEx2 = _misc ? _misc->Attributes[2] : 0;
- AttributesEx3 = _misc ? _misc->Attributes[3] : 0;
- AttributesEx4 = _misc ? _misc->Attributes[4] : 0;
- AttributesEx5 = _misc ? _misc->Attributes[5] : 0;
- AttributesEx6 = _misc ? _misc->Attributes[6] : 0;
- AttributesEx7 = _misc ? _misc->Attributes[7] : 0;
- AttributesEx8 = _misc ? _misc->Attributes[8] : 0;
- AttributesEx9 = _misc ? _misc->Attributes[9] : 0;
- AttributesEx10 = _misc ? _misc->Attributes[10] : 0;
- AttributesEx11 = _misc ? _misc->Attributes[11] : 0;
- AttributesEx12 = _misc ? _misc->Attributes[12] : 0;
- AttributesEx13 = _misc ? _misc->Attributes[13] : 0;
- AttributesEx14 = _misc ? _misc->Attributes[14] : 0;
- CastTimeEntry = _misc ? (_misc->CastingTimeIndex ? sSpellCastTimesStore.LookupEntry(_misc->CastingTimeIndex) : nullptr) : nullptr;
- DurationEntry = _misc ? (_misc->DurationIndex ? sSpellDurationStore.LookupEntry(_misc->DurationIndex) : nullptr) : nullptr;
- RangeIndex = _misc ? _misc->RangeIndex : 0;
- RangeEntry = _misc ? (_misc->RangeIndex ? sSpellRangeStore.LookupEntry(_misc->RangeIndex) : nullptr) : nullptr;
- Speed = _misc ? _misc->Speed : 0;
- LaunchDelay = _misc ? _misc->LaunchDelay : 0;
- SchoolMask = _misc ? _misc->SchoolMask : 0;
- AttributesCu = 0;
- IconFileDataId = _misc ? _misc->SpellIconFileDataID : 0;
- ActiveIconFileDataId = _misc ? _misc->ActiveIconFileDataID : 0;
- ContentTuningId = _misc ? _misc->ContentTuningID : 0;
- ShowFutureSpellPlayerConditionID = _misc ? _misc->ShowFutureSpellPlayerConditionID : 0;
+ if (SpellMiscEntry const* _misc = data.Misc)
+ {
+ Attributes = _misc->Attributes[0];
+ AttributesEx = _misc->Attributes[1];
+ AttributesEx2 = _misc->Attributes[2];
+ AttributesEx3 = _misc->Attributes[3];
+ AttributesEx4 = _misc->Attributes[4];
+ AttributesEx5 = _misc->Attributes[5];
+ AttributesEx6 = _misc->Attributes[6];
+ AttributesEx7 = _misc->Attributes[7];
+ AttributesEx8 = _misc->Attributes[8];
+ AttributesEx9 = _misc->Attributes[9];
+ AttributesEx10 = _misc->Attributes[10];
+ AttributesEx11 = _misc->Attributes[11];
+ AttributesEx12 = _misc->Attributes[12];
+ AttributesEx13 = _misc->Attributes[13];
+ AttributesEx14 = _misc->Attributes[14];
+ CastTimeEntry = sSpellCastTimesStore.LookupEntry(_misc->CastingTimeIndex);
+ DurationEntry = sSpellDurationStore.LookupEntry(_misc->DurationIndex);
+ RangeEntry = sSpellRangeStore.LookupEntry(_misc->RangeIndex);
+ Speed = _misc->Speed;
+ LaunchDelay = _misc->LaunchDelay;
+ SchoolMask = _misc->SchoolMask;
+ IconFileDataId = _misc->SpellIconFileDataID;
+ ActiveIconFileDataId = _misc->ActiveIconFileDataID;
+ ContentTuningId = _misc->ContentTuningID;
+ ShowFutureSpellPlayerConditionID = _misc->ShowFutureSpellPlayerConditionID;
+ }
_visuals = std::move(visuals);
// SpellScalingEntry
- SpellScalingEntry const* _scaling = data.Scaling;
- Scaling.Class = _scaling ? _scaling->Class : 0;
- Scaling.MinScalingLevel = _scaling ? _scaling->MinScalingLevel : 0;
- Scaling.MaxScalingLevel = _scaling ? _scaling->MaxScalingLevel : 0;
- Scaling.ScalesFromItemLevel = _scaling ? _scaling->ScalesFromItemLevel : 0;
+ if (SpellScalingEntry const* _scaling = data.Scaling)
+ {
+ Scaling.Class = _scaling->Class;
+ Scaling.MinScalingLevel = _scaling->MinScalingLevel;
+ Scaling.MaxScalingLevel = _scaling->MaxScalingLevel;
+ Scaling.ScalesFromItemLevel = _scaling->ScalesFromItemLevel;
+ }
// SpellAuraOptionsEntry
- SpellAuraOptionsEntry const* _options = data.AuraOptions;
- SpellProcsPerMinuteEntry const* _ppm = _options ? sSpellProcsPerMinuteStore.LookupEntry(_options->SpellProcsPerMinuteID) : nullptr;
- ProcFlags = _options ? _options->ProcTypeMask[0] : 0;
- ProcChance = _options ? _options->ProcChance : 0;
- ProcCharges = _options ? _options->ProcCharges : 0;
- ProcCooldown = _options ? _options->ProcCategoryRecovery : 0;
- ProcBasePPM = _ppm ? _ppm->BaseProcRate : 0.0f;
- if (_options)
- ProcPPMMods = sDB2Manager.GetSpellProcsPerMinuteMods(_options->SpellProcsPerMinuteID);
- StackAmount = _options ? _options->CumulativeAura : 0;
+ if (SpellAuraOptionsEntry const* _options = data.AuraOptions)
+ {
+ ProcFlags = _options->ProcTypeMask[0];
+ ProcChance = _options->ProcChance;
+ ProcCharges = _options->ProcCharges;
+ ProcCooldown = _options->ProcCategoryRecovery;
+ StackAmount = _options->CumulativeAura;
+ if (SpellProcsPerMinuteEntry const* _ppm = sSpellProcsPerMinuteStore.LookupEntry(_options->SpellProcsPerMinuteID))
+ {
+ ProcBasePPM = _ppm->BaseProcRate;
+ ProcPPMMods = sDB2Manager.GetSpellProcsPerMinuteMods(_ppm->ID);
+ }
+ }
// SpellAuraRestrictionsEntry
- SpellAuraRestrictionsEntry const* _aura = data.AuraRestrictions;
- CasterAuraState = _aura ? _aura->CasterAuraState : 0;
- TargetAuraState = _aura ? _aura->TargetAuraState : 0;
- ExcludeCasterAuraState = _aura ? _aura->ExcludeCasterAuraState : 0;
- ExcludeTargetAuraState = _aura ? _aura->ExcludeTargetAuraState : 0;
- CasterAuraSpell = _aura ? _aura->CasterAuraSpell : 0;
- TargetAuraSpell = _aura ? _aura->TargetAuraSpell : 0;
- ExcludeCasterAuraSpell = _aura ? _aura->ExcludeCasterAuraSpell : 0;
- ExcludeTargetAuraSpell = _aura ? _aura->ExcludeTargetAuraSpell : 0;
+ if (SpellAuraRestrictionsEntry const* _aura = data.AuraRestrictions)
+ {
+ CasterAuraState = _aura->CasterAuraState;
+ TargetAuraState = _aura->TargetAuraState;
+ ExcludeCasterAuraState = _aura->ExcludeCasterAuraState;
+ ExcludeTargetAuraState = _aura->ExcludeTargetAuraState;
+ CasterAuraSpell = _aura->CasterAuraSpell;
+ TargetAuraSpell = _aura->TargetAuraSpell;
+ ExcludeCasterAuraSpell = _aura->ExcludeCasterAuraSpell;
+ ExcludeTargetAuraSpell = _aura->ExcludeTargetAuraSpell;
+ }
// SpellCastingRequirementsEntry
- SpellCastingRequirementsEntry const* _castreq = data.CastingRequirements;
- RequiresSpellFocus = _castreq ? _castreq->RequiresSpellFocus : 0;
- FacingCasterFlags = _castreq ? _castreq->FacingCasterFlags : 0;
- RequiredAreasID = _castreq ? _castreq->RequiredAreasID : -1;
+ if (SpellCastingRequirementsEntry const* _castreq = data.CastingRequirements)
+ {
+ RequiresSpellFocus = _castreq->RequiresSpellFocus;
+ FacingCasterFlags = _castreq->FacingCasterFlags;
+ RequiredAreasID = _castreq->RequiredAreasID;
+ }
// SpellCategoriesEntry
- SpellCategoriesEntry const* _categorie = data.Categories;
- CategoryId = _categorie ? _categorie->Category : 0;
- Dispel = _categorie ? _categorie->DispelType : 0;
- Mechanic = _categorie ? _categorie->Mechanic : 0;
- StartRecoveryCategory = _categorie ? _categorie->StartRecoveryCategory : 0;
- DmgClass = _categorie ? _categorie->DefenseType : 0;
- PreventionType = _categorie ? _categorie->PreventionType : 0;
- ChargeCategoryId = _categorie ? _categorie->ChargeCategory : 0;
+ if (SpellCategoriesEntry const* _categories = data.Categories)
+ {
+ CategoryId = _categories->Category;
+ Dispel = _categories->DispelType;
+ Mechanic = _categories->Mechanic;
+ StartRecoveryCategory = _categories->StartRecoveryCategory;
+ DmgClass = _categories->DefenseType;
+ PreventionType = _categories->PreventionType;
+ ChargeCategoryId = _categories->ChargeCategory;
+ }
// SpellClassOptionsEntry
- SpellClassOptionsEntry const* _class = data.ClassOptions;
- SpellFamilyName = _class ? _class->SpellClassSet : 0;
- SpellFamilyFlags = _class ? _class->SpellClassMask : flag128();
+ if (SpellClassOptionsEntry const* _class = data.ClassOptions)
+ {
+ SpellFamilyName = _class->SpellClassSet;
+ SpellFamilyFlags = _class->SpellClassMask;
+ }
// SpellCooldownsEntry
- SpellCooldownsEntry const* _cooldowns = data.Cooldowns;
- RecoveryTime = _cooldowns ? _cooldowns->RecoveryTime : 0;
- CategoryRecoveryTime = _cooldowns ? _cooldowns->CategoryRecoveryTime : 0;
- StartRecoveryTime = _cooldowns ? _cooldowns->StartRecoveryTime : 0;
+ if (SpellCooldownsEntry const* _cooldowns = data.Cooldowns)
+ {
+ RecoveryTime = _cooldowns->RecoveryTime;
+ CategoryRecoveryTime = _cooldowns->CategoryRecoveryTime;
+ StartRecoveryTime = _cooldowns->StartRecoveryTime;
+ }
// SpellEquippedItemsEntry
- SpellEquippedItemsEntry const* _equipped = data.EquippedItems;
- EquippedItemClass = _equipped ? _equipped->EquippedItemClass : -1;
- EquippedItemSubClassMask = _equipped ?_equipped->EquippedItemSubclass : 0;
- EquippedItemInventoryTypeMask = _equipped ? _equipped->EquippedItemInvTypes : 0;
+ if (SpellEquippedItemsEntry const* _equipped = data.EquippedItems)
+ {
+ EquippedItemClass = _equipped->EquippedItemClass;
+ EquippedItemSubClassMask = _equipped->EquippedItemSubclass;
+ EquippedItemInventoryTypeMask = _equipped->EquippedItemInvTypes;
+ }
// SpellInterruptsEntry
if (SpellInterruptsEntry const* _interrupt = data.Interrupts)
@@ -1202,57 +1216,65 @@ SpellInfo::SpellInfo(SpellNameEntry const* spellName, ::Difficulty difficulty, S
std::copy(std::begin(_interrupt->AuraInterruptFlags), std::end(_interrupt->AuraInterruptFlags), AuraInterruptFlags.begin());
std::copy(std::begin(_interrupt->ChannelInterruptFlags), std::end(_interrupt->ChannelInterruptFlags), ChannelInterruptFlags.begin());
}
- else
- {
- InterruptFlags = 0;
- AuraInterruptFlags.fill(0);
- ChannelInterruptFlags.fill(0);
- }
// SpellLevelsEntry
- SpellLevelsEntry const* _levels = data.Levels;
- MaxLevel = _levels ? _levels->MaxLevel : 0;
- BaseLevel = _levels ? _levels->BaseLevel : 0;
- SpellLevel = _levels ? _levels->SpellLevel : 0;
+ if (SpellLevelsEntry const* _levels = data.Levels)
+ {
+ MaxLevel = _levels->MaxLevel;
+ BaseLevel = _levels->BaseLevel;
+ SpellLevel = _levels->SpellLevel;
+ }
// SpellPowerEntry
PowerCosts = data.Powers;
// SpellReagentsEntry
- SpellReagentsEntry const* _reagents = data.Reagents;
- for (uint8 i = 0; i < MAX_SPELL_REAGENTS; ++i)
- Reagent[i] = _reagents ? _reagents->Reagent[i] : 0;
- for (uint8 i = 0; i < MAX_SPELL_REAGENTS; ++i)
- ReagentCount[i] = _reagents ? _reagents->ReagentCount[i] : 0;
+ if (SpellReagentsEntry const* _reagents = data.Reagents)
+ {
+ std::copy(std::begin(_reagents->Reagent), std::end(_reagents->Reagent), Reagent.begin());
+ std::copy(std::begin(_reagents->ReagentCount), std::end(_reagents->ReagentCount), ReagentCount.begin());
+ }
// SpellShapeshiftEntry
- SpellShapeshiftEntry const* _shapeshift = data.Shapeshift;
- Stances = _shapeshift ? MAKE_PAIR64(_shapeshift->ShapeshiftMask[0], _shapeshift->ShapeshiftMask[1]) : 0;
- StancesNot = _shapeshift ? MAKE_PAIR64(_shapeshift->ShapeshiftExclude[0], _shapeshift->ShapeshiftExclude[1]) : 0;
+ if (SpellShapeshiftEntry const* _shapeshift = data.Shapeshift)
+ {
+ Stances = MAKE_PAIR64(_shapeshift->ShapeshiftMask[0], _shapeshift->ShapeshiftMask[1]);
+ StancesNot = MAKE_PAIR64(_shapeshift->ShapeshiftExclude[0], _shapeshift->ShapeshiftExclude[1]);
+ }
// SpellTargetRestrictionsEntry
- SpellTargetRestrictionsEntry const* _target = data.TargetRestrictions;
- ConeAngle = _target ? _target->ConeDegrees : 0.f;
- Width = _target ? _target->Width : 0.f;
- Targets = _target ? _target->Targets : 0;
- TargetCreatureType = _target ? _target->TargetCreatureType : 0;
- MaxAffectedTargets = _target ? _target->MaxTargets : 0;
- MaxTargetLevel = _target ? _target->MaxTargetLevel : 0;
+ if (SpellTargetRestrictionsEntry const* _target = data.TargetRestrictions)
+ {
+ ConeAngle = _target->ConeDegrees;
+ Width = _target->Width;
+ Targets = _target->Targets;
+ TargetCreatureType = _target->TargetCreatureType;
+ MaxAffectedTargets = _target->MaxTargets;
+ MaxTargetLevel = _target->MaxTargetLevel;
+ }
// SpellTotemsEntry
- SpellTotemsEntry const* _totem = data.Totems;
- for (uint8 i = 0; i < 2; ++i)
- TotemCategory[i] = _totem ? _totem->RequiredTotemCategoryID[i] : 0;
- for (uint8 i = 0; i < 2; ++i)
- Totem[i] = _totem ? _totem->Totem[i] : 0;
+ if (SpellTotemsEntry const* _totem = data.Totems)
+ {
+ std::copy(std::begin(_totem->RequiredTotemCategoryID), std::end(_totem->RequiredTotemCategoryID), TotemCategory.begin());
+ std::copy(std::begin(_totem->Totem), std::end(_totem->Totem), Totem.begin());
+ }
+}
- ChainEntry = nullptr;
- ExplicitTargetMask = 0;
+SpellInfo::SpellInfo(SpellNameEntry const* spellName, ::Difficulty difficulty, std::vector<SpellEffectEntry> const& effects)
+ : Id(spellName->ID), Difficulty(difficulty)
+{
+ SpellName = &spellName->Name;
- _spellSpecific = SPELL_SPECIFIC_NORMAL;
- _auraState = AURA_STATE_NONE;
+ _effects.reserve(32);
+ for (SpellEffectEntry const& spellEffect : effects)
+ {
+ if (uint32(spellEffect.EffectIndex) >= _effects.size())
+ _effects.resize(spellEffect.EffectIndex + 1);
- _allowedMechanicMask = 0;
+ _effects[spellEffect.EffectIndex] = new SpellEffectInfo(this, spellEffect);
+ }
+ _effects.shrink_to_fit();
}
SpellInfo::~SpellInfo()
diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h
index 85ff0682e26..5b129755826 100644
--- a/src/server/game/Spells/SpellInfo.h
+++ b/src/server/game/Spells/SpellInfo.h
@@ -334,8 +334,8 @@ public:
uint32 Effect;
uint32 ApplyAuraName;
uint32 ApplyAuraPeriod;
- float RealPointsPerLevel;
int32 BasePoints;
+ float RealPointsPerLevel;
float PointsPerResource;
float Amplitude;
float ChainAmplitude;
@@ -364,11 +364,12 @@ public:
} Scaling;
SpellEffectInfo() : _spellInfo(nullptr), EffectIndex(0), Effect(0), ApplyAuraName(0), ApplyAuraPeriod(0),
- RealPointsPerLevel(0), BasePoints(0), PointsPerResource(0), Amplitude(0), ChainAmplitude(0),
+ BasePoints(0), RealPointsPerLevel(0), PointsPerResource(0), Amplitude(0), ChainAmplitude(0),
BonusCoefficient(0), MiscValue(0), MiscValueB(0), Mechanic(MECHANIC_NONE), PositionFacing(0),
- RadiusEntry(nullptr), ChainTargets(0), ItemType(0), TriggerSpell(0), BonusCoefficientFromAP(0.0f),
- ImplicitTargetConditions(nullptr), EffectAttributes(SpellEffectAttributes::None) { }
- SpellEffectInfo(SpellInfo const* spellInfo, SpellEffectEntry const* effect);
+ RadiusEntry(nullptr), MaxRadiusEntry(nullptr), ChainTargets(0), ItemType(0), TriggerSpell(0),
+ BonusCoefficientFromAP(0.0f), ImplicitTargetConditions(nullptr),
+ EffectAttributes(SpellEffectAttributes::None), Scaling() { }
+ SpellEffectInfo(SpellInfo const* spellInfo, SpellEffectEntry const& effect);
bool IsEffect() const;
bool IsEffect(SpellEffectName effectName) const;
@@ -440,103 +441,103 @@ class TC_GAME_API SpellInfo
friend class SpellMgr;
public:
- uint32 Id;
- ::Difficulty Difficulty;
- uint32 CategoryId;
- uint32 Dispel;
- uint32 Mechanic;
- uint32 Attributes;
- uint32 AttributesEx;
- uint32 AttributesEx2;
- uint32 AttributesEx3;
- uint32 AttributesEx4;
- uint32 AttributesEx5;
- uint32 AttributesEx6;
- uint32 AttributesEx7;
- uint32 AttributesEx8;
- uint32 AttributesEx9;
- uint32 AttributesEx10;
- uint32 AttributesEx11;
- uint32 AttributesEx12;
- uint32 AttributesEx13;
- uint32 AttributesEx14;
- uint32 AttributesCu;
+ uint32 const Id = 0;
+ ::Difficulty const Difficulty = DIFFICULTY_NONE;
+ uint32 CategoryId = 0;
+ uint32 Dispel = 0;
+ uint32 Mechanic = 0;
+ uint32 Attributes = 0;
+ uint32 AttributesEx = 0;
+ uint32 AttributesEx2 = 0;
+ uint32 AttributesEx3 = 0;
+ uint32 AttributesEx4 = 0;
+ uint32 AttributesEx5 = 0;
+ uint32 AttributesEx6 = 0;
+ uint32 AttributesEx7 = 0;
+ uint32 AttributesEx8 = 0;
+ uint32 AttributesEx9 = 0;
+ uint32 AttributesEx10 = 0;
+ uint32 AttributesEx11 = 0;
+ uint32 AttributesEx12 = 0;
+ uint32 AttributesEx13 = 0;
+ uint32 AttributesEx14 = 0;
+ uint32 AttributesCu = 0;
std::bitset<MAX_SPELL_EFFECTS> NegativeEffects;
- uint64 Stances;
- uint64 StancesNot;
- uint32 Targets;
- uint32 TargetCreatureType;
- uint32 RequiresSpellFocus;
- uint32 FacingCasterFlags;
- uint32 CasterAuraState;
- uint32 TargetAuraState;
- uint32 ExcludeCasterAuraState;
- uint32 ExcludeTargetAuraState;
- uint32 CasterAuraSpell;
- uint32 TargetAuraSpell;
- uint32 ExcludeCasterAuraSpell;
- uint32 ExcludeTargetAuraSpell;
- SpellCastTimesEntry const* CastTimeEntry;
- uint32 RecoveryTime;
- uint32 CategoryRecoveryTime;
- uint32 StartRecoveryCategory;
- uint32 StartRecoveryTime;
- uint32 InterruptFlags;
- std::array<uint32, MAX_SPELL_AURA_INTERRUPT_FLAGS> AuraInterruptFlags;
- std::array<uint32, MAX_SPELL_AURA_INTERRUPT_FLAGS> ChannelInterruptFlags;
- uint32 ProcFlags;
- uint32 ProcChance;
- uint32 ProcCharges;
- uint32 ProcCooldown;
- float ProcBasePPM;
+ uint64 Stances = 0;
+ uint64 StancesNot = 0;
+ uint32 Targets = 0;
+ uint32 TargetCreatureType = 0;
+ uint32 RequiresSpellFocus = 0;
+ uint32 FacingCasterFlags = 0;
+ uint32 CasterAuraState = 0;
+ uint32 TargetAuraState = 0;
+ uint32 ExcludeCasterAuraState = 0;
+ uint32 ExcludeTargetAuraState = 0;
+ uint32 CasterAuraSpell = 0;
+ uint32 TargetAuraSpell = 0;
+ uint32 ExcludeCasterAuraSpell = 0;
+ uint32 ExcludeTargetAuraSpell = 0;
+ SpellCastTimesEntry const* CastTimeEntry = nullptr;
+ uint32 RecoveryTime = 0;
+ uint32 CategoryRecoveryTime = 0;
+ uint32 StartRecoveryCategory = 0;
+ uint32 StartRecoveryTime = 0;
+ uint32 InterruptFlags = 0;
+ std::array<uint32, MAX_SPELL_AURA_INTERRUPT_FLAGS> AuraInterruptFlags = {};
+ std::array<uint32, MAX_SPELL_AURA_INTERRUPT_FLAGS> ChannelInterruptFlags = {};
+ uint32 ProcFlags = 0;
+ uint32 ProcChance = 0;
+ uint32 ProcCharges = 0;
+ uint32 ProcCooldown = 0;
+ float ProcBasePPM = 0.0f;
std::vector<SpellProcsPerMinuteModEntry const*> ProcPPMMods;
- uint32 MaxLevel;
- uint32 BaseLevel;
- uint32 SpellLevel;
- SpellDurationEntry const* DurationEntry;
- std::array<SpellPowerEntry const*, MAX_POWERS_PER_SPELL> PowerCosts;
- uint32 RangeIndex;
- SpellRangeEntry const* RangeEntry;
- float Speed;
- float LaunchDelay;
- uint32 StackAmount;
- uint32 Totem[MAX_SPELL_TOTEMS];
- int32 Reagent[MAX_SPELL_REAGENTS];
- uint32 ReagentCount[MAX_SPELL_REAGENTS];
- int32 EquippedItemClass;
- int32 EquippedItemSubClassMask;
- int32 EquippedItemInventoryTypeMask;
- uint32 TotemCategory[MAX_SPELL_TOTEMS];
- uint32 IconFileDataId;
- uint32 ActiveIconFileDataId;
- uint32 ContentTuningId;
- uint32 ShowFutureSpellPlayerConditionID;
- LocalizedString const* SpellName;
- float ConeAngle;
- float Width;
- uint32 MaxTargetLevel;
- uint32 MaxAffectedTargets;
- uint32 SpellFamilyName;
+ uint32 MaxLevel = 0;
+ uint32 BaseLevel = 0;
+ uint32 SpellLevel = 0;
+ SpellDurationEntry const* DurationEntry = nullptr;
+ std::array<SpellPowerEntry const*, MAX_POWERS_PER_SPELL> PowerCosts = {};
+ SpellRangeEntry const* RangeEntry = nullptr;
+ float Speed = 0.0f;
+ float LaunchDelay = 0.0f;
+ uint32 StackAmount = 0;
+ std::array<uint32, MAX_SPELL_TOTEMS> Totem = {};
+ std::array<uint32, MAX_SPELL_TOTEMS> TotemCategory = {};
+ std::array<int32, MAX_SPELL_REAGENTS> Reagent = {};
+ std::array<uint32, MAX_SPELL_REAGENTS> ReagentCount = {};
+ int32 EquippedItemClass = -1;
+ int32 EquippedItemSubClassMask = 0;
+ int32 EquippedItemInventoryTypeMask = 0;
+ uint32 IconFileDataId = 0;
+ uint32 ActiveIconFileDataId = 0;
+ uint32 ContentTuningId = 0;
+ uint32 ShowFutureSpellPlayerConditionID = 0;
+ LocalizedString const* SpellName = nullptr;
+ float ConeAngle = 0.0f;
+ float Width = 0.0f;
+ uint32 MaxTargetLevel = 0;
+ uint32 MaxAffectedTargets = 0;
+ uint32 SpellFamilyName = 0;
flag128 SpellFamilyFlags;
- uint32 DmgClass;
- uint32 PreventionType;
- int32 RequiredAreasID;
- uint32 SchoolMask;
- uint32 ChargeCategoryId;
+ uint32 DmgClass = 0;
+ uint32 PreventionType = 0;
+ int32 RequiredAreasID = -1;
+ uint32 SchoolMask = 0;
+ uint32 ChargeCategoryId = 0;
// SpellScalingEntry
struct ScalingInfo
{
- int32 Class;
- uint32 MinScalingLevel;
- uint32 MaxScalingLevel;
- uint32 ScalesFromItemLevel;
+ int32 Class = 0;
+ uint32 MinScalingLevel = 0;
+ uint32 MaxScalingLevel = 0;
+ uint32 ScalesFromItemLevel = 0;
} Scaling;
- uint32 ExplicitTargetMask;
- SpellChainNode const* ChainEntry;
+ uint32 ExplicitTargetMask = 0;
+ SpellChainNode const* ChainEntry = nullptr;
SpellInfo(SpellNameEntry const* spellName, ::Difficulty difficulty, SpellInfoLoadHelper const& data, SpellVisualVector&& visuals);
+ SpellInfo(SpellNameEntry const* spellName, ::Difficulty difficulty, std::vector<SpellEffectEntry> const& effects);
~SpellInfo();
uint32 GetCategory() const;
@@ -711,11 +712,11 @@ class TC_GAME_API SpellInfo
private:
SpellEffectInfoVector _effects;
SpellVisualVector _visuals;
- SpellSpecificType _spellSpecific;
- AuraStateType _auraState;
+ SpellSpecificType _spellSpecific = SPELL_SPECIFIC_NORMAL;
+ AuraStateType _auraState = AURA_STATE_NONE;
SpellDiminishInfo _diminishInfo;
- uint32 _allowedMechanicMask;
+ uint32 _allowedMechanicMask = 0;
};
#endif // _SPELLINFO_H
diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp
index 295c4331fc2..8a907aacf66 100644
--- a/src/server/game/Spells/SpellMgr.cpp
+++ b/src/server/game/Spells/SpellMgr.cpp
@@ -49,17 +49,50 @@ namespace
boost::multi_index::tag<SpellIdDifficultyIndex>,
boost::multi_index::composite_key<
SpellInfo,
- boost::multi_index::member<SpellInfo, uint32, &SpellInfo::Id>,
- boost::multi_index::member<SpellInfo, Difficulty, &SpellInfo::Difficulty>
+ boost::multi_index::member<SpellInfo, uint32 const, &SpellInfo::Id>,
+ boost::multi_index::member<SpellInfo, Difficulty const, &SpellInfo::Difficulty>
>
>,
boost::multi_index::hashed_non_unique<
boost::multi_index::tag<SpellIdIndex>,
- boost::multi_index::member<SpellInfo, uint32, &SpellInfo::Id>
+ boost::multi_index::member<SpellInfo, uint32 const, &SpellInfo::Id>
>
>
> mSpellInfoMap;
+ struct ServersideSpellName
+ {
+ explicit ServersideSpellName(uint32 id, std::string name) : NameStorage(std::move(name))
+ {
+ Name.ID = id;
+ InitPointers();
+ }
+
+ ServersideSpellName(ServersideSpellName const& right) : NameStorage(right.NameStorage)
+ {
+ Name.ID = right.Name.ID;
+ InitPointers();
+ }
+
+ ServersideSpellName(ServersideSpellName&& right) noexcept : NameStorage(std::move(right.NameStorage))
+ {
+ Name.ID = right.Name.ID;
+ InitPointers();
+ right.InitPointers();
+ }
+
+ SpellNameEntry Name;
+ std::string NameStorage;
+
+ private:
+ void InitPointers()
+ {
+ std::fill(std::begin(Name.Name.Str), std::end(Name.Name.Str), NameStorage.c_str());
+ }
+ };
+
+ std::vector<ServersideSpellName> mServersideSpellNames;
+
std::unordered_map<std::pair<uint32, Difficulty>, SpellProcEntry> mSpellProcMap;
}
@@ -2585,6 +2618,7 @@ void SpellMgr::LoadSpellInfoStore()
void SpellMgr::UnloadSpellInfoStore()
{
mSpellInfoMap.clear();
+ mServersideSpellNames.clear();
}
void SpellMgr::UnloadSpellInfoImplicitTargetConditionLists()
@@ -2593,6 +2627,236 @@ void SpellMgr::UnloadSpellInfoImplicitTargetConditionLists()
const_cast<SpellInfo&>(spellInfo)._UnloadImplicitTargetConditionLists();
}
+void SpellMgr::LoadSpellInfoServerside()
+{
+ uint32 oldMSTime = getMSTime();
+
+ std::unordered_map<std::pair<uint32, Difficulty>, std::vector<SpellEffectEntry>> spellEffects;
+
+ // 0 1 2 3 4 5 6
+ QueryResult effectsResult = WorldDatabase.Query("SELECT SpellID, EffectIndex, DifficultyID, Effect, EffectAura, EffectAmplitude, EffectAttributes, "
+ // 7 8 9 10 11 12 13
+ "EffectAuraPeriod, EffectBonusCoefficient, EffectChainAmplitude, EffectChainTargets, EffectItemType, EffectMechanic, EffectPointsPerResource, "
+ // 14 15 16 17 18 19 20
+ "EffectPosFacing, EffectRealPointsPerLevel, EffectTriggerSpell, BonusCoefficientFromAP, PvpMultiplier, Coefficient, Variance, "
+ // 21 22 23 24 25 26
+ "ResourceCoefficient, GroupSizeBasePointsCoefficient, EffectBasePoints, EffectMiscValue1, EffectMiscValue2, EffectRadiusIndex1, "
+ // 27 28 29 30 31 32
+ "EffectRadiusIndex2, EffectSpellClassMask1, EffectSpellClassMask2, EffectSpellClassMask3, EffectSpellClassMask4, ImplicitTarget1, "
+ // 33
+ "ImplicitTarget2 FROM serverside_spell_effect");
+ if (effectsResult)
+ {
+ do
+ {
+ Field* fields = effectsResult->Fetch();
+ uint32 spellId = fields[0].GetUInt32();
+ Difficulty difficulty = Difficulty(fields[2].GetUInt32());
+ SpellEffectEntry effect{ };
+ effect.EffectIndex = fields[1].GetInt32();
+ effect.Effect = fields[3].GetInt32();
+ effect.EffectAura = fields[4].GetInt16();
+ effect.EffectAmplitude = fields[5].GetFloat();
+ effect.EffectAttributes = fields[6].GetInt32();
+ effect.EffectAuraPeriod = fields[7].GetInt32();
+ effect.EffectBonusCoefficient = fields[8].GetFloat();
+ effect.EffectChainAmplitude = fields[9].GetFloat();
+ effect.EffectChainTargets = fields[10].GetInt32();
+ effect.EffectItemType = fields[11].GetInt32();
+ effect.EffectMechanic = Mechanics(fields[12].GetInt32());
+ effect.EffectPointsPerResource = fields[13].GetFloat();
+ effect.EffectPosFacing = fields[14].GetFloat();
+ effect.EffectRealPointsPerLevel = fields[15].GetFloat();
+ effect.EffectTriggerSpell = fields[16].GetInt32();
+ effect.BonusCoefficientFromAP = fields[17].GetFloat();
+ effect.PvpMultiplier = fields[18].GetFloat();
+ effect.Coefficient = fields[19].GetFloat();
+ effect.Variance = fields[20].GetFloat();
+ effect.ResourceCoefficient = fields[21].GetFloat();
+ effect.GroupSizeBasePointsCoefficient = fields[22].GetFloat();
+ effect.EffectBasePoints = fields[23].GetFloat();
+ effect.EffectMiscValue[0] = fields[24].GetInt32();
+ effect.EffectMiscValue[1] = fields[25].GetInt32();
+ effect.EffectRadiusIndex[0] = fields[26].GetUInt32();
+ effect.EffectRadiusIndex[1] = fields[27].GetUInt32();
+ effect.EffectSpellClassMask = flag128(fields[28].GetInt32(), fields[29].GetInt32(), fields[30].GetInt32(), fields[31].GetInt32());
+ effect.ImplicitTarget[0] = fields[32].GetInt16();
+ effect.ImplicitTarget[1] = fields[33].GetInt16();
+
+ auto existingSpellBounds = _GetSpellInfo(spellId);
+ if (existingSpellBounds.begin() != existingSpellBounds.end())
+ {
+ TC_LOG_ERROR("sql.sql", "Serverside spell %u difficulty %u effext index %u references a regular spell loaded from file. Adding serverside effects to existing spells is not allowed.",
+ spellId, uint32(difficulty), effect.EffectIndex);
+ continue;
+ }
+
+ if (difficulty != DIFFICULTY_NONE && !sDifficultyStore.HasRecord(difficulty))
+ {
+ TC_LOG_ERROR("sql.sql", "Serverside spell %u effect index %u references non-existing difficulty %u, skipped",
+ spellId, effect.EffectIndex, uint32(difficulty));
+ continue;
+ }
+
+ if (effect.EffectIndex >= MAX_SPELL_EFFECTS)
+ {
+ TC_LOG_ERROR("sql.sql", "Serverside spell %u difficulty %u has more than 32 effects, effect at index %u skipped",
+ spellId, uint32(difficulty), effect.EffectIndex);
+ continue;
+ }
+
+ if (effect.Effect >= TOTAL_SPELL_EFFECTS)
+ {
+ TC_LOG_ERROR("sql.sql", "Serverside spell %u difficulty %u has invalid effect type %u at index %u, skipped",
+ spellId, uint32(difficulty), effect.Effect, effect.EffectIndex);
+ continue;
+ }
+
+ if (effect.EffectAura >= int32(TOTAL_AURAS))
+ {
+ TC_LOG_ERROR("sql.sql", "Serverside spell %u difficulty %u has invalid aura type %u at index %u, skipped",
+ spellId, uint32(difficulty), effect.EffectAura, effect.EffectIndex);
+ continue;
+ }
+
+ if (effect.ImplicitTarget[0] >= TOTAL_SPELL_TARGETS)
+ {
+ TC_LOG_ERROR("sql.sql", "Serverside spell %u difficulty %u has invalid targetA type %u at index %u, skipped",
+ spellId, uint32(difficulty), effect.ImplicitTarget[0], effect.EffectIndex);
+ continue;
+ }
+
+ if (effect.ImplicitTarget[1] >= TOTAL_SPELL_TARGETS)
+ {
+ TC_LOG_ERROR("sql.sql", "Serverside spell %u difficulty %u has invalid targetB type %u at index %u, skipped",
+ spellId, uint32(difficulty), effect.ImplicitTarget[1], effect.EffectIndex);
+ continue;
+ }
+
+ if (effect.EffectRadiusIndex[0] && !sSpellRadiusStore.HasRecord(effect.EffectRadiusIndex[0]))
+ {
+ TC_LOG_ERROR("sql.sql", "Serverside spell %u difficulty %u has invalid radius id %u at index %u, set to 0",
+ spellId, uint32(difficulty), effect.EffectRadiusIndex[0], effect.EffectIndex);
+ }
+
+ if (effect.EffectRadiusIndex[1] && !sSpellRadiusStore.HasRecord(effect.EffectRadiusIndex[1]))
+ {
+ TC_LOG_ERROR("sql.sql", "Serverside spell %u difficulty %u has invalid max radius id %u at index %u, set to 0",
+ spellId, uint32(difficulty), effect.EffectRadiusIndex[1], effect.EffectIndex);
+ }
+
+ spellEffects[{ spellId, difficulty }].push_back(std::move(effect));
+
+ } while (effectsResult->NextRow());
+ }
+
+ // 0 1 2 3 4 5 6 7 8
+ QueryResult spellsResult = WorldDatabase.Query("SELECT Id, DifficultyID, CategoryId, Dispel, Mechanic, Attributes, AttributesEx, AttributesEx2, AttributesEx3, "
+ // 9 10 11 12 13 14 15 16 17 18
+ "AttributesEx4, AttributesEx5, AttributesEx6, AttributesEx7, AttributesEx8, AttributesEx9, AttributesEx10, AttributesEx11, AttributesEx12, AttributesEx13, "
+ // 19 20 21 22 23 24 25 26 27
+ "AttributesEx14, Stances, StancesNot, Targets, TargetCreatureType, RequiresSpellFocus, FacingCasterFlags, CasterAuraState, TargetAuraState, "
+ // 28 29 30 31 32 33 34
+ "ExcludeCasterAuraState, ExcludeTargetAuraState, CasterAuraSpell, TargetAuraSpell, ExcludeCasterAuraSpell, ExcludeTargetAuraSpell, CastingTimeIndex, "
+ // 35 36 37 38 39 40 41
+ "RecoveryTime, CategoryRecoveryTime, StartRecoveryCategory, StartRecoveryTime, InterruptFlags, AuraInterruptFlags1, AuraInterruptFlags2, "
+ // 42 43 44 45 46 47 48 49 50 51
+ "ChannelInterruptFlags1, ChannelInterruptFlags2, ProcFlags, ProcChance, ProcCharges, ProcCooldown, ProcBasePPM, MaxLevel, BaseLevel, SpellLevel, "
+ // 52 53 54 55 56 57 58 59 60
+ "DurationIndex, RangeIndex, Speed, LaunchDelay, StackAmount, EquippedItemClass, EquippedItemSubClassMask, EquippedItemInventoryTypeMask, ContentTuningId, "
+ // 61 62 63 64 65 66 67 68 69 70
+ "SpellName, ConeAngle, ConeWidth, MaxTargetLevel, MaxAffectedTargets, SpellFamilyName, SpellFamilyFlags1, SpellFamilyFlags2, SpellFamilyFlags3, SpellFamilyFlags4, "
+ // 71 72 73 74 75
+ "DmgClass, PreventionType, AreaGroupId, SchoolMask, ChargeCategoryId FROM serverside_spell");
+ if (spellsResult)
+ {
+ mServersideSpellNames.reserve(spellsResult->GetRowCount());
+
+ do
+ {
+ Field* fields = spellsResult->Fetch();
+ uint32 spellId = fields[0].GetUInt32();
+ Difficulty difficulty = Difficulty(fields[2].GetUInt32());
+ mServersideSpellNames.emplace_back(spellId, fields[61].GetString());
+
+ SpellInfo& spellInfo = const_cast<SpellInfo&>(*mSpellInfoMap.emplace(&mServersideSpellNames.back().Name, difficulty, spellEffects[{ spellId, difficulty }]).first);
+ spellInfo.CategoryId = fields[2].GetUInt32();
+ spellInfo.Dispel = fields[3].GetUInt32();
+ spellInfo.Mechanic = fields[4].GetUInt32();
+ spellInfo.Attributes = fields[5].GetUInt32();
+ spellInfo.AttributesEx = fields[6].GetUInt32();
+ spellInfo.AttributesEx2 = fields[7].GetUInt32();
+ spellInfo.AttributesEx3 = fields[8].GetUInt32();
+ spellInfo.AttributesEx4 = fields[9].GetUInt32();
+ spellInfo.AttributesEx5 = fields[10].GetUInt32();
+ spellInfo.AttributesEx6 = fields[11].GetUInt32();
+ spellInfo.AttributesEx7 = fields[12].GetUInt32();
+ spellInfo.AttributesEx8 = fields[13].GetUInt32();
+ spellInfo.AttributesEx9 = fields[14].GetUInt32();
+ spellInfo.AttributesEx10 = fields[15].GetUInt32();
+ spellInfo.AttributesEx11 = fields[16].GetUInt32();
+ spellInfo.AttributesEx12 = fields[17].GetUInt32();
+ spellInfo.AttributesEx13 = fields[18].GetUInt32();
+ spellInfo.AttributesEx14 = fields[19].GetUInt32();
+ spellInfo.Stances = fields[20].GetUInt64();
+ spellInfo.StancesNot = fields[21].GetUInt64();
+ spellInfo.Targets = fields[22].GetUInt32();
+ spellInfo.TargetCreatureType = fields[23].GetUInt32();
+ spellInfo.RequiresSpellFocus = fields[24].GetUInt32();
+ spellInfo.FacingCasterFlags = fields[25].GetUInt32();
+ spellInfo.CasterAuraState = fields[26].GetUInt32();
+ spellInfo.TargetAuraState = fields[27].GetUInt32();
+ spellInfo.ExcludeCasterAuraState = fields[28].GetUInt32();
+ spellInfo.ExcludeTargetAuraState = fields[29].GetUInt32();
+ spellInfo.CasterAuraSpell = fields[30].GetUInt32();
+ spellInfo.TargetAuraSpell = fields[31].GetUInt32();
+ spellInfo.ExcludeCasterAuraSpell = fields[32].GetUInt32();
+ spellInfo.ExcludeTargetAuraSpell = fields[33].GetUInt32();
+ spellInfo.CastTimeEntry = sSpellCastTimesStore.LookupEntry(fields[34].GetUInt32());
+ spellInfo.RecoveryTime = fields[35].GetUInt32();
+ spellInfo.CategoryRecoveryTime = fields[36].GetUInt32();
+ spellInfo.StartRecoveryCategory = fields[37].GetUInt32();
+ spellInfo.StartRecoveryTime = fields[38].GetUInt32();
+ spellInfo.InterruptFlags = fields[39].GetUInt32();
+ spellInfo.AuraInterruptFlags[0] = fields[40].GetUInt32();
+ spellInfo.AuraInterruptFlags[1] = fields[41].GetUInt32();
+ spellInfo.ChannelInterruptFlags[0] = fields[42].GetUInt32();
+ spellInfo.ChannelInterruptFlags[1] = fields[43].GetUInt32();
+ spellInfo.ProcFlags = fields[44].GetUInt32();
+ spellInfo.ProcChance = fields[45].GetUInt32();
+ spellInfo.ProcCharges = fields[46].GetUInt32();
+ spellInfo.ProcCooldown = fields[47].GetUInt32();
+ spellInfo.ProcBasePPM = fields[48].GetFloat();
+ spellInfo.MaxLevel = fields[49].GetUInt32();
+ spellInfo.BaseLevel = fields[50].GetUInt32();
+ spellInfo.SpellLevel = fields[51].GetUInt32();
+ spellInfo.DurationEntry = sSpellDurationStore.LookupEntry(fields[52].GetUInt32());
+ spellInfo.RangeEntry = sSpellRangeStore.LookupEntry(fields[53].GetUInt32());
+ spellInfo.Speed = fields[54].GetFloat();
+ spellInfo.LaunchDelay = fields[55].GetFloat();
+ spellInfo.StackAmount = fields[56].GetUInt32();
+ spellInfo.EquippedItemClass = fields[57].GetInt32();
+ spellInfo.EquippedItemSubClassMask = fields[58].GetInt32();
+ spellInfo.EquippedItemInventoryTypeMask = fields[59].GetInt32();
+ spellInfo.ContentTuningId = fields[60].GetUInt32();
+ spellInfo.ConeAngle = fields[62].GetFloat();
+ spellInfo.Width = fields[63].GetFloat();
+ spellInfo.MaxTargetLevel = fields[64].GetUInt32();
+ spellInfo.MaxAffectedTargets = fields[65].GetUInt32();
+ spellInfo.SpellFamilyName = fields[66].GetUInt32();
+ spellInfo.SpellFamilyFlags = flag128(fields[67].GetUInt32(), fields[68].GetUInt32(), fields[69].GetUInt32(), fields[70].GetUInt32());
+ spellInfo.DmgClass = fields[71].GetUInt32();
+ spellInfo.PreventionType = fields[72].GetUInt32();
+ spellInfo.RequiredAreasID = fields[73].GetInt32();
+ spellInfo.SchoolMask = fields[74].GetUInt32();
+ spellInfo.ChargeCategoryId = fields[75].GetUInt32();
+
+ } while (spellsResult->NextRow());
+ }
+
+ TC_LOG_INFO("server.loading", ">> Loaded " SZFMTD " serverside spells %u ms", mServersideSpellNames.size(), GetMSTimeDiffToNow(oldMSTime));
+}
+
void SpellMgr::LoadSpellInfoCustomAttributes()
{
uint32 oldMSTime = getMSTime();
diff --git a/src/server/game/Spells/SpellMgr.h b/src/server/game/Spells/SpellMgr.h
index dd2df66dbf6..a1f7a5d555d 100644
--- a/src/server/game/Spells/SpellMgr.h
+++ b/src/server/game/Spells/SpellMgr.h
@@ -749,6 +749,7 @@ class TC_GAME_API SpellMgr
void LoadSpellInfoStore();
void UnloadSpellInfoStore();
void UnloadSpellInfoImplicitTargetConditionLists();
+ void LoadSpellInfoServerside();
void LoadSpellInfoCustomAttributes();
void LoadSpellInfoCorrections();
void LoadSpellInfoSpellSpecificAndAuraState();
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index 4dada5a5091..c6413aaddef 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -1758,6 +1758,9 @@ void World::SetInitialWorldSettings()
TC_LOG_INFO("server.loading", "Loading SpellInfo store...");
sSpellMgr->LoadSpellInfoStore();
+ TC_LOG_INFO("server.loading", "Loading serverside spells...");
+ sSpellMgr->LoadSpellInfoServerside();
+
TC_LOG_INFO("server.loading", "Loading SpellInfo corrections...");
sSpellMgr->LoadSpellInfoCorrections();