2 * Copyright (C) 2005-2009 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 // check queueing conditions
121 // check Deserter debuff
122 if (!_player
->CanJoinToBattleground())
124 WorldPacket
data(SMSG_GROUP_JOINED_BATTLEGROUND
, 4);
125 data
<< uint32(0xFFFFFFFE);
126 _player
->GetSession()->SendPacket(&data
);
129 // check if already in queue
130 if (_player
->GetBattleGroundQueueIndex(bgQueueTypeId
) < PLAYER_MAX_BATTLEGROUND_QUEUES
)
131 //player is already in this queue
133 // check if has free queue slots
134 if (!_player
->HasFreeBattleGroundQueueId())
139 grp
= _player
->GetGroup();
140 // no group found, error
143 uint32 err
= grp
->CanJoinBattleGroundQueue(bgTypeId
, bgQueueTypeId
, 0, bg
->GetMaxPlayersPerTeam(), false, 0);
144 isPremade
= (grp
->GetMembersCount() >= bg
->GetMinPlayersPerTeam());
145 if (err
!= BG_JOIN_ERR_OK
)
147 SendBattleGroundOrArenaJoinError(err
);
151 // if we're here, then the conditions to join a bg are met. We can proceed in joining.
153 // _player->GetGroup() was already checked, grp is already initialized
154 BattleGroundQueue
& bgQueue
= sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
];
155 if (joinAsGroup
/* && _player->GetGroup()*/)
157 sLog
.outDebug("Battleground: the following players are joining as group:");
158 GroupQueueInfo
* ginfo
= bgQueue
.AddGroup(_player
, grp
, bgTypeId
, 0, false, isPremade
, 0);
159 uint32 avgTime
= bgQueue
.GetAverageQueueWaitTime(ginfo
, _player
->GetBattleGroundQueueIdFromLevel());
160 for(GroupReference
*itr
= grp
->GetFirstMember(); itr
!= NULL
; itr
= itr
->next())
162 Player
*member
= itr
->getSource();
163 if(!member
) continue; // this should never happen
165 uint32 queueSlot
= member
->AddBattleGroundQueueId(bgQueueTypeId
); // add to queue
168 // send status packet (in queue)
169 sBattleGroundMgr
.BuildBattleGroundStatusPacket(&data
, bg
, queueSlot
, STATUS_WAIT_QUEUE
, avgTime
, 0, ginfo
->ArenaType
);
170 member
->GetSession()->SendPacket(&data
);
171 sBattleGroundMgr
.BuildGroupJoinedBattlegroundPacket(&data
, bgTypeId
);
172 member
->GetSession()->SendPacket(&data
);
173 sLog
.outDebug("Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId
,bgTypeId
,member
->GetGUIDLow(), member
->GetName());
175 sLog
.outDebug("Battleground: group end");
179 GroupQueueInfo
* ginfo
= bgQueue
.AddGroup(_player
, NULL
, bgTypeId
, 0, false, isPremade
, 0);
180 uint32 avgTime
= bgQueue
.GetAverageQueueWaitTime(ginfo
, _player
->GetBattleGroundQueueIdFromLevel());
181 // already checked if queueSlot is valid, now just get it
182 uint32 queueSlot
= _player
->AddBattleGroundQueueId(bgQueueTypeId
);
185 // send status packet (in queue)
186 sBattleGroundMgr
.BuildBattleGroundStatusPacket(&data
, bg
, queueSlot
, STATUS_WAIT_QUEUE
, avgTime
, 0, ginfo
->ArenaType
);
188 sLog
.outDebug("Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId
,bgTypeId
,_player
->GetGUIDLow(), _player
->GetName());
190 sBattleGroundMgr
.ScheduleQueueUpdate(0, 0, bgQueueTypeId
, bgTypeId
, _player
->GetBattleGroundQueueIdFromLevel());
193 void WorldSession::HandleBattleGroundPlayerPositionsOpcode( WorldPacket
& /*recv_data*/ )
196 sLog
.outDebug("WORLD: Recvd MSG_BATTLEGROUND_PLAYER_POSITIONS Message");
198 BattleGround
*bg
= _player
->GetBattleGround();
199 if(!bg
) // can't be received if player not in battleground
202 switch( bg
->GetTypeID() )
204 case BATTLEGROUND_WS
:
206 uint32 count1
= 0; //always constant zero?
207 uint32 count2
= 0; //count of next fields
209 Player
*ali_plr
= sObjectMgr
.GetPlayer(((BattleGroundWS
*)bg
)->GetAllianceFlagPickerGUID());
213 Player
*horde_plr
= sObjectMgr
.GetPlayer(((BattleGroundWS
*)bg
)->GetHordeFlagPickerGUID());
217 WorldPacket
data(MSG_BATTLEGROUND_PLAYER_POSITIONS
, (4+4+16*count1
+16*count2
));
218 data
<< count1
; // alliance flag holders count - obsolete, now always 0
219 /*for(uint8 i = 0; i < count1; ++i)
221 data << uint64(0); // guid
222 data << (float)0; // x
223 data << (float)0; // y
225 data
<< count2
; // horde flag holders count - obsolete, now count of next fields
228 data
<< (uint64
)ali_plr
->GetGUID();
229 data
<< (float)ali_plr
->GetPositionX();
230 data
<< (float)ali_plr
->GetPositionY();
234 data
<< (uint64
)horde_plr
->GetGUID();
235 data
<< (float)horde_plr
->GetPositionX();
236 data
<< (float)horde_plr
->GetPositionY();
242 case BATTLEGROUND_EY
:
245 case BATTLEGROUND_AB
:
246 case BATTLEGROUND_AV
:
248 //for other BG types - send default
249 WorldPacket
data(MSG_BATTLEGROUND_PLAYER_POSITIONS
, (4+4));
256 //maybe it is sent also in arena - do nothing
261 void WorldSession::HandlePVPLogDataOpcode( WorldPacket
& /*recv_data*/ )
263 sLog
.outDebug( "WORLD: Recvd MSG_PVP_LOG_DATA Message");
265 BattleGround
*bg
= _player
->GetBattleGround();
270 sBattleGroundMgr
.BuildPvpLogDataPacket(&data
, bg
);
273 sLog
.outDebug( "WORLD: Sent MSG_PVP_LOG_DATA Message");
276 void WorldSession::HandleBattlefieldListOpcode( WorldPacket
&recv_data
)
278 sLog
.outDebug( "WORLD: Recvd CMSG_BATTLEFIELD_LIST Message");
281 recv_data
>> bgTypeId
; // id from DBC
284 recv_data
>> fromWhere
; // 0 - battlemaster (lua: ShowBattlefieldList), 1 - UI (lua: RequestBattlegroundInstanceInfo)
287 recv_data
>> unk1
; // unknown 3.2.2
289 BattlemasterListEntry
const* bl
= sBattlemasterListStore
.LookupEntry(bgTypeId
);
292 sLog
.outError("Battleground: invalid bgtype received.");
297 sBattleGroundMgr
.BuildBattleGroundListPacket(&data
, 0, _player
, BattleGroundTypeId(bgTypeId
), fromWhere
);
301 void WorldSession::HandleBattleFieldPortOpcode( WorldPacket
&recv_data
)
303 sLog
.outDebug( "WORLD: Recvd CMSG_BATTLEFIELD_PORT Message");
305 uint8 type
; // arenatype if arena
306 uint8 unk2
; // unk, can be 0x0 (may be if was invited?) and 0x1
307 uint32 bgTypeId_
; // type id from dbc
308 uint16 unk
; // 0x1F90 constant?
309 uint8 action
; // enter battle 0x1, leave queue 0x0
311 recv_data
>> type
>> unk2
>> bgTypeId_
>> unk
>> action
;
313 if (!sBattlemasterListStore
.LookupEntry(bgTypeId_
))
315 sLog
.outError("BattlegroundHandler: invalid bgtype (%u) received.", bgTypeId_
);
318 if (!_player
->InBattleGroundQueue())
320 sLog
.outError("BattlegroundHandler: Invalid CMSG_BATTLEFIELD_PORT received from player (%u), he is not in bg_queue.", _player
->GetGUIDLow());
324 //get GroupQueueInfo from BattleGroundQueue
325 BattleGroundTypeId bgTypeId
= BattleGroundTypeId(bgTypeId_
);
326 BattleGroundQueueTypeId bgQueueTypeId
= BattleGroundMgr::BGQueueTypeId(bgTypeId
, type
);
327 BattleGroundQueue
& bgQueue
= sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
];
328 //we must use temporary variable, because GroupQueueInfo pointer can be deleted in BattleGroundQueue::RemovePlayer() function
329 GroupQueueInfo ginfo
;
330 if (!bgQueue
.GetPlayerGroupInfoData(_player
->GetGUID(), &ginfo
))
332 sLog
.outError("BattlegroundHandler: itrplayerstatus not found.");
335 // if action == 1, then instanceId is required
336 if (!ginfo
.IsInvitedToBGInstanceGUID
&& action
== 1)
338 sLog
.outError("BattlegroundHandler: instance not found.");
342 BattleGround
*bg
= sBattleGroundMgr
.GetBattleGround(ginfo
.IsInvitedToBGInstanceGUID
, bgTypeId
);
344 // bg template might and must be used in case of leaving queue, when instance is not created yet
345 if (!bg
&& action
== 0)
346 bg
= sBattleGroundMgr
.GetBattleGroundTemplate(bgTypeId
);
349 sLog
.outError("BattlegroundHandler: bg_template not found for type id %u.", bgTypeId
);
353 //some checks if player isn't cheating - it is not exactly cheating, but we cannot allow it
354 if (action
== 1 && ginfo
.ArenaType
== 0)
356 //if player is trying to enter battleground (not arena!) and he has deserter debuff, we must just remove him from queue
357 if (!_player
->CanJoinToBattleground())
359 //send bg command result to show nice message
360 WorldPacket
data2(SMSG_GROUP_JOINED_BATTLEGROUND
, 4);
361 data2
<< uint32(0xFFFFFFFE);
362 _player
->GetSession()->SendPacket(&data2
);
364 sLog
.outDebug("Battleground: player %s (%u) has a deserter debuff, do not port him to battleground!", _player
->GetName(), _player
->GetGUIDLow());
366 //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
367 if (_player
->getLevel() > bg
->GetMaxLevel())
369 sLog
.outError("Battleground: Player %s (%u) has level (%u) higher than maxlevel (%u) of battleground (%u)! Do not port him to battleground!",
370 _player
->GetName(), _player
->GetGUIDLow(), _player
->getLevel(), bg
->GetMaxLevel(), bg
->GetTypeID());
374 uint32 queueSlot
= _player
->GetBattleGroundQueueIndex(bgQueueTypeId
);
378 case 1: // port to battleground
379 if (!_player
->IsInvitedForBattleGroundQueueType(bgQueueTypeId
))
382 if (!_player
->InBattleGround())
383 _player
->SetBattleGroundEntryPoint();
385 // resurrect the player
386 if (!_player
->isAlive())
388 _player
->ResurrectPlayer(1.0f
);
389 _player
->SpawnCorpseBones();
391 // stop taxi flight at port
392 if (_player
->isInFlight())
394 _player
->GetMotionMaster()->MovementExpired();
395 _player
->m_taxi
.ClearTaxiDestinations();
398 sBattleGroundMgr
.BuildBattleGroundStatusPacket(&data
, bg
, queueSlot
, STATUS_IN_PROGRESS
, 0, bg
->GetStartTime(), bg
->GetArenaType());
399 _player
->GetSession()->SendPacket(&data
);
400 // remove battleground queue status from BGmgr
401 bgQueue
.RemovePlayer(_player
->GetGUID(), false);
402 // this is still needed here if battleground "jumping" shouldn't add deserter debuff
403 // also this is required to prevent stuck at old battleground after SetBattleGroundId set to new
404 if (BattleGround
*currentBg
= _player
->GetBattleGround())
405 currentBg
->RemovePlayerAtLeave(_player
->GetGUID(), false, true);
407 // set the destination instance id
408 _player
->SetBattleGroundId(bg
->GetInstanceID(), bgTypeId
);
409 // set the destination team
410 _player
->SetBGTeam(ginfo
.Team
);
411 // bg->HandleBeforeTeleportToBattleGround(_player);
412 sBattleGroundMgr
.SendToBattleGround(_player
, ginfo
.IsInvitedToBGInstanceGUID
, bgTypeId
);
413 // add only in HandleMoveWorldPortAck()
414 // bg->AddPlayer(_player,team);
415 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
);
417 case 0: // leave queue
418 // if player leaves rated arena match before match start, it is counted as he played but he lost
421 ArenaTeam
* at
= sObjectMgr
.GetArenaTeamById(ginfo
.Team
);
424 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
);
425 at
->MemberLost(_player
, ginfo
.OpponentsTeamRating
);
429 _player
->RemoveBattleGroundQueueId(bgQueueTypeId
); // must be called this way, because if you move this call to queue->removeplayer, it causes bugs
430 sBattleGroundMgr
.BuildBattleGroundStatusPacket(&data
, bg
, queueSlot
, STATUS_NONE
, 0, 0, 0);
431 bgQueue
.RemovePlayer(_player
->GetGUID(), true);
432 // player left queue, we should update it - do not update Arena Queue
433 if (!ginfo
.ArenaType
)
434 sBattleGroundMgr
.ScheduleQueueUpdate(ginfo
.ArenaTeamRating
, ginfo
.ArenaType
, bgQueueTypeId
, bgTypeId
, _player
->GetBattleGroundQueueIdFromLevel());
436 sLog
.outDebug("Battleground: player %s (%u) left queue for bgtype %u, queue type %u.", _player
->GetName(), _player
->GetGUIDLow(), bg
->GetTypeID(), bgQueueTypeId
);
439 sLog
.outError("Battleground port: unknown action %u", action
);
444 void WorldSession::HandleLeaveBattlefieldOpcode( WorldPacket
& /*recv_data*/ )
446 sLog
.outDebug( "WORLD: Recvd CMSG_LEAVE_BATTLEFIELD Message");
449 //uint32 bgTypeId; // id from DBC
452 //recv_data >> unk1 >> unk2 >> bgTypeId >> unk3; - no used currently
454 //if(bgTypeId >= MAX_BATTLEGROUND_TYPES) // cheating? but not important in this case
457 // not allow leave battleground in combat
458 if (_player
->isInCombat())
459 if (BattleGround
* bg
= _player
->GetBattleGround())
460 if (bg
->GetStatus() != STATUS_WAIT_LEAVE
)
463 _player
->LeaveBattleground();
466 void WorldSession::HandleBattlefieldStatusOpcode( WorldPacket
& /*recv_data*/ )
469 sLog
.outDebug( "WORLD: Battleground status" );
472 // we must update all queues here
473 BattleGround
*bg
= NULL
;
474 for (uint8 i
= 0; i
< PLAYER_MAX_BATTLEGROUND_QUEUES
; ++i
)
476 BattleGroundQueueTypeId bgQueueTypeId
= _player
->GetBattleGroundQueueTypeId(i
);
479 BattleGroundTypeId bgTypeId
= BattleGroundMgr::BGTemplateId(bgQueueTypeId
);
480 uint8 arenaType
= BattleGroundMgr::BGArenaType(bgQueueTypeId
);
481 if (bgTypeId
== _player
->GetBattleGroundTypeId())
483 bg
= _player
->GetBattleGround();
484 //i cannot check any variable from player class because player class doesn't know if player is in 2v2 / 3v3 or 5v5 arena
485 //so i must use bg pointer to get that information
486 if (bg
&& bg
->GetArenaType() == arenaType
)
488 // this line is checked, i only don't know if GetStartTime is changing itself after bg end!
489 // send status in BattleGround
490 sBattleGroundMgr
.BuildBattleGroundStatusPacket(&data
, bg
, i
, STATUS_IN_PROGRESS
, bg
->GetEndTime(), bg
->GetStartTime(), arenaType
);
495 //we are sending update to player about queue - he can be invited there!
496 //get GroupQueueInfo for queue status
497 BattleGroundQueue
& bgQueue
= sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
];
498 GroupQueueInfo ginfo
;
499 if (!bgQueue
.GetPlayerGroupInfoData(_player
->GetGUID(), &ginfo
))
501 if (ginfo
.IsInvitedToBGInstanceGUID
)
503 bg
= sBattleGroundMgr
.GetBattleGround(ginfo
.IsInvitedToBGInstanceGUID
, bgTypeId
);
506 uint32 remainingTime
= getMSTimeDiff(getMSTime(), ginfo
.RemoveInviteTime
);
507 // send status invited to BattleGround
508 sBattleGroundMgr
.BuildBattleGroundStatusPacket(&data
, bg
, i
, STATUS_WAIT_JOIN
, remainingTime
, 0, arenaType
);
513 bg
= sBattleGroundMgr
.GetBattleGroundTemplate(bgTypeId
);
516 uint32 avgTime
= bgQueue
.GetAverageQueueWaitTime(&ginfo
, _player
->GetBattleGroundQueueIdFromLevel());
517 // send status in BattleGround Queue
518 sBattleGroundMgr
.BuildBattleGroundStatusPacket(&data
, bg
, i
, STATUS_WAIT_QUEUE
, avgTime
, getMSTimeDiff(ginfo
.JoinTime
, getMSTime()), arenaType
);
524 void WorldSession::HandleAreaSpiritHealerQueryOpcode( WorldPacket
& recv_data
)
526 sLog
.outDebug("WORLD: CMSG_AREA_SPIRIT_HEALER_QUERY");
528 BattleGround
*bg
= _player
->GetBattleGround();
535 Creature
*unit
= GetPlayer()->GetMap()->GetCreature(guid
);
539 if(!unit
->isSpiritService()) // it's not spirit service
542 unit
->SendAreaSpiritHealerQueryOpcode(GetPlayer());
545 void WorldSession::HandleAreaSpiritHealerQueueOpcode( WorldPacket
& recv_data
)
547 sLog
.outDebug("WORLD: CMSG_AREA_SPIRIT_HEALER_QUEUE");
549 BattleGround
*bg
= _player
->GetBattleGround();
556 Creature
*unit
= GetPlayer()->GetMap()->GetCreature(guid
);
560 if(!unit
->isSpiritService()) // it's not spirit service
563 Script
->GossipHello(GetPlayer(), unit
);
566 void WorldSession::HandleBattlemasterJoinArena( WorldPacket
& recv_data
)
568 sLog
.outDebug("WORLD: CMSG_BATTLEMASTER_JOIN_ARENA");
569 //recv_data.hexlike();
571 uint64 guid
; // arena Battlemaster guid
572 uint8 arenaslot
; // 2v2, 3v3 or 5v5
573 uint8 asGroup
; // asGroup
574 uint8 isRated
; // isRated
577 recv_data
>> guid
>> arenaslot
>> asGroup
>> isRated
;
579 // ignore if we already in BG or BG queue
580 if (_player
->InBattleGround())
583 Creature
*unit
= GetPlayer()->GetMap()->GetCreature(guid
);
587 if(!unit
->isBattleMaster()) // it's not battle master
591 uint32 arenaRating
= 0;
596 arenatype
= ARENA_TYPE_2v2
;
599 arenatype
= ARENA_TYPE_3v3
;
602 arenatype
= ARENA_TYPE_5v5
;
605 sLog
.outError("Unknown arena slot %u at HandleBattlemasterJoinArena()", arenaslot
);
610 BattleGround
* bg
= NULL
;
611 if (!(bg
= sBattleGroundMgr
.GetBattleGroundTemplate(BATTLEGROUND_AA
)))
613 sLog
.outError("Battleground: template bg (all arenas) not found");
617 BattleGroundTypeId bgTypeId
= bg
->GetTypeID();
618 BattleGroundQueueTypeId bgQueueTypeId
= BattleGroundMgr::BGQueueTypeId(bgTypeId
, arenatype
);
620 // check queueing conditions
623 // check if already in queue
624 if (_player
->GetBattleGroundQueueIndex(bgQueueTypeId
) < PLAYER_MAX_BATTLEGROUND_QUEUES
)
625 //player is already in this queue
627 // check if has free queue slots
628 if (!_player
->HasFreeBattleGroundQueueId())
633 grp
= _player
->GetGroup();
634 // no group found, error
637 uint32 err
= grp
->CanJoinBattleGroundQueue(bgTypeId
, bgQueueTypeId
, arenatype
, arenatype
, (bool)isRated
, arenaslot
);
638 if (err
!= BG_JOIN_ERR_OK
)
640 SendBattleGroundOrArenaJoinError(err
);
649 ateamId
= _player
->GetArenaTeamId(arenaslot
);
650 // check real arenateam existence only here (if it was moved to group->CanJoin .. () then we would ahve to get it twice)
651 ArenaTeam
* at
= sObjectMgr
.GetArenaTeamById(ateamId
);
654 _player
->GetSession()->SendNotInArenaTeamPacket(arenatype
);
657 // get the team rating for queueing
658 arenaRating
= at
->GetRating();
659 // the arenateam id must match for everyone in the group
660 // get the personal ratings for queueing
661 uint32 avg_pers_rating
= 0;
662 for(GroupReference
*itr
= grp
->GetFirstMember(); itr
!= NULL
; itr
= itr
->next())
664 Player
*member
= itr
->getSource();
666 // calc avg personal rating
667 avg_pers_rating
+= member
->GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1
+ (arenaslot
* ARENA_TEAM_END
) + ARENA_TEAM_PERSONAL_RATING
);
671 avg_pers_rating
/= arenatype
;
673 // 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
674 if (avg_pers_rating
+ 150 < arenaRating
)
675 arenaRating
= avg_pers_rating
;
678 BattleGroundQueue
&bgQueue
= sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
];
681 sLog
.outDebug("Battleground: arena join as group start");
683 sLog
.outDebug("Battleground: arena team id %u, leader %s queued with rating %u for type %u",_player
->GetArenaTeamId(arenaslot
),_player
->GetName(),arenaRating
,arenatype
);
685 GroupQueueInfo
* ginfo
= bgQueue
.AddGroup(_player
, grp
, bgTypeId
, arenatype
, isRated
, false, arenaRating
, ateamId
);
686 uint32 avgTime
= bgQueue
.GetAverageQueueWaitTime(ginfo
, _player
->GetBattleGroundQueueIdFromLevel());
687 for(GroupReference
*itr
= grp
->GetFirstMember(); itr
!= NULL
; itr
= itr
->next())
689 Player
*member
= itr
->getSource();
690 if(!member
) continue;
692 uint32 queueSlot
= member
->AddBattleGroundQueueId(bgQueueTypeId
);// add to queue
695 // send status packet (in queue)
696 sBattleGroundMgr
.BuildBattleGroundStatusPacket(&data
, bg
, queueSlot
, STATUS_WAIT_QUEUE
, avgTime
, 0, arenatype
);
697 member
->GetSession()->SendPacket(&data
);
698 sBattleGroundMgr
.BuildGroupJoinedBattlegroundPacket(&data
, bgTypeId
);
699 member
->GetSession()->SendPacket(&data
);
700 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());
702 sLog
.outDebug("Battleground: arena join as group end");
703 //announce to world ... removed
707 GroupQueueInfo
* ginfo
= bgQueue
.AddGroup(_player
, NULL
, bgTypeId
, arenatype
, isRated
, false, arenaRating
, ateamId
);
708 uint32 avgTime
= bgQueue
.GetAverageQueueWaitTime(ginfo
, _player
->GetBattleGroundQueueIdFromLevel());
709 uint32 queueSlot
= _player
->AddBattleGroundQueueId(bgQueueTypeId
);
712 // send status packet (in queue)
713 sBattleGroundMgr
.BuildBattleGroundStatusPacket(&data
, bg
, queueSlot
, STATUS_WAIT_QUEUE
, avgTime
, 0, arenatype
);
715 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());
717 sBattleGroundMgr
.ScheduleQueueUpdate(arenaRating
, arenatype
, bgQueueTypeId
, bgTypeId
, _player
->GetBattleGroundQueueIdFromLevel());
720 void WorldSession::HandleReportPvPAFK( WorldPacket
& recv_data
)
723 recv_data
>> playerGuid
;
724 Player
*reportedPlayer
= sObjectMgr
.GetPlayer(playerGuid
);
728 sLog
.outDebug("WorldSession::HandleReportPvPAFK: player not found");
732 sLog
.outDebug("WorldSession::HandleReportPvPAFK: %s reported %s", _player
->GetName(), reportedPlayer
->GetName());
734 reportedPlayer
->ReportedAfkBy(_player
);
737 void WorldSession::SendBattleGroundOrArenaJoinError(uint8 err
)
743 case BG_JOIN_ERR_OFFLINE_MEMBER
:
744 msg
= LANG_BG_GROUP_OFFLINE_MEMBER
;
746 case BG_JOIN_ERR_GROUP_TOO_MANY
:
747 msg
= LANG_BG_GROUP_TOO_LARGE
;
749 case BG_JOIN_ERR_MIXED_FACTION
:
750 msg
= LANG_BG_GROUP_MIXED_FACTION
;
752 case BG_JOIN_ERR_MIXED_LEVELS
:
753 msg
= LANG_BG_GROUP_MIXED_LEVELS
;
755 case BG_JOIN_ERR_GROUP_MEMBER_ALREADY_IN_QUEUE
:
756 msg
= LANG_BG_GROUP_MEMBER_ALREADY_IN_QUEUE
;
758 case BG_JOIN_ERR_GROUP_DESERTER
:
759 msg
= LANG_BG_GROUP_MEMBER_DESERTER
;
761 case BG_JOIN_ERR_ALL_QUEUES_USED
:
762 msg
= LANG_BG_GROUP_MEMBER_NO_FREE_QUEUE_SLOTS
;
764 case BG_JOIN_ERR_GROUP_NOT_ENOUGH
:
765 case BG_JOIN_ERR_MIXED_ARENATEAM
:
770 ChatHandler::FillMessageData(&data
, NULL
, CHAT_MSG_BG_SYSTEM_NEUTRAL
, LANG_UNIVERSAL
, NULL
, 0, GetMangosString(msg
), NULL
);