TrinityCore
Loading...
Searching...
No Matches
CharacterHandler.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "WorldSession.h"
19#include "ArenaTeamMgr.h"
20#include "CalendarMgr.h"
21#include "CharacterCache.h"
22#include "CharacterPackets.h"
23#include "Chat.h"
24#include "DatabaseEnv.h"
25#include "DBCStores.h"
26#include "GameObject.h"
27#include "GameTime.h"
28#include "GitRevision.h"
29#include "Group.h"
30#include "GroupMgr.h"
31#include "Guild.h"
32#include "GuildMgr.h"
33#include "InstanceSaveMgr.h"
34#include "Item.h"
35#include "Language.h"
36#include "Log.h"
37#include "Map.h"
38#include "Metric.h"
39#include "MotionMaster.h"
40#include "ObjectAccessor.h"
41#include "ObjectMgr.h"
42#include "Opcodes.h"
43#include "Pet.h"
44#include "Player.h"
45#include "PlayerDump.h"
46#include "RBAC.h"
47#include "Realm.h"
48#include "ReputationMgr.h"
49#include "ScriptMgr.h"
50#include "SocialMgr.h"
51#include "StringConvert.h"
52#include "SystemPackets.h"
53#include "QueryHolder.h"
54#include "World.h"
55
57{
58 private:
61 public:
63 : m_accountId(accountId), m_guid(guid) { }
64 ObjectGuid GetGuid() const { return m_guid; }
65 uint32 GetAccountId() const { return m_accountId; }
66 bool Initialize();
67};
68
70{
72
73 bool res = true;
75
77 stmt->setUInt32(0, lowGuid);
79
80 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GROUP_MEMBER);
81 stmt->setUInt32(0, lowGuid);
83
84 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_INSTANCE);
85 stmt->setUInt32(0, lowGuid);
87
88 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_AURAS);
89 stmt->setUInt32(0, lowGuid);
91
92 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_SPELL);
93 stmt->setUInt32(0, lowGuid);
95
96 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_QUESTSTATUS);
97 stmt->setUInt32(0, lowGuid);
99
100 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_QUESTSTATUS_DAILY);
101 stmt->setUInt32(0, lowGuid);
103
104 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_QUESTSTATUS_WEEKLY);
105 stmt->setUInt32(0, lowGuid);
107
109 stmt->setUInt32(0, lowGuid);
111
113 stmt->setUInt32(0, lowGuid);
115
116 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_REPUTATION);
117 stmt->setUInt32(0, lowGuid);
119
120 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_INVENTORY);
121 stmt->setUInt32(0, lowGuid);
123
124 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_ACTIONS);
125 stmt->setUInt32(0, lowGuid);
127
128 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_MAIL);
129 stmt->setUInt32(0, lowGuid);
131
132 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_MAILITEMS);
133 stmt->setUInt32(0, lowGuid);
135
136 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_SOCIALLIST);
137 stmt->setUInt32(0, lowGuid);
139
140 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_HOMEBIND);
141 stmt->setUInt32(0, lowGuid);
143
144 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_SPELLCOOLDOWNS);
145 stmt->setUInt32(0, lowGuid);
147
148 if (sWorld->getBoolConfig(CONFIG_DECLINED_NAMES_USED))
149 {
150 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_DECLINEDNAMES);
151 stmt->setUInt32(0, lowGuid);
153 }
154
155 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GUILD_MEMBER);
156 stmt->setUInt32(0, lowGuid);
158
159 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_ARENAINFO);
160 stmt->setUInt32(0, lowGuid);
162
163 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_ACHIEVEMENTS);
164 stmt->setUInt32(0, lowGuid);
166
167 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_CRITERIAPROGRESS);
168 stmt->setUInt32(0, lowGuid);
170
171 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_EQUIPMENTSETS);
172 stmt->setUInt32(0, lowGuid);
174
175 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_BGDATA);
176 stmt->setUInt32(0, lowGuid);
178
179 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_GLYPHS);
180 stmt->setUInt32(0, lowGuid);
182
183 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_TALENTS);
184 stmt->setUInt32(0, lowGuid);
186
187 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PLAYER_ACCOUNT_DATA);
188 stmt->setUInt32(0, lowGuid);
190
191 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_SKILLS);
192 stmt->setUInt32(0, lowGuid);
194
195 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_RANDOMBG);
196 stmt->setUInt32(0, lowGuid);
198
199 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_BANNED);
200 stmt->setUInt32(0, lowGuid);
202
203 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_QUESTSTATUSREW);
204 stmt->setUInt32(0, lowGuid);
206
207 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CORPSE_LOCATION);
208 stmt->setUInt32(0, lowGuid);
210
211 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_PETS);
212 stmt->setUInt32(0, lowGuid);
214
215 return res;
216}
217
219{
220 WorldPacket data(SMSG_CHAR_ENUM, 100); // we guess size
221
222 uint8 num = 0;
223
224 data << num;
225
227 if (result)
228 {
229 do
230 {
231 ObjectGuid guid = ObjectGuid::Create<HighGuid::Player>((*result)[0].GetUInt32());
232 TC_LOG_INFO("network", "Loading {} from account {}.", guid.ToString(), GetAccountId());
233 if (Player::BuildEnumData(result, &data))
234 {
235 // Do not allow banned characters to log in
236 if (!(*result)[23].GetUInt32())
237 _legitCharacters.insert(guid);
238
239 if (!sCharacterCache->HasCharacterCacheEntry(guid)) // This can happen if characters are inserted into the database manually. Core hasn't loaded name data yet.
240 sCharacterCache->AddCharacterCacheEntry(guid, GetAccountId(), (*result)[1].GetString(), (*result)[4].GetUInt8(), (*result)[2].GetUInt8(), (*result)[3].GetUInt8(), (*result)[10].GetUInt8());
241 ++num;
242 }
243 }
244 while (result->NextRow() && num < MAX_CHARACTERS_PER_REALM); // client shows an error if more than 10 characters are listed
245 }
246
247 data.put<uint8>(0, num);
248
249 SendPacket(&data);
250}
251
253{
254 // remove expired bans
256 CharacterDatabase.Execute(stmt);
257
259
260 if (sWorld->getBoolConfig(CONFIG_DECLINED_NAMES_USED))
261 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_ENUM_DECLINED_NAME);
262 else
263 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_ENUM);
264
266 stmt->setUInt32(1, GetAccountId());
267
268 _queryProcessor.AddCallback(CharacterDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&WorldSession::HandleCharEnum, this, std::placeholders::_1)));
269}
270
272{
274 {
275 if (uint32 mask = sWorld->getIntConfig(CONFIG_CHARACTER_CREATING_DISABLED))
276 {
277 bool disabled = false;
278
279 switch (Player::TeamForRace(charCreate.CreateInfo->Race))
280 {
281 case ALLIANCE:
282 disabled = (mask & (1 << 0)) != 0;
283 break;
284 case HORDE:
285 disabled = (mask & (1 << 1)) != 0;
286 break;
287 }
288
289 if (disabled)
290 {
292 return;
293 }
294 }
295 }
296
297 ChrClassesEntry const* classEntry = sChrClassesStore.LookupEntry(charCreate.CreateInfo->Class);
298 if (!classEntry)
299 {
300 TC_LOG_ERROR("network", "Class ({}) not found in DBC while creating new char for account (ID: {}): wrong DBC files or cheater?", charCreate.CreateInfo->Class, GetAccountId());
302 return;
303 }
304
305 ChrRacesEntry const* raceEntry = sChrRacesStore.LookupEntry(charCreate.CreateInfo->Race);
306 if (!raceEntry)
307 {
308 TC_LOG_ERROR("network", "Race ({}) not found in DBC while creating new char for account (ID: {}): wrong DBC files or cheater?", charCreate.CreateInfo->Race, GetAccountId());
310 return;
311 }
312
313 // prevent character creating Expansion race without Expansion account
314 if (raceEntry->RequiredExpansion > Expansion())
315 {
316 TC_LOG_ERROR("entities.player.cheat", "Expansion {} account:[{}] tried to Create character with expansion {} race ({})", Expansion(), GetAccountId(), raceEntry->RequiredExpansion, charCreate.CreateInfo->Race);
318 return;
319 }
320
321 // prevent character creating Expansion class without Expansion account
322 if (classEntry->RequiredExpansion > Expansion())
323 {
324 TC_LOG_ERROR("entities.player.cheat", "Expansion {} account:[{}] tried to Create character with expansion {} class ({})", Expansion(), GetAccountId(), classEntry->RequiredExpansion, charCreate.CreateInfo->Class);
326 return;
327 }
328
330 {
332 {
333 TC_LOG_ERROR("network", "Race ({}) was not playable but requested while creating new char for account (ID: {}): wrong DBC files or cheater?", charCreate.CreateInfo->Race, GetAccountId());
335 return;
336 }
337
338 uint32 raceMaskDisabled = sWorld->getIntConfig(CONFIG_CHARACTER_CREATING_DISABLED_RACEMASK);
339 if ((1 << (charCreate.CreateInfo->Race - 1)) & raceMaskDisabled)
340 {
342 return;
343 }
344 }
345
347 {
348 uint32 classMaskDisabled = sWorld->getIntConfig(CONFIG_CHARACTER_CREATING_DISABLED_CLASSMASK);
349 if ((1 << (charCreate.CreateInfo->Class - 1)) & classMaskDisabled)
350 {
352 return;
353 }
354 }
355
356 // prevent character creating with invalid name
357 if (!normalizePlayerName(charCreate.CreateInfo->Name))
358 {
359 TC_LOG_ERROR("entities.player.cheat", "Account:[{}] but tried to Create character with empty [name] ", GetAccountId());
361 return;
362 }
363
364 // check name limitations
366 if (res != CHAR_NAME_SUCCESS)
367 {
368 SendCharCreate(res);
369 return;
370 }
371
373 {
375 return;
376 }
377
379 {
380 // speedup check for death knight class disabled case
381 if (sWorld->getIntConfig(CONFIG_DEATH_KNIGHTS_PER_REALM) == 0)
382 {
384 return;
385 }
386
387 // speedup check for death knight class disabled case
389 {
391 return;
392 }
393 }
394
395 std::shared_ptr<WorldPackets::Character::CharacterCreateInfo> createInfo = charCreate.CreateInfo;
397 stmt->setString(0, charCreate.CreateInfo->Name);
398
400 .WithChainingPreparedCallback([this](QueryCallback& queryCallback, PreparedQueryResult result)
401 {
402 if (result)
403 {
404 SendCharCreate(CHAR_CREATE_NAME_IN_USE);
405 return;
406 }
407
409 stmt->setUInt32(0, GetAccountId());
410 queryCallback.SetNextQuery(LoginDatabase.AsyncQuery(stmt));
411 })
412 .WithChainingPreparedCallback([this](QueryCallback& queryCallback, PreparedQueryResult result)
413 {
414 uint64 acctCharCount = 0;
415 if (result)
416 {
417 Field* fields = result->Fetch();
418 acctCharCount = uint64(fields[0].GetDouble());
419 }
420
421 if (acctCharCount >= sWorld->getIntConfig(CONFIG_CHARACTERS_PER_ACCOUNT))
422 {
423 SendCharCreate(CHAR_CREATE_ACCOUNT_LIMIT);
424 return;
425 }
426
428 stmt->setUInt32(0, GetAccountId());
429 queryCallback.SetNextQuery(CharacterDatabase.AsyncQuery(stmt));
430 })
431 .WithChainingPreparedCallback([this, createInfo](QueryCallback& queryCallback, PreparedQueryResult result)
432 {
433 if (result)
434 {
435 Field* fields = result->Fetch();
436 createInfo->CharCount = uint8(fields[0].GetUInt64()); // SQL's COUNT() returns uint64 but it will always be less than uint8.Max
437
438 if (createInfo->CharCount >= sWorld->getIntConfig(CONFIG_CHARACTERS_PER_REALM))
439 {
440 SendCharCreate(CHAR_CREATE_SERVER_LIMIT);
441 return;
442 }
443 }
444
445 bool allowTwoSideAccounts = !sWorld->IsPvPRealm() || HasPermission(rbac::RBAC_PERM_TWO_SIDE_CHARACTER_CREATION);
446 uint32 skipCinematics = sWorld->getIntConfig(CONFIG_SKIP_CINEMATICS);
447
448 std::function<void(PreparedQueryResult)> finalizeCharacterCreation = [this, createInfo](PreparedQueryResult result)
449 {
450 bool haveSameRace = false;
451 uint32 deathKnightReqLevel = sWorld->getIntConfig(CONFIG_CHARACTER_CREATING_MIN_LEVEL_FOR_DEATH_KNIGHT);
452 bool hasDeathKnightReqLevel = (deathKnightReqLevel == 0);
453 bool allowTwoSideAccounts = !sWorld->IsPvPRealm() || HasPermission(rbac::RBAC_PERM_TWO_SIDE_CHARACTER_CREATION);
454 uint32 skipCinematics = sWorld->getIntConfig(CONFIG_SKIP_CINEMATICS);
455 bool checkDeathKnightReqs = createInfo->Class == CLASS_DEATH_KNIGHT && !HasPermission(rbac::RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_DEATH_KNIGHT);
456
457 if (result)
458 {
459 uint32 team = Player::TeamForRace(createInfo->Race);
460 uint32 freeDeathKnightSlots = sWorld->getIntConfig(CONFIG_DEATH_KNIGHTS_PER_REALM);
461
462 Field* field = result->Fetch();
463 uint8 accRace = field[1].GetUInt8();
464
465 if (checkDeathKnightReqs)
466 {
467 uint8 accClass = field[2].GetUInt8();
468 if (accClass == CLASS_DEATH_KNIGHT)
469 {
470 if (freeDeathKnightSlots > 0)
471 --freeDeathKnightSlots;
472
473 if (freeDeathKnightSlots == 0)
474 {
475 SendCharCreate(CHAR_CREATE_UNIQUE_CLASS_LIMIT);
476 return;
477 }
478 }
479
480 if (!hasDeathKnightReqLevel)
481 {
482 uint8 accLevel = field[0].GetUInt8();
483 if (accLevel >= deathKnightReqLevel)
484 hasDeathKnightReqLevel = true;
485 }
486 }
487
488 // need to check team only for first character
490 if (!allowTwoSideAccounts)
491 {
492 uint32 accTeam = 0;
493 if (accRace > 0)
494 accTeam = Player::TeamForRace(accRace);
495
496 if (accTeam != team)
497 {
498 SendCharCreate(CHAR_CREATE_PVP_TEAMS_VIOLATION);
499 return;
500 }
501 }
502
503 // search same race for cinematic or same class if need
505 while ((skipCinematics == 1 && !haveSameRace) || createInfo->Class == CLASS_DEATH_KNIGHT)
506 {
507 if (!result->NextRow())
508 break;
509
510 field = result->Fetch();
511 accRace = field[1].GetUInt8();
512
513 if (!haveSameRace)
514 haveSameRace = createInfo->Race == accRace;
515
516 if (checkDeathKnightReqs)
517 {
518 uint8 acc_class = field[2].GetUInt8();
519 if (acc_class == CLASS_DEATH_KNIGHT)
520 {
521 if (freeDeathKnightSlots > 0)
522 --freeDeathKnightSlots;
523
524 if (freeDeathKnightSlots == 0)
525 {
526 SendCharCreate(CHAR_CREATE_UNIQUE_CLASS_LIMIT);
527 return;
528 }
529 }
530
531 if (!hasDeathKnightReqLevel)
532 {
533 uint8 acc_level = field[0].GetUInt8();
534 if (acc_level >= deathKnightReqLevel)
535 hasDeathKnightReqLevel = true;
536 }
537 }
538 }
539 }
540
541 if (checkDeathKnightReqs && !hasDeathKnightReqLevel)
542 {
543 SendCharCreate(CHAR_CREATE_LEVEL_REQUIREMENT);
544 return;
545 }
546
547 // Check name uniqueness in the same step as saving to database
548 if (sCharacterCache->GetCharacterCacheByName(createInfo->Name))
549 {
550 SendCharCreate(CHAR_CREATE_NAME_IN_USE);
551 return;
552 }
553
554 std::shared_ptr<Player> newChar(new Player(this), [](Player* ptr)
555 {
557 delete ptr;
558 });
559 newChar->GetMotionMaster()->Initialize();
560 if (!newChar->Create(sObjectMgr->GetGenerator<HighGuid::Player>().Generate(), createInfo.get()))
561 {
562 // Player not create (race/class/etc problem?)
563 SendCharCreate(CHAR_CREATE_ERROR);
564 return;
565 }
566
567 if ((haveSameRace && skipCinematics == 1) || skipCinematics == 2)
568 newChar->setCinematic(1); // not show intro
569
570 newChar->SetAtLoginFlag(AT_LOGIN_FIRST); // First login
571
572 CharacterDatabaseTransaction characterTransaction = CharacterDatabase.BeginTransaction();
573 LoginDatabaseTransaction trans = LoginDatabase.BeginTransaction();
574
575 // Player created, save it now
576 newChar->SaveToDB(characterTransaction, true);
577 createInfo->CharCount += 1;
578
580 stmt->setUInt32(0, createInfo->CharCount);
581 stmt->setUInt32(1, GetAccountId());
582 stmt->setUInt32(2, realm.Id.Realm);
583 trans->Append(stmt);
584
585 AddTransactionCallback(CharacterDatabase.AsyncCommitTransaction(characterTransaction)).AfterComplete([this, newChar = std::move(newChar), trans](bool success)
586 {
587 if (success)
588 {
589 LoginDatabase.CommitTransaction(trans);
590
591 TC_LOG_INFO("entities.player.character", "Account: {} (IP: {}) Create Character: {} {}", GetAccountId(), GetRemoteAddress(), newChar->GetName(), newChar->GetGUID().ToString());
592 sScriptMgr->OnPlayerCreate(newChar.get());
593 sCharacterCache->AddCharacterCacheEntry(newChar->GetGUID(), GetAccountId(), newChar->GetName(), newChar->GetNativeGender(), newChar->GetRace(), newChar->GetClass(), newChar->GetLevel());
594
595 SendCharCreate(CHAR_CREATE_SUCCESS);
596 }
597 else
598 SendCharCreate(CHAR_CREATE_ERROR);
599 });
600 };
601
602 if (allowTwoSideAccounts && !skipCinematics && createInfo->Class != CLASS_DEATH_KNIGHT)
603 {
604 finalizeCharacterCreation(PreparedQueryResult(nullptr));
605 return;
606 }
607
609 stmt->setUInt32(0, GetAccountId());
610 stmt->setUInt32(1, (skipCinematics == 1 || createInfo->Class == CLASS_DEATH_KNIGHT) ? 10 : 1);
611 queryCallback.WithPreparedCallback(std::move(finalizeCharacterCreation)).SetNextQuery(CharacterDatabase.AsyncQuery(stmt));
612 }));
613}
614
616{
617 // Initiating
618 uint32 initAccountId = GetAccountId();
619
620 // can't delete loaded character
621 if (ObjectAccessor::FindPlayer(charDelete.Guid))
622 {
623 sScriptMgr->OnPlayerFailedDelete(charDelete.Guid, initAccountId);
624 return;
625 }
626
627 uint32 accountId = 0;
628 uint8 level = 0;
629 std::string name;
630
631 // is guild leader
632 if (sGuildMgr->GetGuildByLeader(charDelete.Guid))
633 {
634 sScriptMgr->OnPlayerFailedDelete(charDelete.Guid, initAccountId);
636 return;
637 }
638
639 // is arena team captain
640 if (sArenaTeamMgr->GetArenaTeamByCaptain(charDelete.Guid))
641 {
642 sScriptMgr->OnPlayerFailedDelete(charDelete.Guid, initAccountId);
644 return;
645 }
646
647 CharacterCacheEntry const* characterInfo = sCharacterCache->GetCharacterCacheByGuid(charDelete.Guid);
648 if (!characterInfo)
649 {
650 sScriptMgr->OnPlayerFailedDelete(charDelete.Guid, initAccountId);
651 return;
652 }
653
654 accountId = characterInfo->AccountId;
655 name = characterInfo->Name;
656 level = characterInfo->Level;
657
658 // prevent deleting other players' characters using cheating tools
659 if (accountId != initAccountId)
660 {
661 sScriptMgr->OnPlayerFailedDelete(charDelete.Guid, initAccountId);
662 return;
663 }
664
665 TC_LOG_INFO("entities.player.character", "Account: {}, IP: {} deleted character: {}, {}, Level: {}", accountId, GetRemoteAddress(), name, charDelete.Guid.ToString(), level);
666
667 // To prevent hook failure, place hook before removing reference from DB
668 sScriptMgr->OnPlayerDelete(charDelete.Guid, initAccountId); // To prevent race conditioning, but as it also makes sense, we hand the accountId over for successful delete.
669 // Shouldn't interfere with character deletion though
670
671 if (sLog->ShouldLog("entities.player.dump", LOG_LEVEL_INFO)) // optimize GetPlayerDump call
672 {
673 std::string dump;
674 if (PlayerDumpWriter().GetDump(charDelete.Guid.GetCounter(), dump))
675 sLog->OutCharDump(dump.c_str(), accountId, charDelete.Guid.GetRawValue(), name.c_str());
676 }
677
678 sCalendarMgr->RemoveAllPlayerEventsAndInvites(charDelete.Guid);
679 Player::DeleteFromDB(charDelete.Guid, accountId);
680
682}
683
685{
686 if (PlayerLoading() || GetPlayer() != nullptr)
687 {
688 TC_LOG_ERROR("network", "Player tries to login again, AccountId = {}", GetAccountId());
689 KickPlayer("WorldSession::HandlePlayerLoginOpcode Another client logging in");
690 return;
691 }
692
693 m_playerLoading = true;
694 ObjectGuid playerGuid;
695
696 recvData >> playerGuid;
697
698 if (!IsLegitCharacterForAccount(playerGuid))
699 {
700 TC_LOG_ERROR("network", "Account ({}) can't login with that character ({}).", GetAccountId(), playerGuid.ToString());
701 KickPlayer("WorldSession::HandlePlayerLoginOpcode Trying to login with a character of another account");
702 return;
703 }
704
705 std::shared_ptr<LoginQueryHolder> holder = std::make_shared<LoginQueryHolder>(GetAccountId(), playerGuid);
706 if (!holder->Initialize())
707 {
708 m_playerLoading = false;
709 return;
710 }
711
712 AddQueryHolderCallback(CharacterDatabase.DelayQueryHolder(holder)).AfterComplete([this](SQLQueryHolderBase const& holder)
713 {
714 HandlePlayerLogin(static_cast<LoginQueryHolder const&>(holder));
715 });
716}
717
719{
720 ObjectGuid playerGuid = holder.GetGuid();
721
722 Player* pCurrChar = new Player(this);
723 // for send server info and strings (config)
724 ChatHandler chH = ChatHandler(pCurrChar->GetSession());
725
726 // "GetAccountId() == db stored account id" checked in LoadFromDB (prevent login not own character using cheating tools)
727 if (!pCurrChar->LoadFromDB(playerGuid, holder))
728 {
729 SetPlayer(nullptr);
730 KickPlayer("WorldSession::HandlePlayerLogin Player::LoadFromDB failed"); // disconnect client, player no set to session and it will not deleted or saved at kick
731 delete pCurrChar; // delete it manually
732 m_playerLoading = false;
733 return;
734 }
735
736 pCurrChar->GetMotionMaster()->Initialize();
737 pCurrChar->SendDungeonDifficulty(false);
738
740 loginVerifyWorld.MapID = pCurrChar->GetMapId();
741 loginVerifyWorld.Pos = pCurrChar->GetPosition();
742 SendPacket(loginVerifyWorld.Write());
743
744 // load player specific part before send times
747
749
750 // Send MOTD
751 {
753 motd.Text = &sWorld->GetMotd();
754 SendPacket(motd.Write());
755 }
756
757 // send server info
758 {
759 if (sWorld->getIntConfig(CONFIG_ENABLE_SINFO_LOGIN) == 1)
761 }
762
763 //QueryResult* result = CharacterDatabase.PQuery("SELECT guildid, rank FROM guild_member WHERE guid = '{}'", pCurrChar->GetGUID().GetCounter());
765 {
766 Field* fields = resultGuild->Fetch();
767 pCurrChar->SetInGuild(fields[0].GetUInt32());
768 pCurrChar->SetGuildRank(fields[1].GetUInt8());
769 }
770 else if (pCurrChar->GetGuildId()) // clear guild related fields in case wrong data about non existed membership
771 {
772 pCurrChar->SetInGuild(0);
773 pCurrChar->SetGuildRank(0);
774 }
775
776 if (pCurrChar->GetGuildId())
777 {
778 if (Guild* guild = sGuildMgr->GetGuildById(pCurrChar->GetGuildId()))
779 guild->SendLoginInfo(this);
780 else
781 {
782 // remove wrong guild data
783 TC_LOG_ERROR("network", "Player {} {} marked as member of not existing guild (id: {}), removing guild membership for player.", pCurrChar->GetName(), pCurrChar->GetGUID().ToString(), pCurrChar->GetGuildId());
784 pCurrChar->SetInGuild(0);
785 }
786 }
787
789 data << uint32(0);
790 data << uint32(0);
791 SendPacket(&data);
792
794
795 //Show cinematic at the first time that player login
796 if (!pCurrChar->getCinematic())
797 {
798 pCurrChar->setCinematic(1);
799
800 if (ChrClassesEntry const* cEntry = sChrClassesStore.LookupEntry(pCurrChar->GetClass()))
801 {
802 if (cEntry->CinematicSequenceID)
803 pCurrChar->SendCinematicStart(cEntry->CinematicSequenceID);
804 else if (ChrRacesEntry const* rEntry = sChrRacesStore.LookupEntry(pCurrChar->GetRace()))
805 pCurrChar->SendCinematicStart(rEntry->CinematicSequenceID);
806
807 // send new char string if not empty
808 if (!sWorld->GetNewCharString().empty())
809 chH.PSendSysMessage("%s", sWorld->GetNewCharString().c_str());
810 }
811 }
812
813 if (!pCurrChar->GetMap()->AddPlayerToMap(pCurrChar))
814 {
815 AreaTriggerTeleport const* at = sObjectMgr->GetGoBackTrigger(pCurrChar->GetMapId());
816 if (at)
817 pCurrChar->TeleportTo(at->target_mapId, at->target_X, at->target_Y, at->target_Z, pCurrChar->GetOrientation());
818 else
819 pCurrChar->TeleportTo(pCurrChar->m_homebindMapId, pCurrChar->m_homebindX, pCurrChar->m_homebindY, pCurrChar->m_homebindZ, pCurrChar->GetOrientation());
820 }
821
822 ObjectAccessor::AddObject(pCurrChar);
823 //TC_LOG_DEBUG("Player {} added to Map.", pCurrChar->GetName());
824
826
828 stmt->setUInt32(0, pCurrChar->GetGUID().GetCounter());
829 CharacterDatabase.Execute(stmt);
830
832 loginStmt->setUInt32(0, GetAccountId());
833 LoginDatabase.Execute(loginStmt);
834
836
837 // announce group about member online (must be after add to player list to receive announce to self)
838 if (Group* group = pCurrChar->GetGroup())
839 {
840 //pCurrChar->groupInfo.group->SendInit(this); // useless
841 group->SendUpdate();
842 group->ResetMaxEnchantingLevel();
843 if (group->GetLeaderGUID() == pCurrChar->GetGUID())
844 group->StopLeaderOfflineTimer();
845 }
846
847 // friend status
848 sSocialMgr->SendFriendStatus(pCurrChar, FRIEND_ONLINE, pCurrChar->GetGUID(), true);
849
850 // Place character in world (and load zone) before some object loading
852
853 // setting Ghost+speed if dead
854 if (pCurrChar->m_deathState == DEAD)
855 pCurrChar->SetWaterWalking(true);
856
857 pCurrChar->ContinueTaxiFlight();
858
859 // reset for all pets before pet loading
861 Pet::resetTalentsForAllPetsOf(pCurrChar, nullptr, true);
862
863 // Load pet if any (if player not alive and in taxi flight or another then pet will remember as temporary unsummoned)
864 pCurrChar->LoadPet();
865
866 // Set FFA PvP for non GM in non-rest mode
867 if (sWorld->IsFFAPvPRealm() && !pCurrChar->IsGameMaster() && !pCurrChar->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING))
869
871 pCurrChar->SetContestedPvP();
872
873 // Apply at_login requests
875 {
876 pCurrChar->ResetSpells();
878 }
879
881 {
882 pCurrChar->ResetTalents(true);
883 pCurrChar->SendTalentsInfoData(false); // original talents send already in to SendInitialPacketsBeforeAddToMap, resend reset state
884 }
885
886 bool firstLogin = pCurrChar->HasAtLoginFlag(AT_LOGIN_FIRST);
887 if (firstLogin)
888 {
890
891 PlayerInfo const* info = sObjectMgr->GetPlayerInfo(pCurrChar->GetRace(), pCurrChar->GetClass());
892 for (uint32 spellId : info->castSpells)
893 pCurrChar->CastSpell(pCurrChar, spellId, true);
894
895 // Start with all map areas explored if enabled
896 if (sWorld->getBoolConfig(CONFIG_START_ALL_EXPLORED))
897 for (uint8 i = 0; i < PLAYER_EXPLORED_ZONES_SIZE; ++i)
898 pCurrChar->SetFlag(PLAYER_EXPLORED_ZONES_1 + i, 0xFFFFFFFF);
899
900 // Max relevant reputations if "StartAllReputation" is enabled
901 if (sWorld->getBoolConfig(CONFIG_START_ALL_REP))
902 {
903 ReputationMgr& repMgr = pCurrChar->GetReputationMgr();
904 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry( 942), 42999, false); // Cenarion Expedition
905 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry( 935), 42999, false); // The Sha'tar
906 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry( 936), 42999, false); // Shattrath City
907 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry(1011), 42999, false); // Lower City
908 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry( 970), 42999, false); // Sporeggar
909 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry( 967), 42999, false); // The Violet Eye
910 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry( 989), 42999, false); // Keepers of Time
911 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry( 932), 42999, false); // The Aldor
912 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry( 934), 42999, false); // The Scryers
913 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry(1038), 42999, false); // Ogri'la
914 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry(1077), 42999, false); // Shattered Sun Offensive
915 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry(1106), 42999, false); // Argent Crusade
916 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry(1104), 42999, false); // Frenzyheart Tribe
917 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry(1090), 42999, false); // Kirin Tor
918 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry(1098), 42999, false); // Knights of the Ebon Blade
919 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry(1156), 42999, false); // The Ashen Verdict
920 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry(1073), 42999, false); // The Kalu'ak
921 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry(1105), 42999, false); // The Oracles
922 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry(1119), 42999, false); // The Sons of Hodir
923 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry(1091), 42999, false); // The Wyrmrest Accord
924
925 // Factions depending on team, like cities and some more stuff
926 switch (pCurrChar->GetTeam())
927 {
928 case ALLIANCE:
929 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry( 72), 42999, false); // Stormwind
930 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry( 47), 42999, false); // Ironforge
931 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry( 69), 42999, false); // Darnassus
932 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry( 930), 42999, false); // Exodar
933 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry( 730), 42999, false); // Stormpike Guard
934 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry( 978), 42999, false); // Kurenai
935 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry( 54), 42999, false); // Gnomeregan Exiles
936 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry( 946), 42999, false); // Honor Hold
937 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry(1037), 42999, false); // Alliance Vanguard
938 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry(1068), 42999, false); // Explorers' League
939 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry(1126), 42999, false); // The Frostborn
940 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry(1094), 42999, false); // The Silver Covenant
941 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry(1050), 42999, false); // Valiance Expedition
942 break;
943 case HORDE:
944 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry( 76), 42999, false); // Orgrimmar
945 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry( 68), 42999, false); // Undercity
946 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry( 81), 42999, false); // Thunder Bluff
947 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry( 911), 42999, false); // Silvermoon City
948 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry( 729), 42999, false); // Frostwolf Clan
949 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry( 941), 42999, false); // The Mag'har
950 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry( 530), 42999, false); // Darkspear Trolls
951 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry( 947), 42999, false); // Thrallmar
952 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry(1052), 42999, false); // Horde Expedition
953 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry(1067), 42999, false); // The Hand of Vengeance
954 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry(1124), 42999, false); // The Sunreavers
955 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry(1064), 42999, false); // The Taunka
956 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry(1085), 42999, false); // Warsong Offensive
957 break;
958 default:
959 break;
960 }
961 repMgr.SendState(nullptr);
962 }
963 }
964
965 // show time before shutdown if shutdown planned.
966 if (sWorld->IsShuttingDown())
967 sWorld->ShutdownMsg(true, pCurrChar);
968
969 if (sWorld->getBoolConfig(CONFIG_ALL_TAXI_PATHS))
970 pCurrChar->SetTaxiCheater(true);
971
972 if (pCurrChar->IsGameMaster())
974
975 TC_LOG_INFO("entities.player.character", "Account: {} (IP: {}) Login Character:[{}] {} Level: {}, XP: {}/{} ({} left)",
976 GetAccountId(), GetRemoteAddress(), pCurrChar->GetName(), pCurrChar->GetGUID().ToString(), pCurrChar->GetLevel(),
978
979 if (!pCurrChar->IsStandState() && !pCurrChar->HasUnitState(UNIT_STATE_STUNNED))
981
982 m_playerLoading = false;
983
984 // Handle Login-Achievements (should be handled after loading)
986
987 // if we're loading a dead player, repop them to the GY after the load is finished
988 if (pCurrChar->getDeathState() == CORPSE)
989 {
990 pCurrChar->BuildPlayerRepop();
991 pCurrChar->RepopAtGraveyard();
992 }
993
994 sScriptMgr->OnPlayerLogin(pCurrChar, firstLogin);
995
996 TC_METRIC_EVENT("player_events", "Login", pCurrChar->GetName());
997}
998
1006
1008{
1009 TC_LOG_DEBUG("network", "WORLD: Received CMSG_SET_FACTION_ATWAR");
1010
1011 uint32 repListID;
1012 uint8 flag;
1013
1014 recvData >> repListID;
1015 recvData >> flag;
1016
1017 GetPlayer()->GetReputationMgr().SetAtWar(repListID, flag != 0);
1018}
1019
1020//I think this function is never used :/ I dunno, but i guess this opcode not exists
1022{
1023 TC_LOG_ERROR("network", "WORLD SESSION: HandleSetFactionCheat, not expected call, please report.");
1024 GetPlayer()->GetReputationMgr().SendState(nullptr);
1025}
1026
1028{
1029 uint32 data;
1030 recvData >> data;
1031
1032 uint8 index = uint8(data / 32);
1033 if (index >= MAX_ACCOUNT_TUTORIAL_VALUES)
1034 return;
1035
1036 uint32 value = (data % 32);
1037
1038 uint32 flag = GetTutorialInt(index);
1039 flag |= (1 << value);
1040 SetTutorialInt(index, flag);
1041}
1042
1044{
1045 for (uint8 i = 0; i < MAX_ACCOUNT_TUTORIAL_VALUES; ++i)
1046 SetTutorialInt(i, 0xFFFFFFFF);
1047}
1048
1050{
1051 for (uint8 i = 0; i < MAX_ACCOUNT_TUTORIAL_VALUES; ++i)
1052 SetTutorialInt(i, 0x00000000);
1053}
1054
1056{
1057 TC_LOG_DEBUG("network", "WORLD: Received CMSG_SET_WATCHED_FACTION");
1058 uint32 fact;
1059 recvData >> fact;
1061}
1062
1064{
1065 TC_LOG_DEBUG("network", "WORLD: Received CMSG_SET_FACTION_INACTIVE");
1066 uint32 replistid;
1067 uint8 inactive;
1068 recvData >> replistid >> inactive;
1069
1070 _player->GetReputationMgr().SetInactive(replistid, inactive != 0);
1071}
1072
1080
1088
1090{
1091 if (!IsLegitCharacterForAccount(request.RenameInfo->Guid))
1092 {
1093 TC_LOG_ERROR("network", "Account {}, IP: {} tried to rename character {}, but it does not belong to their account!",
1094 GetAccountId(), GetRemoteAddress(), request.RenameInfo->Guid.ToString());
1095 KickPlayer("WorldSession::HandleCharRenameOpcode rename character from a different account");
1096 return;
1097 }
1098
1099 // prevent character rename to invalid name
1100 if (!normalizePlayerName(request.RenameInfo->NewName))
1101 {
1103 return;
1104 }
1105
1107 if (res != CHAR_NAME_SUCCESS)
1108 {
1109 SendCharRename(res, request.RenameInfo.get());
1110 return;
1111 }
1112
1113 // check name limitations
1115 {
1117 return;
1118 }
1119
1120 // Ensure that the character belongs to the current account, that rename at login is enabled
1121 // and that there is no character with the desired new name
1123
1124 stmt->setUInt32(0, request.RenameInfo->Guid.GetCounter());
1125 stmt->setString(1, request.RenameInfo->NewName);
1126
1128 .WithPreparedCallback([this, renameInfo = std::move(request.RenameInfo)](PreparedQueryResult result) mutable
1129 {
1130 HandleCharRenameCallBack(std::move(renameInfo), std::move(result));
1131 }));
1132}
1133
1134void WorldSession::HandleCharRenameCallBack(std::shared_ptr<WorldPackets::Character::CharacterRenameInfo> renameInfo, PreparedQueryResult result)
1135{
1136 if (!result)
1137 {
1138 SendCharRename(CHAR_CREATE_ERROR, renameInfo.get());
1139 return;
1140 }
1141
1142 Field* fields = result->Fetch();
1143
1144 std::string oldName = fields[0].GetString();
1145 uint16 atLoginFlags = fields[1].GetUInt16();
1146
1147 if (!(atLoginFlags & AT_LOGIN_RENAME))
1148 {
1149 SendCharRename(CHAR_CREATE_ERROR, renameInfo.get());
1150 return;
1151 }
1152
1153 atLoginFlags &= ~AT_LOGIN_RENAME;
1154
1155 CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
1156
1157 // Update name and at_login flag in the db
1159
1160 stmt->setString(0, renameInfo->NewName);
1161 stmt->setUInt16(1, atLoginFlags);
1162 stmt->setUInt32(2, renameInfo->Guid.GetCounter());
1163
1164 CharacterDatabase.Execute(stmt);
1165
1166 // Removed declined name from db
1167 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_DECLINED_NAME);
1168
1169 stmt->setUInt32(0, renameInfo->Guid.GetCounter());
1170
1171 CharacterDatabase.Execute(stmt);
1172
1173 TC_LOG_INFO("entities.player.character", "Account: {} (IP: {}) Character:[{}] ({}) Changed name to: {}", GetAccountId(), GetRemoteAddress(), oldName, renameInfo->Guid.ToString(), renameInfo->NewName);
1174
1175 SendCharRename(RESPONSE_SUCCESS, renameInfo.get());
1176
1177 sCharacterCache->UpdateCharacterData(renameInfo->Guid, renameInfo->NewName);
1178}
1179
1181{
1182 ObjectGuid guid;
1183
1184 recvData >> guid;
1185
1186 // not accept declined names for unsupported languages
1187 std::string name;
1188 if (!sCharacterCache->GetCharacterNameByGuid(guid, name))
1189 {
1191 return;
1192 }
1193
1194 std::wstring wname;
1195 if (!Utf8toWStr(name, wname))
1196 {
1198 return;
1199 }
1200
1201 if (!isCyrillicCharacter(wname[0])) // name already stored as only single alphabet using
1202 {
1204 return;
1205 }
1206
1207 std::string name2;
1208 DeclinedName declinedname;
1209
1210 recvData >> name2;
1211
1212 if (name2 != name) // character have different name
1213 {
1215 return;
1216 }
1217
1218 for (int i = 0; i < MAX_DECLINED_NAME_CASES; ++i)
1219 {
1220 recvData >> declinedname.name[i];
1221 if (!normalizePlayerName(declinedname.name[i]))
1222 {
1224 return;
1225 }
1226 }
1227
1228 if (!ObjectMgr::CheckDeclinedNames(wname, declinedname))
1229 {
1231 return;
1232 }
1233
1234 for (int i = 0; i < MAX_DECLINED_NAME_CASES; ++i)
1235 CharacterDatabase.EscapeString(declinedname.name[i]);
1236
1237 CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
1238
1240 stmt->setUInt32(0, guid.GetCounter());
1241 trans->Append(stmt);
1242
1243 stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHAR_DECLINED_NAME);
1244 stmt->setUInt32(0, guid.GetCounter());
1245
1246 for (uint8 i = 0; i < 5; i++)
1247 stmt->setString(i+1, declinedname.name[i]);
1248
1249 trans->Append(stmt);
1250
1251 CharacterDatabase.CommitTransaction(trans);
1252
1254}
1255
1257{
1258 TC_LOG_DEBUG("network", "CMSG_ALTER_APPEARANCE");
1259
1260 uint32 Hair, Color, FacialHair, SkinColor;
1261 recvData >> Hair >> Color >> FacialHair >> SkinColor;
1262
1263 BarberShopStyleEntry const* bs_hair = sBarberShopStyleStore.LookupEntry(Hair);
1264
1265 if (!bs_hair || bs_hair->Type != 0 || bs_hair->Race != _player->GetRace() || Gender(bs_hair->Sex) != _player->GetNativeGender())
1266 return;
1267
1268 BarberShopStyleEntry const* bs_facialHair = sBarberShopStyleStore.LookupEntry(FacialHair);
1269
1270 if (!bs_facialHair || bs_facialHair->Type != 2 || bs_facialHair->Race != _player->GetRace() || Gender(bs_facialHair->Sex) != _player->GetNativeGender())
1271 return;
1272
1273 BarberShopStyleEntry const* bs_skinColor = sBarberShopStyleStore.LookupEntry(SkinColor);
1274
1275 if (bs_skinColor && (bs_skinColor->Type != 3 || bs_skinColor->Race != _player->GetRace() || Gender(bs_skinColor->Sex) != _player->GetNativeGender()))
1276 return;
1277
1279 bs_hair->Data, Color, _player->GetFaceId(), bs_facialHair->Data,
1280 bs_skinColor ? bs_skinColor->Data : _player->GetSkinId()))
1281 return;
1282
1284 if (!go)
1285 {
1287 return;
1288 }
1289
1291 {
1293 return;
1294 }
1295
1296 uint32 cost = _player->GetBarberShopCost(bs_hair->Data, Color, bs_facialHair->Data, bs_skinColor);
1297
1298 // 0 - ok
1299 // 1, 3 - not enough money
1300 // 2 - you have to sit on barber chair
1301 if (!_player->HasEnoughMoney(cost))
1302 {
1304 return;
1305 }
1306
1308
1309 _player->ModifyMoney(-int32(cost)); // it isn't free
1311
1312 _player->SetHairStyleId(uint8(bs_hair->Data));
1313 _player->SetHairColorId(uint8(Color));
1314 _player->SetFacialStyle(uint8(bs_facialHair->Data));
1315 if (bs_skinColor)
1316 _player->SetSkinId(uint8(bs_skinColor->Data));
1317
1319
1321}
1322
1324{
1325 uint32 slot;
1326 recvData >> slot;
1327
1328 if (slot >= MAX_GLYPH_SLOT_INDEX)
1329 {
1330 TC_LOG_DEBUG("network", "Client sent wrong glyph slot number in opcode CMSG_REMOVE_GLYPH {}", slot);
1331 return;
1332 }
1333
1334 if (uint32 glyph = _player->GetGlyph(_player->GetActiveTalentGroup(), slot))
1335 {
1336 if (GlyphPropertiesEntry const* gp = sGlyphPropertiesStore.LookupEntry(glyph))
1337 {
1338 _player->RemoveAurasDueToSpell(gp->SpellID);
1339 _player->SetGlyph(slot, 0);
1341 }
1342 }
1343}
1344
1346{
1347 if (!IsLegitCharacterForAccount(packet.CustomizeInfo->CharGUID))
1348 {
1349 TC_LOG_ERROR("entities.player.cheat", "Account {}, IP: {} tried to customise {}, but it does not belong to their account!",
1350 GetAccountId(), GetRemoteAddress(), packet.CustomizeInfo->CharGUID.ToString());
1351 KickPlayer("WorldSession::HandleCharCustomize Trying to customise character of another account");
1352 return;
1353 }
1354
1356 stmt->setUInt32(0, packet.CustomizeInfo->CharGUID.GetCounter());
1357
1359 .WithPreparedCallback([this, customizeInfo = std::move(packet.CustomizeInfo)](PreparedQueryResult result) mutable
1360 {
1361 HandleCharCustomizeCallback(std::move(customizeInfo), std::move(result));
1362 }));
1363}
1364
1365void WorldSession::HandleCharCustomizeCallback(std::shared_ptr<WorldPackets::Character::CharCustomizeInfo> customizeInfo, PreparedQueryResult result)
1366{
1367 if (!result)
1368 {
1369 SendCharCustomize(CHAR_CREATE_ERROR, customizeInfo.get());
1370 return;
1371 }
1372
1373 Field* fields = result->Fetch();
1374 std::string oldName = fields[0].GetString();
1375 uint8 plrRace = fields[1].GetUInt8();
1376 uint8 plrClass = fields[2].GetUInt8();
1377 uint8 plrGender = fields[3].GetUInt8();
1378 uint16 atLoginFlags = fields[4].GetUInt16();
1379
1380 if (!Player::ValidateAppearance(plrRace, plrClass, plrGender, customizeInfo->HairStyleID, customizeInfo->HairColorID, customizeInfo->FaceID, customizeInfo->FacialHairStyleID, customizeInfo->SkinID, true))
1381 {
1382 SendCharCustomize(CHAR_CREATE_ERROR, customizeInfo.get());
1383 return;
1384 }
1385
1386 if (!(atLoginFlags & AT_LOGIN_CUSTOMIZE))
1387 {
1388 SendCharCustomize(CHAR_CREATE_ERROR, customizeInfo.get());
1389 return;
1390 }
1391
1392 atLoginFlags &= ~AT_LOGIN_CUSTOMIZE;
1393
1394 // prevent character rename
1395 if (sWorld->getBoolConfig(CONFIG_PREVENT_RENAME_CUSTOMIZATION) && (customizeInfo->CharName != oldName))
1396 {
1397 SendCharCustomize(CHAR_NAME_FAILURE, customizeInfo.get());
1398 return;
1399 }
1400
1401 // prevent character rename to invalid name
1402 if (!normalizePlayerName(customizeInfo->CharName))
1403 {
1404 SendCharCustomize(CHAR_NAME_NO_NAME, customizeInfo.get());
1405 return;
1406 }
1407
1408 ResponseCodes res = ObjectMgr::CheckPlayerName(customizeInfo->CharName, GetSessionDbcLocale(), true);
1409 if (res != CHAR_NAME_SUCCESS)
1410 {
1411 SendCharCustomize(res, customizeInfo.get());
1412 return;
1413 }
1414
1415 // check name limitations
1416 if (!HasPermission(rbac::RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_RESERVEDNAME) && sObjectMgr->IsReservedName(customizeInfo->CharName))
1417 {
1418 SendCharCustomize(CHAR_NAME_RESERVED, customizeInfo.get());
1419 return;
1420 }
1421
1422 // character with this name already exist
1423 ObjectGuid newGuid = sCharacterCache->GetCharacterGuidByName(customizeInfo->CharName);
1424 if (!newGuid.IsEmpty())
1425 {
1426 if (newGuid != customizeInfo->CharGUID)
1427 {
1428 SendCharCustomize(CHAR_CREATE_NAME_IN_USE, customizeInfo.get());
1429 return;
1430 }
1431 }
1432
1433 CharacterDatabasePreparedStatement* stmt = nullptr;
1434 CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
1435
1436 ObjectGuid::LowType lowGuid = customizeInfo->CharGUID.GetCounter();
1437
1439 {
1440 stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_GENDER_AND_APPEARANCE);
1441
1442 stmt->setUInt8(0, customizeInfo->SexID);
1443 stmt->setUInt8(1, customizeInfo->SkinID);
1444 stmt->setUInt8(2, customizeInfo->FaceID);
1445 stmt->setUInt8(3, customizeInfo->HairStyleID);
1446 stmt->setUInt8(4, customizeInfo->HairColorID);
1447 stmt->setUInt8(5, customizeInfo->FacialHairStyleID);
1448 stmt->setUInt32(6, customizeInfo->CharGUID.GetCounter());
1449
1450 trans->Append(stmt);
1451 }
1452
1454 {
1455 stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_NAME_AT_LOGIN);
1456 stmt->setString(0, customizeInfo->CharName);
1457 stmt->setUInt16(1, atLoginFlags);
1458 stmt->setUInt32(2, lowGuid);
1459
1460 trans->Append(stmt);
1461
1462 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_DECLINED_NAME);
1463 stmt->setUInt32(0, lowGuid);
1464
1465 trans->Append(stmt);
1466 }
1467
1468 CharacterDatabase.CommitTransaction(trans);
1469
1470 sCharacterCache->UpdateCharacterData(customizeInfo->CharGUID, customizeInfo->CharName, customizeInfo->SexID);
1471
1472 SendCharCustomize(RESPONSE_SUCCESS, customizeInfo.get());
1473
1474 TC_LOG_INFO("entities.player.character", "Account: {} (IP: {}), Character[{}] ({}) Customized to: {}",
1475 GetAccountId(), GetRemoteAddress(), oldName, customizeInfo->CharGUID.ToString(), customizeInfo->CharName);
1476}
1477
1479{
1480 TC_LOG_DEBUG("network", "CMSG_EQUIPMENT_SET_SAVE");
1481
1482 uint64 setGuid;
1483 recvData.readPackGUID(setGuid);
1484
1485 uint32 index;
1486 recvData >> index;
1487 if (index >= MAX_EQUIPMENT_SET_INDEX) // client set slots amount
1488 return;
1489
1490 std::string name;
1491 recvData >> name;
1492
1493 std::string iconName;
1494 recvData >> iconName;
1495
1497 eqData.Guid = setGuid;
1498 eqData.SetID = index;
1499 eqData.SetName = name;
1500 eqData.SetIcon = iconName;
1501
1502 for (uint32 i = 0; i < EQUIPMENT_SLOT_END; ++i)
1503 {
1504 ObjectGuid itemGuid;
1505 recvData >> itemGuid.ReadAsPacked();
1506
1507 // if client sends 0, it means empty slot
1508 if (itemGuid.IsEmpty())
1509 continue;
1510
1511 // equipment manager sends "1" (as raw GUID) for slots set to "ignore" (don't touch slot at equip set)
1512 if (itemGuid.GetRawValue() == 1)
1513 {
1514 // ignored slots saved as bit mask because we have no free special values for Items[i]
1515 eqData.IgnoreMask |= 1 << i;
1516 continue;
1517 }
1518
1519 // some cheating checks
1521 if (!item || item->GetGUID() != itemGuid)
1522 continue;
1523
1524 eqData.Pieces[i] = itemGuid;
1525 }
1526
1527 _player->SetEquipmentSet(eqData);
1528}
1529
1531{
1532 TC_LOG_DEBUG("network", "CMSG_EQUIPMENT_SET_DELETE");
1533
1534 uint64 setGuid;
1535 recvData.readPackGUID(setGuid);
1536
1537 _player->DeleteEquipmentSet(setGuid);
1538}
1539
1541{
1542 TC_LOG_DEBUG("network", "CMSG_EQUIPMENT_SET_USE");
1543
1544 for (uint32 i = 0; i < EQUIPMENT_SLOT_END; ++i)
1545 {
1546 ObjectGuid itemGuid;
1547 recvData >> itemGuid.ReadAsPacked();
1548
1549 uint8 srcbag, srcslot;
1550 recvData >> srcbag >> srcslot;
1551
1552 TC_LOG_DEBUG("entities.player.items", "{}: srcbag {}, srcslot {}", itemGuid.ToString(), srcbag, srcslot);
1553
1554 // check if item slot is set to "ignored" (raw value == 1), must not be unequipped then
1555 if (itemGuid.GetRawValue() == 1)
1556 continue;
1557
1558 // Only equip weapons in combat
1560 continue;
1561
1562 Item* item = _player->GetItemByGuid(itemGuid);
1563
1564 uint16 dstpos = i | (INVENTORY_SLOT_BAG_0 << 8);
1565
1566 if (!item)
1567 {
1569 if (!uItem)
1570 continue;
1571
1572 ItemPosCountVec sDest;
1573 InventoryResult msg = _player->CanStoreItem(NULL_BAG, NULL_SLOT, sDest, uItem, false);
1574 if (msg == EQUIP_ERR_OK)
1575 {
1576 if (_player->CanUnequipItem(dstpos, true) != EQUIP_ERR_OK)
1577 continue;
1578
1580 _player->StoreItem(sDest, uItem, true);
1581 }
1582 else
1583 _player->SendEquipError(msg, uItem, nullptr);
1584
1585 continue;
1586 }
1587
1588 if (item->GetPos() == dstpos)
1589 continue;
1590
1591 if (_player->CanEquipItem(i, dstpos, item, true) != EQUIP_ERR_OK)
1592 continue;
1593
1594 _player->SwapItem(item->GetPos(), dstpos);
1595 }
1596
1598 data << uint8(0); // 4 - equipment swap failed - inventory is full
1599 SendPacket(&data);
1600}
1601
1603{
1605 {
1606 TC_LOG_ERROR("entities.player.cheat", "Account {}, IP: {} tried to factionchange character {}, but it does not belong to their account!",
1607 GetAccountId(), GetRemoteAddress(), packet.RaceOrFactionChangeInfo->Guid.ToString());
1608 KickPlayer("WorldSession::HandleCharRaceOrFactionChange Trying to change faction of character of another account");
1609 return;
1610 }
1611
1613 stmt->setUInt32(0, packet.RaceOrFactionChangeInfo->Guid.GetCounter());
1614
1616 .WithPreparedCallback([this, factionChangeInfo = std::move(packet.RaceOrFactionChangeInfo)](PreparedQueryResult result) mutable
1617 {
1618 HandleCharRaceOrFactionChangeCallback(std::move(factionChangeInfo), std::move(result));
1619 }));
1620}
1621
1622void WorldSession::HandleCharRaceOrFactionChangeCallback(std::shared_ptr<WorldPackets::Character::CharRaceOrFactionChangeInfo> factionChangeInfo, PreparedQueryResult result)
1623{
1624 if (!result)
1625 {
1626 SendCharFactionChange(CHAR_CREATE_ERROR, factionChangeInfo.get());
1627 return;
1628 }
1629
1630 // get the players old (at this moment current) race
1631 CharacterCacheEntry const* characterInfo = sCharacterCache->GetCharacterCacheByGuid(factionChangeInfo->Guid);
1632 if (!characterInfo)
1633 {
1634 SendCharFactionChange(CHAR_CREATE_ERROR, factionChangeInfo.get());
1635 return;
1636 }
1637
1638 uint8 oldRace = characterInfo->Race;
1639 uint8 playerClass = characterInfo->Class;
1640 uint8 level = characterInfo->Level;
1641 //std::string oldName = characterInfo->Name;
1642
1643 if (!sObjectMgr->GetPlayerInfo(factionChangeInfo->RaceID, playerClass))
1644 {
1645 SendCharFactionChange(CHAR_CREATE_ERROR, factionChangeInfo.get());
1646 return;
1647 }
1648
1649 Field* fields = result->Fetch();
1650 uint32 atLoginFlags = fields[0].GetUInt16();
1651 std::string knownTitlesStr = fields[1].GetString();
1652 uint32 groupId = !fields[2].IsNull() ? fields[2].GetUInt32() : 0;
1653 uint32 mapId = fields[3].GetUInt16();
1654
1655 uint32 usedLoginFlag = (factionChangeInfo->FactionChange ? AT_LOGIN_CHANGE_FACTION : AT_LOGIN_CHANGE_RACE);
1656 if (!(atLoginFlags & usedLoginFlag))
1657 {
1658 SendCharFactionChange(CHAR_CREATE_ERROR, factionChangeInfo.get());
1659 return;
1660 }
1661
1662 if (level < 10)
1663 {
1664 SendCharFactionChange(CHAR_CREATE_ERROR, factionChangeInfo.get());
1665 return;
1666 }
1667
1668 if (playerClass == CLASS_DEATH_KNIGHT && (level < 60 || mapId == 609))
1669 {
1671 return;
1672 }
1673
1674 uint32 newTeam = Player::TeamForRace(factionChangeInfo->RaceID);
1675 if (factionChangeInfo->FactionChange == (Player::TeamForRace(oldRace) == newTeam))
1676 {
1677 SendCharFactionChange(factionChangeInfo->FactionChange ? CHAR_CREATE_CHARACTER_SWAP_FACTION : CHAR_CREATE_CHARACTER_RACE_ONLY, factionChangeInfo.get());
1678 return;
1679 }
1680
1682 {
1683 uint32 raceMaskDisabled = sWorld->getIntConfig(CONFIG_CHARACTER_CREATING_DISABLED_RACEMASK);
1684 if ((1 << (factionChangeInfo->RaceID - 1)) & raceMaskDisabled)
1685 {
1686 SendCharFactionChange(CHAR_CREATE_ERROR, factionChangeInfo.get());
1687 return;
1688 }
1689 }
1690
1691 // prevent character rename
1692 if (sWorld->getBoolConfig(CONFIG_PREVENT_RENAME_CUSTOMIZATION) && (factionChangeInfo->Name != characterInfo->Name))
1693 {
1694 SendCharFactionChange(CHAR_NAME_FAILURE, factionChangeInfo.get());
1695 return;
1696 }
1697
1698 // prevent character rename to invalid name
1699 if (!normalizePlayerName(factionChangeInfo->Name))
1700 {
1701 SendCharFactionChange(CHAR_NAME_NO_NAME, factionChangeInfo.get());
1702 return;
1703 }
1704
1705 ResponseCodes res = ObjectMgr::CheckPlayerName(factionChangeInfo->Name, GetSessionDbcLocale(), true);
1706 if (res != CHAR_NAME_SUCCESS)
1707 {
1708 SendCharFactionChange(res, factionChangeInfo.get());
1709 return;
1710 }
1711
1712 // check name limitations
1713 if (!HasPermission(rbac::RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_RESERVEDNAME) && sObjectMgr->IsReservedName(factionChangeInfo->Name))
1714 {
1715 SendCharFactionChange(CHAR_NAME_RESERVED, factionChangeInfo.get());
1716 return;
1717 }
1718
1719 // character with this name already exist
1720 ObjectGuid newGuid = sCharacterCache->GetCharacterGuidByName(factionChangeInfo->Name);
1721 if (!newGuid.IsEmpty())
1722 {
1723 if (newGuid != factionChangeInfo->Guid)
1724 {
1725 SendCharFactionChange(CHAR_CREATE_NAME_IN_USE, factionChangeInfo.get());
1726 return;
1727 }
1728 }
1729
1730 if (sArenaTeamMgr->GetArenaTeamByCaptain(factionChangeInfo->Guid))
1731 {
1733 return;
1734 }
1735
1736 // All checks are fine, deal with race change now
1737 ObjectGuid::LowType lowGuid = factionChangeInfo->Guid.GetCounter();
1738
1739 CharacterDatabasePreparedStatement* stmt = nullptr;
1740 CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
1741
1742 // resurrect the character in case he's dead
1743 Player::OfflineResurrect(factionChangeInfo->Guid, trans);
1744
1745 // Name Change and update atLogin flags
1746 {
1747 CharacterDatabase.EscapeString(factionChangeInfo->Name);
1748
1749 stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_NAME_AT_LOGIN);
1750 stmt->setString(0, factionChangeInfo->Name);
1751 stmt->setUInt16(1, uint16((atLoginFlags | AT_LOGIN_RESURRECT) & ~usedLoginFlag));
1752 stmt->setUInt32(2, lowGuid);
1753 trans->Append(stmt);
1754
1755 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_DECLINED_NAME);
1756 stmt->setUInt32(0, lowGuid);
1757 trans->Append(stmt);
1758 }
1759
1760 // Customize
1761 {
1762 stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_GENDER_AND_APPEARANCE);
1763
1764 stmt->setUInt8(0, factionChangeInfo->SexID);
1765 stmt->setUInt8(1, factionChangeInfo->SkinID);
1766 stmt->setUInt8(2, factionChangeInfo->FaceID);
1767 stmt->setUInt8(3, factionChangeInfo->HairStyleID);
1768 stmt->setUInt8(4, factionChangeInfo->HairColorID);
1769 stmt->setUInt8(5, factionChangeInfo->FacialHairStyleID);
1770 stmt->setUInt32(6, factionChangeInfo->Guid.GetCounter());
1771
1772 trans->Append(stmt);
1773 }
1774
1775 // Race Change
1776 {
1777 stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_RACE);
1778 stmt->setUInt8(0, factionChangeInfo->RaceID);
1780 stmt->setUInt32(2, lowGuid);
1781 trans->Append(stmt);
1782 }
1783
1784 sCharacterCache->UpdateCharacterData(factionChangeInfo->Guid, factionChangeInfo->Name, factionChangeInfo->SexID, factionChangeInfo->RaceID);
1785
1786 if (oldRace != factionChangeInfo->RaceID)
1787 {
1788 // Switch Languages
1789 // delete all languages first
1790 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_SKILL_LANGUAGES);
1791 stmt->setUInt32(0, lowGuid);
1792 trans->Append(stmt);
1793
1794 // Now add them back
1795 stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHAR_SKILL_LANGUAGE);
1796 stmt->setUInt32(0, lowGuid);
1797
1798 // Faction specific languages
1799 if (newTeam == HORDE)
1800 stmt->setUInt16(1, 109);
1801 else
1802 stmt->setUInt16(1, 98);
1803
1804 trans->Append(stmt);
1805
1806 // Race specific languages
1807 if (factionChangeInfo->RaceID != RACE_ORC && factionChangeInfo->RaceID != RACE_HUMAN)
1808 {
1809 stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHAR_SKILL_LANGUAGE);
1810 stmt->setUInt32(0, lowGuid);
1811
1812 switch (factionChangeInfo->RaceID)
1813 {
1814 case RACE_DWARF:
1815 stmt->setUInt16(1, 111);
1816 break;
1817 case RACE_DRAENEI:
1818 stmt->setUInt16(1, 759);
1819 break;
1820 case RACE_GNOME:
1821 stmt->setUInt16(1, 313);
1822 break;
1823 case RACE_NIGHTELF:
1824 stmt->setUInt16(1, 113);
1825 break;
1826 case RACE_UNDEAD_PLAYER:
1827 stmt->setUInt16(1, 673);
1828 break;
1829 case RACE_TAUREN:
1830 stmt->setUInt16(1, 115);
1831 break;
1832 case RACE_TROLL:
1833 stmt->setUInt16(1, 315);
1834 break;
1835 case RACE_BLOODELF:
1836 stmt->setUInt16(1, 137);
1837 break;
1838 }
1839
1840 trans->Append(stmt);
1841 }
1842
1843 if (factionChangeInfo->FactionChange)
1844 {
1845 // Delete all Flypaths
1846 stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_TAXI_PATH);
1847 stmt->setUInt32(0, lowGuid);
1848 trans->Append(stmt);
1849
1850 if (level > 7)
1851 {
1852 // Update Taxi path
1853 // this doesn't seem to be 100% blizzlike... but it can't really be helped.
1854 std::ostringstream taximaskstream;
1855 uint32 numFullTaximasks = level / 7;
1856 if (numFullTaximasks > 11)
1857 numFullTaximasks = 11;
1858
1859 TaxiMask const& factionMask = newTeam == HORDE ? sHordeTaxiNodesMask : sAllianceTaxiNodesMask;
1860 for (uint8 i = 0; i < numFullTaximasks; ++i)
1861 {
1862 uint8 deathKnightExtraNode = (playerClass == CLASS_DEATH_KNIGHT) ? sDeathKnightTaxiNodesMask[i] : 0;
1863 taximaskstream << uint32(factionMask[i] | deathKnightExtraNode) << ' ';
1864 }
1865
1866 uint32 numEmptyTaximasks = 11 - numFullTaximasks;
1867 for (uint8 i = 0; i < numEmptyTaximasks; ++i)
1868 taximaskstream << "0 ";
1869 taximaskstream << '0';
1870
1871 stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_TAXIMASK);
1872 stmt->setString(0, taximaskstream.str());
1873 stmt->setUInt32(1, lowGuid);
1874 trans->Append(stmt);
1875 }
1876
1878 {
1879 // Reset guild
1880 if (Guild* guild = sGuildMgr->GetGuildById(characterInfo->GuildId))
1881 guild->DeleteMember(trans, factionChangeInfo->Guid, false, false);
1882
1883 Player::LeaveAllArenaTeams(factionChangeInfo->Guid);
1884 }
1885
1886 if (groupId && !sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP))
1887 {
1888 if (Group* group = sGroupMgr->GetGroupByDbStoreId(groupId))
1889 group->RemoveMember(factionChangeInfo->Guid);
1890 }
1891
1893 {
1894 // Delete Friend List
1895 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_SOCIAL_BY_GUID);
1896 stmt->setUInt32(0, lowGuid);
1897 trans->Append(stmt);
1898
1899 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_SOCIAL_BY_FRIEND);
1900 stmt->setUInt32(0, lowGuid);
1901 trans->Append(stmt);
1902 }
1903
1904 // Reset homebind and position
1905 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PLAYER_HOMEBIND);
1906 stmt->setUInt32(0, lowGuid);
1907 trans->Append(stmt);
1908
1909 stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_PLAYER_HOMEBIND);
1910 stmt->setUInt32(0, lowGuid);
1911
1912 WorldLocation loc;
1913 uint16 zoneId = 0;
1914 if (newTeam == ALLIANCE)
1915 {
1916 loc.WorldRelocate(0, -8867.68f, 673.373f, 97.9034f, 0.0f);
1917 zoneId = 1519;
1918 }
1919 else
1920 {
1921 loc.WorldRelocate(1, 1633.33f, -4439.11f, 15.7588f, 0.0f);
1922 zoneId = 1637;
1923 }
1924
1925 stmt->setUInt16(1, loc.GetMapId());
1926 stmt->setUInt16(2, zoneId);
1927 stmt->setFloat(3, loc.GetPositionX());
1928 stmt->setFloat(4, loc.GetPositionY());
1929 stmt->setFloat(5, loc.GetPositionZ());
1930 trans->Append(stmt);
1931
1932 Player::SavePositionInDB(loc, zoneId, factionChangeInfo->Guid, trans);
1933
1934 // Achievement conversion
1935 for (std::map<uint32, uint32>::const_iterator it = sObjectMgr->FactionChangeAchievements.begin(); it != sObjectMgr->FactionChangeAchievements.end(); ++it)
1936 {
1937 uint32 achiev_alliance = it->first;
1938 uint32 achiev_horde = it->second;
1939
1941 stmt->setUInt16(0, uint16(newTeam == ALLIANCE ? achiev_alliance : achiev_horde));
1942 stmt->setUInt32(1, lowGuid);
1943 trans->Append(stmt);
1944
1945 stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_ACHIEVEMENT);
1946 stmt->setUInt16(0, uint16(newTeam == ALLIANCE ? achiev_alliance : achiev_horde));
1947 stmt->setUInt16(1, uint16(newTeam == ALLIANCE ? achiev_horde : achiev_alliance));
1948 stmt->setUInt32(2, lowGuid);
1949 trans->Append(stmt);
1950 }
1951
1952 // Item conversion
1953 for (std::map<uint32, uint32>::const_iterator it = sObjectMgr->FactionChangeItems.begin(); it != sObjectMgr->FactionChangeItems.end(); ++it)
1954 {
1955 uint32 item_alliance = it->first;
1956 uint32 item_horde = it->second;
1957
1958 stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_INVENTORY_FACTION_CHANGE);
1959 stmt->setUInt32(0, (newTeam == ALLIANCE ? item_alliance : item_horde));
1960 stmt->setUInt32(1, (newTeam == ALLIANCE ? item_horde : item_alliance));
1961 stmt->setUInt32(2, lowGuid);
1962 trans->Append(stmt);
1963 }
1964
1965 // Delete all current quests
1966 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_QUESTSTATUS);
1967 stmt->setUInt32(0, lowGuid);
1968 trans->Append(stmt);
1969
1970 // Quest conversion
1971 for (std::map<uint32, uint32>::const_iterator it = sObjectMgr->FactionChangeQuests.begin(); it != sObjectMgr->FactionChangeQuests.end(); ++it)
1972 {
1973 uint32 quest_alliance = it->first;
1974 uint32 quest_horde = it->second;
1975
1977 stmt->setUInt32(0, lowGuid);
1978 stmt->setUInt32(1, (newTeam == ALLIANCE ? quest_alliance : quest_horde));
1979 trans->Append(stmt);
1980
1982 stmt->setUInt32(0, (newTeam == ALLIANCE ? quest_alliance : quest_horde));
1983 stmt->setUInt32(1, (newTeam == ALLIANCE ? quest_horde : quest_alliance));
1984 stmt->setUInt32(2, lowGuid);
1985 trans->Append(stmt);
1986 }
1987
1988 // Mark all rewarded quests as "active" (will count for completed quests achievements)
1990 stmt->setUInt32(0, lowGuid);
1991 trans->Append(stmt);
1992
1993 // Disable all old-faction specific quests
1994 {
1995 ObjectMgr::QuestContainer const& questTemplates = sObjectMgr->GetQuestTemplates();
1996 for (auto const& [questId, quest] : questTemplates)
1997 {
1998 uint32 newRaceMask = (newTeam == ALLIANCE) ? RACEMASK_ALLIANCE : RACEMASK_HORDE;
1999 if (quest->GetAllowableRaces() && !(quest->GetAllowableRaces() & newRaceMask))
2000 {
2002 stmt->setUInt32(0, lowGuid);
2003 stmt->setUInt32(1, questId);
2004 trans->Append(stmt);
2005 }
2006 }
2007 }
2008
2009 // Spell conversion
2010 for (std::map<uint32, uint32>::const_iterator it = sObjectMgr->FactionChangeSpells.begin(); it != sObjectMgr->FactionChangeSpells.end(); ++it)
2011 {
2012 uint32 spell_alliance = it->first;
2013 uint32 spell_horde = it->second;
2014
2015 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_SPELL_BY_SPELL);
2016 stmt->setUInt32(0, (newTeam == ALLIANCE ? spell_alliance : spell_horde));
2017 stmt->setUInt32(1, lowGuid);
2018 trans->Append(stmt);
2019
2020 stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_SPELL_FACTION_CHANGE);
2021 stmt->setUInt32(0, (newTeam == ALLIANCE ? spell_alliance : spell_horde));
2022 stmt->setUInt32(1, (newTeam == ALLIANCE ? spell_horde : spell_alliance));
2023 stmt->setUInt32(2, lowGuid);
2024 trans->Append(stmt);
2025 }
2026
2027 // Reputation conversion
2028 for (std::map<uint32, uint32>::const_iterator it = sObjectMgr->FactionChangeReputation.begin(); it != sObjectMgr->FactionChangeReputation.end(); ++it)
2029 {
2030 uint32 reputation_alliance = it->first;
2031 uint32 reputation_horde = it->second;
2032 uint32 newReputation = (newTeam == ALLIANCE) ? reputation_alliance : reputation_horde;
2033 uint32 oldReputation = (newTeam == ALLIANCE) ? reputation_horde : reputation_alliance;
2034
2035 // select old standing set in db
2036 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_REP_BY_FACTION);
2037 stmt->setUInt32(0, oldReputation);
2038 stmt->setUInt32(1, lowGuid);
2039
2040 if (PreparedQueryResult reputationResult = CharacterDatabase.Query(stmt))
2041 {
2042 fields = reputationResult->Fetch();
2043 int32 oldDBRep = fields[0].GetInt32();
2044 FactionEntry const* factionEntry = sFactionStore.LookupEntry(oldReputation);
2045
2046 // old base reputation
2047 int32 oldBaseRep = sObjectMgr->GetBaseReputationOf(factionEntry, oldRace, playerClass);
2048
2049 // new base reputation
2050 int32 newBaseRep = sObjectMgr->GetBaseReputationOf(sFactionStore.LookupEntry(newReputation), factionChangeInfo->RaceID, playerClass);
2051
2052 // final reputation shouldnt change
2053 int32 FinalRep = oldDBRep + oldBaseRep;
2054 int32 newDBRep = FinalRep - newBaseRep;
2055
2056 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_REP_BY_FACTION);
2057 stmt->setUInt32(0, newReputation);
2058 stmt->setUInt32(1, lowGuid);
2059 trans->Append(stmt);
2060
2061 stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_REP_FACTION_CHANGE);
2062 stmt->setUInt16(0, uint16(newReputation));
2063 stmt->setInt32(1, newDBRep);
2064 stmt->setUInt16(2, uint16(oldReputation));
2065 stmt->setUInt32(3, lowGuid);
2066 trans->Append(stmt);
2067 }
2068 }
2069
2070 // Title conversion
2071 if (!knownTitlesStr.empty())
2072 {
2073 std::vector<std::string_view> tokens = Trinity::Tokenize(knownTitlesStr, ' ', false);
2074 std::array<uint32, KNOWN_TITLES_SIZE * 2> knownTitles;
2075
2076 for (uint32 index = 0; index < knownTitles.size(); ++index)
2077 {
2078 Optional<uint32> thisMask;
2079 if (index < tokens.size())
2080 thisMask = Trinity::StringTo<uint32>(tokens[index]);
2081
2082 if (thisMask)
2083 knownTitles[index] = *thisMask;
2084 else
2085 {
2086 TC_LOG_WARN("entities.player", "{} has invalid title data '{}' at index {} - skipped, this may result in titles being lost",
2087 GetPlayerInfo(), (index < tokens.size()) ? std::string(tokens[index]) : "<none>", index);
2088 knownTitles[index] = 0;
2089 }
2090 }
2091
2092 for (std::map<uint32, uint32>::const_iterator it = sObjectMgr->FactionChangeTitles.begin(); it != sObjectMgr->FactionChangeTitles.end(); ++it)
2093 {
2094 uint32 title_alliance = it->first;
2095 uint32 title_horde = it->second;
2096
2097 CharTitlesEntry const* atitleInfo = sCharTitlesStore.AssertEntry(title_alliance);
2098 CharTitlesEntry const* htitleInfo = sCharTitlesStore.AssertEntry(title_horde);
2099 // new team
2100 if (newTeam == ALLIANCE)
2101 {
2102 uint32 bitIndex = htitleInfo->MaskID;
2103 uint32 index = bitIndex / 32;
2104 uint32 old_flag = 1 << (bitIndex % 32);
2105 uint32 new_flag = 1 << (atitleInfo->MaskID % 32);
2106 if (knownTitles[index] & old_flag)
2107 {
2108 knownTitles[index] &= ~old_flag;
2109 // use index of the new title
2110 knownTitles[atitleInfo->MaskID / 32] |= new_flag;
2111 }
2112 }
2113 else
2114 {
2115 uint32 bitIndex = atitleInfo->MaskID;
2116 uint32 index = bitIndex / 32;
2117 uint32 old_flag = 1 << (bitIndex % 32);
2118 uint32 new_flag = 1 << (htitleInfo->MaskID % 32);
2119 if (knownTitles[index] & old_flag)
2120 {
2121 knownTitles[index] &= ~old_flag;
2122 // use index of the new title
2123 knownTitles[htitleInfo->MaskID / 32] |= new_flag;
2124 }
2125 }
2126
2127 std::ostringstream ss;
2128 for (uint32 mask : knownTitles)
2129 ss << mask << ' ';
2130
2131 stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_TITLES_FACTION_CHANGE);
2132 stmt->setString(0, ss.str());
2133 stmt->setUInt32(1, lowGuid);
2134 trans->Append(stmt);
2135
2136 // unset any currently chosen title
2137 stmt = CharacterDatabase.GetPreparedStatement(CHAR_RES_CHAR_TITLES_FACTION_CHANGE);
2138 stmt->setUInt32(0, lowGuid);
2139 trans->Append(stmt);
2140 }
2141 }
2142 }
2143 }
2144
2145 CharacterDatabase.CommitTransaction(trans);
2146
2147 TC_LOG_DEBUG("entities.player", "{} (IP: {}) changed race from {} to {}", GetPlayerInfo(), GetRemoteAddress(), oldRace, factionChangeInfo->RaceID);
2148
2149 SendCharFactionChange(RESPONSE_SUCCESS, factionChangeInfo.get());
2150}
2151
2153{
2155 response.Code = result;
2156
2157 SendPacket(response.Write());
2158}
2159
2161{
2163 response.Code = result;
2164
2165 SendPacket(response.Write());
2166}
2167
2169{
2171 packet.Result = result;
2172 packet.Name = renameInfo->NewName;
2173 packet.Guid = renameInfo->Guid;
2174
2175 SendPacket(packet.Write());
2176}
2177
2179{
2181 response.Code = result;
2182 response.CustomizeInfo = customizeInfo;
2183
2184 SendPacket(response.Write());
2185}
2186
2188{
2190 response.Result = result;
2191 response.RaceOrFactionChangeInfo = factionChangeInfo;
2192
2193 SendPacket(response.Write());
2194}
2195
2197{
2199 data << uint32(result);
2200 data << guid;
2201 SendPacket(&data);
2202}
2203
2205{
2207 data << uint32(result);
2208 SendPacket(&data);
2209}
2210
2212{
2213 // Only players that has not yet gained any experience can use this
2215 return;
2216
2217 if (ChrClassesEntry const* classEntry = sChrClassesStore.LookupEntry(_player->GetClass()))
2218 {
2219 if (classEntry->CinematicSequenceID)
2220 _player->SendCinematicStart(classEntry->CinematicSequenceID);
2221 else if (ChrRacesEntry const* raceEntry = sChrRacesStore.LookupEntry(_player->GetRace()))
2222 _player->SendCinematicStart(raceEntry->CinematicSequenceID);
2223 }
2224}
#define sArenaTeamMgr
#define sCalendarMgr
#define sCharacterCache
@ CHAR_SEL_CHARACTER_ACTIONS
@ CHAR_SEL_CHAR_CUSTOMIZE_INFO
@ CHAR_DEL_CHAR_SOCIAL_BY_FRIEND
@ CHAR_UPD_CHAR_INVENTORY_FACTION_CHANGE
@ CHAR_SEL_CHECK_NAME
@ CHAR_UPD_CHAR_ONLINE
@ CHAR_DEL_CHAR_QUESTSTATUS_REWARDED_BY_QUEST
@ CHAR_SEL_CHARACTER
@ CHAR_SEL_CHARACTER_QUESTSTATUSREW
@ CHAR_SEL_PLAYER_ACCOUNT_DATA
@ CHAR_UPD_CHAR_QUESTSTATUS_REWARDED_FACTION_CHANGE
@ CHAR_DEL_CHAR_SKILL_LANGUAGES
@ CHAR_SEL_CHARACTER_AURAS
@ CHAR_SEL_CHAR_PETS
@ CHAR_UPD_CHAR_ACHIEVEMENT
@ CHAR_DEL_CHAR_DECLINED_NAME
@ CHAR_SEL_CHAR_RACE_OR_FACTION_CHANGE_INFOS
@ CHAR_SEL_CHARACTER_QUESTSTATUS_MONTHLY
@ CHAR_SEL_MAILITEMS
@ CHAR_INS_PLAYER_HOMEBIND
@ CHAR_INS_CHAR_SKILL_LANGUAGE
@ CHAR_SEL_CHARACTER_BGDATA
@ CHAR_SEL_CHARACTER_SOCIALLIST
@ CHAR_UPD_CHAR_SPELL_FACTION_CHANGE
@ CHAR_UPD_CHAR_TAXI_PATH
@ CHAR_UPD_CHAR_TAXIMASK
@ CHAR_SEL_CHARACTER_QUESTSTATUS_WEEKLY
@ CHAR_DEL_PLAYER_HOMEBIND
@ CHAR_SEL_CHAR_REP_BY_FACTION
@ CHAR_SEL_CHARACTER_HOMEBIND
@ CHAR_SEL_FREE_NAME
@ CHAR_SEL_ENUM
@ CHAR_SEL_SUM_CHARS
@ CHAR_SEL_GROUP_MEMBER
@ CHAR_DEL_CHAR_SPELL_BY_SPELL
@ CHAR_SEL_CHAR_CREATE_INFO
@ CHAR_SEL_CHARACTER_INVENTORY
@ CHAR_UPD_CHAR_QUESTSTATUS_REWARDED_ACTIVE_BY_QUEST
@ CHAR_SEL_CHARACTER_INSTANCE
@ CHAR_SEL_CHARACTER_QUESTSTATUS
@ CHAR_DEL_CHAR_ACHIEVEMENT_BY_ACHIEVEMENT
@ CHAR_SEL_CHARACTER_TALENTS
@ CHAR_SEL_MAIL
@ CHAR_SEL_CORPSE_LOCATION
@ CHAR_SEL_CHARACTER_CRITERIAPROGRESS
@ CHAR_SEL_CHARACTER_GLYPHS
@ CHAR_SEL_CHARACTER_REPUTATION
@ CHAR_DEL_CHAR_QUESTSTATUS
@ CHAR_SEL_CHARACTER_SPELL
@ CHAR_UPD_GENDER_AND_APPEARANCE
@ CHAR_UPD_CHAR_REP_FACTION_CHANGE
@ CHAR_SEL_CHARACTER_QUESTSTATUS_SEASONAL
@ CHAR_UPD_CHAR_RACE
@ CHAR_SEL_CHARACTER_RANDOMBG
@ CHAR_SEL_CHARACTER_EQUIPMENTSETS
@ CHAR_SEL_CHARACTER_SKILLS
@ CHAR_SEL_CHARACTER_QUESTSTATUS_DAILY
@ CHAR_UPD_CHAR_TITLES_FACTION_CHANGE
@ CHAR_DEL_CHAR_REP_BY_FACTION
@ CHAR_SEL_ENUM_DECLINED_NAME
@ CHAR_SEL_CHARACTER_SPELLCOOLDOWNS
@ CHAR_RES_CHAR_TITLES_FACTION_CHANGE
@ CHAR_UPD_CHAR_QUESTSTATUS_REWARDED_ACTIVE
@ CHAR_DEL_CHAR_SOCIAL_BY_GUID
@ CHAR_SEL_CHARACTER_ACHIEVEMENTS
@ CHAR_DEL_EXPIRED_BANS
@ CHAR_SEL_GUILD_MEMBER
@ CHAR_SEL_CHARACTER_DECLINEDNAMES
@ CHAR_SEL_CHARACTER_ARENAINFO
@ CHAR_UPD_CHAR_NAME_AT_LOGIN
@ CHAR_INS_CHAR_DECLINED_NAME
@ CHAR_SEL_CHARACTER_BANNED
#define MAX_ACCOUNT_TUTORIAL_VALUES
Definition Common.h:65
@ ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP
Definition DBCEnums.h:174
@ ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_AT_BARBER
Definition DBCEnums.h:189
@ ACHIEVEMENT_CRITERIA_TYPE_ON_LOGIN
Definition DBCEnums.h:197
DBCStorage< CharTitlesEntry > sCharTitlesStore(CharTitlesEntryfmt)
DBCStorage< FactionEntry > sFactionStore(FactionEntryfmt)
TaxiMask sAllianceTaxiNodesMask
DBCStorage< BarberShopStyleEntry > sBarberShopStyleStore(BarberShopStyleEntryfmt)
DBCStorage< ChrRacesEntry > sChrRacesStore(ChrRacesEntryfmt)
TaxiMask sDeathKnightTaxiNodesMask
DBCStorage< GlyphPropertiesEntry > sGlyphPropertiesStore(GlyphPropertiesfmt)
DBCStorage< ChrClassesEntry > sChrClassesStore(ChrClassesEntryfmt)
TaxiMask sHordeTaxiNodesMask
@ CHRRACES_FLAGS_NOT_PLAYABLE
@ CHRRACES_ALLIANCE_TYPE_NOT_PLAYABLE
SQLTransaction< CharacterDatabaseConnection > CharacterDatabaseTransaction
SQLTransaction< LoginDatabaseConnection > LoginDatabaseTransaction
std::shared_ptr< PreparedResultSet > PreparedQueryResult
DatabaseWorkerPool< LoginDatabaseConnection > LoginDatabase
Accessor to the realm/login database.
DatabaseWorkerPool< CharacterDatabaseConnection > CharacterDatabase
Accessor to the character database.
uint8_t uint8
Definition Define.h:135
int32_t int32
Definition Define.h:129
uint64_t uint64
Definition Define.h:132
uint16_t uint16
Definition Define.h:134
uint32_t uint32
Definition Define.h:133
#define MAX_EQUIPMENT_SET_INDEX
#define sGroupMgr
Definition GroupMgr.h:58
#define sGuildMgr
Definition GuildMgr.h:59
InventoryResult
Definition ItemDefines.h:25
@ EQUIP_ERR_OK
Definition ItemDefines.h:26
@ LANG_RESET_SPELLS
Definition Language.h:260
@ LANG_GM_ON
Definition Language.h:387
@ LOG_LEVEL_INFO
Definition LogCommon.h:29
#define TC_LOG_WARN(filterType__,...)
Definition Log.h:162
#define TC_LOG_DEBUG(filterType__,...)
Definition Log.h:156
#define TC_LOG_ERROR(filterType__,...)
Definition Log.h:165
#define sLog
Definition Log.h:130
#define TC_LOG_INFO(filterType__,...)
Definition Log.h:159
@ LOGIN_REP_REALM_CHARACTERS
@ LOGIN_SEL_SUM_REALM_CHARACTERS
@ LOGIN_UPD_ACCOUNT_ONLINE
#define TC_METRIC_EVENT(category, title, description)
Definition Metric.h:195
bool normalizePlayerName(std::string &name)
#define sObjectMgr
Definition ObjectMgr.h:1721
std::optional< T > Optional
Optional helper class to wrap optional values within.
Definition Optional.h:25
@ PET_SAVE_AS_CURRENT
Definition PetDefines.h:42
@ EQUIPMENT_SLOT_MAINHAND
Definition Player.h:567
@ EQUIPMENT_SLOT_END
Definition Player.h:571
@ EQUIPMENT_SLOT_OFFHAND
Definition Player.h:568
@ EQUIPMENT_SLOT_RANGED
Definition Player.h:569
std::vector< ItemPosCount > ItemPosCountVec
Definition Player.h:624
@ PLAYER_EXTRA_HAS_RACE_CHANGED
Definition Player.h:464
@ PLAYER_FLAGS_HIDE_CLOAK
Definition Player.h:355
@ PLAYER_FLAGS_CONTESTED_PVP
Definition Player.h:352
@ PLAYER_FLAGS_RESTING
Definition Player.h:349
@ PLAYER_FLAGS_HIDE_HELM
Definition Player.h:354
@ AT_LOGIN_RESET_TALENTS
Definition Player.h:475
@ AT_LOGIN_RESET_SPELLS
Definition Player.h:474
@ AT_LOGIN_RESET_PET_TALENTS
Definition Player.h:477
@ AT_LOGIN_FIRST
Definition Player.h:478
@ AT_LOGIN_RESURRECT
Definition Player.h:481
@ AT_LOGIN_CUSTOMIZE
Definition Player.h:476
@ AT_LOGIN_RENAME
Definition Player.h:473
@ AT_LOGIN_CHANGE_RACE
Definition Player.h:480
@ AT_LOGIN_CHANGE_FACTION
Definition Player.h:479
#define INVENTORY_SLOT_BAG_0
Definition Player.h:547
#define PLAYER_EXPLORED_ZONES_SIZE
Definition Player.h:117
@ PLAYER_LOGIN_QUERY_LOAD_SPELL_COOLDOWNS
Definition Player.h:735
@ PLAYER_LOGIN_QUERY_LOAD_GLYPHS
Definition Player.h:743
@ PLAYER_LOGIN_QUERY_LOAD_DECLINED_NAMES
Definition Player.h:736
@ PLAYER_LOGIN_QUERY_LOAD_QUEST_STATUS_REW
Definition Player.h:750
@ MAX_PLAYER_LOGIN_QUERY
Definition Player.h:755
@ PLAYER_LOGIN_QUERY_LOAD_DAILY_QUEST_STATUS
Definition Player.h:727
@ PLAYER_LOGIN_QUERY_LOAD_SEASONAL_QUEST_STATUS
Definition Player.h:751
@ PLAYER_LOGIN_QUERY_LOAD_SOCIAL_LIST
Definition Player.h:733
@ PLAYER_LOGIN_QUERY_LOAD_ACTIONS
Definition Player.h:730
@ PLAYER_LOGIN_QUERY_LOAD_SKILLS
Definition Player.h:746
@ PLAYER_LOGIN_QUERY_LOAD_BG_DATA
Definition Player.h:742
@ PLAYER_LOGIN_QUERY_LOAD_ACCOUNT_DATA
Definition Player.h:745
@ PLAYER_LOGIN_QUERY_LOAD_MAIL_ITEMS
Definition Player.h:732
@ PLAYER_LOGIN_QUERY_LOAD_PET_SLOTS
Definition Player.h:754
@ PLAYER_LOGIN_QUERY_LOAD_INVENTORY
Definition Player.h:729
@ PLAYER_LOGIN_QUERY_LOAD_REPUTATION
Definition Player.h:728
@ PLAYER_LOGIN_QUERY_LOAD_FROM
Definition Player.h:721
@ PLAYER_LOGIN_QUERY_LOAD_QUEST_STATUS
Definition Player.h:726
@ PLAYER_LOGIN_QUERY_LOAD_WEEKLY_QUEST_STATUS
Definition Player.h:747
@ PLAYER_LOGIN_QUERY_LOAD_MONTHLY_QUEST_STATUS
Definition Player.h:752
@ PLAYER_LOGIN_QUERY_LOAD_GUILD
Definition Player.h:737
@ PLAYER_LOGIN_QUERY_LOAD_EQUIPMENT_SETS
Definition Player.h:741
@ PLAYER_LOGIN_QUERY_LOAD_MAILS
Definition Player.h:731
@ PLAYER_LOGIN_QUERY_LOAD_AURAS
Definition Player.h:724
@ PLAYER_LOGIN_QUERY_LOAD_TALENTS
Definition Player.h:744
@ PLAYER_LOGIN_QUERY_LOAD_BANNED
Definition Player.h:749
@ PLAYER_LOGIN_QUERY_LOAD_ARENA_INFO
Definition Player.h:738
@ PLAYER_LOGIN_QUERY_LOAD_GROUP
Definition Player.h:722
@ PLAYER_LOGIN_QUERY_LOAD_CRITERIA_PROGRESS
Definition Player.h:740
@ PLAYER_LOGIN_QUERY_LOAD_HOME_BIND
Definition Player.h:734
@ PLAYER_LOGIN_QUERY_LOAD_CORPSE_LOCATION
Definition Player.h:753
@ PLAYER_LOGIN_QUERY_LOAD_SPELLS
Definition Player.h:725
@ PLAYER_LOGIN_QUERY_LOAD_BOUND_INSTANCES
Definition Player.h:723
@ PLAYER_LOGIN_QUERY_LOAD_RANDOM_BG
Definition Player.h:748
@ PLAYER_LOGIN_QUERY_LOAD_ACHIEVEMENTS
Definition Player.h:739
Role Based Access Control related classes definition.
#define sScriptMgr
Definition ScriptMgr.h:1168
@ GAMEOBJECT_TYPE_BARBER_CHAIR
Gender
ResponseCodes
@ CHAR_DELETE_SUCCESS
@ CHAR_CREATE_EXPANSION
@ CHAR_CREATE_CHARACTER_ARENA_LEADER
@ CHAR_NAME_NO_NAME
@ CHAR_CREATE_RESTRICTED_RACECLASS
@ CHAR_CREATE_DISABLED
@ CHAR_NAME_FAILURE
@ RESPONSE_SUCCESS
@ CHAR_CREATE_LEVEL_REQUIREMENT
@ CHAR_CREATE_FAILED
@ CHAR_DELETE_FAILED_GUILD_LEADER
@ CHAR_NAME_RESERVED
@ CHAR_DELETE_FAILED_ARENA_CAPTAIN
@ CHAR_CREATE_ERROR
@ CHAR_CREATE_NAME_IN_USE
@ CHAR_CREATE_CHARACTER_SWAP_FACTION
@ CHAR_CREATE_SERVER_LIMIT
@ CHAR_CREATE_EXPANSION_CLASS
@ CHAR_CREATE_CHARACTER_RACE_ONLY
@ CHAR_CREATE_SUCCESS
@ CHAR_CREATE_PVP_TEAMS_VIOLATION
@ CHAR_CREATE_ACCOUNT_LIMIT
@ CHAR_CREATE_UNIQUE_CLASS_LIMIT
@ CHAR_NAME_SUCCESS
#define MAX_GLYPH_SLOT_INDEX
@ CLASS_DEATH_KNIGHT
@ ALLIANCE
@ HORDE
#define RACEMASK_HORDE
@ RACE_TROLL
@ RACE_UNDEAD_PLAYER
@ RACE_ORC
@ RACE_DRAENEI
@ RACE_NIGHTELF
@ RACE_BLOODELF
@ RACE_DWARF
@ RACE_GNOME
@ RACE_HUMAN
@ RACE_TAUREN
#define RACEMASK_ALLIANCE
@ COMPLAINT_ENABLED_WITH_AUTO_IGNORE
@ FRIEND_ONLINE
Definition SocialMgr.h:69
#define sSocialMgr
Definition SocialMgr.h:159
@ UNIT_STAND_STATE_SIT_LOW_CHAIR
Definition UnitDefines.h:38
@ UNIT_STAND_STATE_STAND
Definition UnitDefines.h:34
#define MAX_DECLINED_NAME_CASES
@ UNIT_BYTE2_FLAG_FFA_PVP
@ CORPSE
Definition Unit.h:213
@ DEAD
Definition Unit.h:214
@ UNIT_STATE_STUNNED
Definition Unit.h:223
@ NULL_BAG
Definition Unit.h:61
@ NULL_SLOT
Definition Unit.h:62
@ PLAYER_XP
@ PLAYER_EXPLORED_ZONES_1
@ PLAYER_FLAGS
@ PLAYER_FIELD_WATCHED_FACTION_INDEX
bool Utf8toWStr(char const *utf8str, size_t csize, wchar_t *wstr, size_t &wsize)
Definition Util.cpp:383
bool isCyrillicCharacter(wchar_t wchar)
Definition Util.h:146
void put(std::size_t pos, T value)
Definition ByteBuffer.h:137
void clear()
Definition ByteBuffer.h:123
void readPackGUID(uint64 &guid)
Definition ByteBuffer.h:369
void PSendSysMessage(char const *fmt, Args &&... args)
Definition Chat.h:69
Class used to access individual fields of database query result.
Definition Field.h:92
uint8 GetUInt8() const
Definition Field.cpp:29
std::string GetString() const
Definition Field.cpp:125
bool IsNull() const
Definition Field.h:128
uint16 GetUInt16() const
Definition Field.cpp:45
uint32 GetUInt32() const
Definition Field.cpp:61
int32 GetInt32() const
Definition Field.cpp:69
GameObjectTemplate const * GetGOInfo() const
Definition GameObject.h:102
Definition Group.h:165
Definition Guild.h:284
Definition Item.h:62
uint16 GetPos() const
Definition Item.h:130
LoginQueryHolder(uint32 accountId, ObjectGuid guid)
ObjectGuid GetGuid() const
uint32 GetAccountId() const
virtual bool AddPlayerToMap(Player *)
Definition Map.cpp:583
LowType GetCounter() const
Definition ObjectGuid.h:156
bool IsEmpty() const
Definition ObjectGuid.h:172
uint64 GetRawValue() const
Definition ObjectGuid.h:148
std::string ToString() const
uint32 LowType
Definition ObjectGuid.h:142
PackedGuidReader ReadAsPacked()
Definition ObjectGuid.h:146
static bool CheckDeclinedNames(const std::wstring &w_ownname, DeclinedName const &names)
static ResponseCodes CheckPlayerName(std::string_view name, LocaleConstant locale, bool create=false)
std::unordered_map< uint32, Trinity::unique_trackable_ptr< Quest > > QuestContainer
Definition ObjectMgr.h:947
uint32 GetUInt32Value(uint16 index) const
Definition Object.cpp:249
void SetFlag(uint16 index, uint32 newFlag)
Definition Object.cpp:760
void RemoveFlag(uint16 index, uint32 oldFlag)
Definition Object.cpp:775
bool HasFlag(uint16 index, uint32 flag) const
Definition Object.cpp:799
static ObjectGuid GetGUID(Object const *o)
Definition Object.h:78
void SetUInt32Value(uint16 index, uint32 value)
Definition Object.cpp:585
static void resetTalentsForAllPetsOf(Player *owner, Pet *online_pet=nullptr, bool involuntarily=false)
Definition Pet.cpp:1720
void ContinueTaxiFlight() const
Definition Player.cpp:21218
void SendInitialPacketsAfterAddToMap()
Definition Player.cpp:22472
uint32 GetXP() const
Definition Player.h:1018
uint32 GetTeam() const
Definition Player.h:1832
InventoryResult CanUnequipItem(uint16 src, bool swap) const
Definition Player.cpp:11139
void RemoveAtLoginFlag(AtLoginFlags flags, bool persist=false)
Definition Player.cpp:25536
uint8 GetSkinId() const
Definition Player.h:1041
void SetHairStyleId(uint8 hairStyle)
Definition Player.h:1046
void ResetSpells(bool myClassOnly=false)
Definition Player.cpp:22666
void SendTalentsInfoData(bool pet)
Definition Player.cpp:25366
void SetEquipmentSet(EquipmentSetInfo::EquipmentSetData const &eqset)
Definition Player.cpp:25417
InventoryResult CanEquipItem(uint8 slot, uint16 &dest, Item *pItem, bool swap, bool not_loading=true) const
Definition Player.cpp:10982
float m_homebindZ
Definition Player.h:2089
Gender GetNativeGender() const override
Definition Player.h:1039
uint32 m_homebindMapId
Definition Player.h:2085
InventoryResult CanStoreItem(uint8 bag, uint8 slot, ItemPosCountVec &dest, Item *pItem, bool swap=false) const
Definition Player.cpp:9994
void SetHairColorId(uint8 hairColor)
Definition Player.h:1048
void CleanupsBeforeDelete(bool finalCleanup=true) override
Definition Player.cpp:369
void UpdateAchievementCriteria(AchievementCriteriaTypes type, uint32 miscValue1=0, uint32 miscValue2=0, WorldObject *ref=nullptr)
Definition Player.cpp:24940
static void OfflineResurrect(ObjectGuid const &guid, CharacterDatabaseTransaction trans)
Definition Player.cpp:4465
bool ModifyMoney(int32 amount, bool sendError=true)
Definition Player.cpp:22339
void SendDungeonDifficulty(bool IsInGroup) const
Definition Player.cpp:20102
void SendInitialPacketsBeforeAddToMap()
Definition Player.cpp:22408
static void SavePositionInDB(WorldLocation const &loc, uint16 zoneId, ObjectGuid guid, CharacterDatabaseTransaction trans)
Definition Player.cpp:20047
void SetFacialStyle(uint8 facialStyle)
Definition Player.h:1050
void SwapItem(uint16 src, uint16 dst)
Definition Player.cpp:12630
Item * StoreItem(ItemPosCountVec const &pos, Item *pItem, bool update)
Definition Player.cpp:11661
WorldSession * GetSession() const
Definition Player.h:1719
void DeleteEquipmentSet(uint64 setGuid)
Definition Player.cpp:25520
Item * GetItemByPos(uint16 pos) const
Definition Player.cpp:9552
void RepopAtGraveyard()
Definition Player.cpp:4773
static uint32 TeamForRace(uint8 race)
Definition Player.cpp:6269
bool HasEnoughMoney(uint32 amount) const
Definition Player.h:1410
uint8 GetFaceId() const
Definition Player.h:1043
void SetInGuild(ObjectGuid::LowType guildId)
Definition Player.cpp:26257
float m_homebindY
Definition Player.h:2088
ObjectGuid::LowType GetGuildId() const
Definition Player.h:1620
Group * GetGroup()
Definition Player.h:2171
bool IsGameMaster() const
Definition Player.h:998
void SetGuildRank(uint8 rankId)
Definition Player.h:1617
void LoadCorpse(PreparedQueryResult result)
Definition Player.cpp:17803
static void DeleteFromDB(ObjectGuid playerguid, uint32 accountId, bool updateRealmChars=true, bool deleteFinally=false)
Definition Player.cpp:3885
void SendCinematicStart(uint32 CinematicSequenceId) const
Definition Player.cpp:6166
void LoadPet()
Definition Player.cpp:18189
void SetGlyph(uint8 slot, uint32 glyph)
Definition Player.cpp:24281
uint8 getCinematic() const
Definition Player.h:1569
bool TeleportTo(uint32 mapid, float x, float y, float z, float orientation, uint32 options=0)
Definition Player.cpp:1524
uint32 GetXPForNextLevel() const
Definition Player.h:1019
bool ResetTalents(bool involuntarily=false)
Definition Player.cpp:3707
uint8 GetActiveTalentGroup() const
Definition Player.h:1496
bool LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder const &holder)
Definition Player.cpp:16875
void SendEquipError(InventoryResult msg, Item *pItem, Item *pItem2=nullptr, uint32 itemid=0) const
Definition Player.cpp:13075
void SetSkinId(uint8 skin)
Definition Player.h:1042
static bool BuildEnumData(PreparedQueryResult result, WorldPacket *data)
Definition Player.cpp:1300
uint32 GetGlyph(uint8 group, uint8 slot) const
Definition Player.h:1524
bool HasAtLoginFlag(AtLoginFlags f) const
Definition Player.h:2113
static void LeaveAllArenaTeams(ObjectGuid guid)
Definition Player.cpp:20959
void RemoveItem(uint8 bag, uint8 slot, bool update)
Definition Player.cpp:11983
void BuildPlayerRepop()
Definition Player.cpp:4292
void SetTaxiCheater(bool on)
Definition Player.h:1005
void SetContestedPvP(Player *attackedPlayer=nullptr)
Definition Player.cpp:20212
Item * GetItemByGuid(ObjectGuid guid) const
Definition Player.cpp:9518
static bool ValidateAppearance(uint8 race, uint8 class_, uint8 gender, uint8 hairID, uint8 hairColor, uint8 faceID, uint8 facialHair, uint8 skinColor, bool create=false)
Definition Player.cpp:26403
void SetInGameTime(uint32 time)
Definition Player.h:1362
void setCinematic(uint8 cine)
Definition Player.h:1570
ReputationMgr & GetReputationMgr()
Definition Player.h:1848
float m_homebindX
Definition Player.h:2087
uint32 GetBarberShopCost(uint8 newhairstyle, uint8 newhaircolor, uint8 newfacialhair, BarberShopStyleEntry const *newSkin=nullptr) const
Definition Player.cpp:24219
void setUInt16(uint8 index, uint16 value)
void setUInt32(uint8 index, uint32 value)
void setFloat(uint8 index, float value)
void setInt32(uint8 index, int32 value)
void setUInt8(uint8 index, uint8 value)
void setString(uint8 index, std::string const &value)
void SetNextQuery(QueryCallback &&next)
QueryCallback && WithPreparedCallback(std::function< void(PreparedQueryResult)> &&callback)
void SetAtWar(RepListID repListID, bool on)
void SendState(FactionState const *faction)
bool SetOneFactionReputation(FactionEntry const *factionEntry, int32 standing, bool incremental)
Public for chat command needs.
void SetInactive(RepListID repListID, bool on)
void SetSize(size_t size)
PreparedQueryResult GetPreparedResult(size_t index) const
void AfterComplete(std::function< void(SQLQueryHolderBase const &)> callback) &
Definition QueryHolder.h:76
bool SetPreparedQuery(size_t index, PreparedStatement< T > *stmt)
Definition QueryHolder.h:44
uint8 GetClass() const
Definition Unit.h:895
MotionMaster * GetMotionMaster()
Definition Unit.h:1667
DeathState m_deathState
Definition Unit.h:1852
bool IsStandState() const
Definition Unit.cpp:10357
void SetPvpFlag(UnitPVPStateFlags flags)
Definition Unit.h:983
void RemoveAurasDueToSpell(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, uint8 reqEffMask=0, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition Unit.cpp:3784
DeathState getDeathState() const
Definition Unit.h:1238
bool HasUnitState(const uint32 f) const
Definition Unit.h:876
void SetStandState(UnitStandStateType state)
Definition Unit.cpp:10363
UnitStandStateType GetStandState() const
Definition Unit.h:1001
bool SetWaterWalking(bool enable)
Definition Unit.cpp:13423
uint8 GetLevel() const
Definition Unit.h:889
uint8 GetRace() const
Definition Unit.h:892
bool IsInCombat() const
Definition Unit.h:1144
void WorldRelocate(WorldLocation const &loc)
Definition Position.h:179
uint32 GetMapId() const
Definition Position.h:193
Map * GetMap() const
Definition Object.h:449
GameObject * FindNearestGameObjectOfType(GameobjectTypes type, float range) const
Definition Object.cpp:2152
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition Object.cpp:2832
std::string const & GetName() const
Definition Object.h:382
std::shared_ptr< CharCustomizeInfo > CustomizeInfo
ObjectGuid Guid
Guid of the character to delete.
CharRaceOrFactionChangeInfo const * RaceOrFactionChangeInfo
std::shared_ptr< CharRaceOrFactionChangeInfo > RaceOrFactionChangeInfo
std::shared_ptr< CharacterRenameInfo > RenameInfo
WorldPacket const * Write() override
std::shared_ptr< CharacterCreateInfo > CreateInfo
WorldPacket const * Write() override
TaggedPosition< Position::XYZO > Pos
WorldPacket const * Write() override
WorldPacket const * Write() override
std::vector< std::string > const * Text
GuidSet _legitCharacters
void SetPlayer(Player *player)
void HandleOpeningCinematic(WorldPackets::Misc::OpeningCinematic &packet)
void HandleEquipmentSetUse(WorldPacket &recvData)
void HandlePlayerLoginOpcode(WorldPacket &recvPacket)
uint8 Expansion() const
void HandleAlterAppearance(WorldPacket &recvData)
void HandleCharRaceOrFactionChangeCallback(std::shared_ptr< WorldPackets::Character::CharRaceOrFactionChangeInfo > factionChangeInfo, PreparedQueryResult result)
void HandleSetFactionAtWar(WorldPacket &recvData)
void HandleCharEnumOpcode(WorldPacket &recvPacket)
void SendPacket(WorldPacket const *packet)
Send a packet to the client.
void SendNotification(const char *format,...) ATTR_PRINTF(2
QueryCallbackProcessor _queryProcessor
void HandleSetWatchedFactionOpcode(WorldPacket &recvData)
void HandleSetFactionInactiveOpcode(WorldPacket &recvData)
void LoadAccountData(PreparedQueryResult result, uint32 mask)
void SendCharDelete(ResponseCodes result)
void HandleShowingCloakOpcode(WorldPackets::Character::ShowingCloak &packet)
LocaleConstant GetSessionDbcLocale() const
void HandleTutorialFlag(WorldPacket &recvData)
std::string GetPlayerInfo() const
void KickPlayer(std::string const &reason)
Kick a player out of the World.
void HandleSetFactionCheat(WorldPacket &recvData)
Player * GetPlayer() const
bool PlayerLoading() const
void HandleCharRenameOpcode(WorldPackets::Character::CharacterRenameRequest &request)
void HandleEquipmentSetDelete(WorldPacket &recvData)
void HandleCharDeleteOpcode(WorldPackets::Character::CharDelete &charDelete)
void HandleCharCreateOpcode(WorldPackets::Character::CreateCharacter &charCreate)
void SendSetPlayerDeclinedNamesResult(DeclinedNameResult result, ObjectGuid guid)
void SendBarberShopResult(BarberShopResult result)
void HandleCharRenameCallBack(std::shared_ptr< WorldPackets::Character::CharacterRenameInfo > renameInfo, PreparedQueryResult result)
SQLQueryHolderCallback & AddQueryHolderCallback(SQLQueryHolderCallback &&callback)
bool IsLegitCharacterForAccount(ObjectGuid lowGUID)
std::string const & GetRemoteAddress() const
void HandlePlayerLogin(LoginQueryHolder const &holder)
void HandleCharEnum(PreparedQueryResult result)
bool HasPermission(uint32 permissionId)
void HandleCharCustomize(WorldPackets::Character::CharCustomize &packet)
uint32 GetAccountId() const
void SendCharCustomize(ResponseCodes result, WorldPackets::Character::CharCustomizeInfo const *customizeInfo)
Player * _player
uint32 GetTutorialInt(uint8 index) const
void SendCharRename(ResponseCodes result, WorldPackets::Character::CharacterRenameInfo const *renameInfo)
void SendFeatureSystemStatus()
void HandleEquipmentSetSave(WorldPacket &recvData)
void HandleRemoveGlyph(WorldPacket &recvData)
void HandleSetPlayerDeclinedNames(WorldPacket &recvData)
void SendAccountDataTimes(uint32 mask)
void HandleTutorialReset(WorldPacket &recvData)
void SendCharFactionChange(ResponseCodes result, WorldPackets::Character::CharRaceOrFactionChangeInfo const *factionChangeInfo)
void SendCharCreate(ResponseCodes result)
void HandleCharCustomizeCallback(std::shared_ptr< WorldPackets::Character::CharCustomizeInfo > customizeInfo, PreparedQueryResult result)
void SetTutorialInt(uint8 index, uint32 value)
void HandleShowingHelmOpcode(WorldPackets::Character::ShowingHelm &packet)
void HandleCharRaceOrFactionChange(WorldPackets::Character::CharRaceOrFactionChange &packet)
void HandleTutorialClear(WorldPacket &recvData)
uint32 constexpr MAX_CHARACTERS_PER_REALM
#define PER_CHARACTER_CACHE_MASK
BarberShopResult
DeclinedNameResult
@ SMSG_SET_PLAYER_DECLINED_NAMES_RESULT
Definition Opcodes.h:1079
@ SMSG_LEARNED_DANCE_MOVES
Definition Opcodes.h:1138
@ SMSG_BARBER_SHOP_RESULT
Definition Opcodes.h:1093
@ SMSG_EQUIPMENT_SET_USE_RESULT
Definition Opcodes.h:1267
@ SMSG_CHAR_ENUM
Definition Opcodes.h:88
@ BARBER_SHOP_RESULT_SUCCESS
@ BARBER_SHOP_RESULT_NO_MONEY
@ BARBER_SHOP_RESULT_NOT_ON_CHAIR
@ DECLINED_NAMES_RESULT_SUCCESS
@ DECLINED_NAMES_RESULT_ERROR
#define sWorld
Definition World.h:900
Realm realm
Definition World.cpp:3605
@ CONFIG_CHARACTER_CREATING_DISABLED_CLASSMASK
Definition World.h:230
@ CONFIG_CHARACTER_CREATING_DISABLED
Definition World.h:228
@ CONFIG_CHARACTER_CREATING_DISABLED_RACEMASK
Definition World.h:229
@ CONFIG_DEATH_KNIGHTS_PER_REALM
Definition World.h:233
@ CONFIG_ENABLE_SINFO_LOGIN
Definition World.h:332
@ CONFIG_MAX_PLAYER_LEVEL
Definition World.h:236
@ CONFIG_CHARACTERS_PER_ACCOUNT
Definition World.h:231
@ CONFIG_CHARACTER_CREATING_MIN_LEVEL_FOR_DEATH_KNIGHT
Definition World.h:234
@ CONFIG_SKIP_CINEMATICS
Definition World.h:235
@ CONFIG_CHARACTERS_PER_REALM
Definition World.h:232
@ CONFIG_ALL_TAXI_PATHS
Definition World.h:102
@ CONFIG_DECLINED_NAMES_USED
Definition World.h:123
@ CONFIG_START_ALL_REP
Definition World.h:138
@ CONFIG_PREVENT_RENAME_CUSTOMIZATION
Definition World.h:175
@ CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP
Definition World.h:98
@ CONFIG_START_ALL_EXPLORED
Definition World.h:137
@ CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD
Definition World.h:99
uint32 GetGameTimeMS()
Definition GameTime.cpp:47
TC_COMMON_API char const * GetFullVersion()
void AddObject(T *object)
TC_GAME_API Player * FindPlayer(ObjectGuid const &)
TC_COMMON_API std::vector< std::string_view > Tokenize(std::string_view str, char sep, bool keepEmpty)
Definition Util.cpp:56
@ RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_TEAMMASK
Definition RBAC.h:67
@ RBAC_PERM_TWO_SIDE_CHARACTER_CREATION
Definition RBAC.h:77
@ RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_RESERVEDNAME
Definition RBAC.h:70
@ RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_RACEMASK
Definition RBAC.h:69
@ RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_DEATH_KNIGHT
Definition RBAC.h:71
@ RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_CLASSMASK
Definition RBAC.h:68
@ RBAC_PERM_TWO_SIDE_ADD_FRIEND
Definition RBAC.h:82
ObjectGuid::LowType GuildId
uint32 RequiredExpansion
bool HasFlag(ChrRacesFlags flag) const
uint32 RequiredExpansion
std::string name[MAX_DECLINED_NAME_CASES]
Data sent in EquipmentSet related packets.
std::array< ObjectGuid, EQUIPMENT_SET_SLOTS > Pieces
uint32 IgnoreMask
Mask of EquipmentSlot.
struct GameObjectTemplate::@191::@219 barberChair
PlayerCreateInfoSpells castSpells
Definition ObjectMgr.h:694
float GetPositionZ() const
Definition Position.h:81
float GetOrientation() const
Definition Position.h:82
float GetPositionX() const
Definition Position.h:79
void GetPosition(float &x, float &y) const
Definition Position.h:84
float GetPositionY() const
Definition Position.h:80
uint32 Realm
Definition Realm.h:44
RealmHandle Id
Definition Realm.h:67