diff options
author | Shauren <shauren.trinity@gmail.com> | 2020-05-31 16:49:18 +0200 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2020-05-31 16:49:18 +0200 |
commit | bf8714b8705c3fccc77083c6dc8665767430d346 (patch) | |
tree | 7abe8a79f1849b7d5299dd784b8ace6d78f6311e | |
parent | 161944b7643c62f9e7705c64e42d42e5d07f1959 (diff) |
Core/Battlegrounds: Queue updates
* Fixed battleground queues for battlegrounds with id higher than 255
* Fixed queue display ingame after entering bg
* Fixed ingame display after leaving bg queue
* Fixed bg scoreboard
17 files changed, 518 insertions, 357 deletions
diff --git a/src/server/game/Battlegrounds/Battleground.cpp b/src/server/game/Battlegrounds/Battleground.cpp index 3296726efa8..46529667602 100644 --- a/src/server/game/Battlegrounds/Battleground.cpp +++ b/src/server/game/Battlegrounds/Battleground.cpp @@ -467,16 +467,9 @@ inline void Battleground::_ProcessJoin(uint32 diff) { /// @todo add arena sound PlaySoundToAll(SOUND_ARENA_START); for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr) + { if (Player* player = ObjectAccessor::FindPlayer(itr->first)) { - // BG Status packet - BattlegroundQueueTypeId bgQueueTypeId = BattlegroundMgr::BGQueueTypeId(GetTypeID(), GetArenaType()); - uint32 queueSlot = player->GetBattlegroundQueueIndex(bgQueueTypeId); - - WorldPackets::Battleground::BattlefieldStatusActive battlefieldStatus; - sBattlegroundMgr->BuildBattlegroundStatusActive(&battlefieldStatus, this, player, queueSlot, player->GetBattlegroundQueueJoinTime(bgQueueTypeId), GetArenaType()); - player->SendDirectMessage(battlefieldStatus.Write()); - // Correctly display EnemyUnitFrame player->SetArenaFaction(player->GetBGTeam()); @@ -496,6 +489,7 @@ inline void Battleground::_ProcessJoin(uint32 diff) }); } } + } CheckWinConditions(); } @@ -504,11 +498,13 @@ inline void Battleground::_ProcessJoin(uint32 diff) PlaySoundToAll(SOUND_BG_START); for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr) + { if (Player* player = ObjectAccessor::FindPlayer(itr->first)) { player->RemoveAurasDueToSpell(SPELL_PREPARATION); player->ResetAllPowers(); } + } // Announce BG starting if (sWorld->getBoolConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE)) sWorld->SendWorldText(LANG_BG_STARTED_ANNOUNCE_WORLD, GetName(), GetMinLevel(), GetMaxLevel()); @@ -734,10 +730,14 @@ void Battleground::EndBattleground(uint32 winner) //we must set it this way, because end time is sent in packet! SetRemainingTime(TIME_AUTOCLOSE_BATTLEGROUND); - WorldPackets::Battleground::PVPLogData pvpLogData; - BuildPvPLogDataPacket(pvpLogData); + WorldPackets::Battleground::PVPMatchEnd pvpMatchEnd; + pvpMatchEnd.Winner = GetWinner(); + pvpMatchEnd.Duration = std::max<int32>(0, (GetElapsedTime() - BG_START_DELAY_2M) / IN_MILLISECONDS); + pvpMatchEnd.LogData.emplace(); + BuildPvPLogDataPacket(*pvpMatchEnd.LogData); + pvpMatchEnd.Write(); - BattlegroundQueueTypeId bgQueueTypeId = BattlegroundMgr::BGQueueTypeId(GetTypeID(), GetArenaType()); + BattlegroundQueueTypeId bgQueueTypeId = GetQueueId(); for (BattlegroundPlayerMap::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) { @@ -832,11 +832,7 @@ void Battleground::EndBattleground(uint32 winner) BlockMovement(player); - player->SendDirectMessage(pvpLogData.Write()); - - WorldPackets::Battleground::BattlefieldStatusActive battlefieldStatus; - sBattlegroundMgr->BuildBattlegroundStatusActive(&battlefieldStatus, this, player, player->GetBattlegroundQueueIndex(bgQueueTypeId), player->GetBattlegroundQueueJoinTime(bgQueueTypeId), GetArenaType()); - player->SendDirectMessage(battlefieldStatus.Write()); + player->SendDirectMessage(pvpMatchEnd.GetRawPacket()); player->UpdateCriteria(CRITERIA_TYPE_COMPLETE_BATTLEGROUND, player->GetMapId()); } @@ -907,7 +903,7 @@ void Battleground::RemovePlayerAtLeave(ObjectGuid guid, bool Transport, bool Sen RemovePlayer(player, guid, team); // BG subclass specific code BattlegroundTypeId bgTypeId = GetTypeID(); - BattlegroundQueueTypeId bgQueueTypeId = BattlegroundMgr::BGQueueTypeId(GetTypeID(), GetArenaType()); + BattlegroundQueueTypeId bgQueueTypeId = GetQueueId(); if (participant) // if the player was a match participant, remove auras, calc rating, update queue { @@ -948,7 +944,7 @@ void Battleground::RemovePlayerAtLeave(ObjectGuid guid, bool Transport, bool Sen { // a player has left the battleground, so there are free slots -> add to queue AddToBGFreeSlotQueue(); - sBattlegroundMgr->ScheduleQueueUpdate(0, 0, bgQueueTypeId, bgTypeId, GetBracketId()); + sBattlegroundMgr->ScheduleQueueUpdate(0, bgQueueTypeId, GetBracketId()); } // Let others know @@ -1050,12 +1046,39 @@ void Battleground::AddPlayer(Player* player) SendPacketToTeam(team, playerJoined.Write(), player); // BG Status packet - BattlegroundQueueTypeId bgQueueTypeId = sBattlegroundMgr->BGQueueTypeId(GetTypeID(), GetArenaType()); + BattlegroundQueueTypeId bgQueueTypeId = GetQueueId(); uint32 queueSlot = player->GetBattlegroundQueueIndex(bgQueueTypeId); - WorldPackets::Battleground::BattlefieldStatusActive battlefieldStatus; - sBattlegroundMgr->BuildBattlegroundStatusActive(&battlefieldStatus, this, player, queueSlot, player->GetBattlegroundQueueJoinTime(bgQueueTypeId), GetArenaType()); - player->SendDirectMessage(battlefieldStatus.Write()); + WorldPackets::Battleground::PVPMatchInit pvpMatchState; + pvpMatchState.MapID = GetMapId(); + switch (GetStatus()) + { + case STATUS_NONE: + case STATUS_WAIT_QUEUE: + pvpMatchState.State = WorldPackets::Battleground::PVPMatchInit::Inactive; + break; + case STATUS_WAIT_JOIN: + case STATUS_IN_PROGRESS: + pvpMatchState.State = WorldPackets::Battleground::PVPMatchInit::InProgress; + break; + case STATUS_WAIT_LEAVE: + pvpMatchState.State = WorldPackets::Battleground::PVPMatchInit::Complete; + break; + default: + break; + } + + if (GetElapsedTime() >= BG_START_DELAY_2M) + { + pvpMatchState.Duration = (GetElapsedTime() - BG_START_DELAY_2M) / IN_MILLISECONDS; + pvpMatchState.StartTime = GameTime::GetGameTime() - pvpMatchState.Duration; + } + pvpMatchState.ArenaFaction = player->GetBGTeam() == HORDE ? BG_TEAM_HORDE : BG_TEAM_ALLIANCE; + pvpMatchState.BattlemasterListID = GetTypeID(); + pvpMatchState.Registered = false; + pvpMatchState.AffectsRating = isRated(); + + player->SendDirectMessage(pvpMatchState.Write()); player->RemoveAurasByType(SPELL_AURA_MOUNTED); @@ -1173,7 +1196,7 @@ void Battleground::AddToBGFreeSlotQueue() { if (!m_InBGFreeSlotQueue && isBattleground()) { - sBattlegroundMgr->AddToBGFreeSlotQueue(GetTypeID(), this); + sBattlegroundMgr->AddToBGFreeSlotQueue(GetQueueId(), this); m_InBGFreeSlotQueue = true; } } @@ -1183,7 +1206,7 @@ void Battleground::RemoveFromBGFreeSlotQueue() { if (m_InBGFreeSlotQueue) { - sBattlegroundMgr->RemoveFromBGFreeSlotQueue(GetTypeID(), m_InstanceID); + sBattlegroundMgr->RemoveFromBGFreeSlotQueue(GetQueueId(), m_InstanceID); m_InBGFreeSlotQueue = false; } } @@ -1764,17 +1787,13 @@ void Battleground::PlayerAddedToBGCheckIfBGIsRunning(Player* player) if (GetStatus() != STATUS_WAIT_LEAVE) return; - WorldPackets::Battleground::PVPLogData pvpLogData; - BattlegroundQueueTypeId bgQueueTypeId = BattlegroundMgr::BGQueueTypeId(GetTypeID(), GetArenaType()); + BattlegroundQueueTypeId bgQueueTypeId = GetQueueId(); BlockMovement(player); - BuildPvPLogDataPacket(pvpLogData); + WorldPackets::Battleground::PVPLogDataMessage pvpLogData; + BuildPvPLogDataPacket(pvpLogData.Data); player->SendDirectMessage(pvpLogData.Write()); - - WorldPackets::Battleground::BattlefieldStatusActive battlefieldStatus; - sBattlegroundMgr->BuildBattlegroundStatusActive(&battlefieldStatus, this, player, player->GetBattlegroundQueueIndex(bgQueueTypeId), player->GetBattlegroundQueueJoinTime(bgQueueTypeId), GetArenaType()); - player->SendDirectMessage(battlefieldStatus.Write()); } uint32 Battleground::GetAlivePlayersCountByTeam(uint32 Team) const @@ -1866,15 +1885,6 @@ char const* Battleground::GetName() const return _battlegroundTemplate->BattlemasterEntry->Name->Str[sWorld->GetDefaultDbcLocale()]; } -uint64 Battleground::GetQueueId() const -{ - BattlegroundQueueIdType type = BattlegroundQueueIdType::Battleground; - if (isArena()) - type = isRated() ? BattlegroundQueueIdType::Arena : BattlegroundQueueIdType::ArenaSkirmish; - - return uint64(_battlegroundTemplate->Id) | uint64(type) << 16 | UI64LIT(0x1F10000000000000); -} - BattlegroundTypeId Battleground::GetTypeID(bool getRandom) const { return getRandom ? m_RandomTypeID : _battlegroundTemplate->Id; diff --git a/src/server/game/Battlegrounds/Battleground.h b/src/server/game/Battlegrounds/Battleground.h index e0c5083e429..ba92d3aa526 100644 --- a/src/server/game/Battlegrounds/Battleground.h +++ b/src/server/game/Battlegrounds/Battleground.h @@ -42,7 +42,7 @@ namespace WorldPackets { namespace Battleground { - class PVPLogData; + struct PVPLogData; struct BattlegroundPlayerPosition; } @@ -239,6 +239,15 @@ enum class BattlegroundQueueIdType : uint8 ArenaSkirmish = 4 }; +enum class BattlegroundPointCaptureStatus +{ + AllianceControlled, + AllianceCapturing, + Neutral, + HordeCapturing, + HordeControlled +}; + /* This class is used to: 1. Add player to battleground @@ -273,7 +282,7 @@ class TC_GAME_API Battleground /* Battleground */ // Get methods: char const* GetName() const; - uint64 GetQueueId() const; + BattlegroundQueueTypeId GetQueueId() const { return m_queueId; } BattlegroundTypeId GetTypeID(bool getRandom = false) const; BattlegroundBracketId GetBracketId() const; uint32 GetInstanceID() const { return m_InstanceID; } @@ -299,6 +308,7 @@ class TC_GAME_API Battleground bool IsRandom() const { return m_IsRandom; } // Set methods: + void SetQueueId(BattlegroundQueueTypeId queueId) { m_queueId = queueId; } void SetRandomTypeID(BattlegroundTypeId TypeID) { m_RandomTypeID = TypeID; } //here we can count minlevel and maxlevel for players void SetBracket(PVPDifficultyEntry const* bracketEntry); @@ -565,6 +575,7 @@ class TC_GAME_API Battleground private: // Battleground + BattlegroundQueueTypeId m_queueId; BattlegroundTypeId m_RandomTypeID; uint32 m_InstanceID; // Battleground Instance's GUID! BattlegroundStatus m_Status; diff --git a/src/server/game/Battlegrounds/BattlegroundMgr.cpp b/src/server/game/Battlegrounds/BattlegroundMgr.cpp index 2556ac012c3..311770bcdd1 100644 --- a/src/server/game/Battlegrounds/BattlegroundMgr.cpp +++ b/src/server/game/Battlegrounds/BattlegroundMgr.cpp @@ -94,13 +94,17 @@ void BattlegroundMgr::DeleteAllBattlegrounds() while (!data.m_Battlegrounds.empty()) delete data.m_Battlegrounds.begin()->second; - data.m_Battlegrounds.clear(); - while (!data.BGFreeSlotQueue.empty()) - delete data.BGFreeSlotQueue.front(); + data.m_Battlegrounds.clear(); } bgDataStore.clear(); + + for (auto itr = m_BGFreeSlotQueue.begin(); itr != m_BGFreeSlotQueue.end(); ++itr) + while (!itr->second.empty()) + delete itr->second.front(); + + m_BGFreeSlotQueue.clear(); } BattlegroundMgr* BattlegroundMgr::instance() @@ -143,23 +147,21 @@ void BattlegroundMgr::Update(uint32 diff) } // update events timer - for (int qtype = BATTLEGROUND_QUEUE_NONE; qtype < MAX_BATTLEGROUND_QUEUE_TYPES; ++qtype) - m_BattlegroundQueues[qtype].UpdateEvents(diff); + for (std::pair<BattlegroundQueueTypeId const, BattlegroundQueue>& pair : m_BattlegroundQueues) + pair.second.UpdateEvents(diff); // update scheduled queues if (!m_QueueUpdateScheduler.empty()) { - std::vector<uint64> scheduled; + std::vector<ScheduledQueueUpdate> scheduled; std::swap(scheduled, m_QueueUpdateScheduler); for (uint8 i = 0; i < scheduled.size(); i++) { - uint32 arenaMMRating = scheduled[i] >> 32; - uint8 arenaType = scheduled[i] >> 24 & 255; - BattlegroundQueueTypeId bgQueueTypeId = BattlegroundQueueTypeId(scheduled[i] >> 16 & 255); - BattlegroundTypeId bgTypeId = BattlegroundTypeId((scheduled[i] >> 8) & 255); - BattlegroundBracketId bracket_id = BattlegroundBracketId(scheduled[i] & 255); - m_BattlegroundQueues[bgQueueTypeId].BattlegroundQueueUpdate(diff, bgTypeId, bracket_id, arenaType, arenaMMRating > 0, arenaMMRating); + uint32 arenaMMRating = scheduled[i].ArenaMatchmakerRating; + BattlegroundQueueTypeId bgQueueTypeId = scheduled[i].QueueId; + BattlegroundBracketId bracket_id = scheduled[i].BracketId; + GetBattlegroundQueue(bgQueueTypeId).BattlegroundQueueUpdate(diff, bracket_id, arenaMMRating); } } @@ -171,11 +173,12 @@ void BattlegroundMgr::Update(uint32 diff) { // forced update for rated arenas (scan all, but skipped non rated) TC_LOG_TRACE("bg.arena", "BattlegroundMgr: UPDATING ARENA QUEUES"); - for (int qtype = BATTLEGROUND_QUEUE_2v2; qtype <= BATTLEGROUND_QUEUE_5v5; ++qtype) + for (uint8 teamSize : { ARENA_TYPE_2v2, ARENA_TYPE_3v3, ARENA_TYPE_5v5 }) + { + BattlegroundQueueTypeId ratedArenaQueueId = BGQueueTypeId(BATTLEGROUND_AA, BattlegroundQueueIdType::Arena, true, teamSize); for (int bracket = BG_BRACKET_ID_FIRST; bracket < MAX_BATTLEGROUND_BRACKETS; ++bracket) - m_BattlegroundQueues[qtype].BattlegroundQueueUpdate(diff, - BATTLEGROUND_AA, BattlegroundBracketId(bracket), - BattlegroundMgr::BGArenaType(BattlegroundQueueTypeId(qtype)), true, 0); + GetBattlegroundQueue(ratedArenaQueueId).BattlegroundQueueUpdate(diff, BattlegroundBracketId(bracket), 0); + } m_NextRatedArenaUpdate = sWorld->getIntConfig(CONFIG_ARENA_RATED_UPDATE_TIMER); } @@ -184,13 +187,13 @@ void BattlegroundMgr::Update(uint32 diff) } } -void BattlegroundMgr::BuildBattlegroundStatusHeader(WorldPackets::Battleground::BattlefieldStatusHeader* header, Battleground* bg, Player* player, uint32 ticketId, uint32 joinTime, uint32 arenaType) +void BattlegroundMgr::BuildBattlegroundStatusHeader(WorldPackets::Battleground::BattlefieldStatusHeader* header, Battleground* bg, Player* player, uint32 ticketId, uint32 joinTime, BattlegroundQueueTypeId queueId, uint32 arenaType) { header->Ticket.RequesterGuid = player->GetGUID(); header->Ticket.Id = ticketId; header->Ticket.Type = WorldPackets::LFG::RideType::Battlegrounds; header->Ticket.Time = joinTime; - header->QueueID.push_back(bg->GetQueueId()); + header->QueueID.push_back(queueId.GetPacked()); header->RangeMin = bg->GetMinLevel(); header->RangeMax = bg->GetMaxLevel(); header->TeamSize = bg->isArena() ? arenaType : 0; @@ -209,7 +212,7 @@ void BattlegroundMgr::BuildBattlegroundStatusNone(WorldPackets::Battleground::Ba void BattlegroundMgr::BuildBattlegroundStatusNeedConfirmation(WorldPackets::Battleground::BattlefieldStatusNeedConfirmation* battlefieldStatus, Battleground* bg, Player* player, uint32 ticketId, uint32 joinTime, uint32 timeout, uint32 arenaType) { - BuildBattlegroundStatusHeader(&battlefieldStatus->Hdr, bg, player, ticketId, joinTime, arenaType); + BuildBattlegroundStatusHeader(&battlefieldStatus->Hdr, bg, player, ticketId, joinTime, bg->GetQueueId(), arenaType); battlefieldStatus->Mapid = bg->GetMapId(); battlefieldStatus->Timeout = timeout; battlefieldStatus->Role = 0; @@ -217,7 +220,7 @@ void BattlegroundMgr::BuildBattlegroundStatusNeedConfirmation(WorldPackets::Batt void BattlegroundMgr::BuildBattlegroundStatusActive(WorldPackets::Battleground::BattlefieldStatusActive* battlefieldStatus, Battleground* bg, Player* player, uint32 ticketId, uint32 joinTime, uint32 arenaType) { - BuildBattlegroundStatusHeader(&battlefieldStatus->Hdr, bg, player, ticketId, joinTime, arenaType); + BuildBattlegroundStatusHeader(&battlefieldStatus->Hdr, bg, player, ticketId, joinTime, bg->GetQueueId(), arenaType); battlefieldStatus->ShutdownTimer = bg->GetRemainingTime(); battlefieldStatus->ArenaFaction = player->GetBGTeam() == HORDE ? BG_TEAM_HORDE : BG_TEAM_ALLIANCE; battlefieldStatus->LeftEarly = false; @@ -225,9 +228,9 @@ void BattlegroundMgr::BuildBattlegroundStatusActive(WorldPackets::Battleground:: battlefieldStatus->Mapid = bg->GetMapId(); } -void BattlegroundMgr::BuildBattlegroundStatusQueued(WorldPackets::Battleground::BattlefieldStatusQueued* battlefieldStatus, Battleground* bg, Player* player, uint32 ticketId, uint32 joinTime, uint32 avgWaitTime, uint32 arenaType, bool asGroup) +void BattlegroundMgr::BuildBattlegroundStatusQueued(WorldPackets::Battleground::BattlefieldStatusQueued* battlefieldStatus, Battleground* bg, Player* player, uint32 ticketId, uint32 joinTime, BattlegroundQueueTypeId queueId, uint32 avgWaitTime, uint32 arenaType, bool asGroup) { - BuildBattlegroundStatusHeader(&battlefieldStatus->Hdr, bg, player, ticketId, joinTime, arenaType); + BuildBattlegroundStatusHeader(&battlefieldStatus->Hdr, bg, player, ticketId, joinTime, queueId, arenaType); battlefieldStatus->AverageWaitTime = avgWaitTime; battlefieldStatus->AsGroup = asGroup; battlefieldStatus->SuspendedQueue = false; @@ -240,8 +243,8 @@ void BattlegroundMgr::BuildBattlegroundStatusFailed(WorldPackets::Battleground:: battlefieldStatus->Ticket.RequesterGuid = pPlayer->GetGUID(); battlefieldStatus->Ticket.Id = ticketId; battlefieldStatus->Ticket.Type = WorldPackets::LFG::RideType::Battlegrounds; - battlefieldStatus->Ticket.Time = pPlayer->GetBattlegroundQueueJoinTime(BGQueueTypeId(bg->GetTypeID(), arenaType)); - battlefieldStatus->QueueID = bg->GetQueueId(); + battlefieldStatus->Ticket.Time = pPlayer->GetBattlegroundQueueJoinTime(bg->GetQueueId()); + battlefieldStatus->QueueID = bg->GetQueueId().GetPacked(); battlefieldStatus->Reason = result; if (errorGuid && (result == ERR_BATTLEGROUND_NOT_IN_BATTLEGROUND || result == ERR_BATTLEGROUND_JOIN_TIMED_OUT)) battlefieldStatus->ClientID = *errorGuid; @@ -254,7 +257,7 @@ Battleground* BattlegroundMgr::GetBattleground(uint32 instanceId, BattlegroundTy BattlegroundDataContainer::const_iterator begin, end; - if (bgTypeId == BATTLEGROUND_TYPE_NONE) + if (bgTypeId == BATTLEGROUND_TYPE_NONE || bgTypeId == BATTLEGROUND_RB || bgTypeId == BATTLEGROUND_RANDOM_EPIC) { begin = bgDataStore.begin(); end = bgDataStore.end(); @@ -315,9 +318,9 @@ uint32 BattlegroundMgr::CreateClientVisibleInstanceId(BattlegroundTypeId bgTypeI } // create a new battleground that will really be used to play -Battleground* BattlegroundMgr::CreateNewBattleground(BattlegroundTypeId originalBgTypeId, PVPDifficultyEntry const* bracketEntry, uint8 arenaType, bool isRated) +Battleground* BattlegroundMgr::CreateNewBattleground(BattlegroundQueueTypeId queueId, PVPDifficultyEntry const* bracketEntry) { - BattlegroundTypeId bgTypeId = GetRandomBG(originalBgTypeId); + BattlegroundTypeId bgTypeId = GetRandomBG(BattlegroundTypeId(queueId.BattlemasterListId)); // get the template BG Battleground* bg_template = GetBattlegroundTemplate(bgTypeId); @@ -373,20 +376,22 @@ Battleground* BattlegroundMgr::CreateNewBattleground(BattlegroundTypeId original break; case BATTLEGROUND_RB: case BATTLEGROUND_AA: + case BATTLEGROUND_RANDOM_EPIC: default: return NULL; } - bool isRandom = bgTypeId != originalBgTypeId && !bg->isArena(); + bool isRandom = bgTypeId != BattlegroundTypeId(queueId.BattlemasterListId) && !bg->isArena(); + bg->SetQueueId(queueId); bg->SetBracket(bracketEntry); bg->SetInstanceID(sMapMgr->GenerateInstanceId()); - bg->SetClientInstanceID(CreateClientVisibleInstanceId(originalBgTypeId, bracketEntry->GetBracketId())); + bg->SetClientInstanceID(CreateClientVisibleInstanceId(BattlegroundTypeId(queueId.BattlemasterListId), bracketEntry->GetBracketId())); bg->Reset(); // reset the new bg (set status to status_wait_queue from status_none) bg->SetStatus(STATUS_WAIT_JOIN); // start the joining of the bg - bg->SetArenaType(arenaType); + bg->SetArenaType(queueId.TeamSize); bg->SetRandomTypeID(bgTypeId); - bg->SetRated(isRated); + bg->SetRated(queueId.Rated); bg->SetRandom(isRandom); return bg; @@ -447,6 +452,10 @@ bool BattlegroundMgr::CreateBattleground(BattlegroundTemplate const* bgTemplate) case BATTLEGROUND_BFG: bg = new BattlegroundBFG(bgTemplate); break; + case BATTLEGROUND_RANDOM_EPIC: + bg = new Battleground(bgTemplate); + bg->SetRandom(true); + break; default: return false; } @@ -455,10 +464,6 @@ bool BattlegroundMgr::CreateBattleground(BattlegroundTemplate const* bgTemplate) AddBattleground(bg); } - bg->SetInstanceID(0); - - AddBattleground(bg); - return true; } @@ -501,7 +506,7 @@ void BattlegroundMgr::LoadBattlegroundTemplates() bgTemplate.ScriptId = sObjectMgr->GetScriptId(fields[5].GetString()); bgTemplate.BattlemasterEntry = bl; - if (bgTemplate.Id != BATTLEGROUND_AA && bgTemplate.Id != BATTLEGROUND_RB) + if (bgTemplate.Id != BATTLEGROUND_AA && bgTemplate.Id != BATTLEGROUND_RB && bgTemplate.Id != BATTLEGROUND_RANDOM_EPIC) { uint32 startId = fields[1].GetUInt32(); if (WorldSafeLocsEntry const* start = sObjectMgr->GetWorldSafeLoc(startId)) @@ -598,94 +603,9 @@ bool BattlegroundMgr::IsArenaType(BattlegroundTypeId bgTypeId) || bgTypeId == BATTLEGROUND_RL; } -BattlegroundQueueTypeId BattlegroundMgr::BGQueueTypeId(BattlegroundTypeId bgTypeId, uint8 arenaType) -{ - switch (bgTypeId) - { - case BATTLEGROUND_AB: - return BATTLEGROUND_QUEUE_AB; - case BATTLEGROUND_AV: - return BATTLEGROUND_QUEUE_AV; - case BATTLEGROUND_EY: - return BATTLEGROUND_QUEUE_EY; - case BATTLEGROUND_IC: - return BATTLEGROUND_QUEUE_IC; - case BATTLEGROUND_TP: - return BATTLEGROUND_QUEUE_TP; - case BATTLEGROUND_BFG: - return BATTLEGROUND_QUEUE_BFG; - case BATTLEGROUND_RB: - return BATTLEGROUND_QUEUE_RB; - case BATTLEGROUND_SA: - return BATTLEGROUND_QUEUE_SA; - case BATTLEGROUND_WS: - return BATTLEGROUND_QUEUE_WS; - case BATTLEGROUND_AA: - case BATTLEGROUND_BE: - case BATTLEGROUND_DS: - case BATTLEGROUND_NA: - case BATTLEGROUND_RL: - case BATTLEGROUND_RV: - switch (arenaType) - { - case ARENA_TYPE_2v2: - return BATTLEGROUND_QUEUE_2v2; - case ARENA_TYPE_3v3: - return BATTLEGROUND_QUEUE_3v3; - case ARENA_TYPE_5v5: - return BATTLEGROUND_QUEUE_5v5; - default: - return BATTLEGROUND_QUEUE_NONE; - } - default: - return BATTLEGROUND_QUEUE_NONE; - } -} - -BattlegroundTypeId BattlegroundMgr::BGTemplateId(BattlegroundQueueTypeId bgQueueTypeId) +BattlegroundQueueTypeId BattlegroundMgr::BGQueueTypeId(uint16 battlemasterListId, BattlegroundQueueIdType type, bool rated, uint8 teamSize) { - switch (bgQueueTypeId) - { - case BATTLEGROUND_QUEUE_WS: - return BATTLEGROUND_WS; - case BATTLEGROUND_QUEUE_AB: - return BATTLEGROUND_AB; - case BATTLEGROUND_QUEUE_AV: - return BATTLEGROUND_AV; - case BATTLEGROUND_QUEUE_EY: - return BATTLEGROUND_EY; - case BATTLEGROUND_QUEUE_SA: - return BATTLEGROUND_SA; - case BATTLEGROUND_QUEUE_IC: - return BATTLEGROUND_IC; - case BATTLEGROUND_QUEUE_TP: - return BATTLEGROUND_TP; - case BATTLEGROUND_QUEUE_BFG: - return BATTLEGROUND_BFG; - case BATTLEGROUND_QUEUE_RB: - return BATTLEGROUND_RB; - case BATTLEGROUND_QUEUE_2v2: - case BATTLEGROUND_QUEUE_3v3: - case BATTLEGROUND_QUEUE_5v5: - return BATTLEGROUND_AA; - default: - return BattlegroundTypeId(0); // used for unknown template (it exists and does nothing) - } -} - -uint8 BattlegroundMgr::BGArenaType(BattlegroundQueueTypeId bgQueueTypeId) -{ - switch (bgQueueTypeId) - { - case BATTLEGROUND_QUEUE_2v2: - return ARENA_TYPE_2v2; - case BATTLEGROUND_QUEUE_3v3: - return ARENA_TYPE_3v3; - case BATTLEGROUND_QUEUE_5v5: - return ARENA_TYPE_5v5; - default: - return 0; - } + return { battlemasterListId, AsUnderlyingType(type), rated, teamSize }; } void BattlegroundMgr::ToggleTesting() @@ -708,11 +628,52 @@ void BattlegroundMgr::SetHolidayWeekends(uint32 mask) bg->SetHoliday((mask & (1 << bgtype)) != 0); } -void BattlegroundMgr::ScheduleQueueUpdate(uint32 arenaMatchmakerRating, uint8 arenaType, BattlegroundQueueTypeId bgQueueTypeId, BattlegroundTypeId bgTypeId, BattlegroundBracketId bracket_id) +bool BattlegroundMgr::IsValidQueueId(BattlegroundQueueTypeId bgQueueTypeId) +{ + BattlemasterListEntry const* battlemasterList = sBattlemasterListStore.LookupEntry(bgQueueTypeId.BattlemasterListId); + if (!battlemasterList) + return false; + + switch (BattlegroundQueueIdType(bgQueueTypeId.Type)) + { + case BattlegroundQueueIdType::Battleground: + if (battlemasterList->InstanceType != MAP_BATTLEGROUND) + return false; + if (bgQueueTypeId.TeamSize) + return false; + break; + case BattlegroundQueueIdType::Arena: + if (battlemasterList->InstanceType != MAP_ARENA) + return false; + if (!bgQueueTypeId.Rated) + return false; + if (!bgQueueTypeId.TeamSize) + return false; + break; + case BattlegroundQueueIdType::Wargame: + if (bgQueueTypeId.Rated) + return false; + break; + case BattlegroundQueueIdType::ArenaSkirmish: + if (battlemasterList->InstanceType != MAP_ARENA) + return false; + if (bgQueueTypeId.Rated) + return false; + if (bgQueueTypeId.TeamSize) + return false; + break; + default: + return false; + } + + return true; +} + +void BattlegroundMgr::ScheduleQueueUpdate(uint32 arenaMatchmakerRating, BattlegroundQueueTypeId bgQueueTypeId, BattlegroundBracketId bracket_id) { //This method must be atomic, @todo add mutex //we will use only 1 number created of bgTypeId and bracket_id - uint64 const scheduleId = ((uint64)arenaMatchmakerRating << 32) | ((uint64)arenaType << 24) | ((uint64)bgQueueTypeId << 16) | ((uint64)bgTypeId << 8) | (uint64)bracket_id; + ScheduledQueueUpdate scheduleId{ arenaMatchmakerRating, bgQueueTypeId, bracket_id }; if (std::find(m_QueueUpdateScheduler.begin(), m_QueueUpdateScheduler.end(), scheduleId) == m_QueueUpdateScheduler.end()) m_QueueUpdateScheduler.push_back(scheduleId); } @@ -862,19 +823,19 @@ BattlegroundTypeId BattlegroundMgr::GetRandomBG(BattlegroundTypeId bgTypeId) return BATTLEGROUND_TYPE_NONE; } -BGFreeSlotQueueContainer& BattlegroundMgr::GetBGFreeSlotQueueStore(BattlegroundTypeId bgTypeId) +BGFreeSlotQueueContainer& BattlegroundMgr::GetBGFreeSlotQueueStore(BattlegroundQueueTypeId bgTypeId) { - return bgDataStore[bgTypeId].BGFreeSlotQueue; + return m_BGFreeSlotQueue[bgTypeId]; } -void BattlegroundMgr::AddToBGFreeSlotQueue(BattlegroundTypeId bgTypeId, Battleground* bg) +void BattlegroundMgr::AddToBGFreeSlotQueue(BattlegroundQueueTypeId bgTypeId, Battleground* bg) { - bgDataStore[bgTypeId].BGFreeSlotQueue.push_front(bg); + m_BGFreeSlotQueue[bgTypeId].push_front(bg); } -void BattlegroundMgr::RemoveFromBGFreeSlotQueue(BattlegroundTypeId bgTypeId, uint32 instanceId) +void BattlegroundMgr::RemoveFromBGFreeSlotQueue(BattlegroundQueueTypeId bgTypeId, uint32 instanceId) { - BGFreeSlotQueueContainer& queues = bgDataStore[bgTypeId].BGFreeSlotQueue; + BGFreeSlotQueueContainer& queues = m_BGFreeSlotQueue[bgTypeId]; for (BGFreeSlotQueueContainer::iterator itr = queues.begin(); itr != queues.end(); ++itr) if ((*itr)->GetInstanceID() == instanceId) { diff --git a/src/server/game/Battlegrounds/BattlegroundMgr.h b/src/server/game/Battlegrounds/BattlegroundMgr.h index 38cc163835c..d571cb00c98 100644 --- a/src/server/game/Battlegrounds/BattlegroundMgr.h +++ b/src/server/game/Battlegrounds/BattlegroundMgr.h @@ -41,7 +41,6 @@ struct BattlegroundData { BattlegroundContainer m_Battlegrounds; BattlegroundClientIdsContainer m_ClientBattlegroundIds[MAX_BATTLEGROUND_BRACKETS]; - BGFreeSlotQueueContainer BGFreeSlotQueue; }; struct BattlegroundTemplate @@ -86,24 +85,24 @@ class TC_GAME_API BattlegroundMgr /* Packet Building */ void SendBattlegroundList(Player* player, ObjectGuid const& guid, BattlegroundTypeId bgTypeId); - void BuildBattlegroundStatusHeader(WorldPackets::Battleground::BattlefieldStatusHeader* battlefieldStatus, Battleground* bg, Player* player, uint32 ticketId, uint32 joinTime, uint32 arenaType); + void BuildBattlegroundStatusHeader(WorldPackets::Battleground::BattlefieldStatusHeader* battlefieldStatus, Battleground* bg, Player* player, uint32 ticketId, uint32 joinTime, BattlegroundQueueTypeId queueId, uint32 arenaType); void BuildBattlegroundStatusNone(WorldPackets::Battleground::BattlefieldStatusNone* battlefieldStatus, Player* player, uint32 ticketId, uint32 joinTime); void BuildBattlegroundStatusNeedConfirmation(WorldPackets::Battleground::BattlefieldStatusNeedConfirmation* battlefieldStatus, Battleground* bg, Player* player, uint32 ticketId, uint32 joinTime, uint32 timeout, uint32 arenaType); void BuildBattlegroundStatusActive(WorldPackets::Battleground::BattlefieldStatusActive* battlefieldStatus, Battleground* bg, Player* player, uint32 ticketId, uint32 joinTime, uint32 arenaType); - void BuildBattlegroundStatusQueued(WorldPackets::Battleground::BattlefieldStatusQueued* battlefieldStatus, Battleground* bg, Player* player, uint32 ticketId, uint32 joinTime, uint32 avgWaitTime, uint32 arenaType, bool asGroup); + void BuildBattlegroundStatusQueued(WorldPackets::Battleground::BattlefieldStatusQueued* battlefieldStatus, Battleground* bg, Player* player, uint32 ticketId, uint32 joinTime, BattlegroundQueueTypeId queueId, uint32 avgWaitTime, uint32 arenaType, bool asGroup); void BuildBattlegroundStatusFailed(WorldPackets::Battleground::BattlefieldStatusFailed* battlefieldStatus, Battleground* bg, Player* pPlayer, uint32 ticketId, uint32 arenaType, GroupJoinBattlegroundResult result, ObjectGuid const* errorGuid = nullptr); void SendAreaSpiritHealerQueryOpcode(Player* player, Battleground* bg, ObjectGuid const& guid); /* Battlegrounds */ Battleground* GetBattleground(uint32 InstanceID, BattlegroundTypeId bgTypeId); Battleground* GetBattlegroundTemplate(BattlegroundTypeId bgTypeId); - Battleground* CreateNewBattleground(BattlegroundTypeId bgTypeId, PVPDifficultyEntry const* bracketEntry, uint8 arenaType, bool isRated); + Battleground* CreateNewBattleground(BattlegroundQueueTypeId queueId, PVPDifficultyEntry const* bracketEntry); void AddBattleground(Battleground* bg); void RemoveBattleground(BattlegroundTypeId bgTypeId, uint32 instanceId); - void AddToBGFreeSlotQueue(BattlegroundTypeId bgTypeId, Battleground* bg); - void RemoveFromBGFreeSlotQueue(BattlegroundTypeId bgTypeId, uint32 instanceId); - BGFreeSlotQueueContainer& GetBGFreeSlotQueueStore(BattlegroundTypeId bgTypeId); + void AddToBGFreeSlotQueue(BattlegroundQueueTypeId bgTypeId, Battleground* bg); + void RemoveFromBGFreeSlotQueue(BattlegroundQueueTypeId bgTypeId, uint32 instanceId); + BGFreeSlotQueueContainer& GetBGFreeSlotQueueStore(BattlegroundQueueTypeId bgTypeId); void LoadBattlegroundTemplates(); void DeleteAllBattlegrounds(); @@ -111,8 +110,9 @@ class TC_GAME_API BattlegroundMgr void SendToBattleground(Player* player, uint32 InstanceID, BattlegroundTypeId bgTypeId); /* Battleground queues */ - BattlegroundQueue& GetBattlegroundQueue(BattlegroundQueueTypeId bgQueueTypeId) { return m_BattlegroundQueues[bgQueueTypeId]; } - void ScheduleQueueUpdate(uint32 arenaMatchmakerRating, uint8 arenaType, BattlegroundQueueTypeId bgQueueTypeId, BattlegroundTypeId bgTypeId, BattlegroundBracketId bracket_id); + static bool IsValidQueueId(BattlegroundQueueTypeId bgQueueTypeId); + BattlegroundQueue& GetBattlegroundQueue(BattlegroundQueueTypeId bgQueueTypeId) { return m_BattlegroundQueues.emplace(bgQueueTypeId, bgQueueTypeId).first->second; } + void ScheduleQueueUpdate(uint32 arenaMatchmakerRating, BattlegroundQueueTypeId bgQueueTypeId, BattlegroundBracketId bracket_id); uint32 GetPrematureFinishTime() const; void ToggleArenaTesting(); @@ -123,9 +123,7 @@ class TC_GAME_API BattlegroundMgr bool isArenaTesting() const { return m_ArenaTesting; } bool isTesting() const { return m_Testing; } - static BattlegroundQueueTypeId BGQueueTypeId(BattlegroundTypeId bgTypeId, uint8 arenaType); - static BattlegroundTypeId BGTemplateId(BattlegroundQueueTypeId bgQueueTypeId); - static uint8 BGArenaType(BattlegroundQueueTypeId bgQueueTypeId); + static BattlegroundQueueTypeId BGQueueTypeId(uint16 battlemasterListId, BattlegroundQueueIdType type, bool rated, uint8 teamSize); static HolidayIds BGTypeToWeekendHolidayId(BattlegroundTypeId bgTypeId); static BattlegroundTypeId WeekendHolidayIdToBGType(HolidayIds holiday); @@ -152,9 +150,22 @@ class TC_GAME_API BattlegroundMgr typedef std::map<BattlegroundTypeId, BattlegroundData> BattlegroundDataContainer; BattlegroundDataContainer bgDataStore; - BattlegroundQueue m_BattlegroundQueues[MAX_BATTLEGROUND_QUEUE_TYPES]; + std::map<BattlegroundQueueTypeId, BattlegroundQueue> m_BattlegroundQueues; + std::map<BattlegroundQueueTypeId, BGFreeSlotQueueContainer> m_BGFreeSlotQueue; - std::vector<uint64> m_QueueUpdateScheduler; + struct ScheduledQueueUpdate + { + uint32 ArenaMatchmakerRating; + BattlegroundQueueTypeId QueueId; + BattlegroundBracketId BracketId; + + bool operator==(ScheduledQueueUpdate const& right) const + { + return ArenaMatchmakerRating == right.ArenaMatchmakerRating && QueueId == right.QueueId && BracketId == right.BracketId; + } + }; + + std::vector<ScheduledQueueUpdate> m_QueueUpdateScheduler; uint32 m_NextRatedArenaUpdate; uint32 m_UpdateTimer; bool m_ArenaTesting; diff --git a/src/server/game/Battlegrounds/BattlegroundQueue.cpp b/src/server/game/Battlegrounds/BattlegroundQueue.cpp index 72dc24b11ba..15dbeb83f9b 100644 --- a/src/server/game/Battlegrounds/BattlegroundQueue.cpp +++ b/src/server/game/Battlegrounds/BattlegroundQueue.cpp @@ -34,7 +34,7 @@ /*** BATTLEGROUND QUEUE SYSTEM ***/ /*********************************************************/ -BattlegroundQueue::BattlegroundQueue() +BattlegroundQueue::BattlegroundQueue(BattlegroundQueueTypeId queueId) : m_queueId(queueId) { for (uint32 i = 0; i < BG_TEAMS_COUNT; ++i) { @@ -391,14 +391,13 @@ void BattlegroundQueue::RemovePlayer(ObjectGuid guid, bool decreaseInvitedCount) // first send removal information if (Player* plr2 = ObjectAccessor::FindConnectedPlayer(group->Players.begin()->first)) { - BattlegroundQueueTypeId bgQueueTypeId = BattlegroundMgr::BGQueueTypeId(group->BgTypeId, group->ArenaType); - uint32 queueSlot = plr2->GetBattlegroundQueueIndex(bgQueueTypeId); + uint32 queueSlot = plr2->GetBattlegroundQueueIndex(m_queueId); - plr2->RemoveBattlegroundQueueId(bgQueueTypeId); // must be called this way, because if you move this call to + plr2->RemoveBattlegroundQueueId(m_queueId); // must be called this way, because if you move this call to // queue->removeplayer, it causes bugs WorldPackets::Battleground::BattlefieldStatusNone battlefieldStatus; - sBattlegroundMgr->BuildBattlegroundStatusNone(&battlefieldStatus, plr2, queueSlot, plr2->GetBattlegroundQueueJoinTime(bgQueueTypeId)); + sBattlegroundMgr->BuildBattlegroundStatusNone(&battlefieldStatus, plr2, queueSlot, plr2->GetBattlegroundQueueJoinTime(m_queueId)); plr2->SendDirectMessage(battlefieldStatus.Write()); } // then actually delete, this may delete the group as well! @@ -441,7 +440,7 @@ bool BattlegroundQueue::InviteGroupToBG(GroupQueueInfo* ginfo, Battleground* bg, // set invitation ginfo->IsInvitedToBGInstanceGUID = bg->GetInstanceID(); BattlegroundTypeId bgTypeId = bg->GetTypeID(); - BattlegroundQueueTypeId bgQueueTypeId = BattlegroundMgr::BGQueueTypeId(bgTypeId, bg->GetArenaType()); + BattlegroundQueueTypeId bgQueueTypeId = bg->GetQueueId(); BattlegroundBracketId bracket_id = bg->GetBracketId(); // set ArenaTeamId for rated matches @@ -472,7 +471,7 @@ bool BattlegroundQueue::InviteGroupToBG(GroupQueueInfo* ginfo, Battleground* bg, BGQueueInviteEvent* inviteEvent = new BGQueueInviteEvent(player->GetGUID(), ginfo->IsInvitedToBGInstanceGUID, bgTypeId, ginfo->ArenaType, ginfo->RemoveInviteTime); m_events.AddEvent(inviteEvent, m_events.CalculateTime(INVITATION_REMIND_TIME)); // create automatic remove events - BGQueueRemoveEvent* removeEvent = new BGQueueRemoveEvent(player->GetGUID(), ginfo->IsInvitedToBGInstanceGUID, bgTypeId, bgQueueTypeId, ginfo->RemoveInviteTime); + BGQueueRemoveEvent* removeEvent = new BGQueueRemoveEvent(player->GetGUID(), ginfo->IsInvitedToBGInstanceGUID, bgQueueTypeId, ginfo->RemoveInviteTime); m_events.AddEvent(removeEvent, m_events.CalculateTime(INVITE_ACCEPT_WAIT_TIME)); uint32 queueSlot = player->GetBattlegroundQueueIndex(bgQueueTypeId); @@ -769,7 +768,7 @@ this method is called when group is inserted, or player / group is removed from it must be called after fully adding the members of a group to ensure group joining should be called from Battleground::RemovePlayer function in some cases */ -void BattlegroundQueue::BattlegroundQueueUpdate(uint32 /*diff*/, BattlegroundTypeId bgTypeId, BattlegroundBracketId bracket_id, uint8 arenaType, bool isRated, uint32 arenaRating) +void BattlegroundQueue::BattlegroundQueueUpdate(uint32 /*diff*/, BattlegroundBracketId bracket_id, uint32 arenaRating) { //if no players in queue - do nothing if (m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_ALLIANCE].empty() && @@ -780,12 +779,12 @@ void BattlegroundQueue::BattlegroundQueueUpdate(uint32 /*diff*/, BattlegroundTyp // battleground with free slot for player should be always in the beggining of the queue // maybe it would be better to create bgfreeslotqueue for each bracket_id - BGFreeSlotQueueContainer& bgQueues = sBattlegroundMgr->GetBGFreeSlotQueueStore(bgTypeId); + BGFreeSlotQueueContainer& bgQueues = sBattlegroundMgr->GetBGFreeSlotQueueStore(m_queueId); for (BGFreeSlotQueueContainer::iterator itr = bgQueues.begin(); itr != bgQueues.end();) { Battleground* bg = *itr; ++itr; // DO NOT allow queue manager to invite new player to rated games - if (!bg->isRated() && bg->GetTypeID() == bgTypeId && bg->GetBracketId() == bracket_id && + if (!bg->isRated() && bg->GetBracketId() == bracket_id && bg->GetStatus() > STATUS_WAIT_QUEUE && bg->GetStatus() < STATUS_WAIT_LEAVE) { // clear selection pools @@ -809,10 +808,10 @@ void BattlegroundQueue::BattlegroundQueueUpdate(uint32 /*diff*/, BattlegroundTyp // finished iterating through the bgs with free slots, maybe we need to create a new bg - Battleground* bg_template = sBattlegroundMgr->GetBattlegroundTemplate(bgTypeId); + Battleground* bg_template = sBattlegroundMgr->GetBattlegroundTemplate(BattlegroundTypeId(m_queueId.BattlemasterListId)); if (!bg_template) { - TC_LOG_ERROR("bg.battleground", "Battleground: Update: bg template not found for %u", bgTypeId); + TC_LOG_ERROR("bg.battleground", "Battleground: Update: bg template not found for %hu", m_queueId.BattlemasterListId); return; } @@ -829,8 +828,8 @@ void BattlegroundQueue::BattlegroundQueueUpdate(uint32 /*diff*/, BattlegroundTyp if (bg_template->isArena()) { - MaxPlayersPerTeam = arenaType; - MinPlayersPerTeam = sBattlegroundMgr->isArenaTesting() ? 1 : arenaType; + MaxPlayersPerTeam = m_queueId.TeamSize; + MinPlayersPerTeam = sBattlegroundMgr->isArenaTesting() ? 1 : m_queueId.TeamSize; } else if (sBattlegroundMgr->isTesting()) MinPlayersPerTeam = 1; @@ -843,10 +842,10 @@ void BattlegroundQueue::BattlegroundQueueUpdate(uint32 /*diff*/, BattlegroundTyp if (CheckPremadeMatch(bracket_id, MinPlayersPerTeam, MaxPlayersPerTeam)) { // create new battleground - Battleground* bg2 = sBattlegroundMgr->CreateNewBattleground(bgTypeId, bracketEntry, 0, false); + Battleground* bg2 = sBattlegroundMgr->CreateNewBattleground(m_queueId, bracketEntry); if (!bg2) { - TC_LOG_ERROR("bg.battleground", "BattlegroundQueue::Update - Cannot create battleground: %u", bgTypeId); + TC_LOG_ERROR("bg.battleground", "BattlegroundQueue::Update - Cannot create battleground: %u", m_queueId.BattlemasterListId); return; } // invite those selection pools @@ -862,17 +861,17 @@ void BattlegroundQueue::BattlegroundQueueUpdate(uint32 /*diff*/, BattlegroundTyp } // now check if there are in queues enough players to start new game of (normal battleground, or non-rated arena) - if (!isRated) + if (!m_queueId.Rated) { // if there are enough players in pools, start new battleground or non rated arena if (CheckNormalMatch(bg_template, bracket_id, MinPlayersPerTeam, MaxPlayersPerTeam) || (bg_template->isArena() && CheckSkirmishForSameFaction(bracket_id, MinPlayersPerTeam))) { // we successfully created a pool - Battleground* bg2 = sBattlegroundMgr->CreateNewBattleground(bgTypeId, bracketEntry, arenaType, false); + Battleground* bg2 = sBattlegroundMgr->CreateNewBattleground(m_queueId, bracketEntry); if (!bg2) { - TC_LOG_ERROR("bg.battleground", "BattlegroundQueue::Update - Cannot create battleground: %u", bgTypeId); + TC_LOG_ERROR("bg.battleground", "BattlegroundQueue::Update - Cannot create battleground: %hu", m_queueId.BattlemasterListId); return; } @@ -968,7 +967,7 @@ void BattlegroundQueue::BattlegroundQueueUpdate(uint32 /*diff*/, BattlegroundTyp { GroupQueueInfo* aTeam = *itr_teams[TEAM_ALLIANCE]; GroupQueueInfo* hTeam = *itr_teams[TEAM_HORDE]; - Battleground* arena = sBattlegroundMgr->CreateNewBattleground(bgTypeId, bracketEntry, arenaType, true); + Battleground* arena = sBattlegroundMgr->CreateNewBattleground(m_queueId, bracketEntry); if (!arena) { TC_LOG_ERROR("bg.battleground", "BattlegroundQueue::Update couldn't create arena instance for rated arena match!"); @@ -1021,7 +1020,7 @@ bool BGQueueInviteEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/) if (!bg) return true; - BattlegroundQueueTypeId bgQueueTypeId = BattlegroundMgr::BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType()); + BattlegroundQueueTypeId bgQueueTypeId = bg->GetQueueId(); uint32 queueSlot = player->GetBattlegroundQueueIndex(bgQueueTypeId); if (queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES) // player is in queue or in battleground { @@ -1058,7 +1057,7 @@ bool BGQueueRemoveEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/) // player logged off (we should do nothing, he is correctly removed from queue in another procedure) return true; - Battleground* bg = sBattlegroundMgr->GetBattleground(m_BgInstanceGUID, m_BgTypeId); + Battleground* bg = sBattlegroundMgr->GetBattleground(m_BgInstanceGUID, BattlegroundTypeId(m_BgQueueTypeId.BattlemasterListId)); //battleground can be deleted already when we are removing queue info //bg pointer can be NULL! so use it carefully! @@ -1075,7 +1074,7 @@ bool BGQueueRemoveEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/) bgQueue.RemovePlayer(m_PlayerGuid, true); //update queues if battleground isn't ended if (bg && bg->isBattleground() && bg->GetStatus() != STATUS_WAIT_LEAVE) - sBattlegroundMgr->ScheduleQueueUpdate(0, 0, m_BgQueueTypeId, m_BgTypeId, bg->GetBracketId()); + sBattlegroundMgr->ScheduleQueueUpdate(0, m_BgQueueTypeId, bg->GetBracketId()); WorldPackets::Battleground::BattlefieldStatusNone battlefieldStatus; sBattlegroundMgr->BuildBattlegroundStatusNone(&battlefieldStatus, player, queueSlot, player->GetBattlegroundQueueJoinTime(m_BgQueueTypeId)); diff --git a/src/server/game/Battlegrounds/BattlegroundQueue.h b/src/server/game/Battlegrounds/BattlegroundQueue.h index 14ac03402b7..e6dba599f12 100644 --- a/src/server/game/Battlegrounds/BattlegroundQueue.h +++ b/src/server/game/Battlegrounds/BattlegroundQueue.h @@ -74,10 +74,10 @@ class Battleground; class TC_GAME_API BattlegroundQueue { public: - BattlegroundQueue(); + BattlegroundQueue(BattlegroundQueueTypeId queueId); ~BattlegroundQueue(); - void BattlegroundQueueUpdate(uint32 diff, BattlegroundTypeId bgTypeId, BattlegroundBracketId bracket_id, uint8 arenaType = 0, bool isRated = false, uint32 minRating = 0); + void BattlegroundQueueUpdate(uint32 diff, BattlegroundBracketId bracket_id, uint32 minRating = 0); void UpdateEvents(uint32 diff); void FillPlayersToBG(Battleground* bg, BattlegroundBracketId bracket_id); @@ -128,6 +128,8 @@ class TC_GAME_API BattlegroundQueue uint32 GetPlayersInQueue(TeamId id); private: + BattlegroundQueueTypeId m_queueId; + bool InviteGroupToBG(GroupQueueInfo* ginfo, Battleground* bg, uint32 side); uint32 m_WaitTimes[BG_TEAMS_COUNT][MAX_BATTLEGROUND_BRACKETS][COUNT_OF_PLAYERS_TO_AVERAGE_WAIT_TIME]; uint32 m_WaitTimeLastPlayer[BG_TEAMS_COUNT][MAX_BATTLEGROUND_BRACKETS]; @@ -167,8 +169,8 @@ class TC_GAME_API BGQueueInviteEvent : public BasicEvent class TC_GAME_API BGQueueRemoveEvent : public BasicEvent { public: - BGQueueRemoveEvent(ObjectGuid pl_guid, uint32 bgInstanceGUID, BattlegroundTypeId BgTypeId, BattlegroundQueueTypeId bgQueueTypeId, uint32 removeTime) - : m_PlayerGuid(pl_guid), m_BgInstanceGUID(bgInstanceGUID), m_RemoveTime(removeTime), m_BgTypeId(BgTypeId), m_BgQueueTypeId(bgQueueTypeId) + BGQueueRemoveEvent(ObjectGuid pl_guid, uint32 bgInstanceGUID, BattlegroundQueueTypeId bgQueueTypeId, uint32 removeTime) + : m_PlayerGuid(pl_guid), m_BgInstanceGUID(bgInstanceGUID), m_RemoveTime(removeTime), m_BgQueueTypeId(bgQueueTypeId) { } virtual ~BGQueueRemoveEvent() { } @@ -179,7 +181,6 @@ class TC_GAME_API BGQueueRemoveEvent : public BasicEvent ObjectGuid m_PlayerGuid; uint32 m_BgInstanceGUID; uint32 m_RemoveTime; - BattlegroundTypeId m_BgTypeId; BattlegroundQueueTypeId m_BgQueueTypeId; }; diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp index 476daf5db21..c83e1ff48b1 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp @@ -65,6 +65,7 @@ BattlegroundEY::BattlegroundEY(BattlegroundTemplate const* battlegroundTemplate) m_PointOwnedByTeam[i] = EY_POINT_NO_OWNER; m_PointState[i] = EY_POINT_STATE_UNCONTROLLED; m_PointBarStatus[i] = BG_EY_PROGRESS_BAR_STATE_MIDDLE; + m_LastPointCaptureStatus[i] = BattlegroundPointCaptureStatus::Neutral; } for (uint8 i = 0; i < 2 * EY_POINTS_MAX; ++i) @@ -170,6 +171,22 @@ void BattlegroundEY::AddPoints(uint32 Team, uint32 Points) UpdateTeamScore(team_index); } +BattlegroundPointCaptureStatus BattlegroundEY::GetPointCaptureStatus(uint32 point) const +{ + if (m_PointBarStatus[point] >= BG_EY_PROGRESS_BAR_ALI_CONTROLLED) + return BattlegroundPointCaptureStatus::AllianceControlled; + + if (m_PointBarStatus[point] <= BG_EY_PROGRESS_BAR_HORDE_CONTROLLED) + return BattlegroundPointCaptureStatus::HordeControlled; + + if (m_CurrentPointPlayersCount[2 * point] == m_CurrentPointPlayersCount[2 * point + 1]) + return BattlegroundPointCaptureStatus::Neutral; + + return m_CurrentPointPlayersCount[2 * point] > m_CurrentPointPlayersCount[2 * point + 1] + ? BattlegroundPointCaptureStatus::AllianceCapturing + : BattlegroundPointCaptureStatus::HordeCapturing; +} + void BattlegroundEY::CheckSomeoneJoinedPoint() { GameObject* obj = NULL; @@ -252,52 +269,63 @@ void BattlegroundEY::UpdatePointStatuses() { for (uint8 point = 0; point < EY_POINTS_MAX; ++point) { - if (m_PlayersNearPoint[point].empty()) - continue; - //count new point bar status: - m_PointBarStatus[point] += (m_CurrentPointPlayersCount[2 * point] - m_CurrentPointPlayersCount[2 * point + 1] < BG_EY_POINT_MAX_CAPTURERS_COUNT) ? m_CurrentPointPlayersCount[2 * point] - m_CurrentPointPlayersCount[2 * point + 1] : BG_EY_POINT_MAX_CAPTURERS_COUNT; - - if (m_PointBarStatus[point] > BG_EY_PROGRESS_BAR_ALI_CONTROLLED) - //point is fully alliance's - m_PointBarStatus[point] = BG_EY_PROGRESS_BAR_ALI_CONTROLLED; - if (m_PointBarStatus[point] < BG_EY_PROGRESS_BAR_HORDE_CONTROLLED) - //point is fully horde's - m_PointBarStatus[point] = BG_EY_PROGRESS_BAR_HORDE_CONTROLLED; - - uint32 pointOwnerTeamId = 0; - //find which team should own this point - if (m_PointBarStatus[point] <= BG_EY_PROGRESS_BAR_NEUTRAL_LOW) - pointOwnerTeamId = HORDE; - else if (m_PointBarStatus[point] >= BG_EY_PROGRESS_BAR_NEUTRAL_HIGH) - pointOwnerTeamId = ALLIANCE; - else - pointOwnerTeamId = EY_POINT_NO_OWNER; - - for (uint8 i = 0; i < m_PlayersNearPoint[point].size(); ++i) + if (!m_PlayersNearPoint[point].empty()) { - Player* player = ObjectAccessor::FindPlayer(m_PlayersNearPoint[point][i]); - if (player) + //count new point bar status: + int32 pointDelta = int32(m_CurrentPointPlayersCount[2 * point]) - int32(m_CurrentPointPlayersCount[2 * point + 1]); + RoundToInterval<int32>(pointDelta, -BG_EY_POINT_MAX_CAPTURERS_COUNT, BG_EY_POINT_MAX_CAPTURERS_COUNT); + m_PointBarStatus[point] += pointDelta; + + if (m_PointBarStatus[point] > BG_EY_PROGRESS_BAR_ALI_CONTROLLED) + //point is fully alliance's + m_PointBarStatus[point] = BG_EY_PROGRESS_BAR_ALI_CONTROLLED; + if (m_PointBarStatus[point] < BG_EY_PROGRESS_BAR_HORDE_CONTROLLED) + //point is fully horde's + m_PointBarStatus[point] = BG_EY_PROGRESS_BAR_HORDE_CONTROLLED; + + uint32 pointOwnerTeamId = 0; + //find which team should own this point + if (m_PointBarStatus[point] <= BG_EY_PROGRESS_BAR_NEUTRAL_LOW) + pointOwnerTeamId = HORDE; + else if (m_PointBarStatus[point] >= BG_EY_PROGRESS_BAR_NEUTRAL_HIGH) + pointOwnerTeamId = ALLIANCE; + else + pointOwnerTeamId = EY_POINT_NO_OWNER; + + for (uint8 i = 0; i < m_PlayersNearPoint[point].size(); ++i) { - player->SendUpdateWorldState(PROGRESS_BAR_STATUS, m_PointBarStatus[point]); - //if point owner changed we must evoke event! - if (pointOwnerTeamId != m_PointOwnedByTeam[point]) + Player* player = ObjectAccessor::FindPlayer(m_PlayersNearPoint[point][i]); + if (player) { - //point was uncontrolled and player is from team which captured point - if (m_PointState[point] == EY_POINT_STATE_UNCONTROLLED && player->GetTeam() == pointOwnerTeamId) - this->EventTeamCapturedPoint(player, point); - - //point was under control and player isn't from team which controlled it - if (m_PointState[point] == EY_POINT_UNDER_CONTROL && player->GetTeam() != m_PointOwnedByTeam[point]) - this->EventTeamLostPoint(player, point); + player->SendUpdateWorldState(PROGRESS_BAR_STATUS, m_PointBarStatus[point]); + //if point owner changed we must evoke event! + if (pointOwnerTeamId != m_PointOwnedByTeam[point]) + { + //point was uncontrolled and player is from team which captured point + if (m_PointState[point] == EY_POINT_STATE_UNCONTROLLED && player->GetTeam() == pointOwnerTeamId) + this->EventTeamCapturedPoint(player, point); + + //point was under control and player isn't from team which controlled it + if (m_PointState[point] == EY_POINT_UNDER_CONTROL && player->GetTeam() != m_PointOwnedByTeam[point]) + this->EventTeamLostPoint(player, point); + } + + /// @workaround The original AreaTrigger is covered by a bigger one and not triggered on client side. + if (point == FEL_REAVER && m_PointOwnedByTeam[point] == player->GetTeam()) + if (m_FlagState && GetFlagPickerGUID() == player->GetGUID()) + if (player->GetDistance(2044.0f, 1729.729f, 1190.03f) < 3.0f) + EventPlayerCapturedFlag(player, BG_EY_OBJECT_FLAG_FEL_REAVER); } - - /// @workaround The original AreaTrigger is covered by a bigger one and not triggered on client side. - if (point == FEL_REAVER && m_PointOwnedByTeam[point] == player->GetTeam()) - if (m_FlagState && GetFlagPickerGUID() == player->GetGUID()) - if (player->GetDistance(2044.0f, 1729.729f, 1190.03f) < 3.0f) - EventPlayerCapturedFlag(player, BG_EY_OBJECT_FLAG_FEL_REAVER); } } + + BattlegroundPointCaptureStatus captureStatus = GetPointCaptureStatus(point); + if (m_LastPointCaptureStatus[point] != captureStatus) + { + UpdateWorldState(m_PointsIconStruct[point].WorldStateAllianceStatusBarIcon, captureStatus == BattlegroundPointCaptureStatus::AllianceControlled ? 2 : (captureStatus == BattlegroundPointCaptureStatus::AllianceCapturing ? 1 : 0)); + UpdateWorldState(m_PointsIconStruct[point].WorldStateHordeStatusBarIcon, captureStatus == BattlegroundPointCaptureStatus::HordeControlled ? 2 : (captureStatus == BattlegroundPointCaptureStatus::HordeCapturing ? 1 : 0)); + m_LastPointCaptureStatus[point] = captureStatus; + } } } @@ -818,6 +846,9 @@ void BattlegroundEY::EventPlayerCapturedFlag(Player* player, uint32 BgObjectType if (m_TeamPointsCount[team_id] > 0) AddPoints(player->GetTeam(), BG_EY_FlagPoints[m_TeamPointsCount[team_id] - 1]); + UpdateWorldState(NETHERSTORM_FLAG_STATE_HORDE, BG_EY_FLAG_STATE_ON_BASE); + UpdateWorldState(NETHERSTORM_FLAG_STATE_ALLIANCE, BG_EY_FLAG_STATE_ON_BASE); + UpdatePlayerScore(player, SCORE_FLAG_CAPTURES, 1); } @@ -867,14 +898,22 @@ void BattlegroundEY::FillInitialWorldStates(WorldPackets::WorldState::InitWorldS packet.Worldstates.emplace_back(0xAD2, 0x1); packet.Worldstates.emplace_back(0xAD1, 0x1); - packet.Worldstates.emplace_back(0xABE, int32(GetTeamScore(TEAM_HORDE))); - packet.Worldstates.emplace_back(0xABD, int32(GetTeamScore(TEAM_ALLIANCE))); + packet.Worldstates.emplace_back(int32(EY_HORDE_RESOURCES), int32(GetTeamScore(TEAM_HORDE))); + packet.Worldstates.emplace_back(int32(EY_ALLIANCE_RESOURCES), int32(GetTeamScore(TEAM_ALLIANCE))); + packet.Worldstates.emplace_back(int32(EY_MAX_RESOURCES), int32(BG_EY_MAX_TEAM_SCORE)); packet.Worldstates.emplace_back(0xA05, 0x8E); packet.Worldstates.emplace_back(0xAA0, 0x0); packet.Worldstates.emplace_back(0xA9F, 0x0); packet.Worldstates.emplace_back(0xA9E, 0x0); packet.Worldstates.emplace_back(0xC0D, 0x17B); + + for (uint8 point = 0; point < EY_POINTS_MAX; ++point) + { + BattlegroundPointCaptureStatus captureStatus = GetPointCaptureStatus(point); + packet.Worldstates.emplace_back(m_PointsIconStruct[point].WorldStateAllianceStatusBarIcon, captureStatus == BattlegroundPointCaptureStatus::AllianceControlled ? 2 : (captureStatus == BattlegroundPointCaptureStatus::AllianceCapturing ? 1 : 0)); + packet.Worldstates.emplace_back(m_PointsIconStruct[point].WorldStateHordeStatusBarIcon, captureStatus == BattlegroundPointCaptureStatus::HordeControlled ? 2 : (captureStatus == BattlegroundPointCaptureStatus::HordeCapturing ? 1 : 0)); + } } WorldSafeLocsEntry const* BattlegroundEY::GetClosestGraveYard(Player* player) diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundEY.h b/src/server/game/Battlegrounds/Zones/BattlegroundEY.h index e1028d491dd..37e3aed3837 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundEY.h +++ b/src/server/game/Battlegrounds/Zones/BattlegroundEY.h @@ -31,8 +31,9 @@ enum BG_EY_Misc enum BG_EY_WorldStates { - EY_ALLIANCE_RESOURCES = 2749, - EY_HORDE_RESOURCES = 2750, + EY_ALLIANCE_RESOURCES = 1776, + EY_HORDE_RESOURCES = 1777, + EY_MAX_RESOURCES = 1780, EY_ALLIANCE_BASE = 2752, EY_HORDE_BASE = 2753, DRAENEI_RUINS_HORDE_CONTROL = 2733, @@ -52,8 +53,17 @@ enum BG_EY_WorldStates PROGRESS_BAR_SHOW = 2718, //1 init, 0 druhy send - bez messagu, 1 = controlled aliance NETHERSTORM_FLAG = 2757, //set to 2 when flag is picked up, and to 1 if it is dropped - NETHERSTORM_FLAG_STATE_ALLIANCE = 2769, - NETHERSTORM_FLAG_STATE_HORDE = 2770 + NETHERSTORM_FLAG_STATE_ALLIANCE = 9808, + NETHERSTORM_FLAG_STATE_HORDE = 9809, + + DRAENEI_RUINS_HORDE_CONTROL_STATE = 17362, + DRAENEI_RUINS_ALLIANCE_CONTROL_STATE = 17366, + MAGE_TOWER_HORDE_CONTROL_STATE = 17361, + MAGE_TOWER_ALLIANCE_CONTROL_STATE = 17368, + FEL_REAVER_HORDE_CONTROL_STATE = 17364, + FEL_REAVER_ALLIANCE_CONTROL_STATE = 17367, + BLOOD_ELF_HORDE_CONTROL_STATE = 17363, + BLOOD_ELF_ALLIANCE_CONTROL_STATE = 17365, }; enum BG_EY_ProgressBarConsts @@ -118,7 +128,7 @@ enum EYBattlegroundGaveyards { EY_GRAVEYARD_MAIN_ALLIANCE = 1103, EY_GRAVEYARD_MAIN_HORDE = 1104, - EY_GRAVEYARD_FEL_REAVER = 1105, + EY_GRAVEYARD_FEL_REAVER = 1105, EY_GRAVEYARD_BLOOD_ELF = 1106, EY_GRAVEYARD_DRAENEI_RUINS = 1107, EY_GRAVEYARD_MAGE_TOWER = 1108 @@ -137,19 +147,19 @@ enum EYBattlegroundPoints enum EYBattlegroundCreaturesTypes { - EY_SPIRIT_FEL_REAVER = 0, + EY_SPIRIT_FEL_REAVER = 0, EY_SPIRIT_BLOOD_ELF = 1, EY_SPIRIT_DRAENEI_RUINS = 2, EY_SPIRIT_MAGE_TOWER = 3, EY_SPIRIT_MAIN_ALLIANCE = 4, EY_SPIRIT_MAIN_HORDE = 5, - EY_TRIGGER_FEL_REAVER = 6, + EY_TRIGGER_FEL_REAVER = 6, EY_TRIGGER_BLOOD_ELF = 7, EY_TRIGGER_DRAENEI_RUINS = 8, EY_TRIGGER_MAGE_TOWER = 9, - BG_EY_CREATURES_MAX = 10 + BG_EY_CREATURES_MAX = 10 }; enum EYBattlegroundObjectTypes @@ -283,11 +293,15 @@ enum BG_EY_BroadcastTexts struct BattlegroundEYPointIconsStruct { - BattlegroundEYPointIconsStruct(uint32 _WorldStateControlIndex, uint32 _WorldStateAllianceControlledIndex, uint32 _WorldStateHordeControlledIndex) - : WorldStateControlIndex(_WorldStateControlIndex), WorldStateAllianceControlledIndex(_WorldStateAllianceControlledIndex), WorldStateHordeControlledIndex(_WorldStateHordeControlledIndex) { } + BattlegroundEYPointIconsStruct(uint32 _WorldStateControlIndex, uint32 _WorldStateAllianceControlledIndex, uint32 _WorldStateHordeControlledIndex, + uint32 worldStateAllianceStatusBarIcon, uint32 worldStateHordeStatusBarIcon) + : WorldStateControlIndex(_WorldStateControlIndex), WorldStateAllianceControlledIndex(_WorldStateAllianceControlledIndex), WorldStateHordeControlledIndex(_WorldStateHordeControlledIndex), + WorldStateAllianceStatusBarIcon(worldStateAllianceStatusBarIcon), WorldStateHordeStatusBarIcon(worldStateHordeStatusBarIcon) { } uint32 WorldStateControlIndex; uint32 WorldStateAllianceControlledIndex; uint32 WorldStateHordeControlledIndex; + uint32 WorldStateAllianceStatusBarIcon; + uint32 WorldStateHordeStatusBarIcon; }; Position const BG_EY_TriggerPositions[EY_POINTS_MAX] = @@ -336,10 +350,10 @@ const uint32 BG_EY_FlagPoints[EY_POINTS_MAX] = {75, 85, 100, 500}; //constant arrays: const BattlegroundEYPointIconsStruct m_PointsIconStruct[EY_POINTS_MAX] = { - BattlegroundEYPointIconsStruct(FEL_REAVER_UNCONTROL, FEL_REAVER_ALLIANCE_CONTROL, FEL_REAVER_HORDE_CONTROL), - BattlegroundEYPointIconsStruct(BLOOD_ELF_UNCONTROL, BLOOD_ELF_ALLIANCE_CONTROL, BLOOD_ELF_HORDE_CONTROL), - BattlegroundEYPointIconsStruct(DRAENEI_RUINS_UNCONTROL, DRAENEI_RUINS_ALLIANCE_CONTROL, DRAENEI_RUINS_HORDE_CONTROL), - BattlegroundEYPointIconsStruct(MAGE_TOWER_UNCONTROL, MAGE_TOWER_ALLIANCE_CONTROL, MAGE_TOWER_HORDE_CONTROL) + BattlegroundEYPointIconsStruct(FEL_REAVER_UNCONTROL, FEL_REAVER_ALLIANCE_CONTROL, FEL_REAVER_HORDE_CONTROL, FEL_REAVER_ALLIANCE_CONTROL_STATE, FEL_REAVER_HORDE_CONTROL_STATE), + BattlegroundEYPointIconsStruct(BLOOD_ELF_UNCONTROL, BLOOD_ELF_ALLIANCE_CONTROL, BLOOD_ELF_HORDE_CONTROL, BLOOD_ELF_ALLIANCE_CONTROL_STATE, BLOOD_ELF_HORDE_CONTROL_STATE), + BattlegroundEYPointIconsStruct(DRAENEI_RUINS_UNCONTROL, DRAENEI_RUINS_ALLIANCE_CONTROL, DRAENEI_RUINS_HORDE_CONTROL, DRAENEI_RUINS_ALLIANCE_CONTROL_STATE, DRAENEI_RUINS_HORDE_CONTROL_STATE), + BattlegroundEYPointIconsStruct(MAGE_TOWER_UNCONTROL, MAGE_TOWER_ALLIANCE_CONTROL, MAGE_TOWER_HORDE_CONTROL, MAGE_TOWER_ALLIANCE_CONTROL_STATE, MAGE_TOWER_HORDE_CONTROL_STATE) }; const BattlegroundEYLosingPointStruct m_LosingPointTypes[EY_POINTS_MAX] = { @@ -450,6 +464,7 @@ protected: void RemovePoint(uint32 TeamID, uint32 Points = 1) { m_TeamScores[GetTeamIndexByTeamId(TeamID)] -= Points; } void SetTeamPoint(uint32 TeamID, uint32 Points = 0) { m_TeamScores[GetTeamIndexByTeamId(TeamID)] = Points; } + BattlegroundPointCaptureStatus GetPointCaptureStatus(uint32 point) const; uint32 m_HonorScoreTics[2]; uint32 m_TeamPointsCount[2]; @@ -466,6 +481,7 @@ protected: uint32 m_PointOwnedByTeam[EY_POINTS_MAX]; uint8 m_PointState[EY_POINTS_MAX]; int32 m_PointBarStatus[EY_POINTS_MAX]; + BattlegroundPointCaptureStatus m_LastPointCaptureStatus[EY_POINTS_MAX]; GuidVector m_PlayersNearPoint[EY_POINTS_MAX + 1]; uint8 m_CurrentPointPlayersCount[2*EY_POINTS_MAX]; diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index dbe5e69ed8a..40c19caf8f6 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -18164,7 +18164,7 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder* holder) { map = currentBg->GetBgMap(); - BattlegroundQueueTypeId bgQueueTypeId = sBattlegroundMgr->BGQueueTypeId(currentBg->GetTypeID(), currentBg->GetArenaType()); + BattlegroundQueueTypeId bgQueueTypeId = currentBg->GetQueueId(); AddBattlegroundQueueId(bgQueueTypeId); m_bgData.bgTypeID = currentBg->GetTypeID(); @@ -24791,7 +24791,7 @@ uint32 Player::AddBattlegroundQueueId(BattlegroundQueueTypeId val) { m_bgBattlegroundQueueID[i].bgQueueTypeId = val; m_bgBattlegroundQueueID[i].invitedToInstance = 0; - m_bgBattlegroundQueueID[i].joinTime = getMSTime(); + m_bgBattlegroundQueueID[i].joinTime = GameTime::GetGameTime(); return i; } } diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp index caef3b52b27..0ce01460161 100644 --- a/src/server/game/Groups/Group.cpp +++ b/src/server/game/Groups/Group.cpp @@ -1826,8 +1826,6 @@ GroupJoinBattlegroundResult Group::CanJoinBattlegroundQueue(Battleground const* uint32 arenaTeamId = reference->GetArenaTeamId(arenaSlot); uint32 team = reference->GetTeam(); - BattlegroundQueueTypeId bgQueueTypeIdRandom = BattlegroundMgr::BGQueueTypeId(BATTLEGROUND_RB, 0); - // check every member of the group to be able to join memberscount = 0; for (GroupReference* itr = GetFirstMember(); itr != NULL; itr = itr->next(), ++memberscount) @@ -1853,10 +1851,12 @@ GroupJoinBattlegroundResult Group::CanJoinBattlegroundQueue(Battleground const* if (member->InBattlegroundQueueForBattlegroundQueueType(bgQueueTypeId)) return ERR_BATTLEGROUND_JOIN_FAILED; // not blizz-like // don't let join if someone from the group is in bg queue random - if (member->InBattlegroundQueueForBattlegroundQueueType(bgQueueTypeIdRandom)) + bool isInRandomBgQueue = member->InBattlegroundQueueForBattlegroundQueueType(BattlegroundMgr::BGQueueTypeId(BATTLEGROUND_RB, BattlegroundQueueIdType::Battleground, false, 0)) + || member->InBattlegroundQueueForBattlegroundQueueType(BattlegroundMgr::BGQueueTypeId(BATTLEGROUND_RANDOM_EPIC, BattlegroundQueueIdType::Battleground, false, 0)); + if (isInRandomBgQueue) return ERR_IN_RANDOM_BG; // don't let join to bg queue random if someone from the group is already in bg queue - if (bgOrTemplate->GetTypeID() == BATTLEGROUND_RB && member->InBattlegroundQueue()) + if ((bgOrTemplate->GetTypeID() == BATTLEGROUND_RB || bgOrTemplate->GetTypeID() == BATTLEGROUND_RANDOM_EPIC) && member->InBattlegroundQueue() && !isInRandomBgQueue) return ERR_IN_NON_RANDOM_BG; // check for deserter debuff in case not arena queue if (bgOrTemplate->GetTypeID() != BATTLEGROUND_AA && !member->CanJoinToBattleground(bgOrTemplate)) diff --git a/src/server/game/Handlers/BattleGroundHandler.cpp b/src/server/game/Handlers/BattleGroundHandler.cpp index d8b5500a66a..7924cf01a18 100644 --- a/src/server/game/Handlers/BattleGroundHandler.cpp +++ b/src/server/game/Handlers/BattleGroundHandler.cpp @@ -69,25 +69,24 @@ void WorldSession::HandleBattlemasterJoinOpcode(WorldPackets::Battleground::Batt return; } - uint32 bgTypeId_ = battlemasterJoin.QueueIDs[0] & 0xFFFF; - BattlemasterListEntry const* battlemasterListEntry = sBattlemasterListStore.LookupEntry(bgTypeId_); - if (!battlemasterListEntry) + BattlegroundQueueTypeId bgQueueTypeId = BattlegroundQueueTypeId::FromPacked(battlemasterJoin.QueueIDs[0]); + if (!BattlegroundMgr::IsValidQueueId(bgQueueTypeId)) { - TC_LOG_ERROR("network", "Battleground: invalid bgtype (%u) received. possible cheater? %s", bgTypeId_, _player->GetGUID().ToString().c_str()); + TC_LOG_ERROR("network", "Battleground: invalid bg queue { BattlemasterListId: %hu, Type: %u, Rated: %s, TeamSize: %u } received. possible cheater? %s", + bgQueueTypeId.BattlemasterListId, uint32(bgQueueTypeId.Type), bgQueueTypeId.Rated ? "true" : "false", uint32(bgQueueTypeId.TeamSize), + _player->GetGUID().ToString().c_str()); return; } - if (DisableMgr::IsDisabledFor(DISABLE_TYPE_BATTLEGROUND, bgTypeId_, NULL) || (battlemasterListEntry->Flags & BATTLEMASTER_LIST_FLAG_DISABLED) != 0) + BattlemasterListEntry const* battlemasterListEntry = sBattlemasterListStore.AssertEntry(bgQueueTypeId.BattlemasterListId); + + if (DisableMgr::IsDisabledFor(DISABLE_TYPE_BATTLEGROUND, bgQueueTypeId.BattlemasterListId, NULL) || (battlemasterListEntry->Flags & BATTLEMASTER_LIST_FLAG_DISABLED) != 0) { ChatHandler(this).PSendSysMessage(LANG_BG_DISABLED); return; } - BattlegroundTypeId bgTypeId = BattlegroundTypeId(bgTypeId_); - - // can do this, since it's battleground, not arena - BattlegroundQueueTypeId bgQueueTypeId = BattlegroundMgr::BGQueueTypeId(bgTypeId, 0); - BattlegroundQueueTypeId bgQueueTypeIdRandom = BattlegroundMgr::BGQueueTypeId(BATTLEGROUND_RB, 0); + BattlegroundTypeId bgTypeId = BattlegroundTypeId(bgQueueTypeId.BattlemasterListId); // ignore if player is already in BG if (_player->InBattleground()) @@ -127,7 +126,9 @@ void WorldSession::HandleBattlemasterJoinOpcode(WorldPackets::Battleground::Batt return; } - if (_player->GetBattlegroundQueueIndex(bgQueueTypeIdRandom) < PLAYER_MAX_BATTLEGROUND_QUEUES) + bool isInRandomBgQueue = _player->InBattlegroundQueueForBattlegroundQueueType(BattlegroundMgr::BGQueueTypeId(BATTLEGROUND_RB, BattlegroundQueueIdType::Battleground, false, 0)) + || _player->InBattlegroundQueueForBattlegroundQueueType(BattlegroundMgr::BGQueueTypeId(BATTLEGROUND_RANDOM_EPIC, BattlegroundQueueIdType::Battleground, false, 0)); + if (bgTypeId != BATTLEGROUND_RB && bgTypeId != BATTLEGROUND_RANDOM_EPIC && isInRandomBgQueue) { // player is already in random queue WorldPackets::Battleground::BattlefieldStatusFailed battlefieldStatus; @@ -136,7 +137,7 @@ void WorldSession::HandleBattlemasterJoinOpcode(WorldPackets::Battleground::Batt return; } - if (_player->InBattlegroundQueue() && bgTypeId == BATTLEGROUND_RB) + if (_player->InBattlegroundQueue() && !isInRandomBgQueue && (bgTypeId == BATTLEGROUND_RB || bgTypeId == BATTLEGROUND_RANDOM_EPIC)) { // player is already in queue, can't start random queue WorldPackets::Battleground::BattlefieldStatusFailed battlefieldStatus; @@ -170,11 +171,12 @@ void WorldSession::HandleBattlemasterJoinOpcode(WorldPackets::Battleground::Batt uint32 queueSlot = _player->AddBattlegroundQueueId(bgQueueTypeId); WorldPackets::Battleground::BattlefieldStatusQueued battlefieldStatus; - sBattlegroundMgr->BuildBattlegroundStatusQueued(&battlefieldStatus, bg, _player, queueSlot, ginfo->JoinTime, avgTime, ginfo->ArenaType, false); + sBattlegroundMgr->BuildBattlegroundStatusQueued(&battlefieldStatus, bg, _player, queueSlot, ginfo->JoinTime, bgQueueTypeId, avgTime, ginfo->ArenaType, false); SendPacket(battlefieldStatus.Write()); - TC_LOG_DEBUG("bg.battleground", "Battleground: player joined queue for bg queue type %u bg type %u, %s, NAME %s", - bgQueueTypeId, bgTypeId, _player->GetGUID().ToString().c_str(), _player->GetName().c_str()); + TC_LOG_DEBUG("bg.battleground", "Battleground: player joined queue for bg queue { BattlemasterListId: %hu, Type: %u, Rated: %s, TeamSize: %u }, %s, NAME %s", + bgQueueTypeId.BattlemasterListId, uint32(bgQueueTypeId.Type), bgQueueTypeId.Rated ? "true" : "false", uint32(bgQueueTypeId.TeamSize), + _player->GetGUID().ToString().c_str(), _player->GetName().c_str()); } else { @@ -214,15 +216,16 @@ void WorldSession::HandleBattlemasterJoinOpcode(WorldPackets::Battleground::Batt uint32 queueSlot = member->AddBattlegroundQueueId(bgQueueTypeId); WorldPackets::Battleground::BattlefieldStatusQueued battlefieldStatus; - sBattlegroundMgr->BuildBattlegroundStatusQueued(&battlefieldStatus, bg, member, queueSlot, ginfo->JoinTime, avgTime, ginfo->ArenaType, true); + sBattlegroundMgr->BuildBattlegroundStatusQueued(&battlefieldStatus, bg, member, queueSlot, ginfo->JoinTime, bgQueueTypeId, avgTime, ginfo->ArenaType, true); member->SendDirectMessage(battlefieldStatus.Write()); - TC_LOG_DEBUG("bg.battleground", "Battleground: player joined queue for bg queue type %u bg type %u, %s, NAME %s", - bgQueueTypeId, bgTypeId, member->GetGUID().ToString().c_str(), member->GetName().c_str()); + TC_LOG_DEBUG("bg.battleground", "Battleground: player joined queue for bg queue { BattlemasterListId: %hu, Type: %u, Rated: %s, TeamSize: %u }, %s, NAME %s", + bgQueueTypeId.BattlemasterListId, uint32(bgQueueTypeId.Type), bgQueueTypeId.Rated ? "true" : "false", uint32(bgQueueTypeId.TeamSize), + member->GetGUID().ToString().c_str(), member->GetName().c_str()); } TC_LOG_DEBUG("bg.battleground", "Battleground: group end"); } - sBattlegroundMgr->ScheduleQueueUpdate(0, 0, bgQueueTypeId, bgTypeId, bracketEntry->GetBracketId()); + sBattlegroundMgr->ScheduleQueueUpdate(0, bgQueueTypeId, bracketEntry->GetBracketId()); } void WorldSession::HandlePVPLogDataOpcode(WorldPackets::Battleground::PVPLogDataRequest& /*pvpLogDataRequest*/) @@ -235,8 +238,8 @@ void WorldSession::HandlePVPLogDataOpcode(WorldPackets::Battleground::PVPLogData if (bg->isArena()) return; - WorldPackets::Battleground::PVPLogData pvpLogData; - bg->BuildPvPLogDataPacket(pvpLogData); + WorldPackets::Battleground::PVPLogDataMessage pvpLogData; + bg->BuildPvPLogDataPacket(pvpLogData.Data); SendPacket(pvpLogData.Write()); } @@ -287,7 +290,7 @@ void WorldSession::HandleBattleFieldPortOpcode(WorldPackets::Battleground::Battl return; } - BattlegroundTypeId bgTypeId = BattlegroundMgr::BGTemplateId(bgQueueTypeId); + BattlegroundTypeId bgTypeId = BattlegroundTypeId(bgQueueTypeId.BattlemasterListId); // BGTemplateId returns BATTLEGROUND_AA when it is arena queue. // Do instance id search as there is no AA bg instances. Battleground* bg = sBattlegroundMgr->GetBattleground(ginfo.IsInvitedToBGInstanceGUID, bgTypeId == BATTLEGROUND_AA ? BATTLEGROUND_TYPE_NONE : bgTypeId); @@ -386,7 +389,9 @@ void WorldSession::HandleBattleFieldPortOpcode(WorldPackets::Battleground::Battl sBattlegroundMgr->SendToBattleground(_player, ginfo.IsInvitedToBGInstanceGUID, bgTypeId); // add only in HandleMoveWorldPortAck() // bg->AddPlayer(_player, team); - TC_LOG_DEBUG("bg.battleground", "Battleground: player %s (%s) joined battle for bg %u, bgtype %u, queue type %u.", _player->GetName().c_str(), _player->GetGUID().ToString().c_str(), bg->GetInstanceID(), bg->GetTypeID(), bgQueueTypeId); + TC_LOG_DEBUG("bg.battleground", "Battleground: player %s (%s) joined battle for bg %u, bgtype %u, queue { BattlemasterListId: %hu, Type: %u, Rated: %s, TeamSize: %u }.", + _player->GetName().c_str(), _player->GetGUID().ToString().c_str(), bg->GetInstanceID(), bg->GetTypeID(), + bgQueueTypeId.BattlemasterListId, uint32(bgQueueTypeId.Type), bgQueueTypeId.Rated ? "true" : "false", uint32(bgQueueTypeId.TeamSize)); } else // leave queue { @@ -410,9 +415,11 @@ void WorldSession::HandleBattleFieldPortOpcode(WorldPackets::Battleground::Battl bgQueue.RemovePlayer(_player->GetGUID(), true); // player left queue, we should update it - do not update Arena Queue if (!ginfo.ArenaType) - sBattlegroundMgr->ScheduleQueueUpdate(ginfo.ArenaMatchmakerRating, ginfo.ArenaType, bgQueueTypeId, bgTypeId, bracketEntry->GetBracketId()); + sBattlegroundMgr->ScheduleQueueUpdate(ginfo.ArenaMatchmakerRating, bgQueueTypeId, bracketEntry->GetBracketId()); - TC_LOG_DEBUG("bg.battleground", "Battleground: player %s (%s) left queue for bgtype %u, queue type %u.", _player->GetName().c_str(), _player->GetGUID().ToString().c_str(), bg->GetTypeID(), bgQueueTypeId); + TC_LOG_DEBUG("bg.battleground", "Battleground: player %s (%s) left queue for bgtype %u, queue { BattlemasterListId: %hu, Type: %u, Rated: %s, TeamSize: %u }.", + _player->GetName().c_str(), _player->GetGUID().ToString().c_str(), bg->GetTypeID(), + bgQueueTypeId.BattlemasterListId, uint32(bgQueueTypeId.Type), bgQueueTypeId.Rated ? "true" : "false", uint32(bgQueueTypeId.TeamSize)); } } @@ -434,22 +441,19 @@ void WorldSession::HandleRequestBattlefieldStatusOpcode(WorldPackets::Battlegrou for (uint8 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; ++i) { BattlegroundQueueTypeId bgQueueTypeId = _player->GetBattlegroundQueueTypeId(i); - if (!bgQueueTypeId) + if (bgQueueTypeId == BATTLEGROUND_QUEUE_NONE) continue; - BattlegroundTypeId bgTypeId = BattlegroundMgr::BGTemplateId(bgQueueTypeId); - uint8 arenaType = BattlegroundMgr::BGArenaType(bgQueueTypeId); - if (bgTypeId == _player->GetBattlegroundTypeId()) + BattlegroundTypeId bgTypeId = BattlegroundTypeId(bgQueueTypeId.BattlemasterListId); + uint8 arenaType = bgQueueTypeId.TeamSize; + bg = _player->GetBattleground(); + if (bg && bg->GetQueueId() == bgQueueTypeId) { - bg = _player->GetBattleground(); //i cannot check any variable from player class because player class doesn't know if player is in 2v2 / 3v3 or 5v5 arena //so i must use bg pointer to get that information - if (bg && bg->GetArenaType() == arenaType) - { - WorldPackets::Battleground::BattlefieldStatusActive battlefieldStatus; - sBattlegroundMgr->BuildBattlegroundStatusActive(&battlefieldStatus, bg, _player, i, _player->GetBattlegroundQueueJoinTime(bgQueueTypeId), arenaType); - SendPacket(battlefieldStatus.Write()); - continue; - } + WorldPackets::Battleground::BattlefieldStatusActive battlefieldStatus; + sBattlegroundMgr->BuildBattlegroundStatusActive(&battlefieldStatus, bg, _player, i, _player->GetBattlegroundQueueJoinTime(bgQueueTypeId), arenaType); + SendPacket(battlefieldStatus.Write()); + continue; } //we are sending update to player about queue - he can be invited there! @@ -482,7 +486,7 @@ void WorldSession::HandleRequestBattlefieldStatusOpcode(WorldPackets::Battlegrou uint32 avgTime = bgQueue.GetAverageQueueWaitTime(&ginfo, bracketEntry->GetBracketId()); WorldPackets::Battleground::BattlefieldStatusQueued battlefieldStatus; - sBattlegroundMgr->BuildBattlegroundStatusQueued(&battlefieldStatus, bg, _player, i, _player->GetBattlegroundQueueJoinTime(bgQueueTypeId), avgTime, arenaType, ginfo.Players.size() > 1); + sBattlegroundMgr->BuildBattlegroundStatusQueued(&battlefieldStatus, bg, _player, i, _player->GetBattlegroundQueueJoinTime(bgQueueTypeId), bgQueueTypeId, avgTime, arenaType, ginfo.Players.size() > 1); SendPacket(battlefieldStatus.Write()); } } @@ -511,7 +515,7 @@ void WorldSession::HandleBattlemasterJoinArena(WorldPackets::Battleground::Battl } BattlegroundTypeId bgTypeId = bg->GetTypeID(); - BattlegroundQueueTypeId bgQueueTypeId = BattlegroundMgr::BGQueueTypeId(bgTypeId, arenatype); + BattlegroundQueueTypeId bgQueueTypeId = BattlegroundMgr::BGQueueTypeId(bgTypeId, BattlegroundQueueIdType::Arena, true, arenatype); PVPDifficultyEntry const* bracketEntry = DB2Manager::GetBattlegroundBracketByLevel(bg->GetMapId(), _player->getLevel()); if (!bracketEntry) return; @@ -570,13 +574,15 @@ void WorldSession::HandleBattlemasterJoinArena(WorldPackets::Battleground::Battl uint32 queueSlot = member->AddBattlegroundQueueId(bgQueueTypeId); WorldPackets::Battleground::BattlefieldStatusQueued battlefieldStatus; - sBattlegroundMgr->BuildBattlegroundStatusQueued(&battlefieldStatus, bg, member, queueSlot, ginfo->JoinTime, avgTime, arenatype, true); + sBattlegroundMgr->BuildBattlegroundStatusQueued(&battlefieldStatus, bg, member, queueSlot, ginfo->JoinTime, bgQueueTypeId, avgTime, arenatype, true); member->SendDirectMessage(battlefieldStatus.Write()); - TC_LOG_DEBUG("bg.battleground", "Battleground: player joined queue for arena as group bg queue type %u bg type %u, %s, NAME %s", bgQueueTypeId, bgTypeId, member->GetGUID().ToString().c_str(), member->GetName().c_str()); + TC_LOG_DEBUG("bg.battleground", "Battleground: player joined queue for arena as group bg queue { BattlemasterListId: %hu, Type: %u, Rated: %s, TeamSize: %u }, %s, NAME %s", + bgQueueTypeId.BattlemasterListId, uint32(bgQueueTypeId.Type), bgQueueTypeId.Rated ? "true" : "false", uint32(bgQueueTypeId.TeamSize), + member->GetGUID().ToString().c_str(), member->GetName().c_str()); } - sBattlegroundMgr->ScheduleQueueUpdate(matchmakerRating, arenatype, bgQueueTypeId, bgTypeId, bracketEntry->GetBracketId()); + sBattlegroundMgr->ScheduleQueueUpdate(matchmakerRating, bgQueueTypeId, bracketEntry->GetBracketId()); } void WorldSession::HandleReportPvPAFK(WorldPackets::Battleground::ReportPvPPlayerAFK& reportPvPPlayerAFK) diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h index cbe5c32ff39..088cc262168 100644 --- a/src/server/game/Miscellaneous/SharedDefines.h +++ b/src/server/game/Miscellaneous/SharedDefines.h @@ -5091,6 +5091,7 @@ enum BattlegroundTypeId : uint32 // 809 = "New Nagrand Arena (Legion)" BATTLEGROUND_AF = 816, // Ashamane's Fall // 844 = "New Blade's Edge Arena (Legion)" + BATTLEGROUND_RANDOM_EPIC = 901 }; #define MAX_BATTLEGROUND_TYPE_ID 845 @@ -5239,25 +5240,54 @@ enum DuelCompleteType : uint8 DUEL_FLED = 2 }; -// handle the queue types and bg types separately to enable joining queue for different sized arenas at the same time -enum BattlegroundQueueTypeId -{ - BATTLEGROUND_QUEUE_NONE = 0, - BATTLEGROUND_QUEUE_AV = 1, - BATTLEGROUND_QUEUE_WS = 2, - BATTLEGROUND_QUEUE_AB = 3, - BATTLEGROUND_QUEUE_EY = 4, - BATTLEGROUND_QUEUE_SA = 5, - BATTLEGROUND_QUEUE_IC = 6, - BATTLEGROUND_QUEUE_TP = 7, - BATTLEGROUND_QUEUE_BFG = 8, - BATTLEGROUND_QUEUE_RB = 9, - BATTLEGROUND_QUEUE_2v2 = 10, - BATTLEGROUND_QUEUE_3v3 = 11, - BATTLEGROUND_QUEUE_5v5 = 12, - MAX_BATTLEGROUND_QUEUE_TYPES +struct BattlegroundQueueTypeId +{ + uint16 BattlemasterListId; + uint8 Type; + bool Rated; + uint8 TeamSize; + + static constexpr BattlegroundQueueTypeId FromPacked(uint64 packedQueueId) + { + return { packedQueueId & 0xFFFF, (packedQueueId >> 16) & 0xF, ((packedQueueId >> 20) & 1) != 0, (packedQueueId >> 24) & 0x3F }; + } + + constexpr uint64 GetPacked() const + { + return uint64(BattlemasterListId) + | (uint64(Type & 0xF) << 16) + | (uint64(Rated ? 1 : 0) << 20) + | (uint64(TeamSize & 0x3F) << 24) + | UI64LIT(0x1F10000000000000); + } + + constexpr bool operator==(BattlegroundQueueTypeId right) const + { + return BattlemasterListId == right.BattlemasterListId + && Type == right.Type + && Rated == right.Rated + && TeamSize == right.TeamSize; + } + + constexpr bool operator!=(BattlegroundQueueTypeId right) const + { + return !(*this == right); + } + + constexpr bool operator<(BattlegroundQueueTypeId right) const + { + if (BattlemasterListId != right.BattlemasterListId) + return BattlemasterListId < right.BattlemasterListId; + if (Type != right.Type) + return Type < right.Type; + if (Rated != right.Rated) + return Rated < right.Rated; + return TeamSize < right.TeamSize; + } }; +constexpr BattlegroundQueueTypeId BATTLEGROUND_QUEUE_NONE = { 0, 0, false, 0 }; + enum GroupJoinBattlegroundResult { ERR_BATTLEGROUND_NONE = 0, diff --git a/src/server/game/Server/Packets/BattlegroundPackets.cpp b/src/server/game/Server/Packets/BattlegroundPackets.cpp index 1b974829633..0d0325644ba 100644 --- a/src/server/game/Server/Packets/BattlegroundPackets.cpp +++ b/src/server/game/Server/Packets/BattlegroundPackets.cpp @@ -114,19 +114,26 @@ ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Battleground::PVPLogData: return data; } -WorldPacket const* WorldPackets::Battleground::PVPLogData::Write() +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Battleground::PVPLogData const& pvpLogData) { - _worldPacket.reserve(Statistics.size() * sizeof(PVPMatchPlayerStatistics) + sizeof(PVPLogData)); + data.WriteBit(pvpLogData.Ratings.is_initialized()); + data << uint32(pvpLogData.Statistics.size()); + data.append(pvpLogData.PlayerCount.data(), pvpLogData.PlayerCount.size()); - _worldPacket.WriteBit(Ratings.is_initialized()); - _worldPacket << uint32(Statistics.size()); - _worldPacket.append(PlayerCount.data(), PlayerCount.size()); + if (pvpLogData.Ratings.is_initialized()) + data << *pvpLogData.Ratings; - if (Ratings.is_initialized()) - _worldPacket << *Ratings; + for (WorldPackets::Battleground::PVPLogData::PVPMatchPlayerStatistics const& player : pvpLogData.Statistics) + data << player; - for (PVPMatchPlayerStatistics const& player : Statistics) - _worldPacket << player; + return data; +} + +WorldPacket const* WorldPackets::Battleground::PVPLogDataMessage::Write() +{ + _worldPacket.reserve(Data.Statistics.size() * sizeof(PVPLogData::PVPMatchPlayerStatistics) + sizeof(PVPLogData)); + + _worldPacket << Data; return &_worldPacket; } @@ -299,3 +306,31 @@ WorldPacket const* WorldPackets::Battleground::DestroyArenaUnit::Write() _worldPacket << Guid; return &_worldPacket; } + +WorldPacket const* WorldPackets::Battleground::PVPMatchInit::Write() +{ + _worldPacket << uint32(MapID); + _worldPacket << uint8(State); + _worldPacket << int32(StartTime); + _worldPacket << int32(Duration); + _worldPacket << uint8(ArenaFaction); + _worldPacket << uint32(BattlemasterListID); + _worldPacket.WriteBit(Registered); + _worldPacket.WriteBit(AffectsRating); + _worldPacket.FlushBits(); + + return &_worldPacket; +} + +WorldPacket const* WorldPackets::Battleground::PVPMatchEnd::Write() +{ + _worldPacket << uint8(Winner); + _worldPacket << int32(Duration); + _worldPacket.WriteBit(LogData.is_initialized()); + _worldPacket.FlushBits(); + + if (LogData) + _worldPacket << *LogData; + + return &_worldPacket; +} diff --git a/src/server/game/Server/Packets/BattlegroundPackets.h b/src/server/game/Server/Packets/BattlegroundPackets.h index 6914dfef818..59c49dcc8b9 100644 --- a/src/server/game/Server/Packets/BattlegroundPackets.h +++ b/src/server/game/Server/Packets/BattlegroundPackets.h @@ -90,13 +90,8 @@ namespace WorldPackets void Read() override { } }; - class PVPLogData final : public ServerPacket + struct PVPLogData { - public: - PVPLogData() : ServerPacket(SMSG_PVP_LOG_DATA, 0) { } - - WorldPacket const* Write() override; - struct RatingData { int32 Prematch[2] = { }; @@ -147,6 +142,16 @@ namespace WorldPackets std::array<int8, 2> PlayerCount = { }; }; + class PVPLogDataMessage final : public ServerPacket + { + public: + PVPLogDataMessage() : ServerPacket(SMSG_PVP_LOG_DATA, 0) { } + + WorldPacket const* Write() override; + + PVPLogData Data; + }; + struct BattlefieldStatusHeader { WorldPackets::LFG::RideTicket Ticket; @@ -418,6 +423,42 @@ namespace WorldPackets void Read() override { } }; + + class PVPMatchInit final : public ServerPacket + { + public: + PVPMatchInit() : ServerPacket(SMSG_PVP_MATCH_INIT, 4 + 1 + 4 + 4 + 1 + 4 + 1) { } + + WorldPacket const* Write() override; + + enum MatchState : uint8 + { + InProgress = 1, + Complete = 3, + Inactive = 4 + }; + + uint32 MapID = 0; + MatchState State = Inactive; + time_t StartTime = time_t(0); + int32 Duration = 0; + uint8 ArenaFaction = 0; + uint32 BattlemasterListID = 0; + bool Registered = false; + bool AffectsRating = false; + }; + + class PVPMatchEnd final : public ServerPacket + { + public: + PVPMatchEnd() : ServerPacket(SMSG_PVP_MATCH_END) { } + + WorldPacket const* Write() override; + + uint8 Winner = 0; + int32 Duration = 0; + Optional<PVPLogData> LogData; + }; } } diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp index a8f0be7874e..521ba8a8407 100644 --- a/src/server/game/Server/Protocol/Opcodes.cpp +++ b/src/server/game/Server/Protocol/Opcodes.cpp @@ -925,8 +925,6 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_AREA_TRIGGER_RE_PATH, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_AREA_TRIGGER_RE_SHAPE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_ARENA_CROWD_CONTROL_SPELLS, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_ARENA_MATCH_END, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_ARENA_MATCH_START, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_ARENA_PREP_OPPONENT_SPECIALIZATIONS, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_ARTIFACT_FORGE_OPENED, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_ARTIFACT_RESPEC_CONFIRM, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); @@ -1637,6 +1635,8 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_PUSH_SPELL_TO_ACTION_BAR, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_PVP_CREDIT, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_PVP_LOG_DATA, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_PVP_MATCH_END, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_PVP_MATCH_INIT, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_PVP_MATCH_START, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_PVP_OPTIONS_ENABLED, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_PVP_SEASON, STATUS_NEVER, CONNECTION_TYPE_REALM); diff --git a/src/server/game/Server/Protocol/Opcodes.h b/src/server/game/Server/Protocol/Opcodes.h index 2c90b66c0db..8b73a6fc26a 100644 --- a/src/server/game/Server/Protocol/Opcodes.h +++ b/src/server/game/Server/Protocol/Opcodes.h @@ -825,8 +825,6 @@ enum OpcodeServer : uint16 SMSG_AREA_TRIGGER_RE_PATH = 0x263F, SMSG_AREA_TRIGGER_RE_SHAPE = 0x2644, SMSG_ARENA_CROWD_CONTROL_SPELLS = 0x2652, - SMSG_ARENA_MATCH_END = 0x28A7, - SMSG_ARENA_MATCH_START = 0x28A6, SMSG_ARENA_PREP_OPPONENT_SPECIALIZATIONS = 0x2668, SMSG_ARTIFACT_FORGE_OPENED = 0x27E8, SMSG_ARTIFACT_RESPEC_CONFIRM = 0x27EB, @@ -1543,7 +1541,9 @@ enum OpcodeServer : uint16 SMSG_PUSH_SPELL_TO_ACTION_BAR = 0x2C51, SMSG_PVP_CREDIT = 0x271F, SMSG_PVP_LOG_DATA = 0x25B4, - SMSG_PVP_MATCH_START = 0x28AC, + SMSG_PVP_MATCH_END = 0x28A7, + SMSG_PVP_MATCH_INIT = 0x28AC, + SMSG_PVP_MATCH_START = 0x28A6, SMSG_PVP_OPTIONS_ENABLED = 0x25B7, SMSG_PVP_SEASON = 0x25D4, SMSG_QUERY_BATTLE_PET_NAME_RESPONSE = 0x270E, diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index 0b7c1583faf..1618267d420 100644 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -541,7 +541,8 @@ void WorldSession::LogoutPlayer(bool save) for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; ++i) { - if (BattlegroundQueueTypeId bgQueueTypeId = _player->GetBattlegroundQueueTypeId(i)) + BattlegroundQueueTypeId bgQueueTypeId = _player->GetBattlegroundQueueTypeId(i); + if (bgQueueTypeId != BATTLEGROUND_QUEUE_NONE) { _player->RemoveBattlegroundQueueId(bgQueueTypeId); BattlegroundQueue& queue = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId); |