Fix wrong logic when processing quest reward spells during maintenance level-up action (#2001)

The previous behavior failed cuz if a spell has no
`SPELL_EFFECT_LEARN_SPELL`, bots learned the original spell from
`quest_template` rewards w/o any checks, when they should never learn
any spells specified in the `RewardSpell` and/or `RewardDisplaySpell`.

PR: https://github.com/mod-playerbots/mod-playerbots/pull/1996 Thx
@Wishmaster117 for the collaboration!

Fix issue https://github.com/mod-playerbots/mod-playerbots/issues/1759
This commit is contained in:
privatecore
2026-01-10 01:31:54 +01:00
committed by GitHub
parent 59d6eb139e
commit dc55ecfd9c

View File

@@ -90,18 +90,25 @@ void AutoMaintenanceOnLevelupAction::LearnQuestSpells(std::ostringstream* out)
//uint32 questId = i->first; //not used, line marked for removal. //uint32 questId = i->first; //not used, line marked for removal.
Quest const* quest = i->second; Quest const* quest = i->second;
if (!quest->GetRequiredClasses() || quest->IsRepeatable() || quest->GetMinLevel() < 10) // only process class-specific quests to learn class-related spells, cuz
// we don't want all these bunch of entries to be handled!
if (!quest->GetRequiredClasses())
continue; continue;
if (!bot->SatisfyQuestClass(quest, false) || quest->GetMinLevel() > bot->GetLevel() || // skip quests that are repeatable, too low level, or above bots' level
!bot->SatisfyQuestRace(quest, false)) if (quest->IsRepeatable() || quest->GetMinLevel() < 10 || quest->GetMinLevel() > bot->GetLevel())
continue; continue;
if (quest->GetRewSpellCast() > 0) // skip if bot doesnt satisfy class, race, or skill requirements
if (!bot->SatisfyQuestClass(quest, false) || !bot->SatisfyQuestRace(quest, false) ||
!bot->SatisfyQuestSkill(quest, false))
continue;
if (quest->GetRewSpellCast() > 0) // RewardSpell - expected route
{ {
LearnSpell(quest->GetRewSpellCast(), out); LearnSpell(quest->GetRewSpellCast(), out);
} }
else if (quest->GetRewSpell() > 0) else if (quest->GetRewSpell() > 0) // RewardDisplaySpell - fallback
{ {
LearnSpell(quest->GetRewSpell(), out); LearnSpell(quest->GetRewSpell(), out);
} }
@@ -123,35 +130,37 @@ std::string const AutoMaintenanceOnLevelupAction::FormatSpell(SpellInfo const* s
void AutoMaintenanceOnLevelupAction::LearnSpell(uint32 spellId, std::ostringstream* out) void AutoMaintenanceOnLevelupAction::LearnSpell(uint32 spellId, std::ostringstream* out)
{ {
SpellInfo const* proto = sSpellMgr->GetSpellInfo(spellId); SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
if (!proto) if (!spellInfo)
return; return;
bool learned = false; SpellInfo const* triggeredInfo;
for (uint8 j = 0; j < 3; ++j)
{
if (proto->Effects[j].Effect == SPELL_EFFECT_LEARN_SPELL)
{
uint32 learnedSpell = proto->Effects[j].TriggerSpell;
if (!bot->HasSpell(learnedSpell)) // find effect with learn spell and check if we have this spell
bool found = false;
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
{ {
bot->learnSpell(learnedSpell); if (spellInfo->Effects[i].Effect == SPELL_EFFECT_LEARN_SPELL && spellInfo->Effects[i].TriggerSpell &&
*out << FormatSpell(sSpellMgr->GetSpellInfo(learnedSpell)) << ", "; !bot->HasSpell(spellInfo->Effects[i].TriggerSpell))
} {
triggeredInfo = sSpellMgr->GetSpellInfo(spellInfo->Effects[i].TriggerSpell);
learned = true; // do not learn profession specialties!
if (!triggeredInfo || triggeredInfo->Effects[0].Effect == SPELL_EFFECT_TRADE_SKILL)
break;
found = true;
break;
} }
} }
if (!learned) if (!found)
{ return;
if (!bot->HasSpell(spellId))
{ // NOTE: When rewarding quests, core casts spells instead of learning them,
bot->learnSpell(spellId); // but we sacrifice safe cast checks here in favor of performance/speed
*out << FormatSpell(proto) << ", "; bot->learnSpell(triggeredInfo->Id);
} *out << FormatSpell(triggeredInfo) << ", ";
}
} }
void AutoMaintenanceOnLevelupAction::AutoUpgradeEquip() void AutoMaintenanceOnLevelupAction::AutoUpgradeEquip()