/* * Copyright (C) 2016+ AzerothCore , released under GNU GPL v2 license: http://github.com/azerothcore/azerothcore-wotlk/LICENSE-GPL2 * Copyright (C) 2008-2016 TrinityCore * Copyright (C) 2005-2009 MaNGOS */ /* ScriptData Name: learn_commandscript %Complete: 100 Comment: All learn related commands Category: commandscripts EndScriptData */ #include "Chat.h" #include "ScriptMgr.h" #include "ObjectMgr.h" #include "Language.h" #include "SpellMgr.h" #include "SpellInfo.h" #include "Player.h" #include "Pet.h" class learn_commandscript : public CommandScript { public: learn_commandscript() : CommandScript("learn_commandscript") { } std::vector GetCommands() const override { static std::vector learnAllMyCommandTable = { { "class", SEC_ADMINISTRATOR, false, &HandleLearnAllMyClassCommand, "" }, { "pettalents", SEC_ADMINISTRATOR, false, &HandleLearnAllMyPetTalentsCommand, "" }, { "spells", SEC_ADMINISTRATOR, false, &HandleLearnAllMySpellsCommand, "" }, { "talents", SEC_ADMINISTRATOR, false, &HandleLearnAllMyTalentsCommand, "" }, { NULL, 0, false, NULL, "" } }; static std::vector learnAllCommandTable = { { "my", SEC_ADMINISTRATOR, false, NULL, "", learnAllMyCommandTable }, { "gm", SEC_GAMEMASTER, false, &HandleLearnAllGMCommand, "" }, { "crafts", SEC_GAMEMASTER, false, &HandleLearnAllCraftsCommand, "" }, { "default", SEC_GAMEMASTER, false, &HandleLearnAllDefaultCommand, "" }, { "lang", SEC_GAMEMASTER, false, &HandleLearnAllLangCommand, "" }, { "recipes", SEC_GAMEMASTER, false, &HandleLearnAllRecipesCommand, "" }, { NULL, 0, false, NULL, "" } }; static std::vector learnCommandTable = { { "all", SEC_ADMINISTRATOR, false, NULL, "", learnAllCommandTable }, { "", SEC_ADMINISTRATOR, false, &HandleLearnCommand, "" }, { NULL, 0, false, NULL, "" } }; static std::vector commandTable = { { "learn", SEC_GAMEMASTER, false, NULL, "", learnCommandTable }, { "unlearn", SEC_ADMINISTRATOR, false, &HandleUnLearnCommand, "" }, { NULL, 0, false, NULL, "" } }; return commandTable; } static bool HandleLearnCommand(ChatHandler* handler, char const* args) { Player* targetPlayer = handler->getSelectedPlayer(); if (!targetPlayer) { handler->SendSysMessage(LANG_PLAYER_NOT_FOUND); handler->SetSentErrorMessage(true); return false; } // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form uint32 spell = handler->extractSpellIdFromLink((char*)args); if (!spell) return false; SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell); if (!spellInfo) { handler->PSendSysMessage(LANG_COMMAND_NOSPELLFOUND); handler->SetSentErrorMessage(true); return false; } if (!SpellMgr::IsSpellValid(spellInfo)) { handler->PSendSysMessage(LANG_COMMAND_SPELL_BROKEN, spell); handler->SetSentErrorMessage(true); return false; } SpellScriptsBounds bounds = sObjectMgr->GetSpellScriptsBounds(spell); uint32 spellDifficultyId = sSpellMgr->GetSpellDifficultyId(spell); if (handler->GetSession()->GetSecurity() < SEC_CONSOLE && (bounds.first != bounds.second || spellDifficultyId)) { handler->PSendSysMessage("Spell %u cannot be learnt using a command!", spell); handler->SetSentErrorMessage(true); return false; } char const* all = strtok(NULL, " "); bool allRanks = all ? (strncmp(all, "all", strlen(all)) == 0) : false; if (!allRanks && targetPlayer->HasSpell(spell)) { if (targetPlayer == handler->GetSession()->GetPlayer()) handler->SendSysMessage(LANG_YOU_KNOWN_SPELL); else handler->PSendSysMessage(LANG_TARGET_KNOWN_SPELL, handler->GetNameLink(targetPlayer).c_str()); handler->SetSentErrorMessage(true); return false; } if (allRanks) targetPlayer->learnSpellHighRank(spell); else targetPlayer->learnSpell(spell); uint32 firstSpell = sSpellMgr->GetFirstSpellInChain(spell); if (GetTalentSpellCost(firstSpell)) targetPlayer->SendTalentsInfoData(false); return true; } static bool HandleLearnAllGMCommand(ChatHandler* handler, char const* /*args*/) { 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, char const* /*args*/) { HandleLearnAllMySpellsCommand(handler, ""); HandleLearnAllMyTalentsCommand(handler, ""); return true; } static bool HandleLearnAllMySpellsCommand(ChatHandler* handler, char const* /*args*/) { 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->spellId); 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, char const* /*args*/) { 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); } handler->SendSysMessage(LANG_COMMAND_LEARN_CLASS_TALENTS); return true; } static bool HandleLearnAllMyPetTalentsCommand(ChatHandler* handler, char const* /*args*/) { Player* player = handler->GetSession()->GetPlayer(); Pet* pet = player->GetPet(); if (!pet) { handler->SendSysMessage(LANG_NO_PET_FOUND); handler->SetSentErrorMessage(true); return false; } CreatureTemplate const* creatureInfo = pet->GetCreatureTemplate(); if (!creatureInfo) { handler->SendSysMessage(LANG_WRONG_PET_TYPE); handler->SetSentErrorMessage(true); return false; } CreatureFamilyEntry const* petFamily = sCreatureFamilyStore.LookupEntry(creatureInfo->family); if (!petFamily) { handler->SendSysMessage(LANG_WRONG_PET_TYPE); handler->SetSentErrorMessage(true); return false; } if (petFamily->petTalentType < 0) // not hunter pet { handler->SendSysMessage(LANG_WRONG_PET_TYPE); handler->SetSentErrorMessage(true); 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, char const* /*args*/) { // skipping UNIVERSAL language (0) for (uint8 i = 1; i < LANGUAGES_COUNT; ++i) handler->GetSession()->GetPlayer()->learnSpell(lang_description[i].spell_id); handler->SendSysMessage(LANG_COMMAND_LEARN_ALL_LANG); return true; } static bool HandleLearnAllDefaultCommand(ChatHandler* handler, char const* args) { Player* target; if (!handler->extractPlayerTarget((char*)args, &target)) return false; target->learnDefaultSpells(); target->learnQuestRewardedSpells(); handler->PSendSysMessage(LANG_COMMAND_LEARN_ALL_DEFAULT_AND_QUEST, handler->GetNameLink(target).c_str()); return true; } static bool HandleLearnAllCraftsCommand(ChatHandler* handler, char const* /*args*/) { 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, char const* args) { // 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 (!*args) return false; std::wstring namePart; if (!Utf8toWStr(args, namePart)) return false; // converting string that we try to find to lower case wstrToLower(namePart); std::string name; SkillLineEntry const* targetSkillInfo = NULL; 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; int locale = handler->GetSessionDbcLocale(); name = skillInfo->name[locale]; if (name.empty()) continue; if (!Utf8FitTo(name, namePart)) { locale = 0; for (; locale < TOTAL_LOCALES; ++locale) { if (locale == handler->GetSessionDbcLocale()) continue; name = skillInfo->name[locale]; if (name.empty()) continue; if (Utf8FitTo(name, namePart)) break; } } if (locale < TOTAL_LOCALES) { targetSkillInfo = skillInfo; break; } } if (!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.c_str()); return true; } static void HandleLearnSkillRecipesHelper(Player* player, uint32 skillId) { uint32 classmask = player->getClassMask(); for (uint32 j = 0; j < sSkillLineAbilityStore.GetNumRows(); ++j) { SkillLineAbilityEntry const* skillLine = sSkillLineAbilityStore.LookupEntry(j); if (!skillLine) continue; // wrong skill if (skillLine->skillId != skillId) continue; // not high rank if (skillLine->forward_spellid) 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->spellId); if (!spellInfo || !SpellMgr::IsSpellValid(spellInfo)) continue; player->learnSpell(skillLine->spellId); } } static bool HandleUnLearnCommand(ChatHandler* handler, char const* args) { if (!*args) return false; // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r uint32 spellId = handler->extractSpellIdFromLink((char*)args); if (!spellId) return false; char const* allStr = strtok(NULL, " "); bool allRanks = allStr ? (strncmp(allStr, "all", strlen(allStr)) == 0) : false; Player* target = handler->getSelectedPlayer(); if (!target) { handler->SendSysMessage(LANG_NO_CHAR_SELECTED); handler->SetSentErrorMessage(true); return false; } if (allRanks) spellId = sSpellMgr->GetFirstSpellInChain (spellId); if (target->HasSpell(spellId)) target->removeSpell(spellId, SPEC_MASK_ALL, false); else handler->SendSysMessage(LANG_FORGET_SPELL); if (GetTalentSpellCost(spellId)) target->SendTalentsInfoData(false); return true; } }; void AddSC_learn_commandscript() { new learn_commandscript(); }