TrinityCore
cs_character.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/* ScriptData
19Name: character_commandscript
20%Complete: 100
21Comment: All character related commands
22Category: commandscripts
23EndScriptData */
24
25#include "ScriptMgr.h"
26#include "AccountMgr.h"
27#include "CharacterCache.h"
28#include "Chat.h"
29#include "ChatCommand.h"
30#include "DatabaseEnv.h"
31#include "DB2Stores.h"
32#include "Log.h"
33#include "ObjectMgr.h"
34#include "Player.h"
35#include "PlayerDump.h"
36#include "ReputationMgr.h"
37#include "World.h"
38#include "WorldSession.h"
39#include <sstream>
40
41using namespace Trinity::ChatCommands;
42
44{
45public:
46 character_commandscript() : CommandScript("character_commandscript") { }
47
49 {
50 static ChatCommandTable pdumpCommandTable =
51 {
55 };
56 static ChatCommandTable characterDeletedCommandTable =
57 {
62 };
63
64 static ChatCommandTable characterCommandTable =
65 {
70 { "deleted", characterDeletedCommandTable },
76 };
77
78 static ChatCommandTable commandTable =
79 {
80 { "character", characterCommandTable },
81 { "levelup", HandleLevelUpCommand, rbac::RBAC_PERM_COMMAND_LEVELUP, Console::No },
82 { "pdump", pdumpCommandTable },
83 };
84 return commandTable;
85 }
86
87 // Stores informations about a deleted character
89 {
91 std::string name;
93 std::string accountName;
94 time_t deleteDate;
95 };
96
97 typedef std::list<DeletedInfo> DeletedInfoList;
98
106 static bool GetDeletedCharacterInfoList(DeletedInfoList& foundList, std::string& searchString)
107 {
108 PreparedQueryResult result;
110 if (!searchString.empty())
111 {
112 // search by GUID
113 if (Optional<uint64> guidValue = Trinity::StringTo<uint64>(searchString))
114 {
115 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_DEL_INFO_BY_GUID);
116 stmt->setUInt64(0, *guidValue);
117 result = CharacterDatabase.Query(stmt);
118 }
119 // search by name
120 else
121 {
122 if (!normalizePlayerName(searchString))
123 return false;
124
125 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_DEL_INFO_BY_NAME);
126 stmt->setString(0, searchString);
127 result = CharacterDatabase.Query(stmt);
128 }
129 }
130 else
131 {
132 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_DEL_INFO);
133 result = CharacterDatabase.Query(stmt);
134 }
135
136 if (result)
137 {
138 do
139 {
140 Field* fields = result->Fetch();
141
142 DeletedInfo info;
143
144 info.guid = ObjectGuid::Create<HighGuid::Player>(fields[0].GetUInt64());
145 info.name = fields[1].GetString();
146 info.accountId = fields[2].GetUInt32();
147
148 // account name will be empty for nonexisting account
150 info.deleteDate = fields[3].GetInt64();
151 foundList.push_back(info);
152 }
153 while (result->NextRow());
154 }
155
156 return true;
157 }
158
169 static void HandleCharacterDeletedListHelper(DeletedInfoList const& foundList, ChatHandler* handler)
170 {
171 if (!handler->GetSession())
172 {
176 }
177
178 for (DeletedInfoList::const_iterator itr = foundList.begin(); itr != foundList.end(); ++itr)
179 {
180 std::string dateStr = TimeToTimestampStr(itr->deleteDate);
181
182 if (!handler->GetSession())
184 itr->guid.ToString().c_str(), itr->name.c_str(), itr->accountName.empty() ? "<Not existing>" : itr->accountName.c_str(),
185 itr->accountId, dateStr.c_str());
186 else
188 itr->guid.ToString().c_str(), itr->name.c_str(), itr->accountName.empty() ? "<Not existing>" : itr->accountName.c_str(),
189 itr->accountId, dateStr.c_str());
190 }
191
192 if (!handler->GetSession())
194 }
195
206 static void HandleCharacterDeletedRestoreHelper(DeletedInfo const& delInfo, ChatHandler* handler)
207 {
208 if (delInfo.accountName.empty()) // account does not exist
209 {
210 handler->PSendSysMessage(LANG_CHARACTER_DELETED_SKIP_ACCOUNT, delInfo.name.c_str(), delInfo.guid.ToString().c_str(), delInfo.accountId);
211 return;
212 }
213
214 // check character count
216 if (charcount >= sWorld->getIntConfig(CONFIG_CHARACTERS_PER_REALM))
217 {
218 handler->PSendSysMessage(LANG_CHARACTER_DELETED_SKIP_FULL, delInfo.name.c_str(), delInfo.guid.ToString().c_str(), delInfo.accountId);
219 return;
220 }
221
222 if (!sCharacterCache->GetCharacterGuidByName(delInfo.name).IsEmpty())
223 {
224 handler->PSendSysMessage(LANG_CHARACTER_DELETED_SKIP_NAME, delInfo.name.c_str(), delInfo.guid.ToString().c_str(), delInfo.accountId);
225 return;
226 }
227
229 stmt->setString(0, delInfo.name);
230 stmt->setUInt32(1, delInfo.accountId);
231 stmt->setUInt64(2, delInfo.guid.GetCounter());
232 CharacterDatabase.Execute(stmt);
233
234 sCharacterCache->UpdateCharacterInfoDeleted(delInfo.guid, false, delInfo.name);
235 }
236
238 {
239 if (!player)
240 player = PlayerIdentifier::FromTargetOrSelf(handler);
241 if (!player || !player->IsConnected())
242 {
244 handler->SetSentErrorMessage(true);
245 return false;
246 }
247
248 Player const* target = player->GetConnectedPlayer();
249
250 LocaleConstant loc = handler->GetSessionDbcLocale();
251 char const* knownStr = handler->GetTrinityString(LANG_KNOWN);
252
253 // Search in CharTitles.dbc
254 for (uint32 id = 0; id < sCharTitlesStore.GetNumRows(); id++)
255 {
256 CharTitlesEntry const* titleInfo = sCharTitlesStore.LookupEntry(id);
257
258 if (titleInfo && target->HasTitle(titleInfo))
259 {
260 char const* name = target->GetNativeGender() == GENDER_MALE ? titleInfo->Name[loc] : titleInfo->Name1[loc];
261 if (!*name)
262 name = (target->GetNativeGender() == GENDER_MALE ? titleInfo->Name[sWorld->GetDefaultDbcLocale()] : titleInfo->Name1[sWorld->GetDefaultDbcLocale()]);
263 if (!*name)
264 continue;
265
266 char const* activeStr = "";
267 if (*target->m_playerData->PlayerTitle == titleInfo->MaskID)
268 activeStr = handler->GetTrinityString(LANG_ACTIVE);
269
270 std::string titleName = fmt::sprintf(name, player->GetName());
271
272 // send title in "id (idx:idx) - [namedlink locale]" format
273 if (handler->GetSession())
274 handler->PSendSysMessage(LANG_TITLE_LIST_CHAT, id, titleInfo->MaskID, id, titleName.c_str(), localeNames[loc], knownStr, activeStr);
275 else
276 handler->PSendSysMessage(LANG_TITLE_LIST_CONSOLE, id, titleInfo->MaskID, name, localeNames[loc], knownStr, activeStr);
277 }
278 }
279
280 return true;
281 }
282
283 //rename characters
285 {
286 if (!player && newNameV)
287 return false;
288
289 if (!player)
290 player = PlayerIdentifier::FromTarget(handler);
291 if (!player)
292 return false;
293
294 if (handler->HasLowerSecurity(nullptr, player->GetGUID()))
295 return false;
296
297 if (newNameV)
298 {
299 std::string newName{ *newNameV };
300 if (!normalizePlayerName(newName))
301 {
303 handler->SetSentErrorMessage(true);
304 return false;
305 }
306
307 if (ObjectMgr::CheckPlayerName(newName, player->IsConnected() ? player->GetConnectedPlayer()->GetSession()->GetSessionDbcLocale() : sWorld->GetDefaultDbcLocale(), true) != CHAR_NAME_SUCCESS)
308 {
310 handler->SetSentErrorMessage(true);
311 return false;
312 }
313
314 if (WorldSession* session = handler->GetSession())
315 {
316 if (!session->HasPermission(rbac::RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_RESERVEDNAME) && sObjectMgr->IsReservedName(newName))
317 {
319 handler->SetSentErrorMessage(true);
320 return false;
321 }
322 }
323
325 stmt->setString(0, newName);
326 PreparedQueryResult result = CharacterDatabase.Query(stmt);
327 if (result)
328 {
329 handler->PSendSysMessage(LANG_RENAME_PLAYER_ALREADY_EXISTS, newName.c_str());
330 handler->SetSentErrorMessage(true);
331 return false;
332 }
333
334 // Remove declined name from db
335 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_DECLINED_NAME);
336 stmt->setUInt64(0, player->GetGUID().GetCounter());
337 CharacterDatabase.Execute(stmt);
338
339 if (Player* target = player->GetConnectedPlayer())
340 {
341 target->SetName(newName);
342
343 if (WorldSession* session = target->GetSession())
344 session->KickPlayer("HandleCharacterRenameCommand GM Command renaming character");
345 }
346 else
347 {
348 stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_NAME_BY_GUID);
349 stmt->setString(0, newName);
350 stmt->setUInt64(1, player->GetGUID().GetCounter());
351 CharacterDatabase.Execute(stmt);
352 }
353
354 sCharacterCache->UpdateCharacterData(*player, newName);
355
356 handler->PSendSysMessage(LANG_RENAME_PLAYER_WITH_NEW_NAME, player->GetName().c_str(), newName.c_str());
357
358 if (WorldSession* session = handler->GetSession())
359 {
360 if (Player* player = session->GetPlayer())
361 sLog->OutCommand(session->GetAccountId(), "GM {} (Account: {}) forced rename {} to player {} (Account: {})", player->GetName(), session->GetAccountId(), newName, player->GetName(), sCharacterCache->GetCharacterAccountIdByGuid(player->GetGUID()));
362 }
363 else
364 sLog->OutCommand(0, "CONSOLE forced rename '{}' to '{}' ({})", player->GetName(), newName, player->GetGUID().ToString());
365 }
366 else
367 {
368 if (Player* target = player->GetConnectedPlayer())
369 {
370 handler->PSendSysMessage(LANG_RENAME_PLAYER, handler->GetNameLink(target).c_str());
371 target->SetAtLoginFlag(AT_LOGIN_RENAME);
372 }
373 else
374 {
375 // check offline security
376 if (handler->HasLowerSecurity(nullptr, player->GetGUID()))
377 return false;
378
379 handler->PSendSysMessage(LANG_RENAME_PLAYER_GUID, handler->playerLink(*player).c_str(), player->GetGUID().ToString().c_str());
380
383 stmt->setUInt64(1, player->GetGUID().GetCounter());
384 CharacterDatabase.Execute(stmt);
385 }
386 }
387
388 return true;
389 }
390
391 // customize characters
393 {
394 if (!player)
395 player = PlayerIdentifier::FromTarget(handler);
396 if (!player)
397 return false;
398
399 if (Player* target = player->GetConnectedPlayer())
400 {
401 handler->PSendSysMessage(LANG_CUSTOMIZE_PLAYER, handler->GetNameLink(target).c_str());
402 target->SetAtLoginFlag(AT_LOGIN_CUSTOMIZE);
403 }
404 else
405 {
406 handler->PSendSysMessage(LANG_CUSTOMIZE_PLAYER_GUID, handler->playerLink(*player).c_str(), player->GetGUID().ToString().c_str());
408 stmt->setUInt16(0, static_cast<uint16>(AT_LOGIN_CUSTOMIZE));
409 stmt->setUInt64(1, player->GetGUID().GetCounter());
410 CharacterDatabase.Execute(stmt);
411 }
412
413 return true;
414 }
415
417 {
418 if (!player)
419 player = PlayerIdentifier::FromTarget(handler);
420 if (!player)
421 return false;
422
423 if (Player* target = player->GetConnectedPlayer())
424 {
425 handler->PSendSysMessage(LANG_CUSTOMIZE_PLAYER, handler->GetNameLink(target).c_str());
426 target->SetAtLoginFlag(AT_LOGIN_CHANGE_FACTION);
427 }
428 else
429 {
430 handler->PSendSysMessage(LANG_CUSTOMIZE_PLAYER_GUID, handler->playerLink(*player).c_str(), player->GetGUID().ToString().c_str());
433 stmt->setUInt64(1, player->GetGUID().GetCounter());
434 CharacterDatabase.Execute(stmt);
435 }
436
437 return true;
438 }
439
441 {
442 if (!player)
443 player = PlayerIdentifier::FromTarget(handler);
444 if (!player)
445 return false;
446
447 if (Player* target = player->GetConnectedPlayer())
448 {
449 handler->PSendSysMessage(LANG_CUSTOMIZE_PLAYER, handler->GetNameLink(target).c_str());
450 target->SetAtLoginFlag(AT_LOGIN_CHANGE_RACE);
451 }
452 else
453 {
454 handler->PSendSysMessage(LANG_CUSTOMIZE_PLAYER_GUID, handler->playerLink(*player).c_str(), player->GetGUID().ToString().c_str());
457 stmt->setUInt64(1, player->GetGUID().GetCounter());
458 CharacterDatabase.Execute(stmt);
459 }
460
461 return true;
462 }
463
465 {
466 if (!player)
467 player = PlayerIdentifier::FromTarget(handler);
468 if (!player)
469 return false;
470
471 CharacterCacheEntry const* characterInfo = sCharacterCache->GetCharacterCacheByGuid(player->GetGUID());
472 if (!characterInfo)
473 {
475 handler->SetSentErrorMessage(true);
476 return false;
477 }
478
479 uint32 oldAccountId = characterInfo->AccountId;
480 // nothing to do :)
481 if (newAccount.GetID() == oldAccountId)
482 return true;
483
484 if (uint32 charCount = AccountMgr::GetCharactersCount(newAccount.GetID()))
485 {
486 if (charCount >= sWorld->getIntConfig(CONFIG_CHARACTERS_PER_REALM))
487 {
488 handler->PSendSysMessage(LANG_ACCOUNT_CHARACTER_LIST_FULL, newAccount.GetName().c_str(), newAccount.GetID());
489 handler->SetSentErrorMessage(true);
490 return false;
491 }
492 }
493
494 if (Player* onlinePlayer = player->GetConnectedPlayer())
495 onlinePlayer->GetSession()->KickPlayer("HandleCharacterChangeAccountCommand GM Command transferring character to another account");
496
498 charStmt->setUInt32(0, newAccount.GetID());
499 charStmt->setUInt64(1, player->GetGUID().GetCounter());
500 CharacterDatabase.DirectExecute(charStmt);
501
502 sWorld->UpdateRealmCharCount(oldAccountId);
503 sWorld->UpdateRealmCharCount(newAccount.GetID());
504
505 sCharacterCache->UpdateCharacterAccountId(*player, newAccount.GetID());
506
507 handler->PSendSysMessage(LANG_CHANGEACCOUNT_SUCCESS, player->GetName().c_str(), newAccount.GetName().c_str());
508
509 std::string logString = Trinity::StringFormat("changed ownership of player {} ({}) from account {} to account {}", player->GetName(), player->GetGUID().ToString(), oldAccountId, newAccount.GetID());
510 if (WorldSession* session = handler->GetSession())
511 {
512 if (Player* player = session->GetPlayer())
513 sLog->OutCommand(session->GetAccountId(), "GM {} (Account: {}) {}", player->GetName(), session->GetAccountId(), logString);
514 }
515 else
516 sLog->OutCommand(0, "{} {}", handler->GetTrinityString(LANG_CONSOLE), logString);
517 return true;
518 }
519
521 {
522 if (!player)
523 player = PlayerIdentifier::FromTargetOrSelf(handler);
524 if (!player || !player->IsConnected())
525 {
527 handler->SetSentErrorMessage(true);
528 return false;
529 }
530
531 Player const* target = player->GetConnectedPlayer();
532 LocaleConstant loc = handler->GetSessionDbcLocale();
533
534 FactionStateList const& targetFSL = target->GetReputationMgr().GetStateList();
535 for (FactionStateList::const_iterator itr = targetFSL.begin(); itr != targetFSL.end(); ++itr)
536 {
537 FactionState const& faction = itr->second;
538 FactionEntry const* factionEntry = sFactionStore.LookupEntry(faction.ID);
539 char const* factionName = factionEntry ? factionEntry->Name[loc] : "#Not found#";
540 std::string rankName = target->GetReputationMgr().GetReputationRankName(factionEntry);
541 std::ostringstream ss;
542 if (handler->GetSession())
543 ss << faction.ID << " - |cffffffff|Hfaction:" << faction.ID << "|h[" << factionName << ' ' << localeNames[loc] << "]|h|r";
544 else
545 ss << faction.ID << " - " << factionName << ' ' << localeNames[loc];
546
547 ss << ' ' << rankName << " (" << target->GetReputationMgr().GetReputation(factionEntry) << ')';
548
552 ss << handler->GetTrinityString(LANG_FACTION_ATWAR);
561
562 handler->SendSysMessage(ss.str().c_str());
563 }
564
565 return true;
566 }
567
579 {
580 std::string needle;
581 if (needleStr)
582 needle.assign(*needleStr);
583 DeletedInfoList foundList;
584 if (!GetDeletedCharacterInfoList(foundList, needle))
585 return false;
586
587 // if no characters have been found, output a warning
588 if (foundList.empty())
589 {
591 handler->SetSentErrorMessage(true);
592 return false;
593 }
594
595 HandleCharacterDeletedListHelper(foundList, handler);
596
597 return true;
598 }
599
611 static bool HandleCharacterDeletedRestoreCommand(ChatHandler* handler, std::string needle, Optional<std::string_view> newCharName, Optional<AccountIdentifier> newAccount)
612 {
613 DeletedInfoList foundList;
614 if (!GetDeletedCharacterInfoList(foundList, needle))
615 return false;
616
617 if (foundList.empty())
618 {
620 handler->SetSentErrorMessage(true);
621 return false;
622 }
623
625 HandleCharacterDeletedListHelper(foundList, handler);
626
627 if (!newCharName)
628 {
629 // Drop nonexisting account cases
630 for (DeletedInfoList::iterator itr = foundList.begin(); itr != foundList.end(); ++itr)
632 return true;
633 }
634
635 if (foundList.size() == 1)
636 {
637 std::string newName{ *newCharName };
638 DeletedInfo delInfo = foundList.front();
639
640 // update name
641 delInfo.name = newName;
642
643 // if new account provided update deleted info
644 if (newAccount)
645 {
646 delInfo.accountId = newAccount->GetID();
647 delInfo.accountName = newAccount->GetName();
648 }
649
650 HandleCharacterDeletedRestoreHelper(delInfo, handler);
651 return true;
652 }
653
655 handler->SetSentErrorMessage(true);
656 return false;
657 }
658
669 static bool HandleCharacterDeletedDeleteCommand(ChatHandler* handler, std::string needle)
670 {
671 DeletedInfoList foundList;
672 if (!GetDeletedCharacterInfoList(foundList, needle))
673 return false;
674
675 if (foundList.empty())
676 {
678 handler->SetSentErrorMessage(true);
679 return false;
680 }
681
683 HandleCharacterDeletedListHelper(foundList, handler);
684
685 // Call the appropriate function to delete them (current account for deleted characters is 0)
686 for (DeletedInfoList::const_iterator itr = foundList.begin(); itr != foundList.end(); ++itr)
687 Player::DeleteFromDB(itr->guid, 0, false, true);
688
689 return true;
690 }
691
704 {
705 int32 keepDays = static_cast<int32>(sWorld->getIntConfig(CONFIG_CHARDELETE_KEEP_DAYS));
706
707 if (days)
708 keepDays = static_cast<int32>(*days);
709 else if (keepDays <= 0) // config option value 0 -> disabled and can't be used
710 return false;
711
712 Player::DeleteOldCharacters(static_cast<uint32>(keepDays));
713
714 return true;
715 }
716
718 {
719 uint32 accountId;
720 if (Player* target = player.GetConnectedPlayer())
721 {
722 accountId = target->GetSession()->GetAccountId();
723 target->GetSession()->KickPlayer("HandleCharacterEraseCommand GM Command deleting character");
724 }
725 else
726 accountId = sCharacterCache->GetCharacterAccountIdByGuid(player);
727
728 std::string accountName;
729 AccountMgr::GetName(accountId, accountName);
730
731 Player::DeleteFromDB(player, accountId, true, true);
732 handler->PSendSysMessage(LANG_CHARACTER_DELETED, player.GetName().c_str(), player.GetGUID().ToString().c_str(), accountName.c_str(), accountId);
733
734 return true;
735 }
736
738 {
739 if (!player)
740 player = PlayerIdentifier::FromTargetOrSelf(handler);
741 if (!player)
742 return false;
743
744 uint8 oldlevel = static_cast<uint8>(player->IsConnected() ? player->GetConnectedPlayer()->GetLevel() : sCharacterCache->GetCharacterLevelByGuid(*player));
745
746 if (newlevel < 1)
747 newlevel = 1;
748
749 if (newlevel > static_cast<int16>(STRONG_MAX_LEVEL))
750 newlevel = static_cast<int16>(STRONG_MAX_LEVEL);
751
752 if (Player* target = player->GetConnectedPlayer())
753 {
754 target->GiveLevel(static_cast<uint8>(newlevel));
755 target->InitTalentForLevel();
756 target->SetXP(0);
757
758 if (handler->needReportToTarget(target))
759 {
760 if (oldlevel == newlevel)
761 ChatHandler(target->GetSession()).PSendSysMessage(LANG_YOURS_LEVEL_PROGRESS_RESET, handler->GetNameLink().c_str());
762 else if (oldlevel < static_cast<uint8>(newlevel))
763 ChatHandler(target->GetSession()).PSendSysMessage(LANG_YOURS_LEVEL_UP, handler->GetNameLink().c_str(), newlevel);
764 else // if (oldlevel > newlevel)
765 ChatHandler(target->GetSession()).PSendSysMessage(LANG_YOURS_LEVEL_DOWN, handler->GetNameLink().c_str(), newlevel);
766 }
767 }
768 else
769 {
770 // Update level and reset XP, everything else will be updated at login
772 stmt->setUInt8(0, static_cast<uint8>(newlevel));
773 stmt->setUInt64(1, player->GetGUID().GetCounter());
774 CharacterDatabase.Execute(stmt);
775 }
776
777 if (!handler->GetSession() || (handler->GetSession()->GetPlayer() != player->GetConnectedPlayer())) // including chr == NULL
778 handler->PSendSysMessage(LANG_YOU_CHANGE_LVL, handler->playerLink(*player).c_str(), newlevel);
779
780 return true;
781 }
782
784 {
785 if (!player)
786 player = PlayerIdentifier::FromTargetOrSelf(handler);
787 if (!player)
788 return false;
789
790 uint8 oldlevel = static_cast<uint8>(player->IsConnected() ? player->GetConnectedPlayer()->GetLevel() : sCharacterCache->GetCharacterLevelByGuid(*player));
791 int16 newlevel = static_cast<int16>(oldlevel) + level;
792
793 if (newlevel < 1)
794 newlevel = 1;
795
796 if (newlevel > static_cast<int16>(STRONG_MAX_LEVEL))
797 newlevel = static_cast<int16>(STRONG_MAX_LEVEL);
798
799 if (Player* target = player->GetConnectedPlayer())
800 {
801 target->GiveLevel(static_cast<uint8>(newlevel));
802 target->InitTalentForLevel();
803 target->SetXP(0);
804
805 if (handler->needReportToTarget(target))
806 {
807 if (oldlevel == newlevel)
808 ChatHandler(target->GetSession()).PSendSysMessage(LANG_YOURS_LEVEL_PROGRESS_RESET, handler->GetNameLink().c_str());
809 else if (oldlevel < static_cast<uint8>(newlevel))
810 ChatHandler(target->GetSession()).PSendSysMessage(LANG_YOURS_LEVEL_UP, handler->GetNameLink().c_str(), newlevel);
811 else // if (oldlevel > newlevel)
812 ChatHandler(target->GetSession()).PSendSysMessage(LANG_YOURS_LEVEL_DOWN, handler->GetNameLink().c_str(), newlevel);
813 }
814 }
815 else
816 {
817 // Update level and reset XP, everything else will be updated at login
819 stmt->setUInt8(0, static_cast<uint8>(newlevel));
820 stmt->setUInt64(1, player->GetGUID().GetCounter());
821 CharacterDatabase.Execute(stmt);
822 }
823
824 if (!handler->GetSession() || (handler->GetSession()->GetPlayer() != player->GetConnectedPlayer())) // including chr == NULL
825 handler->PSendSysMessage(LANG_YOU_CHANGE_LVL, handler->playerLink(*player).c_str(), newlevel);
826
827 return true;
828 }
829
831 {
832 std::string name;
833 if (!ValidatePDumpTarget(handler, name, characterName, characterGUID))
834 return false;
835
836 std::string dump;
837 switch (PlayerDumpWriter().WriteDumpToString(dump, player.GetGUID().GetCounter()))
838 {
839 case DUMP_SUCCESS:
840 break;
843 handler->SetSentErrorMessage(true);
844 return false;
845 case DUMP_FILE_OPEN_ERROR: // this error code should not happen
846 default:
848 handler->SetSentErrorMessage(true);
849 return false;
850 }
851
852 switch (PlayerDumpReader().LoadDumpFromString(dump, account, name, characterGUID.value_or(0)))
853 {
854 case DUMP_SUCCESS:
855 break;
857 handler->PSendSysMessage(LANG_ACCOUNT_CHARACTER_LIST_FULL, account.GetName().c_str(), account.GetID());
858 handler->SetSentErrorMessage(true);
859 return false;
860 case DUMP_FILE_OPEN_ERROR: // this error code should not happen
861 case DUMP_FILE_BROKEN: // this error code should not happen
862 default:
864 handler->SetSentErrorMessage(true);
865 return false;
866 }
867
868 // ToDo: use a new trinity_string for this commands
870
871 return true;
872 }
873
874 static bool HandlePDumpLoadCommand(ChatHandler* handler, std::string fileName, AccountIdentifier account, Optional<std::string_view> characterName, Optional<ObjectGuid::LowType> characterGUID)
875 {
876 std::string name;
877 if (!ValidatePDumpTarget(handler, name, characterName, characterGUID))
878 return false;
879
880 switch (PlayerDumpReader().LoadDumpFromFile(fileName, account, name, characterGUID.value_or(0)))
881 {
882 case DUMP_SUCCESS:
884 break;
886 handler->PSendSysMessage(LANG_FILE_OPEN_FAIL, fileName.c_str());
887 handler->SetSentErrorMessage(true);
888 return false;
889 case DUMP_FILE_BROKEN:
890 handler->PSendSysMessage(LANG_DUMP_BROKEN, fileName.c_str());
891 handler->SetSentErrorMessage(true);
892 return false;
894 handler->PSendSysMessage(LANG_ACCOUNT_CHARACTER_LIST_FULL, account.GetName().c_str(), account.GetID());
895 handler->SetSentErrorMessage(true);
896 return false;
897 default:
899 handler->SetSentErrorMessage(true);
900 return false;
901 }
902
903 return true;
904 }
905
906 static bool ValidatePDumpTarget(ChatHandler* handler, std::string& name, Optional<std::string_view> characterName, Optional<ObjectGuid::LowType> characterGUID)
907 {
908 if (characterName)
909 {
910 name.assign(*characterName);
911 // normalize the name if specified and check if it exists
912 if (!normalizePlayerName(name))
913 {
915 handler->SetSentErrorMessage(true);
916 return false;
917 }
918
919 if (ObjectMgr::CheckPlayerName(name, sWorld->GetDefaultDbcLocale(), true) != CHAR_NAME_SUCCESS)
920 {
922 handler->SetSentErrorMessage(true);
923 return false;
924 }
925 }
926
927 if (characterGUID)
928 {
929 if (sCharacterCache->GetCharacterCacheByGuid(ObjectGuid::Create<HighGuid::Player>(*characterGUID)))
930 {
931 handler->PSendSysMessage(LANG_CHARACTER_GUID_IN_USE, *characterGUID);
932 handler->SetSentErrorMessage(true);
933 return false;
934 }
935 }
936
937 return true;
938 }
939
940 static bool HandlePDumpWriteCommand(ChatHandler* handler, std::string fileName, PlayerIdentifier player)
941 {
942 switch (PlayerDumpWriter().WriteDumpToFile(fileName, player.GetGUID().GetCounter()))
943 {
944 case DUMP_SUCCESS:
946 break;
948 handler->PSendSysMessage(LANG_FILE_OPEN_FAIL, fileName.c_str());
949 handler->SetSentErrorMessage(true);
950 return false;
953 handler->SetSentErrorMessage(true);
954 return false;
955 default:
957 handler->SetSentErrorMessage(true);
958 return false;
959 }
960
961 return true;
962 }
963};
964
966{
968}
#define sCharacterCache
@ CHAR_SEL_CHECK_NAME
@ CHAR_UPD_LEVEL
@ CHAR_SEL_CHAR_DEL_INFO_BY_NAME
@ CHAR_SEL_CHAR_DEL_INFO
@ CHAR_DEL_CHAR_DECLINED_NAME
@ CHAR_UPD_NAME_BY_GUID
@ CHAR_SEL_CHAR_DEL_INFO_BY_GUID
@ CHAR_UPD_ACCOUNT_BY_GUID
@ CHAR_UPD_ADD_AT_LOGIN_FLAG
@ CHAR_UPD_RESTORE_DELETE_INFO
char const * localeNames[TOTAL_LOCALES]
Definition: Common.cpp:20
LocaleConstant
Definition: Common.h:48
DB2Storage< CharTitlesEntry > sCharTitlesStore("CharTitles.db2", &CharTitlesLoadInfo::Instance)
DB2Storage< FactionEntry > sFactionStore("Faction.db2", &FactionLoadInfo::Instance)
@ STRONG_MAX_LEVEL
Definition: DBCEnums.h:55
std::shared_ptr< PreparedResultSet > PreparedQueryResult
DatabaseWorkerPool< CharacterDatabaseConnection > CharacterDatabase
Accessor to the character database.
Definition: DatabaseEnv.cpp:21
uint8_t uint8
Definition: Define.h:144
int16_t int16
Definition: Define.h:139
int32_t int32
Definition: Define.h:138
uint16_t uint16
Definition: Define.h:143
uint32_t uint32
Definition: Define.h:142
@ LANG_FACTION_PEACE_FORCED
Definition: Language.h:370
@ LANG_CHARACTER_DELETED_SKIP_NAME
Definition: Language.h:859
@ LANG_CHARACTER_DELETED_LIST_LINE_CHAT
Definition: Language.h:860
@ LANG_RENAME_PLAYER
Definition: Language.h:302
@ LANG_FACTION_ATWAR
Definition: Language.h:369
@ LANG_CHARACTER_DELETED_ERR_RENAME
Definition: Language.h:856
@ LANG_CHARACTER_DELETED_LIST_HEADER
Definition: Language.h:850
@ LANG_KNOWN
Definition: Language.h:63
@ LANG_DUMP_BROKEN
Definition: Language.h:887
@ LANG_CHARACTER_DELETED_LIST_LINE_CONSOLE
Definition: Language.h:851
@ LANG_FACTION_INVISIBLE_FORCED
Definition: Language.h:372
@ LANG_COMMAND_EXPORT_DELETED_CHAR
Definition: Language.h:903
@ LANG_FILE_OPEN_FAIL
Definition: Language.h:885
@ LANG_CHARACTER_GUID_IN_USE
Definition: Language.h:890
@ LANG_CUSTOMIZE_PLAYER_GUID
Definition: Language.h:402
@ LANG_ACCOUNT_CHARACTER_LIST_FULL
Definition: Language.h:886
@ LANG_RENAME_PLAYER_WITH_NEW_NAME
Definition: Language.h:131
@ LANG_YOU_CHANGE_LVL
Definition: Language.h:163
@ LANG_TITLE_LIST_CHAT
Definition: Language.h:405
@ LANG_CHARACTER_DELETED_RESTORE
Definition: Language.h:854
@ LANG_CHARACTER_DELETED
Definition: Language.h:843
@ LANG_COMMAND_EXPORT_SUCCESS
Definition: Language.h:545
@ LANG_FACTION_HIDDEN
Definition: Language.h:371
@ LANG_CONSOLE
Definition: Language.h:1095
@ LANG_CUSTOMIZE_PLAYER
Definition: Language.h:401
@ LANG_ACTIVE
Definition: Language.h:67
@ LANG_PLAYER_NOT_FOUND
Definition: Language.h:567
@ LANG_CHARACTER_DELETED_SKIP_FULL
Definition: Language.h:858
@ LANG_CHARACTER_DELETED_LIST_EMPTY
Definition: Language.h:853
@ LANG_CHARACTER_DELETED_LIST_BAR
Definition: Language.h:852
@ LANG_BAD_VALUE
Definition: Language.h:149
@ LANG_TITLE_LIST_CONSOLE
Definition: Language.h:406
@ LANG_COMMAND_IMPORT_FAILED
Definition: Language.h:544
@ LANG_YOURS_LEVEL_UP
Definition: Language.h:638
@ LANG_YOURS_LEVEL_PROGRESS_RESET
Definition: Language.h:640
@ LANG_RESERVED_NAME
Definition: Language.h:208
@ LANG_COMMAND_EXPORT_FAILED
Definition: Language.h:546
@ LANG_FACTION_INACTIVE
Definition: Language.h:373
@ LANG_RENAME_PLAYER_ALREADY_EXISTS
Definition: Language.h:130
@ LANG_CHARACTER_DELETED_SKIP_ACCOUNT
Definition: Language.h:857
@ LANG_RENAME_PLAYER_GUID
Definition: Language.h:303
@ LANG_CHANGEACCOUNT_SUCCESS
Definition: Language.h:957
@ LANG_FACTION_VISIBLE
Definition: Language.h:368
@ LANG_YOURS_LEVEL_DOWN
Definition: Language.h:639
@ LANG_INVALID_CHARACTER_NAME
Definition: Language.h:888
@ LANG_COMMAND_IMPORT_SUCCESS
Definition: Language.h:543
@ LANG_CHARACTER_DELETED_DELETE
Definition: Language.h:855
#define sLog
Definition: Log.h:130
bool normalizePlayerName(std::string &name)
Definition: ObjectMgr.cpp:154
#define sObjectMgr
Definition: ObjectMgr.h:1946
std::optional< T > Optional
Optional helper class to wrap optional values within.
Definition: Optional.h:25
@ DUMP_FILE_OPEN_ERROR
Definition: PlayerDump.h:67
@ DUMP_CHARACTER_DELETED
Definition: PlayerDump.h:70
@ DUMP_SUCCESS
Definition: PlayerDump.h:66
@ DUMP_TOO_MANY_CHARS
Definition: PlayerDump.h:68
@ DUMP_FILE_BROKEN
Definition: PlayerDump.h:69
@ AT_LOGIN_CUSTOMIZE
Definition: Player.h:541
@ AT_LOGIN_RENAME
Definition: Player.h:538
@ AT_LOGIN_CHANGE_RACE
Definition: Player.h:545
@ AT_LOGIN_CHANGE_FACTION
Definition: Player.h:544
std::map< RepListID, FactionState > FactionStateList
Definition: ReputationMgr.h:63
@ GENDER_MALE
@ CHAR_NAME_SUCCESS
std::string TimeToTimestampStr(time_t t)
Definition: Util.cpp:290
static uint32 GetCharactersCount(uint32 accountId)
Definition: AccountMgr.cpp:409
static bool GetName(uint32 accountId, std::string &name)
Definition: AccountMgr.cpp:319
std::string playerLink(std::string const &name) const
Definition: Chat.cpp:602
WorldSession * GetSession()
Definition: Chat.h:42
virtual LocaleConstant GetSessionDbcLocale() const
Definition: Chat.cpp:592
virtual std::string GetNameLink() const
Definition: Chat.cpp:58
void PSendSysMessage(const char *fmt, Args &&... args)
Definition: Chat.h:57
bool HasLowerSecurity(Player *target, ObjectGuid guid, bool strong=false)
Definition: Chat.cpp:63
void SetSentErrorMessage(bool val)
Definition: Chat.h:114
virtual void SendSysMessage(std::string_view str, bool escapeCharacters=false)
Definition: Chat.cpp:113
virtual bool needReportToTarget(Player *chr) const
Definition: Chat.cpp:586
virtual char const * GetTrinityString(uint32 entry) const
Definition: Chat.cpp:48
constexpr bool HasFlag(T flag) const
Definition: EnumFlag.h:106
Class used to access individual fields of database query result.
Definition: Field.h:90
std::string GetString() const
Definition: Field.cpp:118
int64 GetInt64() const
Definition: Field.cpp:86
uint32 GetUInt32() const
Definition: Field.cpp:62
LowType GetCounter() const
Definition: ObjectGuid.h:293
std::string ToString() const
Definition: ObjectGuid.cpp:554
static ResponseCodes CheckPlayerName(std::string_view name, LocaleConstant locale, bool create=false)
Definition: ObjectMgr.cpp:8687
static void DeleteOldCharacters()
Definition: Player.cpp:4310
UF::UpdateField< UF::PlayerData, 0, TYPEID_PLAYER > m_playerData
Definition: Player.h:2863
Gender GetNativeGender() const override
Definition: Player.h:1217
bool HasTitle(uint32 bitIndex) const
Definition: Player.cpp:26268
static void DeleteFromDB(ObjectGuid playerguid, uint32 accountId, bool updateRealmChars=true, bool deleteFinally=false)
Definition: Player.cpp:3824
ReputationMgr & GetReputationMgr()
Definition: Player.h:2251
void setUInt8(const uint8 index, const uint8 value)
void setUInt32(const uint8 index, const uint32 value)
void setUInt16(const uint8 index, const uint16 value)
void setString(const uint8 index, const std::string &value)
void setUInt64(const uint8 index, const uint64 value)
std::string GetReputationRankName(FactionEntry const *factionEntry) const
FactionStateList const & GetStateList() const
Definition: ReputationMgr.h:89
int32 GetReputation(uint32 faction_id) const
Player session in the World.
Definition: WorldSession.h:963
Player * GetPlayer() const
static bool HandleCharacterDeletedListCommand(ChatHandler *handler, Optional< std::string_view > needleStr)
static bool HandlePDumpLoadCommand(ChatHandler *handler, std::string fileName, AccountIdentifier account, Optional< std::string_view > characterName, Optional< ObjectGuid::LowType > characterGUID)
static bool HandleLevelUpCommand(ChatHandler *handler, Optional< PlayerIdentifier > player, int16 level)
static bool GetDeletedCharacterInfoList(DeletedInfoList &foundList, std::string &searchString)
static bool HandleCharacterLevelCommand(ChatHandler *handler, Optional< PlayerIdentifier > player, int16 newlevel)
ChatCommandTable GetCommands() const override
static void HandleCharacterDeletedRestoreHelper(DeletedInfo const &delInfo, ChatHandler *handler)
static bool HandlePDumpCopyCommand(ChatHandler *handler, PlayerIdentifier player, AccountIdentifier account, Optional< std::string_view > characterName, Optional< ObjectGuid::LowType > characterGUID)
static bool HandleCharacterCustomizeCommand(ChatHandler *handler, Optional< PlayerIdentifier > player)
static bool HandleCharacterRenameCommand(ChatHandler *handler, Optional< PlayerIdentifier > player, Optional< std::string_view > newNameV)
static bool HandleCharacterDeletedDeleteCommand(ChatHandler *handler, std::string needle)
static bool HandleCharacterChangeRaceCommand(ChatHandler *handler, Optional< PlayerIdentifier > player)
static bool HandleCharacterDeletedOldCommand(ChatHandler *, Optional< uint16 > days)
static bool HandleCharacterChangeAccountCommand(ChatHandler *handler, Optional< PlayerIdentifier > player, AccountIdentifier newAccount)
static bool ValidatePDumpTarget(ChatHandler *handler, std::string &name, Optional< std::string_view > characterName, Optional< ObjectGuid::LowType > characterGUID)
static bool HandleCharacterTitlesCommand(ChatHandler *handler, Optional< PlayerIdentifier > player)
static void HandleCharacterDeletedListHelper(DeletedInfoList const &foundList, ChatHandler *handler)
static bool HandlePDumpWriteCommand(ChatHandler *handler, std::string fileName, PlayerIdentifier player)
static bool HandleCharacterReputationCommand(ChatHandler *handler, Optional< PlayerIdentifier > player)
static bool HandleCharacterEraseCommand(ChatHandler *handler, PlayerIdentifier player)
static bool HandleCharacterChangeFactionCommand(ChatHandler *handler, Optional< PlayerIdentifier > player)
static bool HandleCharacterDeletedRestoreCommand(ChatHandler *handler, std::string needle, Optional< std::string_view > newCharName, Optional< AccountIdentifier > newAccount)
std::list< DeletedInfo > DeletedInfoList
void AddSC_character_commandscript()
#define sWorld
Definition: World.h:931
@ CONFIG_CHARDELETE_KEEP_DAYS
Definition: World.h:369
@ CONFIG_CHARACTERS_PER_REALM
Definition: World.h:254
std::vector< ChatCommandBuilder > ChatCommandTable
Definition: ChatCommand.h:49
std::string StringFormat(FormatString< Args... > fmt, Args &&... args)
Default TC string format function.
Definition: StringFormat.h:38
@ RBAC_PERM_COMMAND_CHARACTER_CHANGERACE
Definition: RBAC.h:190
@ RBAC_PERM_COMMAND_PDUMP_COPY
Definition: RBAC.h:748
@ RBAC_PERM_COMMAND_CHARACTER_DELETED_OLD
Definition: RBAC.h:195
@ RBAC_PERM_COMMAND_LEVELUP
Definition: RBAC.h:201
@ RBAC_PERM_COMMAND_CHARACTER_LEVEL
Definition: RBAC.h:197
@ RBAC_PERM_COMMAND_CHARACTER_DELETED_DELETE
Definition: RBAC.h:192
@ RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_RESERVEDNAME
Definition: RBAC.h:70
@ RBAC_PERM_COMMAND_CHARACTER_CHANGEFACTION
Definition: RBAC.h:189
@ RBAC_PERM_COMMAND_CHARACTER_TITLES
Definition: RBAC.h:200
@ RBAC_PERM_COMMAND_CHARACTER_CUSTOMIZE
Definition: RBAC.h:188
@ RBAC_PERM_COMMAND_CHARACTER_CHANGEACCOUNT
Definition: RBAC.h:570
@ RBAC_PERM_COMMAND_CHARACTER_RENAME
Definition: RBAC.h:198
@ RBAC_PERM_COMMAND_CHARACTER_ERASE
Definition: RBAC.h:196
@ RBAC_PERM_COMMAND_PDUMP_LOAD
Definition: RBAC.h:203
@ RBAC_PERM_COMMAND_CHARACTER_REPUTATION
Definition: RBAC.h:199
@ RBAC_PERM_COMMAND_CHARACTER_DELETED_LIST
Definition: RBAC.h:193
@ RBAC_PERM_COMMAND_CHARACTER_DELETED_RESTORE
Definition: RBAC.h:194
@ RBAC_PERM_COMMAND_PDUMP_WRITE
Definition: RBAC.h:204
LocalizedString Name1
Definition: DB2Structure.h:589
LocalizedString Name
Definition: DB2Structure.h:588
LocalizedString Name
EnumFlag< ReputationFlags > Flags
Definition: ReputationMgr.h:58
std::string const & GetName() const
std::string const & GetName() const
std::string name
the character name
std::string accountName
the account name
time_t deleteDate
the date at which the character has been deleted
ObjectGuid guid
the GUID from the character