diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/server/game/Battlegrounds/Battleground.cpp | 43 | ||||
-rw-r--r-- | src/server/game/Battlegrounds/Battleground.h | 4 | ||||
-rw-r--r-- | src/server/game/Groups/Group.cpp | 39 | ||||
-rw-r--r-- | src/server/game/Groups/Group.h | 32 | ||||
-rw-r--r-- | src/server/game/Handlers/MiscHandler.cpp | 18 | ||||
-rw-r--r-- | src/server/game/Server/Packets/MiscPackets.cpp | 5 | ||||
-rw-r--r-- | src/server/game/Server/Packets/MiscPackets.h | 20 | ||||
-rw-r--r-- | src/server/game/Server/Protocol/Opcodes.cpp | 2 | ||||
-rw-r--r-- | src/server/game/Server/WorldSession.h | 2 |
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); |