Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 11 additions & 51 deletions src/BgAutoQueue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,17 +136,11 @@ void BgAutoQueue::LoadConfig()

_crossFaction = sConfigMgr->GetOption<bool>("BgAutoQueue.CrossFaction", true);

// Mirror mod-cfbg's config (CFBG.cpp LoadConfig; showLogs=false because
// absent CFBG.* keys are the normal state on installs without mod-cfbg).
// While CFBG.Enable is on, mod-cfbg routes every non-rated queue entry
// through the cross-faction bucket (which drives waiter counting) and its
// EvenTeams match formation pins allowedDiff to 0 regardless of
// MaxPlayersThreshold — the threshold only relaxes reinforcement of games
// that already reached threshold*2 — so the parity trim in QueueBucket
// arms on formation strictness alone.
// Mirror mod-cfbg's CFBG.Enable (showLogs=false because absent CFBG.* keys
// are the normal state on installs without mod-cfbg). While it is on,
// mod-cfbg routes every non-rated queue entry through the cross-faction
// bucket -- the bucket the matcher's waiter counting reads.
_cfbgEnabled = sConfigMgr->GetOption<bool>("CFBG.Enable", false, false);
_evenTeamsStrict = _cfbgEnabled
&& sConfigMgr->GetOption<bool>("CFBG.EvenTeams.Enabled", false, false);

if (_cfbgEnabled && !_crossFaction)
LOG_WARN("module", "mod-bg-auto-queue: CFBG.Enable = 1 but BgAutoQueue.CrossFaction = 0. "
Expand Down Expand Up @@ -189,8 +183,8 @@ void BgAutoQueue::LoadConfig()
_deserterWarnLogged = false;
_poolResolveLogged = false;

LOG_INFO("module", "mod-bg-auto-queue: enabled={}, levels=[{}-{}], configured pool size={}, interval={} min, initialDelay={} s, warningLead={} s, crossFaction={}, cfbg={}, evenTeamsStrict={}, skipGM={}, skipAFK={}, skipAuras={}, declineHint={}, optOutAfterDeclines={}.",
_enabled, _levelMin, _levelMax, _poolRaw.size(), intervalMin, initialDelaySec, warningLeadSec, _crossFaction, _cfbgEnabled, _evenTeamsStrict, _skipGameMasters, _skipAfk, _skipAuras.size(), _declineHintEnabled, _optOutAfterDeclines);
LOG_INFO("module", "mod-bg-auto-queue: enabled={}, levels=[{}-{}], configured pool size={}, interval={} min, initialDelay={} s, warningLead={} s, crossFaction={}, cfbg={}, skipGM={}, skipAFK={}, skipAuras={}, declineHint={}, optOutAfterDeclines={}.",
_enabled, _levelMin, _levelMax, _poolRaw.size(), intervalMin, initialDelaySec, warningLeadSec, _crossFaction, _cfbgEnabled, _skipGameMasters, _skipAfk, _skipAuras.size(), _declineHintEnabled, _optOutAfterDeclines);

// Opt-out is stored via the core PlayerSettings system, which only persists
// across logins when EnablePlayerSettings is on. Without it, .bgevents
Expand Down Expand Up @@ -859,45 +853,11 @@ uint32 BgAutoQueue::QueueBucket(BattlegroundTypeId bgTypeId, BracketBucket const
verified.push_back({ player, bracketEntry });
}

// Strict EvenTeams (formation allowedDiff 0) can never invite an odd count
// from one queue list: one solo would be stranded until an external parity
// break. Matching pops per bracket, so parity is enforced per bracket
// (global evenness of a split wave guarantees nothing); the odd bracket's
// newest player is left unqueued and picked up by the next pass. Live-BG
// reinforcement is exempt: how many players the live game absorbs depends
// on its own team imbalance, and trimming there strands a player exactly
// when that imbalance is odd (the routine post-leaver state).
if (_evenTeamsStrict && !liveBracket && !verified.empty())
{
std::vector<BattlegroundBracketId> trimBrackets;
for (auto const& [player, bracketEntry] : verified)
if (std::find(trimBrackets.begin(), trimBrackets.end(), bracketEntry->GetBracketId()) == trimBrackets.end())
trimBrackets.push_back(bracketEntry->GetBracketId());

for (BattlegroundBracketId trimBracket : trimBrackets)
{
size_t const bracketCount = std::count_if(verified.begin(), verified.end(),
[trimBracket](std::pair<Player*, PvPDifficultyEntry const*> const& entry)
{
return entry.second->GetBracketId() == trimBracket;
});

QueuedWaiters const waiters = CountUninvitedWaitersInBracket(bgTypeId, trimBracket);
if ((bracketCount + waiters.total) % 2 == 0)
continue;

for (auto itr = verified.rbegin(); itr != verified.rend(); ++itr)
{
if (itr->second->GetBracketId() != trimBracket)
continue;

LOG_DEBUG("module", "mod-bg-auto-queue: parity trim: leaving {} unqueued to keep bracket {} even for strict EvenTeams.",
itr->first->GetName(), static_cast<uint32>(trimBracket));
verified.erase(std::next(itr).base());
break;
}
}
}
// Queue the whole verified bucket, including an odd solo: under strict CFBG
// EvenTeams the matcher invites the even subset and leaves the odd one
// queued, where it becomes exactly the backfill the queue needs -- the next
// queue update after any decline pulls it in via FillPlayersToCFBG, and a
// manual 6th queuer arriving mid-interval can pop a match with it.
Comment on lines +856 to +860

// Phase 2: queue everyone that survived.
uint32 queued = 0;
Expand Down
21 changes: 7 additions & 14 deletions src/BgAutoQueue.h
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ class BgAutoQueue
uint32 minLevel, uint32 maxLevel) const;

