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 BattleGroundTypeId bgTypeId
= sBattleGroundMgr
.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
, BattleGroundTypeId 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(!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 Creature
*unit
= ObjectAccessor::GetCreature(*_player
, guid
);
109 if(!unit
->isBattleMaster()) // it's not battlemaster
112 // get bg instance or bg template if instance not found
113 BattleGround
* bg
= 0;
115 BattleGround
*bg
= sBattleGroundMgr
.GetBattleGround(instanceId
);
117 if(!bg
&& !(bg
= sBattleGroundMgr
.GetBattleGroundTemplate(bgTypeId
)))
119 sLog
.outError("Battleground: no available bg / template found");
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(bgTypeId
, bgQueueTypeId
, 0, bg
->GetMaxPlayersPerTeam(), false, 0);
149 if (err
!= BG_JOIN_ERR_OK
)
151 SendBattleGroundOrArenaJoinError(err
);
155 // if we're here, then the conditions to join a bg are met. We can proceed in joining.
157 // _player->GetGroup() was already checked, grp is already initialized
158 if(joinAsGroup
/* && _player->GetGroup()*/)
160 sLog
.outDebug("Battleground: the following players are joining as group:");
161 GroupQueueInfo
* ginfo
= sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].AddGroup(_player
, bgTypeId
, 0, false, 0);
162 for(GroupReference
*itr
= grp
->GetFirstMember(); itr
!= NULL
; itr
= itr
->next())
164 Player
*member
= itr
->getSource();
165 if(!member
) continue; // this should never happen
167 uint32 queueSlot
= member
->AddBattleGroundQueueId(bgQueueTypeId
); // add to queue
169 // store entry point coords (same as leader entry point)
170 member
->SetBattleGroundEntryPoint(_player
->GetMapId(),_player
->GetPositionX(),_player
->GetPositionY(),_player
->GetPositionZ(),_player
->GetOrientation());
173 // send status packet (in queue)
174 sBattleGroundMgr
.BuildBattleGroundStatusPacket(&data
, bg
, member
->GetTeam(), queueSlot
, STATUS_WAIT_QUEUE
, 0, 0);
175 member
->GetSession()->SendPacket(&data
);
176 sBattleGroundMgr
.BuildGroupJoinedBattlegroundPacket(&data
, bgTypeId
);
177 member
->GetSession()->SendPacket(&data
);
178 sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].AddPlayer(member
, ginfo
);
179 sLog
.outDebug("Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId
,bgTypeId
,member
->GetGUIDLow(), member
->GetName());
181 sLog
.outDebug("Battleground: group end");
182 sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].Update(bgTypeId
, _player
->GetBattleGroundQueueIdFromLevel(bgTypeId
));
183 if(!ginfo
->IsInvitedToBGInstanceGUID
)
184 sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].AnnounceWorld(ginfo
, _player
->GetGUID(), true);
188 // already checked if queueSlot is valid, now just get it
189 uint32 queueSlot
= _player
->AddBattleGroundQueueId(bgQueueTypeId
);
190 // store entry point coords
191 _player
->SetBattleGroundEntryPoint(_player
->GetMapId(),_player
->GetPositionX(),_player
->GetPositionY(),_player
->GetPositionZ(),_player
->GetOrientation());
194 // send status packet (in queue)
195 sBattleGroundMgr
.BuildBattleGroundStatusPacket(&data
, bg
, _player
->GetTeam(), queueSlot
, STATUS_WAIT_QUEUE
, 0, 0);
198 GroupQueueInfo
* ginfo
= sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].AddGroup(_player
, bgTypeId
, 0, false, 0);
199 sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].AddPlayer(_player
, ginfo
);
200 sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].Update(bgTypeId
, _player
->GetBattleGroundQueueIdFromLevel(bgTypeId
));
201 if(!ginfo
->IsInvitedToBGInstanceGUID
)
202 sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].AnnounceWorld(ginfo
, _player
->GetGUID(), true);
203 sLog
.outDebug("Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId
,bgTypeId
,_player
->GetGUIDLow(), _player
->GetName());
207 void WorldSession::HandleBattleGroundPlayerPositionsOpcode( WorldPacket
& /*recv_data*/ )
210 sLog
.outDebug("WORLD: Recvd MSG_BATTLEGROUND_PLAYER_POSITIONS Message");
212 BattleGround
*bg
= _player
->GetBattleGround();
213 if(!bg
) // can't be received if player not in battleground
216 if(bg
->GetTypeID() == BATTLEGROUND_WS
)
221 Player
*ap
= objmgr
.GetPlayer(((BattleGroundWS
*)bg
)->GetAllianceFlagPickerGUID());
224 Player
*hp
= objmgr
.GetPlayer(((BattleGroundWS
*)bg
)->GetHordeFlagPickerGUID());
227 WorldPacket
data(MSG_BATTLEGROUND_PLAYER_POSITIONS
, (4+4+16*count1
+16*count2
));
228 data
<< count1
; // alliance flag holders count
229 /*for(uint8 i = 0; i < count1; i++)
231 data << uint64(0); // guid
232 data << (float)0; // x
233 data << (float)0; // y
235 data
<< count2
; // horde flag holders count
238 data
<< (uint64
)ap
->GetGUID();
239 data
<< (float)ap
->GetPositionX();
240 data
<< (float)ap
->GetPositionY();
244 data
<< (uint64
)hp
->GetGUID();
245 data
<< (float)hp
->GetPositionX();
246 data
<< (float)hp
->GetPositionY();
253 void WorldSession::HandleBattleGroundPVPlogdataOpcode( WorldPacket
& /*recv_data*/ )
255 sLog
.outDebug( "WORLD: Recvd MSG_PVP_LOG_DATA Message");
257 BattleGround
*bg
= _player
->GetBattleGround();
262 sBattleGroundMgr
.BuildPvpLogDataPacket(&data
, bg
);
265 sLog
.outDebug( "WORLD: Sent MSG_PVP_LOG_DATA Message");
268 void WorldSession::HandleBattleGroundListOpcode( WorldPacket
&recv_data
)
270 CHECK_PACKET_SIZE(recv_data
, 4);
272 sLog
.outDebug( "WORLD: Recvd CMSG_BATTLEFIELD_LIST Message");
275 recv_data
>> bgTypeId
; // id from DBC
277 BattlemasterListEntry
const* bl
= sBattlemasterListStore
.LookupEntry(bgTypeId
);
280 sLog
.outError("Battleground: invalid bgtype received.");
285 sBattleGroundMgr
.BuildBattleGroundListPacket(&data
, _player
->GetGUID(), _player
, BattleGroundTypeId(bgTypeId
));
289 void WorldSession::HandleBattleGroundPlayerPortOpcode( WorldPacket
&recv_data
)
291 CHECK_PACKET_SIZE(recv_data
, 1+1+4+2+1);
293 sLog
.outDebug( "WORLD: Recvd CMSG_BATTLEFIELD_PORT Message");
295 uint8 type
; // arenatype if arena
296 uint8 unk2
; // unk, can be 0x0 (may be if was invited?) and 0x1
298 uint32 bgTypeId_
; // type id from dbc
299 uint16 unk
; // 0x1F90 constant?
300 uint8 action
; // enter battle 0x1, leave queue 0x0
302 recv_data
>> type
>> unk2
>> bgTypeId_
>> unk
>> action
;
304 if(!sBattlemasterListStore
.LookupEntry(bgTypeId_
))
306 sLog
.outError("Battleground: invalid bgtype (%u) received.",bgTypeId_
);
307 // update battleground slots for the player to fix his UI and sent data.
308 // this is a HACK, I don't know why the client starts sending invalid packets in the first place.
309 // it usually happens with extremely high latency (if debugging / stepping in the code for example)
310 if(_player
->InBattleGroundQueue())
312 // update all queues, send invitation info if player is invited, queue info if queued
313 for (uint32 i
= 0; i
< PLAYER_MAX_BATTLEGROUND_QUEUES
; i
++)
315 BattleGroundQueueTypeId bgQueueTypeId
= _player
->GetBattleGroundQueueTypeId(i
);
318 BattleGroundTypeId bgTypeId
= BattleGroundMgr::BGTemplateId(bgQueueTypeId
);
319 uint32 queue_id
= _player
->GetBattleGroundQueueIdFromLevel(bgTypeId
);
320 BattleGroundQueue::QueuedPlayersMap
& qpMap
= sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].m_QueuedPlayers
[queue_id
];
321 BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus
= qpMap
.find(_player
->GetGUID());
322 // if the player is not in queue, continue
323 if(itrPlayerStatus
== qpMap
.end())
326 // no group information, this should never happen
327 if(!itrPlayerStatus
->second
.GroupInfo
)
330 BattleGround
* bg
= NULL
;
332 // get possibly needed data from groupinfo
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 BattleGroundTypeId bgTypeId
= BattleGroundTypeId(bgTypeId_
);
370 BattleGroundQueueTypeId bgQueueTypeId
= BATTLEGROUND_QUEUE_NONE
;
371 // get the bg what we were invited to
372 bgQueueTypeId
= BattleGroundMgr::BGQueueTypeId(bgTypeId
,type
);
373 BattleGroundQueue::QueuedPlayersMap
& qpMap
= sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].m_QueuedPlayers
[_player
->GetBattleGroundQueueIdFromLevel(bgTypeId
)];
374 BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus
= qpMap
.find(_player
->GetGUID());
375 if(itrPlayerStatus
== qpMap
.end())
377 sLog
.outError("Battleground: itrplayerstatus not found.");
380 instanceId
= itrPlayerStatus
->second
.GroupInfo
->IsInvitedToBGInstanceGUID
;
382 // if action == 1, then instanceId is _required_
383 if(!instanceId
&& action
== 1)
385 sLog
.outError("Battleground: instance not found.");
389 BattleGround
*bg
= sBattleGroundMgr
.GetBattleGround(instanceId
);
391 // bg template might and must be used in case of leaving queue, when instance is not created yet
392 if(!bg
&& action
== 0)
393 bg
= sBattleGroundMgr
.GetBattleGroundTemplate(bgTypeId
);
397 sLog
.outError("Battleground: bg not found for type id %u.",bgTypeId
);
401 bgTypeId
= bg
->GetTypeID();
403 if(_player
->InBattleGroundQueue())
405 uint32 queueSlot
= 0;
407 uint32 arenatype
= 0;
410 uint32 opponentsRating
= 0;
411 // get the team info from the queue
413 BattleGroundQueue::QueuedPlayersMap
& qpMap2
= sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].m_QueuedPlayers
[_player
->GetBattleGroundQueueIdFromLevel(bgTypeId
)];
414 BattleGroundQueue::QueuedPlayersMap::iterator pitr
= qpMap2
.find(_player
->GetGUID());
415 if (pitr
!=qpMap2
.end() && pitr
->second
.GroupInfo
)
417 team
= pitr
->second
.GroupInfo
->Team
;
418 arenatype
= pitr
->second
.GroupInfo
->ArenaType
;
419 israted
= pitr
->second
.GroupInfo
->IsRated
;
420 rating
= pitr
->second
.GroupInfo
->ArenaTeamRating
;
421 opponentsRating
= pitr
->second
.GroupInfo
->OpponentsTeamRating
;
425 sLog
.outError("Battleground: Invalid player queue info!");
431 case 1: // port to battleground
432 if(!_player
->IsInvitedForBattleGroundQueueType(bgQueueTypeId
))
434 // resurrect the player
435 if(!_player
->isAlive())
437 _player
->ResurrectPlayer(1.0f
);
438 _player
->SpawnCorpseBones();
440 // stop taxi flight at port
441 if(_player
->isInFlight())
443 _player
->GetMotionMaster()->MovementExpired();
444 _player
->m_taxi
.ClearTaxiDestinations();
446 _player
->RemoveFromGroup();
447 queueSlot
= _player
->GetBattleGroundQueueIndex(bgQueueTypeId
);
448 sBattleGroundMgr
.BuildBattleGroundStatusPacket(&data
, bg
, _player
->GetTeam(), queueSlot
, STATUS_IN_PROGRESS
, 0, bg
->GetStartTime());
449 _player
->GetSession()->SendPacket(&data
);
450 // remove battleground queue status from BGmgr
451 sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].RemovePlayer(_player
->GetGUID(), false);
452 // this is still needed here if battleground "jumping" shouldn't add deserter debuff
453 // also this required to prevent stuck at old battleground after SetBattleGroundId set to new
454 if( BattleGround
*currentBg
= _player
->GetBattleGround() )
455 currentBg
->RemovePlayerAtLeave(_player
->GetGUID(), false, true);
457 // set the destination instance id
458 _player
->SetBattleGroundId(bg
->GetInstanceID());
459 // set the destination team
460 _player
->SetBGTeam(team
);
461 // bg->HandleBeforeTeleportToBattleGround(_player);
462 sBattleGroundMgr
.SendToBattleGround(_player
, instanceId
);
463 // add only in HandleMoveWorldPortAck()
464 // bg->AddPlayer(_player,team);
465 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
);
467 case 0: // leave queue
468 queueSlot
= _player
->GetBattleGroundQueueIndex(bgQueueTypeId
);
470 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
, _player
->GetTeam(), queueSlot
, STATUS_NONE
, 0, 0);
484 sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].RemovePlayer(_player
->GetGUID(), true);
485 // player left queue, we should update it, maybe now his group fits in
486 sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].Update(bgTypeId
,_player
->GetBattleGroundQueueIdFromLevel(bgTypeId
),arenatype
,israted
,rating
);
488 sLog
.outDebug("Battleground: player %s (%u) left queue for bgtype %u, queue type %u.",_player
->GetName(),_player
->GetGUIDLow(),bg
->GetTypeID(),bgQueueTypeId
);
491 sLog
.outError("Battleground port: unknown action %u", action
);
497 void WorldSession::HandleBattleGroundLeaveOpcode( WorldPacket
& /*recv_data*/ )
499 //CHECK_PACKET_SIZE(recv_data, 1+1+4+2);
501 sLog
.outDebug( "WORLD: Recvd CMSG_LEAVE_BATTLEFIELD Message");
504 //uint32 bgTypeId; // id from DBC
507 //recv_data >> unk1 >> unk2 >> bgTypeId >> unk3; - no used currently
509 //if(bgTypeId >= MAX_BATTLEGROUND_TYPES) // cheating? but not important in this case
512 // not allow leave battleground in combat
513 if(_player
->isInCombat())
514 if(BattleGround
* bg
= _player
->GetBattleGround())
515 if(bg
->GetStatus() != STATUS_WAIT_LEAVE
)
518 _player
->LeaveBattleground();
521 void WorldSession::HandleBattlefieldStatusOpcode( WorldPacket
& /*recv_data*/ )
524 sLog
.outDebug( "WORLD: Battleground status" );
528 // 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
529 if(_player
->InBattleGround())
531 BattleGround
*bg
= _player
->GetBattleGround();
534 BattleGroundQueueTypeId bgQueueTypeId_tmp
= BattleGroundMgr::BGQueueTypeId(bg
->GetTypeID(), bg
->GetArenaType());
535 uint32 queueSlot
= _player
->GetBattleGroundQueueIndex(bgQueueTypeId_tmp
);
536 if((bg
->GetStatus() <= STATUS_IN_PROGRESS
))
538 sBattleGroundMgr
.BuildBattleGroundStatusPacket(&data
, bg
, _player
->GetTeam(), queueSlot
, STATUS_IN_PROGRESS
, 0, bg
->GetStartTime());
541 for (uint32 i
= 0; i
< PLAYER_MAX_BATTLEGROUND_QUEUES
; i
++)
543 BattleGroundQueueTypeId bgQueueTypeId
= _player
->GetBattleGroundQueueTypeId(i
);
544 if (i
== queueSlot
|| !bgQueueTypeId
)
546 BattleGroundTypeId bgTypeId
= BattleGroundMgr::BGTemplateId(bgQueueTypeId
);
547 uint8 arenatype
= BattleGroundMgr::BGArenaType(bgQueueTypeId
);
549 uint32 queue_id
= _player
->GetBattleGroundQueueIdFromLevel(bgTypeId
);
550 BattleGroundQueue::QueuedPlayersMap
& qpMap
= sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].m_QueuedPlayers
[queue_id
];
551 BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus
= qpMap
.find(_player
->GetGUID());
552 if(itrPlayerStatus
== qpMap
.end())
554 if(itrPlayerStatus
->second
.GroupInfo
)
556 arenatype
= itrPlayerStatus
->second
.GroupInfo
->ArenaType
;
557 isRated
= itrPlayerStatus
->second
.GroupInfo
->IsRated
;
559 BattleGround
*bg2
= sBattleGroundMgr
.GetBattleGroundTemplate(bgTypeId
);
562 //in this call is small bug, this call should be filled by player's waiting time in queue
563 //this call nulls all timers for client :
564 sBattleGroundMgr
.BuildBattleGroundStatusPacket(&data
, bg2
, _player
->GetTeam(), i
, STATUS_WAIT_QUEUE
, 0, 0,arenatype
,isRated
);
572 // we should update all queues? .. i'm not sure if this code is correct
573 for (uint32 i
= 0; i
< PLAYER_MAX_BATTLEGROUND_QUEUES
; i
++)
575 BattleGroundQueueTypeId bgQueueTypeId
= _player
->GetBattleGroundQueueTypeId(i
);
578 BattleGroundTypeId bgTypeId
= BattleGroundMgr::BGTemplateId(bgQueueTypeId
);
579 uint8 arenatype
= BattleGroundMgr::BGArenaType(bgQueueTypeId
);
581 uint32 queue_id
= _player
->GetBattleGroundQueueIdFromLevel(bgTypeId
);
582 BattleGround
*bg
= sBattleGroundMgr
.GetBattleGroundTemplate(bgTypeId
);
583 BattleGroundQueue::QueuedPlayersMap
& qpMap
= sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].m_QueuedPlayers
[queue_id
];
584 BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus
= qpMap
.find(_player
->GetGUID());
585 if(itrPlayerStatus
== qpMap
.end())
587 if(itrPlayerStatus
->second
.GroupInfo
)
589 arenatype
= itrPlayerStatus
->second
.GroupInfo
->ArenaType
;
590 isRated
= itrPlayerStatus
->second
.GroupInfo
->IsRated
;
594 sBattleGroundMgr
.BuildBattleGroundStatusPacket(&data
, bg
, _player
->GetTeam(), i
, STATUS_WAIT_QUEUE
, 0, 0, arenatype
, isRated
);
599 /* else // not sure if it needed...
601 for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++)
603 sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, NULL, _player->GetTeam(),i , STATUS_NONE, 0, 0);
609 void WorldSession::HandleAreaSpiritHealerQueryOpcode( WorldPacket
& recv_data
)
611 sLog
.outDebug("WORLD: CMSG_AREA_SPIRIT_HEALER_QUERY");
613 CHECK_PACKET_SIZE(recv_data
, 8);
615 BattleGround
*bg
= _player
->GetBattleGround();
622 Creature
*unit
= ObjectAccessor::GetCreature(*_player
, guid
);
626 if(!unit
->isSpiritService()) // it's not spirit service
629 sBattleGroundMgr
.SendAreaSpiritHealerQueryOpcode(_player
, bg
, guid
);
632 void WorldSession::HandleAreaSpiritHealerQueueOpcode( WorldPacket
& recv_data
)
634 sLog
.outDebug("WORLD: CMSG_AREA_SPIRIT_HEALER_QUEUE");
636 CHECK_PACKET_SIZE(recv_data
, 8);
638 BattleGround
*bg
= _player
->GetBattleGround();
645 Creature
*unit
= ObjectAccessor::GetCreature(*_player
, guid
);
649 if(!unit
->isSpiritService()) // it's not spirit service
652 bg
->AddPlayerToResurrectQueue(guid
, _player
->GetGUID());
655 void WorldSession::HandleBattleGroundArenaJoin( WorldPacket
& recv_data
)
657 CHECK_PACKET_SIZE(recv_data
, 8+1+1+1);
659 sLog
.outDebug("WORLD: CMSG_BATTLEMASTER_JOIN_ARENA");
662 // ignore if we already in BG or BG queue
663 if(_player
->InBattleGround())
666 uint64 guid
; // arena Battlemaster guid
667 uint8 arenaslot
; // 2v2, 3v3 or 5v5
668 uint8 asGroup
; // asGroup
669 uint8 isRated
; // isRated
672 recv_data
>> guid
>> arenaslot
>> asGroup
>> isRated
;
674 Creature
*unit
= ObjectAccessor::GetCreature(*_player
, guid
);
678 if(!unit
->isBattleMaster()) // it's not battle master
682 uint32 arenaRating
= 0;
687 arenatype
= ARENA_TYPE_2v2
;
690 arenatype
= ARENA_TYPE_3v3
;
693 arenatype
= ARENA_TYPE_5v5
;
696 sLog
.outError("Unknown arena slot %u at HandleBattleGroundArenaJoin()", arenaslot
);
701 BattleGround
* bg
= NULL
;
702 if( !(bg
= sBattleGroundMgr
.GetBattleGroundTemplate(BATTLEGROUND_AA
)) )
704 sLog
.outError("Battleground: template bg (all arenas) not found");
708 BattleGroundTypeId bgTypeId
= bg
->GetTypeID();
709 BattleGroundQueueTypeId bgQueueTypeId
= BattleGroundMgr::BGQueueTypeId(bgTypeId
, arenatype
);
711 // check queueing conditions
714 // check if already in queue
715 if (_player
->GetBattleGroundQueueIndex(bgQueueTypeId
) < PLAYER_MAX_BATTLEGROUND_QUEUES
)
716 //player is already in this queue
718 // check if has free queue slots
719 if(!_player
->HasFreeBattleGroundQueueId())
724 grp
= _player
->GetGroup();
725 // no group found, error
728 uint32 err
= grp
->CanJoinBattleGroundQueue(bgTypeId
, bgQueueTypeId
, arenatype
, arenatype
, (bool)isRated
, arenaslot
);
729 if (err
!= BG_JOIN_ERR_OK
)
731 SendBattleGroundOrArenaJoinError(err
);
740 ateamId
= _player
->GetArenaTeamId(arenaslot
);
741 // check real arenateam existence only here (if it was moved to group->CanJoin .. () then we would ahve to get it twice)
742 ArenaTeam
* at
= objmgr
.GetArenaTeamById(ateamId
);
745 _player
->GetSession()->SendNotInArenaTeamPacket(arenatype
);
748 // get the team rating for queueing
749 arenaRating
= at
->GetRating();
750 // the arenateam id must match for everyone in the group
751 // get the personal ratings for queueing
752 uint32 avg_pers_rating
= 0;
753 for(GroupReference
*itr
= grp
->GetFirstMember(); itr
!= NULL
; itr
= itr
->next())
755 Player
*member
= itr
->getSource();
757 // calc avg personal rating
758 avg_pers_rating
+= member
->GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1
+ (arenaslot
*6) + 5);
762 avg_pers_rating
/= arenatype
;
764 // 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
765 if(avg_pers_rating
+ 150 < arenaRating
)
766 arenaRating
= avg_pers_rating
;
771 GroupQueueInfo
* ginfo
= sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].AddGroup(_player
, bgTypeId
, arenatype
, isRated
, arenaRating
, ateamId
);
772 sLog
.outDebug("Battleground: arena join as group start");
774 sLog
.outDebug("Battleground: arena team id %u, leader %s queued with rating %u for type %u",_player
->GetArenaTeamId(arenaslot
),_player
->GetName(),arenaRating
,arenatype
);
775 for(GroupReference
*itr
= grp
->GetFirstMember(); itr
!= NULL
; itr
= itr
->next())
777 Player
*member
= itr
->getSource();
778 if(!member
) continue;
780 uint32 queueSlot
= member
->AddBattleGroundQueueId(bgQueueTypeId
);// add to queue
782 // store entry point coords (same as leader entry point)
783 member
->SetBattleGroundEntryPoint(_player
->GetMapId(),_player
->GetPositionX(),_player
->GetPositionY(),_player
->GetPositionZ(),_player
->GetOrientation());
786 // send status packet (in queue)
787 sBattleGroundMgr
.BuildBattleGroundStatusPacket(&data
, bg
, member
->GetTeam(), queueSlot
, STATUS_WAIT_QUEUE
, 0, 0, arenatype
, isRated
);
788 member
->GetSession()->SendPacket(&data
);
789 sBattleGroundMgr
.BuildGroupJoinedBattlegroundPacket(&data
, bgTypeId
);
790 member
->GetSession()->SendPacket(&data
);
791 sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].AddPlayer(member
, ginfo
);
792 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());
794 sLog
.outDebug("Battleground: arena join as group end");
795 sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].Update(bgTypeId
, _player
->GetBattleGroundQueueIdFromLevel(bgTypeId
), arenatype
, isRated
, arenaRating
);
797 sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].AnnounceWorld(ginfo
, _player
->GetGUID(), true);
801 uint32 queueSlot
= _player
->AddBattleGroundQueueId(bgQueueTypeId
);
803 // store entry point coords
804 _player
->SetBattleGroundEntryPoint(_player
->GetMapId(),_player
->GetPositionX(),_player
->GetPositionY(),_player
->GetPositionZ(),_player
->GetOrientation());
807 // send status packet (in queue)
808 sBattleGroundMgr
.BuildBattleGroundStatusPacket(&data
, bg
, _player
->GetTeam(), queueSlot
, STATUS_WAIT_QUEUE
, 0, 0, arenatype
, isRated
);
810 GroupQueueInfo
* ginfo
= sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].AddGroup(_player
, bgTypeId
, arenatype
, isRated
, arenaRating
);
811 sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].AddPlayer(_player
, ginfo
);
812 sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].Update(bgTypeId
, _player
->GetBattleGroundQueueIdFromLevel(bgTypeId
), arenatype
, isRated
, arenaRating
);
813 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());
817 void WorldSession::HandleBattleGroundReportAFK( WorldPacket
& recv_data
)
819 CHECK_PACKET_SIZE(recv_data
, 8);
822 recv_data
>> playerGuid
;
823 Player
*reportedPlayer
= objmgr
.GetPlayer(playerGuid
);
827 sLog
.outDebug("WorldSession::HandleBattleGroundReportAFK: player not found");
831 sLog
.outDebug("WorldSession::HandleBattleGroundReportAFK: %s reported %s", _player
->GetName(), reportedPlayer
->GetName());
833 reportedPlayer
->ReportedAfkBy(_player
);
836 void WorldSession::SendBattleGroundOrArenaJoinError(uint8 err
)
842 case BG_JOIN_ERR_OFFLINE_MEMBER
:
843 msg
= LANG_BG_GROUP_OFFLINE_MEMBER
;
845 case BG_JOIN_ERR_GROUP_TOO_MANY
:
846 msg
= LANG_BG_GROUP_TOO_LARGE
;
848 case BG_JOIN_ERR_MIXED_FACTION
:
849 msg
= LANG_BG_GROUP_MIXED_FACTION
;
851 case BG_JOIN_ERR_MIXED_LEVELS
:
852 msg
= LANG_BG_GROUP_MIXED_LEVELS
;
854 case BG_JOIN_ERR_GROUP_MEMBER_ALREADY_IN_QUEUE
:
855 msg
= LANG_BG_GROUP_MEMBER_ALREADY_IN_QUEUE
;
857 case BG_JOIN_ERR_GROUP_DESERTER
:
858 msg
= LANG_BG_GROUP_MEMBER_DESERTER
;
860 case BG_JOIN_ERR_ALL_QUEUES_USED
:
861 msg
= LANG_BG_GROUP_MEMBER_NO_FREE_QUEUE_SLOTS
;
863 case BG_JOIN_ERR_GROUP_NOT_ENOUGH
:
864 case BG_JOIN_ERR_MIXED_ARENATEAM
:
869 ChatHandler::FillMessageData(&data
, NULL
, CHAT_MSG_BG_SYSTEM_NEUTRAL
, LANG_UNIVERSAL
, NULL
, 0, GetMangosString(msg
), NULL
);