Core/Spells: Load entire proc flags array from db2

Port From (https://github.com/TrinityCore/TrinityCore/commit/3844c79adb749432b0f41b9b1aecde7287b9f765)
This commit is contained in:
hondacrx
2022-05-07 14:56:20 -04:00
parent db6cfeca04
commit cf15d538cc
15 changed files with 292 additions and 234 deletions
+14 -14
View File
@@ -90,7 +90,7 @@ namespace Game.Spells
case AuraType.Transform:
case AuraType.ModRoot2:
m_canBeRecalculated = false;
if (m_spellInfo.ProcFlags == 0)
if (!m_spellInfo.ProcFlags)
break;
amount = (int)(GetBase().GetUnitOwner().CountPctFromMaxHealth(10));
break;
@@ -5065,14 +5065,14 @@ namespace Game.Spells
Unit.DealDamageMods(caster, target, ref damage, ref absorb);
// Set trigger flag
ProcFlags procAttacker = ProcFlags.DonePeriodic;
ProcFlags procVictim = ProcFlags.TakenPeriodic;
ProcFlagsInit procAttacker = new ProcFlagsInit(ProcFlags.DonePeriodic);
ProcFlagsInit procVictim = new ProcFlagsInit(ProcFlags.TakenPeriodic);
ProcFlagsHit hitMask = damageInfo.GetHitMask();
if (damage != 0)
{
hitMask |= crit ? ProcFlagsHit.Critical : ProcFlagsHit.Normal;
procVictim |= ProcFlags.TakenDamage;
procVictim.Or(ProcFlags.TakenDamage);
}
int overkill = (int)(damage - target.GetHealth());
@@ -5156,14 +5156,14 @@ namespace Game.Spells
log.HitInfo |= HitInfo.CriticalHit;
// Set trigger flag
ProcFlags procAttacker = ProcFlags.DonePeriodic;
ProcFlags procVictim = ProcFlags.TakenPeriodic;
ProcFlagsInit procAttacker = new ProcFlagsInit(ProcFlags.DonePeriodic);
ProcFlagsInit procVictim = new ProcFlagsInit(ProcFlags.TakenPeriodic);
ProcFlagsHit hitMask = damageInfo.GetHitMask();
if (damage != 0)
{
hitMask |= crit ? ProcFlagsHit.Critical : ProcFlagsHit.Normal;
procVictim |= ProcFlags.TakenDamage;
procVictim.Or(ProcFlags.TakenDamage);
}
int new_damage = (int)Unit.DealDamage(caster, target, damage, cleanDamage, DamageEffectType.DOT, GetSpellInfo().GetSchoolMask(), GetSpellInfo(), false);
@@ -5182,7 +5182,7 @@ namespace Game.Spells
caster.HealBySpell(healInfo);
caster.GetThreatManager().ForwardThreatForAssistingMe(caster, healInfo.GetEffectiveHeal() * 0.5f, GetSpellInfo());
Unit.ProcSkillsAndAuras(caster, caster, ProcFlags.DonePeriodic, ProcFlags.TakenPeriodic, ProcFlagsSpellType.Heal, ProcFlagsSpellPhase.Hit, hitMask, null, null, healInfo);
Unit.ProcSkillsAndAuras(caster, caster, new ProcFlagsInit(ProcFlags.DonePeriodic), new ProcFlagsInit(ProcFlags.TakenPeriodic), ProcFlagsSpellType.Heal, ProcFlagsSpellPhase.Hit, hitMask, null, null, healInfo);
caster.SendSpellNonMeleeDamageLog(log);
}
@@ -5214,7 +5214,7 @@ namespace Game.Spells
HealInfo healInfo = new(caster, target, damage, GetSpellInfo(), GetSpellInfo().GetSchoolMask());
caster.HealBySpell(healInfo);
Unit.ProcSkillsAndAuras(caster, target, ProcFlags.DonePeriodic, ProcFlags.TakenPeriodic, ProcFlagsSpellType.Heal, ProcFlagsSpellPhase.Hit, ProcFlagsHit.Normal, null, null, healInfo);
Unit.ProcSkillsAndAuras(caster, target, new ProcFlagsInit(ProcFlags.DonePeriodic), new ProcFlagsInit(ProcFlags.TakenPeriodic), ProcFlagsSpellType.Heal, ProcFlagsSpellPhase.Hit, ProcFlagsHit.Normal, null, null, healInfo);
}
void HandlePeriodicHealAurasTick(Unit target, Unit caster)
@@ -5271,8 +5271,8 @@ namespace Game.Spells
if (GetAuraType() == AuraType.ObsModHealth)
return;
ProcFlags procAttacker = ProcFlags.DonePeriodic;
ProcFlags procVictim = ProcFlags.TakenPeriodic;
ProcFlagsInit procAttacker = new ProcFlagsInit(ProcFlags.DonePeriodic);
ProcFlagsInit procVictim = new ProcFlagsInit(ProcFlags.TakenPeriodic);
ProcFlagsHit hitMask = crit ? ProcFlagsHit.Critical : ProcFlagsHit.Normal;
// ignore item heals
if (GetBase().GetCastItemGUID().IsEmpty())
@@ -5426,13 +5426,13 @@ namespace Game.Spells
Unit.DealDamageMods(damageInfo.attacker, damageInfo.target, ref damageInfo.damage, ref damageInfo.absorb);
// Set trigger flag
ProcFlags procAttacker = ProcFlags.DonePeriodic;
ProcFlags procVictim = ProcFlags.TakenPeriodic;
ProcFlagsInit procAttacker = new ProcFlagsInit(ProcFlags.DonePeriodic);
ProcFlagsInit procVictim = new ProcFlagsInit(ProcFlags.TakenPeriodic);
ProcFlagsHit hitMask = Unit.CreateProcHitMask(damageInfo, SpellMissInfo.None);
ProcFlagsSpellType spellTypeMask = ProcFlagsSpellType.NoDmgHeal;
if (damageInfo.damage != 0)
{
procVictim |= ProcFlags.TakenDamage;
procVictim.Or(ProcFlags.TakenDamage);
spellTypeMask |= ProcFlagsSpellType.Damage;
}
+78 -46
View File
@@ -1698,29 +1698,29 @@ namespace Game.Spells
// Create base triggers flags for Attacker and Victim (m_procAttacker, m_procVictim and m_hitMask)
//==========================================================================================
m_procVictim = m_procAttacker = 0;
m_procVictim = m_procAttacker = new ProcFlagsInit();
// Get data for type of attack and fill base info for trigger
switch (m_spellInfo.DmgClass)
{
case SpellDmgClass.Melee:
m_procAttacker = ProcFlags.DoneSpellMeleeDmgClass;
m_procAttacker = new ProcFlagsInit(ProcFlags.DoneSpellMeleeDmgClass);
if (m_attackType == WeaponAttackType.OffAttack)
m_procAttacker |= ProcFlags.DoneOffHandAttack;
m_procAttacker.Or(ProcFlags.DoneOffHandAttack);
else
m_procAttacker |= ProcFlags.DoneMainHandAttack;
m_procVictim = ProcFlags.TakenSpellMeleeDmgClass;
m_procAttacker.Or(ProcFlags.DoneMainHandAttack);
m_procVictim = new ProcFlagsInit(ProcFlags.TakenSpellMeleeDmgClass);
break;
case SpellDmgClass.Ranged:
// Auto attack
if (m_spellInfo.HasAttribute(SpellAttr2.AutorepeatFlag))
{
m_procAttacker = ProcFlags.DoneRangedAutoAttack;
m_procVictim = ProcFlags.TakenRangedAutoAttack;
m_procAttacker = new ProcFlagsInit(ProcFlags.DoneRangedAutoAttack);
m_procVictim = new ProcFlagsInit(ProcFlags.TakenRangedAutoAttack);
}
else // Ranged spell attack
{
m_procAttacker = ProcFlags.DoneSpellRangedDmgClass;
m_procVictim = ProcFlags.TakenSpellRangedDmgClass;
m_procAttacker = new ProcFlagsInit(ProcFlags.DoneSpellRangedDmgClass);
m_procVictim = new ProcFlagsInit(ProcFlags.TakenSpellRangedDmgClass);
}
break;
default:
@@ -1728,8 +1728,8 @@ namespace Game.Spells
Convert.ToBoolean(m_spellInfo.EquippedItemSubClassMask & (1 << (int)ItemSubClassWeapon.Wand))
&& m_spellInfo.HasAttribute(SpellAttr2.AutorepeatFlag)) // Wands auto attack
{
m_procAttacker = ProcFlags.DoneRangedAutoAttack;
m_procVictim = ProcFlags.TakenRangedAutoAttack;
m_procAttacker = new ProcFlagsInit(ProcFlags.DoneRangedAutoAttack);
m_procVictim = new ProcFlagsInit(ProcFlags.TakenRangedAutoAttack);
}
break;
// For other spells trigger procflags are set in Spell::TargetInfo::DoDamageAndTriggers
@@ -1741,18 +1741,18 @@ namespace Game.Spells
m_spellInfo.Id == 57879 || // Snake Trap - done this way to avoid double proc
m_spellInfo.SpellFamilyFlags[2].HasAnyFlag(0x00024000u))) // Explosive and Immolation Trap
{
m_procAttacker |= ProcFlags.DoneTrapActivation;
m_procAttacker.Or(ProcFlags.DoneTrapActivation);
// also fill up other flags (TargetInfo::DoDamageAndTriggers only fills up flag if both are not set)
m_procAttacker |= ProcFlags.DoneSpellMagicDmgClassNeg;
m_procVictim |= ProcFlags.TakenSpellMagicDmgClassNeg;
m_procAttacker.Or(ProcFlags.DoneSpellMagicDmgClassNeg);
m_procVictim.Or(ProcFlags.TakenSpellMagicDmgClassNeg);
}
// Hellfire Effect - trigger as DOT
if (m_spellInfo.SpellFamilyName == SpellFamilyNames.Warlock && m_spellInfo.SpellFamilyFlags[0].HasAnyFlag(0x00000040u))
{
m_procAttacker = ProcFlags.DonePeriodic;
m_procVictim = ProcFlags.TakenPeriodic;
m_procAttacker = new ProcFlagsInit(ProcFlags.DonePeriodic);
m_procVictim = new ProcFlagsInit(ProcFlags.TakenPeriodic);
}
}
@@ -2882,13 +2882,13 @@ namespace Game.Spells
return;
// Handle procs on cast
ProcFlags procAttacker = m_procAttacker;
if (procAttacker == 0)
ProcFlagsInit procAttacker = m_procAttacker;
if (!procAttacker)
{
if (m_spellInfo.DmgClass == SpellDmgClass.Magic)
procAttacker = IsPositive() ? ProcFlags.DoneSpellMagicDmgClassPos : ProcFlags.DoneSpellMagicDmgClassNeg;
procAttacker = new ProcFlagsInit(IsPositive() ? ProcFlags.DoneSpellMagicDmgClassPos : ProcFlags.DoneSpellMagicDmgClassNeg);
else
procAttacker = IsPositive() ? ProcFlags.DoneSpellNoneDmgClassPos : ProcFlags.DoneSpellNoneDmgClassNeg;
procAttacker = new ProcFlagsInit(IsPositive() ? ProcFlags.DoneSpellNoneDmgClassPos : ProcFlags.DoneSpellNoneDmgClassNeg);
}
ProcFlagsHit hitMask = m_hitMask;
@@ -2898,7 +2898,7 @@ namespace Game.Spells
if (!_triggeredCastFlags.HasAnyFlag(TriggerCastFlags.IgnoreAuraInterruptFlags) && !m_spellInfo.HasAttribute(SpellAttr2.IgnoreActionAuraInterruptFlags))
m_originalCaster.RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.ActionDelayed);
Unit.ProcSkillsAndAuras(m_originalCaster, null, procAttacker, ProcFlags.None, ProcFlagsSpellType.MaskAll, ProcFlagsSpellPhase.Cast, hitMask, this, null, null);
Unit.ProcSkillsAndAuras(m_originalCaster, null, procAttacker, new ProcFlagsInit(ProcFlags.None), ProcFlagsSpellType.MaskAll, ProcFlagsSpellPhase.Cast, hitMask, this, null, null);
// Call CreatureAI hook OnSuccessfulSpellCast
Creature caster = m_originalCaster.ToCreature();
@@ -3144,16 +3144,16 @@ namespace Game.Spells
if (!m_originalCaster)
return;
ProcFlags procAttacker = m_procAttacker;
if (procAttacker == 0)
ProcFlagsInit procAttacker = m_procAttacker;
if (!procAttacker)
{
if (m_spellInfo.DmgClass == SpellDmgClass.Magic)
procAttacker = IsPositive() ? ProcFlags.DoneSpellMagicDmgClassPos : ProcFlags.DoneSpellMagicDmgClassNeg;
procAttacker = new ProcFlagsInit(IsPositive() ? ProcFlags.DoneSpellMagicDmgClassPos : ProcFlags.DoneSpellMagicDmgClassNeg);
else
procAttacker = IsPositive() ? ProcFlags.DoneSpellNoneDmgClassPos : ProcFlags.DoneSpellNoneDmgClassNeg;
procAttacker = new ProcFlagsInit(IsPositive() ? ProcFlags.DoneSpellNoneDmgClassPos : ProcFlags.DoneSpellNoneDmgClassNeg);
}
Unit.ProcSkillsAndAuras(m_originalCaster, null, procAttacker, ProcFlags.None, ProcFlagsSpellType.MaskAll, ProcFlagsSpellPhase.Finish, m_hitMask, this, null, null);
Unit.ProcSkillsAndAuras(m_originalCaster, null, procAttacker, new ProcFlagsInit(ProcFlags.None), ProcFlagsSpellType.MaskAll, ProcFlagsSpellPhase.Finish, m_hitMask, this, null, null);
}
void SendSpellCooldown()
@@ -7047,7 +7047,7 @@ namespace Game.Spells
{
return m_originalCaster != null ? m_originalCaster : m_caster.ToUnit();
}
bool IsValidDeadOrAliveTarget(Unit target)
{
if (target.IsAlive())
@@ -7865,8 +7865,8 @@ namespace Game.Spells
// ******************************************
// Spell trigger system
// ******************************************
internal ProcFlags m_procAttacker; // Attacker trigger flags
internal ProcFlags m_procVictim; // Victim trigger flags
internal ProcFlagsInit m_procAttacker; // Attacker trigger flags
internal ProcFlagsInit m_procVictim; // Victim trigger flags
internal ProcFlagsHit m_hitMask;
// *****************************************
@@ -8028,7 +8028,7 @@ namespace Game.Spells
TransportGUID.Clear();
TransportOffset.Relocate(0, 0, 0, 0);
}
public SpellDestination(WorldObject wObj) : this()
{
TransportGUID = wObj.GetTransGUID();
@@ -8190,8 +8190,8 @@ namespace Game.Spells
if (caster != null)
{
// Fill base trigger info
ProcFlags procAttacker = spell.m_procAttacker;
ProcFlags procVictim = spell.m_procVictim;
ProcFlagsInit procAttacker = spell.m_procAttacker;
ProcFlagsInit procVictim = spell.m_procVictim;
ProcFlagsSpellType procSpellType = ProcFlagsSpellType.None;
ProcFlagsHit hitMask = ProcFlagsHit.None;
@@ -8200,7 +8200,7 @@ namespace Game.Spells
(spell.CanExecuteTriggersOnHit(EffectMask) || MissCondition == SpellMissInfo.Immune || MissCondition == SpellMissInfo.Immune2);
// Trigger info was not filled in Spell::prepareDataForTriggerSystem - we do it now
if (canEffectTrigger && procAttacker == 0 && procVictim == 0)
if (canEffectTrigger && !procAttacker && !procVictim)
{
bool positive = true;
if (spell.m_damage > 0)
@@ -8226,25 +8226,25 @@ namespace Game.Spells
case SpellDmgClass.Magic:
if (positive)
{
procAttacker |= ProcFlags.DoneSpellMagicDmgClassPos;
procVictim |= ProcFlags.TakenSpellMagicDmgClassPos;
procAttacker.Or(ProcFlags.DoneSpellMagicDmgClassPos);
procVictim.Or(ProcFlags.TakenSpellMagicDmgClassPos);
}
else
{
procAttacker |= ProcFlags.DoneSpellMagicDmgClassNeg;
procVictim |= ProcFlags.TakenSpellMagicDmgClassNeg;
procAttacker.Or(ProcFlags.DoneSpellMagicDmgClassNeg);
procVictim.Or(ProcFlags.TakenSpellMagicDmgClassNeg);
}
break;
case SpellDmgClass.None:
if (positive)
{
procAttacker |= ProcFlags.DoneSpellNoneDmgClassPos;
procVictim |= ProcFlags.TakenSpellNoneDmgClassPos;
procAttacker.Or(ProcFlags.DoneSpellNoneDmgClassPos);
procVictim.Or(ProcFlags.TakenSpellNoneDmgClassPos);
}
else
{
procAttacker |= ProcFlags.DoneSpellNoneDmgClassNeg;
procVictim |= ProcFlags.TakenSpellNoneDmgClassNeg;
procAttacker.Or(ProcFlags.DoneSpellNoneDmgClassNeg);
procVictim.Or(ProcFlags.TakenSpellNoneDmgClassNeg);
}
break;
}
@@ -8297,7 +8297,7 @@ namespace Game.Spells
Unit.DealDamageMods(damageInfo.attacker, damageInfo.target, ref damageInfo.damage, ref damageInfo.absorb);
hitMask |= Unit.CreateProcHitMask(damageInfo, MissCondition);
procVictim |= ProcFlags.TakenDamage;
procVictim.Or(ProcFlags.TakenDamage);
spell.m_damage = (int)damageInfo.damage;
@@ -8482,7 +8482,7 @@ namespace Game.Spells
spell.CallScriptAfterHitHandlers();
}
}
public class SpellValue
{
public SpellValue(SpellInfo proto, WorldObject caster)
@@ -8934,7 +8934,7 @@ namespace Game.Spells
ProcFlagsSpellPhase spellPhaseMask = ProcFlagsSpellPhase.None;
ProcFlagsHit hitMask = ProcFlagsHit.Reflect;
Unit.ProcSkillsAndAuras(caster, _victim, typeMaskActor, typeMaskActionTarget, spellTypeMask, spellPhaseMask, hitMask, null, null, null);
Unit.ProcSkillsAndAuras(caster, _victim, new ProcFlagsInit(typeMaskActor), new ProcFlagsInit(typeMaskActionTarget), spellTypeMask, spellPhaseMask, hitMask, null, null, null);
return true;
}
@@ -8988,7 +8988,7 @@ namespace Game.Spells
Targets = targets;
}
}
public class CastSpellExtraArgs
{
public TriggerCastFlags TriggerFlags;
@@ -9061,7 +9061,7 @@ namespace Game.Spells
}
return this;
}
public CastSpellExtraArgs SetTriggeringAura(AuraEffect triggeringAura)
{
TriggeringAura = triggeringAura;
@@ -9106,6 +9106,38 @@ namespace Game.Spells
public List<SpellLogEffectGenericVictimParams> GenericVictimTargets = new();
public List<SpellLogEffectTradeSkillItemParams> TradeSkillTargets = new();
public List<SpellLogEffectFeedPetParams> FeedPetTargets = new();
}
public class ProcFlagsInit : FlagsArray<int>
{
public ProcFlagsInit(ProcFlags procFlags = 0, ProcFlags2 procFlags2 = 0) : base(2)
{
_storage[0] = (int)procFlags;
_storage[1] = (int)procFlags2;
}
public ProcFlagsInit(params int[] flags) : base(flags) { }
public ProcFlagsInit Or(ProcFlags procFlags)
{
_storage[0] |= (int)procFlags;
return this;
}
public ProcFlagsInit Or(ProcFlags2 procFlags2)
{
_storage[1] |= (int)procFlags2;
return this;
}
public bool HasFlag(ProcFlags procFlags)
{
return (_storage[0] & procFlags) != 0;
}
public bool HasFlag(ProcFlags2 procFlags)
{
return (_storage[1] & procFlags) != 0;
}
}
}
+2 -2
View File
@@ -2627,9 +2627,9 @@ namespace Game.Spells
duration = unitTarget.ModSpellDuration(m_spellInfo, unitTarget, duration, false, 1u << (int)effectInfo.EffectIndex);
unitTarget.GetSpellHistory().LockSpellSchool(curSpellInfo.GetSchoolMask(), TimeSpan.FromMilliseconds(duration));
if (m_spellInfo.DmgClass == SpellDmgClass.Magic)
Unit.ProcSkillsAndAuras(unitCaster, unitTarget, ProcFlags.DoneSpellMagicDmgClassNeg, ProcFlags.TakenSpellMagicDmgClassNeg, ProcFlagsSpellType.MaskAll, ProcFlagsSpellPhase.Hit, ProcFlagsHit.Interrupt, null, null, null);
Unit.ProcSkillsAndAuras(unitCaster, unitTarget, new ProcFlagsInit(ProcFlags.DoneSpellMagicDmgClassNeg), new ProcFlagsInit(ProcFlags.TakenSpellMagicDmgClassNeg), ProcFlagsSpellType.MaskAll, ProcFlagsSpellPhase.Hit, ProcFlagsHit.Interrupt, null, null, null);
else if (m_spellInfo.DmgClass == SpellDmgClass.Melee)
Unit.ProcSkillsAndAuras(unitCaster, unitTarget, ProcFlags.DoneSpellMeleeDmgClass, ProcFlags.TakenSpellMeleeDmgClass, ProcFlagsSpellType.MaskAll, ProcFlagsSpellPhase.Hit, ProcFlagsHit.Interrupt, null, null, null);
Unit.ProcSkillsAndAuras(unitCaster, unitTarget, new ProcFlagsInit(ProcFlags.DoneSpellMeleeDmgClass), new ProcFlagsInit(ProcFlags.TakenSpellMeleeDmgClass), ProcFlagsSpellType.MaskAll, ProcFlagsSpellPhase.Hit, ProcFlagsHit.Interrupt, null, null, null);
}
SendSpellInterruptLog(unitTarget, curSpellInfo.Id);
unitTarget.InterruptSpell(i, false);
+2 -2
View File
@@ -94,7 +94,7 @@ namespace Game.Spells
SpellAuraOptionsRecord _options = data.AuraOptions;
if (_options != null)
{
ProcFlags = (ProcFlags)_options.ProcTypeMask[0];
ProcFlags = new ProcFlagsInit(_options.ProcTypeMask);
ProcChance = _options.ProcChance;
ProcCharges = (uint)_options.ProcCharges;
ProcCooldown = _options.ProcCategoryRecovery;
@@ -3948,7 +3948,7 @@ namespace Game.Spells
public SpellAuraInterruptFlags2 AuraInterruptFlags2 { get; set; }
public SpellAuraInterruptFlags ChannelInterruptFlags { get; set; }
public SpellAuraInterruptFlags2 ChannelInterruptFlags2 { get; set; }
public ProcFlags ProcFlags { get; set; }
public ProcFlagsInit ProcFlags { get; set; }
public uint ProcChance { get; set; }
public uint ProcCharges { get; set; }
public uint ProcCooldown { get; set; }
+60 -60
View File
@@ -459,7 +459,7 @@ namespace Game.Entities
public static bool CanSpellTriggerProcOnEvent(SpellProcEntry procEntry, ProcEventInfo eventInfo)
{
// proc type doesn't match
if ((eventInfo.GetTypeMask() & procEntry.ProcFlags) == 0)
if (!(eventInfo.GetTypeMask() & procEntry.ProcFlags))
return false;
// check XP or honor target requirement
@@ -484,7 +484,7 @@ namespace Game.Entities
}
// always trigger for these types
if (eventInfo.GetTypeMask().HasAnyFlag(ProcFlags.Killed | ProcFlags.Kill | ProcFlags.Death))
if (eventInfo.GetTypeMask().HasFlag(ProcFlags.Killed | ProcFlags.Kill | ProcFlags.Death))
return true;
// check school mask (if set) for other trigger types
@@ -1293,8 +1293,8 @@ namespace Game.Entities
// 0 1 2 3 4 5 6
SQLResult result = DB.World.Query("SELECT SpellId, SchoolMask, SpellFamilyName, SpellFamilyMask0, SpellFamilyMask1, SpellFamilyMask2, SpellFamilyMask3, " +
//7 8 9 10 11 12 13 14 15 16
"ProcFlags, SpellTypeMask, SpellPhaseMask, HitMask, AttributesMask, DisableEffectsMask, ProcsPerMinute, Chance, Cooldown, Charges FROM spell_proc");
//7 8 9 10 11 12 13 14 15 16 17
"ProcFlags, ProcFlags2, SpellTypeMask, SpellPhaseMask, HitMask, AttributesMask, DisableEffectsMask, ProcsPerMinute, Chance, Cooldown, Charges FROM spell_proc");
uint count = 0;
if (!result.IsEmpty())
@@ -1331,16 +1331,16 @@ namespace Game.Entities
baseProcEntry.SchoolMask = (SpellSchoolMask)result.Read<uint>(1);
baseProcEntry.SpellFamilyName = (SpellFamilyNames)result.Read<uint>(2);
baseProcEntry.SpellFamilyMask = new FlagArray128(result.Read<uint>(3), result.Read<uint>(4), result.Read<uint>(5), result.Read<uint>(6));
baseProcEntry.ProcFlags = (ProcFlags)result.Read<uint>(7);
baseProcEntry.SpellTypeMask = (ProcFlagsSpellType)result.Read<uint>(8);
baseProcEntry.SpellPhaseMask = (ProcFlagsSpellPhase)result.Read<uint>(9);
baseProcEntry.HitMask = (ProcFlagsHit)result.Read<uint>(10);
baseProcEntry.AttributesMask = (ProcAttributes)result.Read<uint>(11);
baseProcEntry.DisableEffectsMask = result.Read<uint>(12);
baseProcEntry.ProcsPerMinute = result.Read<float>(13);
baseProcEntry.Chance = result.Read<float>(14);
baseProcEntry.Cooldown = result.Read<uint>(15);
baseProcEntry.Charges = result.Read<uint>(16);
baseProcEntry.ProcFlags = new ProcFlagsInit(result.Read<int>(7), result.Read<int>(8), 2);
baseProcEntry.SpellTypeMask = (ProcFlagsSpellType)result.Read<uint>(9);
baseProcEntry.SpellPhaseMask = (ProcFlagsSpellPhase)result.Read<uint>(10);
baseProcEntry.HitMask = (ProcFlagsHit)result.Read<uint>(11);
baseProcEntry.AttributesMask = (ProcAttributes)result.Read<uint>(12);
baseProcEntry.DisableEffectsMask = result.Read<uint>(13);
baseProcEntry.ProcsPerMinute = result.Read<float>(14);
baseProcEntry.Chance = result.Read<float>(15);
baseProcEntry.Cooldown = result.Read<uint>(16);
baseProcEntry.Charges = result.Read<uint>(17);
while (spellInfo != null)
{
@@ -1352,7 +1352,7 @@ namespace Game.Entities
SpellProcEntry procEntry = baseProcEntry;
// take defaults from dbcs
if (procEntry.ProcFlags == 0)
if (!procEntry.ProcFlags)
procEntry.ProcFlags = spellInfo.ProcFlags;
if (procEntry.Charges == 0)
procEntry.Charges = spellInfo.ProcCharges;
@@ -1376,21 +1376,21 @@ namespace Game.Entities
Log.outError(LogFilter.Sql, "`spell_proc` table entry for spellId {0} has negative value in `ProcsPerMinute` field", spellInfo.Id);
procEntry.ProcsPerMinute = 0;
}
if (procEntry.ProcFlags == 0)
if (!procEntry.ProcFlags)
Log.outError(LogFilter.Sql, "`spell_proc` table entry for spellId {0} doesn't have `ProcFlags` value defined, proc will not be triggered", spellInfo.Id);
if (Convert.ToBoolean(procEntry.SpellTypeMask & ~ProcFlagsSpellType.MaskAll))
Log.outError(LogFilter.Sql, "`spell_proc` table entry for spellId {0} has wrong `SpellTypeMask` set: {1}", spellInfo.Id, procEntry.SpellTypeMask);
if (procEntry.SpellTypeMask != 0 && !Convert.ToBoolean(procEntry.ProcFlags & (ProcFlags.SpellMask)))
if (procEntry.SpellTypeMask != 0 && !procEntry.ProcFlags.HasFlag(ProcFlags.SpellMask))
Log.outError(LogFilter.Sql, "`spell_proc` table entry for spellId {0} has `SpellTypeMask` value defined, but it won't be used for defined `ProcFlags` value", spellInfo.Id);
if (procEntry.SpellPhaseMask == 0 && Convert.ToBoolean(procEntry.ProcFlags & ProcFlags.ReqSpellPhaseMask))
if (procEntry.SpellPhaseMask == 0 && procEntry.ProcFlags.HasFlag(ProcFlags.ReqSpellPhaseMask))
Log.outError(LogFilter.Sql, "`spell_proc` table entry for spellId {0} doesn't have `SpellPhaseMask` value defined, but it's required for defined `ProcFlags` value, proc will not be triggered", spellInfo.Id);
if (Convert.ToBoolean(procEntry.SpellPhaseMask & ~ProcFlagsSpellPhase.MaskAll))
Log.outError(LogFilter.Sql, "`spell_proc` table entry for spellId {0} has wrong `SpellPhaseMask` set: {1}", spellInfo.Id, procEntry.SpellPhaseMask);
if (procEntry.SpellPhaseMask != 0 && !Convert.ToBoolean(procEntry.ProcFlags & ProcFlags.ReqSpellPhaseMask))
if (procEntry.SpellPhaseMask != 0 && !procEntry.ProcFlags.HasFlag(ProcFlags.ReqSpellPhaseMask))
Log.outError(LogFilter.Sql, "`spell_proc` table entry for spellId {0} has `SpellPhaseMask` value defined, but it won't be used for defined `ProcFlags` value", spellInfo.Id);
if (Convert.ToBoolean(procEntry.HitMask & ~ProcFlagsHit.MaskAll))
Log.outError(LogFilter.Sql, "`spell_proc` table entry for spellId {0} has wrong `HitMask` set: {1}", spellInfo.Id, procEntry.HitMask);
if (procEntry.HitMask != 0 && !(Convert.ToBoolean(procEntry.ProcFlags & ProcFlags.TakenHitMask) || (Convert.ToBoolean(procEntry.ProcFlags & ProcFlags.DoneHitMask) && (procEntry.SpellPhaseMask == 0 || Convert.ToBoolean(procEntry.SpellPhaseMask & (ProcFlagsSpellPhase.Hit | ProcFlagsSpellPhase.Finish))))))
if (procEntry.HitMask != 0 && !(procEntry.ProcFlags.HasFlag(ProcFlags.TakenHitMask) || (procEntry.ProcFlags.HasFlag(ProcFlags.DoneHitMask) && (procEntry.SpellPhaseMask == 0 || Convert.ToBoolean(procEntry.SpellPhaseMask & (ProcFlagsSpellPhase.Hit | ProcFlagsSpellPhase.Finish))))))
Log.outError(LogFilter.Sql, "`spell_proc` table entry for spellId {0} has `HitMask` value defined, but it won't be used for defined `ProcFlags` and `SpellPhaseMask` values", spellInfo.Id);
foreach (var spellEffectInfo in spellInfo.GetEffects())
if ((procEntry.DisableEffectsMask & (1u << (int)spellEffectInfo.EffectIndex)) != 0 && !spellEffectInfo.IsAura())
@@ -1448,7 +1448,7 @@ namespace Game.Entities
continue;
// Nothing to do if no flags set
if (spellInfo.ProcFlags == 0)
if (!spellInfo.ProcFlags)
continue;
bool addTriggerFlag = false;
@@ -1476,7 +1476,7 @@ namespace Game.Entities
// many proc auras with taken procFlag mask don't have attribute "can proc with triggered"
// they should proc nevertheless (example mage armor spells with judgement)
if (!addTriggerFlag && spellInfo.ProcFlags.HasAnyFlag(ProcFlags.TakenHitMask))
if (!addTriggerFlag && spellInfo.ProcFlags.HasFlag(ProcFlags.TakenHitMask))
{
switch (auraName)
{
@@ -1496,7 +1496,7 @@ namespace Game.Entities
{
if (spellEffectInfo.IsAura())
{
Log.outError(LogFilter.Sql, $"Spell Id {spellInfo.Id} has DBC ProcFlags {spellInfo.ProcFlags}, but it's of non-proc aura type, it probably needs an entry in `spell_proc` table to be handled correctly.");
Log.outError(LogFilter.Sql, $"Spell Id {spellInfo.Id} has DBC ProcFlags 0x{spellInfo.ProcFlags[0]:X} 0x{spellInfo.ProcFlags[1]:X}, but it's of non-proc aura type, it probably needs an entry in `spell_proc` table to be handled correctly.");
break;
}
}
@@ -1552,7 +1552,7 @@ namespace Game.Entities
procEntry.AttributesMask = 0;
procEntry.DisableEffectsMask = nonProcMask;
if (spellInfo.ProcFlags.HasAnyFlag(ProcFlags.Kill))
if (spellInfo.ProcFlags.HasFlag(ProcFlags.Kill))
procEntry.AttributesMask |= ProcAttributes.ReqExpOrHonor;
if (addTriggerFlag)
procEntry.AttributesMask |= ProcAttributes.TriggeredCanProc;
@@ -2467,13 +2467,13 @@ namespace Game.Entities
"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
//42 43 44 45 46 47 48 49 50 51 52
"ChannelInterruptFlags1, ChannelInterruptFlags2, ProcFlags, ProcFlags2, ProcChance, ProcCharges, ProcCooldown, ProcBasePPM, MaxLevel, BaseLevel, SpellLevel, " +
//53 54 55 56 57 58 59 60 61
"DurationIndex, RangeIndex, Speed, LaunchDelay, StackAmount, EquippedItemClass, EquippedItemSubClassMask, EquippedItemInventoryTypeMask, ContentTuningId, " +
//61 62 63 64 65 66 67 68 69 70
//62 63 64 65 66 67 68 69 70 71
"SpellName, ConeAngle, ConeWidth, MaxTargetLevel, MaxAffectedTargets, SpellFamilyName, SpellFamilyFlags1, SpellFamilyFlags2, SpellFamilyFlags3, SpellFamilyFlags4, " +
//71 72 73 74 75
//72 73 74 75 76
"DmgClass, PreventionType, AreaGroupId, SchoolMask, ChargeCategoryId FROM serverside_spell");
if (!spellsResult.IsEmpty())
@@ -2488,7 +2488,7 @@ namespace Game.Entities
continue;
}
mServersideSpellNames.Add(new(spellId, spellsResult.Read<string>(61)));
mServersideSpellNames.Add(new(spellId, spellsResult.Read<string>(62)));
SpellInfo spellInfo = new(mServersideSpellNames.Last().Name, difficulty, spellEffects[(spellId, difficulty)]);
spellInfo.CategoryId = spellsResult.Read<uint>(2);
@@ -2533,34 +2533,34 @@ namespace Game.Entities
spellInfo.AuraInterruptFlags2 = (SpellAuraInterruptFlags2)spellsResult.Read<uint>(41);
spellInfo.ChannelInterruptFlags = (SpellAuraInterruptFlags)spellsResult.Read<uint>(42);
spellInfo.ChannelInterruptFlags2 = (SpellAuraInterruptFlags2)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<int>(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);
spellInfo.ProcFlags = new ProcFlagsInit(spellsResult.Read<int>(44), spellsResult.Read<int>(45));
spellInfo.ProcChance = spellsResult.Read<uint>(46);
spellInfo.ProcCharges = spellsResult.Read<uint>(47);
spellInfo.ProcCooldown = spellsResult.Read<uint>(48);
spellInfo.ProcBasePPM = spellsResult.Read<float>(49);
spellInfo.MaxLevel = spellsResult.Read<uint>(50);
spellInfo.BaseLevel = spellsResult.Read<uint>(51);
spellInfo.SpellLevel = spellsResult.Read<uint>(52);
spellInfo.DurationEntry = CliDB.SpellDurationStorage.LookupByKey(spellsResult.Read<uint>(53));
spellInfo.RangeEntry = CliDB.SpellRangeStorage.LookupByKey(spellsResult.Read<uint>(54));
spellInfo.Speed = spellsResult.Read<float>(55);
spellInfo.LaunchDelay = spellsResult.Read<float>(56);
spellInfo.StackAmount = spellsResult.Read<uint>(57);
spellInfo.EquippedItemClass = (ItemClass)spellsResult.Read<int>(58);
spellInfo.EquippedItemSubClassMask = spellsResult.Read<int>(59);
spellInfo.EquippedItemInventoryTypeMask = spellsResult.Read<int>(60);
spellInfo.ContentTuningId = spellsResult.Read<uint>(61);
spellInfo.ConeAngle = spellsResult.Read<float>(63);
spellInfo.Width = spellsResult.Read<float>(64);
spellInfo.MaxTargetLevel = spellsResult.Read<uint>(65);
spellInfo.MaxAffectedTargets = spellsResult.Read<uint>(66);
spellInfo.SpellFamilyName = (SpellFamilyNames)spellsResult.Read<uint>(67);
spellInfo.SpellFamilyFlags = new FlagArray128(spellsResult.Read<uint>(68), spellsResult.Read<uint>(69), spellsResult.Read<uint>(70), spellsResult.Read<uint>(71));
spellInfo.DmgClass = (SpellDmgClass)spellsResult.Read<uint>(72);
spellInfo.PreventionType = (SpellPreventionType)spellsResult.Read<uint>(73);
spellInfo.RequiredAreasID = spellsResult.Read<int>(74);
spellInfo.SchoolMask = (SpellSchoolMask)spellsResult.Read<uint>(75);
spellInfo.ChargeCategoryId = spellsResult.Read<uint>(76);
mSpellInfoMap.Add(spellId, spellInfo);
@@ -4373,7 +4373,7 @@ namespace Game.Entities
// disable proc for magnet auras, they're handled differently
if (spellInfo.HasAura(AuraType.SpellMagnet))
spellInfo.ProcFlags = 0;
spellInfo.ProcFlags = new ProcFlagsInit();
// due to the way spell system works, unit would change orientation in Spell::_cast
if (spellInfo.HasAura(AuraType.ControlVehicle))
@@ -4826,7 +4826,7 @@ namespace Game.Entities
public SpellSchoolMask SchoolMask { get; set; } // if nonzero - bitmask for matching proc condition based on spell's school
public SpellFamilyNames SpellFamilyName { get; set; } // if nonzero - for matching proc condition based on candidate spell's SpellFamilyName
public FlagArray128 SpellFamilyMask { get; set; } = new FlagArray128(); // if nonzero - bitmask for matching proc condition based on candidate spell's SpellFamilyFlags
public ProcFlags ProcFlags { get; set; } // if nonzero - owerwrite procFlags field for given Spell.dbc entry, bitmask for matching proc condition, see enum ProcFlags
public ProcFlagsInit ProcFlags { get; set; } // if nonzero - owerwrite procFlags field for given Spell.dbc entry, bitmask for matching proc condition, see enum ProcFlags
public ProcFlagsSpellType SpellTypeMask { get; set; } // if nonzero - bitmask for matching proc condition based on candidate spell's damage/heal effects, see enum ProcFlagsSpellType
public ProcFlagsSpellPhase SpellPhaseMask { get; set; } // if nonzero - bitmask for matching phase of a spellcast on which proc occurs, see enum ProcFlagsSpellPhase
public ProcFlagsHit HitMask { get; set; } // if nonzero - bitmask for matching proc condition based on hit result, see enum ProcFlagsHit