diff --git a/sql/mangos.sql b/sql/mangos.sql index 68d910f58..47f952cc7 100644 --- a/sql/mangos.sql +++ b/sql/mangos.sql @@ -24,7 +24,7 @@ CREATE TABLE `db_version` ( `version` varchar(120) default NULL, `creature_ai_version` varchar(120) default NULL, `cache_id` int(10) default '0', - `required_12150_01_mangos_mangos_string` bit(1) default NULL + `required_12164_01_mangos_command` bit(1) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes'; -- @@ -619,6 +619,7 @@ INSERT INTO `command` VALUES ('hidearea',3,'Syntax: .hidearea #areaid\r\n\r\nHide the area of #areaid to the selected character. If no character is selected, hide this area to you.'), ('honor add',2,'Syntax: .honor add $amount\r\n\r\nAdd a certain amount of honor (gained today) to the selected player.'), ('honor addkill',2,'Syntax: .honor addkill\r\n\r\nAdd the targeted unit as one of your pvp kills today (you only get honor if it\'s a racial leader or a player)'), +('honor updatekills',2,'Syntax: .honor updatekills\r\n\r\nForce the yesterday\'s honor kill fields to be updated with today\'s data, which will get reset for the selected player.'), ('instance unbind',3,'Syntax: .instance unbind all\r\n All of the selected player\'s binds will be cleared.\r\n.instance unbind #mapid\r\n Only the specified #mapid instance will be cleared.'), ('instance listbinds',3,'Syntax: .instance listbinds\r\n Lists the binds of the selected player.'), ('instance stats',3,'Syntax: .instance stats\r\n Shows statistics about instances.'), diff --git a/sql/updates/12164_01_mangos_command.sql b/sql/updates/12164_01_mangos_command.sql new file mode 100644 index 000000000..52c649651 --- /dev/null +++ b/sql/updates/12164_01_mangos_command.sql @@ -0,0 +1,6 @@ +ALTER TABLE db_version CHANGE COLUMN required_12150_01_mangos_mangos_string required_12164_01_mangos_command bit; + + +DELETE FROM `command` WHERE `name` = 'honor updatekills'; +INSERT INTO `command` VALUE +('honor updatekills',2,'Syntax: .honor updatekills\r\n\r\nForce the yesterday\'s honor kill fields to be updated with today\'s data, which will get reset for the selected player.'); diff --git a/src/game/BattleGround/BattleGroundHandler.cpp b/src/game/BattleGround/BattleGroundHandler.cpp index e6939804a..eb6684377 100644 --- a/src/game/BattleGround/BattleGroundHandler.cpp +++ b/src/game/BattleGround/BattleGroundHandler.cpp @@ -818,3 +818,14 @@ void WorldSession::HandleReportPvPAFK(WorldPacket& recv_data) reportedPlayer->ReportedAfkBy(_player); } + +void WorldSession::HandleRequestPvPOptionsEnabled(WorldPacket& recv_data) +{ + // null packet + + WorldPacket data(SMSG_PVP_OPTIONS_ENABLED, 1); + for (int i = 0; i < 5; ++i) + data.WriteBit(true); + + SendPacket(&data); +} diff --git a/src/game/Chat.cpp b/src/game/Chat.cpp index 98e30815e..1d551622f 100644 --- a/src/game/Chat.cpp +++ b/src/game/Chat.cpp @@ -321,6 +321,7 @@ ChatCommand* ChatHandler::getCommandTable() { { "add", SEC_GAMEMASTER, false, &ChatHandler::HandleHonorAddCommand, "", NULL }, { "addkill", SEC_GAMEMASTER, false, &ChatHandler::HandleHonorAddKillCommand, "", NULL }, + { "updatekills", SEC_GAMEMASTER, false, &ChatHandler::HandleHonorKillsUpdateCommand, "", NULL }, { NULL, 0, false, NULL, "", NULL } }; diff --git a/src/game/Chat.h b/src/game/Chat.h index 17169a365..9353e386f 100644 --- a/src/game/Chat.h +++ b/src/game/Chat.h @@ -268,6 +268,7 @@ class MANGOS_DLL_SPEC ChatHandler bool HandleHonorAddCommand(char* args); bool HandleHonorAddKillCommand(char* args); + bool HandleHonorKillsUpdateCommand(char* args); bool HandleInstanceListBindsCommand(char* args); bool HandleInstanceUnbindCommand(char* args); diff --git a/src/game/Level1.cpp b/src/game/Level1.cpp index 6e852f868..ba6cb3bb2 100644 --- a/src/game/Level1.cpp +++ b/src/game/Level1.cpp @@ -140,8 +140,10 @@ bool ChatHandler::HandleNotifyCommand(char* args) std::string str = GetMangosString(LANG_GLOBAL_NOTIFY); str += args; - WorldPacket data(SMSG_NOTIFICATION, (str.size() + 1)); - data << str; + WorldPacket data(SMSG_NOTIFICATION, str.size() + 1); + data.WriteBits(str.length(), 13); + data.FlushBits(); + data.append(str.c_str(), str.length()); sWorld.SendGlobalMessage(&data); return true; diff --git a/src/game/Level2.cpp b/src/game/Level2.cpp index dcd4e279c..9b4782210 100644 --- a/src/game/Level2.cpp +++ b/src/game/Level2.cpp @@ -4147,6 +4147,24 @@ bool ChatHandler::HandleHonorAddKillCommand(char* /*args*/) return true; } +bool ChatHandler::HandleHonorKillsUpdateCommand(char* /*args*/) +{ + Player* target = getSelectedPlayer(); + if (!target) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + // check online security + if (HasLowerSecurity(target)) + return false; + + target->UpdateHonorKills(); + return true; +} + bool ChatHandler::HandleLookupEventCommand(char* args) { if (!*args) diff --git a/src/game/MiscHandler.cpp b/src/game/MiscHandler.cpp index 0a5ad1cfd..3806ef8d0 100644 --- a/src/game/MiscHandler.cpp +++ b/src/game/MiscHandler.cpp @@ -1138,23 +1138,25 @@ void WorldSession::HandleInspectOpcode(WorldPacket& recv_data) void WorldSession::HandleInspectHonorStatsOpcode(WorldPacket& recv_data) { ObjectGuid guid; - recv_data >> guid; + recv_data.ReadGuidMask<1, 5, 7, 3, 2, 4, 0, 6>(guid); + recv_data.ReadGuidBytes<4, 7, 0, 5, 1, 6, 2, 3>(guid); Player* player = sObjectMgr.GetPlayer(guid); - if (!player) { sLog.outError("InspectHonorStats: WTF, player not found..."); return; } - WorldPacket data(MSG_INSPECT_HONOR_STATS, 8 + 1 + 4 * 4); - data << player->GetObjectGuid(); - data << uint8(player->GetCurrencyCount(CURRENCY_HONOR_POINTS)); - data << uint32(player->GetUInt32Value(PLAYER_FIELD_KILLS)); - //data << uint32(player->GetUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION)); - //data << uint32(player->GetUInt32Value(PLAYER_FIELD_YESTERDAY_CONTRIBUTION)); + WorldPacket data(SMSG_INSPECT_HONOR_STATS, 18); + data.WriteGuidMask<4, 3, 6, 2, 5, 0, 7, 1>(player->GetObjectGuid()); + data << uint8(0); // rank + data << uint16(player->GetUInt16Value(PLAYER_FIELD_KILLS, 1)); // yesterday kills + data << uint16(player->GetUInt16Value(PLAYER_FIELD_KILLS, 0)); // today kills + data.WriteGuidBytes<2, 0, 6, 3, 4, 1, 5>(player->GetObjectGuid()); data << uint32(player->GetUInt32Value(PLAYER_FIELD_LIFETIME_HONORBALE_KILLS)); + data.WriteGuidBytes<7>(player->GetObjectGuid()); + SendPacket(&data); } diff --git a/src/game/Opcodes.cpp b/src/game/Opcodes.cpp index ac6120ee1..ce91a94d3 100644 --- a/src/game/Opcodes.cpp +++ b/src/game/Opcodes.cpp @@ -786,7 +786,8 @@ void InitializeOpcodes() //OPCODE(CMSG_BATTLEFIELD_STATUS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBattlefieldStatusOpcode ); //OPCODE(SMSG_BATTLEFIELD_STATUS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //OPCODE(CMSG_BATTLEFIELD_PORT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBattleFieldPortOpcode ); - //OPCODE(MSG_INSPECT_HONOR_STATS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleInspectHonorStatsOpcode ); + OPCODE(CMSG_INSPECT_HONOR_STATS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleInspectHonorStatsOpcode ); + OPCODE(SMSG_INSPECT_HONOR_STATS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //OPCODE(CMSG_BATTLEMASTER_HELLO, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBattlemasterHelloOpcode ); //OPCODE(CMSG_MOVE_START_SWIM_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); //OPCODE(CMSG_MOVE_STOP_SWIM_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); @@ -947,7 +948,7 @@ void InitializeOpcodes() OPCODE(CMSG_SET_TITLE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetTitleOpcode ); OPCODE(CMSG_CANCEL_MOUNT_AURA, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCancelMountAuraOpcode ); //OPCODE(SMSG_ARENA_ERROR, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - //OPCODE(MSG_INSPECT_ARENA_TEAMS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleInspectArenaTeamsOpcode ); + OPCODE(MSG_INSPECT_ARENA_TEAMS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleInspectArenaTeamsOpcode ); //OPCODE(SMSG_DEATH_RELEASE_LOC, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //OPCODE(CMSG_CANCEL_TEMP_ENCHANTMENT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCancelTempEnchantmentOpcode); //OPCODE(SMSG_FORCED_DEATH_UPDATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); @@ -1377,5 +1378,11 @@ void InitializeOpcodes() OPCODE(SMSG_SET_CURRENCY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); OPCODE(SMSG_SEND_CURRENCIES, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); OPCODE(CMSG_SET_CURRENCY_FLAGS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetCurrencyFlagsOpcode ); - OPCODE(SMSG_WEEKLY_RESET_CURRENCY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + OPCODE(SMSG_WEEKLY_RESET_CURRENCIES, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + //OPCODE(CMSG_INSPECT_RATED_BG_STATS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL ); + //OPCODE(CMSG_REQUEST_RATED_BG_INFO, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL ); + //OPCODE(CMSG_REQUEST_RATED_BG_STATS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL ); + //OPCODE(CMSG_REQUEST_PVP_REWARDS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL ); + OPCODE(CMSG_REQUEST_PVP_OPTIONS_ENABLED, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleRequestPvPOptionsEnabled ); + OPCODE(SMSG_PVP_OPTIONS_ENABLED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); }; diff --git a/src/game/Opcodes.h b/src/game/Opcodes.h index 728b8ceb5..a84e289bc 100644 --- a/src/game/Opcodes.h +++ b/src/game/Opcodes.h @@ -771,7 +771,8 @@ enum Opcodes CMSG_BATTLEFIELD_STATUS = 0x12D4, SMSG_BATTLEFIELD_STATUS = 0x12D5, CMSG_BATTLEFIELD_PORT = 0x12D6, - MSG_INSPECT_HONOR_STATS = 0x12D7, + CMSG_INSPECT_HONOR_STATS = 0x791E, // 4.3.4 15595 + SMSG_INSPECT_HONOR_STATS = 0x79A5, // 4.3.4 15595 CMSG_BATTLEMASTER_HELLO = 0x12D8, CMSG_MOVE_START_SWIM_CHEAT = 0x12D9, CMSG_MOVE_STOP_SWIM_CHEAT = 0x12DA, @@ -932,7 +933,7 @@ enum Opcodes CMSG_SET_TITLE = 0x2117, // 4.3.4 15595 CMSG_CANCEL_MOUNT_AURA = 0x0635, // 4.3.4 15595 SMSG_ARENA_ERROR = 0x1377, - MSG_INSPECT_ARENA_TEAMS = 0x1378, + MSG_INSPECT_ARENA_TEAMS = 0x2704, // 4.3.4 15595 SMSG_DEATH_RELEASE_LOC = 0x1379, CMSG_CANCEL_TEMP_ENCHANTMENT = 0x137A, SMSG_FORCED_DEATH_UPDATE = 0x137B, @@ -1395,7 +1396,13 @@ enum Opcodes SMSG_SET_CURRENCY = 0x59B0, // 4.3.4 15595 SMSG_SEND_CURRENCIES = 0x15A5, // 4.3.4 15595 CMSG_SET_CURRENCY_FLAGS = 0x7306, // 4.3.4 15595 - SMSG_WEEKLY_RESET_CURRENCY = 0x3CA1, // 4.3.4 15595 + SMSG_WEEKLY_RESET_CURRENCIES = 0x3CA1, // 4.3.4 15595 + CMSG_INSPECT_RATED_BG_STATS = 0x3010, // 4.3.4 15595 + CMSG_REQUEST_RATED_BG_INFO = 0x2423, // 4.3.4 15595 + CMSG_REQUEST_RATED_BG_STATS = 0x05B3, // 4.3.4 15595 + CMSG_REQUEST_PVP_REWARDS = 0x780C, // 4.3.4 15595 + CMSG_REQUEST_PVP_OPTIONS_ENABLED = 0x24A1, // 4.3.4 15595 + SMSG_PVP_OPTIONS_ENABLED = 0x50A1, // 4.3.4 15595 }; #define MAX_OPCODE_TABLE_SIZE 0xFFFF diff --git a/src/game/Player.cpp b/src/game/Player.cpp index b43f71323..9d04c59a9 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -554,6 +554,8 @@ Player::Player(WorldSession* session): Unit(), m_mover(this), m_camera(this), m_ m_armorPenetrationPct = 0.0f; m_spellPenetrationItemMod = 0; + m_lastHonorKillsUpdateTime = time(NULL); + // Player summoning m_summon_expire = 0; m_summon_mapid = 0; @@ -6531,6 +6533,35 @@ void Player::RewardReputation(Quest const* pQuest) // TODO: implement reputation spillover } +void Player::UpdateHonorKills() +{ + /// called when rewarding honor and at each save + time_t now = time(NULL); + time_t today = (time(NULL) / DAY) * DAY; + + if (m_lastHonorKillsUpdateTime < today) + { + time_t yesterday = today - DAY; + + uint16 kills_today = GetUInt16Value(PLAYER_FIELD_KILLS, 0); + + // update yesterday's contribution + if (m_lastHonorKillsUpdateTime >= yesterday) + { + // this is the first update today, reset today's contribution + SetUInt16Value(PLAYER_FIELD_KILLS, 0, 0); + SetUInt16Value(PLAYER_FIELD_KILLS, 1, kills_today); + } + else + { + // no honor/kills yesterday or today, reset + SetUInt32Value(PLAYER_FIELD_KILLS, 0); + } + } + + m_lastHonorKillsUpdateTime = now; +} + /// Calculate the amount of honor gained based on the victim /// and the size of the group for which the honor is divided /// An exact honor value can also be given (overriding the calcs) @@ -6555,6 +6586,9 @@ bool Player::RewardHonor(Unit* uVictim, uint32 groupsize, float honor) ObjectGuid victim_guid; uint32 victim_rank = 0; + // need call before fields update to have chance move yesterday data to appropriate fields before today data change. + UpdateHonorKills(); + if (honor <= 0) { if (!uVictim || uVictim == this || uVictim->HasAuraType(SPELL_AURA_NO_PVP_CREDIT)) @@ -15333,8 +15367,8 @@ bool Player::LoadFromDB(ObjectGuid guid, SqlQueryHolder* holder) } SetUInt32Value(PLAYER_FIELD_LIFETIME_HONORBALE_KILLS, fields[40].GetUInt32()); - SetUInt16Value(PLAYER_FIELD_KILLS, 0, fields[41].GetUInt16()); - SetUInt16Value(PLAYER_FIELD_KILLS, 1, fields[42].GetUInt16()); + SetUInt16Value(PLAYER_FIELD_KILLS, 0, fields[41].GetUInt16()); // today + SetUInt16Value(PLAYER_FIELD_KILLS, 1, fields[42].GetUInt16()); // yesterday _LoadBoundInstances(holder->GetResult(PLAYER_LOGIN_QUERY_LOADBOUNDINSTANCES)); @@ -15531,6 +15565,10 @@ bool Player::LoadFromDB(ObjectGuid guid, SqlQueryHolder* holder) m_atLoginFlags = fields[34].GetUInt32(); + // Update Honor kills data + m_lastHonorKillsUpdateTime = logoutTime; + UpdateHonorKills(); + m_deathExpireTime = (time_t)fields[37].GetUInt64(); if (m_deathExpireTime > now + MAX_DEATH_COUNT * DEATH_EXPIRE_STEP) m_deathExpireTime = now + MAX_DEATH_COUNT * DEATH_EXPIRE_STEP - 1; @@ -17028,6 +17066,9 @@ void Player::SaveToDB() return; } + // first save/honor gain after midnight will also update the player's honor fields + UpdateHonorKills(); + DEBUG_FILTER_LOG(LOG_FILTER_PLAYER_STATS, "The value of player %s at save: ", m_name.c_str()); outDebugStatsValues(); @@ -23506,6 +23547,6 @@ void Player::ResetCurrencyWeekCounts() itr->second.state = PLAYERCURRENCY_CHANGED; } - WorldPacket data(SMSG_WEEKLY_RESET_CURRENCY, 0); + WorldPacket data(SMSG_WEEKLY_RESET_CURRENCIES, 0); SendDirectMessage(&data); } diff --git a/src/game/Player.h b/src/game/Player.h index 3b490f216..820667e55 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -1991,6 +1991,7 @@ class MANGOS_DLL_SPEC Player : public Unit /*********************************************************/ /*** PVP SYSTEM ***/ /*********************************************************/ + void UpdateHonorKills(); bool RewardHonor(Unit *pVictim, uint32 groupsize, float honor = -1); uint32 GetMaxPersonalArenaRatingRequirement(uint32 minarenaslot); @@ -2484,6 +2485,7 @@ class MANGOS_DLL_SPEC Player : public Unit uint32 m_speakCount; Difficulty m_dungeonDifficulty; Difficulty m_raidDifficulty; + time_t m_lastHonorKillsUpdateTime; uint32 m_atLoginFlags; diff --git a/src/game/WorldSession.cpp b/src/game/WorldSession.cpp index 9b9217147..dea7ed36b 100644 --- a/src/game/WorldSession.cpp +++ b/src/game/WorldSession.cpp @@ -548,7 +548,9 @@ void WorldSession::SendNotification(const char* format, ...) va_end(ap); WorldPacket data(SMSG_NOTIFICATION, (strlen(szStr) + 1)); - data << szStr; + data.WriteBits(strlen(szStr), 13); + data.FlushBits(); + data.append(szStr, strlen(szStr)); SendPacket(&data); } } @@ -566,7 +568,9 @@ void WorldSession::SendNotification(int32 string_id, ...) va_end(ap); WorldPacket data(SMSG_NOTIFICATION, (strlen(szStr) + 1)); - data << szStr; + data.WriteBits(strlen(szStr), 13); + data.FlushBits(); + data.append(szStr, strlen(szStr)); SendPacket(&data); } } diff --git a/src/game/WorldSession.h b/src/game/WorldSession.h index c29270e9d..5650df58e 100644 --- a/src/game/WorldSession.h +++ b/src/game/WorldSession.h @@ -764,6 +764,7 @@ class MANGOS_DLL_SPEC WorldSession void HandleLeaveBattlefieldOpcode(WorldPacket& recv_data); void HandleBattlemasterJoinArena(WorldPacket& recv_data); void HandleReportPvPAFK(WorldPacket& recv_data); + void HandleRequestPvPOptionsEnabled(WorldPacket& recv_data); void HandleWardenDataOpcode(WorldPacket& recv_data); void HandleWorldTeleportOpcode(WorldPacket& recv_data); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 84c46d4fb..86b999778 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "12163" + #define REVISION_NR "12164" #endif // __REVISION_NR_H__ diff --git a/src/shared/revision_sql.h b/src/shared/revision_sql.h index a124195f9..6b7fd64cc 100644 --- a/src/shared/revision_sql.h +++ b/src/shared/revision_sql.h @@ -1,6 +1,6 @@ #ifndef __REVISION_SQL_H__ #define __REVISION_SQL_H__ #define REVISION_DB_CHARACTERS "required_12161_01_characters_characters" - #define REVISION_DB_MANGOS "required_12150_01_mangos_mangos_string" + #define REVISION_DB_MANGOS "required_12164_01_mangos_command" #define REVISION_DB_REALMD "required_12112_01_realmd_account_access" #endif // __REVISION_SQL_H__