mirror of
https://github.com/liyunfan1223/azerothcore-wotlk.git
synced 2026-08-04 22:07:52 +00:00
fix(Core/Player): learn higher-rank talent spells in all specs that have the talent (#23945)
Co-authored-by: glubbl <glubbl@users.noreply.github.com> Co-authored-by: sudlud <sudlud@users.noreply.github.com> Co-authored-by: kclnn <kclnn@users.noreply.github.com>
This commit is contained in:
@@ -3416,9 +3416,9 @@ void Player::learnSpell(uint32 spellId, bool temporary /*= false*/, bool learnFr
|
||||
return;
|
||||
}
|
||||
|
||||
uint32 firstRankSpellId = sSpellMgr->GetFirstSpellInChain(spellId);
|
||||
bool thisSpec = GetTalentSpellCost(firstRankSpellId) > 0 || sSpellMgr->IsAdditionalTalentSpell(firstRankSpellId);
|
||||
bool added = addSpell(spellId, thisSpec ? GetActiveSpecMask() : SPEC_MASK_ALL, true, temporary, learnFromSkill);
|
||||
uint8 const specMask = GetLearnSpellSpecMask(spellId);
|
||||
|
||||
bool const added = addSpell(spellId, specMask, true, temporary, learnFromSkill);
|
||||
if (added)
|
||||
{
|
||||
sScriptMgr->OnPlayerLearnSpell(this, spellId);
|
||||
@@ -3448,6 +3448,47 @@ void Player::learnSpell(uint32 spellId, bool temporary /*= false*/, bool learnFr
|
||||
}
|
||||
}
|
||||
|
||||
uint8 Player::GetLearnSpellSpecMask(uint32 spellId) const
|
||||
{
|
||||
uint32 const firstRankSpellId = sSpellMgr->GetFirstSpellInChain(spellId);
|
||||
|
||||
bool const isTalentBasedSpell = GetTalentSpellCost(firstRankSpellId) > 0 || sSpellMgr->IsAdditionalTalentSpell(firstRankSpellId);
|
||||
|
||||
// If this spell doesn't require any talents, learn it in all talent specs
|
||||
if (!isTalentBasedSpell)
|
||||
return SPEC_MASK_ALL;
|
||||
|
||||
uint8 specMask = GetActiveSpecMask();
|
||||
|
||||
// If the first rank of a talent-based spell has already been learned in another spec,
|
||||
// the following ranks should also be learned in that spec.
|
||||
if (m_spells.find(firstRankSpellId) != m_spells.end())
|
||||
{
|
||||
specMask |= m_spells.at(firstRankSpellId)->specMask;
|
||||
}
|
||||
|
||||
// When learning a talent-based spell that has other spells as a requirement, it should not only be learned in the current spec,
|
||||
// but also in all other specs that have the required spells.
|
||||
// Example: Greater Blessing of Sanctuary has Blessing of Sanctuary as required spell.
|
||||
auto const spellsRequiredForSpellBounds = sSpellMgr->GetSpellsRequiredForSpellBounds(spellId);
|
||||
bool const spellHasRequiredSpells = (spellsRequiredForSpellBounds.begin() != spellsRequiredForSpellBounds.end());
|
||||
if (spellHasRequiredSpells)
|
||||
{
|
||||
uint8 requiredSpellsSpecMask = SPEC_MASK_ALL;
|
||||
for (SpellRequiredMap::const_iterator itr = spellsRequiredForSpellBounds.begin(); itr != spellsRequiredForSpellBounds.end(); ++itr)
|
||||
{
|
||||
uint32 const requiredSpellId = itr->second;
|
||||
bool const requiredSpellExistsAsPlayerSpell = (m_spells.find(requiredSpellId) != m_spells.end());
|
||||
|
||||
// The required spell should usually exist at least in the current spec, but maybe we are learning a spell via GM command
|
||||
requiredSpellsSpecMask &= requiredSpellExistsAsPlayerSpell ? m_spells.at(requiredSpellId)->specMask : 0;
|
||||
}
|
||||
specMask |= requiredSpellsSpecMask;
|
||||
}
|
||||
|
||||
return specMask;
|
||||
}
|
||||
|
||||
void Player::removeSpell(uint32 spell_id, uint8 removeSpecMask, bool onlyTemporary)
|
||||
{
|
||||
PlayerSpellMap::iterator itr = m_spells.find(spell_id);
|
||||
|
||||
@@ -3010,6 +3010,8 @@ private:
|
||||
[[nodiscard]] bool HasDelayedTeleport() const { return m_bHasDelayedTeleport; }
|
||||
void SetHasDelayedTeleport(bool setting) { m_bHasDelayedTeleport = setting; }
|
||||
|
||||
uint8 GetLearnSpellSpecMask(uint32 spellId) const;
|
||||
|
||||
MapReference m_mapRef;
|
||||
|
||||
void UpdateCharmedAI();
|
||||
|
||||
Reference in New Issue
Block a user