diff --git a/src/BgAutoQueue.cpp b/src/BgAutoQueue.cpp index 05ae429..d243626 100644 --- a/src/BgAutoQueue.cpp +++ b/src/BgAutoQueue.cpp @@ -381,6 +381,24 @@ bool BgAutoQueue::IsEligible(Player* player, SkipReason* reason) const return true; } +bool BgAutoQueue::IsQueueEligible(Player* player, SkipReason* reason, PvPDifficultyEntry const** bracket) const +{ + if (!IsEligible(player, reason)) + return false; + + PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketByLevel(BG_BRACKET_REFERENCE_MAP, player->GetLevel()); + if (!bracketEntry) + { + if (reason) + *reason = SkipReason::NoBracket; + return false; + } + + if (bracket) + *bracket = bracketEntry; + return true; +} + Battleground* BgAutoQueue::GetDeserterCheckTemplate() const { // CanJoinToBattleground only reads the template's arena/RB type, which is @@ -984,19 +1002,13 @@ BgAutoQueue::QueuePassResult BgAutoQueue::RunQueuePass() ++result.considered; SkipReason reason = SkipReason::NotInWorld; - if (!IsEligible(player, &reason)) + PvPDifficultyEntry const* bracketEntry = nullptr; + if (!IsQueueEligible(player, &reason, &bracketEntry)) { ++result.skipped[static_cast(reason)]; continue; } - PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketByLevel(BG_BRACKET_REFERENCE_MAP, player->GetLevel()); - if (!bracketEntry) - { - ++result.skipped[static_cast(SkipReason::NoBracket)]; - continue; - } - BracketBucket& bucket = buckets[bracketEntry->GetBracketId()]; bucket.minLevel = bracketEntry->minLevel; bucket.maxLevel = bracketEntry->maxLevel; @@ -1083,7 +1095,7 @@ void BgAutoQueue::BroadcastWarning() const uint32 sent = 0; for (auto const& [guid, player] : ObjectAccessor::GetPlayers()) { - if (!IsEligible(player)) + if (!IsQueueEligible(player)) continue; WorldSession* session = player->GetSession(); diff --git a/src/BgAutoQueue.h b/src/BgAutoQueue.h index f845e4e..95f3860 100644 --- a/src/BgAutoQueue.h +++ b/src/BgAutoQueue.h @@ -64,6 +64,13 @@ class BgAutoQueue static char const* GetSkipReasonLabel(SkipReason reason); + // Full gather-time per-player queue eligibility: every IsEligible gate plus + // the reference-map bracket check (NoBracket). On false, *reason is the first + // failing gate; on true, *bracket (when non-null) gets the resolved bracket. + // Public so .bgevents can report real eligibility with the pass's own logic. + bool IsQueueEligible(Player* player, SkipReason* reason = nullptr, + PvPDifficultyEntry const** bracket = nullptr) const; + // Outcome of a queue pass, reported back to .bgevents run so an operator // can see whether anyone was actually queued, broken down per bracket, // plus why the rest were skipped. @@ -119,10 +126,11 @@ class BgAutoQueue uint32 maxLevel = 0; }; - // Shared per-player eligibility used by both the queue pass and the - // warning broadcast. Excludes the BG-specific OnPlayerCanJoinInBattleground - // Queue veto (that runs only at queue time). When non-null, reason is set - // to the first failing filter (only meaningful when this returns false). + // Shared per-player eligibility used by IsQueueEligible and by the + // queue-time re-check in QueueBucket. Excludes the BG-specific + // OnPlayerCanJoinInBattlegroundQueue veto (that runs only at queue time). + // When non-null, reason is set to the first failing filter (only + // meaningful when this returns false). bool IsEligible(Player* player, SkipReason* reason = nullptr) const; // True when the player can be queued into bgTypeId at their level. diff --git a/src/cs_bg_auto_queue.cpp b/src/cs_bg_auto_queue.cpp index e6b8695..af9761b 100644 --- a/src/cs_bg_auto_queue.cpp +++ b/src/cs_bg_auto_queue.cpp @@ -56,17 +56,26 @@ class bg_auto_queue_commandscript : public CommandScript return true; } - if (sBgAutoQueue->IsOptedOut(player)) - handler->SendSysMessage("Battleground events are currently DISABLED for your character."); - else - handler->SendSysMessage("Battleground events are currently ENABLED for your character."); + BgAutoQueue::SkipReason reason = BgAutoQueue::SkipReason::NotInWorld; + bool const eligible = sBgAutoQueue->IsQueueEligible(player, &reason); + + uint32 const msToNext = sBgAutoQueue->GetTimeUntilNextPass(); + bool const eventsScheduled = sBgAutoQueue->IsEnabled() && msToNext > 0; + + if (!eventsScheduled) + { + handler->SendSysMessage("Battleground automatic events are currently turned OFF on this server. An administrator can still trigger one manually."); + if (!eligible) + handler->PSendSysMessage("Battleground events are DISABLED for your character because {}", GetPlayerSkipReasonMessage(reason)); + return true; + } - uint32 msToNext = sBgAutoQueue->GetTimeUntilNextPass(); - if (sBgAutoQueue->IsEnabled() && msToNext > 0) - handler->PSendSysMessage("Next scheduled event in {}.", secsToTimeString(msToNext / 1000)); + if (eligible) + handler->SendSysMessage("Battleground events are ENABLED for your character. You will be auto-queued at the next event."); else - handler->SendSysMessage("There are no scheduled events (an administrator may still trigger one)."); + handler->PSendSysMessage("Battleground events are DISABLED for your character because {}", GetPlayerSkipReasonMessage(reason)); + handler->PSendSysMessage("Next scheduled event in {}.", secsToTimeString(msToNext / 1000)); return true; } @@ -97,6 +106,29 @@ class bg_auto_queue_commandscript : public CommandScript } private: + // Second-person wording for the .bgevents (no-arg) player report. Distinct + // from GetSkipReasonLabel, which is operator-flavored copy for .bgevents run. + // Each clause ends with its own period; the format string adds none. + static char const* GetPlayerSkipReasonMessage(BgAutoQueue::SkipReason reason) + { + switch (reason) + { + case BgAutoQueue::SkipReason::OptedOut: return "you opted out. Use \".bgevents on\" to opt back in."; + case BgAutoQueue::SkipReason::Level: return "your level is outside the range set for battleground events."; + case BgAutoQueue::SkipReason::Dungeon: return "you are in a dungeon or raid."; + case BgAutoQueue::SkipReason::InBattleground: return "you are already in a battleground."; + case BgAutoQueue::SkipReason::AlreadyQueued: return "you are already queued elsewhere (or have no free queue slot)."; + case BgAutoQueue::SkipReason::Deserter: return "you have the Deserter debuff or cannot currently join a battleground."; + case BgAutoQueue::SkipReason::Lfg: return "you are using the LFG (Dungeon Finder) system."; + case BgAutoQueue::SkipReason::DeathKnightEbonHold: return "your Death Knight has not yet left Ebon Hold."; + case BgAutoQueue::SkipReason::GameMaster: return "you are in GM mode."; + case BgAutoQueue::SkipReason::Afk: return "you are flagged AFK."; + case BgAutoQueue::SkipReason::Aura: return "you have an aura that excludes you from battleground events."; + case BgAutoQueue::SkipReason::NoBracket: return "there is no battleground bracket for your level."; + default: return "you are not currently eligible for battleground events."; + } + } + // Prints why online players were not queued, so an operator can tell an // opted-out character from a wrong-level one (etc.) without reading logs. static void ReportSkips(ChatHandler* handler, BgAutoQueue::QueuePassResult const& result)