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
+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];