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 "MapManager.h"
27 #include "ObjectAccessor.h"
30 #include "BattleGroundMgr.h"
31 #include "BattleGroundWS.h"
32 #include "BattleGround.h"
33 #include "ArenaTeam.h"
36 void WorldSession::HandleBattleGroundHelloOpcode( WorldPacket
& recv_data
)
38 CHECK_PACKET_SIZE(recv_data
, 8);
42 sLog
.outDebug( "WORLD: Recvd CMSG_BATTLEMASTER_HELLO Message from: " I64FMT
, guid
);
44 Creature
*unit
= ObjectAccessor::GetCreature(*_player
, guid
);
48 if(!unit
->isBattleMaster()) // it's not battlemaster
51 // Stop the npc if moving
54 uint32 bgTypeId
= objmgr
.GetBattleMasterBG(unit
->GetEntry());
56 if(!_player
->GetBGAccessByLevel(bgTypeId
))
58 // temp, must be gossip message...
59 SendNotification(LANG_YOUR_BG_LEVEL_REQ_ERROR
);
63 SendBattlegGroundList(guid
, bgTypeId
);
66 void WorldSession::SendBattlegGroundList( uint64 guid
, uint32 bgTypeId
)
69 sBattleGroundMgr
.BuildBattleGroundListPacket(&data
, guid
, _player
, bgTypeId
);
73 void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket
& recv_data
)
75 CHECK_PACKET_SIZE(recv_data
, 8+4+4+1);
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(bgTypeId
>= MAX_BATTLEGROUND_TYPES
)
90 sLog
.outError("Battleground: invalid bgtype received. possible cheater? player guid %u",_player
->GetGUIDLow());
94 sLog
.outDebug( "WORLD: Recvd CMSG_BATTLEMASTER_JOIN Message from: " I64FMT
, guid
);
96 // can do this, since it's battleground, not arena
97 uint32 bgQueueTypeId
= BattleGroundMgr::BGQueueTypeId(bgTypeId
, 0);
99 // ignore if player is already in BG
100 if(_player
->InBattleGround())
103 Creature
*unit
= ObjectAccessor::GetCreature(*_player
, guid
);
107 if(!unit
->isBattleMaster()) // it's not battlemaster
110 // get bg instance or bg template if instance not found
111 BattleGround
* bg
= 0;
113 BattleGround
*bg
= sBattleGroundMgr
.GetBattleGround(instanceId
);
115 if(!bg
&& !(bg
= sBattleGroundMgr
.GetBattleGroundTemplate(bgTypeId
)))
117 sLog
.outError("Battleground: no available bg / template found");
121 // check queueing conditions
124 // check Deserter debuff
125 if( !_player
->CanJoinToBattleground() )
127 WorldPacket
data(SMSG_GROUP_JOINED_BATTLEGROUND
, 4);
128 data
<< (uint32
) 0xFFFFFFFE;
129 _player
->GetSession()->SendPacket(&data
);
132 // check if already in queue
133 if (_player
->GetBattleGroundQueueIndex(bgQueueTypeId
) < PLAYER_MAX_BATTLEGROUND_QUEUES
)
134 //player is already in this queue
136 // check if has free queue slots
137 if(!_player
->HasFreeBattleGroundQueueId())
142 grp
= _player
->GetGroup();
143 // no group found, error
146 uint32 err
= grp
->CanJoinBattleGroundQueue(bgTypeId
, bgQueueTypeId
, 0, bg
->GetMaxPlayersPerTeam(), false, 0);
147 if (err
!= BG_JOIN_ERR_OK
)
149 SendBattleGroundOrArenaJoinError(err
);
153 // if we're here, then the conditions to join a bg are met. We can proceed in joining.
155 // _player->GetGroup() was already checked, grp is already initialized
156 if(joinAsGroup
/* && _player->GetGroup()*/)
158 sLog
.outDebug("Battleground: the following players are joining as group:");
159 GroupQueueInfo
* ginfo
= sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].AddGroup(_player
, bgTypeId
, 0, false, 0);
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
167 // store entry point coords (same as leader entry point)
168 member
->SetBattleGroundEntryPoint(_player
->GetMapId(),_player
->GetPositionX(),_player
->GetPositionY(),_player
->GetPositionZ(),_player
->GetOrientation());
171 // send status packet (in queue)
172 sBattleGroundMgr
.BuildBattleGroundStatusPacket(&data
, bg
, member
->GetTeam(), queueSlot
, STATUS_WAIT_QUEUE
, 0, 0);
173 member
->GetSession()->SendPacket(&data
);
174 sBattleGroundMgr
.BuildGroupJoinedBattlegroundPacket(&data
, bgTypeId
);
175 member
->GetSession()->SendPacket(&data
);
176 sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].AddPlayer(member
, ginfo
);
177 sLog
.outDebug("Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId
,bgTypeId
,member
->GetGUIDLow(), member
->GetName());
179 sLog
.outDebug("Battleground: group end");
180 sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].Update(bgTypeId
, _player
->GetBattleGroundQueueIdFromLevel());
181 if(!ginfo
->IsInvitedToBGInstanceGUID
)
182 sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].AnnounceWorld(ginfo
, _player
->GetGUID(), true);
186 // already checked if queueSlot is valid, now just get it
187 uint32 queueSlot
= _player
->AddBattleGroundQueueId(bgQueueTypeId
);
188 // store entry point coords
189 _player
->SetBattleGroundEntryPoint(_player
->GetMapId(),_player
->GetPositionX(),_player
->GetPositionY(),_player
->GetPositionZ(),_player
->GetOrientation());
192 // send status packet (in queue)
193 sBattleGroundMgr
.BuildBattleGroundStatusPacket(&data
, bg
, _player
->GetTeam(), queueSlot
, STATUS_WAIT_QUEUE
, 0, 0);
196 GroupQueueInfo
* ginfo
= sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].AddGroup(_player
, bgTypeId
, 0, false, 0);
197 sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].AddPlayer(_player
, ginfo
);
198 sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].Update(bgTypeId
, _player
->GetBattleGroundQueueIdFromLevel());
199 if(!ginfo
->IsInvitedToBGInstanceGUID
)
200 sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].AnnounceWorld(ginfo
, _player
->GetGUID(), true);
201 sLog
.outDebug("Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId
,bgTypeId
,_player
->GetGUIDLow(), _player
->GetName());
205 void WorldSession::HandleBattleGroundPlayerPositionsOpcode( WorldPacket
& /*recv_data*/ )
208 sLog
.outDebug("WORLD: Recvd MSG_BATTLEGROUND_PLAYER_POSITIONS Message");
210 BattleGround
*bg
= _player
->GetBattleGround();
211 if(!bg
) // can't be received if player not in battleground
214 if(bg
->GetTypeID() == BATTLEGROUND_WS
)
219 Player
*ap
= objmgr
.GetPlayer(((BattleGroundWS
*)bg
)->GetAllianceFlagPickerGUID());
222 Player
*hp
= objmgr
.GetPlayer(((BattleGroundWS
*)bg
)->GetHordeFlagPickerGUID());
225 WorldPacket
data(MSG_BATTLEGROUND_PLAYER_POSITIONS
, (4+4+16*count1
+16*count2
));
226 data
<< count1
; // alliance flag holders count
227 /*for(uint8 i = 0; i < count1; i++)
229 data << uint64(0); // guid
230 data << (float)0; // x
231 data << (float)0; // y
233 data
<< count2
; // horde flag holders count
236 data
<< (uint64
)ap
->GetGUID();
237 data
<< (float)ap
->GetPositionX();
238 data
<< (float)ap
->GetPositionY();
242 data
<< (uint64
)hp
->GetGUID();
243 data
<< (float)hp
->GetPositionX();
244 data
<< (float)hp
->GetPositionY();
251 void WorldSession::HandleBattleGroundPVPlogdataOpcode( WorldPacket
& /*recv_data*/ )
253 sLog
.outDebug( "WORLD: Recvd MSG_PVP_LOG_DATA Message");
255 BattleGround
*bg
= _player
->GetBattleGround();
260 sBattleGroundMgr
.BuildPvpLogDataPacket(&data
, bg
);
263 sLog
.outDebug( "WORLD: Sent MSG_PVP_LOG_DATA Message");
266 void WorldSession::HandleBattleGroundListOpcode( WorldPacket
&recv_data
)
268 CHECK_PACKET_SIZE(recv_data
, 4);
270 sLog
.outDebug( "WORLD: Recvd CMSG_BATTLEFIELD_LIST Message");
273 recv_data
>> bgTypeId
; // id from DBC
275 if(bgTypeId
>= MAX_BATTLEGROUND_TYPES
)
277 sLog
.outError("Battleground: invalid bgtype received.");
281 BattlemasterListEntry
const* bl
= sBattlemasterListStore
.LookupEntry(bgTypeId
);
287 sBattleGroundMgr
.BuildBattleGroundListPacket(&data
, _player
->GetGUID(), _player
, bgTypeId
);
291 void WorldSession::HandleBattleGroundPlayerPortOpcode( WorldPacket
&recv_data
)
293 CHECK_PACKET_SIZE(recv_data
, 1+1+4+2+1);
295 sLog
.outDebug( "WORLD: Recvd CMSG_BATTLEFIELD_PORT Message");
297 uint8 type
; // arenatype if arena
298 uint8 unk2
; // unk, can be 0x0 (may be if was invited?) and 0x1
300 uint32 bgTypeId
; // type id from dbc
301 uint16 unk
; // 0x1F90 constant?
302 uint8 action
; // enter battle 0x1, leave queue 0x0
304 recv_data
>> type
>> unk2
>> bgTypeId
>> unk
>> action
;
306 if(bgTypeId
>= MAX_BATTLEGROUND_TYPES
)
308 sLog
.outError("Battleground: invalid bgtype received.");
309 // update battleground slots for the player to fix his UI and sent data.
310 // this is a HACK, I don't know why the client starts sending invalid packets in the first place.
311 // it usually happens with extremely high latency (if debugging / stepping in the code for example)
312 if(_player
->InBattleGroundQueue())
314 // update all queues, send invitation info if player is invited, queue info if queued
315 for (uint32 i
= 0; i
< PLAYER_MAX_BATTLEGROUND_QUEUES
; i
++)
317 uint32 queue_id
= _player
->GetBattleGroundQueueId(i
);
320 BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus
= sBattleGroundMgr
.m_BattleGroundQueues
[queue_id
].m_QueuedPlayers
[_player
->GetBattleGroundQueueIdFromLevel()].find(_player
->GetGUID());
321 // if the player is not in queue, contine
322 if(itrPlayerStatus
== sBattleGroundMgr
.m_BattleGroundQueues
[queue_id
].m_QueuedPlayers
[_player
->GetBattleGroundQueueIdFromLevel()].end())
325 // no group information, this should never happen
326 if(!itrPlayerStatus
->second
.GroupInfo
)
329 BattleGround
* bg
= NULL
;
331 // get possibly needed data from groupinfo
332 bgTypeId
= itrPlayerStatus
->second
.GroupInfo
->BgTypeId
;
333 uint8 arenatype
= itrPlayerStatus
->second
.GroupInfo
->ArenaType
;
334 uint8 israted
= itrPlayerStatus
->second
.GroupInfo
->IsRated
;
338 if(!itrPlayerStatus
->second
.GroupInfo
->IsInvitedToBGInstanceGUID
)
340 // not invited to bg, get template
341 bg
= sBattleGroundMgr
.GetBattleGroundTemplate(bgTypeId
);
342 status
= STATUS_WAIT_QUEUE
;
346 // get the bg we're invited to
347 BattleGround
* bg
= sBattleGroundMgr
.GetBattleGround(itrPlayerStatus
->second
.GroupInfo
->IsInvitedToBGInstanceGUID
);
348 status
= STATUS_WAIT_JOIN
;
351 // if bg not found, then continue
355 // don't invite if already in the instance
356 if(_player
->InBattleGround() && _player
->GetBattleGround() && _player
->GetBattleGround()->GetInstanceID() == bg
->GetInstanceID())
359 // re - invite player with proper data
361 sBattleGroundMgr
.BuildBattleGroundStatusPacket(&data
, bg
, itrPlayerStatus
->second
.GroupInfo
->Team
?itrPlayerStatus
->second
.GroupInfo
->Team
:_player
->GetTeam(), i
, status
, INVITE_ACCEPT_WAIT_TIME
, 0, arenatype
, israted
);
368 uint32 bgQueueTypeId
= 0;
369 // get the bg what we were invited to
370 BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus
;
371 bgQueueTypeId
= BattleGroundMgr::BGQueueTypeId(bgTypeId
,type
);
372 itrPlayerStatus
= sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].m_QueuedPlayers
[_player
->GetBattleGroundQueueIdFromLevel()].find(_player
->GetGUID());
374 if(itrPlayerStatus
== sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].m_QueuedPlayers
[_player
->GetBattleGroundQueueIdFromLevel()].end())
376 sLog
.outError("Battleground: itrplayerstatus not found.");
379 instanceId
= itrPlayerStatus
->second
.GroupInfo
->IsInvitedToBGInstanceGUID
;
381 // if action == 1, then instanceId is _required_
382 if(!instanceId
&& action
== 1)
384 sLog
.outError("Battleground: instance not found.");
388 BattleGround
*bg
= sBattleGroundMgr
.GetBattleGround(instanceId
);
390 // bg template might and must be used in case of leaving queue, when instance is not created yet
391 if(!bg
&& action
== 0)
392 bg
= sBattleGroundMgr
.GetBattleGroundTemplate(bgTypeId
);
396 sLog
.outError("Battleground: bg not found.");
400 bgTypeId
= bg
->GetTypeID();
402 if(_player
->InBattleGroundQueue())
404 uint32 queueSlot
= 0;
406 uint32 arenatype
= 0;
409 uint32 opponentsRating
= 0;
410 // get the team info from the queue
411 BattleGroundQueue::QueuedPlayersMap::iterator pitr
= sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].m_QueuedPlayers
[_player
->GetBattleGroundQueueIdFromLevel()].find(_player
->GetGUID());
412 if(pitr
!=sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].m_QueuedPlayers
[_player
->GetBattleGroundQueueIdFromLevel()].end()
413 && pitr
->second
.GroupInfo
)
415 team
= pitr
->second
.GroupInfo
->Team
;
416 arenatype
= pitr
->second
.GroupInfo
->ArenaType
;
417 israted
= pitr
->second
.GroupInfo
->IsRated
;
418 rating
= pitr
->second
.GroupInfo
->ArenaTeamRating
;
419 opponentsRating
= pitr
->second
.GroupInfo
->OpponentsTeamRating
;
423 sLog
.outError("Battleground: Invalid player queue info!");
429 case 1: // port to battleground
430 if(!_player
->IsInvitedForBattleGroundQueueType(bgQueueTypeId
))
432 // resurrect the player
433 if(!_player
->isAlive())
435 _player
->ResurrectPlayer(1.0f
);
436 _player
->SpawnCorpseBones();
438 // stop taxi flight at port
439 if(_player
->isInFlight())
441 _player
->GetMotionMaster()->MovementExpired();
442 _player
->m_taxi
.ClearTaxiDestinations();
444 _player
->RemoveFromGroup();
445 queueSlot
= _player
->GetBattleGroundQueueIndex(bgQueueTypeId
);
446 sBattleGroundMgr
.BuildBattleGroundStatusPacket(&data
, bg
, _player
->GetTeam(), queueSlot
, STATUS_IN_PROGRESS
, 0, bg
->GetStartTime());
447 _player
->GetSession()->SendPacket(&data
);
448 // remove battleground queue status from BGmgr
449 sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].RemovePlayer(_player
->GetGUID(), false);
450 // this is still needed here if battleground "jumping" shouldn't add deserter debuff
451 // also this required to prevent stuck at old battleground after SetBattleGroundId set to new
452 if( BattleGround
*currentBg
= _player
->GetBattleGround() )
453 currentBg
->RemovePlayerAtLeave(_player
->GetGUID(), false, true);
455 // set the destination instance id
456 _player
->SetBattleGroundId(bg
->GetInstanceID());
457 // set the destination team
458 _player
->SetBGTeam(team
);
459 // bg->HandleBeforeTeleportToBattleGround(_player);
460 sBattleGroundMgr
.SendToBattleGround(_player
, instanceId
);
461 // add only in HandleMoveWorldPortAck()
462 // bg->AddPlayer(_player,team);
463 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
);
465 case 0: // leave queue
466 queueSlot
= _player
->GetBattleGroundQueueIndex(bgQueueTypeId
);
468 if player leaves rated arena match before match start, it is counted as he played but he lost
472 ArenaTeam
* at
= objmgr
.GetArenaTeamById(team
);
475 sLog
.outDebug("UPDATING memberLost's personal arena rating for %u by opponents rating: %u, because he has left queue!", GUID_LOPART(_player
->GetGUID()), opponentsRating
);
476 at
->MemberLost(_player
, opponentsRating
);
480 _player
->RemoveBattleGroundQueueId(bgQueueTypeId
); // must be called this way, because if you move this call to queue->removeplayer, it causes bugs
481 sBattleGroundMgr
.BuildBattleGroundStatusPacket(&data
, bg
, _player
->GetTeam(), queueSlot
, STATUS_NONE
, 0, 0);
482 sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].RemovePlayer(_player
->GetGUID(), true);
483 // player left queue, we should update it, maybe now his group fits in
484 sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].Update(bgTypeId
,_player
->GetBattleGroundQueueIdFromLevel(),arenatype
,israted
,rating
);
486 sLog
.outDebug("Battleground: player %s (%u) left queue for bgtype %u, queue type %u.",_player
->GetName(),_player
->GetGUIDLow(),bg
->GetTypeID(),bgQueueTypeId
);
489 sLog
.outError("Battleground port: unknown action %u", action
);
495 void WorldSession::HandleBattleGroundLeaveOpcode( WorldPacket
& /*recv_data*/ )
497 //CHECK_PACKET_SIZE(recv_data, 1+1+4+2);
499 sLog
.outDebug( "WORLD: Recvd CMSG_LEAVE_BATTLEFIELD Message");
502 //uint32 bgTypeId; // id from DBC
505 //recv_data >> unk1 >> unk2 >> bgTypeId >> unk3; - no used currently
507 //if(bgTypeId >= MAX_BATTLEGROUND_TYPES) // cheating? but not important in this case
510 // not allow leave battleground in combat
511 if(_player
->isInCombat())
512 if(BattleGround
* bg
= _player
->GetBattleGround())
513 if(bg
->GetStatus() != STATUS_WAIT_LEAVE
)
516 _player
->LeaveBattleground();
519 void WorldSession::HandleBattlefieldStatusOpcode( WorldPacket
& /*recv_data*/ )
522 sLog
.outDebug( "WORLD: Battleground status" );
526 // TODO: we must put player back to battleground in case disconnect (< 5 minutes offline time) or teleport player on login(!) from battleground map to entry point
527 if(_player
->InBattleGround())
529 BattleGround
*bg
= _player
->GetBattleGround();
532 uint32 bgQueueTypeId
= BattleGroundMgr::BGQueueTypeId(bg
->GetTypeID(), bg
->GetArenaType());
533 uint32 queueSlot
= _player
->GetBattleGroundQueueIndex(bgQueueTypeId
);
534 if((bg
->GetStatus() <= STATUS_IN_PROGRESS
))
536 sBattleGroundMgr
.BuildBattleGroundStatusPacket(&data
, bg
, _player
->GetTeam(), queueSlot
, STATUS_IN_PROGRESS
, 0, bg
->GetStartTime());
539 for (uint32 i
= 0; i
< PLAYER_MAX_BATTLEGROUND_QUEUES
; i
++)
541 uint32 queue_id
= _player
->GetBattleGroundQueueId(i
); // battlegroundqueueid stores the type id, not the instance id, so this is definitely wrong
542 uint8 arenatype
= BattleGroundMgr::BGArenaType(queue_id
);
544 if (i
== queueSlot
|| !queue_id
) // we need to get the instance ids
546 BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus
= sBattleGroundMgr
.m_BattleGroundQueues
[queue_id
].m_QueuedPlayers
[_player
->GetBattleGroundQueueIdFromLevel()].find(_player
->GetGUID());
547 if(itrPlayerStatus
== sBattleGroundMgr
.m_BattleGroundQueues
[queue_id
].m_QueuedPlayers
[_player
->GetBattleGroundQueueIdFromLevel()].end())
549 if(itrPlayerStatus
->second
.GroupInfo
)
551 arenatype
= itrPlayerStatus
->second
.GroupInfo
->ArenaType
;
552 isRated
= itrPlayerStatus
->second
.GroupInfo
->IsRated
;
554 BattleGround
*bg2
= sBattleGroundMgr
.GetBattleGroundTemplate(BattleGroundMgr::BGTemplateId(queue_id
)); // try this
557 //in this call is small bug, this call should be filled by player's waiting time in queue
558 //this call nulls all timers for client :
559 sBattleGroundMgr
.BuildBattleGroundStatusPacket(&data
, bg2
, _player
->GetTeam(), i
, STATUS_WAIT_QUEUE
, 0, 0,arenatype
,isRated
);
567 // we should update all queues? .. i'm not sure if this code is correct
568 for (uint32 i
= 0; i
< PLAYER_MAX_BATTLEGROUND_QUEUES
; i
++)
570 uint32 queue_id
= _player
->GetBattleGroundQueueId(i
);
573 uint32 bgTypeId
= BattleGroundMgr::BGTemplateId(queue_id
);
574 uint8 arenatype
= BattleGroundMgr::BGArenaType(queue_id
);
576 BattleGround
*bg
= sBattleGroundMgr
.GetBattleGroundTemplate(bgTypeId
);
577 BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus
= sBattleGroundMgr
.m_BattleGroundQueues
[queue_id
].m_QueuedPlayers
[_player
->GetBattleGroundQueueIdFromLevel()].find(_player
->GetGUID());
578 if(itrPlayerStatus
== sBattleGroundMgr
.m_BattleGroundQueues
[queue_id
].m_QueuedPlayers
[_player
->GetBattleGroundQueueIdFromLevel()].end())
580 if(itrPlayerStatus
->second
.GroupInfo
)
582 arenatype
= itrPlayerStatus
->second
.GroupInfo
->ArenaType
;
583 isRated
= itrPlayerStatus
->second
.GroupInfo
->IsRated
;
587 sBattleGroundMgr
.BuildBattleGroundStatusPacket(&data
, bg
, _player
->GetTeam(), i
, STATUS_WAIT_QUEUE
, 0, 0, arenatype
, isRated
);
592 /* else // not sure if it needed...
594 for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++)
596 sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, NULL, _player->GetTeam(),i , STATUS_NONE, 0, 0);
602 void WorldSession::HandleAreaSpiritHealerQueryOpcode( WorldPacket
& recv_data
)
604 sLog
.outDebug("WORLD: CMSG_AREA_SPIRIT_HEALER_QUERY");
606 CHECK_PACKET_SIZE(recv_data
, 8);
608 BattleGround
*bg
= _player
->GetBattleGround();
615 Creature
*unit
= ObjectAccessor::GetCreature(*_player
, guid
);
619 if(!unit
->isSpiritService()) // it's not spirit service
622 sBattleGroundMgr
.SendAreaSpiritHealerQueryOpcode(_player
, bg
, guid
);
625 void WorldSession::HandleAreaSpiritHealerQueueOpcode( WorldPacket
& recv_data
)
627 sLog
.outDebug("WORLD: CMSG_AREA_SPIRIT_HEALER_QUEUE");
629 CHECK_PACKET_SIZE(recv_data
, 8);
631 BattleGround
*bg
= _player
->GetBattleGround();
638 Creature
*unit
= ObjectAccessor::GetCreature(*_player
, guid
);
642 if(!unit
->isSpiritService()) // it's not spirit service
645 bg
->AddPlayerToResurrectQueue(guid
, _player
->GetGUID());
648 void WorldSession::HandleBattleGroundArenaJoin( WorldPacket
& recv_data
)
650 CHECK_PACKET_SIZE(recv_data
, 8+1+1+1);
652 sLog
.outDebug("WORLD: CMSG_BATTLEMASTER_JOIN_ARENA");
655 // ignore if we already in BG or BG queue
656 if(_player
->InBattleGround())
659 uint64 guid
; // arena Battlemaster guid
660 uint8 type
; // 2v2, 3v3 or 5v5
661 uint8 asGroup
; // asGroup
662 uint8 isRated
; // isRated
665 recv_data
>> guid
>> type
>> asGroup
>> isRated
;
667 Creature
*unit
= ObjectAccessor::GetCreature(*_player
, guid
);
671 if(!unit
->isBattleMaster()) // it's not battle master
675 uint32 arenaRating
= 0;
680 arenatype
= ARENA_TYPE_2v2
;
683 arenatype
= ARENA_TYPE_3v3
;
686 arenatype
= ARENA_TYPE_5v5
;
689 sLog
.outError("Unknown arena type %u at HandleBattleGroundArenaJoin()", type
);
694 BattleGround
* bg
= NULL
;
695 if( !(bg
= sBattleGroundMgr
.GetBattleGroundTemplate(BATTLEGROUND_AA
)) )
697 sLog
.outError("Battleground: template bg (all arenas) not found");
701 uint8 bgTypeId
= bg
->GetTypeID();
702 uint32 bgQueueTypeId
= BattleGroundMgr::BGQueueTypeId(bgTypeId
, arenatype
);
704 // check queueing conditions
707 // check if already in queue
708 if (_player
->GetBattleGroundQueueIndex(bgQueueTypeId
) < PLAYER_MAX_BATTLEGROUND_QUEUES
)
709 //player is already in this queue
711 // check if has free queue slots
712 if(!_player
->HasFreeBattleGroundQueueId())
717 grp
= _player
->GetGroup();
718 // no group found, error
721 uint32 err
= grp
->CanJoinBattleGroundQueue(bgTypeId
, bgQueueTypeId
, arenatype
, arenatype
, (bool)isRated
, type
);
722 if (err
!= BG_JOIN_ERR_OK
)
724 SendBattleGroundOrArenaJoinError(err
);
733 ateamId
= _player
->GetArenaTeamId(type
);
734 // check real arenateam existence only here (if it was moved to group->CanJoin .. () then we would ahve to get it twice)
735 ArenaTeam
* at
= objmgr
.GetArenaTeamById(ateamId
);
738 _player
->GetSession()->SendNotInArenaTeamPacket(arenatype
);
741 // get the team rating for queueing
742 arenaRating
= at
->GetRating();
743 // the arenateam id must match for everyone in the group
744 // get the personal ratings for queueing
745 uint32 avg_pers_rating
= 0;
746 for(GroupReference
*itr
= grp
->GetFirstMember(); itr
!= NULL
; itr
= itr
->next())
748 Player
*member
= itr
->getSource();
750 // calc avg personal rating
751 avg_pers_rating
+= member
->GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1
+ (type
*6) + 5);
755 avg_pers_rating
/= arenatype
;
757 // 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
758 if(avg_pers_rating
+ 150 < arenaRating
)
759 arenaRating
= avg_pers_rating
;
764 GroupQueueInfo
* ginfo
= sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].AddGroup(_player
, bgTypeId
, arenatype
, isRated
, arenaRating
, ateamId
);
765 sLog
.outDebug("Battleground: arena join as group start");
767 sLog
.outDebug("Battleground: arena team id %u, leader %s queued with rating %u for type %u",_player
->GetArenaTeamId(type
),_player
->GetName(),arenaRating
,arenatype
);
768 for(GroupReference
*itr
= grp
->GetFirstMember(); itr
!= NULL
; itr
= itr
->next())
770 Player
*member
= itr
->getSource();
771 if(!member
) continue;
773 uint32 queueSlot
= member
->AddBattleGroundQueueId(bgQueueTypeId
);// add to queue
775 // store entry point coords (same as leader entry point)
776 member
->SetBattleGroundEntryPoint(_player
->GetMapId(),_player
->GetPositionX(),_player
->GetPositionY(),_player
->GetPositionZ(),_player
->GetOrientation());
779 // send status packet (in queue)
780 sBattleGroundMgr
.BuildBattleGroundStatusPacket(&data
, bg
, member
->GetTeam(), queueSlot
, STATUS_WAIT_QUEUE
, 0, 0, arenatype
, isRated
);
781 member
->GetSession()->SendPacket(&data
);
782 sBattleGroundMgr
.BuildGroupJoinedBattlegroundPacket(&data
, bgTypeId
);
783 member
->GetSession()->SendPacket(&data
);
784 sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].AddPlayer(member
, ginfo
);
785 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());
787 sLog
.outDebug("Battleground: arena join as group end");
788 sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].Update(bgTypeId
, _player
->GetBattleGroundQueueIdFromLevel(), arenatype
, isRated
, arenaRating
);
790 sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].AnnounceWorld(ginfo
, _player
->GetGUID(), true);
794 uint32 queueSlot
= _player
->AddBattleGroundQueueId(bgQueueTypeId
);
796 // store entry point coords
797 _player
->SetBattleGroundEntryPoint(_player
->GetMapId(),_player
->GetPositionX(),_player
->GetPositionY(),_player
->GetPositionZ(),_player
->GetOrientation());
800 // send status packet (in queue)
801 sBattleGroundMgr
.BuildBattleGroundStatusPacket(&data
, bg
, _player
->GetTeam(), queueSlot
, STATUS_WAIT_QUEUE
, 0, 0, arenatype
, isRated
);
803 GroupQueueInfo
* ginfo
= sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].AddGroup(_player
, bgTypeId
, arenatype
, isRated
, arenaRating
);
804 sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].AddPlayer(_player
, ginfo
);
805 sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].Update(bgTypeId
, _player
->GetBattleGroundQueueIdFromLevel(), arenatype
, isRated
, arenaRating
);
806 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());
810 void WorldSession::HandleBattleGroundReportAFK( WorldPacket
& recv_data
)
812 CHECK_PACKET_SIZE(recv_data
, 8);
815 recv_data
>> playerGuid
;
816 Player
*reportedPlayer
= objmgr
.GetPlayer(playerGuid
);
820 sLog
.outDebug("WorldSession::HandleBattleGroundReportAFK: player not found");
824 sLog
.outDebug("WorldSession::HandleBattleGroundReportAFK: %s reported %s", _player
->GetName(), reportedPlayer
->GetName());
826 reportedPlayer
->ReportedAfkBy(_player
);
829 void WorldSession::SendBattleGroundOrArenaJoinError(uint8 err
)
835 case BG_JOIN_ERR_OFFLINE_MEMBER
:
836 msg
= LANG_BG_GROUP_OFFLINE_MEMBER
;
838 case BG_JOIN_ERR_GROUP_TOO_MANY
:
839 msg
= LANG_BG_GROUP_TOO_LARGE
;
841 case BG_JOIN_ERR_MIXED_FACTION
:
842 msg
= LANG_BG_GROUP_MIXED_FACTION
;
844 case BG_JOIN_ERR_MIXED_LEVELS
:
845 msg
= LANG_BG_GROUP_MIXED_LEVELS
;
847 case BG_JOIN_ERR_GROUP_MEMBER_ALREADY_IN_QUEUE
:
848 msg
= LANG_BG_GROUP_MEMBER_ALREADY_IN_QUEUE
;
850 case BG_JOIN_ERR_GROUP_DESERTER
:
851 msg
= LANG_BG_GROUP_MEMBER_DESERTER
;
853 case BG_JOIN_ERR_ALL_QUEUES_USED
:
854 msg
= LANG_BG_GROUP_MEMBER_NO_FREE_QUEUE_SLOTS
;
856 case BG_JOIN_ERR_GROUP_NOT_ENOUGH
:
857 case BG_JOIN_ERR_MIXED_ARENATEAM
:
862 ChatHandler::FillMessageData(&data
, NULL
, CHAT_MSG_BG_SYSTEM_NEUTRAL
, LANG_UNIVERSAL
, NULL
, 0, GetMangosString(msg
), NULL
);