[11623] Implement ClassFamilyMask as wrapper for uint64+uint32 spell family masks

Inspired by patch suggested by darkstalker

Also
* Remove existed enums for family masks as contra-productive for developement.
* Drop one from horrible hack checks in SpellMgr::IsNoStackSpellDueToSpell
  (spells for any fimilies with exactly 0x800 mask) I fail find useful cases
  for current spell data with this check. All cases expected work correct without it.
  If will some problems detected with this please report for fix in less strange way.
This commit is contained in:
VladimirMangos 2011-06-11 20:16:44 +04:00
parent 20e9484e74
commit c686697c2d
12 changed files with 117 additions and 127 deletions

View file

@ -1500,6 +1500,42 @@ struct SoundEntriesEntry
// 29 m_soundEntriesAdvancedID
};
struct ClassFamilyMask
{
uint64 Flags;
uint32 Flags2;
ClassFamilyMask() : Flags(0), Flags2(0) {}
explicit ClassFamilyMask(uint64 familyFlags, uint32 familyFlags2 = 0) : Flags(familyFlags), Flags2(familyFlags2) {}
bool Empty() const { return Flags == 0 && Flags2 == 0; }
bool operator! () const { return Empty(); }
operator void const* () const { return Empty() ? NULL : this; }// for allow normal use in if(mask)
bool IsFitToFamilyMask(uint64 familyFlags, uint32 familyFlags2 = 0) const
{
return (Flags & familyFlags) || (Flags2 & familyFlags2);
}
bool IsFitToFamilyMask(ClassFamilyMask const& mask) const
{
return (Flags & mask.Flags) || (Flags2 & mask.Flags2);
}
uint64 operator& (uint64 mask) const // possible will removed at finish convertion code use IsFitToFamilyMask
{
return Flags & mask;
}
ClassFamilyMask& operator|= (ClassFamilyMask const& mask)
{
Flags |= mask.Flags;
Flags2 |= mask.Flags2;
return *this;
}
};
#define MAX_SPELL_REAGENTS 8
#define MAX_SPELL_TOTEMS 2
#define MAX_SPELL_TOTEM_CATEGORIES 2
@ -1579,9 +1615,7 @@ struct SpellEntry
int32 EffectMiscValueB[MAX_EFFECT_INDEX]; // 113-115 m_effectMiscValueB
uint32 EffectTriggerSpell[MAX_EFFECT_INDEX]; // 116-118 m_effectTriggerSpell
float EffectPointsPerComboPoint[MAX_EFFECT_INDEX]; // 119-121 m_effectPointsPerCombo
uint32 EffectSpellClassMaskA[3]; // 122-124 m_effectSpellClassMaskA, effect 0
uint32 EffectSpellClassMaskB[3]; // 125-127 m_effectSpellClassMaskB, effect 1
uint32 EffectSpellClassMaskC[3]; // 128-130 m_effectSpellClassMaskC, effect 2
ClassFamilyMask EffectSpellClassMask[MAX_EFFECT_INDEX]; // 122-130 m_effectSpellClassMaskA/B/C, effect 0/1/2
uint32 SpellVisual[2]; // 131-132 m_spellVisualID
uint32 SpellIconID; // 133 m_spellIconID
uint32 activeIconID; // 134 m_activeIconID
@ -1599,8 +1633,7 @@ struct SpellEntry
uint32 StartRecoveryTime; // 206 m_startRecoveryTime
uint32 MaxTargetLevel; // 207 m_maxTargetLevel
uint32 SpellFamilyName; // 208 m_spellClassSet
uint64 SpellFamilyFlags; // 209-210 m_spellClassMask NOTE: size is 12 bytes!!!
uint32 SpellFamilyFlags2; // 211 addition to m_spellClassMask
ClassFamilyMask SpellFamilyFlags; // 209-211 m_spellClassMask NOTE: size is 12 bytes!!!
uint32 MaxAffectedTargets; // 212 m_maxTargets
uint32 DmgClass; // 213 m_defenseType
uint32 PreventionType; // 214 m_preventionType
@ -1621,14 +1654,14 @@ struct SpellEntry
// helpers
int32 CalculateSimpleValue(SpellEffectIndex eff) const { return EffectBasePoints[eff] + int32(1); }
uint32 const* GetEffectSpellClassMask(SpellEffectIndex effect) const
ClassFamilyMask const& GetEffectSpellClassMask(SpellEffectIndex effect) const
{
return EffectSpellClassMaskA + effect * 3;
return EffectSpellClassMask[effect];
}
bool IsFitToFamilyMask(uint64 familyFlags, uint32 familyFlags2 = 0) const
{
return (SpellFamilyFlags & familyFlags) || (SpellFamilyFlags2 & familyFlags2);
return SpellFamilyFlags.IsFitToFamilyMask(familyFlags, familyFlags2);
}
bool IsFitToFamily(SpellFamily family, uint64 familyFlags, uint32 familyFlags2 = 0) const
@ -1636,6 +1669,16 @@ struct SpellEntry
return SpellFamily(SpellFamilyName) == family && IsFitToFamilyMask(familyFlags, familyFlags2);
}
bool IsFitToFamilyMask(ClassFamilyMask const& mask) const
{
return SpellFamilyFlags.IsFitToFamilyMask(mask);
}
bool IsFitToFamily(SpellFamily family, ClassFamilyMask const& mask) const
{
return SpellFamily(SpellFamilyName) == family && IsFitToFamilyMask(mask);
}
private:
// prevent creating custom entries (copy data from original in fact)
SpellEntry(SpellEntry const&); // DON'T must have implementation

