aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2024-08-27 13:50:33 +0200
committerOvahlord <dreadkiller@gmx.de>2024-08-27 17:22:18 +0200
commitab0d7ac8f35543bea2d3073a2f337c30dddf3a0d (patch)
tree62cdcb1dbf5c5d4b348da4b989e1bebd526d6666
parentd451defc22b09ee70e3f96c8443d9afe3e7ec09d (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.cpp12
-rw-r--r--src/server/game/Spells/SpellMgr.cpp12
-rw-r--r--src/server/game/Spells/SpellMgr.h5
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;