OregonCore  revision 3611e8a-git
Your Favourite TBC server
BattlegroundHandler.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 "Common.h"
19 #include "WorldPacket.h"
20 #include "Opcodes.h"
21 #include "Log.h"
22 #include "Player.h"
23 #include "ObjectMgr.h"
24 #include "WorldSession.h"
25 #include "MapManager.h"
26 #include "ObjectAccessor.h"
27 #include "Object.h"
28 #include "Chat.h"
29 #include "BattlegroundMgr.h"
30 #include "BattlegroundWS.h"
31 #include "Battleground.h"
32 #include "ArenaTeam.h"
33 #include "Language.h"
34 #include "World.h"
35 #include "DisableMgr.h"
36 
38 {
39  uint64 guid;
40  recv_data >> guid;
41  sLog.outDebug("WORLD: Recvd CMSG_BATTLEMASTER_HELLO Message from (GUID: %u TypeId:%u)", GUID_LOPART(guid), GuidHigh2TypeId(GUID_HIPART(guid)));
42 
43  Creature* unit = GetPlayer()->GetMap()->GetCreature(guid);
44  if (!unit)
45  return;
46 
47  if (!unit->isBattleMaster()) // it's not battlemaster
48  return;
49 
50  // Stop the npc if moving
51  if (!unit->IsStopped())
52  unit->StopMoving();
53 
54  uint32 bgTypeId = sObjectMgr.GetBattleMasterBG(unit->GetEntry());
55 
56  if (!_player->GetBGAccessByLevel(bgTypeId))
57  {
58  // temp, must be gossip message...
60  return;
61  }
62 
63  SendBattlegGroundList(guid, bgTypeId);
64 }
65 
67 {
68  WorldPacket data;
69  sBattlegroundMgr.BuildBattlegroundListPacket(&data, guid, _player, bgTypeId);
70  SendPacket(&data);
71 }
72 
74 {
75  uint64 guid;
76  uint32 bgTypeId;
77  uint32 instanceId;
78  uint8 joinAsGroup;
79  Group* grp;
80 
81  recv_data >> guid; // battlemaster guid
82  recv_data >> bgTypeId; // battleground type id (DBC id)
83  recv_data >> instanceId; // instance id, 0 if First Available selected
84  recv_data >> joinAsGroup; // join as group
85 
86  if (bgTypeId >= MAX_BATTLEGROUND_TYPES)
87  {
88  sLog.outError("Battleground: invalid bgtype received. possible cheater? player guid %u", _player->GetGUIDLow());
89  return;
90  }
91 
92  if (sDisableMgr.IsDisabledFor(DISABLE_TYPE_BATTLEGROUND, bgTypeId, NULL))
93  {
95  return;
96  }
97 
98  sLog.outDebug("WORLD: Recvd CMSG_BATTLEMASTER_JOIN Message from (GUID: %u TypeId:%u)", GUID_LOPART(guid), GuidHigh2TypeId(GUID_HIPART(guid)));
99 
100  // can do this, since it's battleground, not arena
101  uint32 bgQueueTypeId = sBattlegroundMgr.BGQueueTypeId(bgTypeId, 0);
102 
103  // ignore if player is already in BG
104  if (_player->InBattleground())
105  return;
106 
107  Creature* unit = GetPlayer()->GetMap()->GetCreature(guid);
108  if (!unit)
109  return;
110 
111  if (!unit->isBattleMaster()) // it's not battlemaster
112  return;
113 
114  // get bg instance or bg template if instance not found
115  Battleground* bg = NULL;
116  if (instanceId)
117  bg = sBattlegroundMgr.GetBattleground(instanceId);
118 
119  if (!bg && !(bg = sBattlegroundMgr.GetBattlegroundTemplate(bgTypeId)))
120  {
121  sLog.outError("Battleground: no available bg / template found");
122  return;
123  }
124 
125  // check queueing conditions
126  if (!joinAsGroup)
127  {
128  // check Deserter debuff
130  {
132  data << (uint32) 0xFFFFFFFE;
133  _player->GetSession()->SendPacket(&data);
134  return;
135  }
136  // check if already in queue
138  //player is already in this queue
139  return;
140  // check if has free queue slots
142  return;
143  }
144  else
145  {
146  grp = _player->GetGroup();
147  // no group found, error
148  if (!grp)
149  return;
150  uint32 err = grp->CanJoinBattlegroundQueue(bgTypeId, bgQueueTypeId, 0, bg->GetMaxPlayersPerTeam(), false, 0);
151  if (err != BG_JOIN_ERR_OK)
152  {
154  return;
155  }
156  }
157  // if we're here, then the conditions to join a bg are met. We can proceed in joining.
158 
159  // _player->GetGroup() was already checked, grp is already initialized
160  if (joinAsGroup /* && _player->GetGroup()*/)
161  {
162  sLog.outDebug("Battleground: the following players are joining as group:");
163  GroupQueueInfo* ginfo = sBattlegroundMgr.m_BattlegroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, 0, false, 0);
164  for (GroupReference* itr = grp->GetFirstMember(); itr != NULL; itr = itr->next())
165  {
166  Player* member = itr->GetSource();
167  if (!member) continue; // this should never happen
168 
169  uint32 queueSlot = member->AddBattlegroundQueueId(bgQueueTypeId); // add to queue
170 
171  // store entry point coords (same as leader entry point)
174 
175  WorldPacket data;
176  // send status packet (in queue)
177  sBattlegroundMgr.BuildBattlegroundStatusPacket(&data, bg, member->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0);
178  member->GetSession()->SendPacket(&data);
179  sBattlegroundMgr.BuildGroupJoinedBattlegroundPacket(&data, bgTypeId);
180  member->GetSession()->SendPacket(&data);
181  sBattlegroundMgr.m_BattlegroundQueues[bgQueueTypeId].AddPlayer(member, ginfo);
182  sLog.outDebug("Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s", bgQueueTypeId, bgTypeId, member->GetGUIDLow(), member->GetName());
183  }
184  sLog.outDebug("Battleground: group end");
185  sBattlegroundMgr.m_BattlegroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattlegroundQueueIdFromLevel());
186  }
187  else
188  {
189  // already checked if queueSlot is valid, now just get it
190  uint32 queueSlot = _player->AddBattlegroundQueueId(bgQueueTypeId);
191  // store entry point coords
194 
195  WorldPacket data;
196  // send status packet (in queue)
197  sBattlegroundMgr.BuildBattlegroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0);
198  SendPacket(&data);
199 
200  GroupQueueInfo* ginfo = sBattlegroundMgr.m_BattlegroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, 0, false, 0);
201  sBattlegroundMgr.m_BattlegroundQueues[bgQueueTypeId].AddPlayer(_player, ginfo);
202  sBattlegroundMgr.m_BattlegroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattlegroundQueueIdFromLevel());
203  sLog.outDebug("Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s", bgQueueTypeId, bgTypeId, _player->GetGUIDLow(), _player->GetName());
204  }
205 }
206 
208 {
209  // empty opcode
210  sLog.outDebug("WORLD: Recvd MSG_BATTLEGROUND_PLAYER_POSITIONS Message");
211 
213  if (!bg) // can't be received if player not in battleground
214  return;
215 
216  switch (bg->GetTypeID())
217  {
218  case BATTLEGROUND_WS:
219  {
220  uint32 count1 = 0; //always constant zero?
221  uint32 count2 = 0; //count of next fields
222 
223  Player* ali_plr = sObjectMgr.GetPlayer(((BattlegroundWS*)bg)->GetAllianceFlagPickerGUID());
224  if (ali_plr)
225  ++count2;
226 
227  Player* horde_plr = sObjectMgr.GetPlayer(((BattlegroundWS*)bg)->GetHordeFlagPickerGUID());
228  if (horde_plr)
229  ++count2;
230 
231  WorldPacket data(MSG_BATTLEGROUND_PLAYER_POSITIONS, (4 + 4 + 16 * count1 + 16 * count2));
232  data << count1; // alliance flag holders count - obsolete, now always 0
233  /*for (uint8 i = 0; i < count1; ++i)
234  {
235  data << uint64(0); // guid
236  data << (float)0; // x
237  data << (float)0; // y
238  }*/
239  data << count2; // horde flag holders count - obsolete, now count of next fields
240  if (ali_plr)
241  {
242  data << (uint64)ali_plr->GetGUID();
243  data << (float)ali_plr->GetPositionX();
244  data << (float)ali_plr->GetPositionY();
245  }
246  if (horde_plr)
247  {
248  data << (uint64)horde_plr->GetGUID();
249  data << (float)horde_plr->GetPositionX();
250  data << (float)horde_plr->GetPositionY();
251  }
252 
253  SendPacket(&data);
254  }
255  break;
256  case BATTLEGROUND_EY:
257  //TODO : fix me!
258  break;
259  case BATTLEGROUND_AB:
260  case BATTLEGROUND_AV:
261  {
262  //for other BG types - send default
264  data << uint32(0);
265  data << uint32(0);
266  SendPacket(&data);
267  }
268  break;
269  default:
270  //maybe it is sent also in arena - do nothing
271  break;
272  }
273 }
274 
276 {
277  sLog.outDebug("WORLD: Recvd MSG_PVP_LOG_DATA Message");
278 
280  if (!bg)
281  return;
282 
283  WorldPacket data;
284  sBattlegroundMgr.BuildPvpLogDataPacket(&data, bg);
285  SendPacket(&data);
286 
287  DEBUG_LOG("WORLD: Sent MSG_PVP_LOG_DATA Message");
288 }
289 
291 {
292  sLog.outDebug("WORLD: Recvd CMSG_BATTLEFIELD_LIST Message");
293 
294  uint32 bgTypeId;
295  recv_data >> bgTypeId; // id from DBC
296 
297  if (bgTypeId >= MAX_BATTLEGROUND_TYPES)
298  {
299  sLog.outError("Battleground: invalid bgtype received.");
300  return;
301  }
302 
303  BattlemasterListEntry const* bl = sBattlemasterListStore.LookupEntry(bgTypeId);
304 
305  if (!bl)
306  return;
307 
308  WorldPacket data;
309  sBattlegroundMgr.BuildBattlegroundListPacket(&data, _player->GetGUID(), _player, bgTypeId);
310  SendPacket(&data);
311 }
312 
314 {
315  sLog.outDebug("WORLD: Recvd CMSG_BATTLEFIELD_PORT Message");
316 
317  uint8 type; // arenatype if arena
318  uint8 unk2; // unk, can be 0x0 (may be if was invited?) and 0x1
319  uint32 instanceId;
320  uint32 bgTypeId; // type id from dbc
321  uint16 unk; // 0x1F90 constant?
322  uint8 action; // enter battle 0x1, leave queue 0x0
323 
324  recv_data >> type >> unk2 >> bgTypeId >> unk >> action;
325 
326  if (bgTypeId >= MAX_BATTLEGROUND_TYPES)
327  {
328  sLog.outError("Battleground: invalid bgtype received.");
329  // update battleground slots for the player to fix his UI and sent data.
330  // this is a HACK, I don't know why the client starts sending invalid packets in the first place.
331  // it usually happens with extremely high latency (if debugging / stepping in the code for example)
333  {
334  // update all queues, send invitation info if player is invited, queue info if queued
335  for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++)
336  {
337  uint32 queue_id = _player->GetBattlegroundQueueId(i);
338  if (!queue_id)
339  continue;
340  BattlegroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = sBattlegroundMgr.m_BattlegroundQueues[queue_id].m_QueuedPlayers[_player->GetBattlegroundQueueIdFromLevel()].find(_player->GetGUID());
341  // if the player is not in queue, contine
342  if (itrPlayerStatus == sBattlegroundMgr.m_BattlegroundQueues[queue_id].m_QueuedPlayers[_player->GetBattlegroundQueueIdFromLevel()].end())
343  continue;
344 
345  // no group information, this should never happen
346  if (!itrPlayerStatus->second.GroupInfo)
347  continue;
348 
349  Battleground* bg = NULL;
350 
351  // get possibly needed data from groupinfo
352  bgTypeId = itrPlayerStatus->second.GroupInfo->BgTypeId;
353  uint8 arenatype = itrPlayerStatus->second.GroupInfo->ArenaType;
354  uint8 israted = itrPlayerStatus->second.GroupInfo->IsRated;
355  uint8 status = 0;
356 
357 
358  if (!itrPlayerStatus->second.GroupInfo->IsInvitedToBGInstanceGUID)
359  {
360  // not invited to bg, get template
361  bg = sBattlegroundMgr.GetBattlegroundTemplate(bgTypeId);
362  status = STATUS_WAIT_QUEUE;
363  }
364  else
365  {
366  // get the bg we're invited to
367  bg = sBattlegroundMgr.GetBattleground(itrPlayerStatus->second.GroupInfo->IsInvitedToBGInstanceGUID);
368  status = STATUS_WAIT_JOIN;
369  }
370 
371  // if bg not found, then continue
372  if (!bg)
373  continue;
374 
375  // don't invite if already in the instance
377  continue;
378 
379  // re - invite player with proper data
380  WorldPacket data;
381  sBattlegroundMgr.BuildBattlegroundStatusPacket(&data, bg, itrPlayerStatus->second.GroupInfo->Team ? itrPlayerStatus->second.GroupInfo->Team : _player->GetTeam(), i, status, INVITE_ACCEPT_WAIT_TIME, 0, arenatype, israted);
382  SendPacket(&data);
383  }
384  }
385  return;
386  }
387 
388  uint32 bgQueueTypeId = 0;
389  // get the bg what we were invited to
390  BattlegroundQueue::QueuedPlayersMap::iterator itrPlayerStatus;
391  bgQueueTypeId = sBattlegroundMgr.BGQueueTypeId(bgTypeId, type);
392  itrPlayerStatus = sBattlegroundMgr.m_BattlegroundQueues[bgQueueTypeId].m_QueuedPlayers[_player->GetBattlegroundQueueIdFromLevel()].find(_player->GetGUID());
393 
394  if (itrPlayerStatus == sBattlegroundMgr.m_BattlegroundQueues[bgQueueTypeId].m_QueuedPlayers[_player->GetBattlegroundQueueIdFromLevel()].end())
395  {
396  sLog.outError("Battleground: itrplayerstatus not found.");
397  return;
398  }
399  instanceId = itrPlayerStatus->second.GroupInfo->IsInvitedToBGInstanceGUID;
400 
401  // if action == 1, then instanceId is _required_
402  if (!instanceId && action == 1)
403  {
404  sLog.outError("Battleground: instance not found.");
405  return;
406  }
407 
408  Battleground* bg = sBattlegroundMgr.GetBattleground(instanceId);
409 
410  // bg template might and must be used in case of leaving queue, when instance is not created yet
411  if (!bg && action == 0)
412  bg = sBattlegroundMgr.GetBattlegroundTemplate(bgTypeId);
413 
414  if (!bg)
415  {
416  sLog.outError("Battleground: bg not found.");
417  return;
418  }
419 
420  bgTypeId = bg->GetTypeID();
421 
423  {
424  uint32 queueSlot = 0;
425  uint32 team = 0;
426  uint32 arenatype = 0;
427  uint32 israted = 0;
428  uint32 rating = 0;
429  uint32 opponentsRating = 0;
430  // get the team info from the queue
431  BattlegroundQueue::QueuedPlayersMap::iterator pitr = sBattlegroundMgr.m_BattlegroundQueues[bgQueueTypeId].m_QueuedPlayers[_player->GetBattlegroundQueueIdFromLevel()].find(_player->GetGUID());
432  if (pitr != sBattlegroundMgr.m_BattlegroundQueues[bgQueueTypeId].m_QueuedPlayers[_player->GetBattlegroundQueueIdFromLevel()].end()
433  && pitr->second.GroupInfo)
434  {
435  team = pitr->second.GroupInfo->Team;
436  arenatype = pitr->second.GroupInfo->ArenaType;
437  israted = pitr->second.GroupInfo->IsRated;
438  rating = pitr->second.GroupInfo->ArenaTeamRating;
439  opponentsRating = pitr->second.GroupInfo->OpponentsTeamRating;
440  }
441  else
442  {
443  sLog.outError("Battleground: Invalid player queue info!");
444  return;
445  }
446  // if player is trying to enter battleground (not arena) and he has deserter debuff, we must just remove him from queue
447  if (arenatype == 0 && !_player->CanJoinToBattleground())
448  {
449  sLog.outDebug("Battleground: player %s (%u) has a deserter debuff, do not port him to battleground!", _player->GetName(), _player->GetGUIDLow());
450  action = 0;
451  }
452  WorldPacket data;
453  switch (action)
454  {
455  case 1: // port to battleground
456  if (!_player->IsInvitedForBattlegroundQueueType(bgQueueTypeId))
457  return; // cheating?
458 
461 
462  // resurrect the player
463  if (!_player->IsAlive())
464  {
465  _player->ResurrectPlayer(1.0f);
467  }
468  // stop taxi flight at port
469  if (_player->isInFlight())
470  {
473  }
474  queueSlot = _player->GetBattlegroundQueueIndex(bgQueueTypeId);
475  sBattlegroundMgr.BuildBattlegroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_IN_PROGRESS, 0, bg->GetStartTime());
476  _player->GetSession()->SendPacket(&data);
477  // remove battleground queue status from BGmgr
478  sBattlegroundMgr.m_BattlegroundQueues[bgQueueTypeId].RemovePlayer(_player->GetGUID(), false);
479  // this is still needed here if battleground "jumping" shouldn't add deserter debuff
480  // also this required to prevent stuck at old battleground after SetBattlegroundId set to new
481  if (Battleground* currentBg = _player->GetBattleground())
482  currentBg->RemovePlayerAtLeave(_player->GetGUID(), false, true);
483 
484  // set the destination instance id
486  // set the destination team
487  _player->SetBGTeam(team);
488  // bg->HandleBeforeTeleportToBattleground(_player);
489  sBattlegroundMgr.SendToBattleground(_player, instanceId);
490  // add only in HandleMoveWorldPortAck()
491  // bg->AddPlayer(_player,team);
492  sLog.outDebug("Battleground: player %s (%u) joined battle for bg %u, bgtype %u, queue type %u.", _player->GetName(), _player->GetGUIDLow(), bg->GetInstanceID(), bg->GetTypeID(), bgQueueTypeId);
493  break;
494  case 0: // leave queue
495  queueSlot = _player->GetBattlegroundQueueIndex(bgQueueTypeId);
496  /*
497  if player leaves rated arena match before match start, it is counted as he played but he lost
498  */
499  if (israted)
500  {
501  ArenaTeam* at = sObjectMgr.GetArenaTeamById(team);
502  if (at)
503  {
504  sLog.outDebug("UPDATING memberLost's personal arena rating for %u by opponents rating: %u, because he has left queue!", GUID_LOPART(_player->GetGUID()), opponentsRating);
505  at->MemberLost(_player, opponentsRating);
506  at->SaveToDB();
507  }
508  }
509  _player->RemoveBattlegroundQueueId(bgQueueTypeId); // must be called this way, because if you move this call to queue->removeplayer, it causes bugs
510  sBattlegroundMgr.BuildBattlegroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_NONE, 0, 0);
511  sBattlegroundMgr.m_BattlegroundQueues[bgQueueTypeId].RemovePlayer(_player->GetGUID(), true);
512  // player left queue, we should update it, maybe now his group fits in
513  sBattlegroundMgr.m_BattlegroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattlegroundQueueIdFromLevel(), arenatype, israted, rating);
514  SendPacket(&data);
515  sLog.outDebug("Battleground: player %s (%u) left queue for bgtype %u, queue type %u.", _player->GetName(), _player->GetGUIDLow(), bg->GetTypeID(), bgQueueTypeId);
516  break;
517  default:
518  sLog.outError("Battleground port: unknown action %u", action);
519  break;
520  }
521  }
522 }
523 
525 {
526  sLog.outDebug("WORLD: Recvd CMSG_LEAVE_BATTLEFIELD Message");
527 
528  recv_data.read_skip<uint8>(); // unk1
529  recv_data.read_skip<uint8>(); // unk2
530  recv_data.read_skip<uint32>(); // BattlegroundTypeId
531  recv_data.read_skip<uint16>(); // unk3
532 
533  //if (bgTypeId >= MAX_BATTLEGROUND_TYPES) // cheating? but not important in this case
534  // return;
535 
536  // not allow leave battleground in combat
537  if (_player->IsInCombat())
538  if (Battleground* bg = _player->GetBattleground())
539  if (bg->GetStatus() != STATUS_WAIT_LEAVE)
540  return;
541 
543 }
544 
546 {
547  // empty opcode
548  sLog.outDebug("WORLD: Battleground status");
549 
550  WorldPacket data;
551 
552  // @todo we must put player back to battleground in case disconnect (< 5 minutes offline time) or teleport player on login(!) from battleground map to entry point
553  if (_player->InBattleground())
554  {
556  if (bg)
557  {
558  uint32 bgQueueTypeId = sBattlegroundMgr.BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType());
559  uint32 queueSlot = _player->GetBattlegroundQueueIndex(bgQueueTypeId);
560  if ((bg->GetStatus() <= STATUS_IN_PROGRESS))
561  {
562  sBattlegroundMgr.BuildBattlegroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_IN_PROGRESS, 0, bg->GetStartTime());
563  SendPacket(&data);
564  }
565  for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++)
566  {
567  uint32 queue_id = _player->GetBattlegroundQueueId(i); // battlegroundqueueid stores the type id, not the instance id, so this is definitely wrong
568  uint8 arenatype = sBattlegroundMgr.BGArenaType(queue_id);
569  uint8 isRated = 0;
570  if (i == queueSlot || !queue_id) // we need to get the instance ids
571  continue;
572  BattlegroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = sBattlegroundMgr.m_BattlegroundQueues[queue_id].m_QueuedPlayers[_player->GetBattlegroundQueueIdFromLevel()].find(_player->GetGUID());
573  if (itrPlayerStatus == sBattlegroundMgr.m_BattlegroundQueues[queue_id].m_QueuedPlayers[_player->GetBattlegroundQueueIdFromLevel()].end())
574  continue;
575  if (itrPlayerStatus->second.GroupInfo)
576  {
577  arenatype = itrPlayerStatus->second.GroupInfo->ArenaType;
578  isRated = itrPlayerStatus->second.GroupInfo->IsRated;
579  }
580  Battleground* bg2 = sBattlegroundMgr.GetBattlegroundTemplate(sBattlegroundMgr.BGTemplateId(queue_id)); // try this
581  if (bg2)
582  {
583  //in this call is small bug, this call should be filled by player's waiting time in queue
584  //this call nulls all timers for client :
585  sBattlegroundMgr.BuildBattlegroundStatusPacket(&data, bg2, _player->GetTeam(), i, STATUS_WAIT_QUEUE, 0, 0, arenatype, isRated);
586  SendPacket(&data);
587  }
588  }
589  }
590  }
591  else
592  {
593  // we should update all queues? .. i'm not sure if this code is correct
594  for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++)
595  {
596  uint32 queue_id = _player->GetBattlegroundQueueId(i);
597  if (!queue_id)
598  continue;
599 
600  uint32 bgTypeId = sBattlegroundMgr.BGTemplateId(queue_id);
601  uint8 arenatype = sBattlegroundMgr.BGArenaType(queue_id);
602  uint8 isRated = 0;
603  Battleground* bg = sBattlegroundMgr.GetBattlegroundTemplate(bgTypeId);
604  BattlegroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = sBattlegroundMgr.m_BattlegroundQueues[queue_id].m_QueuedPlayers[_player->GetBattlegroundQueueIdFromLevel()].find(_player->GetGUID());
605  if (itrPlayerStatus == sBattlegroundMgr.m_BattlegroundQueues[queue_id].m_QueuedPlayers[_player->GetBattlegroundQueueIdFromLevel()].end())
606  continue;
607  if (itrPlayerStatus->second.GroupInfo)
608  {
609  arenatype = itrPlayerStatus->second.GroupInfo->ArenaType;
610  isRated = itrPlayerStatus->second.GroupInfo->IsRated;
611  }
612  if (bg && queue_id)
613  {
614  sBattlegroundMgr.BuildBattlegroundStatusPacket(&data, bg, _player->GetTeam(), i, STATUS_WAIT_QUEUE, 0, 0, arenatype, isRated);
615  SendPacket(&data);
616  }
617  }
618  }
619  /* else // not sure if it needed...
620  {
621  for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++)
622  {
623  sBattlegroundMgr.BuildBattlegroundStatusPacket(&data, NULL, _player->GetTeam(),i , STATUS_NONE, 0, 0);
624  SendPacket(&data);
625  }
626  }*/
627 }
628 
630 {
631  sLog.outDebug("WORLD: CMSG_AREA_SPIRIT_HEALER_QUERY");
632 
634  if (!bg)
635  return;
636 
637  uint64 guid;
638  recv_data >> guid;
639 
640  Creature* unit = GetPlayer()->GetMap()->GetCreature(guid);
641  if (!unit)
642  return;
643 
644  if (!unit->isSpiritService()) // it's not spirit service
645  return;
646 
647  sBattlegroundMgr.SendAreaSpiritHealerQueryOpcode(_player, bg, guid);
648 }
649 
651 {
652  sLog.outDebug("WORLD: CMSG_AREA_SPIRIT_HEALER_QUEUE");
653 
655  if (!bg)
656  return;
657 
658  uint64 guid;
659  recv_data >> guid;
660 
661  Creature* unit = GetPlayer()->GetMap()->GetCreature(guid);
662  if (!unit)
663  return;
664 
665  if (!unit->isSpiritService()) // it's not spirit service
666  return;
667 
669 }
670 
672 {
673  sLog.outDebug("WORLD: CMSG_BATTLEMASTER_JOIN_ARENA");
674  //recv_data.hexlike();
675 
676  uint64 guid; // arena Battlemaster guid
677  uint8 arenaslot; // 2v2, 3v3 or 5v5
678  uint8 asGroup; // asGroup
679  uint8 isRated; // isRated
680  Group* grp = NULL;
681 
682  recv_data >> guid >> arenaslot >> asGroup >> isRated;
683 
684  // ignore if we already in BG or BG queue
685  if (_player->InBattleground())
686  return;
687 
688  Creature* unit = GetPlayer()->GetMap()->GetCreature(guid);
689  if (!unit)
690  return;
691 
692  if (!unit->isBattleMaster()) // it's not battle master
693  return;
694 
695  uint8 arenatype = 0;
696  uint32 arenaRating = 0;
697 
698  switch (arenaslot)
699  {
700  case 0:
701  arenatype = ARENA_TYPE_2v2;
702  break;
703  case 1:
704  arenatype = ARENA_TYPE_3v3;
705  break;
706  case 2:
707  arenatype = ARENA_TYPE_5v5;
708  break;
709  default:
710  sLog.outError("Unknown arena slot %u at HandleBattlegroundArenaJoin()", arenaslot);
711  return;
712  }
713 
714  //check existance
715  Battleground* bg = NULL;
716  if (!(bg = sBattlegroundMgr.GetBattlegroundTemplate(BATTLEGROUND_AA)))
717  {
718  sLog.outError("Battleground: template bg (all arenas) not found");
719  return;
720  }
721 
722  if (sDisableMgr.IsDisabledFor(DISABLE_TYPE_BATTLEGROUND, BATTLEGROUND_AA, NULL))
723  {
725  return;
726  }
727 
728  uint8 bgTypeId = bg->GetTypeID();
729  uint32 bgQueueTypeId = sBattlegroundMgr.BGQueueTypeId(bgTypeId, arenatype);
730 
731  // check queueing conditions
732  if (!asGroup)
733  {
734  // check if already in queue
736  //player is already in this queue
737  return;
738  // check if has free queue slots
740  return;
741  }
742  else
743  {
744  grp = _player->GetGroup();
745  // no group found, error
746  if (!grp)
747  return;
748  uint32 err = grp->CanJoinBattlegroundQueue(bgTypeId, bgQueueTypeId, arenatype, arenatype, (bool)isRated, arenaslot);
749  if (err != BG_JOIN_ERR_OK)
750  {
752  return;
753  }
754  }
755 
756  uint32 ateamId = 0;
757 
758  if (isRated)
759  {
760  ateamId = _player->GetArenaTeamId(arenaslot);
761  // check real arenateam existence only here (if it was moved to group->CanJoin .. () then we would ahve to get it twice)
762  ArenaTeam* at = sObjectMgr.GetArenaTeamById(ateamId);
763  if (!at)
764  {
766  return;
767  }
768  // get the team rating for queueing
769  arenaRating = at->GetRating();
770  // the arenateam id must match for everyone in the group
771  // get the personal ratings for queueing
772  uint32 avg_pers_rating = 0;
773  for (GroupReference* itr = grp->GetFirstMember(); itr != NULL; itr = itr->next())
774  {
775  Player* member = itr->GetSource();
776 
777  // calc avg personal rating
778  avg_pers_rating += member->GetArenaPersonalRating(arenaslot);
779  }
780 
781  if (arenatype)
782  avg_pers_rating /= arenatype;
783 
784  // if avg personal rating is more than 150 points below the teams rating, the team will be queued against an opponent matching or similar to the average personal rating
785  if (avg_pers_rating + 150 < arenaRating)
786  arenaRating = avg_pers_rating;
787  }
788 
789  if (asGroup)
790  {
791  GroupQueueInfo* ginfo = sBattlegroundMgr.m_BattlegroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, arenatype, isRated, arenaRating, ateamId);
792  sLog.outDebug("Battleground: arena join as group start");
793  if (isRated)
794  sLog.outDebug("Battleground: arena team id %u, leader %s queued with rating %u for type %u", _player->GetArenaTeamId(arenaslot), _player->GetName(), arenaRating, arenatype);
795  for (GroupReference* itr = grp->GetFirstMember(); itr != NULL; itr = itr->next())
796  {
797  Player* member = itr->GetSource();
798  if (!member) continue;
799 
800  uint32 queueSlot = member->AddBattlegroundQueueId(bgQueueTypeId);// add to queue
801 
802  // store entry point coords (same as leader entry point)
805 
806  WorldPacket data;
807  // send status packet (in queue)
808  sBattlegroundMgr.BuildBattlegroundStatusPacket(&data, bg, member->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0, arenatype, isRated);
809  member->GetSession()->SendPacket(&data);
810  sBattlegroundMgr.BuildGroupJoinedBattlegroundPacket(&data, bgTypeId);
811  member->GetSession()->SendPacket(&data);
812  sBattlegroundMgr.m_BattlegroundQueues[bgQueueTypeId].AddPlayer(member, ginfo);
813  sLog.outDebug("Battleground: player joined queue for arena as group bg queue type %u bg type %u: GUID %u, NAME %s", bgQueueTypeId, bgTypeId, member->GetGUIDLow(), member->GetName());
814  }
815  sLog.outDebug("Battleground: arena join as group end");
816  sBattlegroundMgr.m_BattlegroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattlegroundQueueIdFromLevel(), arenatype, isRated, arenaRating);
817  }
818  else
819  {
820  uint32 queueSlot = _player->AddBattlegroundQueueId(bgQueueTypeId);
821 
822  // store entry point coords
825 
826  WorldPacket data;
827  // send status packet (in queue)
828  sBattlegroundMgr.BuildBattlegroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0, arenatype, isRated);
829  SendPacket(&data);
830  GroupQueueInfo* ginfo = sBattlegroundMgr.m_BattlegroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, arenatype, isRated, arenaRating);
831  sBattlegroundMgr.m_BattlegroundQueues[bgQueueTypeId].AddPlayer(_player, ginfo);
832  sBattlegroundMgr.m_BattlegroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattlegroundQueueIdFromLevel(), arenatype, isRated, arenaRating);
833  sLog.outDebug("Battleground: player joined queue for arena, skirmish, bg queue type %u bg type %u: GUID %u, NAME %s", bgQueueTypeId, bgTypeId, _player->GetGUIDLow(), _player->GetName());
834  }
835 }
836 
838 {
839  uint64 playerGuid;
840  recv_data >> playerGuid;
841  Player* reportedPlayer = sObjectMgr.GetPlayer(playerGuid);
842 
843  if (!reportedPlayer)
844  {
845  sLog.outDebug("WorldSession::HandleBattlegroundReportAFK: player not found");
846  return;
847  }
848 
849  sLog.outDebug("WorldSession::HandleBattlegroundReportAFK: %s reported %s", _player->GetName(), reportedPlayer->GetName());
850 
851  reportedPlayer->ReportedAfkBy(_player);
852 }
853 
855 {
856  WorldPacket data;
857  int32 msg;
858  switch (err)
859  {
862  break;
865  break;
868  break;
871  break;
874  break;
877  break;
880  break;
883  default:
884  return;
885  break;
886  }
888  SendPacket(&data);
889  return;
890 }
891 
void SendNotification(const char *format,...) ATTR_PRINTF(2
Group * GetGroup()
Definition: Player.h:2589
void read_skip()
Definition: ByteBuffer.h:276
void HandleAreaSpiritHealerQueueOpcode(WorldPacket &recv_data)
#define GUID_LOPART(x)
Definition: ObjectGuid.h:110
Battleground * GetBattleground() const
Definition: Player.cpp:19386
#define sDisableMgr
Definition: DisableMgr.h:73
void HandleBattlegroundPlayerPositionsOpcode(WorldPacket &recv_data)
Map * GetMap() const
Definition: Object.h:829
uint32 AddBattlegroundQueueId(uint32 val)
Definition: Player.h:2257
void MemberLost(Player *plr, uint32 againstRating)
Definition: ArenaTeam.cpp:605
#define PLAYER_MAX_BATTLEGROUND_QUEUES
void SetBGTeam(uint32 team)
Definition: Player.h:2312
void SendBattlegroundOrArenaJoinError(uint8 err)
DBCStorage< BattlemasterListEntry > sBattlemasterListStore(BattlemasterListEntryfmt)
MotionMaster * GetMotionMaster()
Definition: Unit.h:2001
bool IsInCombat() const
Definition: Unit.h:1318
void SetBattlegroundEntryPoint()
Definition: Player.cpp:18557
#define sLog
Log class singleton.
Definition: Log.h:187
void HandleBattlegroundListOpcode(WorldPacket &recv_data)
void HandleAreaSpiritHealerQueryOpcode(WorldPacket &recv_data)
ACE_INT32 int32
Definition: Define.h:67
bool CanJoinToBattleground() const
Definition: Player.cpp:18631
#define GUID_HIPART(x)
Definition: ObjectGuid.h:82
Player * GetPlayer() const
Definition: WorldSession.h:104
uint32 GetGUIDLow() const
Definition: Object.h:160
void SpawnCorpseBones()
Definition: Player.cpp:4380
uint32 GetStatus() const
Definition: Battleground.h:317
void SendBattlegGroundList(uint64 guid, uint32 bgTypeId)
#define sObjectMgr
Definition: ObjectMgr.h:1285
void SendPacket(WorldPacket const *packet)
uint32 CanJoinBattlegroundQueue(uint32 bgTypeId, uint32 bgQueueType, uint32 MinPlayerCount, uint32 MaxPlayerCount, bool isRated, uint32 arenaSlot)
Definition: Group.cpp:1441
#define MAX_BATTLEGROUND_TYPES
void HandleBattlegroundLeaveOpcode(WorldPacket &recv_data)
uint32 GetRating() const
Definition: ArenaTeam.h:150
bool isBattleMaster() const
Definition: Unit.h:1256
Creature * GetCreature(uint64 guid)
Definition: Map.cpp:2632
uint32 GetBattlegroundQueueId(uint32 index) const
Definition: Player.h:2230
ACE_UINT8 uint8
Definition: Define.h:73
float GetOrientation() const
Definition: Position.h:100
uint8 GetArenaType() const
Definition: Battleground.h:364
uint32 GuidHigh2TypeId(uint32 guid_hi)
Definition: Object.cpp:43
void HandleBattlegroundHelloOpcode(WorldPacket &recv_data)
uint32 GetBattlegroundQueueIndex(uint32 bgQueueType) const
Definition: Player.h:2234
void LeaveBattleground(bool teleportToEntryPoint=true)
Definition: Player.cpp:18607
bool IsStopped() const
Definition: Unit.h:2006
void PSendSysMessage(const char *format,...) ATTR_PRINTF(2
Definition: Chat.cpp:855
bool IsAlive() const
Definition: Unit.h:1433
float GetPositionY() const
Definition: Position.h:98
void HandleBattlegroundPlayerPortOpcode(WorldPacket &recv_data)
float GetPositionZ() const
Definition: Position.h:99
uint32 GetArenaPersonalRating(uint8 slot)
Definition: Player.h:1866
#define DEBUG_LOG(...)
Definition: Log.h:194
void ResurrectPlayer(float restore_percent, bool applySickness=false)
Definition: Player.cpp:4209
void HandleBattlegroundReportAFK(WorldPacket &recv_data)
uint32 GetMapId() const
Definition: Object.h:585
GroupReference * GetFirstMember()
Definition: Group.h:304
const char * GetOregonString(int32 entry) const
void CleanupAfterTaxiFlight()
Definition: Player.cpp:17893
GroupReference * next()
uint32 GetInstanceID() const
Definition: Battleground.h:313
void SaveToDB()
Definition: ArenaTeam.cpp:702
void SetBattlegroundId(uint32 val)
Definition: Player.h:2253
const char * GetName() const
Definition: Object.h:692
bool InBattlegroundQueue() const
Definition: Player.h:2222
ACE_UINT64 uint64
Definition: Define.h:70
void AddPlayerToResurrectQueue(uint64 npc_guid, uint64 player_guid)
bool InBattleground() const
Definition: Player.h:2207
uint32 GetArenaTeamId(uint8 slot)
Definition: Player.h:1862
uint32 GetTypeID() const
Definition: Battleground.h:305
bool isSpiritService() const
Definition: Unit.h:1296
Player * _player
Definition: WorldSession.h:729
uint32 GetStartTime() const
Definition: Battleground.h:321
uint32 GetMaxPlayersPerTeam() const
Definition: Battleground.h:351
bool HasFreeBattlegroundQueueId()
Definition: Player.h:2270
#define sBattlegroundMgr
uint32 GetTeam() const
Definition: Player.h:2075
void ReportedAfkBy(Player *reporter)
Definition: Player.cpp:18650
uint32 GetEntry() const
Definition: Object.h:186
WorldSession * GetSession() const
Definition: Player.h:1959
#define sWorld
Definition: World.h:860
void HandleBattlegroundJoinOpcode(WorldPacket &recv_data)
ACE_UINT16 uint16
Definition: Define.h:72
bool isInFlight() const
Definition: Unit.h:1308
void HandleBattlefieldStatusOpcode(WorldPacket &recv_data)
ACE_UINT32 uint32
Definition: Define.h:71
float GetPositionX() const
Definition: Position.h:97
uint32 GetBattlegroundQueueIdFromLevel() const
Definition: Player.cpp:19436
void MovementExpired(bool reset=true)
Definition: MotionMaster.h:158
void StopMoving()
Definition: Unit.cpp:11838
bool GetBGAccessByLevel(uint32 bgTypeId) const
Definition: Player.cpp:19403
void RemoveBattlegroundQueueId(uint32 val)
Definition: Player.h:2277
Definition: Player.h:922
void HandleBattlegroundArenaJoin(WorldPacket &recv_data)
void SendNotInArenaTeamPacket(uint8 type)
void HandleBattlegroundPVPlogdataOpcode(WorldPacket &recv_data)
Definition: Group.h:154
static void FillMessageData(WorldPacket *data, WorldSession *session, uint8 type, uint32 language, const char *channelName, uint64 target_guid, const char *message, Unit *speaker)
Definition: Chat.cpp:1515
const uint64 & GetGUID() const
Definition: Object.h:156
bool IsInvitedForBattlegroundQueueType(uint32 bgQueueType) const
Definition: Player.h:2241