Core/Players: PCT spell mods are now additive as well (this got changed in 6.x)

This commit is contained in:
Ovahlord
2020-10-22 17:03:59 +02:00
parent 561cb13ceb
commit a311740d3b
3 changed files with 44 additions and 65 deletions

View File

@@ -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));

View File

@@ -95,9 +95,8 @@ typedef std::deque<Mail*> 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<Player>
uint32 m_baseHealthRegen;
int32 m_spellPenetrationItemMod;
SpellModContainer m_spellMods[MAX_SPELLMOD][SPELLMOD_END];
SpellModContainer m_spellMods[MAX_SPELLMOD];
EnchantDurationList m_enchantDuration;
ItemDurationList m_itemDuration;

View File

@@ -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;
}