refactor(Script/Command): learn spell (#24319)
Co-authored-by: Treeston <14020072+Treeston@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
parent
b90c917b49
commit
e6054ec7ea
6 changed files with 71 additions and 43 deletions
|
|
@ -0,0 +1,8 @@
|
|||
--
|
||||
DELETE FROM `command` WHERE `name`='learn all my quest';
|
||||
DELETE FROM `command` WHERE `name`='learn all my trainer';
|
||||
DELETE FROM `command` WHERE `name`='learn all my spells';
|
||||
INSERT INTO `command` (`name`, `security`, `help`) VALUES
|
||||
('learn all my quest', 2, 'Syntax: .learn all my quest Learn all spells rewarded from quest for your class.'),
|
||||
('learn all my trainer', 2, 'Syntax: .learn all my trainer Learn all spells taught by trainers for your class.');
|
||||
UPDATE `command` SET `help` = 'Syntax: .learn all my class Learn all spells (trainer, talent, and quest rewards) for your class.' WHERE `name`='learn all my class';
|
||||
|
|
@ -130,7 +130,7 @@ namespace Trainer
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
bool Trainer::CanTeachSpell(Player const* player, Spell const* trainerSpell)
|
||||
bool Trainer::CanTeachSpell(Player const* player, Spell const* trainerSpell) const
|
||||
{
|
||||
SpellState state = GetSpellState(player, trainerSpell);
|
||||
if (state != SpellState::Available)
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ namespace Trainer
|
|||
[[nodiscard]] Spell const* GetSpell(uint32 spellId) const;
|
||||
[[nodiscard]] std::vector<Spell> const& GetSpells() const { return _spells; }
|
||||
void SendSpells(Creature* npc, Player* player, LocaleConstant locale) const;
|
||||
bool CanTeachSpell(Player const* player, Spell const* trainerSpell);
|
||||
bool CanTeachSpell(Player const* player, Spell const* trainerSpell) const;
|
||||
void TeachSpell(Creature* npc, Player* player, uint32 spellId);
|
||||
|
||||
[[nodiscard]] Type GetTrainerType() const { return _type; }
|
||||
|
|
|
|||
|
|
@ -9719,6 +9719,7 @@ void ObjectMgr::LoadTrainers()
|
|||
|
||||
// For reload case
|
||||
_trainers.clear();
|
||||
_classTrainers.clear();
|
||||
|
||||
std::unordered_map<int32, std::vector<Trainer::Spell>> spellsByTrainer;
|
||||
if (QueryResult trainerSpellsResult = WorldDatabase.Query("SELECT TrainerId, SpellId, MoneyCost, ReqSkillLine, ReqSkillRank, ReqAbility1, ReqAbility2, ReqAbility3, ReqLevel FROM trainer_spell"))
|
||||
|
|
@ -9795,7 +9796,18 @@ void ObjectMgr::LoadTrainers()
|
|||
spellsByTrainer.erase(spellsItr);
|
||||
}
|
||||
|
||||
_trainers.emplace(std::piecewise_construct, std::forward_as_tuple(trainerId), std::forward_as_tuple(trainerId, trainerType, requirement, std::move(greeting), std::move(spells)));
|
||||
auto [it, isNew] = _trainers.emplace(std::piecewise_construct, std::forward_as_tuple(trainerId), std::forward_as_tuple(trainerId, trainerType, requirement, std::move(greeting), std::move(spells)));
|
||||
ASSERT(isNew);
|
||||
if (trainerType == Trainer::Type::Class)
|
||||
{
|
||||
if (!requirement || requirement >= MAX_CLASSES)
|
||||
LOG_ERROR("sql.sql", "Table `trainer` has invalid class requirement for trainer {}, ignoring");
|
||||
else
|
||||
{
|
||||
uint8 classId = static_cast<uint8>(requirement);
|
||||
_classTrainers[classId].push_back(&it->second);
|
||||
}
|
||||
}
|
||||
} while (trainersResult->NextRow());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1418,6 +1418,7 @@ public:
|
|||
bool DeleteGameTele(std::string_view name);
|
||||
|
||||
Trainer::Trainer* GetTrainer(uint32 creatureId);
|
||||
std::vector<Trainer::Trainer const*> const& GetClassTrainers(uint8 classId) const { return _classTrainers.at(classId); }
|
||||
|
||||
[[nodiscard]] VendorItemData const* GetNpcVendorItemList(uint32 entry) const
|
||||
{
|
||||
|
|
@ -1666,6 +1667,7 @@ private:
|
|||
|
||||
CacheVendorItemContainer _cacheVendorItemStore;
|
||||
std::unordered_map<uint32, Trainer::Trainer> _trainers;
|
||||
std::unordered_map<uint8, std::vector<Trainer::Trainer const*>> _classTrainers;
|
||||
std::unordered_map<uint32, uint32> _creatureDefaultTrainers;
|
||||
|
||||
std::set<uint32> _difficultyEntries[MAX_DIFFICULTY - 1]; // already loaded difficulty 1 value in creatures, used in CheckCreatureTemplate
|
||||
|
|
|
|||
|
|
@ -37,8 +37,9 @@ public:
|
|||
{
|
||||
{ "class", HandleLearnAllMyClassCommand, SEC_GAMEMASTER, Console::No },
|
||||
{ "pettalents", HandleLearnAllMyPetTalentsCommand, SEC_GAMEMASTER, Console::No },
|
||||
{ "spells", HandleLearnAllMySpellsCommand, SEC_GAMEMASTER, Console::No },
|
||||
{ "talents", HandleLearnAllMyTalentsCommand, SEC_GAMEMASTER, Console::No }
|
||||
{ "trainer", HandleLearnAllMyTrainerSpellsCommand, SEC_GAMEMASTER, Console::No },
|
||||
{ "talents", HandleLearnAllMyTalentsCommand, SEC_GAMEMASTER, Console::No },
|
||||
{ "quest", HandleLearnAllMyQuestSpells, SEC_GAMEMASTER, Console::No }
|
||||
};
|
||||
|
||||
static ChatCommandTable learnAllCommandTable =
|
||||
|
|
@ -98,52 +99,57 @@ public:
|
|||
|
||||
static bool HandleLearnAllMyClassCommand(ChatHandler* handler)
|
||||
{
|
||||
HandleLearnAllMySpellsCommand(handler);
|
||||
HandleLearnAllMyTrainerSpellsCommand(handler);
|
||||
HandleLearnAllMyTalentsCommand(handler);
|
||||
HandleLearnAllMyQuestSpells(handler);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool HandleLearnAllMySpellsCommand(ChatHandler* handler)
|
||||
static bool HandleLearnAllMyQuestSpells(ChatHandler* handler)
|
||||
{
|
||||
ChrClassesEntry const* classEntry = sChrClassesStore.LookupEntry(handler->GetSession()->GetPlayer()->getClass());
|
||||
if (!classEntry)
|
||||
return true;
|
||||
uint32 family = classEntry->spellfamily;
|
||||
|
||||
for (uint32 i = 0; i < sSkillLineAbilityStore.GetNumRows(); ++i)
|
||||
Player* player = handler->GetPlayer();
|
||||
for (auto const& questPair : sObjectMgr->GetQuestTemplates())
|
||||
{
|
||||
SkillLineAbilityEntry const* entry = sSkillLineAbilityStore.LookupEntry(i);
|
||||
if (!entry)
|
||||
continue;
|
||||
|
||||
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(entry->Spell);
|
||||
if (!spellInfo)
|
||||
continue;
|
||||
|
||||
// skip server-side/triggered spells
|
||||
if (spellInfo->SpellLevel == 0)
|
||||
continue;
|
||||
|
||||
// skip wrong class/race skills
|
||||
if (!handler->GetSession()->GetPlayer()->IsSpellFitByClassAndRace(spellInfo->Id))
|
||||
continue;
|
||||
|
||||
// skip other spell families
|
||||
if (spellInfo->SpellFamilyName != family)
|
||||
continue;
|
||||
|
||||
// skip spells with first rank learned as talent (and all talents then also)
|
||||
uint32 firstRank = sSpellMgr->GetFirstSpellInChain(spellInfo->Id);
|
||||
if (GetTalentSpellCost(firstRank) > 0)
|
||||
continue;
|
||||
|
||||
// skip broken spells
|
||||
if (!SpellMgr::IsSpellValid(spellInfo))
|
||||
continue;
|
||||
|
||||
handler->GetSession()->GetPlayer()->learnSpell(spellInfo->Id);
|
||||
Quest const* quest = questPair.second;
|
||||
if (quest->GetRequiredClasses() && player->SatisfyQuestClass(quest, false))
|
||||
player->learnQuestRewardedSpells(quest);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool HandleLearnAllMyTrainerSpellsCommand(ChatHandler* handler)
|
||||
{
|
||||
if (!sChrClassesStore.LookupEntry(handler->GetSession()->GetPlayer()->getClass()))
|
||||
return true;
|
||||
|
||||
Player* player = handler->GetPlayer();
|
||||
std::vector<Trainer::Trainer const*> const& trainers = sObjectMgr->GetClassTrainers(player->getClass());
|
||||
|
||||
bool hadNew;
|
||||
do
|
||||
{
|
||||
hadNew = false;
|
||||
for (Trainer::Trainer const* trainer : trainers)
|
||||
{
|
||||
if (!trainer->IsTrainerValidForPlayer(player))
|
||||
continue;
|
||||
|
||||
for (Trainer::Spell const& trainerSpell : trainer->GetSpells())
|
||||
{
|
||||
if (!trainer->CanTeachSpell(player, &trainerSpell))
|
||||
continue;
|
||||
|
||||
if (trainerSpell.IsCastable())
|
||||
player->CastSpell(player, trainerSpell.SpellId, true);
|
||||
else
|
||||
player->learnSpell(trainerSpell.SpellId, false);
|
||||
|
||||
hadNew = true;
|
||||
}
|
||||
}
|
||||
} while (hadNew);
|
||||
|
||||
handler->SendSysMessage(LANG_COMMAND_LEARN_CLASS_SPELLS);
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue