aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authormegamage <none@none>2009-05-17 16:40:40 -0500
committermegamage <none@none>2009-05-17 16:40:40 -0500
commit1c134f81e38137bbfb1c6925a3a42d9628571d4c (patch)
tree479972a69d9badeffab98d51e8c19178afb99ec1 /src
parentb95e67375c00e7e24609450178c4f7ba44064441 (diff)
parent7c6757d7ee652c8e688caa5c6856d116c1f034c1 (diff)
*Merge.
--HG-- branch : trunk
Diffstat (limited to 'src')
-rw-r--r--src/game/AggressorAI.cpp2
-rw-r--r--src/game/Spell.cpp42
-rw-r--r--src/game/Spell.h6
-rw-r--r--src/game/SpellAuras.cpp26
-rw-r--r--src/game/SpellAuras.h7
-rw-r--r--src/game/SpellMgr.cpp9
-rw-r--r--src/game/SpellMgr.h5
-rw-r--r--src/game/Unit.cpp30
-rw-r--r--src/game/Unit.h1
9 files changed, 83 insertions, 45 deletions
diff --git a/src/game/AggressorAI.cpp b/src/game/AggressorAI.cpp
index 22ebe87cdc6..218f19a1c21 100644
--- a/src/game/AggressorAI.cpp
+++ b/src/game/AggressorAI.cpp
@@ -67,7 +67,7 @@ void SpellAI::EnterCombat(Unit *who)
for(SpellVct::iterator i = spells.begin(); i != spells.end(); ++i)
{
if(AISpellInfo[*i].condition == AICOND_AGGRO)
- me->CastSpell(who, *i, true);
+ me->CastSpell(who, *i, false);
else if(AISpellInfo[*i].condition == AICOND_COMBAT)
events.ScheduleEvent(*i, AISpellInfo[*i].cooldown + rand()%AISpellInfo[*i].cooldown);
}
diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp
index 7e94e86ab4d..33a3e4e1599 100644
--- a/src/game/Spell.cpp
+++ b/src/game/Spell.cpp
@@ -364,6 +364,8 @@ Spell::Spell( Unit* Caster, SpellEntry const *info, bool triggered, uint64 origi
m_delayStart = 0;
m_delayAtDamageCount = 0;
+ m_canTrigger=true;
+
m_applyMultiplierMask = 0;
m_effectMask = 0;
@@ -723,14 +725,38 @@ void Spell::FillTargetMap()
}
}
-void Spell::prepareDataForTriggerSystem()
+void Spell::prepareDataForTriggerSystem(AuraEffect * triggeredByAura)
{
//==========================================================================================
// Now fill data for trigger system, need know:
- // an spell trigger another or not ( m_canTrigger )
- // Create base triggers flags for Attacker and Victim ( m_procAttacker and m_procVictim)
+ // can spell trigger another or not ( m_canTrigger )
+ // 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()->CanProc())
+ {
+ m_canTrigger=false;
+ }
+
+ m_procEx = (m_IsTriggeredSpell)
+ && !(m_spellInfo->AttributesEx2 & SPELL_ATTR_EX2_TRIGGERED_CAN_TRIGGER)
+ && !(m_spellInfo->AttributesEx2 & SPELL_ATTR_EX2_TRIGGERED_CAN_TRIGGER_2)
+ ? PROC_EX_INTERNAL_TRIGGERED : PROC_EX_NONE;
+
+ if (m_IsTriggeredSpell && (m_spellInfo->AttributesEx2 & SPELL_ATTR_EX2_TRIGGERED_CAN_TRIGGER_2 | SPELL_ATTR_EX2_TRIGGERED_CAN_TRIGGER))
+ 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
switch (m_spellInfo->DmgClass)
{
@@ -973,15 +999,13 @@ void Spell::DoAllEffectOnTarget(TargetInfo *target)
// Fill base trigger info
uint32 procAttacker = m_procAttacker;
uint32 procVictim = m_procVictim;
- uint32 procEx = m_triggeredByAuraSpell
- && !(m_spellInfo->AttributesEx2 & SPELL_ATTR_EX2_TRIGGERED_CAN_TRIGGER)
- && !(m_spellInfo->AttributesEx2 & SPELL_ATTR_EX2_TRIGGERED_CAN_TRIGGER_2)
- ? PROC_EX_INTERNAL_TRIGGERED : PROC_EX_NONE;
+ uint32 procEx = m_procEx;
+
m_spellAura = NULL; // Set aura to null for every target-make sure that pointer is not used for unit without aura applied
//Spells with this flag cannot trigger if effect is casted on self
// Slice and Dice, relentless strikes, eviscerate
- bool canEffectTrigger = (m_spellInfo->AttributesEx4 & (SPELL_ATTR_EX4_CANT_PROC_FROM_SELFCAST | SPELL_ATTR_EX4_UNK4) ? m_caster!=unitTarget : true);
+ bool canEffectTrigger = m_canTrigger && (m_spellInfo->AttributesEx4 & (SPELL_ATTR_EX4_CANT_PROC_FROM_SELFCAST | SPELL_ATTR_EX4_UNK4) ? m_caster!=unitTarget : true);
Unit * spellHitTarget = NULL;
if (missInfo==SPELL_MISS_NONE) // In case spell hit target, do all effect on that target
@@ -2327,7 +2351,7 @@ void Spell::prepare(SpellCastTargets const* targets, AuraEffect* triggeredByAura
}
// Prepare data for triggers
- prepareDataForTriggerSystem();
+ prepareDataForTriggerSystem(triggeredByAura);
// Set combo point requirement
if (m_IsTriggeredSpell || m_CastItem || m_caster->GetTypeId()!=TYPEID_PLAYER)
diff --git a/src/game/Spell.h b/src/game/Spell.h
index 083bb338371..99017742e2f 100644
--- a/src/game/Spell.h
+++ b/src/game/Spell.h
@@ -458,7 +458,7 @@ class Spell
bool IsDeletable() const { return !m_referencedFromCurrentSpell && !m_executedCurrently; }
void SetReferencedFromCurrent(bool yes) { m_referencedFromCurrentSpell = yes; }
bool IsInterruptable() const { return !m_executedCurrently; }
- void SetExecutedCurrently(bool yes) { m_executedCurrently = yes; }
+ void SetExecutedCurrently(bool yes) {m_executedCurrently = yes;}
uint64 GetDelayStart() const { return m_delayStart; }
void SetDelayStart(uint64 m_time) { m_delayStart = m_time; }
uint64 GetDelayMoment() const { return m_delayMoment; }
@@ -552,7 +552,9 @@ class Spell
//******************************************
uint32 m_procAttacker; // Attacker trigger flags
uint32 m_procVictim; // Victim trigger flags
- void prepareDataForTriggerSystem();
+ uint32 m_procEx;
+ bool m_canTrigger;
+ void prepareDataForTriggerSystem(AuraEffect * triggeredByAura);
//*****************************************
// Spell target subsystem
diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp
index 8867522e549..6ca43844c76 100644
--- a/src/game/SpellAuras.cpp
+++ b/src/game/SpellAuras.cpp
@@ -346,7 +346,7 @@ pAuraHandler AuraHandler[TOTAL_AURAS]=
Aura::Aura(SpellEntry const* spellproto, uint32 effMask, int32 *currentBasePoints, Unit *target, Unit *caster, Item* castItem, Unit * formalCaster) :
m_caster_guid(0), m_castItemGuid(castItem?castItem->GetGUID():0), m_target(target),
m_timeCla(1000), m_removeMode(AURA_REMOVE_BY_DEFAULT), m_AuraDRGroup(DIMINISHING_NONE),
-m_auraSlot(MAX_AURAS), m_auraLevel(1), m_procCharges(0), m_stackAmount(1),m_auraStateMask(0), m_updated(false), m_isRemoved(false)
+m_auraSlot(MAX_AURAS), m_auraLevel(1), m_procCharges(0), m_stackAmount(1),m_auraStateMask(0), m_updated(false), m_isRemoved(false), m_canProc(true)
{
assert(target);
@@ -613,6 +613,8 @@ Unit* AreaAuraEffect::GetFormalCaster() const
void Aura::Update(uint32 diff)
{
+ // Reset can proc requirement-prevent use of outdated value
+ m_canProc = true;
if (m_duration > 0)
{
m_duration -= diff;
@@ -1837,7 +1839,7 @@ void AuraEffect::TriggerSpell()
// Doom
case 31347:
{
- m_target->CastSpell(m_target,31350,true);
+ m_target->CastSpell(m_target,31350,true, NULL, this);
m_target->DealDamage(m_target, m_target->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
return;
}
@@ -1867,9 +1869,9 @@ void AuraEffect::TriggerSpell()
{
// cast 24 spells 34269-34289, 34314-34316
for(uint32 spell_id = 34269; spell_id != 34290; ++spell_id)
- caster->CastSpell(m_target,spell_id,true);
+ caster->CastSpell(m_target,spell_id,true, NULL, this);
for(uint32 spell_id = 34314; spell_id != 34317; ++spell_id)
- caster->CastSpell(m_target,spell_id,true);
+ caster->CastSpell(m_target,spell_id,true, NULL, this);
return;
}
// // Gravity Lapse
@@ -1951,7 +1953,7 @@ void AuraEffect::TriggerSpell()
// Eye of Grillok
case 38495:
{
- m_target->CastSpell(m_target, 38530, true);
+ m_target->CastSpell(m_target, 38530, true, NULL, this);
return;
}
// Absorb Eye of Grillok (Zezzak's Shard)
@@ -1960,7 +1962,7 @@ void AuraEffect::TriggerSpell()
if(m_target->GetTypeId() != TYPEID_UNIT)
return;
- caster->CastSpell(caster, 38495, true);
+ caster->CastSpell(caster, 38495, true, NULL, this);
Creature* creatureTarget = (Creature*)m_target;
@@ -2198,7 +2200,7 @@ void AuraEffect::TriggerSpell()
}
if(all)
- caster->CastSpell(caster,38437,true);
+ caster->CastSpell(caster,38437,true, NULL, this);
else
caster->RemoveAurasDueToSpell(38437);
return;
@@ -2278,7 +2280,7 @@ void AuraEffect::TriggerSpell()
// Curse of the Plaguebringer (22/15)
case 29213:
case 54835:
- caster->CastSpell(m_target, trigger_spell_id, true);
+ caster->CastSpell(m_target, trigger_spell_id, true, NULL, this);
return;
}
}
@@ -4244,10 +4246,10 @@ void AuraEffect::HandleModMechanicImmunity(bool apply, bool Real, bool /*changeA
{
if(apply)
{
- m_target->CastSpell(m_target,24395,true);
- m_target->CastSpell(m_target,24396,true);
- m_target->CastSpell(m_target,24397,true);
- m_target->CastSpell(m_target,26592,true);
+ m_target->CastSpell(m_target,24395,true, NULL, this);
+ m_target->CastSpell(m_target,24396,true, NULL, this);
+ m_target->CastSpell(m_target,24397,true, NULL, this);
+ m_target->CastSpell(m_target,26592,true, NULL, this);
}
else
{
diff --git a/src/game/SpellAuras.h b/src/game/SpellAuras.h
index b4d7eefb706..fc0b42f58bf 100644
--- a/src/game/SpellAuras.h
+++ b/src/game/SpellAuras.h
@@ -107,6 +107,8 @@ class TRINITY_DLL_SPEC Aura
bool IsRemoved() const { return m_isRemoved; }
void SetUpdated(bool val) { m_updated = val; }
+ bool CanProc(){return m_canProc;}
+ void SetCanProc(bool val){ m_canProc = val; }
bool IsPersistent() const;
bool IsAreaAura() const;
bool IsAuraType(AuraType type) const;
@@ -152,11 +154,13 @@ class TRINITY_DLL_SPEC Aura
uint8 m_auraFlags; // Aura info flag (for send data to client)
uint8 m_auraLevel; // Aura level (store caster level for correct show level dep amount)
uint8 m_procCharges; // Aura charges (0 for infinite)
- uint32 m_procDamage; // used in aura proc code
uint8 m_stackAmount; // Aura stack amount
uint32 m_auraStateMask;
AuraEffect * m_partAuras[3];
+ uint32 m_procDamage; // used in aura proc code
+ bool m_canProc:1;
+
bool m_isDeathPersist:1;
bool m_isRemovedOnShapeLost:1;
bool m_isPassive:1;
@@ -396,6 +400,7 @@ class TRINITY_DLL_SPEC AreaAuraEffect : public AuraEffect
AreaAuraEffect(Aura * parentAura, uint32 effIndex, int32 * currentBasePoints, Unit * caster=NULL, Item * castItem=NULL, Unit * formalCaster=NULL);
~AreaAuraEffect();
Unit* GetFormalCaster() const;
+ uint64 const& GetFormalCasterGUID() const { return m_formalCasterGUID; }
void Update(uint32 diff);
private:
float m_radius;
diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp
index a960942579e..c7bf8cd5bac 100644
--- a/src/game/SpellMgr.cpp
+++ b/src/game/SpellMgr.cpp
@@ -1222,6 +1222,8 @@ bool SpellMgr::IsSpellProcEventCanTriggeredBy(SpellProcEventEntry const* spellPr
if((procFlags & EventProcFlag) == 0)
return false;
+ bool hasFamilyMask = false;
+
/* Check Periodic Auras
* Both hots and dots can trigger if spell has no PROC_FLAG_SUCCESSFUL_POSITIVE_SPELL
@@ -1288,10 +1290,17 @@ bool SpellMgr::IsSpellProcEventCanTriggeredBy(SpellProcEventEntry const* spellPr
if ((spellProcEvent->spellFamilyMask & procSpell->SpellFamilyFlags ) == 0)
return false;
active = true; // Spell added manualy -> so its active spell
+ hasFamilyMask = true;
}
}
}
+ if (procExtra & PROC_EX_INTERNAL_REQ_FAMILY)
+ {
+ if (!hasFamilyMask)
+ return false;
+ }
+
// Check for extra req (if none) and hit/crit
if (procEvent_procEx == PROC_EX_NONE)
{
diff --git a/src/game/SpellMgr.h b/src/game/SpellMgr.h
index 1848cf03805..4427e4c6abb 100644
--- a/src/game/SpellMgr.h
+++ b/src/game/SpellMgr.h
@@ -467,11 +467,12 @@ enum ProcFlagsEx
PROC_EX_AURA_REMOVE_DESTROY = 0x0002000, // aura absorb destroy or dispel
PROC_EX_AURA_REMOVE_EXPIRE = 0x0004000, // aura remove by default and by cancel
PROC_EX_EX_TRIGGER_ALWAYS = 0x0010000, // If set trigger always ( no matter another flags) used for drop charges
- PROC_EX_EX_ONE_TIME_TRIGGER = 0x0020000, // If set trigger always but only one time (not used)
+ PROC_EX_EX_ONE_TIME_TRIGGER = 0x0020000, // If set trigger always but only one time (not used)
+ PROC_EX_INTERNAL_CANT_PROC = 0x0800000,
PROC_EX_INTERNAL_DOT = 0x1000000, // Only for internal use
PROC_EX_INTERNAL_HOT = 0x2000000, // Only for internal use
PROC_EX_INTERNAL_TRIGGERED = 0x4000000, // Only for internal use
- PROC_EX_INTERNAL_ITEM_CAST = 0x8000000
+ PROC_EX_INTERNAL_REQ_FAMILY = 0x8000000 // Only for internal use
};
#define AURA_REMOVE_PROC_EX_MASK \
(PROC_EX_AURA_REMOVE_DESTROY | PROC_EX_AURA_REMOVE_EXPIRE)
diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp
index a5e285f7149..8b7677e6d2f 100644
--- a/src/game/Unit.cpp
+++ b/src/game/Unit.cpp
@@ -1046,7 +1046,7 @@ void Unit::CastSpell(Unit* Victim,SpellEntry const *spellInfo, bool triggered, I
return;
}
- if (!originalCaster && GetTypeId()==TYPEID_UNIT && ((Creature*)this)->isTotem())
+ if (!originalCaster && GetTypeId()==TYPEID_UNIT && ((Creature*)this)->isTotem() && IsControlledByPlayer())
if (Unit * owner = GetOwner())
originalCaster=owner->GetGUID();
@@ -4236,7 +4236,7 @@ void Unit::RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode)
// Remove totem at next update if totem looses its aura
if (GetTypeId()==TYPEID_UNIT && ((Creature*)this)->isTotem()&& ((TempSummon*)this)->GetSummonerGUID()==Aur->GetCasterGUID())
{
- if (((Totem*)this)->GetSpell()==Aur->GetId())
+ if (((Totem*)this)->GetSpell()==Aur->GetId() && ((Totem*)this)->GetTotemType()==TOTEM_PASSIVE)
((Totem*)this)->setDeathState(JUST_DIED);
}
@@ -5571,7 +5571,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger
{
if(!pVictim || !pVictim->isAlive())
return false;
- pVictim->CastSpell(pVictim, 60946,true);
+ pVictim->CastSpell(pVictim, 60946,true, castItem, triggeredByAura);
return true;
}
// Improved Fear (Rank 2)
@@ -5579,7 +5579,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger
{
if(!pVictim || !pVictim->isAlive())
return false;
- pVictim->CastSpell(pVictim, 60947,true);
+ pVictim->CastSpell(pVictim, 60947,true, castItem, triggeredByAura);
return true;
}
// Shadowflame (Voidheart Raiment set bonus)
@@ -5711,7 +5711,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger
{
if(!pVictim || !pVictim->isAlive())
return false;
- pVictim->CastSpell(pVictim, 59980,true);
+ pVictim->CastSpell(pVictim, 59980,true, castItem, triggeredByAura);
return true;
}
// Psychic Horror (Rank 2)
@@ -5719,7 +5719,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger
{
if(!pVictim || !pVictim->isAlive())
return false;
- pVictim->CastSpell(pVictim, 59981,true);
+ pVictim->CastSpell(pVictim, 59981,true, castItem, triggeredByAura);
return true;
}
// Glyph of Dispel Magic
@@ -6038,7 +6038,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger
target = this;
triggered_spell_id = 31930;
// replenishment
- CastSpell(this,57669,true);
+ CastSpell(this,57669,true, castItem, triggeredByAura);
break;
}
// Sanctified Wrath
@@ -6869,8 +6869,6 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, AuraEffect* trig
// Set trigger spell id, target, custom basepoints
uint32 trigger_spell_id = auraSpellInfo->EffectTriggerSpell[triggeredByAura->GetEffIndex()];
- if(procSpell && procSpell->Id == trigger_spell_id)
- return false;
Unit* target = NULL;
int32 basepoints0 = 0;
@@ -8502,8 +8500,6 @@ Unit* Unit::SelectMagnetTarget(Unit *victim, SpellEntry const *spellInfo)
if(Unit* magnet = (*itr)->IsAreaAura() ? ((AreaAuraEffect*)(*itr))->GetFormalCaster():(*itr)->GetCaster() )
if(magnet->isAlive())
{
- if (Aura * aur = magnet->GetAura((*itr)->GetId(),(*itr)->GetCasterGUID()))
- aur->DropAuraCharge();
return magnet;
}
}
@@ -12003,7 +11999,6 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag
for(AuraMap::const_iterator itr = GetAuras().begin(); itr!= GetAuras().end(); ++itr)
{
ProcTriggeredData triggerData(itr->second);
-
if(!IsTriggeredAtSpellProcEvent(pTarget, triggerData.aura, procSpell, procFlag, procExtra, attType, isVictim, (damage > 0), triggerData.spellProcEvent))
continue;
for (uint8 i=0; i<MAX_SPELL_EFFECTS;++i)
@@ -12017,6 +12012,10 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag
if (!isTriggerAura[aurEff->GetAuraName()] && triggerData.spellProcEvent==NULL)
continue;
triggerData.effMask |= 1<<i;
+ if (procExtra & (PROC_EX_INTERNAL_TRIGGERED | PROC_EX_INTERNAL_CANT_PROC))
+ itr->second->SetCanProc(false);
+ else
+ itr->second->SetCanProc(true);
}
}
if (triggerData.effMask)
@@ -12832,11 +12831,6 @@ bool Unit::IsTriggeredAtSpellProcEvent(Unit *pVictim, Aura * aura, SpellEntry co
if (!EventProcFlag)
return false;
- // Do not proc spells for totem if aura does not require family to proc
- if (GetTypeId()==TYPEID_UNIT && ((Creature*)this)->isTotem() && ((Totem*)this)->IsControlledByPlayer())
- if (!spellProcEvent || !spellProcEvent->spellFamilyName)
- return false;
-
// Additional checks for triggered spells
if (procExtra & PROC_EX_INTERNAL_TRIGGERED)
{
@@ -13027,7 +13021,7 @@ void Unit::SetToNotify()
void Unit::Kill(Unit *pVictim, bool durabilityLoss)
{
// Prevent killing unit twice (and giving reward from kill twice)
- if (!pVictim->isAlive())
+ if (!pVictim->GetHealth())
return;
pVictim->SetHealth(0);
diff --git a/src/game/Unit.h b/src/game/Unit.h
index bbd7471b1b8..084dcd53789 100644
--- a/src/game/Unit.h
+++ b/src/game/Unit.h
@@ -1659,6 +1659,7 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
void _DeleteAuras();
void _UpdateAutoRepeatSpell();
+
bool m_AutoRepeatFirstCast;
uint32 m_attackTimer[MAX_ATTACK];