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 "SharedDefines.h"
22 #include "BattleGroundMgr.h"
23 #include "BattleGroundAV.h"
24 #include "BattleGroundAB.h"
25 #include "BattleGroundEY.h"
26 #include "BattleGroundWS.h"
27 #include "BattleGroundNA.h"
28 #include "BattleGroundBE.h"
29 #include "BattleGroundAA.h"
30 #include "BattleGroundRL.h"
31 #include "BattleGroundSA.h"
32 #include "BattleGroundDS.h"
33 #include "BattleGroundRV.h"
34 #include "MapManager.h"
36 #include "MapInstanced.h"
37 #include "ObjectMgr.h"
38 #include "ProgressBar.h"
40 #include "ArenaTeam.h"
42 #include "WorldPacket.h"
43 #include "ProgressBar.h"
45 #include "Policies/SingletonImp.h"
47 INSTANTIATE_SINGLETON_1( BattleGroundMgr
);
49 /*********************************************************/
50 /*** BATTLEGROUND QUEUE SYSTEM ***/
51 /*********************************************************/
53 BattleGroundQueue::BattleGroundQueue()
55 //queues are empty, we don't have to call clear()
58 BattleGroundQueue::~BattleGroundQueue()
60 for (int i
= 0; i
< MAX_BATTLEGROUND_QUEUES
; i
++)
62 m_QueuedPlayers
[i
].clear();
63 for(QueuedGroupsList::iterator itr
= m_QueuedGroups
[i
].begin(); itr
!= m_QueuedGroups
[i
].end(); ++itr
)
67 m_QueuedGroups
[i
].clear();
71 // initialize eligible groups from the given source matching the given specifications
72 void BattleGroundQueue::EligibleGroups::Init(BattleGroundQueue::QueuedGroupsList
*source
, BattleGroundTypeId BgTypeId
, uint32 side
, uint32 MaxPlayers
, uint8 ArenaType
, bool IsRated
, uint32 MinRating
, uint32 MaxRating
, uint32 DisregardTime
, uint32 excludeTeam
)
74 // clear from prev initialization
76 BattleGroundQueue::QueuedGroupsList::iterator itr
, next
;
77 // iterate through the source
78 for(itr
= source
->begin(); itr
!= source
->end(); itr
= next
)
82 if( (*itr
)->BgTypeId
== BgTypeId
&& // bg type must match
83 (*itr
)->ArenaType
== ArenaType
&& // arena type must match
84 (*itr
)->IsRated
== IsRated
&& // israted must match
85 (*itr
)->IsInvitedToBGInstanceGUID
== 0 && // leave out already invited groups
86 (*itr
)->Team
== side
&& // match side
87 (*itr
)->Players
.size() <= MaxPlayers
&& // the group must fit in the bg
88 ( !excludeTeam
|| (*itr
)->ArenaTeamId
!= excludeTeam
) && // if excludeTeam is specified, leave out those arena team ids
89 ( !IsRated
|| (*itr
)->Players
.size() == MaxPlayers
) && // if rated, then pass only if the player count is exact NEEDS TESTING! (but now this should never happen)
90 ( (*itr
)->JoinTime
<= DisregardTime
// pass if disregard time is greater than join time
91 || (*itr
)->ArenaTeamRating
== 0 // pass if no rating info
92 || ( (*itr
)->ArenaTeamRating
>= MinRating
// pass if matches the rating range
93 && (*itr
)->ArenaTeamRating
<= MaxRating
) ) )
95 // the group matches the conditions
96 // insert it in order of groupsize, and join time
97 uint32 size
= (*itr
)->Players
.size();
98 uint32 jointime
= (*itr
)->JoinTime
;
99 bool inserted
= false;
101 for(std::list
<GroupQueueInfo
*>::iterator elig_itr
= begin(); elig_itr
!= end(); ++elig_itr
)
103 // if the next one's size is smaller, then insert
104 // also insert if the next one's size is equal, but it joined the queue later
105 if( ((*elig_itr
)->Players
.size()<size
) ||
106 ((*elig_itr
)->Players
.size() == size
&& (*elig_itr
)->JoinTime
> jointime
) )
108 insert(elig_itr
,(*itr
));
113 // if not inserted -> this is the smallest group -> push_back
122 // remove group from eligible groups
123 // used when building selection pools
124 void BattleGroundQueue::EligibleGroups::RemoveGroup(GroupQueueInfo
* ginfo
)
126 for(std::list
<GroupQueueInfo
*>::iterator itr
= begin(); itr
!= end(); ++itr
)
136 // selection pool initialization, used to clean up from prev selection
137 void BattleGroundQueue::SelectionPool::Init()
139 SelectedGroups
.clear();
144 // get the maximal group from the selection pool
145 // used when building the pool, and have to remove the largest
146 GroupQueueInfo
* BattleGroundQueue::SelectionPool::GetMaximalGroup()
148 if(SelectedGroups
.empty())
150 sLog
.outError("Getting max group when selection pool is empty, this should never happen.");
154 // actually select the max group if it's not set
155 if(MaxGroup
==0 && !SelectedGroups
.empty())
158 for(std::list
<GroupQueueInfo
*>::iterator itr
= SelectedGroups
.begin(); itr
!= SelectedGroups
.end(); ++itr
)
160 if(max_size
<(*itr
)->Players
.size())
163 max_size
= MaxGroup
->Players
.size();
170 // remove group info from selection pool
171 // used when building selection pools and have to remove maximal group
172 void BattleGroundQueue::SelectionPool::RemoveGroup(GroupQueueInfo
*ginfo
)
174 // uninitiate max group info if needed
175 if(MaxGroup
== ginfo
)
177 // find what to remove
178 for(std::list
<GroupQueueInfo
*>::iterator itr
= SelectedGroups
.begin(); itr
!= SelectedGroups
.end(); ++itr
)
182 SelectedGroups
.erase(itr
);
183 // decrease selected players count
184 PlayerCount
-= ginfo
->Players
.size();
190 // add group to selection
191 // used when building selection pools
192 void BattleGroundQueue::SelectionPool::AddGroup(GroupQueueInfo
* ginfo
)
194 SelectedGroups
.push_back(ginfo
);
195 // increase selected players count
196 PlayerCount
+=ginfo
->Players
.size();
197 if(!MaxGroup
|| ginfo
->Players
.size() > MaxGroup
->Players
.size())
199 // update max group info if needed
204 // add group to bg queue with the given leader and bg specifications
205 GroupQueueInfo
* BattleGroundQueue::AddGroup(Player
*leader
, BattleGroundTypeId BgTypeId
, uint8 ArenaType
, bool isRated
, uint32 arenaRating
, uint32 arenateamid
)
207 uint32 queue_id
= leader
->GetBattleGroundQueueIdFromLevel(BgTypeId
);
210 // cannot use the method like in addplayer, because that could modify an in-queue group's stats
211 // (e.g. leader leaving queue then joining as individual again)
212 GroupQueueInfo
* ginfo
= new GroupQueueInfo
;
213 ginfo
->BgTypeId
= BgTypeId
;
214 ginfo
->ArenaType
= ArenaType
;
215 ginfo
->ArenaTeamId
= arenateamid
;
216 ginfo
->IsRated
= isRated
;
217 ginfo
->IsInvitedToBGInstanceGUID
= 0; // maybe this should be modifiable by function arguments to enable selection of running instances?
218 ginfo
->JoinTime
= getMSTime();
219 ginfo
->Team
= leader
->GetTeam();
220 ginfo
->ArenaTeamRating
= arenaRating
;
221 ginfo
->OpponentsTeamRating
= 0; //initialize it to 0
223 ginfo
->Players
.clear();
225 m_QueuedGroups
[queue_id
].push_back(ginfo
);
227 // return ginfo, because it is needed to add players to this group info
231 void BattleGroundQueue::AddPlayer(Player
*plr
, GroupQueueInfo
*ginfo
)
233 uint32 queue_id
= plr
->GetBattleGroundQueueIdFromLevel(ginfo
->BgTypeId
);
235 //if player isn't in queue, he is added, if already is, then values are overwritten, no memory leak
236 PlayerQueueInfo
& info
= m_QueuedPlayers
[queue_id
][plr
->GetGUID()];
238 info
.LastInviteTime
= 0;
239 info
.LastOnlineTime
= getMSTime();
240 info
.GroupInfo
= ginfo
;
242 // add the pinfo to ginfo's list
243 ginfo
->Players
[plr
->GetGUID()] = &info
;
246 void BattleGroundQueue::RemovePlayer(const uint64
& guid
, bool decreaseInvitedCount
)
248 Player
*plr
= objmgr
.GetPlayer(guid
);
250 int32 queue_id
= 0; // signed for proper for-loop finish
251 QueuedPlayersMap::iterator itr
;
253 // mostly people with the highest levels are in battlegrounds, thats why
254 // we count from MAX_BATTLEGROUND_QUEUES to 0
255 for (queue_id
= MAX_BATTLEGROUND_QUEUES
-1; queue_id
>= 0; queue_id
--)
257 itr
= m_QueuedPlayers
[queue_id
].find(guid
);
258 if(itr
!= m_QueuedPlayers
[queue_id
].end())
262 // couldn't find the player in bg queue, return
263 if(itr
== m_QueuedPlayers
[queue_id
].end())
265 sLog
.outError("Battleground: couldn't find player to remove.");
269 GroupQueueInfo
* group
= itr
->second
.GroupInfo
;
271 QueuedGroupsList::iterator group_itr
= m_QueuedGroups
[queue_id
].begin();
272 for(; group_itr
!= m_QueuedGroups
[queue_id
].end(); ++group_itr
)
274 if(group
== *group_itr
)
278 // variables are set (what about leveling up when in queue????
279 // iterate through all queue_ids this isn't bad for us)
280 // remove player from group
281 // if only player there, remove group
283 // remove player queue info from group queue info
284 std::map
<uint64
, PlayerQueueInfo
*>::iterator pitr
= group
->Players
.find(guid
);
286 if(pitr
!= group
->Players
.end())
287 group
->Players
.erase(pitr
);
289 // check for iterator correctness
290 if (group_itr
!= m_QueuedGroups
[queue_id
].end() && itr
!= m_QueuedPlayers
[queue_id
].end())
292 // used when player left the queue, NOT used when porting to bg
293 if (decreaseInvitedCount
)
295 // if invited to bg, and should decrease invited count, then do it
296 if(group
->IsInvitedToBGInstanceGUID
)
298 BattleGround
* bg
= sBattleGroundMgr
.GetBattleGround(group
->IsInvitedToBGInstanceGUID
);
300 bg
->DecreaseInvitedCount(group
->Team
);
301 if (bg
&& !bg
->GetPlayersSize() && !bg
->GetInvitedCount(ALLIANCE
) && !bg
->GetInvitedCount(HORDE
))
303 // no more players on battleground, set delete it
307 // update the join queue, maybe now the player's group fits in a queue!
308 // not yet implemented (should store bgTypeId in group queue info?)
310 // remove player queue info
311 m_QueuedPlayers
[queue_id
].erase(itr
);
312 // remove group queue info if needed
314 //if we left BG queue(not porting) OR if arena team left queue for rated match
315 if((decreaseInvitedCount
&& !group
->ArenaType
) || (group
->ArenaType
&& group
->IsRated
&& group
->Players
.empty()))
316 AnnounceWorld(group
, guid
, false);
318 if(group
->Players
.empty())
320 m_QueuedGroups
[queue_id
].erase(group_itr
);
324 // group wasn't empty, so it wasn't deleted, and player have left a rated queue -> everyone from the group should leave too
325 // don't remove recursively if already invited to bg!
326 else if(!group
->IsInvitedToBGInstanceGUID
&& decreaseInvitedCount
&& group
->IsRated
)
328 // remove next player, this is recursive
329 // first send removal information
330 if(Player
*plr2
= objmgr
.GetPlayer(group
->Players
.begin()->first
))
332 BattleGround
* bg
= sBattleGroundMgr
.GetBattleGroundTemplate(group
->BgTypeId
);
333 BattleGroundQueueTypeId bgQueueTypeId
= BattleGroundMgr::BGQueueTypeId(group
->BgTypeId
,group
->ArenaType
);
334 uint32 queueSlot
= plr2
->GetBattleGroundQueueIndex(bgQueueTypeId
);
335 plr2
->RemoveBattleGroundQueueId(bgQueueTypeId
); // must be called this way, because if you move this call to queue->removeplayer, it causes bugs
337 sBattleGroundMgr
.BuildBattleGroundStatusPacket(&data
, bg
, plr2
->GetTeam(), queueSlot
, STATUS_NONE
, 0, 0);
338 plr2
->GetSession()->SendPacket(&data
);
340 // then actually delete, this may delete the group as well!
341 RemovePlayer(group
->Players
.begin()->first
,decreaseInvitedCount
);
346 void BattleGroundQueue::AnnounceWorld(GroupQueueInfo
*ginfo
, const uint64
& playerGUID
, bool isAddedToQueue
)
349 if(ginfo
->ArenaType
) //if Arena
351 if( sWorld
.getConfig(CONFIG_ARENA_QUEUE_ANNOUNCER_ENABLE
) && ginfo
->IsRated
)
353 BattleGround
* bg
= sBattleGroundMgr
.GetBattleGroundTemplate(ginfo
->BgTypeId
);
357 char const* bgName
= bg
->GetName();
359 sWorld
.SendWorldText(LANG_ARENA_QUEUE_ANNOUNCE_WORLD_JOIN
, bgName
, ginfo
->ArenaType
, ginfo
->ArenaType
, ginfo
->ArenaTeamRating
);
361 sWorld
.SendWorldText(LANG_ARENA_QUEUE_ANNOUNCE_WORLD_EXIT
, bgName
, ginfo
->ArenaType
, ginfo
->ArenaType
, ginfo
->ArenaTeamRating
);
366 if( sWorld
.getConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE
) )
368 Player
*plr
= objmgr
.GetPlayer(playerGUID
);
372 BattleGround
* bg
= sBattleGroundMgr
.GetBattleGroundTemplate(ginfo
->BgTypeId
);
376 uint32 queue_id
= plr
->GetBattleGroundQueueIdFromLevel(bg
->GetTypeID());
377 char const* bgName
= bg
->GetName();
379 uint32 q_min_level
= Player::GetMinLevelForBattleGroundQueueId(queue_id
, ginfo
->BgTypeId
);
380 uint32 q_max_level
= Player::GetMaxLevelForBattleGroundQueueId(queue_id
, ginfo
->BgTypeId
);
382 // replace hardcoded max level by player max level for nice output
383 if(q_max_level
> sWorld
.getConfig(CONFIG_MAX_PLAYER_LEVEL
))
384 q_max_level
= sWorld
.getConfig(CONFIG_MAX_PLAYER_LEVEL
);
386 int8 MinPlayers
= bg
->GetMinPlayersPerTeam();
391 BattleGroundTypeId bgTypeId
= ginfo
->BgTypeId
;
392 QueuedPlayersMap::iterator itr
;
393 for(itr
= m_QueuedPlayers
[queue_id
].begin(); itr
!= m_QueuedPlayers
[queue_id
].end(); ++itr
)
395 if(itr
->second
.GroupInfo
->BgTypeId
== bgTypeId
)
397 switch(itr
->second
.GroupInfo
->Team
)
409 // Show queue status to player only (when joining queue)
410 if(sWorld
.getConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_PLAYERONLY
))
412 ChatHandler(plr
).PSendSysMessage(LANG_BG_QUEUE_ANNOUNCE_SELF
,
413 bgName
, q_min_level
, q_max_level
, qAlliance
, MinPlayers
, qHorde
, MinPlayers
);
418 sWorld
.SendWorldText(LANG_BG_QUEUE_ANNOUNCE_WORLD
,
419 bgName
, q_min_level
, q_max_level
, qAlliance
, MinPlayers
, qHorde
, MinPlayers
);
425 bool BattleGroundQueue::InviteGroupToBG(GroupQueueInfo
* ginfo
, BattleGround
* bg
, uint32 side
)
427 // set side if needed
431 if(!ginfo
->IsInvitedToBGInstanceGUID
)
435 ginfo
->IsInvitedToBGInstanceGUID
= bg
->GetInstanceID();
436 BattleGroundQueueTypeId bgQueueTypeId
= BattleGroundMgr::BGQueueTypeId(bg
->GetTypeID(), bg
->GetArenaType());
437 // loop through the players
438 for(std::map
<uint64
,PlayerQueueInfo
*>::iterator itr
= ginfo
->Players
.begin(); itr
!= ginfo
->Players
.end(); ++itr
)
441 itr
->second
->InviteTime
= getMSTime();
442 itr
->second
->LastInviteTime
= getMSTime();
445 Player
* plr
= objmgr
.GetPlayer(itr
->first
);
446 // if offline, skip him
451 sBattleGroundMgr
.InvitePlayer(plr
, bg
->GetInstanceID(),ginfo
->Team
);
455 uint32 queueSlot
= plr
->GetBattleGroundQueueIndex(bgQueueTypeId
);
457 sLog
.outDebug("Battleground: invited plr %s (%u) to BG instance %u queueindex %u bgtype %u, I can't help it if they don't press the enter battle button.",plr
->GetName(),plr
->GetGUIDLow(),bg
->GetInstanceID(),queueSlot
,bg
->GetTypeID());
459 // send status packet
460 sBattleGroundMgr
.BuildBattleGroundStatusPacket(&data
, bg
, side
?side
:plr
->GetTeam(), queueSlot
, STATUS_WAIT_JOIN
, INVITE_ACCEPT_WAIT_TIME
, 0);
461 plr
->GetSession()->SendPacket(&data
);
469 // this function is responsible for the selection of queued groups when trying to create new battlegrounds
470 bool BattleGroundQueue::BuildSelectionPool(BattleGroundTypeId bgTypeId
, uint32 queue_id
, uint32 MinPlayers
, uint32 MaxPlayers
, SelectionPoolBuildMode mode
, uint8 ArenaType
, bool isRated
, uint32 MinRating
, uint32 MaxRating
, uint32 DisregardTime
, uint32 excludeTeam
)
475 case NORMAL_ALLIANCE
:
476 case ONESIDE_ALLIANCE_TEAM1
:
477 case ONESIDE_ALLIANCE_TEAM2
:
481 case ONESIDE_HORDE_TEAM1
:
482 case ONESIDE_HORDE_TEAM2
:
486 //unknown mode, return false
487 sLog
.outDebug("Battleground: unknown selection pool build mode, returning...");
491 // inititate the groups eligible to create the bg
492 m_EligibleGroups
.Init(&(m_QueuedGroups
[queue_id
]), bgTypeId
, side
, MaxPlayers
, ArenaType
, isRated
, MinRating
, MaxRating
, DisregardTime
, excludeTeam
);
493 // init the selected groups (clear)
494 m_SelectionPools
[mode
].Init();
495 while(!(m_EligibleGroups
.empty()))
497 sLog
.outDebug("m_EligibleGroups is not empty, continue building selection pool");
498 // in decreasing group size, add groups to join if they fit in the MaxPlayersPerTeam players
499 for(EligibleGroups::iterator itr
= m_EligibleGroups
.begin(); itr
!=m_EligibleGroups
.end(); ++itr
)
501 // get the maximal not yet checked group
502 GroupQueueInfo
* MaxGroup
= (*itr
);
503 // if it fits in the maxplayer size, add it
504 if( (m_SelectionPools
[mode
].GetPlayerCount() + MaxGroup
->Players
.size()) <= MaxPlayers
)
506 m_SelectionPools
[mode
].AddGroup(MaxGroup
);
509 if(m_SelectionPools
[mode
].GetPlayerCount()>=MinPlayers
)
511 // the selection pool is set, return
512 sLog
.outDebug("pool build succeeded, return true");
515 // if the selection pool's not set, then remove the group with the highest player count, and try again with the rest.
516 GroupQueueInfo
* MaxGroup
= m_SelectionPools
[mode
].GetMaximalGroup();
517 m_EligibleGroups
.RemoveGroup(MaxGroup
);
518 m_SelectionPools
[mode
].RemoveGroup(MaxGroup
);
520 // failed to build a selection pool matching the given values
524 // used to remove the Enter Battle window if the battle has already, but someone still has it
525 // (this can happen in arenas mainly, since the preparation is shorter than the timer for the bgqueueremove event
526 void BattleGroundQueue::BGEndedRemoveInvites(BattleGround
*bg
)
528 uint32 queue_id
= bg
->GetQueueId();
529 uint32 bgInstanceId
= bg
->GetInstanceID();
530 BattleGroundQueueTypeId bgQueueTypeId
= BattleGroundMgr::BGQueueTypeId(bg
->GetTypeID(), bg
->GetArenaType());
531 QueuedGroupsList::iterator itr
, next
;
532 for(itr
= m_QueuedGroups
[queue_id
].begin(); itr
!= m_QueuedGroups
[queue_id
].end(); itr
= next
)
534 // must do this way, because the groupinfo will be deleted when all playerinfos are removed
535 GroupQueueInfo
* ginfo
= (*itr
);
538 // if group was invited to this bg instance, then remove all references
539 if(ginfo
->IsInvitedToBGInstanceGUID
== bgInstanceId
)
541 // after removing this much playerinfos, the ginfo will be deleted, so we'll use a for loop
542 uint32 to_remove
= ginfo
->Players
.size();
543 uint32 team
= ginfo
->Team
;
544 for(int i
= 0; i
< to_remove
; ++i
)
546 // always remove the first one in the group
547 std::map
<uint64
, PlayerQueueInfo
* >::iterator itr2
= ginfo
->Players
.begin();
548 if(itr2
== ginfo
->Players
.end())
550 sLog
.outError("Empty Players in ginfo, this should never happen!");
555 Player
* plr
= objmgr
.GetPlayer(itr2
->first
);
558 sLog
.outError("Player offline when trying to remove from GroupQueueInfo, this should never happen.");
563 uint32 queueSlot
= plr
->GetBattleGroundQueueIndex(bgQueueTypeId
);
564 if (queueSlot
< PLAYER_MAX_BATTLEGROUND_QUEUES
) // player is in queue
566 plr
->RemoveBattleGroundQueueId(bgQueueTypeId
);
567 // remove player from queue, this might delete the ginfo as well! don't use that pointer after this!
568 RemovePlayer(itr2
->first
, true);
569 // this is probably unneeded, since this player was already invited -> does not fit when initing eligible groups
570 // but updateing the queue can't hurt
571 Update(bg
->GetTypeID(), bg
->GetQueueId());
572 // send info to client
574 sBattleGroundMgr
.BuildBattleGroundStatusPacket(&data
, bg
, team
, queueSlot
, STATUS_NONE
, 0, 0);
575 plr
->GetSession()->SendPacket(&data
);
583 this method is called when group is inserted, or player / group is removed from BG Queue - there is only one player's status changed, so we don't use while(true) cycles to invite whole queue
584 it must be called after fully adding the members of a group to ensure group joining
585 should be called after removeplayer functions in some cases
587 void BattleGroundQueue::Update(BattleGroundTypeId bgTypeId
, uint32 queue_id
, uint8 arenatype
, bool isRated
, uint32 arenaRating
)
589 if (queue_id
>= MAX_BATTLEGROUND_QUEUES
)
591 //this is error, that caused crashes (not in , but now it shouldn't)
592 sLog
.outError("BattleGroundQueue::Update() called for non existing queue type - this can cause crash, pls report problem, if this is the last line of error log before crash");
596 //if no players in queue ... do nothing
597 if (m_QueuedGroups
[queue_id
].empty())
600 BattleGroundQueueTypeId bgQueueTypeId
= BattleGroundMgr::BGQueueTypeId(bgTypeId
, arenatype
);
602 //battleground with free slot for player should be always the last in this queue
603 BGFreeSlotQueueType::iterator itr
, next
;
604 for (itr
= sBattleGroundMgr
.BGFreeSlotQueue
[bgTypeId
].begin(); itr
!= sBattleGroundMgr
.BGFreeSlotQueue
[bgTypeId
].end(); itr
= next
)
608 // battleground is running, so if:
609 // DO NOT allow queue manager to invite new player to running arena
610 if ((*itr
)->isBattleGround() && (*itr
)->GetTypeID() == bgTypeId
&& (*itr
)->GetQueueId() == queue_id
&& (*itr
)->GetStatus() > STATUS_WAIT_QUEUE
&& (*itr
)->GetStatus() < STATUS_WAIT_LEAVE
)
612 //we must check both teams
613 BattleGround
* bg
= *itr
; //we have to store battleground pointer here, because when battleground is full, it is removed from free queue (not yet implemented!!)
614 // and iterator is invalid
616 for(QueuedGroupsList::iterator itr
= m_QueuedGroups
[queue_id
].begin(); itr
!= m_QueuedGroups
[queue_id
].end(); ++itr
)
618 // did the group join for this bg type?
619 if((*itr
)->BgTypeId
!= bgTypeId
)
621 // if so, check if fits in
622 if(bg
->GetFreeSlotsForTeam((*itr
)->Team
) >= (*itr
)->Players
.size())
624 // if group fits in, invite it
625 InviteGroupToBG((*itr
),bg
,(*itr
)->Team
);
629 if (!bg
->HasFreeSlots())
631 //remove BG from BGFreeSlotQueue
632 bg
->RemoveFromBGFreeSlotQueue();
637 // finished iterating through the bgs with free slots, maybe we need to create a new bg
639 BattleGround
* bg_template
= sBattleGroundMgr
.GetBattleGroundTemplate(bgTypeId
);
642 sLog
.outError("Battleground: Update: bg template not found for %u", bgTypeId
);
646 // get the min. players per team, properly for larger arenas as well. (must have full teams for arena matches!)
647 uint32 MinPlayersPerTeam
= bg_template
->GetMinPlayersPerTeam();
648 uint32 MaxPlayersPerTeam
= bg_template
->GetMaxPlayersPerTeam();
649 if(bg_template
->isArena())
651 if(sBattleGroundMgr
.isArenaTesting())
653 MaxPlayersPerTeam
= 1;
654 MinPlayersPerTeam
= 1;
661 MaxPlayersPerTeam
= 2;
662 MinPlayersPerTeam
= 2;
665 MaxPlayersPerTeam
= 3;
666 MinPlayersPerTeam
= 3;
669 MaxPlayersPerTeam
= 5;
670 MinPlayersPerTeam
= 5;
678 if(sBattleGroundMgr
.isTesting())
680 MinPlayersPerTeam
= 1;
684 // found out the minimum and maximum ratings the newly added team should battle against
685 // arenaRating is the rating of the latest joined team
686 uint32 arenaMinRating
= (arenaRating
<= sBattleGroundMgr
.GetMaxRatingDifference()) ? 0 : arenaRating
- sBattleGroundMgr
.GetMaxRatingDifference();
687 // if no rating is specified, set maxrating to 0
688 uint32 arenaMaxRating
= (arenaRating
== 0)? 0 : arenaRating
+ sBattleGroundMgr
.GetMaxRatingDifference();
689 uint32 discardTime
= 0;
690 // if max rating difference is set and the time past since server startup is greater than the rating discard time
691 // (after what time the ratings aren't taken into account when making teams) then
692 // the discard time is current_time - time_to_discard, teams that joined after that, will have their ratings taken into account
693 // else leave the discard time on 0, this way all ratings will be discarded
694 if(sBattleGroundMgr
.GetMaxRatingDifference() && getMSTime() >= sBattleGroundMgr
.GetRatingDiscardTimer())
695 discardTime
= getMSTime() - sBattleGroundMgr
.GetRatingDiscardTimer();
697 // try to build the selection pools
698 bool bAllyOK
= BuildSelectionPool(bgTypeId
, queue_id
, MinPlayersPerTeam
, MaxPlayersPerTeam
, NORMAL_ALLIANCE
, arenatype
, isRated
, arenaMinRating
, arenaMaxRating
, discardTime
);
700 sLog
.outDebug("Battleground: ally pool succesfully build");
702 sLog
.outDebug("Battleground: ally pool wasn't created");
703 bool bHordeOK
= BuildSelectionPool(bgTypeId
, queue_id
, MinPlayersPerTeam
, MaxPlayersPerTeam
, NORMAL_HORDE
, arenatype
, isRated
, arenaMinRating
, arenaMaxRating
, discardTime
);
705 sLog
.outDebug("Battleground: horde pool succesfully built");
707 sLog
.outDebug("Battleground: horde pool wasn't created");
709 // if selection pools are ready, create the new bg
710 if ((bAllyOK
&& bHordeOK
) || ( sBattleGroundMgr
.isTesting() && (bAllyOK
|| bHordeOK
)))
712 BattleGround
* bg2
= 0;
713 // special handling for arenas
714 if(bg_template
->isArena())
716 // Find a random arena, that can be created
717 BattleGroundTypeId arenas
[] = {BATTLEGROUND_NA
, BATTLEGROUND_BE
, BATTLEGROUND_RL
};
718 uint32 arena_num
= urand(0,2);
719 if( !(bg2
= sBattleGroundMgr
.CreateNewBattleGround(arenas
[arena_num
%3])) &&
720 !(bg2
= sBattleGroundMgr
.CreateNewBattleGround(arenas
[(arena_num
+1)%3])) &&
721 !(bg2
= sBattleGroundMgr
.CreateNewBattleGround(arenas
[(arena_num
+2)%3])) )
723 sLog
.outError("Battleground: couldn't create any arena instance!");
727 // set the MaxPlayersPerTeam values based on arenatype
728 // setting the min player values isn't needed, since we won't be using that value later on.
729 if(sBattleGroundMgr
.isArenaTesting())
731 bg2
->SetMaxPlayersPerTeam(1);
732 bg2
->SetMaxPlayers(2);
739 bg2
->SetMaxPlayersPerTeam(2);
740 bg2
->SetMaxPlayers(4);
743 bg2
->SetMaxPlayersPerTeam(3);
744 bg2
->SetMaxPlayers(6);
747 bg2
->SetMaxPlayersPerTeam(5);
748 bg2
->SetMaxPlayers(10);
757 // create new battleground
758 bg2
= sBattleGroundMgr
.CreateNewBattleGround(bgTypeId
);
759 if( sWorld
.getConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE
) )
761 char const* bgName
= bg2
->GetName();
762 uint32 q_min_level
= Player::GetMinLevelForBattleGroundQueueId(queue_id
, bgTypeId
);
763 uint32 q_max_level
= Player::GetMaxLevelForBattleGroundQueueId(queue_id
, bgTypeId
);
764 if(q_max_level
> sWorld
.getConfig(CONFIG_MAX_PLAYER_LEVEL
))
765 q_max_level
= sWorld
.getConfig(CONFIG_MAX_PLAYER_LEVEL
);
766 sWorld
.SendWorldText(LANG_BG_STARTED_ANNOUNCE_WORLD
, bgName
, q_min_level
, q_max_level
);
772 sLog
.outError("Battleground: couldn't create bg %u",bgTypeId
);
776 // start the joining of the bg
777 bg2
->SetStatus(STATUS_WAIT_JOIN
);
778 bg2
->SetQueueId(queue_id
);
779 // initialize arena / rating info
780 bg2
->SetArenaType(arenatype
);
782 bg2
->SetRated(isRated
);
784 std::list
<GroupQueueInfo
* >::iterator itr
;
786 // invite groups from horde selection pool
787 for(itr
= m_SelectionPools
[NORMAL_HORDE
].SelectedGroups
.begin(); itr
!= m_SelectionPools
[NORMAL_HORDE
].SelectedGroups
.end(); ++itr
)
789 InviteGroupToBG((*itr
),bg2
,HORDE
);
792 // invite groups from ally selection pools
793 for(itr
= m_SelectionPools
[NORMAL_ALLIANCE
].SelectedGroups
.begin(); itr
!= m_SelectionPools
[NORMAL_ALLIANCE
].SelectedGroups
.end(); ++itr
)
795 InviteGroupToBG((*itr
),bg2
,ALLIANCE
);
800 std::list
<GroupQueueInfo
* >::iterator itr_alliance
= m_SelectionPools
[NORMAL_ALLIANCE
].SelectedGroups
.begin();
801 std::list
<GroupQueueInfo
* >::iterator itr_horde
= m_SelectionPools
[NORMAL_HORDE
].SelectedGroups
.begin();
802 (*itr_alliance
)->OpponentsTeamRating
= (*itr_horde
)->ArenaTeamRating
;
803 sLog
.outDebug("setting oposite teamrating for team %u to %u", (*itr_alliance
)->ArenaTeamId
, (*itr_alliance
)->OpponentsTeamRating
);
804 (*itr_horde
)->OpponentsTeamRating
= (*itr_alliance
)->ArenaTeamRating
;
805 sLog
.outDebug("setting oposite teamrating for team %u to %u", (*itr_horde
)->ArenaTeamId
, (*itr_horde
)->OpponentsTeamRating
);
808 // start the battleground
809 bg2
->StartBattleGround();
812 // there weren't enough players for a "normal" match
813 // if arena, enable horde versus horde or alliance versus alliance teams here
815 else if(bg_template
->isArena())
817 bool bOneSideHordeTeam1
= false, bOneSideHordeTeam2
= false;
818 bool bOneSideAllyTeam1
= false, bOneSideAllyTeam2
= false;
819 bOneSideHordeTeam1
= BuildSelectionPool(bgTypeId
, queue_id
,MaxPlayersPerTeam
,MaxPlayersPerTeam
,ONESIDE_HORDE_TEAM1
,arenatype
, isRated
, arenaMinRating
, arenaMaxRating
, discardTime
);
820 if(bOneSideHordeTeam1
)
822 // one team has been selected, find out if other can be selected too
823 std::list
<GroupQueueInfo
* >::iterator itr
;
824 // temporarily change the team side to enable building the next pool excluding the already selected groups
825 for(itr
= m_SelectionPools
[ONESIDE_HORDE_TEAM1
].SelectedGroups
.begin(); itr
!= m_SelectionPools
[ONESIDE_HORDE_TEAM1
].SelectedGroups
.end(); ++itr
)
826 (*itr
)->Team
=ALLIANCE
;
828 bOneSideHordeTeam2
= BuildSelectionPool(bgTypeId
, queue_id
,MaxPlayersPerTeam
,MaxPlayersPerTeam
,ONESIDE_HORDE_TEAM2
,arenatype
, isRated
, arenaMinRating
, arenaMaxRating
, discardTime
, (*(m_SelectionPools
[ONESIDE_HORDE_TEAM1
].SelectedGroups
.begin()))->ArenaTeamId
);
830 // change back the team to horde
831 for(itr
= m_SelectionPools
[ONESIDE_HORDE_TEAM1
].SelectedGroups
.begin(); itr
!= m_SelectionPools
[ONESIDE_HORDE_TEAM1
].SelectedGroups
.end(); ++itr
)
834 if(!bOneSideHordeTeam2
)
835 bOneSideHordeTeam1
= false;
837 if(!bOneSideHordeTeam1
)
839 // check for one sided ally
840 bOneSideAllyTeam1
= BuildSelectionPool(bgTypeId
, queue_id
,MaxPlayersPerTeam
,MaxPlayersPerTeam
,ONESIDE_ALLIANCE_TEAM1
,arenatype
, isRated
, arenaMinRating
, arenaMaxRating
, discardTime
);
841 if(bOneSideAllyTeam1
)
843 // one team has been selected, find out if other can be selected too
844 std::list
<GroupQueueInfo
* >::iterator itr
;
845 // temporarily change the team side to enable building the next pool excluding the already selected groups
846 for(itr
= m_SelectionPools
[ONESIDE_ALLIANCE_TEAM1
].SelectedGroups
.begin(); itr
!= m_SelectionPools
[ONESIDE_ALLIANCE_TEAM1
].SelectedGroups
.end(); ++itr
)
849 bOneSideAllyTeam2
= BuildSelectionPool(bgTypeId
, queue_id
,MaxPlayersPerTeam
,MaxPlayersPerTeam
,ONESIDE_ALLIANCE_TEAM2
,arenatype
, isRated
, arenaMinRating
, arenaMaxRating
, discardTime
,(*(m_SelectionPools
[ONESIDE_ALLIANCE_TEAM1
].SelectedGroups
.begin()))->ArenaTeamId
);
851 // change back the team to ally
852 for(itr
= m_SelectionPools
[ONESIDE_ALLIANCE_TEAM1
].SelectedGroups
.begin(); itr
!= m_SelectionPools
[ONESIDE_ALLIANCE_TEAM1
].SelectedGroups
.end(); ++itr
)
853 (*itr
)->Team
=ALLIANCE
;
856 if(!bOneSideAllyTeam2
)
857 bOneSideAllyTeam1
= false;
859 // 1-sided BuildSelectionPool() will work, because the MinPlayersPerTeam == MaxPlayersPerTeam in every arena!!!!
860 if( (bOneSideHordeTeam1
&& bOneSideHordeTeam2
) ||
861 (bOneSideAllyTeam1
&& bOneSideAllyTeam2
) )
863 // which side has enough players?
865 SelectionPoolBuildMode mode1
, mode2
;
866 // find out what pools are we using
867 if(bOneSideAllyTeam1
&& bOneSideAllyTeam2
)
870 mode1
= ONESIDE_ALLIANCE_TEAM1
;
871 mode2
= ONESIDE_ALLIANCE_TEAM2
;
876 mode1
= ONESIDE_HORDE_TEAM1
;
877 mode2
= ONESIDE_HORDE_TEAM2
;
880 // create random arena
881 BattleGroundTypeId arenas
[] = {BATTLEGROUND_NA
, BATTLEGROUND_BE
, BATTLEGROUND_RL
};
882 uint32 arena_num
= urand(0,2);
883 BattleGround
* bg2
= NULL
;
884 if( !(bg2
= sBattleGroundMgr
.CreateNewBattleGround(arenas
[arena_num
%3])) &&
885 !(bg2
= sBattleGroundMgr
.CreateNewBattleGround(arenas
[(arena_num
+1)%3])) &&
886 !(bg2
= sBattleGroundMgr
.CreateNewBattleGround(arenas
[(arena_num
+2)%3])) )
888 sLog
.outError("Could not create arena.");
892 sLog
.outDebug("Battleground: One-faction arena created.");
894 if(sBattleGroundMgr
.isArenaTesting())
896 bg2
->SetMaxPlayersPerTeam(1);
897 bg2
->SetMaxPlayers(2);
904 bg2
->SetMaxPlayersPerTeam(2);
905 bg2
->SetMaxPlayers(4);
908 bg2
->SetMaxPlayersPerTeam(3);
909 bg2
->SetMaxPlayers(6);
912 bg2
->SetMaxPlayersPerTeam(5);
913 bg2
->SetMaxPlayers(10);
920 bg2
->SetRated(isRated
);
922 // assigned team of the other group
927 other_side
= ALLIANCE
;
929 // start the joining of the bg
930 bg2
->SetStatus(STATUS_WAIT_JOIN
);
931 bg2
->SetQueueId(queue_id
);
932 // initialize arena / rating info
933 bg2
->SetArenaType(arenatype
);
935 std::list
<GroupQueueInfo
* >::iterator itr
;
937 // invite players from the first group as horde players (actually green team)
938 for(itr
= m_SelectionPools
[mode1
].SelectedGroups
.begin(); itr
!= m_SelectionPools
[mode1
].SelectedGroups
.end(); ++itr
)
940 InviteGroupToBG((*itr
),bg2
,HORDE
);
943 // invite players from the second group as ally players (actually gold team)
944 for(itr
= m_SelectionPools
[mode2
].SelectedGroups
.begin(); itr
!= m_SelectionPools
[mode2
].SelectedGroups
.end(); ++itr
)
946 InviteGroupToBG((*itr
),bg2
,ALLIANCE
);
951 std::list
<GroupQueueInfo
* >::iterator itr_alliance
= m_SelectionPools
[mode1
].SelectedGroups
.begin();
952 std::list
<GroupQueueInfo
* >::iterator itr_horde
= m_SelectionPools
[mode2
].SelectedGroups
.begin();
953 (*itr_alliance
)->OpponentsTeamRating
= (*itr_horde
)->ArenaTeamRating
;
954 (*itr_horde
)->OpponentsTeamRating
= (*itr_alliance
)->ArenaTeamRating
;
957 bg2
->StartBattleGround();
962 /*********************************************************/
963 /*** BATTLEGROUND QUEUE EVENTS ***/
964 /*********************************************************/
966 bool BGQueueInviteEvent::Execute(uint64
/*e_time*/, uint32
/*p_time*/)
968 Player
* plr
= objmgr
.GetPlayer( m_PlayerGuid
);
970 // player logged off (we should do nothing, he is correctly removed from queue in another procedure)
974 // Player can be in another BG queue and must be removed in normal way in any case
975 // // player is already in battleground ... do nothing (battleground queue status is deleted when player is teleported to BG)
976 // if (plr->GetBattleGroundId() > 0)
979 BattleGround
* bg
= sBattleGroundMgr
.GetBattleGround(m_BgInstanceGUID
);
983 BattleGroundQueueTypeId bgQueueTypeId
= BattleGroundMgr::BGQueueTypeId(bg
->GetTypeID(), bg
->GetArenaType());
984 BattleGroundTypeId bgTypeId
= BattleGroundMgr::BGTemplateId(bgQueueTypeId
);
985 uint32 queueSlot
= plr
->GetBattleGroundQueueIndex(bgQueueTypeId
);
986 if (queueSlot
< PLAYER_MAX_BATTLEGROUND_QUEUES
) // player is in queue
988 // check if player is invited to this bg ... this check must be here, because when player leaves queue and joins another, it would cause a problems
989 BattleGroundQueue::QueuedPlayersMap
const& qpMap
= sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].m_QueuedPlayers
[plr
->GetBattleGroundQueueIdFromLevel(bgTypeId
)];
990 BattleGroundQueue::QueuedPlayersMap::const_iterator qItr
= qpMap
.find(m_PlayerGuid
);
991 if (qItr
!= qpMap
.end() && qItr
->second
.GroupInfo
->IsInvitedToBGInstanceGUID
== m_BgInstanceGUID
)
994 sBattleGroundMgr
.BuildBattleGroundStatusPacket(&data
, bg
, qItr
->second
.GroupInfo
->Team
, queueSlot
, STATUS_WAIT_JOIN
, INVITE_ACCEPT_WAIT_TIME
/2, 0);
995 plr
->GetSession()->SendPacket(&data
);
998 return true; //event will be deleted
1001 void BGQueueInviteEvent::Abort(uint64
/*e_time*/)
1003 //this should not be called
1004 sLog
.outError("Battleground invite event ABORTED!");
1007 bool BGQueueRemoveEvent::Execute(uint64
/*e_time*/, uint32
/*p_time*/)
1009 Player
* plr
= objmgr
.GetPlayer( m_PlayerGuid
);
1011 // player logged off (we should do nothing, he is correctly removed from queue in another procedure)
1014 BattleGround
* bg
= sBattleGroundMgr
.GetBattleGround(m_BgInstanceGUID
);
1018 sLog
.outDebug("Battleground: removing player %u from bg queue for instance %u because of not pressing enter battle in time.",plr
->GetGUIDLow(),m_BgInstanceGUID
);
1020 BattleGroundQueueTypeId bgQueueTypeId
= BattleGroundMgr::BGQueueTypeId(bg
->GetTypeID(), bg
->GetArenaType());
1021 uint32 queueSlot
= plr
->GetBattleGroundQueueIndex(bgQueueTypeId
);
1022 if (queueSlot
< PLAYER_MAX_BATTLEGROUND_QUEUES
) // player is in queue
1024 // check if player is invited to this bg ... this check must be here, because when player leaves queue and joins another, it would cause a problems
1025 uint32 queue_id
=plr
->GetBattleGroundQueueIdFromLevel(bg
->GetTypeID());
1026 BattleGroundQueue::QueuedPlayersMap
& qpMap
= sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].m_QueuedPlayers
[queue_id
];
1027 BattleGroundQueue::QueuedPlayersMap::iterator qMapItr
= qpMap
.find(m_PlayerGuid
);
1028 if (qMapItr
!= qpMap
.end() && qMapItr
->second
.GroupInfo
&& qMapItr
->second
.GroupInfo
->IsInvitedToBGInstanceGUID
== m_BgInstanceGUID
)
1030 if (qMapItr
->second
.GroupInfo
->IsRated
)
1032 ArenaTeam
* at
= objmgr
.GetArenaTeamById(qMapItr
->second
.GroupInfo
->ArenaTeamId
);
1035 sLog
.outDebug("UPDATING memberLost's personal arena rating for %u by opponents rating: %u", GUID_LOPART(plr
->GetGUID()), qMapItr
->second
.GroupInfo
->OpponentsTeamRating
);
1036 at
->MemberLost(plr
, qMapItr
->second
.GroupInfo
->OpponentsTeamRating
);
1040 plr
->RemoveBattleGroundQueueId(bgQueueTypeId
);
1041 sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].RemovePlayer(m_PlayerGuid
, true);
1042 sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].Update(bg
->GetTypeID(),bg
->GetQueueId());
1044 sBattleGroundMgr
.BuildBattleGroundStatusPacket(&data
, bg
, m_PlayersTeam
, queueSlot
, STATUS_NONE
, 0, 0);
1045 plr
->GetSession()->SendPacket(&data
);
1049 sLog
.outDebug("Battleground: Player was already removed from queue");
1051 //event will be deleted
1055 void BGQueueRemoveEvent::Abort(uint64
/*e_time*/)
1057 //this should not be called
1058 sLog
.outError("Battleground remove event ABORTED!");
1061 /*********************************************************/
1062 /*** BATTLEGROUND MANAGER ***/
1063 /*********************************************************/
1065 BattleGroundMgr::BattleGroundMgr() : m_AutoDistributionTimeChecker(0), m_ArenaTesting(false)
1067 m_BattleGrounds
.clear();
1068 m_NextRatingDiscardUpdate
= sWorld
.getConfig(CONFIG_ARENA_RATING_DISCARD_TIMER
);
1072 BattleGroundMgr::~BattleGroundMgr()
1074 DeleteAlllBattleGrounds();
1077 void BattleGroundMgr::DeleteAlllBattleGrounds()
1079 for(BattleGroundSet::iterator itr
= m_BattleGrounds
.begin(); itr
!= m_BattleGrounds
.end();)
1081 BattleGround
* bg
= itr
->second
;
1082 m_BattleGrounds
.erase(itr
++);
1086 // destroy template battlegrounds that listed only in queues (other already terminated)
1087 for(uint32 bgTypeId
= 0; bgTypeId
< MAX_BATTLEGROUND_TYPE_ID
; ++bgTypeId
)
1089 // ~BattleGround call unregistring BG from queue
1090 while(!BGFreeSlotQueue
[bgTypeId
].empty())
1091 delete BGFreeSlotQueue
[bgTypeId
].front();
1095 // used to update running battlegrounds, and delete finished ones
1096 void BattleGroundMgr::Update(uint32 diff
)
1098 BattleGroundSet::iterator itr
, next
;
1099 for(itr
= m_BattleGrounds
.begin(); itr
!= m_BattleGrounds
.end(); itr
= next
)
1103 itr
->second
->Update(diff
);
1104 // use the SetDeleteThis variable
1105 // direct deletion caused crashes
1106 if(itr
->second
->m_SetDeleteThis
)
1108 BattleGround
* bg
= itr
->second
;
1109 m_BattleGrounds
.erase(itr
);
1113 // if rating difference counts, maybe force-update queues
1114 if(sWorld
.getConfig(CONFIG_ARENA_MAX_RATING_DIFFERENCE
))
1116 // it's time to force update
1117 if(m_NextRatingDiscardUpdate
< diff
)
1119 // forced update for level 70 rated arenas
1120 m_BattleGroundQueues
[BATTLEGROUND_QUEUE_2v2
].Update(BATTLEGROUND_AA
,6,ARENA_TYPE_2v2
,true,0);
1121 m_BattleGroundQueues
[BATTLEGROUND_QUEUE_3v3
].Update(BATTLEGROUND_AA
,6,ARENA_TYPE_3v3
,true,0);
1122 m_BattleGroundQueues
[BATTLEGROUND_QUEUE_5v5
].Update(BATTLEGROUND_AA
,6,ARENA_TYPE_5v5
,true,0);
1123 m_NextRatingDiscardUpdate
= sWorld
.getConfig(CONFIG_ARENA_RATING_DISCARD_TIMER
);
1126 m_NextRatingDiscardUpdate
-= diff
;
1128 if(sWorld
.getConfig(CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS
))
1130 if(m_AutoDistributionTimeChecker
< diff
)
1132 if(sWorld
.GetGameTime() > m_NextAutoDistributionTime
)
1134 DistributeArenaPoints();
1135 m_NextAutoDistributionTime
= sWorld
.GetGameTime() + BATTLEGROUND_ARENA_POINT_DISTRIBUTION_DAY
* sWorld
.getConfig(CONFIG_ARENA_AUTO_DISTRIBUTE_INTERVAL_DAYS
);
1136 CharacterDatabase
.PExecute("UPDATE saved_variables SET NextArenaPointDistributionTime = '"I64FMTD
"'", m_NextAutoDistributionTime
);
1138 m_AutoDistributionTimeChecker
= 600000; // check 10 minutes
1141 m_AutoDistributionTimeChecker
-= diff
;
1145 void BattleGroundMgr::BuildBattleGroundStatusPacket(WorldPacket
*data
, BattleGround
*bg
, uint32 team
, uint8 QueueSlot
, uint8 StatusID
, uint32 Time1
, uint32 Time2
, uint32 arenatype
, uint8 israted
)
1147 // we can be in 3 queues in same time...
1150 data
->Initialize(SMSG_BATTLEFIELD_STATUS
, 4*3);
1151 *data
<< uint32(QueueSlot
); // queue id (0...2)
1156 data
->Initialize(SMSG_BATTLEFIELD_STATUS
, (4+1+1+4+2+4+1+4+4+4));
1157 *data
<< uint32(QueueSlot
); // queue id (0...2) - player can be in 3 queues in time
1159 *data
<< uint64( uint64(arenatype
? arenatype
: bg
->GetArenaType()) | (uint64(0x0D) << 8) | (uint64(bg
->GetTypeID()) << 16) | (uint64(0x1F90) << 48) );
1160 *data
<< uint32(0); // unknown
1161 // alliance/horde for BG and skirmish/rated for Arenas
1162 *data
<< uint8(bg
->isArena() ? ( israted
? israted
: bg
->isRated() ) : bg
->GetTeamIndexByTeamId(team
));
1163 /* *data << uint8(arenatype ? arenatype : bg->GetArenaType()); // team type (0=BG, 2=2x2, 3=3x3, 5=5x5), for arenas // NOT PROPER VALUE IF ARENA ISN'T RUNNING YET!!!!
1164 switch(bg->GetTypeID()) // value depends on bg id
1166 case BATTLEGROUND_AV:
1169 case BATTLEGROUND_WS:
1172 case BATTLEGROUND_AB:
1175 case BATTLEGROUND_NA:
1178 case BATTLEGROUND_BE:
1181 case BATTLEGROUND_AA:
1184 case BATTLEGROUND_EY:
1187 case BATTLEGROUND_RL:
1190 case BATTLEGROUND_SA:
1193 case BATTLEGROUND_DS:
1196 case BATTLEGROUND_RV:
1204 if(bg->isArena() && (StatusID == STATUS_WAIT_QUEUE))
1205 *data << uint32(BATTLEGROUND_AA); // all arenas I don't think so.
1207 *data << uint32(bg->GetTypeID()); // BG id from DBC
1209 *data << uint16(0x1F90); // unk value 8080
1210 *data << uint32(bg->GetInstanceID()); // instance id
1212 if(bg->isBattleGround())
1213 *data << uint8(bg->GetTeamIndexByTeamId(team)); // team
1215 *data << uint8(israted?israted:bg->isRated()); // is rated battle
1217 *data
<< uint32(StatusID
); // status
1220 case STATUS_WAIT_QUEUE
: // status_in_queue
1221 *data
<< uint32(Time1
); // average wait time, milliseconds
1222 *data
<< uint32(Time2
); // time in queue, updated every minute?
1224 case STATUS_WAIT_JOIN
: // status_invite
1225 *data
<< uint32(bg
->GetMapId()); // map id
1226 *data
<< uint32(Time1
); // time to remove from queue, milliseconds
1228 case STATUS_IN_PROGRESS
: // status_in_progress
1229 *data
<< uint32(bg
->GetMapId()); // map id
1230 *data
<< uint32(Time1
); // 0 at bg start, 120000 after bg end, time to bg auto leave, milliseconds
1231 *data
<< uint32(Time2
); // time from bg start, milliseconds
1232 *data
<< uint8(0x1); // unk sometimes 0x0!
1235 sLog
.outError("Unknown BG status!");
1240 void BattleGroundMgr::BuildPvpLogDataPacket(WorldPacket
*data
, BattleGround
*bg
)
1242 uint8 type
= (bg
->isArena() ? 1 : 0);
1243 // last check on 3.0.3
1244 data
->Initialize(MSG_PVP_LOG_DATA
, (1+1+4+40*bg
->GetPlayerScoresSize()));
1245 *data
<< uint8(type
); // type (battleground=0/arena=1)
1249 // it seems this must be according to BG_WINNER_A/H and _NOT_ BG_TEAM_A/H
1250 for(int i
= 1; i
>= 0; --i
)
1252 *data
<< uint32(bg
->m_ArenaTeamRatingChanges
[i
]);
1253 *data
<< uint32(3999); // huge thanks for TOM_RUS for this!
1254 sLog
.outDebug("rating change: %d", bg
->m_ArenaTeamRatingChanges
[i
]);
1256 for(int i
= 1; i
>= 0; --i
)
1258 uint32 at_id
= bg
->m_ArenaTeamIds
[i
];
1259 ArenaTeam
* at
= objmgr
.GetArenaTeamById(at_id
);
1261 *data
<< at
->GetName();
1267 if(bg
->GetStatus() != STATUS_WAIT_LEAVE
)
1269 *data
<< uint8(0); // bg not ended
1273 *data
<< uint8(1); // bg ended
1274 *data
<< uint8(bg
->GetWinner()); // who win
1277 *data
<< (int32
)(bg
->GetPlayerScoresSize());
1279 for(std::map
<uint64
, BattleGroundScore
*>::const_iterator itr
= bg
->GetPlayerScoresBegin(); itr
!= bg
->GetPlayerScoresEnd(); ++itr
)
1281 *data
<< (uint64
)itr
->first
;
1282 *data
<< (int32
)itr
->second
->KillingBlows
;
1285 *data
<< (int32
)itr
->second
->HonorableKills
;
1286 *data
<< (int32
)itr
->second
->Deaths
;
1287 *data
<< (int32
)(itr
->second
->BonusHonor
);
1291 Player
*plr
= objmgr
.GetPlayer(itr
->first
);
1292 uint32 team
= bg
->GetPlayerTeam(itr
->first
);
1294 team
= plr
->GetTeam();
1295 if( ( bg
->GetWinner()==0 && team
== ALLIANCE
) || ( bg
->GetWinner()==1 && team
==HORDE
) )
1300 *data
<< (int32
)itr
->second
->DamageDone
; // damage done
1301 *data
<< (int32
)itr
->second
->HealingDone
; // healing done
1302 switch(bg
->GetTypeID()) // battleground specific things
1304 case BATTLEGROUND_AV
:
1305 *data
<< (uint32
)0x00000005; // count of next fields
1306 *data
<< (uint32
)((BattleGroundAVScore
*)itr
->second
)->GraveyardsAssaulted
; // GraveyardsAssaulted
1307 *data
<< (uint32
)((BattleGroundAVScore
*)itr
->second
)->GraveyardsDefended
; // GraveyardsDefended
1308 *data
<< (uint32
)((BattleGroundAVScore
*)itr
->second
)->TowersAssaulted
; // TowersAssaulted
1309 *data
<< (uint32
)((BattleGroundAVScore
*)itr
->second
)->TowersDefended
; // TowersDefended
1310 *data
<< (uint32
)((BattleGroundAVScore
*)itr
->second
)->MinesCaptured
; // MinesCaptured
1312 case BATTLEGROUND_WS
:
1313 *data
<< (uint32
)0x00000002; // count of next fields
1314 *data
<< (uint32
)((BattleGroundWGScore
*)itr
->second
)->FlagCaptures
; // flag captures
1315 *data
<< (uint32
)((BattleGroundWGScore
*)itr
->second
)->FlagReturns
; // flag returns
1317 case BATTLEGROUND_AB
:
1318 *data
<< (uint32
)0x00000002; // count of next fields
1319 *data
<< (uint32
)((BattleGroundABScore
*)itr
->second
)->BasesAssaulted
; // bases asssulted
1320 *data
<< (uint32
)((BattleGroundABScore
*)itr
->second
)->BasesDefended
; // bases defended
1322 case BATTLEGROUND_EY
:
1323 *data
<< (uint32
)0x00000001; // count of next fields
1324 *data
<< (uint32
)((BattleGroundEYScore
*)itr
->second
)->FlagCaptures
; // flag captures
1326 case BATTLEGROUND_NA
:
1327 case BATTLEGROUND_BE
:
1328 case BATTLEGROUND_AA
:
1329 case BATTLEGROUND_RL
:
1330 case BATTLEGROUND_SA
: // wotlk
1331 case BATTLEGROUND_DS
: // wotlk
1332 case BATTLEGROUND_RV
: // wotlk
1333 *data
<< (int32
)0; // 0
1336 sLog
.outDebug("Unhandled MSG_PVP_LOG_DATA for BG id %u", bg
->GetTypeID());
1343 void BattleGroundMgr::BuildGroupJoinedBattlegroundPacket(WorldPacket
*data
, BattleGroundTypeId bgTypeId
)
1346 0 - Your group has joined a battleground queue, but you are not eligible
1347 1 - Your group has joined the queue for AV
1348 2 - Your group has joined the queue for WS
1349 3 - Your group has joined the queue for AB
1350 4 - Your group has joined the queue for NA
1351 5 - Your group has joined the queue for BE Arena
1352 6 - Your group has joined the queue for All Arenas
1353 7 - Your group has joined the queue for EotS*/
1354 data
->Initialize(SMSG_GROUP_JOINED_BATTLEGROUND
, 4);
1355 *data
<< uint32(bgTypeId
);
1358 void BattleGroundMgr::BuildUpdateWorldStatePacket(WorldPacket
*data
, uint32 field
, uint32 value
)
1360 data
->Initialize(SMSG_UPDATE_WORLD_STATE
, 4+4);
1361 *data
<< uint32(field
);
1362 *data
<< uint32(value
);
1365 void BattleGroundMgr::BuildPlaySoundPacket(WorldPacket
*data
, uint32 soundid
)
1367 data
->Initialize(SMSG_PLAY_SOUND
, 4);
1368 *data
<< uint32(soundid
);
1371 void BattleGroundMgr::BuildPlayerLeftBattleGroundPacket(WorldPacket
*data
, Player
*plr
)
1373 data
->Initialize(SMSG_BATTLEGROUND_PLAYER_LEFT
, 8);
1374 *data
<< uint64(plr
->GetGUID());
1377 void BattleGroundMgr::BuildPlayerJoinedBattleGroundPacket(WorldPacket
*data
, Player
*plr
)
1379 data
->Initialize(SMSG_BATTLEGROUND_PLAYER_JOINED
, 8);
1380 *data
<< uint64(plr
->GetGUID());
1383 void BattleGroundMgr::InvitePlayer(Player
* plr
, uint32 bgInstanceGUID
, uint32 team
)
1385 // set invited player counters:
1386 BattleGround
* bg
= GetBattleGround(bgInstanceGUID
);
1389 bg
->IncreaseInvitedCount(team
);
1391 plr
->SetInviteForBattleGroundQueueType(BGQueueTypeId(bg
->GetTypeID(),bg
->GetArenaType()), bgInstanceGUID
);
1393 // set the arena teams for rated matches
1394 if(bg
->isArena() && bg
->isRated())
1396 switch(bg
->GetArenaType())
1398 case ARENA_TYPE_2v2
:
1399 bg
->SetArenaTeamIdForTeam(team
, plr
->GetArenaTeamId(0));
1401 case ARENA_TYPE_3v3
:
1402 bg
->SetArenaTeamIdForTeam(team
, plr
->GetArenaTeamId(1));
1404 case ARENA_TYPE_5v5
:
1405 bg
->SetArenaTeamIdForTeam(team
, plr
->GetArenaTeamId(2));
1412 // create invite events:
1413 //add events to player's counters ---- this is not good way - there should be something like global event processor, where we should add those events
1414 BGQueueInviteEvent
* inviteEvent
= new BGQueueInviteEvent(plr
->GetGUID(), bgInstanceGUID
);
1415 plr
->m_Events
.AddEvent(inviteEvent
, plr
->m_Events
.CalculateTime(INVITE_ACCEPT_WAIT_TIME
/2));
1416 BGQueueRemoveEvent
* removeEvent
= new BGQueueRemoveEvent(plr
->GetGUID(), bgInstanceGUID
, team
);
1417 plr
->m_Events
.AddEvent(removeEvent
, plr
->m_Events
.CalculateTime(INVITE_ACCEPT_WAIT_TIME
));
1420 BattleGround
* BattleGroundMgr::GetBattleGroundTemplate(BattleGroundTypeId bgTypeId
)
1422 return BGFreeSlotQueue
[bgTypeId
].empty() ? NULL
: BGFreeSlotQueue
[bgTypeId
].back();
1425 // create a new battleground that will really be used to play
1426 BattleGround
* BattleGroundMgr::CreateNewBattleGround(BattleGroundTypeId bgTypeId
)
1428 // get the template BG
1429 BattleGround
*bg_template
= GetBattleGroundTemplate(bgTypeId
);
1432 sLog
.outError("BattleGround: CreateNewBattleGround - bg template not found for %u", bgTypeId
);
1436 BattleGround
*bg
= NULL
;
1438 // create a copy of the BG template
1441 case BATTLEGROUND_AV
:
1442 bg
= new BattleGroundAV(*(BattleGroundAV
*)bg_template
);
1444 case BATTLEGROUND_WS
:
1445 bg
= new BattleGroundWS(*(BattleGroundWS
*)bg_template
);
1447 case BATTLEGROUND_AB
:
1448 bg
= new BattleGroundAB(*(BattleGroundAB
*)bg_template
);
1450 case BATTLEGROUND_NA
:
1451 bg
= new BattleGroundNA(*(BattleGroundNA
*)bg_template
);
1453 case BATTLEGROUND_BE
:
1454 bg
= new BattleGroundBE(*(BattleGroundBE
*)bg_template
);
1456 case BATTLEGROUND_AA
:
1457 bg
= new BattleGroundAA(*(BattleGroundAA
*)bg_template
);
1459 case BATTLEGROUND_EY
:
1460 bg
= new BattleGroundEY(*(BattleGroundEY
*)bg_template
);
1462 case BATTLEGROUND_RL
:
1463 bg
= new BattleGroundRL(*(BattleGroundRL
*)bg_template
);
1465 case BATTLEGROUND_SA
:
1466 bg
= new BattleGroundSA(*(BattleGroundSA
*)bg_template
);
1468 case BATTLEGROUND_DS
:
1469 bg
= new BattleGroundDS(*(BattleGroundDS
*)bg_template
);
1471 case BATTLEGROUND_RV
:
1472 bg
= new BattleGroundRV(*(BattleGroundRV
*)bg_template
);
1475 //error, but it is handled few lines above
1479 // generate a new instance id
1480 bg
->SetInstanceID(MapManager::Instance().GenerateInstanceId()); // set instance id
1482 // reset the new bg (set status to status_wait_queue from status_none)
1485 /* will be setup in BG::Update() when the first player is ported in
1486 if(!(bg->SetupBattleGround()))
1488 sLog.outError("BattleGround: CreateNewBattleGround: SetupBattleGround failed for bg %u", bgTypeId);
1494 // add BG to free slot queue
1495 bg
->AddToBGFreeSlotQueue();
1497 // add bg to update list
1498 AddBattleGround(bg
->GetInstanceID(), bg
);
1503 // used to create the BG templates
1504 uint32
BattleGroundMgr::CreateBattleGround(BattleGroundTypeId bgTypeId
, bool IsArena
, uint32 MinPlayersPerTeam
, uint32 MaxPlayersPerTeam
, uint32 LevelMin
, uint32 LevelMax
, char* BattleGroundName
, uint32 MapID
, float Team1StartLocX
, float Team1StartLocY
, float Team1StartLocZ
, float Team1StartLocO
, float Team2StartLocX
, float Team2StartLocY
, float Team2StartLocZ
, float Team2StartLocO
)
1507 BattleGround
*bg
= NULL
;
1510 case BATTLEGROUND_AV
: bg
= new BattleGroundAV
; break;
1511 case BATTLEGROUND_WS
: bg
= new BattleGroundWS
; break;
1512 case BATTLEGROUND_AB
: bg
= new BattleGroundAB
; break;
1513 case BATTLEGROUND_NA
: bg
= new BattleGroundNA
; break;
1514 case BATTLEGROUND_BE
: bg
= new BattleGroundBE
; break;
1515 case BATTLEGROUND_AA
: bg
= new BattleGroundAA
; break;
1516 case BATTLEGROUND_EY
: bg
= new BattleGroundEY
; break;
1517 case BATTLEGROUND_RL
: bg
= new BattleGroundRL
; break;
1518 case BATTLEGROUND_SA
: bg
= new BattleGroundSA
; break;
1519 case BATTLEGROUND_DS
: bg
= new BattleGroundDS
; break;
1520 case BATTLEGROUND_RV
: bg
= new BattleGroundRV
; break;
1521 default:bg
= new BattleGround
; break; // placeholder for non implemented BG
1524 bg
->SetMapId(MapID
);
1528 bg
->SetTypeID(bgTypeId
);
1529 bg
->SetInstanceID(0);
1530 bg
->SetArenaorBGType(IsArena
);
1531 bg
->SetMinPlayersPerTeam(MinPlayersPerTeam
);
1532 bg
->SetMaxPlayersPerTeam(MaxPlayersPerTeam
);
1533 bg
->SetMinPlayers(MinPlayersPerTeam
* 2);
1534 bg
->SetMaxPlayers(MaxPlayersPerTeam
* 2);
1535 bg
->SetName(BattleGroundName
);
1536 bg
->SetTeamStartLoc(ALLIANCE
, Team1StartLocX
, Team1StartLocY
, Team1StartLocZ
, Team1StartLocO
);
1537 bg
->SetTeamStartLoc(HORDE
, Team2StartLocX
, Team2StartLocY
, Team2StartLocZ
, Team2StartLocO
);
1538 bg
->SetLevelRange(LevelMin
, LevelMax
);
1540 //add BattleGround instance to FreeSlotQueue (.back() will return the template!)
1541 bg
->AddToBGFreeSlotQueue();
1543 // do NOT add to update list, since this is a template battleground!
1545 // return some not-null value, bgTypeId is good enough for me
1549 void BattleGroundMgr::CreateInitialBattleGrounds()
1553 uint32 MaxPlayersPerTeam
, MinPlayersPerTeam
, MinLvl
, MaxLvl
, start1
, start2
;
1554 BattlemasterListEntry
const *bl
;
1555 WorldSafeLocsEntry
const *start
;
1560 // 0 1 2 3 4 5 6 7 8
1561 QueryResult
*result
= WorldDatabase
.Query("SELECT id, MinPlayersPerTeam,MaxPlayersPerTeam,MinLvl,MaxLvl,AllianceStartLoc,AllianceStartO,HordeStartLoc,HordeStartO FROM battleground_template");
1570 sLog
.outErrorDb(">> Loaded 0 battlegrounds. DB table `battleground_template` is empty.");
1574 barGoLink
bar(result
->GetRowCount());
1578 Field
*fields
= result
->Fetch();
1581 uint32 bgTypeID_
= fields
[0].GetUInt32();
1583 // can be overwrite by values from DB
1584 bl
= sBattlemasterListStore
.LookupEntry(bgTypeID_
);
1587 sLog
.outError("Battleground ID %u not found in BattlemasterList.dbc. Battleground not created.", bgTypeID_
);
1591 BattleGroundTypeId bgTypeID
= BattleGroundTypeId(bgTypeID_
);
1593 IsArena
= (bl
->type
== TYPE_ARENA
);
1594 MinPlayersPerTeam
= fields
[1].GetUInt32();
1595 MaxPlayersPerTeam
= fields
[2].GetUInt32();
1596 MinLvl
= fields
[3].GetUInt32();
1597 MaxLvl
= fields
[4].GetUInt32();
1598 //check values from DB
1599 if( MaxPlayersPerTeam
== 0 || MinPlayersPerTeam
== 0 || MinPlayersPerTeam
> MaxPlayersPerTeam
)
1601 MaxPlayersPerTeam
= bl
->maxplayersperteam
;
1602 MinPlayersPerTeam
= bl
->maxplayersperteam
/ 2;
1604 if( MinLvl
== 0 || MaxLvl
== 0 || MinLvl
> MaxLvl
)
1606 MinLvl
= bl
->minlvl
;
1607 MaxLvl
= bl
->maxlvl
;
1610 start1
= fields
[5].GetUInt32();
1612 start
= sWorldSafeLocsStore
.LookupEntry(start1
);
1615 AStartLoc
[0] = start
->x
;
1616 AStartLoc
[1] = start
->y
;
1617 AStartLoc
[2] = start
->z
;
1618 AStartLoc
[3] = fields
[6].GetFloat();
1620 else if(bgTypeID
== BATTLEGROUND_AA
)
1625 AStartLoc
[3] = fields
[6].GetFloat();
1629 sLog
.outErrorDb("Table `battleground_template` for id %u have non-existed WorldSafeLocs.dbc id %u in field `AllianceStartLoc`. BG not created.", bgTypeID
, start1
);
1633 start2
= fields
[7].GetUInt32();
1635 start
= sWorldSafeLocsStore
.LookupEntry(start2
);
1638 HStartLoc
[0] = start
->x
;
1639 HStartLoc
[1] = start
->y
;
1640 HStartLoc
[2] = start
->z
;
1641 HStartLoc
[3] = fields
[8].GetFloat();
1643 else if(bgTypeID
== BATTLEGROUND_AA
)
1648 HStartLoc
[3] = fields
[8].GetFloat();
1652 sLog
.outErrorDb("Table `battleground_template` for id %u have non-existed WorldSafeLocs.dbc id %u in field `HordeStartLoc`. BG not created.", bgTypeID
, start2
);
1656 //sLog.outDetail("Creating battleground %s, %u-%u", bl->name[sWorld.GetDBClang()], MinLvl, MaxLvl);
1657 if(!CreateBattleGround(bgTypeID
, IsArena
, MinPlayersPerTeam
, MaxPlayersPerTeam
, MinLvl
, MaxLvl
, bl
->name
[sWorld
.GetDefaultDbcLocale()], bl
->mapid
[0], AStartLoc
[0], AStartLoc
[1], AStartLoc
[2], AStartLoc
[3], HStartLoc
[0], HStartLoc
[1], HStartLoc
[2], HStartLoc
[3]))
1661 } while (result
->NextRow());
1666 sLog
.outString( ">> Loaded %u battlegrounds", count
);
1669 void BattleGroundMgr::InitAutomaticArenaPointDistribution()
1671 if(sWorld
.getConfig(CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS
))
1673 sLog
.outDebug("Initializing Automatic Arena Point Distribution");
1674 QueryResult
* result
= CharacterDatabase
.Query("SELECT NextArenaPointDistributionTime FROM saved_variables");
1677 sLog
.outDebug("Battleground: Next arena point distribution time not found in SavedVariables, reseting it now.");
1678 m_NextAutoDistributionTime
= sWorld
.GetGameTime() + BATTLEGROUND_ARENA_POINT_DISTRIBUTION_DAY
* sWorld
.getConfig(CONFIG_ARENA_AUTO_DISTRIBUTE_INTERVAL_DAYS
);
1679 CharacterDatabase
.PExecute("INSERT INTO saved_variables (NextArenaPointDistributionTime) VALUES ('"I64FMTD
"')", m_NextAutoDistributionTime
);
1683 m_NextAutoDistributionTime
= (*result
)[0].GetUInt64();
1686 sLog
.outDebug("Automatic Arena Point Distribution initialized.");
1690 void BattleGroundMgr::DistributeArenaPoints()
1692 // used to distribute arena points based on last week's stats
1693 sWorld
.SendWorldText(LANG_DIST_ARENA_POINTS_START
);
1695 sWorld
.SendWorldText(LANG_DIST_ARENA_POINTS_ONLINE_START
);
1697 //temporary structure for storing maximum points to add values for all players
1698 std::map
<uint32
, uint32
> PlayerPoints
;
1700 //at first update all points for all team members
1701 for(ObjectMgr::ArenaTeamMap::iterator team_itr
= objmgr
.GetArenaTeamMapBegin(); team_itr
!= objmgr
.GetArenaTeamMapEnd(); ++team_itr
)
1703 if(ArenaTeam
* at
= team_itr
->second
)
1705 at
->UpdateArenaPointsHelper(PlayerPoints
);
1709 //cycle that gives points to all players
1710 for (std::map
<uint32
, uint32
>::iterator plr_itr
= PlayerPoints
.begin(); plr_itr
!= PlayerPoints
.end(); ++plr_itr
)
1712 //update to database
1713 CharacterDatabase
.PExecute("UPDATE characters SET arena_pending_points = '%u' WHERE `guid` = '%u'", plr_itr
->second
, plr_itr
->first
);
1714 //add points if player is online
1715 Player
* pl
= objmgr
.GetPlayer(plr_itr
->first
);
1717 pl
->ModifyArenaPoints(plr_itr
->second
);
1720 PlayerPoints
.clear();
1722 sWorld
.SendWorldText(LANG_DIST_ARENA_POINTS_ONLINE_END
);
1724 sWorld
.SendWorldText(LANG_DIST_ARENA_POINTS_TEAM_START
);
1725 for(ObjectMgr::ArenaTeamMap::iterator titr
= objmgr
.GetArenaTeamMapBegin(); titr
!= objmgr
.GetArenaTeamMapEnd(); ++titr
)
1727 if(ArenaTeam
* at
= titr
->second
)
1729 at
->FinishWeek(); // set played this week etc values to 0 in memory, too
1730 at
->SaveToDB(); // save changes
1731 at
->NotifyStatsChanged(); // notify the players of the changes
1735 sWorld
.SendWorldText(LANG_DIST_ARENA_POINTS_TEAM_END
);
1737 sWorld
.SendWorldText(LANG_DIST_ARENA_POINTS_END
);
1740 void BattleGroundMgr::BuildBattleGroundListPacket(WorldPacket
*data
, const uint64
& guid
, Player
* plr
, BattleGroundTypeId bgTypeId
)
1742 uint32 PlayerLevel
= 10;
1745 PlayerLevel
= plr
->getLevel();
1747 data
->Initialize(SMSG_BATTLEFIELD_LIST
);
1748 *data
<< uint64(guid
); // battlemaster guid
1749 *data
<< uint32(bgTypeId
); // battleground id
1750 if(bgTypeId
== BATTLEGROUND_AA
) // arena
1752 *data
<< uint8(5); // unk
1753 *data
<< uint32(0); // unk
1755 else // battleground
1757 *data
<< uint8(0x00); // unk
1759 size_t count_pos
= data
->wpos();
1761 *data
<< uint32(0x00); // number of bg instances
1763 for(std::map
<uint32
, BattleGround
*>::iterator itr
= m_BattleGrounds
.begin(); itr
!= m_BattleGrounds
.end(); ++itr
)
1765 if(itr
->second
->GetTypeID() == bgTypeId
&& (PlayerLevel
>= itr
->second
->GetMinLevel()) && (PlayerLevel
<= itr
->second
->GetMaxLevel()))
1767 *data
<< uint32(itr
->second
->GetInstanceID());
1771 data
->put
<uint32
>( count_pos
, count
);
1775 void BattleGroundMgr::SendToBattleGround(Player
*pl
, uint32 instanceId
)
1777 BattleGround
*bg
= GetBattleGround(instanceId
);
1780 uint32 mapid
= bg
->GetMapId();
1782 uint32 team
= pl
->GetBGTeam();
1784 team
= pl
->GetTeam();
1785 bg
->GetTeamStartLoc(team
, x
, y
, z
, O
);
1787 sLog
.outDetail("BATTLEGROUND: Sending %s to map %u, X %f, Y %f, Z %f, O %f", pl
->GetName(), mapid
, x
, y
, z
, O
);
1788 pl
->TeleportTo(mapid
, x
, y
, z
, O
);
1792 sLog
.outError("player %u trying to port to non-existent bg instance %u",pl
->GetGUIDLow(), instanceId
);
1796 void BattleGroundMgr::SendAreaSpiritHealerQueryOpcode(Player
*pl
, BattleGround
*bg
, const uint64
& guid
)
1798 WorldPacket
data(SMSG_AREA_SPIRIT_HEALER_TIME
, 12);
1799 uint32 time_
= 30000 - bg
->GetLastResurrectTime(); // resurrect every 30 seconds
1800 if(time_
== uint32(-1))
1802 data
<< guid
<< time_
;
1803 pl
->GetSession()->SendPacket(&data
);
1806 bool BattleGroundMgr::IsArenaType(BattleGroundTypeId bgTypeId
)
1808 return ( bgTypeId
== BATTLEGROUND_AA
||
1809 bgTypeId
== BATTLEGROUND_BE
||
1810 bgTypeId
== BATTLEGROUND_NA
||
1811 bgTypeId
== BATTLEGROUND_RL
);
1814 BattleGroundQueueTypeId
BattleGroundMgr::BGQueueTypeId(BattleGroundTypeId bgTypeId
, uint8 arenaType
)
1818 case BATTLEGROUND_WS
:
1819 return BATTLEGROUND_QUEUE_WS
;
1820 case BATTLEGROUND_AB
:
1821 return BATTLEGROUND_QUEUE_AB
;
1822 case BATTLEGROUND_AV
:
1823 return BATTLEGROUND_QUEUE_AV
;
1824 case BATTLEGROUND_EY
:
1825 return BATTLEGROUND_QUEUE_EY
;
1826 case BATTLEGROUND_SA
:
1827 return BATTLEGROUND_QUEUE_SA
;
1828 case BATTLEGROUND_AA
:
1829 case BATTLEGROUND_NA
:
1830 case BATTLEGROUND_RL
:
1831 case BATTLEGROUND_BE
:
1832 case BATTLEGROUND_DS
:
1833 case BATTLEGROUND_RV
:
1836 case ARENA_TYPE_2v2
:
1837 return BATTLEGROUND_QUEUE_2v2
;
1838 case ARENA_TYPE_3v3
:
1839 return BATTLEGROUND_QUEUE_3v3
;
1840 case ARENA_TYPE_5v5
:
1841 return BATTLEGROUND_QUEUE_5v5
;
1843 return BATTLEGROUND_QUEUE_NONE
;
1846 return BATTLEGROUND_QUEUE_NONE
;
1850 BattleGroundTypeId
BattleGroundMgr::BGTemplateId(BattleGroundQueueTypeId bgQueueTypeId
)
1852 switch(bgQueueTypeId
)
1854 case BATTLEGROUND_QUEUE_WS
:
1855 return BATTLEGROUND_WS
;
1856 case BATTLEGROUND_QUEUE_AB
:
1857 return BATTLEGROUND_AB
;
1858 case BATTLEGROUND_QUEUE_AV
:
1859 return BATTLEGROUND_AV
;
1860 case BATTLEGROUND_QUEUE_EY
:
1861 return BATTLEGROUND_EY
;
1862 case BATTLEGROUND_QUEUE_SA
:
1863 return BATTLEGROUND_SA
;
1864 case BATTLEGROUND_QUEUE_2v2
:
1865 case BATTLEGROUND_QUEUE_3v3
:
1866 case BATTLEGROUND_QUEUE_5v5
:
1867 return BATTLEGROUND_AA
;
1869 return BattleGroundTypeId(0); // used for unknown template (it existed and do nothing)
1873 uint8
BattleGroundMgr::BGArenaType(BattleGroundQueueTypeId bgQueueTypeId
)
1875 switch(bgQueueTypeId
)
1877 case BATTLEGROUND_QUEUE_2v2
:
1878 return ARENA_TYPE_2v2
;
1879 case BATTLEGROUND_QUEUE_3v3
:
1880 return ARENA_TYPE_3v3
;
1881 case BATTLEGROUND_QUEUE_5v5
:
1882 return ARENA_TYPE_5v5
;
1888 void BattleGroundMgr::ToggleTesting()
1890 m_Testing
= !m_Testing
;
1892 sWorld
.SendWorldText(LANG_DEBUG_BG_ON
);
1894 sWorld
.SendWorldText(LANG_DEBUG_BG_OFF
);
1897 void BattleGroundMgr::ToggleArenaTesting()
1899 m_ArenaTesting
= !m_ArenaTesting
;
1901 sWorld
.SendWorldText(LANG_DEBUG_ARENA_ON
);
1903 sWorld
.SendWorldText(LANG_DEBUG_ARENA_OFF
);
1906 uint32
BattleGroundMgr::GetMaxRatingDifference() const
1908 return sWorld
.getConfig(CONFIG_ARENA_MAX_RATING_DIFFERENCE
);
1911 uint32
BattleGroundMgr::GetRatingDiscardTimer() const
1913 return sWorld
.getConfig(CONFIG_ARENA_RATING_DISCARD_TIMER
);
1916 uint32
BattleGroundMgr::GetPrematureFinishTime() const
1918 return sWorld
.getConfig(CONFIG_BATTLEGROUND_PREMATURE_FINISH_TIMER
);
1921 void BattleGroundMgr::LoadBattleMastersEntry()
1923 mBattleMastersMap
.clear(); // need for reload case
1925 QueryResult
*result
= WorldDatabase
.Query( "SELECT entry,bg_template FROM battlemaster_entry" );
1935 sLog
.outString( ">> Loaded 0 battlemaster entries - table is empty!" );
1939 barGoLink
bar( result
->GetRowCount() );
1946 Field
*fields
= result
->Fetch();
1948 uint32 entry
= fields
[0].GetUInt32();
1949 uint32 bgTypeId
= fields
[1].GetUInt32();
1950 if (!sBattlemasterListStore
.LookupEntry(bgTypeId
))
1952 sLog
.outErrorDb("Table `battlemaster_entry` contain entry %u for not existed battleground type %u, ignored.",entry
,bgTypeId
);
1956 mBattleMastersMap
[entry
] = BattleGroundTypeId(bgTypeId
);
1958 } while( result
->NextRow() );
1963 sLog
.outString( ">> Loaded %u battlemaster entries", count
);