diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 59a739b9bd8..a08b6487474 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -21323,12 +21323,12 @@ void Player::ApplySpellMod(uint32 spellId, SpellModOp op, T& basevalue, Spell* s case SPELLMOD_CASTING_TIME: { SpellModifier* modInstantSpell = nullptr; - for (SpellModifier* mod : m_spellMods[op][SPELLMOD_PCT]) + for (SpellModifier* mod : m_spellMods[op]) { if (!IsAffectedBySpellmod(spellInfo, mod, spell)) continue; - if (basevalue < T(10000) && mod->value <= -100) + if (mod->type == SPELLMOD_PCT && basevalue < T(10000) && mod->value <= -100) { modInstantSpell = mod; break; @@ -21347,12 +21347,12 @@ void Player::ApplySpellMod(uint32 spellId, SpellModOp op, T& basevalue, Spell* s case SPELLMOD_CRITICAL_CHANCE: { SpellModifier* modCritical = nullptr; - for (SpellModifier* mod : m_spellMods[op][SPELLMOD_FLAT]) + for (SpellModifier* mod : m_spellMods[op]) { if (!IsAffectedBySpellmod(spellInfo, mod, spell)) continue; - if (mod->value >= 100) + if (mod->type == SPELLMOD_FLAT && mod->value >= 100) { modCritical = mod; break; @@ -21371,35 +21371,44 @@ void Player::ApplySpellMod(uint32 spellId, SpellModOp op, T& basevalue, Spell* s break; } - for (SpellModifier* mod : m_spellMods[op][SPELLMOD_FLAT]) + for (SpellModifier* mod : m_spellMods[op]) { if (!IsAffectedBySpellmod(spellInfo, mod, spell)) continue; - totalflat += mod->value; - Player::ApplyModToSpell(mod, spell); - } - - for (SpellModifier* mod : m_spellMods[op][SPELLMOD_PCT]) - { - 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 (op == SPELLMOD_CASTING_TIME) + switch (mod->type) { - if (basevalue >= T(10000) && mod->value <= -100) - continue; + case SPELLMOD_FLAT: + totalflat += mod->value; + break; + case SPELLMOD_PCT: + { + // skip percent mods with null basevalue (most important for spell mods with charges) + if (basevalue == T(0)) + continue; + + // special case (skip > 10sec spell casts for instant cast setting) + if (op == SPELLMOD_CASTING_TIME && mod->value <= -100 && basevalue >= T(10000)) + continue; + else if (!Player::HasSpellModApplied(mod, spell)) + { + // special case for Surge of Light, don't apply critical chance reduction if other mods not applied (ie procs while casting another spell) + // (Surge of Light is the only PCT_MOD on critical chance) + if (op == SPELLMOD_CRITICAL_CHANCE) + continue; + // special case for Backdraft, dont' apply GCD reduction if cast time reduction wasn't applied (ie when Backlash is consumed first) + // (Backdraft is the only PCT_MOD on global cooldown) + else if (op == SPELLMOD_GLOBAL_COOLDOWN) + continue; + } + + totalmul += CalculatePct(1.0f, mod->value); + break; + } } - totalmul *= 1.0f + CalculatePct(1.0f, mod->value); Player::ApplyModToSpell(mod, spell); } - basevalue = T(float(basevalue + totalflat) * totalmul); } @@ -21413,9 +21422,9 @@ void Player::AddSpellMod(SpellModifier* mod, bool apply) /// First, manipulate our spellmodifier container if (apply) - m_spellMods[mod->op][mod->type].insert(mod); + m_spellMods[mod->op].insert(mod); else - m_spellMods[mod->op][mod->type].erase(mod); + m_spellMods[mod->op].erase(mod); /// Now, send spellmodifier packet if (!IsLoading()) @@ -21438,27 +21447,9 @@ void Player::AddSpellMod(SpellModifier* mod, bool apply) { WorldPackets::Spells::SpellModifierData modData; - if (mod->type == SPELLMOD_FLAT) - { - modData.ModifierValue = 0.0f; - for (SpellModifier* spellMod : m_spellMods[mod->op][SPELLMOD_FLAT]) - if (spellMod->mask & mask) - modData.ModifierValue += spellMod->value; - } - else - { - modData.ModifierValue = 0.0f; - for (SpellModifier* spellMod : m_spellMods[mod->op][SPELLMOD_PCT]) - { - if (spellMod->mask & mask) - { - if (modData.ModifierValue > 0.f) - AddPct(modData.ModifierValue, spellMod->value); - else - modData.ModifierValue += spellMod->value; - } - } - } + for (SpellModifier* spellMod : m_spellMods[mod->op]) + if (spellMod->mask & mask) + modData.ModifierValue += spellMod->value; modData.ClassIndex = eff; @@ -21523,20 +21514,9 @@ void Player::SendSpellModifiers() const pctMod.ModifierData[j].ClassIndex = j; pctMod.ModifierData[j].ModifierValue = 0.0f; - for (SpellModifier* mod : m_spellMods[i][SPELLMOD_FLAT]) + for (SpellModifier* mod : m_spellMods[i]) if (mod->mask & mask) flatMod.ModifierData[j].ModifierValue += mod->value; - - for (SpellModifier* mod : m_spellMods[i][SPELLMOD_PCT]) - { - if (mod->mask & mask) - { - if (flatMod.ModifierData[j].ModifierValue > 0.f) - AddPct(flatMod.ModifierData[j].ModifierValue, mod->value); - else - flatMod.ModifierData[j].ModifierValue += mod->value; - } - } } flatMod.ModifierData.erase(std::remove_if(flatMod.ModifierData.begin(), flatMod.ModifierData.end(), [](WorldPackets::Spells::SpellModifierData const& mod) @@ -21546,7 +21526,7 @@ void Player::SendSpellModifiers() const pctMod.ModifierData.erase(std::remove_if(pctMod.ModifierData.begin(), pctMod.ModifierData.end(), [](WorldPackets::Spells::SpellModifierData const& mod) { - return G3D::fuzzyEq(mod.ModifierValue, 1.0f); + return G3D::fuzzyEq(mod.ModifierValue, 0.0f); }), pctMod.ModifierData.end()); flatMods.Modifiers.emplace_back(std::move(flatMod)); diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index ab7058b89ad..495ad9e5d35 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -95,9 +95,8 @@ typedef std::deque PlayerMails; // Note: SPELLMOD_* values is aura types in fact enum SpellModType : uint8 { - SPELLMOD_FLAT = 0, // SPELL_AURA_ADD_FLAT_MODIFIER - SPELLMOD_PCT = 1, // SPELL_AURA_ADD_PCT_MODIFIER - SPELLMOD_END + SPELLMOD_FLAT = SPELL_AURA_ADD_FLAT_MODIFIER, + SPELLMOD_PCT = SPELL_AURA_ADD_PCT_MODIFIER }; // 2^n values, Player::m_isunderwater is a bitmask. These are Trinity internal values, they are never send to any client @@ -2603,7 +2602,7 @@ class TC_GAME_API Player : public Unit, public GridObject uint32 m_baseHealthRegen; int32 m_spellPenetrationItemMod; - SpellModContainer m_spellMods[MAX_SPELLMOD][SPELLMOD_END]; + SpellModContainer m_spellMods[MAX_SPELLMOD]; EnchantDurationList m_enchantDuration; ItemDurationList m_itemDuration; diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index ddc69a64f12..0f98e55a190 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -693,7 +693,7 @@ void AuraEffect::CalculateSpellMod() m_spellmod = new SpellModifier(GetBase()); m_spellmod->op = SpellModOp(GetMiscValue()); - m_spellmod->type = GetAuraType() == SPELL_AURA_ADD_PCT_MODIFIER ? SPELLMOD_PCT : SPELLMOD_FLAT; + m_spellmod->type = SpellModType(uint32(GetAuraType())); // SpellModType value == spell aura types m_spellmod->spellId = GetId(); m_spellmod->mask = GetSpellInfo()->Effects[GetEffIndex()].SpellClassMask; }