mirror of
https://github.com/liyunfan1223/azerothcore-wotlk.git
synced 2026-08-04 22:07:52 +00:00
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:
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user