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] << " ";
|
ss << taxi.m_taximask[i] << " ";
|
||||||
return ss;
|
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* TradeData::GetTraderData() const
|
TradeData* TradeData::GetTraderData() const
|
||||||
|
|
@ -439,8 +419,6 @@ Player::Player (WorldSession *session): Unit(), m_mover(this), m_camera(this), m
|
||||||
|
|
||||||
clearResurrectRequestData();
|
clearResurrectRequestData();
|
||||||
|
|
||||||
m_SpellModRemoveCount = 0;
|
|
||||||
|
|
||||||
memset(m_items, 0, sizeof(Item*)*PLAYER_SLOTS_COUNT);
|
memset(m_items, 0, sizeof(Item*)*PLAYER_SLOTS_COUNT);
|
||||||
|
|
||||||
m_social = NULL;
|
m_social = NULL;
|
||||||
|
|
@ -18600,29 +18578,10 @@ void Player::RemovePetActionBar()
|
||||||
SendDirectMessage(&data);
|
SendDirectMessage(&data);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Player::IsAffectedBySpellmod(SpellEntry const *spellInfo, SpellModifier *mod, Spell const* spell)
|
void Player::AddSpellMod(Aura* aura, bool apply)
|
||||||
{
|
{
|
||||||
if (!mod || !spellInfo)
|
Modifier const* mod = aura->GetModifier();
|
||||||
return false;
|
uint16 Opcode= (mod->m_auraname == SPELL_AURA_ADD_FLAT_MODIFIER) ? SMSG_SET_FLAT_SPELL_MODIFIER : SMSG_SET_PCT_SPELL_MODIFIER;
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
for(int eff = 0; eff < 96; ++eff)
|
for(int eff = 0; eff < 96; ++eff)
|
||||||
{
|
{
|
||||||
|
|
@ -18634,81 +18593,27 @@ void Player::AddSpellMod(SpellModifier* mod, bool apply)
|
||||||
else
|
else
|
||||||
_mask2= uint32(1) << (eff - 64);
|
_mask2= uint32(1) << (eff - 64);
|
||||||
|
|
||||||
if (mod->mask.IsFitToFamilyMask(_mask, _mask2))
|
if (aura->GetSpellProto()->IsFitToFamilyMask(_mask, _mask2))
|
||||||
{
|
{
|
||||||
int32 val = 0;
|
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)))
|
if ((*itr)->GetModifier()->m_auraname == mod->m_auraname && ((*itr)->GetSpellProto()->IsFitToFamilyMask(_mask, _mask2)))
|
||||||
val += (*itr)->value;
|
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));
|
WorldPacket data(Opcode, (1+1+4));
|
||||||
data << uint8(eff);
|
data << uint8(eff);
|
||||||
data << uint8(mod->op);
|
data << uint8(mod->m_miscvalue);
|
||||||
data << int32(val);
|
data << int32(val);
|
||||||
SendDirectMessage(&data);
|
SendDirectMessage(&data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (apply)
|
if (apply)
|
||||||
m_spellMods[mod->op].push_back(mod);
|
m_spellMods[mod->m_miscvalue].push_back(aura);
|
||||||
else
|
else
|
||||||
{
|
m_spellMods[mod->m_miscvalue].remove(aura);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// send Proficiency
|
// send Proficiency
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,7 @@
|
||||||
#include "BattleGround.h"
|
#include "BattleGround.h"
|
||||||
#include "DBCStores.h"
|
#include "DBCStores.h"
|
||||||
#include "SharedDefines.h"
|
#include "SharedDefines.h"
|
||||||
|
#include "SpellAuras.h"
|
||||||
|
|
||||||
#include<string>
|
#include<string>
|
||||||
#include<vector>
|
#include<vector>
|
||||||
|
|
@ -114,36 +115,6 @@ struct PlayerTalent
|
||||||
typedef UNORDERED_MAP<uint32, PlayerSpell> PlayerSpellMap;
|
typedef UNORDERED_MAP<uint32, PlayerSpell> PlayerSpellMap;
|
||||||
typedef UNORDERED_MAP<uint32, PlayerTalent> PlayerTalentMap;
|
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
|
struct SpellCooldown
|
||||||
{
|
{
|
||||||
time_t end;
|
time_t end;
|
||||||
|
|
@ -1643,11 +1614,8 @@ class MANGOS_DLL_SPEC Player : public Unit
|
||||||
PlayerTalent const* GetKnownTalentById(int32 talentId) const;
|
PlayerTalent const* GetKnownTalentById(int32 talentId) const;
|
||||||
SpellEntry const* GetKnownTalentRankById(int32 talentId) const;
|
SpellEntry const* GetKnownTalentRankById(int32 talentId) const;
|
||||||
|
|
||||||
void AddSpellMod(SpellModifier* mod, bool apply);
|
void AddSpellMod(Aura* aura, bool apply);
|
||||||
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);
|
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 infinityCooldownDelay = MONTH; // used for set "infinity cooldowns" for spells and check
|
||||||
static uint32 const infinityCooldownDelayCheck = MONTH/2;
|
static uint32 const infinityCooldownDelayCheck = MONTH/2;
|
||||||
|
|
@ -2500,8 +2468,7 @@ class MANGOS_DLL_SPEC Player : public Unit
|
||||||
float m_armorPenetrationPct;
|
float m_armorPenetrationPct;
|
||||||
int32 m_spellPenetrationItemMod;
|
int32 m_spellPenetrationItemMod;
|
||||||
|
|
||||||
SpellModList m_spellMods[MAX_SPELLMOD];
|
AuraList m_spellMods[MAX_SPELLMOD];
|
||||||
int32 m_SpellModRemoveCount;
|
|
||||||
EnchantDurationList m_enchantDuration;
|
EnchantDurationList m_enchantDuration;
|
||||||
ItemDurationList m_itemDuration;
|
ItemDurationList m_itemDuration;
|
||||||
|
|
||||||
|
|
@ -2672,45 +2639,28 @@ template <class T> T Player::ApplySpellMod(uint32 spellId, SpellModOp op, T &bas
|
||||||
if (!spellInfo) return 0;
|
if (!spellInfo) return 0;
|
||||||
int32 totalpct = 0;
|
int32 totalpct = 0;
|
||||||
int32 totalflat = 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;
|
||||||
|
|
||||||
|
Modifier const* mod = aura->GetModifier();
|
||||||
|
|
||||||
if(!IsAffectedBySpellmod(spellInfo,mod,spell))
|
if (!aura->isAffectedOnSpell(spellInfo))
|
||||||
continue;
|
continue;
|
||||||
if (mod->type == SPELLMOD_FLAT)
|
|
||||||
totalflat += mod->value;
|
if (mod->m_auraname == SPELL_AURA_ADD_FLAT_MODIFIER)
|
||||||
else if (mod->type == SPELLMOD_PCT)
|
totalflat += mod->m_amount;
|
||||||
|
else
|
||||||
{
|
{
|
||||||
// skip percent mods for null basevalue (most important for spell mods with charges )
|
// skip percent mods for null basevalue (most important for spell mods with charges )
|
||||||
if(basevalue == T(0))
|
if (basevalue == T(0))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// special case (skip >10sec spell casts for instant cast setting)
|
// 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;
|
continue;
|
||||||
|
|
||||||
totalpct += mod->value;
|
totalpct += mod->m_amount;
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3216,9 +3216,17 @@ void Spell::cast(bool skipCheck)
|
||||||
m_immediateHandled = false;
|
m_immediateHandled = false;
|
||||||
m_spellState = SPELL_STATE_DELAYED;
|
m_spellState = SPELL_STATE_DELAYED;
|
||||||
SetDelayStart(0);
|
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
|
else
|
||||||
{
|
{
|
||||||
|
m_caster->ProcDamageAndSpell(m_targets.getUnitTarget(), m_procAttacker, 0, PROC_EX_NORMAL_HIT, 0, m_attackType, m_spellInfo);
|
||||||
|
|
||||||
// Immediate spell, no big deal
|
// Immediate spell, no big deal
|
||||||
handle_immediate();
|
handle_immediate();
|
||||||
}
|
}
|
||||||
|
|
@ -3500,18 +3508,8 @@ void Spell::finish(bool ok)
|
||||||
if (m_spellState == SPELL_STATE_FINISHED)
|
if (m_spellState == SPELL_STATE_FINISHED)
|
||||||
return;
|
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;
|
m_spellState = SPELL_STATE_FINISHED;
|
||||||
|
|
||||||
|
|
||||||
// other code related only to successfully finished spells
|
// other code related only to successfully finished spells
|
||||||
if (!ok)
|
if (!ok)
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -372,7 +372,7 @@ pAuraHandler AuraHandler[TOTAL_AURAS]=
|
||||||
static AuraType const frozenAuraTypes[] = { SPELL_AURA_MOD_ROOT, SPELL_AURA_MOD_STUN, SPELL_AURA_NONE };
|
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) :
|
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_effIndex(eff), m_positive(false), m_isPeriodic(false), m_isAreaAura(false),
|
||||||
m_isPersistent(false), m_in_use(0), m_spellAuraHolder(holder)
|
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());
|
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
|
// Check EffectClassMask
|
||||||
ClassFamilyMask const& mask = GetAuraSpellClassMask();
|
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))
|
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
|
// Check for extra req (if none) and hit/crit
|
||||||
if (EventProcEx == PROC_EX_NONE)
|
if (EventProcEx == PROC_EX_NONE)
|
||||||
{
|
{
|
||||||
|
|
@ -1015,30 +1025,24 @@ void Aura::HandleAddModifier(bool apply, bool Real)
|
||||||
break;
|
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
|
// Everlasting Affliction, overwrite wrong data, if will need more better restore support of spell_affect table
|
||||||
if (spellProto->SpellFamilyName == SPELLFAMILY_WARLOCK && spellProto->SpellIconID == 3169)
|
if (spellProto->SpellFamilyName == SPELLFAMILY_WARLOCK && spellProto->SpellIconID == 3169)
|
||||||
{
|
{
|
||||||
// Corruption and Unstable Affliction
|
// 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
|
// Improved Flametongue Weapon, overwrite wrong data, maybe time re-add table
|
||||||
else if (spellProto->Id == 37212)
|
else if (spellProto->Id == 37212)
|
||||||
{
|
{
|
||||||
// Flametongue Weapon (Passive)
|
// 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(this, apply);
|
||||||
((Player*)GetTarget())->AddSpellMod(m_spellmod, apply);
|
|
||||||
|
|
||||||
ReapplyAffectedPassiveAuras();
|
ReapplyAffectedPassiveAuras();
|
||||||
}
|
}
|
||||||
|
|
@ -2840,39 +2844,10 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
|
||||||
}
|
}
|
||||||
break;
|
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:
|
case SPELLFAMILY_DRUID:
|
||||||
{
|
{
|
||||||
switch(GetId())
|
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
|
case 52610: // Savage Roar
|
||||||
{
|
{
|
||||||
if (apply)
|
if (apply)
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,6 @@ struct Modifier
|
||||||
|
|
||||||
class Unit;
|
class Unit;
|
||||||
struct SpellEntry;
|
struct SpellEntry;
|
||||||
struct SpellModifier;
|
|
||||||
struct ProcTriggerSpell;
|
struct ProcTriggerSpell;
|
||||||
|
|
||||||
// forward decl
|
// forward decl
|
||||||
|
|
@ -123,12 +122,14 @@ class MANGOS_DLL_SPEC SpellAuraHolder
|
||||||
uint8 GetAuraLevel() const { return m_auraLevel; }
|
uint8 GetAuraLevel() const { return m_auraLevel; }
|
||||||
void SetAuraLevel(uint8 level) { m_auraLevel = level; }
|
void SetAuraLevel(uint8 level) { m_auraLevel = level; }
|
||||||
uint32 GetAuraCharges() const { return m_procCharges; }
|
uint32 GetAuraCharges() const { return m_procCharges; }
|
||||||
void SetAuraCharges(uint32 charges)
|
void SetAuraCharges(uint32 charges, bool update = true)
|
||||||
{
|
{
|
||||||
if (m_procCharges == charges)
|
if (m_procCharges == charges)
|
||||||
return;
|
return;
|
||||||
m_procCharges = charges;
|
m_procCharges = charges;
|
||||||
SendAuraUpdate(false);
|
|
||||||
|
if (update)
|
||||||
|
SendAuraUpdate(false);
|
||||||
}
|
}
|
||||||
bool DropAuraCharge() // return true if last charge dropped
|
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); }
|
ClassFamilyMask const& GetAuraSpellClassMask() const { return m_spellAuraHolder->GetSpellProto()->GetEffectSpellClassMask(m_effIndex); }
|
||||||
bool isAffectedOnSpell(SpellEntry const *spell) const;
|
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 const* GetHolder() const { return m_spellHolder; }
|
||||||
SpellAuraHolder* GetHolder() { return m_spellAuraHolder; }
|
SpellAuraHolder* GetHolder() { return m_spellAuraHolder; }
|
||||||
|
|
@ -467,7 +468,6 @@ class MANGOS_DLL_SPEC Aura
|
||||||
void ReapplyAffectedPassiveAuras();
|
void ReapplyAffectedPassiveAuras();
|
||||||
|
|
||||||
Modifier m_modifier;
|
Modifier m_modifier;
|
||||||
SpellModifier *m_spellmod;
|
|
||||||
|
|
||||||
time_t m_applyTime;
|
time_t m_applyTime;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -397,12 +397,6 @@ void Spell::EffectSchoolDMG(SpellEffectIndex effect_idx)
|
||||||
}
|
}
|
||||||
break;
|
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:
|
case SPELLFAMILY_WARRIOR:
|
||||||
{
|
{
|
||||||
// Bloodthirst
|
// Bloodthirst
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,6 @@ class Player;
|
||||||
class Spell;
|
class Spell;
|
||||||
class Unit;
|
class Unit;
|
||||||
struct CreatureInfo;
|
struct CreatureInfo;
|
||||||
struct SpellModifier;
|
|
||||||
|
|
||||||
// only used in code
|
// only used in code
|
||||||
enum SpellCategories
|
enum SpellCategories
|
||||||
|
|
@ -596,6 +595,13 @@ enum ProcFlags
|
||||||
PROC_FLAG_SUCCESSFUL_NEGATIVE_SPELL_HIT | \
|
PROC_FLAG_SUCCESSFUL_NEGATIVE_SPELL_HIT | \
|
||||||
PROC_FLAG_TAKEN_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
|
enum ProcFlagsEx
|
||||||
{
|
{
|
||||||
PROC_EX_NONE = 0x0000000, // If none can tigger on Hit/Crit only (passive spells MUST defined by SpellFamily flag)
|
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();
|
int32 basePoints = aur->GetBasePoints();
|
||||||
// construct the new aura for the attacker - will never return NULL, it's just a wrapper for
|
// construct the new aura for the attacker - will never return NULL, it's just a wrapper for
|
||||||
// some different constructors
|
// 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)
|
// set periodic to do at least one tick (for case when original aura has been at last tick preparing)
|
||||||
int32 periodic = aur->GetModifier()->periodictime;
|
int32 periodic = aur->GetModifier()->periodictime;
|
||||||
|
|
@ -6530,6 +6530,13 @@ uint32 Unit::SpellDamageBonusTaken(Unit *pCaster, SpellEntry const *spellProto,
|
||||||
case 25899: // Greater Blessing of Sanctuary
|
case 25899: // Greater Blessing of Sanctuary
|
||||||
TakenTotalMod *= ((*i)->GetModifier()->m_amount + 100.0f) / 100.0f;
|
TakenTotalMod *= ((*i)->GetModifier()->m_amount + 100.0f) / 100.0f;
|
||||||
break;
|
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,22 +6963,40 @@ uint32 Unit::SpellHealingBonusDone(Unit *pVictim, SpellEntry const *spellProto,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Nourish 20% of heal increase if target is affected by Druids HOTs
|
if (spellProto->SpellFamilyName == SPELLFAMILY_DRUID)
|
||||||
if (spellProto->SpellFamilyName == SPELLFAMILY_DRUID && (spellProto->SpellFamilyFlags & UI64LIT(0x0200000000000000)))
|
|
||||||
{
|
{
|
||||||
int ownHotCount = 0; // counted HoT types amount, not stacks
|
// Nourish 20% of heal increase if target is affected by Druids HOTs
|
||||||
Unit::AuraList const& RejorRegr = pVictim->GetAurasByType(SPELL_AURA_PERIODIC_HEAL);
|
if (spellProto->SpellFamilyFlags & UI64LIT(0x0200000000000000))
|
||||||
for(Unit::AuraList::const_iterator i = RejorRegr.begin(); i != RejorRegr.end(); ++i)
|
|
||||||
if ((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID &&
|
|
||||||
(*i)->GetCasterGuid() == GetObjectGuid())
|
|
||||||
++ownHotCount;
|
|
||||||
|
|
||||||
if (ownHotCount)
|
|
||||||
{
|
{
|
||||||
DoneTotalMod *= 1.2f; // base bonus at HoTs
|
int ownHotCount = 0; // counted HoT types amount, not stacks
|
||||||
|
Unit::AuraList const& RejorRegr = pVictim->GetAurasByType(SPELL_AURA_PERIODIC_HEAL);
|
||||||
|
for(Unit::AuraList::const_iterator i = RejorRegr.begin(); i != RejorRegr.end(); ++i)
|
||||||
|
if ((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID &&
|
||||||
|
(*i)->GetCasterGuid() == GetObjectGuid())
|
||||||
|
++ownHotCount;
|
||||||
|
|
||||||
if (Aura* glyph = GetAura(62971, EFFECT_INDEX_0))// Glyph of Nourish
|
if (ownHotCount)
|
||||||
DoneTotalMod *= (glyph->GetModifier()->m_amount * ownHotCount + 100.0f) / 100.0f;
|
{
|
||||||
|
DoneTotalMod *= 1.2f; // base bonus at HoTs
|
||||||
|
|
||||||
|
if (Aura* glyph = GetAura(62971, EFFECT_INDEX_0))// Glyph of Nourish
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -9724,12 +9749,17 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag
|
||||||
{
|
{
|
||||||
if (!procSpell->IsFitToFamilyMask(spellProcEvent->spellFamilyMask[i]))
|
if (!procSpell->IsFitToFamilyMask(spellProcEvent->spellFamilyMask[i]))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
// 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;
|
||||||
}
|
}
|
||||||
// don't check dbc FamilyFlags if schoolMask exists
|
// don't check dbc FamilyFlags if schoolMask exists
|
||||||
else if (!triggeredByAura->CanProcFrom(procSpell, spellProcEvent->procEx, procExtra, damage != 0, !spellProcEvent->schoolMask))
|
else if (!triggeredByAura->CanProcFrom(procSpell, procFlag, spellProcEvent->procEx, procExtra, damage != 0, !spellProcEvent->schoolMask))
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (!triggeredByAura->CanProcFrom(procSpell, PROC_EX_NONE, procExtra, damage != 0, true))
|
else if (!triggeredByAura->CanProcFrom(procSpell, procFlag, PROC_EX_NONE, procExtra, damage != 0, true))
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3788,9 +3788,6 @@ SpellAuraProcResult Unit::HandleMendingAuraProc( Unit* /*pVictim*/, uint32 /*dam
|
||||||
// jumps
|
// jumps
|
||||||
int32 jumps = triggeredByAura->GetHolder()->GetAuraCharges()-1;
|
int32 jumps = triggeredByAura->GetHolder()->GetAuraCharges()-1;
|
||||||
|
|
||||||
// current aura expire
|
|
||||||
triggeredByAura->GetHolder()->SetAuraCharges(1); // will removed at next charges decrease
|
|
||||||
|
|
||||||
// next target selection
|
// next target selection
|
||||||
if (jumps > 0 && GetTypeId()==TYPEID_PLAYER && caster_guid.IsPlayer())
|
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()))
|
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))
|
if(Player* target = ((Player*)this)->GetNextRandomRaidMember(radius))
|
||||||
{
|
{
|
||||||
// aura will applied from caster, but spell casted from current aura holder
|
SpellAuraHolder *holder = GetSpellAuraHolder(spellProto->Id, caster->GetObjectGuid());
|
||||||
SpellModifier *mod = new SpellModifier(SPELLMOD_CHARGES,SPELLMOD_FLAT,jumps-5,spellProto->Id,spellProto->SpellFamilyFlags);
|
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);
|
triggeredByAura->SetInUse(true);
|
||||||
RemoveAurasByCasterSpell(spellProto->Id,caster->GetObjectGuid());
|
target->AddSpellAuraHolder(new_holder);
|
||||||
|
|
||||||
caster->AddSpellMod(mod, true);
|
|
||||||
CastCustomSpell(target, spellProto->Id, &heal, NULL, NULL, true, NULL, triggeredByAura, caster->GetObjectGuid());
|
|
||||||
caster->AddSpellMod(mod, false);
|
|
||||||
triggeredByAura->SetInUse(false);
|
triggeredByAura->SetInUse(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// heal
|
// 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;
|
return SPELL_AURA_PROC_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
#ifndef __REVISION_NR_H__
|
#ifndef __REVISION_NR_H__
|
||||||
#define __REVISION_NR_H__
|
#define __REVISION_NR_H__
|
||||||
#define REVISION_NR "11747"
|
#define REVISION_NR "11748"
|
||||||
#endif // __REVISION_NR_H__
|
#endif // __REVISION_NR_H__
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue