diff options
author | Shauren <shauren.trinity@gmail.com> | 2024-08-27 13:50:33 +0200 |
---|---|---|
committer | Ovahlord <dreadkiller@gmx.de> | 2024-08-27 17:22:18 +0200 |
commit | ab0d7ac8f35543bea2d3073a2f337c30dddf3a0d (patch) | |
tree | 62cdcb1dbf5c5d4b348da4b989e1bebd526d6666 | |
parent | d451defc22b09ee70e3f96c8443d9afe3e7ec09d (diff) |
Core/Players: Fixed spells being unintentionally removed by talent swaps when they are learned from more than one spell (affects balance druid Celesial Alignment and Incarnation)
(cherry picked from commit 2c6ddcce3d6374a82214bb0ddb9d7432351982c9)
# Conflicts:
# src/server/game/Spells/SpellMgr.cpp
-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 432700be071..b6b7ea4b836 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -3107,6 +3107,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 b27f7db6dbd..ba212cb04b8 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)); @@ -1053,6 +1058,7 @@ void SpellMgr::LoadSpellLearnSpells() { uint32 oldMSTime = getMSTime(); + mSpellLearnedBySpells.clear(); mSpellLearnSpells.clear(); // need for reload case // 0 1 2 @@ -1071,6 +1077,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(); @@ -1115,6 +1122,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; @@ -1188,6 +1196,7 @@ void SpellMgr::LoadSpellLearnSpells() continue; SpellLearnSpellNode dbcLearnNode; + dbcLearnNode.SourceSpell = spellLearnSpell->SpellID; dbcLearnNode.Spell = spellLearnSpell->LearnSpellID; dbcLearnNode.OverridesSpell = spellLearnSpell->OverridesSpellID; dbcLearnNode.Active = true; @@ -1254,6 +1263,9 @@ void SpellMgr::LoadSpellLearnSpells() } } + for (auto const& [spellId, learnedSpellNode] : mSpellLearnSpells) + mSpellLearnedBySpells.emplace(learnedSpellNode.Spell, &learnedSpellNode); + TC_LOG_INFO("server.loading", ">> Loaded {} spell learn spells, {} found in Spell.dbc and {} found in TalentTab.db2 in {} ms", count, dbc_count, mastery_count, GetMSTimeDiffToNow(oldMSTime)); } diff --git a/src/server/game/Spells/SpellMgr.h b/src/server/game/Spells/SpellMgr.h index 91470991901..b681dcbf5cd 100644 --- a/src/server/game/Spells/SpellMgr.h +++ b/src/server/game/Spells/SpellMgr.h @@ -589,6 +589,7 @@ typedef std::unordered_map<uint32, SpellLearnSkillNode> SpellLearnSkillMap; struct SpellLearnSpellNode { + uint32 SourceSpell; uint32 Spell; uint32 OverridesSpell; bool Active; // show in spellbook or not @@ -617,6 +618,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; @@ -723,6 +726,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; @@ -827,6 +831,7 @@ class TC_GAME_API SpellMgr SpellRequiredMap mSpellReq; SpellLearnSkillMap mSpellLearnSkills; SpellLearnSpellMap mSpellLearnSpells; + SpellLearnedBySpellMap mSpellLearnedBySpells; SpellTargetPositionMap mSpellTargetPositions; SpellSpellGroupMap mSpellSpellGroup; SpellGroupSpellMap mSpellGroupSpell; |