Files
TrinityCore/src/server/scripts/Commands/cs_learn.cpp

1115 lines
30 KiB
C++

/*
* Copyright (C) 2008-2010 TrinityCore <http://www.trinitycore.org/>
*
* 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 "ScriptMgr.h"
#include "ObjectMgr.h"
#include "SpellMgr.h"
#include "Chat.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_MODERATOR, false, &HandleLearnAllDefaultCommand, "", NULL },
{ "lang", SEC_MODERATOR, false, &HandleLearnAllLangCommand, "", NULL },
{ "recipes", SEC_GAMEMASTER, false, &HandleLearnAllRecipesCommand, "", NULL },
{ "", SEC_ADMINISTRATOR, false, &HandleLearnAllCommand, "", 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_MODERATOR, false, NULL, "", learnCommandTable },
{ NULL, 0, false, NULL, "", NULL }
};
return commandTable;
}
static bool HandleLearnCommand(ChatHandler* handler, const char* 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 || !sSpellStore.LookupEntry(spell))
return false;
char const* allStr = strtok(NULL," ");
bool allRanks = allStr ? (strncmp(allStr, "all", strlen(allStr)) == 0) : false;
SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell);
if (!spellInfo || !SpellMgr::IsSpellValid(spellInfo,handler->GetSession()->GetPlayer()))
{
handler->PSendSysMessage(LANG_COMMAND_SPELL_BROKEN,spell);
handler->SetSentErrorMessage(true);
return 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, false);
uint32 first_spell = sSpellMgr.GetFirstSpellInChain(spell);
if (GetTalentSpellCost(first_spell))
targetPlayer->SendTalentsInfoData(false);
return true;
}
static bool HandleLearnAllCommand(ChatHandler* handler, const char* /*args*/)
{
static const char *allSpellList[] =
{
"3365",
"6233",
"6247",
"6246",
"6477",
"6478",
"22810",
"8386",
"21651",
"21652",
"522",
"7266",
"8597",
"2479",
"22027",
"6603",
"5019",
"133",
"168",
"227",
"5009",
"9078",
"668",
"203",
"20599",
"20600",
"81",
"20597",
"20598",
"20864",
"1459",
"5504",
"587",
"5143",
"118",
"5505",
"597",
"604",
"1449",
"1460",
"2855",
"1008",
"475",
"5506",
"1463",
"12824",
"8437",
"990",
"5145",
"8450",
"1461",
"759",
"8494",
"8455",
"8438",
"6127",
"8416",
"6129",
"8451",
"8495",
"8439",
"3552",
"8417",
"10138",
"12825",
"10169",
"10156",
"10144",
"10191",
"10201",
"10211",
"10053",
"10173",
"10139",
"10145",
"10192",
"10170",
"10202",
"10054",
"10174",
"10193",
"12826",
"2136",
"143",
"145",
"2137",
"2120",
"3140",
"543",
"2138",
"2948",
"8400",
"2121",
"8444",
"8412",
"8457",
"8401",
"8422",
"8445",
"8402",
"8413",
"8458",
"8423",
"8446",
"10148",
"10197",
"10205",
"10149",
"10215",
"10223",
"10206",
"10199",
"10150",
"10216",
"10207",
"10225",
"10151",
"116",
"205",
"7300",
"122",
"837",
"10",
"7301",
"7322",
"6143",
"120",
"865",
"8406",
"6141",
"7302",
"8461",
"8407",
"8492",
"8427",
"8408",
"6131",
"7320",
"10159",
"8462",
"10185",
"10179",
"10160",
"10180",
"10219",
"10186",
"10177",
"10230",
"10181",
"10161",
"10187",
"10220",
"2018",
"2663",
"12260",
"2660",
"3115",
"3326",
"2665",
"3116",
"2738",
"3293",
"2661",
"3319",
"2662",
"9983",
"8880",
"2737",
"2739",
"7408",
"3320",
"2666",
"3323",
"3324",
"3294",
"22723",
"23219",
"23220",
"23221",
"23228",
"23338",
"10788",
"10790",
"5611",
"5016",
"5609",
"2060",
"10963",
"10964",
"10965",
"22593",
"22594",
"596",
"996",
"499",
"768",
"17002",
"1448",
"1082",
"16979",
"1079",
"5215",
"20484",
"5221",
"15590",
"17007",
"6795",
"6807",
"5487",
"1446",
"1066",
"5421",
"3139",
"779",
"6811",
"6808",
"1445",
"5216",
"1737",
"5222",
"5217",
"1432",
"6812",
"9492",
"5210",
"3030",
"1441",
"783",
"6801",
"20739",
"8944",
"9491",
"22569",
"5226",
"6786",
"1433",
"8973",
"1828",
"9495",
"9006",
"6794",
"8993",
"5203",
"16914",
"6784",
"9635",
"22830",
"20722",
"9748",
"6790",
"9753",
"9493",
"9752",
"9831",
"9825",
"9822",
"5204",
"5401",
"22831",
"6793",
"9845",
"17401",
"9882",
"9868",
"20749",
"9893",
"9899",
"9895",
"9832",
"9902",
"9909",
"22832",
"9828",
"9851",
"9883",
"9869",
"17406",
"17402",
"9914",
"20750",
"9897",
"9848",
"3127",
"107",
"204",
"9116",
"2457",
"78",
"18848",
"331",
"403",
"2098",
"1752",
"11278",
"11288",
"11284",
"6461",
"2344",
"2345",
"6463",
"2346",
"2352",
"775",
"1434",
"1612",
"71",
"2468",
"2458",
"2467",
"7164",
"7178",
"7367",
"7376",
"7381",
"21156",
"5209",
"3029",
"5201",
"9849",
"9850",
"20719",
"22568",
"22827",
"22828",
"22829",
"6809",
"8972",
"9005",
"9823",
"9827",
"6783",
"9913",
"6785",
"6787",
"9866",
"9867",
"9894",
"9896",
"6800",
"8992",
"9829",
"9830",
"780",
"769",
"6749",
"6750",
"9755",
"9754",
"9908",
"20745",
"20742",
"20747",
"20748",
"9746",
"9745",
"9880",
"9881",
"5391",
"842",
"3025",
"3031",
"3287",
"3329",
"1945",
"3559",
"4933",
"4934",
"4935",
"4936",
"5142",
"5390",
"5392",
"5404",
"5420",
"6405",
"7293",
"7965",
"8041",
"8153",
"9033",
"9034",
//"9036", problems with ghost state
"16421",
"21653",
"22660",
"5225",
"9846",
"2426",
"5916",
"6634",
//"6718", phasing stealth, annoying for learn all case.
"6719",
"8822",
"9591",
"9590",
"10032",
"17746",
"17747",
"8203",
"11392",
"12495",
"16380",
"23452",
"4079",
"4996",
"4997",
"4998",
"4999",
"5000",
"6348",
"6349",
"6481",
"6482",
"6483",
"6484",
"11362",
"11410",
"11409",
"12510",
"12509",
"12885",
"13142",
"21463",
"23460",
"11421",
"11416",
"11418",
"1851",
"10059",
"11423",
"11417",
"11422",
"11419",
"11424",
"11420",
"27",
"31",
"33",
"34",
"35",
"15125",
"21127",
"22950",
"1180",
"201",
"12593",
"16770",
"6057",
"12051",
"18468",
"12606",
"12605",
"18466",
"12502",
"12043",
"15060",
"12042",
"12341",
"12848",
"12344",
"12353",
"18460",
"11366",
"12350",
"12352",
"13043",
"11368",
"11113",
"12400",
"11129",
"16766",
"12573",
"12580",
"12472",
"12953",
"12488",
"11189",
"12985",
"12519",
"16758",
"11958",
"12490",
"11426",
"3565",
"3562",
"18960",
"3567",
"3561",
"3566",
"3563",
"1953",
"2139",
"12505",
"13018",
"12522",
"12523",
"5146",
"5144",
"5148",
"8419",
"8418",
"10213",
"10212",
"10157",
"12524",
"13019",
"12525",
"13020",
"12526",
"13021",
"18809",
"13031",
"13032",
"13033",
"4036",
"3920",
"3919",
"3918",
"7430",
"3922",
"3923",
"7411",
"7418",
"7421",
"13262",
"7412",
"7415",
"7413",
"7416",
"13920",
"13921",
"7745",
"7779",
"7428",
"7457",
"7857",
"7748",
"7426",
"13421",
"7454",
"13378",
"7788",
"14807",
"14293",
"7795",
"6296",
"20608",
"755",
"444",
"427",
"428",
"442",
"447",
"3578",
"3581",
"19027",
"3580",
"665",
"3579",
"3577",
"6755",
"3576",
"2575",
"2577",
"2578",
"2579",
"2580",
"2656",
"2657",
"2576",
"3564",
"10248",
"8388",
"2659",
"14891",
"3308",
"3307",
"10097",
"2658",
"3569",
"16153",
"3304",
"10098",
"4037",
"3929",
"3931",
"3926",
"3924",
"3930",
"3977",
"3925",
"136",
"228",
"5487",
"43",
"202",
"0"
};
int loop = 0;
while (strcmp(allSpellList[loop], "0"))
{
uint32 spell = atol((char*)allSpellList[loop++]);
if (handler->GetSession()->GetPlayer()->HasSpell(spell))
continue;
SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell);
if (!spellInfo || !SpellMgr::IsSpellValid(spellInfo,handler->GetSession()->GetPlayer()))
{
handler->PSendSysMessage(LANG_COMMAND_SPELL_BROKEN,spell);
continue;
}
handler->GetSession()->GetPlayer()->learnSpell(spell, false);
}
handler->SendSysMessage(LANG_COMMAND_LEARN_MANY_SPELLS);
return true;
}
static bool HandleLearnAllGMCommand(ChatHandler* handler, const char* /*args*/)
{
static const char *gmSpellList[] =
{
"24347", // Become A Fish, No Breath Bar
"35132", // Visual Boom
"38488", // Attack 4000-8000 AOE
"38795", // Attack 2000 AOE + Slow Down 90%
"15712", // Attack 200
"1852", // GM Spell Silence
"31899", // Kill
"31924", // Kill
"29878", // Kill My Self
"26644", // More Kill
"28550", //Invisible 24
"23452", //Invisible + Target
"0"
};
uint16 gmSpellIter = 0;
while (strcmp(gmSpellList[gmSpellIter], "0"))
{
uint32 spell = atol((char*)gmSpellList[gmSpellIter++]);
SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell);
if (!spellInfo || !SpellMgr::IsSpellValid(spellInfo,handler->GetSession()->GetPlayer()))
{
handler->PSendSysMessage(LANG_COMMAND_SPELL_BROKEN,spell);
continue;
}
handler->GetSession()->GetPlayer()->learnSpell(spell, false);
}
handler->SendSysMessage(LANG_LEARNING_GM_SKILLS);
return true;
}
static bool HandleLearnAllMyClassCommand(ChatHandler* handler, const char* /*args*/)
{
HandleLearnAllMySpellsCommand(handler, "");
HandleLearnAllMyTalentsCommand(handler, "");
return true;
}
static bool HandleLearnAllMySpellsCommand(ChatHandler* handler, const char* /*args*/)
{
ChrClassesEntry const* clsEntry = sChrClassesStore.LookupEntry(handler->GetSession()->GetPlayer()->getClass());
if (!clsEntry)
return true;
uint32 family = clsEntry->spellfamily;
for (uint32 i = 0; i < sSpellStore.GetNumRows(); ++i)
{
SpellEntry const *spellInfo = sSpellStore.LookupEntry(i);
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 first_rank = sSpellMgr.GetFirstSpellInChain(spellInfo->Id);
if (GetTalentSpellCost(first_rank) > 0)
continue;
// skip broken spells
if (!SpellMgr::IsSpellValid(spellInfo,handler->GetSession()->GetPlayer(),false))
continue;
handler->GetSession()->GetPlayer()->learnSpell(i, false);
}
handler->SendSysMessage(LANG_COMMAND_LEARN_CLASS_SPELLS);
return true;
}
static bool HandleLearnAllMyTalentsCommand(ChatHandler* handler, const char* /*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;
// 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;
SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellId);
if (!spellInfo || !SpellMgr::IsSpellValid(spellInfo,handler->GetSession()->GetPlayer(),false))
continue;
// learn highest rank of talent and learn all non-talent spell ranks (recursive by tree)
player->learnSpellHighRank(spellId);
player->AddTalent(spellId, player->GetActiveSpec(), true);
}
player->SetFreeTalentPoints(0);
handler->SendSysMessage(LANG_COMMAND_LEARN_CLASS_TALENTS);
return true;
}
static bool HandleLearnAllMyPetTalentsCommand(ChatHandler* handler, const char* /*args*/)
{
Player* player = handler->GetSession()->GetPlayer();
Pet* pet = player->GetPet();
if (!pet)
{
handler->SendSysMessage(LANG_NO_PET_FOUND);
handler->SetSentErrorMessage(true);
return false;
}
CreatureInfo const *ci = pet->GetCreatureInfo();
if (!ci)
{
handler->SendSysMessage(LANG_WRONG_PET_TYPE);
handler->SetSentErrorMessage(true);
return false;
}
CreatureFamilyEntry const *pet_family = sCreatureFamilyStore.LookupEntry(ci->family);
if (!pet_family)
{
handler->SendSysMessage(LANG_WRONG_PET_TYPE);
handler->SetSentErrorMessage(true);
return false;
}
if (pet_family->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 << pet_family->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;
SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellid);
if (!spellInfo || !SpellMgr::IsSpellValid(spellInfo,handler->GetSession()->GetPlayer(),false))
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, const char* /*args*/)
{
// skipping UNIVERSAL language (0)
for (uint8 i = 1; i < LANGUAGES_COUNT; ++i)
handler->GetSession()->GetPlayer()->learnSpell(lang_description[i].spell_id, false);
handler->SendSysMessage(LANG_COMMAND_LEARN_ALL_LANG);
return true;
}
static bool HandleLearnAllDefaultCommand(ChatHandler* handler, const char* 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, const char* /*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, const char* 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 wnamepart;
if (!Utf8toWStr(args,wnamepart))
return false;
// converting string that we try to find to lower case
wstrToLower(wnamepart);
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 loc = handler->GetSessionDbcLocale();
name = skillInfo->name[loc];
if (name.empty())
continue;
if (!Utf8FitTo(name, wnamepart))
{
loc = 0;
for (; loc < TOTAL_LOCALES; ++loc)
{
if (loc == handler->GetSessionDbcLocale())
continue;
name = skillInfo->name[loc];
if (name.empty())
continue;
if (Utf8FitTo(name, wnamepart))
break;
}
}
if (loc < 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 skill_id)
{
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 != skill_id)
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;
SpellEntry const* spellInfo = sSpellStore.LookupEntry(skillLine->spellId);
if (!spellInfo || !SpellMgr::IsSpellValid(spellInfo,player,false))
continue;
player->learnSpell(skillLine->spellId, false);
}
}
};
void AddSC_learn_commandscript()
{
new learn_commandscript();
}