Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
ArenaTeam.cpp
Go to the documentation of this file.
1/*
2* This file is part of Project SkyFire https://www.projectskyfire.org.
3* See LICENSE.md file for Copyright information
4*/
5
6#include "ArenaTeam.h"
7#include "ArenaTeamMgr.h"
8#include "Group.h"
9#include "ObjectMgr.h"
10#include "Opcodes.h"
11#include "Player.h"
12#include "World.h"
13#include "WorldPacket.h"
14#include "WorldSession.h"
15
19{
20 Stats.WeekGames = 0;
21 Stats.SeasonGames = 0;
22 Stats.Rank = 0;
24 Stats.WeekWins = 0;
25 Stats.SeasonWins = 0;
26}
27
30
32{
34 data << uint32(GetId()); // team id
35 data << uint32(Stats.Rating); // rating
36 data << uint32(Stats.WeekGames); // games this week
37 data << uint32(Stats.WeekWins); // wins this week
38 data << uint32(Stats.SeasonGames); // played this season
39 data << uint32(Stats.SeasonWins); // wins this season
40 data << uint32(Stats.Rank); // rank
41 session->SendPacket(&data);
42}
43
45{
46 // This is called after a rated match ended
47 // Updates arena team stats for every member of the team (not only the ones who participated!)
48 for (MemberList::const_iterator itr = Members.begin(); itr != Members.end(); ++itr)
49 if (Player* player = ObjectAccessor::FindPlayer(itr->Guid))
50 SendStats(player->GetSession());
51}
52
54{
55 if (int32(PersonalRating) + mod < 0)
57 else
58 PersonalRating += mod;
59
60 if (player)
61 {
62 //player->SetArenaTeamInfoField(ArenaTeam::GetSlotByType(type), ARENA_TEAM_PERSONAL_RATING, PersonalRating);
63 //player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_PERSONAL_RATING, PersonalRating, type);
64 }
65}
66
68{
69 if (int32(MatchMakerRating) + mod < 0)
71 else
72 MatchMakerRating += mod;
73}
74
76{
77 for (MemberList::const_iterator itr = Members.begin(); itr != Members.end(); ++itr)
78 if (Player* player = ObjectAccessor::FindPlayer(itr->Guid))
79 player->GetSession()->SendPacket(packet);
80}
81
82void ArenaTeam::BroadcastEvent(ArenaTeamEvents event, uint64 guid, uint8 strCount, std::string const& str1, std::string const& str2, std::string const& str3)
83{
84 WorldPacket data(SMSG_ARENA_TEAM_EVENT, 1 + 1 + 1);
85 data << uint8(event);
86 data << uint8(strCount);
87 switch (strCount)
88 {
89 case 0:
90 break;
91 case 1:
92 data << str1;
93 break;
94 case 2:
95 data << str1 << str2;
96 break;
97 case 3:
98 data << str1 << str2 << str3;
99 break;
100 default:
101 SF_LOG_ERROR("bg.arena", "Unhandled strCount %u in ArenaTeam::BroadcastEvent", strCount);
102 return;
103 }
104
105 if (guid)
106 data << uint64(guid);
107
108 BroadcastPacket(&data);
109
110 SF_LOG_DEBUG("network", "WORLD: Sent SMSG_ARENA_TEAM_EVENT");
111}
112
114{
115 WorldPacket data(SMSG_CALENDAR_ARENA_TEAM, (Members.size() - 1) * (4 + 8 + 1));
116 data << uint32(Members.size() - 1);
117
118 for (MemberList::const_iterator itr = Members.begin(); itr != Members.end(); ++itr)
119 {
120 if (itr->Guid != session->GetPlayer()->GetGUID())
121 {
122 data.appendPackGUID(itr->Guid);
123 data << uint8(0); // unk
124 }
125 }
126
127 session->SendPacket(&data);
128}
129
131{
132 switch (type)
133 {
134 case ARENA_TEAM_2v2: return 0;
135 case ARENA_TEAM_3v3: return 1;
136 case ARENA_TEAM_5v5: return 2;
137 default:
138 break;
139 }
140 SF_LOG_ERROR("bg.arena", "FATAL: Unknown arena team type %u for some arena team", type);
141 return 0xFF;
142}
143
145{
146 switch (slot)
147 {
148 case 0: return ARENA_TEAM_2v2;
149 case 1: return ARENA_TEAM_3v3;
150 case 2: return ARENA_TEAM_5v5;
151 default:
152 break;
153 }
154 SF_LOG_ERROR("bg.arena", "FATAL: Unknown arena team slot %u for some arena team", slot);
155 return 0xFF;
156}
157
159{
160 for (MemberList::const_iterator itr = Members.begin(); itr != Members.end(); ++itr)
161 if (itr->Guid == guid)
162 return true;
163
164 return false;
165}
166
168{
169 if (!group)
170 return 0;
171
172 uint32 matchMakerRating = 0;
173 uint32 playerDivider = 0;
174 for (MemberList::const_iterator itr = Members.begin(); itr != Members.end(); ++itr)
175 {
176 // Skip if player is not online
177 if (!ObjectAccessor::FindPlayer(itr->Guid))
178 continue;
179
180 // Skip if player is not a member of group
181 if (!group->IsMember(itr->Guid))
182 continue;
183
184 matchMakerRating += itr->MatchMakerRating;
185 ++playerDivider;
186 }
187
188 // x/0 = crash
189 if (playerDivider == 0)
190 playerDivider = 1;
191
192 matchMakerRating /= playerDivider;
193
194 return matchMakerRating;
195}
196
197float ArenaTeam::GetChanceAgainst(uint32 ownRating, uint32 opponentRating)
198{
199 // Returns the chance to win against a team with the given rating, used in the rating adjustment calculation
200 // ELO system
201 return 1.0f / (1.0f + exp(log(10.0f) * (float)((float)opponentRating - (float)ownRating) / 650.0f));
202}
203
204int32 ArenaTeam::GetMatchmakerRatingMod(uint32 ownRating, uint32 opponentRating, bool won)
205{
206 // 'Chance' calculation - to beat the opponent
207 // This is a simulation. Not much info on how it really works
208 float chance = GetChanceAgainst(ownRating, opponentRating);
209 float won_mod = (won) ? 1.0f : 0.0f;
210 float mod = won_mod - chance;
211
212 // Work in progress:
213 /*
214 // This is a simulation, as there is not much info on how it really works
215 float confidence_mod = min(1.0f - fabs(mod), 0.5f);
216
217 // Apply confidence factor to the mod:
218 mod *= confidence_factor
219
220 // And only after that update the new confidence factor
221 confidence_factor -= ((confidence_factor - 1.0f) * confidence_mod) / confidence_factor;
222 */
223
224 // Real rating modification
225 mod *= 24.0f;
226
227 return (int32)ceil(mod);
228}
229
230int32 ArenaTeam::GetRatingMod(uint32 ownRating, uint32 opponentRating, bool won /*, float confidence_factor*/)
231{
232 // 'Chance' calculation - to beat the opponent
233 // This is a simulation. Not much info on how it really works
234 float chance = GetChanceAgainst(ownRating, opponentRating);
235 float won_mod = (won) ? 1.0f : 0.0f;
236
237 // Calculate the rating modification
238 float mod;
239
241 if (won && ownRating < 1300)
242 {
243 if (ownRating < 1000)
244 mod = 48.0f * (won_mod - chance);
245 else
246 mod = (24.0f + (24.0f * (1300.0f - float(ownRating)) / 300.0f)) * (won_mod - chance);
247 }
248 else
249 mod = 24.0f * (won_mod - chance);
250
251 return (int32)ceil(mod);
252}
253
255{
256 // Rating can only drop to 0
257 if (int32(Stats.Rating) + mod < 0)
258 Stats.Rating = 0;
259 else
260 {
261 Stats.Rating += mod;
262
263 // Check if rating related achivements are met
264 for (MemberList::iterator itr = Members.begin(); itr != Members.end(); ++itr)
265 if (Player* member = ObjectAccessor::FindPlayer(itr->Guid))
266 member->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_TEAM_RATING, Stats.Rating, Type);
267 }
268
269 // Update number of games played per season or week
270 Stats.WeekGames += 1;
271 Stats.SeasonGames += 1;
272
273 // Update team's rank, start with rank 1 and increase until no team with more rating was found
274 Stats.Rank = 1;
275 ArenaTeamMgr::ArenaTeamContainer::const_iterator i = sArenaTeamMgr->GetArenaTeamMapBegin();
276 for (; i != sArenaTeamMgr->GetArenaTeamMapEnd(); ++i)
277 {
278 if (i->second->GetType() == Type && i->second->GetStats().Rating > Stats.Rating)
279 ++Stats.Rank;
280 }
281}
282
283int32 ArenaTeam::WonAgainst(uint32 ownMMRating, uint32 opponentMMRating, int32& ratingChange)
284{
285 // Called when the team has won
286 // Change in Matchmaker rating
287 int32 mod = GetMatchmakerRatingMod(ownMMRating, opponentMMRating, true);
288
289 // Change in Team Rating
290 ratingChange = GetRatingMod(Stats.Rating, opponentMMRating, true);
291
292 // Modify the team stats accordingly
293 FinishGame(ratingChange);
294
295 // Update number of wins per season and week
296 Stats.WeekWins += 1;
297 Stats.SeasonWins += 1;
298
299 // Return the rating change, used to display it on the results screen
300 return mod;
301}
302
303int32 ArenaTeam::LostAgainst(uint32 ownMMRating, uint32 opponentMMRating, int32& ratingChange)
304{
305 // Called when the team has lost
306 // Change in Matchmaker Rating
307 int32 mod = GetMatchmakerRatingMod(ownMMRating, opponentMMRating, false);
308
309 // Change in Team Rating
310 ratingChange = GetRatingMod(Stats.Rating, opponentMMRating, false);
311
312 // Modify the team stats accordingly
313 FinishGame(ratingChange);
314
315 // return the rating change, used to display it on the results screen
316 return mod;
317}
318
319void ArenaTeam::MemberLost(Player* player, uint32 againstMatchmakerRating, int32 matchmakerRatingChange)
320{
321 // Called for each participant of a match after losing
322 for (MemberList::iterator itr = Members.begin(); itr != Members.end(); ++itr)
323 {
324 if (itr->Guid == player->GetGUID())
325 {
326 // Update personal rating
327 int32 mod = GetRatingMod(itr->PersonalRating, againstMatchmakerRating, false);
328 itr->ModifyPersonalRating(player, mod, GetType());
329
330 // Update matchmaker rating
331 itr->ModifyMatchmakerRating(matchmakerRatingChange, GetSlot());
332
333 // Update personal played stats
334 itr->WeekGames += 1;
335 itr->SeasonGames += 1;
336
337 // update the unit fields
338 //player->SetArenaTeamInfoField(GetSlot(), ARENA_TEAM_GAMES_WEEK, itr->WeekGames);
339 //player->SetArenaTeamInfoField(GetSlot(), ARENA_TEAM_GAMES_SEASON, itr->SeasonGames);
340 return;
341 }
342 }
343}
344
345void ArenaTeam::OfflineMemberLost(uint64 guid, uint32 againstMatchmakerRating, int32 matchmakerRatingChange)
346{
347 // Called for offline player after ending rated arena match!
348 for (MemberList::iterator itr = Members.begin(); itr != Members.end(); ++itr)
349 {
350 if (itr->Guid == guid)
351 {
352 // update personal rating
353 int32 mod = GetRatingMod(itr->PersonalRating, againstMatchmakerRating, false);
354 itr->ModifyPersonalRating(NULL, mod, GetType());
355
356 // update matchmaker rating
357 itr->ModifyMatchmakerRating(matchmakerRatingChange, GetSlot());
358
359 // update personal played stats
360 itr->WeekGames += 1;
361 itr->SeasonGames += 1;
362 return;
363 }
364 }
365}
366
367void ArenaTeam::MemberWon(Player* player, uint32 againstMatchmakerRating, int32 matchmakerRatingChange)
368{
369 // called for each participant after winning a match
370 for (MemberList::iterator itr = Members.begin(); itr != Members.end(); ++itr)
371 {
372 if (itr->Guid == player->GetGUID())
373 {
374 // update personal rating
375 int32 mod = GetRatingMod(itr->PersonalRating, againstMatchmakerRating, true);
376 itr->ModifyPersonalRating(player, mod, GetType());
377
378 // update matchmaker rating
379 itr->ModifyMatchmakerRating(matchmakerRatingChange, GetSlot());
380
381 // update personal stats
382 itr->WeekGames += 1;
383 itr->SeasonGames += 1;
384 itr->SeasonWins += 1;
385 itr->WeekWins += 1;
386 // update unit fields
387 //player->SetArenaTeamInfoField(GetSlot(), ARENA_TEAM_GAMES_WEEK, itr->WeekGames);
388 //player->SetArenaTeamInfoField(GetSlot(), ARENA_TEAM_GAMES_SEASON, itr->SeasonGames);
389 return;
390 }
391 }
392}
393
394
396{
397 // Reset team stats
398 Stats.WeekGames = 0;
399 Stats.WeekWins = 0;
400
401 // Reset member stats
402 for (MemberList::iterator itr = Members.begin(); itr != Members.end(); ++itr)
403 {
404 itr->WeekGames = 0;
405 itr->WeekWins = 0;
406 }
407}
408
410{
411 for (MemberList::const_iterator itr = Members.begin(); itr != Members.end(); ++itr)
412 if (Player* player = ObjectAccessor::FindPlayer(itr->Guid))
413 if (player->GetMap()->IsBattleArena())
414 return true;
415
416 return false;
417}
418
419ArenaTeamMember* ArenaTeam::GetMember(const std::string& name)
420{
421 for (MemberList::iterator itr = Members.begin(); itr != Members.end(); ++itr)
422 if (itr->Name == name)
423 return &(*itr);
424
425 return NULL;
426}
427
429{
430 for (MemberList::iterator itr = Members.begin(); itr != Members.end(); ++itr)
431 if (itr->Guid == guid)
432 return &(*itr);
433
434 return NULL;
435}
@ ARENA_TEAM_5v5
Definition ArenaTeam.h:67
@ ARENA_TEAM_2v2
Definition ArenaTeam.h:65
@ ARENA_TEAM_3v3
Definition ArenaTeam.h:66
ArenaTeamEvents
Definition ArenaTeam.h:54
#define sArenaTeamMgr
@ ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_TEAM_RATING
Definition DBCEnums.h:203
std::int32_t int32
Definition Define.h:73
std::uint8_t uint8
Definition Define.h:79
std::uint32_t uint32
Definition Define.h:77
std::uint64_t uint64
Definition Define.h:76
#define SF_LOG_DEBUG(filterType__,...)
Definition Log.h:134
#define SF_LOG_ERROR(filterType__,...)
Definition Log.h:143
int32 WonAgainst(uint32 ownMMRating, uint32 opponentMMRating, int32 &rating_change)
uint32 EmblemColor
Definition ArenaTeam.h:159
static float GetChanceAgainst(uint32 ownRating, uint32 opponentRating)
uint32 BorderColor
Definition ArenaTeam.h:161
uint32 TeamId
Definition ArenaTeam.h:152
static int32 GetRatingMod(uint32 ownRating, uint32 opponentRating, bool won)
ArenaTeamStats Stats
Definition ArenaTeam.h:164
bool IsMember(uint64 guid) const
uint8 Type
Definition ArenaTeam.h:153
void OfflineMemberLost(uint64 guid, uint32 againstMatchmakerRating, int32 matchmakerRatingChange=-12)
void BroadcastEvent(ArenaTeamEvents event, uint64 guid, uint8 strCount, std::string const &str1, std::string const &str2, std::string const &str3)
Definition ArenaTeam.cpp:82
uint8 EmblemStyle
Definition ArenaTeam.h:158
uint64 CaptainGuid
Definition ArenaTeam.h:155
uint8 BorderStyle
Definition ArenaTeam.h:160
static int32 GetMatchmakerRatingMod(uint32 ownRating, uint32 opponentRating, bool won)
void SendStats(WorldSession *session)
Definition ArenaTeam.cpp:31
uint8 GetSlot() const
Definition ArenaTeam.h:108
void MemberWon(Player *player, uint32 againstMatchmakerRating, int32 matchmakerRatingChange=12)
void FinishGame(int32 mod)
void FinishWeek()
uint32 GetType() const
Definition ArenaTeam.h:107
std::string TeamName
Definition ArenaTeam.h:154
MemberList Members
Definition ArenaTeam.h:163
void NotifyStatsChanged()
Definition ArenaTeam.cpp:44
void MassInviteToEvent(WorldSession *session)
uint32 BackgroundColor
Definition ArenaTeam.h:157
void BroadcastPacket(WorldPacket *packet)
Definition ArenaTeam.cpp:75
uint32 GetAverageMMR(Group *group) const
bool IsFighting() const
void MemberLost(Player *player, uint32 againstMatchmakerRating, int32 matchmakerRatingChange=-12)
ArenaTeamMember * GetMember(uint64 guid)
static uint8 GetTypeBySlot(uint8 slot)
uint32 GetId() const
Definition ArenaTeam.h:106
int32 LostAgainst(uint32 ownMMRating, uint32 opponentMMRating, int32 &rating_change)
static uint8 GetSlotByType(uint32 type)
void appendPackGUID(uint64 guid)
Definition ByteBuffer.h:681
Definition Group.h:147
bool IsMember(uint64 guid) const
Definition Group.cpp:2603
static Player * FindPlayer(uint64)
uint64 GetGUID() const
Definition Object.h:119
Player session in the World.
Player * GetPlayer() const
void SendPacket(WorldPacket const *packet, bool forced=false)
Send a packet to the client.
@ SMSG_ARENA_TEAM_STATS
Definition Opcodes.h:517
@ SMSG_ARENA_TEAM_EVENT
Definition Opcodes.h:516
@ SMSG_CALENDAR_ARENA_TEAM
Definition Opcodes.h:573
#define sWorld
Definition World.h:910
@ CONFIG_ARENA_START_RATING
Definition World.h:299
uint16 PersonalRating
Definition ArenaTeam.h:79
void ModifyPersonalRating(Player *player, int32 mod, uint32 type)
Definition ArenaTeam.cpp:53
void ModifyMatchmakerRating(int32 mod, uint32 slot)
Definition ArenaTeam.cpp:67
uint16 MatchMakerRating
Definition ArenaTeam.h:80