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 "EquipmentSetPackets.h"
27#include "GameObject.h"
28#include "GameTime.h"
29#include "GitRevision.h"
30#include "Group.h"
31#include "GroupMgr.h"
32#include "Guild.h"
33#include "GuildMgr.h"
34#include "InstanceSaveMgr.h"
35#include "Item.h"
36#include "Language.h"
37#include "Log.h"
38#include "Map.h"
39#include "Metric.h"
40#include "MiscPackets.h"
41#include "MotionMaster.h"
42#include "ObjectAccessor.h"
43#include "ObjectMgr.h"
44#include "Opcodes.h"
45#include "Pet.h"
46#include "Player.h"
47#include "PlayerDump.h"
48#include "RBAC.h"
49#include "Realm.h"
50#include "ReputationMgr.h"
51#include "ScriptMgr.h"
52#include "SocialMgr.h"
53#include "StringConvert.h"
54#include "SystemPackets.h"
55#include "QueryHolder.h"
56#include "World.h"
57
59{
60 private:
63 public:
65 : m_accountId(accountId), m_guid(guid) { }
66 ObjectGuid GetGuid() const { return m_guid; }
67 uint32 GetAccountId() const { return m_accountId; }
68 bool Initialize();
69};
70
72{
74
75 bool res = true;
77
79 stmt->setUInt32(0, lowGuid);
81
82 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GROUP_MEMBER);
83 stmt->setUInt32(0, lowGuid);
85
86 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_INSTANCE);
87 stmt->setUInt32(0, lowGuid);
89
90 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_AURAS);
91 stmt->setUInt32(0, lowGuid);
93
94 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_SPELL);
95 stmt->setUInt32(0, lowGuid);
97
98 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_QUESTSTATUS);
99 stmt->setUInt32(0, lowGuid);
101
102 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_QUESTSTATUS_DAILY);
103 stmt->setUInt32(0, lowGuid);
105
106 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_QUESTSTATUS_WEEKLY);
107 stmt->setUInt32(0, lowGuid);
109
111 stmt->setUInt32(0, lowGuid);
113
115 stmt->setUInt32(0, lowGuid);
117
118 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_REPUTATION);
119 stmt->setUInt32(0, lowGuid);
121
122 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_INVENTORY);
123 stmt->setUInt32(0, lowGuid);
125
126 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_ACTIONS);
127 stmt->setUInt32(0, lowGuid);
129
130 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_MAIL);
131 stmt->setUInt32(0, lowGuid);
133
134 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_MAILITEMS);
135 stmt->setUInt32(0, lowGuid);
137
138 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_SOCIALLIST);
139 stmt->setUInt32(0, lowGuid);
141
142 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_HOMEBIND);
143 stmt->setUInt32(0, lowGuid);
145
146 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_SPELLCOOLDOWNS);
147 stmt->setUInt32(0, lowGuid);
149
150 if (sWorld->getBoolConfig(CONFIG_DECLINED_NAMES_USED))
151 {
152 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_DECLINEDNAMES);
153 stmt->setUInt32(0, lowGuid);
155 }
156
157 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GUILD_MEMBER);
158 stmt->setUInt32(0, lowGuid);
160
161 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_ARENAINFO);
162 stmt->setUInt32(0, lowGuid);
164
165 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_ACHIEVEMENTS);
166 stmt->setUInt32(0, lowGuid);
168
169 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_CRITERIAPROGRESS);
170 stmt->setUInt32(0, lowGuid);
172
173 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_EQUIPMENTSETS);
174 stmt->setUInt32(0, lowGuid);
176
177 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_BGDATA);
178 stmt->setUInt32(0, lowGuid);
180
181 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_GLYPHS);
182 stmt->setUInt32(0, lowGuid);
184
185 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_TALENTS);
186 stmt->setUInt32(0, lowGuid);
188
189 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PLAYER_ACCOUNT_DATA);
190 stmt->setUInt32(0, lowGuid);
192
193 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_SKILLS);
194 stmt->setUInt32(0, lowGuid);
196
197 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_RANDOMBG);
198 stmt->setUInt32(0, lowGuid);
200
201 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_BANNED);
202 stmt->setUInt32(0, lowGuid);
204
205 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_QUESTSTATUSREW);
206 stmt->setUInt32(0, lowGuid);
208
209 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CORPSE_LOCATION);
210 stmt->setUInt32(0, lowGuid);
212
213 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_PETS);
214 stmt->setUInt32(0, lowGuid);
216
217 return res;
218}
219
221{
222 WorldPacket data(SMSG_CHAR_ENUM, 100); // we guess size
223
224 uint8 num = 0;
225
226 data << num;
227
229 if (result)
230 {
231 do
232 {
233 ObjectGuid guid = ObjectGuid::Create<HighGuid::Player>((*result)[0].GetUInt32());
234 TC_LOG_INFO("network", "Loading {} from account {}.", guid.ToString(), GetAccountId());
235 if (Player::BuildEnumData(result, &data))
236 {
237 // Do not allow banned characters to log in
238 if (!(*result)[23].GetUInt32())
239 _legitCharacters.insert(guid);
240
241 if (!sCharacterCache->HasCharacterCacheEntry(guid)) // This can happen if characters are inserted into the database manually. Core hasn't loaded name data yet.
242 sCharacterCache->AddCharacterCacheEntry(guid, GetAccountId(), (*result)[1].GetString(), (*result)[4].GetUInt8(), (*result)[2].GetUInt8(), (*result)[3].GetUInt8(), (*result)[10].GetUInt8());
243 ++num;
244 }
245 }
246 while (result->NextRow() && num < MAX_CHARACTERS_PER_REALM); // client shows an error if more than 10 characters are listed
247 }
248
249 data.put<uint8>(0, num);
250
251 SendPacket(&data);
252}
253
255{
256 // remove expired bans
258 CharacterDatabase.Execute(stmt);
259
261
262 if (sWorld->getBoolConfig(CONFIG_DECLINED_NAMES_USED))
263 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_ENUM_DECLINED_NAME);
264 else
265 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_ENUM);
266
268 stmt->setUInt32(1, GetAccountId());
269
270 _queryProcessor.AddCallback(CharacterDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&WorldSession::HandleCharEnum, this, std::placeholders::_1)));
271}
272
274{
276 {
277 if (uint32 mask = sWorld->getIntConfig(CONFIG_CHARACTER_CREATING_DISABLED))
278 {
279 bool disabled = false;
280
281 switch (Player::TeamForRace(charCreate.CreateInfo->Race))
282 {
283 case ALLIANCE:
284 disabled = (mask & (1 << 0)) != 0;
285 break;
286 case HORDE:
287 disabled = (mask & (1 << 1)) != 0;
288 break;
289 }
290
291 if (disabled)
292 {
294 return;
295 }
296 }
297 }
298
299 ChrClassesEntry const* classEntry = sChrClassesStore.LookupEntry(charCreate.CreateInfo->Class);
300 if (!classEntry)
301 {
302 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());
304 return;
305 }
306
307 ChrRacesEntry const* raceEntry = sChrRacesStore.LookupEntry(charCreate.CreateInfo->Race);
308 if (!raceEntry)
309 {
310 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());
312 return;
313 }
314
315 // prevent character creating Expansion race without Expansion account
316 if (raceEntry->RequiredExpansion > GetExpansion())
317 {
318 TC_LOG_ERROR("entities.player.cheat", "Expansion {} account:[{}] tried to Create character with expansion {} race ({})", GetExpansion(), GetAccountId(), raceEntry->RequiredExpansion, charCreate.CreateInfo->Race);
320 return;
321 }
322
323 // prevent character creating Expansion class without Expansion account
324 if (classEntry->RequiredExpansion > GetExpansion())
325 {
326 TC_LOG_ERROR("entities.player.cheat", "Expansion {} account:[{}] tried to Create character with expansion {} class ({})", GetExpansion(), GetAccountId(), classEntry->RequiredExpansion, charCreate.CreateInfo->Class);
328 return;
329 }
330
332 {
334 {
335 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());
337 return;
338 }
339
340 uint32 raceMaskDisabled = sWorld->getIntConfig(CONFIG_CHARACTER_CREATING_DISABLED_RACEMASK);
341 if ((1 << (charCreate.CreateInfo->Race - 1)) & raceMaskDisabled)
342 {
344 return;
345 }
346 }
347
349 {
350 uint32 classMaskDisabled = sWorld->getIntConfig(CONFIG_CHARACTER_CREATING_DISABLED_CLASSMASK);
351 if ((1 << (charCreate.CreateInfo->Class - 1)) & classMaskDisabled)
352 {
354 return;
355 }
356 }
357
358 // prevent character creating with invalid name
359 if (!normalizePlayerName(charCreate.CreateInfo->Name))
360 {
361 TC_LOG_ERROR("entities.player.cheat", "Account:[{}] but tried to Create character with empty [name] ", GetAccountId());
363 return;
364 }
365
366 // check name limitations
368 if (res != CHAR_NAME_SUCCESS)
369 {
370 SendCharCreate(res);
371 return;
372 }
373
375 {
377 return;
378 }
379
381 {
382 // speedup check for death knight class disabled case
383 if (sWorld->getIntConfig(CONFIG_DEATH_KNIGHTS_PER_REALM) == 0)
384 {
386 return;
387 }
388
389 // speedup check for death knight class disabled case
391 {
393 return;
394 }
395 }
396
397 std::shared_ptr<WorldPackets::Character::CharacterCreateInfo> createInfo = charCreate.CreateInfo;
399 stmt->setString(0, charCreate.CreateInfo->Name);
400
402 .WithChainingPreparedCallback([this](QueryCallback& queryCallback, PreparedQueryResult result)
403 {
404 if (result)
405 {
406 SendCharCreate(CHAR_CREATE_NAME_IN_USE);
407 return;
408 }
409
411 stmt->setUInt32(0, GetAccountId());
412 queryCallback.SetNextQuery(LoginDatabase.AsyncQuery(stmt));
413 })
414 .WithChainingPreparedCallback([this](QueryCallback& queryCallback, PreparedQueryResult result)
415 {
416 uint64 acctCharCount = 0;
417 if (result)
418 {
419 Field* fields = result->Fetch();
420 acctCharCount = uint64(fields[0].GetDouble());
421 }
422
423 if (acctCharCount >= sWorld->getIntConfig(CONFIG_CHARACTERS_PER_ACCOUNT))
424 {
425 SendCharCreate(CHAR_CREATE_ACCOUNT_LIMIT);
426 return;
427 }
428
430 stmt->setUInt32(0, GetAccountId());
431 queryCallback.SetNextQuery(CharacterDatabase.AsyncQuery(stmt));
432 })
433 .WithChainingPreparedCallback([this, createInfo](QueryCallback& queryCallback, PreparedQueryResult result)
434 {
435 if (result)
436 {
437 Field* fields = result->Fetch();
438 createInfo->CharCount = uint8(fields[0].GetUInt64()); // SQL's COUNT() returns uint64 but it will always be less than uint8.Max
439
440 if (createInfo->CharCount >= sWorld->getIntConfig(CONFIG_CHARACTERS_PER_REALM))
441 {
442 SendCharCreate(CHAR_CREATE_SERVER_LIMIT);
443 return;
444 }
445 }
446
447 bool allowTwoSideAccounts = !sWorld->IsPvPRealm() || HasPermission(rbac::RBAC_PERM_TWO_SIDE_CHARACTER_CREATION);
448 uint32 skipCinematics = sWorld->getIntConfig(CONFIG_SKIP_CINEMATICS);
449
450 std::function<void(PreparedQueryResult)> finalizeCharacterCreation = [this, createInfo](PreparedQueryResult result)
451 {
452 bool haveSameRace = false;
453 uint32 deathKnightReqLevel = sWorld->getIntConfig(CONFIG_CHARACTER_CREATING_MIN_LEVEL_FOR_DEATH_KNIGHT);
454 bool hasDeathKnightReqLevel = (deathKnightReqLevel == 0);
455 bool allowTwoSideAccounts = !sWorld->IsPvPRealm() || HasPermission(rbac::RBAC_PERM_TWO_SIDE_CHARACTER_CREATION);
456 uint32 skipCinematics = sWorld->getIntConfig(CONFIG_SKIP_CINEMATICS);
457 bool checkDeathKnightReqs = createInfo->Class == CLASS_DEATH_KNIGHT && !HasPermission(rbac::RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_DEATH_KNIGHT);
458
459 if (result)
460 {
461 uint32 team = Player::TeamForRace(createInfo->Race);
462 uint32 freeDeathKnightSlots = sWorld->getIntConfig(CONFIG_DEATH_KNIGHTS_PER_REALM);
463
464 Field* field = result->Fetch();
465 uint8 accRace = field[1].GetUInt8();
466
467 if (checkDeathKnightReqs)
468 {
469 uint8 accClass = field[2].GetUInt8();
470 if (accClass == CLASS_DEATH_KNIGHT)
471 {
472 if (freeDeathKnightSlots > 0)
473 --freeDeathKnightSlots;
474
475 if (freeDeathKnightSlots == 0)
476 {
477 SendCharCreate(CHAR_CREATE_UNIQUE_CLASS_LIMIT);
478 return;
479 }
480 }
481
482 if (!hasDeathKnightReqLevel)
483 {
484 uint8 accLevel = field[0].GetUInt8();
485 if (accLevel >= deathKnightReqLevel)
486 hasDeathKnightReqLevel = true;
487 }
488 }
489
490 // need to check team only for first character
492 if (!allowTwoSideAccounts)
493 {
494 uint32 accTeam = 0;
495 if (accRace > 0)
496 accTeam = Player::TeamForRace(accRace);
497
498 if (accTeam != team)
499 {
500 SendCharCreate(CHAR_CREATE_PVP_TEAMS_VIOLATION);
501 return;
502 }
503 }
504
505 // search same race for cinematic or same class if need
507 while ((skipCinematics == 1 && !haveSameRace) || createInfo->Class == CLASS_DEATH_KNIGHT)
508 {
509 if (!result->NextRow())
510 break;
511
512 field = result->Fetch();
513 accRace = field[1].GetUInt8();
514
515 if (!haveSameRace)
516 haveSameRace = createInfo->Race == accRace;
517
518 if (checkDeathKnightReqs)
519 {
520 uint8 acc_class = field[2].GetUInt8();
521 if (acc_class == CLASS_DEATH_KNIGHT)
522 {
523 if (freeDeathKnightSlots > 0)
524 --freeDeathKnightSlots;
525
526 if (freeDeathKnightSlots == 0)
527 {
528 SendCharCreate(CHAR_CREATE_UNIQUE_CLASS_LIMIT);
529 return;
530 }
531 }
532
533 if (!hasDeathKnightReqLevel)
534 {
535 uint8 acc_level = field[0].GetUInt8();
536 if (acc_level >= deathKnightReqLevel)
537 hasDeathKnightReqLevel = true;
538 }
539 }
540 }
541 }
542
543 if (checkDeathKnightReqs && !hasDeathKnightReqLevel)
544 {
545 SendCharCreate(CHAR_CREATE_LEVEL_REQUIREMENT);
546 return;
547 }
548
549 // Check name uniqueness in the same step as saving to database
550 if (sCharacterCache->GetCharacterCacheByName(createInfo->Name))
551 {
552 SendCharCreate(CHAR_CREATE_NAME_IN_USE);
553 return;
554 }
555
556 std::shared_ptr<Player> newChar(new Player(this), [](Player* ptr)
557 {
559 delete ptr;
560 });
561 newChar->GetMotionMaster()->Initialize();
562 if (!newChar->Create(sObjectMgr->GetGenerator<HighGuid::Player>().Generate(), createInfo.get()))
563 {
564 // Player not create (race/class/etc problem?)
565 SendCharCreate(CHAR_CREATE_ERROR);
566 return;
567 }
568
569 if ((haveSameRace && skipCinematics == 1) || skipCinematics == 2)
570 newChar->setCinematic(1); // not show intro
571
572 newChar->SetAtLoginFlag(AT_LOGIN_FIRST); // First login
573
574 CharacterDatabaseTransaction characterTransaction = CharacterDatabase.BeginTransaction();
575 LoginDatabaseTransaction trans = LoginDatabase.BeginTransaction();
576
577 // Player created, save it now
578 newChar->SaveToDB(characterTransaction, true);
579 createInfo->CharCount += 1;
580
582 stmt->setUInt32(0, createInfo->CharCount);
583 stmt->setUInt32(1, GetAccountId());
584 stmt->setUInt32(2, realm.Id.Realm);
585 trans->Append(stmt);
586
587 AddTransactionCallback(CharacterDatabase.AsyncCommitTransaction(characterTransaction)).AfterComplete([this, newChar = std::move(newChar), trans](bool success)
588 {
589 if (success)
590 {
591 LoginDatabase.CommitTransaction(trans);
592
593 TC_LOG_INFO("entities.player.character", "Account: {} (IP: {}) Create Character: {} {}", GetAccountId(), GetRemoteAddress(), newChar->GetName(), newChar->GetGUID().ToString());
594 sScriptMgr->OnPlayerCreate(newChar.get());
595 sCharacterCache->AddCharacterCacheEntry(newChar->GetGUID(), GetAccountId(), newChar->GetName(), newChar->GetNativeGender(), newChar->GetRace(), newChar->GetClass(), newChar->GetLevel());
596
597 SendCharCreate(CHAR_CREATE_SUCCESS);
598 }
599 else
600 SendCharCreate(CHAR_CREATE_ERROR);
601 });
602 };
603
604 if (allowTwoSideAccounts && !skipCinematics && createInfo->Class != CLASS_DEATH_KNIGHT)
605 {
606 finalizeCharacterCreation(PreparedQueryResult(nullptr));
607 return;
608 }
609
611 stmt->setUInt32(0, GetAccountId());
612 stmt->setUInt32(1, (skipCinematics == 1 || createInfo->Class == CLASS_DEATH_KNIGHT) ? 10 : 1);
613 queryCallback.WithPreparedCallback(std::move(finalizeCharacterCreation)).SetNextQuery(CharacterDatabase.AsyncQuery(stmt));
614 }));
615}
616
618{
619 // Initiating
620 uint32 initAccountId = GetAccountId();
621
622 // can't delete loaded character
623 if (ObjectAccessor::FindPlayer(charDelete.Guid))
624 {
625 sScriptMgr->OnPlayerFailedDelete(charDelete.Guid, initAccountId);
626 return;
627 }
628
629 uint32 accountId = 0;
630 uint8 level = 0;
631 std::string name;
632
633 // is guild leader
634 if (sGuildMgr->GetGuildByLeader(charDelete.Guid))
635 {
636 sScriptMgr->OnPlayerFailedDelete(charDelete.Guid, initAccountId);
638 return;
639 }
640
641 // is arena team captain
642 if (sArenaTeamMgr->GetArenaTeamByCaptain(charDelete.Guid))
643 {
644 sScriptMgr->OnPlayerFailedDelete(charDelete.Guid, initAccountId);
646 return;
647 }
648
649 CharacterCacheEntry const* characterInfo = sCharacterCache->GetCharacterCacheByGuid(charDelete.Guid);
650 if (!characterInfo)
651 {
652 sScriptMgr->OnPlayerFailedDelete(charDelete.Guid, initAccountId);
653 return;
654 }
655
656 accountId = characterInfo->AccountId;
657 name = characterInfo->Name;
658 level = characterInfo->Level;
659
660 // prevent deleting other players' characters using cheating tools
661 if (accountId != initAccountId)
662 {
663 sScriptMgr->OnPlayerFailedDelete(charDelete.Guid, initAccountId);
664 return;
665 }
666
667 TC_LOG_INFO("entities.player.character", "Account: {}, IP: {} deleted character: {}, {}, Level: {}", accountId, GetRemoteAddress(), name, charDelete.Guid.ToString(), level);
668
669 // To prevent hook failure, place hook before removing reference from DB
670 sScriptMgr->OnPlayerDelete(charDelete.Guid, initAccountId); // To prevent race conditioning, but as it also makes sense, we hand the accountId over for successful delete.
671 // Shouldn't interfere with character deletion though
672
673 if (sLog->ShouldLog("entities.player.dump", LOG_LEVEL_INFO)) // optimize GetPlayerDump call
674 {
675 std::string dump;
676 if (PlayerDumpWriter().GetDump(charDelete.Guid.GetCounter(), dump))
677 sLog->OutCharDump(dump.c_str(), accountId, charDelete.Guid.GetRawValue(), name.c_str());
678 }
679
680 sCalendarMgr->RemoveAllPlayerEventsAndInvites(charDelete.Guid);
681 Player::DeleteFromDB(charDelete.Guid, accountId);
682
684}
685
687{
688 if (PlayerLoading() || GetPlayer() != nullptr)
689 {
690 TC_LOG_ERROR("network", "Player tries to login again, AccountId = {}", GetAccountId());
691 KickPlayer("WorldSession::HandlePlayerLoginOpcode Another client logging in");
692 return;
693 }
694
695 m_playerLoading = true;
696 ObjectGuid playerGuid;
697
698 recvData >> playerGuid;
699
700 if (!IsLegitCharacterForAccount(playerGuid))
701 {
702 TC_LOG_ERROR("network", "Account ({}) can't login with that character ({}).", GetAccountId(), playerGuid.ToString());
703 KickPlayer("WorldSession::HandlePlayerLoginOpcode Trying to login with a character of another account");
704 return;
705 }
706
707 std::shared_ptr<LoginQueryHolder> holder = std::make_shared<LoginQueryHolder>(GetAccountId(), playerGuid);
708 if (!holder->Initialize())
709 {
710 m_playerLoading = false;
711 return;
712 }
713
714 AddQueryHolderCallback(CharacterDatabase.DelayQueryHolder(holder)).AfterComplete([this](SQLQueryHolderBase const& holder)
715 {
716 HandlePlayerLogin(static_cast<LoginQueryHolder const&>(holder));
717 });
718}
719
721{
722 ObjectGuid playerGuid = holder.GetGuid();
723
724 Player* pCurrChar = new Player(this);
725 // for send server info and strings (config)
726 ChatHandler chH = ChatHandler(pCurrChar->GetSession());
727
728 // "GetAccountId() == db stored account id" checked in LoadFromDB (prevent login not own character using cheating tools)
729 if (!pCurrChar->LoadFromDB(playerGuid, holder))
730 {
731 SetPlayer(nullptr);
732 KickPlayer("WorldSession::HandlePlayerLogin Player::LoadFromDB failed"); // disconnect client, player no set to session and it will not deleted or saved at kick
733 delete pCurrChar; // delete it manually
734 m_playerLoading = false;
735 return;
736 }
737
738 pCurrChar->GetMotionMaster()->Initialize();
739 pCurrChar->SendDungeonDifficulty(true, false);
740 pCurrChar->SendRaidDifficulty(true, false);
741
743 loginVerifyWorld.MapID = pCurrChar->GetMapId();
744 loginVerifyWorld.Pos = pCurrChar->GetPosition();
745 SendPacket(loginVerifyWorld.Write());
746
747 // load player specific part before send times
750
752
753 // Send MOTD
754 {
756 motd.Text = &sWorld->GetMotd();
757 SendPacket(motd.Write());
758 }
759
760 // send server info
761 {
762 if (sWorld->getIntConfig(CONFIG_ENABLE_SINFO_LOGIN) == 1)
764 }
765
766 //QueryResult* result = CharacterDatabase.PQuery("SELECT guildid, rank FROM guild_member WHERE guid = '{}'", pCurrChar->GetGUID().GetCounter());
768 {
769 Field* fields = resultGuild->Fetch();
770 pCurrChar->SetInGuild(fields[0].GetUInt32());
771 pCurrChar->SetGuildRank(fields[1].GetUInt8());
772 }
773 else if (pCurrChar->GetGuildId()) // clear guild related fields in case wrong data about non existed membership
774 {
775 pCurrChar->SetInGuild(0);
776 pCurrChar->SetGuildRank(0);
777 }
778
779 if (pCurrChar->GetGuildId())
780 {
781 if (Guild* guild = sGuildMgr->GetGuildById(pCurrChar->GetGuildId()))
782 guild->SendLoginInfo(this);
783 else
784 {
785 // remove wrong guild data
786 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());
787 pCurrChar->SetInGuild(0);
788 }
789 }
790
792 data << uint32(0);
793 data << uint32(0);
794 SendPacket(&data);
795
797
798 //Show cinematic at the first time that player login
799 if (!pCurrChar->getCinematic())
800 {
801 pCurrChar->setCinematic(1);
802
803 if (ChrClassesEntry const* cEntry = sChrClassesStore.LookupEntry(pCurrChar->GetClass()))
804 {
805 if (cEntry->CinematicSequenceID)
806 pCurrChar->SendCinematicStart(cEntry->CinematicSequenceID);
807 else if (ChrRacesEntry const* rEntry = sChrRacesStore.LookupEntry(pCurrChar->GetRace()))
808 pCurrChar->SendCinematicStart(rEntry->CinematicSequenceID);
809
810 // send new char string if not empty
811 if (!sWorld->GetNewCharString().empty())
812 chH.PSendSysMessage("%s", sWorld->GetNewCharString().c_str());
813 }
814 }
815
816 if (!pCurrChar->GetMap()->AddPlayerToMap(pCurrChar))
817 {
818 AreaTriggerTeleport const* at = sObjectMgr->GetGoBackTrigger(pCurrChar->GetMapId());
819 if (at)
820 pCurrChar->TeleportTo(at->target_mapId, at->target_X, at->target_Y, at->target_Z, pCurrChar->GetOrientation());
821 else
822 pCurrChar->TeleportTo(pCurrChar->m_homebindMapId, pCurrChar->m_homebindX, pCurrChar->m_homebindY, pCurrChar->m_homebindZ, pCurrChar->GetOrientation());
823 }
824
825 ObjectAccessor::AddObject(pCurrChar);
826 //TC_LOG_DEBUG("Player {} added to Map.", pCurrChar->GetName());
827
829
831 stmt->setUInt32(0, pCurrChar->GetGUID().GetCounter());
832 CharacterDatabase.Execute(stmt);
833
835 loginStmt->setUInt32(0, GetAccountId());
836 LoginDatabase.Execute(loginStmt);
837
839
840 // announce group about member online (must be after add to player list to receive announce to self)
841 if (Group* group = pCurrChar->GetGroup())
842 {
843 //pCurrChar->groupInfo.group->SendInit(this); // useless
844 group->SendUpdate();
845 group->ResetMaxEnchantingLevel();
846 if (group->GetLeaderGUID() == pCurrChar->GetGUID())
847 group->StopLeaderOfflineTimer();
848 }
849
850 // friend status
851 sSocialMgr->SendFriendStatus(pCurrChar, FRIEND_ONLINE, pCurrChar->GetGUID(), true);
852
853 // Place character in world (and load zone) before some object loading
855
856 // setting Ghost+speed if dead
857 if (pCurrChar->m_deathState == DEAD)
858 pCurrChar->SetWaterWalking(true);
859
860 pCurrChar->ContinueTaxiFlight();
861
862 // reset for all pets before pet loading
864 Pet::resetTalentsForAllPetsOf(pCurrChar, nullptr, true);
865
866 // Load pet if any (if player not alive and in taxi flight or another then pet will remember as temporary unsummoned)
867 pCurrChar->LoadPet();
868
869 // Set FFA PvP for non GM in non-rest mode
870 if (sWorld->IsFFAPvPRealm() && !pCurrChar->IsGameMaster() && !pCurrChar->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING))
872
874 pCurrChar->SetContestedPvP();
875
876 // Apply at_login requests
878 {
879 pCurrChar->ResetSpells();
881 }
882
884 {
885 pCurrChar->ResetTalents(true);
886 pCurrChar->SendTalentsInfoData(false); // original talents send already in to SendInitialPacketsBeforeAddToMap, resend reset state
887 }
888
889 bool firstLogin = pCurrChar->HasAtLoginFlag(AT_LOGIN_FIRST);
890 if (firstLogin)
891 {
893
894 PlayerInfo const* info = sObjectMgr->GetPlayerInfo(pCurrChar->GetRace(), pCurrChar->GetClass());
895 for (uint32 spellId : info->castSpells)
896 pCurrChar->CastSpell(pCurrChar, spellId, true);
897
898 // Start with all map areas explored if enabled
899 if (sWorld->getBoolConfig(CONFIG_START_ALL_EXPLORED))
900 for (uint8 i = 0; i < PLAYER_EXPLORED_ZONES_SIZE; ++i)
901 pCurrChar->SetFlag(PLAYER_EXPLORED_ZONES_1 + i, 0xFFFFFFFF);
902
903 // Max relevant reputations if "StartAllReputation" is enabled
904 if (sWorld->getBoolConfig(CONFIG_START_ALL_REP))
905 {
906 ReputationMgr& repMgr = pCurrChar->GetReputationMgr();
907 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry( 942), 42999, false); // Cenarion Expedition
908 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry( 935), 42999, false); // The Sha'tar
909 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry( 936), 42999, false); // Shattrath City
910 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry(1011), 42999, false); // Lower City
911 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry( 970), 42999, false); // Sporeggar
912 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry( 967), 42999, false); // The Violet Eye
913 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry( 989), 42999, false); // Keepers of Time
914 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry( 932), 42999, false); // The Aldor
915 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry( 934), 42999, false); // The Scryers
916 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry(1038), 42999, false); // Ogri'la
917 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry(1077), 42999, false); // Shattered Sun Offensive
918 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry(1106), 42999, false); // Argent Crusade
919 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry(1104), 42999, false); // Frenzyheart Tribe
920 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry(1090), 42999, false); // Kirin Tor
921 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry(1098), 42999, false); // Knights of the Ebon Blade
922 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry(1156), 42999, false); // The Ashen Verdict
923 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry(1073), 42999, false); // The Kalu'ak
924 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry(1105), 42999, false); // The Oracles
925 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry(1119), 42999, false); // The Sons of Hodir
926 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry(1091), 42999, false); // The Wyrmrest Accord
927
928 // Factions depending on team, like cities and some more stuff
929 switch (pCurrChar->GetTeam())
930 {
931 case ALLIANCE:
932 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry( 72), 42999, false); // Stormwind
933 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry( 47), 42999, false); // Ironforge
934 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry( 69), 42999, false); // Darnassus
935 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry( 930), 42999, false); // Exodar
936 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry( 730), 42999, false); // Stormpike Guard
937 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry( 978), 42999, false); // Kurenai
938 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry( 54), 42999, false); // Gnomeregan Exiles
939 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry( 946), 42999, false); // Honor Hold
940 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry(1037), 42999, false); // Alliance Vanguard
941 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry(1068), 42999, false); // Explorers' League
942 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry(1126), 42999, false); // The Frostborn
943 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry(1094), 42999, false); // The Silver Covenant
944 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry(1050), 42999, false); // Valiance Expedition
945 break;
946 case HORDE:
947 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry( 76), 42999, false); // Orgrimmar
948 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry( 68), 42999, false); // Undercity
949 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry( 81), 42999, false); // Thunder Bluff
950 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry( 911), 42999, false); // Silvermoon City
951 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry( 729), 42999, false); // Frostwolf Clan
952 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry( 941), 42999, false); // The Mag'har
953 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry( 530), 42999, false); // Darkspear Trolls
954 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry( 947), 42999, false); // Thrallmar
955 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry(1052), 42999, false); // Horde Expedition
956 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry(1067), 42999, false); // The Hand of Vengeance
957 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry(1124), 42999, false); // The Sunreavers
958 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry(1064), 42999, false); // The Taunka
959 repMgr.SetOneFactionReputation(sFactionStore.LookupEntry(1085), 42999, false); // Warsong Offensive
960 break;
961 default:
962 break;
963 }
964 repMgr.SendState(nullptr);
965 }
966 }
967
968 // show time before shutdown if shutdown planned.
969 if (sWorld->IsShuttingDown())
970 sWorld->ShutdownMsg(true, pCurrChar);
971
972 if (sWorld->getBoolConfig(CONFIG_ALL_TAXI_PATHS))
973 pCurrChar->SetTaxiCheater(true);
974
975 if (pCurrChar->IsGameMaster())
977
978 TC_LOG_INFO("entities.player.character", "Account: {} (IP: {}) Login Character:[{}] {} Level: {}, XP: {}/{} ({} left)",
979 GetAccountId(), GetRemoteAddress(), pCurrChar->GetName(), pCurrChar->GetGUID().ToString(), pCurrChar->GetLevel(),
981
982 if (!pCurrChar->IsStandState() && !pCurrChar->HasUnitState(UNIT_STATE_STUNNED))
984
985 m_playerLoading = false;
986
987 // Handle Login-Achievements (should be handled after loading)
989
990 // if we're loading a dead player, repop them to the GY after the load is finished
991 if (pCurrChar->getDeathState() == CORPSE)
992 {
993 pCurrChar->BuildPlayerRepop();
994 pCurrChar->RepopAtGraveyard();
995 }
996
997 sScriptMgr->OnPlayerLogin(pCurrChar, firstLogin);
998
999 TC_METRIC_EVENT("player_events", "Login", pCurrChar->GetName());
1000}
1001
1009
1011{
1012 TC_LOG_DEBUG("network", "WORLD: Received CMSG_SET_FACTION_AT_WAR");
1013
1014 uint32 repListID;
1015 uint8 flag;
1016
1017 recvData >> repListID;
1018 recvData >> flag;
1019
1020 GetPlayer()->GetReputationMgr().SetAtWar(repListID, flag != 0);
1021}
1022
1023//I think this function is never used :/ I dunno, but i guess this opcode not exists
1025{
1026 TC_LOG_ERROR("network", "WORLD SESSION: HandleSetFactionCheat, not expected call, please report.");
1027 GetPlayer()->GetReputationMgr().SendState(nullptr);
1028}
1029
1031{
1032 uint8 index = uint8(packet.TutorialBit / 32);
1033 if (index >= MAX_ACCOUNT_TUTORIAL_VALUES)
1034 return;
1035
1036 uint32 value = (packet.TutorialBit % 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 if (saveEquipmentSet.Set.SetID >= MAX_EQUIPMENT_SET_INDEX) // client set slots amount
1481 return;
1482
1483 for (uint32 i = 0; i < EQUIPMENT_SLOT_END; ++i)
1484 {
1485 ObjectGuid const& itemGuid = saveEquipmentSet.Set.Pieces[i];
1486
1487 // if client sends 0, it means empty slot
1488 if (itemGuid.IsEmpty())
1489 continue;
1490
1491 // equipment manager sends "1" (as raw GUID) for slots set to "ignore" (don't touch slot at equip set)
1492 if (itemGuid == EquipmentSetInfo::IgnoredSlot)
1493 {
1494 // ignored slots saved as bit mask because we have no free special values for Items[i]
1495 saveEquipmentSet.Set.IgnoreMask |= 1 << i;
1496 continue;
1497 }
1498
1499 // some cheating checks
1501 if (!item || item->GetGUID() != itemGuid)
1502 saveEquipmentSet.Set.Pieces[i].Clear();
1503 }
1504
1505 _player->SetEquipmentSet(saveEquipmentSet.Set);
1506}
1507
1509{
1510 TC_LOG_DEBUG("network", "CMSG_EQUIPMENT_SET_DELETE");
1511
1512 uint64 setGuid;
1513 recvData.readPackGUID(setGuid);
1514
1515 _player->DeleteEquipmentSet(setGuid);
1516}
1517
1519{
1520 TC_LOG_DEBUG("network", "CMSG_EQUIPMENT_SET_USE");
1521
1522 for (uint32 i = 0; i < EQUIPMENT_SLOT_END; ++i)
1523 {
1524 ObjectGuid itemGuid;
1525 recvData >> itemGuid.ReadAsPacked();
1526
1527 uint8 srcbag, srcslot;
1528 recvData >> srcbag >> srcslot;
1529
1530 TC_LOG_DEBUG("entities.player.items", "{}: srcbag {}, srcslot {}", itemGuid.ToString(), srcbag, srcslot);
1531
1532 // check if item slot is set to "ignored" (raw value == 1), must not be unequipped then
1533 if (itemGuid == EquipmentSetInfo::IgnoredSlot)
1534 continue;
1535
1536 // Only equip weapons in combat
1538 continue;
1539
1540 Item* item = _player->GetItemByGuid(itemGuid);
1541
1542 uint16 dstpos = i | (INVENTORY_SLOT_BAG_0 << 8);
1543
1544 if (!item)
1545 {
1547 if (!uItem)
1548 continue;
1549
1550 ItemPosCountVec sDest;
1551 InventoryResult msg = _player->CanStoreItem(NULL_BAG, NULL_SLOT, sDest, uItem, false);
1552 if (msg == EQUIP_ERR_OK)
1553 {
1554 if (_player->CanUnequipItem(dstpos, true) != EQUIP_ERR_OK)
1555 continue;
1556
1558 _player->StoreItem(sDest, uItem, true);
1559 }
1560 else
1561 _player->SendEquipError(msg, uItem, nullptr);
1562
1563 continue;
1564 }
1565
1566 if (item->GetPos() == dstpos)
1567 continue;
1568
1569 if (_player->CanEquipItem(i, dstpos, item, true) != EQUIP_ERR_OK)
1570 continue;
1571
1572 _player->SwapItem(item->GetPos(), dstpos);
1573 }
1574
1576 data << uint8(0); // 4 - equipment swap failed - inventory is full
1577 SendPacket(&data);
1578}
1579
1581{
1583 {
1584 TC_LOG_ERROR("entities.player.cheat", "Account {}, IP: {} tried to factionchange character {}, but it does not belong to their account!",
1585 GetAccountId(), GetRemoteAddress(), packet.RaceOrFactionChangeInfo->Guid.ToString());
1586 KickPlayer("WorldSession::HandleCharRaceOrFactionChange Trying to change faction of character of another account");
1587 return;
1588 }
1589
1591 stmt->setUInt32(0, packet.RaceOrFactionChangeInfo->Guid.GetCounter());
1592
1594 .WithPreparedCallback([this, factionChangeInfo = std::move(packet.RaceOrFactionChangeInfo)](PreparedQueryResult result) mutable
1595 {
1596 HandleCharRaceOrFactionChangeCallback(std::move(factionChangeInfo), std::move(result));
1597 }));
1598}
1599
1600void WorldSession::HandleCharRaceOrFactionChangeCallback(std::shared_ptr<WorldPackets::Character::CharRaceOrFactionChangeInfo> factionChangeInfo, PreparedQueryResult result)
1601{
1602 if (!result)
1603 {
1604 SendCharFactionChange(CHAR_CREATE_ERROR, factionChangeInfo.get());
1605 return;
1606 }
1607
1608 // get the players old (at this moment current) race
1609 CharacterCacheEntry const* characterInfo = sCharacterCache->GetCharacterCacheByGuid(factionChangeInfo->Guid);
1610 if (!characterInfo)
1611 {
1612 SendCharFactionChange(CHAR_CREATE_ERROR, factionChangeInfo.get());
1613 return;
1614 }
1615
1616 uint8 oldRace = characterInfo->Race;
1617 uint8 playerClass = characterInfo->Class;
1618 uint8 level = characterInfo->Level;
1619 //std::string oldName = characterInfo->Name;
1620
1621 if (!sObjectMgr->GetPlayerInfo(factionChangeInfo->RaceID, playerClass))
1622 {
1623 SendCharFactionChange(CHAR_CREATE_ERROR, factionChangeInfo.get());
1624 return;
1625 }
1626
1627 Field* fields = result->Fetch();
1628 uint32 atLoginFlags = fields[0].GetUInt16();
1629 std::string knownTitlesStr = fields[1].GetString();
1630 uint32 groupId = !fields[2].IsNull() ? fields[2].GetUInt32() : 0;
1631 uint32 mapId = fields[3].GetUInt16();
1632
1633 uint32 usedLoginFlag = (factionChangeInfo->FactionChange ? AT_LOGIN_CHANGE_FACTION : AT_LOGIN_CHANGE_RACE);
1634 if (!(atLoginFlags & usedLoginFlag))
1635 {
1636 SendCharFactionChange(CHAR_CREATE_ERROR, factionChangeInfo.get());
1637 return;
1638 }
1639
1640 if (level < 10)
1641 {
1642 SendCharFactionChange(CHAR_CREATE_ERROR, factionChangeInfo.get());
1643 return;
1644 }
1645
1646 if (playerClass == CLASS_DEATH_KNIGHT && (level < 60 || mapId == 609))
1647 {
1649 return;
1650 }
1651
1652 uint32 newTeam = Player::TeamForRace(factionChangeInfo->RaceID);
1653 if (factionChangeInfo->FactionChange == (Player::TeamForRace(oldRace) == newTeam))
1654 {
1655 SendCharFactionChange(factionChangeInfo->FactionChange ? CHAR_CREATE_CHARACTER_SWAP_FACTION : CHAR_CREATE_CHARACTER_RACE_ONLY, factionChangeInfo.get());
1656 return;
1657 }
1658
1660 {
1661 uint32 raceMaskDisabled = sWorld->getIntConfig(CONFIG_CHARACTER_CREATING_DISABLED_RACEMASK);
1662 if ((1 << (factionChangeInfo->RaceID - 1)) & raceMaskDisabled)
1663 {
1664 SendCharFactionChange(CHAR_CREATE_ERROR, factionChangeInfo.get());
1665 return;
1666 }
1667 }
1668
1669 // prevent character rename
1670 if (sWorld->getBoolConfig(CONFIG_PREVENT_RENAME_CUSTOMIZATION) && (factionChangeInfo->Name != characterInfo->Name))
1671 {
1672 SendCharFactionChange(CHAR_NAME_FAILURE, factionChangeInfo.get());
1673 return;
1674 }
1675
1676 // prevent character rename to invalid name
1677 if (!normalizePlayerName(factionChangeInfo->Name))
1678 {
1679 SendCharFactionChange(CHAR_NAME_NO_NAME, factionChangeInfo.get());
1680 return;
1681 }
1682
1683 ResponseCodes res = ObjectMgr::CheckPlayerName(factionChangeInfo->Name, GetSessionDbcLocale(), true);
1684 if (res != CHAR_NAME_SUCCESS)
1685 {
1686 SendCharFactionChange(res, factionChangeInfo.get());
1687 return;
1688 }
1689
1690 // check name limitations
1691 if (!HasPermission(rbac::RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_RESERVEDNAME) && sObjectMgr->IsReservedName(factionChangeInfo->Name))
1692 {
1693 SendCharFactionChange(CHAR_NAME_RESERVED, factionChangeInfo.get());
1694 return;
1695 }
1696
1697 // character with this name already exist
1698 ObjectGuid newGuid = sCharacterCache->GetCharacterGuidByName(factionChangeInfo->Name);
1699 if (!newGuid.IsEmpty())
1700 {
1701 if (newGuid != factionChangeInfo->Guid)
1702 {
1703 SendCharFactionChange(CHAR_CREATE_NAME_IN_USE, factionChangeInfo.get());
1704 return;
1705 }
1706 }
1707
1708 if (sArenaTeamMgr->GetArenaTeamByCaptain(factionChangeInfo->Guid))
1709 {
1711 return;
1712 }
1713
1714 // All checks are fine, deal with race change now
1715 ObjectGuid::LowType lowGuid = factionChangeInfo->Guid.GetCounter();
1716
1717 CharacterDatabasePreparedStatement* stmt = nullptr;
1718 CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
1719
1720 // resurrect the character in case he's dead
1721 Player::OfflineResurrect(factionChangeInfo->Guid, trans);
1722
1723 // Name Change and update atLogin flags
1724 {
1725 CharacterDatabase.EscapeString(factionChangeInfo->Name);
1726
1727 stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_NAME_AT_LOGIN);
1728 stmt->setString(0, factionChangeInfo->Name);
1729 stmt->setUInt16(1, uint16((atLoginFlags | AT_LOGIN_RESURRECT) & ~usedLoginFlag));
1730 stmt->setUInt32(2, lowGuid);
1731 trans->Append(stmt);
1732
1733 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_DECLINED_NAME);
1734 stmt->setUInt32(0, lowGuid);
1735 trans->Append(stmt);
1736 }
1737
1738 // Customize
1739 {
1740 stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_GENDER_AND_APPEARANCE);
1741
1742 stmt->setUInt8(0, factionChangeInfo->SexID);
1743 stmt->setUInt8(1, factionChangeInfo->SkinID);
1744 stmt->setUInt8(2, factionChangeInfo->FaceID);
1745 stmt->setUInt8(3, factionChangeInfo->HairStyleID);
1746 stmt->setUInt8(4, factionChangeInfo->HairColorID);
1747 stmt->setUInt8(5, factionChangeInfo->FacialHairStyleID);
1748 stmt->setUInt32(6, factionChangeInfo->Guid.GetCounter());
1749
1750 trans->Append(stmt);
1751 }
1752
1753 // Race Change
1754 {
1755 stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_RACE);
1756 stmt->setUInt8(0, factionChangeInfo->RaceID);
1758 stmt->setUInt32(2, lowGuid);
1759 trans->Append(stmt);
1760 }
1761
1762 sCharacterCache->UpdateCharacterData(factionChangeInfo->Guid, factionChangeInfo->Name, factionChangeInfo->SexID, factionChangeInfo->RaceID);
1763
1764 if (oldRace != factionChangeInfo->RaceID)
1765 {
1766 // Switch Languages
1767 // delete all languages first
1768 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_SKILL_LANGUAGES);
1769 stmt->setUInt32(0, lowGuid);
1770 trans->Append(stmt);
1771
1772 // Now add them back
1773 stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHAR_SKILL_LANGUAGE);
1774 stmt->setUInt32(0, lowGuid);
1775
1776 // Faction specific languages
1777 if (newTeam == HORDE)
1778 stmt->setUInt16(1, 109);
1779 else
1780 stmt->setUInt16(1, 98);
1781
1782 trans->Append(stmt);
1783
1784 // Race specific languages
1785 if (factionChangeInfo->RaceID != RACE_ORC && factionChangeInfo->RaceID != RACE_HUMAN)
1786 {
1787 stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHAR_SKILL_LANGUAGE);
1788 stmt->setUInt32(0, lowGuid);
1789
1790 switch (factionChangeInfo->RaceID)
1791 {
1792 case RACE_DWARF:
1793 stmt->setUInt16(1, 111);
1794 break;
1795 case RACE_DRAENEI:
1796 stmt->setUInt16(1, 759);
1797 break;
1798 case RACE_GNOME:
1799 stmt->setUInt16(1, 313);
1800 break;
1801 case RACE_NIGHTELF:
1802 stmt->setUInt16(1, 113);
1803 break;
1804 case RACE_UNDEAD_PLAYER:
1805 stmt->setUInt16(1, 673);
1806 break;
1807 case RACE_TAUREN:
1808 stmt->setUInt16(1, 115);
1809 break;
1810 case RACE_TROLL:
1811 stmt->setUInt16(1, 315);
1812 break;
1813 case RACE_BLOODELF:
1814 stmt->setUInt16(1, 137);
1815 break;
1816 }
1817
1818 trans->Append(stmt);
1819 }
1820
1821 if (factionChangeInfo->FactionChange)
1822 {
1823 // Delete all Flypaths
1824 stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_TAXI_PATH);
1825 stmt->setUInt32(0, lowGuid);
1826 trans->Append(stmt);
1827
1828 if (level > 7)
1829 {
1830 // Update Taxi path
1831 // this doesn't seem to be 100% blizzlike... but it can't really be helped.
1832 std::ostringstream taximaskstream;
1833 uint32 numFullTaximasks = level / 7;
1834 if (numFullTaximasks > 11)
1835 numFullTaximasks = 11;
1836
1837 TaxiMask const& factionMask = newTeam == HORDE ? sHordeTaxiNodesMask : sAllianceTaxiNodesMask;
1838 for (uint8 i = 0; i < numFullTaximasks; ++i)
1839 {
1840 uint8 deathKnightExtraNode = (playerClass == CLASS_DEATH_KNIGHT) ? sDeathKnightTaxiNodesMask[i] : 0;
1841 taximaskstream << uint32(factionMask[i] | deathKnightExtraNode) << ' ';
1842 }
1843
1844 uint32 numEmptyTaximasks = 11 - numFullTaximasks;
1845 for (uint8 i = 0; i < numEmptyTaximasks; ++i)
1846 taximaskstream << "0 ";
1847 taximaskstream << '0';
1848
1849 stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_TAXIMASK);
1850 stmt->setString(0, taximaskstream.str());
1851 stmt->setUInt32(1, lowGuid);
1852 trans->Append(stmt);
1853 }
1854
1856 {
1857 // Reset guild
1858 if (Guild* guild = sGuildMgr->GetGuildById(characterInfo->GuildId))
1859 guild->DeleteMember(trans, factionChangeInfo->Guid, false, false);
1860
1861 Player::LeaveAllArenaTeams(factionChangeInfo->Guid);
1862 }
1863
1864 if (groupId && !sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP))
1865 {
1866 if (Group* group = sGroupMgr->GetGroupByDbStoreId(groupId))
1867 group->RemoveMember(factionChangeInfo->Guid);
1868 }
1869
1871 {
1872 // Delete Friend List
1873 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_SOCIAL_BY_GUID);
1874 stmt->setUInt32(0, lowGuid);
1875 trans->Append(stmt);
1876
1877 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_SOCIAL_BY_FRIEND);
1878 stmt->setUInt32(0, lowGuid);
1879 trans->Append(stmt);
1880 }
1881
1882 // Reset homebind and position
1883 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PLAYER_HOMEBIND);
1884 stmt->setUInt32(0, lowGuid);
1885 trans->Append(stmt);
1886
1887 stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_PLAYER_HOMEBIND);
1888 stmt->setUInt32(0, lowGuid);
1889
1890 WorldLocation loc;
1891 uint16 zoneId = 0;
1892 if (newTeam == ALLIANCE)
1893 {
1894 loc.WorldRelocate(0, -8867.68f, 673.373f, 97.9034f, 0.0f);
1895 zoneId = 1519;
1896 }
1897 else
1898 {
1899 loc.WorldRelocate(1, 1633.33f, -4439.11f, 15.7588f, 0.0f);
1900 zoneId = 1637;
1901 }
1902
1903 stmt->setUInt16(1, loc.GetMapId());
1904 stmt->setUInt16(2, zoneId);
1905 stmt->setFloat(3, loc.GetPositionX());
1906 stmt->setFloat(4, loc.GetPositionY());
1907 stmt->setFloat(5, loc.GetPositionZ());
1908 trans->Append(stmt);
1909
1910 Player::SavePositionInDB(loc, zoneId, factionChangeInfo->Guid, trans);
1911
1912 // Achievement conversion
1913 for (std::map<uint32, uint32>::const_iterator it = sObjectMgr->FactionChangeAchievements.begin(); it != sObjectMgr->FactionChangeAchievements.end(); ++it)
1914 {
1915 uint32 achiev_alliance = it->first;
1916 uint32 achiev_horde = it->second;
1917
1919 stmt->setUInt16(0, uint16(newTeam == ALLIANCE ? achiev_alliance : achiev_horde));
1920 stmt->setUInt32(1, lowGuid);
1921 trans->Append(stmt);
1922
1923 stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_ACHIEVEMENT);
1924 stmt->setUInt16(0, uint16(newTeam == ALLIANCE ? achiev_alliance : achiev_horde));
1925 stmt->setUInt16(1, uint16(newTeam == ALLIANCE ? achiev_horde : achiev_alliance));
1926 stmt->setUInt32(2, lowGuid);
1927 trans->Append(stmt);
1928 }
1929
1930 // Item conversion
1931 for (std::map<uint32, uint32>::const_iterator it = sObjectMgr->FactionChangeItems.begin(); it != sObjectMgr->FactionChangeItems.end(); ++it)
1932 {
1933 uint32 item_alliance = it->first;
1934 uint32 item_horde = it->second;
1935
1936 stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_INVENTORY_FACTION_CHANGE);
1937 stmt->setUInt32(0, (newTeam == ALLIANCE ? item_alliance : item_horde));
1938 stmt->setUInt32(1, (newTeam == ALLIANCE ? item_horde : item_alliance));
1939 stmt->setUInt32(2, lowGuid);
1940 trans->Append(stmt);
1941 }
1942
1943 // Delete all current quests
1944 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_QUESTSTATUS);
1945 stmt->setUInt32(0, lowGuid);
1946 trans->Append(stmt);
1947
1948 // Quest conversion
1949 for (std::map<uint32, uint32>::const_iterator it = sObjectMgr->FactionChangeQuests.begin(); it != sObjectMgr->FactionChangeQuests.end(); ++it)
1950 {
1951 uint32 quest_alliance = it->first;
1952 uint32 quest_horde = it->second;
1953
1955 stmt->setUInt32(0, lowGuid);
1956 stmt->setUInt32(1, (newTeam == ALLIANCE ? quest_alliance : quest_horde));
1957 trans->Append(stmt);
1958
1960 stmt->setUInt32(0, (newTeam == ALLIANCE ? quest_alliance : quest_horde));
1961 stmt->setUInt32(1, (newTeam == ALLIANCE ? quest_horde : quest_alliance));
1962 stmt->setUInt32(2, lowGuid);
1963 trans->Append(stmt);
1964 }
1965
1966 // Mark all rewarded quests as "active" (will count for completed quests achievements)
1968 stmt->setUInt32(0, lowGuid);
1969 trans->Append(stmt);
1970
1971 // Disable all old-faction specific quests
1972 {
1973 ObjectMgr::QuestContainer const& questTemplates = sObjectMgr->GetQuestTemplates();
1974 for (auto const& [questId, quest] : questTemplates)
1975 {
1976 uint32 newRaceMask = (newTeam == ALLIANCE) ? RACEMASK_ALLIANCE : RACEMASK_HORDE;
1977 if (quest->GetAllowableRaces() && !(quest->GetAllowableRaces() & newRaceMask))
1978 {
1980 stmt->setUInt32(0, lowGuid);
1981 stmt->setUInt32(1, questId);
1982 trans->Append(stmt);
1983 }
1984 }
1985 }
1986
1987 // Spell conversion
1988 for (std::map<uint32, uint32>::const_iterator it = sObjectMgr->FactionChangeSpells.begin(); it != sObjectMgr->FactionChangeSpells.end(); ++it)
1989 {
1990 uint32 spell_alliance = it->first;
1991 uint32 spell_horde = it->second;
1992
1993 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_SPELL_BY_SPELL);
1994 stmt->setUInt32(0, (newTeam == ALLIANCE ? spell_alliance : spell_horde));
1995 stmt->setUInt32(1, lowGuid);
1996 trans->Append(stmt);
1997
1998 stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_SPELL_FACTION_CHANGE);
1999 stmt->setUInt32(0, (newTeam == ALLIANCE ? spell_alliance : spell_horde));
2000 stmt->setUInt32(1, (newTeam == ALLIANCE ? spell_horde : spell_alliance));
2001 stmt->setUInt32(2, lowGuid);
2002 trans->Append(stmt);
2003 }
2004
2005 // Reputation conversion
2006 for (std::map<uint32, uint32>::const_iterator it = sObjectMgr->FactionChangeReputation.begin(); it != sObjectMgr->FactionChangeReputation.end(); ++it)
2007 {
2008 uint32 reputation_alliance = it->first;
2009 uint32 reputation_horde = it->second;
2010 uint32 newReputation = (newTeam == ALLIANCE) ? reputation_alliance : reputation_horde;
2011 uint32 oldReputation = (newTeam == ALLIANCE) ? reputation_horde : reputation_alliance;
2012
2013 // select old standing set in db
2014 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_REP_BY_FACTION);
2015 stmt->setUInt32(0, oldReputation);
2016 stmt->setUInt32(1, lowGuid);
2017
2018 if (PreparedQueryResult reputationResult = CharacterDatabase.Query(stmt))
2019 {
2020 fields = reputationResult->Fetch();
2021 int32 oldDBRep = fields[0].GetInt32();
2022 FactionEntry const* factionEntry = sFactionStore.LookupEntry(oldReputation);
2023
2024 // old base reputation
2025 int32 oldBaseRep = sObjectMgr->GetBaseReputationOf(factionEntry, oldRace, playerClass);
2026
2027 // new base reputation
2028 int32 newBaseRep = sObjectMgr->GetBaseReputationOf(sFactionStore.LookupEntry(newReputation), factionChangeInfo->RaceID, playerClass);
2029
2030 // final reputation shouldnt change
2031 int32 FinalRep = oldDBRep + oldBaseRep;
2032 int32 newDBRep = FinalRep - newBaseRep;
2033
2034 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_REP_BY_FACTION);
2035 stmt->setUInt32(0, newReputation);
2036 stmt->setUInt32(1, lowGuid);
2037 trans->Append(stmt);
2038
2039 stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_REP_FACTION_CHANGE);
2040 stmt->setUInt16(0, uint16(newReputation));
2041 stmt->setInt32(1, newDBRep);
2042 stmt->setUInt16(2, uint16(oldReputation));
2043 stmt->setUInt32(3, lowGuid);
2044 trans->Append(stmt);
2045 }
2046 }
2047
2048 // Title conversion
2049 if (!knownTitlesStr.empty())
2050 {
2051 std::vector<std::string_view> tokens = Trinity::Tokenize(knownTitlesStr, ' ', false);
2052 std::array<uint32, KNOWN_TITLES_SIZE * 2> knownTitles;
2053
2054 for (uint32 index = 0; index < knownTitles.size(); ++index)
2055 {
2056 Optional<uint32> thisMask;
2057 if (index < tokens.size())
2058 thisMask = Trinity::StringTo<uint32>(tokens[index]);
2059
2060 if (thisMask)
2061 knownTitles[index] = *thisMask;
2062 else
2063 {
2064 TC_LOG_WARN("entities.player", "{} has invalid title data '{}' at index {} - skipped, this may result in titles being lost",
2065 GetPlayerInfo(), (index < tokens.size()) ? std::string(tokens[index]) : "<none>", index);
2066 knownTitles[index] = 0;
2067 }
2068 }
2069
2070 for (std::map<uint32, uint32>::const_iterator it = sObjectMgr->FactionChangeTitles.begin(); it != sObjectMgr->FactionChangeTitles.end(); ++it)
2071 {
2072 uint32 title_alliance = it->first;
2073 uint32 title_horde = it->second;
2074
2075 CharTitlesEntry const* atitleInfo = sCharTitlesStore.AssertEntry(title_alliance);
2076 CharTitlesEntry const* htitleInfo = sCharTitlesStore.AssertEntry(title_horde);
2077 // new team
2078 if (newTeam == ALLIANCE)
2079 {
2080 uint32 bitIndex = htitleInfo->MaskID;
2081 uint32 index = bitIndex / 32;
2082 uint32 old_flag = 1 << (bitIndex % 32);
2083 uint32 new_flag = 1 << (atitleInfo->MaskID % 32);
2084 if (knownTitles[index] & old_flag)
2085 {
2086 knownTitles[index] &= ~old_flag;
2087 // use index of the new title
2088 knownTitles[atitleInfo->MaskID / 32] |= new_flag;
2089 }
2090 }
2091 else
2092 {
2093 uint32 bitIndex = atitleInfo->MaskID;
2094 uint32 index = bitIndex / 32;
2095 uint32 old_flag = 1 << (bitIndex % 32);
2096 uint32 new_flag = 1 << (htitleInfo->MaskID % 32);
2097 if (knownTitles[index] & old_flag)
2098 {
2099 knownTitles[index] &= ~old_flag;
2100 // use index of the new title
2101 knownTitles[htitleInfo->MaskID / 32] |= new_flag;
2102 }
2103 }
2104
2105 std::ostringstream ss;
2106 for (uint32 mask : knownTitles)
2107 ss << mask << ' ';
2108
2109 stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_TITLES_FACTION_CHANGE);
2110 stmt->setString(0, ss.str());
2111 stmt->setUInt32(1, lowGuid);
2112 trans->Append(stmt);
2113
2114 // unset any currently chosen title
2115 stmt = CharacterDatabase.GetPreparedStatement(CHAR_RES_CHAR_TITLES_FACTION_CHANGE);
2116 stmt->setUInt32(0, lowGuid);
2117 trans->Append(stmt);
2118 }
2119 }
2120 }
2121 }
2122
2123 CharacterDatabase.CommitTransaction(trans);
2124
2125 TC_LOG_DEBUG("entities.player", "{} (IP: {}) changed race from {} to {}", GetPlayerInfo(), GetRemoteAddress(), oldRace, factionChangeInfo->RaceID);
2126
2127 SendCharFactionChange(RESPONSE_SUCCESS, factionChangeInfo.get());
2128}
2129
2131{
2133 response.Code = result;
2134
2135 SendPacket(response.Write());
2136}
2137
2139{
2141 response.Code = result;
2142
2143 SendPacket(response.Write());
2144}
2145
2147{
2149 packet.Result = result;
2150 packet.Name = renameInfo->NewName;
2151 packet.Guid = renameInfo->Guid;
2152
2153 SendPacket(packet.Write());
2154}
2155
2157{
2159 response.Code = result;
2160 response.CustomizeInfo = customizeInfo;
2161
2162 SendPacket(response.Write());
2163}
2164
2166{
2168 response.Result = result;
2169 response.RaceOrFactionChangeInfo = factionChangeInfo;
2170
2171 SendPacket(response.Write());
2172}
2173
2175{
2177 data << uint32(result);
2178 data << guid;
2179 SendPacket(&data);
2180}
2181
2183{
2185 data << uint32(result);
2186 SendPacket(&data);
2187}
2188
2190{
2191 // Only players that has not yet gained any experience can use this
2193 return;
2194
2195 if (ChrClassesEntry const* classEntry = sChrClassesStore.LookupEntry(_player->GetClass()))
2196 {
2197 if (classEntry->CinematicSequenceID)
2198 _player->SendCinematicStart(classEntry->CinematicSequenceID);
2199 else if (ChrRacesEntry const* raceEntry = sChrRacesStore.LookupEntry(_player->GetRace()))
2200 _player->SendCinematicStart(raceEntry->CinematicSequenceID);
2201 }
2202}
#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
@ 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:575
@ EQUIPMENT_SLOT_END
Definition Player.h:579
@ EQUIPMENT_SLOT_OFFHAND
Definition Player.h:576
@ EQUIPMENT_SLOT_RANGED
Definition Player.h:577
std::vector< ItemPosCount > ItemPosCountVec
Definition Player.h:632
@ PLAYER_EXTRA_HAS_RACE_CHANGED
Definition Player.h:472
@ PLAYER_FLAGS_HIDE_CLOAK
Definition Player.h:357
@ PLAYER_FLAGS_CONTESTED_PVP
Definition Player.h:354
@ PLAYER_FLAGS_RESTING
Definition Player.h:351
@ PLAYER_FLAGS_HIDE_HELM
Definition Player.h:356
@ AT_LOGIN_RESET_TALENTS
Definition Player.h:483
@ AT_LOGIN_RESET_SPELLS
Definition Player.h:482
@ AT_LOGIN_RESET_PET_TALENTS
Definition Player.h:485
@ AT_LOGIN_FIRST
Definition Player.h:486
@ AT_LOGIN_RESURRECT
Definition Player.h:489
@ AT_LOGIN_CUSTOMIZE
Definition Player.h:484
@ AT_LOGIN_RENAME
Definition Player.h:481
@ AT_LOGIN_CHANGE_RACE
Definition Player.h:488
@ AT_LOGIN_CHANGE_FACTION
Definition Player.h:487
#define INVENTORY_SLOT_BAG_0
Definition Player.h:555
#define PLAYER_EXPLORED_ZONES_SIZE
Definition Player.h:119
@ PLAYER_LOGIN_QUERY_LOAD_SPELL_COOLDOWNS
Definition Player.h:713
@ PLAYER_LOGIN_QUERY_LOAD_GLYPHS
Definition Player.h:721
@ PLAYER_LOGIN_QUERY_LOAD_DECLINED_NAMES
Definition Player.h:714
@ PLAYER_LOGIN_QUERY_LOAD_QUEST_STATUS_REW
Definition Player.h:728
@ MAX_PLAYER_LOGIN_QUERY
Definition Player.h:733
@ PLAYER_LOGIN_QUERY_LOAD_DAILY_QUEST_STATUS
Definition Player.h:705
@ PLAYER_LOGIN_QUERY_LOAD_SEASONAL_QUEST_STATUS
Definition Player.h:729
@ PLAYER_LOGIN_QUERY_LOAD_SOCIAL_LIST
Definition Player.h:711
@ PLAYER_LOGIN_QUERY_LOAD_ACTIONS
Definition Player.h:708
@ PLAYER_LOGIN_QUERY_LOAD_SKILLS
Definition Player.h:724
@ PLAYER_LOGIN_QUERY_LOAD_BG_DATA
Definition Player.h:720
@ PLAYER_LOGIN_QUERY_LOAD_ACCOUNT_DATA
Definition Player.h:723
@ PLAYER_LOGIN_QUERY_LOAD_MAIL_ITEMS
Definition Player.h:710
@ PLAYER_LOGIN_QUERY_LOAD_PET_SLOTS
Definition Player.h:732
@ PLAYER_LOGIN_QUERY_LOAD_INVENTORY
Definition Player.h:707
@ PLAYER_LOGIN_QUERY_LOAD_REPUTATION
Definition Player.h:706
@ PLAYER_LOGIN_QUERY_LOAD_FROM
Definition Player.h:699
@ PLAYER_LOGIN_QUERY_LOAD_QUEST_STATUS
Definition Player.h:704
@ PLAYER_LOGIN_QUERY_LOAD_WEEKLY_QUEST_STATUS
Definition Player.h:725
@ PLAYER_LOGIN_QUERY_LOAD_MONTHLY_QUEST_STATUS
Definition Player.h:730
@ PLAYER_LOGIN_QUERY_LOAD_GUILD
Definition Player.h:715
@ PLAYER_LOGIN_QUERY_LOAD_EQUIPMENT_SETS
Definition Player.h:719
@ PLAYER_LOGIN_QUERY_LOAD_MAILS
Definition Player.h:709
@ PLAYER_LOGIN_QUERY_LOAD_AURAS
Definition Player.h:702
@ PLAYER_LOGIN_QUERY_LOAD_TALENTS
Definition Player.h:722
@ PLAYER_LOGIN_QUERY_LOAD_BANNED
Definition Player.h:727
@ PLAYER_LOGIN_QUERY_LOAD_ARENA_INFO
Definition Player.h:716
@ PLAYER_LOGIN_QUERY_LOAD_GROUP
Definition Player.h:700
@ PLAYER_LOGIN_QUERY_LOAD_CRITERIA_PROGRESS
Definition Player.h:718
@ PLAYER_LOGIN_QUERY_LOAD_HOME_BIND
Definition Player.h:712
@ PLAYER_LOGIN_QUERY_LOAD_CORPSE_LOCATION
Definition Player.h:731
@ PLAYER_LOGIN_QUERY_LOAD_SPELLS
Definition Player.h:703
@ PLAYER_LOGIN_QUERY_LOAD_BOUND_INSTANCES
Definition Player.h:701
@ PLAYER_LOGIN_QUERY_LOAD_RANDOM_BG
Definition Player.h:726
@ PLAYER_LOGIN_QUERY_LOAD_ACHIEVEMENTS
Definition Player.h:717
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
#define MAX_ACCOUNT_TUTORIAL_VALUES
@ 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:227
@ DEAD
Definition Unit.h:228
@ UNIT_STATE_STUNNED
Definition Unit.h:237
@ NULL_BAG
Definition Unit.h:60
@ NULL_SLOT
Definition Unit.h:61
@ 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:141
void clear()
Definition ByteBuffer.h:126
void readPackGUID(uint64 &guid)
Definition ByteBuffer.h:373
void PSendSysMessage(char const *fmt, Args &&... args)
Definition Chat.h:61
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:147
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:941
uint32 GetUInt32Value(uint16 index) const
Definition Object.cpp:241
void SetFlag(uint16 index, uint32 newFlag)
Definition Object.cpp:761
void RemoveFlag(uint16 index, uint32 oldFlag)
Definition Object.cpp:776
bool HasFlag(uint16 index, uint32 flag) const
Definition Object.cpp:800
static ObjectGuid GetGUID(Object const *o)
Definition Object.h:78
void SetUInt32Value(uint16 index, uint32 value)
Definition Object.cpp:577
static void resetTalentsForAllPetsOf(Player *owner, Pet *online_pet=nullptr, bool involuntarily=false)
Definition Pet.cpp:1717
void ContinueTaxiFlight() const
Definition Player.cpp:21215
void SendEquipError(InventoryResult msg, Item const *item1=nullptr, Item const *item2=nullptr, uint32 itemId=0) const
Definition Player.cpp:13070
void SendInitialPacketsAfterAddToMap()
Definition Player.cpp:22470
uint32 GetXP() const
Definition Player.h:996
uint32 GetTeam() const
Definition Player.h:1818
InventoryResult CanUnequipItem(uint16 src, bool swap) const
Definition Player.cpp:11137
void RemoveAtLoginFlag(AtLoginFlags flags, bool persist=false)
Definition Player.cpp:25490
uint8 GetSkinId() const
Definition Player.h:1019
void SetHairStyleId(uint8 hairStyle)
Definition Player.h:1024
void ResetSpells(bool myClassOnly=false)
Definition Player.cpp:22642
void SendTalentsInfoData(bool pet)
Definition Player.cpp:25337
void SetEquipmentSet(EquipmentSetInfo::EquipmentSetData const &eqset)
Definition Player.cpp:25371
InventoryResult CanEquipItem(uint8 slot, uint16 &dest, Item *pItem, bool swap, bool not_loading=true) const
Definition Player.cpp:10980
float m_homebindZ
Definition Player.h:2077
Gender GetNativeGender() const override
Definition Player.h:1017
uint32 m_homebindMapId
Definition Player.h:2073
InventoryResult CanStoreItem(uint8 bag, uint8 slot, ItemPosCountVec &dest, Item *pItem, bool swap=false) const
Definition Player.cpp:9992
void SetHairColorId(uint8 hairColor)
Definition Player.h:1026
void CleanupsBeforeDelete(bool finalCleanup=true) override
Definition Player.cpp:373
void UpdateAchievementCriteria(AchievementCriteriaTypes type, uint32 miscValue1=0, uint32 miscValue2=0, WorldObject *ref=nullptr)
Definition Player.cpp:24914
static void OfflineResurrect(ObjectGuid const &guid, CharacterDatabaseTransaction trans)
Definition Player.cpp:4493
bool ModifyMoney(int32 amount, bool sendError=true)
Definition Player.cpp:22336
void SendInitialPacketsBeforeAddToMap()
Definition Player.cpp:22405
static void SavePositionInDB(WorldLocation const &loc, uint16 zoneId, ObjectGuid guid, CharacterDatabaseTransaction trans)
Definition Player.cpp:20047
void SetFacialStyle(uint8 facialStyle)
Definition Player.h:1028
void SwapItem(uint16 src, uint16 dst)
Definition Player.cpp:12628
Item * StoreItem(ItemPosCountVec const &pos, Item *pItem, bool update)
Definition Player.cpp:11659
WorldSession * GetSession() const
Definition Player.h:1705
Item * GetItemByPos(uint16 pos) const
Definition Player.cpp:9550
void RepopAtGraveyard()
Definition Player.cpp:4792
static uint32 TeamForRace(uint8 race)
Definition Player.cpp:6271
bool HasEnoughMoney(uint32 amount) const
Definition Player.h:1394
uint8 GetFaceId() const
Definition Player.h:1021
void SetInGuild(ObjectGuid::LowType guildId)
Definition Player.cpp:26212
float m_homebindY
Definition Player.h:2076
void SendRaidDifficulty(bool changeCurrentDifficuly, bool changeGroupDifficuly) const
Definition Player.cpp:20111
ObjectGuid::LowType GetGuildId() const
Definition Player.h:1605
Group * GetGroup()
Definition Player.h:2159
bool IsGameMaster() const
Definition Player.h:976
void SetGuildRank(uint8 rankId)
Definition Player.h:1602
void LoadCorpse(PreparedQueryResult result)
Definition Player.cpp:17808
static void DeleteFromDB(ObjectGuid playerguid, uint32 accountId, bool updateRealmChars=true, bool deleteFinally=false)
Definition Player.cpp:3913
void SendCinematicStart(uint32 CinematicSequenceId) const
Definition Player.cpp:6168
void LoadPet()
Definition Player.cpp:18194
void SetGlyph(uint8 slot, uint32 glyph)
Definition Player.cpp:24256
uint8 getCinematic() const
Definition Player.h:1553
bool TeleportTo(uint32 mapid, float x, float y, float z, float orientation, uint32 options=0)
Definition Player.cpp:1539
uint32 GetXPForNextLevel() const
Definition Player.h:997
bool ResetTalents(bool involuntarily=false)
Definition Player.cpp:3735
void DeleteEquipmentSet(uint64 id)
Definition Player.cpp:25474
uint8 GetActiveTalentGroup() const
Definition Player.h:1480
bool LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder const &holder)
Definition Player.cpp:16886
void SetSkinId(uint8 skin)
Definition Player.h:1020
static bool BuildEnumData(PreparedQueryResult result, WorldPacket *data)
Definition Player.cpp:1315
uint32 GetGlyph(uint8 group, uint8 slot) const
Definition Player.h:1508
bool HasAtLoginFlag(AtLoginFlags f) const
Definition Player.h:2101
static void LeaveAllArenaTeams(ObjectGuid guid)
Definition Player.cpp:20956
void RemoveItem(uint8 bag, uint8 slot, bool update)
Definition Player.cpp:11981
void BuildPlayerRepop()
Definition Player.cpp:4320
void SetTaxiCheater(bool on)
Definition Player.h:983
void SetContestedPvP(Player *attackedPlayer=nullptr)
Definition Player.cpp:20210
Item * GetItemByGuid(ObjectGuid guid) const
Definition Player.cpp:9516
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:26385
void SetInGameTime(uint32 time)
Definition Player.h:1346
void setCinematic(uint8 cine)
Definition Player.h:1554
void SendDungeonDifficulty(bool changeCurrentDifficuly, bool changeGroupDifficuly) const
Definition Player.cpp:20102
ReputationMgr & GetReputationMgr()
Definition Player.h:1834
float m_homebindX
Definition Player.h:2075
uint32 GetBarberShopCost(uint8 newhairstyle, uint8 newhaircolor, uint8 newfacialhair, BarberShopStyleEntry const *newSkin=nullptr) const
Definition Player.cpp:24194
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:909
MotionMaster * GetMotionMaster()
Definition Unit.h:1683
DeathState m_deathState
Definition Unit.h:1868
bool IsStandState() const
Definition Unit.cpp:10334
void SetPvpFlag(UnitPVPStateFlags flags)
Definition Unit.h:997
void RemoveAurasDueToSpell(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, uint8 reqEffMask=0, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition Unit.cpp:3807
DeathState getDeathState() const
Definition Unit.h:1251
bool HasUnitState(const uint32 f) const
Definition Unit.h:890
void SetStandState(UnitStandStateType state)
Definition Unit.cpp:10340
UnitStandStateType GetStandState() const
Definition Unit.h:1015
bool SetWaterWalking(bool enable)
Definition Unit.cpp:13397
uint8 GetLevel() const
Definition Unit.h:903
uint8 GetRace() const
Definition Unit.h:906
bool IsInCombat() const
Definition Unit.h:1158
void WorldRelocate(WorldLocation const &loc)
Definition Position.h:179
uint32 GetMapId() const
Definition Position.h:193
Map * GetMap() const
Definition Object.h:451
GameObject * FindNearestGameObjectOfType(GameobjectTypes type, float range) const
Definition Object.cpp:2153
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition Object.cpp:2833
std::string const & GetName() const
Definition Object.h:384
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
EquipmentSetInfo::EquipmentSetData Set
WorldPacket const * Write() override
WorldPacket const * Write() override
std::vector< std::string > const * Text
GuidSet _legitCharacters
void HandleCharEnumOpcode(WorldPackets::Character::EnumCharacters &enumCharacters)
void SetPlayer(Player *player)
void HandleOpeningCinematic(WorldPackets::Misc::OpeningCinematic &packet)
void HandleEquipmentSetUse(WorldPacket &recvData)
void HandlePlayerLoginOpcode(WorldPacket &recvPacket)
void HandleTutorialFlag(WorldPackets::Misc::TutorialSetFlag &packet)
void HandleAlterAppearance(WorldPacket &recvData)
void HandleCharRaceOrFactionChangeCallback(std::shared_ptr< WorldPackets::Character::CharRaceOrFactionChangeInfo > factionChangeInfo, PreparedQueryResult result)
void HandleSetFactionAtWar(WorldPacket &recvData)
void SendNotification(char const *format,...) ATTR_PRINTF(2
void SendPacket(WorldPacket const *packet)
Send a packet to the client.
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
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)
void HandleTutorialClear(WorldPackets::Misc::TutorialClear &tutorialClear)
SQLQueryHolderCallback & AddQueryHolderCallback(SQLQueryHolderCallback &&callback)
bool IsLegitCharacterForAccount(ObjectGuid lowGUID)
std::string const & GetRemoteAddress() const
void HandlePlayerLogin(LoginQueryHolder const &holder)
void HandleCharEnum(PreparedQueryResult result)
void HandleTutorialReset(WorldPackets::Misc::TutorialReset &tutorialReset)
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)
uint8 GetExpansion() const
void HandleRemoveGlyph(WorldPacket &recvData)
void HandleSetPlayerDeclinedNames(WorldPacket &recvData)
void SendAccountDataTimes(uint32 mask)
void SendCharFactionChange(ResponseCodes result, WorldPackets::Character::CharRaceOrFactionChangeInfo const *factionChangeInfo)
void HandleEquipmentSetSave(WorldPackets::EquipmentSet::SaveEquipmentSet &saveEquipmentSet)
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)
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:901
Realm realm
Definition World.cpp:3610
@ CONFIG_CHARACTER_CREATING_DISABLED_CLASSMASK
Definition World.h:231
@ CONFIG_CHARACTER_CREATING_DISABLED
Definition World.h:229
@ CONFIG_CHARACTER_CREATING_DISABLED_RACEMASK
Definition World.h:230
@ CONFIG_DEATH_KNIGHTS_PER_REALM
Definition World.h:234
@ CONFIG_ENABLE_SINFO_LOGIN
Definition World.h:333
@ CONFIG_MAX_PLAYER_LEVEL
Definition World.h:237
@ CONFIG_CHARACTERS_PER_ACCOUNT
Definition World.h:232
@ CONFIG_CHARACTER_CREATING_MIN_LEVEL_FOR_DEATH_KNIGHT
Definition World.h:235
@ CONFIG_SKIP_CINEMATICS
Definition World.h:236
@ CONFIG_CHARACTERS_PER_REALM
Definition World.h:233
@ 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]
std::array< ObjectGuid, EQUIPMENT_SET_SLOTS > Pieces
uint32 IgnoreMask
Mask of EquipmentSlot.
static ObjectGuid const IgnoredSlot
struct GameObjectTemplate::@191::@219 barberChair
PlayerCreateInfoSpells castSpells
Definition ObjectMgr.h:688
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