fix(Core/Battlegrounds): aggregate BG queue announcer on burst (#26086)

This commit is contained in:
Francesco Borzì
2026-06-07 16:20:29 +02:00
committed by GitHub
parent 4a940e4983
commit 4d26913310
5 changed files with 90 additions and 37 deletions

1
.gitignore vendored
View File

@@ -2,6 +2,7 @@
# AzerothCore
#
.cache
/conf/*
!/conf/dist
/modules/*

View File

@@ -1039,42 +1039,43 @@ void BattlegroundQueue::BattlegroundQueueAnnouncerUpdate(uint32 diff, Battlegrou
return;
}
if (sWorld->getBoolConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_TIMED))
{
uint32 qPlayers = 0;
// Armed per-bracket timer drives both Timed mode and the deferred immediate
// announcement; the spam-window/Limit throttle gates only immediate mode.
bool const isTimed = sWorld->getBoolConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_TIMED);
if (_queueAnnouncementCrossfactioned)
uint32 qPlayers = 0;
if (_queueAnnouncementCrossfactioned)
qPlayers = GetPlayersCountInGroupsQueue(bracket_id, BG_QUEUE_CFBG);
else
qPlayers = GetPlayersCountInGroupsQueue(bracket_id, BG_QUEUE_NORMAL_HORDE) + GetPlayersCountInGroupsQueue(bracket_id, BG_QUEUE_NORMAL_ALLIANCE);
if (!qPlayers)
{
_queueAnnouncementTimer[bracket_id] = -1;
return;
}
if (_queueAnnouncementTimer[bracket_id] >= 0)
{
if (_queueAnnouncementTimer[bracket_id] <= static_cast<int32>(diff))
{
qPlayers = GetPlayersCountInGroupsQueue(bracket_id, BG_QUEUE_CFBG);
_queueAnnouncementTimer[bracket_id] = -1;
uint32 q_min_level = std::min(bracketEntry->minLevel, (uint32) 80);
if (!isTimed && !sBGSpam->CanAnnounce(bg_template, bracket_id, q_min_level, qPlayers))
return;
auto bgName = bg_template->GetName();
uint32 MaxPlayers = GetMinPlayersPerTeam(bg_template, bracketEntry) * 2;
uint32 q_max_level = std::min(bracketEntry->maxLevel, (uint32) 80);
ChatHandler(nullptr).SendWorldTextOptional(LANG_BG_QUEUE_ANNOUNCE_WORLD, ANNOUNCER_FLAG_DISABLE_BG_QUEUE, bgName.c_str(), q_min_level, q_max_level, qPlayers, MaxPlayers);
}
else
{
qPlayers = GetPlayersCountInGroupsQueue(bracket_id, BG_QUEUE_NORMAL_HORDE) + GetPlayersCountInGroupsQueue(bracket_id, BG_QUEUE_NORMAL_ALLIANCE);
}
if (!qPlayers)
{
_queueAnnouncementTimer[bracket_id] = -1;
return;
}
if (_queueAnnouncementTimer[bracket_id] >= 0)
{
if (_queueAnnouncementTimer[bracket_id] <= static_cast<int32>(diff))
{
_queueAnnouncementTimer[bracket_id] = -1;
auto bgName = bg_template->GetName();
uint32 MaxPlayers = GetMinPlayersPerTeam(bg_template, bracketEntry) * 2;
uint32 q_min_level = std::min(bracketEntry->minLevel, (uint32) 80);
uint32 q_max_level = std::min(bracketEntry->maxLevel, (uint32) 80);
ChatHandler(nullptr).SendWorldTextOptional(LANG_BG_QUEUE_ANNOUNCE_WORLD, ANNOUNCER_FLAG_DISABLE_BG_QUEUE, bgName.c_str(), q_min_level, q_max_level, qPlayers, MaxPlayers);
}
else
{
_queueAnnouncementTimer[bracket_id] -= static_cast<int32>(diff);
}
_queueAnnouncementTimer[bracket_id] -= static_cast<int32>(diff);
}
}
}
@@ -1145,12 +1146,10 @@ void BattlegroundQueue::SendMessageBGQueue(Player* leader, Battleground* bg, PvP
}
else
{
if (!sBGSpam->CanAnnounce(leader, bg, q_min_level, qTotal))
{
return;
}
ChatHandler(nullptr).SendWorldTextOptional(LANG_BG_QUEUE_ANNOUNCE_WORLD, ANNOUNCER_FLAG_DISABLE_BG_QUEUE, bgName.c_str(), q_min_level, q_max_level, qAlliance + qHorde, MaxPlayers);
// Arm the per-bracket debounce; first join arms, rest are no-ops.
// BattlegroundQueueAnnouncerUpdate emits the aggregated line later.
if (_queueAnnouncementTimer[bracketId] < 0)
SetQueueAnnouncementTimer(bracketId, BG_QUEUE_ANNOUNCER_IMMEDIATE_DEBOUNCE, false);
}
}
}

View File

@@ -27,6 +27,10 @@
constexpr auto COUNT_OF_PLAYERS_TO_AVERAGE_WAIT_TIME = 10;
// Immediate-mode announcer debounce (ms): fires on the next periodic pass, by
// which point a same-tick queue burst has collapsed into one aggregated line.
constexpr int32 BG_QUEUE_ANNOUNCER_IMMEDIATE_DEBOUNCE = 1;
struct GroupQueueInfo // stores information about the group in queue (also used when joined as solo!)
{
GuidSet Players; // player guid set

View File

@@ -25,6 +25,7 @@
namespace
{
std::unordered_map<ObjectGuid /*player guid*/, uint32 /*time*/> _players;
std::unordered_map<uint32 /*bracket+bg key*/, uint32 /*time*/> _brackets;
void AddTime(ObjectGuid guid)
{
@@ -47,6 +48,26 @@ namespace
// Skip if spam time < 30 secs (default)
return GameTime::GetGameTime().count() - GetTime(guid) >= sWorld->getIntConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_SPAM_DELAY);
}
void AddTime(uint32 key)
{
_brackets.insert_or_assign(key, GameTime::GetGameTime().count());
}
uint32 GetTime(uint32 key)
{
auto const& itr = _brackets.find(key);
if (itr != _brackets.end())
return itr->second;
return 0;
}
bool IsCorrectDelay(uint32 key)
{
// Skip if spam time < 30 secs (default)
return GameTime::GetGameTime().count() - GetTime(key) >= sWorld->getIntConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_SPAM_DELAY);
}
}
BGSpamProtect* BGSpamProtect::instance()
@@ -84,3 +105,29 @@ bool BGSpamProtect::CanAnnounce(Player* player, Battleground* bg, uint32 minLeve
AddTime(guid);
return true;
}
bool BGSpamProtect::CanAnnounce(Battleground* bg, BattlegroundBracketId bracketId, uint32 minLevel, uint32 queueTotal)
{
if (!bg)
return false;
uint32 key = uint32(bg->GetBgTypeID()) * MAX_BATTLEGROUND_BRACKETS + uint32(bracketId);
// Check prev time
if (!IsCorrectDelay(key))
return false;
// When limited, it announces only if there are at least CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_LIMIT_MIN_PLAYERS in queue
auto limitQueueMinLevel = sWorld->getIntConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_LIMIT_MIN_LEVEL);
if (limitQueueMinLevel && minLevel >= limitQueueMinLevel)
{
// limit only RBG for 80, WSG for lower levels
auto bgTypeToLimit = minLevel == 80 ? BATTLEGROUND_RB : BATTLEGROUND_WS;
if (bg->GetBgTypeID() == bgTypeToLimit && queueTotal < sWorld->getIntConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_LIMIT_MIN_PLAYERS))
return false;
}
AddTime(key);
return true;
}

View File

@@ -19,6 +19,7 @@
#define _BATTLEGROUND_SPAM_PROTECT_H_
#include "Define.h"
#include "DBCEnums.h"
class Player;
class Battleground;
@@ -29,6 +30,7 @@ public:
static BGSpamProtect* instance();
bool CanAnnounce(Player* player, Battleground* bg, uint32 minLevel, uint32 queueTotal);
bool CanAnnounce(Battleground* bg, BattlegroundBracketId bracketId, uint32 minLevel, uint32 queueTotal);
};
#define sBGSpam BGSpamProtect::instance()