mirror of
https://github.com/mangosfour/server.git
synced 2025-12-13 13:37:05 +00:00
[11748] Replace SpellModifier struct by direct aura access (this should fix charge drops of 36032) also revert [11740]
This commit is contained in:
parent
c9a9179d89
commit
e178c79d51
10 changed files with 131 additions and 267 deletions
|
|
@ -271,26 +271,6 @@ std::ostringstream& operator<< (std::ostringstream& ss, PlayerTaxi const& taxi)
|
|||
ss << taxi.m_taximask[i] << " ";
|
||||
return ss;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
return false;
|
||||
return spell->IsFitToFamilyMask(mask);
|
||||
}
|
||||
|
||||
//== TradeData =================================================
|
||||
|
||||
TradeData* TradeData::GetTraderData() const
|
||||
|
|
@ -439,8 +419,6 @@ Player::Player (WorldSession *session): Unit(), m_mover(this), m_camera(this), m
|
|||
|
||||
clearResurrectRequestData();
|
||||
|
||||
m_SpellModRemoveCount = 0;
|
||||
|
||||
memset(m_items, 0, sizeof(Item*)*PLAYER_SLOTS_COUNT);
|
||||
|
||||
m_social = NULL;
|
||||
|
|
@ -18600,29 +18578,10 @@ void Player::RemovePetActionBar()
|
|||
SendDirectMessage(&data);
|
||||
}
|
||||
|
||||
bool Player::IsAffectedBySpellmod(SpellEntry const *spellInfo, SpellModifier *mod, Spell const* spell)
|
||||
void Player::AddSpellMod(Aura* aura, bool apply)
|
||||
{
|
||||
if (!mod || !spellInfo)
|
||||
return false;
|
||||
|
||||
if(mod->charges == -1 && mod->lastAffected ) // marked as expired but locked until spell casting finish
|
||||
{
|
||||
// prevent apply to any spell except spell that trigger expire
|
||||
if(spell)
|
||||
{
|
||||
if(mod->lastAffected != spell)
|
||||
return false;
|
||||
}
|
||||
else if(mod->lastAffected != FindCurrentSpellBySpellId(spellInfo->Id))
|
||||
return false;
|
||||
}
|
||||
|
||||
return mod->isAffectedOnSpell(spellInfo);
|
||||
}
|
||||
|
||||
void Player::AddSpellMod(SpellModifier* mod, bool apply)
|
||||
{
|
||||
uint16 Opcode= (mod->type == SPELLMOD_FLAT) ? SMSG_SET_FLAT_SPELL_MODIFIER : SMSG_SET_PCT_SPELL_MODIFIER;
|
||||
Modifier const* mod = aura->GetModifier();
|
||||
uint16 Opcode= (mod->m_auraname == SPELL_AURA_ADD_FLAT_MODIFIER) ? SMSG_SET_FLAT_SPELL_MODIFIER : SMSG_SET_PCT_SPELL_MODIFIER;
|
||||
|
||||
for(int eff = 0; eff < 96; ++eff)
|
||||
{
|
||||
|
|
@ -18634,81 +18593,27 @@ void Player::AddSpellMod(SpellModifier* mod, bool apply)
|
|||
else
|
||||
_mask2= uint32(1) << (eff - 64);
|
||||
|
||||
if (mod->mask.IsFitToFamilyMask(_mask, _mask2))
|
||||
if (aura->GetSpellProto()->IsFitToFamilyMask(_mask, _mask2))
|
||||
{
|
||||
int32 val = 0;
|
||||
for (SpellModList::const_iterator itr = m_spellMods[mod->op].begin(); itr != m_spellMods[mod->op].end(); ++itr)
|
||||
for (AuraList::const_iterator itr = m_spellMods[mod->m_miscvalue].begin(); itr != m_spellMods[mod->m_miscvalue].end(); ++itr)
|
||||
{
|
||||
if ((*itr)->type == mod->type && ((*itr)->mask.IsFitToFamilyMask(_mask, _mask2)))
|
||||
val += (*itr)->value;
|
||||
if ((*itr)->GetModifier()->m_auraname == mod->m_auraname && ((*itr)->GetSpellProto()->IsFitToFamilyMask(_mask, _mask2)))
|
||||
val += (*itr)->GetModifier()->m_amount;
|
||||
}
|
||||
val += apply ? mod->value : -(mod->value);
|
||||
val += apply ? mod->m_amount : -(mod->m_amount);
|
||||
WorldPacket data(Opcode, (1+1+4));
|
||||
data << uint8(eff);
|
||||
data << uint8(mod->op);
|
||||
data << uint8(mod->m_miscvalue);
|
||||
data << int32(val);
|
||||
SendDirectMessage(&data);
|
||||
}
|
||||
}
|
||||
|
||||
if (apply)
|
||||
m_spellMods[mod->op].push_back(mod);
|
||||
m_spellMods[mod->m_miscvalue].push_back(aura);
|
||||
else
|
||||
{
|
||||
if (mod->charges == -1)
|
||||
--m_SpellModRemoveCount;
|
||||
m_spellMods[mod->op].remove(mod);
|
||||
delete mod;
|
||||
}
|
||||
}
|
||||
|
||||
void Player::RemoveSpellMods(Spell const* spell)
|
||||
{
|
||||
if (!spell || (m_SpellModRemoveCount == 0))
|
||||
return;
|
||||
|
||||
for(int i = 0; i < MAX_SPELLMOD; ++i)
|
||||
{
|
||||
for (SpellModList::const_iterator itr = m_spellMods[i].begin(); itr != m_spellMods[i].end();)
|
||||
{
|
||||
SpellModifier *mod = *itr;
|
||||
++itr;
|
||||
|
||||
if (mod && mod->charges == -1 && (mod->lastAffected == spell || mod->lastAffected==NULL))
|
||||
{
|
||||
RemoveAurasDueToSpell(mod->spellId);
|
||||
if (m_spellMods[i].empty())
|
||||
break;
|
||||
else
|
||||
itr = m_spellMods[i].begin();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Player::ResetSpellModsDueToCanceledSpell (Spell const* spell)
|
||||
{
|
||||
for(int i = 0; i < MAX_SPELLMOD; ++i )
|
||||
{
|
||||
for (SpellModList::const_iterator itr = m_spellMods[i].begin(); itr != m_spellMods[i].end(); ++itr)
|
||||
{
|
||||
SpellModifier *mod = *itr;
|
||||
|
||||
if (mod->lastAffected != spell)
|
||||
continue;
|
||||
|
||||
mod->lastAffected = NULL;
|
||||
|
||||
if (mod->charges == -1)
|
||||
{
|
||||
mod->charges = 1;
|
||||
if (m_SpellModRemoveCount > 0)
|
||||
--m_SpellModRemoveCount;
|
||||
}
|
||||
else if (mod->charges > 0)
|
||||
++mod->charges;
|
||||
}
|
||||
}
|
||||
m_spellMods[mod->m_miscvalue].remove(aura);
|
||||
}
|
||||
|
||||
// send Proficiency
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@
|
|||
#include "BattleGround.h"
|
||||
#include "DBCStores.h"
|
||||
#include "SharedDefines.h"
|
||||
#include "SpellAuras.h"
|
||||
|
||||
#include<string>
|
||||
#include<vector>
|
||||
|
|
@ -114,36 +115,6 @@ struct PlayerTalent
|
|||
typedef UNORDERED_MAP<uint32, PlayerSpell> PlayerSpellMap;
|
||||
typedef UNORDERED_MAP<uint32, PlayerTalent> PlayerTalentMap;
|
||||
|
||||
// Spell modifier (used for modify other spells)
|
||||
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), 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);
|
||||
|
||||
SpellModifier(SpellModOp _op, SpellModType _type, int32 _value, Aura const* aura, int16 _charges = 0);
|
||||
|
||||
bool isAffectedOnSpell(SpellEntry const *spell) const;
|
||||
|
||||
SpellModOp op : 8;
|
||||
SpellModType type : 8;
|
||||
int16 charges : 16;
|
||||
int32 value;
|
||||
ClassFamilyMask mask;
|
||||
uint32 spellId;
|
||||
Spell const* lastAffected; // mark last charge user, used for cleanup delayed remove spellmods at spell success or restore charges at cast fail (Is one pointer only need for cases mixed castes?)
|
||||
};
|
||||
|
||||
typedef std::list<SpellModifier*> SpellModList;
|
||||
|
||||
struct SpellCooldown
|
||||
{
|
||||
time_t end;
|
||||
|
|
@ -1643,11 +1614,8 @@ class MANGOS_DLL_SPEC Player : public Unit
|
|||
PlayerTalent const* GetKnownTalentById(int32 talentId) const;
|
||||
SpellEntry const* GetKnownTalentRankById(int32 talentId) const;
|
||||
|
||||
void AddSpellMod(SpellModifier* mod, bool apply);
|
||||
bool IsAffectedBySpellmod(SpellEntry const *spellInfo, SpellModifier *mod, Spell const* spell = NULL);
|
||||
void AddSpellMod(Aura* aura, bool apply);
|
||||
template <class T> T ApplySpellMod(uint32 spellId, SpellModOp op, T &basevalue, Spell const* spell = NULL);
|
||||
void RemoveSpellMods(Spell const* spell);
|
||||
void ResetSpellModsDueToCanceledSpell (Spell const* spell);
|
||||
|
||||
static uint32 const infinityCooldownDelay = MONTH; // used for set "infinity cooldowns" for spells and check
|
||||
static uint32 const infinityCooldownDelayCheck = MONTH/2;
|
||||
|
|
@ -2500,8 +2468,7 @@ class MANGOS_DLL_SPEC Player : public Unit
|
|||
float m_armorPenetrationPct;
|
||||
int32 m_spellPenetrationItemMod;
|
||||
|
||||
SpellModList m_spellMods[MAX_SPELLMOD];
|
||||
int32 m_SpellModRemoveCount;
|
||||
AuraList m_spellMods[MAX_SPELLMOD];
|
||||
EnchantDurationList m_enchantDuration;
|
||||
ItemDurationList m_itemDuration;
|
||||
|
||||
|
|
@ -2672,45 +2639,28 @@ template <class T> T Player::ApplySpellMod(uint32 spellId, SpellModOp op, T &bas
|
|||
if (!spellInfo) return 0;
|
||||
int32 totalpct = 0;
|
||||
int32 totalflat = 0;
|
||||
for (SpellModList::iterator itr = m_spellMods[op].begin(); itr != m_spellMods[op].end(); ++itr)
|
||||
for (AuraList::iterator itr = m_spellMods[op].begin(); itr != m_spellMods[op].end(); ++itr)
|
||||
{
|
||||
SpellModifier *mod = *itr;
|
||||
Aura *aura = *itr;
|
||||
|
||||
if(!IsAffectedBySpellmod(spellInfo,mod,spell))
|
||||
Modifier const* mod = aura->GetModifier();
|
||||
|
||||
if (!aura->isAffectedOnSpell(spellInfo))
|
||||
continue;
|
||||
if (mod->type == SPELLMOD_FLAT)
|
||||
totalflat += mod->value;
|
||||
else if (mod->type == SPELLMOD_PCT)
|
||||
|
||||
if (mod->m_auraname == SPELL_AURA_ADD_FLAT_MODIFIER)
|
||||
totalflat += mod->m_amount;
|
||||
else
|
||||
{
|
||||
// skip percent mods for null basevalue (most important for spell mods with charges )
|
||||
if(basevalue == T(0))
|
||||
if (basevalue == T(0))
|
||||
continue;
|
||||
|
||||
// special case (skip >10sec spell casts for instant cast setting)
|
||||
if( mod->op==SPELLMOD_CASTING_TIME && basevalue >= T(10*IN_MILLISECONDS) && mod->value <= -100)
|
||||
if (mod->m_miscvalue == SPELLMOD_CASTING_TIME && basevalue >= T(10*IN_MILLISECONDS) && mod->m_amount <= -100)
|
||||
continue;
|
||||
|
||||
totalpct += mod->value;
|
||||
}
|
||||
|
||||
if (mod->charges > 0)
|
||||
{
|
||||
if (!spell)
|
||||
spell = FindCurrentSpellBySpellId(spellId);
|
||||
|
||||
// avoid double use spellmod charge by same spell
|
||||
if (!mod->lastAffected || mod->lastAffected != spell)
|
||||
{
|
||||
--mod->charges;
|
||||
|
||||
if (mod->charges == 0)
|
||||
{
|
||||
mod->charges = -1;
|
||||
++m_SpellModRemoveCount;
|
||||
}
|
||||
|
||||
mod->lastAffected = spell;
|
||||
}
|
||||
totalpct += mod->m_amount;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3216,9 +3216,17 @@ void Spell::cast(bool skipCheck)
|
|||
m_immediateHandled = false;
|
||||
m_spellState = SPELL_STATE_DELAYED;
|
||||
SetDelayStart(0);
|
||||
|
||||
// on spell cast end proc,
|
||||
// critical hit related part is currently done on hit so proc there,
|
||||
// 0 damage since any damage based procs should be on hit
|
||||
// 0 victim proc since there is no victim proc dependent on successfull cast for caster
|
||||
m_caster->ProcDamageAndSpell(m_targets.getUnitTarget(), m_procAttacker, 0, PROC_EX_NORMAL_HIT, 0, m_attackType, m_spellInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_caster->ProcDamageAndSpell(m_targets.getUnitTarget(), m_procAttacker, 0, PROC_EX_NORMAL_HIT, 0, m_attackType, m_spellInfo);
|
||||
|
||||
// Immediate spell, no big deal
|
||||
handle_immediate();
|
||||
}
|
||||
|
|
@ -3500,18 +3508,8 @@ void Spell::finish(bool ok)
|
|||
if (m_spellState == SPELL_STATE_FINISHED)
|
||||
return;
|
||||
|
||||
// remove/restore spell mods before m_spellState update
|
||||
if (Player* modOwner = m_caster->GetSpellModOwner())
|
||||
{
|
||||
if (ok || m_spellState != SPELL_STATE_PREPARING) // fail after start channeling or throw to target not affect spell mods
|
||||
modOwner->RemoveSpellMods(this);
|
||||
else
|
||||
modOwner->ResetSpellModsDueToCanceledSpell(this);
|
||||
}
|
||||
|
||||
m_spellState = SPELL_STATE_FINISHED;
|
||||
|
||||
|
||||
// other code related only to successfully finished spells
|
||||
if (!ok)
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -372,7 +372,7 @@ pAuraHandler AuraHandler[TOTAL_AURAS]=
|
|||
static AuraType const frozenAuraTypes[] = { SPELL_AURA_MOD_ROOT, SPELL_AURA_MOD_STUN, SPELL_AURA_NONE };
|
||||
|
||||
Aura::Aura(SpellEntry const* spellproto, SpellEffectIndex eff, int32 *currentBasePoints, SpellAuraHolder *holder, Unit *target, Unit *caster, Item* castItem) :
|
||||
m_spellmod(NULL), m_periodicTimer(0), m_periodicTick(0), m_removeMode(AURA_REMOVE_BY_DEFAULT),
|
||||
m_periodicTimer(0), m_periodicTick(0), m_removeMode(AURA_REMOVE_BY_DEFAULT),
|
||||
m_effIndex(eff), m_positive(false), m_isPeriodic(false), m_isAreaAura(false),
|
||||
m_isPersistent(false), m_in_use(0), m_spellAuraHolder(holder)
|
||||
{
|
||||
|
|
@ -855,7 +855,7 @@ bool Aura::isAffectedOnSpell(SpellEntry const *spell) const
|
|||
return spell->IsFitToFamily(SpellFamily(GetSpellProto()->SpellFamilyName), GetAuraSpellClassMask());
|
||||
}
|
||||
|
||||
bool Aura::CanProcFrom(SpellEntry const *spell, uint32 EventProcEx, uint32 procEx, bool active, bool useClassMask) const
|
||||
bool Aura::CanProcFrom(SpellEntry const *spell, uint32 procFlag, uint32 EventProcEx, uint32 procEx, bool active, bool useClassMask) const
|
||||
{
|
||||
// Check EffectClassMask
|
||||
ClassFamilyMask const& mask = GetAuraSpellClassMask();
|
||||
|
|
@ -865,6 +865,16 @@ bool Aura::CanProcFrom(SpellEntry const *spell, uint32 EventProcEx, uint32 procE
|
|||
{
|
||||
if (!(EventProcEx & PROC_EX_EX_TRIGGER_ALWAYS))
|
||||
{
|
||||
// modifier aura procs by default are not active and only allowed with non zero charges
|
||||
// procEx == PROC_EX_NORMAL_HIT only for real "on cast" cases
|
||||
if (!active && procEx == PROC_EX_NORMAL_HIT && (procFlag & SPELL_CAST_TRIGGER_MASK))
|
||||
{
|
||||
if (GetHolder()->GetAuraCharges() > 0)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for extra req (if none) and hit/crit
|
||||
if (EventProcEx == PROC_EX_NONE)
|
||||
{
|
||||
|
|
@ -1015,30 +1025,24 @@ void Aura::HandleAddModifier(bool apply, bool Real)
|
|||
break;
|
||||
}
|
||||
|
||||
m_spellmod = new SpellModifier(
|
||||
SpellModOp(m_modifier.m_miscvalue),
|
||||
SpellModType(m_modifier.m_auraname), // SpellModType value == spell aura types
|
||||
m_modifier.m_amount,
|
||||
this,
|
||||
// prevent expire spell mods with (charges > 0 && m_stackAmount > 1)
|
||||
// all this spell expected expire not at use but at spell proc event check
|
||||
GetSpellProto()->StackAmount > 1 ? 0 : GetHolder()->GetAuraCharges());
|
||||
|
||||
// Everlasting Affliction, overwrite wrong data, if will need more better restore support of spell_affect table
|
||||
if (spellProto->SpellFamilyName == SPELLFAMILY_WARLOCK && spellProto->SpellIconID == 3169)
|
||||
{
|
||||
// Corruption and Unstable Affliction
|
||||
m_spellmod->mask = ClassFamilyMask(UI64LIT(0x0000010000000002));
|
||||
// TODO: drop when override will be possible
|
||||
SpellEntry *entry = (SpellEntry*)(&(*spellProto));
|
||||
entry->EffectSpellClassMask[GetEffIndex()].Flags = UI64LIT(0x0000010000000002);
|
||||
}
|
||||
// Improved Flametongue Weapon, overwrite wrong data, maybe time re-add table
|
||||
else if (spellProto->Id == 37212)
|
||||
{
|
||||
// Flametongue Weapon (Passive)
|
||||
m_spellmod->mask = ClassFamilyMask(UI64LIT(0x0000000000200000));
|
||||
// TODO: drop when override will be possible
|
||||
SpellEntry *entry = (SpellEntry*)(&(*spellProto));
|
||||
entry->EffectSpellClassMask[GetEffIndex()].Flags = UI64LIT(0x0000000000200000);
|
||||
}
|
||||
}
|
||||
|
||||
((Player*)GetTarget())->AddSpellMod(m_spellmod, apply);
|
||||
((Player*)GetTarget())->AddSpellMod(this, apply);
|
||||
|
||||
ReapplyAffectedPassiveAuras();
|
||||
}
|
||||
|
|
@ -2840,39 +2844,10 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
|
|||
}
|
||||
break;
|
||||
}
|
||||
case SPELLFAMILY_PRIEST:
|
||||
{
|
||||
// Pain and Suffering
|
||||
if (GetSpellProto()->SpellIconID == 2874 && target->GetTypeId()==TYPEID_PLAYER)
|
||||
{
|
||||
if (apply)
|
||||
{
|
||||
// Reduce backfire damage (dot damage) from Shadow Word: Death
|
||||
// aura have wrong effectclassmask, so use hardcoded value
|
||||
m_spellmod = new SpellModifier(SPELLMOD_DOT,SPELLMOD_PCT,m_modifier.m_amount,GetId(),UI64LIT(0x0000200000000000));
|
||||
}
|
||||
((Player*)target)->AddSpellMod(m_spellmod, apply);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SPELLFAMILY_DRUID:
|
||||
{
|
||||
switch(GetId())
|
||||
{
|
||||
case 34246: // Idol of the Emerald Queen
|
||||
case 60779: // Idol of Lush Moss
|
||||
{
|
||||
if (target->GetTypeId() != TYPEID_PLAYER)
|
||||
return;
|
||||
|
||||
if (apply)
|
||||
// dummy not have proper effectclassmask
|
||||
m_spellmod = new SpellModifier(SPELLMOD_DOT,SPELLMOD_FLAT,m_modifier.m_amount/7,GetId(),UI64LIT(0x001000000000));
|
||||
|
||||
((Player*)target)->AddSpellMod(m_spellmod, apply);
|
||||
return;
|
||||
}
|
||||
case 52610: // Savage Roar
|
||||
{
|
||||
if (apply)
|
||||
|
|
|
|||
|
|
@ -32,7 +32,6 @@ struct Modifier
|
|||
|
||||
class Unit;
|
||||
struct SpellEntry;
|
||||
struct SpellModifier;
|
||||
struct ProcTriggerSpell;
|
||||
|
||||
// forward decl
|
||||
|
|
@ -123,11 +122,13 @@ class MANGOS_DLL_SPEC SpellAuraHolder
|
|||
uint8 GetAuraLevel() const { return m_auraLevel; }
|
||||
void SetAuraLevel(uint8 level) { m_auraLevel = level; }
|
||||
uint32 GetAuraCharges() const { return m_procCharges; }
|
||||
void SetAuraCharges(uint32 charges)
|
||||
void SetAuraCharges(uint32 charges, bool update = true)
|
||||
{
|
||||
if (m_procCharges == charges)
|
||||
return;
|
||||
m_procCharges = charges;
|
||||
|
||||
if (update)
|
||||
SendAuraUpdate(false);
|
||||
}
|
||||
bool DropAuraCharge() // return true if last charge dropped
|
||||
|
|
@ -444,7 +445,7 @@ class MANGOS_DLL_SPEC Aura
|
|||
|
||||
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;
|
||||
bool CanProcFrom(SpellEntry const *spell, uint32 procFlag, uint32 EventProcEx, uint32 procEx, bool active, bool useClassMask) const;
|
||||
|
||||
//SpellAuraHolder const* GetHolder() const { return m_spellHolder; }
|
||||
SpellAuraHolder* GetHolder() { return m_spellAuraHolder; }
|
||||
|
|
@ -467,7 +468,6 @@ class MANGOS_DLL_SPEC Aura
|
|||
void ReapplyAffectedPassiveAuras();
|
||||
|
||||
Modifier m_modifier;
|
||||
SpellModifier *m_spellmod;
|
||||
|
||||
time_t m_applyTime;
|
||||
|
||||
|
|
|
|||
|
|
@ -397,12 +397,6 @@ void Spell::EffectSchoolDMG(SpellEffectIndex effect_idx)
|
|||
}
|
||||
break;
|
||||
}
|
||||
case SPELLFAMILY_MAGE:
|
||||
// remove Arcane Blast buffs at any non-Arcane Blast arcane damage spell.
|
||||
// NOTE: it removed at hit instead cast because currently spell done-damage calculated at hit instead cast
|
||||
if ((m_spellInfo->SchoolMask & SPELL_SCHOOL_MASK_ARCANE) && !(m_spellInfo->SpellFamilyFlags & UI64LIT(0x20000000)))
|
||||
m_caster->RemoveAurasDueToSpell(36032); // Arcane Blast buff
|
||||
break;
|
||||
case SPELLFAMILY_WARRIOR:
|
||||
{
|
||||
// Bloodthirst
|
||||
|
|
|
|||
|
|
@ -37,7 +37,6 @@ class Player;
|
|||
class Spell;
|
||||
class Unit;
|
||||
struct CreatureInfo;
|
||||
struct SpellModifier;
|
||||
|
||||
// only used in code
|
||||
enum SpellCategories
|
||||
|
|
@ -596,6 +595,13 @@ enum ProcFlags
|
|||
PROC_FLAG_SUCCESSFUL_NEGATIVE_SPELL_HIT | \
|
||||
PROC_FLAG_TAKEN_NEGATIVE_SPELL_HIT)
|
||||
|
||||
#define SPELL_CAST_TRIGGER_MASK (PROC_FLAG_SUCCESSFUL_MELEE_SPELL_HIT | \
|
||||
PROC_FLAG_SUCCESSFUL_RANGED_HIT | \
|
||||
PROC_FLAG_SUCCESSFUL_RANGED_SPELL_HIT | \
|
||||
PROC_FLAG_SUCCESSFUL_POSITIVE_AOE_HIT | \
|
||||
PROC_FLAG_SUCCESSFUL_AOE_SPELL_HIT | \
|
||||
PROC_FLAG_SUCCESSFUL_POSITIVE_SPELL | \
|
||||
PROC_FLAG_SUCCESSFUL_NEGATIVE_SPELL_HIT)
|
||||
enum ProcFlagsEx
|
||||
{
|
||||
PROC_EX_NONE = 0x0000000, // If none can tigger on Hit/Crit only (passive spells MUST defined by SpellFamily flag)
|
||||
|
|
|
|||
|
|
@ -4441,7 +4441,7 @@ void Unit::RemoveAurasDueToSpellBySteal(uint32 spellId, ObjectGuid casterGuid, U
|
|||
int32 basePoints = aur->GetBasePoints();
|
||||
// construct the new aura for the attacker - will never return NULL, it's just a wrapper for
|
||||
// some different constructors
|
||||
Aura * new_aur = CreateAura(aur->GetSpellProto(), aur->GetEffIndex(), &basePoints, new_holder, stealer, this);
|
||||
Aura * new_aur = CreateAura(spellProto, aur->GetEffIndex(), &basePoints, new_holder, stealer, this);
|
||||
|
||||
// set periodic to do at least one tick (for case when original aura has been at last tick preparing)
|
||||
int32 periodic = aur->GetModifier()->periodictime;
|
||||
|
|
@ -6530,6 +6530,13 @@ uint32 Unit::SpellDamageBonusTaken(Unit *pCaster, SpellEntry const *spellProto,
|
|||
case 25899: // Greater Blessing of Sanctuary
|
||||
TakenTotalMod *= ((*i)->GetModifier()->m_amount + 100.0f) / 100.0f;
|
||||
break;
|
||||
case 47580: // Pain and Suffering (Rank 1) TODO: can be pct modifier aura
|
||||
case 47581: // Pain and Suffering (Rank 2)
|
||||
case 47582: // Pain and Suffering (Rank 3)
|
||||
// Shadow Word: Death
|
||||
if (spellProto->IsFitToFamilyMask(UI64LIT(0x0000000200000000)))
|
||||
TakenTotalMod *= ((*i)->GetModifier()->m_amount + 100.0f) / 100.0f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -6956,8 +6963,10 @@ uint32 Unit::SpellHealingBonusDone(Unit *pVictim, SpellEntry const *spellProto,
|
|||
}
|
||||
}
|
||||
|
||||
if (spellProto->SpellFamilyName == SPELLFAMILY_DRUID)
|
||||
{
|
||||
// Nourish 20% of heal increase if target is affected by Druids HOTs
|
||||
if (spellProto->SpellFamilyName == SPELLFAMILY_DRUID && (spellProto->SpellFamilyFlags & UI64LIT(0x0200000000000000)))
|
||||
if (spellProto->SpellFamilyFlags & UI64LIT(0x0200000000000000))
|
||||
{
|
||||
int ownHotCount = 0; // counted HoT types amount, not stacks
|
||||
Unit::AuraList const& RejorRegr = pVictim->GetAurasByType(SPELL_AURA_PERIODIC_HEAL);
|
||||
|
|
@ -6974,6 +6983,22 @@ uint32 Unit::SpellHealingBonusDone(Unit *pVictim, SpellEntry const *spellProto,
|
|||
DoneTotalMod *= (glyph->GetModifier()->m_amount * ownHotCount + 100.0f) / 100.0f;
|
||||
}
|
||||
}
|
||||
// Lifebloom
|
||||
else if (spellProto->IsFitToFamilyMask(0x0000001000000000))
|
||||
{
|
||||
AuraList const& dummyList = owner->GetAurasByType(SPELL_AURA_DUMMY);
|
||||
for(AuraList::const_iterator i = dummyList.begin(); i != dummyList.end(); ++i)
|
||||
{
|
||||
switch((*i)->GetId())
|
||||
{
|
||||
case 34246: // Idol of the Emerald Queen TODO: can be flat modifier aura
|
||||
case 60779: // Idol of Lush Moss
|
||||
DoneTotal += (*i)->GetModifier()->m_amount / 7;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Done fixed damage bonus auras
|
||||
int32 DoneAdvertisedBenefit = SpellBaseHealingBonusDone(GetSpellSchoolMask(spellProto));
|
||||
|
|
@ -9724,12 +9749,17 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag
|
|||
{
|
||||
if (!procSpell->IsFitToFamilyMask(spellProcEvent->spellFamilyMask[i]))
|
||||
continue;
|
||||
}
|
||||
// don't check dbc FamilyFlags if schoolMask exists
|
||||
else if (!triggeredByAura->CanProcFrom(procSpell, spellProcEvent->procEx, procExtra, damage != 0, !spellProcEvent->schoolMask))
|
||||
|
||||
// modifier aura procs by default are not active and only allowed with non zero charges
|
||||
// procEx == PROC_EX_NORMAL_HIT only for real "on cast" cases
|
||||
if (!useCharges && damage == 0 && procExtra == PROC_EX_NORMAL_HIT && (procFlag & SPELL_CAST_TRIGGER_MASK))
|
||||
continue;
|
||||
}
|
||||
else if (!triggeredByAura->CanProcFrom(procSpell, PROC_EX_NONE, procExtra, damage != 0, true))
|
||||
// don't check dbc FamilyFlags if schoolMask exists
|
||||
else if (!triggeredByAura->CanProcFrom(procSpell, procFlag, spellProcEvent->procEx, procExtra, damage != 0, !spellProcEvent->schoolMask))
|
||||
continue;
|
||||
}
|
||||
else if (!triggeredByAura->CanProcFrom(procSpell, procFlag, PROC_EX_NONE, procExtra, damage != 0, true))
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3788,9 +3788,6 @@ SpellAuraProcResult Unit::HandleMendingAuraProc( Unit* /*pVictim*/, uint32 /*dam
|
|||
// jumps
|
||||
int32 jumps = triggeredByAura->GetHolder()->GetAuraCharges()-1;
|
||||
|
||||
// current aura expire
|
||||
triggeredByAura->GetHolder()->SetAuraCharges(1); // will removed at next charges decrease
|
||||
|
||||
// next target selection
|
||||
if (jumps > 0 && GetTypeId()==TYPEID_PLAYER && caster_guid.IsPlayer())
|
||||
{
|
||||
|
|
@ -3802,27 +3799,36 @@ SpellAuraProcResult Unit::HandleMendingAuraProc( Unit* /*pVictim*/, uint32 /*dam
|
|||
|
||||
if(Player* caster = ((Player*)triggeredByAura->GetCaster()))
|
||||
{
|
||||
caster->ApplySpellMod(spellProto->Id, SPELLMOD_RADIUS, radius,NULL);
|
||||
caster->ApplySpellMod(spellProto->Id, SPELLMOD_RADIUS, radius, NULL);
|
||||
|
||||
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);
|
||||
SpellAuraHolder *holder = GetSpellAuraHolder(spellProto->Id, caster->GetObjectGuid());
|
||||
SpellAuraHolder *new_holder = CreateSpellAuraHolder(spellProto, target, caster);
|
||||
|
||||
// remove before apply next (locked against deleted)
|
||||
for (int32 i = 0; i < MAX_EFFECT_INDEX; ++i)
|
||||
{
|
||||
Aura *aur = holder->GetAuraByEffectIndex(SpellEffectIndex(i));
|
||||
if (!aur)
|
||||
continue;
|
||||
|
||||
int32 basePoints = aur->GetBasePoints();
|
||||
Aura * new_aur = CreateAura(spellProto, aur->GetEffIndex(), &basePoints, new_holder, target, caster);
|
||||
new_holder->AddAura(new_aur, new_aur->GetEffIndex());
|
||||
}
|
||||
new_holder->SetAuraCharges(jumps, false);
|
||||
|
||||
// lock aura holder (currently SPELL_AURA_PRAYER_OF_MENDING is single target spell, so will attempt removing from old target
|
||||
// when applied to new one)
|
||||
triggeredByAura->SetInUse(true);
|
||||
RemoveAurasByCasterSpell(spellProto->Id,caster->GetObjectGuid());
|
||||
|
||||
caster->AddSpellMod(mod, true);
|
||||
CastCustomSpell(target, spellProto->Id, &heal, NULL, NULL, true, NULL, triggeredByAura, caster->GetObjectGuid());
|
||||
caster->AddSpellMod(mod, false);
|
||||
target->AddSpellAuraHolder(new_holder);
|
||||
triggeredByAura->SetInUse(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// heal
|
||||
CastCustomSpell(this,33110,&heal,NULL,NULL,true,NULL,NULL,caster_guid);
|
||||
CastCustomSpell(this,33110,&heal,NULL,NULL,true,NULL,NULL,caster_guid, spellProto);
|
||||
return SPELL_AURA_PROC_OK;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#ifndef __REVISION_NR_H__
|
||||
#define __REVISION_NR_H__
|
||||
#define REVISION_NR "11747"
|
||||
#define REVISION_NR "11748"
|
||||
#endif // __REVISION_NR_H__
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue