diff options
-rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 12 | ||||
-rw-r--r-- | src/server/game/Spells/SpellMgr.cpp | 12 | ||||
-rw-r--r-- | src/server/game/Spells/SpellMgr.h | 5 |
3 files changed, 29 insertions, 0 deletions
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 2a53a6906bb..6ee68e5f7aa 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -3407,6 +3407,18 @@ void Player::RemoveSpell(uint32 spell_id, bool disabled /*= false*/, bool learn_ for (SpellLearnSpellMap::const_iterator itr2 = spell_bounds.first; itr2 != spell_bounds.second; ++itr2) { + bool hasOtherSpellTeachingThis = std::ranges::any_of(sSpellMgr->GetSpellLearnedBySpellMapBounds(itr2->second.Spell), [&](SpellLearnSpellNode const* learnNode) + { + if (learnNode->SourceSpell == spell_id) + return false; + if (!learnNode->Active) + return false; + return HasSpell(learnNode->SourceSpell); + }, &SpellLearnedBySpellMap::value_type::second); + + if (hasOtherSpellTeachingThis) + continue; + RemoveSpell(itr2->second.Spell, disabled); if (itr2->second.OverridesSpell) RemoveOverrideSpell(itr2->second.OverridesSpell, itr2->second.Spell); diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index 057a7e2c9e6..3527310f4ec 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -342,6 +342,11 @@ bool SpellMgr::IsSpellLearnToSpell(uint32 spell_id1, uint32 spell_id2) const return false; } +Trinity::IteratorPair<SpellLearnedBySpellMap::const_iterator> SpellMgr::GetSpellLearnedBySpellMapBounds(uint32 learnedSpellId) const +{ + return Trinity::Containers::MapEqualRange(mSpellLearnedBySpells, learnedSpellId); +} + SpellTargetPosition const* SpellMgr::GetSpellTargetPosition(uint32 spell_id, SpellEffIndex effIndex) const { SpellTargetPositionMap::const_iterator itr = mSpellTargetPositions.find(std::make_pair(spell_id, effIndex)); @@ -992,6 +997,7 @@ void SpellMgr::LoadSpellLearnSpells() { uint32 oldMSTime = getMSTime(); + mSpellLearnedBySpells.clear(); mSpellLearnSpells.clear(); // need for reload case // 0 1 2 @@ -1010,6 +1016,7 @@ void SpellMgr::LoadSpellLearnSpells() uint32 spell_id = fields[0].GetUInt32(); SpellLearnSpellNode node; + node.SourceSpell = spell_id; node.Spell = fields[1].GetUInt32(); node.OverridesSpell = 0; node.Active = fields[2].GetBool(); @@ -1054,6 +1061,7 @@ void SpellMgr::LoadSpellLearnSpells() if (spellEffectInfo.IsEffect(SPELL_EFFECT_LEARN_SPELL)) { SpellLearnSpellNode dbc_node; + dbc_node.SourceSpell = entry.Id; dbc_node.Spell = spellEffectInfo.TriggerSpell; dbc_node.Active = true; // all dbc based learned spells is active (show in spell book or hide by client itself) dbc_node.OverridesSpell = 0; @@ -1127,6 +1135,7 @@ void SpellMgr::LoadSpellLearnSpells() continue; SpellLearnSpellNode dbcLearnNode; + dbcLearnNode.SourceSpell = spellLearnSpell->SpellID; dbcLearnNode.Spell = spellLearnSpell->LearnSpellID; dbcLearnNode.OverridesSpell = spellLearnSpell->OverridesSpellID; dbcLearnNode.Active = true; @@ -1136,6 +1145,9 @@ void SpellMgr::LoadSpellLearnSpells() ++dbc_count; } + for (auto const& [spellId, learnedSpellNode] : mSpellLearnSpells) + mSpellLearnedBySpells.emplace(learnedSpellNode.Spell, &learnedSpellNode); + TC_LOG_INFO("server.loading", ">> Loaded {} spell learn spells, {} found in Spell.dbc in {} ms", count, dbc_count, GetMSTimeDiffToNow(oldMSTime)); } diff --git a/src/server/game/Spells/SpellMgr.h b/src/server/game/Spells/SpellMgr.h index e8a6c2a8b1b..3d638aa61d9 100644 --- a/src/server/game/Spells/SpellMgr.h +++ b/src/server/game/Spells/SpellMgr.h @@ -590,6 +590,7 @@ typedef std::unordered_map<uint32, SpellLearnSkillNode> SpellLearnSkillMap; struct SpellLearnSpellNode { + uint32 SourceSpell; uint32 Spell; uint32 OverridesSpell; bool Active; // show in spellbook or not @@ -618,6 +619,8 @@ struct CreatureImmunities typedef std::multimap<uint32, SpellLearnSpellNode> SpellLearnSpellMap; typedef std::pair<SpellLearnSpellMap::const_iterator, SpellLearnSpellMap::const_iterator> SpellLearnSpellMapBounds; +typedef std::multimap<uint32, SpellLearnSpellNode const*> SpellLearnedBySpellMap; + typedef std::multimap<uint32, SkillLineAbilityEntry const*> SkillLineAbilityMap; typedef std::pair<SkillLineAbilityMap::const_iterator, SkillLineAbilityMap::const_iterator> SkillLineAbilityMapBounds; @@ -725,6 +728,7 @@ class TC_GAME_API SpellMgr SpellLearnSpellMapBounds GetSpellLearnSpellMapBounds(uint32 spell_id) const; bool IsSpellLearnSpell(uint32 spell_id) const; bool IsSpellLearnToSpell(uint32 spell_id1, uint32 spell_id2) const; + Trinity::IteratorPair<SpellLearnedBySpellMap::const_iterator> GetSpellLearnedBySpellMapBounds(uint32 learnedSpellId) const; // Spell target coordinates SpellTargetPosition const* GetSpellTargetPosition(uint32 spell_id, SpellEffIndex effIndex) const; @@ -828,6 +832,7 @@ class TC_GAME_API SpellMgr SpellRequiredMap mSpellReq; SpellLearnSkillMap mSpellLearnSkills; SpellLearnSpellMap mSpellLearnSpells; + SpellLearnedBySpellMap mSpellLearnedBySpells; SpellTargetPositionMap mSpellTargetPositions; SpellSpellGroupMap mSpellSpellGroup; SpellGroupSpellMap mSpellGroupSpell; |