/* * This file is part of the AzerothCore Project. See AUTHORS file for Copyright information * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU Affero General Public License as published by the * Free Software Foundation; either version 3 of the License, or (at your * option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for * more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ #include "CommandScript.h" #include "Language.h" #include "ObjectMgr.h" #include "Pet.h" #include "Player.h" #include "PlayerCommand.h" #include "SpellInfo.h" #include "SpellMgr.h" using namespace Acore::ChatCommands; class learn_commandscript : public CommandScript { public: learn_commandscript() : CommandScript("learn_commandscript") { } ChatCommandTable GetCommands() const override { static ChatCommandTable learnAllMyCommandTable = { { "class", HandleLearnAllMyClassCommand, SEC_GAMEMASTER, Console::No }, { "pettalents", HandleLearnAllMyPetTalentsCommand, SEC_GAMEMASTER, Console::No }, { "spells", HandleLearnAllMySpellsCommand, SEC_GAMEMASTER, Console::No }, { "talents", HandleLearnAllMyTalentsCommand, SEC_GAMEMASTER, Console::No } }; static ChatCommandTable learnAllCommandTable = { { "my", learnAllMyCommandTable }, { "gm", HandleLearnAllGMCommand, SEC_GAMEMASTER, Console::No }, { "crafts", HandleLearnAllCraftsCommand, SEC_GAMEMASTER, Console::No }, { "default", HandleLearnAllDefaultCommand, SEC_GAMEMASTER, Console::No }, { "lang", HandleLearnAllLangCommand, SEC_GAMEMASTER, Console::No }, { "recipes", HandleLearnAllRecipesCommand, SEC_GAMEMASTER, Console::No }, }; static ChatCommandTable learnCommandTable = { { "all", learnAllCommandTable }, { "", HandleLearnCommand, SEC_GAMEMASTER, Console::No } }; static ChatCommandTable commandTable = { { "learn", learnCommandTable }, { "unlearn", HandleUnLearnCommand, SEC_GAMEMASTER, Console::No } }; return commandTable; } static bool HandleLearnCommand(ChatHandler* handler, SpellInfo const* spell, Optional allRanks) { Player* targetPlayer = handler->getSelectedPlayer(); if (!targetPlayer) { handler->SendErrorMessage(LANG_PLAYER_NOT_FOUND); return false; } return Acore::PlayerCommand::HandleLearnSpellCommand(handler, targetPlayer, spell, allRanks); } static bool HandleLearnAllGMCommand(ChatHandler* handler) { for (uint32 i = 0; i < sSpellMgr->GetSpellInfoStoreSize(); ++i) { SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(i); if (!spellInfo || !SpellMgr::IsSpellValid(spellInfo)) continue; if (!spellInfo->IsAbilityOfSkillType(SKILL_INTERNAL)) continue; handler->GetSession()->GetPlayer()->learnSpell(i); } handler->SendSysMessage(LANG_LEARNING_GM_SKILLS); return true; } static bool HandleLearnAllMyClassCommand(ChatHandler* handler) { HandleLearnAllMySpellsCommand(handler); HandleLearnAllMyTalentsCommand(handler); return true; } static bool HandleLearnAllMySpellsCommand(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) { 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); } handler->SendSysMessage(LANG_COMMAND_LEARN_CLASS_SPELLS); return true; } static bool HandleLearnAllMyTalentsCommand(ChatHandler* handler) { Player* player = handler->GetSession()->GetPlayer(); uint32 classMask = player->getClassMask(); for (uint32 i = 0; i < sTalentStore.GetNumRows(); ++i) { TalentEntry const* talentInfo = sTalentStore.LookupEntry(i); if (!talentInfo) continue; TalentTabEntry const* talentTabInfo = sTalentTabStore.LookupEntry(talentInfo->TalentTab); if (!talentTabInfo) continue; if ((classMask & talentTabInfo->ClassMask) == 0) continue; // xinef: search highest talent rank uint32 spellId = 0; uint8 rankId = MAX_TALENT_RANK; for (int8 rank = MAX_TALENT_RANK - 1; rank >= 0; --rank) { if (talentInfo->RankID[rank] != 0) { rankId = rank; spellId = talentInfo->RankID[rank]; break; } } // xinef: some errors? if (!spellId || rankId == MAX_TALENT_RANK) continue; SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); if (!spellInfo || !SpellMgr::IsSpellValid(spellInfo)) continue; player->LearnTalent(talentInfo->TalentID, rankId, true); } player->SetFreeTalentPoints(0); player->SendTalentsInfoData(false); handler->SendSysMessage(LANG_COMMAND_LEARN_CLASS_TALENTS); return true; } static bool HandleLearnAllMyPetTalentsCommand(ChatHandler* handler) { Player* player = handler->GetSession()->GetPlayer(); Pet* pet = player->GetPet(); if (!pet) { handler->SendErrorMessage(LANG_NO_PET_FOUND); return false; } CreatureTemplate const* creatureInfo = pet->GetCreatureTemplate(); if (!creatureInfo) { handler->SendErrorMessage(LANG_WRONG_PET_TYPE); return false; } CreatureFamilyEntry const* petFamily = sCreatureFamilyStore.LookupEntry(creatureInfo->family); if (!petFamily) { handler->SendErrorMessage(LANG_WRONG_PET_TYPE); return false; } if (petFamily->petTalentType < 0) // not hunter pet { handler->SendErrorMessage(LANG_WRONG_PET_TYPE); return false; } for (uint32 i = 0; i < sTalentStore.GetNumRows(); ++i) { TalentEntry const* talentInfo = sTalentStore.LookupEntry(i); if (!talentInfo) continue; TalentTabEntry const* talentTabInfo = sTalentTabStore.LookupEntry(talentInfo->TalentTab); if (!talentTabInfo) continue; // prevent learn talent for different family (cheating) if (((1 << petFamily->petTalentType) & talentTabInfo->petTalentMask) == 0) continue; // search highest talent rank uint32 spellId = 0; for (int8 rank = MAX_TALENT_RANK - 1; rank >= 0; --rank) { if (talentInfo->RankID[rank] != 0) { spellId = talentInfo->RankID[rank]; break; } } if (!spellId) // ??? none spells in talent continue; SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); if (!spellInfo || !SpellMgr::IsSpellValid(spellInfo)) continue; // learn highest rank of talent and learn all non-talent spell ranks (recursive by tree) pet->learnSpellHighRank(spellId); } pet->SetFreeTalentPoints(0); handler->SendSysMessage(LANG_COMMAND_LEARN_PET_TALENTS); return true; } static bool HandleLearnAllLangCommand(ChatHandler* handler) { for (LanguageDesc const& langDesc : lang_description) if (uint32 langSpellId = langDesc.spell_id) { handler->GetPlayer()->learnSpell(langSpellId); handler->GetPlayer()->SetSkill(langDesc.skill_id, 0, 300, 300); } handler->SendSysMessage(LANG_COMMAND_LEARN_ALL_LANG); return true; } static bool HandleLearnAllDefaultCommand(ChatHandler* handler, Optional player) { if (!player) player = PlayerIdentifier::FromTargetOrSelf(handler); if (!player || !player->IsConnected()) return false; Player* target = player->GetConnectedPlayer(); target->LearnDefaultSkills(); target->LearnCustomSpells(); target->learnQuestRewardedSpells(); handler->PSendSysMessage(LANG_COMMAND_LEARN_ALL_DEFAULT_AND_QUEST, handler->GetNameLink(target)); return true; } static bool HandleLearnAllCraftsCommand(ChatHandler* handler) { for (uint32 i = 0; i < sSkillLineStore.GetNumRows(); ++i) { SkillLineEntry const* skillInfo = sSkillLineStore.LookupEntry(i); if (!skillInfo) continue; if ((skillInfo->categoryId == SKILL_CATEGORY_PROFESSION || skillInfo->categoryId == SKILL_CATEGORY_SECONDARY) && skillInfo->canLink) // only prof. with recipes have { HandleLearnSkillRecipesHelper(handler->GetSession()->GetPlayer(), skillInfo->id); } } handler->SendSysMessage(LANG_COMMAND_LEARN_ALL_CRAFT); return true; } static bool HandleLearnAllRecipesCommand(ChatHandler* handler, WTail namePart) { // Learns all recipes of specified profession and sets skill to max // Example: .learn all_recipes enchanting Player* target = handler->getSelectedPlayer(); if (!target) { handler->SendSysMessage(LANG_PLAYER_NOT_FOUND); return false; } if (namePart.empty()) return false; // converting string that we try to find to lower case wstrToLower(namePart); SkillLineEntry const* targetSkillInfo = nullptr; char const* name = nullptr; for (uint32 i = 1; i < sSkillLineStore.GetNumRows(); ++i) { SkillLineEntry const* skillInfo = sSkillLineStore.LookupEntry(i); if (!skillInfo) continue; if ((skillInfo->categoryId != SKILL_CATEGORY_PROFESSION && skillInfo->categoryId != SKILL_CATEGORY_SECONDARY) || !skillInfo->canLink) // only prof with recipes have set continue; uint8 locale = 0; for (; locale < TOTAL_LOCALES; ++locale) { name = skillInfo->name[locale]; if (!name || !*name) continue; if (Utf8FitTo(name, namePart)) break; } if (locale < TOTAL_LOCALES) { targetSkillInfo = skillInfo; break; } } if (!(name && targetSkillInfo)) return false; HandleLearnSkillRecipesHelper(target, targetSkillInfo->id); uint16 maxLevel = target->GetPureMaxSkillValue(targetSkillInfo->id); target->SetSkill(targetSkillInfo->id, target->GetSkillStep(targetSkillInfo->id), maxLevel, maxLevel); handler->PSendSysMessage(LANG_COMMAND_LEARN_ALL_RECIPES, name); return true; } static void HandleLearnSkillRecipesHelper(Player* player, uint32 skillId) { uint32 classmask = player->getClassMask(); for (SkillLineAbilityEntry const* skillLine : GetSkillLineAbilitiesBySkillLine(skillId)) { // not high rank if (skillLine->SupercededBySpell) continue; // skip racial skills if (skillLine->RaceMask != 0) continue; // skip wrong class skills if (skillLine->ClassMask && (skillLine->ClassMask & classmask) == 0) continue; SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(skillLine->Spell); if (!spellInfo || !SpellMgr::IsSpellValid(spellInfo)) continue; player->learnSpell(skillLine->Spell); } } static bool HandleUnLearnCommand(ChatHandler* handler, SpellInfo const* spell, Optional allRanks) { Player* target = handler->getSelectedPlayer(); if (!target) { handler->SendErrorMessage(LANG_NO_CHAR_SELECTED); return false; } return Acore::PlayerCommand::HandleUnlearnSpellCommand(handler, target, spell, allRanks); } }; void AddSC_learn_commandscript() { new learn_commandscript(); }