View file

@ -274,29 +274,21 @@ std::ostringstream& operator<< (std::ostringstream& ss, PlayerTaxi const& taxi)
SpellModifier::SpellModifier( SpellModOp _op, SpellModType _type, int32 _value, SpellEntry const* spellEntry, SpellEffectIndex eff, int16 _charges /*= 0*/ ) : op(_op), type(_type), charges(_charges), value(_value), spellId(spellEntry->Id), lastAffected(NULL)
{
uint32 const* ptr = spellEntry->GetEffectSpellClassMask(eff);
mask = uint64(ptr[0]) | (uint64(ptr[1]) << 32);
mask2= ptr[2];
mask = spellEntry->GetEffectSpellClassMask(eff);
}
SpellModifier::SpellModifier( SpellModOp _op, SpellModType _type, int32 _value, Aura const* aura, int16 _charges /*= 0*/ ) : op(_op), type(_type), charges(_charges), value(_value), spellId(aura->GetId()), lastAffected(NULL)
{
uint32 const* ptr = aura->getAuraSpellClassMask();
mask = uint64(ptr[0]) | (uint64(ptr[1]) << 32);
mask2= ptr[2];
mask = aura->GetAuraSpellClassMask();
}
bool SpellModifier::isAffectedOnSpell( SpellEntry const *spell ) const
{
SpellEntry const *affect_spell = sSpellStore.LookupEntry(spellId);
// False if affect_spell == NULL or spellFamily not equal
if (!affect_spell || affect_spell->SpellFamilyName != spell->SpellFamilyName)
if (!affect_spell)
return false;
if (mask & spell->SpellFamilyFlags)
return true;
if (mask2 & spell->SpellFamilyFlags2)
return true;
return false;
return affect_spell->IsFitToFamily(SpellFamily(spell->SpellFamilyName), spell->SpellFamilyFlags);
}
//== TradeData =================================================
@ -18564,12 +18556,12 @@ void Player::AddSpellMod(SpellModifier* mod, bool apply)
else
_mask2= uint32(1) << (eff - 64);
if ( mod->mask & _mask || mod->mask2 & _mask2)
if (mod->mask.IsFitToFamilyMask(_mask, _mask2))
{
int32 val = 0;
for (SpellModList::const_iterator itr = m_spellMods[mod->op].begin(); itr != m_spellMods[mod->op].end(); ++itr)
{
if ((*itr)->type == mod->type && ((*itr)->mask & _mask || (*itr)->mask2 & _mask2))
if ((*itr)->type == mod->type && ((*itr)->mask.IsFitToFamilyMask(_mask, _mask2)))
val += (*itr)->value;
}
val += apply ? mod->value : -(mod->value);
@ -20832,8 +20824,7 @@ bool Player::CanNoReagentCast(SpellEntry const* spellInfo) const
// Check no reagent use mask
uint64 noReagentMask_0_1 = GetUInt64Value(PLAYER_NO_REAGENT_COST_1);
uint32 noReagentMask_2 = GetUInt32Value(PLAYER_NO_REAGENT_COST_1+2);
if (spellInfo->SpellFamilyFlags & noReagentMask_0_1 ||
spellInfo->SpellFamilyFlags2 & noReagentMask_2)
if (spellInfo->IsFitToFamilyMask(noReagentMask_0_1, noReagentMask_2))
return true;
return false;

View file

@ -120,7 +120,11 @@ struct SpellModifier
SpellModifier() : charges(0), lastAffected(NULL) {}
SpellModifier(SpellModOp _op, SpellModType _type, int32 _value, uint32 _spellId, uint64 _mask, uint32 _mask2 = 0, int16 _charges = 0)
: op(_op), type(_type), charges(_charges), value(_value), mask(_mask), mask2(_mask2), spellId(_spellId), lastAffected(NULL)
: op(_op), type(_type), charges(_charges), value(_value), mask(_mask, _mask2), spellId(_spellId), lastAffected(NULL)
{}
SpellModifier(SpellModOp _op, SpellModType _type, int32 _value, uint32 _spellId, ClassFamilyMask _mask, int16 _charges = 0)
: op(_op), type(_type), charges(_charges), value(_value), mask(_mask), spellId(_spellId), lastAffected(NULL)
{}
SpellModifier(SpellModOp _op, SpellModType _type, int32 _value, SpellEntry const* spellEntry, SpellEffectIndex eff, int16 _charges = 0);
@ -133,8 +137,7 @@ struct SpellModifier
SpellModType type : 8;
int16 charges : 16;
int32 value;
uint64 mask;
uint32 mask2;
ClassFamilyMask mask;
uint32 spellId;
Spell const* lastAffected;
};

