diff --git a/data/sql/updates/db_world/2018_12_01_00.sql b/data/sql/updates/db_world/2018_12_01_00.sql new file mode 100644 index 000000000..9693d15cf --- /dev/null +++ b/data/sql/updates/db_world/2018_12_01_00.sql @@ -0,0 +1,39 @@ +-- DB update 2018_11_25_00 -> 2018_12_01_00 +DROP PROCEDURE IF EXISTS `updateDb`; +DELIMITER // +CREATE PROCEDURE updateDb () +proc:BEGIN DECLARE OK VARCHAR(100) DEFAULT 'FALSE'; +SELECT COUNT(*) INTO @COLEXISTS +FROM information_schema.COLUMNS +WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'version_db_world' AND COLUMN_NAME = '2018_11_25_00'; +IF @COLEXISTS = 0 THEN LEAVE proc; END IF; +START TRANSACTION; +ALTER TABLE version_db_world CHANGE COLUMN 2018_11_25_00 2018_12_01_00 bit; +SELECT sql_rev INTO OK FROM version_db_world WHERE sql_rev = '1543682164947860900'; IF OK <> 'FALSE' THEN LEAVE proc; END IF; +-- +-- START UPDATING QUERIES +-- + +INSERT INTO version_db_world (`sql_rev`) VALUES ('1543682164947860900'); +INSERT INTO `trinity_string`(`entry`, `content_default`, `content_loc1`, `content_loc2`, `content_loc3`, `content_loc4`, `content_loc5`, `content_loc6`, `content_loc7`, `content_loc8`) VALUES (35400, '│Player %s %s (guid: %u)', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `trinity_string`(`entry`, `content_default`, `content_loc1`, `content_loc2`, `content_loc3`, `content_loc4`, `content_loc5`, `content_loc6`, `content_loc7`, `content_loc8`) VALUES (35401, '│ GM Mode active, Phase: -1', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `trinity_string`(`entry`, `content_default`, `content_loc1`, `content_loc2`, `content_loc3`, `content_loc4`, `content_loc5`, `content_loc6`, `content_loc7`, `content_loc8`) VALUES (35402, '├─ Banned: (Type: %s, Reason: %s, Time: %s, By: %s)', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `trinity_string`(`entry`, `content_default`, `content_loc1`, `content_loc2`, `content_loc3`, `content_loc4`, `content_loc5`, `content_loc6`, `content_loc7`, `content_loc8`) VALUES (35403, '├─ Muted: (Reason: %s, Time: %s, By: %s)', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `trinity_string`(`entry`, `content_default`, `content_loc1`, `content_loc2`, `content_loc3`, `content_loc4`, `content_loc5`, `content_loc6`, `content_loc7`, `content_loc8`) VALUES (35404, '│ Account: %s (ID: %u), GMLevel: %u', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `trinity_string`(`entry`, `content_default`, `content_loc1`, `content_loc2`, `content_loc3`, `content_loc4`, `content_loc5`, `content_loc6`, `content_loc7`, `content_loc8`) VALUES (35405, '│ Last Login: %s (Failed Logins: %u)', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `trinity_string`(`entry`, `content_default`, `content_loc1`, `content_loc2`, `content_loc3`, `content_loc4`, `content_loc5`, `content_loc6`, `content_loc7`, `content_loc8`) VALUES (35406, '└ Registration Email: %s - Email: %s', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +UPDATE `trinity_string` SET `content_default` = '│ Map: %s, Zone: %s' WHERE `entry` = 848; +UPDATE `trinity_string` SET `content_default` = '│ Mails: %d Read/%u Total' WHERE `entry` = 854; +INSERT INTO `trinity_string`(`entry`, `content_default`) VALUES (35407, 'No reason given.'); +INSERT INTO `trinity_string`(`entry`, `content_default`, `content_loc1`, `content_loc2`, `content_loc3`, `content_loc4`, `content_loc5`, `content_loc6`, `content_loc7`, `content_loc8`) VALUES (35408, '', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `trinity_string`(`entry`, `content_default`, `content_loc1`, `content_loc2`, `content_loc3`, `content_loc4`, `content_loc5`, `content_loc6`, `content_loc7`, `content_loc8`) VALUES (35409, '│ Map: %s, Zone: %s, Area: %s', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + +-- +-- END UPDATING QUERIES +-- +COMMIT; +END // +DELIMITER ; +CALL updateDb(); +DROP PROCEDURE IF EXISTS `updateDb`; + diff --git a/src/common/Database/Implementation/CharacterDatabase.cpp b/src/common/Database/Implementation/CharacterDatabase.cpp index 1bc091237..24bc308e5 100644 --- a/src/common/Database/Implementation/CharacterDatabase.cpp +++ b/src/common/Database/Implementation/CharacterDatabase.cpp @@ -381,8 +381,10 @@ void CharacterDatabaseConnection::DoPrepareStatements() PrepareStatement(CHAR_SEL_CHAR_DEL_INFO_BY_NAME, "SELECT guid, deleteInfos_Name, deleteInfos_Account, deleteDate FROM characters WHERE deleteDate IS NOT NULL AND deleteInfos_Name LIKE CONCAT('%%', ?, '%%')", CONNECTION_SYNCH); PrepareStatement(CHAR_SEL_CHAR_DEL_INFO, "SELECT guid, deleteInfos_Name, deleteInfos_Account, deleteDate FROM characters WHERE deleteDate IS NOT NULL", CONNECTION_SYNCH); PrepareStatement(CHAR_SEL_CHARS_BY_ACCOUNT_ID, "SELECT guid FROM characters WHERE account = ?", CONNECTION_SYNCH); - PrepareStatement(CHAR_SEL_CHAR_PINFO, "SELECT totaltime, level, money, account, race, class, map, zone FROM characters WHERE guid = ?", CONNECTION_SYNCH); + PrepareStatement(CHAR_SEL_CHAR_PINFO, "SELECT totaltime, level, money, account, race, class, map, zone, gender, health, playerFlags FROM characters WHERE guid = ?", CONNECTION_SYNCH); PrepareStatement(CHAR_SEL_PINFO_BANS, "SELECT unbandate, bandate = unbandate, bannedby, banreason FROM character_banned WHERE guid = ? AND active ORDER BY bandate ASC LIMIT 1", CONNECTION_SYNCH); + PrepareStatement(CHAR_SEL_PINFO_MAILS, "SELECT SUM(CASE WHEN (checked & 1) THEN 1 ELSE 0 END) AS 'readmail', COUNT(*) AS 'totalmail' FROM mail WHERE `receiver` = ?", CONNECTION_SYNCH); + PrepareStatement(CHAR_SEL_PINFO_XP, "SELECT a.xp, b.guid FROM characters a LEFT JOIN guild_member b ON a.guid = b.guid WHERE a.guid = ?", CONNECTION_SYNCH); PrepareStatement(CHAR_SEL_CHAR_HOMEBIND, "SELECT mapId, zoneId, posX, posY, posZ FROM character_homebind WHERE guid = ?", CONNECTION_SYNCH); PrepareStatement(CHAR_SEL_CHAR_GUID_NAME_BY_ACC, "SELECT guid, name FROM characters WHERE account = ?", CONNECTION_SYNCH); PrepareStatement(CHAR_SEL_POOL_QUEST_SAVE, "SELECT quest_id FROM pool_quest_save WHERE pool_id = ?", CONNECTION_SYNCH); diff --git a/src/common/Database/Implementation/CharacterDatabase.h b/src/common/Database/Implementation/CharacterDatabase.h index 8a7480d81..ae7707871 100644 --- a/src/common/Database/Implementation/CharacterDatabase.h +++ b/src/common/Database/Implementation/CharacterDatabase.h @@ -330,6 +330,8 @@ enum CharacterDatabaseStatements CHAR_SEL_CHARS_BY_ACCOUNT_ID, CHAR_SEL_CHAR_PINFO, + CHAR_SEL_PINFO_XP, + CHAR_SEL_PINFO_MAILS, CHAR_SEL_PINFO_BANS, CHAR_SEL_CHAR_HOMEBIND, CHAR_SEL_CHAR_GUID_NAME_BY_ACC, diff --git a/src/common/Database/Implementation/LoginDatabase.cpp b/src/common/Database/Implementation/LoginDatabase.cpp index 48ae612f0..86cb43b78 100644 --- a/src/common/Database/Implementation/LoginDatabase.cpp +++ b/src/common/Database/Implementation/LoginDatabase.cpp @@ -68,7 +68,7 @@ void LoginDatabaseConnection::DoPrepareStatements() PrepareStatement(LOGIN_GET_USERNAME_BY_ID, "SELECT username FROM account WHERE id = ?", CONNECTION_SYNCH); PrepareStatement(LOGIN_SEL_CHECK_PASSWORD, "SELECT 1 FROM account WHERE id = ? AND sha_pass_hash = ?", CONNECTION_SYNCH); PrepareStatement(LOGIN_SEL_CHECK_PASSWORD_BY_NAME, "SELECT 1 FROM account WHERE username = ? AND sha_pass_hash = ?", CONNECTION_SYNCH); - PrepareStatement(LOGIN_SEL_PINFO, "SELECT a.username, aa.gmlevel, a.email, a.last_ip, DATE_FORMAT(a.last_login, '%Y-%m-%d %T'), a.mutetime, a.mutereason, a.muteby FROM account a LEFT JOIN account_access aa ON (a.id = aa.id AND (aa.RealmID = ? OR aa.RealmID = -1)) WHERE a.id = ?", CONNECTION_SYNCH); + PrepareStatement(LOGIN_SEL_PINFO, "SELECT a.username, aa.gmlevel, a.email, a.reg_mail, a.last_ip, DATE_FORMAT(a.last_login, '%Y-%m-%d %T'), a.mutetime, a.mutereason, a.muteby, a.failed_logins, a.locked, a.OS FROM account a LEFT JOIN account_access aa ON (a.id = aa.id AND (aa.RealmID = ? OR aa.RealmID = -1)) WHERE a.id = ?", CONNECTION_SYNCH); PrepareStatement(LOGIN_SEL_PINFO_BANS, "SELECT unbandate, bandate = unbandate, bannedby, banreason FROM account_banned WHERE id = ? AND active ORDER BY bandate ASC LIMIT 1", CONNECTION_SYNCH); PrepareStatement(LOGIN_SEL_GM_ACCOUNTS, "SELECT a.username, aa.gmlevel FROM account a, account_access aa WHERE a.id=aa.id AND aa.gmlevel >= ? AND (aa.realmid = -1 OR aa.realmid = ?)", CONNECTION_SYNCH); PrepareStatement(LOGIN_SEL_ACCOUNT_INFO, "SELECT a.username, a.last_ip, aa.gmlevel, a.expansion FROM account a LEFT JOIN account_access aa ON (a.id = aa.id) WHERE a.id = ?", CONNECTION_SYNCH); diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h index 9a00adb1c..f74b4926d 100644 --- a/src/server/game/Miscellaneous/Language.h +++ b/src/server/game/Miscellaneous/Language.h @@ -789,14 +789,14 @@ enum TrinityStrings LANG_NPCINFO_PLAYER_VEHICLE = 842, // Pinfo commands - LANG_PINFO_PLAYER = 453, - LANG_PINFO_GM_ACTIVE = 548, - LANG_PINFO_BANNED = 549, - LANG_PINFO_MUTED = 550, - LANG_PINFO_ACC_ACCOUNT = 714, - LANG_PINFO_ACC_LASTLOGIN = 716, + LANG_PINFO_PLAYER = 35400, + LANG_PINFO_GM_ACTIVE = 35401, + LANG_PINFO_BANNED = 35402, + LANG_PINFO_MUTED = 35403, + LANG_PINFO_ACC_ACCOUNT = 35404, + LANG_PINFO_ACC_LASTLOGIN = 35405, LANG_PINFO_ACC_OS = 749, - LANG_PINFO_ACC_REGMAILS = 879, + LANG_PINFO_ACC_REGMAILS = 35406, LANG_PINFO_ACC_IP = 752, LANG_PINFO_CHR_LEVEL_LOW = 843, LANG_PINFO_CHR_RACE = 844, @@ -811,6 +811,9 @@ enum TrinityStrings LANG_PINFO_CHR_PLAYEDTIME = 853, LANG_PINFO_CHR_MAILS = 854, LANG_PINFO_CHR_LEVEL_HIGH = 871, + LANG_NO_REASON = 35407, + LANG_UNAUTHORIZED = 35408, + LANG_PINFO_CHR_MAP_WITH_AREA = 35409, LANG_CHARACTER_GENDER_MALE = 855, LANG_CHARACTER_GENDER_FEMALE = 856, diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index dc6874a9c..2b83e83c9 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -1785,7 +1785,8 @@ public: Player* target; uint64 targetGuid; std::string targetName; - + PreparedStatement* stmt = nullptr; + uint32 parseGUID = MAKE_NEW_GUID(atol((char*)args), 0, HIGHGUID_PLAYER); if (sObjectMgr->GetPlayerNameByGUID(parseGUID, targetName)) @@ -1796,35 +1797,57 @@ public: else if (!handler->extractPlayerTarget((char*)args, &target, &targetGuid, &targetName)) return false; - uint32 accId = 0; - uint32 money = 0; - uint32 totalPlayerTime = 0; - uint8 level = 0; - uint32 latency = 0; - uint8 race; - uint8 Class; - int64 muteTime = 0; - int64 banTime = -1; + // Account data print variables + std::string userName = handler->GetTrinityString(LANG_ERROR); + uint32 accId = 0; + std::string eMail = handler->GetTrinityString(LANG_ERROR); + std::string regMail = handler->GetTrinityString(LANG_ERROR); + uint32 security = 0; + std::string lastIp = handler->GetTrinityString(LANG_ERROR); + uint8 locked = 0; + std::string lastLogin = handler->GetTrinityString(LANG_ERROR); + uint32 failedLogins = 0; + uint32 latency = 0; + std::string OS = handler->GetTrinityString(LANG_UNKNOWN); + + // Mute data print variables + int64 muteTime = -1; + std::string muteReason = handler->GetTrinityString(LANG_NO_REASON); + std::string muteBy = handler->GetTrinityString(LANG_UNKNOWN); + + // Ban data print variables + int64 banTime = -1; + std::string banType = handler->GetTrinityString(LANG_UNKNOWN); + std::string banReason = handler->GetTrinityString(LANG_NO_REASON); + std::string bannedBy = handler->GetTrinityString(LANG_UNKNOWN); + + // Character data print variables + uint8 raceid, classid = 0; //RACE_NONE, CLASS_NONE + std::string raceStr, classStr = handler->GetTrinityString(LANG_UNKNOWN); + uint8 gender = 0; + int8 locale = handler->GetSessionDbcLocale(); + uint32 totalPlayerTime = 0; + uint8 level = 0; + std::string alive = handler->GetTrinityString(LANG_ERROR); + uint32 money = 0; + uint32 xp = 0; + uint32 xptotal = 0; + + // Position data print uint32 mapId; uint32 areaId; uint32 phase = 0; - - // pussywizard: guild info - std::string guildName = ""; - bool guildIsLeader = false; - uint64 guildMoney = 0; - uint32 guildMemberCount = 0; - if (const GlobalPlayerData* gpd = sWorld->GetGlobalPlayerData(targetGuid)) - if (gpd->guildId) - if (Guild* targetGuild = sGuildMgr->GetGuildById(gpd->guildId)) - { - guildName = targetGuild->GetName(); - guildMoney = targetGuild->GetTotalBankMoney(); - guildMemberCount = targetGuild->GetMemberCount(); - if (targetGuild->GetLeaderGUID() == targetGuid) - guildIsLeader = true; - } - + char const* areaName = nullptr; + char const* zoneName = nullptr; + + // Guild data print variables defined so that they exist, but are not necessarily used + uint32 guildId = 0; + uint8 guildRankId = 0; + std::string guildName; + std::string guildRank; + std::string note; + std::string officeNote; + // get additional information from Player object if (target) { @@ -1837,11 +1860,13 @@ public: totalPlayerTime = target->GetTotalPlayedTime(); level = target->getLevel(); latency = target->GetSession()->GetLatency(); - race = target->getRace(); - Class = target->getClass(); + raceid = target->getRace(); + classid = target->getClass(); muteTime = target->GetSession()->m_muteTime; mapId = target->GetMapId(); areaId = target->GetAreaId(); + alive = target->IsAlive() ? handler->GetTrinityString(LANG_YES) : handler->GetTrinityString(LANG_NO); + gender = target->getGender(); phase = target->GetPhaseMask(); } // get additional information from DB @@ -1851,33 +1876,35 @@ public: if (handler->HasLowerSecurity(nullptr, targetGuid)) return false; - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_PINFO); + // Query informations from the DB + stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_PINFO); stmt->setUInt32(0, GUID_LOPART(targetGuid)); PreparedQueryResult result = CharacterDatabase.Query(stmt); if (!result) return false; - Field* fields = result->Fetch(); - totalPlayerTime = fields[0].GetUInt32(); - level = fields[1].GetUInt8(); - money = fields[2].GetUInt32(); - accId = fields[3].GetUInt32(); - race = fields[4].GetUInt8(); - Class = fields[5].GetUInt8(); - mapId = fields[6].GetUInt16(); - areaId = fields[7].GetUInt16(); + Field* fields = result->Fetch(); + totalPlayerTime = fields[0].GetUInt32(); + level = fields[1].GetUInt8(); + money = fields[2].GetUInt32(); + accId = fields[3].GetUInt32(); + raceid = fields[4].GetUInt8(); + classid = fields[5].GetUInt8(); + mapId = fields[6].GetUInt16(); + areaId = fields[7].GetUInt16(); + gender = fields[8].GetUInt8(); + uint32 health = fields[9].GetUInt32(); + uint32 playerFlags = fields[10].GetUInt32(); + + if (!health || playerFlags & PLAYER_FLAGS_GHOST) + alive = handler->GetTrinityString(LANG_NO); + else + alive = handler->GetTrinityString(LANG_YES); } - - std::string userName = handler->GetTrinityString(LANG_ERROR); - std::string eMail = handler->GetTrinityString(LANG_ERROR); - std::string muteReason = ""; - std::string muteBy = ""; - std::string lastIp = handler->GetTrinityString(LANG_ERROR); - uint32 security = 0; - std::string lastLogin = handler->GetTrinityString(LANG_ERROR); - - PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_PINFO); + + // Query the prepared statement for login data + stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_PINFO); stmt->setInt32(0, int32(realmID)); stmt->setUInt32(1, accId); PreparedQueryResult result = LoginDatabase.Query(stmt); @@ -1887,24 +1914,27 @@ public: Field* fields = result->Fetch(); userName = fields[0].GetString(); security = fields[1].GetUInt8(); - eMail = fields[2].GetString(); - muteTime = fields[5].GetUInt64(); - muteReason = fields[6].GetString(); - muteBy = fields[7].GetString(); - - if (eMail.empty()) - eMail = "-"; + // Only fetch these fields if commander has sufficient rights) if (!handler->GetSession() || handler->GetSession()->GetSecurity() >= AccountTypes(security)) { - lastIp = fields[3].GetString(); - lastLogin = fields[4].GetString(); + eMail = fields[2].GetString(); + regMail = fields[3].GetString(); + lastIp = fields[4].GetString(); + lastLogin = fields[5].GetString(); - uint32 ip = inet_addr(lastIp.c_str()); + /** if (IpLocationRecord const* location = sIPLocation->GetLocationRecord(lastIp)) + { + lastIp.append(" ("); + lastIp.append(location->CountryName); + lastIp.append(")"); + } **/ + + uint32 ip = inet_addr(lastIp.c_str()); #if TRINITY_ENDIAN == BIGENDIAN EndianConvertReverse(ip); #endif - PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_IP2NATION_COUNTRY); + stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_IP2NATION_COUNTRY); stmt->setUInt32(0, ip); @@ -1920,23 +1950,29 @@ public: } else { - lastIp = "-"; - lastLogin = "-"; + eMail = handler->GetTrinityString(LANG_UNAUTHORIZED); + regMail = handler->GetTrinityString(LANG_UNAUTHORIZED); + lastIp = handler->GetTrinityString(LANG_UNAUTHORIZED); + lastLogin = handler->GetTrinityString(LANG_UNAUTHORIZED); } + muteTime = fields[6].GetUInt64(); + muteReason = fields[7].GetString(); + muteBy = fields[8].GetString(); + failedLogins = fields[9].GetUInt32(); + locked = fields[10].GetUInt8(); + OS = fields[11].GetString(); } - + + // Creates a chat link to the character. Returns nameLink std::string nameLink = handler->playerLink(targetName); - handler->PSendSysMessage(LANG_PINFO_ACCOUNT, (target ? "" : handler->GetTrinityString(LANG_OFFLINE)), nameLink.c_str(), GUID_LOPART(targetGuid), userName.c_str(), accId, eMail.c_str(), security, lastIp.c_str(), lastLogin.c_str(), latency); - - std::string bannedby = "unknown"; - std::string banreason = ""; - - stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_PINFO_BANS); - stmt->setUInt32(0, accId); - PreparedQueryResult result2 = LoginDatabase.Query(stmt); + // Returns banType, banTime, bannedBy, banreason + PreparedStatement* stmt2 = LoginDatabase.GetPreparedStatement(LOGIN_SEL_PINFO_BANS); + stmt2->setUInt32(0, accId); + PreparedQueryResult result2 = LoginDatabase.Query(stmt2); if (!result2) { + banType = handler->GetTrinityString(LANG_CHARACTER); stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PINFO_BANS); stmt->setUInt32(0, GUID_LOPART(targetGuid)); result2 = CharacterDatabase.Query(stmt); @@ -1946,18 +1982,49 @@ public: { Field* fields = result2->Fetch(); banTime = int64(fields[1].GetUInt64() ? 0 : fields[0].GetUInt32()); - bannedby = fields[2].GetString(); - banreason = fields[3].GetString(); + bannedBy = fields[2].GetString(); + banReason = fields[3].GetString(); } - - if (muteTime > 0 && muteTime > time(nullptr)) - handler->PSendSysMessage(LANG_PINFO_MUTE, secsToTimeString(muteTime - time(nullptr), true).c_str(), muteBy.c_str(), muteReason.c_str()); - + + // Initiate output + // Output I. LANG_PINFO_PLAYER + handler->PSendSysMessage(LANG_PINFO_PLAYER, target ? "" : handler->GetTrinityString(LANG_OFFLINE), nameLink.c_str(), GUID_LOPART(targetGuid)); + + // Output II. LANG_PINFO_GM_ACTIVE if character is gamemaster + if (target && target->IsGameMaster()) + handler->PSendSysMessage(LANG_PINFO_GM_ACTIVE); + + // Output III. LANG_PINFO_BANNED if ban exists and is applied if (banTime >= 0) - handler->PSendSysMessage(LANG_PINFO_BAN, banTime > 0 ? secsToTimeString(banTime - time(nullptr), true).c_str() : "permanently", bannedby.c_str(), banreason.c_str()); + handler->PSendSysMessage(LANG_PINFO_BANNED, banType.c_str(), banReason.c_str(), banTime > 0 ? secsToTimeString(banTime - time(nullptr), true).c_str() : handler->GetTrinityString(LANG_PERMANENTLY), bannedBy.c_str()); + + // Output IV. LANG_PINFO_MUTED if mute is applied + if (muteTime > 0) + handler->PSendSysMessage(LANG_PINFO_MUTED, muteReason.c_str(), secsToTimeString(muteTime - time(nullptr), true).c_str(), muteBy.c_str()); - std::string raceStr, ClassStr; - switch (race) + // Output V. LANG_PINFO_ACC_ACCOUNT + handler->PSendSysMessage(LANG_PINFO_ACC_ACCOUNT, userName.c_str(), accId, security); + + // Output VI. LANG_PINFO_ACC_LASTLOGIN + handler->PSendSysMessage(LANG_PINFO_ACC_LASTLOGIN, lastLogin.c_str(), failedLogins); + + // Output VII. LANG_PINFO_ACC_OS + handler->PSendSysMessage(LANG_PINFO_ACC_OS, OS.c_str(), latency); + + // Output VIII. LANG_PINFO_ACC_REGMAILS + handler->PSendSysMessage(LANG_PINFO_ACC_REGMAILS, regMail.c_str(), eMail.c_str()); + + // Output IX. LANG_PINFO_ACC_IP + handler->PSendSysMessage(LANG_PINFO_ACC_IP, lastIp.c_str(), locked ? handler->GetTrinityString(LANG_YES) : handler->GetTrinityString(LANG_NO)); + + // Output X. LANG_PINFO_CHR_LEVEL + if (level != sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL)) + handler->PSendSysMessage(LANG_PINFO_CHR_LEVEL_LOW, level, xp, xptotal, (xptotal - xp)); + else + handler->PSendSysMessage(LANG_PINFO_CHR_LEVEL_HIGH, level); + + // Output XI. LANG_PINFO_CHR_RACE + switch (raceid) { case RACE_HUMAN: raceStr = "Human"; @@ -1991,79 +2058,107 @@ public: break; } - switch (Class) + switch (classid) { case CLASS_WARRIOR: - ClassStr = "Warrior"; + classStr = "Warrior"; break; case CLASS_PALADIN: - ClassStr = "Paladin"; + classStr = "Paladin"; break; case CLASS_HUNTER: - ClassStr = "Hunter"; + classStr = "Hunter"; break; case CLASS_ROGUE: - ClassStr = "Rogue"; + classStr = "Rogue"; break; case CLASS_PRIEST: - ClassStr = "Priest"; + classStr = "Priest"; break; case CLASS_DEATH_KNIGHT: - ClassStr = "Death Knight"; + classStr = "Death Knight"; break; case CLASS_SHAMAN: - ClassStr = "Shaman"; + classStr = "Shaman"; break; case CLASS_MAGE: - ClassStr = "Mage"; + classStr = "Mage"; break; case CLASS_WARLOCK: - ClassStr = "Warlock"; + classStr = "Warlock"; break; case CLASS_DRUID: - ClassStr = "Druid"; + classStr = "Druid"; break; } + + + handler->PSendSysMessage(LANG_PINFO_CHR_RACE, (gender == 0 ? handler->GetTrinityString(LANG_CHARACTER_GENDER_MALE) : handler->GetTrinityString(LANG_CHARACTER_GENDER_FEMALE)), raceStr.c_str(), classStr.c_str()); - std::string timeStr = secsToTimeString(totalPlayerTime, true); - uint32 gold = money /GOLD; - uint32 silv = (money % GOLD) / SILVER; - uint32 copp = (money % GOLD) % SILVER; - handler->PSendSysMessage(LANG_PINFO_LEVEL, raceStr.c_str(), ClassStr.c_str(), timeStr.c_str(), level, gold, silv, copp); + // Output XII. LANG_PINFO_CHR_ALIVE + handler->PSendSysMessage(LANG_PINFO_CHR_ALIVE, alive.c_str()); - // Add map, zone, subzone and phase to output - int locale = handler->GetSessionDbcLocale(); - std::string areaName = ""; - std::string zoneName = ""; + // Output XIII. LANG_PINFO_CHR_PHASE if player is not in GM mode (GM is in every phase) + if (target && !target->IsGameMaster()) // IsInWorld() returns false on loadingscreen, so it's more + handler->PSendSysMessage(LANG_PINFO_CHR_PHASE, phase); // precise than just target (safer ?). + // However, as we usually just require a target here, we use target instead. + // Output XIV. LANG_PINFO_CHR_MONEY + uint32 gold = money / GOLD; + uint32 silv = (money % GOLD) / SILVER; + uint32 copp = (money % GOLD) % SILVER; + handler->PSendSysMessage(LANG_PINFO_CHR_MONEY, gold, silv, copp); + // Position data MapEntry const* map = sMapStore.LookupEntry(mapId); - AreaTableEntry const* area = sAreaTableStore.LookupEntry(areaId); if (area) { - areaName = area->area_name[locale]; + zoneName = area->area_name[locale]; AreaTableEntry const* zone = sAreaTableStore.LookupEntry(area->zone); if (zone) + { + areaName = zoneName; zoneName = zone->area_name[locale]; + } } - if (target) - { - if (!zoneName.empty()) - handler->PSendSysMessage(LANG_PINFO_MAP_ONLINE, map->name[locale], zoneName.c_str(), areaName.c_str(), phase); - else - handler->PSendSysMessage(LANG_PINFO_MAP_ONLINE, map->name[locale], areaName.c_str(), "", phase); - } + if (!zoneName) + zoneName = handler->GetTrinityString(LANG_UNKNOWN); + + if (areaName) + handler->PSendSysMessage(LANG_PINFO_CHR_MAP_WITH_AREA, map->name[locale], zoneName, areaName); else - handler->PSendSysMessage(LANG_PINFO_MAP_OFFLINE, map->name[locale], areaName.c_str()); + handler->PSendSysMessage(LANG_PINFO_CHR_MAP, map->name[locale], zoneName); + // Output XVII. - XVIX. if they are not empty if (!guildName.empty()) { - uint32 gold = guildMoney /GOLD; - uint32 silv = (guildMoney % GOLD) / SILVER; - uint32 copp = (guildMoney % GOLD) % SILVER; - handler->PSendSysMessage("Guild: %s, members: %u, gb money: %ug %us %uc, is guild leader: %s", guildName.c_str(), guildMemberCount, gold, silv, copp, guildIsLeader ? "yes" : "no"); + handler->PSendSysMessage(LANG_PINFO_CHR_GUILD, guildName.c_str(), guildId); + handler->PSendSysMessage(LANG_PINFO_CHR_GUILD_RANK, guildRank.c_str(), uint32(guildRankId)); + if (!note.empty()) + handler->PSendSysMessage(LANG_PINFO_CHR_GUILD_NOTE, note.c_str()); + if (!officeNote.empty()) + handler->PSendSysMessage(LANG_PINFO_CHR_GUILD_ONOTE, officeNote.c_str()); + } + + // Output XX. LANG_PINFO_CHR_PLAYEDTIME + handler->PSendSysMessage(LANG_PINFO_CHR_PLAYEDTIME, (secsToTimeString(totalPlayerTime, true)).c_str()); + + // Mail Data - an own query, because it may or may not be useful. + // SQL: "SELECT SUM(CASE WHEN (checked & 1) THEN 1 ELSE 0 END) AS 'readmail', COUNT(*) AS 'totalmail' FROM mail WHERE `receiver` = ?" + PreparedStatement* stmt4 = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PINFO_MAILS); + stmt4->setUInt32(0, GUID_LOPART(targetGuid)); + PreparedQueryResult result6 = CharacterDatabase.Query(stmt4); + if (result6) + { + Field* fields = result6->Fetch(); + uint32 readmail = uint32(fields[0].GetDouble()); + uint32 totalmail = uint32(fields[1].GetUInt64()); + + // Output XXI. LANG_INFO_CHR_MAILS if at least one mail is given + if (totalmail >= 1) + handler->PSendSysMessage(LANG_PINFO_CHR_MAILS, readmail, totalmail); } return true;