mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-19 00:48:56 +01:00
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 2c6ddcce3d)
# Conflicts:
# src/server/game/Spells/SpellMgr.cpp
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user