[11748] Replace SpellModifier struct by direct aura access (this should fix charge drops of 36032) also revert [11740]

This commit is contained in:
Laise 2011-07-20 15:41:01 +03:00
parent c9a9179d89
commit e178c79d51
10 changed files with 131 additions and 267 deletions

View file

@ -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

View file

@ -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;
}
}

View file

@ -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;

View file

@ -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)

View file

@ -32,7 +32,6 @@ struct Modifier
class Unit;
struct SpellEntry;
struct SpellModifier;
struct ProcTriggerSpell;
// forward decl
@ -123,12 +122,14 @@ 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;
SendAuraUpdate(false);
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;

View file

@ -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

View file

@ -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)

View file

@ -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,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 && (spellProto->SpellFamilyFlags & UI64LIT(0x0200000000000000)))
if (spellProto->SpellFamilyName == SPELLFAMILY_DRUID)
{
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 (ownHotCount)
// Nourish 20% of heal increase if target is affected by Druids HOTs
if (spellProto->SpellFamilyFlags & UI64LIT(0x0200000000000000))
{
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
DoneTotalMod *= (glyph->GetModifier()->m_amount * ownHotCount + 100.0f) / 100.0f;
if (ownHotCount)
{
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]))
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
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;
}
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;
}

View file

@ -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;
}

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__
#define __REVISION_NR_H__
#define REVISION_NR "11747"
#define REVISION_NR "11748"
#endif // __REVISION_NR_H__