diff options
| author | Shauren <shauren.trinity@gmail.com> | 2021-10-16 22:05:02 +0200 |
|---|---|---|
| committer | Shauren <shauren.trinity@gmail.com> | 2021-10-16 22:05:02 +0200 |
| commit | ba4fa060d765a35507f1a73287504c3f2e440fdb (patch) | |
| tree | e166fc1f4de33ddb87243482d159077cda2879d8 /src | |
| parent | 3e81db7b9380269d4561eb5deb21fbef26913779 (diff) | |
Core/Auras: Implemented SPELL_AURA_ADD_PCT_MODIFIER_BY_SPELL_LABEL and SPELL_AURA_ADD_FLAT_MODIFIER_BY_SPELL_LABEL
Diffstat (limited to 'src')
| -rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 181 | ||||
| -rw-r--r-- | src/server/game/Entities/Player/Player.h | 27 | ||||
| -rw-r--r-- | src/server/game/Spells/Auras/SpellAuraDefines.h | 4 | ||||
| -rw-r--r-- | src/server/game/Spells/Auras/SpellAuraEffects.cpp | 45 | ||||
| -rw-r--r-- | src/server/game/Spells/SpellInfo.cpp | 19 | ||||
| -rw-r--r-- | src/server/game/Spells/SpellMgr.cpp | 3 | ||||
| -rw-r--r-- | src/server/scripts/Spells/spell_druid.cpp | 13 |
7 files changed, 225 insertions, 67 deletions
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 61d463ed7e0..9d1c63086fb 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -22283,7 +22283,7 @@ void Player::SendRemoveControlBar() const SendDirectMessage(packet.Write()); } -bool Player::IsAffectedBySpellmod(SpellInfo const* spellInfo, SpellModifier* mod, Spell* spell) +bool Player::IsAffectedBySpellmod(SpellInfo const* spellInfo, SpellModifier const* mod, Spell* spell) { if (!mod || !spellInfo) return false; @@ -22326,13 +22326,28 @@ void Player::GetSpellModValues(SpellInfo const* spellInfo, SpellModOp op, Spell* if (!IsAffectedBySpellmod(spellInfo, mod, spell)) continue; - if (base < T(10000) && mod->value <= -100) + if (base < T(10000) && static_cast<SpellModifierByClassMask*>(mod)->value <= -100) { modInstantSpell = mod; break; } } + if (!modInstantSpell) + { + for (SpellModifier* mod : m_spellMods[AsUnderlyingType(op)][SPELLMOD_LABEL_PCT]) + { + if (!IsAffectedBySpellmod(spellInfo, mod, spell)) + continue; + + if (base < T(10000) && static_cast<SpellPctModifierByLabel*>(mod)->value.ModifierValue <= -1.0f) + { + modInstantSpell = mod; + break; + } + } + } + if (modInstantSpell) { Player::ApplyModToSpell(modInstantSpell, spell); @@ -22350,13 +22365,28 @@ void Player::GetSpellModValues(SpellInfo const* spellInfo, SpellModOp op, Spell* if (!IsAffectedBySpellmod(spellInfo, mod, spell)) continue; - if (mod->value >= 100) + if (static_cast<SpellModifierByClassMask*>(mod)->value >= 100) { modCritical = mod; break; } } + if (!modCritical) + { + for (SpellModifier* mod : m_spellMods[AsUnderlyingType(op)][SPELLMOD_LABEL_FLAT]) + { + if (!IsAffectedBySpellmod(spellInfo, mod, spell)) + continue; + + if (static_cast<SpellFlatModifierByLabel*>(mod)->value.ModifierValue >= 100) + { + modCritical = mod; + break; + } + } + } + if (modCritical) { Player::ApplyModToSpell(modCritical, spell); @@ -22374,7 +22404,16 @@ void Player::GetSpellModValues(SpellInfo const* spellInfo, SpellModOp op, Spell* if (!IsAffectedBySpellmod(spellInfo, mod, spell)) continue; - *flat += mod->value; + *flat += static_cast<SpellModifierByClassMask*>(mod)->value; + Player::ApplyModToSpell(mod, spell); + } + + for (SpellModifier* mod : m_spellMods[AsUnderlyingType(op)][SPELLMOD_LABEL_FLAT]) + { + if (!IsAffectedBySpellmod(spellInfo, mod, spell)) + continue; + + *flat += static_cast<SpellFlatModifierByLabel*>(mod)->value.ModifierValue; Player::ApplyModToSpell(mod, spell); } @@ -22390,11 +22429,31 @@ void Player::GetSpellModValues(SpellInfo const* spellInfo, SpellModOp op, Spell* // special case (skip > 10sec spell casts for instant cast setting) if (op == SpellModOp::ChangeCastTime) { - if (base >= T(10000) && mod->value <= -100) + if (base >= T(10000) && static_cast<SpellModifierByClassMask*>(mod)->value <= -100) continue; } - *pct *= 1.0f + CalculatePct(1.0f, mod->value); + *pct *= 1.0f + CalculatePct(1.0f, static_cast<SpellModifierByClassMask*>(mod)->value); + Player::ApplyModToSpell(mod, spell); + } + + for (SpellModifier* mod : m_spellMods[AsUnderlyingType(op)][SPELLMOD_LABEL_PCT]) + { + if (!IsAffectedBySpellmod(spellInfo, mod, spell)) + continue; + + // skip percent mods for null basevalue (most important for spell mods with charges) + if (base + *flat == T(0)) + continue; + + // special case (skip > 10sec spell casts for instant cast setting) + if (op == SpellModOp::ChangeCastTime) + { + if (base >= T(10000) && static_cast<SpellPctModifierByLabel*>(mod)->value.ModifierValue <= -1.0f) + continue; + } + + *pct *= static_cast<SpellPctModifierByLabel*>(mod)->value.ModifierValue; Player::ApplyModToSpell(mod, spell); } } @@ -22429,48 +22488,84 @@ void Player::AddSpellMod(SpellModifier* mod, bool apply) m_spellMods[AsUnderlyingType(mod->op)][mod->type].erase(mod); /// Now, send spellmodifier packet - if (!IsLoading()) + switch (mod->type) { - OpcodeServer opcode = (mod->type == SPELLMOD_FLAT) ? SMSG_SET_FLAT_SPELL_MODIFIER : SMSG_SET_PCT_SPELL_MODIFIER; + case SPELLMOD_FLAT: + case SPELLMOD_PCT: + if (!IsLoading()) + { + OpcodeServer opcode = (mod->type == SPELLMOD_FLAT) ? SMSG_SET_FLAT_SPELL_MODIFIER : SMSG_SET_PCT_SPELL_MODIFIER; - WorldPackets::Spells::SetSpellModifier packet(opcode); + WorldPackets::Spells::SetSpellModifier packet(opcode); - /// @todo Implement sending of bulk modifiers instead of single - packet.Modifiers.resize(1); - WorldPackets::Spells::SpellModifier& spellMod = packet.Modifiers[0]; + /// @todo Implement sending of bulk modifiers instead of single + packet.Modifiers.resize(1); + WorldPackets::Spells::SpellModifier& spellMod = packet.Modifiers[0]; - spellMod.ModIndex = AsUnderlyingType(mod->op); + spellMod.ModIndex = AsUnderlyingType(mod->op); - for (int eff = 0; eff < 128; ++eff) - { - flag128 mask; - mask[eff / 32] = 1u << (eff % 32); - if (mod->mask & mask) - { - WorldPackets::Spells::SpellModifierData modData; - - if (mod->type == SPELLMOD_FLAT) + for (int eff = 0; eff < 128; ++eff) { - modData.ModifierValue = 0.0f; - for (SpellModifier* spellMod : m_spellMods[AsUnderlyingType(mod->op)][SPELLMOD_FLAT]) - if (spellMod->mask & mask) - modData.ModifierValue += spellMod->value; - } - else - { - modData.ModifierValue = 1.0f; - for (SpellModifier* spellMod : m_spellMods[AsUnderlyingType(mod->op)][SPELLMOD_PCT]) - if (spellMod->mask & mask) - modData.ModifierValue *= 1.0f + CalculatePct(1.0f, spellMod->value); - } + flag128 mask; + mask[eff / 32] = 1u << (eff % 32); + if (static_cast<SpellModifierByClassMask const*>(mod)->mask & mask) + { + WorldPackets::Spells::SpellModifierData modData; - modData.ClassIndex = eff; + if (mod->type == SPELLMOD_FLAT) + { + modData.ModifierValue = 0.0f; + for (SpellModifier* spellMod : m_spellMods[AsUnderlyingType(mod->op)][SPELLMOD_FLAT]) + if (static_cast<SpellModifierByClassMask const*>(spellMod)->mask & mask) + modData.ModifierValue += static_cast<SpellModifierByClassMask const*>(spellMod)->value; + } + else + { + modData.ModifierValue = 1.0f; + for (SpellModifier* spellMod : m_spellMods[AsUnderlyingType(mod->op)][SPELLMOD_PCT]) + if (static_cast<SpellModifierByClassMask const*>(spellMod)->mask & mask) + modData.ModifierValue *= 1.0f + CalculatePct(1.0f, static_cast<SpellModifierByClassMask const*>(spellMod)->value); + } - spellMod.ModifierData.push_back(modData); - } - } + modData.ClassIndex = eff; - SendDirectMessage(packet.Write()); + spellMod.ModifierData.push_back(modData); + } + } + + SendDirectMessage(packet.Write()); + } + break; + case SPELLMOD_LABEL_FLAT: + if (apply) + { + AddDynamicUpdateFieldValue(m_values.ModifyValue(&Player::m_activePlayerData) + .ModifyValue(&UF::ActivePlayerData::SpellFlatModByLabel)) = static_cast<SpellFlatModifierByLabel const*>(mod)->value; + } + else + { + int32 firstIndex = m_activePlayerData->SpellFlatModByLabel.FindIndex(static_cast<SpellFlatModifierByLabel const*>(mod)->value); + if (firstIndex >= 0) + RemoveDynamicUpdateFieldValue(m_values.ModifyValue(&Player::m_activePlayerData) + .ModifyValue(&UF::ActivePlayerData::SpellFlatModByLabel), firstIndex); + } + break; + case SPELLMOD_LABEL_PCT: + if (apply) + { + AddDynamicUpdateFieldValue(m_values.ModifyValue(&Player::m_activePlayerData) + .ModifyValue(&UF::ActivePlayerData::SpellPctModByLabel)) = static_cast<SpellPctModifierByLabel const*>(mod)->value; + } + else + { + int32 firstIndex = m_activePlayerData->SpellPctModByLabel.FindIndex(static_cast<SpellPctModifierByLabel const*>(mod)->value); + if (firstIndex >= 0) + RemoveDynamicUpdateFieldValue(m_values.ModifyValue(&Player::m_activePlayerData) + .ModifyValue(&UF::ActivePlayerData::SpellPctModByLabel), firstIndex); + } + break; + default: + break; } } @@ -22520,12 +22615,12 @@ void Player::SendSpellModifiers() const pctMod.ModifierData[j].ModifierValue = 1.0f; for (SpellModifier* mod : m_spellMods[i][SPELLMOD_FLAT]) - if (mod->mask & mask) - flatMod.ModifierData[j].ModifierValue += mod->value; + if (static_cast<SpellModifierByClassMask const*>(mod)->mask & mask) + flatMod.ModifierData[j].ModifierValue += static_cast<SpellModifierByClassMask const*>(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); + if (static_cast<SpellModifierByClassMask const*>(mod)->mask & mask) + pctMod.ModifierData[j].ModifierValue *= 1.0f + CalculatePct(1.0f, static_cast<SpellModifierByClassMask const*>(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 f35b5430973..131ea5b775c 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -147,6 +147,8 @@ enum SpellModType : uint8 { SPELLMOD_FLAT = 0, // SPELL_AURA_ADD_FLAT_MODIFIER SPELLMOD_PCT = 1, // SPELL_AURA_ADD_PCT_MODIFIER + SPELLMOD_LABEL_FLAT = 2, // SPELL_AURA_ADD_FLAT_MODIFIER_BY_SPELL_LABEL + SPELLMOD_LABEL_PCT = 3, // SPELL_AURA_ADD_PCT_MODIFIER_BY_SPELL_LABEL SPELLMOD_END }; @@ -250,17 +252,34 @@ enum SpecResetType // Spell modifier (used for modify other spells) struct SpellModifier { - SpellModifier(Aura* _ownerAura) : op(SpellModOp::HealingAndDamage), type(SPELLMOD_FLAT), value(0), mask(), spellId(0), ownerAura(_ownerAura) { } + SpellModifier(Aura* _ownerAura) : op(SpellModOp::HealingAndDamage), type(SPELLMOD_FLAT), spellId(0), ownerAura(_ownerAura) { } SpellModOp op; SpellModType type; - int32 value; - flag128 mask; uint32 spellId; Aura* const ownerAura; }; +struct SpellModifierByClassMask : SpellModifier +{ + SpellModifierByClassMask(Aura* _ownerAura) : SpellModifier(_ownerAura), value(0), mask() { } + + int32 value; + flag128 mask; +}; + +template<typename T> +struct SpellModifierByLabel : SpellModifier +{ + SpellModifierByLabel(Aura* _ownerAura) : SpellModifier(_ownerAura) { } + + T value; +}; + +using SpellFlatModifierByLabel = SpellModifierByLabel<UF::SpellFlatModByLabel>; +using SpellPctModifierByLabel = SpellModifierByLabel<UF::SpellPctModByLabel>; + enum PlayerCurrencyState { PLAYERCURRENCY_UNCHANGED = 0, @@ -1804,7 +1823,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player> PlayerSpellMap & GetSpellMap() { return m_spells; } void AddSpellMod(SpellModifier* mod, bool apply); - static bool IsAffectedBySpellmod(SpellInfo const* spellInfo, SpellModifier* mod, Spell* spell = nullptr); + static bool IsAffectedBySpellmod(SpellInfo const* spellInfo, SpellModifier const* mod, Spell* spell = nullptr); template <class T> void GetSpellModValues(SpellInfo const* spellInfo, SpellModOp op, Spell* spell, T base, int32* flat, float* pct) const; template <class T> diff --git a/src/server/game/Spells/Auras/SpellAuraDefines.h b/src/server/game/Spells/Auras/SpellAuraDefines.h index 2287a1f772f..d81015afa44 100644 --- a/src/server/game/Spells/Auras/SpellAuraDefines.h +++ b/src/server/game/Spells/Auras/SpellAuraDefines.h @@ -303,8 +303,8 @@ enum AuraType : uint32 SPELL_AURA_ARENA_PREPARATION = 215, SPELL_AURA_HASTE_SPELLS = 216, SPELL_AURA_MOD_MELEE_HASTE_2 = 217, - SPELL_AURA_ADD_PCT_MODIFIER_BY_SPELL_LABEL = 218, // NYI - SPELL_AURA_ADD_FLAT_MODIFIER_BY_SPELL_LABEL = 219, // NYI + SPELL_AURA_ADD_PCT_MODIFIER_BY_SPELL_LABEL = 218, + SPELL_AURA_ADD_FLAT_MODIFIER_BY_SPELL_LABEL = 219, SPELL_AURA_MOD_ABILITY_SCHOOL_MASK = 220, // NYI SPELL_AURA_MOD_DETAUNT = 221, SPELL_AURA_REMOVE_TRANSMOG_COST = 222, diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index ff7ffd5f443..38a5ac9c563 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -286,8 +286,8 @@ NonDefaultConstructible<pAuraEffectHandler> AuraEffectHandler[TOTAL_AURAS]= &AuraEffect::HandleArenaPreparation, //215 SPELL_AURA_ARENA_PREPARATION &AuraEffect::HandleModCastingSpeed, //216 SPELL_AURA_HASTE_SPELLS &AuraEffect::HandleModMeleeSpeedPct, //217 SPELL_AURA_MOD_MELEE_HASTE_2 - &AuraEffect::HandleNULL, //218 SPELL_AURA_ADD_PCT_MODIFIER_BY_SPELL_LABEL - &AuraEffect::HandleNULL, //219 SPELL_AURA_ADD_FLAT_MODIFIER_BY_SPELL_LABEL + &AuraEffect::HandleNoImmediateEffect, //218 SPELL_AURA_ADD_PCT_MODIFIER_BY_SPELL_LABEL implemented in AuraEffect::CalculateSpellMod() + &AuraEffect::HandleNoImmediateEffect, //219 SPELL_AURA_ADD_FLAT_MODIFIER_BY_SPELL_LABEL implemented in AuraEffect::CalculateSpellMod() &AuraEffect::HandleNULL, //220 SPELL_AURA_MOD_ABILITY_SCHOOL_MASK &AuraEffect::HandleModDetaunt, //221 SPELL_AURA_MOD_DETAUNT &AuraEffect::HandleNoImmediateEffect, //222 SPELL_AURA_REMOVE_TRANSMOG_COST implemented in WorldSession::HandleTransmogrifyItems @@ -808,14 +808,43 @@ void AuraEffect::CalculateSpellMod() case SPELL_AURA_ADD_PCT_MODIFIER: if (!m_spellmod) { - m_spellmod = new SpellModifier(GetBase()); - m_spellmod->op = SpellModOp(GetMiscValue()); + SpellModifierByClassMask* spellmod = new SpellModifierByClassMask(GetBase()); + spellmod->op = SpellModOp(GetMiscValue()); - m_spellmod->type = GetAuraType() == SPELL_AURA_ADD_PCT_MODIFIER ? SPELLMOD_PCT : SPELLMOD_FLAT; - m_spellmod->spellId = GetId(); - m_spellmod->mask = GetSpellEffectInfo().SpellClassMask; + spellmod->type = GetAuraType() == SPELL_AURA_ADD_PCT_MODIFIER ? SPELLMOD_PCT : SPELLMOD_FLAT; + spellmod->spellId = GetId(); + spellmod->mask = GetSpellEffectInfo().SpellClassMask; + m_spellmod = spellmod; } - m_spellmod->value = GetAmount(); + static_cast<SpellModifierByClassMask*>(m_spellmod)->value = GetAmount(); + break; + case SPELL_AURA_ADD_FLAT_MODIFIER_BY_SPELL_LABEL: + if (!m_spellmod) + { + SpellFlatModifierByLabel* spellmod = new SpellFlatModifierByLabel(GetBase()); + spellmod->op = SpellModOp(GetMiscValue()); + + spellmod->type = SPELLMOD_LABEL_FLAT; + spellmod->spellId = GetId(); + spellmod->value.ModIndex = GetMiscValue(); + spellmod->value.LabelID = GetMiscValueB(); + m_spellmod = spellmod; + } + static_cast<SpellFlatModifierByLabel*>(m_spellmod)->value.ModifierValue = GetAmount(); + break; + case SPELL_AURA_ADD_PCT_MODIFIER_BY_SPELL_LABEL: + if (!m_spellmod) + { + SpellPctModifierByLabel* spellmod = new SpellPctModifierByLabel(GetBase()); + spellmod->op = SpellModOp(GetMiscValue()); + + spellmod->type = SPELLMOD_LABEL_PCT; + spellmod->spellId = GetId(); + spellmod->value.ModIndex = GetMiscValue(); + spellmod->value.LabelID = GetMiscValueB(); + m_spellmod = spellmod; + } + static_cast<SpellPctModifierByLabel*>(m_spellmod)->value.ModifierValue = 1.0f + CalculatePct(1.0f, GetAmount()); break; default: break; diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp index 44896751acb..3ae31465448 100644 --- a/src/server/game/Spells/SpellInfo.cpp +++ b/src/server/game/Spells/SpellInfo.cpp @@ -1729,9 +1729,22 @@ bool SpellInfo::IsAffectedBySpellMod(SpellModifier const* mod) const if (!affectSpell) return false; - // TEMP: dont use IsAffected - !familyName and !familyFlags are not valid options for spell mods - // TODO: investigate if the !familyName and !familyFlags conditions are even valid for all other (nonmod) uses of SpellInfo::IsAffected - return affectSpell->SpellFamilyName == SpellFamilyName && mod->mask & SpellFamilyFlags; + switch (mod->type) + { + case SPELLMOD_FLAT: + case SPELLMOD_PCT: + // TEMP: dont use IsAffected - !familyName and !familyFlags are not valid options for spell mods + // TODO: investigate if the !familyName and !familyFlags conditions are even valid for all other (nonmod) uses of SpellInfo::IsAffected + return affectSpell->SpellFamilyName == SpellFamilyName && static_cast<SpellModifierByClassMask const*>(mod)->mask & SpellFamilyFlags; + case SPELLMOD_LABEL_FLAT: + return HasLabel(static_cast<SpellFlatModifierByLabel const*>(mod)->value.LabelID); + case SPELLMOD_LABEL_PCT: + return HasLabel(static_cast<SpellPctModifierByLabel const*>(mod)->value.LabelID); + default: + break; + } + + return false; } bool SpellInfo::CanPierceImmuneAura(SpellInfo const* auraSpellInfo) const diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index acbd500edba..6824392d3d0 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -1618,7 +1618,8 @@ void SpellMgr::LoadSpellProcs() if (!spellEffectInfo.IsAura()) continue; - if (spellEffectInfo.ApplyAuraName == SPELL_AURA_ADD_PCT_MODIFIER || spellEffectInfo.ApplyAuraName == SPELL_AURA_ADD_FLAT_MODIFIER) + if (spellEffectInfo.ApplyAuraName == SPELL_AURA_ADD_PCT_MODIFIER || spellEffectInfo.ApplyAuraName == SPELL_AURA_ADD_FLAT_MODIFIER + || spellEffectInfo.ApplyAuraName == SPELL_AURA_ADD_PCT_MODIFIER_BY_SPELL_LABEL || spellEffectInfo.ApplyAuraName == SPELL_AURA_ADD_FLAT_MODIFIER_BY_SPELL_LABEL) { found = true; break; diff --git a/src/server/scripts/Spells/spell_druid.cpp b/src/server/scripts/Spells/spell_druid.cpp index b37be52e21a..5e068be5a77 100644 --- a/src/server/scripts/Spells/spell_druid.cpp +++ b/src/server/scripts/Spells/spell_druid.cpp @@ -729,13 +729,14 @@ public: { if (!spellMod) { - spellMod = new SpellModifier(GetAura()); - spellMod->op = SpellModOp::PeriodicHealingAndDamage; - spellMod->type = SPELLMOD_FLAT; - spellMod->spellId = GetId(); - spellMod->mask = aurEff->GetSpellEffectInfo().SpellClassMask; + SpellModifierByClassMask* mod = new SpellModifierByClassMask(GetAura()); + mod->op = SpellModOp::PeriodicHealingAndDamage; + mod->type = SPELLMOD_FLAT; + mod->spellId = GetId(); + mod->mask = aurEff->GetSpellEffectInfo().SpellClassMask; + spellMod = mod; } - spellMod->value = aurEff->GetAmount() / 7; + static_cast<SpellModifierByClassMask*>(spellMod)->value = aurEff->GetAmount() / 7; } void Register() override |
