diff --git a/src/server/game/Battlegrounds/ArenaTeam.cpp b/src/server/game/Battlegrounds/ArenaTeam.cpp index 2f1fa5a7b0a17..eb67d2d14c325 100755 --- a/src/server/game/Battlegrounds/ArenaTeam.cpp +++ b/src/server/game/Battlegrounds/ArenaTeam.cpp @@ -606,27 +606,52 @@ float ArenaTeam::GetChanceAgainst(uint32 ownRating, uint32 opponentRating) { // Returns the chance to win against a team with the given rating, used in the rating adjustment calculation // ELO system - return 1.0f / (1.0f + exp(log(10.0f) * (float)((float)opponentRating - (float)ownRating) / 400.0f)); + return 1.0f / (1.0f + exp(log(10.0f) * (float)((float)opponentRating - (float)ownRating) / 650.0f)); } -int32 ArenaTeam::GetRatingMod(uint32 ownRating, uint32 opponentRating, bool won, bool calculateMatchMakerRating) +int32 ArenaTeam::GetMatchmakerRatingMod(uint32 ownRating, uint32 opponentRating, bool won /*, float& confidence_factor*/) { // 'Chance' calculation - to beat the opponent + // This is a simulation. Not much info on how it really works + float chance = GetChanceAgainst(ownRating, opponentRating); + float won_mod = (won) ? 1.0f : 0.0f; + float mod = won_mod - chance; + + // Work in progress: + /* + // This is a simulation, as there is not much info on how it really works + float confidence_mod = min(1.0f - fabs(mod), 0.5f); + + // Apply confidence factor to the mod: + mod *= confidence_factor + + // And only after that update the new confidence factor + confidence_factor -= ((confidence_factor - 1.0f) * confidence_mod) / confidence_factor; + */ + + // Real rating modification + mod *= 24.0f; + + return (int32)ceil(mod); +} + +int32 ArenaTeam::GetRatingMod(uint32 ownRating, uint32 opponentRating, bool won /*, float confidence_factor*/) +{ + // 'Chance' calculation - to beat the opponent + // This is a simulation. Not much info on how it really works float chance = GetChanceAgainst(ownRating, opponentRating); float won_mod = (won) ? 1.0f : 0.0f; // Calculate the rating modification - // Simulation on how it works. Not much info on how it really works float mod; - if (won && !calculateMatchMakerRating) + // TODO: Replace this hack with using the confidence factor (limiting the factor to 2.0f) + if (won && ownRating < 1300) { if (ownRating < 1000) mod = 48.0f * (won_mod - chance); - else if (ownRating < 1300) - mod = (24.0f + (24.0f * (1300.0f - int32(ownRating)) / 300.0f)) * (won_mod - chance); else - mod = 24.0f * (won_mod - chance); + mod = (24.0f + (24.0f * (1300.0f - float(ownRating)) / 300.0f)) * (won_mod - chance); } else mod = 24.0f * (won_mod - chance); @@ -634,15 +659,6 @@ int32 ArenaTeam::GetRatingMod(uint32 ownRating, uint32 opponentRating, bool won, return (int32)ceil(mod); } -int32 ArenaTeam::GetPersonalRatingMod(int32 baseRating, uint32 ownRating, uint32 opponentRating) -{ - // Max (2 * team rating gain/loss), min 0 gain/loss - float chance = GetChanceAgainst(ownRating, opponentRating); - chance *= 2.0f; - - return (int32)ceil(float(baseRating) * chance); -} - void ArenaTeam::FinishGame(int32 mod) { // Rating can only drop to 0 @@ -672,14 +688,17 @@ void ArenaTeam::FinishGame(int32 mod) } } -int32 ArenaTeam::WonAgainst(uint32 againstRating) +int32 ArenaTeam::WonAgainst(uint32 Own_MMRating, uint32 Opponent_MMRating, int32& rating_change) { // Called when the team has won - // Own team rating versus opponents matchmaker rating - int32 mod = GetRatingMod(Stats.Rating, againstRating, true); + // Change in Matchmaker rating + int32 mod = GetMatchmakerRatingMod(Own_MMRating, Opponent_MMRating, true); + + // Change in Team Rating + rating_change = GetRatingMod(Stats.Rating, Opponent_MMRating, true); // Modify the team stats accordingly - FinishGame(mod); + FinishGame(rating_change); // Update number of wins per season and week Stats.WeekWins += 1; @@ -689,20 +708,23 @@ int32 ArenaTeam::WonAgainst(uint32 againstRating) return mod; } -int32 ArenaTeam::LostAgainst(uint32 againstRating) +int32 ArenaTeam::LostAgainst(uint32 Own_MMRating, uint32 Opponent_MMRating, int32& rating_change) { // Called when the team has lost - // Own team rating versus opponents matchmaker rating - int32 mod = GetRatingMod(Stats.Rating, againstRating, false); + // Change in Matchmaker Rating + int32 mod = GetMatchmakerRatingMod(Own_MMRating, Opponent_MMRating, false); + + // Change in Team Rating + rating_change = GetRatingMod(Stats.Rating, Opponent_MMRating, false); // Modify the team stats accordingly - FinishGame(mod); + FinishGame(rating_change); // return the rating change, used to display it on the results screen return mod; } -void ArenaTeam::MemberLost(Player* plr, uint32 againstMatchmakerRating, int32 teamratingchange) +void ArenaTeam::MemberLost(Player* plr, uint32 againstMatchmakerRating, int32 MatchmakerRatingChange) { // Called for each participant of a match after losing for (MemberList::iterator itr = Members.begin(); itr != Members.end(); ++itr) @@ -710,12 +732,11 @@ void ArenaTeam::MemberLost(Player* plr, uint32 againstMatchmakerRating, int32 te if (itr->Guid == plr->GetGUID()) { // Update personal rating - int32 mod = GetPersonalRatingMod(teamratingchange, itr->PersonalRating, (Stats.Rating - teamratingchange)); + int32 mod = GetRatingMod(itr->PersonalRating, againstMatchmakerRating, false); itr->ModifyPersonalRating(plr, mod, GetSlot()); // Update matchmaker rating - mod = GetRatingMod(itr->MatchMakerRating, againstMatchmakerRating, false, true); - itr->ModifyMatchmakerRating(mod, GetSlot()); + itr->ModifyMatchmakerRating(MatchmakerRatingChange, GetSlot()); // Update personal played stats itr->WeekGames +=1; @@ -729,7 +750,7 @@ void ArenaTeam::MemberLost(Player* plr, uint32 againstMatchmakerRating, int32 te } } -void ArenaTeam::OfflineMemberLost(uint64 guid, uint32 againstMatchMakerRating, int32 ratingChange) +void ArenaTeam::OfflineMemberLost(uint64 guid, uint32 againstMatchmakerRating, int32 MatchmakerRatingChange) { // Called for offline player after ending rated arena match! for (MemberList::iterator itr = Members.begin(); itr != Members.end(); ++itr) @@ -737,12 +758,11 @@ void ArenaTeam::OfflineMemberLost(uint64 guid, uint32 againstMatchMakerRating, i if (itr->Guid == guid) { // update personal rating - int32 mod = GetPersonalRatingMod(ratingChange, itr->PersonalRating, (Stats.Rating - ratingChange)); + int32 mod = GetRatingMod(itr->PersonalRating, againstMatchmakerRating, false); itr->ModifyPersonalRating(NULL, mod, GetSlot()); // update matchmaker rating - mod = GetRatingMod(itr->MatchMakerRating, againstMatchMakerRating, false, true); - itr->ModifyMatchmakerRating(mod, GetSlot()); + itr->ModifyMatchmakerRating(MatchmakerRatingChange, GetSlot()); // update personal played stats itr->WeekGames += 1; @@ -752,7 +772,7 @@ void ArenaTeam::OfflineMemberLost(uint64 guid, uint32 againstMatchMakerRating, i } } -void ArenaTeam::MemberWon(Player* plr, uint32 againstMatchMakerRating, int32 ratingChange) +void ArenaTeam::MemberWon(Player* plr, uint32 againstMatchmakerRating, int32 MatchmakerRatingChange) { // called for each participant after winning a match for (MemberList::iterator itr = Members.begin(); itr != Members.end(); ++itr) @@ -760,12 +780,11 @@ void ArenaTeam::MemberWon(Player* plr, uint32 againstMatchMakerRating, int32 rat if (itr->Guid == plr->GetGUID()) { // update personal rating - int32 mod = GetPersonalRatingMod(ratingChange, (Stats.Rating - ratingChange), itr->PersonalRating); + int32 mod = GetRatingMod(itr->PersonalRating, againstMatchmakerRating, true); itr->ModifyPersonalRating(plr, mod, GetSlot()); // update matchmaker rating - mod = GetRatingMod(itr->MatchMakerRating, againstMatchMakerRating, true, true); - itr->ModifyMatchmakerRating(mod, GetSlot()); + itr->ModifyMatchmakerRating(MatchmakerRatingChange, GetSlot()); // update personal stats itr->WeekGames +=1; diff --git a/src/server/game/Battlegrounds/ArenaTeam.h b/src/server/game/Battlegrounds/ArenaTeam.h index 9b76715a340c1..ce4efecc22817 100755 --- a/src/server/game/Battlegrounds/ArenaTeam.h +++ b/src/server/game/Battlegrounds/ArenaTeam.h @@ -164,14 +164,14 @@ class ArenaTeam void Inspect(WorldSession* session, uint64 guid); uint32 GetPoints(uint32 MemberRating); - int32 GetRatingMod(uint32 ownRating, uint32 opponentRating, bool won, bool calculating_mmr = false); - int32 GetPersonalRatingMod(int32 base_rating, uint32 ownRating, uint32 opponentRating); + int32 GetMatchmakerRatingMod(uint32 ownRating, uint32 opponentRating, bool won); + int32 GetRatingMod(uint32 ownRating, uint32 opponentRating, bool won); float GetChanceAgainst(uint32 ownRating, uint32 opponentRating); - int32 WonAgainst(uint32 againstRating); - void MemberWon(Player* plr, uint32 againstMatchmakerRating, int32 teamratingchange = 12); - int32 LostAgainst(uint32 againstRating); - void MemberLost(Player* plr, uint32 againstMatchmakerRating, int32 teamratingchange = -12); - void OfflineMemberLost(uint64 guid, uint32 againstMatchmakerRating, int32 teamratingchange = -12); + int32 WonAgainst(uint32 Own_MMRating, uint32 Opponent_MMRating, int32& rating_change); + void MemberWon(Player* plr, uint32 againstMatchmakerRating, int32 MatchmakerRatingChange); + int32 LostAgainst(uint32 Own_MMRating, uint32 Opponent_MMRating, int32& rating_change); + void MemberLost(Player* plr, uint32 againstMatchmakerRating, int32 MatchmakerRatingChange = -12); + void OfflineMemberLost(uint64 guid, uint32 againstMatchmakerRating, int32 MatchmakerRatingChange = -12); void UpdateArenaPointsHelper(std::map & PlayerPoints); diff --git a/src/server/game/Battlegrounds/Battleground.cpp b/src/server/game/Battlegrounds/Battleground.cpp index bbf1f6272aacc..4d0a12c84e993 100755 --- a/src/server/game/Battlegrounds/Battleground.cpp +++ b/src/server/game/Battlegrounds/Battleground.cpp @@ -656,9 +656,11 @@ void Battleground::EndBattleground(uint32 winner) uint32 loser_team_rating = 0; uint32 loser_matchmaker_rating = 0; int32 loser_change = 0; + int32 loser_matchmaker_change = 0; uint32 winner_team_rating = 0; uint32 winner_matchmaker_rating = 0; int32 winner_change = 0; + int32 winner_matchmaker_change = 0; WorldPacket data; int32 winmsg_id = 0; @@ -700,10 +702,12 @@ void Battleground::EndBattleground(uint32 winner) loser_matchmaker_rating = GetArenaMatchmakerRating(GetOtherTeam(winner)); winner_team_rating = winner_arena_team->GetRating(); winner_matchmaker_rating = GetArenaMatchmakerRating(winner); - winner_change = winner_arena_team->WonAgainst(loser_matchmaker_rating); - loser_change = loser_arena_team->LostAgainst(winner_matchmaker_rating); - sLog->outArena("--- Winner rating: %u, Loser rating: %u, Winner MMR: %u, Loser MMR: %u, Winner change: %d, Loser change: %d ---", winner_team_rating, loser_team_rating, - winner_matchmaker_rating, loser_matchmaker_rating, winner_change, loser_change); + winner_matchmaker_change = winner_arena_team->WonAgainst(winner_matchmaker_rating, loser_matchmaker_rating, winner_change); + loser_matchmaker_change = loser_arena_team->LostAgainst(loser_matchmaker_rating, winner_matchmaker_rating, loser_change); + sLog->outArena("--- Winner: old rating: %u, rating gain: %d, old MMR: %u, MMR gain: %d --- Loser: old rating: %u, rating loss: %d, old MMR: %u, MMR loss: %d ---", winner_team_rating, winner_change, winner_matchmaker_rating, + winner_matchmaker_change, loser_team_rating, loser_change, loser_matchmaker_rating, loser_matchmaker_change); + SetArenaMatchmakerRating(winner, winner_matchmaker_rating + winner_matchmaker_change); + SetArenaMatchmakerRating(GetOtherTeam(winner), loser_matchmaker_rating + loser_matchmaker_change); SetArenaTeamRatingChangeForTeam(winner, winner_change); SetArenaTeamRatingChangeForTeam(GetOtherTeam(winner), loser_change); sLog->outArena("Arena match Type: %u for Team1Id: %u - Team2Id: %u ended. WinnerTeamId: %u. Winner rating: +%d, Loser rating: %d", m_ArenaType, m_ArenaTeamIds[BG_TEAM_ALLIANCE], m_ArenaTeamIds[BG_TEAM_HORDE], winner_arena_team->GetId(), winner_change, loser_change); @@ -738,9 +742,9 @@ void Battleground::EndBattleground(uint32 winner) if (isArena() && isRated() && winner_arena_team && loser_arena_team && winner_arena_team != loser_arena_team) { if (team == winner) - winner_arena_team->OfflineMemberLost(itr->first, loser_matchmaker_rating, winner_change); + winner_arena_team->OfflineMemberLost(itr->first, loser_matchmaker_rating, winner_matchmaker_change); else - loser_arena_team->OfflineMemberLost(itr->first, winner_matchmaker_rating, loser_change); + loser_arena_team->OfflineMemberLost(itr->first, winner_matchmaker_rating, loser_matchmaker_change); } continue; } @@ -778,11 +782,11 @@ void Battleground::EndBattleground(uint32 winner) if (member) plr->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA, member->PersonalRating); - winner_arena_team->MemberWon(plr, loser_matchmaker_rating, winner_change); + winner_arena_team->MemberWon(plr, loser_matchmaker_rating, winner_matchmaker_change); } else { - loser_arena_team->MemberLost(plr, winner_matchmaker_rating, loser_change); + loser_arena_team->MemberLost(plr, winner_matchmaker_rating, loser_matchmaker_change); // Arena lost => reset the win_rated_arena having the "no_lose" condition plr->GetAchievementMgr().ResetAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA, ACHIEVEMENT_CRITERIA_CONDITION_NO_LOSE);