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");
458 recv_data
.read_skip
<uint8
>(); // unk1
459 recv_data
.read_skip
<uint8
>(); // unk2
460 recv_data
.read_skip
<uint32
>(); // BattleGroundTypeId
461 recv_data
.read_skip
<uint16
>(); // unk3
463 //if(bgTypeId >= MAX_BATTLEGROUND_TYPES) // cheating? but not important in this case
466 // not allow leave battleground in combat
467 if (_player
->isInCombat())
468 if (BattleGround
* bg
= _player
->GetBattleGround())
469 if (bg
->GetStatus() != STATUS_WAIT_LEAVE
)
472 _player
->LeaveBattleground();
475 void WorldSession::HandleBattlefieldStatusOpcode( WorldPacket
& /*recv_data*/ )
478 sLog
.outDebug( "WORLD: Battleground status" );
481 // we must update all queues here
482 BattleGround
*bg
= NULL
;
483 for (uint8 i
= 0; i
< PLAYER_MAX_BATTLEGROUND_QUEUES
; ++i
)
485 BattleGroundQueueTypeId bgQueueTypeId
= _player
->GetBattleGroundQueueTypeId(i
);
488 BattleGroundTypeId bgTypeId
= BattleGroundMgr::BGTemplateId(bgQueueTypeId
);
489 uint8 arenaType
= BattleGroundMgr::BGArenaType(bgQueueTypeId
);
490 if (bgTypeId
== _player
->GetBattleGroundTypeId())
492 bg
= _player
->GetBattleGround();
493 //i cannot check any variable from player class because player class doesn't know if player is in 2v2 / 3v3 or 5v5 arena
494 //so i must use bg pointer to get that information
495 if (bg
&& bg
->GetArenaType() == arenaType
)
497 // this line is checked, i only don't know if GetStartTime is changing itself after bg end!
498 // send status in BattleGround
499 sBattleGroundMgr
.BuildBattleGroundStatusPacket(&data
, bg
, i
, STATUS_IN_PROGRESS
, bg
->GetEndTime(), bg
->GetStartTime(), arenaType
);
504 //we are sending update to player about queue - he can be invited there!
505 //get GroupQueueInfo for queue status
506 BattleGroundQueue
& bgQueue
= sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
];
507 GroupQueueInfo ginfo
;
508 if (!bgQueue
.GetPlayerGroupInfoData(_player
->GetGUID(), &ginfo
))
510 if (ginfo
.IsInvitedToBGInstanceGUID
)
512 bg
= sBattleGroundMgr
.GetBattleGround(ginfo
.IsInvitedToBGInstanceGUID
, bgTypeId
);
515 uint32 remainingTime
= getMSTimeDiff(getMSTime(), ginfo
.RemoveInviteTime
);
516 // send status invited to BattleGround
517 sBattleGroundMgr
.BuildBattleGroundStatusPacket(&data
, bg
, i
, STATUS_WAIT_JOIN
, remainingTime
, 0, arenaType
);
522 bg
= sBattleGroundMgr
.GetBattleGroundTemplate(bgTypeId
);
526 // expected bracket entry
527 PvPDifficultyEntry
const* bracketEntry
= GetBattlegroundBracketByLevel(bg
->GetMapId(),_player
->getLevel());
531 uint32 avgTime
= bgQueue
.GetAverageQueueWaitTime(&ginfo
, bracketEntry
->GetBracketId());
532 // send status in BattleGround Queue
533 sBattleGroundMgr
.BuildBattleGroundStatusPacket(&data
, bg
, i
, STATUS_WAIT_QUEUE
, avgTime
, getMSTimeDiff(ginfo
.JoinTime
, getMSTime()), arenaType
);
539 void WorldSession::HandleAreaSpiritHealerQueryOpcode( WorldPacket
& recv_data
)
541 sLog
.outDebug("WORLD: CMSG_AREA_SPIRIT_HEALER_QUERY");
543 BattleGround
*bg
= _player
->GetBattleGround();
550 Creature
*unit
= GetPlayer()->GetMap()->GetCreature(guid
);
554 if(!unit
->isSpiritService()) // it's not spirit service
557 unit
->SendAreaSpiritHealerQueryOpcode(GetPlayer());
560 void WorldSession::HandleAreaSpiritHealerQueueOpcode( WorldPacket
& recv_data
)
562 sLog
.outDebug("WORLD: CMSG_AREA_SPIRIT_HEALER_QUEUE");
564 BattleGround
*bg
= _player
->GetBattleGround();
571 Creature
*unit
= GetPlayer()->GetMap()->GetCreature(guid
);
575 if(!unit
->isSpiritService()) // it's not spirit service
578 Script
->GossipHello(GetPlayer(), unit
);
581 void WorldSession::HandleBattlemasterJoinArena( WorldPacket
& recv_data
)
583 sLog
.outDebug("WORLD: CMSG_BATTLEMASTER_JOIN_ARENA");
584 //recv_data.hexlike();
586 uint64 guid
; // arena Battlemaster guid
587 uint8 arenaslot
; // 2v2, 3v3 or 5v5
588 uint8 asGroup
; // asGroup
589 uint8 isRated
; // isRated
592 recv_data
>> guid
>> arenaslot
>> asGroup
>> isRated
;
594 // ignore if we already in BG or BG queue
595 if (_player
->InBattleGround())
598 Creature
*unit
= GetPlayer()->GetMap()->GetCreature(guid
);
602 if(!unit
->isBattleMaster()) // it's not battle master
606 uint32 arenaRating
= 0;
611 arenatype
= ARENA_TYPE_2v2
;
614 arenatype
= ARENA_TYPE_3v3
;
617 arenatype
= ARENA_TYPE_5v5
;
620 sLog
.outError("Unknown arena slot %u at HandleBattlemasterJoinArena()", arenaslot
);
625 BattleGround
* bg
= sBattleGroundMgr
.GetBattleGroundTemplate(BATTLEGROUND_AA
);
628 sLog
.outError("Battleground: template bg (all arenas) not found");
632 BattleGroundTypeId bgTypeId
= bg
->GetTypeID();
633 BattleGroundQueueTypeId bgQueueTypeId
= BattleGroundMgr::BGQueueTypeId(bgTypeId
, arenatype
);
634 PvPDifficultyEntry
const* bracketEntry
= GetBattlegroundBracketByLevel(bg
->GetMapId(),_player
->getLevel());
638 // check queueing conditions
641 // check if already in queue
642 if (_player
->GetBattleGroundQueueIndex(bgQueueTypeId
) < PLAYER_MAX_BATTLEGROUND_QUEUES
)
643 //player is already in this queue
645 // check if has free queue slots
646 if (!_player
->HasFreeBattleGroundQueueId())
651 grp
= _player
->GetGroup();
652 // no group found, error
655 uint32 err
= grp
->CanJoinBattleGroundQueue(bg
, bgQueueTypeId
, arenatype
, arenatype
, (bool)isRated
, arenaslot
);
656 if (err
!= BG_JOIN_ERR_OK
)
658 SendBattleGroundOrArenaJoinError(err
);
667 ateamId
= _player
->GetArenaTeamId(arenaslot
);
668 // check real arenateam existence only here (if it was moved to group->CanJoin .. () then we would ahve to get it twice)
669 ArenaTeam
* at
= sObjectMgr
.GetArenaTeamById(ateamId
);
672 _player
->GetSession()->SendNotInArenaTeamPacket(arenatype
);
675 // get the team rating for queueing
676 arenaRating
= at
->GetRating();
677 // the arenateam id must match for everyone in the group
678 // get the personal ratings for queueing
679 uint32 avg_pers_rating
= 0;
680 for(GroupReference
*itr
= grp
->GetFirstMember(); itr
!= NULL
; itr
= itr
->next())
682 Player
*member
= itr
->getSource();
684 // calc avg personal rating
685 avg_pers_rating
+= member
->GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1
+ (arenaslot
* ARENA_TEAM_END
) + ARENA_TEAM_PERSONAL_RATING
);
689 avg_pers_rating
/= arenatype
;
691 // 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
692 if (avg_pers_rating
+ 150 < arenaRating
)
693 arenaRating
= avg_pers_rating
;
696 BattleGroundQueue
&bgQueue
= sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
];
699 sLog
.outDebug("Battleground: arena join as group start");
701 sLog
.outDebug("Battleground: arena team id %u, leader %s queued with rating %u for type %u",_player
->GetArenaTeamId(arenaslot
),_player
->GetName(),arenaRating
,arenatype
);
703 GroupQueueInfo
* ginfo
= bgQueue
.AddGroup(_player
, grp
, bgTypeId
, bracketEntry
, arenatype
, isRated
, false, arenaRating
, ateamId
);
704 uint32 avgTime
= bgQueue
.GetAverageQueueWaitTime(ginfo
, bracketEntry
->GetBracketId());
705 for(GroupReference
*itr
= grp
->GetFirstMember(); itr
!= NULL
; itr
= itr
->next())
707 Player
*member
= itr
->getSource();
708 if(!member
) continue;
710 uint32 queueSlot
= member
->AddBattleGroundQueueId(bgQueueTypeId
);// add to queue
713 // send status packet (in queue)
714 sBattleGroundMgr
.BuildBattleGroundStatusPacket(&data
, bg
, queueSlot
, STATUS_WAIT_QUEUE
, avgTime
, 0, arenatype
);
715 member
->GetSession()->SendPacket(&data
);
716 sBattleGroundMgr
.BuildGroupJoinedBattlegroundPacket(&data
, bgTypeId
);
717 member
->GetSession()->SendPacket(&data
);
718 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());
720 sLog
.outDebug("Battleground: arena join as group end");
721 //announce to world ... removed
725 GroupQueueInfo
* ginfo
= bgQueue
.AddGroup(_player
, NULL
, bgTypeId
, bracketEntry
, arenatype
, isRated
, false, arenaRating
, ateamId
);
726 uint32 avgTime
= bgQueue
.GetAverageQueueWaitTime(ginfo
, bracketEntry
->GetBracketId());
727 uint32 queueSlot
= _player
->AddBattleGroundQueueId(bgQueueTypeId
);
730 // send status packet (in queue)
731 sBattleGroundMgr
.BuildBattleGroundStatusPacket(&data
, bg
, queueSlot
, STATUS_WAIT_QUEUE
, avgTime
, 0, arenatype
);
733 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());
735 sBattleGroundMgr
.ScheduleQueueUpdate(arenaRating
, arenatype
, bgQueueTypeId
, bgTypeId
, bracketEntry
->GetBracketId());
738 void WorldSession::HandleReportPvPAFK( WorldPacket
& recv_data
)
741 recv_data
>> playerGuid
;
742 Player
*reportedPlayer
= sObjectMgr
.GetPlayer(playerGuid
);
746 sLog
.outDebug("WorldSession::HandleReportPvPAFK: player not found");
750 sLog
.outDebug("WorldSession::HandleReportPvPAFK: %s reported %s", _player
->GetName(), reportedPlayer
->GetName());
752 reportedPlayer
->ReportedAfkBy(_player
);
755 void WorldSession::SendBattleGroundOrArenaJoinError(uint8 err
)
761 case BG_JOIN_ERR_OFFLINE_MEMBER
:
762 msg
= LANG_BG_GROUP_OFFLINE_MEMBER
;
764 case BG_JOIN_ERR_GROUP_TOO_MANY
:
765 msg
= LANG_BG_GROUP_TOO_LARGE
;
767 case BG_JOIN_ERR_MIXED_FACTION
:
768 msg
= LANG_BG_GROUP_MIXED_FACTION
;
770 case BG_JOIN_ERR_MIXED_LEVELS
:
771 msg
= LANG_BG_GROUP_MIXED_LEVELS
;
773 case BG_JOIN_ERR_GROUP_MEMBER_ALREADY_IN_QUEUE
:
774 msg
= LANG_BG_GROUP_MEMBER_ALREADY_IN_QUEUE
;
776 case BG_JOIN_ERR_GROUP_DESERTER
:
777 msg
= LANG_BG_GROUP_MEMBER_DESERTER
;
779 case BG_JOIN_ERR_ALL_QUEUES_USED
:
780 msg
= LANG_BG_GROUP_MEMBER_NO_FREE_QUEUE_SLOTS
;
782 case BG_JOIN_ERR_GROUP_NOT_ENOUGH
:
783 case BG_JOIN_ERR_MIXED_ARENATEAM
:
788 ChatHandler::FillMessageData(&data
, NULL
, CHAT_MSG_BG_SYSTEM_NEUTRAL
, LANG_UNIVERSAL
, NULL
, 0, GetMangosString(msg
), NULL
);