diff --git a/src/server/apps/worldserver/worldserver.conf.dist b/src/server/apps/worldserver/worldserver.conf.dist index e59978780..2e62d2829 100644 --- a/src/server/apps/worldserver/worldserver.conf.dist +++ b/src/server/apps/worldserver/worldserver.conf.dist @@ -3627,6 +3627,15 @@ Wintergrasp.NoBattleTimer = 150 Wintergrasp.CrashRestartTimer = 10 +# +# Wintergrasp.SkipBattleSessionCount +# Description: When the peace timer expires, if the number of active sessions +# exceeds this value, a new war will not start. +# Set to 0 to disable this check. +# Default: 3500 + +Wintergrasp.SkipBattleSessionCount = 3500 + # ################################################################################################### diff --git a/src/server/game/Battlefield/Battlefield.cpp b/src/server/game/Battlefield/Battlefield.cpp index b9d9d43e8..2edfa3fa4 100644 --- a/src/server/game/Battlefield/Battlefield.cpp +++ b/src/server/game/Battlefield/Battlefield.cpp @@ -31,6 +31,7 @@ #include "ObjectAccessor.h" #include "ObjectMgr.h" #include "Transport.h" +#include "World.h" #include "WorldPacket.h" #include "WorldSessionMgr.h" @@ -57,9 +58,6 @@ Battlefield::Battlefield() : NoWarBattleTime(0), RestartAfterCrash(0), TimeForAcceptInvite(20), - KickDontAcceptTimer(1000), - KickAfkPlayersTimer(1000), - LastResurrectTimer(RESURRECTION_INTERVAL), StartGroupingTimer(0), StartGrouping(false) { @@ -147,7 +145,11 @@ bool Battlefield::Update(uint32 diff) { if (Timer <= diff) { - if (!IsEnabled() || (!IsWarTime() && sWorldSessionMgr->GetActiveSessionCount() > 3500)) // if WG is disabled or there is more than 3500 connections, switch automatically + uint32 sessionLimit = sWorld->getIntConfig(CONFIG_WINTERGRASP_SKIP_BATTLE_SESSION_COUNT); + bool tooManySessions = sessionLimit && !IsWarTime() + && sWorldSessionMgr->GetActiveSessionCount() > sessionLimit; + + if (!IsEnabled() || tooManySessions) { Active = true; EndBattle(false); @@ -174,52 +176,16 @@ bool Battlefield::Update(uint32 diff) SendUpdateWorldStates(); } + _scheduler.Update(diff); + bool objectiveChanged = false; if (IsWarTime()) { - if (KickAfkPlayersTimer <= diff) - { - KickAfkPlayersTimer = 20000; - KickAfkPlayers(); - } - else - KickAfkPlayersTimer -= diff; - - // Kick players who chose not to accept invitation to the battle - if (KickDontAcceptTimer <= diff) - { - time_t now = GameTime::GetGameTime().count(); - for (uint8 team = 0; team < PVP_TEAMS_COUNT; ++team) - for (PlayerTimerMap::value_type const& pair : InvitedPlayers[team]) - if (pair.second <= now) - KickPlayerFromBattlefield(pair.first); - - InvitePlayersInZoneToWar(); - for (uint8 team = 0; team < PVP_TEAMS_COUNT; ++team) - for (PlayerTimerMap::value_type const& pair : PlayersWillBeKick[team]) - if (pair.second <= now) - KickPlayerFromBattlefield(pair.first); - - KickDontAcceptTimer = 5000; - } - else - KickDontAcceptTimer -= diff; - for (BfCapturePoint* cp : CapturePoints) if (cp->Update(diff)) objectiveChanged = true; } - if (LastResurrectTimer <= diff) - { - for (BfGraveyard* gy : GraveyardList) - if (gy) - gy->Resurrect(); - LastResurrectTimer = RESURRECTION_INTERVAL; - } - else - LastResurrectTimer -= diff; - return objectiveChanged; } @@ -342,6 +308,30 @@ void Battlefield::StartBattle() Timer = BattleTime; Active = true; + // Schedule war-only periodic timers + _scheduler.Schedule(1s, BATTLEFIELD_TIMER_GROUP_WAR, [this](TaskContext context) + { + KickAfkPlayers(); + context.Repeat(20s); + }); + + _scheduler.Schedule(1s, BATTLEFIELD_TIMER_GROUP_WAR, [this](TaskContext context) + { + time_t now = GameTime::GetGameTime().count(); + for (uint8 team = 0; team < PVP_TEAMS_COUNT; ++team) + for (PlayerTimerMap::value_type const& pair : InvitedPlayers[team]) + if (pair.second <= now) + KickPlayerFromBattlefield(pair.first); + + InvitePlayersInZoneToWar(); + for (uint8 team = 0; team < PVP_TEAMS_COUNT; ++team) + for (PlayerTimerMap::value_type const& pair : PlayersWillBeKick[team]) + if (pair.second <= now) + KickPlayerFromBattlefield(pair.first); + + context.Repeat(5s); + }); + InvitePlayersInZoneToWar(); InvitePlayersInQueueToWar(); @@ -359,6 +349,8 @@ void Battlefield::EndBattle(bool endByTimer) Active = false; + _scheduler.CancelGroup(BATTLEFIELD_TIMER_GROUP_WAR); + StartGrouping = false; if (!endByTimer) @@ -626,7 +618,9 @@ void Battlefield::RemovePlayerFromResurrectQueue(ObjectGuid playerGuid) void Battlefield::SendAreaSpiritHealerQueryOpcode(Player* player, ObjectGuid const& guid) { WorldPacket data(SMSG_AREA_SPIRIT_HEALER_TIME, 12); - uint32 time = LastResurrectTimer; // resurrect every 30 seconds + Milliseconds remaining = _scheduler.GetNextGroupOccurrence(BATTLEFIELD_TIMER_GROUP_RESURRECT); + uint32 time = static_cast(std::clamp(remaining, + Milliseconds::zero(), Milliseconds(RESURRECTION_INTERVAL)).count()); data << guid << time; ASSERT(player); diff --git a/src/server/game/Battlefield/Battlefield.h b/src/server/game/Battlefield/Battlefield.h index ad2a3394c..b3b45cb42 100644 --- a/src/server/game/Battlefield/Battlefield.h +++ b/src/server/game/Battlefield/Battlefield.h @@ -22,6 +22,7 @@ #include "GameObject.h" #include "ObjectAccessor.h" #include "SharedDefines.h" +#include "TaskScheduler.h" #include "ZoneScript.h" enum BattlefieldTypes @@ -55,6 +56,13 @@ enum BattlefieldSounds constexpr auto BATTLEFIELD_OBJECTIVE_UPDATE_INTERVAL = 1000; +enum BattlefieldTimerGroups +{ + BATTLEFIELD_TIMER_GROUP_RESURRECT = 1, + BATTLEFIELD_TIMER_GROUP_WAR = 2, + BATTLEFIELD_TIMER_GROUP_SAVE = 3, +}; + const uint32 BattlefieldFactions[PVP_TEAMS_COUNT] = { 1732, // Alliance @@ -401,18 +409,16 @@ protected: uint32 NoWarBattleTime; // Time between two battles uint32 RestartAfterCrash; // Delay to restart Wintergrasp if the server crashed during a running battle uint32 TimeForAcceptInvite; - uint32 KickDontAcceptTimer; WorldLocation KickPosition; // Position where players are teleported if they switch to afk during the battle or if they don't accept invitation - uint32 KickAfkPlayersTimer; // Timer for check Afk in war - // Graveyard variables GraveyardVect GraveyardList; // Vector which contains the different GY of the battle - uint32 LastResurrectTimer; // Timer for resurrect player every 30 sec uint32 StartGroupingTimer; // Timer for invite players in area 15 minutes before start battle bool StartGrouping; // bool for knowing if all players in area have been invited + TaskScheduler _scheduler; + GuidUnorderedSet Groups[PVP_TEAMS_COUNT]; // Contains different raid groups std::vector Data64; diff --git a/src/server/game/Battlefield/Zones/BattlefieldWG.cpp b/src/server/game/Battlefield/Zones/BattlefieldWG.cpp index 2478162d7..f0f9ee4fc 100644 --- a/src/server/game/Battlefield/Zones/BattlefieldWG.cpp +++ b/src/server/game/Battlefield/Zones/BattlefieldWG.cpp @@ -77,8 +77,6 @@ bool BattlefieldWG::SetupBattlefield() Data32.resize(BATTLEFIELD_WG_DATA_MAX); - SaveTimer = 60000; - // Init Graveyards SetGraveyardNumber(BATTLEFIELD_WG_GRAVEYARD_MAX); @@ -189,37 +187,31 @@ bool BattlefieldWG::SetupBattlefield() } UpdateCounterVehicle(true); + + // Schedule always-running periodic timers + _scheduler.Schedule(Milliseconds(RESURRECTION_INTERVAL), + BATTLEFIELD_TIMER_GROUP_RESURRECT, [this](TaskContext context) + { + for (BfGraveyard* gy : GraveyardList) + if (gy) + gy->Resurrect(); + context.Repeat(); + }); + + _scheduler.Schedule(60s, BATTLEFIELD_TIMER_GROUP_SAVE, [this](TaskContext context) + { + sWorldState->setWorldState(WORLD_STATE_BATTLEFIELD_WG_ACTIVE, Active); + sWorldState->setWorldState(WORLD_STATE_BATTLEFIELD_WG_DEFENDER, DefenderTeam); + sWorldState->setWorldState(ClockWorldState[0], Timer); + context.Repeat(); + }); + return true; } bool BattlefieldWG::Update(uint32 diff) { - bool result = Battlefield::Update(diff); - if (SaveTimer <= diff) - { - sWorldState->setWorldState(WORLD_STATE_BATTLEFIELD_WG_ACTIVE, Active); - sWorldState->setWorldState(WORLD_STATE_BATTLEFIELD_WG_DEFENDER, DefenderTeam); - sWorldState->setWorldState(ClockWorldState[0], Timer); - SaveTimer = 60 * IN_MILLISECONDS; - } - else - SaveTimer -= diff; - - // Update Tenacity - if (IsWarTime()) - { - if (TenacityUpdateTimer <= diff) - { - TenacityUpdateTimer = 10000; - if (!UpdateTenacityList.empty()) - UpdateTenacity(); - UpdateTenacityList.clear(); - } - else - TenacityUpdateTimer -= diff; - } - - return result; + return Battlefield::Update(diff); } void BattlefieldWG::OnBattleStart() @@ -293,7 +285,14 @@ void BattlefieldWG::OnBattleStart() // Xinef: reset tenacity counter TenacityStack = 0; - TenacityUpdateTimer = 20000; + + _scheduler.Schedule(20s, BATTLEFIELD_TIMER_GROUP_WAR, [this](TaskContext context) + { + if (!UpdateTenacityList.empty()) + UpdateTenacity(); + UpdateTenacityList.clear(); + context.Repeat(10s); + }); if (sWorld->getBoolConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE)) ChatHandler(nullptr).SendWorldText(BATTLEFIELD_WG_WORLD_START_MESSAGE); diff --git a/src/server/game/Battlefield/Zones/BattlefieldWG.h b/src/server/game/Battlefield/Zones/BattlefieldWG.h index 58d39e55f..8ea7d3ef3 100644 --- a/src/server/game/Battlefield/Zones/BattlefieldWG.h +++ b/src/server/game/Battlefield/Zones/BattlefieldWG.h @@ -449,8 +449,6 @@ protected: GuidUnorderedSet UpdateTenacityList; int32 TenacityStack; - uint32 TenacityUpdateTimer; - uint32 SaveTimer; ObjectGuid TitansRelic; }; diff --git a/src/server/game/World/WorldConfig.cpp b/src/server/game/World/WorldConfig.cpp index b30587974..d754951d3 100644 --- a/src/server/game/World/WorldConfig.cpp +++ b/src/server/game/World/WorldConfig.cpp @@ -591,6 +591,8 @@ void WorldConfig::BuildConfigCache() SetConfigValue(CONFIG_WINTERGRASP_NOBATTLETIME, "Wintergrasp.NoBattleTimer", 150); SetConfigValue(CONFIG_WINTERGRASP_RESTART_AFTER_CRASH, "Wintergrasp.CrashRestartTimer", 10); + SetConfigValue(CONFIG_WINTERGRASP_SKIP_BATTLE_SESSION_COUNT, "Wintergrasp.SkipBattleSessionCount", 3500); + SetConfigValue(CONFIG_BIRTHDAY_TIME, "BirthdayTime", 1222964635); SetConfigValue(CONFIG_MINIGOB_MANABONK, "Minigob.Manabonk.Enable", true); diff --git a/src/server/game/World/WorldConfig.h b/src/server/game/World/WorldConfig.h index 0e4480af2..6356e4111 100644 --- a/src/server/game/World/WorldConfig.h +++ b/src/server/game/World/WorldConfig.h @@ -327,6 +327,7 @@ enum ServerConfigs CONFIG_WINTERGRASP_BATTLETIME, CONFIG_WINTERGRASP_NOBATTLETIME, CONFIG_WINTERGRASP_RESTART_AFTER_CRASH, + CONFIG_WINTERGRASP_SKIP_BATTLE_SESSION_COUNT, CONFIG_PACKET_SPOOF_BANMODE, CONFIG_PACKET_SPOOF_BANDURATION, CONFIG_WARDEN_CLIENT_RESPONSE_DELAY,