TrinityCore
Loading...
Searching...
No Matches
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 "DatabaseEnv.h"
30#include "DBCStores.h"
31#include "Log.h"
32#include "ObjectAccessor.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
40using namespace Trinity::ChatCommands;
41
43{
44public:
45 character_commandscript() : CommandScript("character_commandscript") { }
46
48 {
49 static ChatCommandTable pdumpCommandTable =
50 {
54 };
55 static ChatCommandTable characterDeletedCommandTable =
56 {
61 };
62
63 static ChatCommandTable characterCommandTable =
64 {
69 { "deleted", characterDeletedCommandTable },
75 };
76
77 static ChatCommandTable commandTable =
78 {
79 { "character", characterCommandTable },
80 { "levelup", HandleLevelUpCommand, rbac::RBAC_PERM_COMMAND_LEVELUP, Console::No },
81 { "pdump", pdumpCommandTable },
82 };
83 return commandTable;
84 }
85
86 // Stores informations about a deleted character
88 {
90 std::string name;
92 std::string accountName;
93 time_t deleteDate;
94 };
95
96 typedef std::list<DeletedInfo> DeletedInfoList;
97
105 static bool GetDeletedCharacterInfoList(DeletedInfoList& foundList, std::string& searchString)
106 {
107 PreparedQueryResult result;
109 if (!searchString.empty())
110 {
111 // search by GUID
112 if (Optional<uint32> guidValue = Trinity::StringTo<uint64>(searchString))
113 {
114 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_DEL_INFO_BY_GUID);
115 stmt->setUInt32(0, *guidValue);
116 result = CharacterDatabase.Query(stmt);
117 }
118 // search by name
119 else
120 {
121 if (!normalizePlayerName(searchString))
122 return false;
123
124 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_DEL_INFO_BY_NAME);
125 stmt->setString(0, searchString);
126 result = CharacterDatabase.Query(stmt);
127 }
128 }
129 else
130 {
131 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_DEL_INFO);
132 result = CharacterDatabase.Query(stmt);
133 }
134
135 if (result)
136 {
137 do
138 {
139 Field* fields = result->Fetch();
140
141 DeletedInfo info;
142
143 info.guid = ObjectGuid::Create<HighGuid::Player>(fields[0].GetUInt32());
144 info.name = fields[1].GetString();
145 info.accountId = fields[2].GetUInt32();
146
147 // account name will be empty for nonexisting account
149 info.deleteDate = time_t(fields[3].GetUInt32());
150 foundList.push_back(info);
151 }
152 while (result->NextRow());
153 }
154
155 return true;
156 }
157
168 static void HandleCharacterDeletedListHelper(DeletedInfoList const& foundList, ChatHandler* handler)
169 {
170 if (!handler->GetSession())
171 {
175 }
176
177 for (DeletedInfoList::const_iterator itr = foundList.begin(); itr != foundList.end(); ++itr)
178 {
179 std::string dateStr = TimeToTimestampStr(itr->deleteDate);
180
181 if (!handler->GetSession())
183 itr->guid.ToString().c_str(), itr->name.c_str(), itr->accountName.empty() ? "<Not existing>" : itr->accountName.c_str(),
184 itr->accountId, dateStr.c_str());
185 else
187 itr->guid.ToString().c_str(), itr->name.c_str(), itr->accountName.empty() ? "<Not existing>" : itr->accountName.c_str(),
188 itr->accountId, dateStr.c_str());
189 }
190
191 if (!handler->GetSession())
193 }
194
205 static void HandleCharacterDeletedRestoreHelper(DeletedInfo const& delInfo, ChatHandler* handler)
206 {
207 if (delInfo.accountName.empty()) // account does not exist
208 {
209 handler->PSendSysMessage(LANG_CHARACTER_DELETED_SKIP_ACCOUNT, delInfo.name.c_str(), delInfo.guid.ToString().c_str(), delInfo.accountId);
210 return;
211 }
212
213 // check character count
215 if (charcount >= 10)
216 {
217 handler->PSendSysMessage(LANG_CHARACTER_DELETED_SKIP_FULL, delInfo.name.c_str(), delInfo.guid.ToString().c_str(), delInfo.accountId);
218 return;
219 }
220
221 if (!sCharacterCache->GetCharacterGuidByName(delInfo.name).IsEmpty())
222 {
223 handler->PSendSysMessage(LANG_CHARACTER_DELETED_SKIP_NAME, delInfo.name.c_str(), delInfo.guid.ToString().c_str(), delInfo.accountId);
224 return;
225 }
226
228 stmt->setString(0, delInfo.name);
229 stmt->setUInt32(1, delInfo.accountId);
230 stmt->setUInt32(2, delInfo.guid.GetCounter());
231 CharacterDatabase.Execute(stmt);
232
233 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_NAME_DATA);
234 stmt->setUInt32(0, delInfo.guid.GetCounter());
235 if (PreparedQueryResult result = CharacterDatabase.Query(stmt))
236 sCharacterCache->AddCharacterCacheEntry(delInfo.guid, delInfo.accountId, delInfo.name, (*result)[2].GetUInt8(), (*result)[0].GetUInt8(), (*result)[1].GetUInt8(), (*result)[3].GetUInt8());
237 }
238
240 {
241 if (!player)
242 player = PlayerIdentifier::FromTargetOrSelf(handler);
243 if (!player || !player->IsConnected())
244 {
246 handler->SetSentErrorMessage(true);
247 return false;
248 }
249
250 Player const* target = player->GetConnectedPlayer();
251
252 LocaleConstant loc = handler->GetSessionDbcLocale();
253 char const* knownStr = handler->GetTrinityString(LANG_KNOWN);
254
255 // Search in CharTitles.dbc
256 for (uint32 id = 0; id < sCharTitlesStore.GetNumRows(); id++)
257 {
258 CharTitlesEntry const* titleInfo = sCharTitlesStore.LookupEntry(id);
259
260 if (titleInfo && target->HasTitle(titleInfo))
261 {
262 char const* name = target->GetNativeGender() == GENDER_MALE ? titleInfo->Name[loc] : titleInfo->Name1[loc];
263 if (!*name)
264 name = (target->GetNativeGender() == GENDER_MALE ? titleInfo->Name[sWorld->GetDefaultDbcLocale()] : titleInfo->Name1[sWorld->GetDefaultDbcLocale()]);
265 if (!*name)
266 continue;
267
268 char const* activeStr = "";
269 if (target->GetUInt32Value(PLAYER_CHOSEN_TITLE) == titleInfo->MaskID)
270 activeStr = handler->GetTrinityString(LANG_ACTIVE);
271
272 std::string titleName = ChatHandler::PGetParseString(name, player->GetName());
273
274 // send title in "id (idx:idx) - [namedlink locale]" format
275 if (handler->GetSession())
276 handler->PSendSysMessage(LANG_TITLE_LIST_CHAT, id, titleInfo->MaskID, id, titleName.c_str(), localeNames[loc], knownStr, activeStr);
277 else
278 handler->PSendSysMessage(LANG_TITLE_LIST_CONSOLE, id, titleInfo->MaskID, name, localeNames[loc], knownStr, activeStr);
279 }
280 }
281
282 return true;
283 }
284
285 //rename characters
287 {
288 if (!player && newNameV)
289 return false;
290
291 if (!player)
292 player = PlayerIdentifier::FromTarget(handler);
293 if (!player)
294 return false;
295
296 if (handler->HasLowerSecurity(nullptr, player->GetGUID()))
297 return false;
298
299 if (newNameV)
300 {
301 std::string newName{ *newNameV };
302 if (!normalizePlayerName(newName))
303 {
305 handler->SetSentErrorMessage(true);
306 return false;
307 }
308
309 if (ObjectMgr::CheckPlayerName(newName, player->IsConnected() ? player->GetConnectedPlayer()->GetSession()->GetSessionDbcLocale() : sWorld->GetDefaultDbcLocale(), true) != CHAR_NAME_SUCCESS)
310 {
312 handler->SetSentErrorMessage(true);
313 return false;
314 }
315
316 if (WorldSession* session = handler->GetSession())
317 {
318 if (!session->HasPermission(rbac::RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_RESERVEDNAME) && sObjectMgr->IsReservedName(newName))
319 {
321 handler->SetSentErrorMessage(true);
322 return false;
323 }
324 }
325
327 stmt->setString(0, newName);
328 PreparedQueryResult result = CharacterDatabase.Query(stmt);
329 if (result)
330 {
331 handler->PSendSysMessage(LANG_RENAME_PLAYER_ALREADY_EXISTS, newName.c_str());
332 handler->SetSentErrorMessage(true);
333 return false;
334 }
335
336 // Remove declined name from db
337 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_DECLINED_NAME);
338 stmt->setUInt32(0, player->GetGUID().GetCounter());
339 CharacterDatabase.Execute(stmt);
340
341 if (Player* target = player->GetConnectedPlayer())
342 {
343 target->SetName(newName);
344
345 if (WorldSession* session = target->GetSession())
346 session->KickPlayer("HandleCharacterRenameCommand GM Command renaming character");
347 }
348 else
349 {
350 stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_NAME_BY_GUID);
351 stmt->setString(0, newName);
352 stmt->setUInt32(1, player->GetGUID().GetCounter());
353 CharacterDatabase.Execute(stmt);
354 }
355
356 sCharacterCache->UpdateCharacterData(*player, newName);
357
358 handler->PSendSysMessage(LANG_RENAME_PLAYER_WITH_NEW_NAME, player->GetName().c_str(), newName.c_str());
359
360 if (WorldSession* session = handler->GetSession())
361 {
362 if (Player* player = session->GetPlayer())
363 sLog->OutCommand(session->GetAccountId(), "GM {} (Account: {}) forced rename {} to player {} (Account: {})", player->GetName(), session->GetAccountId(), newName, player->GetName(), sCharacterCache->GetCharacterAccountIdByGuid(player->GetGUID()));
364 }
365 else
366 sLog->OutCommand(0, "CONSOLE forced rename '{}' to '{}' ({})", player->GetName(), newName, player->GetGUID().ToString());
367 }
368 else
369 {
370 if (Player* target = player->GetConnectedPlayer())
371 {
372 handler->PSendSysMessage(LANG_RENAME_PLAYER, handler->GetNameLink(target).c_str());
373 target->SetAtLoginFlag(AT_LOGIN_RENAME);
374 }
375 else
376 {
377 // check offline security
378 if (handler->HasLowerSecurity(nullptr, player->GetGUID()))
379 return false;
380
381 handler->PSendSysMessage(LANG_RENAME_PLAYER_GUID, handler->playerLink(*player).c_str(), player->GetGUID().ToString().c_str());
382
385 stmt->setUInt32(1, player->GetGUID().GetCounter());
386 CharacterDatabase.Execute(stmt);
387 }
388 }
389
390 return true;
391 }
392
393 // customize characters
395 {
396 if (!player)
397 player = PlayerIdentifier::FromTarget(handler);
398 if (!player)
399 return false;
400
401 if (Player* target = player->GetConnectedPlayer())
402 {
403 handler->PSendSysMessage(LANG_CUSTOMIZE_PLAYER, handler->GetNameLink(target).c_str());
404 target->SetAtLoginFlag(AT_LOGIN_CUSTOMIZE);
405 }
406 else
407 {
408 handler->PSendSysMessage(LANG_CUSTOMIZE_PLAYER_GUID, handler->playerLink(*player).c_str(), player->GetGUID().ToString().c_str());
410 stmt->setUInt16(0, static_cast<uint16>(AT_LOGIN_CUSTOMIZE));
411 stmt->setUInt32(1, player->GetGUID().GetCounter());
412 CharacterDatabase.Execute(stmt);
413 }
414
415 return true;
416 }
417
419 {
420 if (!player)
421 player = PlayerIdentifier::FromTarget(handler);
422 if (!player)
423 return false;
424
425 CharacterCacheEntry const* characterInfo = sCharacterCache->GetCharacterCacheByGuid(player->GetGUID());
426 if (!characterInfo)
427 return false;
428
429 if (characterInfo->Level < 10)
430 {
432 handler->SetSentErrorMessage(true);
433 return false;
434 }
435
436 if (characterInfo->Class == CLASS_DEATH_KNIGHT && characterInfo->Level < 60)
437 {
439 handler->SetSentErrorMessage(true);
440 return false;
441 }
442
443 if (Player* target = player->GetConnectedPlayer())
444 {
445 handler->PSendSysMessage(LANG_CUSTOMIZE_PLAYER, handler->GetNameLink(target).c_str());
446 target->SetAtLoginFlag(AT_LOGIN_CHANGE_FACTION);
447 }
448 else
449 {
450 handler->PSendSysMessage(LANG_CUSTOMIZE_PLAYER_GUID, handler->playerLink(*player).c_str(), player->GetGUID().ToString().c_str());
453 stmt->setUInt32(1, player->GetGUID().GetCounter());
454 CharacterDatabase.Execute(stmt);
455 }
456
457 return true;
458 }
459
461 {
462 if (!player)
463 player = PlayerIdentifier::FromTarget(handler);
464 if (!player)
465 return false;
466
467 if (Player* target = player->GetConnectedPlayer())
468 {
469 handler->PSendSysMessage(LANG_CUSTOMIZE_PLAYER, handler->GetNameLink(target).c_str());
470 target->SetAtLoginFlag(AT_LOGIN_CHANGE_RACE);
471 }
472 else
473 {
474 handler->PSendSysMessage(LANG_CUSTOMIZE_PLAYER_GUID, handler->playerLink(*player).c_str(), player->GetGUID().ToString().c_str());
477 stmt->setUInt32(1, player->GetGUID().GetCounter());
478 CharacterDatabase.Execute(stmt);
479 }
480
481 return true;
482 }
483
485 {
486 if (!player)
487 player = PlayerIdentifier::FromTarget(handler);
488 if (!player)
489 return false;
490
491 CharacterCacheEntry const* characterInfo = sCharacterCache->GetCharacterCacheByGuid(player->GetGUID());
492 if (!characterInfo)
493 {
495 handler->SetSentErrorMessage(true);
496 return false;
497 }
498
499 uint32 oldAccountId = characterInfo->AccountId;
500 // nothing to do :)
501 if (newAccount.GetID() == oldAccountId)
502 return true;
503
504 if (uint32 charCount = AccountMgr::GetCharactersCount(newAccount.GetID()))
505 {
506 if (charCount >= sWorld->getIntConfig(CONFIG_CHARACTERS_PER_REALM))
507 {
508 handler->PSendSysMessage(LANG_ACCOUNT_CHARACTER_LIST_FULL, newAccount.GetName().c_str(), newAccount.GetID());
509 handler->SetSentErrorMessage(true);
510 return false;
511 }
512 }
513
514 if (Player* onlinePlayer = player->GetConnectedPlayer())
515 onlinePlayer->GetSession()->KickPlayer("HandleCharacterChangeAccountCommand GM Command transferring character to another account");
516
518 charStmt->setUInt32(0, newAccount.GetID());
519 charStmt->setUInt32(1, player->GetGUID().GetCounter());
520 CharacterDatabase.DirectExecute(charStmt);
521
522 sWorld->UpdateRealmCharCount(oldAccountId);
523 sWorld->UpdateRealmCharCount(newAccount.GetID());
524
525 sCharacterCache->UpdateCharacterAccountId(*player, newAccount.GetID());
526
527 handler->PSendSysMessage(LANG_CHANGEACCOUNT_SUCCESS, player->GetName().c_str(), newAccount.GetName().c_str());
528
529 std::string logString = Trinity::StringFormat("changed ownership of player {} ({}) from account {} to account {}", player->GetName(), player->GetGUID().ToString(), oldAccountId, newAccount.GetID());
530 if (WorldSession* session = handler->GetSession())
531 {
532 if (Player* player = session->GetPlayer())
533 sLog->OutCommand(session->GetAccountId(), "GM {} (Account: {}) {}", player->GetName(), session->GetAccountId(), logString);
534 }
535 else
536 sLog->OutCommand(0, "{} {}", handler->GetTrinityString(LANG_CONSOLE), logString);
537 return true;
538 }
539
541 {
542 if (!player)
543 player = PlayerIdentifier::FromTargetOrSelf(handler);
544 if (!player || !player->IsConnected())
545 {
547 handler->SetSentErrorMessage(true);
548 return false;
549 }
550
551 Player const* target = player->GetConnectedPlayer();
552 LocaleConstant loc = handler->GetSessionDbcLocale();
553
554 FactionStateList const& targetFSL = target->GetReputationMgr().GetStateList();
555 for (FactionStateList::const_iterator itr = targetFSL.begin(); itr != targetFSL.end(); ++itr)
556 {
557 FactionState const& faction = itr->second;
558 FactionEntry const* factionEntry = sFactionStore.LookupEntry(faction.ID);
559 char const* factionName = factionEntry ? factionEntry->Name[loc] : "#Not found#";
560 std::string rankName = target->GetReputationMgr().GetReputationRankName(factionEntry);
561 std::ostringstream ss;
562 if (handler->GetSession())
563 ss << faction.ID << " - |cffffffff|Hfaction:" << faction.ID << "|h[" << factionName << ' ' << localeNames[loc] << "]|h|r";
564 else
565 ss << faction.ID << " - " << factionName << ' ' << localeNames[loc];
566
567 ss << ' ' << rankName << " (" << target->GetReputationMgr().GetReputation(factionEntry) << ')';
568
572 ss << handler->GetTrinityString(LANG_FACTION_ATWAR);
581
582 handler->SendSysMessage(ss.str().c_str());
583 }
584
585 return true;
586 }
587
599 {
600 std::string needle;
601 if (needleStr)
602 needle.assign(*needleStr);
603 DeletedInfoList foundList;
604 if (!GetDeletedCharacterInfoList(foundList, needle))
605 return false;
606
607 // if no characters have been found, output a warning
608 if (foundList.empty())
609 {
611 handler->SetSentErrorMessage(true);
612 return false;
613 }
614
615 HandleCharacterDeletedListHelper(foundList, handler);
616
617 return true;
618 }
619
631 static bool HandleCharacterDeletedRestoreCommand(ChatHandler* handler, std::string needle, Optional<std::string_view> newCharName, Optional<AccountIdentifier> newAccount)
632 {
633 DeletedInfoList foundList;
634 if (!GetDeletedCharacterInfoList(foundList, needle))
635 return false;
636
637 if (foundList.empty())
638 {
640 handler->SetSentErrorMessage(true);
641 return false;
642 }
643
645 HandleCharacterDeletedListHelper(foundList, handler);
646
647 if (!newCharName)
648 {
649 // Drop nonexisting account cases
650 for (DeletedInfoList::iterator itr = foundList.begin(); itr != foundList.end(); ++itr)
652 return true;
653 }
654
655 if (foundList.size() == 1)
656 {
657 std::string newName{ *newCharName };
658 DeletedInfo delInfo = foundList.front();
659
660 // update name
661 delInfo.name = newName;
662
663 // if new account provided update deleted info
664 if (newAccount)
665 {
666 delInfo.accountId = newAccount->GetID();
667 delInfo.accountName = newAccount->GetName();
668 }
669
670 HandleCharacterDeletedRestoreHelper(delInfo, handler);
671 return true;
672 }
673
675 handler->SetSentErrorMessage(true);
676 return false;
677 }
678
689 static bool HandleCharacterDeletedDeleteCommand(ChatHandler* handler, std::string needle)
690 {
691 DeletedInfoList foundList;
692 if (!GetDeletedCharacterInfoList(foundList, needle))
693 return false;
694
695 if (foundList.empty())
696 {
698 handler->SetSentErrorMessage(true);
699 return false;
700 }
701
703 HandleCharacterDeletedListHelper(foundList, handler);
704
705 // Call the appropriate function to delete them (current account for deleted characters is 0)
706 for (DeletedInfoList::const_iterator itr = foundList.begin(); itr != foundList.end(); ++itr)
707 Player::DeleteFromDB(itr->guid, 0, false, true);
708
709 return true;
710 }
711
724 {
725 int32 keepDays = static_cast<int32>(sWorld->getIntConfig(CONFIG_CHARDELETE_KEEP_DAYS));
726
727 if (days)
728 keepDays = static_cast<int32>(*days);
729 else if (keepDays <= 0) // config option value 0 -> disabled and can't be used
730 return false;
731
732 Player::DeleteOldCharacters(static_cast<uint32>(keepDays));
733
734 return true;
735 }
736
738 {
739 uint32 accountId;
740 if (Player* target = player.GetConnectedPlayer())
741 {
742 accountId = target->GetSession()->GetAccountId();
743 target->GetSession()->KickPlayer("HandleCharacterEraseCommand GM Command deleting character");
744 }
745 else
746 accountId = sCharacterCache->GetCharacterAccountIdByGuid(player);
747
748 std::string accountName;
749 AccountMgr::GetName(accountId, accountName);
750
751 Player::DeleteFromDB(player, accountId, true, true);
752 handler->PSendSysMessage(LANG_CHARACTER_DELETED, player.GetName().c_str(), player.GetGUID().ToString().c_str(), accountName.c_str(), accountId);
753
754 return true;
755 }
756
758 {
759 if (!player)
760 player = PlayerIdentifier::FromTargetOrSelf(handler);
761 if (!player)
762 return false;
763
764 uint8 oldlevel = static_cast<uint8>(player->IsConnected() ? player->GetConnectedPlayer()->GetLevel() : sCharacterCache->GetCharacterLevelByGuid(*player));
765
766 if (newlevel < 1)
767 newlevel = 1;
768
769 if (newlevel > static_cast<int16>(STRONG_MAX_LEVEL))
770 newlevel = static_cast<int16>(STRONG_MAX_LEVEL);
771
772 if (Player* target = player->GetConnectedPlayer())
773 {
774 target->GiveLevel(static_cast<uint8>(newlevel));
775 target->InitTalentForLevel();
776 target->SetXP(0);
777
778 if (handler->needReportToTarget(target))
779 {
780 if (oldlevel == newlevel)
781 ChatHandler(target->GetSession()).PSendSysMessage(LANG_YOURS_LEVEL_PROGRESS_RESET, handler->GetNameLink().c_str());
782 else if (oldlevel < static_cast<uint8>(newlevel))
783 ChatHandler(target->GetSession()).PSendSysMessage(LANG_YOURS_LEVEL_UP, handler->GetNameLink().c_str(), newlevel);
784 else // if (oldlevel > newlevel)
785 ChatHandler(target->GetSession()).PSendSysMessage(LANG_YOURS_LEVEL_DOWN, handler->GetNameLink().c_str(), newlevel);
786 }
787 }
788 else
789 {
790 // Update level and reset XP, everything else will be updated at login
792 stmt->setUInt8(0, static_cast<uint8>(newlevel));
793 stmt->setUInt32(1, player->GetGUID().GetCounter());
794 CharacterDatabase.Execute(stmt);
795 }
796
797 if (!handler->GetSession() || (handler->GetSession()->GetPlayer() != player->GetConnectedPlayer())) // including chr == NULL
798 handler->PSendSysMessage(LANG_YOU_CHANGE_LVL, handler->playerLink(*player).c_str(), newlevel);
799
800 return true;
801 }
802
804 {
805 if (!player)
806 player = PlayerIdentifier::FromTargetOrSelf(handler);
807 if (!player)
808 return false;
809
810 uint8 oldlevel = static_cast<uint8>(player->IsConnected() ? player->GetConnectedPlayer()->GetLevel() : sCharacterCache->GetCharacterLevelByGuid(*player));
811 int16 newlevel = static_cast<int16>(oldlevel) + level;
812
813 if (newlevel < 1)
814 newlevel = 1;
815
816 if (newlevel > static_cast<int16>(STRONG_MAX_LEVEL))
817 newlevel = static_cast<int16>(STRONG_MAX_LEVEL);
818
819 if (Player* target = player->GetConnectedPlayer())
820 {
821 target->GiveLevel(static_cast<uint8>(newlevel));
822 target->InitTalentForLevel();
823 target->SetXP(0);
824
825 if (handler->needReportToTarget(target))
826 {
827 if (oldlevel == newlevel)
828 ChatHandler(target->GetSession()).PSendSysMessage(LANG_YOURS_LEVEL_PROGRESS_RESET, handler->GetNameLink().c_str());
829 else if (oldlevel < static_cast<uint8>(newlevel))
830 ChatHandler(target->GetSession()).PSendSysMessage(LANG_YOURS_LEVEL_UP, handler->GetNameLink().c_str(), newlevel);
831 else // if (oldlevel > newlevel)
832 ChatHandler(target->GetSession()).PSendSysMessage(LANG_YOURS_LEVEL_DOWN, handler->GetNameLink().c_str(), newlevel);
833 }
834 }
835 else
836 {
837 // Update level and reset XP, everything else will be updated at login
839 stmt->setUInt8(0, static_cast<uint8>(newlevel));
840 stmt->setUInt32(1, player->GetGUID().GetCounter());
841 CharacterDatabase.Execute(stmt);
842 }
843
844 if (!handler->GetSession() || (handler->GetSession()->GetPlayer() != player->GetConnectedPlayer())) // including chr == NULL
845 handler->PSendSysMessage(LANG_YOU_CHANGE_LVL, handler->playerLink(*player).c_str(), newlevel);
846
847 return true;
848 }
849
851 {
852 std::string name;
853 if (!ValidatePDumpTarget(handler, name, characterName, characterGUID))
854 return false;
855
856 std::string dump;
857 switch (PlayerDumpWriter().WriteDumpToString(dump, player.GetGUID().GetCounter()))
858 {
859 case DUMP_SUCCESS:
860 break;
863 handler->SetSentErrorMessage(true);
864 return false;
865 case DUMP_FILE_OPEN_ERROR: // this error code should not happen
866 default:
868 handler->SetSentErrorMessage(true);
869 return false;
870 }
871
872 switch (PlayerDumpReader().LoadDumpFromString(dump, account, name, characterGUID.value_or(0)))
873 {
874 case DUMP_SUCCESS:
875 break;
877 handler->PSendSysMessage(LANG_ACCOUNT_CHARACTER_LIST_FULL, account.GetName().c_str(), account.GetID());
878 handler->SetSentErrorMessage(true);
879 return false;
880 case DUMP_FILE_OPEN_ERROR: // this error code should not happen
881 case DUMP_FILE_BROKEN: // this error code should not happen
882 default:
884 handler->SetSentErrorMessage(true);
885 return false;
886 }
887
888 // ToDo: use a new trinity_string for this commands
890
891 return true;
892 }
893
894 static bool HandlePDumpLoadCommand(ChatHandler* handler, std::string fileName, AccountIdentifier account, Optional<std::string_view> characterName, Optional<ObjectGuid::LowType> characterGUID)
895 {
896 std::string name;
897 if (!ValidatePDumpTarget(handler, name, characterName, characterGUID))
898 return false;
899
900 switch (PlayerDumpReader().LoadDumpFromFile(fileName, account, name, characterGUID.value_or(0)))
901 {
902 case DUMP_SUCCESS:
904 break;
906 handler->PSendSysMessage(LANG_FILE_OPEN_FAIL, fileName.c_str());
907 handler->SetSentErrorMessage(true);
908 return false;
909 case DUMP_FILE_BROKEN:
910 handler->PSendSysMessage(LANG_DUMP_BROKEN, fileName.c_str());
911 handler->SetSentErrorMessage(true);
912 return false;
914 handler->PSendSysMessage(LANG_ACCOUNT_CHARACTER_LIST_FULL, account.GetName().c_str(), account.GetID());
915 handler->SetSentErrorMessage(true);
916 return false;
917 default:
919 handler->SetSentErrorMessage(true);
920 return false;
921 }
922
923 return true;
924 }
925
926 static bool ValidatePDumpTarget(ChatHandler* handler, std::string& name, Optional<std::string_view> characterName, Optional<ObjectGuid::LowType> characterGUID)
927 {
928 if (characterName)
929 {
930 name.assign(*characterName);
931 // normalize the name if specified and check if it exists
932 if (!normalizePlayerName(name))
933 {
935 handler->SetSentErrorMessage(true);
936 return false;
937 }
938
939 if (ObjectMgr::CheckPlayerName(name, sWorld->GetDefaultDbcLocale(), true) != CHAR_NAME_SUCCESS)
940 {
942 handler->SetSentErrorMessage(true);
943 return false;
944 }
945 }
946
947 if (characterGUID)
948 {
949 if (sCharacterCache->GetCharacterCacheByGuid(ObjectGuid::Create<HighGuid::Player>(*characterGUID)))
950 {
951 handler->PSendSysMessage(LANG_CHARACTER_GUID_IN_USE, *characterGUID);
952 handler->SetSentErrorMessage(true);
953 return false;
954 }
955 }
956
957 return true;
958 }
959
960 static bool HandlePDumpWriteCommand(ChatHandler* handler, std::string fileName, PlayerIdentifier player)
961 {
962 switch (PlayerDumpWriter().WriteDumpToFile(fileName, player.GetGUID().GetCounter()))
963 {
964 case DUMP_SUCCESS:
966 break;
968 handler->PSendSysMessage(LANG_FILE_OPEN_FAIL, fileName.c_str());
969 handler->SetSentErrorMessage(true);
970 return false;
973 handler->SetSentErrorMessage(true);
974 return false;
975 default:
977 handler->SetSentErrorMessage(true);
978 return false;
979 }
980
981 return true;
982 }
983};
984
#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_SEL_CHARACTER_NAME_DATA
@ 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
@ STRONG_MAX_LEVEL
Definition DBCEnums.h:53
DBCStorage< CharTitlesEntry > sCharTitlesStore(CharTitlesEntryfmt)
DBCStorage< FactionEntry > sFactionStore(FactionEntryfmt)
std::shared_ptr< PreparedResultSet > PreparedQueryResult
DatabaseWorkerPool< CharacterDatabaseConnection > CharacterDatabase
Accessor to the character database.
uint8_t uint8
Definition Define.h:135
int16_t int16
Definition Define.h:130
int32_t int32
Definition Define.h:129
uint16_t uint16
Definition Define.h:134
uint32_t uint32
Definition Define.h:133
@ LANG_FACTION_PEACE_FORCED
Definition Language.h:369
@ LANG_CHARACTER_DELETED_SKIP_NAME
Definition Language.h:862
@ LANG_CHARACTER_DELETED_LIST_LINE_CHAT
Definition Language.h:863
@ LANG_RENAME_PLAYER
Definition Language.h:301
@ LANG_FACTION_ATWAR
Definition Language.h:368
@ LANG_CHARACTER_DELETED_ERR_RENAME
Definition Language.h:859
@ LANG_CHARACTER_DELETED_LIST_HEADER
Definition Language.h:853
@ LANG_KNOWN
Definition Language.h:63
@ LANG_DUMP_BROKEN
Definition Language.h:890
@ LANG_CHARACTER_DELETED_LIST_LINE_CONSOLE
Definition Language.h:854
@ LANG_FACTION_INVISIBLE_FORCED
Definition Language.h:371
@ LANG_COMMAND_EXPORT_DELETED_CHAR
Definition Language.h:906
@ LANG_FILE_OPEN_FAIL
Definition Language.h:888
@ LANG_CHANGEFACTION_NOT_ELIGIBLE_60
Definition Language.h:453
@ LANG_CHARACTER_GUID_IN_USE
Definition Language.h:893
@ LANG_CUSTOMIZE_PLAYER_GUID
Definition Language.h:401
@ LANG_ACCOUNT_CHARACTER_LIST_FULL
Definition Language.h:889
@ 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:404
@ LANG_CHARACTER_DELETED_RESTORE
Definition Language.h:857
@ LANG_CHARACTER_DELETED
Definition Language.h:846
@ LANG_COMMAND_EXPORT_SUCCESS
Definition Language.h:548
@ LANG_FACTION_HIDDEN
Definition Language.h:370
@ LANG_CONSOLE
Definition Language.h:1098
@ LANG_CUSTOMIZE_PLAYER
Definition Language.h:400
@ LANG_ACTIVE
Definition Language.h:67
@ LANG_PLAYER_NOT_FOUND
Definition Language.h:570
@ LANG_CHARACTER_DELETED_SKIP_FULL
Definition Language.h:861
@ LANG_CHARACTER_DELETED_LIST_EMPTY
Definition Language.h:856
@ LANG_CHARACTER_DELETED_LIST_BAR
Definition Language.h:855
@ LANG_BAD_VALUE
Definition Language.h:149
@ LANG_TITLE_LIST_CONSOLE
Definition Language.h:405
@ LANG_COMMAND_IMPORT_FAILED
Definition Language.h:547
@ LANG_YOURS_LEVEL_UP
Definition Language.h:641
@ LANG_YOURS_LEVEL_PROGRESS_RESET
Definition Language.h:643
@ LANG_RESERVED_NAME
Definition Language.h:208
@ LANG_COMMAND_EXPORT_FAILED
Definition Language.h:549
@ LANG_CHANGEFACTION_NOT_ELIGIBLE_10
Definition Language.h:452
@ LANG_FACTION_INACTIVE
Definition Language.h:372
@ LANG_RENAME_PLAYER_ALREADY_EXISTS
Definition Language.h:130
@ LANG_CHARACTER_DELETED_SKIP_ACCOUNT
Definition Language.h:860
@ LANG_RENAME_PLAYER_GUID
Definition Language.h:302
@ LANG_CHANGEACCOUNT_SUCCESS
Definition Language.h:960
@ LANG_FACTION_VISIBLE
Definition Language.h:367
@ LANG_YOURS_LEVEL_DOWN
Definition Language.h:642
@ LANG_INVALID_CHARACTER_NAME
Definition Language.h:891
@ LANG_COMMAND_IMPORT_SUCCESS
Definition Language.h:546
@ LANG_CHARACTER_DELETED_DELETE
Definition Language.h:858
#define sLog
Definition Log.h:130
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
@ DUMP_FILE_OPEN_ERROR
Definition PlayerDump.h:58
@ DUMP_CHARACTER_DELETED
Definition PlayerDump.h:61
@ DUMP_SUCCESS
Definition PlayerDump.h:57
@ DUMP_TOO_MANY_CHARS
Definition PlayerDump.h:59
@ DUMP_FILE_BROKEN
Definition PlayerDump.h:60
@ AT_LOGIN_CUSTOMIZE
Definition Player.h:476
@ AT_LOGIN_RENAME
Definition Player.h:473
@ AT_LOGIN_CHANGE_RACE
Definition Player.h:480
@ AT_LOGIN_CHANGE_FACTION
Definition Player.h:479
std::map< RepListID, FactionState > FactionStateList
@ GENDER_MALE
@ CHAR_NAME_SUCCESS
@ CLASS_DEATH_KNIGHT
@ PLAYER_CHOSEN_TITLE
std::string TimeToTimestampStr(time_t t)
Definition Util.cpp:290
static uint32 GetCharactersCount(uint32 accountId)
static bool GetName(uint32 accountId, std::string &name)
std::string playerLink(std::string const &name) const
Definition Chat.h:127
static std::string PGetParseString(std::string_view fmt, Args &&... args)
Definition Chat.h:81
WorldSession * GetSession()
Definition Chat.h:46
virtual LocaleConstant GetSessionDbcLocale() const
Definition Chat.cpp:692
virtual std::string GetNameLink() const
Definition Chat.cpp:46
bool HasLowerSecurity(Player *target, ObjectGuid guid, bool strong=false)
Definition Chat.cpp:51
void SetSentErrorMessage(bool val)
Definition Chat.h:134
void PSendSysMessage(char const *fmt, Args &&... args)
Definition Chat.h:69
virtual void SendSysMessage(std::string_view str, bool escapeCharacters=false)
Definition Chat.cpp:101
virtual bool needReportToTarget(Player *chr) const
Definition Chat.cpp:686
virtual char const * GetTrinityString(uint32 entry) const
Definition Chat.cpp:36
constexpr bool HasFlag(T flag) const
Definition EnumFlag.h:106
Class used to access individual fields of database query result.
Definition Field.h:92
std::string GetString() const
Definition Field.cpp:125
uint32 GetUInt32() const
Definition Field.cpp:61
LowType GetCounter() const
Definition ObjectGuid.h:156
std::string ToString() const
static ResponseCodes CheckPlayerName(std::string_view name, LocaleConstant locale, bool create=false)
uint32 GetUInt32Value(uint16 index) const
Definition Object.cpp:249
static void DeleteOldCharacters()
Definition Player.cpp:4252
Gender GetNativeGender() const override
Definition Player.h:1039
bool HasTitle(uint32 bitIndex) const
Definition Player.cpp:24301
static void DeleteFromDB(ObjectGuid playerguid, uint32 accountId, bool updateRealmChars=true, bool deleteFinally=false)
Definition Player.cpp:3885
ReputationMgr & GetReputationMgr()
Definition Player.h:1848
void setUInt16(uint8 index, uint16 value)
void setUInt32(uint8 index, uint32 value)
void setUInt8(uint8 index, uint8 value)
void setString(uint8 index, std::string const &value)
std::string GetReputationRankName(FactionEntry const *factionEntry) const
FactionStateList const & GetStateList() const
int32 GetReputation(uint32 faction_id) const
Player session in the World.
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:900
@ CONFIG_CHARDELETE_KEEP_DAYS
Definition World.h:344
@ CONFIG_CHARACTERS_PER_REALM
Definition World.h:232
std::vector< ChatCommandBuilder > ChatCommandTable
Definition ChatCommand.h:50
std::string StringFormat(FormatString< Args... > fmt, Args &&... args)
Default TC string format function.
@ RBAC_PERM_COMMAND_CHARACTER_CHANGERACE
Definition RBAC.h:192
@ RBAC_PERM_COMMAND_PDUMP_COPY
Definition RBAC.h:747
@ RBAC_PERM_COMMAND_CHARACTER_DELETED_OLD
Definition RBAC.h:197
@ RBAC_PERM_COMMAND_LEVELUP
Definition RBAC.h:203
@ RBAC_PERM_COMMAND_CHARACTER_LEVEL
Definition RBAC.h:199
@ RBAC_PERM_COMMAND_CHARACTER_DELETED_DELETE
Definition RBAC.h:194
@ RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_RESERVEDNAME
Definition RBAC.h:70
@ RBAC_PERM_COMMAND_CHARACTER_CHANGEFACTION
Definition RBAC.h:191
@ RBAC_PERM_COMMAND_CHARACTER_TITLES
Definition RBAC.h:202
@ RBAC_PERM_COMMAND_CHARACTER_CUSTOMIZE
Definition RBAC.h:190
@ RBAC_PERM_COMMAND_CHARACTER_CHANGEACCOUNT
Definition RBAC.h:568
@ RBAC_PERM_COMMAND_CHARACTER_RENAME
Definition RBAC.h:200
@ RBAC_PERM_COMMAND_CHARACTER_ERASE
Definition RBAC.h:198
@ RBAC_PERM_COMMAND_PDUMP_LOAD
Definition RBAC.h:205
@ RBAC_PERM_COMMAND_CHARACTER_REPUTATION
Definition RBAC.h:201
@ RBAC_PERM_COMMAND_CHARACTER_DELETED_LIST
Definition RBAC.h:195
@ RBAC_PERM_COMMAND_CHARACTER_DELETED_RESTORE
Definition RBAC.h:196
@ RBAC_PERM_COMMAND_PDUMP_WRITE
Definition RBAC.h:206
char const * Name[16]
char const * Name1[16]
char const * Name[16]
EnumFlag< ReputationFlags > Flags
static Optional< PlayerIdentifier > FromTarget(ChatHandler *handler)
std::string const & GetName() const
static Optional< PlayerIdentifier > FromTargetOrSelf(ChatHandler *handler)
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