2 * Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #include "WorldPacket.h"
24 #include "ObjectMgr.h"
25 #include "WorldSession.h"
28 #include "BattleGroundMgr.h"
29 #include "BattleGroundWS.h"
30 #include "BattleGround.h"
31 #include "ArenaTeam.h"
33 #include "ScriptCalls.h"
35 void WorldSession::HandleBattlemasterHelloOpcode(WorldPacket
& recv_data
)
40 sLog
.outDebug("WORLD: Recvd CMSG_BATTLEMASTER_HELLO Message from (GUID: %u TypeId:%u)", GUID_LOPART(guid
),GuidHigh2TypeId(GUID_HIPART(guid
)));
42 Creature
*pCreature
= GetPlayer()->GetMap()->GetCreature(guid
);
47 if (!pCreature
->isBattleMaster()) // it's not battlemaster
50 // Stop the npc if moving
51 if (!pCreature
->IsStopped())
52 pCreature
->StopMoving();
54 BattleGroundTypeId bgTypeId
= sBattleGroundMgr
.GetBattleMasterBG(pCreature
->GetEntry());
56 if (bgTypeId
== BATTLEGROUND_TYPE_NONE
)
59 if (!_player
->GetBGAccessByLevel(bgTypeId
))
61 // temp, must be gossip message...
62 SendNotification(LANG_YOUR_BG_LEVEL_REQ_ERROR
);
66 SendBattlegGroundList(guid
, bgTypeId
);
69 void WorldSession::SendBattlegGroundList( uint64 guid
, BattleGroundTypeId bgTypeId
)
72 sBattleGroundMgr
.BuildBattleGroundListPacket(&data
, guid
, _player
, bgTypeId
, 0);
76 void WorldSession::HandleBattlemasterJoinOpcode( WorldPacket
& recv_data
)
82 bool isPremade
= false;
85 recv_data
>> guid
; // battlemaster guid
86 recv_data
>> bgTypeId_
; // battleground type id (DBC id)
87 recv_data
>> instanceId
; // instance id, 0 if First Available selected
88 recv_data
>> joinAsGroup
; // join as group
90 if (!sBattlemasterListStore
.LookupEntry(bgTypeId_
))
92 sLog
.outError("Battleground: invalid bgtype (%u) received. possible cheater? player guid %u",bgTypeId_
,_player
->GetGUIDLow());
96 BattleGroundTypeId bgTypeId
= BattleGroundTypeId(bgTypeId_
);
98 sLog
.outDebug( "WORLD: Recvd CMSG_BATTLEMASTER_JOIN Message from (GUID: %u TypeId:%u)", GUID_LOPART(guid
), GuidHigh2TypeId(GUID_HIPART(guid
)));
100 // can do this, since it's battleground, not arena
101 BattleGroundQueueTypeId bgQueueTypeId
= BattleGroundMgr::BGQueueTypeId(bgTypeId
, 0);
103 // ignore if player is already in BG
104 if (_player
->InBattleGround())
107 // get bg instance or bg template if instance not found
108 BattleGround
*bg
= NULL
;
110 bg
= sBattleGroundMgr
.GetBattleGroundThroughClientInstance(instanceId
, bgTypeId
);
112 if (!bg
&& !(bg
= sBattleGroundMgr
.GetBattleGroundTemplate(bgTypeId
)))
114 sLog
.outError("Battleground: no available bg / template found");
118 // expected bracket entry
119 PvPDifficultyEntry
const* bracketEntry
= GetBattlegroundBracketByLevel(bg
->GetMapId(),_player
->getLevel());
123 // check queueing conditions
126 // check Deserter debuff
127 if (!_player
->CanJoinToBattleground())
129 WorldPacket
data(SMSG_GROUP_JOINED_BATTLEGROUND
, 4);
130 data
<< uint32(0xFFFFFFFE);
131 _player
->GetSession()->SendPacket(&data
);
134 // check if already in queue
135 if (_player
->GetBattleGroundQueueIndex(bgQueueTypeId
) < PLAYER_MAX_BATTLEGROUND_QUEUES
)
136 //player is already in this queue
138 // check if has free queue slots
139 if (!_player
->HasFreeBattleGroundQueueId())
144 grp
= _player
->GetGroup();
145 // no group found, error
148 uint32 err
= grp
->CanJoinBattleGroundQueue(bg
, bgQueueTypeId
, 0, bg
->GetMaxPlayersPerTeam(), false, 0);
149 isPremade
= (grp
->GetMembersCount() >= bg
->GetMinPlayersPerTeam());
150 if (err
!= BG_JOIN_ERR_OK
)
152 SendBattleGroundOrArenaJoinError(err
);
156 // if we're here, then the conditions to join a bg are met. We can proceed in joining.
158 // _player->GetGroup() was already checked, grp is already initialized
159 BattleGroundQueue
& bgQueue
= sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
];
160 if (joinAsGroup
/* && _player->GetGroup()*/)
162 sLog
.outDebug("Battleground: the following players are joining as group:");
163 GroupQueueInfo
* ginfo
= bgQueue
.AddGroup(_player
, grp
, bgTypeId
, bracketEntry
, 0, false, isPremade
, 0);
164 uint32 avgTime
= bgQueue
.GetAverageQueueWaitTime(ginfo
, bracketEntry
->GetBracketId());
165 for(GroupReference
*itr
= grp
->GetFirstMember(); itr
!= NULL
; itr
= itr
->next())
167 Player
*member
= itr
->getSource();
168 if(!member
) continue; // this should never happen
170 uint32 queueSlot
= member
->AddBattleGroundQueueId(bgQueueTypeId
); // add to queue
173 // send status packet (in queue)
174 sBattleGroundMgr
.BuildBattleGroundStatusPacket(&data
, bg
, queueSlot
, STATUS_WAIT_QUEUE
, avgTime
, 0, ginfo
->ArenaType
);
175 member
->GetSession()->SendPacket(&data
);
176 sBattleGroundMgr
.BuildGroupJoinedBattlegroundPacket(&data
, bgTypeId
);
177 member
->GetSession()->SendPacket(&data
);
178 sLog
.outDebug("Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId
,bgTypeId
,member
->GetGUIDLow(), member
->GetName());
180 sLog
.outDebug("Battleground: group end");
184 GroupQueueInfo
* ginfo
= bgQueue
.AddGroup(_player
, NULL
, bgTypeId
, bracketEntry
, 0, false, isPremade
, 0);
185 uint32 avgTime
= bgQueue
.GetAverageQueueWaitTime(ginfo
, bracketEntry
->GetBracketId());
186 // already checked if queueSlot is valid, now just get it
187 uint32 queueSlot
= _player
->AddBattleGroundQueueId(bgQueueTypeId
);
190 // send status packet (in queue)
191 sBattleGroundMgr
.BuildBattleGroundStatusPacket(&data
, bg
, queueSlot
, STATUS_WAIT_QUEUE
, avgTime
, 0, ginfo
->ArenaType
);
193 sLog
.outDebug("Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId
,bgTypeId
,_player
->GetGUIDLow(), _player
->GetName());
195 sBattleGroundMgr
.ScheduleQueueUpdate(0, 0, bgQueueTypeId
, bgTypeId
, bracketEntry
->GetBracketId());
198 void WorldSession::HandleBattleGroundPlayerPositionsOpcode( WorldPacket
& /*recv_data*/ )
201 sLog
.outDebug("WORLD: Recvd MSG_BATTLEGROUND_PLAYER_POSITIONS Message");
203 BattleGround
*bg
= _player
->GetBattleGround();
204 if(!bg
) // can't be received if player not in battleground
207 switch( bg
->GetTypeID() )
209 case BATTLEGROUND_WS
:
211 uint32 count1
= 0; //always constant zero?
212 uint32 count2
= 0; //count of next fields
214 Player
*ali_plr
= sObjectMgr
.GetPlayer(((BattleGroundWS
*)bg
)->GetAllianceFlagPickerGUID());
218 Player
*horde_plr
= sObjectMgr
.GetPlayer(((BattleGroundWS
*)bg
)->GetHordeFlagPickerGUID());
222 WorldPacket
data(MSG_BATTLEGROUND_PLAYER_POSITIONS
, (4+4+16*count1
+16*count2
));
223 data
<< count1
; // alliance flag holders count - obsolete, now always 0
224 /*for(uint8 i = 0; i < count1; ++i)
226 data << uint64(0); // guid
227 data << (float)0; // x
228 data << (float)0; // y
230 data
<< count2
; // horde flag holders count - obsolete, now count of next fields
233 data
<< (uint64
)ali_plr
->GetGUID();
234 data
<< (float)ali_plr
->GetPositionX();
235 data
<< (float)ali_plr
->GetPositionY();
239 data
<< (uint64
)horde_plr
->GetGUID();
240 data
<< (float)horde_plr
->GetPositionX();
241 data
<< (float)horde_plr
->GetPositionY();
247 case BATTLEGROUND_EY
:
250 case BATTLEGROUND_AB
:
251 case BATTLEGROUND_AV
:
253 //for other BG types - send default
254 WorldPacket
data(MSG_BATTLEGROUND_PLAYER_POSITIONS
, (4+4));
261 //maybe it is sent also in arena - do nothing
266 void WorldSession::HandlePVPLogDataOpcode( WorldPacket
& /*recv_data*/ )
268 sLog
.outDebug( "WORLD: Recvd MSG_PVP_LOG_DATA Message");
270 BattleGround
*bg
= _player
->GetBattleGround();
275 sBattleGroundMgr
.BuildPvpLogDataPacket(&data
, bg
);
278 sLog
.outDebug( "WORLD: Sent MSG_PVP_LOG_DATA Message");
281 void WorldSession::HandleBattlefieldListOpcode( WorldPacket
&recv_data
)
283 sLog
.outDebug( "WORLD: Recvd CMSG_BATTLEFIELD_LIST Message");
286 recv_data
>> bgTypeId
; // id from DBC
289 recv_data
>> fromWhere
; // 0 - battlemaster (lua: ShowBattlefieldList), 1 - UI (lua: RequestBattlegroundInstanceInfo)
292 recv_data
>> unk1
; // unknown 3.2.2
294 BattlemasterListEntry
const* bl
= sBattlemasterListStore
.LookupEntry(bgTypeId
);
297 sLog
.outError("Battleground: invalid bgtype received.");
302 sBattleGroundMgr
.BuildBattleGroundListPacket(&data
, 0, _player
, BattleGroundTypeId(bgTypeId
), fromWhere
);
306 void WorldSession::HandleBattleFieldPortOpcode( WorldPacket
&recv_data
)
308 sLog
.outDebug( "WORLD: Recvd CMSG_BATTLEFIELD_PORT Message");
310 uint8 type
; // arenatype if arena
311 uint8 unk2
; // unk, can be 0x0 (may be if was invited?) and 0x1
312 uint32 bgTypeId_
; // type id from dbc
313 uint16 unk
; // 0x1F90 constant?
314 uint8 action
; // enter battle 0x1, leave queue 0x0
316 recv_data
>> type
>> unk2
>> bgTypeId_
>> unk
>> action
;
318 if (!sBattlemasterListStore
.LookupEntry(bgTypeId_
))
320 sLog
.outError("BattlegroundHandler: invalid bgtype (%u) received.", bgTypeId_
);
323 if (!_player
->InBattleGroundQueue())
325 sLog
.outError("BattlegroundHandler: Invalid CMSG_BATTLEFIELD_PORT received from player (%u), he is not in bg_queue.", _player
->GetGUIDLow());
329 //get GroupQueueInfo from BattleGroundQueue
330 BattleGroundTypeId bgTypeId
= BattleGroundTypeId(bgTypeId_
);
331 BattleGroundQueueTypeId bgQueueTypeId
= BattleGroundMgr::BGQueueTypeId(bgTypeId
, type
);
332 BattleGroundQueue
& bgQueue
= sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
];
333 //we must use temporary variable, because GroupQueueInfo pointer can be deleted in BattleGroundQueue::RemovePlayer() function
334 GroupQueueInfo ginfo
;
335 if (!bgQueue
.GetPlayerGroupInfoData(_player
->GetGUID(), &ginfo
))
337 sLog
.outError("BattlegroundHandler: itrplayerstatus not found.");
340 // if action == 1, then instanceId is required
341 if (!ginfo
.IsInvitedToBGInstanceGUID
&& action
== 1)
343 sLog
.outError("BattlegroundHandler: instance not found.");
347 BattleGround
*bg
= sBattleGroundMgr
.GetBattleGround(ginfo
.IsInvitedToBGInstanceGUID
, bgTypeId
);
349 // bg template might and must be used in case of leaving queue, when instance is not created yet
350 if (!bg
&& action
== 0)
351 bg
= sBattleGroundMgr
.GetBattleGroundTemplate(bgTypeId
);
354 sLog
.outError("BattlegroundHandler: bg_template not found for type id %u.", bgTypeId
);
358 // expected bracket entry
359 PvPDifficultyEntry
const* bracketEntry
= GetBattlegroundBracketByLevel(bg
->GetMapId(),_player
->getLevel());
363 //some checks if player isn't cheating - it is not exactly cheating, but we cannot allow it
364 if (action
== 1 && ginfo
.ArenaType
== 0)
366 //if player is trying to enter battleground (not arena!) and he has deserter debuff, we must just remove him from queue
367 if (!_player
->CanJoinToBattleground())
369 //send bg command result to show nice message
370 WorldPacket
data2(SMSG_GROUP_JOINED_BATTLEGROUND
, 4);
371 data2
<< uint32(0xFFFFFFFE);
372 _player
->GetSession()->SendPacket(&data2
);
374 sLog
.outDebug("Battleground: player %s (%u) has a deserter debuff, do not port him to battleground!", _player
->GetName(), _player
->GetGUIDLow());
376 //if player don't match battleground max level, then do not allow him to enter! (this might happen when player leveled up during his waiting in queue
377 if (_player
->getLevel() > bg
->GetMaxLevel())
379 sLog
.outError("Battleground: Player %s (%u) has level (%u) higher than maxlevel (%u) of battleground (%u)! Do not port him to battleground!",
380 _player
->GetName(), _player
->GetGUIDLow(), _player
->getLevel(), bg
->GetMaxLevel(), bg
->GetTypeID());
384 uint32 queueSlot
= _player
->GetBattleGroundQueueIndex(bgQueueTypeId
);
388 case 1: // port to battleground
389 if (!_player
->IsInvitedForBattleGroundQueueType(bgQueueTypeId
))
392 if (!_player
->InBattleGround())
393 _player
->SetBattleGroundEntryPoint();
395 // resurrect the player
396 if (!_player
->isAlive())
398 _player
->ResurrectPlayer(1.0f
);
399 _player
->SpawnCorpseBones();
401 // stop taxi flight at port
402 if (_player
->isInFlight())
404 _player
->GetMotionMaster()->MovementExpired();
405 _player
->m_taxi
.ClearTaxiDestinations();
408 sBattleGroundMgr
.BuildBattleGroundStatusPacket(&data
, bg
, queueSlot
, STATUS_IN_PROGRESS
, 0, bg
->GetStartTime(), bg
->GetArenaType());
409 _player
->GetSession()->SendPacket(&data
);
410 // remove battleground queue status from BGmgr
411 bgQueue
.RemovePlayer(_player
->GetGUID(), false);
412 // this is still needed here if battleground "jumping" shouldn't add deserter debuff
413 // also this is required to prevent stuck at old battleground after SetBattleGroundId set to new
414 if (BattleGround
*currentBg
= _player
->GetBattleGround())
415 currentBg
->RemovePlayerAtLeave(_player
->GetGUID(), false, true);
417 // set the destination instance id
418 _player
->SetBattleGroundId(bg
->GetInstanceID(), bgTypeId
);
419 // set the destination team
420 _player
->SetBGTeam(ginfo
.Team
);
421 // bg->HandleBeforeTeleportToBattleGround(_player);
422 sBattleGroundMgr
.SendToBattleGround(_player
, ginfo
.IsInvitedToBGInstanceGUID
, bgTypeId
);
423 // add only in HandleMoveWorldPortAck()
424 // bg->AddPlayer(_player,team);
425 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
);
427 case 0: // leave queue
428 // if player leaves rated arena match before match start, it is counted as he played but he lost
431 ArenaTeam
* at
= sObjectMgr
.GetArenaTeamById(ginfo
.Team
);
434 sLog
.outDebug("UPDATING memberLost's personal arena rating for %u by opponents rating: %u, because he has left queue!", GUID_LOPART(_player
->GetGUID()), ginfo
.OpponentsTeamRating
);
435 at
->MemberLost(_player
, ginfo
.OpponentsTeamRating
);
439 _player
->RemoveBattleGroundQueueId(bgQueueTypeId
); // must be called this way, because if you move this call to queue->removeplayer, it causes bugs
440 sBattleGroundMgr
.BuildBattleGroundStatusPacket(&data
, bg
, queueSlot
, STATUS_NONE
, 0, 0, 0);
441 bgQueue
.RemovePlayer(_player
->GetGUID(), true);
442 // player left queue, we should update it - do not update Arena Queue
443 if (!ginfo
.ArenaType
)
444 sBattleGroundMgr
.ScheduleQueueUpdate(ginfo
.ArenaTeamRating
, ginfo
.ArenaType
, bgQueueTypeId
, bgTypeId
, bracketEntry
->GetBracketId());
446 sLog
.outDebug("Battleground: player %s (%u) left queue for bgtype %u, queue type %u.", _player
->GetName(), _player
->GetGUIDLow(), bg
->GetTypeID(), bgQueueTypeId
);
449 sLog
.outError("Battleground port: unknown action %u", action
);
454 void WorldSession::HandleLeaveBattlefieldOpcode( WorldPacket
& /*recv_data*/ )
456 sLog
.outDebug( "WORLD: Recvd CMSG_LEAVE_BATTLEFIELD Message");
459 //uint32 bgTypeId; // id from DBC
462 //recv_data >> unk1 >> unk2 >> bgTypeId >> unk3; - no used currently
464 //if(bgTypeId >= MAX_BATTLEGROUND_TYPES) // cheating? but not important in this case
467 // not allow leave battleground in combat
468 if (_player
->isInCombat())
469 if (BattleGround
* bg
= _player
->GetBattleGround())
470 if (bg
->GetStatus() != STATUS_WAIT_LEAVE
)
473 _player
->LeaveBattleground();
476 void WorldSession::HandleBattlefieldStatusOpcode( WorldPacket
& /*recv_data*/ )
479 sLog
.outDebug( "WORLD: Battleground status" );
482 // we must update all queues here
483 BattleGround
*bg
= NULL
;
484 for (uint8 i
= 0; i
< PLAYER_MAX_BATTLEGROUND_QUEUES
; ++i
)
486 BattleGroundQueueTypeId bgQueueTypeId
= _player
->GetBattleGroundQueueTypeId(i
);
489 BattleGroundTypeId bgTypeId
= BattleGroundMgr::BGTemplateId(bgQueueTypeId
);
490 uint8 arenaType
= BattleGroundMgr::BGArenaType(bgQueueTypeId
);
491 if (bgTypeId
== _player
->GetBattleGroundTypeId())
493 bg
= _player
->GetBattleGround();
494 //i cannot check any variable from player class because player class doesn't know if player is in 2v2 / 3v3 or 5v5 arena
495 //so i must use bg pointer to get that information
496 if (bg
&& bg
->GetArenaType() == arenaType
)
498 // this line is checked, i only don't know if GetStartTime is changing itself after bg end!
499 // send status in BattleGround
500 sBattleGroundMgr
.BuildBattleGroundStatusPacket(&data
, bg
, i
, STATUS_IN_PROGRESS
, bg
->GetEndTime(), bg
->GetStartTime(), arenaType
);
505 //we are sending update to player about queue - he can be invited there!
506 //get GroupQueueInfo for queue status
507 BattleGroundQueue
& bgQueue
= sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
];
508 GroupQueueInfo ginfo
;
509 if (!bgQueue
.GetPlayerGroupInfoData(_player
->GetGUID(), &ginfo
))
511 if (ginfo
.IsInvitedToBGInstanceGUID
)
513 bg
= sBattleGroundMgr
.GetBattleGround(ginfo
.IsInvitedToBGInstanceGUID
, bgTypeId
);
516 uint32 remainingTime
= getMSTimeDiff(getMSTime(), ginfo
.RemoveInviteTime
);
517 // send status invited to BattleGround
518 sBattleGroundMgr
.BuildBattleGroundStatusPacket(&data
, bg
, i
, STATUS_WAIT_JOIN
, remainingTime
, 0, arenaType
);
523 bg
= sBattleGroundMgr
.GetBattleGroundTemplate(bgTypeId
);
527 // expected bracket entry
528 PvPDifficultyEntry
const* bracketEntry
= GetBattlegroundBracketByLevel(bg
->GetMapId(),_player
->getLevel());
532 uint32 avgTime
= bgQueue
.GetAverageQueueWaitTime(&ginfo
, bracketEntry
->GetBracketId());
533 // send status in BattleGround Queue
534 sBattleGroundMgr
.BuildBattleGroundStatusPacket(&data
, bg
, i
, STATUS_WAIT_QUEUE
, avgTime
, getMSTimeDiff(ginfo
.JoinTime
, getMSTime()), arenaType
);
540 void WorldSession::HandleAreaSpiritHealerQueryOpcode( WorldPacket
& recv_data
)
542 sLog
.outDebug("WORLD: CMSG_AREA_SPIRIT_HEALER_QUERY");
544 BattleGround
*bg
= _player
->GetBattleGround();
551 Creature
*unit
= GetPlayer()->GetMap()->GetCreature(guid
);
555 if(!unit
->isSpiritService()) // it's not spirit service
558 unit
->SendAreaSpiritHealerQueryOpcode(GetPlayer());
561 void WorldSession::HandleAreaSpiritHealerQueueOpcode( WorldPacket
& recv_data
)
563 sLog
.outDebug("WORLD: CMSG_AREA_SPIRIT_HEALER_QUEUE");
565 BattleGround
*bg
= _player
->GetBattleGround();
572 Creature
*unit
= GetPlayer()->GetMap()->GetCreature(guid
);
576 if(!unit
->isSpiritService()) // it's not spirit service
579 Script
->GossipHello(GetPlayer(), unit
);
582 void WorldSession::HandleBattlemasterJoinArena( WorldPacket
& recv_data
)
584 sLog
.outDebug("WORLD: CMSG_BATTLEMASTER_JOIN_ARENA");
585 //recv_data.hexlike();
587 uint64 guid
; // arena Battlemaster guid
588 uint8 arenaslot
; // 2v2, 3v3 or 5v5
589 uint8 asGroup
; // asGroup
590 uint8 isRated
; // isRated
593 recv_data
>> guid
>> arenaslot
>> asGroup
>> isRated
;
595 // ignore if we already in BG or BG queue
596 if (_player
->InBattleGround())
599 Creature
*unit
= GetPlayer()->GetMap()->GetCreature(guid
);
603 if(!unit
->isBattleMaster()) // it's not battle master
607 uint32 arenaRating
= 0;
612 arenatype
= ARENA_TYPE_2v2
;
615 arenatype
= ARENA_TYPE_3v3
;
618 arenatype
= ARENA_TYPE_5v5
;
621 sLog
.outError("Unknown arena slot %u at HandleBattlemasterJoinArena()", arenaslot
);
626 BattleGround
* bg
= sBattleGroundMgr
.GetBattleGroundTemplate(BATTLEGROUND_AA
);
629 sLog
.outError("Battleground: template bg (all arenas) not found");
633 BattleGroundTypeId bgTypeId
= bg
->GetTypeID();
634 BattleGroundQueueTypeId bgQueueTypeId
= BattleGroundMgr::BGQueueTypeId(bgTypeId
, arenatype
);
635 PvPDifficultyEntry
const* bracketEntry
= GetBattlegroundBracketByLevel(bg
->GetMapId(),_player
->getLevel());
639 // check queueing conditions
642 // check if already in queue
643 if (_player
->GetBattleGroundQueueIndex(bgQueueTypeId
) < PLAYER_MAX_BATTLEGROUND_QUEUES
)
644 //player is already in this queue
646 // check if has free queue slots
647 if (!_player
->HasFreeBattleGroundQueueId())
652 grp
= _player
->GetGroup();
653 // no group found, error
656 uint32 err
= grp
->CanJoinBattleGroundQueue(bg
, bgQueueTypeId
, arenatype
, arenatype
, (bool)isRated
, arenaslot
);
657 if (err
!= BG_JOIN_ERR_OK
)
659 SendBattleGroundOrArenaJoinError(err
);
668 ateamId
= _player
->GetArenaTeamId(arenaslot
);
669 // check real arenateam existence only here (if it was moved to group->CanJoin .. () then we would ahve to get it twice)
670 ArenaTeam
* at
= sObjectMgr
.GetArenaTeamById(ateamId
);
673 _player
->GetSession()->SendNotInArenaTeamPacket(arenatype
);
676 // get the team rating for queueing
677 arenaRating
= at
->GetRating();
678 // the arenateam id must match for everyone in the group
679 // get the personal ratings for queueing
680 uint32 avg_pers_rating
= 0;
681 for(GroupReference
*itr
= grp
->GetFirstMember(); itr
!= NULL
; itr
= itr
->next())
683 Player
*member
= itr
->getSource();
685 // calc avg personal rating
686 avg_pers_rating
+= member
->GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1
+ (arenaslot
* ARENA_TEAM_END
) + ARENA_TEAM_PERSONAL_RATING
);
690 avg_pers_rating
/= arenatype
;
692 // 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
693 if (avg_pers_rating
+ 150 < arenaRating
)
694 arenaRating
= avg_pers_rating
;
697 BattleGroundQueue
&bgQueue
= sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
];
700 sLog
.outDebug("Battleground: arena join as group start");
702 sLog
.outDebug("Battleground: arena team id %u, leader %s queued with rating %u for type %u",_player
->GetArenaTeamId(arenaslot
),_player
->GetName(),arenaRating
,arenatype
);
704 GroupQueueInfo
* ginfo
= bgQueue
.AddGroup(_player
, grp
, bgTypeId
, bracketEntry
, arenatype
, isRated
, false, arenaRating
, ateamId
);
705 uint32 avgTime
= bgQueue
.GetAverageQueueWaitTime(ginfo
, bracketEntry
->GetBracketId());
706 for(GroupReference
*itr
= grp
->GetFirstMember(); itr
!= NULL
; itr
= itr
->next())
708 Player
*member
= itr
->getSource();
709 if(!member
) continue;
711 uint32 queueSlot
= member
->AddBattleGroundQueueId(bgQueueTypeId
);// add to queue
714 // send status packet (in queue)
715 sBattleGroundMgr
.BuildBattleGroundStatusPacket(&data
, bg
, queueSlot
, STATUS_WAIT_QUEUE
, avgTime
, 0, arenatype
);
716 member
->GetSession()->SendPacket(&data
);
717 sBattleGroundMgr
.BuildGroupJoinedBattlegroundPacket(&data
, bgTypeId
);
718 member
->GetSession()->SendPacket(&data
);
719 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());
721 sLog
.outDebug("Battleground: arena join as group end");
722 //announce to world ... removed
726 GroupQueueInfo
* ginfo
= bgQueue
.AddGroup(_player
, NULL
, bgTypeId
, bracketEntry
, arenatype
, isRated
, false, arenaRating
, ateamId
);
727 uint32 avgTime
= bgQueue
.GetAverageQueueWaitTime(ginfo
, bracketEntry
->GetBracketId());
728 uint32 queueSlot
= _player
->AddBattleGroundQueueId(bgQueueTypeId
);
731 // send status packet (in queue)
732 sBattleGroundMgr
.BuildBattleGroundStatusPacket(&data
, bg
, queueSlot
, STATUS_WAIT_QUEUE
, avgTime
, 0, arenatype
);
734 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());
736 sBattleGroundMgr
.ScheduleQueueUpdate(arenaRating
, arenatype
, bgQueueTypeId
, bgTypeId
, bracketEntry
->GetBracketId());
739 void WorldSession::HandleReportPvPAFK( WorldPacket
& recv_data
)
742 recv_data
>> playerGuid
;
743 Player
*reportedPlayer
= sObjectMgr
.GetPlayer(playerGuid
);
747 sLog
.outDebug("WorldSession::HandleReportPvPAFK: player not found");
751 sLog
.outDebug("WorldSession::HandleReportPvPAFK: %s reported %s", _player
->GetName(), reportedPlayer
->GetName());
753 reportedPlayer
->ReportedAfkBy(_player
);
756 void WorldSession::SendBattleGroundOrArenaJoinError(uint8 err
)
762 case BG_JOIN_ERR_OFFLINE_MEMBER
:
763 msg
= LANG_BG_GROUP_OFFLINE_MEMBER
;
765 case BG_JOIN_ERR_GROUP_TOO_MANY
:
766 msg
= LANG_BG_GROUP_TOO_LARGE
;
768 case BG_JOIN_ERR_MIXED_FACTION
:
769 msg
= LANG_BG_GROUP_MIXED_FACTION
;
771 case BG_JOIN_ERR_MIXED_LEVELS
:
772 msg
= LANG_BG_GROUP_MIXED_LEVELS
;
774 case BG_JOIN_ERR_GROUP_MEMBER_ALREADY_IN_QUEUE
:
775 msg
= LANG_BG_GROUP_MEMBER_ALREADY_IN_QUEUE
;
777 case BG_JOIN_ERR_GROUP_DESERTER
:
778 msg
= LANG_BG_GROUP_MEMBER_DESERTER
;
780 case BG_JOIN_ERR_ALL_QUEUES_USED
:
781 msg
= LANG_BG_GROUP_MEMBER_NO_FREE_QUEUE_SLOTS
;
783 case BG_JOIN_ERR_GROUP_NOT_ENOUGH
:
784 case BG_JOIN_ERR_MIXED_ARENATEAM
:
789 ChatHandler::FillMessageData(&data
, NULL
, CHAT_MSG_BG_SYSTEM_NEUTRAL
, LANG_UNIVERSAL
, NULL
, 0, GetMangosString(msg
), NULL
);