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"
26 #include "ObjectAccessor.h"
29 #include "BattleGroundMgr.h"
30 #include "BattleGroundWS.h"
31 #include "BattleGround.h"
32 #include "ArenaTeam.h"
35 void WorldSession::HandleBattlemasterHelloOpcode( WorldPacket
& recv_data
)
37 CHECK_PACKET_SIZE(recv_data
, 8);
41 sLog
.outDebug( "WORLD: Recvd CMSG_BATTLEMASTER_HELLO Message from: " I64FMT
, guid
);
43 Creature
*unit
= GetPlayer()->GetMap()->GetCreature(guid
);
47 if(!unit
->isBattleMaster()) // it's not battlemaster
50 // Stop the npc if moving
53 BattleGroundTypeId bgTypeId
= sBattleGroundMgr
.GetBattleMasterBG(unit
->GetEntry());
55 if (!_player
->GetBGAccessByLevel(bgTypeId
))
57 // temp, must be gossip message...
58 SendNotification(LANG_YOUR_BG_LEVEL_REQ_ERROR
);
62 SendBattlegGroundList(guid
, bgTypeId
);
65 void WorldSession::SendBattlegGroundList( uint64 guid
, BattleGroundTypeId bgTypeId
)
68 sBattleGroundMgr
.BuildBattleGroundListPacket(&data
, guid
, _player
, bgTypeId
, 0);
72 void WorldSession::HandleBattlemasterJoinOpcode( WorldPacket
& recv_data
)
74 CHECK_PACKET_SIZE(recv_data
, 8+4+4+1);
80 bool isPremade
= false;
83 recv_data
>> guid
; // battlemaster guid
84 recv_data
>> bgTypeId_
; // battleground type id (DBC id)
85 recv_data
>> instanceId
; // instance id, 0 if First Available selected
86 recv_data
>> joinAsGroup
; // join as group
88 if (!sBattlemasterListStore
.LookupEntry(bgTypeId_
))
90 sLog
.outError("Battleground: invalid bgtype (%u) received. possible cheater? player guid %u",bgTypeId_
,_player
->GetGUIDLow());
94 BattleGroundTypeId bgTypeId
= BattleGroundTypeId(bgTypeId_
);
96 sLog
.outDebug( "WORLD: Recvd CMSG_BATTLEMASTER_JOIN Message from: " I64FMT
, guid
);
98 // can do this, since it's battleground, not arena
99 BattleGroundQueueTypeId bgQueueTypeId
= BattleGroundMgr::BGQueueTypeId(bgTypeId
, 0);
101 // ignore if player is already in BG
102 if (_player
->InBattleGround())
105 // get bg instance or bg template if instance not found
106 BattleGround
*bg
= NULL
;
108 bg
= sBattleGroundMgr
.GetBattleGroundThroughClientInstance(instanceId
, bgTypeId
);
110 if (!bg
&& !(bg
= sBattleGroundMgr
.GetBattleGroundTemplate(bgTypeId
)))
112 sLog
.outError("Battleground: no available bg / template found");
116 // check queueing conditions
119 // check Deserter debuff
120 if (!_player
->CanJoinToBattleground())
122 WorldPacket
data(SMSG_GROUP_JOINED_BATTLEGROUND
, 4);
123 data
<< uint32(0xFFFFFFFE);
124 _player
->GetSession()->SendPacket(&data
);
127 // check if already in queue
128 if (_player
->GetBattleGroundQueueIndex(bgQueueTypeId
) < PLAYER_MAX_BATTLEGROUND_QUEUES
)
129 //player is already in this queue
131 // check if has free queue slots
132 if (!_player
->HasFreeBattleGroundQueueId())
137 grp
= _player
->GetGroup();
138 // no group found, error
141 uint32 err
= grp
->CanJoinBattleGroundQueue(bgTypeId
, bgQueueTypeId
, 0, bg
->GetMaxPlayersPerTeam(), false, 0);
142 isPremade
= (grp
->GetMembersCount() >= bg
->GetMinPlayersPerTeam());
143 if (err
!= BG_JOIN_ERR_OK
)
145 SendBattleGroundOrArenaJoinError(err
);
149 // if we're here, then the conditions to join a bg are met. We can proceed in joining.
151 // _player->GetGroup() was already checked, grp is already initialized
152 GroupQueueInfo
* ginfo
= sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].AddGroup(_player
, bgTypeId
, 0, false, isPremade
, 0);
153 uint32 avgTime
= sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].GetAverageQueueWaitTime(ginfo
, _player
->GetBattleGroundQueueIdFromLevel(bgTypeId
));
154 if (joinAsGroup
/* && _player->GetGroup()*/)
156 sLog
.outDebug("Battleground: the following players are joining as group:");
157 for(GroupReference
*itr
= grp
->GetFirstMember(); itr
!= NULL
; itr
= itr
->next())
159 Player
*member
= itr
->getSource();
160 if(!member
) continue; // this should never happen
162 uint32 queueSlot
= member
->AddBattleGroundQueueId(bgQueueTypeId
); // add to queue
164 // store entry point coords (same as leader entry point)
165 member
->SetBattleGroundEntryPoint(_player
->GetMapId(),_player
->GetPositionX(),_player
->GetPositionY(),_player
->GetPositionZ(),_player
->GetOrientation());
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 sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].AddPlayer(member
, ginfo
);
174 sLog
.outDebug("Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId
,bgTypeId
,member
->GetGUIDLow(), member
->GetName());
176 sLog
.outDebug("Battleground: group end");
180 // already checked if queueSlot is valid, now just get it
181 uint32 queueSlot
= _player
->AddBattleGroundQueueId(bgQueueTypeId
);
182 // store entry point coords
183 _player
->SetBattleGroundEntryPoint(_player
->GetMapId(),_player
->GetPositionX(),_player
->GetPositionY(),_player
->GetPositionZ(),_player
->GetOrientation());
186 // send status packet (in queue)
187 sBattleGroundMgr
.BuildBattleGroundStatusPacket(&data
, bg
, queueSlot
, STATUS_WAIT_QUEUE
, avgTime
, 0, ginfo
->ArenaType
);
190 sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].AddPlayer(_player
, ginfo
);
191 sLog
.outDebug("Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId
,bgTypeId
,_player
->GetGUIDLow(), _player
->GetName());
193 sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].Update(bgTypeId
, _player
->GetBattleGroundQueueIdFromLevel(bgTypeId
));
194 if (!ginfo
->IsInvitedToBGInstanceGUID
)
195 sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].AnnounceWorld(ginfo
, _player
->GetGUID(), true);
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
= objmgr
.GetPlayer(((BattleGroundWS
*)bg
)->GetAllianceFlagPickerGUID());
218 Player
*horde_plr
= objmgr
.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 CHECK_PACKET_SIZE(recv_data
, 4 + 1);
285 sLog
.outDebug( "WORLD: Recvd CMSG_BATTLEFIELD_LIST Message");
288 recv_data
>> bgTypeId
; // id from DBC
291 recv_data
>> fromWhere
; // 0 - battlemaster, 1 - UI
293 BattlemasterListEntry
const* bl
= sBattlemasterListStore
.LookupEntry(bgTypeId
);
296 sLog
.outError("Battleground: invalid bgtype received.");
301 sBattleGroundMgr
.BuildBattleGroundListPacket(&data
, 0, _player
, BattleGroundTypeId(bgTypeId
), fromWhere
);
305 void WorldSession::HandleBattleFieldPortOpcode( WorldPacket
&recv_data
)
307 CHECK_PACKET_SIZE(recv_data
, 1+1+4+2+1);
309 sLog
.outDebug( "WORLD: Recvd CMSG_BATTLEFIELD_PORT Message");
311 uint8 type
; // arenatype if arena
312 uint8 unk2
; // unk, can be 0x0 (may be if was invited?) and 0x1
314 uint32 bgTypeId_
; // type id from dbc
315 uint16 unk
; // 0x1F90 constant?
316 uint8 action
; // enter battle 0x1, leave queue 0x0
318 recv_data
>> type
>> unk2
>> bgTypeId_
>> unk
>> action
;
320 if (!sBattlemasterListStore
.LookupEntry(bgTypeId_
))
322 sLog
.outError("Battleground: invalid bgtype (%u) received.", bgTypeId_
);
323 // update battleground slots for the player to fix his UI and sent data.
324 // this is a HACK, I don't know why the client starts sending invalid packets in the first place.
325 // it usually happens with extremely high latency (if debugging / stepping in the code for example)
326 if (_player
->InBattleGroundQueue())
328 // update all queues, send invitation info if player is invited, queue info if queued
329 for (uint32 i
= 0; i
< PLAYER_MAX_BATTLEGROUND_QUEUES
; ++i
)
331 BattleGroundQueueTypeId bgQueueTypeId
= _player
->GetBattleGroundQueueTypeId(i
);
334 BattleGroundTypeId bgTypeId
= BattleGroundMgr::BGTemplateId(bgQueueTypeId
);
335 BattleGroundQueue::QueuedPlayersMap
& qpMap
= sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].m_QueuedPlayers
;
336 BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus
= qpMap
.find(_player
->GetGUID());
337 // if the player is not in queue, continue or no group information - this should never happen
338 if (itrPlayerStatus
== qpMap
.end() || !itrPlayerStatus
->second
.GroupInfo
)
341 BattleGround
* bg
= NULL
;
342 // get possibly needed data from groupinfo
343 uint8 arenatype
= itrPlayerStatus
->second
.GroupInfo
->ArenaType
;
346 if (!itrPlayerStatus
->second
.GroupInfo
->IsInvitedToBGInstanceGUID
)
348 // not invited to bg, get template
349 bg
= sBattleGroundMgr
.GetBattleGroundTemplate(bgTypeId
);
350 status
= STATUS_WAIT_QUEUE
;
354 // get the bg we're invited to
355 bg
= sBattleGroundMgr
.GetBattleGround(itrPlayerStatus
->second
.GroupInfo
->IsInvitedToBGInstanceGUID
, bgTypeId
);
356 status
= STATUS_WAIT_JOIN
;
359 // if bg not found, then continue, don't invite if already in the instance
360 if (!bg
|| (_player
->InBattleGround() && _player
->GetBattleGround() && _player
->GetBattleGround()->GetInstanceID() == bg
->GetInstanceID()))
363 // re - invite player with proper data
365 sBattleGroundMgr
.BuildBattleGroundStatusPacket(&data
, bg
, i
, status
, INVITE_ACCEPT_WAIT_TIME
, 0, arenatype
);
372 //get GroupQueueInfo from BattleGroundQueue
373 BattleGroundTypeId bgTypeId
= BattleGroundTypeId(bgTypeId_
);
374 BattleGroundQueueTypeId bgQueueTypeId
= BattleGroundMgr::BGQueueTypeId(bgTypeId
, type
);
375 BattleGroundQueue::QueuedPlayersMap
& qpMap
= sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].m_QueuedPlayers
;
376 BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus
= qpMap
.find(_player
->GetGUID());
377 if (itrPlayerStatus
== qpMap
.end())
379 sLog
.outError("Battleground: itrplayerstatus not found.");
383 instanceId
= itrPlayerStatus
->second
.GroupInfo
->IsInvitedToBGInstanceGUID
;
384 // if action == 1, then instanceId is required
385 if (!instanceId
&& action
== 1)
387 sLog
.outError("Battleground: instance not found.");
391 BattleGround
*bg
= sBattleGroundMgr
.GetBattleGround(instanceId
, bgTypeId
);
393 // bg template might and must be used in case of leaving queue, when instance is not created yet
394 if (!bg
&& action
== 0)
395 bg
= sBattleGroundMgr
.GetBattleGroundTemplate(bgTypeId
);
398 sLog
.outError("Battleground: bg_template not found for type id %u.", bgTypeId
);
402 if (_player
->InBattleGroundQueue())
404 //we must use temporary variables, because GroupQueueInfo pointer can be deleted in BattleGroundQueue::RemovePlayer() function!
405 uint32 team
= itrPlayerStatus
->second
.GroupInfo
->Team
;
406 uint32 arenaType
= itrPlayerStatus
->second
.GroupInfo
->ArenaType
;
407 uint32 isRated
= itrPlayerStatus
->second
.GroupInfo
->IsRated
;
408 uint32 rating
= itrPlayerStatus
->second
.GroupInfo
->ArenaTeamRating
;
409 uint32 opponentsRating
= itrPlayerStatus
->second
.GroupInfo
->OpponentsTeamRating
;
411 //some checks if player isn't cheating - it is not exactly cheating, but we cannot allow it
412 if (action
== 1 && arenaType
== 0)
414 //if player is trying to enter battleground (not arena!) and he has deserter debuff, we must just remove him from queue
415 if (!_player
->CanJoinToBattleground())
417 //send bg command result to show nice message
418 WorldPacket
data2(SMSG_GROUP_JOINED_BATTLEGROUND
, 4);
419 data2
<< uint32(0xFFFFFFFE);
420 _player
->GetSession()->SendPacket(&data2
);
422 sLog
.outDebug("Battleground: player %s (%u) has a deserter debuff, do not port him to battleground!", _player
->GetName(), _player
->GetGUIDLow());
424 //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
425 if (_player
->getLevel() > bg
->GetMaxLevel())
427 sLog
.outError("Battleground: Player %s (%u) has level higher than maxlevel of battleground! Do not port him to battleground!", _player
->GetName(), _player
->GetGUIDLow());
431 uint32 queueSlot
= _player
->GetBattleGroundQueueIndex(bgQueueTypeId
);
435 case 1: // port to battleground
436 if (!_player
->IsInvitedForBattleGroundQueueType(bgQueueTypeId
))
438 // resurrect the player
439 if (!_player
->isAlive())
441 _player
->ResurrectPlayer(1.0f
);
442 _player
->SpawnCorpseBones();
444 // stop taxi flight at port
445 if (_player
->isInFlight())
447 _player
->GetMotionMaster()->MovementExpired();
448 _player
->m_taxi
.ClearTaxiDestinations();
451 sBattleGroundMgr
.BuildBattleGroundStatusPacket(&data
, bg
, queueSlot
, STATUS_IN_PROGRESS
, 0, bg
->GetStartTime(), bg
->GetArenaType());
452 _player
->GetSession()->SendPacket(&data
);
453 // remove battleground queue status from BGmgr
454 sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].RemovePlayer(_player
->GetGUID(), false);
455 // this is still needed here if battleground "jumping" shouldn't add deserter debuff
456 // also this is required to prevent stuck at old battleground after SetBattleGroundId set to new
457 if (BattleGround
*currentBg
= _player
->GetBattleGround())
458 currentBg
->RemovePlayerAtLeave(_player
->GetGUID(), false, true);
460 // set the destination instance id
461 _player
->SetBattleGroundId(bg
->GetInstanceID(), bgTypeId
);
462 // set the destination team
463 _player
->SetBGTeam(team
);
464 // bg->HandleBeforeTeleportToBattleGround(_player);
465 sBattleGroundMgr
.SendToBattleGround(_player
, instanceId
, bgTypeId
);
466 // add only in HandleMoveWorldPortAck()
467 // bg->AddPlayer(_player,team);
468 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
);
470 case 0: // leave queue
471 // if player leaves rated arena match before match start, it is counted as he played but he lost
474 ArenaTeam
* at
= objmgr
.GetArenaTeamById(team
);
477 sLog
.outDebug("UPDATING memberLost's personal arena rating for %u by opponents rating: %u, because he has left queue!", GUID_LOPART(_player
->GetGUID()), opponentsRating
);
478 at
->MemberLost(_player
, opponentsRating
);
482 _player
->RemoveBattleGroundQueueId(bgQueueTypeId
); // must be called this way, because if you move this call to queue->removeplayer, it causes bugs
483 sBattleGroundMgr
.BuildBattleGroundStatusPacket(&data
, bg
, queueSlot
, STATUS_NONE
, 0, 0, 0);
484 sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].RemovePlayer(_player
->GetGUID(), true);
485 // player left queue, we should update it - do not update Arena Queue
487 sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].Update(bgTypeId
, _player
->GetBattleGroundQueueIdFromLevel(bgTypeId
), arenaType
, isRated
, rating
);
489 sLog
.outDebug("Battleground: player %s (%u) left queue for bgtype %u, queue type %u.", _player
->GetName(), _player
->GetGUIDLow(), bg
->GetTypeID(), bgQueueTypeId
);
492 sLog
.outError("Battleground port: unknown action %u", action
);
498 void WorldSession::HandleLeaveBattlefieldOpcode( WorldPacket
& /*recv_data*/ )
500 //CHECK_PACKET_SIZE(recv_data, 1+1+4+2);
502 sLog
.outDebug( "WORLD: Recvd CMSG_LEAVE_BATTLEFIELD Message");
505 //uint32 bgTypeId; // id from DBC
508 //recv_data >> unk1 >> unk2 >> bgTypeId >> unk3; - no used currently
510 //if(bgTypeId >= MAX_BATTLEGROUND_TYPES) // cheating? but not important in this case
513 // not allow leave battleground in combat
514 if (_player
->isInCombat())
515 if (BattleGround
* bg
= _player
->GetBattleGround())
516 if (bg
->GetStatus() != STATUS_WAIT_LEAVE
)
519 _player
->LeaveBattleground();
522 void WorldSession::HandleBattlefieldStatusOpcode( WorldPacket
& /*recv_data*/ )
525 sLog
.outDebug( "WORLD: Battleground status" );
528 // we must update all queues here
529 BattleGround
*bg
= NULL
;
530 for (uint8 i
= 0; i
< PLAYER_MAX_BATTLEGROUND_QUEUES
; ++i
)
532 BattleGroundQueueTypeId bgQueueTypeId
= _player
->GetBattleGroundQueueTypeId(i
);
535 BattleGroundTypeId bgTypeId
= BattleGroundMgr::BGTemplateId(bgQueueTypeId
);
536 uint8 arenaType
= BattleGroundMgr::BGArenaType(bgQueueTypeId
);
537 if (bgTypeId
== _player
->GetBattleGroundTypeId())
539 bg
= _player
->GetBattleGround();
540 //i cannot check any variable from player class because player class doesn't know if player is in 2v2 / 3v3 or 5v5 arena
541 //so i must use bg pointer to get that information
542 if (bg
&& bg
->GetArenaType() == arenaType
)
544 // this line is checked, i only don't know if GetStartTime is changing itself after bg end!
545 // send status in BattleGround
546 sBattleGroundMgr
.BuildBattleGroundStatusPacket(&data
, bg
, i
, STATUS_IN_PROGRESS
, bg
->GetEndTime(), bg
->GetStartTime(), arenaType
);
551 //we are sending update to player about queue - he can be invited there!
552 //get GroupQueueInfo for queue status
553 BattleGroundQueue::QueuedPlayersMap
& qpMap
= sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].m_QueuedPlayers
;
554 BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus
= qpMap
.find(_player
->GetGUID());
555 if (itrPlayerStatus
== qpMap
.end())
557 if (itrPlayerStatus
->second
.GroupInfo
->IsInvitedToBGInstanceGUID
)
559 bg
= sBattleGroundMgr
.GetBattleGround(itrPlayerStatus
->second
.GroupInfo
->IsInvitedToBGInstanceGUID
, bgTypeId
);
562 uint32 remainingTime
= getMSTimeDiff(getMSTime(), itrPlayerStatus
->second
.GroupInfo
->RemoveInviteTime
);
563 // send status invited to BattleGround
564 sBattleGroundMgr
.BuildBattleGroundStatusPacket(&data
, bg
, i
, STATUS_WAIT_JOIN
, remainingTime
, 0, arenaType
);
569 bg
= sBattleGroundMgr
.GetBattleGroundTemplate(bgTypeId
);
572 uint32 avgTime
= sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].GetAverageQueueWaitTime(itrPlayerStatus
->second
.GroupInfo
, _player
->GetBattleGroundQueueIdFromLevel(bgTypeId
));
573 // send status in BattleGround Queue
574 sBattleGroundMgr
.BuildBattleGroundStatusPacket(&data
, bg
, i
, STATUS_WAIT_QUEUE
, avgTime
, getMSTimeDiff(itrPlayerStatus
->second
.GroupInfo
->JoinTime
, getMSTime()), arenaType
);
580 void WorldSession::HandleAreaSpiritHealerQueryOpcode( WorldPacket
& recv_data
)
582 sLog
.outDebug("WORLD: CMSG_AREA_SPIRIT_HEALER_QUERY");
584 CHECK_PACKET_SIZE(recv_data
, 8);
586 BattleGround
*bg
= _player
->GetBattleGround();
593 Creature
*unit
= GetPlayer()->GetMap()->GetCreature(guid
);
597 if(!unit
->isSpiritService()) // it's not spirit service
600 sBattleGroundMgr
.SendAreaSpiritHealerQueryOpcode(_player
, bg
, guid
);
603 void WorldSession::HandleAreaSpiritHealerQueueOpcode( WorldPacket
& recv_data
)
605 sLog
.outDebug("WORLD: CMSG_AREA_SPIRIT_HEALER_QUEUE");
607 CHECK_PACKET_SIZE(recv_data
, 8);
609 BattleGround
*bg
= _player
->GetBattleGround();
616 Creature
*unit
= GetPlayer()->GetMap()->GetCreature(guid
);
620 if(!unit
->isSpiritService()) // it's not spirit service
623 bg
->AddPlayerToResurrectQueue(guid
, _player
->GetGUID());
626 void WorldSession::HandleBattlemasterJoinArena( WorldPacket
& recv_data
)
628 CHECK_PACKET_SIZE(recv_data
, 8+1+1+1);
630 sLog
.outDebug("WORLD: CMSG_BATTLEMASTER_JOIN_ARENA");
633 // ignore if we already in BG or BG queue
634 if (_player
->InBattleGround())
637 uint64 guid
; // arena Battlemaster guid
638 uint8 arenaslot
; // 2v2, 3v3 or 5v5
639 uint8 asGroup
; // asGroup
640 uint8 isRated
; // isRated
643 recv_data
>> guid
>> arenaslot
>> asGroup
>> isRated
;
645 Creature
*unit
= GetPlayer()->GetMap()->GetCreature(guid
);
649 if(!unit
->isBattleMaster()) // it's not battle master
653 uint32 arenaRating
= 0;
658 arenatype
= ARENA_TYPE_2v2
;
661 arenatype
= ARENA_TYPE_3v3
;
664 arenatype
= ARENA_TYPE_5v5
;
667 sLog
.outError("Unknown arena slot %u at HandleBattlemasterJoinArena()", arenaslot
);
672 BattleGround
* bg
= NULL
;
673 if (!(bg
= sBattleGroundMgr
.GetBattleGroundTemplate(BATTLEGROUND_AA
)))
675 sLog
.outError("Battleground: template bg (all arenas) not found");
679 BattleGroundTypeId bgTypeId
= bg
->GetTypeID();
680 BattleGroundQueueTypeId bgQueueTypeId
= BattleGroundMgr::BGQueueTypeId(bgTypeId
, arenatype
);
682 // check queueing conditions
685 // check if already in queue
686 if (_player
->GetBattleGroundQueueIndex(bgQueueTypeId
) < PLAYER_MAX_BATTLEGROUND_QUEUES
)
687 //player is already in this queue
689 // check if has free queue slots
690 if (!_player
->HasFreeBattleGroundQueueId())
695 grp
= _player
->GetGroup();
696 // no group found, error
699 uint32 err
= grp
->CanJoinBattleGroundQueue(bgTypeId
, bgQueueTypeId
, arenatype
, arenatype
, (bool)isRated
, arenaslot
);
700 if (err
!= BG_JOIN_ERR_OK
)
702 SendBattleGroundOrArenaJoinError(err
);
711 ateamId
= _player
->GetArenaTeamId(arenaslot
);
712 // check real arenateam existence only here (if it was moved to group->CanJoin .. () then we would ahve to get it twice)
713 ArenaTeam
* at
= objmgr
.GetArenaTeamById(ateamId
);
716 _player
->GetSession()->SendNotInArenaTeamPacket(arenatype
);
719 // get the team rating for queueing
720 arenaRating
= at
->GetRating();
721 // the arenateam id must match for everyone in the group
722 // get the personal ratings for queueing
723 uint32 avg_pers_rating
= 0;
724 for(GroupReference
*itr
= grp
->GetFirstMember(); itr
!= NULL
; itr
= itr
->next())
726 Player
*member
= itr
->getSource();
728 // calc avg personal rating
729 avg_pers_rating
+= member
->GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1
+ (arenaslot
*6) + 5);
733 avg_pers_rating
/= arenatype
;
735 // 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
736 if (avg_pers_rating
+ 150 < arenaRating
)
737 arenaRating
= avg_pers_rating
;
740 GroupQueueInfo
* ginfo
= sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].AddGroup(_player
, bgTypeId
, arenatype
, isRated
, false, arenaRating
, ateamId
);
741 uint32 avgTime
= sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].GetAverageQueueWaitTime(ginfo
, _player
->GetBattleGroundQueueIdFromLevel(bgTypeId
));
744 sLog
.outDebug("Battleground: arena join as group start");
746 sLog
.outDebug("Battleground: arena team id %u, leader %s queued with rating %u for type %u",_player
->GetArenaTeamId(arenaslot
),_player
->GetName(),arenaRating
,arenatype
);
747 for(GroupReference
*itr
= grp
->GetFirstMember(); itr
!= NULL
; itr
= itr
->next())
749 Player
*member
= itr
->getSource();
750 if(!member
) continue;
752 uint32 queueSlot
= member
->AddBattleGroundQueueId(bgQueueTypeId
);// add to queue
754 // store entry point coords (same as leader entry point)
755 member
->SetBattleGroundEntryPoint(_player
->GetMapId(),_player
->GetPositionX(),_player
->GetPositionY(),_player
->GetPositionZ(),_player
->GetOrientation());
758 // send status packet (in queue)
759 sBattleGroundMgr
.BuildBattleGroundStatusPacket(&data
, bg
, queueSlot
, STATUS_WAIT_QUEUE
, avgTime
, 0, arenatype
);
760 member
->GetSession()->SendPacket(&data
);
761 sBattleGroundMgr
.BuildGroupJoinedBattlegroundPacket(&data
, bgTypeId
);
762 member
->GetSession()->SendPacket(&data
);
763 sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].AddPlayer(member
, ginfo
);
764 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());
766 sLog
.outDebug("Battleground: arena join as group end");
768 sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].AnnounceWorld(ginfo
, _player
->GetGUID(), true);
772 uint32 queueSlot
= _player
->AddBattleGroundQueueId(bgQueueTypeId
);
774 // store entry point coords
775 _player
->SetBattleGroundEntryPoint(_player
->GetMapId(),_player
->GetPositionX(),_player
->GetPositionY(),_player
->GetPositionZ(),_player
->GetOrientation());
778 // send status packet (in queue)
779 sBattleGroundMgr
.BuildBattleGroundStatusPacket(&data
, bg
, queueSlot
, STATUS_WAIT_QUEUE
, avgTime
, 0, arenatype
);
781 sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].AddPlayer(_player
, ginfo
);
782 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());
784 sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].Update(bgTypeId
, _player
->GetBattleGroundQueueIdFromLevel(bgTypeId
), arenatype
, isRated
, arenaRating
);
787 void WorldSession::HandleReportPvPAFK( WorldPacket
& recv_data
)
789 CHECK_PACKET_SIZE(recv_data
, 8);
792 recv_data
>> playerGuid
;
793 Player
*reportedPlayer
= objmgr
.GetPlayer(playerGuid
);
797 sLog
.outDebug("WorldSession::HandleReportPvPAFK: player not found");
801 sLog
.outDebug("WorldSession::HandleReportPvPAFK: %s reported %s", _player
->GetName(), reportedPlayer
->GetName());
803 reportedPlayer
->ReportedAfkBy(_player
);
806 void WorldSession::SendBattleGroundOrArenaJoinError(uint8 err
)
812 case BG_JOIN_ERR_OFFLINE_MEMBER
:
813 msg
= LANG_BG_GROUP_OFFLINE_MEMBER
;
815 case BG_JOIN_ERR_GROUP_TOO_MANY
:
816 msg
= LANG_BG_GROUP_TOO_LARGE
;
818 case BG_JOIN_ERR_MIXED_FACTION
:
819 msg
= LANG_BG_GROUP_MIXED_FACTION
;
821 case BG_JOIN_ERR_MIXED_LEVELS
:
822 msg
= LANG_BG_GROUP_MIXED_LEVELS
;
824 case BG_JOIN_ERR_GROUP_MEMBER_ALREADY_IN_QUEUE
:
825 msg
= LANG_BG_GROUP_MEMBER_ALREADY_IN_QUEUE
;
827 case BG_JOIN_ERR_GROUP_DESERTER
:
828 msg
= LANG_BG_GROUP_MEMBER_DESERTER
;
830 case BG_JOIN_ERR_ALL_QUEUES_USED
:
831 msg
= LANG_BG_GROUP_MEMBER_NO_FREE_QUEUE_SLOTS
;
833 case BG_JOIN_ERR_GROUP_NOT_ENOUGH
:
834 case BG_JOIN_ERR_MIXED_ARENATEAM
:
839 ChatHandler::FillMessageData(&data
, NULL
, CHAT_MSG_BG_SYSTEM_NEUTRAL
, LANG_UNIVERSAL
, NULL
, 0, GetMangosString(msg
), NULL
);