From 27da054661b9994ff6c6dbd2cce6d0b14deca835 Mon Sep 17 00:00:00 2001 From: NoxMax <50133316+NoxMax@users.noreply.github.com> Date: Fri, 25 Jul 2025 19:09:20 -0600 Subject: [PATCH] feat(Core): make BGs and Arena prep time configurable (#22136) Co-authored-by: Tereneckla --- .../apps/worldserver/worldserver.conf.dist | 15 +++++ .../game/Battlegrounds/Battleground.cpp | 56 ++++++++++++++++--- src/server/game/Battlegrounds/Battleground.h | 3 + src/server/game/World/WorldConfig.cpp | 2 + src/server/game/World/WorldConfig.h | 2 + 5 files changed, 70 insertions(+), 8 deletions(-) diff --git a/src/server/apps/worldserver/worldserver.conf.dist b/src/server/apps/worldserver/worldserver.conf.dist index f2662fda9..79b496ff0 100644 --- a/src/server/apps/worldserver/worldserver.conf.dist +++ b/src/server/apps/worldserver/worldserver.conf.dist @@ -3501,6 +3501,14 @@ Wintergrasp.CrashRestartTimer = 10 ################################################################################################### # BATTLEGROUND +# +# Battleground.PrepTime +# Description: Time (in seconds) for battleground preparation phase. Strand of the Ancients will be +# the exception and will always use the default 120 seconds timer, due to its boat timing mechanic. +# Default: 120 + +Battleground.PrepTime = 120 + # # Battleground.CastDeserter # Description: Cast Deserter spell at players who leave battlegrounds in progress. @@ -3766,6 +3774,13 @@ Battleground.EyeOfTheStorm.CapturePoints = 1600 ################################################################################################### # ARENA +# +# Arena.PrepTime +# Description: Time (in seconds) for arena preparation phase. +# Default: 60 + +Arena.PrepTime = 60 + # # Arena.MaxRatingDifference # Description: Maximum rating difference between two teams in rated matches. diff --git a/src/server/game/Battlegrounds/Battleground.cpp b/src/server/game/Battlegrounds/Battleground.cpp index 1d87e34e8..7ddd4e87e 100644 --- a/src/server/game/Battlegrounds/Battleground.cpp +++ b/src/server/game/Battlegrounds/Battleground.cpp @@ -195,6 +195,8 @@ Battleground::Battleground() m_HonorMode = BG_NORMAL; + m_SetupCompleted = false; + StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_2M; StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_1M; StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_30S; @@ -475,10 +477,8 @@ inline void Battleground::_ProcessJoin(uint32 diff) itr->second->ResetAllPowers(); } - if (!(m_Events & BG_STARTING_EVENT_1)) + if (!m_SetupCompleted) { - m_Events |= BG_STARTING_EVENT_1; - if (!FindBgMap()) { LOG_ERROR("bg.battleground", "Battleground::_ProcessJoin: map (map id: {}, instance id: {}) is not created!", m_MapId, m_InstanceID); @@ -494,13 +494,52 @@ inline void Battleground::_ProcessJoin(uint32 diff) } StartingEventCloseDoors(); - SetStartDelayTime(StartDelayTimes[BG_STARTING_EVENT_FIRST]); - // First start warning - 2 or 1 minute + // Get the configured prep time + uint32 configuredPrepTime; + + // Special case for Strand of the Ancients - always use 120 seconds due to boat timing mechanics + if (GetBgTypeID() == BATTLEGROUND_SA) + configuredPrepTime = 120 * IN_MILLISECONDS; + else + configuredPrepTime = isArena() ? + sWorld->getIntConfig(CONFIG_ARENA_PREP_TIME) * IN_MILLISECONDS : + sWorld->getIntConfig(CONFIG_BATTLEGROUND_PREP_TIME) * IN_MILLISECONDS; + + SetStartDelayTime(configuredPrepTime); + + // Pre-mark events for announcements that should be skipped based on configured prep time + if (configuredPrepTime < StartDelayTimes[BG_STARTING_EVENT_FIRST]) + { + // Skip first announcement (120s for BG, 60s for Arena) + m_Events |= BG_STARTING_EVENT_1; + + if (configuredPrepTime < StartDelayTimes[BG_STARTING_EVENT_SECOND]) + { + // Skip second announcement (60s for BG, 30s for Arena) + m_Events |= BG_STARTING_EVENT_2; + + if (configuredPrepTime < StartDelayTimes[BG_STARTING_EVENT_THIRD]) + { + // Skip third announcement (30s for BG, 15s for Arena) + m_Events |= BG_STARTING_EVENT_3; + } + } + } + + // Mark setup as completed + m_SetupCompleted = true; + } + + // First announcement at 120s or 60s (Depending on BG or Arena and configured time) + if (GetStartDelayTime() <= StartDelayTimes[BG_STARTING_EVENT_FIRST] && !(m_Events & BG_STARTING_EVENT_1)) + { + m_Events |= BG_STARTING_EVENT_1; + if (StartMessageIds[BG_STARTING_EVENT_FIRST]) SendBroadcastText(StartMessageIds[BG_STARTING_EVENT_FIRST], CHAT_MSG_BG_SYSTEM_NEUTRAL); } - // After 1 minute or 30 seconds, warning is signaled + // Second announcement at 60s or 30s else if (GetStartDelayTime() <= StartDelayTimes[BG_STARTING_EVENT_SECOND] && !(m_Events & BG_STARTING_EVENT_2)) { m_Events |= BG_STARTING_EVENT_2; @@ -508,7 +547,7 @@ inline void Battleground::_ProcessJoin(uint32 diff) if (StartMessageIds[BG_STARTING_EVENT_SECOND]) SendBroadcastText(StartMessageIds[BG_STARTING_EVENT_SECOND], CHAT_MSG_BG_SYSTEM_NEUTRAL); } - // After 30 or 15 seconds, warning is signaled + // Third announcement at 30s or 15s else if (GetStartDelayTime() <= StartDelayTimes[BG_STARTING_EVENT_THIRD] && !(m_Events & BG_STARTING_EVENT_3)) { m_Events |= BG_STARTING_EVENT_3; @@ -543,11 +582,12 @@ inline void Battleground::_ProcessJoin(uint32 diff) break; } } - // Delay expired (after 2 or 1 minute) + // Delay expired (after configured prep time) else if (GetStartDelayTime() <= 0 && !(m_Events & BG_STARTING_EVENT_4)) { m_Events |= BG_STARTING_EVENT_4; + // Start the battle StartingEventOpenDoors(); if (StartMessageIds[BG_STARTING_EVENT_FOURTH]) diff --git a/src/server/game/Battlegrounds/Battleground.h b/src/server/game/Battlegrounds/Battleground.h index 35ffebc4d..90b828e69 100644 --- a/src/server/game/Battlegrounds/Battleground.h +++ b/src/server/game/Battlegrounds/Battleground.h @@ -614,6 +614,9 @@ protected: void _ProcessJoin(uint32 diff); void _CheckSafePositions(uint32 diff); + // Setup completion marker + bool m_SetupCompleted; + // Scorekeeping BattlegroundScoreMap PlayerScores; // Player scores // must be implemented in BG subclass diff --git a/src/server/game/World/WorldConfig.cpp b/src/server/game/World/WorldConfig.cpp index 5db780298..19a55465e 100644 --- a/src/server/game/World/WorldConfig.cpp +++ b/src/server/game/World/WorldConfig.cpp @@ -406,6 +406,7 @@ void WorldConfig::BuildConfigCache() SetConfigValue(CONFIG_LISTEN_RANGE_TEXTEMOTE, "ListenRange.TextEmote", 40.0f); SetConfigValue(CONFIG_LISTEN_RANGE_YELL, "ListenRange.Yell", 300.0f); + SetConfigValue(CONFIG_BATTLEGROUND_PREP_TIME, "Battleground.PrepTime", 120); SetConfigValue(CONFIG_BATTLEGROUND_OVERRIDE_LOWLEVELS_MINPLAYERS, "Battleground.Override.LowLevels.MinPlayers", 0); SetConfigValue(CONFIG_BATTLEGROUND_DISABLE_QUEST_SHARE_IN_BG, "Battleground.DisableQuestShareInBG", false); SetConfigValue(CONFIG_BATTLEGROUND_DISABLE_READY_CHECK_IN_BG, "Battleground.DisableReadyCheckInBG", false); @@ -436,6 +437,7 @@ void WorldConfig::BuildConfigCache() SetConfigValue(CONFIG_BATTLEGROUND_ALTERAC_REP_ONBOSSDEATH, "Battleground.Alterac.ReputationOnBossDeath", 350); SetConfigValue(CONFIG_BATTLEGROUND_EYEOFTHESTORM_CAPTUREPOINTS, "Battleground.EyeOfTheStorm.CapturePoints", 1600); + SetConfigValue(CONFIG_ARENA_PREP_TIME, "Arena.PrepTime", 60); SetConfigValue(CONFIG_ARENA_MAX_RATING_DIFFERENCE, "Arena.MaxRatingDifference", 150); SetConfigValue(CONFIG_ARENA_RATING_DISCARD_TIMER, "Arena.RatingDiscardTimer", 600000); SetConfigValue(CONFIG_ARENA_PREV_OPPONENTS_DISCARD_TIMER, "Arena.PreviousOpponentsDiscardTimer", 120000); diff --git a/src/server/game/World/WorldConfig.h b/src/server/game/World/WorldConfig.h index 989746b81..b874ebc75 100644 --- a/src/server/game/World/WorldConfig.h +++ b/src/server/game/World/WorldConfig.h @@ -254,6 +254,7 @@ enum ServerConfigs CONFIG_DEATH_SICKNESS_LEVEL, CONFIG_INSTANT_LOGOUT, CONFIG_DISABLE_BREATHING, + CONFIG_BATTLEGROUND_PREP_TIME, CONFIG_BATTLEGROUND_OVERRIDE_LOWLEVELS_MINPLAYERS, CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_SPAM_DELAY, CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_TIMER, @@ -274,6 +275,7 @@ enum ServerConfigs CONFIG_BATTLEGROUND_ALTERAC_REP_ONBOSSDEATH, CONFIG_BATTLEGROUND_EYEOFTHESTORM_CAPTUREPOINTS, CONFIG_WINTERGRASP_ENABLE, + CONFIG_ARENA_PREP_TIME, CONFIG_ARENA_MAX_RATING_DIFFERENCE, CONFIG_ARENA_RATING_DISCARD_TIMER, CONFIG_ARENA_PREV_OPPONENTS_DISCARD_TIMER,