mirror of
https://github.com/liyunfan1223/azerothcore-wotlk.git
synced 2026-08-09 08:17:56 +00:00
fix(Core/Battlegrounds): aggregate BG queue announcer on burst (#26086)
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -2,6 +2,7 @@
|
||||
# AzerothCore
|
||||
#
|
||||
|
||||
.cache
|
||||
/conf/*
|
||||
!/conf/dist
|
||||
/modules/*
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user