Work under spell mods

* Add support > 64 bit spellFamily mask
    * Remove not used fields in SpellModifier
    * Remove not used (and not correct work vs charges) GetTotalFlatMods, GetTotalPctMods
    * Use DBC based data for spell_affect
    * More better work SPELL_AURA_ADD_TARGET_TRIGGER aura

Signed-off-by: DiSlord <dislord@nomail.com>
This commit is contained in:
DiSlord 2008-12-08 23:22:39 +03:00
parent 916bd178a2
commit 9b842b6fdc
13 changed files with 145 additions and 127 deletions

View file

@ -0,0 +1,12 @@
--
-- Table structure for table `spell_affect`
--
DROP TABLE IF EXISTS `spell_affect`;
CREATE TABLE `spell_affect` (
`entry` smallint(5) unsigned NOT NULL default '0',
`effectId` tinyint(3) unsigned NOT NULL default '0',
`SpellClassMask0` int(5) unsigned NOT NULL default '0',
`SpellClassMask1` int(5) unsigned NOT NULL default '0',
`SpellClassMask2` int(5) unsigned NOT NULL default '0',
PRIMARY KEY (`entry`,`effectId`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

View file

@ -16361,42 +16361,6 @@ void Player::CharmSpellInitialize()
GetSession()->SendPacket(&data);
}
int32 Player::GetTotalFlatMods(uint32 spellId, SpellModOp op)
{
SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId);
if (!spellInfo) return 0;
int32 total = 0;
for (SpellModList::iterator itr = m_spellMods[op].begin(); itr != m_spellMods[op].end(); ++itr)
{
SpellModifier *mod = *itr;
if(!IsAffectedBySpellmod(spellInfo,mod))
continue;
if (mod->type == SPELLMOD_FLAT)
total += mod->value;
}
return total;
}
int32 Player::GetTotalPctMods(uint32 spellId, SpellModOp op)
{
SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId);
if (!spellInfo) return 0;
int32 total = 0;
for (SpellModList::iterator itr = m_spellMods[op].begin(); itr != m_spellMods[op].end(); ++itr)
{
SpellModifier *mod = *itr;
if(!IsAffectedBySpellmod(spellInfo,mod))
continue;
if (mod->type == SPELLMOD_PCT)
total += mod->value;
}
return total;
}
bool Player::IsAffectedBySpellmod(SpellEntry const *spellInfo, SpellModifier *mod, Spell const* spell)
{
if (!mod || !spellInfo)
@ -16414,22 +16378,25 @@ bool Player::IsAffectedBySpellmod(SpellEntry const *spellInfo, SpellModifier *mo
return false;
}
return spellmgr.IsAffectedBySpell(spellInfo,mod->spellId,mod->effectId,mod->mask);
return spellmgr.IsAffectedByMod(spellInfo, mod);
}
void Player::AddSpellMod(SpellModifier* mod, bool apply)
{
uint16 Opcode= (mod->type == SPELLMOD_FLAT) ? SMSG_SET_FLAT_SPELL_MODIFIER : SMSG_SET_PCT_SPELL_MODIFIER;
for(int eff=0;eff<64;++eff)
for(int eff=0;eff<96;++eff)
{
uint64 _mask = uint64(1) << eff;
if ( mod->mask & _mask)
uint64 _mask = 0;
uint64 _mask2= 0;
if (eff<64) _mask = uint64(1) << (eff- 0);
else _mask2= uint64(1) << (eff-64);
if ( mod->mask & _mask || mod->mask2 & _mask2)
{
int32 val = 0;
for (SpellModList::iterator itr = m_spellMods[mod->op].begin(); itr != m_spellMods[mod->op].end(); ++itr)
{
if ((*itr)->type == mod->type && (*itr)->mask & _mask)
if ((*itr)->type == mod->type && ((*itr)->mask & _mask || (*itr)->mask2 & _mask2))
val += (*itr)->value;
}
val += apply ? mod->value : -(mod->value);

View file

@ -80,15 +80,17 @@ struct PlayerSpell
#define SPELL_WITHOUT_SLOT_ID uint16(-1)
// Spell modifier (used for modify other spells)
struct SpellModifier
{
SpellModifier() : charges(0), lastAffected(NULL) {}
SpellModOp op : 8;
SpellModType type : 8;
int16 charges : 16;
int32 value;
uint64 mask;
uint64 mask2;
uint32 spellId;
uint32 effectId;
Spell const* lastAffected;
};
@ -1483,8 +1485,6 @@ class MANGOS_DLL_SPEC Player : public Unit
PlayerSpellMap & GetSpellMap() { return m_spells; }
void AddSpellMod(SpellModifier* mod, bool apply);
int32 GetTotalFlatMods(uint32 spellId, SpellModOp op);
int32 GetTotalPctMods(uint32 spellId, SpellModOp op);
bool IsAffectedBySpellmod(SpellEntry const *spellInfo, SpellModifier *mod, Spell const* spell = NULL);
template <class T> T ApplySpellMod(uint32 spellId, SpellModOp op, T &basevalue, Spell const* spell = NULL);
void RemoveSpellMods(Spell const* spell);

View file

@ -2521,7 +2521,7 @@ void Spell::finish(bool ok)
{
SpellEntry const *auraSpellInfo = (*i)->GetSpellProto();
uint32 auraSpellIdx = (*i)->GetEffIndex();
if (IsAffectedBy(auraSpellInfo, auraSpellIdx))
if (IsAffectedByAura((*i)))
{
for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit)
if( ihit->effectMask & (1<<auraSpellIdx) )
@ -5039,9 +5039,9 @@ void Spell::UpdatePointers()
m_targets.Update(m_caster);
}
bool Spell::IsAffectedBy(SpellEntry const *spellInfo, uint32 effectId)
bool Spell::IsAffectedByAura(Aura *aura)
{
return spellmgr.IsAffectedBySpell(m_spellInfo,spellInfo->Id,effectId,spellInfo->EffectItemType[effectId]);
return spellmgr.IsAffectedByMod(m_spellInfo, aura->getAuraSpellMod());
}
bool Spell::CheckTargetCreatureType(Unit* target) const

View file

@ -422,7 +422,7 @@ class Spell
void UpdatePointers(); // must be used at call Spell code after time delay (non triggered spell cast/update spell call/etc)
bool IsAffectedBy(SpellEntry const *spellInfo, uint32 effectId);
bool IsAffectedByAura(Aura *aura);
bool CheckTargetCreatureType(Unit* target) const;

View file

@ -159,7 +159,7 @@ pAuraHandler AuraHandler[TOTAL_AURAS]=
&Aura::HandleAuraHover, //106 SPELL_AURA_HOVER
&Aura::HandleAddModifier, //107 SPELL_AURA_ADD_FLAT_MODIFIER
&Aura::HandleAddModifier, //108 SPELL_AURA_ADD_PCT_MODIFIER
&Aura::HandleNoImmediateEffect, //109 SPELL_AURA_ADD_TARGET_TRIGGER
&Aura::HandleAddTargetTrigger, //109 SPELL_AURA_ADD_TARGET_TRIGGER
&Aura::HandleModPowerRegenPCT, //110 SPELL_AURA_MOD_POWER_REGEN_PERCENT
&Aura::HandleNULL, //111 SPELL_AURA_ADD_CASTER_HIT_TRIGGER
&Aura::HandleNoImmediateEffect, //112 SPELL_AURA_OVERRIDE_CLASS_SCRIPTS
@ -1180,10 +1180,6 @@ void Aura::HandleAddModifier(bool apply, bool Real)
if(m_target->GetTypeId() != TYPEID_PLAYER || !Real)
return;
SpellEntry const *spellInfo = GetSpellProto();
if(!spellInfo)
return;
if(m_modifier.m_miscvalue >= MAX_SPELLMOD)
return;
@ -1204,15 +1200,25 @@ void Aura::HandleAddModifier(bool apply, bool Real)
mod->value = m_modifier.m_amount;
mod->type = SpellModType(m_modifier.m_auraname); // SpellModType value == spell aura types
mod->spellId = GetId();
mod->effectId = m_effIndex;
mod->lastAffected = NULL;
uint64 spellAffectMask = spellmgr.GetSpellAffectMask(GetId(), m_effIndex);
if (spellAffectMask)
mod->mask = spellAffectMask;
uint32 const *ptr;
SpellAffectEntry const *spellAffect = spellmgr.GetSpellAffect(GetId(), m_effIndex);
if (spellAffect)
ptr = spellAffect->SpellClassMask;
else
mod->mask = spellInfo->EffectItemType[m_effIndex];
{
switch (m_effIndex)
{
case 0: ptr = m_spellProto->EffectSpellClassMaskA; break;
case 1: ptr = m_spellProto->EffectSpellClassMaskB; break;
case 2: ptr = m_spellProto->EffectSpellClassMaskC; break;
default:
return;
}
}
mod->mask = (uint64)ptr[0] | (uint64)ptr[1]<<32;
mod->mask2= (uint64)ptr[2];
if (m_procCharges > 0)
mod->charges = m_procCharges;
@ -1227,7 +1233,7 @@ void Aura::HandleAddModifier(bool apply, bool Real)
((Player*)m_target)->AddSpellMod(m_spellmod, apply);
// reapply some passive spells after add/remove related spellmods
if(spellInfo->SpellFamilyName==SPELLFAMILY_WARRIOR && (spellFamilyMask & 0x0000100000000000LL))
if(m_spellProto->SpellFamilyName==SPELLFAMILY_WARRIOR && (spellFamilyMask & 0x0000100000000000LL))
{
m_target->RemoveAurasDueToSpell(45471);
@ -1235,7 +1241,42 @@ void Aura::HandleAddModifier(bool apply, bool Real)
m_target->CastSpell(m_target,45471,true);
}
}
void Aura::HandleAddTargetTrigger(bool apply, bool Real)
{
// Use SpellModifier structure for check
// used only fields:
// spellId, mask, mask2
if (apply)
{
SpellModifier *mod = new SpellModifier;
mod->spellId = GetId();
uint32 const *ptr;
SpellAffectEntry const *spellAffect = spellmgr.GetSpellAffect(GetId(), m_effIndex);
if (spellAffect)
ptr = spellAffect->SpellClassMask;
else
{
switch (m_effIndex)
{
case 0: ptr = m_spellProto->EffectSpellClassMaskA; break;
case 1: ptr = m_spellProto->EffectSpellClassMaskB; break;
case 2: ptr = m_spellProto->EffectSpellClassMaskC; break;
default:
return;
}
}
mod->mask = (uint64)ptr[0] | (uint64)ptr[1]<<32;
mod->mask2= (uint64)ptr[2];
m_spellmod = mod;
}
else
{
delete m_spellmod;
m_spellmod = NULL;
}
}
void Aura::TriggerSpell()
{
Unit* caster = GetCaster();
@ -2193,10 +2234,8 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
mod->value = m_modifier.m_amount/7;
mod->type = SPELLMOD_FLAT;
mod->spellId = GetId();
mod->effectId = m_effIndex;
mod->lastAffected = NULL;
mod->mask = 0x001000000000LL;
mod->charges = 0;
mod->mask2= 0LL;
m_spellmod = mod;
}
@ -2219,10 +2258,8 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
mod->value = m_modifier.m_amount;
mod->type = SPELLMOD_FLAT;
mod->spellId = GetId();
mod->effectId = m_effIndex;
mod->lastAffected = NULL;
mod->mask = 0x4000000000000LL;
mod->charges = 0;
mod->mask2= 0LL;
m_spellmod = mod;
}
@ -2244,18 +2281,17 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
mod->value = m_modifier.m_amount;
mod->type = SPELLMOD_PCT;
mod->spellId = GetId();
mod->effectId = m_effIndex;
mod->lastAffected = NULL;
switch (m_effIndex)
{
case 0:
mod->mask = 0x00200000000LL; // Windfury Totem
mod->mask2= 0LL;
break;
case 1:
mod->mask = 0x00400000000LL; // Flametongue Totem
mod->mask2= 0LL;
break;
}
mod->charges = 0;
m_spellmod = mod;
}

