aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/server/game/Entities/Player/Player.cpp147
-rw-r--r--src/server/game/Entities/Player/Player.h42
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.cpp2
3 files changed, 108 insertions, 83 deletions
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index dbe61592ec1..e03e856e156 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -21199,13 +21199,25 @@ void Player::AddSpellMod(SpellModifier* mod, bool apply)
{
WorldPackets::Spells::SpellModifierData modData;
- for (SpellModList::iterator itr = m_spellMods[mod->op].begin(); itr != m_spellMods[mod->op].end(); ++itr)
- if ((*itr)->type == mod->type && (*itr)->mask & _mask)
- modData.ModifierValue += (*itr)->value;
+ if (mod->type == SPELLMOD_FLAT)
+ {
+ for (SpellModList::iterator itr = m_spellMods[mod->op][SPELLMOD_FLAT].begin(); itr != m_spellMods[mod->op][SPELLMOD_FLAT].end(); ++itr)
+ if (*itr != mod && (*itr)->mask & _mask)
+ modData.ModifierValue += (*itr)->value;
+
+ if (apply)
+ modData.ModifierValue += mod->value;
+ }
+ else
+ {
+ modData.ModifierValue = 1.0f;
+ for (SpellModList::iterator itr = m_spellMods[mod->op][SPELLMOD_PCT].begin(); itr != m_spellMods[mod->op][SPELLMOD_PCT].end(); ++itr)
+ if (*itr != mod && (*itr)->mask & _mask)
+ modData.ModifierValue *= CalculatePct(1.0f, (*itr)->value);
- modData.ModifierValue += apply ? mod->value : -(mod->value);
- if (mod->type == SPELLMOD_PCT)
- modData.ModifierValue = 1.0f + (modData.ModifierValue * 0.01f);
+ if (apply)
+ modData.ModifierValue *= CalculatePct(1.0f, mod->value);
+ }
modData.ClassIndex = eff;
@@ -21217,10 +21229,10 @@ void Player::AddSpellMod(SpellModifier* mod, bool apply)
}
if (apply)
- m_spellMods[mod->op].push_back(mod);
+ m_spellMods[mod->op][mod->type].push_back(mod);
else
{
- m_spellMods[mod->op].remove(mod);
+ m_spellMods[mod->op][mod->type].remove(mod);
// mods bound to aura will be removed in AuraEffect::~AuraEffect
if (!mod->ownerAura)
delete mod;
@@ -21237,49 +21249,52 @@ void Player::RestoreSpellMods(Spell* spell, uint32 ownerAuraId, Aura* aura)
for (uint8 i=0; i<MAX_SPELLMOD; ++i)
{
- for (SpellModList::iterator itr = m_spellMods[i].begin(); itr != m_spellMods[i].end(); ++itr)
+ for (uint8 j = 0; j < SPELLMOD_END; ++j)
{
- SpellModifier* mod = *itr;
+ for (SpellModList::iterator itr = m_spellMods[i][j].begin(); itr != m_spellMods[i][j].end(); ++itr)
+ {
+ SpellModifier* mod = *itr;
- // Spellmods without aura set cannot be charged
- if (!mod->ownerAura || !mod->ownerAura->IsUsingCharges())
- continue;
+ // Spellmods without aura set cannot be charged
+ if (!mod->ownerAura || !mod->ownerAura->IsUsingCharges())
+ continue;
- // Restore only specific owner aura mods
- if (ownerAuraId && (ownerAuraId != mod->ownerAura->GetSpellInfo()->Id))
- continue;
+ // Restore only specific owner aura mods
+ if (ownerAuraId && (ownerAuraId != mod->ownerAura->GetSpellInfo()->Id))
+ continue;
- if (aura && mod->ownerAura != aura)
- continue;
+ if (aura && mod->ownerAura != aura)
+ continue;
- // Check if mod affected this spell
- // First, check if the mod aura applied at least one spellmod to this spell
- Spell::UsedSpellMods::iterator iterMod = spell->m_appliedMods.find(mod->ownerAura);
- if (iterMod == spell->m_appliedMods.end())
- continue;
- // Second, check if the current mod is one of those applied by the mod aura
- if (!(mod->mask & spell->m_spellInfo->SpellFamilyFlags))
- continue;
+ // Check if mod affected this spell
+ // First, check if the mod aura applied at least one spellmod to this spell
+ Spell::UsedSpellMods::iterator iterMod = spell->m_appliedMods.find(mod->ownerAura);
+ if (iterMod == spell->m_appliedMods.end())
+ continue;
+ // Second, check if the current mod is one of those applied by the mod aura
+ if (!(mod->mask & spell->m_spellInfo->SpellFamilyFlags))
+ continue;
- // remove from list - This will be done after all mods have been gone through
- // to ensure we iterate over all mods of an aura before removing said aura
- // from applied mods (Else, an aura with two mods on the current spell would
- // only see the first of its modifier restored)
- aurasQueue.push_back(mod->ownerAura);
+ // remove from list - This will be done after all mods have been gone through
+ // to ensure we iterate over all mods of an aura before removing said aura
+ // from applied mods (Else, an aura with two mods on the current spell would
+ // only see the first of its modifier restored)
+ aurasQueue.push_back(mod->ownerAura);
- // add mod charges back to mod
- if (mod->charges == -1)
- mod->charges = 1;
- else
- mod->charges++;
+ // add mod charges back to mod
+ if (mod->charges == -1)
+ mod->charges = 1;
+ else
+ mod->charges++;
- // Do not set more spellmods than available
- if (mod->ownerAura->GetCharges() < mod->charges)
- mod->charges = mod->ownerAura->GetCharges();
+ // Do not set more spellmods than available
+ if (mod->ownerAura->GetCharges() < mod->charges)
+ mod->charges = mod->ownerAura->GetCharges();
- // Skip this check for now - aura charges may change due to various reason
- /// @todo track these changes correctly
- //ASSERT (mod->ownerAura->GetCharges() <= mod->charges);
+ // Skip this check for now - aura charges may change due to various reason
+ /// @todo track these changes correctly
+ //ASSERT (mod->ownerAura->GetCharges() <= mod->charges);
+ }
}
}
@@ -21306,27 +21321,30 @@ void Player::RemoveSpellMods(Spell* spell)
if (spell->m_appliedMods.empty())
return;
- for (uint8 i=0; i<MAX_SPELLMOD; ++i)
+ for (uint8 i = 0; i < MAX_SPELLMOD; ++i)
{
- for (SpellModList::const_iterator itr = m_spellMods[i].begin(); itr != m_spellMods[i].end();)
+ for (uint8 j = 0; j < SPELLMOD_END; ++j)
{
- SpellModifier* mod = *itr;
- ++itr;
+ for (SpellModList::const_iterator itr = m_spellMods[i][j].begin(); itr != m_spellMods[i][j].end();)
+ {
+ SpellModifier* mod = *itr;
+ ++itr;
- // spellmods without aura set cannot be charged
- if (!mod->ownerAura || !mod->ownerAura->IsUsingCharges())
- continue;
+ // spellmods without aura set cannot be charged
+ if (!mod->ownerAura || !mod->ownerAura->IsUsingCharges())
+ continue;
- // check if mod affected this spell
- Spell::UsedSpellMods::iterator iterMod = spell->m_appliedMods.find(mod->ownerAura);
- if (iterMod == spell->m_appliedMods.end())
- 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);
+ // remove from list
+ spell->m_appliedMods.erase(iterMod);
- if (mod->ownerAura->DropCharge(AURA_REMOVE_BY_EXPIRE))
- itr = m_spellMods[i].begin();
+ if (mod->ownerAura->DropCharge(AURA_REMOVE_BY_EXPIRE))
+ itr = m_spellMods[i][j].begin();
+ }
}
}
}
@@ -21379,16 +21397,13 @@ void Player::SendSpellModifiers() const
pctMod.ModifierData[j].ClassIndex = j;
pctMod.ModifierData[j].ModifierValue = 1.0f;
- for (SpellModifier* mod : m_spellMods[i])
- {
+ for (SpellModifier* mod : m_spellMods[i][SPELLMOD_FLAT])
if (mod->mask & mask)
- {
- if (mod->type == SPELLMOD_FLAT)
- flatMod.ModifierData[j].ModifierValue += mod->value;
- else
- pctMod.ModifierData[j].ModifierValue *= 1.0f + (mod->value * 0.01f);
- }
- }
+ flatMod.ModifierData[j].ModifierValue += mod->value;
+
+ for (SpellModifier* mod : m_spellMods[i][SPELLMOD_PCT])
+ if (mod->mask & mask)
+ pctMod.ModifierData[j].ModifierValue *= 1.0f + CalculatePct(1.0f, mod->value);
}
flatMod.ModifierData.erase(std::remove_if(flatMod.ModifierData.begin(), flatMod.ModifierData.end(), [](WorldPackets::Spells::SpellModifierData const& mod)
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index c33ec0d2d4d..3c2248058b5 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -74,8 +74,9 @@ enum SkillFieldOffset
// Note: SPELLMOD_* values is aura types in fact
enum SpellModType
{
- SPELLMOD_FLAT = 107, // SPELL_AURA_ADD_FLAT_MODIFIER
- SPELLMOD_PCT = 108 // SPELL_AURA_ADD_PCT_MODIFIER
+ SPELLMOD_FLAT = 0, // SPELL_AURA_ADD_FLAT_MODIFIER
+ SPELLMOD_PCT = 1, // SPELL_AURA_ADD_PCT_MODIFIER
+ SPELLMOD_END
};
// 2^n values, Player::m_isunderwater is a bitmask. These are Trinity internal values, they are never send to any client
@@ -2681,7 +2682,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
uint32 m_baseHealthRegen;
int32 m_spellPenetrationItemMod;
- SpellModList m_spellMods[MAX_SPELLMOD];
+ SpellModList m_spellMods[MAX_SPELLMOD][SPELLMOD_END];
EnchantDurationList m_enchantDuration;
ItemDurationList m_itemDuration;
@@ -2864,7 +2865,7 @@ void Player::ApplySpellMod(uint32 spellId, SpellModOp op, T& basevalue, Spell* s
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][SPELLMOD_FLAT].begin(); itr != m_spellMods[op][SPELLMOD_FLAT].end(); ++itr)
{
SpellModifier* mod = *itr;
@@ -2875,21 +2876,30 @@ void Player::ApplySpellMod(uint32 spellId, SpellModOp op, T& basevalue, Spell* s
if (!IsAffectedBySpellmod(spellInfo, mod, spell))
continue;
- if (mod->type == SPELLMOD_FLAT)
- totalflat += mod->value;
- else if (mod->type == SPELLMOD_PCT)
- {
- // skip percent mods for null basevalue (most important for spell mods with charges)
- if (basevalue == T(0))
- continue;
+ totalflat += mod->value;
+ DropModCharge(mod, spell);
+ }
- // special case (skip > 10sec spell casts for instant cast setting)
- if (mod->op == SPELLMOD_CASTING_TIME && basevalue >= T(10000) && mod->value <= -100)
- continue;
+ for (SpellModList::iterator itr = m_spellMods[op][SPELLMOD_PCT].begin(); itr != m_spellMods[op][SPELLMOD_PCT].end(); ++itr)
+ {
+ SpellModifier* mod = *itr;
- totalmul += CalculatePct(1.0f, mod->value);
- }
+ // Charges can be set only for mods with auras
+ if (!mod->ownerAura)
+ ASSERT(mod->charges == 0);
+
+ if (!IsAffectedBySpellmod(spellInfo, mod, spell))
+ continue;
+
+ // skip percent mods for null basevalue (most important for spell mods with charges)
+ if (basevalue + totalflat == T(0))
+ continue;
+
+ // special case (skip > 10sec spell casts for instant cast setting)
+ if (mod->op == SPELLMOD_CASTING_TIME && basevalue >= T(10000) && mod->value <= -100)
+ continue;
+ totalmul *= 1.0f + CalculatePct(1.0f, mod->value);
DropModCharge(mod, spell);
}
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
index 96bf92a5cf8..395b732f6a7 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
@@ -809,7 +809,7 @@ void AuraEffect::CalculateSpellMod()
m_spellmod = new SpellModifier(GetBase());
m_spellmod->op = SpellModOp(GetMiscValue());
- m_spellmod->type = SpellModType(uint32(GetAuraType())); // SpellModType value == spell aura types
+ m_spellmod->type = GetAuraType() == SPELL_AURA_ADD_PCT_MODIFIER ? SPELLMOD_PCT : SPELLMOD_FLAT;
m_spellmod->spellId = GetId();
m_spellmod->mask = GetSpellEffectInfo()->SpellClassMask;
m_spellmod->charges = GetBase()->GetCharges();