diff --git a/src/BgAutoQueue.cpp b/src/BgAutoQueue.cpp index 6237e87..6d6f312 100644 --- a/src/BgAutoQueue.cpp +++ b/src/BgAutoQueue.cpp @@ -136,17 +136,11 @@ void BgAutoQueue::LoadConfig() _crossFaction = sConfigMgr->GetOption("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("CFBG.Enable", false, false); - _evenTeamsStrict = _cfbgEnabled - && sConfigMgr->GetOption("CFBG.EvenTeams.Enabled", false, false); if (_cfbgEnabled && !_crossFaction) LOG_WARN("module", "mod-bg-auto-queue: CFBG.Enable = 1 but BgAutoQueue.CrossFaction = 0. " @@ -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 @@ -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 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 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(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. // Phase 2: queue everyone that survived. uint32 queued = 0; diff --git a/src/BgAutoQueue.h b/src/BgAutoQueue.h index 437eaa3..51c92f9 100644 --- a/src/BgAutoQueue.h +++ b/src/BgAutoQueue.h @@ -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). @@ -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 liveBracket, uint32* skippedAtQueueTime = nullptr); @@ -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 _skipAuras; // aura ids that exclude a player from a pass