mirror of
https://github.com/liyunfan1223/azerothcore-wotlk.git
synced 2026-08-07 15:28:02 +00:00
fix(Core/Commands): Learn profession rank spells in .learn all recipes (#25114)
Co-authored-by: Ludwig <sudlud@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -33,6 +33,8 @@
|
||||
#include "Tokenize.h"
|
||||
#include "World.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
bool IsPrimaryProfessionSkill(uint32 skill)
|
||||
{
|
||||
SkillLineEntry const* pSkill = sSkillLineStore.LookupEntry(skill);
|
||||
@@ -687,6 +689,24 @@ SpellLearnSkillNode const* SpellMgr::GetSpellLearnSkill(uint32 spell_id) const
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::vector<uint32> SpellMgr::GetSkillRankSpells(uint32 skillId) const
|
||||
{
|
||||
// Returns every spell that grants this skill via SPELL_EFFECT_SKILL,
|
||||
// i.e. the profession rank/proficiency spells (Apprentice -> Grand Master),
|
||||
// ordered by step. Not strictly limited to the six ranks: any skill-granting
|
||||
// spell for the line is included.
|
||||
std::vector<uint32> result;
|
||||
for (auto const& [spellId, node] : mSpellLearnSkills)
|
||||
if (node.skill == skillId)
|
||||
result.push_back(spellId);
|
||||
|
||||
std::ranges::sort(result, [this](uint32 a, uint32 b)
|
||||
{
|
||||
return mSpellLearnSkills.at(a).step < mSpellLearnSkills.at(b).step;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
SpellTargetPosition const* SpellMgr::GetSpellTargetPosition(uint32 spell_id, SpellEffIndex effIndex) const
|
||||
{
|
||||
SpellTargetPositionMap::const_iterator itr = mSpellTargetPositions.find(std::make_pair(spell_id, effIndex));
|
||||
|
||||
@@ -687,6 +687,7 @@ public:
|
||||
|
||||
// Spell learning
|
||||
[[nodiscard]] SpellLearnSkillNode const* GetSpellLearnSkill(uint32 spell_id) const;
|
||||
[[nodiscard]] std::vector<uint32> GetSkillRankSpells(uint32 skillId) const;
|
||||
|
||||
// Spell target coordinates
|
||||
[[nodiscard]] SpellTargetPosition const* GetSpellTargetPosition(uint32 spell_id, SpellEffIndex effIndex) const;
|
||||
|
||||
@@ -309,6 +309,8 @@ public:
|
||||
|
||||
static bool HandleLearnAllCraftsCommand(ChatHandler* handler)
|
||||
{
|
||||
Player* target = handler->GetSession()->GetPlayer();
|
||||
|
||||
for (uint32 i = 0; i < sSkillLineStore.GetNumRows(); ++i)
|
||||
{
|
||||
SkillLineEntry const* skillInfo = sSkillLineStore.LookupEntry(i);
|
||||
@@ -318,7 +320,10 @@ public:
|
||||
if ((skillInfo->categoryId == SKILL_CATEGORY_PROFESSION || skillInfo->categoryId == SKILL_CATEGORY_SECONDARY) &&
|
||||
skillInfo->canLink) // only prof. with recipes have
|
||||
{
|
||||
HandleLearnSkillRecipesHelper(handler->GetSession()->GetPlayer(), skillInfo->id);
|
||||
HandleLearnSkillRecipesHelper(target, skillInfo->id);
|
||||
|
||||
uint16 const maxLevel = target->GetPureMaxSkillValue(skillInfo->id);
|
||||
target->SetSkill(skillInfo->id, target->GetSkillStep(skillInfo->id), maxLevel, maxLevel);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -388,6 +393,15 @@ public:
|
||||
|
||||
static void HandleLearnSkillRecipesHelper(Player* player, uint32 skillId)
|
||||
{
|
||||
// Rank spells (Apprentice -> Grand Master) must be learned so that the
|
||||
// skill-cleanup loop in Player::SetSkill (which calls removeSpell on the
|
||||
// first spell in each chain) can walk forward and strip every rank on
|
||||
// profession unlearn. Without the first rank in the spellbook that loop
|
||||
// bails out and the leftover rank spells re-grant the skill after relog
|
||||
// (issue #2330).
|
||||
for (uint32 rankSpell : sSpellMgr->GetSkillRankSpells(skillId))
|
||||
player->learnSpell(rankSpell);
|
||||
|
||||
uint32 classmask = player->getClassMask();
|
||||
|
||||
for (SkillLineAbilityEntry const* skillLine : GetSkillLineAbilitiesBySkillLine(skillId))
|
||||
|
||||
Reference in New Issue
Block a user