mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-16 07:30:42 +01:00
Core/Scripts: added command to move characters across accounts
(cherry-picked from f7f865f818)
This commit is contained in:
@@ -1888,7 +1888,7 @@ INSERT INTO `rbac_permissions` VALUES
|
||||
(695,'Command: reload spell_loot_template'),
|
||||
(696,'Command: reload spell_linked_spell'),
|
||||
(697,'Command: reload spell_pet_auras'),
|
||||
(698,'Command: reload spell_proc_event'),
|
||||
(698,'Command: character changeaccount'),
|
||||
(699,'Command: reload spell_proc'),
|
||||
(700,'Command: reload spell_scripts'),
|
||||
(701,'Command: reload spell_target_position'),
|
||||
@@ -2242,7 +2242,8 @@ INSERT INTO `updates` VALUES
|
||||
('2018_05_24_00_auth.sql','B98FD71AAA13810856729E034E6B8C9F8D5D4F6B','RELEASED','2018-05-24 22:32:49',0),
|
||||
('2018_06_14_00_auth.sql','67EAB915BF0C7F2D410BE45F885A1A39D42C8C14','RELEASED','2018-06-14 23:06:59',0),
|
||||
('2018_06_22_00_auth.sql','9DA24F70B8A365AFDEF58A9B578255CDEDFCA47C','RELEASED','2018-06-22 17:45:45',0),
|
||||
('2018_06_29_00_auth.sql','03AAEA7E52848FA5522C3F0C6D9C38B988407480','RELEASED','2018-06-29 22:34:04',0);
|
||||
('2018_06_29_00_auth.sql','03AAEA7E52848FA5522C3F0C6D9C38B988407480','RELEASED','2018-06-29 22:34:04',0),
|
||||
('2018_12_09_00_auth_2017_01_06_00_auth.sql','6CCFE6A9774EC733C9863D36A0F15F3534189BBD','RELEASED','2018-11-22 22:21:26',0);
|
||||
/*!40000 ALTER TABLE `updates` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
DELETE FROM `rbac_permissions` WHERE `id`=698;
|
||||
INSERT INTO `rbac_permissions` (`id`, `name`) VALUES
|
||||
(698, 'Command: character changeaccount');
|
||||
INSERT INTO `rbac_linked_permissions` (`id`, `linkedId`) VALUES
|
||||
(196, 698);
|
||||
@@ -0,0 +1,7 @@
|
||||
DELETE FROM `command` WHERE `permission`=698;
|
||||
INSERT INTO `command` (`name`, `permission`, `help`) VALUES
|
||||
('character changeaccount', 698, 'Syntax: .character changeaccount [$player] $account\n\nTransfers ownership of named (or selected) character to another account');
|
||||
|
||||
DELETE FROM `trinity_string` WHERE `entry`=1192;
|
||||
INSERT INTO `trinity_string` (`entry`, `content_default`) VALUES
|
||||
(1192, 'Successfully transferred ownership of character %s to account %s');
|
||||
@@ -196,6 +196,7 @@ void CharacterDatabaseConnection::DoPrepareStatements()
|
||||
PrepareStatement(CHAR_DEL_GIFT, "DELETE FROM character_gifts WHERE item_guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_GIFT_BY_ITEM, "SELECT entry, flags FROM character_gifts WHERE item_guid = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_ACCOUNT_BY_NAME, "SELECT account FROM characters WHERE name = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_UPD_ACCOUNT_BY_GUID, "UPDATE characters SET account = ? WHERE guid = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_DEL_ACCOUNT_INSTANCE_LOCK_TIMES, "DELETE FROM account_instance_times WHERE accountId = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_ACCOUNT_INSTANCE_LOCK_TIMES, "INSERT INTO account_instance_times (accountId, instanceId, releaseTime) VALUES (?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_MATCH_MAKER_RATING, "SELECT matchMakerRating FROM character_arena_stats WHERE guid = ? AND slot = ?", CONNECTION_SYNCH);
|
||||
|
||||
@@ -165,6 +165,7 @@ enum CharacterDatabaseStatements : uint32
|
||||
CHAR_DEL_GIFT,
|
||||
CHAR_SEL_CHARACTER_GIFT_BY_ITEM,
|
||||
CHAR_SEL_ACCOUNT_BY_NAME,
|
||||
CHAR_UPD_ACCOUNT_BY_GUID,
|
||||
CHAR_DEL_ACCOUNT_INSTANCE_LOCK_TIMES,
|
||||
CHAR_INS_ACCOUNT_INSTANCE_LOCK_TIMES,
|
||||
CHAR_SEL_MATCH_MAKER_RATING,
|
||||
|
||||
@@ -603,7 +603,7 @@ enum RBACPermissions
|
||||
RBAC_PERM_COMMAND_RELOAD_SPELL_LOOT_TEMPLATE = 695,
|
||||
RBAC_PERM_COMMAND_RELOAD_SPELL_LINKED_SPELL = 696,
|
||||
RBAC_PERM_COMMAND_RELOAD_SPELL_PET_AURAS = 697,
|
||||
// 698 - reuse
|
||||
RBAC_PERM_COMMAND_CHARACTER_CHANGEACCOUNT = 698,
|
||||
RBAC_PERM_COMMAND_RELOAD_SPELL_PROC = 699,
|
||||
RBAC_PERM_COMMAND_RELOAD_SPELL_SCRIPTS = 700,
|
||||
RBAC_PERM_COMMAND_RELOAD_SPELL_TARGET_POSITION = 701,
|
||||
|
||||
@@ -927,7 +927,8 @@ enum TrinityStrings
|
||||
LANG_ACCOUNT_BNET_NOT_LINKED = 1189,
|
||||
LANG_DISALLOW_TICKETS_CONFIG = 1190,
|
||||
LANG_BAN_EXISTS = 1191,
|
||||
// Room for more level 3 1192-1198 not used
|
||||
LANG_CHANGEACCOUNT_SUCCESS = 1192,
|
||||
// Room for more level 3 1193-1198 not used
|
||||
|
||||
// Debug commands
|
||||
LANG_DEBUG_AREATRIGGER_LEFT = 1999,
|
||||
|
||||
@@ -3616,6 +3616,15 @@ void World::UpdateCharacterInfoLevel(ObjectGuid const& guid, uint8 level)
|
||||
itr->second.Level = level;
|
||||
}
|
||||
|
||||
void World::UpdateCharacterInfoAccount(ObjectGuid const& guid, uint32 accountId)
|
||||
{
|
||||
auto itr = _characterInfoStore.find(guid);
|
||||
if (itr == _characterInfoStore.end())
|
||||
return;
|
||||
|
||||
itr->second.AccountId = accountId;
|
||||
}
|
||||
|
||||
void World::UpdateCharacterInfoDeleted(ObjectGuid const& guid, bool deleted, std::string const* name /*= nullptr*/)
|
||||
{
|
||||
CharacterInfoContainer::iterator itr = _characterInfoStore.find(guid);
|
||||
|
||||
@@ -794,6 +794,7 @@ class TC_GAME_API World
|
||||
bool HasCharacterInfo(ObjectGuid const& guid) { return _characterInfoStore.find(guid) != _characterInfoStore.end(); }
|
||||
void UpdateCharacterInfo(ObjectGuid const& guid, std::string const& name, uint8 gender = GENDER_NONE, uint8 race = RACE_NONE);
|
||||
void UpdateCharacterInfoLevel(ObjectGuid const& guid, uint8 level);
|
||||
void UpdateCharacterInfoAccount(ObjectGuid const& guid, uint32 accountId);
|
||||
void UpdateCharacterInfoDeleted(ObjectGuid const& guid, bool deleted, std::string const* name = nullptr);
|
||||
|
||||
uint32 GetCleaningFlags() const { return m_CleaningFlags; }
|
||||
|
||||
@@ -61,6 +61,7 @@ public:
|
||||
{ "customize", rbac::RBAC_PERM_COMMAND_CHARACTER_CUSTOMIZE, true, &HandleCharacterCustomizeCommand, "", },
|
||||
{ "changefaction", rbac::RBAC_PERM_COMMAND_CHARACTER_CHANGEFACTION, true, &HandleCharacterChangeFactionCommand, "", },
|
||||
{ "changerace", rbac::RBAC_PERM_COMMAND_CHARACTER_CHANGERACE, true, &HandleCharacterChangeRaceCommand, "", },
|
||||
{ "changeaccount", rbac::RBAC_PERM_COMMAND_CHARACTER_CHANGEACCOUNT, true, &HandleCharacterChangeAccountCommand, "", },
|
||||
{ "deleted", rbac::RBAC_PERM_COMMAND_CHARACTER_DELETED, true, NULL, "", characterDeletedCommandTable },
|
||||
{ "erase", rbac::RBAC_PERM_COMMAND_CHARACTER_ERASE, true, &HandleCharacterEraseCommand, "", },
|
||||
{ "level", rbac::RBAC_PERM_COMMAND_CHARACTER_LEVEL, true, &HandleCharacterLevelCommand, "", },
|
||||
@@ -551,6 +552,86 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool HandleCharacterChangeAccountCommand(ChatHandler* handler, char const* args)
|
||||
{
|
||||
char* playerNameStr;
|
||||
char* accountNameStr;
|
||||
handler->extractOptFirstArg(const_cast<char*>(args), &playerNameStr, &accountNameStr);
|
||||
if (!accountNameStr)
|
||||
return false;
|
||||
|
||||
ObjectGuid targetGuid;
|
||||
std::string targetName;
|
||||
if (!handler->extractPlayerTarget(playerNameStr, nullptr, &targetGuid, &targetName))
|
||||
return false;
|
||||
|
||||
CharacterInfo const* characterInfo = sWorld->GetCharacterInfo(targetGuid);
|
||||
if (!characterInfo)
|
||||
{
|
||||
handler->SendSysMessage(LANG_PLAYER_NOT_FOUND);
|
||||
handler->SetSentErrorMessage(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32 oldAccountId = characterInfo->AccountId;
|
||||
uint32 newAccountId = oldAccountId;
|
||||
|
||||
std::string accountName(accountNameStr);
|
||||
if (!Utf8ToUpperOnlyLatin(accountName))
|
||||
{
|
||||
handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, accountName.c_str());
|
||||
handler->SetSentErrorMessage(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_ID_BY_NAME);
|
||||
stmt->setString(0, accountName);
|
||||
if (PreparedQueryResult result = LoginDatabase.Query(stmt))
|
||||
newAccountId = (*result)[0].GetUInt32();
|
||||
else
|
||||
{
|
||||
handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, accountName.c_str());
|
||||
handler->SetSentErrorMessage(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
// nothing to do :)
|
||||
if (newAccountId == oldAccountId)
|
||||
return true;
|
||||
|
||||
if (uint32 charCount = AccountMgr::GetCharactersCount(newAccountId))
|
||||
{
|
||||
if (charCount >= sWorld->getIntConfig(CONFIG_CHARACTERS_PER_REALM))
|
||||
{
|
||||
handler->PSendSysMessage(LANG_ACCOUNT_CHARACTER_LIST_FULL, accountName.c_str(), newAccountId);
|
||||
handler->SetSentErrorMessage(true);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ACCOUNT_BY_GUID);
|
||||
stmt->setUInt32(0, newAccountId);
|
||||
stmt->setUInt32(1, targetGuid.GetCounter());
|
||||
CharacterDatabase.DirectExecute(stmt);
|
||||
|
||||
sWorld->UpdateRealmCharCount(oldAccountId);
|
||||
sWorld->UpdateRealmCharCount(newAccountId);
|
||||
|
||||
sWorld->UpdateCharacterInfoAccount(targetGuid, newAccountId);
|
||||
|
||||
handler->PSendSysMessage(LANG_CHANGEACCOUNT_SUCCESS, targetName.c_str(), accountName.c_str());
|
||||
|
||||
std::string logString = Trinity::StringFormat("changed ownership of player %s (%s) from account %u to account %u", targetName.c_str(), targetGuid.ToString().c_str(), oldAccountId, newAccountId);
|
||||
if (WorldSession* session = handler->GetSession())
|
||||
{
|
||||
if (Player* player = session->GetPlayer())
|
||||
sLog->outCommand(session->GetAccountId(), "GM %s (Account: %u) %s", player->GetName().c_str(), session->GetAccountId(), logString.c_str());
|
||||
}
|
||||
else
|
||||
sLog->outCommand(0, "%s %s", handler->GetTrinityString(LANG_CONSOLE), logString.c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool HandleCharacterReputationCommand(ChatHandler* handler, char const* args)
|
||||
{
|
||||
Player* target;
|
||||
|
||||
Reference in New Issue
Block a user