aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy <Golrag@users.noreply.github.com>2024-01-25 14:15:58 +0100
committerGitHub <noreply@github.com>2024-01-25 14:15:58 +0100
commit6ed8b5c9077aba788ff5bc51f2652109bfea6175 (patch)
tree50b7261909a6ea4504a429dbb0060181dd2ea755
parent6a0de41fd2b2e7d2d9478b3d61ae0842013523ed (diff)
Core/PacketIO: Handle QueryCountdownTimer (#29539)
* Add it to battleground * Base implementation countdowns in Group * Fix timer sync between groups in battlegrounds
-rw-r--r--src/server/game/Battlegrounds/Battleground.cpp43
-rw-r--r--src/server/game/Battlegrounds/Battleground.h4
-rw-r--r--src/server/game/Groups/Group.cpp39
-rw-r--r--src/server/game/Groups/Group.h32
-rw-r--r--src/server/game/Handlers/MiscHandler.cpp18
-rw-r--r--src/server/game/Server/Packets/MiscPackets.cpp5
-rw-r--r--src/server/game/Server/Packets/MiscPackets.h20
-rw-r--r--src/server/game/Server/Protocol/Opcodes.cpp2
-rw-r--r--src/server/game/Server/WorldSession.h2
9 files changed, 123 insertions, 42 deletions
diff --git a/src/server/game/Battlegrounds/Battleground.cpp b/src/server/game/Battlegrounds/Battleground.cpp
index 5f3dff221aa..67f47e2733d 100644
--- a/src/server/game/Battlegrounds/Battleground.cpp
+++ b/src/server/game/Battlegrounds/Battleground.cpp
@@ -56,7 +56,7 @@ void Battleground::BroadcastWorker(Do& _do)
_do(player);
}
-Battleground::Battleground(BattlegroundTemplate const* battlegroundTemplate) : _battlegroundTemplate(battlegroundTemplate), _pvpDifficultyEntry(nullptr), _pvpStatIds(nullptr)
+Battleground::Battleground(BattlegroundTemplate const* battlegroundTemplate) : _battlegroundTemplate(battlegroundTemplate), _pvpDifficultyEntry(nullptr), _pvpStatIds(nullptr), _preparationStartTime(0)
{
ASSERT(_battlegroundTemplate, "Nonexisting Battleground Template passed to battleground ctor!");
@@ -69,7 +69,6 @@ Battleground::Battleground(BattlegroundTemplate const* battlegroundTemplate) : _
m_ArenaType = 0;
_winnerTeamId = PVP_TEAM_NEUTRAL;
m_StartTime = 0;
- m_CountdownTimer = 0;
m_ResetStatTimer = 0;
m_ValidStartPositionTimer = 0;
m_Events = 0;
@@ -206,10 +205,7 @@ void Battleground::Update(uint32 diff)
// Update start time and reset stats timer
SetElapsedTime(GetElapsedTime() + diff);
if (GetStatus() == STATUS_WAIT_JOIN)
- {
m_ResetStatTimer += diff;
- m_CountdownTimer += diff;
- }
PostUpdateImpl(diff);
}
@@ -349,23 +345,6 @@ inline void Battleground::_ProcessJoin(uint32 diff)
player->ResetAllPowers();
}
- // Send packet every 10 seconds until the 2nd field reach 0
- if (m_CountdownTimer >= 10000)
- {
- Seconds countdownMaxForBGType = Seconds(isArena() ? ARENA_COUNTDOWN_MAX : BATTLEGROUND_COUNTDOWN_MAX);
-
- WorldPackets::Misc::StartTimer startTimer;
- startTimer.Type = WorldPackets::Misc::StartTimer::Pvp;
- startTimer.TimeLeft = std::chrono::duration_cast<Seconds>(countdownMaxForBGType - Milliseconds(GetElapsedTime()));
- startTimer.TotalTime = countdownMaxForBGType;
-
- for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
- if (Player* player = ObjectAccessor::FindPlayer(itr->first))
- player->SendDirectMessage(startTimer.Write());
-
- m_CountdownTimer = 0;
- }
-
if (!(m_Events & BG_STARTING_EVENT_1))
{
m_Events |= BG_STARTING_EVENT_1;
@@ -384,6 +363,11 @@ inline void Battleground::_ProcessJoin(uint32 diff)
return;
}
+ _preparationStartTime = GameTime::GetGameTime();
+ for (Group* group : m_BgRaids)
+ if (group)
+ group->StartCountdown(CountdownTimerType::Pvp, Seconds(StartDelayTimes[BG_STARTING_EVENT_FIRST] / 1000), _preparationStartTime);
+
StartingEventCloseDoors();
SetStartDelayTime(StartDelayTimes[BG_STARTING_EVENT_FIRST]);
// First start warning - 2 or 1 minute
@@ -1076,18 +1060,8 @@ void Battleground::AddPlayer(Player* player, BattlegroundQueueTypeId queueId)
else
{
if (GetStatus() == STATUS_WAIT_JOIN) // not started yet
- {
player->CastSpell(player, SPELL_PREPARATION, true); // reduces all mana cost of spells.
- Seconds countdownMaxForBGType = Seconds(isArena() ? ARENA_COUNTDOWN_MAX : BATTLEGROUND_COUNTDOWN_MAX);
-
- WorldPackets::Misc::StartTimer startTimer;
- startTimer.Type = WorldPackets::Misc::StartTimer::Pvp;
- startTimer.TimeLeft = std::chrono::duration_cast<Seconds>(countdownMaxForBGType - Milliseconds(GetElapsedTime()));
- startTimer.TotalTime = countdownMaxForBGType;
- player->SendDirectMessage(startTimer.Write());
- }
-
if (bp.Mercenary)
{
if (bp.Team == HORDE)
@@ -1120,6 +1094,11 @@ void Battleground::AddOrSetPlayerToCorrectBgGroup(Player* player, Team team)
group = new Group;
SetBgRaid(team, group);
group->Create(player);
+ Seconds countdownMaxForBGType = Seconds(StartDelayTimes[BG_STARTING_EVENT_FIRST] / 1000);
+ if (_preparationStartTime)
+ group->StartCountdown(CountdownTimerType::Pvp, countdownMaxForBGType, _preparationStartTime);
+ else
+ group->StartCountdown(CountdownTimerType::Pvp, countdownMaxForBGType);
}
else // raid already exist
{
diff --git a/src/server/game/Battlegrounds/Battleground.h b/src/server/game/Battlegrounds/Battleground.h
index 31593798616..843f1c57f1d 100644
--- a/src/server/game/Battlegrounds/Battleground.h
+++ b/src/server/game/Battlegrounds/Battleground.h
@@ -563,7 +563,6 @@ class TC_GAME_API Battleground : public ZoneScript
BattlegroundStatus m_Status;
uint32 m_ClientInstanceID; // the instance-id which is sent to the client and without any other internal use
uint32 m_StartTime;
- uint32 m_CountdownTimer;
uint32 m_ResetStatTimer;
uint32 m_ValidStartPositionTimer;
int32 m_EndTime; // it is set to 120000 when bg is ending and it decreases itself
@@ -607,5 +606,8 @@ class TC_GAME_API Battleground : public ZoneScript
std::unordered_set<uint32> const* _pvpStatIds;
std::vector<WorldPackets::Battleground::BattlegroundPlayerPosition> _playerPositions;
+
+ // Time when the first message "the battle will begin in 2minutes" is send (or 1m for arenas)
+ time_t _preparationStartTime;
};
#endif
diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp
index 1e1a1f28e66..c98dcee1152 100644
--- a/src/server/game/Groups/Group.cpp
+++ b/src/server/game/Groups/Group.cpp
@@ -23,12 +23,14 @@
#include "DB2Stores.h"
#include "Formulas.h"
#include "GameObject.h"
+#include "GameTime.h"
#include "GroupMgr.h"
#include "Item.h"
#include "LFGMgr.h"
#include "Log.h"
#include "Loot.h"
#include "MapManager.h"
+#include "MiscPackets.h"
#include "ObjectAccessor.h"
#include "ObjectMgr.h"
#include "PartyPackets.h"
@@ -37,6 +39,22 @@
#include "UpdateData.h"
#include "WorldSession.h"
+Seconds Group::CountdownInfo::GetTimeLeft() const
+{
+ return Seconds(std::max<time_t>(_endTime - GameTime::GetGameTime(), 0));
+}
+
+void Group::CountdownInfo::StartCountdown(Seconds duration, Optional<time_t> startTime)
+{
+ _startTime = startTime ? *startTime : GameTime::GetGameTime();
+ _endTime = _startTime + duration.count();
+}
+
+bool Group::CountdownInfo::IsRunning() const
+{
+ return _endTime > GameTime::GetGameTime();
+}
+
Group::Group() : m_leaderGuid(), m_leaderFactionGroup(0), m_leaderName(""), m_groupFlags(GROUP_FLAG_NONE), m_groupCategory(GROUP_CATEGORY_HOME),
m_dungeonDifficulty(DIFFICULTY_NORMAL), m_raidDifficulty(DIFFICULTY_NORMAL_RAID), m_legacyRaidDifficulty(DIFFICULTY_10_N),
m_bgGroup(nullptr), m_bfGroup(nullptr), m_lootMethod(PERSONAL_LOOT), m_lootThreshold(ITEM_QUALITY_UNCOMMON), m_looterGuid(),
@@ -48,6 +66,8 @@ m_readyCheckStarted(false), m_readyCheckTimer(Milliseconds::zero()), m_activeMar
for (uint8 i = 0; i < RAID_MARKERS_COUNT; ++i)
m_markers[i] = nullptr;
+
+ _countdowns = { nullptr, nullptr, nullptr };
}
Group::~Group()
@@ -1403,6 +1423,25 @@ void Group::BroadcastGroupUpdate(void)
}
}
+void Group::StartCountdown(CountdownTimerType timerType, Seconds duration, Optional<time_t> startTime)
+{
+ if (AsUnderlyingType(timerType) < 0 || AsUnderlyingType(timerType) >= std::ssize(_countdowns))
+ return;
+
+ if (!_countdowns[AsUnderlyingType(timerType)])
+ _countdowns[AsUnderlyingType(timerType)] = std::make_unique<CountdownInfo>();
+
+ _countdowns[AsUnderlyingType(timerType)]->StartCountdown(duration, startTime);
+}
+
+Group::CountdownInfo const* Group::GetCountdownInfo(CountdownTimerType timerType) const
+{
+ if (AsUnderlyingType(timerType) < 0 || AsUnderlyingType(timerType) >= std::ssize(_countdowns))
+ return nullptr;
+
+ return _countdowns[AsUnderlyingType(timerType)].get();
+}
+
void Group::SetLootMethod(LootMethod method)
{
m_lootMethod = method;
diff --git a/src/server/game/Groups/Group.h b/src/server/game/Groups/Group.h
index 5358795efc6..ee28dcb7f9a 100644
--- a/src/server/game/Groups/Group.h
+++ b/src/server/game/Groups/Group.h
@@ -171,6 +171,13 @@ struct RaidMarker
}
};
+enum class CountdownTimerType : int32
+{
+ Pvp = 0,
+ ChallengeMode = 1,
+ PlayerCountdown = 2
+};
+
enum class PingSubjectType : uint8
{
Attack = 0,
@@ -202,6 +209,26 @@ class TC_GAME_API Group
typedef std::list<MemberSlot> MemberSlotList;
typedef MemberSlotList::const_iterator member_citerator;
+ class CountdownInfo
+ {
+ public:
+ CountdownInfo() : _startTime(0), _endTime(0) { }
+
+ Seconds GetTimeLeft() const;
+
+ Seconds GetTotalTime() const
+ {
+ return Seconds(_endTime - _startTime);
+ }
+
+ void StartCountdown(Seconds duration, Optional<time_t> startTime = { });
+ bool IsRunning() const;
+
+ private:
+ time_t _startTime;
+ time_t _endTime;
+ };
+
protected:
typedef MemberSlotList::iterator member_witerator;
typedef std::set<Player*> InvitesList;
@@ -379,6 +406,9 @@ class TC_GAME_API Group
// FG: evil hacks
void BroadcastGroupUpdate(void);
+ void StartCountdown(CountdownTimerType timerType, Seconds duration, Optional<time_t> startTime = { });
+ CountdownInfo const* GetCountdownInfo(CountdownTimerType timerType) const;
+
protected:
bool _setMembersGroup(ObjectGuid guid, uint8 group);
void _homebindIfInstance(Player* player);
@@ -423,5 +453,7 @@ class TC_GAME_API Group
// Raid markers
std::array<std::unique_ptr<RaidMarker>, RAID_MARKERS_COUNT> m_markers;
uint32 m_activeMarkers;
+
+ std::array<std::unique_ptr<CountdownInfo>, 3> _countdowns;
};
#endif
diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp
index 48bd713ee0d..2416a635d1d 100644
--- a/src/server/game/Handlers/MiscHandler.cpp
+++ b/src/server/game/Handlers/MiscHandler.cpp
@@ -1181,3 +1181,21 @@ void WorldSession::HandleRequestLatestSplashScreen(WorldPackets::Misc::RequestLa
splashScreenShowLatest.UISplashScreenID = splashScreen ? splashScreen->ID : 0;
SendPacket(splashScreenShowLatest.Write());
}
+
+void WorldSession::HandleQueryCountdownTimer(WorldPackets::Misc::QueryCountdownTimer& queryCountdownTimer)
+{
+ Group const* group = _player->GetGroup();
+ if (!group)
+ return;
+
+ Group::CountdownInfo const* info = group->GetCountdownInfo(queryCountdownTimer.TimerType);
+ if (!info)
+ return;
+
+ WorldPackets::Misc::StartTimer startTimer;
+ startTimer.Type = queryCountdownTimer.TimerType;
+ startTimer.TimeLeft = info->GetTimeLeft();
+ startTimer.TotalTime = info->GetTotalTime();
+
+ _player->SendDirectMessage(startTimer.Write());
+}
diff --git a/src/server/game/Server/Packets/MiscPackets.cpp b/src/server/game/Server/Packets/MiscPackets.cpp
index 5df2b2e4f91..41f012e26a8 100644
--- a/src/server/game/Server/Packets/MiscPackets.cpp
+++ b/src/server/game/Server/Packets/MiscPackets.cpp
@@ -760,6 +760,11 @@ WorldPacket const* WorldPackets::Misc::StartTimer::Write()
return &_worldPacket;
}
+void WorldPackets::Misc::QueryCountdownTimer::Read()
+{
+ TimerType = _worldPacket.read<CountdownTimerType, int32>();
+}
+
void WorldPackets::Misc::ConversationLineStarted::Read()
{
_worldPacket >> ConversationGUID;
diff --git a/src/server/game/Server/Packets/MiscPackets.h b/src/server/game/Server/Packets/MiscPackets.h
index 67af0bb244c..040c2a6e3c2 100644
--- a/src/server/game/Server/Packets/MiscPackets.h
+++ b/src/server/game/Server/Packets/MiscPackets.h
@@ -32,6 +32,7 @@
#include <array>
#include <map>
+enum class CountdownTimerType : int32;
enum UnitStandStateType : uint8;
enum WeatherState : uint32;
@@ -929,20 +930,23 @@ namespace WorldPackets
class StartTimer final : public ServerPacket
{
public:
- enum TimerType : int32
- {
- Pvp = 0,
- ChallengeMode = 1,
- PlayerCountdown = 2
- };
-
StartTimer() : ServerPacket(SMSG_START_TIMER, 12) { }
WorldPacket const* Write() override;
Duration<Seconds> TotalTime;
Duration<Seconds> TimeLeft;
- TimerType Type = Pvp;
+ CountdownTimerType Type = {};
+ };
+
+ class QueryCountdownTimer final : public ClientPacket
+ {
+ public:
+ QueryCountdownTimer(WorldPacket&& packet) : ClientPacket(CMSG_QUERY_COUNTDOWN_TIMER, std::move(packet)) { }
+
+ void Read() override;
+
+ CountdownTimerType TimerType = {};
};
class ConversationLineStarted final : public ClientPacket
diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp
index 9a40d087df3..bba1839d92b 100644
--- a/src/server/game/Server/Protocol/Opcodes.cpp
+++ b/src/server/game/Server/Protocol/Opcodes.cpp
@@ -729,7 +729,7 @@ void OpcodeTable::Initialize()
DEFINE_HANDLER(CMSG_QUERY_BATTLE_PET_NAME, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleQueryBattlePetName);
DEFINE_HANDLER(CMSG_QUERY_CORPSE_LOCATION_FROM_CLIENT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQueryCorpseLocation);
DEFINE_HANDLER(CMSG_QUERY_CORPSE_TRANSPORT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQueryCorpseTransport);
- DEFINE_HANDLER(CMSG_QUERY_COUNTDOWN_TIMER, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL);
+ DEFINE_HANDLER(CMSG_QUERY_COUNTDOWN_TIMER, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleQueryCountdownTimer);
DEFINE_HANDLER(CMSG_QUERY_CREATURE, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleCreatureQuery);
DEFINE_HANDLER(CMSG_QUERY_GAME_OBJECT, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleGameObjectQueryOpcode);
DEFINE_HANDLER(CMSG_QUERY_GARRISON_PET_NAME, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL);
diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h
index 782e2919024..a1b5b5524aa 100644
--- a/src/server/game/Server/WorldSession.h
+++ b/src/server/game/Server/WorldSession.h
@@ -522,6 +522,7 @@ namespace WorldPackets
class CloseInteraction;
class ConversationLineStarted;
class RequestLatestSplashScreen;
+ class QueryCountdownTimer;
}
namespace Movement
@@ -1751,6 +1752,7 @@ class TC_GAME_API WorldSession
void HandleCloseInteraction(WorldPackets::Misc::CloseInteraction& closeInteraction);
void HandleConversationLineStarted(WorldPackets::Misc::ConversationLineStarted& conversationLineStarted);
void HandleKeyboundOverride(WorldPackets::Spells::KeyboundOverride& keyboundOverride);
+ void HandleQueryCountdownTimer(WorldPackets::Misc::QueryCountdownTimer& queryCountdownTimer);
// Adventure Journal
void HandleAdventureJournalOpenQuest(WorldPackets::AdventureJournal::AdventureJournalOpenQuest& openQuest);