fix(Core/Player): Fixed some spells appearing as available at trainer when they are already known (#22678)

Co-authored-by: Shauren <shauren.trinity@gmail.com>
* cherry-pick commit (baebb2d602)
This commit is contained in:
EricksOliveira
2026-07-18 22:58:50 +00:00
committed by GitHub
parent 37c723895b
commit c83cb5de7d
2 changed files with 75 additions and 4 deletions

View File

@@ -2841,6 +2841,66 @@ void Player::SendInitialSpells()
SendDirectMessage(&data);
}
void Player::SendUnlearnSpells()
{
WorldPacket data(SMSG_SEND_UNLEARN_SPELLS, 4 + 4 * m_spells.size());
uint32 spellCount = 0;
size_t countPos = data.wpos();
data << uint32(spellCount);
for (auto const& itr : m_spells)
{
if (itr.second->State == PLAYERSPELL_REMOVED || itr.second->Active)
continue;
auto skillLineAbilities = sSpellMgr->GetSkillLineAbilityMapBounds(itr.first);
if (skillLineAbilities.first == skillLineAbilities.second)
continue;
// Client already hides ranks that have a superseding rank
bool hasSupercedingRank = false;
for (auto slaItr = skillLineAbilities.first; slaItr != skillLineAbilities.second; ++slaItr)
{
if (slaItr->second->SupercededBySpell)
{
hasSupercedingRank = true;
break;
}
}
if (hasSupercedingRank)
continue;
uint32 nextRank = sSpellMgr->GetNextSpellInChain(itr.first);
if (!nextRank || !HasSpell(nextRank))
continue;
data << uint32(itr.first);
++spellCount;
}
data.put<uint32>(countPos, spellCount);
SendDirectMessage(&data);
}
bool Player::IsUnlearnNeededForSpell(uint32 spellId)
{
SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(spellId);
if (spellInfo->IsRanked() && !spellInfo->IsStackableWithRanks())
{
auto skillLineAbilities = sSpellMgr->GetSkillLineAbilityMapBounds(spellId);
if (skillLineAbilities.first != skillLineAbilities.second)
{
for (auto itr = skillLineAbilities.first; itr != skillLineAbilities.second; ++itr)
if (itr->second->SupercededBySpell)
return false;
return true;
}
}
return false;
}
void Player::RemoveMail(uint32 id)
{
for (PlayerMails::iterator itr = m_mail.begin(); itr != m_mail.end(); ++itr)
@@ -3066,6 +3126,10 @@ bool Player::addSpell(uint32 spellId, uint8 addSpecMask, bool updateActive, bool
if (nextSpellInfo->GetRank() < spellInfo->GetRank())
{
itr->second->Active = false;
if (!isBeingLoaded() && IsUnlearnNeededForSpell(spellId))
SendUnlearnSpells();
if (IsInWorld())
{
WorldPacket data(SMSG_SUPERCEDED_SPELL, 4 + 4);
@@ -3080,6 +3144,10 @@ bool Player::addSpell(uint32 spellId, uint8 addSpecMask, bool updateActive, bool
PlayerSpellMap::iterator itr2 = m_spells.find(spellInfo->Id);
if (itr2 != m_spells.end())
itr2->second->Active = false;
if (!isBeingLoaded() && IsUnlearnNeededForSpell(spellId))
SendUnlearnSpells();
return false;
}
}
@@ -3087,6 +3155,9 @@ bool Player::addSpell(uint32 spellId, uint8 addSpecMask, bool updateActive, bool
}
}
if (!isBeingLoaded() && IsUnlearnNeededForSpell(spellId))
SendUnlearnSpells();
return true;
}
@@ -11628,10 +11699,7 @@ void Player::SendInitialPacketsBeforeAddToMap()
SendDirectMessage(&data);
SendInitialSpells();
data.Initialize(SMSG_SEND_UNLEARN_SPELLS, 4);
data << uint32(0); // count, for (count) uint32;
SendDirectMessage(&data);
SendUnlearnSpells();
SendInitialActionButtons();
m_reputationMgr->SendInitialReputations();

View File

@@ -1664,6 +1664,9 @@ public:
void UpdateNextMailTimeAndUnreads();
void AddNewMailDeliverTime(time_t deliver_time);
void SendUnlearnSpells();
static bool IsUnlearnNeededForSpell(uint32 spellId);
void RemoveMail(uint32 id);
void AddMail(Mail* mail) { m_mail.push_front(mail); }// for call from WorldSession::SendMailTo