*Update spellmod system

*Implement SPELL_ATTR_EX6_IGNORE_CASTER_AURAS
*Fix some bugs with traps proc flags

--HG--
branch : trunk
This commit is contained in:
QAston
2009-06-06 08:27:36 +02:00
parent 00582cf9d4
commit 39548d6822
13 changed files with 209 additions and 103 deletions
+1 -1
View File
@@ -1326,7 +1326,7 @@ struct SpellEntry
uint32 AttributesEx3; // 7 m_attributesExC uint32 AttributesEx3; // 7 m_attributesExC
uint32 AttributesEx4; // 8 m_attributesExD uint32 AttributesEx4; // 8 m_attributesExD
uint32 AttributesEx5; // 9 m_attributesExE uint32 AttributesEx5; // 9 m_attributesExE
//uint32 AttributesEx6; // 10 m_attributesExF not used uint32 AttributesEx6; // 10 m_attributesExF
uint32 Stances; // 11 m_shapeshiftMask uint32 Stances; // 11 m_shapeshiftMask
uint32 StancesNot; // 12 m_shapeshiftExclude uint32 StancesNot; // 12 m_shapeshiftExclude
uint32 Targets; // 13 m_targets uint32 Targets; // 13 m_targets
+1 -1
View File
@@ -86,7 +86,7 @@ const char SkillLineAbilityfmt[]="niiiixxiiiiixx";
const char SoundEntriesfmt[]="nxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; const char SoundEntriesfmt[]="nxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
const char SpellCastTimefmt[]="nixx"; const char SpellCastTimefmt[]="nixx";
const char SpellDurationfmt[]="niii"; const char SpellDurationfmt[]="niii";
const char SpellEntryfmt[]="niiiiiiiiixiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiifxiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiffffffiiiiiiiiiiiiiiiiiiiiifffiiiiiiiiiiiiiiifffiiiiiiiiiiiiixssssssssssssssssxssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiiiiiiiiiiixfffxxxiiiiix"; const char SpellEntryfmt[]="niiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiifxiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiffffffiiiiiiiiiiiiiiiiiiiiifffiiiiiiiiiiiiiiifffiiiiiiiiiiiiixssssssssssssssssxssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiiiiiiiiiiixfffxxxiiiiix";
const char SpellFocusObjectfmt[]="nxxxxxxxxxxxxxxxxx"; const char SpellFocusObjectfmt[]="nxxxxxxxxxxxxxxxxx";
const char SpellItemEnchantmentfmt[]="nxiiiiiixxxiiissssssssssssssssxiiiixx"; const char SpellItemEnchantmentfmt[]="nxiiiiiixxxiiissssssssssssssssxiiiixx";
const char SpellItemEnchantmentConditionfmt[]="nbbbbbxxxxxbbbbbbbbbbiiiiiXXXXX"; const char SpellItemEnchantmentConditionfmt[]="nbbbbbxxxxxbbbbbbbbbbiiiiiXXXXX";
+65 -30
View File
@@ -275,7 +275,7 @@ std::ostringstream& operator<< (std::ostringstream& ss, PlayerTaxi const& taxi)
UpdateMask Player::updateVisualBits; UpdateMask Player::updateVisualBits;
Player::Player (WorldSession *session): Unit(), m_achievementMgr(this), m_reputationMgr(this) Player::Player (WorldSession *session): Unit(), m_achievementMgr(this), m_reputationMgr(this) , m_spellModTakingSpell(NULL)
{ {
m_speakTime = 0; m_speakTime = 0;
m_speakCount = 0; m_speakCount = 0;
@@ -320,8 +320,6 @@ Player::Player (WorldSession *session): Unit(), m_achievementMgr(this), m_reputa
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;
@@ -1134,6 +1132,10 @@ void Player::Update( uint32 p_time )
m_nextMailDelivereTime = 0; m_nextMailDelivereTime = 0;
} }
// If this is set during update SetSpellModTakingSpell call is missing somewhere in the code
// Having this would prevent more aura charges to be dropped, so let's crash
assert (!m_spellModTakingSpell);
Unit::Update( p_time ); Unit::Update( p_time );
time_t now = time (NULL); time_t now = time (NULL);
@@ -16983,22 +16985,14 @@ void Player::SendRemoveControlBar()
GetSession()->SendPacket(&data); GetSession()->SendPacket(&data);
} }
bool Player::IsAffectedBySpellmod(SpellEntry const *spellInfo, SpellModifier *mod, Spell const* spell) bool Player::IsAffectedBySpellmod(SpellEntry const *spellInfo, SpellModifier *mod, Spell * spell)
{ {
if (!mod || !spellInfo) if (!mod || !spellInfo)
return false; return false;
if(mod->charges == -1 && mod->lastAffected ) // marked as expired but locked until spell casting finish // Mod out of charges
{ if (spell && mod->charges == -1 && spell->m_appliedMods.find(mod->ownerAura) == spell->m_appliedMods.end())
// prevent apply to any spell except spell that trigger expire
if(spell)
{
if(mod->lastAffected != spell)
return false; return false;
}
else if(mod->lastAffected != FindCurrentSpellBySpellId(spellInfo->Id))
return false;
}
return spellmgr.IsAffectedByMod(spellInfo, mod); return spellmgr.IsAffectedByMod(spellInfo, mod);
} }
@@ -17036,8 +17030,6 @@ void Player::AddSpellMod(SpellModifier* mod, bool apply)
m_spellMods[mod->op].push_back(mod); m_spellMods[mod->op].push_back(mod);
else else
{ {
if (mod->charges == -1)
--m_SpellModRemoveCount;
m_spellMods[mod->op].remove(mod); m_spellMods[mod->op].remove(mod);
delete mod; delete mod;
} }
@@ -17046,7 +17038,7 @@ void Player::AddSpellMod(SpellModifier* mod, bool apply)
// Restore spellmods in case of failed cast // Restore spellmods in case of failed cast
void Player::RestoreSpellMods(Spell const* spell) void Player::RestoreSpellMods(Spell const* spell)
{ {
if(!spell || (m_SpellModRemoveCount == 0)) if (!spell || spell->m_appliedMods.empty())
return; return;
for(int i=0;i<MAX_SPELLMOD;++i) for(int i=0;i<MAX_SPELLMOD;++i)
@@ -17055,21 +17047,34 @@ void Player::RestoreSpellMods(Spell const* spell)
{ {
SpellModifier *mod = *itr; SpellModifier *mod = *itr;
if (mod && mod->charges == -1 && mod->lastAffected == spell) // spellmods without aura set cannot be charged
{ if (!mod->ownerAura || !mod->ownerAura->GetAuraCharges())
mod->lastAffected = NULL; continue;
// check if mod affected this spell
Spell::UsedSpellMods::iterator iterMod = spell->m_appliedMods.find(mod->ownerAura);
if (iterMod == spell->m_appliedMods.end())
continue;
// remove from list
spell->m_appliedMods.erase(iterMod);
// add mod charges back to mod
if (mod->charges == -1)
mod->charges = 1; mod->charges = 1;
m_SpellModRemoveCount--; else
} mod->charges++;
assert (mod->ownerAura->GetAuraCharges() <=charges);
} }
} }
} }
void Player::RemoveSpellMods(Spell const* spell) void Player::RemoveSpellMods(Spell * spell)
{ {
if(!spell || (m_SpellModRemoveCount == 0)) if (!spell || spell->m_appliedMods.empty())
return; return;
std::set <uint32> checkedSpells;
for(int i=0;i<MAX_SPELLMOD;++i) for(int i=0;i<MAX_SPELLMOD;++i)
{ {
for (SpellModList::iterator itr = m_spellMods[i].begin(); itr != m_spellMods[i].end();) for (SpellModList::iterator itr = m_spellMods[i].begin(); itr != m_spellMods[i].end();)
@@ -17077,16 +17082,46 @@ void Player::RemoveSpellMods(Spell const* spell)
SpellModifier *mod = *itr; SpellModifier *mod = *itr;
++itr; ++itr;
if (mod && mod->charges == -1 && (mod->lastAffected == spell || mod->lastAffected==NULL)) // spellmods without aura set cannot be charged
{ if (!mod->ownerAura || !mod->ownerAura->GetAuraCharges())
RemoveAurasDueToSpell(mod->spellId, 0, AURA_REMOVE_BY_EXPIRE); continue;
if (m_spellMods[i].empty())
break; // check if mod affected this spell
else Spell::UsedSpellMods::iterator iterMod = spell->m_appliedMods.find(mod->ownerAura);
if (iterMod == spell->m_appliedMods.end())
continue;
// remove from list
spell->m_appliedMods.erase(iterMod);
if (mod->ownerAura->DropAuraCharge())
itr = m_spellMods[i].begin(); itr = m_spellMods[i].begin();
} }
} }
} }
void Player::DropModCharge(SpellModifier * mod, Spell * spell)
{
if (spell && mod->ownerAura && mod->charges > 0 )
{
--mod->charges;
if (mod->charges == 0)
{
mod->charges = -1;
}
spell->m_appliedMods.insert(mod->ownerAura);
}
}
void Player::SetSpellModTakingSpell(Spell * spell, bool apply)
{
if (!spell || (m_spellModTakingSpell && m_spellModTakingSpell != spell))
return;
if (apply)
m_spellModTakingSpell = spell;
else
m_spellModTakingSpell = NULL;
} }
// send Proficiency // send Proficiency
+20 -19
View File
@@ -97,7 +97,7 @@ struct PlayerSpell
// Spell modifier (used for modify other spells) // Spell modifier (used for modify other spells)
struct SpellModifier struct SpellModifier
{ {
SpellModifier() : charges(0), lastAffected(NULL) {} SpellModifier(Aura * _ownerAura = NULL) : charges(0), ownerAura(_ownerAura) {}
SpellModOp op : 8; SpellModOp op : 8;
SpellModType type : 8; SpellModType type : 8;
int16 charges : 16; int16 charges : 16;
@@ -1389,10 +1389,12 @@ class TRINITY_DLL_SPEC Player : public Unit
PlayerSpellMap & GetSpellMap() { return m_spells; } PlayerSpellMap & GetSpellMap() { return m_spells; }
void AddSpellMod(SpellModifier* mod, bool apply); void AddSpellMod(SpellModifier* mod, bool apply);
bool IsAffectedBySpellmod(SpellEntry const *spellInfo, SpellModifier *mod, Spell const* spell = NULL); bool IsAffectedBySpellmod(SpellEntry const *spellInfo, SpellModifier *mod, Spell * 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 * spell = NULL);
void RemoveSpellMods(Spell const* spell); void RemoveSpellMods(Spell * spell);
void RestoreSpellMods(Spell const* spell); void RestoreSpellMods(Spell * spell);
void DropModCharge(SpellModifier * mod, Spell * spell);
void SetSpellModTakingSpell(Spell* spell, bool apply);
bool HasSpellCooldown(uint32 spell_id) const bool HasSpellCooldown(uint32 spell_id) const
{ {
@@ -2200,7 +2202,8 @@ class TRINITY_DLL_SPEC Player : public Unit
uint16 m_baseManaRegen; uint16 m_baseManaRegen;
SpellModList m_spellMods[MAX_SPELLMOD]; SpellModList m_spellMods[MAX_SPELLMOD];
int32 m_SpellModRemoveCount; Spell * m_spellModTakingSpell; // Spell for which charges are dropped in spell::finish
EnchantDurationList m_enchantDuration; EnchantDurationList m_enchantDuration;
ItemDurationList m_itemDuration; ItemDurationList m_itemDuration;
@@ -2328,16 +2331,25 @@ void AddItemsSetItem(Player*player,Item *item);
void RemoveItemsSetItem(Player*player,ItemPrototype const *proto); void RemoveItemsSetItem(Player*player,ItemPrototype const *proto);
// "the bodies of template functions must be made available in a header file" // "the bodies of template functions must be made available in a header file"
template <class T> T Player::ApplySpellMod(uint32 spellId, SpellModOp op, T &basevalue, Spell const* spell) template <class T> T Player::ApplySpellMod(uint32 spellId, SpellModOp op, T &basevalue, Spell * spell)
{ {
SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId); SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId);
if (!spellInfo) return 0; if (!spellInfo) return 0;
int32 totalpct = 0; int32 totalpct = 0;
int32 totalflat = 0; int32 totalflat = 0;
// Drop charges for triggering spells instead of triggered ones
if (m_spellModTakingSpell)
spell = m_spellModTakingSpell;
for (SpellModList::iterator itr = m_spellMods[op].begin(); itr != m_spellMods[op].end(); ++itr) for (SpellModList::iterator itr = m_spellMods[op].begin(); itr != m_spellMods[op].end(); ++itr)
{ {
SpellModifier *mod = *itr; SpellModifier *mod = *itr;
// Charges can be set only for mods with auras
if (!mod->ownerAura)
assert(mod->charges==0);
if(!IsAffectedBySpellmod(spellInfo,mod,spell)) if(!IsAffectedBySpellmod(spellInfo,mod,spell))
continue; continue;
if (mod->type == SPELLMOD_FLAT) if (mod->type == SPELLMOD_FLAT)
@@ -2355,18 +2367,7 @@ template <class T> T Player::ApplySpellMod(uint32 spellId, SpellModOp op, T &bas
totalpct += mod->value; totalpct += mod->value;
} }
if (mod->charges > 0 ) DropModCharge(mod, spell);
{
--mod->charges;
if (mod->charges == 0)
{
mod->charges = -1;
mod->lastAffected = spell;
if(!mod->lastAffected)
mod->lastAffected = FindCurrentSpellBySpellId(spellId);
++m_SpellModRemoveCount;
}
}
} }
float diff = (float)basevalue*(float)totalpct/100.0f + (float)totalflat; float diff = (float)basevalue*(float)totalpct/100.0f + (float)totalflat;
+3 -3
View File
@@ -306,7 +306,7 @@ enum SpellCategory
#define SPELL_ATTR_EX2_NOT_NEED_SHAPESHIFT 0x00080000 // 19 does not necessarly need shapeshift #define SPELL_ATTR_EX2_NOT_NEED_SHAPESHIFT 0x00080000 // 19 does not necessarly need shapeshift
#define SPELL_ATTR_EX2_UNK20 0x00100000 // 20 #define SPELL_ATTR_EX2_UNK20 0x00100000 // 20
#define SPELL_ATTR_EX2_DAMAGE_REDUCED_SHIELD 0x00200000 // 21 for ice blocks, pala immunity buffs, priest absorb shields, but used also for other spells -> not sure! #define SPELL_ATTR_EX2_DAMAGE_REDUCED_SHIELD 0x00200000 // 21 for ice blocks, pala immunity buffs, priest absorb shields, but used also for other spells -> not sure!
#define SPELL_ATTR_EX2_UNK22 0x00400000 // 22 spell can trigger even if triggered #define SPELL_ATTR_EX2_UNK22 0x00400000 // 22
#define SPELL_ATTR_EX2_UNK23 0x00800000 // 23 Only mage Arcane Concentration have this flag #define SPELL_ATTR_EX2_UNK23 0x00800000 // 23 Only mage Arcane Concentration have this flag
#define SPELL_ATTR_EX2_UNK24 0x01000000 // 24 #define SPELL_ATTR_EX2_UNK24 0x01000000 // 24
#define SPELL_ATTR_EX2_UNK25 0x02000000 // 25 #define SPELL_ATTR_EX2_UNK25 0x02000000 // 25
@@ -324,7 +324,7 @@ enum SpellCategory
#define SPELL_ATTR_EX3_UNK4 0x00000010 // 4 Druid Rebirth only this spell have this flag #define SPELL_ATTR_EX3_UNK4 0x00000010 // 4 Druid Rebirth only this spell have this flag
#define SPELL_ATTR_EX3_UNK5 0x00000020 // 5 #define SPELL_ATTR_EX3_UNK5 0x00000020 // 5
#define SPELL_ATTR_EX3_UNK6 0x00000040 // 6 #define SPELL_ATTR_EX3_UNK6 0x00000040 // 6
#define SPELL_ATTR_EX3_UNK7 0x00000080 // 7 #define SPELL_ATTR_EX3_UNK7 0x00000080 // 7 separate stack for every caster
#define SPELL_ATTR_EX3_PLAYERS_ONLY 0x00000100 // 8 Player only? #define SPELL_ATTR_EX3_PLAYERS_ONLY 0x00000100 // 8 Player only?
#define SPELL_ATTR_EX3_TRIGGERED_CAN_TRIGGER_2 0x00000200 // 9 triggered from effect? #define SPELL_ATTR_EX3_TRIGGERED_CAN_TRIGGER_2 0x00000200 // 9 triggered from effect?
#define SPELL_ATTR_EX3_MAIN_HAND 0x00000400 // 10 Main hand weapon required #define SPELL_ATTR_EX3_MAIN_HAND 0x00000400 // 10 Main hand weapon required
@@ -418,7 +418,7 @@ enum SpellCategory
#define SPELL_ATTR_EX6_UNK0 0x00000001 // 0 Only Move spell have this flag #define SPELL_ATTR_EX6_UNK0 0x00000001 // 0 Only Move spell have this flag
#define SPELL_ATTR_EX6_UNK1 0x00000002 // 1 not set in 3.0.3 #define SPELL_ATTR_EX6_UNK1 0x00000002 // 1 not set in 3.0.3
#define SPELL_ATTR_EX6_UNK2 0x00000004 // 2 #define SPELL_ATTR_EX6_IGNORE_CASTER_AURAS 0x00000004 // 2
#define SPELL_ATTR_EX6_UNK3 0x00000008 // 3 #define SPELL_ATTR_EX6_UNK3 0x00000008 // 3
#define SPELL_ATTR_EX6_UNK4 0x00000010 // 4 #define SPELL_ATTR_EX6_UNK4 0x00000010 // 4
#define SPELL_ATTR_EX6_UNK5 0x00000020 // 5 #define SPELL_ATTR_EX6_UNK5 0x00000020 // 5
+76 -35
View File
@@ -733,32 +733,6 @@ void Spell::prepareDataForTriggerSystem(AuraEffect * triggeredByAura)
// Create base triggers flags for Attacker and Victim ( m_procAttacker, m_procVictim and m_procEx) // Create base triggers flags for Attacker and Victim ( m_procAttacker, m_procVictim and m_procEx)
//========================================================================================== //==========================================================================================
/*
Effects which are result of aura proc from triggered spell cannot proc
to prevent chain proc of these spells
*/
if (triggeredByAura && !triggeredByAura->GetParentAura()->GetTarget()->CanProc())
{
m_canTrigger=false;
}
m_procEx = (m_IsTriggeredSpell)
&& !(m_spellInfo->AttributesEx2 & SPELL_ATTR_EX2_TRIGGERED_CAN_TRIGGER)
&& !(m_spellInfo->AttributesEx3 & SPELL_ATTR_EX3_TRIGGERED_CAN_TRIGGER_2)
? PROC_EX_INTERNAL_TRIGGERED : PROC_EX_NONE;
if (m_IsTriggeredSpell &&
(m_spellInfo->AttributesEx2 & SPELL_ATTR_EX2_TRIGGERED_CAN_TRIGGER ||
m_spellInfo->AttributesEx3 & SPELL_ATTR_EX3_TRIGGERED_CAN_TRIGGER_2))
m_procEx |= PROC_EX_INTERNAL_CANT_PROC;
// Totem casts require spellfamilymask defined in spell_proc_event to proc
if (m_originalCaster && m_caster != m_originalCaster && m_caster->GetTypeId()==TYPEID_UNIT && ((Creature*)m_caster)->isTotem() && m_caster->IsControlledByPlayer())
{
m_procEx |= PROC_EX_INTERNAL_REQ_FAMILY;
}
// Get data for type of attack and fill base info for trigger // Get data for type of attack and fill base info for trigger
switch (m_spellInfo->DmgClass) switch (m_spellInfo->DmgClass)
{ {
@@ -797,10 +771,36 @@ void Spell::prepareDataForTriggerSystem(AuraEffect * triggeredByAura)
} }
break; break;
} }
m_procEx= PROC_EX_NONE;
// Hunter traps spells (for Entrapment trigger) // Hunter traps spells (for Entrapment trigger)
// Gives your Immolation Trap, Frost Trap, Explosive Trap, and Snake Trap .... // Gives your Immolation Trap, Frost Trap, Explosive Trap, and Snake Trap ....
if (m_spellInfo->SpellFamilyName == SPELLFAMILY_HUNTER && (m_spellInfo->SpellFamilyFlags[1] & 0x00002000 || m_spellInfo->SpellFamilyFlags[0] & 0x1C)) if (m_spellInfo->SpellFamilyName == SPELLFAMILY_HUNTER && (m_spellInfo->SpellFamilyFlags[1] & 0x00002000 || m_spellInfo->SpellFamilyFlags[0] & 0x1C))
m_procAttacker |= PROC_FLAG_ON_TRAP_ACTIVATION; {
m_procAttacker = PROC_FLAG_ON_TRAP_ACTIVATION;
}
else
{
/*
Effects which are result of aura proc from triggered spell cannot proc
to prevent chain proc of these spells
*/
if (triggeredByAura && !triggeredByAura->GetParentAura()->GetTarget()->CanProc())
{
m_canTrigger=false;
}
if (m_IsTriggeredSpell &&
(m_spellInfo->AttributesEx2 & SPELL_ATTR_EX2_TRIGGERED_CAN_TRIGGER ||
m_spellInfo->AttributesEx3 & SPELL_ATTR_EX3_TRIGGERED_CAN_TRIGGER_2))
m_procEx |= PROC_EX_INTERNAL_CANT_PROC | PROC_EX_INTERNAL_TRIGGERED;
// Totem casts require spellfamilymask defined in spell_proc_event to proc
if (m_originalCaster && m_caster != m_originalCaster && m_caster->GetTypeId()==TYPEID_UNIT && ((Creature*)m_caster)->isTotem() && m_caster->IsControlledByPlayer())
{
m_procEx |= PROC_EX_INTERNAL_REQ_FAMILY;
}
}
} }
void Spell::CleanupTargetList() void Spell::CleanupTargetList()
@@ -2514,6 +2514,12 @@ void Spell::cancel()
SendChannelUpdate(0); SendChannelUpdate(0);
SendInterrupted(0); SendInterrupted(0);
SendCastResult(SPELL_FAILED_INTERRUPTED); SendCastResult(SPELL_FAILED_INTERRUPTED);
// spell is canceled-take mods and clear list
if (m_caster->GetTypeId() == TYPEID_PLAYER)
((Player*)m_caster)->RemoveSpellMods(this);
m_appliedMods.clear();
} break; } break;
default: default:
@@ -2548,6 +2554,12 @@ void Spell::cast(bool skipCheck)
if(m_caster->GetTypeId() != TYPEID_PLAYER && m_targets.getUnitTarget() && m_targets.getUnitTarget() != m_caster) if(m_caster->GetTypeId() != TYPEID_PLAYER && m_targets.getUnitTarget() && m_targets.getUnitTarget() != m_caster)
m_caster->SetInFront(m_targets.getUnitTarget()); m_caster->SetInFront(m_targets.getUnitTarget());
// Should this be done for original caster?
if (m_caster->GetTypeId()==TYPEID_PLAYER)
{
// Set spell which will drop charges for triggered cast spells
((Player*)m_caster)->SetSpellModTakingSpell(this, true);
}
// triggered cast called from Spell::prepare where it was already checked // triggered cast called from Spell::prepare where it was already checked
if(!m_IsTriggeredSpell || !skipCheck) if(!m_IsTriggeredSpell || !skipCheck)
@@ -2673,6 +2685,9 @@ void Spell::cast(bool skipCheck)
m_caster->CastSpell(m_targets.getUnitTarget() ? m_targets.getUnitTarget() : m_caster, *i, true); m_caster->CastSpell(m_targets.getUnitTarget() ? m_targets.getUnitTarget() : m_caster, *i, true);
} }
if (m_caster->GetTypeId()==TYPEID_PLAYER)
((Player*)m_caster)->SetSpellModTakingSpell(this, false);
SetExecutedCurrently(false); SetExecutedCurrently(false);
} }
@@ -2717,6 +2732,10 @@ void Spell::handle_immediate()
uint64 Spell::handle_delayed(uint64 t_offset) uint64 Spell::handle_delayed(uint64 t_offset)
{ {
UpdatePointers(); UpdatePointers();
if (m_caster->GetTypeId()==TYPEID_PLAYER)
((Player*)m_caster)->SetSpellModTakingSpell(this, true);
uint64 next_time = 0; uint64 next_time = 0;
if (!m_immediateHandled) if (!m_immediateHandled)
@@ -2750,6 +2769,7 @@ uint64 Spell::handle_delayed(uint64 t_offset)
next_time = ighit->timeDelay; next_time = ighit->timeDelay;
} }
} }
// All targets passed - need finish phase // All targets passed - need finish phase
if (next_time == 0) if (next_time == 0)
{ {
@@ -2763,6 +2783,9 @@ uint64 Spell::handle_delayed(uint64 t_offset)
} }
else else
{ {
if (m_caster->GetTypeId()==TYPEID_PLAYER)
((Player*)m_caster)->SetSpellModTakingSpell(this, false);
// spell is unfinished, return next execution time // spell is unfinished, return next execution time
return next_time; return next_time;
} }
@@ -2996,7 +3019,12 @@ void Spell::finish(bool ok)
{ {
//restore spell mods //restore spell mods
if (m_caster->GetTypeId() == TYPEID_PLAYER) if (m_caster->GetTypeId() == TYPEID_PLAYER)
{
((Player*)m_caster)->RestoreSpellMods(this); ((Player*)m_caster)->RestoreSpellMods(this);
// cleanup after mod system
// triggered spell pointer can be not removed in some cases
((Player*)m_caster)->SetSpellModTakingSpell(this, false);
}
return; return;
} }
@@ -3013,10 +3041,6 @@ void Spell::finish(bool ok)
} }
} }
//remove spell mods
if (m_caster->GetTypeId() == TYPEID_PLAYER)
((Player*)m_caster)->RemoveSpellMods(this);
// Okay to remove extra attacks // Okay to remove extra attacks
if(IsSpellHaveEffect(m_spellInfo, SPELL_EFFECT_ADD_EXTRA_ATTACKS)) if(IsSpellHaveEffect(m_spellInfo, SPELL_EFFECT_ADD_EXTRA_ATTACKS))
m_caster->m_extraAttacks = 0; m_caster->m_extraAttacks = 0;
@@ -3036,13 +3060,27 @@ void Spell::finish(bool ok)
// potions disabled by client, send event "not in combat" if need // potions disabled by client, send event "not in combat" if need
if (!m_triggeredByAuraSpell && m_caster->GetTypeId() == TYPEID_PLAYER) if (!m_triggeredByAuraSpell && m_caster->GetTypeId() == TYPEID_PLAYER)
{
((Player*)m_caster)->UpdatePotionCooldown(this); ((Player*)m_caster)->UpdatePotionCooldown(this);
// triggered spell pointer can be not set in some cases
// this is needed for proper apply of triggered spell mods
((Player*)m_caster)->SetSpellModTakingSpell(this, true);
}
// call triggered spell only at successful cast (after clear combo points -> for add some if need) // call triggered spell only at successful cast (after clear combo points -> for add some if need)
// I assume what he means is that some triggered spells may add combo points // I assume what he means is that some triggered spells may add combo points
if(!m_TriggerSpells.empty()) if(!m_TriggerSpells.empty())
TriggerSpell(); TriggerSpell();
// Take mods after trigger spell (needed for 14177 to affect 48664)
// mods are taken only on succesfull cast and independantly from targets of the spell
if (m_caster->GetTypeId() == TYPEID_PLAYER)
{
((Player*)m_caster)->RemoveSpellMods(this);
((Player*)m_caster)->SetSpellModTakingSpell(this, false);
}
// Stop Attack for some spells // Stop Attack for some spells
if( m_spellInfo->Attributes & SPELL_ATTR_STOP_ATTACK_TARGET ) if( m_spellInfo->Attributes & SPELL_ATTR_STOP_ATTACK_TARGET )
m_caster->AttackStop(); m_caster->AttackStop();
@@ -4797,10 +4835,8 @@ SpellCastResult Spell::CheckPetCast(Unit* target)
SpellCastResult Spell::CheckCasterAuras() const SpellCastResult Spell::CheckCasterAuras() const
{ {
// Flag drop spells totally immuned to caster auras // spells totally immuned to caster auras ( wsg flag drop, give marks etc
// FIXME: find more nice check for all totally immuned spells if(m_spellInfo->AttributesEx6& SPELL_ATTR_EX6_IGNORE_CASTER_AURAS)
// AttributesEx3 & 0x10000000?
if(m_spellInfo->Id == 23336 || m_spellInfo->Id == 23334 || m_spellInfo->Id == 34991)
return SPELL_CAST_OK; return SPELL_CAST_OK;
uint8 school_immune = 0; uint8 school_immune = 0;
@@ -5863,8 +5899,13 @@ bool SpellEvent::Execute(uint64 e_time, uint32 p_time)
} }
else else
{ {
// Set last not triggered spell for apply spellmods
((Player*)m_Spell->GetCaster())->SetSpellModTakingSpell(m_Spell, true);
// do the action (pass spell to channeling state) // do the action (pass spell to channeling state)
m_Spell->handle_immediate(); m_Spell->handle_immediate();
// And remove after effect handling
((Player*)m_Spell->GetCaster())->SetSpellModTakingSpell(m_Spell, false);
} }
// event will be re-added automatically at the end of routine) // event will be re-added automatically at the end of routine)
} }
+5
View File
@@ -366,6 +366,8 @@ class Spell
void EffectTitanGrip(uint32 i); void EffectTitanGrip(uint32 i);
void EffectEnchantItemPrismatic(uint32 i); void EffectEnchantItemPrismatic(uint32 i);
typedef std::set<Aura *> UsedSpellMods;
Spell( Unit* Caster, SpellEntry const *info, bool triggered, uint64 originalCasterGUID = 0, Spell** triggeringContainer = NULL, bool skipCheck = false ); Spell( Unit* Caster, SpellEntry const *info, bool triggered, uint64 originalCasterGUID = 0, Spell** triggeringContainer = NULL, bool skipCheck = false );
~Spell(); ~Spell();
@@ -445,6 +447,8 @@ class Spell
uint32 m_preCastSpell; uint32 m_preCastSpell;
SpellCastTargets m_targets; SpellCastTargets m_targets;
UsedSpellMods m_appliedMods;
int32 GetCastTime() const { return m_casttime; } int32 GetCastTime() const { return m_casttime; }
bool IsAutoRepeat() const { return m_autoRepeat; } bool IsAutoRepeat() const { return m_autoRepeat; }
void SetAutoRepeat(bool rep) { m_autoRepeat = rep; } void SetAutoRepeat(bool rep) { m_autoRepeat = rep; }
@@ -453,6 +457,7 @@ class Spell
{ {
return m_spellInfo->Attributes & SPELL_ATTR_ON_NEXT_SWING; return m_spellInfo->Attributes & SPELL_ATTR_ON_NEXT_SWING;
} }
bool IsTriggered() const {return m_IsTriggeredSpell;};
bool IsChannelActive() const { return m_caster->GetUInt32Value(UNIT_CHANNEL_SPELL) != 0; } bool IsChannelActive() const { return m_caster->GetUInt32Value(UNIT_CHANNEL_SPELL) != 0; }
bool IsMeleeAttackResetSpell() const { return !m_IsTriggeredSpell && (m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_AUTOATTACK); } bool IsMeleeAttackResetSpell() const { return !m_IsTriggeredSpell && (m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_AUTOATTACK); }
bool IsRangedAttackResetSpell() const { return !m_IsTriggeredSpell && /*IsRangedSpell() &&*/ !(m_spellInfo->AttributesEx2 & SPELL_ATTR_EX2_NOT_RESET_AUTOSHOT); } bool IsRangedAttackResetSpell() const { return !m_IsTriggeredSpell && /*IsRangedSpell() &&*/ !(m_spellInfo->AttributesEx2 & SPELL_ATTR_EX2_NOT_RESET_AUTOSHOT); }
+22 -2
View File
@@ -623,6 +623,8 @@ Unit* AuraEffect::GetSource() const
void Aura::Update(uint32 diff) void Aura::Update(uint32 diff)
{ {
// TODO: store pointer to caster in aura class for update/mod handling code
if (m_duration > 0) if (m_duration > 0)
{ {
m_duration -= diff; m_duration -= diff;
@@ -666,9 +668,23 @@ void Aura::Update(uint32 diff)
} }
} }
// Apply charged spellmods for channeled auras
// used for example when triggered spell of spell:10 is modded
Spell * modSpell = NULL;
Unit* caster = NULL;
if (IS_PLAYER_GUID(GetCasterGUID())
{
caster = GetCaster();
modSpell = ((Player*)caster)->FindCurrentSpellBySpellId(GetId());
if (caster)
((Player*)caster)->SetSpellModTakingSpell(modSpell, true);
}
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
if (m_partAuras[i]) if (m_partAuras[i])
m_partAuras[i]->Update(diff); m_partAuras[i]->Update(diff);
if (caster)
((Player*)caster)->SetSpellModTakingSpell(modSpell, false);
} }
void AuraEffect::Update(uint32 diff) void AuraEffect::Update(uint32 diff)
@@ -1295,16 +1311,20 @@ void Aura::SetAuraCharges(uint8 charges)
SendAuraUpdate(); SendAuraUpdate();
} }
void Aura::DropAuraCharge() bool Aura::DropAuraCharge()
{ {
if(m_procCharges) //auras without charges always have charge = 0 if(m_procCharges) //auras without charges always have charge = 0
{ {
if(--m_procCharges) // Send charge change if(--m_procCharges) // Send charge change
SendAuraUpdate(); SendAuraUpdate();
else // Last charge dropped else // Last charge dropped
{
m_target->RemoveAura(this, AURA_REMOVE_BY_EXPIRE); m_target->RemoveAura(this, AURA_REMOVE_BY_EXPIRE);
return true;
} }
} }
return false;
}
bool Aura::IsPersistent() const bool Aura::IsPersistent() const
{ {
@@ -1533,7 +1553,7 @@ void AuraEffect::HandleAddModifier(bool apply, bool Real, bool changeAmount)
if (apply) if (apply)
{ {
SpellModifier *mod = new SpellModifier; SpellModifier *mod = new SpellModifier(GetParentAura());
mod->op = SpellModOp(modOp); mod->op = SpellModOp(modOp);
mod->value = m_amount; mod->value = m_amount;
mod->type = SpellModType(m_auraName); // SpellModType value == spell aura types mod->type = SpellModType(m_auraName); // SpellModType value == spell aura types
+1 -1
View File
@@ -77,7 +77,7 @@ class TRINITY_DLL_SPEC Aura
void SetAuraSlot(uint8 slot) { m_auraSlot = slot; } void SetAuraSlot(uint8 slot) { m_auraSlot = slot; }
uint8 GetAuraCharges() const { return m_procCharges; } uint8 GetAuraCharges() const { return m_procCharges; }
void SetAuraCharges(uint8 charges); void SetAuraCharges(uint8 charges);
void DropAuraCharge(); bool DropAuraCharge();
void SetProcDamage(uint32 val) { m_procDamage = val; } void SetProcDamage(uint32 val) { m_procDamage = val; }
uint32 GetProcDamage() const { return m_procDamage; } uint32 GetProcDamage() const { return m_procDamage; }
+2 -2
View File
@@ -279,7 +279,7 @@ bool GetDispelChance(Unit* caster, uint32 spellId)
return !roll_chance_i(miss_chance); return !roll_chance_i(miss_chance);
} }
uint32 GetSpellCastTime(SpellEntry const* spellInfo, Spell const* spell) uint32 GetSpellCastTime(SpellEntry const* spellInfo, Spell * spell)
{ {
SpellCastTimesEntry const *spellCastTimeEntry = sSpellCastTimesStore.LookupEntry(spellInfo->CastingTimeIndex); SpellCastTimesEntry const *spellCastTimeEntry = sSpellCastTimesStore.LookupEntry(spellInfo->CastingTimeIndex);
@@ -1309,7 +1309,7 @@ bool SpellMgr::IsSpellProcEventCanTriggeredBy(SpellProcEventEntry const* spellPr
} }
// Always trigger for this // Always trigger for this
if (EventProcFlag & (PROC_FLAG_KILLED | PROC_FLAG_KILL | PROC_FLAG_ON_TRAP_ACTIVATION)) if (procFlags & (PROC_FLAG_KILLED | PROC_FLAG_KILL | PROC_FLAG_ON_TRAP_ACTIVATION))
return true; return true;
if (spellProcEvent) // Exist event data if (spellProcEvent) // Exist event data
{ {
+1 -1
View File
@@ -158,7 +158,7 @@ SpellSpecific GetSpellSpecific(uint32 spellId);
// Different spell properties // Different spell properties
inline float GetSpellRadiusForHostile(SpellRadiusEntry const *radius) { return (radius ? radius->radiusHostile : 0); } inline float GetSpellRadiusForHostile(SpellRadiusEntry const *radius) { return (radius ? radius->radiusHostile : 0); }
inline float GetSpellRadiusForFriend(SpellRadiusEntry const *radius) { return (radius ? radius->radiusFriend : 0); } inline float GetSpellRadiusForFriend(SpellRadiusEntry const *radius) { return (radius ? radius->radiusFriend : 0); }
uint32 GetSpellCastTime(SpellEntry const* spellInfo, Spell const* spell = NULL); uint32 GetSpellCastTime(SpellEntry const* spellInfo, Spell * spell = NULL);
bool GetDispelChance(Unit* caster, uint32 spellId); bool GetDispelChance(Unit* caster, uint32 spellId);
inline float GetSpellMinRangeForHostile(SpellRangeEntry const *range) { return (range ? range->minRangeHostile : 0); } inline float GetSpellMinRangeForHostile(SpellRangeEntry const *range) { return (range ? range->minRangeHostile : 0); }
inline float GetSpellMaxRangeForHostile(SpellRangeEntry const *range) { return (range ? range->maxRangeHostile : 0); } inline float GetSpellMaxRangeForHostile(SpellRangeEntry const *range) { return (range ? range->maxRangeHostile : 0); }
+6 -2
View File
@@ -7568,7 +7568,7 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, AuraEffect* trig
case 56453: case 56453:
{ {
// Proc only from trap activation (from periodic proc another aura of this spell) // Proc only from trap activation (from periodic proc another aura of this spell)
if (!(procFlags & PROC_FLAG_ON_TRAP_ACTIVATION) || !roll_chance_i(triggerAmount)) if (!(procFlags & PROC_FLAG_ON_TRAP_ACTIVATION))
return false; return false;
break; break;
} }
@@ -11065,7 +11065,7 @@ int32 Unit::ModSpellDuration(SpellEntry const* spellProto, Unit const* target, i
return duration>0 ? duration : 0; return duration>0 ? duration : 0;
} }
void Unit::ModSpellCastTime(SpellEntry const* spellProto, int32 & castTime, Spell const * spell) void Unit::ModSpellCastTime(SpellEntry const* spellProto, int32 & castTime, Spell * spell)
{ {
if (!spellProto || castTime<0) if (!spellProto || castTime<0)
return; return;
@@ -12359,6 +12359,10 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag
if (triggeredByAura->GetCasterGUID() != pTarget->GetGUID()) if (triggeredByAura->GetCasterGUID() != pTarget->GetGUID())
continue; continue;
break; break;
/*case SPELL_AURA_ADD_FLAT_MODIFIER:
case SPELL_AURA_ADD_PCT_MODIFIER:
// HandleSpellModAuraProc
break;*/
default: default:
// nothing do, just charges counter // nothing do, just charges counter
break; break;
+1 -1
View File
@@ -1643,7 +1643,7 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
int32 CalculateSpellDamage(SpellEntry const* spellProto, uint8 effect_index, int32 basePoints, Unit const* target); int32 CalculateSpellDamage(SpellEntry const* spellProto, uint8 effect_index, int32 basePoints, Unit const* target);
int32 CalcSpellDuration(SpellEntry const* spellProto); int32 CalcSpellDuration(SpellEntry const* spellProto);
int32 ModSpellDuration(SpellEntry const* spellProto, Unit const* target, int32 duration, bool positive); int32 ModSpellDuration(SpellEntry const* spellProto, Unit const* target, int32 duration, bool positive);
void ModSpellCastTime(SpellEntry const* spellProto, int32 & castTime, Spell const * spell=NULL); void ModSpellCastTime(SpellEntry const* spellProto, int32 & castTime, Spell * spell=NULL);
float CalculateLevelPenalty(SpellEntry const* spellProto) const; float CalculateLevelPenalty(SpellEntry const* spellProto) const;
void addFollower(FollowerReference* pRef) { m_FollowingRefManager.insertFirst(pRef); } void addFollower(FollowerReference* pRef) { m_FollowingRefManager.insertFirst(pRef); }