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
@@ -2507,6 +2507,15 @@ namespace Framework.Constants
MeleeBasedTriggerMask = (DoneMeleeAutoAttack | TakenMeleeAutoAttack | DoneSpellMeleeDmgClass | TakenSpellMeleeDmgClass |
DoneRangedAutoAttack | TakenRangedAutoAttack | DoneSpellRangedDmgClass | TakenSpellRangedDmgClass)
}
public enum ProcFlags2
{
None = 0x00,
TargetDies = 0x01,
Knockback = 0x02,
CastSuccessful = 0x04
}
public enum ProcFlagsSpellPhase
{
None = 0x0,
+94 -79
View File
@@ -19,104 +19,119 @@ using System;
namespace Framework.Dynamic
{
public class FlagArray128
public class FlagsArray<T> where T : struct
{
public FlagArray128(params uint[] parts)
protected dynamic[] _storage;
public FlagsArray(uint length)
{
_values = new uint[4];
for (var i = 0; i < parts.Length; ++i)
_values[i] = parts[i];
_storage = new dynamic[length];
}
public FlagArray128(int[] parts)
public FlagsArray(params T[] parts)
{
_values = new uint[4];
_storage = new dynamic[parts.Length];
for (var i = 0; i < parts.Length; ++i)
_values[i] = (uint)parts[i];
_storage[i] = parts[i];
}
public FlagsArray(T[] parts, uint length)
{
_storage = new dynamic[length];
for (var i = 0; i < length && i < parts.Length; ++i)
_storage[i] = parts[i];
}
public static bool operator <(FlagsArray<T> left, FlagsArray<T> right)
{
for (var i = left._storage.Length; i > 0; --i)
{
if ((dynamic)left._storage[i - 1] < right._storage[i - 1])
return true;
else if ((dynamic)left._storage[i - 1] > right._storage[i - 1])
return false;
}
return false;
}
public static bool operator >(FlagsArray<T> left, FlagsArray<T> right)
{
for (var i = left._storage.Length; i > 0; --i)
{
if ((dynamic)left._storage[i - 1] > right._storage[i - 1])
return true;
else if ((dynamic)left._storage[i - 1] < right._storage[i - 1])
return false;
}
return false;
}
public static FlagArray128 operator &(FlagsArray<T> left, FlagsArray<T> right)
{
FlagArray128 fl = new();
for (var i = 0; i < left._storage.Length; ++i)
fl[i] = left._storage[i] & right._storage[i];
return fl;
}
public static FlagArray128 operator |(FlagsArray<T> left, FlagsArray<T> right)
{
FlagArray128 fl = new();
for (var i = 0; i < left._storage.Length; ++i)
fl[i] = left._storage[i] | right._storage[i];
return fl;
}
public static FlagArray128 operator ^(FlagsArray<T> left, FlagsArray<T> right)
{
FlagArray128 fl = new();
for (var i = 0; i < left._storage.Length; ++i)
fl[i] = left._storage[i] ^ right._storage[i];
return fl;
}
public static implicit operator bool(FlagsArray<T> left)
{
for (var i = 0; i < left._storage.Length; ++i)
if (left._storage[i] != 0)
return true;
return false;
}
public T this[int i]
{
get
{
return _storage[i];
}
set
{
_storage[i] = value;
}
}
}
public class FlagArray128 : FlagsArray<uint>
{
public FlagArray128(params uint[] parts) : base(parts, 4) { }
public bool IsEqual(params uint[] parts)
{
for (var i = 0; i < _values.Length; ++i)
if (_values[i] == parts[i])
for (var i = 0; i < _storage.Length; ++i)
if (_storage[i] == parts[i])
return false;
return true;
}
public bool HasFlag(params uint[] parts)
{
return (_storage[0] & parts[0] || _storage[1] & parts[1] || _storage[2] & parts[2] || _storage[3] & parts[3]);
}
public void Set(params uint[] parts)
{
for (var i = 0; i < parts.Length; ++i)
_values[i] = parts[i];
_storage[i] = parts[i];
}
public static bool operator <(FlagArray128 left, FlagArray128 right)
{
for (var i = left._values.Length; i > 0; --i)
{
if (left._values[i - 1] < right._values[i - 1])
return true;
else if (left._values[i - 1] > right._values[i - 1])
return false;
}
return false;
}
public static bool operator >(FlagArray128 left, FlagArray128 right)
{
for (var i = left._values.Length; i > 0; --i)
{
if (left._values[i - 1] > right._values[i - 1])
return true;
else if (left._values[i - 1] < right._values[i - 1])
return false;
}
return false;
}
public static FlagArray128 operator &(FlagArray128 left, FlagArray128 right)
{
FlagArray128 fl = new();
for (var i = 0; i < left._values.Length; ++i)
fl[i] = left._values[i] & right._values[i];
return fl;
}
public static FlagArray128 operator |(FlagArray128 left, FlagArray128 right)
{
FlagArray128 fl = new();
for (var i = 0; i < left._values.Length; ++i)
fl[i] = left._values[i] | right._values[i];
return fl;
}
public static FlagArray128 operator ^(FlagArray128 left, FlagArray128 right)
{
FlagArray128 fl = new();
for (var i = 0; i < left._values.Length; ++i)
fl[i] = left._values[i] ^ right._values[i];
return fl;
}
public static implicit operator bool (FlagArray128 left)
{
for (var i = 0; i < left._values.Length; ++i)
if (left._values[i] != 0)
return true;
return false;
}
public uint this[int i]
{
get
{
return _values[i];
}
set
{
_values[i] = value;
}
}
uint[] _values { get; set; }
}
public class FlaggedArray<T> where T : struct
@@ -180,7 +180,7 @@ namespace Game.DataStorage
}
else if (type == typeof(FlagArray128))
{
f.SetValue(obj, new FlagArray128(ReadArray<int>(result, dbIndex, 4)));
f.SetValue(obj, new FlagArray128(ReadArray<uint>(result, dbIndex, 4)));
dbIndex += 4;
}
break;
+11 -11
View File
@@ -47,7 +47,7 @@ namespace Game.Entities
InterruptNonMeleeSpells(false);
RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.EnteringCombat);
ProcSkillsAndAuras(this, null, ProcFlags.EnterCombat, ProcFlags.None, ProcFlagsSpellType.MaskAll, ProcFlagsSpellPhase.None, ProcFlagsHit.None, null, null, null);
ProcSkillsAndAuras(this, null, new ProcFlagsInit(ProcFlags.EnterCombat), new ProcFlagsInit(ProcFlags.None), ProcFlagsSpellType.MaskAll, ProcFlagsSpellPhase.None, ProcFlagsHit.None, null, null, null);
}
public virtual void AtExitCombat()
@@ -793,14 +793,14 @@ namespace Game.Entities
// proc only once for victim
Unit owner = attacker.GetOwner();
if (owner != null)
ProcSkillsAndAuras(owner, victim, ProcFlags.Kill, ProcFlags.None, ProcFlagsSpellType.MaskAll, ProcFlagsSpellPhase.None, ProcFlagsHit.None, null, null, null);
ProcSkillsAndAuras(owner, victim, new ProcFlagsInit(ProcFlags.Kill), new ProcFlagsInit(ProcFlags.None), ProcFlagsSpellType.MaskAll, ProcFlagsSpellPhase.None, ProcFlagsHit.None, null, null, null);
}
if (!victim.IsCritter())
ProcSkillsAndAuras(attacker, victim, ProcFlags.Kill, ProcFlags.Killed, ProcFlagsSpellType.MaskAll, ProcFlagsSpellPhase.None, ProcFlagsHit.None, null, null, null);
ProcSkillsAndAuras(attacker, victim, new ProcFlagsInit(ProcFlags.Kill), new ProcFlagsInit(ProcFlags.Killed), ProcFlagsSpellType.MaskAll, ProcFlagsSpellPhase.None, ProcFlagsHit.None, null, null, null);
// Proc auras on death - must be before aura/combat remove
ProcSkillsAndAuras(victim, victim, ProcFlags.None, ProcFlags.Death, ProcFlagsSpellType.MaskAll, ProcFlagsSpellPhase.None, ProcFlagsHit.None, null, null, null);
ProcSkillsAndAuras(victim, victim, new ProcFlagsInit(ProcFlags.None), new ProcFlagsInit(ProcFlags.Death), ProcFlagsSpellType.MaskAll, ProcFlagsSpellPhase.None, ProcFlagsHit.None, null, null, null);
// update get killing blow achievements, must be done before setDeathState to be able to require auras on target
// and before Spirit of Redemption as it also removes auras
@@ -1026,8 +1026,8 @@ namespace Game.Entities
damageInfo.TargetState = 0;
damageInfo.AttackType = attackType;
damageInfo.ProcAttacker = ProcFlags.None;
damageInfo.ProcVictim = ProcFlags.None;
damageInfo.ProcAttacker = new ProcFlagsInit();
damageInfo.ProcVictim = new ProcFlagsInit();
damageInfo.CleanDamage = 0;
damageInfo.HitOutCome = MeleeHitOutcome.Evade;
@@ -1041,12 +1041,12 @@ namespace Game.Entities
switch (attackType)
{
case WeaponAttackType.BaseAttack:
damageInfo.ProcAttacker = ProcFlags.DoneMeleeAutoAttack | ProcFlags.DoneMainHandAttack;
damageInfo.ProcVictim = ProcFlags.TakenMeleeAutoAttack;
damageInfo.ProcAttacker = new ProcFlagsInit(ProcFlags.DoneMeleeAutoAttack | ProcFlags.DoneMainHandAttack);
damageInfo.ProcVictim = new ProcFlagsInit(ProcFlags.TakenMeleeAutoAttack);
break;
case WeaponAttackType.OffAttack:
damageInfo.ProcAttacker = ProcFlags.DoneMeleeAutoAttack | ProcFlags.DoneOffHandAttack;
damageInfo.ProcVictim = ProcFlags.TakenMeleeAutoAttack;
damageInfo.ProcAttacker = new ProcFlagsInit(ProcFlags.DoneMeleeAutoAttack | ProcFlags.DoneOffHandAttack);
damageInfo.ProcVictim = new ProcFlagsInit(ProcFlags.TakenMeleeAutoAttack);
damageInfo.HitInfo = HitInfo.OffHand;
break;
default:
@@ -1185,7 +1185,7 @@ namespace Game.Entities
// Calculate absorb resist
if (damageInfo.Damage > 0)
{
damageInfo.ProcVictim |= ProcFlags.TakenDamage;
damageInfo.ProcVictim.Or(ProcFlags.TakenDamage);
// Calculate absorb & resists
DamageInfo dmgInfo = new(damageInfo);
CalcAbsorbResist(dmgInfo);
+5 -5
View File
@@ -162,7 +162,7 @@ namespace Game.Entities
public class ProcEventInfo
{
public ProcEventInfo(Unit actor, Unit actionTarget, Unit procTarget, ProcFlags typeMask, ProcFlagsSpellType spellTypeMask,
public ProcEventInfo(Unit actor, Unit actionTarget, Unit procTarget, ProcFlagsInit typeMask, ProcFlagsSpellType spellTypeMask,
ProcFlagsSpellPhase spellPhaseMask, ProcFlagsHit hitMask, Spell spell, DamageInfo damageInfo, HealInfo healInfo)
{
_actor = actor;
@@ -181,7 +181,7 @@ namespace Game.Entities
public Unit GetActionTarget() { return _actionTarget; }
public Unit GetProcTarget() { return _procTarget; }
public ProcFlags GetTypeMask() { return _typeMask; }
public ProcFlagsInit GetTypeMask() { return _typeMask; }
public ProcFlagsSpellType GetSpellTypeMask() { return _spellTypeMask; }
public ProcFlagsSpellPhase GetSpellPhaseMask() { return _spellPhaseMask; }
public ProcFlagsHit GetHitMask() { return _hitMask; }
@@ -217,7 +217,7 @@ namespace Game.Entities
Unit _actor;
Unit _actionTarget;
Unit _procTarget;
ProcFlags _typeMask;
ProcFlagsInit _typeMask;
ProcFlagsSpellType _spellTypeMask;
ProcFlagsSpellPhase _spellPhaseMask;
ProcFlagsHit _hitMask;
@@ -444,8 +444,8 @@ namespace Game.Entities
// Helper
public WeaponAttackType AttackType { get; set; }
public ProcFlags ProcAttacker { get; set; }
public ProcFlags ProcVictim { get; set; }
public ProcFlagsInit ProcAttacker { get; set; }
public ProcFlagsInit ProcVictim { get; set; }
public uint CleanDamage { get; set; } // Used only for rage calculation
public MeleeHitOutcome HitOutCome { get; set; } // TODO: remove this field (need use TargetState)
}
+10 -10
View File
@@ -1419,28 +1419,28 @@ namespace Game.Entities
return false;
}
public static void ProcSkillsAndAuras(Unit actor, Unit actionTarget, ProcFlags typeMaskActor, ProcFlags typeMaskActionTarget, ProcFlagsSpellType spellTypeMask, ProcFlagsSpellPhase spellPhaseMask, ProcFlagsHit hitMask, Spell spell, DamageInfo damageInfo, HealInfo healInfo)
public static void ProcSkillsAndAuras(Unit actor, Unit actionTarget, ProcFlagsInit typeMaskActor, ProcFlagsInit typeMaskActionTarget, ProcFlagsSpellType spellTypeMask, ProcFlagsSpellPhase spellPhaseMask, ProcFlagsHit hitMask, Spell spell, DamageInfo damageInfo, HealInfo healInfo)
{
WeaponAttackType attType = damageInfo != null ? damageInfo.GetAttackType() : WeaponAttackType.BaseAttack;
if (typeMaskActor != 0 && actor != null)
if (typeMaskActor && actor != null)
actor.ProcSkillsAndReactives(false, actionTarget, typeMaskActor, hitMask, attType);
if (typeMaskActionTarget != 0 && actionTarget)
if (typeMaskActionTarget && actionTarget)
actionTarget.ProcSkillsAndReactives(true, actor, typeMaskActionTarget, hitMask, attType);
if (actor != null)
actor.TriggerAurasProcOnEvent(null, null, actionTarget, typeMaskActor, typeMaskActionTarget, spellTypeMask, spellPhaseMask, hitMask, spell, damageInfo, healInfo);
}
void ProcSkillsAndReactives(bool isVictim, Unit procTarget, ProcFlags typeMask, ProcFlagsHit hitMask, WeaponAttackType attType)
void ProcSkillsAndReactives(bool isVictim, Unit procTarget, ProcFlagsInit typeMask, ProcFlagsHit hitMask, WeaponAttackType attType)
{
// Player is loaded now - do not allow passive spell casts to proc
if (IsPlayer() && ToPlayer().GetSession().PlayerLoading())
return;
// For melee/ranged based attack need update skills and set some Aura states if victim present
if (typeMask.HasAnyFlag(ProcFlags.MeleeBasedTriggerMask) && procTarget)
if (typeMask.HasFlag(ProcFlags.MeleeBasedTriggerMask) && procTarget)
{
// If exist crit/parry/dodge/block need update aura state (for victim and attacker)
if (hitMask.HasAnyFlag(ProcFlagsHit.Critical | ProcFlagsHit.Parry | ProcFlagsHit.Dodge | ProcFlagsHit.Block))
@@ -1508,12 +1508,12 @@ namespace Game.Entities
}
}
void TriggerAurasProcOnEvent(List<AuraApplication> myProcAuras, List<AuraApplication> targetProcAuras, Unit actionTarget, ProcFlags typeMaskActor, ProcFlags typeMaskActionTarget, ProcFlagsSpellType spellTypeMask, ProcFlagsSpellPhase spellPhaseMask, ProcFlagsHit hitMask, Spell spell, DamageInfo damageInfo, HealInfo healInfo)
void TriggerAurasProcOnEvent(List<AuraApplication> myProcAuras, List<AuraApplication> targetProcAuras, Unit actionTarget, ProcFlagsInit typeMaskActor, ProcFlagsInit typeMaskActionTarget, ProcFlagsSpellType spellTypeMask, ProcFlagsSpellPhase spellPhaseMask, ProcFlagsHit hitMask, Spell spell, DamageInfo damageInfo, HealInfo healInfo)
{
// prepare data for self trigger
ProcEventInfo myProcEventInfo = new(this, actionTarget, actionTarget, typeMaskActor, spellTypeMask, spellPhaseMask, hitMask, spell, damageInfo, healInfo);
List<Tuple<uint, AuraApplication>> myAurasTriggeringProc = new();
if (typeMaskActor != 0)
if (typeMaskActor)
{
GetProcAurasTriggeredOnEvent(myAurasTriggeringProc, myProcAuras, myProcEventInfo);
@@ -1537,12 +1537,12 @@ namespace Game.Entities
// prepare data for target trigger
ProcEventInfo targetProcEventInfo = new(this, actionTarget, this, typeMaskActionTarget, spellTypeMask, spellPhaseMask, hitMask, spell, damageInfo, healInfo);
List<Tuple<uint, AuraApplication>> targetAurasTriggeringProc = new();
if (typeMaskActionTarget != 0 && actionTarget)
if (typeMaskActionTarget && actionTarget)
actionTarget.GetProcAurasTriggeredOnEvent(targetAurasTriggeringProc, targetProcAuras, targetProcEventInfo);
TriggerAurasProcOnEvent(myProcEventInfo, myAurasTriggeringProc);
if (typeMaskActionTarget != 0 && actionTarget)
if (typeMaskActionTarget && actionTarget)
actionTarget.TriggerAurasProcOnEvent(targetProcEventInfo, targetAurasTriggeringProc);
}
+1 -1
View File
@@ -3513,7 +3513,7 @@ namespace Game.Entities
caster.SendSpellNonMeleeDamageLog(log);
// break 'Fear' and similar auras
ProcSkillsAndAuras(damageInfo.GetAttacker(), caster, ProcFlags.None, ProcFlags.TakenSpellMagicDmgClassNeg, ProcFlagsSpellType.Damage, ProcFlagsSpellPhase.Hit, ProcFlagsHit.None, null, damageInfo, null);
ProcSkillsAndAuras(damageInfo.GetAttacker(), caster, new ProcFlagsInit(ProcFlags.None), new ProcFlagsInit(ProcFlags.TakenSpellMagicDmgClassNeg), ProcFlagsSpellType.Damage, ProcFlagsSpellPhase.Hit, ProcFlagsHit.None, null, damageInfo, null);
}
}
}
+2 -1
View File
@@ -24,6 +24,7 @@ using Game.Maps;
using Game.Movement;
using Game.Networking;
using Game.Networking.Packets;
using Game.Spells;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -205,7 +206,7 @@ namespace Game
if (opcode == ClientOpcodes.MoveJump)
{
plrMover.RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags2.Jump); // Mind Control
Unit.ProcSkillsAndAuras(plrMover, null, ProcFlags.Jump, ProcFlags.None, ProcFlagsSpellType.MaskAll, ProcFlagsSpellPhase.None, ProcFlagsHit.None, null, null, null);
Unit.ProcSkillsAndAuras(plrMover, null, new ProcFlagsInit(ProcFlags.Jump), new ProcFlagsInit(ProcFlags.None), ProcFlagsSpellType.MaskAll, ProcFlagsSpellPhase.None, ProcFlagsHit.None, null, null, null);
}
}
}
+2 -1
View File
@@ -22,6 +22,7 @@ using Game.Entities;
using Game.Groups;
using Game.Networking.Packets;
using Game.Scenarios;
using Game.Spells;
using System;
using System.Collections.Generic;
using System.Text;
@@ -367,7 +368,7 @@ namespace Game.Maps
var playerList = instance.GetPlayers();
foreach (var player in playerList)
if (player.IsAlive())
Unit.ProcSkillsAndAuras(player, null, ProcFlags.EncounterStart, ProcFlags.None, ProcFlagsSpellType.MaskAll, ProcFlagsSpellPhase.None, ProcFlagsHit.None, null, null, null);
Unit.ProcSkillsAndAuras(player, null, new ProcFlagsInit(ProcFlags.EncounterStart), new ProcFlagsInit(ProcFlags.None), ProcFlagsSpellType.MaskAll, ProcFlagsSpellPhase.None, ProcFlagsHit.None, null, null, null);
break;
}
case EncounterState.Fail:
+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
+1 -1
View File
@@ -1498,7 +1498,7 @@ namespace Scripts.Spells.Items
void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo)
{
if (eventInfo.GetTypeMask().HasAnyFlag(ProcFlags.DoneRangedAutoAttack | ProcFlags.DoneSpellRangedDmgClass))
if (eventInfo.GetTypeMask().HasFlag(ProcFlags.DoneRangedAutoAttack | ProcFlags.DoneSpellRangedDmgClass))
{
// in that case, do not cast heal spell
PreventDefaultAction();