From 5a9bf21cd8e55d3575906f6097f27b7bc2cdecf9 Mon Sep 17 00:00:00 2001 From: UltraNix <80540499+UltraNix@users.noreply.github.com> Date: Sat, 16 Apr 2022 15:28:24 +0200 Subject: [PATCH] fix(Core/Spells): Implemented spell priorities. (#11278) * fix(Core/Spells): Implemented spell priorities. Fixes #11261 * Update. * Update. * Update. --- src/server/game/Entities/Player/Player.h | 90 +++++++++++++++---- src/server/game/Spells/SpellInfo.cpp | 1 + src/server/game/Spells/SpellInfo.h | 1 + .../game/Spells/SpellInfoCorrections.cpp | 8 +- src/server/shared/DataStores/DBCStructure.h | 2 +- src/server/shared/DataStores/DBCfmt.h | 2 +- 6 files changed, 83 insertions(+), 21 deletions(-) diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index d79bac33d..bf2d5d24b 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -36,7 +36,9 @@ #include "PlayerSettings.h" #include "PlayerTaxi.h" #include "QuestDef.h" +#include "SpellAuras.h" #include "SpellMgr.h" +#include "SpellInfo.h" #include "TradeData.h" #include "Unit.h" #include "WorldSession.h" @@ -2920,32 +2922,28 @@ template T Player::ApplySpellMod(uint32 spellId, SpellModOp op, T& bas { SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); if (!spellInfo) + { return 0; + } + float totalmul = 1.0f; int32 totalflat = 0; - // Drop charges for triggering spells instead of triggered ones - if (m_spellModTakingSpell) - spell = m_spellModTakingSpell; - - for (auto mod : m_spellMods[op]) + auto calculateSpellMod = [&](SpellModifier* mod) { - // Charges can be set only for mods with auras - if (!mod->ownerAura) - ASSERT(mod->charges == 0); - - if (!IsAffectedBySpellmod(spellInfo, mod, spell)) - continue; - // xinef: temporary pets cannot use charged mods of owner, needed for mirror image QQ they should use their own auras if (temporaryPet && mod->charges != 0) - continue; + { + return; + } if (mod->type == SPELLMOD_FLAT) { // xinef: do not allow to consume more than one 100% crit increasing spell if (mod->op == SPELLMOD_CRITICAL_CHANCE && totalflat >= 100) - continue; + { + return; + } totalflat += mod->value; } @@ -2953,32 +2951,88 @@ template T Player::ApplySpellMod(uint32 spellId, SpellModOp op, T& bas { // skip percent mods for null basevalue (most important for spell mods with charges) if (basevalue == T(0) || totalmul == 0.0f) - continue; + { + return; + } // special case (skip > 10sec spell casts for instant cast setting) if (mod->op == SPELLMOD_CASTING_TIME && basevalue >= T(10000) && mod->value <= -100) - continue; + { + return; + } // xinef: special exception for surge of light, dont affect crit chance if previous mods were not applied else if (mod->op == SPELLMOD_CRITICAL_CHANCE && spell && !HasSpellMod(mod, spell)) - continue; + { + return; + } // xinef: special case for backdraft gcd reduce with backlast time reduction, dont affect gcd if cast time was not applied else if (mod->op == SPELLMOD_GLOBAL_COOLDOWN && spell && !HasSpellMod(mod, spell)) - continue; + { + return; + } // xinef: those two mods should be multiplicative (Glyph of Renew) if (mod->op == SPELLMOD_DAMAGE || mod->op == SPELLMOD_DOT) + { totalmul *= CalculatePct(1.0f, 100.0f + mod->value); + } else + { totalmul += CalculatePct(1.0f, mod->value); + } } DropModCharge(mod, spell); + }; + + // Drop charges for triggering spells instead of triggered ones + if (m_spellModTakingSpell) + { + spell = m_spellModTakingSpell; } + + SpellModifier* chargedMod = nullptr; + for (auto mod : m_spellMods[op]) + { + // Charges can be set only for mods with auras + if (!mod->ownerAura) + { + ASSERT(!mod->charges); + } + + if (!IsAffectedBySpellmod(spellInfo, mod, spell)) + { + continue; + } + + if (mod->ownerAura->IsUsingCharges()) + { + if (!chargedMod || (chargedMod->ownerAura->GetSpellInfo()->SpellPriority < mod->ownerAura->GetSpellInfo()->SpellPriority)) + { + chargedMod = mod; + } + + continue; + } + + calculateSpellMod(mod); + } + + if (chargedMod) + { + calculateSpellMod(chargedMod); + } + float diff = 0.0f; if (op == SPELLMOD_CASTING_TIME || op == SPELLMOD_DURATION) + { diff = ((float)basevalue + totalflat) * (totalmul - 1.0f) + (float)totalflat; + } else + { diff = (float)basevalue * (totalmul - 1.0f) + (float)totalflat; + } + basevalue = T((float)basevalue + diff); return T(diff); } diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp index 63fefa962..e7e55bc2a 100644 --- a/src/server/game/Spells/SpellInfo.cpp +++ b/src/server/game/Spells/SpellInfo.cpp @@ -831,6 +831,7 @@ SpellInfo::SpellInfo(SpellEntry const* spellEntry) SpellVisual = spellEntry->SpellVisual; SpellIconID = spellEntry->SpellIconID; ActiveIconID = spellEntry->ActiveIconID; + SpellPriority = spellEntry->SpellPriority; SpellName = spellEntry->SpellName; Rank = spellEntry->Rank; MaxTargetLevel = spellEntry->MaxTargetLevel; diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h index c80bf7c3d..d93e9e6b3 100644 --- a/src/server/game/Spells/SpellInfo.h +++ b/src/server/game/Spells/SpellInfo.h @@ -377,6 +377,7 @@ public: std::array SpellVisual; uint32 SpellIconID; uint32 ActiveIconID; + uint32 SpellPriority; std::array SpellName; std::array Rank; uint32 MaxTargetLevel; diff --git a/src/server/game/Spells/SpellInfoCorrections.cpp b/src/server/game/Spells/SpellInfoCorrections.cpp index d465e8b00..c1e442e66 100644 --- a/src/server/game/Spells/SpellInfoCorrections.cpp +++ b/src/server/game/Spells/SpellInfoCorrections.cpp @@ -244,7 +244,6 @@ void SpellMgr::LoadSpellInfoCorrections() 48108, // Hot Streak 51124, // Killing Machine 54741, // Firestarter - 57761, // Fireball! 64823, // Item - Druid T8 Balance 4P Bonus 34477, // Misdirection 44401, // Missile Barrage @@ -254,6 +253,13 @@ void SpellMgr::LoadSpellInfoCorrections() spellInfo->ProcCharges = 1; }); + // Fireball + ApplySpellFix({ 57761 }, [](SpellInfo* spellInfo) + { + spellInfo->ProcCharges = 1; + spellInfo->SpellPriority = 50; + }); + // Tidal Wave ApplySpellFix({ 53390 }, [](SpellInfo* spellInfo) { diff --git a/src/server/shared/DataStores/DBCStructure.h b/src/server/shared/DataStores/DBCStructure.h index 2bbc7c5bc..63a5a1075 100644 --- a/src/server/shared/DataStores/DBCStructure.h +++ b/src/server/shared/DataStores/DBCStructure.h @@ -1637,7 +1637,7 @@ struct SpellEntry std::array SpellVisual; // 131-132 m_spellVisualID uint32 SpellIconID; // 133 m_spellIconID uint32 ActiveIconID; // 134 m_activeIconID - //uint32 SpellPriority; // 135 not used + uint32 SpellPriority; // 135 not used std::array SpellName; // 136-151 m_name_lang //uint32 SpellNameFlag; // 152 not used std::array Rank; // 153-168 m_nameSubtext_lang diff --git a/src/server/shared/DataStores/DBCfmt.h b/src/server/shared/DataStores/DBCfmt.h index 857c94c46..0cf21d8b3 100644 --- a/src/server/shared/DataStores/DBCfmt.h +++ b/src/server/shared/DataStores/DBCfmt.h @@ -100,7 +100,7 @@ char constexpr SpellCastTimefmt[] = "nixx"; char constexpr SpellCategoryfmt[] = "ni"; char constexpr SpellDifficultyfmt[] = "niiii"; char constexpr SpellDurationfmt[] = "niii"; -char constexpr SpellEntryfmt[] = "niiiiiiiiiiiixixiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiifxiiiiiiiiiiiiiiiiiiiiiiiiiiiifffiiiiiiiiiiiiiiiiiiiiifffiiiiiiiiiiiiiiifffiiiiiiiiiiiiixssssssssssssssssxssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiiiiiiiiiiixfffxxxiiiiixxfffxx"; +char constexpr SpellEntryfmt[] = "niiiiiiiiiiiixixiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiifxiiiiiiiiiiiiiiiiiiiiiiiiiiiifffiiiiiiiiiiiiiiiiiiiiifffiiiiiiiiiiiiiiifffiiiiiiiiiiiiiissssssssssssssssxssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiiiiiiiiiiixfffxxxiiiiixxfffxx"; char constexpr SpellFocusObjectfmt[] = "nxxxxxxxxxxxxxxxxx"; char constexpr SpellItemEnchantmentfmt[] = "niiiiiiixxxiiissssssssssssssssxiiiiiii"; char constexpr SpellItemEnchantmentConditionfmt[] = "nbbbbbxxxxxbbbbbbbbbbiiiiiXXXXX";