mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-16 07:30:42 +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)
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user