1111#include " Config.h"
1212#include " Containers.h"
1313#include " Language.h"
14- #include " Log.h"
1514#include " Opcodes.h"
1615#include " ReputationMgr.h"
1716#include " ScriptMgr.h"
@@ -160,7 +159,7 @@ void CFBG::LoadConfig()
160159 _IsEnableResetCooldowns = sConfigMgr ->GetOption <bool >(" CFBG.ResetCooldowns" , false );
161160 _IsEnableBalanceTeamsOnEntry = sConfigMgr ->GetOption <bool >(" CFBG.BalanceTeamsOnEntry.Enabled" , true );
162161 _showPlayerName = sConfigMgr ->GetOption <bool >(" CFBG.Show.PlayerName" , false );
163- _EvenTeamsMaxPlayersThreshold = sConfigMgr ->GetOption <uint32>(" CFBG.EvenTeams.MaxPlayersThreshold" , 5 );
162+ _EvenTeamsMaxPlayersThreshold = sConfigMgr ->GetOption <uint32>(" CFBG.EvenTeams.MaxPlayersThreshold" , 0 );
164163 _MaxPlayersCountInGroup = sConfigMgr ->GetOption <uint32>(" CFBG.Players.Count.In.Group" , 3 );
165164 _balanceClassMinLevel = sConfigMgr ->GetOption <uint8>(" CFBG.BalancedTeams.Class.MinLevel" , 10 );
166165 _balanceClassMaxLevel = sConfigMgr ->GetOption <uint8>(" CFBG.BalancedTeams.Class.MaxLevel" , 19 );
@@ -796,95 +795,6 @@ bool CFBG::FillPlayersToCFBG(BattlegroundQueue* bgqueue, Battleground* bg, Battl
796795
797796 GroupsList groups{ bgqueue->m_QueuedGroups [bracket_id][BG_QUEUE_CFBG ].begin (), bgqueue->m_QueuedGroups [bracket_id][BG_QUEUE_CFBG ].end () };
798797
799- // Sort for check same groups
800- std::sort (groups.begin (), groups.end (), [](GroupQueueInfo const * a, GroupQueueInfo const * b) { return a->Players .size () < b->Players .size (); });
801-
802- std::array<std::size_t , 2 > playersInvitedToBGCount{};
803-
804- if (IsEnableEvenTeams ())
805- {
806- std::vector<std::pair<GroupQueueInfo*, GroupQueueInfo*>> sameGroups;
807-
808- // Check groups with equal players
809- for (auto itr = groups.begin (); itr != groups.end ();)
810- {
811- if ((*itr)->IsInvitedToBGInstanceGUID )
812- {
813- itr++;
814- continue ;
815- }
816-
817- auto nextItr{ itr + 1 };
818- if (nextItr != groups.end ())
819- {
820- if ((*nextItr)->IsInvitedToBGInstanceGUID || (*itr)->Players .size () != (*nextItr)->Players .size ())
821- {
822- itr++;
823- continue ;
824- }
825-
826- sameGroups.emplace_back (*itr, *nextItr);
827- itr = itr + 2 ;
828-
829- if (itr == groups.end ())
830- break ;
831- else
832- continue ;
833- }
834-
835- itr++;
836- }
837-
838- if (!sameGroups.empty ())
839- {
840- auto InviteGroupToBG = [this , bg, bgqueue, maxAli, maxHorde](GroupQueueInfo* gInfo )
841- {
842- TeamId targetTeam = GetLowerTeamIdInBG (bg, bgqueue, gInfo );
843- gInfo ->teamId = targetTeam;
844-
845- if (bgqueue->m_SelectionPools [targetTeam].AddGroup (gInfo , targetTeam == TEAM_ALLIANCE ? maxAli : maxHorde))
846- return targetTeam;
847-
848- return TEAM_NEUTRAL ;
849- };
850-
851- for (auto & [group1, group2] : sameGroups)
852- {
853- auto team1{ InviteGroupToBG (group1) };
854- auto team2{ InviteGroupToBG (group2) };
855-
856- if (team1 != TEAM_NEUTRAL && team2 != TEAM_NEUTRAL )
857- {
858- std::erase (groups, group1);
859- std::erase (groups, group2);
860- playersInvitedToBGCount.at (team1) += group1->Players .size ();
861- playersInvitedToBGCount.at (team2) += group2->Players .size ();
862- }
863- }
864- }
865-
866- if (groups.empty ())
867- return true ; // we invited all players, done
868- }
869-
870- // Sort with join time (default)
871- std::sort (groups.begin (), groups.end (), [](GroupQueueInfo const * a, GroupQueueInfo const * b) { return a->JoinTime < b->JoinTime ; });
872-
873- if (IsEnableEvenTeams ())
874- {
875- InviteSameCountGroups (groups, bgqueue, maxAli, maxHorde, bg);
876-
877- if (groups.empty ())
878- return true ; // we invited all players, done
879- }
880-
881- // Check invited players to bg
882- for (auto const & gInfo : bgqueue->m_QueuedGroups [bracket_id][BG_QUEUE_CFBG ])
883- {
884- if (gInfo ->IsInvitedToBGInstanceGUID )
885- playersInvitedToBGCount.at (gInfo ->teamId ) += gInfo ->Players .size ();
886- }
887-
888798 auto DefaultInvitePlayersToBG = [this , bg, bgqueue, &groups, maxAli, maxHorde]()
889799 {
890800 GroupsList toDeleteGroups;
@@ -905,79 +815,68 @@ bool CFBG::FillPlayersToCFBG(BattlegroundQueue* bgqueue, Battleground* bg, Battl
905815 std::erase (groups, itr);
906816 };
907817
908- auto playersInBGAli{ bg->GetPlayersCountByTeam (TEAM_ALLIANCE ) + playersInvitedToBGCount.at (TEAM_ALLIANCE ) };
909- auto playersInBGHorde{ bg->GetPlayersCountByTeam (TEAM_HORDE ) + playersInvitedToBGCount.at (TEAM_HORDE ) };
910- auto playersInBG{ static_cast <std::size_t >(playersInBGAli + playersInBGHorde) };
911- auto evenTeamsCount{ EvenTeamsMaxPlayersThreshold () };
912-
913- if (IsEnableEvenTeams () && evenTeamsCount && playersInBG < evenTeamsCount * 2 )
818+ if (IsEnableEvenTeams ())
914819 {
915- int32 aliNeed = evenTeamsCount - playersInBGAli;
916- int32 hordeNeed = evenTeamsCount - playersInBGHorde;
820+ // Projected team sizes: players already in the BG plus players invited in
821+ // earlier queue updates that have not entered yet.
822+ uint32 playersInBGAli{ bg->GetPlayersCountByTeam (TEAM_ALLIANCE ) };
823+ uint32 playersInBGHorde{ bg->GetPlayersCountByTeam (TEAM_HORDE ) };
917824
918- if (aliNeed < 0 )
919- aliNeed = 0 ;
825+ for (auto const & gInfo : bgqueue->m_QueuedGroups [bracket_id][BG_QUEUE_CFBG ])
826+ if (gInfo ->IsInvitedToBGInstanceGUID )
827+ (gInfo ->teamId == TEAM_ALLIANCE ? playersInBGAli : playersInBGHorde) += gInfo ->Players .size ();
920828
921- if (hordeNeed < 0 )
922- hordeNeed = 0 ;
829+ uint32 evenTeamsCount{ EvenTeamsMaxPlayersThreshold () };
830+ uint32 playersInBG{ playersInBGAli + playersInBGHorde } ;
923831
924- if ((aliNeed || hordeNeed) && (aliNeed != hordeNeed))
832+ // A threshold of 0 enforces even teams for all match sizes. A non-zero
833+ // threshold stops enforcing once both teams reach it (total >= threshold * 2).
834+ if (evenTeamsCount && playersInBG >= evenTeamsCount * 2 )
925835 {
926- uint32 playersNeed{ 0 };
927- TeamId targetTeam = TEAM_NEUTRAL ;
836+ DefaultInvitePlayersToBG ();
837+ return true ;
838+ }
928839
929- if (aliNeed && aliNeed > hordeNeed)
930- {
931- playersNeed = aliNeed - hordeNeed;
932- targetTeam = TEAM_ALLIANCE ;
933- }
934- else if (hordeNeed && hordeNeed > aliNeed)
935- {
936- playersNeed = hordeNeed - aliNeed ;
937- targetTeam = TEAM_HORDE ;
938- }
840+ // 1. Close any existing imbalance by topping up the smaller team only.
841+ if (playersInBGAli != playersInBGHorde)
842+ {
843+ TeamId targetTeam{ playersInBGAli < playersInBGHorde ? TEAM_ALLIANCE : TEAM_HORDE } ;
844+ uint32 gap{ targetTeam == TEAM_ALLIANCE ? playersInBGHorde - playersInBGAli : playersInBGAli - playersInBGHorde };
845+ uint32 targetCount{ std::min<uint32>(gap, targetTeam == TEAM_ALLIANCE ? maxAli : maxHorde) };
846+
847+ std::sort (groups. begin (), groups. end (), [](GroupQueueInfo const * a, GroupQueueInfo const * b) { return a-> Players . size () < b-> Players . size (); }) ;
848+
849+ GroupsList toDeleteGroups;
939850
940- if (playersNeed > 0 && targetTeam != TEAM_NEUTRAL )
851+ for ( auto const & gInfo : groups )
941852 {
942- GroupsList toDeleteGroups;
943-
944- // #1. Try fill players to even team
945- for (auto const & gInfo : groups)
946- {
947- // We can add only single players
948- if (gInfo ->IsInvitedToBGInstanceGUID )
949- continue ;
950-
951- gInfo ->teamId = targetTeam;
952-
953- if (bgqueue->m_SelectionPools [targetTeam].AddGroup (gInfo , playersNeed))
954- {
955- auto groupPlayerSize{ gInfo ->Players .size () };
956- playersNeed -= groupPlayerSize;
957- toDeleteGroups.emplace_back (gInfo );
958- targetTeam == TEAM_ALLIANCE ? aliNeed -= groupPlayerSize : hordeNeed -= groupPlayerSize;
959- }
960-
961- // Stop invited if found players for even teams
962- if (!playersNeed)
963- break ;
964- }
965-
966- // Delete invited groups
967- for (auto const & gInfo : toDeleteGroups)
968- std::erase (groups, gInfo );
853+ if (gInfo ->IsInvitedToBGInstanceGUID )
854+ continue ;
855+
856+ if (bgqueue->m_SelectionPools [targetTeam].GetPlayerCount () >= targetCount)
857+ break ;
858+
859+ gInfo ->teamId = targetTeam;
860+ auto before{ bgqueue->m_SelectionPools [targetTeam].GetPlayerCount () };
861+ bgqueue->m_SelectionPools [targetTeam].AddGroup (gInfo , targetCount);
862+
863+ if (bgqueue->m_SelectionPools [targetTeam].GetPlayerCount () > before)
864+ toDeleteGroups.emplace_back (gInfo );
969865 }
970- else
971- LOG_FATAL (" module" , " > CFBG: Incorrect conditions for check even teams. Players need: {}. Target team: {}" , playersNeed, targetTeam);
866+
867+ for (auto const & gInfo : toDeleteGroups)
868+ std::erase (groups, gInfo );
972869 }
973870
974- // #2 if all teams even and `MaxPlayersThreshold` complete
975- if (!aliNeed && !hordeNeed)
976- DefaultInvitePlayersToBG ();
871+ // 2. Invite the rest only in balanced same-size pairs. Any group that would
872+ // break N vs N stays in the queue for the next update.
873+ std::sort (groups.begin (), groups.end (), [](GroupQueueInfo const * a, GroupQueueInfo const * b) { return a->Players .size () > b->Players .size (); });
874+ InviteSameCountGroups (groups, bgqueue, maxAli, maxHorde, bg);
875+
876+ return true ;
977877 }
978- else
979- DefaultInvitePlayersToBG ();
980878
879+ DefaultInvitePlayersToBG ();
981880 return true ;
982881}
983882
@@ -1009,7 +908,6 @@ void CFBG::UpdateForget(Player* player)
1009908 }
1010909}
1011910
1012- std::unordered_map<ObjectGuid, Seconds> BGSpamProtectionCFBG;
1013911void CFBG::SendMessageQueue (BattlegroundQueue* bgQueue, Battleground* bg, PvPDifficultyEntry const * bracketEntry, Player* leader)
1014912{
1015913 BattlegroundBracketId bracketId = bracketEntry->GetBracketId ();
@@ -1035,57 +933,11 @@ void CFBG::SendMessageQueue(BattlegroundQueue* bgQueue, Battleground* bg, PvPDif
1035933 }
1036934 else
1037935 {
1038- auto searchGUID = BGSpamProtectionCFBG.find (leader->GetGUID ());
1039-
1040- if (searchGUID == BGSpamProtectionCFBG.end ())
1041- BGSpamProtectionCFBG[leader->GetGUID ()] = 0s;
1042-
1043- // Skip if spam time < 30 secs (default)
1044- if (GameTime::GetGameTime () - BGSpamProtectionCFBG[leader->GetGUID ()] < Seconds (sWorld ->getIntConfig (CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_SPAM_DELAY )))
1045- {
1046- return ;
1047- }
1048-
1049- // When limited, it announces only if there are at least CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_LIMIT_MIN_PLAYERS in queue
1050- auto limitQueueMinLevel = sWorld ->getIntConfig (CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_LIMIT_MIN_LEVEL );
1051- if (limitQueueMinLevel != 0 && q_min_level >= limitQueueMinLevel)
1052- {
1053- // limit only RBG for 80, WSG for lower levels
1054- auto bgTypeToLimit = q_min_level == 80 ? BATTLEGROUND_RB : BATTLEGROUND_WS ;
1055-
1056- if (bg->GetBgTypeID () == bgTypeToLimit && qTotal < sWorld ->getIntConfig (CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_LIMIT_MIN_PLAYERS ))
1057- {
1058- return ;
1059- }
1060- }
1061-
1062- BGSpamProtectionCFBG[leader->GetGUID ()] = GameTime::GetGameTime ();
1063-
1064- if (_showPlayerName)
1065- {
1066- std::string msg = Acore::StringFormat (" {} |cffffffffHas Joined|r |cffff0000{}|r|cffffffff(|r|cff00ffff{}|r|cffffffff/|r|cff00ffff{}|r|cffffffff)|r" ,
1067- leader->GetPlayerName (), bg->GetName (), qTotal, MinPlayers);
1068-
1069- auto const & sessions = sWorldSessionMgr ->GetAllSessions ();
1070- for (auto const & session : sessions)
1071- {
1072- if (Player* player = session.second ->GetPlayer ())
1073- {
1074- if (player->GetPlayerSetting (AzerothcorePSSource, SETTING_ANNOUNCER_FLAGS ).HasFlag (ANNOUNCER_FLAG_DISABLE_BG_QUEUE ))
1075- {
1076- continue ;
1077- }
1078-
1079- WorldPacket data (SMSG_CHAT_SERVER_MESSAGE , (msg.size () + 1 ));
1080- data << uint32 (3 );
1081- data << msg;
1082- player->GetSession ()->SendPacket (&data);
1083- }
1084- }
1085- }
1086- else
936+ // Defer to the shared core announcer (cross-faction); spam-window and
937+ // Limit gating now happen centrally in BattlegroundQueueAnnouncerUpdate.
938+ if (bgQueue->GetQueueAnnouncementTimer (bracketId) < 0 )
1087939 {
1088- ChatHandler ( nullptr ). SendWorldTextOptional ( LANG_BG_QUEUE_ANNOUNCE_WORLD , ANNOUNCER_FLAG_DISABLE_BG_QUEUE , bgName, q_min_level, q_max_level, qTotal, MinPlayers );
940+ bgQueue-> SetQueueAnnouncementTimer (bracketId, BG_QUEUE_ANNOUNCER_IMMEDIATE_DEBOUNCE , true );
1089941 }
1090942 }
1091943 }
0 commit comments