/*
* Copyright (C)
*
* Copyright (C) 2008-2016 TrinityCore
* Copyright (C) 2005-2009 MaNGOS
*/
/* ScriptData
Name: character_commandscript
%Complete: 100
Comment: All character related commands
Category: commandscripts
EndScriptData */
#include "AccountMgr.h"
#include "Chat.h"
#include "ObjectMgr.h"
#include "PlayerDump.h"
#include "Player.h"
#include "ReputationMgr.h"
#include "ScriptMgr.h"
class character_commandscript : public CommandScript
{
public:
character_commandscript() : CommandScript("character_commandscript") { }
std::vector GetCommands() const override
{
static std::vector pdumpCommandTable =
{
{ "load", SEC_ADMINISTRATOR, true, &HandlePDumpLoadCommand, "" },
{ "write", SEC_ADMINISTRATOR, true, &HandlePDumpWriteCommand, "" },
{ NULL, 0, false, NULL, "" }
};
static std::vector characterCommandTable =
{
{ "customize", SEC_GAMEMASTER, true, &HandleCharacterCustomizeCommand, "" },
{ "changefaction", SEC_GAMEMASTER, true, &HandleCharacterChangeFactionCommand, "" },
{ "changerace", SEC_GAMEMASTER, true, &HandleCharacterChangeRaceCommand, "" },
{ "level", SEC_ADMINISTRATOR, true, &HandleCharacterLevelCommand, "" },
{ "rename", SEC_GAMEMASTER, true, &HandleCharacterRenameCommand, "" },
{ "reputation", SEC_GAMEMASTER, true, &HandleCharacterReputationCommand, "" },
{ "titles", SEC_GAMEMASTER, true, &HandleCharacterTitlesCommand, "" },
{ NULL, 0, false, NULL, "" }
};
static std::vector commandTable =
{
{ "character", SEC_GAMEMASTER, true, NULL, "", characterCommandTable },
{ "levelup", SEC_ADMINISTRATOR, false, &HandleLevelUpCommand, "" },
{ "pdump", SEC_ADMINISTRATOR, true, NULL, "", pdumpCommandTable },
{ NULL, 0, false, NULL, "" }
};
return commandTable;
}
// Stores informations about a deleted character
struct DeletedInfo
{
uint32 lowGuid; ///< the low GUID from the character
std::string name; ///< the character name
uint32 accountId; ///< the account id
std::string accountName; ///< the account name
time_t deleteDate; ///< the date at which the character has been deleted
};
static void HandleCharacterLevel(Player* player, uint64 playerGuid, uint32 oldLevel, uint32 newLevel, ChatHandler* handler)
{
if (player)
{
player->GiveLevel(newLevel);
player->InitTalentForLevel();
player->SetUInt32Value(PLAYER_XP, 0);
if (handler->needReportToTarget(player))
{
if (oldLevel == newLevel)
ChatHandler(player->GetSession()).PSendSysMessage(LANG_YOURS_LEVEL_PROGRESS_RESET, handler->GetNameLink().c_str());
else if (oldLevel < newLevel)
ChatHandler(player->GetSession()).PSendSysMessage(LANG_YOURS_LEVEL_UP, handler->GetNameLink().c_str(), newLevel);
else // if (oldlevel > newlevel)
ChatHandler(player->GetSession()).PSendSysMessage(LANG_YOURS_LEVEL_DOWN, handler->GetNameLink().c_str(), newLevel);
}
}
else
{
// Update level and reset XP, everything else will be updated at login
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_LEVEL);
stmt->setUInt8(0, uint8(newLevel));
stmt->setUInt32(1, GUID_LOPART(playerGuid));
CharacterDatabase.Execute(stmt);
// xinef: update global storage
sWorld->UpdateGlobalPlayerData(GUID_LOPART(playerGuid), PLAYER_UPDATE_DATA_LEVEL, "", newLevel);
}
}
static bool HandleCharacterTitlesCommand(ChatHandler* handler, char const* args)
{
if (!*args)
return false;
Player* target;
if (!handler->extractPlayerTarget((char*)args, &target))
return false;
LocaleConstant loc = handler->GetSessionDbcLocale();
char const* targetName = target->GetName().c_str();
char const* knownStr = handler->GetTrinityString(LANG_KNOWN);
// Search in CharTitles.dbc
for (uint32 id = 0; id < sCharTitlesStore.GetNumRows(); id++)
{
CharTitlesEntry const* titleInfo = sCharTitlesStore.LookupEntry(id);
if (titleInfo && target->HasTitle(titleInfo))
{
std::string name = target->getGender() == GENDER_MALE ? titleInfo->nameMale[loc] : titleInfo->nameFemale[loc];
if (name.empty())
continue;
char const* activeStr = target && target->GetUInt32Value(PLAYER_CHOSEN_TITLE) == titleInfo->bit_index
? handler->GetTrinityString(LANG_ACTIVE)
: "";
char titleNameStr[80];
snprintf(titleNameStr, 80, name.c_str(), targetName);
// send title in "id (idx:idx) - [namedlink locale]" format
if (handler->GetSession())
handler->PSendSysMessage(LANG_TITLE_LIST_CHAT, id, titleInfo->bit_index, id, titleNameStr, localeNames[loc], knownStr, activeStr);
else
handler->PSendSysMessage(LANG_TITLE_LIST_CONSOLE, id, titleInfo->bit_index, name.c_str(), localeNames[loc], knownStr, activeStr);
}
}
return true;
}
//rename characters
static bool HandleCharacterRenameCommand(ChatHandler* handler, char const* args)
{
Player* target;
uint64 targetGuid;
std::string targetName;
if (!handler->extractPlayerTarget((char*)args, &target, &targetGuid, &targetName))
return false;
if (target)
{
// check online security
if (handler->HasLowerSecurity(target, 0))
return false;
handler->PSendSysMessage(LANG_RENAME_PLAYER, handler->GetNameLink(target).c_str());
target->SetAtLoginFlag(AT_LOGIN_RENAME);
}
else
{
// check offline security
if (handler->HasLowerSecurity(NULL, targetGuid))
return false;
std::string oldNameLink = handler->playerLink(targetName);
handler->PSendSysMessage(LANG_RENAME_PLAYER_GUID, oldNameLink.c_str(), GUID_LOPART(targetGuid));
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ADD_AT_LOGIN_FLAG);
stmt->setUInt16(0, uint16(AT_LOGIN_RENAME));
stmt->setUInt32(1, GUID_LOPART(targetGuid));
CharacterDatabase.Execute(stmt);
}
return true;
}
static bool HandleCharacterLevelCommand(ChatHandler* handler, char const* args)
{
char* nameStr;
char* levelStr;
handler->extractOptFirstArg((char*)args, &nameStr, &levelStr);
if (!levelStr)
return false;
// exception opt second arg: .character level $name
if (isalpha(levelStr[0]))
{
nameStr = levelStr;
levelStr = NULL; // current level will used
}
Player* target;
uint64 targetGuid;
std::string targetName;
if (!handler->extractPlayerTarget(nameStr, &target, &targetGuid, &targetName))
return false;
int32 oldlevel = target ? target->getLevel() : Player::GetLevelFromStorage(targetGuid);
int32 newlevel = levelStr ? atoi(levelStr) : oldlevel;
if (newlevel < 1)
return false; // invalid level
if (newlevel > DEFAULT_MAX_LEVEL) // hardcoded maximum level
newlevel = DEFAULT_MAX_LEVEL;
HandleCharacterLevel(target, targetGuid, oldlevel, newlevel, handler);
if (!handler->GetSession() || handler->GetSession()->GetPlayer() != target) // including player == NULL
{
std::string nameLink = handler->playerLink(targetName);
handler->PSendSysMessage(LANG_YOU_CHANGE_LVL, nameLink.c_str(), newlevel);
}
return true;
}
// customize characters
static bool HandleCharacterCustomizeCommand(ChatHandler* handler, char const* args)
{
Player* target;
uint64 targetGuid;
std::string targetName;
if (!handler->extractPlayerTarget((char*)args, &target, &targetGuid, &targetName))
return false;
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ADD_AT_LOGIN_FLAG);
stmt->setUInt16(0, uint16(AT_LOGIN_CUSTOMIZE));
if (target)
{
handler->PSendSysMessage(LANG_CUSTOMIZE_PLAYER, handler->GetNameLink(target).c_str());
target->SetAtLoginFlag(AT_LOGIN_CUSTOMIZE);
stmt->setUInt32(1, target->GetGUIDLow());
}
else
{
std::string oldNameLink = handler->playerLink(targetName);
stmt->setUInt32(1, GUID_LOPART(targetGuid));
handler->PSendSysMessage(LANG_CUSTOMIZE_PLAYER_GUID, oldNameLink.c_str(), GUID_LOPART(targetGuid));
}
CharacterDatabase.Execute(stmt);
return true;
}
static bool HandleCharacterChangeFactionCommand(ChatHandler* handler, char const* args)
{
Player* target;
uint64 targetGuid;
std::string targetName;
if (!handler->extractPlayerTarget((char*)args, &target, &targetGuid, &targetName))
return false;
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ADD_AT_LOGIN_FLAG);
stmt->setUInt16(0, uint16(AT_LOGIN_CHANGE_FACTION));
if (target)
{
handler->PSendSysMessage(LANG_CUSTOMIZE_PLAYER, handler->GetNameLink(target).c_str());
target->SetAtLoginFlag(AT_LOGIN_CHANGE_FACTION);
stmt->setUInt32(1, target->GetGUIDLow());
}
else
{
std::string oldNameLink = handler->playerLink(targetName);
handler->PSendSysMessage(LANG_CUSTOMIZE_PLAYER_GUID, oldNameLink.c_str(), GUID_LOPART(targetGuid));
stmt->setUInt32(1, GUID_LOPART(targetGuid));
}
CharacterDatabase.Execute(stmt);
return true;
}
static bool HandleCharacterChangeRaceCommand(ChatHandler* handler, char const* args)
{
Player* target;
uint64 targetGuid;
std::string targetName;
if (!handler->extractPlayerTarget((char*)args, &target, &targetGuid, &targetName))
return false;
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ADD_AT_LOGIN_FLAG);
stmt->setUInt16(0, uint16(AT_LOGIN_CHANGE_RACE));
if (target)
{
// TODO : add text into database
handler->PSendSysMessage(LANG_CUSTOMIZE_PLAYER, handler->GetNameLink(target).c_str());
target->SetAtLoginFlag(AT_LOGIN_CHANGE_RACE);
stmt->setUInt32(1, target->GetGUIDLow());
}
else
{
std::string oldNameLink = handler->playerLink(targetName);
// TODO : add text into database
handler->PSendSysMessage(LANG_CUSTOMIZE_PLAYER_GUID, oldNameLink.c_str(), GUID_LOPART(targetGuid));
stmt->setUInt32(1, GUID_LOPART(targetGuid));
}
CharacterDatabase.Execute(stmt);
return true;
}
static bool HandleCharacterReputationCommand(ChatHandler* handler, char const* args)
{
Player* target;
if (!handler->extractPlayerTarget((char*)args, &target))
return false;
LocaleConstant loc = handler->GetSessionDbcLocale();
FactionStateList const& targetFSL = target->GetReputationMgr().GetStateList();
for (FactionStateList::const_iterator itr = targetFSL.begin(); itr != targetFSL.end(); ++itr)
{
FactionState const& faction = itr->second;
FactionEntry const* factionEntry = sFactionStore.LookupEntry(faction.ID);
char const* factionName = factionEntry ? factionEntry->name[loc] : "#Not found#";
ReputationRank rank = target->GetReputationMgr().GetRank(factionEntry);
std::string rankName = handler->GetTrinityString(ReputationRankStrIndex[rank]);
std::ostringstream ss;
if (handler->GetSession())
ss << faction.ID << " - |cffffffff|Hfaction:" << faction.ID << "|h[" << factionName << ' ' << localeNames[loc] << "]|h|r";
else
ss << faction.ID << " - " << factionName << ' ' << localeNames[loc];
ss << ' ' << rankName << " (" << target->GetReputationMgr().GetReputation(factionEntry) << ')';
if (faction.Flags & FACTION_FLAG_VISIBLE)
ss << handler->GetTrinityString(LANG_FACTION_VISIBLE);
if (faction.Flags & FACTION_FLAG_AT_WAR)
ss << handler->GetTrinityString(LANG_FACTION_ATWAR);
if (faction.Flags & FACTION_FLAG_PEACE_FORCED)
ss << handler->GetTrinityString(LANG_FACTION_PEACE_FORCED);
if (faction.Flags & FACTION_FLAG_HIDDEN)
ss << handler->GetTrinityString(LANG_FACTION_HIDDEN);
if (faction.Flags & FACTION_FLAG_INVISIBLE_FORCED)
ss << handler->GetTrinityString(LANG_FACTION_INVISIBLE_FORCED);
if (faction.Flags & FACTION_FLAG_INACTIVE)
ss << handler->GetTrinityString(LANG_FACTION_INACTIVE);
handler->SendSysMessage(ss.str().c_str());
}
return true;
}
static bool HandleLevelUpCommand(ChatHandler* handler, char const* args)
{
char* nameStr;
char* levelStr;
handler->extractOptFirstArg((char*)args, &nameStr, &levelStr);
// exception opt second arg: .character level $name
if (levelStr && isalpha(levelStr[0]))
{
nameStr = levelStr;
levelStr = NULL; // current level will used
}
Player* target;
uint64 targetGuid;
std::string targetName;
if (!handler->extractPlayerTarget(nameStr, &target, &targetGuid, &targetName))
return false;
int32 oldlevel = target ? target->getLevel() : Player::GetLevelFromStorage(targetGuid);
int32 addlevel = levelStr ? atoi(levelStr) : 1;
int32 newlevel = oldlevel + addlevel;
if (newlevel < 1)
newlevel = 1;
if (newlevel > STRONG_MAX_LEVEL) // hardcoded maximum level
newlevel = STRONG_MAX_LEVEL;
HandleCharacterLevel(target, targetGuid, oldlevel, newlevel, handler);
if (!handler->GetSession() || handler->GetSession()->GetPlayer() != target) // including chr == NULL
{
std::string nameLink = handler->playerLink(targetName);
handler->PSendSysMessage(LANG_YOU_CHANGE_LVL, nameLink.c_str(), newlevel);
}
return true;
}
static bool HandlePDumpLoadCommand(ChatHandler* handler, char const* args)
{
if (!*args)
return false;
char* fileStr = strtok((char*)args, " ");
if (!fileStr)
return false;
char* accountStr = strtok(NULL, " ");
if (!accountStr)
return false;
std::string accountName = accountStr;
if (!AccountMgr::normalizeString(accountName))
{
handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, accountName.c_str());
handler->SetSentErrorMessage(true);
return false;
}
uint32 accountId = AccountMgr::GetId(accountName);
if (!accountId)
{
accountId = atoi(accountStr); // use original string
if (!accountId)
{
handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, accountName.c_str());
handler->SetSentErrorMessage(true);
return false;
}
}
if (!AccountMgr::GetName(accountId, accountName))
{
handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, accountName.c_str());
handler->SetSentErrorMessage(true);
return false;
}
char* guidStr = NULL;
char* nameStr = strtok(NULL, " ");
std::string name;
if (nameStr)
{
name = nameStr;
// normalize the name if specified and check if it exists
if (!normalizePlayerName(name))
{
handler->PSendSysMessage(LANG_INVALID_CHARACTER_NAME);
handler->SetSentErrorMessage(true);
return false;
}
if (ObjectMgr::CheckPlayerName(name, true) != CHAR_NAME_SUCCESS)
{
handler->PSendSysMessage(LANG_INVALID_CHARACTER_NAME);
handler->SetSentErrorMessage(true);
return false;
}
guidStr = strtok(NULL, " ");
}
uint32 guid = 0;
if (guidStr)
{
guid = uint32(atoi(guidStr));
if (!guid)
{
handler->PSendSysMessage(LANG_INVALID_CHARACTER_GUID);
handler->SetSentErrorMessage(true);
return false;
}
if (sObjectMgr->GetPlayerAccountIdByGUID(guid))
{
handler->PSendSysMessage(LANG_CHARACTER_GUID_IN_USE, guid);
handler->SetSentErrorMessage(true);
return false;
}
}
switch (PlayerDumpReader().LoadDump(fileStr, accountId, name, guid))
{
case DUMP_SUCCESS:
handler->PSendSysMessage(LANG_COMMAND_IMPORT_SUCCESS);
break;
case DUMP_FILE_OPEN_ERROR:
handler->PSendSysMessage(LANG_FILE_OPEN_FAIL, fileStr);
handler->SetSentErrorMessage(true);
return false;
case DUMP_FILE_BROKEN:
handler->PSendSysMessage(LANG_DUMP_BROKEN, fileStr);
handler->SetSentErrorMessage(true);
return false;
case DUMP_TOO_MANY_CHARS:
handler->PSendSysMessage(LANG_ACCOUNT_CHARACTER_LIST_FULL, accountName.c_str(), accountId);
handler->SetSentErrorMessage(true);
return false;
default:
handler->PSendSysMessage(LANG_COMMAND_IMPORT_FAILED);
handler->SetSentErrorMessage(true);
return false;
}
return true;
}
static bool HandlePDumpWriteCommand(ChatHandler* handler, char const* args)
{
if (!*args)
return false;
char* fileStr = strtok((char*)args, " ");
char* playerStr = strtok(NULL, " ");
if (!fileStr && !playerStr)
{
QueryResult result = CharacterDatabase.PQuery("SELECT guid FROM characters");
if (!result)
return true;
do{
uint64 _guid = result->Fetch()[0].GetUInt64();
char buff[20];
sprintf(buff,"%I64u", _guid);
switch(PlayerDumpWriter().WriteDump(buff, uint32(_guid)))
{
case DUMP_SUCCESS:
handler->PSendSysMessage(LANG_COMMAND_EXPORT_SUCCESS);
break;
case DUMP_FILE_OPEN_ERROR:
handler->PSendSysMessage(LANG_FILE_OPEN_FAIL, buff);
handler->SetSentErrorMessage(true);
return false;
case DUMP_CHARACTER_DELETED:
handler->PSendSysMessage(LANG_COMMAND_EXPORT_DELETED_CHAR);
handler->SetSentErrorMessage(true);
return false;
default:
handler->PSendSysMessage(LANG_COMMAND_EXPORT_FAILED);
handler->SetSentErrorMessage(true);
return false;
}
}while(result->NextRow());
}
if (!fileStr || !playerStr)
return false;
uint64 guid;
// character name can't start from number
if (isNumeric(playerStr))
guid = MAKE_NEW_GUID(atoi(playerStr), 0, HIGHGUID_PLAYER);
else
{
std::string name = handler->extractPlayerNameFromLink(playerStr);
if (name.empty())
{
handler->SendSysMessage(LANG_PLAYER_NOT_FOUND);
handler->SetSentErrorMessage(true);
return false;
}
guid = sObjectMgr->GetPlayerGUIDByName(name);
}
if (!sObjectMgr->GetPlayerAccountIdByGUID(guid))
{
handler->PSendSysMessage(LANG_PLAYER_NOT_FOUND);
handler->SetSentErrorMessage(true);
return false;
}
switch (PlayerDumpWriter().WriteDump(fileStr, uint32(guid)))
{
case DUMP_SUCCESS:
handler->PSendSysMessage(LANG_COMMAND_EXPORT_SUCCESS);
break;
case DUMP_FILE_OPEN_ERROR:
handler->PSendSysMessage(LANG_FILE_OPEN_FAIL, fileStr);
handler->SetSentErrorMessage(true);
return false;
case DUMP_CHARACTER_DELETED:
handler->PSendSysMessage(LANG_COMMAND_EXPORT_DELETED_CHAR);
handler->SetSentErrorMessage(true);
return false;
default:
handler->PSendSysMessage(LANG_COMMAND_EXPORT_FAILED);
handler->SetSentErrorMessage(true);
return false;
}
return true;
}
};
void AddSC_character_commandscript()
{
new character_commandscript();
}