View file

@ -98,6 +98,7 @@ class MANGOS_DLL_SPEC Aura
void HandleAuraFeatherFall(bool Apply, bool Real);
void HandleAuraHover(bool Apply, bool Real);
void HandleAddModifier(bool Apply, bool Real);
void HandleAddTargetTrigger(bool Apply, bool Real);
void HandleAuraModStun(bool Apply, bool Real);
void HandleModDamageDone(bool Apply, bool Real);
void HandleAuraUntrackable(bool Apply, bool Real);
@ -230,6 +231,8 @@ class MANGOS_DLL_SPEC Aura
void SetAuraDuration(int32 duration) { m_duration = duration; }
time_t GetAuraApplyTime() { return m_applyTime; }
SpellModifier *getAuraSpellMod() {return m_spellmod; }
uint64 const& GetCasterGUID() const { return m_caster_guid; }
Unit* GetCaster() const;
Unit* GetTarget() const { return m_target; }

View file

@ -1524,10 +1524,8 @@ void Spell::EffectDummy(uint32 i)
mod->value = -50;
mod->type = SPELLMOD_PCT;
mod->spellId = m_spellInfo->Id;
mod->effectId = i;
mod->lastAffected = NULL;
mod->mask = 0x0000020000000000LL;
mod->charges = 0;
mod->mask2= 0LL;
((Player*)m_caster)->AddSpellMod(mod, true);
m_caster->CastSpell(unitTarget,spell_proto,true,NULL);

