Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
cs_learn.cpp
Go to the documentation of this file.
1/*
2* This file is part of Project SkyFire https://www.projectskyfire.org.
3* See LICENSE.md file for Copyright information
4*/
5
6/* ScriptData
7Name: learn_commandscript
8%Complete: 100
9Comment: All learn related commands
10Category: commandscripts
11EndScriptData */
12
13#include "Chat.h"
14#include "Language.h"
15#include "ObjectMgr.h"
16#include "Pet.h"
17#include "Player.h"
18#include "ScriptMgr.h"
19#include "SpellInfo.h"
20#include "SpellMgr.h"
21
23{
24public:
25 learn_commandscript() : CommandScript("learn_commandscript") { }
26
27 std::vector<ChatCommand> GetCommands() const OVERRIDE
28 {
29 static std::vector<ChatCommand> learnAllMyCommandTable =
30 {
34 };
35
36 static std::vector<ChatCommand> learnAllCommandTable =
37 {
38 { "my", rbac::RBAC_PERM_COMMAND_LEARN_ALL_MY, false, NULL, "", learnAllMyCommandTable },
44 };
45
46 static std::vector<ChatCommand> learnCommandTable =
47 {
48 { "all", rbac::RBAC_PERM_COMMAND_LEARN_ALL, false, NULL, "", learnAllCommandTable },
50 };
51
52 static std::vector<ChatCommand> commandTable =
53 {
54 { "learn", rbac::RBAC_PERM_COMMAND_LEARN, false, NULL, "", learnCommandTable },
55 { "unlearn", rbac::RBAC_PERM_COMMAND_UNLEARN, false, &HandleUnLearnCommand, "", },
56 };
57 return commandTable;
58 }
59
60 static bool HandleLearnCommand(ChatHandler* handler, char const* args)
61 {
62 Player* targetPlayer = handler->getSelectedPlayer();
63
64 if (!targetPlayer)
65 {
67 handler->SetSentErrorMessage(true);
68 return false;
69 }
70
71 // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form
72 uint32 spell = handler->extractSpellIdFromLink((char*)args);
73 if (!spell || !sSpellMgr->GetSpellInfo(spell))
74 return false;
75
76 char const* all = strtok(NULL, " ");
77 bool allRanks = all ? (strncmp(all, "all", strlen(all)) == 0) : false;
78
79 SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell);
80 if (!spellInfo || !SpellMgr::IsSpellValid(spellInfo, handler->GetSession()->GetPlayer()))
81 {
83 handler->SetSentErrorMessage(true);
84 return false;
85 }
86
87 if (!allRanks && targetPlayer->HasSpell(spell))
88 {
89 if (targetPlayer == handler->GetSession()->GetPlayer())
91 else
92 handler->PSendSysMessage(LANG_TARGET_KNOWN_SPELL, handler->GetNameLink(targetPlayer).c_str());
93 handler->SetSentErrorMessage(true);
94 return false;
95 }
96
97 if (allRanks)
98 targetPlayer->learnSpellHighRank(spell);
99 else
100 targetPlayer->learnSpell(spell, false);
101
102 if (GetTalentSpellCost(spellInfo->GetFirstRankSpell()->Id))
103 targetPlayer->SendTalentsInfoData();
104
105 return true;
106 }
107
108 static bool HandleLearnAllGMCommand(ChatHandler* handler, char const* /*args*/)
109 {
110 for (uint32 i = 0; i < sSpellMgr->GetSpellInfoStoreSize(); ++i)
111 {
112 SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(i);
113 if (!spellInfo || !SpellMgr::IsSpellValid(spellInfo, handler->GetSession()->GetPlayer(), false))
114 continue;
115
116 if (!spellInfo->IsAbilityOfSkillType(SKILL_INTERNAL))
117 continue;
118
119 handler->GetSession()->GetPlayer()->learnSpell(i, false);
120 }
121
123 return true;
124 }
125
126 static bool HandleLearnAllMyClassCommand(ChatHandler* handler, char const* /*args*/)
127 {
130 return true;
131 }
132
133 static bool HandleLearnAllMySpellsCommand(ChatHandler* handler, char const* /*args*/)
134 {
135 ChrClassesEntry const* classEntry = sChrClassesStore.LookupEntry(handler->GetSession()->GetPlayer()->getClass());
136 if (!classEntry)
137 return true;
138 uint32 family = classEntry->spellfamily;
139
140 for (uint32 i = 0; i < sSkillLineAbilityStore.GetNumRows(); ++i)
141 {
142 SkillLineAbilityEntry const* entry = sSkillLineAbilityStore.LookupEntry(i);
143 if (!entry)
144 continue;
145
146 SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(entry->spellId);
147 if (!spellInfo)
148 continue;
149
150 // skip server-side/triggered spells
151 if (spellInfo->SpellLevel == 0)
152 continue;
153
154 // skip wrong class/race skills
155 if (!handler->GetSession()->GetPlayer()->IsSpellFitByClassAndRace(spellInfo->Id))
156 continue;
157
158 // skip other spell families
159 if (spellInfo->SpellFamilyName != family)
160 continue;
161
162 // skip spells with first rank learned as talent (and all talents then also)
163 if (GetTalentSpellCost(spellInfo->GetFirstRankSpell()->Id) > 0)
164 continue;
165
166 // skip broken spells
167 if (!SpellMgr::IsSpellValid(spellInfo, handler->GetSession()->GetPlayer(), false))
168 continue;
169
170 handler->GetSession()->GetPlayer()->learnSpell(spellInfo->Id, false);
171 }
172
174 return true;
175 }
176
177 static bool HandleLearnAllMyTalentsCommand(ChatHandler* handler, char const* /*args*/)
178 {
179 Player* player = handler->GetSession()->GetPlayer();
180
181 for (uint32 i = 0; i < sTalentStore.GetNumRows(); ++i)
182 {
183 TalentEntry const* talentInfo = sTalentStore.LookupEntry(i);
184 if (!talentInfo)
185 continue;
186
187 if (talentInfo->playerClass != player->getClass())
188 continue;
189
190 // search highest talent rank
191 uint32 spellId = talentInfo->SpellId;
192
193 if (!spellId) // ??? none spells in talent
194 continue;
195
196 SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
197 if (!spellInfo || !SpellMgr::IsSpellValid(spellInfo, handler->GetSession()->GetPlayer(), false))
198 continue;
199
200 // learn highest rank of talent and learn all non-talent spell ranks (recursive by tree)
201 player->learnSpellHighRank(spellId);
202 player->AddTalent(spellId, player->GetActiveSpec(), true);
203 }
204
206 return true;
207 }
208
209 static bool HandleLearnAllLangCommand(ChatHandler* handler, char const* /*args*/)
210 {
211 // skipping UNIVERSAL language (0)
212 for (uint8 i = 1; i < LANGUAGES_COUNT; ++i)
213 handler->GetSession()->GetPlayer()->learnSpell(lang_description[i].spell_id, false);
214
216 return true;
217 }
218
219 static bool HandleLearnAllDefaultCommand(ChatHandler* handler, char const* args)
220 {
221 Player* target;
222 if (!handler->extractPlayerTarget((char*)args, &target))
223 return false;
224
225 target->learnDefaultSpells();
226 target->learnQuestRewardedSpells();
227
228 handler->PSendSysMessage(LANG_COMMAND_LEARN_ALL_DEFAULT_AND_QUEST, handler->GetNameLink(target).c_str());
229 return true;
230 }
231
232 static bool HandleLearnAllCraftsCommand(ChatHandler* handler, char const* args)
233 {
234 Player* target;
235 if (!handler->extractPlayerTarget((char*)args, &target))
236 return false;
237
238 for (uint32 i = 0; i < sSkillLineStore.GetNumRows(); ++i)
239 {
240 SkillLineEntry const* skillInfo = sSkillLineStore.LookupEntry(i);
241 if (!skillInfo)
242 continue;
243
244 if ((skillInfo->categoryId == SKILL_CATEGORY_PROFESSION || skillInfo->categoryId == SKILL_CATEGORY_SECONDARY) &&
245 skillInfo->canLink) // only prof. with recipes have
246 {
247 HandleLearnSkillRecipesHelper(target, skillInfo->id);
248 }
249 }
250
252 return true;
253 }
254
255 static bool HandleLearnAllRecipesCommand(ChatHandler* handler, char const* args)
256 {
257 // Learns all recipes of specified profession and sets skill to max
258 // Example: .learn all_recipes enchanting
259
260 Player* target = handler->getSelectedPlayer();
261 if (!target)
262 {
264 return false;
265 }
266
267 if (!*args)
268 return false;
269
270 std::wstring namePart;
271
272 if (!Utf8toWStr(args, namePart))
273 return false;
274
275 // converting string that we try to find to lower case
276 wstrToLower(namePart);
277
278 std::string name;
279
280 SkillLineEntry const* targetSkillInfo = NULL;
281 for (uint32 i = 1; i < sSkillLineStore.GetNumRows(); ++i)
282 {
283 SkillLineEntry const* skillInfo = sSkillLineStore.LookupEntry(i);
284 if (!skillInfo)
285 continue;
286
287 if ((skillInfo->categoryId != SKILL_CATEGORY_PROFESSION &&
288 skillInfo->categoryId != SKILL_CATEGORY_SECONDARY) ||
289 !skillInfo->canLink) // only prof with recipes have set
290 continue;
291
292 name = skillInfo->name;
293 if (name.empty())
294 continue;
295
296 if (!Utf8FitTo(name, namePart))
297 continue;
298
299 targetSkillInfo = skillInfo;
300 }
301
302 if (!targetSkillInfo)
303 return false;
304
305 HandleLearnSkillRecipesHelper(target, targetSkillInfo->id);
306
307 uint16 maxLevel = target->GetPureMaxSkillValue(targetSkillInfo->id);
308 target->SetSkill(targetSkillInfo->id, target->GetSkillStep(targetSkillInfo->id), maxLevel, maxLevel);
309 handler->PSendSysMessage(LANG_COMMAND_LEARN_ALL_RECIPES, name.c_str());
310 return true;
311 }
312
313 static void HandleLearnSkillRecipesHelper(Player* player, uint32 skillId)
314 {
315 uint32 classmask = player->getClassMask();
316
317 for (uint32 j = 0; j < sSkillLineAbilityStore.GetNumRows(); ++j)
318 {
319 SkillLineAbilityEntry const* skillLine = sSkillLineAbilityStore.LookupEntry(j);
320 if (!skillLine)
321 continue;
322
323 // wrong skill
324 if (skillLine->skillId != skillId)
325 continue;
326
327 // not high rank
328 if (skillLine->forward_spellid)
329 continue;
330
331 // skip racial skills
332 if (skillLine->racemask != 0)
333 continue;
334
335 // skip wrong class skills
336 if (skillLine->classmask && (skillLine->classmask & classmask) == 0)
337 continue;
338
339 SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(skillLine->spellId);
340 if (!spellInfo || !SpellMgr::IsSpellValid(spellInfo, player, false))
341 continue;
342
343 player->learnSpell(skillLine->spellId, false);
344 }
345 }
346
347 static bool HandleUnLearnCommand(ChatHandler* handler, char const* args)
348 {
349 if (!*args)
350 return false;
351
352 // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r
353 uint32 spellId = handler->extractSpellIdFromLink((char*)args);
354 if (!spellId)
355 return false;
356
357 char const* allStr = strtok(NULL, " ");
358 bool allRanks = allStr ? (strncmp(allStr, "all", strlen(allStr)) == 0) : false;
359
360 Player* target = handler->getSelectedPlayer();
361 if (!target)
362 {
364 handler->SetSentErrorMessage(true);
365 return false;
366 }
367
368 if (allRanks)
369 spellId = sSpellMgr->GetFirstSpellInChain(spellId);
370
371 if (target->HasSpell(spellId))
372 target->removeSpell(spellId, false, !allRanks);
373 else
375
376 if (GetTalentSpellCost(spellId))
377 target->SendTalentsInfoData();
378
379 return true;
380 }
381};
382
uint32 GetTalentSpellCost(uint32 spellId)
DBCStorage< SkillLineEntry > sSkillLineStore(SkillLinefmt)
DBCStorage< TalentEntry > sTalentStore(TalentEntryfmt)
DBCStorage< SkillLineAbilityEntry > sSkillLineAbilityStore(SkillLineAbilityfmt)
DBCStorage< ChrClassesEntry > sChrClassesStore(ChrClassesEntryfmt)
std::uint8_t uint8
Definition Define.h:79
std::uint32_t uint32
Definition Define.h:77
#define OVERRIDE
Definition Define.h:60
std::uint16_t uint16
Definition Define.h:78
@ LANG_COMMAND_LEARN_ALL_RECIPES
Definition Language.h:599
@ LANG_YOU_KNOWN_SPELL
Definition Language.h:475
@ LANG_FORGET_SPELL
Definition Language.h:478
@ LANG_COMMAND_LEARN_ALL_CRAFT
Definition Language.h:413
@ LANG_LEARNING_GM_SKILLS
Definition Language.h:474
@ LANG_COMMAND_LEARN_CLASS_TALENTS
Definition Language.h:411
@ LANG_COMMAND_LEARN_CLASS_SPELLS
Definition Language.h:410
@ LANG_COMMAND_LEARN_ALL_LANG
Definition Language.h:412
@ LANG_NO_CHAR_SELECTED
Definition Language.h:118
@ LANG_PLAYER_NOT_FOUND
Definition Language.h:487
@ LANG_COMMAND_SPELL_BROKEN
Definition Language.h:468
@ LANG_COMMAND_LEARN_ALL_DEFAULT_AND_QUEST
Definition Language.h:584
@ LANG_TARGET_KNOWN_SPELL
Definition Language.h:476
LanguageDesc lang_description[LANGUAGES_COUNT]
#define LANGUAGES_COUNT
@ SKILL_CATEGORY_SECONDARY
@ SKILL_CATEGORY_PROFESSION
@ SKILL_INTERNAL
#define sSpellMgr
Definition SpellMgr.h:744
bool Utf8FitTo(const std::string &str, const std::wstring &search)
Definition Util.cpp:473
bool Utf8toWStr(char const *utf8str, size_t csize, wchar_t *wstr, size_t &wsize)
Definition Util.cpp:305
void wstrToLower(std::wstring &str)
Definition Util.h:314
virtual std::string GetNameLink() const
Definition Chat.h:79
Player * getSelectedPlayer()
Definition Chat.cpp:829
WorldSession * GetSession()
Definition Chat.h:43
uint32 extractSpellIdFromLink(char *text)
Definition Chat.cpp:1042
void PSendSysMessage(const char *format,...) ATTR_PRINTF(2
Definition Chat.cpp:221
void SetSentErrorMessage(bool val)
Definition Chat.h:114
bool extractPlayerTarget(char *args, Player **player, uint64 *player_guid=NULL, std::string *player_name=NULL)
Definition Chat.cpp:1184
virtual void SendSysMessage(const char *str)
Definition Chat.cpp:153
CommandScript(const char *name)
void learnDefaultSpells()
Definition Player.cpp:18837
void SendTalentsInfoData()
Definition Player.cpp:21306
bool IsSpellFitByClassAndRace(uint32 spell_id) const
Definition Player.cpp:19350
uint16 GetSkillStep(uint16 skill) const
Definition Player.cpp:6551
uint16 GetPureMaxSkillValue(uint32 skill) const
Definition Player.cpp:6599
void SetSkill(uint16 id, uint16 step, uint16 currVal, uint16 maxVal)
Definition Player.cpp:6377
void learnSpellHighRank(uint32 spellid)
Definition Player.cpp:20807
void removeSpell(uint32 spell_id, bool disabled=false, bool learn_low_rank=true)
Definition Player.cpp:4073
void learnSpell(uint32 spell_id, bool dependent)
Definition Player.cpp:4021
uint8 GetActiveSpec() const
Definition Player.h:2077
bool HasSpell(uint32 spell) const override
Definition Player.cpp:4674
void learnQuestRewardedSpells()
Definition Player.cpp:18938
bool AddTalent(uint32 spellId, uint8 spec, bool learning)
Definition Player.cpp:3580
uint32 SpellLevel
Definition SpellInfo.h:206
SpellInfo const * GetFirstRankSpell() const
uint32 Id
Definition SpellInfo.h:160
bool IsAbilityOfSkillType(uint32 skillType) const
uint32 SpellFamilyName
Definition SpellInfo.h:226
static bool IsSpellValid(SpellInfo const *spellInfo, Player *player=NULL, bool msg=true)
Some checks for spells, to prevent adding deprecated/broken spells for trainers, spell book,...
Definition SpellMgr.cpp:319
uint8 getClass() const
Definition Unit.h:1543
uint32 getClassMask() const
Definition Unit.h:1547
Player * GetPlayer() const
static bool HandleLearnAllDefaultCommand(ChatHandler *handler, char const *args)
Definition cs_learn.cpp:219
static bool HandleLearnAllCraftsCommand(ChatHandler *handler, char const *args)
Definition cs_learn.cpp:232
static bool HandleLearnAllMyClassCommand(ChatHandler *handler, char const *)
Definition cs_learn.cpp:126
static bool HandleLearnAllMySpellsCommand(ChatHandler *handler, char const *)
Definition cs_learn.cpp:133
static bool HandleLearnAllRecipesCommand(ChatHandler *handler, char const *args)
Definition cs_learn.cpp:255
static bool HandleLearnCommand(ChatHandler *handler, char const *args)
Definition cs_learn.cpp:60
std::vector< ChatCommand > GetCommands() const OVERRIDE
Definition cs_learn.cpp:27
static bool HandleLearnAllLangCommand(ChatHandler *handler, char const *)
Definition cs_learn.cpp:209
static bool HandleUnLearnCommand(ChatHandler *handler, char const *args)
Definition cs_learn.cpp:347
static bool HandleLearnAllMyTalentsCommand(ChatHandler *handler, char const *)
Definition cs_learn.cpp:177
static bool HandleLearnAllGMCommand(ChatHandler *handler, char const *)
Definition cs_learn.cpp:108
static void HandleLearnSkillRecipesHelper(Player *player, uint32 skillId)
Definition cs_learn.cpp:313
void AddSC_learn_commandscript()
Definition cs_learn.cpp:383
@ RBAC_PERM_COMMAND_UNLEARN
Definition RBAC.h:317
@ RBAC_PERM_COMMAND_LEARN_ALL_LANG
Definition RBAC.h:315
@ RBAC_PERM_COMMAND_LEARN_ALL_CRAFTS
Definition RBAC.h:313
@ RBAC_PERM_COMMAND_LEARN_ALL_MY
Definition RBAC.h:307
@ RBAC_PERM_COMMAND_LEARN_ALL_RECIPES
Definition RBAC.h:316
@ RBAC_PERM_COMMAND_LEARN_ALL_MY_CLASS
Definition RBAC.h:308
@ RBAC_PERM_COMMAND_LEARN
Definition RBAC.h:305
@ RBAC_PERM_COMMAND_LEARN_ALL_MY_TALENTS
Definition RBAC.h:311
@ RBAC_PERM_COMMAND_LEARN_ALL_MY_SPELLS
Definition RBAC.h:310
@ RBAC_PERM_COMMAND_LEARN_ALL_GM
Definition RBAC.h:312
@ RBAC_PERM_COMMAND_LEARN_ALL_DEFAULT
Definition RBAC.h:314
@ RBAC_PERM_COMMAND_LEARN_ALL
Definition RBAC.h:306
uint32 spellfamily
uint32 spellId
uint32 classmask
uint32 racemask
uint32 skillId
uint32 forward_spellid
char * name
uint32 id
int32 categoryId
uint32 canLink
uint32 SpellId
uint32 playerClass