Core/Spells: Restore serverside spells fuinctionality

Port From (https://github.com/TrinityCore/TrinityCore/commit/71112d4d169ef192f8c3c9eb1303bdd880336eaa)
This commit is contained in:
hondacrx
2021-03-15 16:29:10 -04:00
parent cee1fbe0d2
commit 98088d1d35
6 changed files with 4762 additions and 41 deletions
+3
View File
@@ -442,6 +442,9 @@ namespace Game
Log.outInfo(LogFilter.ServerLoading, "Loading SpellInfo Storage...");
Global.SpellMgr.LoadSpellInfoStore();
Log.outInfo(LogFilter.ServerLoading, "Loading serverside spells...");
Global.SpellMgr.LoadSpellInfoServerside();
Log.outInfo(LogFilter.ServerLoading, "Loading SpellInfo corrections...");
Global.SpellMgr.LoadSpellInfoCorrections();
+1 -1
View File
@@ -4570,7 +4570,7 @@ namespace Game.Spells
{
if (m_spellInfo.CasterAuraState != 0 && !m_caster.HasAuraState(m_spellInfo.CasterAuraState, m_spellInfo, m_caster))
return SpellCastResult.CasterAurastate;
if (m_spellInfo.CasterAuraStateNot != 0 && m_caster.HasAuraState(m_spellInfo.CasterAuraStateNot, m_spellInfo, m_caster))
if (m_spellInfo.ExcludeCasterAuraState != 0 && m_caster.HasAuraState(m_spellInfo.ExcludeCasterAuraState, m_spellInfo, m_caster))
return SpellCastResult.CasterAurastate;
// Note: spell 62473 requres casterAuraSpell = triggering spell
+54 -40
View File
@@ -66,13 +66,10 @@ namespace Game.Spells
AttributesEx14 = (SpellAttr14)_misc.Attributes[14];
CastTimeEntry = CliDB.SpellCastTimesStorage.LookupByKey(_misc.CastingTimeIndex);
DurationEntry = CliDB.SpellDurationStorage.LookupByKey(_misc.DurationIndex);
RangeIndex = _misc.RangeIndex;
RangeEntry = CliDB.SpellRangeStorage.LookupByKey(_misc.RangeIndex);
Speed = _misc.Speed;
LaunchDelay = _misc.LaunchDelay;
SchoolMask = (SpellSchoolMask)_misc.SchoolMask;
AttributesCu = 0;
IconFileDataId = _misc.SpellIconFileDataID;
ActiveIconFileDataId = _misc.ActiveIconFileDataID;
ContentTuningId = _misc.ContentTuningID;
@@ -96,14 +93,18 @@ namespace Game.Spells
SpellAuraOptionsRecord _options = data.AuraOptions;
if (_options != null)
{
SpellProcsPerMinuteRecord _ppm = CliDB.SpellProcsPerMinuteStorage.LookupByKey(_options.SpellProcsPerMinuteID);
ProcFlags = (ProcFlags)_options.ProcTypeMask[0];
ProcChance = _options.ProcChance;
ProcCharges = (uint)_options.ProcCharges;
ProcCooldown = _options.ProcCategoryRecovery;
ProcBasePPM = _ppm != null ? _ppm.BaseProcRate : 0.0f;
ProcPPMMods = Global.DB2Mgr.GetSpellProcsPerMinuteMods(_options.SpellProcsPerMinuteID);
StackAmount = _options.CumulativeAura;
SpellProcsPerMinuteRecord _ppm = CliDB.SpellProcsPerMinuteStorage.LookupByKey(_options.SpellProcsPerMinuteID);
if (_ppm != null)
{
ProcBasePPM = _ppm.BaseProcRate;
ProcPPMMods = Global.DB2Mgr.GetSpellProcsPerMinuteMods(_ppm.Id);
}
}
// SpellAuraRestrictionsEntry
@@ -112,8 +113,8 @@ namespace Game.Spells
{
CasterAuraState = (AuraStateType)_aura.CasterAuraState;
TargetAuraState = (AuraStateType)_aura.TargetAuraState;
CasterAuraStateNot = (AuraStateType)_aura.ExcludeCasterAuraState;
TargetAuraStateNot = (AuraStateType)_aura.ExcludeTargetAuraState;
ExcludeCasterAuraState = (AuraStateType)_aura.ExcludeCasterAuraState;
ExcludeTargetAuraState = (AuraStateType)_aura.ExcludeTargetAuraState;
CasterAuraSpell = _aura.CasterAuraSpell;
TargetAuraSpell = _aura.TargetAuraSpell;
ExcludeCasterAuraSpell = _aura.ExcludeCasterAuraSpell;
@@ -196,10 +197,13 @@ namespace Game.Spells
// SpellReagentsEntry
SpellReagentsRecord _reagents = data.Reagents;
for (var i = 0; i < SpellConst.MaxReagents; ++i)
if (_reagents != null)
{
Reagent[i] = _reagents != null ? _reagents.Reagent[i] : 0;
ReagentCount[i] = _reagents != null ? _reagents.ReagentCount[i] : 0u;
for (var i = 0; i < SpellConst.MaxReagents; ++i)
{
Reagent[i] = _reagents.Reagent[i];
ReagentCount[i] = _reagents.ReagentCount[i];
}
}
// SpellShapeshiftEntry
@@ -214,7 +218,7 @@ namespace Game.Spells
SpellTargetRestrictionsRecord _target = data.TargetRestrictions;
if (_target != null)
{
targets = (SpellCastTargetFlags)_target.Targets;
Targets = (SpellCastTargetFlags)_target.Targets;
ConeAngle = _target.ConeDegrees;
Width = _target.Width;
TargetCreatureType = _target.TargetCreatureType;
@@ -224,18 +228,30 @@ namespace Game.Spells
// SpellTotemsEntry
SpellTotemsRecord _totem = data.Totems;
for (var i = 0; i < 2; ++i)
if (_totem != null)
{
TotemCategory[i] = _totem != null ? _totem.RequiredTotemCategoryID[i] : 0u;
Totem[i] = _totem != null ? _totem.Totem[i] : 0;
for (var i = 0; i < 2; ++i)
{
TotemCategory[i] = _totem.RequiredTotemCategoryID[i];
Totem[i] = _totem.Totem[i];
}
}
ChainEntry = null;
ExplicitTargetMask = 0;
_spellSpecific = SpellSpecificType.Normal;
_auraState = AuraStateType.None;
}
public SpellInfo(SpellNameRecord spellName, Difficulty difficulty, List<SpellEffectRecord> effects)
{
Id = spellName.Id;
Difficulty = difficulty;
SpellName = spellName.Name;
foreach (SpellEffectRecord spellEffect in effects)
_effects[spellEffect.EffectIndex] = new SpellEffectInfo(this, spellEffect);
}
public bool HasEffect(SpellEffectName effect)
{
foreach (SpellEffectInfo eff in _effects)
@@ -387,8 +403,8 @@ namespace Game.Spells
SpellCastTargetFlags mask = 0;
foreach (SpellEffectInfo effect in _effects)
{
if (effect != null && (effect.TargetA.GetTarget() != Targets.UnitCaster && effect.TargetA.GetTarget() != Targets.DestCaster
&& effect.TargetB.GetTarget() != Targets.UnitCaster && effect.TargetB.GetTarget() != Targets.DestCaster))
if (effect != null && (effect.TargetA.GetTarget() != Framework.Constants.Targets.UnitCaster && effect.TargetA.GetTarget() != Framework.Constants.Targets.DestCaster
&& effect.TargetB.GetTarget() != Framework.Constants.Targets.UnitCaster && effect.TargetB.GetTarget() != Framework.Constants.Targets.DestCaster))
{
mask |= effect.GetProvidedTargetMask();
}
@@ -481,7 +497,7 @@ namespace Game.Spells
public bool IsAllowingDeadTarget()
{
if (HasAttribute(SpellAttr2.CanTargetDead) || targets.HasAnyFlag(SpellCastTargetFlags.CorpseAlly | SpellCastTargetFlags.CorpseEnemy | SpellCastTargetFlags.UnitDead))
if (HasAttribute(SpellAttr2.CanTargetDead) || Targets.HasAnyFlag(SpellCastTargetFlags.CorpseAlly | SpellCastTargetFlags.CorpseEnemy | SpellCastTargetFlags.UnitDead))
return true;
foreach (SpellEffectInfo effect in _effects)
@@ -1115,7 +1131,7 @@ namespace Game.Spells
if (TargetAuraState != 0 && !unitTarget.HasAuraState(TargetAuraState, this, caster))
return SpellCastResult.TargetAurastate;
if (TargetAuraStateNot != 0 && unitTarget.HasAuraState(TargetAuraStateNot, this, caster))
if (ExcludeTargetAuraState != 0 && unitTarget.HasAuraState(ExcludeTargetAuraState, this, caster))
return SpellCastResult.TargetAurastate;
}
@@ -3168,7 +3184,7 @@ namespace Game.Spells
{
bool srcSet = false;
bool dstSet = false;
SpellCastTargetFlags targetMask = targets;
SpellCastTargetFlags targetMask = Targets;
// prepare target mask using effect target entries
foreach (SpellEffectInfo effect in _effects)
{
@@ -3360,12 +3376,12 @@ namespace Game.Spells
return false;
case AuraType.PeriodicDamage: // used in positive spells also.
// part of negative spell if casted at self (prevent cancel)
if (effect.TargetA.GetTarget() == Targets.UnitCaster)
if (effect.TargetA.GetTarget() == Framework.Constants.Targets.UnitCaster)
return false;
break;
case AuraType.ModDecreaseSpeed: // used in positive spells also
// part of positive spell if casted at self
if (effect.TargetA.GetTarget() != Targets.UnitCaster)
if (effect.TargetA.GetTarget() != Framework.Constants.Targets.UnitCaster)
return false;
// but not this if this first effect (didn't find better check)
if (HasAttribute(SpellAttr0.Negative1) && effIndex == 0)
@@ -3452,14 +3468,14 @@ namespace Game.Spells
// non-positive targets
switch (targetA)
{
case Targets.UnitNearbyEnemy:
case Targets.UnitTargetEnemy:
case Targets.UnitSrcAreaEnemy:
case Targets.UnitDestAreaEnemy:
case Targets.UnitConeEnemy24:
case Targets.UnitConeEnemy104:
case Targets.DestDynobjEnemy:
case Targets.DestTargetEnemy:
case Framework.Constants.Targets.UnitNearbyEnemy:
case Framework.Constants.Targets.UnitTargetEnemy:
case Framework.Constants.Targets.UnitSrcAreaEnemy:
case Framework.Constants.Targets.UnitDestAreaEnemy:
case Framework.Constants.Targets.UnitConeEnemy24:
case Framework.Constants.Targets.UnitConeEnemy104:
case Framework.Constants.Targets.DestDynobjEnemy:
case Framework.Constants.Targets.DestTargetEnemy:
return false;
default:
break;
@@ -3570,7 +3586,6 @@ namespace Game.Spells
public bool HasChannelInterruptFlag(SpellChannelInterruptFlags flag) { return (ChannelInterruptFlags[0] & (uint)flag) != 0; }
#region Fields
public uint Id { get; set; }
public Difficulty Difficulty { get; set; }
@@ -3596,14 +3611,14 @@ namespace Game.Spells
public BitSet NegativeEffects { get; set; } = new BitSet(SpellConst.MaxEffects);
public ulong Stances { get; set; }
public ulong StancesNot { get; set; }
public SpellCastTargetFlags targets { get; set; }
public SpellCastTargetFlags Targets { get; set; }
public uint TargetCreatureType { get; set; }
public uint RequiresSpellFocus { get; set; }
public uint FacingCasterFlags { get; set; }
public AuraStateType CasterAuraState { get; set; }
public AuraStateType TargetAuraState { get; set; }
public AuraStateType CasterAuraStateNot { get; set; }
public AuraStateType TargetAuraStateNot { get; set; }
public AuraStateType ExcludeCasterAuraState { get; set; }
public AuraStateType ExcludeTargetAuraState { get; set; }
public uint CasterAuraSpell { get; set; }
public uint TargetAuraSpell { get; set; }
public uint ExcludeCasterAuraSpell { get; set; }
@@ -3627,18 +3642,17 @@ namespace Game.Spells
public uint SpellLevel { get; set; }
public SpellDurationRecord DurationEntry { get; set; }
public SpellPowerRecord[] PowerCosts = new SpellPowerRecord[SpellConst.MaxPowersPerSpell];
public uint RangeIndex { get; set; }
public SpellRangeRecord RangeEntry { get; set; }
public float Speed { get; set; }
public float LaunchDelay { get; set; }
public uint StackAmount { get; set; }
public uint[] Totem = new uint[SpellConst.MaxTotems];
public uint[] TotemCategory = new uint[SpellConst.MaxTotems];
public int[] Reagent = new int[SpellConst.MaxReagents];
public uint[] ReagentCount = new uint[SpellConst.MaxReagents];
public ItemClass EquippedItemClass { get; set; }
public int EquippedItemSubClassMask { get; set; }
public int EquippedItemInventoryTypeMask { get; set; }
public uint[] TotemCategory = new uint[SpellConst.MaxTotems];
public uint IconFileDataId { get; set; }
public uint ActiveIconFileDataId { get; set; }
public uint ContentTuningId { get; set; }
@@ -3687,8 +3701,8 @@ namespace Game.Spells
Effect = (SpellEffectName)effect.Effect;
ApplyAuraName = (AuraType)effect.EffectAura;
ApplyAuraPeriod = effect.EffectAuraPeriod;
RealPointsPerLevel = effect.EffectRealPointsPerLevel;
BasePoints = (int)effect.EffectBasePoints;
RealPointsPerLevel = effect.EffectRealPointsPerLevel;
PointsPerResource = effect.EffectPointsPerResource;
Amplitude = effect.EffectAmplitude;
ChainAmplitude = effect.EffectChainAmplitude;
@@ -4433,8 +4447,8 @@ namespace Game.Spells
public SpellEffectName Effect;
public AuraType ApplyAuraName;
public uint ApplyAuraPeriod;
public float RealPointsPerLevel;
public int BasePoints;
public float RealPointsPerLevel;
public float PointsPerResource;
public float Amplitude;
public float ChainAmplitude;
+239
View File
@@ -2360,6 +2360,227 @@ namespace Game.Entities
}
public void LoadSpellInfoServerside()
{
uint oldMSTime = Time.GetMSTime();
MultiMap<(uint spellId, Difficulty difficulty), SpellEffectRecord> spellEffects = new MultiMap<(uint spellId, Difficulty difficulty), SpellEffectRecord>();
// 0 1 2 3 4 5 6
SQLResult effectsResult = DB.World.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.IsEmpty())
{
do
{
uint spellId = effectsResult.Read<uint>(0);
Difficulty difficulty = (Difficulty)effectsResult.Read<uint>(2);
SpellEffectRecord effect = new();
effect.EffectIndex = effectsResult.Read<uint>(1);
effect.Effect = effectsResult.Read<uint>(3);
effect.EffectAura = effectsResult.Read<short>(4);
effect.EffectAmplitude = effectsResult.Read<float>(5);
effect.EffectAttributes = (SpellEffectAttributes)effectsResult.Read<int>(6);
effect.EffectAuraPeriod = effectsResult.Read<uint>(7);
effect.EffectBonusCoefficient = effectsResult.Read<float>(8);
effect.EffectChainAmplitude = effectsResult.Read<float>(9);
effect.EffectChainTargets = effectsResult.Read<int>(10);
effect.EffectItemType = effectsResult.Read<uint>(11);
effect.EffectMechanic = effectsResult.Read<int>(12);
effect.EffectPointsPerResource = effectsResult.Read<float>(13);
effect.EffectPosFacing = effectsResult.Read<float>(14);
effect.EffectRealPointsPerLevel = effectsResult.Read<float>(15);
effect.EffectTriggerSpell = effectsResult.Read<uint>(16);
effect.BonusCoefficientFromAP = effectsResult.Read<float>(17);
effect.PvpMultiplier = effectsResult.Read<float>(18);
effect.Coefficient = effectsResult.Read<float>(19);
effect.Variance = effectsResult.Read<float>(20);
effect.ResourceCoefficient = effectsResult.Read<float>(21);
effect.GroupSizeBasePointsCoefficient = effectsResult.Read<float>(22);
effect.EffectBasePoints = effectsResult.Read<float>(23);
effect.EffectMiscValue[0] = effectsResult.Read<int>(24);
effect.EffectMiscValue[1] = effectsResult.Read<int>(25);
effect.EffectRadiusIndex[0] = effectsResult.Read<uint>(26);
effect.EffectRadiusIndex[1] = effectsResult.Read<uint>(27);
effect.EffectSpellClassMask = new FlagArray128(effectsResult.Read<uint>(28), effectsResult.Read<uint>(29), effectsResult.Read<uint>(30), effectsResult.Read<uint>(31));
effect.ImplicitTarget[0] = effectsResult.Read<short>(32);
effect.ImplicitTarget[1] = effectsResult.Read<short>(33);
var existingSpellBounds = _GetSpellInfo(spellId);
if (existingSpellBounds == null)
{
Log.outError(LogFilter.Sql, $"Serverside spell {spellId} difficulty {difficulty} effext index {effect.EffectIndex} references a regular spell loaded from file. Adding serverside effects to existing spells is not allowed.");
continue;
}
if (difficulty != Difficulty.None && !CliDB.DifficultyStorage.HasRecord((uint)difficulty))
{
Log.outError(LogFilter.Sql, $"Serverside spell {spellId} effect index {effect.EffectIndex} references non-existing difficulty {difficulty}, skipped");
continue;
}
if (effect.EffectIndex >= SpellConst.MaxEffects)
{
Log.outError(LogFilter.Sql, $"Serverside spell {spellId} difficulty {difficulty} has more than 32 effects, effect at index {effect.EffectIndex} skipped");
continue;
}
if (effect.Effect >= (uint)SpellEffectName.TotalSpellEffects)
{
Log.outError(LogFilter.Sql, $"Serverside spell {spellId} difficulty {difficulty} has invalid effect type {effect.Effect} at index {effect.EffectIndex}, skipped");
continue;
}
if (effect.EffectAura >= (uint)AuraType.Total)
{
Log.outError(LogFilter.Sql, $"Serverside spell {spellId} difficulty {difficulty} has invalid aura type {effect.EffectAura} at index {effect.EffectIndex}, skipped");
continue;
}
if (effect.ImplicitTarget[0] >= (uint)Targets.TotalSpellTargets)
{
Log.outError(LogFilter.Sql, $"Serverside spell {spellId} difficulty {difficulty} has invalid targetA type {effect.ImplicitTarget[0]} at index {effect.EffectIndex}, skipped");
continue;
}
if (effect.ImplicitTarget[1] >= (uint)Targets.TotalSpellTargets)
{
Log.outError(LogFilter.Sql, $"Serverside spell {spellId} difficulty {difficulty} has invalid targetB type {effect.ImplicitTarget[1]} at index {effect.EffectIndex}, skipped");
continue;
}
if (effect.EffectRadiusIndex[0] != 0 && !CliDB.SpellRadiusStorage.HasRecord(effect.EffectRadiusIndex[0]))
{
Log.outError(LogFilter.Sql, $"Serverside spell {spellId} difficulty {difficulty} has invalid radius id {effect.EffectRadiusIndex[0]} at index {effect.EffectIndex}, set to 0");
}
if (effect.EffectRadiusIndex[1] != 0 && !CliDB.SpellRadiusStorage.HasRecord(effect.EffectRadiusIndex[1]))
{
Log.outError(LogFilter.Sql, $"Serverside spell {spellId} difficulty {difficulty} has invalid max radius id {effect.EffectRadiusIndex[1]} at index {effect.EffectIndex}, set to 0");
}
spellEffects[(spellId, difficulty)].Add(effect);
} while (effectsResult.NextRow());
}
// 0 1 2 3 4 5 6 7 8
SQLResult spellsResult = DB.World.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.IsEmpty())
{
do
{
uint spellId = spellsResult.Read<uint>(0);
Difficulty difficulty = (Difficulty)spellsResult.Read<uint>(2);
mServersideSpellNames.Add(new (spellId, spellsResult.Read<string>(61)));
SpellInfo spellInfo = new SpellInfo(mServersideSpellNames.Last().Name, difficulty, spellEffects[(spellId, difficulty)]);
spellInfo.CategoryId = spellsResult.Read<uint>(2);
spellInfo.Dispel = (DispelType)spellsResult.Read<uint>(3);
spellInfo.Mechanic = (Mechanics)spellsResult.Read<uint>(4);
spellInfo.Attributes = (SpellAttr0)spellsResult.Read<uint>(5);
spellInfo.AttributesEx = (SpellAttr1)spellsResult.Read<uint>(6);
spellInfo.AttributesEx2 = (SpellAttr2)spellsResult.Read<uint>(7);
spellInfo.AttributesEx3 = (SpellAttr3)spellsResult.Read<uint>(8);
spellInfo.AttributesEx4 = (SpellAttr4)spellsResult.Read<uint>(9);
spellInfo.AttributesEx5 = (SpellAttr5)spellsResult.Read<uint>(10);
spellInfo.AttributesEx6 = (SpellAttr6)spellsResult.Read<uint>(11);
spellInfo.AttributesEx7 = (SpellAttr7)spellsResult.Read<uint>(12);
spellInfo.AttributesEx8 = (SpellAttr8)spellsResult.Read<uint>(13);
spellInfo.AttributesEx9 = (SpellAttr9)spellsResult.Read<uint>(14);
spellInfo.AttributesEx10 = (SpellAttr10)spellsResult.Read<uint>(15);
spellInfo.AttributesEx11 = (SpellAttr11)spellsResult.Read<uint>(16);
spellInfo.AttributesEx12 = (SpellAttr12)spellsResult.Read<uint>(17);
spellInfo.AttributesEx13 = (SpellAttr13)spellsResult.Read<uint>(18);
spellInfo.AttributesEx14 = (SpellAttr14)spellsResult.Read<uint>(19);
spellInfo.Stances = spellsResult.Read<ulong>(20);
spellInfo.StancesNot = spellsResult.Read<ulong>(21);
spellInfo.Targets = (SpellCastTargetFlags)spellsResult.Read<uint>(22);
spellInfo.TargetCreatureType = spellsResult.Read<uint>(23);
spellInfo.RequiresSpellFocus = spellsResult.Read<uint>(24);
spellInfo.FacingCasterFlags = spellsResult.Read<uint>(25);
spellInfo.CasterAuraState = (AuraStateType)spellsResult.Read<uint>(26);
spellInfo.TargetAuraState = (AuraStateType)spellsResult.Read<uint>(27);
spellInfo.ExcludeCasterAuraState = (AuraStateType)spellsResult.Read<uint>(28);
spellInfo.ExcludeTargetAuraState = (AuraStateType)spellsResult.Read<uint>(29);
spellInfo.CasterAuraSpell = spellsResult.Read<uint>(30);
spellInfo.TargetAuraSpell = spellsResult.Read<uint>(31);
spellInfo.ExcludeCasterAuraSpell = spellsResult.Read<uint>(32);
spellInfo.ExcludeTargetAuraSpell = spellsResult.Read<uint>(33);
spellInfo.CastTimeEntry = CliDB.SpellCastTimesStorage.LookupByKey(spellsResult.Read<uint>(34));
spellInfo.RecoveryTime = spellsResult.Read<uint>(35);
spellInfo.CategoryRecoveryTime = spellsResult.Read<uint>(36);
spellInfo.StartRecoveryCategory = spellsResult.Read<uint>(37);
spellInfo.StartRecoveryTime = spellsResult.Read<uint>(38);
spellInfo.InterruptFlags = (SpellInterruptFlags)spellsResult.Read<uint>(39);
spellInfo.AuraInterruptFlags[0] = spellsResult.Read<uint>(40);
spellInfo.AuraInterruptFlags[1] = spellsResult.Read<uint>(41);
spellInfo.ChannelInterruptFlags[0] = spellsResult.Read<uint>(42);
spellInfo.ChannelInterruptFlags[1] = spellsResult.Read<uint>(43);
spellInfo.ProcFlags = (ProcFlags)spellsResult.Read<uint>(44);
spellInfo.ProcChance = spellsResult.Read<uint>(45);
spellInfo.ProcCharges = spellsResult.Read<uint>(46);
spellInfo.ProcCooldown = spellsResult.Read<uint>(47);
spellInfo.ProcBasePPM = spellsResult.Read<float>(48);
spellInfo.MaxLevel = spellsResult.Read<uint>(49);
spellInfo.BaseLevel = spellsResult.Read<uint>(50);
spellInfo.SpellLevel = spellsResult.Read<uint>(51);
spellInfo.DurationEntry = CliDB.SpellDurationStorage.LookupByKey(spellsResult.Read<uint>(52));
spellInfo.RangeEntry = CliDB.SpellRangeStorage.LookupByKey(spellsResult.Read<uint>(53));
spellInfo.Speed = spellsResult.Read<float>(54);
spellInfo.LaunchDelay = spellsResult.Read<float>(55);
spellInfo.StackAmount = spellsResult.Read<uint>(56);
spellInfo.EquippedItemClass = (ItemClass)spellsResult.Read<uint>(57);
spellInfo.EquippedItemSubClassMask = spellsResult.Read<int>(58);
spellInfo.EquippedItemInventoryTypeMask = spellsResult.Read<int>(59);
spellInfo.ContentTuningId = spellsResult.Read<uint>(60);
spellInfo.ConeAngle = spellsResult.Read<float>(62);
spellInfo.Width = spellsResult.Read<float>(63);
spellInfo.MaxTargetLevel = spellsResult.Read<uint>(64);
spellInfo.MaxAffectedTargets = spellsResult.Read<uint>(65);
spellInfo.SpellFamilyName = (SpellFamilyNames)spellsResult.Read<uint>(66);
spellInfo.SpellFamilyFlags = new FlagArray128(spellsResult.Read<uint>(67), spellsResult.Read<uint>(68), spellsResult.Read<uint>(69), spellsResult.Read<uint>(70));
spellInfo.DmgClass = (SpellDmgClass)spellsResult.Read<uint>(71);
spellInfo.PreventionType = (SpellPreventionType)spellsResult.Read<uint>(72);
spellInfo.RequiredAreasID = spellsResult.Read<int>(73);
spellInfo.SchoolMask = (SpellSchoolMask)spellsResult.Read<uint>(74);
spellInfo.ChargeCategoryId = spellsResult.Read<uint>(75);
mSpellInfoMap.Add(spellInfo.Id, spellInfo);
} while (spellsResult.NextRow());
}
Log.outInfo(LogFilter.ServerLoading, $"Loaded {mServersideSpellNames} serverside spells {Time.GetMSTimeDiffToNow(oldMSTime)} ms");
}
public void LoadSpellInfoCustomAttributes()
{
uint oldMSTime = Time.GetMSTime();
@@ -3674,6 +3895,7 @@ namespace Game.Entities
MultiMap<SpellGroup, int> mSpellGroupSpell = new MultiMap<SpellGroup, int>();
Dictionary<SpellGroup, SpellGroupStackRule> mSpellGroupStack = new Dictionary<SpellGroup, SpellGroupStackRule>();
MultiMap<SpellGroup, AuraType> mSpellSameEffectStack = new MultiMap<SpellGroup, AuraType>();
List<ServersideSpellName> mServersideSpellNames = new List<ServersideSpellName>();
Dictionary<(uint id, Difficulty difficulty), SpellProcEntry> mSpellProcMap = new Dictionary<(uint id, Difficulty difficulty), SpellProcEntry>();
Dictionary<uint, SpellThreatEntry> mSpellThreatMap = new Dictionary<uint, SpellThreatEntry>();
Dictionary<uint, PetAura> mSpellPetAuraMap = new Dictionary<uint, PetAura>();
@@ -3770,6 +3992,23 @@ namespace Game.Entities
public uint Charges { get; set; } // if nonzero - owerwrite procCharges field for given Spell.dbc entry, defines how many times proc can occur before aura remove, 0 - infinite
}
struct ServersideSpellName
{
public SpellNameRecord Name;
public string NameStorage;
public ServersideSpellName(uint id, string name)
{
Name = new();
NameStorage = name;
Name.Id = id;
for (Locale i = 0; i < Locale.Total; ++i)
Name.Name[i] = name;
}
}
public class PetDefaultSpellsEntry
{
public uint[] spellid = new uint[4];
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,2 @@
DELETE FROM `serverside_spell` WHERE `Id` IN (34145,62388,5302,29153,31348,34915,35479,41951,77608,77996);
DELETE FROM `serverside_spell_effect` WHERE `SpellId` IN (34145,62388,5302,29153,31348,34915,35479,41951,77608,77996);