View file

@ -666,8 +666,8 @@ void SpellMgr::LoadSpellAffects()
uint32 count = 0;
// 0 1 2
QueryResult *result = WorldDatabase.Query("SELECT entry, effectId, SpellFamilyMask FROM spell_affect");
// 0 1 2 3 4
QueryResult *result = WorldDatabase.Query("SELECT entry, effectId, SpellClassMask0, SpellClassMask1, SpellClassMask2 FROM spell_affect");
if( !result )
{
@ -714,26 +714,29 @@ void SpellMgr::LoadSpellAffects()
continue;
}
uint64 spellAffectMask = fields[2].GetUInt64();
SpellAffectEntry affect;
affect.SpellClassMask[0] = fields[2].GetUInt32();
affect.SpellClassMask[1] = fields[3].GetUInt32();
affect.SpellClassMask[2] = fields[4].GetUInt32();
// Spell.dbc have own data for low part of SpellFamilyMask
if( spellInfo->EffectItemType[effectId])
// Spell.dbc have own data
uint32 const *ptr = 0;
switch (effectId)
{
if(spellInfo->EffectItemType[effectId] == spellAffectMask)
{
sLog.outErrorDb("Spell %u listed in `spell_affect` have redundant (same with EffectItemType%d) data for effect index (%u) and not needed, skipped.", entry,effectId+1,effectId);
case 0: ptr = spellInfo->EffectSpellClassMaskA; break;
case 1: ptr = spellInfo->EffectSpellClassMaskB; break;
case 2: ptr = spellInfo->EffectSpellClassMaskC; break;
default:
continue;
}
// 24429 have wrong data in EffectItemType and overwrites by DB, possible bug in client
if(spellInfo->Id!=24429 && spellInfo->EffectItemType[effectId] != spellAffectMask)
{
sLog.outErrorDb("Spell %u listed in `spell_affect` have different low part from EffectItemType%d for effect index (%u) and not needed, skipped.", entry,effectId+1,effectId);
continue;
}
}
if(ptr[0] == affect.SpellClassMask[0] || ptr[1] == affect.SpellClassMask[1] || ptr[2] == affect.SpellClassMask[2])
{
char text[]="ABC";
sLog.outErrorDb("Spell %u listed in `spell_affect` have redundant (same with EffectSpellClassMask%c) data for effect index (%u) and not needed, skipped.", entry, text[effectId], effectId);
continue;
}
mSpellAffectMap.insert(SpellAffectMap::value_type((entry<<8) + effectId,spellAffectMask));
mSpellAffectMap[(entry<<8) + effectId] = affect;
++count;
} while( result->NextRow() );
@ -741,7 +744,7 @@ void SpellMgr::LoadSpellAffects()
delete result;
sLog.outString();
sLog.outString( ">> Loaded %u spell affect definitions", count );
sLog.outString( ">> Loaded %u custom spell affect definitions", count );
for (uint32 id = 0; id < sSpellStore.GetNumRows(); ++id)
{
@ -757,7 +760,16 @@ void SpellMgr::LoadSpellAffects()
spellInfo->EffectApplyAuraName[effectId] != SPELL_AURA_ADD_TARGET_TRIGGER) )
continue;
if(spellInfo->EffectItemType[effectId] != 0)
uint32 const *ptr = 0;
switch (effectId)
{
case 0: ptr = spellInfo->EffectSpellClassMaskA; break;
case 1: ptr = spellInfo->EffectSpellClassMaskB; break;
case 2: ptr = spellInfo->EffectSpellClassMaskC; break;
default:
continue;
}
if(ptr[0] || ptr[1] || ptr[2])
continue;
if(mSpellAffectMap.find((id<<8) + effectId) != mSpellAffectMap.end())
@ -768,33 +780,20 @@ void SpellMgr::LoadSpellAffects()
}
}
bool SpellMgr::IsAffectedBySpell(SpellEntry const *spellInfo, uint32 spellId, uint8 effectId, uint64 familyFlags) const
bool SpellMgr::IsAffectedByMod(SpellEntry const *spellInfo, SpellModifier *mod) const
{
// false for spellInfo == NULL
if (!spellInfo)
if (!spellInfo || !mod)
return false;
SpellEntry const *affect_spell = sSpellStore.LookupEntry(spellId);
// false for affect_spell == NULL
if (!affect_spell)
SpellEntry const *affect_spell = sSpellStore.LookupEntry(mod->spellId);
// False if affect_spell == NULL or spellFamily not equal
if (!affect_spell || affect_spell->SpellFamilyName != spellInfo->SpellFamilyName)
return false;
// False if spellFamily not equal
if (affect_spell->SpellFamilyName != spellInfo->SpellFamilyName)
return false;
// If familyFlags == 0
if (!familyFlags)
{
// Get it from spellAffect table
familyFlags = GetSpellAffectMask(spellId,effectId);
// false if familyFlags == 0
if (!familyFlags)
return false;
}
// true
if (familyFlags & spellInfo->SpellFamilyFlags)
if (mod->mask & spellInfo->SpellFamilyFlags ||
mod->mask2 & spellInfo->SpellFamilyFlags2)
return true;
return false;

View file

@ -27,6 +27,9 @@
#include "Database/SQLStorage.h"
#include "Utilities/UnorderedMap.h"
#include "Player.h"
#include <map>
class Player;
@ -450,7 +453,11 @@ bool IsDiminishingReturnsGroupDurationLimited(DiminishingGroup group);
DiminishingReturnsType GetDiminishingReturnsGroupType(DiminishingGroup group);
// Spell affects related declarations (accessed using SpellMgr functions)
typedef std::map<uint32, uint64> SpellAffectMap;
struct SpellAffectEntry
{
uint32 SpellClassMask[3];
};
typedef UNORDERED_MAP<uint32, SpellAffectEntry> SpellAffectMap;
// Spell proc event related declarations (accessed using SpellMgr functions)
enum ProcFlags
@ -657,15 +664,15 @@ class SpellMgr
// Accessors (const or static functions)
public:
// Spell affects
uint64 GetSpellAffectMask(uint16 spellId, uint8 effectId) const
SpellAffectEntry const*GetSpellAffect(uint16 spellId, uint8 effectId) const
{
SpellAffectMap::const_iterator itr = mSpellAffectMap.find((spellId<<8) + effectId);
if( itr != mSpellAffectMap.end( ) )
return itr->second;
return &itr->second;
return 0;
}
bool IsAffectedBySpell(SpellEntry const *spellInfo, uint32 spellId, uint8 effectId, uint64 familyFlags) const;
bool IsAffectedByMod(SpellEntry const *spellInfo, SpellModifier *mod) const;
SpellElixirMap const& GetSpellElixirMap() const { return mSpellElixirs; }

View file

@ -5763,10 +5763,8 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
mod->value = -100;
mod->type = SPELLMOD_PCT;
mod->spellId = dummySpell->Id;
mod->effectId = 0;
mod->lastAffected = NULL;
mod->mask = 0x0000000000000003LL;
mod->charges = 0;
mod->mask2= 0LL;
((Player*)this)->AddSpellMod(mod, true);
// Remove cooldown (Chain Lightning - have Category Recovery time)
@ -10929,10 +10927,8 @@ bool Unit::HandleMeandingAuraProc( Aura* triggeredByAura )
mod->value = jumps-5; // negative
mod->type = SPELLMOD_FLAT;
mod->spellId = spellProto->Id;
mod->effectId = effIdx;
mod->lastAffected = NULL;
mod->mask = spellProto->SpellFamilyFlags;
mod->charges = 0;
mod->mask = spellProto->SpellFamilyFlags;
mod->mask2 = spellProto->SpellFamilyFlags2;
caster->AddSpellMod(mod, true);
CastCustomSpell(target,spellProto->Id,&heal,NULL,NULL,true,NULL,triggeredByAura,caster->GetGUID());

View file

@ -1110,9 +1110,9 @@ struct SpellEntry
int32 EffectMiscValueB[3]; // 116-118 m_effectMiscValueB
uint32 EffectTriggerSpell[3]; // 119-121 m_effectTriggerSpell
float EffectPointsPerComboPoint[3]; // 122-124 m_effectPointsPerCombo
//uint32 EffectSpellClassMaskA[3]; // 125-127 m_effectSpellClassMaskA not used
//uint32 EffectSpellClassMaskB[3]; // 128-130 m_effectSpellClassMaskB not used
//uint32 EffectSpellClassMaskC[3]; // 131-133 m_effectSpellClassMaskC not used
uint32 EffectSpellClassMaskA[3]; // 125-127 m_effectSpellClassMaskA
uint32 EffectSpellClassMaskB[3]; // 128-130 m_effectSpellClassMaskB
uint32 EffectSpellClassMaskC[3]; // 131-133 m_effectSpellClassMaskC
uint32 SpellVisual[2]; // 134-135 m_spellVisualID
uint32 SpellIconID; // 136 m_spellIconID
uint32 activeIconID; // 137 m_activeIconID

View file

@ -69,7 +69,7 @@ const char SkillLineAbilityfmt[]="niiiixxiiiiixx";
const char SoundEntriesfmt[]="nxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
const char SpellCastTimefmt[]="nixx";
const char SpellDurationfmt[]="niii";
const char SpellEntryfmt[]="niiiiiiiiixiiiiiiiiiixxxxiiiiiiiiiiiiiiiiiiifxiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiffffffiiiiiiiiiiiiiiiiiiiiifffiiiiiiiiiiiiiiifffxxxxxxxxxiiiixssssssssssssssssxssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiiiiiiiiiiixfffxxxiiiiix";
const char SpellEntryfmt[]="niiiiiiiiixiiiiiiiiiixxxxiiiiiiiiiiiiiiiiiiifxiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiffffffiiiiiiiiiiiiiiiiiiiiifffiiiiiiiiiiiiiiifffiiiiiiiiiiiiixssssssssssssssssxssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiiiiiiiiiiixfffxxxiiiiix";
const char SpellFocusObjectfmt[]="nxxxxxxxxxxxxxxxxx";
const char SpellItemEnchantmentfmt[]="nxiiiiiixxxiiissssssssssssssssxiiiixx";
const char SpellItemEnchantmentConditionfmt[]="nbbbbbxxxxxbbbbbbbbbbiiiiiXXXXX";