diff options
author | megamage <none@none> | 2009-02-27 12:13:59 -0600 |
---|---|---|
committer | megamage <none@none> | 2009-02-27 12:13:59 -0600 |
commit | 472f897b0a1475991f70fdc428387ce3d322d5ce (patch) | |
tree | 5ebd3cd397bfff6d18c9beeb8c5a1aa3be9fda29 /src | |
parent | d3a69006675bb5317fab76584d5990b36c2fd5a5 (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.cpp | 6 | ||||
-rw-r--r-- | src/game/BattleGround.cpp | 71 | ||||
-rw-r--r-- | src/game/BattleGround.h | 65 | ||||
-rw-r--r-- | src/game/BattleGroundHandler.cpp | 23 | ||||
-rw-r--r-- | src/game/BattleGroundMgr.cpp | 1161 | ||||
-rw-r--r-- | src/game/BattleGroundMgr.h | 81 | ||||
-rw-r--r-- | src/game/Group.cpp | 2 | ||||
-rw-r--r-- | src/game/Player.cpp | 34 | ||||
-rw-r--r-- | src/game/Player.h | 11 | ||||
-rw-r--r-- | src/game/World.cpp | 57 | ||||
-rw-r--r-- | src/game/World.h | 13 | ||||
-rw-r--r-- | src/mangosd/mangosd.conf.dist.in | 131 | ||||
-rw-r--r-- | src/shared/Common.h | 3 | ||||
-rw-r--r-- | src/shared/revision_nr.h | 2 |
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__ |