OregonCore  revision fb2a440-git
Your Favourite TBC server
ArenaTeam.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the OregonCore Project. See AUTHORS file for Copyright information
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License as published by the
6  * Free Software Foundation; either version 2 of the License, or (at your
7  * option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include "ObjectMgr.h"
19 #include "WorldPacket.h"
20 #include "ArenaTeam.h"
21 #include "BattlegroundMgr.h"
22 
24 {
25  if (int32(personal_rating) + mod < 0)
26  personal_rating = 0;
27  else
28  personal_rating += mod;
29  if (plr)
31 }
32 
34 {
35  m_TeamId = 0;
36  m_Type = 0;
37  m_Name = "";
38  m_CaptainGuid = 0;
39  m_BackgroundColor = 0; // background
40  m_EmblemStyle = 0; // icon
41  m_EmblemColor = 0; // icon color
42  m_BorderStyle = 0; // border
43  m_BorderColor = 0; // border color
44  m_stats.games_week = 0;
45  m_stats.games_season = 0;
46  m_stats.rank = 0;
47  m_stats.rating = ARENA_NEW_TEAM_RATING;
48  m_stats.wins_week = 0;
49  m_stats.wins_season = 0;
50 }
51 
53 {
54 }
55 
56 bool ArenaTeam::Create(uint64 captainGuid, uint32 type, std::string arenaTeamName)
57 {
58  if (!sObjectMgr.GetPlayer(captainGuid)) // player not exist
59  return false;
60  if (sObjectMgr.GetArenaTeamByName(arenaTeamName)) // arena team with this name already exist
61  return false;
62 
63  sLog.outDebug("GUILD: creating arena team %s to leader: %u", arenaTeamName.c_str(), GUID_LOPART(captainGuid));
64 
65  m_CaptainGuid = captainGuid;
66  m_Name = arenaTeamName;
67  m_Type = type;
68 
69  m_TeamId = sObjectMgr.GenerateArenaTeamId();
70 
71  // ArenaTeamName already assigned to ArenaTeam::name, use it to encode string for DB
72  CharacterDatabase.escape_string(arenaTeamName);
73 
75  // CharacterDatabase.PExecute("DELETE FROM arena_team WHERE arenateamid='%u'", m_TeamId); - MAX(arenateam)+1 not exist
76  CharacterDatabase.PExecute("DELETE FROM arena_team_member WHERE arenateamid='%u'", m_TeamId);
77  CharacterDatabase.PExecute("INSERT INTO arena_team (arenateamid,name,captainguid,type,BackgroundColor,EmblemStyle,EmblemColor,BorderStyle,BorderColor) "
78  "VALUES('%u','%s','%u','%u','%u','%u','%u','%u','%u')",
79  m_TeamId, arenaTeamName.c_str(), GUID_LOPART(m_CaptainGuid), m_Type, m_BackgroundColor, m_EmblemStyle, m_EmblemColor, m_BorderStyle, m_BorderColor);
80  CharacterDatabase.PExecute("INSERT INTO arena_team_stats (arenateamid, rating, games, wins, played, wins2, rank) VALUES "
81  "('%u', '%u', '%u', '%u', '%u', '%u', '%u')", m_TeamId, m_stats.rating, m_stats.games_week, m_stats.wins_week, m_stats.games_season, m_stats.wins_season, m_stats.rank);
82 
84 
85  AddMember(m_CaptainGuid);
86  sLog.outArena("New ArenaTeam created [Id: %u] [Type: %u] [Captain GUID: " UI64FMTD "]", GetId(), GetType(), GetCaptain());
87  return true;
88 }
89 
90 bool ArenaTeam::AddMember(const uint64& playerGuid)
91 {
92  std::string plName;
93  uint8 plClass;
94 
95  // arena team is full (can't have more than type * 2 players!)
96  if (GetMembersSize() >= GetType() * 2)
97  return false;
98 
99  Player* pl = sObjectMgr.GetPlayer(playerGuid);
100  if (pl)
101  {
102  if (pl->GetArenaTeamId(GetSlot()))
103  {
104  sLog.outError("Arena::AddMember() : player already in this sized team");
105  return false;
106  }
107 
108  plClass = pl->getClass();
109  plName = pl->GetName();
110  }
111  else
112  {
113  // 0 1
114  QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT name, class FROM characters WHERE guid='%u'", GUID_LOPART(playerGuid));
115  if (!result)
116  return false;
117 
118  plName = (*result)[0].GetCppString();
119  plClass = (*result)[1].GetUInt8();
120 
121  // check if player already in arenateam of that size
122  if (Player::GetArenaTeamIdFromDB(playerGuid, GetType()) != 0)
123  {
124  sLog.outError("Arena::AddMember() : player " UI64FMTD " already in this sized team", playerGuid);
125  return false;
126  }
127  }
128 
129  // remove all player signs from another petitions
130  // this will be prevent attempt joining player to many arenateams and corrupt arena team data integrity
131  Player::RemovePetitionsAndSigns(playerGuid, GetType());
132 
133  ArenaTeamMember newmember;
134  newmember.name = plName;
135  newmember.guid = playerGuid;
136  newmember.Class = plClass;
137  newmember.games_season = 0;
138  newmember.games_week = 0;
139  newmember.wins_season = 0;
140  newmember.wins_week = 0;
142  m_members.push_back(newmember);
143 
144  CharacterDatabase.PExecute("INSERT INTO arena_team_member (arenateamid, guid, personal_rating) VALUES ('%u', '%u', '%u')", m_TeamId, GUID_LOPART(newmember.guid), newmember.personal_rating);
145 
146  if (pl)
147  {
148  pl->SetInArenaTeam(m_TeamId, GetSlot());
149  pl->SetArenaTeamIdInvited(0);
151 
152  // hide promote/remove buttons
153  if (m_CaptainGuid != playerGuid)
154  pl->SetArenaTeamInfoField(GetSlot(), ARENA_TEAM_MEMBER, 1);
155  sLog.outArena("Player: %s [GUID: %u] joined arena team type: %u [Id: %u].", pl->GetName(), pl->GetGUIDLow(), GetType(), GetId());
156  }
157  return true;
158 }
159 
161 {
162  if (!arenaTeamDataResult)
163  return false;
164 
165  Field* fields = arenaTeamDataResult->Fetch();
166 
167  m_TeamId = fields[0].GetUInt32();
168  m_Name = fields[1].GetCppString();
169  m_CaptainGuid = MAKE_NEW_GUID(fields[2].GetUInt32(), 0, HIGHGUID_PLAYER);
170  m_Type = fields[3].GetUInt32();
171  m_BackgroundColor = fields[4].GetUInt32();
172  m_EmblemStyle = fields[5].GetUInt32();
173  m_EmblemColor = fields[6].GetUInt32();
174  m_BorderStyle = fields[7].GetUInt32();
175  m_BorderColor = fields[8].GetUInt32();
176  // load team stats
177  m_stats.rating = fields[9].GetUInt32();
178  m_stats.games_week = fields[10].GetUInt32();
179  m_stats.wins_week = fields[11].GetUInt32();
180  m_stats.games_season = fields[12].GetUInt32();
181  m_stats.wins_season = fields[13].GetUInt32();
182  m_stats.rank = fields[14].GetUInt32();
183 
184  return true;
185 }
186 
188 {
189  if (!arenaTeamMembersResult)
190  return false;
191 
192  bool captainPresentInTeam = false;
193 
194  do
195  {
196  Field* fields = arenaTeamMembersResult->Fetch();
197  // prevent crash if db records are broken, when all members in result are already processed and current team hasn't got any members
198  if (!fields)
199  break;
200  uint32 arenaTeamId = fields[0].GetUInt32();
201  if (arenaTeamId < m_TeamId)
202  {
203  // there is in table arena_team_member record which doesn't have arenateamid in arena_team table, report error
204  sLog.outErrorDb("ArenaTeam %u does not exist but it has record in arena_team_member table, deleting it!", arenaTeamId);
205  CharacterDatabase.PExecute("DELETE FROM arena_team_member WHERE arenateamid = '%u'", arenaTeamId);
206  continue;
207  }
208 
209  if (arenaTeamId > m_TeamId)
210  // we loaded all members for this arena_team already, break cycle
211  break;
212 
213  ArenaTeamMember newmember;
214  newmember.guid = MAKE_NEW_GUID(fields[1].GetUInt32(), 0, HIGHGUID_PLAYER);
215  newmember.games_week = fields[2].GetUInt32();
216  newmember.wins_week = fields[3].GetUInt32();
217  newmember.games_season = fields[4].GetUInt32();
218  newmember.wins_season = fields[5].GetUInt32();
219  newmember.personal_rating = fields[6].GetUInt32();
220  newmember.name = fields[7].GetCppString();
221  newmember.Class = fields[8].GetUInt8();
222 
223  //check if member exists in characters table
224  if (newmember.name.empty())
225  {
226  sLog.outErrorDb("ArenaTeam %u has member with empty name - probably player %u doesn't exist, deleting him from memberlist!", arenaTeamId, GUID_LOPART(newmember.guid));
227  this->DelMember(newmember.guid);
228  continue;
229  }
230 
231  if (newmember.guid == GetCaptain())
232  captainPresentInTeam = true;
233 
234  m_members.push_back(newmember);
235  }
236  while (arenaTeamMembersResult->NextRow());
237 
238  if (Empty() || !captainPresentInTeam)
239  {
240  // arena team is empty or captain is not in team, delete from db
241  sLog.outErrorDb("ArenaTeam %u does not have any members or its captain is not in team, disbanding it...", m_TeamId);
242  return false;
243  }
244 
245  return true;
246 }
247 
249 {
250  // disable remove/promote buttons
251  Player* oldcaptain = sObjectMgr.GetPlayer(GetCaptain());
252  if (oldcaptain)
253  oldcaptain->SetArenaTeamInfoField(GetSlot(), ARENA_TEAM_MEMBER, 1);
254 
255  // set new captain
256  m_CaptainGuid = guid;
257 
258  // update database
259  CharacterDatabase.PExecute("UPDATE arena_team SET captainguid = '%u' WHERE arenateamid = '%u'", GUID_LOPART(guid), GetId());
260 
261  // enable remove/promote buttons
262  if (Player* newcaptain = sObjectMgr.GetPlayer(guid))
263  {
264  newcaptain->SetArenaTeamInfoField(GetSlot(), ARENA_TEAM_MEMBER, 0);
265  sLog.outArena("Player: %s [GUID: %u] promoted player: %s [GUID: %u] to leader of arena team [Id: %u] [Type: %u].", oldcaptain->GetName(), oldcaptain->GetGUIDLow(), newcaptain->GetName(), newcaptain->GetGUIDLow(), GetId(), GetType());
266  }
267 }
268 
270 {
271  for (MemberList::iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
272  if (itr->guid == guid)
273  {
274  m_members.erase(itr);
275  break;
276  }
277 
278  if (Player* player = sObjectMgr.GetPlayer(guid))
279  {
280  // remove from arena queue, if queued
281  for (uint8 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; ++i)
282  {
283  if (uint32 bgQueueType = player->GetBattlegroundQueueId(i))
284  {
285  Battleground* bg = sBattlegroundMgr.GetBattlegroundTemplate(bgQueueType);
286  if (!bg || !bg->isArena())
287  break;
288 
289  WorldPacket data;
290  sBattlegroundMgr.BuildBattlegroundStatusPacket(&data, bg, player->GetTeam(), player->GetBattlegroundQueueIndex(bgQueueType), STATUS_NONE, 0, 0);
291  player->GetSession()->SendPacket(&data);
292  sBattlegroundMgr.m_BattlegroundQueues[bgQueueType].RemovePlayer(player->GetGUID(), false);
293  }
294  }
295 
296  player->SetInArenaTeam(0, GetSlot());
297  player->GetSession()->SendArenaTeamCommandResult(ERR_ARENA_TEAM_QUIT_S, GetName(), "", 0);
298  // delete all info regarding this team
299  for (uint32 i = 0; i < ARENA_TEAM_END; ++i)
300  player->SetArenaTeamInfoField(GetSlot(), ArenaTeamInfoType(i), 0);
301  sLog.outArena("Player: %s [GUID: %u] left arena team type: %u [Id: %u].", player->GetName(), player->GetGUIDLow(), GetType(), GetId());
302  }
303 
304  CharacterDatabase.PExecute("DELETE FROM arena_team_member WHERE arenateamid = '%u' AND guid = '%u'", GetId(), GUID_LOPART(guid));
305 }
306 
308 {
309  // event
310  if (session)
311  BroadcastEvent(ERR_ARENA_TEAM_DISBANDED_S, session->GetPlayerName(), GetName().c_str());
312 
313  while (!m_members.empty())
314  // Removing from members is done in DelMember.
315  DelMember(m_members.front().guid);
316 
317  if (session)
318  if (Player* player = session->GetPlayer())
319  sLog.outArena("Player: %s [GUID: %u] disbanded arena team type: %u [Id: %u].", player->GetName(), player->GetGUIDLow(), GetType(), GetId());
320 
322  CharacterDatabase.PExecute("DELETE FROM arena_team WHERE arenateamid = '%u'", m_TeamId);
323  CharacterDatabase.PExecute("DELETE FROM arena_team_member WHERE arenateamid = '%u'", m_TeamId); // this should be alredy done by calling DelMember(memberGuids[j]); for each member
324  CharacterDatabase.PExecute("DELETE FROM arena_team_stats WHERE arenateamid = '%u'", m_TeamId);
326  sObjectMgr.RemoveArenaTeam(m_TeamId);
327 }
328 
330 {
331  Player* pl = NULL;
332 
334  data << uint32(GetId()); // arena team id
335  data << uint32(GetMembersSize()); // members count
336  data << uint32(GetType()); // arena team type?
337 
338  for (MemberList::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
339  {
340  pl = sObjectMgr.GetPlayer(itr->guid);
341 
342  data << uint64(itr->guid); // guid
343  data << uint8((pl ? 1 : 0)); // online flag
344  data << itr->name; // member name
345  data << uint32((itr->guid == GetCaptain() ? 0 : 1));// captain flag 0 captain 1 member
346  data << uint8((pl ? pl->getLevel() : 0)); // unknown, level?
347  data << uint8(itr->Class); // class
348  data << uint32(itr->games_week); // played this week
349  data << uint32(itr->wins_week); // wins this week
350  data << uint32(itr->games_season); // played this season
351  data << uint32(itr->wins_season); // wins this season
352  data << uint32(itr->personal_rating); // personal rating
353  }
354 
355  session->SendPacket(&data);
356  DEBUG_LOG("WORLD: Sent SMSG_ARENA_TEAM_ROSTER");
357 }
358 
360 {
361  WorldPacket data(SMSG_ARENA_TEAM_QUERY_RESPONSE, 4 * 7 + GetName().size() + 1);
362  data << uint32(GetId()); // team id
363  data << GetName(); // team name
364  data << uint32(GetType()); // arena team type (2=2x2, 3=3x3 or 5=5x5)
365  data << uint32(m_BackgroundColor); // background color
366  data << uint32(m_EmblemStyle); // emblem style
367  data << uint32(m_EmblemColor); // emblem color
368  data << uint32(m_BorderStyle); // border style
369  data << uint32(m_BorderColor); // border color
370  session->SendPacket(&data);
371  DEBUG_LOG("WORLD: Sent SMSG_ARENA_TEAM_QUERY_RESPONSE");
372 }
373 
375 {
376  WorldPacket data(SMSG_ARENA_TEAM_STATS, 4 * 7);
377  data << uint32(GetId()); // team id
378  data << uint32(m_stats.rating); // rating
379  data << uint32(m_stats.games_week); // games this week
380  data << uint32(m_stats.wins_week); // wins this week
381  data << uint32(m_stats.games_season); // played this season
382  data << uint32(m_stats.wins_season); // wins this season
383  data << uint32(m_stats.rank); // rank
384  session->SendPacket(&data);
385 }
386 
388 {
389  // this is called after a rated match ended
390  // updates arena team stats for every member of the team (not only the ones who participated!)
391  for (MemberList::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
392  {
393  Player* plr = sObjectMgr.GetPlayer(itr->guid);
394  if (plr)
395  Stats(plr->GetSession());
396  }
397 }
398 
400 {
401  ArenaTeamMember* member = GetMember(guid);
402  if (!member)
403  return;
404 
405  WorldPacket data(MSG_INSPECT_ARENA_TEAMS, 8 + 1 + 4 * 6);
406  data << uint64(guid); // player guid
407  data << uint8(GetSlot()); // slot (0...2)
408  data << uint32(GetId()); // arena team id
409  data << uint32(m_stats.rating); // rating
410  data << uint32(m_stats.games_season); // season played
411  data << uint32(m_stats.wins_season); // season wins
412  data << uint32(member->games_season); // played (count of all games, that the inspected member participated...)
413  data << uint32(member->personal_rating); // personal rating
414  session->SendPacket(&data);
415 }
416 
417 void ArenaTeam::SetEmblem(uint32 backgroundColor, uint32 emblemStyle, uint32 emblemColor, uint32 borderStyle, uint32 borderColor)
418 {
419  m_BackgroundColor = backgroundColor;
420  m_EmblemStyle = emblemStyle;
421  m_EmblemColor = emblemColor;
422  m_BorderStyle = borderStyle;
423  m_BorderColor = borderColor;
424 
425  CharacterDatabase.PExecute("UPDATE arena_team SET BackgroundColor='%u', EmblemStyle='%u', EmblemColor='%u', BorderStyle='%u', BorderColor='%u' WHERE arenateamid='%u'", m_BackgroundColor, m_EmblemStyle, m_EmblemColor, m_BorderStyle, m_BorderColor, m_TeamId);
426 }
427 
429 {
430  switch (stat_type)
431  {
432  case STAT_TYPE_RATING:
433  m_stats.rating = value;
434  CharacterDatabase.PExecute("UPDATE arena_team_stats SET rating = '%u' WHERE arenateamid = '%u'", value, GetId());
435  break;
437  m_stats.games_week = value;
438  CharacterDatabase.PExecute("UPDATE arena_team_stats SET games = '%u' WHERE arenateamid = '%u'", value, GetId());
439  break;
440  case STAT_TYPE_WINS_WEEK:
441  m_stats.wins_week = value;
442  CharacterDatabase.PExecute("UPDATE arena_team_stats SET wins = '%u' WHERE arenateamid = '%u'", value, GetId());
443  break;
445  m_stats.games_season = value;
446  CharacterDatabase.PExecute("UPDATE arena_team_stats SET played = '%u' WHERE arenateamid = '%u'", value, GetId());
447  break;
449  m_stats.wins_season = value;
450  CharacterDatabase.PExecute("UPDATE arena_team_stats SET wins2 = '%u' WHERE arenateamid = '%u'", value, GetId());
451  break;
452  case STAT_TYPE_RANK:
453  m_stats.rank = value;
454  CharacterDatabase.PExecute("UPDATE arena_team_stats SET rank = '%u' WHERE arenateamid = '%u'", value, GetId());
455  break;
456  default:
457  sLog.outDebug("unknown stat type in ArenaTeam::SetStats() %u", stat_type);
458  break;
459  }
460 }
461 
463 {
464  for (MemberList::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
465  {
466  Player* player = sObjectMgr.GetPlayer(itr->guid);
467  if (player)
468  player->GetSession()->SendPacket(packet);
469  }
470 }
471 
472 void ArenaTeam::BroadcastEvent(ArenaTeamEvents event, uint64 guid, char const* str1 /*=NULL*/, char const* str2 /*=NULL*/, char const* str3 /*=NULL*/)
473 {
474  uint8 strCount = !str1 ? 0 : (!str2 ? 1 : (!str3 ? 2 : 3));
475 
476  WorldPacket data(SMSG_ARENA_TEAM_EVENT, 1 + 1 + 1 * strCount + (!guid ? 0 : 8));
477  data << uint8(event);
478  data << uint8(strCount);
479 
480  if (str3)
481  {
482  data << str1;
483  data << str2;
484  data << str3;
485  }
486  else if (str2)
487  {
488  data << str1;
489  data << str2;
490  }
491  else if (str1)
492  data << str1;
493 
494  if (guid)
495  data << guid;
496 
497  BroadcastPacket(&data);
498 
499  DEBUG_LOG("WORLD: Sent SMSG_ARENA_TEAM_EVENT");
500 }
501 
503 {
504  switch (type)
505  {
506  case ARENA_TEAM_2v2:
507  return 0;
508  case ARENA_TEAM_3v3:
509  return 1;
510  case ARENA_TEAM_5v5:
511  return 2;
512  default:
513  break;
514  }
515  sLog.outError("FATAL: Unknown arena team type %u for some arena team", type);
516  return 0xFF;
517 }
518 
520 {
521  for (MemberList::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
522  if (itr->guid == guid)
523  return true;
524 
525  return false;
526 }
527 
529 {
530  // returns how many points would be awarded with this team type with this rating
531  float points;
532 
533  uint32 rating = MemberRating + 150 < m_stats.rating ? MemberRating : m_stats.rating;
534 
535  if (rating <= 1500)
536  points = (float)rating * 0.22f + 14.0f;
537  else
538  points = 1511.26f / (1.0f + 1639.28f * exp(-0.00412f * (float)rating));
539 
540  // type penalties for <5v5 teams
541  if (m_Type == ARENA_TEAM_2v2)
542  points *= 0.76f;
543  else if (m_Type == ARENA_TEAM_3v3)
544  points *= 0.88f;
545 
546  return (uint32) points;
547 }
548 
549 float ArenaTeam::GetChanceAgainst(uint32 own_rating, uint32 enemy_rating)
550 {
551  // returns the chance to win against a team with the given rating, used in the rating adjustment calculation
552  // ELO system
553  return 1.0f / (1.0f + exp(log(10.0f) * (float)((float)enemy_rating - (float)own_rating) / 400.0f));
554 }
555 
557 {
558  if (int32(m_stats.rating) + mod < 0)
559  m_stats.rating = 0;
560  else
561  m_stats.rating += mod;
562 
563  m_stats.games_week += 1;
564  m_stats.games_season += 1;
565  // update team's rank
566  m_stats.rank = 1;
567  ObjectMgr::ArenaTeamMap::const_iterator i = sObjectMgr.GetArenaTeamMapBegin();
568  for (; i != sObjectMgr.GetArenaTeamMapEnd(); ++i)
569  {
570  if (i->second->GetType() == m_Type && i->second->GetStats().rating > m_stats.rating)
571  ++m_stats.rank;
572  }
573 }
574 
576 {
577  // called when the team has won
578  // 'chance' calculation - to beat the opponent
579  float chance = GetChanceAgainst(m_stats.rating, againstRating);
580  // calculate the rating modification (ELO system with k=32)
581  int32 mod = (int32)floor(32.0f * (1.0f - chance));
582  // modify the team stats accordingly
583  FinishGame(mod);
584  m_stats.wins_week += 1;
585  m_stats.wins_season += 1;
586 
587  // return the rating change, used to display it on the results screen
588  return mod;
589 }
590 
592 {
593  // called when the team has lost
594  // 'chance' calculation - to loose to the opponent
595  float chance = GetChanceAgainst(m_stats.rating, againstRating);
596  // calculate the rating modification (ELO system with k=32)
597  int32 mod = (int32)ceil(32.0f * (0.0f - chance));
598  // modify the team stats accordingly
599  FinishGame(mod);
600 
601  // return the rating change, used to display it on the results screen
602  return mod;
603 }
604 
605 void ArenaTeam::MemberLost(Player* plr, uint32 againstRating)
606 {
607  // called for each participant of a match after losing
608  for (MemberList::iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
609  {
610  if (itr->guid == plr->GetGUID())
611  {
612  // update personal rating
613  float chance = GetChanceAgainst(itr->personal_rating, againstRating);
614  int32 mod = (int32)ceil(32.0f * (0.0f - chance));
615  itr->ModifyPersonalRating(plr, mod, GetSlot());
616  // update personal played stats
617  itr->games_week += 1;
618  itr->games_season += 1;
619  // update the unit fields
620  plr->SetArenaTeamInfoField(GetSlot(), ARENA_TEAM_GAMES_WEEK, itr->games_week);
621  plr->SetArenaTeamInfoField(GetSlot(), ARENA_TEAM_GAMES_SEASON, itr->games_season);
622  return;
623  }
624  }
625 }
626 
628 {
629  // called for offline player after ending rated arena match!
630  for (MemberList::iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
631  {
632  if (itr->guid == guid)
633  {
634  // update personal rating
635  float chance = GetChanceAgainst(itr->personal_rating, againstRating);
636  int32 mod = (int32)ceil(32.0f * (0.0f - chance));
637 
638  int32 rating = int32(itr->personal_rating) + mod;
639  itr->personal_rating = rating < 0 ? 0 : rating;
640 
641  // update personal played stats
642  itr->games_week += 1;
643  itr->games_season += 1;
644  return;
645  }
646  }
647 }
648 
649 void ArenaTeam::MemberWon(Player* plr, uint32 againstRating)
650 {
651  // called for each participant after winning a match
652  for (MemberList::iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
653  {
654  if (itr->guid == plr->GetGUID())
655  {
656  // update personal rating
657  float chance = GetChanceAgainst(itr->personal_rating, againstRating);
658  int32 mod = (int32)floor(32.0f * (1.0f - chance));
659  itr->ModifyPersonalRating(plr, mod, GetSlot());
660  // update personal stats
661  itr->games_week += 1;
662  itr->games_season += 1;
663  itr->wins_season += 1;
664  itr->wins_week += 1;
665  // update unit fields
666  plr->SetArenaTeamInfoField(GetSlot(), ARENA_TEAM_GAMES_WEEK, itr->games_week);
667  plr->SetArenaTeamInfoField(GetSlot(), ARENA_TEAM_GAMES_SEASON, itr->games_season);
668  return;
669  }
670  }
671 }
672 
673 void ArenaTeam::UpdateArenaPointsHelper(std::map<uint32, uint32>& PlayerPoints)
674 {
675  // called after a match has ended and the stats are already modified
676  // helper function for arena point distribution (this way, when distributing, no actual calculation is required, just a few comparisons)
677  // 10 played games per week is a minimum
678  if (m_stats.games_week < 10)
679  return;
680  // to get points, a player has to participate in at least 30% of the matches
681  uint32 min_plays = (uint32) ceil(m_stats.games_week * 0.3);
682  for (MemberList::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
683  {
684  // the player participated in enough games, update his points
685  uint32 points_to_add = 0;
686  if (itr->games_week >= min_plays)
687  points_to_add = GetPoints(itr->personal_rating);
688  // OBSOLETE : CharacterDatabase.PExecute("UPDATE arena_team_member SET points_to_add = '%u' WHERE arenateamid = '%u' AND guid = '%u'", points_to_add, m_TeamId, itr->guid);
689 
690  std::map<uint32, uint32>::iterator plr_itr = PlayerPoints.find(GUID_LOPART(itr->guid));
691  if (plr_itr != PlayerPoints.end())
692  {
693  // check if there is already more points
694  if (plr_itr->second < points_to_add)
695  PlayerPoints[GUID_LOPART(itr->guid)] = points_to_add;
696  }
697  else
698  PlayerPoints[GUID_LOPART(itr->guid)] = points_to_add;
699  }
700 }
701 
703 {
704  // save team and member stats to db
705  // called after a match has ended, or when calculating arena_points
707  CharacterDatabase.PExecute("UPDATE arena_team_stats SET rating = '%u',games = '%u',played = '%u',rank = '%u',wins = '%u',wins2 = '%u' WHERE arenateamid = '%u'", m_stats.rating, m_stats.games_week, m_stats.games_season, m_stats.rank, m_stats.wins_week, m_stats.wins_season, GetId());
708  for (MemberList::iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
709  CharacterDatabase.PExecute("UPDATE arena_team_member SET played_week = '%u', wons_week = '%u', played_season = '%u', wons_season = '%u', personal_rating = '%u' WHERE arenateamid = '%u' AND guid = '%u'", itr->games_week, itr->wins_week, itr->games_season, itr->wins_season, itr->personal_rating, m_TeamId, GUID_LOPART(itr->guid));
711 }
712 
714 {
715  m_stats.games_week = 0; // played this week
716  m_stats.wins_week = 0; // wins this week
717  for (MemberList::iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
718  {
719  itr->games_week = 0;
720  itr->wins_week = 0;
721  }
722 }
723 
725 {
726  for (MemberList::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
727  if (Player* p = sObjectMgr.GetPlayer(itr->guid))
728  if (p->GetMap()->IsBattleArena())
729  return true;
730  return false;
731 }
732 
void OfflineMemberLost(uint64 guid, uint32 againstRating)
Definition: ArenaTeam.cpp:627
ArenaTeamEvents
Definition: ArenaTeam.h:49
void Query(WorldSession *session)
Definition: ArenaTeam.cpp:359
#define ARENA_NEW_TEAM_RATING
Definition: ArenaTeam.h:84
void DelMember(uint64 guid)
Definition: ArenaTeam.cpp:269
void SetArenaTeamInfoField(uint8 slot, ArenaTeamInfoType type, uint32 value)
Definition: Player.h:1844
void Disband(WorldSession *session)
Definition: ArenaTeam.cpp:307
#define GUID_LOPART(x)
Definition: ObjectGuid.h:110
bool AddMember(const uint64 &playerGuid)
Definition: ArenaTeam.cpp:90
void FinishWeek()
Definition: ArenaTeam.cpp:713
bool BeginTransaction()
Definition: Database.cpp:533
static uint8 GetSlotByType(uint32 type)
Definition: ArenaTeam.cpp:502
QueryResult_AutoPtr PQuery(const char *format,...) ATTR_PRINTF(2
Definition: Database.cpp:400
void MemberLost(Player *plr, uint32 againstRating)
Definition: ArenaTeam.cpp:605
void SetCaptain(const uint64 &guid)
Definition: ArenaTeam.cpp:248
Definition: Field.h:24
void BroadcastEvent(ArenaTeamEvents event, uint64 guid, char const *str1=NULL, char const *str2=NULL, char const *str3=NULL)
Definition: ArenaTeam.cpp:472
#define PLAYER_MAX_BATTLEGROUND_QUEUES
void UpdateArenaPointsHelper(std::map< uint32, uint32 > &PlayerPoints)
Definition: ArenaTeam.cpp:673
void Stats(WorldSession *session)
Definition: ArenaTeam.cpp:374
#define sLog
Log class singleton.
Definition: Log.h:187
ACE_INT32 int32
Definition: Define.h:67
unsigned long escape_string(char *to, const char *from, unsigned long length)
Definition: Database.cpp:212
float GetChanceAgainst(uint32 own_rating, uint32 enemy_rating)
Definition: ArenaTeam.cpp:549
Player * GetPlayer() const
Definition: WorldSession.h:104
uint32 GetGUIDLow() const
Definition: Object.h:166
int32 LostAgainst(uint32 againstRating)
Definition: ArenaTeam.cpp:591
ArenaTeamInfoType
Definition: Player.h:637
static void RemovePetitionsAndSigns(uint64 guid, uint32 type)
Definition: Player.cpp:17662
#define sObjectMgr
Definition: ObjectMgr.h:1285
void SendPacket(WorldPacket const *packet)
bool CommitTransaction()
Definition: Database.cpp:551
#define ARENA_NEW_PERSONAL_RATING
Definition: ArenaTeam.h:85
uint8 getLevel() const
Definition: Unit.h:1057
bool isArena() const
Definition: Battleground.h:481
uint32 games_season
Definition: ArenaTeam.h:94
void ModifyPersonalRating(Player *plr, int32 mod, uint32 slot)
Definition: ArenaTeam.cpp:23
void SetEmblem(uint32 backgroundColor, uint32 emblemStyle, uint32 emblemColor, uint32 borderStyle, uint32 borderColor)
Definition: ArenaTeam.cpp:417
void FinishGame(int32 mod)
Definition: ArenaTeam.cpp:556
ACE_UINT8 uint8
Definition: Define.h:73
#define UI64FMTD
Definition: Common.h:149
std::string GetCppString() const
Definition: Field.h:52
void NotifyStatsChanged()
Definition: ArenaTeam.cpp:387
void Roster(WorldSession *session)
Definition: ArenaTeam.cpp:329
Stats
void SetArenaTeamIdInvited(uint32 ArenaTeamId)
Definition: Player.h:1857
#define MAKE_NEW_GUID(l, e, h)
Definition: ObjectGuid.h:80
bool LoadArenaTeamFromDB(QueryResult_AutoPtr arenaTeamDataResult)
Definition: ArenaTeam.cpp:160
etc mysql my cnf *Then change max_allowed_packet to a bigger value
#define DEBUG_LOG(...)
Definition: Log.h:194
void SetStats(uint32 stat_type, uint32 value)
Definition: ArenaTeam.cpp:428
bool HaveMember(const uint64 &guid) const
Definition: ArenaTeam.cpp:519
bool PExecute(const char *format,...) ATTR_PRINTF(2
Definition: Database.cpp:441
void InspectStats(WorldSession *session, uint64 guid)
Definition: ArenaTeam.cpp:399
char const * GetPlayerName() const
void SaveToDB()
Definition: ArenaTeam.cpp:702
uint32 wins_season
Definition: ArenaTeam.h:95
const char * GetName() const
Definition: Object.h:704
uint32 wins_week
Definition: ArenaTeam.h:93
static uint32 GetArenaTeamIdFromDB(uint64 guid, uint8 slot)
Definition: Player.cpp:6209
ACE_UINT64 uint64
Definition: Define.h:70
uint32 personal_rating
Definition: ArenaTeam.h:96
uint32 GetPoints(uint32 MemberRating)
Definition: ArenaTeam.cpp:528
uint32 GetArenaTeamId(uint8 slot)
Definition: Player.h:1848
ACE_Refcounted_Auto_Ptr< QueryResult, ACE_Null_Mutex > QueryResult_AutoPtr
Definition: QueryResult.h:113
bool IsFighting() const
Definition: ArenaTeam.cpp:724
bool LoadMembersFromDB(QueryResult_AutoPtr arenaTeamMembersResult)
Definition: ArenaTeam.cpp:187
void MemberWon(Player *plr, uint32 againstRating)
Definition: ArenaTeam.cpp:649
uint8 getClass() const
Definition: Unit.h:1062
#define sBattlegroundMgr
void BroadcastPacket(WorldPacket *packet)
Definition: ArenaTeam.cpp:462
WorldSession * GetSession() const
Definition: Player.h:1944
uint32 games_week
Definition: ArenaTeam.h:92
void SetInArenaTeam(uint32 ArenaTeamId, uint8 slot)
Definition: Player.h:1840
DatabaseType CharacterDatabase
Accessor to the character database.
Definition: Main.cpp:54
std::string name
Definition: ArenaTeam.h:90
ACE_UINT32 uint32
Definition: Define.h:71
int32 WonAgainst(uint32 againstRating)
Definition: ArenaTeam.cpp:575
Definition: Player.h:922
bool Create(uint64 captainGuid, uint32 type, std::string arenaTeamName)
Definition: ArenaTeam.cpp:56
const uint64 & GetGUID() const
Definition: Object.h:162