// One candidate-map bracket's share of a bucket. Core matching pops
// strictly per bracket_id, so viability and parity must be judged on these
// strictly per bracket_id, so viability must be judged on these
// partitions, never on the pooled bucket total (AV's shifted brackets
// split the 60-69 and 70-79 reference buckets in two; a pooled total can
// look viable while every partition is below minimum).
Expand Down Expand Up @@ -229,18 +229,12 @@ class BgAutoQueue
// queue update per distinct bracket queued into and registers the bracket
// for backlog draining (see UpdatePendingDrains). When liveBracket is set
// (live-BG reinforcement), players whose own bracket differs are skipped —
// that game's queue list would never serve them. Under strict CFBG
// EvenTeams (see _evenTeamsStrict), a bracket whose wave (re-validated
// players plus that bracket's uninvited waiters) is odd leaves its newest
// player unqueued for this pass so no solo is stranded behind an
// allowedDiff of 0; the next pass picks them up. Parity is judged per
// bracket (matching pops per bracket, so global evenness guarantees
// nothing) and skipped entirely for live-BG reinforcement, where how many
// players fit depends on the live game's own team imbalance. Returns the
// number of players queued. When non-null, skippedAtQueueTime is
// incremented for each bucket player dropped by the queue-time re-check,
// the BG-specific veto, or the level/bracket mismatch skips (not for the
// parity trim — a deferral, not a drop).
// that game's queue list would never serve them. The whole verified bucket
// is queued, including an odd solo: under strict CFBG EvenTeams the matcher
// invites the even subset and leaves the odd one queued as backfill for the
// next decline. Returns the number of players queued. When non-null,
// skippedAtQueueTime is incremented for each bucket player dropped by the
// queue-time re-check, the BG-specific veto, or the level/bracket mismatch.
uint32 QueueBucket(BattlegroundTypeId bgTypeId, BracketBucket const& bucket,
Optional<BattlegroundBracketId> liveBracket, uint32* skippedAtQueueTime = nullptr);

Expand Down Expand Up @@ -313,7 +307,6 @@ class BgAutoQueue
uint32 _warningLeadMs = 60u * 1000u;
bool _crossFaction = true;
bool _cfbgEnabled = false; // mirrored CFBG.Enable; selects which queue buckets the matcher reads
bool _evenTeamsStrict = false; // mod-cfbg EvenTeams active: match formation pins allowedDiff to 0 (see LoadConfig)
bool _skipGameMasters = true;
bool _skipAfk = true;
std::vector<uint32> _skipAuras; // aura ids that exclude a player from a pass
Expand Down
Loading