View file

@ -4787,8 +4787,8 @@ SpellCastResult Spell::CheckCast(bool strict)
// Exclusion for Pounce: Facing Limitation was removed in 2.0.1, but it still uses the same, old Ex-Flags
// Exclusion for Mutilate:Facing Limitation was removed in 2.0.1 and 3.0.3, but they still use the same, old Ex-Flags
// Exclusion for Throw: Facing limitation was added in 3.2.x, but that shouldn't be
if ((m_spellInfo->SpellFamilyName != SPELLFAMILY_DRUID || (m_spellInfo->SpellFamilyFlags != UI64LIT(0x0000000000020000))) &&
(m_spellInfo->SpellFamilyName != SPELLFAMILY_ROGUE || (m_spellInfo->SpellFamilyFlags != UI64LIT(0x0020000000000000))) &&
if (!m_spellInfo->IsFitToFamily(SPELLFAMILY_DRUID, UI64LIT(0x0000000000020000)) &&
!m_spellInfo->IsFitToFamily(SPELLFAMILY_ROGUE, UI64LIT(0x0020000000000000)) &&
m_spellInfo->Id != 2764)
{
SendInterrupted(2);

View file

@ -852,25 +852,16 @@ void Aura::ApplyModifier(bool apply, bool Real)
bool Aura::isAffectedOnSpell(SpellEntry const *spell) const
{
// Check family name
if (spell->SpellFamilyName != GetSpellProto()->SpellFamilyName)
return false;
// Check EffectClassMask
uint32 const *ptr = getAuraSpellClassMask();
if (((uint64*)ptr)[0] & spell->SpellFamilyFlags)
return true;
if (ptr[2] & spell->SpellFamilyFlags2)
return true;
return false;
return spell->IsFitToFamily(SpellFamily(GetSpellProto()->SpellFamilyName), GetAuraSpellClassMask());
}
bool Aura::CanProcFrom(SpellEntry const *spell, uint32 EventProcEx, uint32 procEx, bool active, bool useClassMask) const
{
// Check EffectClassMask
uint32 const *ptr = getAuraSpellClassMask();
ClassFamilyMask const& mask = GetAuraSpellClassMask();
// if no class mask defined, or spell_proc_event has SpellFamilyName=0 - allow proc
if (!useClassMask || (!((uint64*)ptr)[0] && !ptr[2]))
if (!useClassMask || !mask)
{
if (!(EventProcEx & PROC_EX_EX_TRIGGER_ALWAYS))
{
@ -896,14 +887,8 @@ bool Aura::CanProcFrom(SpellEntry const *spell, uint32 EventProcEx, uint32 procE
{
// SpellFamilyName check is performed in SpellMgr::IsSpellProcEventCanTriggeredBy and it is done once for whole holder
// note: SpellFamilyName is not checked if no spell_proc_event is defined
if (((uint64*)ptr)[0] & spell->SpellFamilyFlags)
return true;
if (ptr[2] & spell->SpellFamilyFlags2)
return true;
return mask.IsFitToFamilyMask(spell->SpellFamilyFlags);
}
return false;
}
void Aura::ReapplyAffectedPassiveAuras( Unit* target, bool owner_mode )
@ -1042,14 +1027,14 @@ void Aura::HandleAddModifier(bool apply, bool Real)
// Everlasting Affliction, overwrite wrong data, if will need more better restore support of spell_affect table
if (spellProto->SpellFamilyName == SPELLFAMILY_WARLOCK && spellProto->SpellIconID == 3169)
{
m_spellmod->mask = UI64LIT(0x0000010000000002); // Corruption and Unstable Affliction
m_spellmod->mask2 = 0x00000000;
// Corruption and Unstable Affliction
m_spellmod->mask = ClassFamilyMask(UI64LIT(0x0000010000000002));
}
// Improved Flametongue Weapon, overwrite wrong data, maybe time re-add table
else if (spellProto->Id == 37212)
{
m_spellmod->mask = UI64LIT(0x0000000000200000); // Flametongue Weapon (Passive)
m_spellmod->mask2 = 0x00000000;
// Flametongue Weapon (Passive)
m_spellmod->mask = ClassFamilyMask(UI64LIT(0x0000000000200000));
}
}
@ -6358,19 +6343,13 @@ void Aura::HandleNoReagentUseAura(bool /*Apply*/, bool Real)
if(target->GetTypeId() != TYPEID_PLAYER)
return;
uint32 mask[3] = {0, 0, 0};
ClassFamilyMask mask;
Unit::AuraList const& noReagent = target->GetAurasByType(SPELL_AURA_NO_REAGENT_USE);
for(Unit::AuraList::const_iterator i = noReagent.begin(); i != noReagent.end(); ++i)
{
uint32 const *ptr = (*i)->getAuraSpellClassMask();
mask[0] |= ptr[0];
mask[1] |= ptr[1];
mask[2] |= ptr[2];
}
for(Unit::AuraList::const_iterator i = noReagent.begin(); i != noReagent.end(); ++i)
mask |= (*i)->GetAuraSpellClassMask();
target->SetUInt32Value(PLAYER_NO_REAGENT_COST_1+0, mask[0]);
target->SetUInt32Value(PLAYER_NO_REAGENT_COST_1+1, mask[1]);
target->SetUInt32Value(PLAYER_NO_REAGENT_COST_1+2, mask[2]);
target->SetUInt64Value(PLAYER_NO_REAGENT_COST_1+0, mask.Flags);
target->SetUInt32Value(PLAYER_NO_REAGENT_COST_1+2, mask.Flags2);
}
/*********************************************************/
@ -8626,8 +8605,7 @@ void SpellAuraHolder::_RemoveSpellAuraHolder()
}
uint32 removeState = 0;
uint64 removeFamilyFlag = m_spellProto->SpellFamilyFlags;
uint32 removeFamilyFlag2 = m_spellProto->SpellFamilyFlags2;
ClassFamilyMask removeFamilyFlag = m_spellProto->SpellFamilyFlags;
switch(m_spellProto->SpellFamilyName)
{
case SPELLFAMILY_PALADIN:
@ -8638,8 +8616,7 @@ void SpellAuraHolder::_RemoveSpellAuraHolder()
// Conflagrate aura state on Immolate and Shadowflame,
if (m_spellProto->IsFitToFamilyMask(UI64LIT(0x0000000000000004), 0x00000002))
{
removeFamilyFlag = UI64LIT(0x0000000000000004);
removeFamilyFlag2 = 0x00000002;
removeFamilyFlag = ClassFamilyMask(UI64LIT(0x0000000000000004), 0x00000002);
removeState = AURA_STATE_CONFLAGRATE;
}
break;
@ -8648,7 +8625,7 @@ void SpellAuraHolder::_RemoveSpellAuraHolder()
removeState = AURA_STATE_FAERIE_FIRE; // Faerie Fire (druid versions)
else if (m_spellProto->IsFitToFamilyMask(UI64LIT(0x0000000000000050)))
{
removeFamilyFlag = 0x50;
removeFamilyFlag = ClassFamilyMask(UI64LIT(0x00000000000050));
removeState = AURA_STATE_SWIFTMEND; // Swiftmend aura state
}
break;
@ -8673,7 +8650,7 @@ void SpellAuraHolder::_RemoveSpellAuraHolder()
for (Unit::SpellAuraHolderMap::const_iterator i = holders.begin(); i != holders.end(); ++i)
{
SpellEntry const *auraSpellInfo = (*i).second->GetSpellProto();
if (auraSpellInfo->IsFitToFamily(SpellFamily(m_spellProto->SpellFamilyName), removeFamilyFlag, removeFamilyFlag2))
if (auraSpellInfo->IsFitToFamily(SpellFamily(m_spellProto->SpellFamilyName), removeFamilyFlag))
{
found = true;
break;

View file

@ -441,7 +441,7 @@ class MANGOS_DLL_SPEC Aura
void TriggerSpell();
void TriggerSpellWithValue();
uint32 const *getAuraSpellClassMask() const { return m_spellAuraHolder->GetSpellProto()->GetEffectSpellClassMask(m_effIndex); }
ClassFamilyMask const& GetAuraSpellClassMask() const { return m_spellAuraHolder->GetSpellProto()->GetEffectSpellClassMask(m_effIndex); }
bool isAffectedOnSpell(SpellEntry const *spell) const;
bool CanProcFrom(SpellEntry const *spell, uint32 EventProcEx, uint32 procEx, bool active, bool useClassMask) const;

View file

@ -6061,7 +6061,7 @@ void Spell::EffectWeaponDmg(SpellEffectIndex eff_idx)
((Player*)m_caster)->AddComboPoints(unitTarget, 1);
}
// Mangle (Cat): CP
else if (m_spellInfo->SpellFamilyName==SPELLFAMILY_DRUID && (m_spellInfo->SpellFamilyFlags==UI64LIT(0x0000040000000000)))
else if (m_spellInfo->IsFitToFamily(SPELLFAMILY_DRUID, UI64LIT(0x0000040000000000)))
{
if(m_caster->GetTypeId()==TYPEID_PLAYER)
((Player*)m_caster)->AddComboPoints(unitTarget, 1);
@ -7494,8 +7494,8 @@ void Spell::EffectScriptEffect(SpellEffectIndex eff_idx)
continue;
// Search only Serpent Sting, Viper Sting, Scorpid Sting auras
uint64 familyFlag = holder->GetSpellProto()->SpellFamilyFlags;
if (!(familyFlag & UI64LIT(0x000000800000C000)))
ClassFamilyMask const& familyFlag = holder->GetSpellProto()->SpellFamilyFlags;
if (!familyFlag.IsFitToFamilyMask(UI64LIT(0x000000800000C000)))
continue;
// Refresh aura duration
@ -7507,7 +7507,7 @@ void Spell::EffectScriptEffect(SpellEffectIndex eff_idx)
continue;
// Serpent Sting - Instantly deals 40% of the damage done by your Serpent Sting.
if ((familyFlag & UI64LIT(0x0000000000004000)))
if (familyFlag.IsFitToFamilyMask(UI64LIT(0x0000000000004000)))
{
// m_amount already include RAP bonus
basePoint = aura->GetModifier()->m_amount * aura->GetAuraMaxTicks() * 40 / 100;
@ -7515,7 +7515,7 @@ void Spell::EffectScriptEffect(SpellEffectIndex eff_idx)
}
// Viper Sting - Instantly restores mana to you equal to 60% of the total amount drained by your Viper Sting.
if ((familyFlag & UI64LIT(0x0000008000000000)))
if (familyFlag.IsFitToFamilyMask(UI64LIT(0x0000008000000000)))
{
uint32 target_max_mana = unitTarget->GetMaxPower(POWER_MANA);
if (!target_max_mana)
@ -7538,7 +7538,7 @@ void Spell::EffectScriptEffect(SpellEffectIndex eff_idx)
}
// Scorpid Sting - Attempts to Disarm the target for 10 sec. This effect cannot occur more than once per 1 minute.
if (familyFlag & UI64LIT(0x0000000000008000))
if (familyFlag.IsFitToFamilyMask(UI64LIT(0x0000000000008000)))
spellId = 53359; // Chimera Shot - Scorpid
// ?? nothing say in spell desc (possibly need addition check)
//if ((familyFlag & UI64LIT(0x0000010000000000)) || // dot
@ -7743,11 +7743,10 @@ void Spell::EffectSanctuary(SpellEffectIndex /*eff_idx*/)
unitTarget->CombatStop();
unitTarget->getHostileRefManager().deleteReferences(); // stop all fighting
// Vanish allows to remove all threat and cast regular stealth so other spells can be used
if(m_spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && (m_spellInfo->SpellFamilyFlags & SPELLFAMILYFLAG_ROGUE_VANISH))
{
if (m_spellInfo->IsFitToFamily(SPELLFAMILY_ROGUE, UI64LIT(0x0000000000000800)))
((Player *)m_caster)->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
}
}
void Spell::EffectAddComboPoints(SpellEffectIndex /*eff_idx*/)

View file

@ -1164,13 +1164,7 @@ struct DoSpellProcEvent
{
if (spe.spellFamilyMask[i] != r_spe.spellFamilyMask[i])
{
sLog.outErrorDb("Spell %u listed in `spell_proc_event` as custom rank have different spellFamilyMask from first rank in chain", spell_id);
break;
}
if (spe.spellFamilyMask2[i] != r_spe.spellFamilyMask2[i])
{
sLog.outErrorDb("Spell %u listed in `spell_proc_event` as custom rank have different spellFamilyMask2 from first rank in chain", spell_id);
sLog.outErrorDb("Spell %u listed in `spell_proc_event` as custom rank have different spellFamilyMask/spellFamilyMask2 from first rank in chain", spell_id);
break;
}
}
@ -1244,11 +1238,11 @@ struct DoSpellProcEvent
bool empty = !spe.spellFamilyName ? true : false;
for (int32 i = 0; i < MAX_EFFECT_INDEX; ++i)
{
if (spe.spellFamilyMask[i] || spe.spellFamilyMask2[i])
if (spe.spellFamilyMask[i])
{
empty = false;
uint32 const* ptr = spell->GetEffectSpellClassMask(SpellEffectIndex(i));
if ((((uint64*)ptr)[0] != 0 && spe.spellFamilyMask[i] == ((uint64*)ptr)[0]) && (ptr[2] == 0 || spe.spellFamilyMask2[i] == ptr[2]))
ClassFamilyMask const& mask = spell->GetEffectSpellClassMask(SpellEffectIndex(i));
if (mask == spe.spellFamilyMask[i])
sLog.outErrorDb("Spell %u listed in `spell_proc_event` has same class mask as in Spell.dbc (EffectIndex %u) and doesn't have any other data", spell->Id, i);
}
}
@ -1304,8 +1298,9 @@ void SpellMgr::LoadSpellProcEvents()
for (int32 i = 0; i < MAX_EFFECT_INDEX; ++i)
{
spe.spellFamilyMask[i] = (uint64)fields[i+3].GetUInt32()|((uint64)fields[i+6].GetUInt32()<<32);
spe.spellFamilyMask2[i] = fields[i+9].GetUInt32();
spe.spellFamilyMask[i] = ClassFamilyMask(
(uint64)fields[i+3].GetUInt32() | ((uint64)fields[i+6].GetUInt32()<<32),
fields[i+9].GetUInt32());
}
spe.procFlags = fields[12].GetUInt32();
spe.procEx = fields[13].GetUInt32();
@ -1827,19 +1822,14 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons
SpellEntry const *spellInfo_1 = sSpellStore.LookupEntry(spellId_1);
SpellEntry const *spellInfo_2 = sSpellStore.LookupEntry(spellId_2);
if(!spellInfo_1 || !spellInfo_2)
if (!spellInfo_1 || !spellInfo_2)
return false;
if(spellId_1 == spellId_2)
return false;
//I think we don't check this correctly because i need a exception for spell:
//72,11327,18461...(called from 1856,1857...) Call Aura 16,31, after trigger another spell who call aura 77 and 77 remove 16 and 31, this should not happen.
if(spellInfo_2->SpellFamilyFlags == 2048)
if (spellId_1 == spellId_2)
return false;
// Resurrection sickness
if((spellInfo_1->Id == SPELL_ID_PASSIVE_RESURRECTION_SICKNESS) != (spellInfo_2->Id==SPELL_ID_PASSIVE_RESURRECTION_SICKNESS))
if ((spellInfo_1->Id == SPELL_ID_PASSIVE_RESURRECTION_SICKNESS) != (spellInfo_2->Id==SPELL_ID_PASSIVE_RESURRECTION_SICKNESS))
return false;
// Allow stack passive and not passive spells
@ -2255,8 +2245,8 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons
return true;
// Swift Retribution / Improved Devotion Aura (talents) and Paladin Auras
if (((spellInfo_1->SpellFamilyFlags2 & 0x00000020) && (spellInfo_2->SpellIconID == 291 || spellInfo_2->SpellIconID == 3028)) ||
((spellInfo_2->SpellFamilyFlags2 & 0x00000020) && (spellInfo_1->SpellIconID == 291 || spellInfo_1->SpellIconID == 3028)))
if ((spellInfo_1->IsFitToFamilyMask(UI64LIT(0x0), 0x00000020) && (spellInfo_2->SpellIconID == 291 || spellInfo_2->SpellIconID == 3028)) ||
(spellInfo_2->IsFitToFamilyMask(UI64LIT(0x0), 0x00000020) && (spellInfo_1->SpellIconID == 291 || spellInfo_1->SpellIconID == 3028)))
return false;
// Beacon of Light and Light's Beacon
@ -2302,7 +2292,7 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons
{
// Windfury weapon
if (spellInfo_1->SpellIconID==220 && spellInfo_2->SpellIconID==220 &&
spellInfo_1->SpellFamilyFlags != spellInfo_2->SpellFamilyFlags)
!spellInfo_1->IsFitToFamilyMask(spellInfo_2->SpellFamilyFlags))
return false;
// Ghost Wolf
@ -4107,7 +4097,7 @@ void SpellMgr::CheckUsedSpells(char const* table)
{
if(familyMaskA == UI64LIT(0x0000000000000000) && familyMaskB == 0x00000000)
{
if(spellEntry->SpellFamilyFlags != 0 || spellEntry->SpellFamilyFlags2 != 0)
if (spellEntry->SpellFamilyFlags)
{
sLog.outError("Spell %u '%s' not fit to (" I64FMT "," I32FMT ") but used in %s.",
spell, name.c_str(), familyMaskA, familyMaskB, code.c_str());
@ -4117,7 +4107,7 @@ void SpellMgr::CheckUsedSpells(char const* table)
}
else
{
if((spellEntry->SpellFamilyFlags & familyMaskA)==0 && (spellEntry->SpellFamilyFlags2 & familyMaskB)==0)
if (!spellEntry->IsFitToFamilyMask(familyMaskA, familyMaskB))
{
sLog.outError("Spell %u '%s' not fit to (" I64FMT "," I32FMT ") but used in %s.",spell,name.c_str(),familyMaskA,familyMaskB,code.c_str());
continue;
@ -4192,12 +4182,12 @@ void SpellMgr::CheckUsedSpells(char const* table)
{
if(familyMaskA == UI64LIT(0x0000000000000000) && familyMaskB == 0x00000000)
{
if(spellEntry->SpellFamilyFlags != 0 || spellEntry->SpellFamilyFlags2 != 0)
if (spellEntry->SpellFamilyFlags)
continue;
}
else
{
if ((spellEntry->SpellFamilyFlags & familyMaskA)==0 && (spellEntry->SpellFamilyFlags2 & familyMaskB)==0)
if (!spellEntry->IsFitToFamilyMask(familyMaskA, familyMaskB))
continue;
}
}

View file

@ -47,17 +47,6 @@ enum SpellCategories
SPELLCATEGORY_JUDGEMENT = 1210, // Judgement (seal trigger)
};
//Some SpellFamilyFlags
#define SPELLFAMILYFLAG_ROGUE_VANISH UI64LIT(0x0000000000000800)
#define SPELLFAMILYFLAG_ROGUE_STEALTH UI64LIT(0x0000000000400000)
#define SPELLFAMILYFLAG_ROGUE_BACKSTAB UI64LIT(0x0000000000800004)
#define SPELLFAMILYFLAG_ROGUE_SAP UI64LIT(0x0000000000000080)
#define SPELLFAMILYFLAG_ROGUE_FEINT UI64LIT(0x0000000008000000)
#define SPELLFAMILYFLAG_ROGUE_KIDNEYSHOT UI64LIT(0x0000000000200000)
#define SPELLFAMILYFLAG_ROGUE__FINISHING_MOVE UI64LIT(0x00000009003E0000)
#define SPELLFAMILYFLAG_PALADIN_SEALS UI64LIT(0x26000C000A000000)
// Spell clasification
enum SpellSpecific
{
@ -179,8 +168,7 @@ bool IsNoStackAuraDueToAura(uint32 spellId_1, uint32 spellId_2);
inline bool IsSealSpell(SpellEntry const *spellInfo)
{
//Collection of all the seal family flags. No other paladin spell has any of those.
return spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN &&
( spellInfo->SpellFamilyFlags & SPELLFAMILYFLAG_PALADIN_SEALS ) &&
return spellInfo->IsFitToFamily(SPELLFAMILY_PALADIN, UI64LIT(0x26000C000A000000)) &&
// avoid counting target triggered effect as seal for avoid remove it or seal by it.
spellInfo->EffectImplicitTargetA[EFFECT_INDEX_0] == TARGET_SELF;
}
@ -618,8 +606,7 @@ struct SpellProcEventEntry
{
uint32 schoolMask; // if nonzero - bit mask for matching proc condition based on spell candidate's school: Fire=2, Mask=1<<(2-1)=2
uint32 spellFamilyName; // if nonzero - for matching proc condition based on candidate spell's SpellFamilyNamer value
uint64 spellFamilyMask[MAX_EFFECT_INDEX]; // if nonzero - for matching proc condition based on candidate spell's SpellFamilyFlags (like auras 107 and 108 do)
uint32 spellFamilyMask2[MAX_EFFECT_INDEX]; // if nonzero - for matching proc condition based on candidate spell's SpellFamilyFlags2 (like auras 107 and 108 do)
ClassFamilyMask spellFamilyMask[MAX_EFFECT_INDEX]; // if nonzero - for matching proc condition based on candidate spell's SpellFamilyFlags (like auras 107 and 108 do)
uint32 procFlags; // bitmask for matching proc event
uint32 procEx; // proc Extend info (see ProcFlagsEx)
float ppmRate; // for melee (ranged?) damage spells - proc rate per minute. if zero, falls back to flat chance from Spell.dbc

View file

@ -2127,7 +2127,7 @@ void Unit::CalculateDamageAbsorbAndResist(Unit *pCaster, SpellSchoolMask schoolM
continue;
}
// Reflective Shield
if (spellProto->SpellFamilyFlags == 0x1 && canReflect)
if (spellProto->IsFitToFamilyMask(UI64LIT(0x0000000000000001)) && canReflect)
{
if (pCaster == this)
break;
@ -9814,9 +9814,9 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag
{
if (spellProcEvent)
{
if (spellProcEvent->spellFamilyMask[i] || spellProcEvent->spellFamilyMask2[i])
if (spellProcEvent->spellFamilyMask[i])
{
if (!procSpell->IsFitToFamilyMask(spellProcEvent->spellFamilyMask[i], spellProcEvent->spellFamilyMask2[i]))
if (!procSpell->IsFitToFamilyMask(spellProcEvent->spellFamilyMask[i]))
continue;
}
// don't check dbc FamilyFlags if schoolMask exists

View file

@ -1154,7 +1154,7 @@ SpellAuraProcResult Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura
case SPELLFAMILY_WARRIOR:
{
// Retaliation
if (dummySpell->SpellFamilyFlags == UI64LIT(0x0000000800000000))
if (dummySpell->IsFitToFamilyMask(UI64LIT(0x0000000800000000)))
{
// check attack comes not from behind
if (!HasInArc(M_PI_F, pVictim))
@ -3796,7 +3796,7 @@ SpellAuraProcResult Unit::HandleMendingAuraProc( Unit* /*pVictim*/, uint32 /*dam
if(Player* target = ((Player*)this)->GetNextRandomRaidMember(radius))
{
// aura will applied from caster, but spell casted from current aura holder
SpellModifier *mod = new SpellModifier(SPELLMOD_CHARGES,SPELLMOD_FLAT,jumps-5,spellProto->Id,spellProto->SpellFamilyFlags,spellProto->SpellFamilyFlags2);
SpellModifier *mod = new SpellModifier(SPELLMOD_CHARGES,SPELLMOD_FLAT,jumps-5,spellProto->Id,spellProto->SpellFamilyFlags);
// remove before apply next (locked against deleted)
triggeredByAura->SetInUse(true);

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__
#define __REVISION_NR_H__
#define REVISION_NR "11622"
#define REVISION_NR "11623"
#endif // __REVISION_NR_H__