aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp24
-rw-r--r--src/server/game/Entities/Unit/Unit.h2
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.cpp62
-rw-r--r--src/server/game/Spells/SpellMgr.cpp9
-rw-r--r--src/server/game/Spells/SpellMgr.h1
5 files changed, 93 insertions, 5 deletions
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index 2b6cb9dd8ba..e0c880334ea 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -17742,3 +17742,27 @@ void Unit::BuildCooldownPacket(WorldPacket& data, uint8 flags, PacketCooldowns c
data << uint32(itr->second);
}
}
+
+int32 Unit::GetHighestExclusiveSameEffectSpellGroupValue(AuraEffect const* aurEff, AuraType auraType, bool sameMiscValue /*= false*/) const
+{
+ int32 val = 0;
+ SpellSpellGroupMapBounds spellGroup = sSpellMgr->GetSpellSpellGroupMapBounds(aurEff->GetSpellInfo()->GetFirstRankSpell()->Id);
+ for (SpellSpellGroupMap::const_iterator itr = spellGroup.first; itr != spellGroup.second ; ++itr)
+ {
+ if (sSpellMgr->GetSpellGroupStackRule(itr->second) == SPELL_GROUP_STACK_RULE_EXCLUSIVE_SAME_EFFECT)
+ {
+ AuraEffectList const& auraEffList = GetAuraEffectsByType(auraType);
+ for (AuraEffectList::const_iterator auraItr = auraEffList.begin(); auraItr != auraEffList.end(); ++auraItr)
+ {
+ if (aurEff != (*auraItr) && (!sameMiscValue || aurEff->GetMiscValue() == (*auraItr)->GetMiscValue()) &&
+ sSpellMgr->IsSpellMemberOfSpellGroup((*auraItr)->GetSpellInfo()->Id, itr->second))
+ {
+ // absolute value only
+ if (abs(val) < abs((*auraItr)->GetAmount()))
+ val = (*auraItr)->GetAmount();
+ }
+ }
+ }
+ }
+ return val;
+}
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index dbb463585f0..20c987c5105 100644
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -2155,6 +2155,8 @@ class Unit : public WorldObject
time_t GetLastDamagedTime() const { return _lastDamagedTime; }
void SetLastDamagedTime(time_t val) { _lastDamagedTime = val; }
+ int32 GetHighestExclusiveSameEffectSpellGroupValue(AuraEffect const* aurEff, AuraType auraType, bool sameMiscValue = false) const;
+
protected:
explicit Unit (bool isWorldObject);
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
index a0883c895d3..97a2db796d5 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
@@ -3493,11 +3493,23 @@ void AuraEffect::HandleModResistancePercent(AuraApplication const* aurApp, uint8
return;
Unit* target = aurApp->GetTarget();
+ int32 spellGroupVal = target->GetHighestExclusiveSameEffectSpellGroupValue(this, SPELL_AURA_MOD_RESISTANCE_PCT);
+ if (abs(spellGroupVal) >= abs(GetAmount()))
+ return;
for (int8 i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; i++)
{
if (GetMiscValue() & int32(1<<i))
{
+ if (spellGroupVal)
+ {
+ target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_PCT, (float)spellGroupVal, !apply);
+ if (target->GetTypeId() == TYPEID_PLAYER || target->IsPet())
+ {
+ target->ApplyResistanceBuffModsPercentMod(SpellSchools(i), true, (float)spellGroupVal, !apply);
+ target->ApplyResistanceBuffModsPercentMod(SpellSchools(i), false, (float)spellGroupVal, !apply);
+ }
+ }
target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_PCT, float(GetAmount()), apply);
if (target->GetTypeId() == TYPEID_PLAYER || target->ToCreature()->IsPet())
{
@@ -3557,19 +3569,29 @@ void AuraEffect::HandleAuraModStat(AuraApplication const* aurApp, uint8 mode, bo
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
- Unit* target = aurApp->GetTarget();
-
if (GetMiscValue() < -2 || GetMiscValue() > 4)
{
TC_LOG_ERROR("spells", "WARNING: Spell %u effect %u has an unsupported misc value (%i) for SPELL_AURA_MOD_STAT ", GetId(), GetEffIndex(), GetMiscValue());
return;
}
+ Unit* target = aurApp->GetTarget();
+ int32 spellGroupVal = target->GetHighestExclusiveSameEffectSpellGroupValue(this, SPELL_AURA_MOD_STAT, true);
+ if (abs(spellGroupVal) >= abs(GetAmount()))
+ return;
+
for (int32 i = STAT_STRENGTH; i < MAX_STATS; i++)
{
// -1 or -2 is all stats (misc < -2 checked in function beginning)
if (GetMiscValue() < 0 || GetMiscValue() == i)
{
+ if (spellGroupVal)
+ {
+ target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_VALUE, float(spellGroupVal), !apply);
+ if (target->GetTypeId() == TYPEID_PLAYER || target->ToCreature()->IsPet())
+ target->ApplyStatBuffMod(Stats(i), float(spellGroupVal), !apply);
+ }
+
//target->ApplyStatMod(Stats(i), m_amount, apply);
target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_VALUE, float(GetAmount()), apply);
if (target->GetTypeId() == TYPEID_PLAYER || target->ToCreature()->IsPet())
@@ -4095,7 +4117,17 @@ void AuraEffect::HandleModCombatSpeedPct(AuraApplication const* aurApp, uint8 mo
return;
Unit* target = aurApp->GetTarget();
+ int32 spellGroupVal = target->GetHighestExclusiveSameEffectSpellGroupValue(this, SPELL_AURA_MELEE_SLOW);
+ if (abs(spellGroupVal) >= abs(GetAmount()))
+ return;
+ if (spellGroupVal)
+ {
+ target->ApplyCastTimePercentMod(float(spellGroupVal), !apply);
+ target->ApplyAttackTimePercentMod(BASE_ATTACK, float(spellGroupVal), !apply);
+ target->ApplyAttackTimePercentMod(OFF_ATTACK, float(spellGroupVal), !apply);
+ target->ApplyAttackTimePercentMod(RANGED_ATTACK, float(spellGroupVal), !apply);
+ }
target->ApplyCastTimePercentMod(float(m_amount), apply);
target->ApplyAttackTimePercentMod(BASE_ATTACK, float(GetAmount()), apply);
target->ApplyAttackTimePercentMod(OFF_ATTACK, float(GetAmount()), apply);
@@ -4119,7 +4151,15 @@ void AuraEffect::HandleModMeleeSpeedPct(AuraApplication const* aurApp, uint8 mod
return;
Unit* target = aurApp->GetTarget();
+ int32 spellGroupVal = target->GetHighestExclusiveSameEffectSpellGroupValue(this, SPELL_AURA_MOD_MELEE_HASTE);
+ if (abs(spellGroupVal) >= abs(GetAmount()))
+ return;
+ if (spellGroupVal)
+ {
+ target->ApplyAttackTimePercentMod(BASE_ATTACK, (float)GetAmount(), !apply);
+ target->ApplyAttackTimePercentMod(OFF_ATTACK, (float)GetAmount(), !apply);
+ }
target->ApplyAttackTimePercentMod(BASE_ATTACK, float(GetAmount()), apply);
target->ApplyAttackTimePercentMod(OFF_ATTACK, float(GetAmount()), apply);
}
@@ -4356,7 +4396,8 @@ void AuraEffect::HandleModDamagePercentDone(AuraApplication const* aurApp, uint8
return;
Unit* target = aurApp->GetTarget();
- if (!target)
+ int32 spellGroupVal = target->GetHighestExclusiveSameEffectSpellGroupValue(this, SPELL_AURA_MOD_DAMAGE_PERCENT_DONE);
+ if (abs(spellGroupVal) >= abs(GetAmount()))
return;
if (target->GetTypeId() == TYPEID_PLAYER)
@@ -4368,12 +4409,23 @@ void AuraEffect::HandleModDamagePercentDone(AuraApplication const* aurApp, uint8
if ((GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL) && (GetSpellInfo()->EquippedItemClass == -1 || target->GetTypeId() != TYPEID_PLAYER))
{
+ if (spellGroupVal)
+ {
+ target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, float(spellGroupVal), !apply);
+ target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(spellGroupVal), !apply);
+ target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_PCT, float(spellGroupVal), !apply);
+ }
target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, float(GetAmount()), apply);
target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(GetAmount()), apply);
target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_PCT, float(GetAmount()), apply);
- if (target->GetTypeId() == TYPEID_PLAYER)
- target->ToPlayer()->ApplyPercentModFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT, float (GetAmount()), apply);
+ if (Player* player = target->ToPlayer())
+ {
+ if (spellGroupVal)
+ player->ApplyPercentModFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT, float(spellGroupVal), !apply);
+
+ player->ApplyPercentModFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT, float(GetAmount()), apply);
+ }
}
else
{
diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp
index b94d0def3dd..6f56c0ebc40 100644
--- a/src/server/game/Spells/SpellMgr.cpp
+++ b/src/server/game/Spells/SpellMgr.cpp
@@ -765,6 +765,15 @@ SpellGroupStackRule SpellMgr::CheckSpellGroupStackRules(SpellInfo const* spellIn
return rule;
}
+SpellGroupStackRule SpellMgr::GetSpellGroupStackRule(SpellGroup group) const
+{
+ SpellGroupStackMap::const_iterator itr = mSpellGroupStack.find(group);
+ if (itr != mSpellGroupStack.end())
+ return itr->second;
+
+ return SPELL_GROUP_STACK_RULE_DEFAULT;
+}
+
SpellProcEventEntry const* SpellMgr::GetSpellProcEvent(uint32 spellId) const
{
SpellProcEventMap::const_iterator itr = mSpellProcEventMap.find(spellId);
diff --git a/src/server/game/Spells/SpellMgr.h b/src/server/game/Spells/SpellMgr.h
index 7b54aca3759..9108618176f 100644
--- a/src/server/game/Spells/SpellMgr.h
+++ b/src/server/game/Spells/SpellMgr.h
@@ -655,6 +655,7 @@ class SpellMgr
// Spell Group Stack Rules table
bool AddSameEffectStackRuleSpellGroups(SpellInfo const* spellInfo, int32 amount, std::map<SpellGroup, int32>& groups) const;
SpellGroupStackRule CheckSpellGroupStackRules(SpellInfo const* spellInfo1, SpellInfo const* spellInfo2) const;
+ SpellGroupStackRule GetSpellGroupStackRule(SpellGroup groupid) const;
// Spell proc event table
SpellProcEventEntry const* GetSpellProcEvent(uint32 spellId) const;