aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authormegamage <none@none>2009-02-27 12:13:59 -0600
committermegamage <none@none>2009-02-27 12:13:59 -0600
commit472f897b0a1475991f70fdc428387ce3d322d5ce (patch)
tree5ebd3cd397bfff6d18c9beeb8c5a1aa3be9fda29 /src
parentd3a69006675bb5317fab76584d5990b36c2fd5a5 (diff)
[7336] Implemented new BattleGroundQueue invitation system. Now it supports premade group versus premade group matches.
Added 2 new config options - InvitationType and PremadeGroupWaitForMatch - you can find more info in default config file. This patch can cause crashes. Author: Triply [7338] Little cleanup in battleground queues code. Author: ApoC --HG-- branch : trunk
Diffstat (limited to 'src')
-rw-r--r--src/game/AchievementMgr.cpp6
-rw-r--r--src/game/BattleGround.cpp71
-rw-r--r--src/game/BattleGround.h65
-rw-r--r--src/game/BattleGroundHandler.cpp23
-rw-r--r--src/game/BattleGroundMgr.cpp1161
-rw-r--r--src/game/BattleGroundMgr.h81
-rw-r--r--src/game/Group.cpp2
-rw-r--r--src/game/Player.cpp34
-rw-r--r--src/game/Player.h11
-rw-r--r--src/game/World.cpp57
-rw-r--r--src/game/World.h13
-rw-r--r--src/mangosd/mangosd.conf.dist.in131
-rw-r--r--src/shared/Common.h3
-rw-r--r--src/shared/revision_nr.h2
14 files changed, 818 insertions, 842 deletions
diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp
index 989c1be35d9..83a6302bcbd 100644
--- a/src/game/AchievementMgr.cpp
+++ b/src/game/AchievementMgr.cpp
@@ -573,11 +573,11 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
uint32 spellCount = 0;
for (PlayerSpellMap::const_iterator spellIter = GetPlayer()->GetSpellMap().begin();
spellIter != GetPlayer()->GetSpellMap().end();
- spellIter++)
+ ++spellIter)
{
for(SkillLineAbilityMap::const_iterator skillIter = spellmgr.GetBeginSkillLineAbilityMap(spellIter->first);
skillIter != spellmgr.GetEndSkillLineAbilityMap(spellIter->first);
- skillIter++)
+ ++skillIter)
{
if(skillIter->second->skillId == achievementCriteria->learn_skilline_spell.skillLine)
spellCount++;
@@ -605,7 +605,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
{
uint32 counter = 0;
const FactionStateList factionStateList = GetPlayer()->GetFactionStateList();
- for (FactionStateList::const_iterator iter = factionStateList.begin(); iter!= factionStateList.end(); iter++)
+ for (FactionStateList::const_iterator iter = factionStateList.begin(); iter!= factionStateList.end(); ++iter)
{
if(GetPlayer()->ReputationToRank(iter->second.Standing) >= REP_EXALTED)
++counter;
diff --git a/src/game/BattleGround.cpp b/src/game/BattleGround.cpp
index bdb78552102..0874210e1d4 100644
--- a/src/game/BattleGround.cpp
+++ b/src/game/BattleGround.cpp
@@ -41,7 +41,7 @@ BattleGround::BattleGround()
m_Status = 0;
m_EndTime = 0;
m_LastResurrectTime = 0;
- m_QueueId = MAX_BATTLEGROUND_QUEUES;
+ m_QueueId = QUEUE_ID_MAX_LEVEL_19;
m_InvitedAlliance = 0;
m_InvitedHorde = 0;
m_ArenaType = 0;
@@ -134,8 +134,6 @@ void BattleGround::Update(uint32 diff)
//BG is empty
return;
- WorldPacket data;
-
if(GetRemovedPlayersSize())
{
for(std::map<uint64, uint8>::iterator itr = m_RemovedPlayers.begin(); itr != m_RemovedPlayers.end(); ++itr)
@@ -143,16 +141,6 @@ void BattleGround::Update(uint32 diff)
Player *plr = objmgr.GetPlayer(itr->first);
switch(itr->second)
{
- //following code is handled by event:
- /*case 0:
- sBattleGroundMgr.m_BattleGroundQueues[GetTypeID()].RemovePlayer(itr->first);
- //RemovePlayerFromQueue(itr->first);
- if(plr)
- {
- sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, plr->GetTeam(), plr->GetBattleGroundQueueIndex(m_TypeID), STATUS_NONE, 0, 0);
- plr->GetSession()->SendPacket(&data);
- }
- break;*/
case 1: // currently in bg and was removed from bg
if(plr)
RemovePlayerAtLeave(itr->first, true, true);
@@ -895,7 +883,7 @@ void BattleGround::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPac
// this method is called when no players remains in battleground
void BattleGround::Reset()
{
- SetQueueId(MAX_BATTLEGROUND_QUEUES);
+ SetQueueId(QUEUE_ID_MAX_LEVEL_19);
SetWinner(WINNER_NONE);
SetStatus(STATUS_WAIT_QUEUE);
SetStartTime(0);
@@ -1030,7 +1018,7 @@ void BattleGround::AddOrSetPlayerToCorrectBgGroup(Player *plr, uint64 plr_guid,
void BattleGround::AddToBGFreeSlotQueue()
{
// make sure to add only once
- if(!m_InBGFreeSlotQueue)
+ if(!m_InBGFreeSlotQueue && isBattleGround())
{
sBattleGroundMgr.BGFreeSlotQueue[m_TypeID].push_front(this);
m_InBGFreeSlotQueue = true;
@@ -1054,61 +1042,12 @@ void BattleGround::RemoveFromBGFreeSlotQueue()
}
// get the number of free slots for team
-// works in similar way that HasFreeSlotsForTeam did, but this is needed for join as group
+// returns the number how many players can join battleground to MaxPlayersPerTeam
uint32 BattleGround::GetFreeSlotsForTeam(uint32 Team) const
{
//if BG is starting ... invite anyone
- if (GetStatus() == STATUS_WAIT_JOIN)
+ if (GetStatus() == STATUS_WAIT_JOIN || GetStatus() == STATUS_IN_PROGRESS)
return (GetInvitedCount(Team) < GetMaxPlayersPerTeam()) ? GetMaxPlayersPerTeam() - GetInvitedCount(Team) : 0;
- //if BG is already started .. do not allow to join too much players of one faction
- uint32 otherTeam;
- uint32 otherIn;
- if (Team == ALLIANCE)
- {
- otherTeam = GetInvitedCount(HORDE);
- otherIn = GetPlayersCountByTeam(HORDE);
- }
- else
- {
- otherTeam = GetInvitedCount(ALLIANCE);
- otherIn = GetPlayersCountByTeam(ALLIANCE);
- }
- if (GetStatus() == STATUS_IN_PROGRESS)
- {
- // difference based on ppl invited (not necessarily entered battle)
- // default: allow 0
- uint32 diff = 0;
- // allow join one person if the sides are equal (to fill up bg to minplayersperteam)
- if (otherTeam == GetInvitedCount(Team))
- diff = 1;
- // allow join more ppl if the other side has more players
- else if(otherTeam > GetInvitedCount(Team))
- diff = otherTeam - GetInvitedCount(Team);
-
- // difference based on max players per team (don't allow inviting more)
- uint32 diff2 = (GetInvitedCount(Team) < GetMaxPlayersPerTeam()) ? GetMaxPlayersPerTeam() - GetInvitedCount(Team) : 0;
-
- // difference based on players who already entered
- // default: allow 0
- uint32 diff3 = 0;
- // allow join one person if the sides are equal (to fill up bg minplayersperteam)
- if (otherIn == GetPlayersCountByTeam(Team))
- diff3 = 1;
- // allow join more ppl if the other side has more players
- else if (otherIn > GetPlayersCountByTeam(Team))
- diff3 = otherIn - GetPlayersCountByTeam(Team);
- // or other side has less than minPlayersPerTeam
- else if (GetInvitedCount(Team) <= GetMinPlayersPerTeam())
- diff3 = GetMinPlayersPerTeam() - GetInvitedCount(Team) + 1;
-
- // return the minimum of the 3 differences
-
- // min of diff and diff 2
- diff = diff < diff2 ? diff : diff2;
-
- // min of diff, diff2 and diff3
- return diff < diff3 ? diff : diff3 ;
- }
return 0;
}
diff --git a/src/game/BattleGround.h b/src/game/BattleGround.h
index fd93746ebfc..4e1c2a197c0 100644
--- a/src/game/BattleGround.h
+++ b/src/game/BattleGround.h
@@ -89,6 +89,7 @@ enum BattleGroundTimeIntervals
{
RESURRECTION_INTERVAL = 30000, // ms
REMIND_INTERVAL = 30000, // ms
+ INVITATION_REMIND_TIME = 60000, // ms
INVITE_ACCEPT_WAIT_TIME = 80000, // ms
TIME_TO_AUTOREMOVE = 120000, // ms
MAX_OFFLINE_TIME = 300000, // ms
@@ -138,16 +139,30 @@ struct BattleGroundObjectInfo
// handle the queue types and bg types separately to enable joining queue for different sized arenas at the same time
enum BattleGroundQueueTypeId
{
- BATTLEGROUND_QUEUE_NONE = 0,
- BATTLEGROUND_QUEUE_AV = 1,
- BATTLEGROUND_QUEUE_WS = 2,
- BATTLEGROUND_QUEUE_AB = 3,
- BATTLEGROUND_QUEUE_EY = 4,
- BATTLEGROUND_QUEUE_SA = 5,
- BATTLEGROUND_QUEUE_2v2 = 6,
- BATTLEGROUND_QUEUE_3v3 = 7,
- BATTLEGROUND_QUEUE_5v5 = 8,
+ BATTLEGROUND_QUEUE_NONE = 0,
+ BATTLEGROUND_QUEUE_AV = 1,
+ BATTLEGROUND_QUEUE_WS = 2,
+ BATTLEGROUND_QUEUE_AB = 3,
+ BATTLEGROUND_QUEUE_EY = 4,
+ BATTLEGROUND_QUEUE_SA = 5,
+ BATTLEGROUND_QUEUE_2v2 = 6,
+ BATTLEGROUND_QUEUE_3v3 = 7,
+ BATTLEGROUND_QUEUE_5v5 = 8
};
+#define MAX_BATTLEGROUND_QUEUE_TYPES 9
+
+enum BGQueueIdBasedOnLevel // queue_id for level ranges
+{
+ QUEUE_ID_MAX_LEVEL_19 = 0,
+ QUEUE_ID_MAX_LEVEL_29 = 1,
+ QUEUE_ID_MAX_LEVEL_39 = 2,
+ QUEUE_ID_MAX_LEVEL_49 = 3,
+ QUEUE_ID_MAX_LEVEL_59 = 4,
+ QUEUE_ID_MAX_LEVEL_69 = 5,
+ QUEUE_ID_MAX_LEVEL_79 = 6,
+ QUEUE_ID_MAX_LEVEL_80 = 7
+};
+#define MAX_BATTLEGROUND_QUEUES 8
enum ScoreType
{
@@ -198,7 +213,8 @@ enum BattleGroundWinner
enum BattleGroundTeamId
{
BG_TEAM_ALLIANCE = 0,
- BG_TEAM_HORDE = 1
+ BG_TEAM_HORDE = 1,
+ BG_TEAMS_COUNT = 2
};
enum BattleGroundJoinError
@@ -265,7 +281,7 @@ class BattleGround
// Get methods:
char const* GetName() const { return m_Name; }
BattleGroundTypeId GetTypeID() const { return m_TypeID; }
- uint32 GetQueueId() const { return m_QueueId; }
+ BGQueueIdBasedOnLevel GetQueueId() const { return m_QueueId; }
uint32 GetInstanceID() const { return m_InstanceID; }
uint32 GetStatus() const { return m_Status; }
uint32 GetStartTime() const { return m_StartTime; }
@@ -288,7 +304,13 @@ class BattleGround
// Set methods:
void SetName(char const* Name) { m_Name = Name; }
void SetTypeID(BattleGroundTypeId TypeID) { m_TypeID = TypeID; }
- void SetQueueId(uint32 ID) { m_QueueId = ID; }
+ //here we can count minlevel and maxlevel for players
+ void SetQueueId(BGQueueIdBasedOnLevel ID)
+ {
+ m_QueueId = ID;
+ uint8 diff = (m_TypeID == BATTLEGROUND_AV) ? 1 : 0;
+ this->SetLevelRange((ID + 1) * 10 + diff, (ID + 2) * 10 - ((diff + 1) % 2));
+ }
void SetInstanceID(uint32 InstanceID) { m_InstanceID = InstanceID; }
void SetStatus(uint32 Status) { m_Status = Status; }
void SetStartTime(uint32 Time) { m_StartTime = Time; }
@@ -320,7 +342,6 @@ class BattleGround
else
return m_InvitedHorde;
}
- bool HasFreeSlotsForTeam(uint32 Team) const;
bool HasFreeSlots() const;
uint32 GetFreeSlotsForTeam(uint32 Team) const;
@@ -489,7 +510,7 @@ class BattleGround
uint32 m_StartTime;
uint32 m_EndTime;
uint32 m_LastResurrectTime;
- uint32 m_QueueId;
+ BGQueueIdBasedOnLevel m_QueueId;
uint8 m_ArenaType; // 2=2v2, 3=3v3, 5=5v5
bool m_InBGFreeSlotQueue; // used to make sure that BG is only once inserted into the BattleGroundMgr.BGFreeSlotQueue[bgTypeId] deque
bool m_SetDeleteThis; // used for safe deletion of the bg after end / all players leave
@@ -515,15 +536,15 @@ class BattleGround
uint32 m_InvitedHorde;
/* Raid Group */
- Group *m_BgRaids[2]; // 0 - alliance, 1 - horde
+ Group *m_BgRaids[BG_TEAMS_COUNT]; // 0 - alliance, 1 - horde
/* Players count by team */
- uint32 m_PlayersCount[2];
+ uint32 m_PlayersCount[BG_TEAMS_COUNT];
/* Arena team ids by team */
- uint32 m_ArenaTeamIds[2];
+ uint32 m_ArenaTeamIds[BG_TEAMS_COUNT];
- int32 m_ArenaTeamRatingChanges[2];
+ int32 m_ArenaTeamRatingChanges[BG_TEAMS_COUNT];
/* Limits */
uint32 m_LevelMin;
@@ -535,10 +556,10 @@ class BattleGround
/* Location */
uint32 m_MapId;
- float m_TeamStartLocX[2];
- float m_TeamStartLocY[2];
- float m_TeamStartLocZ[2];
- float m_TeamStartLocO[2];
+ float m_TeamStartLocX[BG_TEAMS_COUNT];
+ float m_TeamStartLocY[BG_TEAMS_COUNT];
+ float m_TeamStartLocZ[BG_TEAMS_COUNT];
+ float m_TeamStartLocO[BG_TEAMS_COUNT];
};
#endif
diff --git a/src/game/BattleGroundHandler.cpp b/src/game/BattleGroundHandler.cpp
index 7d5a2f503bf..1f75bab4429 100644
--- a/src/game/BattleGroundHandler.cpp
+++ b/src/game/BattleGroundHandler.cpp
@@ -80,6 +80,7 @@ void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data )
uint32 bgTypeId_;
uint32 instanceId;
uint8 joinAsGroup;
+ bool isPremade = false;
Group * grp;
recv_data >> guid; // battlemaster guid
@@ -148,6 +149,7 @@ void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data )
if(!grp)
return;
uint32 err = grp->CanJoinBattleGroundQueue(bgTypeId, bgQueueTypeId, 0, bg->GetMaxPlayersPerTeam(), false, 0);
+ isPremade = (grp->GetMembersCount() >= bg->GetMinPlayersPerTeam());
if (err != BG_JOIN_ERR_OK)
{
SendBattleGroundOrArenaJoinError(err);
@@ -160,7 +162,7 @@ void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data )
if(joinAsGroup /* && _player->GetGroup()*/)
{
sLog.outDebug("Battleground: the following players are joining as group:");
- GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, 0, false, 0);
+ GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, 0, false, isPremade, 0);
for(GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next())
{
Player *member = itr->getSource();
@@ -197,7 +199,7 @@ void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data )
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0);
SendPacket(&data);
- GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, 0, false, 0);
+ GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, 0, false, false, 0);
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddPlayer(_player, ginfo);
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel(bgTypeId));
if(!ginfo->IsInvitedToBGInstanceGUID)
@@ -318,8 +320,7 @@ void WorldSession::HandleBattleGroundPlayerPortOpcode( WorldPacket &recv_data )
if(!bgQueueTypeId)
continue;
BattleGroundTypeId bgTypeId = BattleGroundMgr::BGTemplateId(bgQueueTypeId);
- uint32 queue_id = _player->GetBattleGroundQueueIdFromLevel(bgTypeId);
- BattleGroundQueue::QueuedPlayersMap& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[queue_id];
+ BattleGroundQueue::QueuedPlayersMap& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers;
BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = qpMap.find(_player->GetGUID());
// if the player is not in queue, continue
if(itrPlayerStatus == qpMap.end())
@@ -372,7 +373,7 @@ void WorldSession::HandleBattleGroundPlayerPortOpcode( WorldPacket &recv_data )
BattleGroundQueueTypeId bgQueueTypeId = BATTLEGROUND_QUEUE_NONE;
// get the bg what we were invited to
bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bgTypeId,type);
- BattleGroundQueue::QueuedPlayersMap& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel(bgTypeId)];
+ BattleGroundQueue::QueuedPlayersMap& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers;
BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = qpMap.find(_player->GetGUID());
if(itrPlayerStatus == qpMap.end())
{
@@ -412,7 +413,7 @@ void WorldSession::HandleBattleGroundPlayerPortOpcode( WorldPacket &recv_data )
uint32 opponentsRating = 0;
// get the team info from the queue
- BattleGroundQueue::QueuedPlayersMap& qpMap2 = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel(bgTypeId)];
+ BattleGroundQueue::QueuedPlayersMap& qpMap2 = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers;
BattleGroundQueue::QueuedPlayersMap::iterator pitr = qpMap2.find(_player->GetGUID());
if (pitr !=qpMap2.end() && pitr->second.GroupInfo)
{
@@ -548,8 +549,7 @@ void WorldSession::HandleBattlefieldStatusOpcode( WorldPacket & /*recv_data*/ )
BattleGroundTypeId bgTypeId = BattleGroundMgr::BGTemplateId(bgQueueTypeId);
uint8 arenatype = BattleGroundMgr::BGArenaType(bgQueueTypeId);
uint8 isRated = 0;
- uint32 queue_id = _player->GetBattleGroundQueueIdFromLevel(bgTypeId);
- BattleGroundQueue::QueuedPlayersMap& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[queue_id];
+ BattleGroundQueue::QueuedPlayersMap& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers;
BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = qpMap.find(_player->GetGUID());
if(itrPlayerStatus == qpMap.end())
continue;
@@ -580,9 +580,8 @@ void WorldSession::HandleBattlefieldStatusOpcode( WorldPacket & /*recv_data*/ )
BattleGroundTypeId bgTypeId = BattleGroundMgr::BGTemplateId(bgQueueTypeId);
uint8 arenatype = BattleGroundMgr::BGArenaType(bgQueueTypeId);
uint8 isRated = 0;
- uint32 queue_id = _player->GetBattleGroundQueueIdFromLevel(bgTypeId);
BattleGround *bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId);
- BattleGroundQueue::QueuedPlayersMap& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[queue_id];
+ BattleGroundQueue::QueuedPlayersMap& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers;
BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = qpMap.find(_player->GetGUID());
if(itrPlayerStatus == qpMap.end())
continue;
@@ -770,7 +769,7 @@ void WorldSession::HandleBattleGroundArenaJoin( WorldPacket & recv_data )
if(asGroup)
{
- GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, arenatype, isRated, arenaRating, ateamId);
+ GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, arenatype, isRated, false, arenaRating, ateamId);
sLog.outDebug("Battleground: arena join as group start");
if(isRated)
sLog.outDebug("Battleground: arena team id %u, leader %s queued with rating %u for type %u",_player->GetArenaTeamId(arenaslot),_player->GetName(),arenaRating,arenatype);
@@ -809,7 +808,7 @@ void WorldSession::HandleBattleGroundArenaJoin( WorldPacket & recv_data )
// send status packet (in queue)
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0, arenatype, isRated);
SendPacket(&data);
- GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, arenatype, isRated, arenaRating);
+ GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, arenatype, isRated, false, arenaRating);
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddPlayer(_player, ginfo);
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel(bgTypeId), arenatype, isRated, arenaRating);
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());
diff --git a/src/game/BattleGroundMgr.cpp b/src/game/BattleGroundMgr.cpp
index d151f3bc232..ce1fa4a9fe9 100644
--- a/src/game/BattleGroundMgr.cpp
+++ b/src/game/BattleGroundMgr.cpp
@@ -54,91 +54,90 @@ INSTANTIATE_SINGLETON_1( BattleGroundMgr );
BattleGroundQueue::BattleGroundQueue()
{
- //queues are empty, we don't have to call clear()
}
BattleGroundQueue::~BattleGroundQueue()
{
+ m_QueuedPlayers.clear();
for (int i = 0; i < MAX_BATTLEGROUND_QUEUES; i++)
{
- m_QueuedPlayers[i].clear();
- for(QueuedGroupsList::iterator itr = m_QueuedGroups[i].begin(); itr!= m_QueuedGroups[i].end(); ++itr)
+ for(uint32 j = 0; j < BG_QUEUE_GROUP_TYPES_COUNT; j++)
{
- delete (*itr);
+ for(GroupsQueueType::iterator itr = m_QueuedGroups[i][j].begin(); itr!= m_QueuedGroups[i][j].end(); ++itr)
+ delete (*itr);
+ m_QueuedGroups[i][j].clear();
}
- m_QueuedGroups[i].clear();
}
}
-// initialize eligible groups from the given source matching the given specifications
-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)
-{
- // clear from prev initialization
- clear();
- BattleGroundQueue::QueuedGroupsList::iterator itr, next;
- // iterate through the source
- for(itr = source->begin(); itr!= source->end(); itr = next)
- {
- next = itr;
- ++next;
- if( (*itr)->BgTypeId == BgTypeId && // bg type must match
- (*itr)->ArenaType == ArenaType && // arena type must match
- (*itr)->IsRated == IsRated && // israted must match
- (*itr)->IsInvitedToBGInstanceGUID == 0 && // leave out already invited groups
- (*itr)->Team == side && // match side
- (*itr)->Players.size() <= MaxPlayers && // the group must fit in the bg
- ( !excludeTeam || (*itr)->ArenaTeamId != excludeTeam ) && // if excludeTeam is specified, leave out those arena team ids
- ( !IsRated || (*itr)->Players.size() == MaxPlayers ) && // if rated, then pass only if the player count is exact NEEDS TESTING! (but now this should never happen)
- ( !DisregardTime || (*itr)->JoinTime <= DisregardTime // pass if disregard time is greater than join time
- || (*itr)->ArenaTeamRating == 0 // pass if no rating info
- || ( (*itr)->ArenaTeamRating >= MinRating // pass if matches the rating range
- && (*itr)->ArenaTeamRating <= MaxRating ) ) )
- {
- // the group matches the conditions
- // the source is ordered by join time in decreasing order
- // so here we push_front for increasing order
- push_front((*itr));
- }
- }
-}
+/*********************************************************/
+/*** BATTLEGROUND QUEUE SELECTION POOLS ***/
+/*********************************************************/
// selection pool initialization, used to clean up from prev selection
-void BattleGroundQueue::SelectionPool::Init(EligibleGroups * curr)
+void BattleGroundQueue::SelectionPool::Init()
{
- m_CurrEligGroups = curr;
SelectedGroups.clear();
PlayerCount = 0;
}
// remove group info from selection pool
-void BattleGroundQueue::SelectionPool::RemoveGroup(GroupQueueInfo *ginfo)
+// returns true when we need to try to add new group to selection pool
+// or false when pool is ok
+// sometimes it can be called on empty selection pool
+bool BattleGroundQueue::SelectionPool::KickGroup(uint32 size)
{
- // find what to remove
- for(std::list<GroupQueueInfo *>::iterator itr = SelectedGroups.begin(); itr != SelectedGroups.end(); ++itr)
+ //find maxgroup or LAST group with size == size and kick it
+ bool found = false;
+ GroupsQueueType::iterator groupToKick = SelectedGroups.begin();
+ for (GroupsQueueType::iterator itr = groupToKick; itr != SelectedGroups.end(); ++itr)
{
- if((*itr)==ginfo)
+ if( abs((int32)((*itr)->Players.size() - size)) <= 1 )
{
- SelectedGroups.erase(itr);
- // decrease selected players count
- PlayerCount -= ginfo->Players.size();
- return;
+ groupToKick = itr;
+ found = true;
}
+ else if (!found && (*itr)->Players.size() >= (*groupToKick)->Players.size())
+ groupToKick = itr;
+ }
+ //if pool is empty, do nothing
+ if( GetPlayerCount() )
+ {
+ //update player count
+ GroupQueueInfo* ginfo = (*groupToKick);
+ SelectedGroups.erase(groupToKick);
+ PlayerCount -= ginfo->Players.size();
+ if (abs((int32)(ginfo->Players.size() - size)) <= 1)
+ return false;
}
+ return true;
}
-// add group to selection
+// add group to selection pool
// used when building selection pools
-void BattleGroundQueue::SelectionPool::AddGroup(GroupQueueInfo * ginfo)
+// returns true if we can invite more players, otherwise return false - (selection pool is set that time)
+bool BattleGroundQueue::SelectionPool::AddGroup(GroupQueueInfo *ginfo, uint32 desiredCount)
{
- SelectedGroups.push_back(ginfo);
- // increase selected players count
- PlayerCount+=ginfo->Players.size();
+ //if group is larger than desired count - don't allow to add it to pool
+ if (!ginfo->IsInvitedToBGInstanceGUID && desiredCount >= PlayerCount + ginfo->Players.size())
+ {
+ SelectedGroups.push_back(ginfo);
+ // increase selected players count
+ PlayerCount += ginfo->Players.size();
+ }
+ if (PlayerCount == desiredCount)
+ return true;
+ return false;
}
+/*********************************************************/
+/*** BATTLEGROUND QUEUES ***/
+/*********************************************************/
+
// add group to bg queue with the given leader and bg specifications
-GroupQueueInfo * BattleGroundQueue::AddGroup(Player *leader, BattleGroundTypeId BgTypeId, uint8 ArenaType, bool isRated, uint32 arenaRating, uint32 arenateamid)
+GroupQueueInfo * BattleGroundQueue::AddGroup(Player *leader, BattleGroundTypeId BgTypeId, uint8 ArenaType, bool isRated, bool isPremade, uint32 arenaRating, uint32 arenateamid)
{
- uint32 queue_id = leader->GetBattleGroundQueueIdFromLevel(BgTypeId);
+ BGQueueIdBasedOnLevel queue_id = leader->GetBattleGroundQueueIdFromLevel(BgTypeId);
// create new ginfo
// cannot use the method like in addplayer, because that could modify an in-queue group's stats
@@ -148,26 +147,33 @@ GroupQueueInfo * BattleGroundQueue::AddGroup(Player *leader, BattleGroundTypeId
ginfo->ArenaType = ArenaType;
ginfo->ArenaTeamId = arenateamid;
ginfo->IsRated = isRated;
- ginfo->IsInvitedToBGInstanceGUID = 0; // maybe this should be modifiable by function arguments to enable selection of running instances?
+ ginfo->IsInvitedToBGInstanceGUID = 0;
ginfo->JoinTime = getMSTime();
ginfo->Team = leader->GetTeam();
ginfo->ArenaTeamRating = arenaRating;
- ginfo->OpponentsTeamRating = 0; //initialize it to 0
+ ginfo->OpponentsTeamRating = 0;
ginfo->Players.clear();
- m_QueuedGroups[queue_id].push_back(ginfo);
+ //compute index (if group is premade or joined a rated match) to queues
+ uint32 index = 0;
+ if(!isRated && !isPremade)
+ index += BG_TEAMS_COUNT;
+ if(ginfo->Team == HORDE)
+ index++;
+ sLog.outDebug("Adding Group to BattleGroundQueue bgTypeId : %u, queue_id : %u, index : %u", BgTypeId, queue_id, index);
+
+ m_QueuedGroups[queue_id][index].push_back(ginfo);
// return ginfo, because it is needed to add players to this group info
return ginfo;
}
+//add player to playermap
void BattleGroundQueue::AddPlayer(Player *plr, GroupQueueInfo *ginfo)
{
- uint32 queue_id = plr->GetBattleGroundQueueIdFromLevel(ginfo->BgTypeId);
-
//if player isn't in queue, he is added, if already is, then values are overwritten, no memory leak
- PlayerQueueInfo& info = m_QueuedPlayers[queue_id][plr->GetGUID()];
+ PlayerQueueInfo& info = m_QueuedPlayers[plr->GetGUID()];
info.InviteTime = 0;
info.LastInviteTime = 0;
info.LastOnlineTime = getMSTime();
@@ -177,112 +183,116 @@ void BattleGroundQueue::AddPlayer(Player *plr, GroupQueueInfo *ginfo)
ginfo->Players[plr->GetGUID()] = &info;
}
+//remove player from queue and from group info, if group info is empty then remove it too
void BattleGroundQueue::RemovePlayer(const uint64& guid, bool decreaseInvitedCount)
{
- Player *plr = objmgr.GetPlayer(guid);
+ //Player *plr = objmgr.GetPlayer(guid);
- int32 queue_id = 0; // signed for proper for-loop finish
+ int32 queue_id = -1; // signed for proper for-loop finish
QueuedPlayersMap::iterator itr;
- // mostly people with the highest levels are in battlegrounds, thats why
- // we count from MAX_BATTLEGROUND_QUEUES to 0
- for (queue_id = MAX_BATTLEGROUND_QUEUES-1; queue_id >= 0; queue_id--)
- {
- itr = m_QueuedPlayers[queue_id].find(guid);
- if(itr != m_QueuedPlayers[queue_id].end())
- break;
- }
-
- // couldn't find the player in bg queue, return
- if(queue_id == -1)
+ //remove player from map, if he's there
+ itr = m_QueuedPlayers.find(guid);
+ if( itr == m_QueuedPlayers.end() )
{
- sLog.outError("Battleground: couldn't find player to remove.");
+ sLog.outError("BattleGroundQueue: couldn't find player to remove GUID: %u", GUID_LOPART(guid));
return;
}
GroupQueueInfo* group = itr->second.GroupInfo;
+ GroupsQueueType::iterator group_itr, group_itr_tmp;
+ // mostly people with the highest levels are in battlegrounds, thats why
+ // we count from MAX_BATTLEGROUND_QUEUES - 1 to 0
+ // variable index removes useless searching in other team's queue
+ uint32 index = (group->Team == HORDE) ? BG_TEAM_HORDE : BG_TEAM_ALLIANCE;
- QueuedGroupsList::iterator group_itr = m_QueuedGroups[queue_id].begin();
- for(; group_itr != m_QueuedGroups[queue_id].end(); ++group_itr)
+ for (int32 queue_id_tmp = MAX_BATTLEGROUND_QUEUES - 1; queue_id_tmp >= 0 && queue_id == -1; --queue_id_tmp)
{
- if(group == *group_itr)
- break;
+ //we must check premade and normal team's queue - because when players from premade are joining bg,
+ //they leave groupinfo so we can't use its players size to find out index
+ for (uint32 j = index; j < BG_QUEUE_GROUP_TYPES_COUNT - 1; j += BG_QUEUE_NORMAL_ALLIANCE)
+ {
+ for(group_itr_tmp = m_QueuedGroups[queue_id_tmp][j].begin(); group_itr_tmp != m_QueuedGroups[queue_id_tmp][j].end(); ++group_itr_tmp)
+ {
+ if( (*group_itr_tmp) == group )
+ {
+ queue_id = queue_id_tmp;
+ group_itr = group_itr_tmp;
+ //we must store index to be able to erase iterator
+ index = j;
+ break;
+ }
+ }
+ }
}
+ //player can't be in queue without group, but just in case
+ if( queue_id == -1 )
+ {
+ sLog.outError("BattleGroundQueue: ERROR Cannot find groupinfo for player GUID: %u", GUID_LOPART(guid));
+ return;
+ }
+ sLog.outDebug("BattleGroundQueue: Removing player GUID %u, from queue_id %u", GUID_LOPART(guid), (uint32)queue_id);
- // variables are set (what about leveling up when in queue????
- // iterate through all queue_ids this isn't bad for us)
+ // ALL variables are corrcetly set
+ // We can ignore leveling up in queue - it should not cause crash
// remove player from group
- // if only player there, remove group
+ // if only one player there, remove group
// remove player queue info from group queue info
std::map<uint64, PlayerQueueInfo*>::iterator pitr = group->Players.find(guid);
-
- if(pitr != group->Players.end())
+ if( pitr != group->Players.end() )
group->Players.erase(pitr);
- // check for iterator correctness
- if (group_itr != m_QueuedGroups[queue_id].end() && itr != m_QueuedPlayers[queue_id].end())
+ // if invited to bg, and should decrease invited count, then do it
+ if( decreaseInvitedCount && group->IsInvitedToBGInstanceGUID )
{
- // used when player left the queue, NOT used when porting to bg
- if (decreaseInvitedCount)
- {
- // if invited to bg, and should decrease invited count, then do it
- if(group->IsInvitedToBGInstanceGUID)
- {
- BattleGround* bg = sBattleGroundMgr.GetBattleGround(group->IsInvitedToBGInstanceGUID);
- if (bg)
- bg->DecreaseInvitedCount(group->Team);
- if (bg && !bg->GetPlayersSize() && !bg->GetInvitedCount(ALLIANCE) && !bg->GetInvitedCount(HORDE))
- {
- // no more players on battleground, set delete it
- bg->SetDeleteThis();
- }
- }
- // update the join queue, maybe now the player's group fits in a queue!
- // not yet implemented (should store bgTypeId in group queue info?)
- }
- // remove player queue info
- m_QueuedPlayers[queue_id].erase(itr);
- // remove group queue info if needed
+ BattleGround* bg = sBattleGroundMgr.GetBattleGround(group->IsInvitedToBGInstanceGUID);
+ if( bg )
+ bg->DecreaseInvitedCount(group->Team);
+ }
- //if we left BG queue(not porting) OR if arena team left queue for rated match
- if((decreaseInvitedCount && !group->ArenaType) || (group->ArenaType && group->IsRated && group->Players.empty()))
- AnnounceWorld(group, guid, false);
+ // remove player queue info
+ m_QueuedPlayers.erase(itr);
- if(group->Players.empty())
- {
- m_QueuedGroups[queue_id].erase(group_itr);
- delete group;
- }
- // NEEDS TESTING!
- // group wasn't empty, so it wasn't deleted, and player have left a rated queue -> everyone from the group should leave too
- // don't remove recursively if already invited to bg!
- else if(!group->IsInvitedToBGInstanceGUID && decreaseInvitedCount && group->IsRated)
+ //if we left BG queue(not porting) OR if arena team left queue for rated match
+ if( (decreaseInvitedCount && !group->ArenaType) || (group->ArenaType && group->IsRated && group->Players.empty()) )
+ AnnounceWorld(group, guid, false);
+
+ // remove group queue info if needed
+ if( group->Players.empty() )
+ {
+ m_QueuedGroups[queue_id][index].erase(group_itr);
+ delete group;
+ }
+ // if group wasn't empty, so it wasn't deleted, and player have left a rated
+ // queue -> everyone from the group should leave too
+ // don't remove recursively if already invited to bg!
+ else if( !group->IsInvitedToBGInstanceGUID && group->IsRated )
+ {
+ // remove next player, this is recursive
+ // first send removal information
+ if(Player *plr2 = objmgr.GetPlayer(group->Players.begin()->first))
{
- // remove next player, this is recursive
- // first send removal information
- if(Player *plr2 = objmgr.GetPlayer(group->Players.begin()->first))
- {
- BattleGround * bg = sBattleGroundMgr.GetBattleGroundTemplate(group->BgTypeId);
- BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(group->BgTypeId,group->ArenaType);
- uint32 queueSlot = plr2->GetBattleGroundQueueIndex(bgQueueTypeId);
- plr2->RemoveBattleGroundQueueId(bgQueueTypeId); // must be called this way, because if you move this call to queue->removeplayer, it causes bugs
- WorldPacket data;
- sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, plr2->GetTeam(), queueSlot, STATUS_NONE, 0, 0);
- plr2->GetSession()->SendPacket(&data);
- }
- // then actually delete, this may delete the group as well!
- RemovePlayer(group->Players.begin()->first,decreaseInvitedCount);
+ BattleGround * bg = sBattleGroundMgr.GetBattleGroundTemplate(group->BgTypeId);
+ BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(group->BgTypeId, group->ArenaType);
+ uint32 queueSlot = plr2->GetBattleGroundQueueIndex(bgQueueTypeId);
+ plr2->RemoveBattleGroundQueueId(bgQueueTypeId); // must be called this way, because if you move this call to
+ // queue->removeplayer, it causes bugs
+ WorldPacket data;
+ sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, plr2->GetTeam(), queueSlot, STATUS_NONE, 0, 0);
+ plr2->GetSession()->SendPacket(&data);
}
+ // then actually delete, this may delete the group as well!
+ RemovePlayer(group->Players.begin()->first, decreaseInvitedCount);
}
}
+//Announce world message
void BattleGroundQueue::AnnounceWorld(GroupQueueInfo *ginfo, const uint64& playerGUID, bool isAddedToQueue)
{
-
if(ginfo->ArenaType) //if Arena
{
- if( sWorld.getConfig(CONFIG_ARENA_QUEUE_ANNOUNCER_ENABLE) && ginfo->IsRated)
+ if( sWorld.getConfig(CONFIG_ARENA_QUEUE_ANNOUNCER_ENABLE) && ginfo->IsRated )
{
BattleGround* bg = sBattleGroundMgr.GetBattleGroundTemplate(ginfo->BgTypeId);
if(!bg)
@@ -300,57 +310,35 @@ void BattleGroundQueue::AnnounceWorld(GroupQueueInfo *ginfo, const uint64& playe
if( sWorld.getConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE) )
{
Player *plr = objmgr.GetPlayer(playerGUID);
- if(!plr)
- return;
-
BattleGround* bg = sBattleGroundMgr.GetBattleGroundTemplate(ginfo->BgTypeId);
- if(!bg)
+ if(!bg || !plr)
return;
- uint32 queue_id = plr->GetBattleGroundQueueIdFromLevel(bg->GetTypeID());
+ BGQueueIdBasedOnLevel queue_id = plr->GetBattleGroundQueueIdFromLevel(bg->GetTypeID());
char const* bgName = bg->GetName();
-
- uint32 q_min_level = Player::GetMinLevelForBattleGroundQueueId(queue_id, ginfo->BgTypeId);
- uint32 q_max_level = Player::GetMaxLevelForBattleGroundQueueId(queue_id, ginfo->BgTypeId);
-
- // replace hardcoded max level by player max level for nice output
- if(q_max_level > sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL))
- q_max_level = sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL);
-
- int8 MinPlayers = bg->GetMinPlayersPerTeam();
-
- uint8 qHorde = 0;
- uint8 qAlliance = 0;
-
- BattleGroundTypeId bgTypeId = ginfo->BgTypeId;
- QueuedPlayersMap::iterator itr;
- for(itr = m_QueuedPlayers[queue_id].begin(); itr!= m_QueuedPlayers[queue_id].end(); ++itr)
- {
- if(itr->second.GroupInfo->BgTypeId == bgTypeId)
- {
- switch(itr->second.GroupInfo->Team)
- {
- case HORDE:
- qHorde++; break;
- case ALLIANCE:
- qAlliance++; break;
- default:
- break;
- }
- }
- }
+ uint32 MinPlayers = bg->GetMinPlayersPerTeam();
+ uint32 qHorde = 0;
+ uint32 qAlliance = 0;
+ uint32 q_min_level = (queue_id + 1) * 10;
+ GroupsQueueType::const_iterator itr;
+ for(itr = m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE].begin(); itr != m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE].end(); ++itr)
+ if( !(*itr)->IsInvitedToBGInstanceGUID )
+ qAlliance += (*itr)->Players.size();
+ for(itr = m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_HORDE].begin(); itr != m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_HORDE].end(); ++itr)
+ if( !(*itr)->IsInvitedToBGInstanceGUID )
+ qHorde += (*itr)->Players.size();
// Show queue status to player only (when joining queue)
- if(sWorld.getConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_PLAYERONLY))
+ if( sWorld.getConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_PLAYERONLY) )
{
ChatHandler(plr).PSendSysMessage(LANG_BG_QUEUE_ANNOUNCE_SELF,
- bgName, q_min_level, q_max_level, qAlliance, MinPlayers, qHorde, MinPlayers);
+ bgName, q_min_level, q_min_level + 10, qAlliance, MinPlayers, qHorde, MinPlayers);
}
// System message
else
{
sWorld.SendWorldText(LANG_BG_QUEUE_ANNOUNCE_WORLD,
- bgName, q_min_level, q_max_level, qAlliance, MinPlayers, qHorde, MinPlayers);
+ bgName, q_min_level, q_min_level + 10, qAlliance, MinPlayers, qHorde, MinPlayers);
}
}
}
@@ -359,10 +347,10 @@ void BattleGroundQueue::AnnounceWorld(GroupQueueInfo *ginfo, const uint64& playe
bool BattleGroundQueue::InviteGroupToBG(GroupQueueInfo * ginfo, BattleGround * bg, uint32 side)
{
// set side if needed
- if(side)
+ if( side )
ginfo->Team = side;
- if(!ginfo->IsInvitedToBGInstanceGUID)
+ if( !ginfo->IsInvitedToBGInstanceGUID )
{
// not yet invited
// set invitation
@@ -377,12 +365,12 @@ bool BattleGroundQueue::InviteGroupToBG(GroupQueueInfo * ginfo, BattleGround * b
// get the player
Player* plr = objmgr.GetPlayer(itr->first);
- // if offline, skip him
- if(!plr)
+ // if offline, skip him, this should not happen - player is removed from queue when he logs out
+ if( !plr )
continue;
// invite the player
- sBattleGroundMgr.InvitePlayer(plr, bg->GetInstanceID(),ginfo->Team);
+ sBattleGroundMgr.InvitePlayer(plr, bg->GetInstanceID(), ginfo->Team);
WorldPacket data;
@@ -400,189 +388,291 @@ bool BattleGroundQueue::InviteGroupToBG(GroupQueueInfo * ginfo, BattleGround * b
return false;
}
-// used to recursively select groups from eligible groups
-bool BattleGroundQueue::SelectionPool::Build(uint32 MinPlayers, uint32 MaxPlayers, EligibleGroups::iterator startitr)
+// used to remove the Enter Battle window if the battle has already ended, but someone still has it
+// (this can happen in arenas mainly, since the preparation is shorter than the timer for the bgqueueremove event
+void BattleGroundQueue::BGEndedRemoveInvites(BattleGround *bg)
{
- // start from the specified start iterator
- for(EligibleGroups::iterator itr1 = startitr; itr1 != m_CurrEligGroups->end(); ++itr1)
+ BGQueueIdBasedOnLevel queue_id = bg->GetQueueId();
+ uint32 bgInstanceId = bg->GetInstanceID();
+ BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType());
+ GroupsQueueType::iterator itr, next;
+ for(uint32 i = 0; i < BG_QUEUE_GROUP_TYPES_COUNT; i++)
{
- // if it fits in, select it
- if(GetPlayerCount() + (*itr1)->Players.size() <= MaxPlayers)
+ for(itr = m_QueuedGroups[queue_id][i].begin(); itr != m_QueuedGroups[queue_id][i].end(); itr = next)
{
- EligibleGroups::iterator next = itr1;
+ // must do this way, because the groupinfo will be deleted when all playerinfos are removed
+ GroupQueueInfo * ginfo = (*itr);
+ next = itr;
++next;
- AddGroup((*itr1));
- if(GetPlayerCount() >= MinPlayers)
+ // if group was invited to this bg instance, then remove all references
+ if( ginfo->IsInvitedToBGInstanceGUID == bgInstanceId )
{
- // enough players are selected
- return true;
+ // after removing this much playerinfos, the ginfo will be deleted, so we'll use a for loop
+ uint32 to_remove = ginfo->Players.size();
+ uint32 team = ginfo->Team;
+ for(uint32 j = 0; j < to_remove; j++)
+ {
+ // always remove the first one in the group
+ std::map<uint64, PlayerQueueInfo * >::iterator itr2 = ginfo->Players.begin();
+ if( itr2 == ginfo->Players.end() )
+ {
+ sLog.outError("Empty Players in ginfo, this should never happen!");
+ return;
+ }
+ // get the player
+ Player * plr = objmgr.GetPlayer(itr2->first);
+ if( !plr )
+ {
+ sLog.outError("Player offline when trying to remove from GroupQueueInfo, this should never happen.");
+ continue;
+ }
+
+ // get the queueslot
+ uint32 queueSlot = plr->GetBattleGroundQueueIndex(bgQueueTypeId);
+ if (queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES) // player is in queue
+ {
+ plr->RemoveBattleGroundQueueId(bgQueueTypeId);
+ // remove player from queue, this might delete the ginfo as well! don't use that pointer after this!
+ RemovePlayer(itr2->first, true);
+ WorldPacket data;
+ sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, team, queueSlot, STATUS_NONE, 0, 0);
+ plr->GetSession()->SendPacket(&data);
+ }
+ }
}
- // try building from the rest of the elig. groups
- // if that succeeds, return true
- if(Build(MinPlayers,MaxPlayers,next))
- return true;
- // the rest didn't succeed, so this group cannot be included
- RemoveGroup((*itr1));
}
}
- // build didn't succeed
- return false;
}
-// this function is responsible for the selection of queued groups when trying to create new battlegrounds
-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)
+/*
+This function is inviting players to already running battlegrounds
+Invitation type is based on config file
+large groups are disadvantageous, because they will be kicked first if invitation type = 1
+*/
+void BattleGroundQueue::FillPlayersToBG(BattleGround* bg, BGQueueIdBasedOnLevel queue_id)
{
- uint32 side;
- switch(mode)
- {
- case NORMAL_ALLIANCE:
- case ONESIDE_ALLIANCE_TEAM1:
- case ONESIDE_ALLIANCE_TEAM2:
- side = ALLIANCE;
- break;
- case NORMAL_HORDE:
- case ONESIDE_HORDE_TEAM1:
- case ONESIDE_HORDE_TEAM2:
- side = HORDE;
- break;
- default:
- //unknown mode, return false
- sLog.outDebug("Battleground: unknown selection pool build mode, returning...");
- return false;
- }
+ uint32 hordeFree = bg->GetFreeSlotsForTeam(HORDE);
+ uint32 aliFree = bg->GetFreeSlotsForTeam(ALLIANCE);
+
+ //iterator for iterating through bg queue
+ GroupsQueueType::const_iterator Ali_itr = m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE].begin();
+ //count of groups in queue - used to stop cycles
+ uint32 aliCount = m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE].size();
+ //index to queue which group is current
+ uint32 aliIndex = 0;
+ for (; aliIndex < aliCount && m_SelectionPools[BG_TEAM_ALLIANCE].AddGroup((*Ali_itr), aliFree); aliIndex++)
+ ++Ali_itr;
+ //the same thing for horde
+ GroupsQueueType::const_iterator Horde_itr = m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_HORDE].begin();
+ uint32 hordeCount = m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_HORDE].size();
+ uint32 hordeIndex = 0;
+ for (; hordeIndex < hordeCount && m_SelectionPools[BG_TEAM_HORDE].AddGroup((*Horde_itr), hordeFree); hordeIndex++)
+ ++Horde_itr;
+
+ //if ofc like BG queue invitation is set in config, then we are happy
+ if (sWorld.getConfig(CONFIG_BATTLEGROUND_INVITATION_TYPE) == 0)
+ return;
+
+ /*
+ if we reached this code, then we have to solve NP - complete problem called Subset sum problem
+ So one solution is to check all possible invitation subgroups, or we can use these conditions:
+ 1. Last time when BattleGroundQueue::Update was executed we invited all possible players - so there is only small possibility
+ that we will invite now whole queue, because only 1 change has been made to queues from the last BattleGroundQueue::Update call
+ 2. Other thing we should consider is group order in queue
+ */
- // initiate the groups eligible to create the bg
- m_EligibleGroups.Init(&(m_QueuedGroups[queue_id]), bgTypeId, side, MaxPlayers, ArenaType, isRated, MinRating, MaxRating, DisregardTime, excludeTeam);
- // init the selected groups (clear)
- // and set m_CurrEligGroups pointer
- // we set it this way to only have one EligibleGroups object to save some memory
- m_SelectionPools[mode].Init(&m_EligibleGroups);
- // build succeeded
- if(m_SelectionPools[mode].Build(MinPlayers,MaxPlayers,m_EligibleGroups.begin()))
+ // At first we need to compare free space in bg and our selection pool
+ int32 diffAli = aliFree - m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount();
+ int32 diffHorde = hordeFree - m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount();
+ while( abs(diffAli - diffHorde) > 1 && (m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount() > 0 || m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount() > 0) )
{
- // the selection pool is set, return
- sLog.outDebug("Battleground-debug: pool build succeeded, return true");
- sLog.outDebug("Battleground-debug: Player size for mode %u is %u", mode, m_SelectionPools[mode].GetPlayerCount());
- for(std::list<GroupQueueInfo* >::iterator itr = m_SelectionPools[mode].SelectedGroups.begin(); itr != m_SelectionPools[mode].SelectedGroups.end(); ++itr)
+ //each cycle execution we need to kick at least 1 group
+ if( diffAli < diffHorde )
{
- sLog.outDebug("Battleground-debug: queued group in selection with %u players",(*itr)->Players.size());
- for(std::map<uint64, PlayerQueueInfo * >::iterator itr2 = (*itr)->Players.begin(); itr2 != (*itr)->Players.end(); ++itr2)
- sLog.outDebug("Battleground-debug: player in above group GUID %u", (uint32)(itr2->first));
+ //kick alliance group, add to pool new group if needed
+ if( m_SelectionPools[BG_TEAM_ALLIANCE].KickGroup(diffHorde - diffAli) )
+ {
+ for (; aliIndex < aliCount && m_SelectionPools[BG_TEAM_ALLIANCE].AddGroup((*Ali_itr), (aliFree >= diffHorde) ? aliFree - diffHorde : 0); aliIndex++)
+ ++Ali_itr;
+ }
+ //if ali selection is already empty, then kick horde group, but if there are less horde than ali in bg - break;
+ if( !m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount() )
+ if( aliFree <= diffHorde - 1 )
+ break;
+ m_SelectionPools[BG_TEAM_HORDE].KickGroup(diffHorde - diffAli);
}
- return true;
+ else
+ {
+ //kick horde group, add to pool new group if needed
+ if( m_SelectionPools[BG_TEAM_HORDE].KickGroup(diffAli - diffHorde) )
+ {
+ for (; hordeIndex < hordeCount && m_SelectionPools[BG_TEAM_HORDE].AddGroup((*Horde_itr), (hordeFree >= diffAli) ? hordeFree - diffAli : 0); hordeIndex++)
+ ++Horde_itr;
+ }
+ if( !m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount() )
+ if( hordeFree <= diffAli - 1 )
+ break;
+ m_SelectionPools[BG_TEAM_ALLIANCE].KickGroup(diffAli - diffHorde);
+ }
+ //count diffs after small update
+ diffAli = aliFree - m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount();
+ diffHorde = hordeFree - m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount();
}
- // failed to build a selection pool matching the given values
- return false;
}
-// used to remove the Enter Battle window if the battle has already, but someone still has it
-// (this can happen in arenas mainly, since the preparation is shorter than the timer for the bgqueueremove event
-void BattleGroundQueue::BGEndedRemoveInvites(BattleGround *bg)
+// this method checks if premade versus premade battleground is possible
+// then after 30 mins (default) in queue it moves premade group to normal queue
+// it tries to invite as much players as it can - to MaxPlayersPerTeam, because premade groups have more than MinPlayersPerTeam players
+bool BattleGroundQueue::CheckPremadeMatch(BGQueueIdBasedOnLevel queue_id, uint32 MaxPlayersPerTeam, uint32 MinPlayersPerTeam)
{
- uint32 queue_id = bg->GetQueueId();
- uint32 bgInstanceId = bg->GetInstanceID();
- BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType());
- QueuedGroupsList::iterator itr, next;
- for(itr = m_QueuedGroups[queue_id].begin(); itr != m_QueuedGroups[queue_id].end(); itr = next)
+ //check match
+ if(!m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_ALLIANCE].empty() && !m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_HORDE].empty())
{
- // must do this way, because the groupinfo will be deleted when all playerinfos are removed
- GroupQueueInfo * ginfo = (*itr);
- next = itr;
- ++next;
- // if group was invited to this bg instance, then remove all references
- if(ginfo->IsInvitedToBGInstanceGUID == bgInstanceId)
+ //start premade match
+ //if groups aren't invited
+ GroupsQueueType::const_iterator ali_group, horde_group;
+ for( ali_group = m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_ALLIANCE].begin(); ali_group != m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_ALLIANCE].end(); ++ali_group)
+ if( !(*ali_group)->IsInvitedToBGInstanceGUID )
+ break;
+ for( horde_group = m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_HORDE].begin(); horde_group != m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_HORDE].end(); ++horde_group)
+ if( !(*horde_group)->IsInvitedToBGInstanceGUID )
+ break;
+
+ if( ali_group != m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_ALLIANCE].end() && horde_group != m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_HORDE].end())
{
- // after removing this much playerinfos, the ginfo will be deleted, so we'll use a for loop
- uint32 to_remove = ginfo->Players.size();
- uint32 team = ginfo->Team;
- for(int i = 0; i < to_remove; ++i)
+ m_SelectionPools[BG_TEAM_ALLIANCE].AddGroup((*ali_group), MaxPlayersPerTeam);
+ m_SelectionPools[BG_TEAM_HORDE].AddGroup((*horde_group), MaxPlayersPerTeam);
+ //add groups/players from normal queue to size of bigger group
+ uint32 maxPlayers = std::max(m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount(), m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount());
+ GroupsQueueType::const_iterator itr;
+ for(uint32 i = 0; i < BG_TEAMS_COUNT; i++)
{
- // always remove the first one in the group
- std::map<uint64, PlayerQueueInfo * >::iterator itr2 = ginfo->Players.begin();
- if(itr2 == ginfo->Players.end())
+ for(itr = m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE + i].begin(); itr != m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE + i].end(); ++itr)
{
- sLog.outError("Empty Players in ginfo, this should never happen!");
- return;
+ if( !(*itr)->IsInvitedToBGInstanceGUID && m_SelectionPools[i].AddGroup((*itr), maxPlayers) )
+ break;
}
+ }
+ //premade selection pools are set
+ return true;
+ }
+ }
+ // now check if we can move group from Premade queue to normal queue (timer has expired) or group size lowered!!
+ // this could be 2 cycles but i'm checking only first team in queue - it can cause problem -
+ // if first is invited to BG and seconds timer expired, but we can ignore it, because players have only 80 seconds to click to enter bg
+ // and when they click or after 80 seconds the queue info is removed from queue
+ uint32 time_before = getMSTime() - sWorld.getConfig(CONFIG_BATTLEGROUND_PREMADE_GROUP_WAIT_FOR_MATCH);
+ for(uint32 i = 0; i < BG_TEAMS_COUNT; i++)
+ {
+ if(!m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_ALLIANCE + i].empty())
+ {
+ GroupsQueueType::iterator itr = m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_ALLIANCE + i].begin();
+ if(!(*itr)->IsInvitedToBGInstanceGUID && ((*itr)->JoinTime < time_before || (*itr)->Players.size() < MinPlayersPerTeam))
+ {
+ //we must insert group to normal queue and erase pointer from premade queue
+ m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE + i].push_front((*itr));
+ m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_ALLIANCE + i].erase(itr); //pop_front();
+ }
+ }
+ }
+ //selection pools are not set
+ return false;
+}
- // get the player
- Player * plr = objmgr.GetPlayer(itr2->first);
- if(!plr)
- {
- sLog.outError("Player offline when trying to remove from GroupQueueInfo, this should never happen.");
- continue;
- }
+//this function tries to create battleground or arena with MinPlayersPerTeam against MinPlayersPerTeam
+bool BattleGroundQueue::CheckNormalMatch(BattleGround* bg_template, BGQueueIdBasedOnLevel queue_id, uint32 MinPlayersPerTeam)
+{
+ uint32 minPlayers = bg_template->GetMinPlayersPerTeam();
+ uint32 maxPlayers = bg_template->GetMaxPlayersPerTeam();
- // get the queueslot
- uint32 queueSlot = plr->GetBattleGroundQueueIndex(bgQueueTypeId);
- if (queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES) // player is in queue
- {
- plr->RemoveBattleGroundQueueId(bgQueueTypeId);
- // remove player from queue, this might delete the ginfo as well! don't use that pointer after this!
- RemovePlayer(itr2->first, true);
- // this is probably unneeded, since this player was already invited -> does not fit when initing eligible groups
- // but updateing the queue can't hurt
- Update(bg->GetTypeID(), bg->GetQueueId());
- // send info to client
- WorldPacket data;
- sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, team, queueSlot, STATUS_NONE, 0, 0);
- plr->GetSession()->SendPacket(&data);
- }
+ GroupsQueueType::const_iterator itr_team[BG_TEAMS_COUNT];
+ for(uint32 i = 0; i < BG_TEAMS_COUNT; i++)
+ {
+ itr_team[i] = m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE + i].begin();
+ for(; itr_team[i] != m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE + i].end(); ++(itr_team[i]))
+ {
+ if( !(*(itr_team[i]))->IsInvitedToBGInstanceGUID )
+ {
+ m_SelectionPools[i].AddGroup(*(itr_team[i]), maxPlayers);
+ if( m_SelectionPools[i].GetPlayerCount() >= minPlayers )
+ break;
}
}
}
+ //try to invite same number of players - this cycle may cause longer wait time even if there are enough players in queue, but we want ballanced bg
+ uint32 j = BG_TEAM_ALLIANCE;
+ if( m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount() < m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount() )
+ j = BG_TEAM_HORDE;
+ if( sWorld.getConfig(CONFIG_BATTLEGROUND_INVITATION_TYPE) != 0
+ && m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount() >= minPlayers && m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount() >= minPlayers )
+ {
+ //we will try to invite more groups to team with less players indexed by j
+ ++(itr_team[j]); //this will not cause a crash, because for cycle above reached break;
+ for(; itr_team[j] != m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE + j].end(); ++(itr_team[j]))
+ {
+ if( !(*(itr_team[j]))->IsInvitedToBGInstanceGUID )
+ if( m_SelectionPools[j].AddGroup(*(itr_team[j]), m_SelectionPools[(j + 1) % BG_TEAMS_COUNT].GetPlayerCount()) )
+ break;
+ }
+ // do not allow to start bg with more than 2 players more on 1 faction
+ if( abs((int32)(m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount() - m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount())) > 2 )
+ return false;
+ }
+
+ //return true if there are enough players in selection pools - enable to work .debug bg command correctly
+ return m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount() >= MinPlayersPerTeam && m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount() >= MinPlayersPerTeam;
}
/*
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
it must be called after fully adding the members of a group to ensure group joining
-should be called after removeplayer functions in some cases
+should be called from BattleGround::RemovePlayer function in some cases
*/
-void BattleGroundQueue::Update(BattleGroundTypeId bgTypeId, uint32 queue_id, uint8 arenatype, bool isRated, uint32 arenaRating)
+void BattleGroundQueue::Update(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLevel queue_id, uint8 arenaType, bool isRated, uint32 arenaRating)
{
- if (queue_id >= MAX_BATTLEGROUND_QUEUES)
- {
- //this is error, that caused crashes (not in , but now it shouldn't)
- 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");
+ // this can happen when removing last player from battleground
+ if( queue_id == MAX_BATTLEGROUND_QUEUES )
return;
- }
//if no players in queue ... do nothing
- if (m_QueuedGroups[queue_id].empty())
+ if( m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_ALLIANCE].empty() &&
+ m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_HORDE].empty() &&
+ m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE].empty() &&
+ m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_HORDE].empty() )
return;
- BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bgTypeId, arenatype);
+ BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bgTypeId, arenaType);
- //battleground with free slot for player should be always the last in this queue
+ //battleground with free slot for player should be always in the beggining of the queue
+ // maybe it would be better to create bgfreeslotqueue for each queue_id_based_on_level
BGFreeSlotQueueType::iterator itr, next;
for (itr = sBattleGroundMgr.BGFreeSlotQueue[bgTypeId].begin(); itr != sBattleGroundMgr.BGFreeSlotQueue[bgTypeId].end(); itr = next)
{
next = itr;
++next;
- // battleground is running, so if:
- // DO NOT allow queue manager to invite new player to running arena
- if ((*itr)->isBattleGround() && (*itr)->GetTypeID() == bgTypeId && (*itr)->GetQueueId() == queue_id && (*itr)->GetStatus() > STATUS_WAIT_QUEUE && (*itr)->GetStatus() < STATUS_WAIT_LEAVE)
+ // DO NOT allow queue manager to invite new player to arena
+ if( (*itr)->isBattleGround() && (*itr)->GetTypeID() == bgTypeId && (*itr)->GetQueueId() == queue_id &&
+ (*itr)->GetStatus() > STATUS_WAIT_QUEUE && (*itr)->GetStatus() < STATUS_WAIT_LEAVE )
{
- //we must check both teams
BattleGround* bg = *itr; //we have to store battleground pointer here, because when battleground is full, it is removed from free queue (not yet implemented!!)
// and iterator is invalid
- for(QueuedGroupsList::iterator itr = m_QueuedGroups[queue_id].begin(); itr != m_QueuedGroups[queue_id].end(); ++itr)
- {
- // did the group join for this bg type?
- if((*itr)->BgTypeId != bgTypeId)
- continue;
- // if so, check if fits in
- if(bg->GetFreeSlotsForTeam((*itr)->Team) >= (*itr)->Players.size())
- {
- // if group fits in, invite it
- InviteGroupToBG((*itr),bg,(*itr)->Team);
- }
- }
+ // clear selection pools
+ m_SelectionPools[BG_TEAM_ALLIANCE].Init();
+ m_SelectionPools[BG_TEAM_HORDE].Init();
+
+ // call a function that does the job for us
+ FillPlayersToBG(bg, queue_id);
- if (!bg->HasFreeSlots())
+ // now everything is set, invite players
+ for(GroupsQueueType::const_iterator itr = m_SelectionPools[BG_TEAM_ALLIANCE].SelectedGroups.begin(); itr != m_SelectionPools[BG_TEAM_ALLIANCE].SelectedGroups.end(); ++itr)
+ InviteGroupToBG((*itr), bg, (*itr)->Team);
+ for(GroupsQueueType::const_iterator itr = m_SelectionPools[BG_TEAM_HORDE].SelectedGroups.begin(); itr != m_SelectionPools[BG_TEAM_HORDE].SelectedGroups.end(); ++itr)
+ InviteGroupToBG((*itr), bg, (*itr)->Team);
+
+ if( !bg->HasFreeSlots() )
{
- //remove BG from BGFreeSlotQueue
+ // remove BG from BGFreeSlotQueue
bg->RemoveFromBGFreeSlotQueue();
}
}
@@ -591,25 +681,29 @@ void BattleGroundQueue::Update(BattleGroundTypeId bgTypeId, uint32 queue_id, uin
// finished iterating through the bgs with free slots, maybe we need to create a new bg
BattleGround * bg_template = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId);
- if(!bg_template)
+ if( !bg_template )
{
sLog.outError("Battleground: Update: bg template not found for %u", bgTypeId);
return;
}
-
// get the min. players per team, properly for larger arenas as well. (must have full teams for arena matches!)
uint32 MinPlayersPerTeam = bg_template->GetMinPlayersPerTeam();
uint32 MaxPlayersPerTeam = bg_template->GetMaxPlayersPerTeam();
- if(bg_template->isArena())
+ if( sBattleGroundMgr.isTesting() )
+ MinPlayersPerTeam = 1;
+ if( bg_template->isArena() )
{
- if(sBattleGroundMgr.isArenaTesting())
+ if( sBattleGroundMgr.isArenaTesting() )
{
MaxPlayersPerTeam = 1;
MinPlayersPerTeam = 1;
}
else
{
- switch(arenatype)
+ //this switch can be much shorter
+ MaxPlayersPerTeam = arenaType;
+ MinPlayersPerTeam = arenaType;
+ /*switch(arenaType)
{
case ARENA_TYPE_2v2:
MaxPlayersPerTeam = 2;
@@ -623,292 +717,189 @@ void BattleGroundQueue::Update(BattleGroundTypeId bgTypeId, uint32 queue_id, uin
MaxPlayersPerTeam = 5;
MinPlayersPerTeam = 5;
break;
- }
+ }*/
}
}
- // BG case
- else
+
+ m_SelectionPools[BG_TEAM_ALLIANCE].Init();
+ m_SelectionPools[BG_TEAM_HORDE].Init();
+
+ if( bg_template->isBattleGround() )
{
- if(sBattleGroundMgr.isTesting())
+ //check if there is premade against premade match
+ if( CheckPremadeMatch(queue_id, bg_template->GetMaxPlayersPerTeam(), bg_template->GetMinPlayersPerTeam()) )
{
- MinPlayersPerTeam = 1;
+ //create new battleground
+ BattleGround * bg2 = NULL;
+ if( !(bg2 = sBattleGroundMgr.CreateNewBattleGround(bgTypeId, queue_id, 0, false)) )
+ {
+ sLog.outError("BattleGroundQueue::Update - Cannot create battleground: %u", bgTypeId);
+ return;
+ }
+ //invite those selection pools
+ for(uint32 i = 0; i < BG_TEAMS_COUNT; i++)
+ for(GroupsQueueType::const_iterator itr = m_SelectionPools[BG_TEAM_ALLIANCE + i].SelectedGroups.begin(); itr != m_SelectionPools[BG_TEAM_ALLIANCE + i].SelectedGroups.end(); ++itr)
+ InviteGroupToBG((*itr), bg2, (*itr)->Team);
+ //start bg
+ bg2->StartBattleGround();
+ //clear structures
+ m_SelectionPools[BG_TEAM_ALLIANCE].Init();
+ m_SelectionPools[BG_TEAM_HORDE].Init();
}
}
- // found out the minimum and maximum ratings the newly added team should battle against
- // arenaRating is the rating of the latest joined team
- uint32 arenaMinRating = (arenaRating <= sBattleGroundMgr.GetMaxRatingDifference()) ? 0 : arenaRating - sBattleGroundMgr.GetMaxRatingDifference();
- // if no rating is specified, set maxrating to 0
- uint32 arenaMaxRating = (arenaRating == 0)? 0 : arenaRating + sBattleGroundMgr.GetMaxRatingDifference();
- uint32 discardTime = 0;
- // if max rating difference is set and the time past since server startup is greater than the rating discard time
- // (after what time the ratings aren't taken into account when making teams) then
- // the discard time is current_time - time_to_discard, teams that joined after that, will have their ratings taken into account
- // else leave the discard time on 0, this way all ratings will be discarded
- if(sBattleGroundMgr.GetMaxRatingDifference() && getMSTime() >= sBattleGroundMgr.GetRatingDiscardTimer())
- discardTime = getMSTime() - sBattleGroundMgr.GetRatingDiscardTimer();
-
- // try to build the selection pools
- bool bAllyOK = BuildSelectionPool(bgTypeId, queue_id, MinPlayersPerTeam, MaxPlayersPerTeam, NORMAL_ALLIANCE, arenatype, isRated, arenaMinRating, arenaMaxRating, discardTime);
- if(bAllyOK)
- sLog.outDebug("Battleground: ally pool successfully built");
- else
- sLog.outDebug("Battleground: ally pool wasn't created");
- bool bHordeOK = BuildSelectionPool(bgTypeId, queue_id, MinPlayersPerTeam, MaxPlayersPerTeam, NORMAL_HORDE, arenatype, isRated, arenaMinRating, arenaMaxRating, discardTime);
- if(bHordeOK)
- sLog.outDebug("Battleground: horde pool successfully built");
- else
- sLog.outDebug("Battleground: horde pool wasn't created");
-
- // if selection pools are ready, create the new bg
- if ((bAllyOK && bHordeOK) || ( sBattleGroundMgr.isTesting() && (bAllyOK || bHordeOK)))
+ // now check if there are in queues enough players to start new game of (normal battleground, or non-rated arena)
+ if( !isRated )
{
- BattleGround * bg2 = 0;
- // special handling for arenas
- if(bg_template->isArena())
+ // if there are enough players in pools, start new battleground or non rated arena
+ if( CheckNormalMatch(bg_template, queue_id, MinPlayersPerTeam) )
{
- // Find a random arena, that can be created
- BattleGroundTypeId arenas[] = {BATTLEGROUND_NA, BATTLEGROUND_BE, BATTLEGROUND_RL};
- uint32 arena_num = urand(0,2);
- if( !(bg2 = sBattleGroundMgr.CreateNewBattleGround(arenas[arena_num%3])) &&
- !(bg2 = sBattleGroundMgr.CreateNewBattleGround(arenas[(arena_num+1)%3])) &&
- !(bg2 = sBattleGroundMgr.CreateNewBattleGround(arenas[(arena_num+2)%3])) )
+ // we successfully created a pool
+ BattleGround * bg2 = NULL;
+ if( !(bg2 = sBattleGroundMgr.CreateNewBattleGround(bgTypeId, queue_id, arenaType, false)) )
{
- sLog.outError("Battleground: couldn't create any arena instance!");
+ sLog.outError("BattleGroundQueue::Update - Cannot create battleground: %u", bgTypeId);
return;
}
- // set the MaxPlayersPerTeam values based on arenatype
- // setting the min player values isn't needed, since we won't be using that value later on.
- if(sBattleGroundMgr.isArenaTesting())
+ // invite those selection pools
+ for(uint32 i = 0; i < BG_TEAMS_COUNT; i++)
+ for(GroupsQueueType::const_iterator itr = m_SelectionPools[BG_TEAM_ALLIANCE + i].SelectedGroups.begin(); itr != m_SelectionPools[BG_TEAM_ALLIANCE + i].SelectedGroups.end(); ++itr)
+ InviteGroupToBG((*itr), bg2, (*itr)->Team);
+ // start bg
+ bg2->StartBattleGround();
+ }
+ }
+ else if( bg_template->isArena() )
+ {
+ // found out the minimum and maximum ratings the newly added team should battle against
+ // arenaRating is the rating of the latest joined team, or 0
+ // 0 is on (automatic update call) and we must set it to team's with longest wait time
+ if ( !arenaRating )
+ {
+ GroupQueueInfo* front1 = NULL;
+ GroupQueueInfo* front2 = NULL;
+ if( !m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_ALLIANCE].empty() )
{
- bg2->SetMaxPlayersPerTeam(1);
- bg2->SetMaxPlayers(2);
+ front1 = m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_ALLIANCE].front();
+ arenaRating = front1->ArenaTeamRating;
}
- else
+ if( !m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_HORDE].empty() )
{
- switch(arenatype)
- {
- case ARENA_TYPE_2v2:
- bg2->SetMaxPlayersPerTeam(2);
- bg2->SetMaxPlayers(4);
- break;
- case ARENA_TYPE_3v3:
- bg2->SetMaxPlayersPerTeam(3);
- bg2->SetMaxPlayers(6);
- break;
- case ARENA_TYPE_5v5:
- bg2->SetMaxPlayersPerTeam(5);
- bg2->SetMaxPlayers(10);
- break;
- default:
- break;
- }
+ front2 = m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_HORDE].front();
+ arenaRating = front2->ArenaTeamRating;
}
- }
- else
- {
- // create new battleground
- bg2 = sBattleGroundMgr.CreateNewBattleGround(bgTypeId);
- if( sWorld.getConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE) )
+ if( front1 && front2 )
{
- char const* bgName = bg2->GetName();
- uint32 q_min_level = Player::GetMinLevelForBattleGroundQueueId(queue_id, bgTypeId);
- uint32 q_max_level = Player::GetMaxLevelForBattleGroundQueueId(queue_id, bgTypeId);
- if(q_max_level > sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL))
- q_max_level = sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL);
- sWorld.SendWorldText(LANG_BG_STARTED_ANNOUNCE_WORLD, bgName, q_min_level, q_max_level);
+ if( front1->JoinTime < front2->JoinTime )
+ arenaRating = front1->ArenaTeamRating;
}
+ else if( !front1 && !front2 )
+ return; //queues are empty
}
- if(!bg2)
- {
- sLog.outError("Battleground: couldn't create bg %u",bgTypeId);
- return;
- }
-
- // start the joining of the bg
- bg2->SetStatus(STATUS_WAIT_JOIN);
- bg2->SetQueueId(queue_id);
- // initialize arena / rating info
- bg2->SetArenaType(arenatype);
- // set rating
- bg2->SetRated(isRated);
-
- std::list<GroupQueueInfo* >::iterator itr;
-
- // invite groups from horde selection pool
- for(itr = m_SelectionPools[NORMAL_HORDE].SelectedGroups.begin(); itr != m_SelectionPools[NORMAL_HORDE].SelectedGroups.end(); ++itr)
- {
- InviteGroupToBG((*itr),bg2,HORDE);
- }
-
- // invite groups from ally selection pools
- for(itr = m_SelectionPools[NORMAL_ALLIANCE].SelectedGroups.begin(); itr != m_SelectionPools[NORMAL_ALLIANCE].SelectedGroups.end(); ++itr)
- {
- InviteGroupToBG((*itr),bg2,ALLIANCE);
- }
-
- if (isRated)
- {
- std::list<GroupQueueInfo* >::iterator itr_alliance = m_SelectionPools[NORMAL_ALLIANCE].SelectedGroups.begin();
- std::list<GroupQueueInfo* >::iterator itr_horde = m_SelectionPools[NORMAL_HORDE].SelectedGroups.begin();
- (*itr_alliance)->OpponentsTeamRating = (*itr_horde)->ArenaTeamRating;
- sLog.outDebug("setting opposite team rating for team %u to %u", (*itr_alliance)->ArenaTeamId, (*itr_alliance)->OpponentsTeamRating);
- (*itr_horde)->OpponentsTeamRating = (*itr_alliance)->ArenaTeamRating;
- sLog.outDebug("setting opposite team rating for team %u to %u", (*itr_horde)->ArenaTeamId, (*itr_horde)->OpponentsTeamRating);
- }
+ //set rating range
+ uint32 arenaMinRating = (arenaRating <= sBattleGroundMgr.GetMaxRatingDifference()) ? 0 : arenaRating - sBattleGroundMgr.GetMaxRatingDifference();
+ uint32 arenaMaxRating = arenaRating + sBattleGroundMgr.GetMaxRatingDifference();
+ // if max rating difference is set and the time past since server startup is greater than the rating discard time
+ // (after what time the ratings aren't taken into account when making teams) then
+ // the discard time is current_time - time_to_discard, teams that joined after that, will have their ratings taken into account
+ // else leave the discard time on 0, this way all ratings will be discarded
+ uint32 discardTime = getMSTime() - sBattleGroundMgr.GetRatingDiscardTimer();
- // start the battleground
- bg2->StartBattleGround();
- }
-
- // there weren't enough players for a "normal" match
- // if arena, enable horde versus horde or alliance versus alliance teams here
-
- else if(bg_template->isArena())
- {
- bool bOneSideHordeTeam1 = false, bOneSideHordeTeam2 = false;
- bool bOneSideAllyTeam1 = false, bOneSideAllyTeam2 = false;
- bOneSideHordeTeam1 = BuildSelectionPool(bgTypeId, queue_id,MaxPlayersPerTeam,MaxPlayersPerTeam,ONESIDE_HORDE_TEAM1,arenatype, isRated, arenaMinRating, arenaMaxRating, discardTime);
- if(bOneSideHordeTeam1)
- {
- // one team has been selected, find out if other can be selected too
- std::list<GroupQueueInfo* >::iterator itr;
- // temporarily change the team side to enable building the next pool excluding the already selected groups
- for(itr = m_SelectionPools[ONESIDE_HORDE_TEAM1].SelectedGroups.begin(); itr != m_SelectionPools[ONESIDE_HORDE_TEAM1].SelectedGroups.end(); ++itr)
- (*itr)->Team=ALLIANCE;
+ // we need to find 2 teams which will play next game
- bOneSideHordeTeam2 = BuildSelectionPool(bgTypeId, queue_id,MaxPlayersPerTeam,MaxPlayersPerTeam,ONESIDE_HORDE_TEAM2,arenatype, isRated, arenaMinRating, arenaMaxRating, discardTime, (*(m_SelectionPools[ONESIDE_HORDE_TEAM1].SelectedGroups.begin()))->ArenaTeamId);
+ GroupsQueueType::iterator itr_team[BG_TEAMS_COUNT];
- // change back the team to horde
- for(itr = m_SelectionPools[ONESIDE_HORDE_TEAM1].SelectedGroups.begin(); itr != m_SelectionPools[ONESIDE_HORDE_TEAM1].SelectedGroups.end(); ++itr)
- (*itr)->Team=HORDE;
+ //optimalization : --- we dont need to use selection_pools - each update we select max 2 groups
- if(!bOneSideHordeTeam2)
- bOneSideHordeTeam1 = false;
- }
- if(!bOneSideHordeTeam1)
+ for(uint32 i = BG_QUEUE_PREMADE_ALLIANCE; i < BG_QUEUE_NORMAL_ALLIANCE; i++)
{
- // check for one sided ally
- bOneSideAllyTeam1 = BuildSelectionPool(bgTypeId, queue_id,MaxPlayersPerTeam,MaxPlayersPerTeam,ONESIDE_ALLIANCE_TEAM1,arenatype, isRated, arenaMinRating, arenaMaxRating, discardTime);
- if(bOneSideAllyTeam1)
+ // take the group that joined first
+ itr_team[i] = m_QueuedGroups[queue_id][i].begin();
+ for(; itr_team[i] != m_QueuedGroups[queue_id][i].end(); ++(itr_team[i]))
{
- // one team has been selected, find out if other can be selected too
- std::list<GroupQueueInfo* >::iterator itr;
- // temporarily change the team side to enable building the next pool excluding the already selected groups
- for(itr = m_SelectionPools[ONESIDE_ALLIANCE_TEAM1].SelectedGroups.begin(); itr != m_SelectionPools[ONESIDE_ALLIANCE_TEAM1].SelectedGroups.end(); ++itr)
- (*itr)->Team=HORDE;
-
- bOneSideAllyTeam2 = BuildSelectionPool(bgTypeId, queue_id,MaxPlayersPerTeam,MaxPlayersPerTeam,ONESIDE_ALLIANCE_TEAM2,arenatype, isRated, arenaMinRating, arenaMaxRating, discardTime,(*(m_SelectionPools[ONESIDE_ALLIANCE_TEAM1].SelectedGroups.begin()))->ArenaTeamId);
-
- // change back the team to ally
- for(itr = m_SelectionPools[ONESIDE_ALLIANCE_TEAM1].SelectedGroups.begin(); itr != m_SelectionPools[ONESIDE_ALLIANCE_TEAM1].SelectedGroups.end(); ++itr)
- (*itr)->Team=ALLIANCE;
+ // if group match conditions, then add it to pool
+ if( !(*itr_team[i])->IsInvitedToBGInstanceGUID
+ && (((*itr_team[i])->ArenaTeamRating >= arenaMinRating && (*itr_team[i])->ArenaTeamRating <= arenaMaxRating)
+ || (*itr_team[i])->JoinTime < discardTime) )
+ {
+ m_SelectionPools[i].AddGroup((*itr_team[i]), MaxPlayersPerTeam);
+ // break for cycle to be able to start selecting another group from same faction queue
+ break;
+ }
}
-
- if(!bOneSideAllyTeam2)
- bOneSideAllyTeam1 = false;
}
- // 1-sided BuildSelectionPool() will work, because the MinPlayersPerTeam == MaxPlayersPerTeam in every arena!!!!
- if( (bOneSideHordeTeam1 && bOneSideHordeTeam2) ||
- (bOneSideAllyTeam1 && bOneSideAllyTeam2) )
+ // now we are done if we have 2 groups - ali vs horde!
+ // if we don't have, we must try to continue search in same queue
+ // tmp variables are correctly set
+ // this code isn't much userfriendly - but it is supposed to continue search for mathing group in HORDE queue
+ if( m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount() == 0 && m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount() )
{
- // which side has enough players?
- uint32 side = 0;
- SelectionPoolBuildMode mode1, mode2;
- // find out what pools are we using
- if(bOneSideAllyTeam1 && bOneSideAllyTeam2)
+ itr_team[BG_TEAM_ALLIANCE] = itr_team[BG_TEAM_HORDE];
+ ++itr_team[BG_TEAM_ALLIANCE];
+ for(; itr_team[BG_TEAM_ALLIANCE] != m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_HORDE].end(); ++(itr_team[BG_TEAM_ALLIANCE]))
{
- side = ALLIANCE;
- mode1 = ONESIDE_ALLIANCE_TEAM1;
- mode2 = ONESIDE_ALLIANCE_TEAM2;
- }
- else
- {
- side = HORDE;
- mode1 = ONESIDE_HORDE_TEAM1;
- mode2 = ONESIDE_HORDE_TEAM2;
- }
-
- // create random arena
- BattleGroundTypeId arenas[] = {BATTLEGROUND_NA, BATTLEGROUND_BE, BATTLEGROUND_RL};
- uint32 arena_num = urand(0,2);
- BattleGround* bg2 = NULL;
- if( !(bg2 = sBattleGroundMgr.CreateNewBattleGround(arenas[arena_num%3])) &&
- !(bg2 = sBattleGroundMgr.CreateNewBattleGround(arenas[(arena_num+1)%3])) &&
- !(bg2 = sBattleGroundMgr.CreateNewBattleGround(arenas[(arena_num+2)%3])) )
- {
- sLog.outError("Could not create arena.");
- return;
- }
-
- sLog.outDebug("Battleground: One-faction arena created.");
- // init stats
- if(sBattleGroundMgr.isArenaTesting())
- {
- bg2->SetMaxPlayersPerTeam(1);
- bg2->SetMaxPlayers(2);
+ if( !(*itr_team[BG_TEAM_ALLIANCE])->IsInvitedToBGInstanceGUID
+ && (((*itr_team[BG_TEAM_ALLIANCE])->ArenaTeamRating >= arenaMinRating && (*itr_team[BG_TEAM_ALLIANCE])->ArenaTeamRating <= arenaMaxRating)
+ || (*itr_team[BG_TEAM_ALLIANCE])->JoinTime < discardTime) )
+ {
+ m_SelectionPools[BG_TEAM_ALLIANCE].AddGroup((*itr_team[BG_TEAM_ALLIANCE]), MaxPlayersPerTeam);
+ break;
+ }
}
- else
+ }
+ // this code isn't much userfriendly - but it is supposed to continue search for mathing group in ALLIANCE queue
+ if( m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount() == 0 && m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount() )
+ {
+ itr_team[BG_TEAM_HORDE] = itr_team[BG_TEAM_ALLIANCE];
+ ++itr_team[BG_TEAM_HORDE];
+ for(; itr_team[BG_TEAM_HORDE] != m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_ALLIANCE].end(); ++(itr_team[BG_TEAM_HORDE]))
{
- switch(arenatype)
+ if( !(*itr_team[BG_TEAM_HORDE])->IsInvitedToBGInstanceGUID
+ && (((*itr_team[BG_TEAM_HORDE])->ArenaTeamRating >= arenaMinRating && (*itr_team[BG_TEAM_HORDE])->ArenaTeamRating <= arenaMaxRating)
+ || (*itr_team[BG_TEAM_HORDE])->JoinTime < discardTime) )
{
- case ARENA_TYPE_2v2:
- bg2->SetMaxPlayersPerTeam(2);
- bg2->SetMaxPlayers(4);
- break;
- case ARENA_TYPE_3v3:
- bg2->SetMaxPlayersPerTeam(3);
- bg2->SetMaxPlayers(6);
- break;
- case ARENA_TYPE_5v5:
- bg2->SetMaxPlayersPerTeam(5);
- bg2->SetMaxPlayers(10);
- break;
- default:
+ m_SelectionPools[BG_TEAM_HORDE].AddGroup((*itr_team[BG_TEAM_HORDE]), MaxPlayersPerTeam);
break;
}
}
+ }
- bg2->SetRated(isRated);
-
- // assigned team of the other group
- uint32 other_side;
- if(side == ALLIANCE)
- other_side = HORDE;
- else
- other_side = ALLIANCE;
-
- // start the joining of the bg
- bg2->SetStatus(STATUS_WAIT_JOIN);
- bg2->SetQueueId(queue_id);
- // initialize arena / rating info
- bg2->SetArenaType(arenatype);
-
- std::list<GroupQueueInfo* >::iterator itr;
-
- // invite players from the first group as horde players (actually green team)
- for(itr = m_SelectionPools[mode1].SelectedGroups.begin(); itr != m_SelectionPools[mode1].SelectedGroups.end(); ++itr)
+ //if we have 2 teams, then start new arena and invite players!
+ if( m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount() && m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount() )
+ {
+ BattleGround* arena = NULL;
+ if( !(arena = sBattleGroundMgr.CreateNewBattleGround(bgTypeId, queue_id, arenaType, true)) )
{
- InviteGroupToBG((*itr),bg2,HORDE);
+ sLog.outError("BattlegroundQueue::Update couldn't create arena instance for rated arena match!");
+ return;
}
- // invite players from the second group as ally players (actually gold team)
- for(itr = m_SelectionPools[mode2].SelectedGroups.begin(); itr != m_SelectionPools[mode2].SelectedGroups.end(); ++itr)
+ (*(itr_team[BG_TEAM_ALLIANCE]))->OpponentsTeamRating = (*(itr_team[BG_TEAM_HORDE]))->ArenaTeamRating;
+ sLog.outDebug("setting oposite teamrating for team %u to %u", (*(itr_team[BG_TEAM_ALLIANCE]))->ArenaTeamId, (*(itr_team[BG_TEAM_ALLIANCE]))->OpponentsTeamRating);
+ (*(itr_team[BG_TEAM_HORDE]))->OpponentsTeamRating = (*(itr_team[BG_TEAM_ALLIANCE]))->ArenaTeamRating;
+ sLog.outDebug("setting oposite teamrating for team %u to %u", (*(itr_team[BG_TEAM_HORDE]))->ArenaTeamId, (*(itr_team[BG_TEAM_HORDE]))->OpponentsTeamRating);
+ // now we must move team if we changed its faction to another faction queue, because then we will spam log by errors in Queue::RemovePlayer
+ if( (*(itr_team[BG_TEAM_ALLIANCE]))->Team != ALLIANCE )
{
- InviteGroupToBG((*itr),bg2,ALLIANCE);
+ // add to alliance queue
+ m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_ALLIANCE].push_front(*(itr_team[BG_TEAM_ALLIANCE]));
+ // erase from horde queue
+ m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_HORDE].erase(itr_team[BG_TEAM_ALLIANCE]);
}
-
- if (isRated)
+ if( (*(itr_team[BG_TEAM_HORDE]))->Team != HORDE )
{
- std::list<GroupQueueInfo* >::iterator itr_alliance = m_SelectionPools[mode1].SelectedGroups.begin();
- std::list<GroupQueueInfo* >::iterator itr_horde = m_SelectionPools[mode2].SelectedGroups.begin();
- (*itr_alliance)->OpponentsTeamRating = (*itr_horde)->ArenaTeamRating;
- (*itr_horde)->OpponentsTeamRating = (*itr_alliance)->ArenaTeamRating;
+ m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_HORDE].push_front(*(itr_team[BG_TEAM_HORDE]));
+ m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_ALLIANCE].erase(itr_team[BG_TEAM_HORDE]);
}
- bg2->StartBattleGround();
+ InviteGroupToBG(*(itr_team[BG_TEAM_ALLIANCE]), arena, ALLIANCE);
+ InviteGroupToBG(*(itr_team[BG_TEAM_HORDE]), arena, HORDE);
+
+ sLog.outDebug("Starting rated arena match!");
+
+ arena->StartBattleGround();
}
}
}
@@ -926,26 +917,22 @@ bool BGQueueInviteEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
return true;
// Player can be in another BG queue and must be removed in normal way in any case
- // // player is already in battleground ... do nothing (battleground queue status is deleted when player is teleported to BG)
- // if (plr->GetBattleGroundId() > 0)
- // return true;
BattleGround* bg = sBattleGroundMgr.GetBattleGround(m_BgInstanceGUID);
if (!bg)
return true;
BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType());
- BattleGroundTypeId bgTypeId = BattleGroundMgr::BGTemplateId(bgQueueTypeId);
uint32 queueSlot = plr->GetBattleGroundQueueIndex(bgQueueTypeId);
if (queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES) // player is in queue
{
// 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
- BattleGroundQueue::QueuedPlayersMap const& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[plr->GetBattleGroundQueueIdFromLevel(bgTypeId)];
+ BattleGroundQueue::QueuedPlayersMap const& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers;
BattleGroundQueue::QueuedPlayersMap::const_iterator qItr = qpMap.find(m_PlayerGuid);
if (qItr != qpMap.end() && qItr->second.GroupInfo->IsInvitedToBGInstanceGUID == m_BgInstanceGUID)
{
WorldPacket data;
- sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, qItr->second.GroupInfo->Team, queueSlot, STATUS_WAIT_JOIN, INVITE_ACCEPT_WAIT_TIME/2, 0);
+ sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, qItr->second.GroupInfo->Team, queueSlot, STATUS_WAIT_JOIN, INVITATION_REMIND_TIME, 0);
plr->GetSession()->SendPacket(&data);
}
}
@@ -976,8 +963,7 @@ bool BGQueueRemoveEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
if (queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES) // player is in queue
{
// 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
- uint32 queue_id=plr->GetBattleGroundQueueIdFromLevel(bg->GetTypeID());
- BattleGroundQueue::QueuedPlayersMap& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[queue_id];
+ BattleGroundQueue::QueuedPlayersMap& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers;
BattleGroundQueue::QueuedPlayersMap::iterator qMapItr = qpMap.find(m_PlayerGuid);
if (qMapItr != qpMap.end() && qMapItr->second.GroupInfo && qMapItr->second.GroupInfo->IsInvitedToBGInstanceGUID == m_BgInstanceGUID)
{
@@ -993,7 +979,7 @@ bool BGQueueRemoveEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
}
plr->RemoveBattleGroundQueueId(bgQueueTypeId);
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].RemovePlayer(m_PlayerGuid, true);
- sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bg->GetTypeID(),bg->GetQueueId());
+ sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bg->GetTypeID(), bg->GetQueueId());
WorldPacket data;
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, m_PlayersTeam, queueSlot, STATUS_NONE, 0, 0);
plr->GetSession()->SendPacket(&data);
@@ -1065,15 +1051,19 @@ void BattleGroundMgr::Update(uint32 diff)
}
}
// if rating difference counts, maybe force-update queues
- if(sWorld.getConfig(CONFIG_ARENA_MAX_RATING_DIFFERENCE))
+ if(sWorld.getConfig(CONFIG_ARENA_MAX_RATING_DIFFERENCE) && sWorld.getConfig(CONFIG_ARENA_RATING_DISCARD_TIMER))
{
// it's time to force update
if(m_NextRatingDiscardUpdate < diff)
{
// forced update for level 70 rated arenas
- m_BattleGroundQueues[BATTLEGROUND_QUEUE_2v2].Update(BATTLEGROUND_AA,6,ARENA_TYPE_2v2,true,0);
- m_BattleGroundQueues[BATTLEGROUND_QUEUE_3v3].Update(BATTLEGROUND_AA,6,ARENA_TYPE_3v3,true,0);
- m_BattleGroundQueues[BATTLEGROUND_QUEUE_5v5].Update(BATTLEGROUND_AA,6,ARENA_TYPE_5v5,true,0);
+ sLog.outDebug("BattleGroundMgr: UPDATING ARENA QUEUES");
+ m_BattleGroundQueues[BATTLEGROUND_QUEUE_2v2].Update(BATTLEGROUND_AA, QUEUE_ID_MAX_LEVEL_79, ARENA_TYPE_2v2, true, 0);
+ m_BattleGroundQueues[BATTLEGROUND_QUEUE_2v2].Update(BATTLEGROUND_AA, QUEUE_ID_MAX_LEVEL_80, ARENA_TYPE_2v2, true, 0);
+ m_BattleGroundQueues[BATTLEGROUND_QUEUE_3v3].Update(BATTLEGROUND_AA, QUEUE_ID_MAX_LEVEL_79, ARENA_TYPE_3v3, true, 0);
+ m_BattleGroundQueues[BATTLEGROUND_QUEUE_3v3].Update(BATTLEGROUND_AA, QUEUE_ID_MAX_LEVEL_80, ARENA_TYPE_3v3, true, 0);
+ m_BattleGroundQueues[BATTLEGROUND_QUEUE_5v5].Update(BATTLEGROUND_AA, QUEUE_ID_MAX_LEVEL_79, ARENA_TYPE_5v5, true, 0);
+ m_BattleGroundQueues[BATTLEGROUND_QUEUE_5v5].Update(BATTLEGROUND_AA, QUEUE_ID_MAX_LEVEL_80, ARENA_TYPE_5v5, true, 0);
m_NextRatingDiscardUpdate = sWorld.getConfig(CONFIG_ARENA_RATING_DISCARD_TIMER);
}
else
@@ -1366,7 +1356,7 @@ void BattleGroundMgr::InvitePlayer(Player* plr, uint32 bgInstanceGUID, uint32 te
// create invite events:
//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
BGQueueInviteEvent* inviteEvent = new BGQueueInviteEvent(plr->GetGUID(), bgInstanceGUID);
- plr->m_Events.AddEvent(inviteEvent, plr->m_Events.CalculateTime(INVITE_ACCEPT_WAIT_TIME/2));
+ plr->m_Events.AddEvent(inviteEvent, plr->m_Events.CalculateTime(INVITATION_REMIND_TIME));
BGQueueRemoveEvent* removeEvent = new BGQueueRemoveEvent(plr->GetGUID(), bgInstanceGUID, team);
plr->m_Events.AddEvent(removeEvent, plr->m_Events.CalculateTime(INVITE_ACCEPT_WAIT_TIME));
}
@@ -1377,7 +1367,7 @@ BattleGround * BattleGroundMgr::GetBattleGroundTemplate(BattleGroundTypeId bgTyp
}
// create a new battleground that will really be used to play
-BattleGround * BattleGroundMgr::CreateNewBattleGround(BattleGroundTypeId bgTypeId)
+BattleGround * BattleGroundMgr::CreateNewBattleGround(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLevel queue_id, uint8 arenaType, bool isRated)
{
// get the template BG
BattleGround *bg_template = GetBattleGroundTemplate(bgTypeId);
@@ -1387,8 +1377,21 @@ BattleGround * BattleGroundMgr::CreateNewBattleGround(BattleGroundTypeId bgTypeI
return NULL;
}
- BattleGround *bg = NULL;
+ //for arenas there is random map used
+ if(bg_template->isArena())
+ {
+ BattleGroundTypeId arenas[] = {BATTLEGROUND_NA, BATTLEGROUND_BE, BATTLEGROUND_RL};
+ uint32 arena_num = urand(0,2);
+ bgTypeId = arenas[arena_num];
+ bg_template = GetBattleGroundTemplate(bgTypeId);
+ if(!bg_template)
+ {
+ sLog.outError("BattleGround: CreateNewBattleGround - bg template not found for %u", bgTypeId);
+ return NULL;
+ }
+ }
+ BattleGround *bg = NULL;
// create a copy of the BG template
switch(bgTypeId)
{
@@ -1436,13 +1439,21 @@ BattleGround * BattleGroundMgr::CreateNewBattleGround(BattleGroundTypeId bgTypeI
// reset the new bg (set status to status_wait_queue from status_none)
bg->Reset();
- /* will be setup in BG::Update() when the first player is ported in
- if(!(bg->SetupBattleGround()))
+ if( bg->isBattleGround() && sWorld.getConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE) )
{
- sLog.outError("BattleGround: CreateNewBattleGround: SetupBattleGround failed for bg %u", bgTypeId);
- delete bg;
- return 0;
+ sWorld.SendWorldText(LANG_BG_STARTED_ANNOUNCE_WORLD, bg->GetName(), bg->GetMinLevel(), bg->GetMaxLevel());
}
+
+ // start the joining of the bg
+ bg->SetStatus(STATUS_WAIT_JOIN);
+ bg->SetQueueId(queue_id);
+ // initialize arena / rating info
+ bg->SetArenaType(arenaType);
+ // set rating
+ bg->SetRated(isRated);
+
+ /* will be setup in BG::Update() when the first player is ported in
+ if(!(bg->SetupBattleGround()))
*/
// add BG to free slot queue
@@ -1870,7 +1881,11 @@ void BattleGroundMgr::SetHolidayWeekends(uint32 mask)
uint32 BattleGroundMgr::GetMaxRatingDifference() const
{
- return sWorld.getConfig(CONFIG_ARENA_MAX_RATING_DIFFERENCE);
+ // this is for stupid people who can't use brain and set max rating difference to 0
+ uint32 diff = sWorld.getConfig(CONFIG_ARENA_MAX_RATING_DIFFERENCE);
+ if (diff == 0)
+ diff = 5000;
+ return diff;
}
uint32 BattleGroundMgr::GetRatingDiscardTimer() const
diff --git a/src/game/BattleGroundMgr.h b/src/game/BattleGroundMgr.h
index 11ff62ab37f..1c2a1d8a093 100644
--- a/src/game/BattleGroundMgr.h
+++ b/src/game/BattleGroundMgr.h
@@ -27,15 +27,11 @@
//TODO it is not possible to have this structure, because we should have BattlegroundSet for each queue
//so i propose to change this type to array 1..MAX_BATTLEGROUND_TYPES of sets or maps..
typedef std::map<uint32, BattleGround*> BattleGroundSet;
-//typedef std::map<uint32, BattleGroundQueue*> BattleGroundQueueSet;
+
typedef std::deque<BattleGround*> BGFreeSlotQueueType;
typedef UNORDERED_MAP<uint32, BattleGroundTypeId> BattleMastersMap;
-#define MAX_BATTLEGROUND_QUEUES 8 // for level ranges 10-19, 20-29, 30-39, 40-49, 50-59, 60-69, 70-79, 80+
-
-#define MAX_BATTLEGROUND_QUEUE_TYPES 9
-
#define BATTLEGROUND_ARENA_POINT_DISTRIBUTION_DAY 86400 // seconds in a day
struct GroupQueueInfo; // type predefinition
@@ -61,6 +57,15 @@ struct GroupQueueInfo // stores informatio
uint32 OpponentsTeamRating; // for rated arena matches
};
+enum BattleGroundQueueGroupTypes
+{
+ BG_QUEUE_PREMADE_ALLIANCE = 0,
+ BG_QUEUE_PREMADE_HORDE = 1,
+ BG_QUEUE_NORMAL_ALLIANCE = 2,
+ BG_QUEUE_NORMAL_HORDE = 3
+};
+#define BG_QUEUE_GROUP_TYPES_COUNT 4
+
class BattleGround;
class BattleGroundQueue
{
@@ -68,9 +73,12 @@ class BattleGroundQueue
BattleGroundQueue();
~BattleGroundQueue();
- void Update(BattleGroundTypeId bgTypeId, uint32 queue_id, uint8 arenatype = 0, bool isRated = false, uint32 minRating = 0);
+ void Update(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLevel queue_id, uint8 arenaType = 0, bool isRated = false, uint32 minRating = 0);
- GroupQueueInfo * AddGroup(Player * leader, BattleGroundTypeId bgTypeId, uint8 ArenaType, bool isRated, uint32 ArenaRating, uint32 ArenaTeamId = 0);
+ void FillPlayersToBG(BattleGround* bg, BGQueueIdBasedOnLevel queue_id);
+ bool CheckPremadeMatch(BGQueueIdBasedOnLevel queue_id, uint32 MaxPlayersPerTeam, uint32 MinPlayersPerTeam);
+ bool CheckNormalMatch(BattleGround* bg_template, BGQueueIdBasedOnLevel queue_id, uint32 MinPlayersPerTeam);
+ GroupQueueInfo * AddGroup(Player * leader, BattleGroundTypeId bgTypeId, uint8 ArenaType, bool isRated, bool isPremade, uint32 ArenaRating, uint32 ArenaTeamId = 0);
void AddPlayer(Player *plr, GroupQueueInfo *ginfo);
void RemovePlayer(const uint64& guid, bool decreaseInvitedCount);
void DecreaseGroupLength(uint32 queueId, uint32 AsGroup);
@@ -78,51 +86,38 @@ class BattleGroundQueue
void AnnounceWorld(GroupQueueInfo *ginfo, const uint64& playerGUID, bool isAddedToQueue);
typedef std::map<uint64, PlayerQueueInfo> QueuedPlayersMap;
- QueuedPlayersMap m_QueuedPlayers[MAX_BATTLEGROUND_QUEUES];
-
- typedef std::list<GroupQueueInfo*> QueuedGroupsList;
- QueuedGroupsList m_QueuedGroups[MAX_BATTLEGROUND_QUEUES];
-
- // class to hold pointers to the groups eligible for a specific selection pool building mode
- class EligibleGroups : public std::list<GroupQueueInfo *>
- {
- public:
- void Init(QueuedGroupsList * source, BattleGroundTypeId BgTypeId, uint32 side, uint32 MaxPlayers, uint8 ArenaType = 0, bool IsRated = false, uint32 MinRating = 0, uint32 MaxRating = 0, uint32 DisregardTime = 0, uint32 excludeTeam = 0);
- };
-
- EligibleGroups m_EligibleGroups;
+ QueuedPlayersMap m_QueuedPlayers;
+
+ //we need constant add to begin and constant remove / add from the end, therefore deque suits our problem well
+ typedef std::deque<GroupQueueInfo*> GroupsQueueType;
+
+ /*
+ This two dimensional array is used to store All queued groups
+ First dimension specifies the bgTypeId
+ Second dimension specifies the player's group types -
+ BG_QUEUE_PREMADE_ALLIANCE is used for premade alliance groups and alliance rated arena teams
+ BG_QUEUE_PREMADE_HORDE is used for premade horde groups and horde rated arena teams
+ BG_QUEUE_NORMAL_ALLIANCE is used for normal (or small) alliance groups or non-rated arena matches
+ BG_QUEUE_NORMAL_HORDE is used for normal (or small) horde groups or non-rated arena matches
+ */
+ GroupsQueueType m_QueuedGroups[MAX_BATTLEGROUND_QUEUES][BG_QUEUE_GROUP_TYPES_COUNT];
// class to select and invite groups to bg
class SelectionPool
{
public:
- void Init(EligibleGroups * curr);
- void AddGroup(GroupQueueInfo * group);
- void RemoveGroup(GroupQueueInfo * group);
+ void Init();
+ bool AddGroup(GroupQueueInfo *ginfo, uint32 desiredCount);
+ bool KickGroup(uint32 size);
uint32 GetPlayerCount() const {return PlayerCount;}
- bool Build(uint32 MinPlayers, uint32 MaxPlayers, EligibleGroups::iterator startitr);
public:
- std::list<GroupQueueInfo *> SelectedGroups;
+ GroupsQueueType SelectedGroups;
private:
uint32 PlayerCount;
- EligibleGroups * m_CurrEligGroups;
};
- enum SelectionPoolBuildMode
- {
- NORMAL_ALLIANCE,
- NORMAL_HORDE,
- ONESIDE_ALLIANCE_TEAM1,
- ONESIDE_ALLIANCE_TEAM2,
- ONESIDE_HORDE_TEAM1,
- ONESIDE_HORDE_TEAM2,
-
- NUM_SELECTION_POOL_TYPES
- };
-
- SelectionPool m_SelectionPools[NUM_SELECTION_POOL_TYPES];
-
- bool BuildSelectionPool(BattleGroundTypeId bgTypeId, uint32 queue_id, uint32 MinPlayers, uint32 MaxPlayers, SelectionPoolBuildMode mode, uint8 ArenaType = 0, bool isRated = false, uint32 MinRating = 0, uint32 MaxRating = 0, uint32 DisregardTime = 0, uint32 excludeTeam = 0);
+ //one selection pool for horde, other one for alliance
+ SelectionPool m_SelectionPools[BG_TEAMS_COUNT];
private:
@@ -183,8 +178,8 @@ class BattleGroundMgr
void BuildPvpLogDataPacket(WorldPacket *data, BattleGround *bg);
void BuildBattleGroundStatusPacket(WorldPacket *data, BattleGround *bg, uint32 team, uint8 QueueSlot, uint8 StatusID, uint32 Time1, uint32 Time2, uint32 arenatype = 0, uint8 israted = 0);
void BuildPlaySoundPacket(WorldPacket *data, uint32 soundid);
-
void SendAreaSpiritHealerQueryOpcode(Player *pl, BattleGround *bg, const uint64& guid);
+
/* Player invitation */
// called from Queue update, or from Addplayer to queue
void InvitePlayer(Player* plr, uint32 bgInstanceGUID, uint32 team);
@@ -200,7 +195,7 @@ class BattleGroundMgr
};
BattleGround * GetBattleGroundTemplate(BattleGroundTypeId bgTypeId);
- BattleGround * CreateNewBattleGround(BattleGroundTypeId bgTypeId);
+ BattleGround * CreateNewBattleGround(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLevel queue_id, uint8 arenaType, bool isRated);
uint32 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);
diff --git a/src/game/Group.cpp b/src/game/Group.cpp
index 33dc3226ec2..1a2301a0fb7 100644
--- a/src/game/Group.cpp
+++ b/src/game/Group.cpp
@@ -1348,7 +1348,7 @@ uint32 Group::CanJoinBattleGroundQueue(BattleGroundTypeId bgTypeId, BattleGround
if(!reference)
return BG_JOIN_ERR_OFFLINE_MEMBER;
- uint32 queue_id = reference->GetBattleGroundQueueIdFromLevel(bgTypeId);
+ BGQueueIdBasedOnLevel queue_id = reference->GetBattleGroundQueueIdFromLevel(bgTypeId);
uint32 arenaTeamId = reference->GetArenaTeamId(arenaSlot);
uint32 team = reference->GetTeam();
diff --git a/src/game/Player.cpp b/src/game/Player.cpp
index fb5fcb3f089..a5466edebd8 100644
--- a/src/game/Player.cpp
+++ b/src/game/Player.cpp
@@ -19035,34 +19035,20 @@ bool Player::GetBGAccessByLevel(BattleGroundTypeId bgTypeId) const
return true;
}
-uint32 Player::GetMinLevelForBattleGroundQueueId(uint32 queue_id, BattleGroundTypeId bgTypeId)
+BGQueueIdBasedOnLevel Player::GetBattleGroundQueueIdFromLevel(BattleGroundTypeId bgTypeId) const
{
- BattleGround *bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId);
- assert(bg);
- return (queue_id*10)+bg->GetMinLevel();
-}
-
-uint32 Player::GetMaxLevelForBattleGroundQueueId(uint32 queue_id, BattleGroundTypeId bgTypeId)
-{
- return GetMinLevelForBattleGroundQueueId(queue_id, bgTypeId)+10;
-}
+ //returned to hardcoded version of this function, because there is no way to code it dynamic
+ uint32 level = getLevel();
+ if( bgTypeId == BATTLEGROUND_QUEUE_AV )
+ level--;
-uint32 Player::GetBattleGroundQueueIdFromLevel(BattleGroundTypeId bgTypeId) const
-{
- BattleGround *bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId);
- assert(bg);
- if(getLevel()<bg->GetMinLevel())
- {
- sLog.outError("getting queue_id for player who doesn't meet the requirements - this shouldn't happen");
- return 0;
- }
- uint32 queue_id = (getLevel() - bg->GetMinLevel()) / 10;
- if(queue_id>MAX_BATTLEGROUND_QUEUES)
+ uint32 queue_id = (level / 10) - 1; // for ranges 0 - 19, 20 - 29, 30 - 39, 40 - 49, 50 - 59, 60 - 69, 70 -79, 80
+ if( queue_id >= MAX_BATTLEGROUND_QUEUES )
{
- sLog.outError("to high queue_id %u this shouldn't happen",queue_id);
- return 0;
+ sLog.outError("BattleGround: too high queue_id %u this shouldn't happen", queue_id);
+ return QUEUE_ID_MAX_LEVEL_80;
}
- return queue_id;
+ return BGQueueIdBasedOnLevel(queue_id);
}
float Player::GetReputationPriceDiscount( Creature const* pCreature ) const
diff --git a/src/game/Player.h b/src/game/Player.h
index 5904f8e948e..00c07d039ae 100644
--- a/src/game/Player.h
+++ b/src/game/Player.h
@@ -1862,14 +1862,13 @@ class TRINITY_DLL_SPEC Player : public Unit
/*** BATTLEGROUND SYSTEM ***/
/*********************************************************/
- bool InBattleGround() const { return m_bgBattleGroundID != 0; }
- uint32 GetBattleGroundId() const { return m_bgBattleGroundID; }
- BattleGround* GetBattleGround() const;
+ bool InBattleGround() const { return m_bgBattleGroundID != 0; }
bool InArena() const;
+ uint32 GetBattleGroundId() const { return m_bgBattleGroundID; }
+ BattleGround* GetBattleGround() const;
+
- static uint32 GetMinLevelForBattleGroundQueueId(uint32 queue_id, BattleGroundTypeId bgTypeId);
- static uint32 GetMaxLevelForBattleGroundQueueId(uint32 queue_id, BattleGroundTypeId bgTypeId);
- uint32 GetBattleGroundQueueIdFromLevel(BattleGroundTypeId bgTypeId) const;
+ BGQueueIdBasedOnLevel GetBattleGroundQueueIdFromLevel(BattleGroundTypeId bgTypeId) const;
bool InBattleGroundQueue() const
{
diff --git a/src/game/World.cpp b/src/game/World.cpp
index e073633fc26..dd9beb10efb 100644
--- a/src/game/World.cpp
+++ b/src/game/World.cpp
@@ -627,21 +627,21 @@ void World::LoadConfigSettings(bool reload)
else
m_configs[CONFIG_REALM_ZONE] = sConfig.GetIntDefault("RealmZone", REALM_ZONE_DEVELOPMENT);
- m_configs[CONFIG_ALLOW_TWO_SIDE_ACCOUNTS] = sConfig.GetBoolDefault("AllowTwoSide.Accounts", false);
+ m_configs[CONFIG_ALLOW_TWO_SIDE_ACCOUNTS] = sConfig.GetBoolDefault("AllowTwoSide.Accounts", false);
m_configs[CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHAT] = sConfig.GetBoolDefault("AllowTwoSide.Interaction.Chat",false);
m_configs[CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHANNEL] = sConfig.GetBoolDefault("AllowTwoSide.Interaction.Channel",false);
m_configs[CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP] = sConfig.GetBoolDefault("AllowTwoSide.Interaction.Group",false);
m_configs[CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD] = sConfig.GetBoolDefault("AllowTwoSide.Interaction.Guild",false);
m_configs[CONFIG_ALLOW_TWO_SIDE_INTERACTION_AUCTION] = sConfig.GetBoolDefault("AllowTwoSide.Interaction.Auction",false);
m_configs[CONFIG_ALLOW_TWO_SIDE_INTERACTION_MAIL] = sConfig.GetBoolDefault("AllowTwoSide.Interaction.Mail",false);
- m_configs[CONFIG_ALLOW_TWO_SIDE_WHO_LIST] = sConfig.GetBoolDefault("AllowTwoSide.WhoList", false);
- m_configs[CONFIG_ALLOW_TWO_SIDE_ADD_FRIEND] = sConfig.GetBoolDefault("AllowTwoSide.AddFriend", false);
- m_configs[CONFIG_ALLOW_TWO_SIDE_TRADE] = sConfig.GetBoolDefault("AllowTwoSide.trade", false);
- m_configs[CONFIG_STRICT_PLAYER_NAMES] = sConfig.GetIntDefault("StrictPlayerNames", 0);
- m_configs[CONFIG_STRICT_CHARTER_NAMES] = sConfig.GetIntDefault("StrictCharterNames", 0);
- m_configs[CONFIG_STRICT_PET_NAMES] = sConfig.GetIntDefault("StrictPetNames", 0);
+ m_configs[CONFIG_ALLOW_TWO_SIDE_WHO_LIST] = sConfig.GetBoolDefault("AllowTwoSide.WhoList", false);
+ m_configs[CONFIG_ALLOW_TWO_SIDE_ADD_FRIEND] = sConfig.GetBoolDefault("AllowTwoSide.AddFriend", false);
+ m_configs[CONFIG_ALLOW_TWO_SIDE_TRADE] = sConfig.GetBoolDefault("AllowTwoSide.trade", false);
+ m_configs[CONFIG_STRICT_PLAYER_NAMES] = sConfig.GetIntDefault ("StrictPlayerNames", 0);
+ m_configs[CONFIG_STRICT_CHARTER_NAMES] = sConfig.GetIntDefault ("StrictCharterNames", 0);
+ m_configs[CONFIG_STRICT_PET_NAMES] = sConfig.GetIntDefault ("StrictPetNames", 0);
- m_configs[CONFIG_CHARACTERS_CREATING_DISABLED] = sConfig.GetIntDefault("CharactersCreatingDisabled", 0);
+ m_configs[CONFIG_CHARACTERS_CREATING_DISABLED] = sConfig.GetIntDefault ("CharactersCreatingDisabled", 0);
m_configs[CONFIG_CHARACTERS_PER_REALM] = sConfig.GetIntDefault("CharactersPerRealm", 10);
if(m_configs[CONFIG_CHARACTERS_PER_REALM] < 1 || m_configs[CONFIG_CHARACTERS_PER_REALM] > 10)
@@ -775,13 +775,6 @@ void World::LoadConfigSettings(bool reload)
m_configs[CONFIG_INSTANCE_IGNORE_LEVEL] = sConfig.GetBoolDefault("Instance.IgnoreLevel", false);
m_configs[CONFIG_INSTANCE_IGNORE_RAID] = sConfig.GetBoolDefault("Instance.IgnoreRaid", false);
- m_configs[CONFIG_BATTLEGROUND_CAST_DESERTER] = sConfig.GetBoolDefault("Battleground.CastDeserter", true);
- m_configs[CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE] = sConfig.GetBoolDefault("Battleground.QueueAnnouncer.Enable", false);
- m_configs[CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_PLAYERONLY] = sConfig.GetBoolDefault("Battleground.QueueAnnouncer.PlayerOnly", false);
- m_configs[CONFIG_ARENA_QUEUE_ANNOUNCER_ENABLE] = sConfig.GetBoolDefault("Arena.QueueAnnouncer.Enable", false);
- m_configs[CONFIG_ARENA_SEASON_ID] = sConfig.GetIntDefault ("Arena.ArenaSeason.ID", 1);
- m_configs[CONFIG_ARENA_SEASON_IN_PROGRESS] = sConfig.GetBoolDefault("Arena.ArenaSeason.InProgress", true);
-
m_configs[CONFIG_CAST_UNSTUCK] = sConfig.GetBoolDefault("CastUnstuck", true);
m_configs[CONFIG_INSTANCE_RESET_TIME_HOUR] = sConfig.GetIntDefault("Instance.ResetTimeHour", 4);
m_configs[CONFIG_INSTANCE_UNLOAD_DELAY] = sConfig.GetIntDefault("Instance.UnloadDelay", 1800000);
@@ -916,23 +909,23 @@ void World::LoadConfigSettings(bool reload)
m_configs[CONFIG_DETECT_POS_COLLISION] = sConfig.GetBoolDefault("DetectPosCollision", true);
- m_configs[CONFIG_RESTRICTED_LFG_CHANNEL] = sConfig.GetBoolDefault("Channel.RestrictedLfg", true);
+ m_configs[CONFIG_RESTRICTED_LFG_CHANNEL] = sConfig.GetBoolDefault("Channel.RestrictedLfg", true);
m_configs[CONFIG_SILENTLY_GM_JOIN_TO_CHANNEL] = sConfig.GetBoolDefault("Channel.SilentlyGMJoin", false);
- m_configs[CONFIG_TALENTS_INSPECTING] = sConfig.GetBoolDefault("TalentsInspecting", true);
+ m_configs[CONFIG_TALENTS_INSPECTING] = sConfig.GetBoolDefault("TalentsInspecting", true);
m_configs[CONFIG_CHAT_FAKE_MESSAGE_PREVENTING] = sConfig.GetBoolDefault("ChatFakeMessagePreventing", false);
- m_configs[CONFIG_CORPSE_DECAY_NORMAL] = sConfig.GetIntDefault("Corpse.Decay.NORMAL", 60);
- m_configs[CONFIG_CORPSE_DECAY_RARE] = sConfig.GetIntDefault("Corpse.Decay.RARE", 300);
- m_configs[CONFIG_CORPSE_DECAY_ELITE] = sConfig.GetIntDefault("Corpse.Decay.ELITE", 300);
+ m_configs[CONFIG_CORPSE_DECAY_NORMAL] = sConfig.GetIntDefault("Corpse.Decay.NORMAL", 60);
+ m_configs[CONFIG_CORPSE_DECAY_RARE] = sConfig.GetIntDefault("Corpse.Decay.RARE", 300);
+ m_configs[CONFIG_CORPSE_DECAY_ELITE] = sConfig.GetIntDefault("Corpse.Decay.ELITE", 300);
m_configs[CONFIG_CORPSE_DECAY_RAREELITE] = sConfig.GetIntDefault("Corpse.Decay.RAREELITE", 300);
m_configs[CONFIG_CORPSE_DECAY_WORLDBOSS] = sConfig.GetIntDefault("Corpse.Decay.WORLDBOSS", 3600);
- m_configs[CONFIG_DEATH_SICKNESS_LEVEL] = sConfig.GetIntDefault("Death.SicknessLevel", 11);
+ m_configs[CONFIG_DEATH_SICKNESS_LEVEL] = sConfig.GetIntDefault ("Death.SicknessLevel", 11);
m_configs[CONFIG_DEATH_CORPSE_RECLAIM_DELAY_PVP] = sConfig.GetBoolDefault("Death.CorpseReclaimDelay.PvP", true);
m_configs[CONFIG_DEATH_CORPSE_RECLAIM_DELAY_PVE] = sConfig.GetBoolDefault("Death.CorpseReclaimDelay.PvE", true);
- m_configs[CONFIG_DEATH_BONES_WORLD] = sConfig.GetBoolDefault("Death.Bones.World", true);
- m_configs[CONFIG_DEATH_BONES_BG_OR_ARENA] = sConfig.GetBoolDefault("Death.Bones.BattlegroundOrArena", true);
+ m_configs[CONFIG_DEATH_BONES_WORLD] = sConfig.GetBoolDefault("Death.Bones.World", true);
+ m_configs[CONFIG_DEATH_BONES_BG_OR_ARENA] = sConfig.GetBoolDefault("Death.Bones.BattlegroundOrArena", true);
m_configs[CONFIG_THREAT_RADIUS] = sConfig.GetIntDefault("ThreatRadius", 60);
@@ -944,12 +937,20 @@ void World::LoadConfigSettings(bool reload)
m_configs[CONFIG_LISTEN_RANGE_TEXTEMOTE] = sConfig.GetIntDefault("ListenRange.TextEmote", 25);
m_configs[CONFIG_LISTEN_RANGE_YELL] = sConfig.GetIntDefault("ListenRange.Yell", 300);
- m_configs[CONFIG_ARENA_MAX_RATING_DIFFERENCE] = sConfig.GetIntDefault("Arena.MaxRatingDifference", 0);
- m_configs[CONFIG_ARENA_RATING_DISCARD_TIMER] = sConfig.GetIntDefault("Arena.RatingDiscardTimer",300000);
- m_configs[CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS] = sConfig.GetBoolDefault("Arena.AutoDistributePoints", false);
- m_configs[CONFIG_ARENA_AUTO_DISTRIBUTE_INTERVAL_DAYS] = sConfig.GetIntDefault("Arena.AutoDistributeInterval", 7);
+ m_configs[CONFIG_BATTLEGROUND_CAST_DESERTER] = sConfig.GetBoolDefault("Battleground.CastDeserter", true);
+ m_configs[CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE] = sConfig.GetBoolDefault("Battleground.QueueAnnouncer.Enable", false);
+ m_configs[CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_PLAYERONLY] = sConfig.GetBoolDefault("Battleground.QueueAnnouncer.PlayerOnly", false);
+ m_configs[CONFIG_BATTLEGROUND_INVITATION_TYPE] = sConfig.GetIntDefault ("Battleground.InvitationType", 0);
+ m_configs[CONFIG_BATTLEGROUND_PREMATURE_FINISH_TIMER] = sConfig.GetIntDefault ("BattleGround.PrematureFinishTimer", 5 * MINUTE * IN_MILISECONDS);
+ m_configs[CONFIG_BATTLEGROUND_PREMADE_GROUP_WAIT_FOR_MATCH] = sConfig.GetIntDefault ("BattleGround.PremadeGroupWaitForMatch", 30 * MINUTE * IN_MILISECONDS);
+ m_configs[CONFIG_ARENA_MAX_RATING_DIFFERENCE] = sConfig.GetIntDefault ("Arena.MaxRatingDifference", 100);
+ m_configs[CONFIG_ARENA_RATING_DISCARD_TIMER] = sConfig.GetIntDefault ("Arena.RatingDiscardTimer", 10 * MINUTE * IN_MILISECONDS);
+ m_configs[CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS] = sConfig.GetBoolDefault("Arena.AutoDistributePoints", false);
+ m_configs[CONFIG_ARENA_AUTO_DISTRIBUTE_INTERVAL_DAYS] = sConfig.GetIntDefault ("Arena.AutoDistributeInterval", 7);
+ m_configs[CONFIG_ARENA_QUEUE_ANNOUNCER_ENABLE] = sConfig.GetBoolDefault("Arena.QueueAnnouncer.Enable", false);
+ m_configs[CONFIG_ARENA_SEASON_ID] = sConfig.GetIntDefault ("Arena.ArenaSeason.ID", 1);
+ m_configs[CONFIG_ARENA_SEASON_IN_PROGRESS] = sConfig.GetBoolDefault("Arena.ArenaSeason.InProgress", true);
- m_configs[CONFIG_BATTLEGROUND_PREMATURE_FINISH_TIMER] = sConfig.GetIntDefault("BattleGround.PrematureFinishTimer", 0);
m_configs[CONFIG_INSTANT_LOGOUT] = sConfig.GetIntDefault("InstantLogout", SEC_MODERATOR);
m_VisibleUnitGreyDistance = sConfig.GetFloatDefault("Visibility.Distance.Grey.Unit", 1);
diff --git a/src/game/World.h b/src/game/World.h
index 8bbbf335625..02577e5e767 100644
--- a/src/game/World.h
+++ b/src/game/World.h
@@ -117,9 +117,6 @@ enum WorldConfigs
CONFIG_START_ARENA_POINTS,
CONFIG_INSTANCE_IGNORE_LEVEL,
CONFIG_INSTANCE_IGNORE_RAID,
- CONFIG_BATTLEGROUND_CAST_DESERTER,
- CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE,
- CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_PLAYERONLY,
CONFIG_INSTANCE_RESET_TIME_HOUR,
CONFIG_INSTANCE_UNLOAD_DELAY,
CONFIG_CAST_UNSTUCK,
@@ -188,6 +185,13 @@ enum WorldConfigs
CONFIG_LISTEN_RANGE_SAY,
CONFIG_LISTEN_RANGE_TEXTEMOTE,
CONFIG_LISTEN_RANGE_YELL,
+ CONFIG_SKILL_MILLING,
+ CONFIG_BATTLEGROUND_CAST_DESERTER,
+ CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE,
+ CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_PLAYERONLY,
+ CONFIG_BATTLEGROUND_INVITATION_TYPE,
+ CONFIG_BATTLEGROUND_PREMATURE_FINISH_TIMER,
+ CONFIG_BATTLEGROUND_PREMADE_GROUP_WAIT_FOR_MATCH,
CONFIG_ARENA_MAX_RATING_DIFFERENCE,
CONFIG_ARENA_RATING_DISCARD_TIMER,
CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS,
@@ -195,8 +199,6 @@ enum WorldConfigs
CONFIG_ARENA_QUEUE_ANNOUNCER_ENABLE,
CONFIG_ARENA_SEASON_ID,
CONFIG_ARENA_SEASON_IN_PROGRESS,
- CONFIG_BATTLEGROUND_PREMATURE_FINISH_TIMER,
- CONFIG_SKILL_MILLING,
CONFIG_MAX_WHO,
CONFIG_BG_START_MUSIC,
CONFIG_START_ALL_SPELLS,
@@ -213,7 +215,6 @@ enum WorldConfigs
CONFIG_INTERVAL_LOG_UPDATE,
CONFIG_MIN_LOG_UPDATE,
CONFIG_ENABLE_SINFO_LOGIN,
-
CONFIG_VALUE_COUNT
};
diff --git a/src/mangosd/mangosd.conf.dist.in b/src/mangosd/mangosd.conf.dist.in
index 516a6bc2a62..ee07906372c 100644
--- a/src/mangosd/mangosd.conf.dist.in
+++ b/src/mangosd/mangosd.conf.dist.in
@@ -503,25 +503,6 @@ LogColors = ""
# Default: 1 (true)
# 0 (false)
#
-# Battleground.CastDeserter
-# Cast or not Deserter spell at player who leave battleground in progress
-# Default: 1 (true)
-# 0 (false)
-#
-# Battleground.QueueAnnouncer.Enable
-# Enable queue announcer posting to chat
-# Default: 0 (false)
-# 1 (true)
-#
-# Battleground.QueueAnnouncer.PlayerOnly
-# Enable queue announcer posting to chat
-# Default: 0 (false)
-# 1 (true)
-#
-# Arena.QueueAnnouncer.Enable: Enable queue announcer posting to chat
-# Default: 0 (false)
-# 1 (true)
-#
# CastUnstuck
# Allow cast or not Unstuck spell at .start or client Help option use
# Default: 1 (true)
@@ -632,10 +613,6 @@ DisableWaterBreath = 4
AllFlightPaths = 0
AlwaysMaxSkillForLevel = 0
ActivateWeather = 1
-Battleground.CastDeserter = 1
-Battleground.QueueAnnouncer.Enable = 0
-Battleground.QueueAnnouncer.PlayerOnly = 0
-Arena.QueueAnnouncer.Enable = 0
CastUnstuck = 1
Instance.IgnoreLevel = 0
Instance.IgnoreRaid = 0
@@ -1168,59 +1145,101 @@ Death.CorpseReclaimDelay.PvE = 0
Death.Bones.World = 1
Death.Bones.BattlegroundOrArena = 1
+
###################################################################################################################
+# BATTLEGROUND CONFIG
#
-# Rated arena matches config
-#
-# MaxRatingDifference: the maximum rating difference between two groups in rated matches
-# Default: 0 (disable, rating difference is discarded)
+# Battleground.CastDeserter
+# Cast or not Deserter spell at player who leave battleground in progress
+# Default: 1 (true)
+# 0 (false)
#
-# RatingDiscardTimer: after the specified milliseconds has passed,
-# rating information will be discarded when selecting teams for matches
-# also initiates an update by this timer
-# Default: 60000
+# Battleground.QueueAnnouncer.Enable
+# Enable queue announcer posting to chat
+# Default: 0 (false)
+# 1 (true)
#
-# AutoDistributePoints: set if arena points should be distributed automatically, or by GM command
-# Default: 0 (disable) (recommended): use gm command or sql query to distribute the points
-# 1 (enable): arena points are distributed automatically
+# Battleground.QueueAnnouncer.PlayerOnly
+# Enable queue announcer posting to chat
+# Default: 0 (false)
+# 1 (true)
#
-# AutoDistributeInterval: how often should the distribution take place
-# if automatic distribution is enabled
-# in days
-# Default: 7 (weekly)
+# Battleground.InvitationType
+# Set Battleground invitation type
+# Default: 0 (normal - invite as much players to bg as possible, don't bother with ballance)
+# 1 (Experimental - don't allow to invite much more players of one faction)
#
-# ArenaSeason.ID: current area season id show in client
-# Default: 1
+# Battleground.PrematureFinishTimer
+# The time to end the bg if there are less than MinPlayersPerTeam on one side in milliseconds
+# Default: 300000 (5 minutes)
+# 0 - disable (not recommended)
#
-# ArenaSeason.InProgress: current area season state
-# Default: 1 (active)
-# 0 (finished)
+# BattleGround.PremadeGroupWaitForMatch
+# The time in which premade group of 1 faction waits in BG Queue for premade group of other faction
+# Default: 1800000 (30 minutes)
+# 0 - disable (not recommended)
#
###################################################################################################################
-Arena.MaxRatingDifference = 0
-Arena.RatingDiscardTimer = 60000
-Arena.AutoDistributePoints = 0
-Arena.AutoDistributeInterval = 7
-Arena.ArenaSeason.ID = 1
-Arena.ArenaSeason.InProgress = 1
+Battleground.CastDeserter = 1
+Battleground.QueueAnnouncer.Enable = 0
+Battleground.QueueAnnouncer.PlayerOnly = 0
+Battleground.InvitationType = 0
+BattleGround.PrematureFinishTimer = 300000
+BattleGround.PremadeGroupWaitForMatch = 1800000
+
###################################################################################################################
+# ARENA CONFIG
+#
+# Arena.MaxRatingDifference
+# The maximum rating difference between two groups in rated matches
+# Default: 100 (enable, recommended)
+# 0 (disable, rating difference is discarded)
+#
+# Arena.RatingDiscardTimer
+# After the specified milliseconds has passed,
+# rating information will be discarded when selecting teams for matches
+# also initiates an update by this timer
+# Default: 600000 (10 minutes, recommended)
+# 0 (disable, DO NOT USE - it will cause lags)
+#
+# Arena.AutoDistributePoints
+# Set if arena points should be distributed automatically, or by GM command
+# Default: 0 (disable) (recommended): use gm command or sql query to distribute the points
+# 1 (enable) arena points are distributed automatically
+#
+# Arena.AutoDistributeInterval
+# How often should the distribution take place
+# If automatic distribution is enabled in days
+# Default: 7 (weekly)
+#
+# Arena.QueueAnnouncer.Enable
+# Enable bg queue announcer posting to chat
+# Default: 0 (false)
+# 1 (true)
#
-# Battleground config
+# Arena.ArenaSeason.ID
+# Current area season id show in client
+# Default: 1
#
-# PrematureFinishTimer: the time to end the bg if there are less than minplayersperteam on one side
-# in milliseconds
-# Default: 300000
-# 0 - disable
+# Arena.ArenaSeason.InProgress
+# Current area season state
+# Default: 1 (active)
+# 0 (finished)
#
###################################################################################################################
-BattleGround.PrematureFinishTimer = 300000
+Arena.MaxRatingDifference = 100
+Arena.RatingDiscardTimer = 600000
+Arena.AutoDistributePoints = 0
+Arena.AutoDistributeInterval = 7
+Arena.QueueAnnouncer.Enable = 0
+Arena.ArenaSeason.ID = 1
+Arena.ArenaSeason.InProgress = 1
###################################################################################################################
-#
# NETWORK CONFIG
#
# Network.Threads
diff --git a/src/shared/Common.h b/src/shared/Common.h
index 9f5b9473bd9..d1bbb5e4e01 100644
--- a/src/shared/Common.h
+++ b/src/shared/Common.h
@@ -163,7 +163,8 @@ enum TimeConstants
MINUTE = 60,
HOUR = MINUTE*60,
DAY = HOUR*24,
- MONTH = DAY*30
+ MONTH = DAY*30,
+ IN_MILISECONDS = 1000
};
enum AccountTypes
diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h
index 90e21aa91e5..3241034185f 100644
--- a/src/shared/revision_nr.h
+++ b/src/shared/revision_nr.h
@@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__
#define __REVISION_NR_H__
- #define REVISION_NR "7334"
+ #define REVISION_NR "7336"
#endif // __REVISION_NR_H__