summaryrefslogtreecommitdiff
path: root/src/scripts/Commands/cs_learn.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/scripts/Commands/cs_learn.cpp')
-rw-r--r--src/scripts/Commands/cs_learn.cpp528
1 files changed, 528 insertions, 0 deletions
diff --git a/src/scripts/Commands/cs_learn.cpp b/src/scripts/Commands/cs_learn.cpp
new file mode 100644
index 0000000000..5fd16c6f1a
--- /dev/null
+++ b/src/scripts/Commands/cs_learn.cpp
@@ -0,0 +1,528 @@
+/*
+ * Copyright (C)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 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 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 <http://www.gnu.org/licenses/>.
+ */
+
+/* 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") { }
+
+ ChatCommand* GetCommands() const
+ {
+ static ChatCommand learnAllMyCommandTable[] =
+ {
+ { "class", SEC_ADMINISTRATOR, false, &HandleLearnAllMyClassCommand, "", NULL },
+ { "pettalents", SEC_ADMINISTRATOR, false, &HandleLearnAllMyPetTalentsCommand, "", NULL },
+ { "spells", SEC_ADMINISTRATOR, false, &HandleLearnAllMySpellsCommand, "", NULL },
+ { "talents", SEC_ADMINISTRATOR, false, &HandleLearnAllMyTalentsCommand, "", NULL },
+ { NULL, 0, false, NULL, "", NULL }
+ };
+
+ static ChatCommand learnAllCommandTable[] =
+ {
+ { "my", SEC_ADMINISTRATOR, false, NULL, "", learnAllMyCommandTable },
+ { "gm", SEC_GAMEMASTER, false, &HandleLearnAllGMCommand, "", NULL },
+ { "crafts", SEC_GAMEMASTER, false, &HandleLearnAllCraftsCommand, "", NULL },
+ { "default", SEC_GAMEMASTER, false, &HandleLearnAllDefaultCommand, "", NULL },
+ { "lang", SEC_GAMEMASTER, false, &HandleLearnAllLangCommand, "", NULL },
+ { "recipes", SEC_GAMEMASTER, false, &HandleLearnAllRecipesCommand, "", NULL },
+ { NULL, 0, false, NULL, "", NULL }
+ };
+
+ static ChatCommand learnCommandTable[] =
+ {
+ { "all", SEC_ADMINISTRATOR, false, NULL, "", learnAllCommandTable },
+ { "", SEC_ADMINISTRATOR, false, &HandleLearnCommand, "", NULL },
+ { NULL, 0, false, NULL, "", NULL }
+ };
+
+ static ChatCommand commandTable[] =
+ {
+ { "learn", SEC_GAMEMASTER, false, NULL, "", learnCommandTable },
+ { "unlearn", SEC_ADMINISTRATOR, false, &HandleUnLearnCommand, "", NULL },
+ { NULL, 0, false, NULL, "", 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();
+}