aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTrisjdc <trisjdc@gmail.com>2014-06-15 17:27:57 +0100
committerTrisjdc <trisjdc@gmail.com>2014-06-15 17:27:57 +0100
commit6098a5e43ad52e016ff6e2b263db6d92a0718995 (patch)
treed37c68621b17462cb96760191207c02dbb11fc9b
parente55835a6a9ae09dd4b65de494cba712c322a2419 (diff)
Core/Auras: Add a new stack rule to handle cases where the aura that is 'stronger' prevails (SPELL_GROUP_STACK_RULE_EXCLUSIVE_HIGHEST)
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp59
-rw-r--r--src/server/game/Entities/Unit/Unit.h1
-rw-r--r--src/server/game/Spells/Auras/SpellAuras.cpp31
-rw-r--r--src/server/game/Spells/Auras/SpellAuras.h1
-rw-r--r--src/server/game/Spells/SpellMgr.h12
5 files changed, 93 insertions, 11 deletions
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index 433352b642a..1b262946c10 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -3503,6 +3503,19 @@ void Unit::_RemoveNoStackAurasDueToAura(Aura* aura)
if (spellProto->IsPassiveStackableWithRanks())
return;
+ if (!IsHighestExclusiveAura(aura))
+ {
+ if (!aura->GetSpellInfo()->IsAffectingArea())
+ {
+ Unit* caster = aura->GetCaster();
+ if (caster && caster->GetTypeId() == TYPEID_PLAYER)
+ Spell::SendCastResult(caster->ToPlayer(), aura->GetSpellInfo(), 1, SPELL_FAILED_AURA_BOUNCED);
+ }
+
+ RemoveAura(aura);
+ return;
+ }
+
bool remove = false;
for (AuraApplicationMap::iterator i = m_appliedAuras.begin(); i != m_appliedAuras.end(); ++i)
{
@@ -17771,3 +17784,49 @@ int32 Unit::GetHighestExclusiveSameEffectSpellGroupValue(AuraEffect const* aurEf
}
return val;
}
+
+bool Unit::IsHighestExclusiveAura(Aura const* aura, bool removeOtherAuraApplications /*= false*/)
+{
+ for (uint32 i = 0 ; i < MAX_SPELL_EFFECTS; ++i)
+ {
+ if (AuraEffect const* aurEff = aura->GetEffect(i))
+ {
+ AuraType const auraType = AuraType(aura->GetSpellInfo()->Effects[i].ApplyAuraName);
+ AuraEffectList const& auras = GetAuraEffectsByType(auraType);
+ for (Unit::AuraEffectList::const_iterator itr = auras.begin(); itr != auras.end();)
+ {
+ AuraEffect const* existingAurEff = (*itr);
+ ++itr;
+
+ if (sSpellMgr->CheckSpellGroupStackRules(aura->GetSpellInfo(), existingAurEff->GetSpellInfo())
+ == SPELL_GROUP_STACK_RULE_EXCLUSIVE_HIGHEST)
+ {
+ int32 diff = abs(aurEff->GetAmount()) - abs(existingAurEff->GetAmount());
+ if (!diff)
+ diff = int32(aura->GetEffectMask()) - int32(existingAurEff->GetBase()->GetEffectMask());
+
+ if (diff > 0)
+ {
+ Aura const* base = existingAurEff->GetBase();
+ // no removing of area auras from the original owner, as that completely cancels them
+ if (removeOtherAuraApplications && (!base->IsArea() || base->GetOwner() != this))
+ {
+ if (AuraApplication* aurApp = existingAurEff->GetBase()->GetApplicationOfTarget(GetGUID()))
+ {
+ bool hasMoreThanOneEffect = base->HasMoreThanOneEffectForType(auraType);
+ uint32 removedAuras = m_removedAurasCount;
+ RemoveAura(aurApp);
+ if (hasMoreThanOneEffect || m_removedAurasCount > removedAuras + 1)
+ itr = auras.begin();
+ }
+ }
+ }
+ else if (diff < 0)
+ return false;
+ }
+ }
+ }
+ }
+
+ return true;
+}
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index 103f6b596d9..9e0cfcf6af1 100644
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -2156,6 +2156,7 @@ class Unit : public WorldObject
void SetLastDamagedTime(time_t val) { _lastDamagedTime = val; }
int32 GetHighestExclusiveSameEffectSpellGroupValue(AuraEffect const* aurEff, AuraType auraType, bool sameMiscValue = false) const;
+ bool IsHighestExclusiveAura(Aura const* aura, bool removeOtherAuraApplications = false);
protected:
explicit Unit (bool isWorldObject);
diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp
index 683059b8e99..29fbd7590a1 100644
--- a/src/server/game/Spells/Auras/SpellAuras.cpp
+++ b/src/server/game/Spells/Auras/SpellAuras.cpp
@@ -539,6 +539,9 @@ void Aura::UpdateTargetMap(Unit* caster, bool apply)
|| !CanBeAppliedOn(itr->first))
addUnit = false;
+ if (addUnit && !itr->first->IsHighestExclusiveAura(this, true))
+ addUnit = false;
+
if (addUnit)
{
// persistent area aura does not hit flying targets
@@ -894,6 +897,18 @@ void Aura::RefreshSpellMods()
player->RestoreAllSpellMods(0, this);
}
+bool Aura::HasMoreThanOneEffectForType(AuraType auraType) const
+{
+ uint32 count = 0;
+ for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i)
+ {
+ if (HasEffect(i) && GetSpellInfo()->Effects[i].ApplyAuraName == auraType)
+ ++count;
+ }
+
+ return count > 1;
+}
+
bool Aura::IsArea() const
{
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
@@ -1758,13 +1773,19 @@ bool Aura::CanStackWith(Aura const* existingAura) const
return false;
// check spell group stack rules
- SpellGroupStackRule stackRule = sSpellMgr->CheckSpellGroupStackRules(m_spellInfo, existingSpellInfo);
- if (stackRule)
+ switch (sSpellMgr->CheckSpellGroupStackRules(m_spellInfo, existingSpellInfo))
{
- if (stackRule == SPELL_GROUP_STACK_RULE_EXCLUSIVE)
- return false;
- if (sameCaster && stackRule == SPELL_GROUP_STACK_RULE_EXCLUSIVE_FROM_SAME_CASTER)
+ case SPELL_GROUP_STACK_RULE_EXCLUSIVE:
+ case SPELL_GROUP_STACK_RULE_EXCLUSIVE_HIGHEST: // if it reaches this point, existing aura is lower/equal
return false;
+ case SPELL_GROUP_STACK_RULE_EXCLUSIVE_FROM_SAME_CASTER:
+ if (sameCaster)
+ return false;
+ break;
+ case SPELL_GROUP_STACK_RULE_DEFAULT:
+ case SPELL_GROUP_STACK_RULE_EXCLUSIVE_SAME_EFFECT:
+ default:
+ break;
}
if (m_spellInfo->SpellFamilyName != existingSpellInfo->SpellFamilyName)
diff --git a/src/server/game/Spells/Auras/SpellAuras.h b/src/server/game/Spells/Auras/SpellAuras.h
index 669d2a529a1..8c426ea2175 100644
--- a/src/server/game/Spells/Auras/SpellAuras.h
+++ b/src/server/game/Spells/Auras/SpellAuras.h
@@ -149,6 +149,7 @@ class Aura
uint8 GetCasterLevel() const { return m_casterLevel; }
+ bool HasMoreThanOneEffectForType(AuraType auraType) const;
bool IsArea() const;
bool IsPassive() const;
bool IsDeathPersistent() const;
diff --git a/src/server/game/Spells/SpellMgr.h b/src/server/game/Spells/SpellMgr.h
index 9108618176f..757bd813613 100644
--- a/src/server/game/Spells/SpellMgr.h
+++ b/src/server/game/Spells/SpellMgr.h
@@ -349,14 +349,14 @@ typedef std::pair<SpellGroupSpellMap::const_iterator, SpellGroupSpellMap::const_
enum SpellGroupStackRule
{
- SPELL_GROUP_STACK_RULE_DEFAULT = 0,
- SPELL_GROUP_STACK_RULE_EXCLUSIVE = 1,
- SPELL_GROUP_STACK_RULE_EXCLUSIVE_FROM_SAME_CASTER = 2,
- SPELL_GROUP_STACK_RULE_EXCLUSIVE_SAME_EFFECT = 3
+ SPELL_GROUP_STACK_RULE_DEFAULT,
+ SPELL_GROUP_STACK_RULE_EXCLUSIVE,
+ SPELL_GROUP_STACK_RULE_EXCLUSIVE_FROM_SAME_CASTER,
+ SPELL_GROUP_STACK_RULE_EXCLUSIVE_SAME_EFFECT,
+ SPELL_GROUP_STACK_RULE_EXCLUSIVE_HIGHEST,
+ SPELL_GROUP_STACK_RULE_MAX
};
-#define SPELL_GROUP_STACK_RULE_MAX 4
-
typedef std::map<SpellGroup, SpellGroupStackRule> SpellGroupStackMap;
struct SpellThreatEntry