feat(Core/Battleground): rework bg queue system (#10817)

This commit is contained in:
Kargatum
2022-03-16 00:36:49 +07:00
committed by GitHub
parent 6c60dc3841
commit 78bdc89881
29 changed files with 1354 additions and 963 deletions
@@ -0,0 +1,5 @@
INSERT INTO `version_db_world` (`sql_rev`) VALUES ('1645819759880724600');
DELETE FROM `acore_string` WHERE `entry` = 726;
INSERT INTO `acore_string` (`entry`, `content_default`, `locale_koKR`, `locale_frFR`, `locale_deDE`, `locale_zhCN`, `locale_zhTW`, `locale_esES`, `locale_esMX`, `locale_ruRU`) VALUES
(726, '|cffff0000[Arena Queue]:|r %s (skirmish %s) -- [%u-%u] [%u/%u]|r', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+1 -1
View File
@@ -56,7 +56,7 @@ AC_COMMON_API std::string GetDebugInfo();
#define WPAssert(cond, ...) do { if (!(cond)) Acore::Assert(__FILE__, __LINE__, __FUNCTION__, GetDebugInfo(), #cond, ##__VA_ARGS__); } while(0) #define WPAssert(cond, ...) do { if (!(cond)) Acore::Assert(__FILE__, __LINE__, __FUNCTION__, GetDebugInfo(), #cond, ##__VA_ARGS__); } while(0)
#define WPAssert_NODEBUGINFO(cond) do { if (!(cond)) Acore::Assert(__FILE__, __LINE__, __FUNCTION__, "", #cond); } while(0) #define WPAssert_NODEBUGINFO(cond) do { if (!(cond)) Acore::Assert(__FILE__, __LINE__, __FUNCTION__, "", #cond); } while(0)
#define WPFatal(cond, ...) do { if (!(cond)) Acore::Fatal(__FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__); } while(0) #define WPFatal(cond, ...) do { if (!(cond)) Acore::Fatal(__FILE__, __LINE__, __FUNCTION__, #cond, ##__VA_ARGS__); } while(0)
#define WPError(cond, msg) do { if (!(cond)) Acore::Error(__FILE__, __LINE__, __FUNCTION__, (msg)); } while(0) #define WPError(cond, msg) do { if (!(cond)) Acore::Error(__FILE__, __LINE__, __FUNCTION__, (msg)); } while(0)
#define WPWarning(cond, msg) do { if (!(cond)) Acore::Warning(__FILE__, __LINE__, __FUNCTION__, (msg)); } while(0) #define WPWarning(cond, msg) do { if (!(cond)) Acore::Warning(__FILE__, __LINE__, __FUNCTION__, (msg)); } while(0)
#define WPAbort(...) do { Acore::Abort(__FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__); } while(0) #define WPAbort(...) do { Acore::Abort(__FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__); } while(0)
@@ -137,7 +137,7 @@ bool ArenaSpectator::HandleSpectatorSpectateCommand(ChatHandler* handler, std::s
if (uint32 inviteInstanceId = player->GetPendingSpectatorInviteInstanceId()) if (uint32 inviteInstanceId = player->GetPendingSpectatorInviteInstanceId())
{ {
if (Battleground* tbg = sBattlegroundMgr->GetBattleground(inviteInstanceId)) if (Battleground* tbg = sBattlegroundMgr->GetBattleground(inviteInstanceId, BATTLEGROUND_TYPE_NONE))
tbg->RemoveToBeTeleported(player->GetGUID()); tbg->RemoveToBeTeleported(player->GetGUID());
player->SetPendingSpectatorInviteInstanceId(0); player->SetPendingSpectatorInviteInstanceId(0);
} }
+4
View File
@@ -312,6 +312,10 @@ void Arena::EndBattleground(TeamId winnerTeamId)
} }
} }
// update previous opponents for arena queue
winnerArenaTeam->SetPreviousOpponents(loserArenaTeam->GetId());
loserArenaTeam->SetPreviousOpponents(winnerArenaTeam->GetId());
// save the stat changes // save the stat changes
if (bValidArena) if (bValidArena)
{ {
+1 -1
View File
@@ -61,7 +61,7 @@ protected:
{ {
RatingChange = ratingChange; RatingChange = ratingChange;
MatchmakerRating = matchMakerRating; MatchmakerRating = matchMakerRating;
TeamName = teamName; TeamName = std::string(teamName);
} }
void BuildRatingInfoBlock(WorldPacket& data); void BuildRatingInfoBlock(WorldPacket& data);
+1 -1
View File
@@ -345,7 +345,7 @@ void ArenaTeam::DelMember(ObjectGuid guid, bool cleanDb)
WorldPacket data; WorldPacket data;
playerMember->RemoveBattlegroundQueueId(bgQueue); playerMember->RemoveBattlegroundQueueId(bgQueue);
sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, nullptr, playerMember->GetBattlegroundQueueIndex(bgQueue), STATUS_NONE, 0, 0, 0, TEAM_NEUTRAL); sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, nullptr, playerMember->GetBattlegroundQueueIndex(bgQueue), STATUS_NONE, 0, 0, 0, TEAM_NEUTRAL);
queue.RemovePlayer(playerMember->GetGUID(), true, 0); queue.RemovePlayer(playerMember->GetGUID(), true);
playerMember->GetSession()->SendPacket(&data); playerMember->GetSession()->SendPacket(&data);
} }
} }
@@ -209,6 +209,9 @@ public:
void FinishWeek(); void FinishWeek();
void FinishGame(int32 mod, const Map* bgMap); void FinishGame(int32 mod, const Map* bgMap);
void SetPreviousOpponents(uint32 arenaTeamId) { PreviousOpponents = arenaTeamId; }
uint32 GetPreviousOpponents() { return PreviousOpponents; }
void CreateTempArenaTeam(std::vector<Player*> playerList, uint8 type, std::string const& teamName); void CreateTempArenaTeam(std::vector<Player*> playerList, uint8 type, std::string const& teamName);
// Containers // Containers
@@ -229,5 +232,7 @@ protected:
MemberList Members; MemberList Members;
ArenaTeamStats Stats; ArenaTeamStats Stats;
uint32 PreviousOpponents = 0;
}; };
#endif #endif
+70 -2
View File
@@ -232,6 +232,9 @@ Battleground::~Battleground()
m_Map = nullptr; m_Map = nullptr;
} }
// remove from bg free slot queue
RemoveFromBGFreeSlotQueue();
for (auto const& itr : PlayerScores) for (auto const& itr : PlayerScores)
delete itr.second; delete itr.second;
} }
@@ -251,8 +254,21 @@ void Battleground::Update(uint32 diff)
if (!GetPlayersSize()) if (!GetPlayersSize())
{ {
//BG is empty
// if there are no players invited, delete BG
// this will delete arena or bg object, where any player entered
// [[ but if you use battleground object again (more battles possible to be played on 1 instance)
// then this condition should be removed and code:
// if (!GetInvitedCount(TEAM_HORDE) && !GetInvitedCount(TEAM_ALLIANCE))
// AddToFreeBGObjectsQueue(); // not yet implemented
// should be used instead of current
// ]]
// Battleground Template instance cannot be updated, because it would be deleted
if (!GetInvitedCount(TEAM_HORDE) && !GetInvitedCount(TEAM_ALLIANCE)) if (!GetInvitedCount(TEAM_HORDE) && !GetInvitedCount(TEAM_ALLIANCE))
{
m_SetDeleteThis = true; m_SetDeleteThis = true;
}
return; return;
} }
@@ -768,6 +784,7 @@ void Battleground::EndBattleground(PvPTeamId winnerTeamId)
if (GetStatus() == STATUS_WAIT_LEAVE) if (GetStatus() == STATUS_WAIT_LEAVE)
return; return;
RemoveFromBGFreeSlotQueue();
SetStatus(STATUS_WAIT_LEAVE); SetStatus(STATUS_WAIT_LEAVE);
SetWinner(winnerTeamId); SetWinner(winnerTeamId);
@@ -956,13 +973,17 @@ void Battleground::RemovePlayerAtLeave(Player* player)
// if the player was a match participant // if the player was a match participant
if (participant) if (participant)
{ {
WorldPacket data;
player->ClearAfkReports(); player->ClearAfkReports();
WorldPacket data;
sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, this, player->GetCurrentBattlegroundQueueSlot(), STATUS_NONE, 0, 0, 0, TEAM_NEUTRAL); sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, this, player->GetCurrentBattlegroundQueueSlot(), STATUS_NONE, 0, 0, 0, TEAM_NEUTRAL);
player->GetSession()->SendPacket(&data); player->GetSession()->SendPacket(&data);
BattlegroundQueueTypeId bgQueueTypeId = BattlegroundMgr::BGQueueTypeId(GetBgTypeID(), GetArenaType());
// this call is important, because player, when joins to battleground, this method is not called, so it must be called when leaving bg
player->RemoveBattlegroundQueueId(bgQueueTypeId);
// remove from raid group if player is member // remove from raid group if player is member
if (Group* group = GetBgRaid(teamId)) if (Group* group = GetBgRaid(teamId))
if (group->IsMember(player->GetGUID())) if (group->IsMember(player->GetGUID()))
@@ -977,6 +998,19 @@ void Battleground::RemovePlayerAtLeave(Player* player)
if (isBattleground() && !player->IsGameMaster() && sWorld->getBoolConfig(CONFIG_BATTLEGROUND_CAST_DESERTER)) if (isBattleground() && !player->IsGameMaster() && sWorld->getBoolConfig(CONFIG_BATTLEGROUND_CAST_DESERTER))
if (status == STATUS_IN_PROGRESS || status == STATUS_WAIT_JOIN) if (status == STATUS_IN_PROGRESS || status == STATUS_WAIT_JOIN)
player->ScheduleDelayedOperation(DELAYED_SPELL_CAST_DESERTER); player->ScheduleDelayedOperation(DELAYED_SPELL_CAST_DESERTER);
DecreaseInvitedCount(teamId);
//we should update battleground queue, but only if bg isn't ending
if (isBattleground() && GetStatus() < STATUS_WAIT_LEAVE)
{
BattlegroundTypeId bgTypeId = GetBgTypeID();
BattlegroundQueueTypeId bgQueueTypeId = BattlegroundMgr::BGQueueTypeId(GetBgTypeID(), GetArenaType());
// a player has left the battleground, so there are free slots -> add to queue
AddToBGFreeSlotQueue();
sBattlegroundMgr->ScheduleQueueUpdate(0, 0, bgQueueTypeId, bgTypeId, GetBracketId());
}
} }
// Remove shapeshift auras // Remove shapeshift auras
@@ -1009,6 +1043,7 @@ void Battleground::Init()
m_BgInvitedPlayers[TEAM_ALLIANCE] = 0; m_BgInvitedPlayers[TEAM_ALLIANCE] = 0;
m_BgInvitedPlayers[TEAM_HORDE] = 0; m_BgInvitedPlayers[TEAM_HORDE] = 0;
_InBGFreeSlotQueue = false;
m_Players.clear(); m_Players.clear();
@@ -1028,9 +1063,15 @@ void Battleground::StartBattleground()
SetStartTime(0); SetStartTime(0);
SetLastResurrectTime(0); SetLastResurrectTime(0);
// add BG to free slot queue
AddToBGFreeSlotQueue();
// add bg to update list // add bg to update list
// this must be done here, because we need to have already invited some players when first Battleground::Update() method is executed // this must be done here, because we need to have already invited some players when first Battleground::Update() method is executed
sBattlegroundMgr->AddBattleground(this); sBattlegroundMgr->AddBattleground(this);
if (m_IsRated)
LOG_DEBUG("bg.arena", "Arena match type: {} for Team1Id: {} - Team2Id: {} started.", m_ArenaType, m_ArenaTeamIds[TEAM_ALLIANCE], m_ArenaTeamIds[TEAM_HORDE]);
} }
void Battleground::AddPlayer(Player* player) void Battleground::AddPlayer(Player* player)
@@ -1129,6 +1170,26 @@ void Battleground::AddOrSetPlayerToCorrectBgGroup(Player* player, TeamId teamId)
} }
} }
// This method should be called only once ... it adds pointer to queue
void Battleground::AddToBGFreeSlotQueue()
{
if (!_InBGFreeSlotQueue && isBattleground())
{
sBattlegroundMgr->AddToBGFreeSlotQueue(m_RealTypeID, this);
_InBGFreeSlotQueue = true;
}
}
// This method removes this battleground from free queue - it must be called when deleting battleground
void Battleground::RemoveFromBGFreeSlotQueue()
{
if (_InBGFreeSlotQueue)
{
sBattlegroundMgr->RemoveFromBGFreeSlotQueue(m_RealTypeID, m_InstanceID);
_InBGFreeSlotQueue = false;
}
}
uint32 Battleground::GetFreeSlotsForTeam(TeamId teamId) const uint32 Battleground::GetFreeSlotsForTeam(TeamId teamId) const
{ {
if (!(GetStatus() == STATUS_IN_PROGRESS || GetStatus() == STATUS_WAIT_JOIN)) if (!(GetStatus() == STATUS_IN_PROGRESS || GetStatus() == STATUS_WAIT_JOIN))
@@ -1611,6 +1672,7 @@ void Battleground::SendMessage2ToAll(uint32 entry, ChatMsg type, Player const* s
void Battleground::EndNow() void Battleground::EndNow()
{ {
RemoveFromBGFreeSlotQueue();
SetStatus(STATUS_WAIT_LEAVE); SetStatus(STATUS_WAIT_LEAVE);
SetEndTime(0); SetEndTime(0);
} }
@@ -1777,6 +1839,12 @@ GraveyardStruct const* Battleground::GetClosestGraveyard(Player* player)
return sGraveyard->GetClosestGraveyard(player, player->GetBgTeamId()); return sGraveyard->GetClosestGraveyard(player, player->GetBgTeamId());
} }
void Battleground::SetBracket(PvPDifficultyEntry const* bracketEntry)
{
m_BracketId = bracketEntry->GetBracketId();
SetLevelRange(bracketEntry->minLevel, bracketEntry->maxLevel);
}
void Battleground::StartTimedAchievement(AchievementCriteriaTimedTypes type, uint32 entry) void Battleground::StartTimedAchievement(AchievementCriteriaTimedTypes type, uint32 entry)
{ {
for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr) for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
@@ -316,6 +316,7 @@ public:
// Get methods: // Get methods:
[[nodiscard]] std::string GetName() const { return m_Name; } [[nodiscard]] std::string GetName() const { return m_Name; }
[[nodiscard]] BattlegroundTypeId GetBgTypeID(bool GetRandom = false) const { return GetRandom ? m_RandomTypeID : m_RealTypeID; } [[nodiscard]] BattlegroundTypeId GetBgTypeID(bool GetRandom = false) const { return GetRandom ? m_RandomTypeID : m_RealTypeID; }
[[nodiscard]] BattlegroundBracketId GetBracketId() const { return m_BracketId; }
[[nodiscard]] uint32 GetInstanceID() const { return m_InstanceID; } [[nodiscard]] uint32 GetInstanceID() const { return m_InstanceID; }
[[nodiscard]] BattlegroundStatus GetStatus() const { return m_Status; } [[nodiscard]] BattlegroundStatus GetStatus() const { return m_Status; }
[[nodiscard]] uint32 GetClientInstanceID() const { return m_ClientInstanceID; } [[nodiscard]] uint32 GetClientInstanceID() const { return m_ClientInstanceID; }
@@ -341,6 +342,7 @@ public:
void SetName(std::string_view name) { m_Name = std::string(name); } void SetName(std::string_view name) { m_Name = std::string(name); }
void SetBgTypeID(BattlegroundTypeId TypeID) { m_RealTypeID = TypeID; } void SetBgTypeID(BattlegroundTypeId TypeID) { m_RealTypeID = TypeID; }
void SetRandomTypeID(BattlegroundTypeId TypeID) { m_RandomTypeID = TypeID; } void SetRandomTypeID(BattlegroundTypeId TypeID) { m_RandomTypeID = TypeID; }
void SetBracket(PvPDifficultyEntry const* bracketEntry);
void SetInstanceID(uint32 InstanceID) { m_InstanceID = InstanceID; } void SetInstanceID(uint32 InstanceID) { m_InstanceID = InstanceID; }
void SetStatus(BattlegroundStatus Status) { m_Status = Status; } void SetStatus(BattlegroundStatus Status) { m_Status = Status; }
void SetClientInstanceID(uint32 InstanceID) { m_ClientInstanceID = InstanceID; } void SetClientInstanceID(uint32 InstanceID) { m_ClientInstanceID = InstanceID; }
@@ -361,6 +363,9 @@ public:
void SetMaxPlayersPerTeam(uint32 MaxPlayers) { m_MaxPlayersPerTeam = MaxPlayers; } void SetMaxPlayersPerTeam(uint32 MaxPlayers) { m_MaxPlayersPerTeam = MaxPlayers; }
void SetMinPlayersPerTeam(uint32 MinPlayers) { m_MinPlayersPerTeam = MinPlayers; } void SetMinPlayersPerTeam(uint32 MinPlayers) { m_MinPlayersPerTeam = MinPlayers; }
void AddToBGFreeSlotQueue(); // this queue will be useful when more battlegrounds instances will be available
void RemoveFromBGFreeSlotQueue(); // this method could delete whole BG instance, if another free is available
void DecreaseInvitedCount(TeamId teamId) { if (m_BgInvitedPlayers[teamId]) --m_BgInvitedPlayers[teamId]; } void DecreaseInvitedCount(TeamId teamId) { if (m_BgInvitedPlayers[teamId]) --m_BgInvitedPlayers[teamId]; }
void IncreaseInvitedCount(TeamId teamId) { ++m_BgInvitedPlayers[teamId]; } void IncreaseInvitedCount(TeamId teamId) { ++m_BgInvitedPlayers[teamId]; }
[[nodiscard]] uint32 GetInvitedCount(TeamId teamId) const { return m_BgInvitedPlayers[teamId]; } [[nodiscard]] uint32 GetInvitedCount(TeamId teamId) const { return m_BgInvitedPlayers[teamId]; }
@@ -642,7 +647,9 @@ private:
uint32 m_ValidStartPositionTimer; uint32 m_ValidStartPositionTimer;
int32 m_EndTime; // it is set to 120000 when bg is ending and it decreases itself int32 m_EndTime; // it is set to 120000 when bg is ending and it decreases itself
uint32 m_LastResurrectTime; uint32 m_LastResurrectTime;
BattlegroundBracketId m_BracketId{ BG_BRACKET_ID_FIRST };
uint8 m_ArenaType; // 2=2v2, 3=3v3, 5=5v5 uint8 m_ArenaType; // 2=2v2, 3=3v3, 5=5v5
bool _InBGFreeSlotQueue{ false }; // used to make sure that BG is only once inserted into the BattlegroundMgr.BGFreeSlotQueue[bgTypeId] deque
bool m_SetDeleteThis; // used for safe deletion of the bg after end / all players leave bool m_SetDeleteThis; // used for safe deletion of the bg after end / all players leave
bool m_IsArena; bool m_IsArena;
PvPTeamId m_WinnerId; PvPTeamId m_WinnerId;
+252 -121
View File
@@ -48,15 +48,22 @@
#include "WorldPacket.h" #include "WorldPacket.h"
#include <unordered_map> #include <unordered_map>
bool BattlegroundTemplate::IsArena() const
{
return BattlemasterEntry->type == MAP_ARENA;
}
/*********************************************************/ /*********************************************************/
/*** BATTLEGROUND MANAGER ***/ /*** BATTLEGROUND MANAGER ***/
/*********************************************************/ /*********************************************************/
BattlegroundMgr::BattlegroundMgr() : m_ArenaTesting(false), m_Testing(false), BattlegroundMgr::BattlegroundMgr() :
m_lastClientVisibleInstanceId(0), m_NextAutoDistributionTime(0), m_AutoDistributionTimeChecker(0), m_NextPeriodicQueueUpdateTime(5 * IN_MILLISECONDS) m_ArenaTesting(false),
m_Testing(false),
m_NextAutoDistributionTime(0),
m_AutoDistributionTimeChecker(0),
m_NextPeriodicQueueUpdateTime(5 * IN_MILLISECONDS)
{ {
for (uint32 qtype = BATTLEGROUND_QUEUE_NONE; qtype < MAX_BATTLEGROUND_QUEUE_TYPES; ++qtype)
m_BattlegroundQueues[qtype].SetBgTypeIdAndArenaType(BGTemplateId(BattlegroundQueueTypeId(qtype)), BGArenaType(BattlegroundQueueTypeId(qtype)));
} }
BattlegroundMgr::~BattlegroundMgr() BattlegroundMgr::~BattlegroundMgr()
@@ -72,47 +79,68 @@ BattlegroundMgr* BattlegroundMgr::instance()
void BattlegroundMgr::DeleteAllBattlegrounds() void BattlegroundMgr::DeleteAllBattlegrounds()
{ {
while (!m_Battlegrounds.empty()) for (auto& [_, data] : bgDataStore)
delete m_Battlegrounds.begin()->second; {
m_Battlegrounds.clear(); while (!data._Battlegrounds.empty())
delete data._Battlegrounds.begin()->second;
while (!m_BattlegroundTemplates.empty()) data._Battlegrounds.clear();
delete m_BattlegroundTemplates.begin()->second;
m_BattlegroundTemplates.clear(); while (!data.BGFreeSlotQueue.empty())
delete data.BGFreeSlotQueue.front();
}
bgDataStore.clear();
} }
// used to update running battlegrounds, and delete finished ones // used to update running battlegrounds, and delete finished ones
void BattlegroundMgr::Update(uint32 diff) void BattlegroundMgr::Update(uint32 diff)
{ {
// update all battlegrounds and delete if needed // update all battlegrounds and delete if needed
for (BattlegroundContainer::iterator itr = m_Battlegrounds.begin(), itrDelete; itr != m_Battlegrounds.end(); ) for (auto& [_, bgData] : bgDataStore)
{
auto& bgList = bgData._Battlegrounds;
auto itrDelete = bgList.begin();
// first one is template and should not be deleted
for (BattlegroundContainer::iterator itr = ++itrDelete; itr != bgList.end();)
{ {
itrDelete = itr++; itrDelete = itr++;
Battleground* bg = itrDelete->second; Battleground* bg = itrDelete->second;
bg->Update(diff); bg->Update(diff);
if (bg->ToBeDeleted()) if (bg->ToBeDeleted())
{ {
itrDelete->second = nullptr; itrDelete->second = nullptr;
m_Battlegrounds.erase(itrDelete); bgList.erase(itrDelete);
BattlegroundClientIdsContainer& clients = bgData._ClientBattlegroundIds[bg->GetBracketId()];
if (!clients.empty())
clients.erase(bg->GetClientInstanceID());
delete bg; delete bg;
} }
} }
}
// update events // update events
for (int qtype = BATTLEGROUND_QUEUE_NONE; qtype < MAX_BATTLEGROUND_QUEUE_TYPES; ++qtype) for (uint8 qtype = BATTLEGROUND_QUEUE_NONE; qtype < MAX_BATTLEGROUND_QUEUE_TYPES; ++qtype)
m_BattlegroundQueues[qtype].UpdateEvents(diff); m_BattlegroundQueues[qtype].UpdateEvents(diff);
// update using scheduled tasks (used only for rated arenas, initial opponent search works differently than periodic queue update) // update using scheduled tasks (used only for rated arenas, initial opponent search works differently than periodic queue update)
if (!m_ArenaQueueUpdateScheduler.empty()) if (!m_QueueUpdateScheduler.empty())
{ {
std::vector<uint64> scheduled; std::vector<uint64> scheduled;
std::swap(scheduled, m_ArenaQueueUpdateScheduler); std::swap(scheduled, m_QueueUpdateScheduler);
for (uint8 i = 0; i < scheduled.size(); i++) for (uint8 i = 0; i < scheduled.size(); i++)
{ {
uint32 arenaRatedTeamId = scheduled[i] >> 32; uint32 arenaMMRating = scheduled[i] >> 32;
uint8 arenaType = scheduled[i] >> 24 & 255;
BattlegroundQueueTypeId bgQueueTypeId = BattlegroundQueueTypeId(scheduled[i] >> 16 & 255); BattlegroundQueueTypeId bgQueueTypeId = BattlegroundQueueTypeId(scheduled[i] >> 16 & 255);
BattlegroundTypeId bgTypeId = BattlegroundTypeId((scheduled[i] >> 8) & 255);
BattlegroundBracketId bracket_id = BattlegroundBracketId(scheduled[i] & 255); BattlegroundBracketId bracket_id = BattlegroundBracketId(scheduled[i] & 255);
m_BattlegroundQueues[bgQueueTypeId].BattlegroundQueueUpdate(diff, bracket_id, true, arenaRatedTeamId); // pussywizard: looking for opponents only for this team m_BattlegroundQueues[bgQueueTypeId].BattlegroundQueueUpdate(diff, bgTypeId, bracket_id, arenaType, arenaMMRating > 0, arenaMMRating);
} }
} }
@@ -121,16 +149,16 @@ void BattlegroundMgr::Update(uint32 diff)
{ {
m_NextPeriodicQueueUpdateTime = 5 * IN_MILLISECONDS; m_NextPeriodicQueueUpdateTime = 5 * IN_MILLISECONDS;
LOG_TRACE("bg.arena", "BattlegroundMgr: UPDATING ARENA QUEUES");
// for rated arenas // for rated arenas
for (uint32 qtype = BATTLEGROUND_QUEUE_2v2; qtype < MAX_BATTLEGROUND_QUEUE_TYPES; ++qtype) for (uint32 qtype = BATTLEGROUND_QUEUE_2v2; qtype < MAX_BATTLEGROUND_QUEUE_TYPES; ++qtype)
{
for (uint32 bracket = BG_BRACKET_ID_FIRST; bracket < MAX_BATTLEGROUND_BRACKETS; ++bracket) for (uint32 bracket = BG_BRACKET_ID_FIRST; bracket < MAX_BATTLEGROUND_BRACKETS; ++bracket)
m_BattlegroundQueues[qtype].BattlegroundQueueUpdate(m_NextPeriodicQueueUpdateTime, BattlegroundBracketId(bracket), true, 0); // pussywizard: 0 for rated means looking for opponents for every team {
m_BattlegroundQueues[qtype].BattlegroundQueueUpdate(diff, BATTLEGROUND_AA, BattlegroundBracketId(bracket), BattlegroundMgr::BGArenaType(BattlegroundQueueTypeId(qtype)), true, 0);
// for battlegrounds and not rated arenas }
// in first loop try to fill already running battlegrounds, then in a second loop try to create new battlegrounds }
for (uint32 qtype = BATTLEGROUND_QUEUE_AV; qtype < MAX_BATTLEGROUND_QUEUE_TYPES; ++qtype)
for (uint32 bracket = BG_BRACKET_ID_FIRST; bracket < MAX_BATTLEGROUND_BRACKETS; ++bracket)
m_BattlegroundQueues[qtype].BattlegroundQueueUpdate(m_NextPeriodicQueueUpdateTime, BattlegroundBracketId(bracket), false, 0);
} }
else else
m_NextPeriodicQueueUpdateTime -= diff; m_NextPeriodicQueueUpdateTime -= diff;
@@ -225,36 +253,108 @@ void BattlegroundMgr::BuildPlayerJoinedBattlegroundPacket(WorldPacket* data, Pla
*data << player->GetGUID(); *data << player->GetGUID();
} }
Battleground* BattlegroundMgr::GetBattleground(uint32 instanceId) Battleground* BattlegroundMgr::GetBattlegroundThroughClientInstance(uint32 instanceId, BattlegroundTypeId bgTypeId)
{
//cause at HandleBattlegroundJoinOpcode the clients sends the instanceid he gets from
//SMSG_BATTLEFIELD_LIST we need to find the battleground with this clientinstance-id
Battleground* bg = GetBattlegroundTemplate(bgTypeId);
if (!bg)
return nullptr;
if (bg->isArena())
return GetBattleground(instanceId, bgTypeId);
auto const& it = bgDataStore.find(bgTypeId);
if (it == bgDataStore.end())
return nullptr;
for (auto const& itr : it->second._Battlegrounds)
{
if (itr.second->GetClientInstanceID() == instanceId)
return itr.second;
}
return nullptr;
}
Battleground* BattlegroundMgr::GetBattleground(uint32 instanceId, BattlegroundTypeId bgTypeId)
{ {
if (!instanceId) if (!instanceId)
return nullptr; return nullptr;
BattlegroundContainer::const_iterator itr = m_Battlegrounds.find(instanceId); auto GetBgWithInstanceID = [instanceId](BattlegroundData const* bgData) -> Battleground*
if (itr != m_Battlegrounds.end()) {
auto const& itr = bgData->_Battlegrounds.find(instanceId);
if (itr != bgData->_Battlegrounds.end())
return itr->second; return itr->second;
return nullptr;
};
if (bgTypeId == BATTLEGROUND_TYPE_NONE)
{
for (auto const& [bgType, bgData] : bgDataStore)
{
if (auto bg = GetBgWithInstanceID(&bgData))
return bg;
}
}
else
{
auto const& itr = bgDataStore.find(bgTypeId);
if (itr == bgDataStore.end())
return nullptr;
if (auto bg = GetBgWithInstanceID(&itr->second))
return bg;
}
return nullptr; return nullptr;
} }
Battleground* BattlegroundMgr::GetBattlegroundTemplate(BattlegroundTypeId bgTypeId) Battleground* BattlegroundMgr::GetBattlegroundTemplate(BattlegroundTypeId bgTypeId)
{ {
BattlegroundTemplateContainer::const_iterator itr = m_BattlegroundTemplates.find(bgTypeId); BattlegroundDataContainer::const_iterator itr = bgDataStore.find(bgTypeId);
if (itr != m_BattlegroundTemplates.end()) if (itr == bgDataStore.end())
return itr->second;
return nullptr; return nullptr;
BattlegroundContainer const& bgs = itr->second._Battlegrounds;
// map is sorted and we can be sure that lowest instance id has only BG template
return bgs.empty() ? nullptr : bgs.begin()->second;
} }
uint32 BattlegroundMgr::GetNextClientVisibleInstanceId() uint32 BattlegroundMgr::CreateClientVisibleInstanceId(BattlegroundTypeId bgTypeId, BattlegroundBracketId bracket_id)
{ {
return ++m_lastClientVisibleInstanceId; if (IsArenaType(bgTypeId))
return 0; // arenas don't have client-instanceids
// we create here an instanceid, which is just for
// displaying this to the client and without any other use..
// the client-instanceIds are unique for each battleground-type
// the instance-id just needs to be as low as possible, beginning with 1
// the following works, because std::set is default ordered with "<"
// the optimalization would be to use as bitmask std::vector<uint32> - but that would only make code unreadable
BattlegroundClientIdsContainer& clientIds = bgDataStore[bgTypeId]._ClientBattlegroundIds[bracket_id];
uint32 lastId = 0;
for (BattlegroundClientIdsContainer::const_iterator itr = clientIds.begin(); itr != clientIds.end();)
{
if ((++lastId) != *itr) // if there is a gap between the ids, we will break..
break;
lastId = *itr;
}
clientIds.emplace(++lastId);
return lastId;
} }
// create a new battleground that will really be used to play // create a new battleground that will really be used to play
Battleground* BattlegroundMgr::CreateNewBattleground(BattlegroundTypeId originalBgTypeId, uint32 minLevel, uint32 maxLevel, uint8 arenaType, bool isRated) Battleground* BattlegroundMgr::CreateNewBattleground(BattlegroundTypeId originalBgTypeId, PvPDifficultyEntry const* bracketEntry, uint8 arenaType, bool isRated)
{ {
BattlegroundTypeId bgTypeId = GetRandomBG(originalBgTypeId, minLevel); BattlegroundTypeId bgTypeId = GetRandomBG(originalBgTypeId, bracketEntry->minLevel);
if (originalBgTypeId == BATTLEGROUND_AA) if (originalBgTypeId == BATTLEGROUND_AA)
originalBgTypeId = bgTypeId; originalBgTypeId = bgTypeId;
@@ -262,9 +362,13 @@ Battleground* BattlegroundMgr::CreateNewBattleground(BattlegroundTypeId original
// get the template BG // get the template BG
Battleground* bg_template = GetBattlegroundTemplate(bgTypeId); Battleground* bg_template = GetBattlegroundTemplate(bgTypeId);
if (!bg_template) if (!bg_template)
{
LOG_ERROR("bg.battleground", "Battleground: CreateNewBattleground - bg template not found for {}", bgTypeId);
return nullptr; return nullptr;
}
Battleground* bg = nullptr; Battleground* bg = nullptr;
// create a copy of the BG template // create a copy of the BG template
if (BattlegroundMgr::bgTypeToTemplate.find(bgTypeId) == BattlegroundMgr::bgTypeToTemplate.end()) if (BattlegroundMgr::bgTypeToTemplate.find(bgTypeId) == BattlegroundMgr::bgTypeToTemplate.end())
{ {
@@ -275,9 +379,9 @@ Battleground* BattlegroundMgr::CreateNewBattleground(BattlegroundTypeId original
bool isRandom = bgTypeId != originalBgTypeId && !bg->isArena(); bool isRandom = bgTypeId != originalBgTypeId && !bg->isArena();
bg->SetLevelRange(minLevel, maxLevel); bg->SetBracket(bracketEntry);
bg->SetInstanceID(sMapMgr->GenerateInstanceId()); bg->SetInstanceID(sMapMgr->GenerateInstanceId());
bg->SetClientInstanceID(IsArenaType(originalBgTypeId) ? 0 : GetNextClientVisibleInstanceId()); bg->SetClientInstanceID(CreateClientVisibleInstanceId(originalBgTypeId, bracketEntry->GetBracketId()));
bg->Init(); bg->Init();
bg->SetStatus(STATUS_WAIT_JOIN); // start the joining of the bg bg->SetStatus(STATUS_WAIT_JOIN); // start the joining of the bg
bg->SetArenaType(arenaType); bg->SetArenaType(arenaType);
@@ -298,37 +402,40 @@ Battleground* BattlegroundMgr::CreateNewBattleground(BattlegroundTypeId original
} }
// used to create the BG templates // used to create the BG templates
bool BattlegroundMgr::CreateBattleground(CreateBattlegroundData& data) bool BattlegroundMgr::CreateBattleground(BattlegroundTemplate const* bgTemplate)
{ {
// Create the BG // Create the BG
Battleground* bg = nullptr; Battleground* bg = GetBattlegroundTemplate(bgTemplate->Id);
bg = BattlegroundMgr::bgtypeToBattleground[data.bgTypeId];
if (bg == nullptr) if (!bg)
return false; {
bg = BattlegroundMgr::bgtypeToBattleground[bgTemplate->Id];
if (data.bgTypeId == BATTLEGROUND_RB) ASSERT(bg);
if (bgTemplate->Id == BATTLEGROUND_RB)
bg->SetRandom(true); bg->SetRandom(true);
bg->SetMapId(data.MapID); bg->SetBgTypeID(bgTemplate->Id);
bg->SetBgTypeID(data.bgTypeId);
bg->SetInstanceID(0); bg->SetInstanceID(0);
bg->SetArenaorBGType(data.IsArena);
bg->SetMinPlayersPerTeam(data.MinPlayersPerTeam);
bg->SetMaxPlayersPerTeam(data.MaxPlayersPerTeam);
bg->SetName(data.BattlegroundName);
bg->SetTeamStartPosition(TEAM_ALLIANCE, data.StartLocation[TEAM_ALLIANCE]);
bg->SetTeamStartPosition(TEAM_HORDE, data.StartLocation[TEAM_HORDE]);
bg->SetStartMaxDist(data.StartMaxDist);
bg->SetLevelRange(data.LevelMin, data.LevelMax);
bg->SetScriptId(data.scriptId);
AddBattleground(bg); AddBattleground(bg);
}
bg->SetMapId(bgTemplate->BattlemasterEntry->mapid[0]);
bg->SetName(bgTemplate->BattlemasterEntry->name[sWorld->GetDefaultDbcLocale()]);
bg->SetArenaorBGType(bgTemplate->IsArena());
bg->SetMinPlayersPerTeam(bgTemplate->MinPlayersPerTeam);
bg->SetMaxPlayersPerTeam(bgTemplate->MaxPlayersPerTeam);
bg->SetTeamStartPosition(TEAM_ALLIANCE, bgTemplate->StartLocation[TEAM_ALLIANCE]);
bg->SetTeamStartPosition(TEAM_HORDE, bgTemplate->StartLocation[TEAM_HORDE]);
bg->SetStartMaxDist(bgTemplate->MaxStartDistSq);
bg->SetLevelRange(bgTemplate->MinLevel, bgTemplate->MaxLevel);
bg->SetScriptId(bgTemplate->ScriptId);
return true; return true;
} }
void BattlegroundMgr::CreateInitialBattlegrounds() void BattlegroundMgr::LoadBattlegroundTemplates()
{ {
uint32 oldMSTime = getMSTime(); uint32 oldMSTime = getMSTime();
@@ -344,13 +451,11 @@ void BattlegroundMgr::CreateInitialBattlegrounds()
return; return;
} }
uint32 count = 0;
do do
{ {
Field* fields = result->Fetch(); Field* fields = result->Fetch();
uint32 bgTypeId = fields[0].Get<uint32>(); BattlegroundTypeId bgTypeId = static_cast<BattlegroundTypeId>(fields[0].Get<uint32>());
if (DisableMgr::IsDisabledFor(DISABLE_TYPE_BATTLEGROUND, bgTypeId, nullptr)) if (DisableMgr::IsDisabledFor(DISABLE_TYPE_BATTLEGROUND, bgTypeId, nullptr))
continue; continue;
@@ -363,72 +468,69 @@ void BattlegroundMgr::CreateInitialBattlegrounds()
continue; continue;
} }
CreateBattlegroundData data; BattlegroundTemplate bgTemplate;
data.bgTypeId = BattlegroundTypeId(bgTypeId); bgTemplate.Id = bgTypeId;
data.IsArena = (bl->type == TYPE_ARENA); bgTemplate.MinPlayersPerTeam = fields[1].Get<uint16>();
data.MinPlayersPerTeam = fields[1].Get<uint16>(); bgTemplate.MaxPlayersPerTeam = fields[2].Get<uint16>();
data.MaxPlayersPerTeam = fields[2].Get<uint16>(); bgTemplate.MinLevel = fields[3].Get<uint8>();
data.LevelMin = fields[3].Get<uint8>(); bgTemplate.MaxLevel = fields[4].Get<uint8>();
data.LevelMax = fields[4].Get<uint8>();
float dist = fields[9].Get<float>(); float dist = fields[9].Get<float>();
data.StartMaxDist = dist * dist; bgTemplate.MaxStartDistSq = dist * dist;
data.Weight = fields[10].Get<uint8>(); bgTemplate.Weight = fields[10].Get<uint8>();
bgTemplate.ScriptId = sObjectMgr->GetScriptId(fields[11].Get<std::string>());
bgTemplate.BattlemasterEntry = bl;
data.scriptId = sObjectMgr->GetScriptId(fields[11].Get<std::string>()); if (bgTemplate.MaxPlayersPerTeam == 0 || bgTemplate.MinPlayersPerTeam > bgTemplate.MaxPlayersPerTeam)
data.BattlegroundName = bl->name[sWorld->GetDefaultDbcLocale()];
data.MapID = bl->mapid[0];
if (data.MaxPlayersPerTeam == 0 || data.MinPlayersPerTeam > data.MaxPlayersPerTeam)
{ {
LOG_ERROR("bg.battleground", "Table `battleground_template` for id {} has bad values for MinPlayersPerTeam ({}) and MaxPlayersPerTeam({})", LOG_ERROR("sql.sql", "Table `battleground_template` for id {} contains bad values for MinPlayersPerTeam ({}) and MaxPlayersPerTeam({}).",
data.bgTypeId, data.MinPlayersPerTeam, data.MaxPlayersPerTeam); bgTemplate.Id, bgTemplate.MinPlayersPerTeam, bgTemplate.MaxPlayersPerTeam);
continue; continue;
} }
if (data.LevelMin == 0 || data.LevelMax == 0 || data.LevelMin > data.LevelMax) if (bgTemplate.MinLevel == 0 || bgTemplate.MaxLevel == 0 || bgTemplate.MinLevel > bgTemplate.MaxLevel)
{ {
LOG_ERROR("bg.battleground", "Table `battleground_template` for id {} has bad values for LevelMin ({}) and LevelMax({})", LOG_ERROR("sql.sql", "Table `battleground_template` for id {} has bad values for LevelMin ({}) and LevelMax({})",
data.bgTypeId, data.LevelMin, data.LevelMax); bgTemplate.Id, bgTemplate.MinLevel, bgTemplate.MaxLevel);
continue; continue;
} }
if (data.bgTypeId != BATTLEGROUND_AA && data.bgTypeId != BATTLEGROUND_RB) if (bgTemplate.Id != BATTLEGROUND_AA && bgTemplate.Id != BATTLEGROUND_RB)
{ {
uint32 startId = fields[5].Get<uint32>(); uint32 startId = fields[5].Get<uint32>();
if (GraveyardStruct const* start = sGraveyard->GetGraveyard(startId)) if (GraveyardStruct const* start = sGraveyard->GetGraveyard(startId))
{ {
data.StartLocation[TEAM_ALLIANCE].Relocate(start->x, start->y, start->z, fields[6].Get<float>()); bgTemplate.StartLocation[TEAM_ALLIANCE].Relocate(start->x, start->y, start->z, fields[6].Get<float>());
} }
else else
{ {
LOG_ERROR("sql.sql", "Table `battleground_template` for id %u contains a non-existing WorldSafeLocs.dbc id %u in field `AllianceStartLoc`. BG not created.", data.bgTypeId, startId); LOG_ERROR("sql.sql", "Table `battleground_template` for id {} contains a non-existing WorldSafeLocs.dbc id {} in field `AllianceStartLoc`. BG not created.", bgTemplate.Id, startId);
continue; continue;
} }
startId = fields[7].Get<uint32>(); startId = fields[7].Get<uint32>();
if (GraveyardStruct const* start = sGraveyard->GetGraveyard(startId)) if (GraveyardStruct const* start = sGraveyard->GetGraveyard(startId))
{ {
data.StartLocation[TEAM_HORDE].Relocate(start->x, start->y, start->z, fields[8].Get<float>()); bgTemplate.StartLocation[TEAM_HORDE].Relocate(start->x, start->y, start->z, fields[8].Get<float>());
} }
else else
{ {
LOG_ERROR("sql.sql", "Table `battleground_template` for id %u contains a non-existing WorldSafeLocs.dbc id %u in field `HordeStartLoc`. BG not created.", data.bgTypeId, startId); LOG_ERROR("sql.sql", "Table `battleground_template` for id {} contains a non-existing WorldSafeLocs.dbc id {} in field `HordeStartLoc`. BG not created.", bgTemplate.Id, startId);
continue; continue;
} }
} }
if (!CreateBattleground(data)) if (!CreateBattleground(&bgTemplate))
continue; continue;
_battlegroundTemplates[BattlegroundTypeId(bgTypeId)] = data; _battlegroundTemplates[bgTypeId] = bgTemplate;
if (bl->mapid[1] == -1) // in this case we have only one mapId if (bgTemplate.BattlemasterEntry->mapid[1] == -1) // in this case we have only one mapId
_battlegroundMapTemplates[bl->mapid[0]] = &_battlegroundTemplates[BattlegroundTypeId(bgTypeId)]; _battlegroundMapTemplates[bgTemplate.BattlemasterEntry->mapid[0]] = &_battlegroundTemplates[bgTypeId];
++count;
} while (result->NextRow()); } while (result->NextRow());
LOG_INFO("server.loading", ">> Loaded {} battlegrounds in {} ms", count, GetMSTimeDiffToNow(oldMSTime)); LOG_INFO("server.loading", ">> Loaded {} battlegrounds in {} ms", _battlegroundTemplates.size(), GetMSTimeDiffToNow(oldMSTime));
LOG_INFO("server.loading", " "); LOG_INFO("server.loading", " ");
} }
@@ -499,23 +601,31 @@ void BattlegroundMgr::BuildBattlegroundListPacket(WorldPacket* data, ObjectGuid
size_t count_pos = data->wpos(); size_t count_pos = data->wpos();
*data << uint32(0); // number of bg instances *data << uint32(0); // number of bg instances
if (Battleground* bgt = GetBattlegroundTemplate(bgTypeId)) auto const& it = bgDataStore.find(bgTypeId);
if (GetBattlegroundBracketByLevel(bgt->GetMapId(), player->getLevel())) if (it != bgDataStore.end())
{
// expected bracket entry
if (PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketByLevel(it->second._Battlegrounds.begin()->second->GetMapId(), player->getLevel()))
{ {
uint32 count = 0; uint32 count = 0;
/*for (BattlegroundClientIdsContainer::const_iterator itr = clientIds.begin(); itr != clientIds.end(); ++itr) BattlegroundBracketId bracketId = bracketEntry->GetBracketId();
BattlegroundClientIdsContainer& clientIds = it->second._ClientBattlegroundIds[bracketId];
for (auto const& itr : clientIds)
{ {
*data << uint32(*itr); *data << uint32(itr);
++count; ++count;
}*/ }
data->put<uint32>(count_pos, count); data->put<uint32>(count_pos, count);
} }
} }
}
} }
void BattlegroundMgr::SendToBattleground(Player* player, uint32 instanceId, BattlegroundTypeId bgTypeId) void BattlegroundMgr::SendToBattleground(Player* player, uint32 instanceId, BattlegroundTypeId bgTypeId)
{ {
if (Battleground* bg = GetBattleground(instanceId)) if (Battleground* bg = GetBattleground(instanceId, bgTypeId))
{ {
uint32 mapid = bg->GetMapId(); uint32 mapid = bg->GetMapId();
Position const* pos = bg->GetTeamStartPosition(player->GetBgTeamId()); Position const* pos = bg->GetTeamStartPosition(player->GetBgTeamId());
@@ -636,11 +746,25 @@ void BattlegroundMgr::SetHolidayWeekends(uint32 mask)
} }
} }
void BattlegroundMgr::ScheduleArenaQueueUpdate(uint32 arenaRatedTeamId, BattlegroundQueueTypeId bgQueueTypeId, BattlegroundBracketId bracket_id) void BattlegroundMgr::ScheduleQueueUpdate(uint32 arenaMatchmakerRating, uint8 arenaType, BattlegroundQueueTypeId bgQueueTypeId, BattlegroundTypeId bgTypeId, BattlegroundBracketId bracket_id)
{ {
uint64 const scheduleId = ((uint64)arenaRatedTeamId << 32) | (bgQueueTypeId << 16) | bracket_id; //This method must be atomic, @todo add mutex
if (std::find(m_ArenaQueueUpdateScheduler.begin(), m_ArenaQueueUpdateScheduler.end(), scheduleId) == m_ArenaQueueUpdateScheduler.end()) //we will use only 1 number created of bgTypeId and bracket_id
m_ArenaQueueUpdateScheduler.push_back(scheduleId); uint64 const scheduleId = ((uint64)arenaMatchmakerRating << 32) | ((uint64)arenaType << 24) | ((uint64)bgQueueTypeId << 16) | ((uint64)bgTypeId << 8) | (uint64)bracket_id;
if (std::find(m_QueueUpdateScheduler.begin(), m_QueueUpdateScheduler.end(), scheduleId) == m_QueueUpdateScheduler.end())
m_QueueUpdateScheduler.emplace_back(scheduleId);
}
uint32 BattlegroundMgr::GetMaxRatingDifference() const
{
uint32 diff = sWorld->getIntConfig(CONFIG_ARENA_MAX_RATING_DIFFERENCE);
if (diff == 0)
{
diff = 5000;
}
return diff;
} }
uint32 BattlegroundMgr::GetRatingDiscardTimer() const uint32 BattlegroundMgr::GetRatingDiscardTimer() const
@@ -766,24 +890,23 @@ bool BattlegroundMgr::IsBGWeekend(BattlegroundTypeId bgTypeId)
BattlegroundTypeId BattlegroundMgr::GetRandomBG(BattlegroundTypeId bgTypeId, uint32 minLevel) BattlegroundTypeId BattlegroundMgr::GetRandomBG(BattlegroundTypeId bgTypeId, uint32 minLevel)
{ {
if (GetBattlegroundTemplateByTypeId(bgTypeId)) if (BattlegroundTemplate const* bgTemplate = GetBattlegroundTemplateByTypeId(bgTypeId))
{ {
std::vector<BattlegroundTypeId> ids; std::vector<BattlegroundTypeId> ids;
ids.reserve(16); ids.reserve(16);
std::vector<double> weights; std::vector<double> weights;
weights.reserve(16); weights.reserve(16);
BattlemasterListEntry const* bl = sBattlemasterListStore.LookupEntry(bgTypeId);
for (int32 mapId : bl->mapid) for (int32 mapId : bgTemplate->BattlemasterEntry->mapid)
{ {
if (mapId == -1) if (mapId == -1)
break; break;
if (CreateBattlegroundData const* bg = GetBattlegroundTemplateByMapId(mapId)) if (BattlegroundTemplate const* bg = GetBattlegroundTemplateByMapId(mapId))
{ {
if (bg->LevelMin <= minLevel) if (bg->MinLevel <= minLevel)
{ {
ids.push_back(bg->bgTypeId); ids.push_back(bg->Id);
weights.push_back(bg->Weight); weights.push_back(bg->Weight);
} }
} }
@@ -795,30 +918,38 @@ BattlegroundTypeId BattlegroundMgr::GetRandomBG(BattlegroundTypeId bgTypeId, uin
return BATTLEGROUND_TYPE_NONE; return BATTLEGROUND_TYPE_NONE;
} }
BGFreeSlotQueueContainer& BattlegroundMgr::GetBGFreeSlotQueueStore(BattlegroundTypeId bgTypeId)
{
return bgDataStore[bgTypeId].BGFreeSlotQueue;
}
void BattlegroundMgr::AddToBGFreeSlotQueue(BattlegroundTypeId bgTypeId, Battleground* bg)
{
bgDataStore[bgTypeId].BGFreeSlotQueue.push_front(bg);
}
void BattlegroundMgr::RemoveFromBGFreeSlotQueue(BattlegroundTypeId bgTypeId, uint32 instanceId)
{
BGFreeSlotQueueContainer& queues = bgDataStore[bgTypeId].BGFreeSlotQueue;
for (BGFreeSlotQueueContainer::iterator itr = queues.begin(); itr != queues.end(); ++itr)
if ((*itr)->GetInstanceID() == instanceId)
{
queues.erase(itr);
return;
}
}
void BattlegroundMgr::AddBattleground(Battleground* bg) void BattlegroundMgr::AddBattleground(Battleground* bg)
{ {
if (bg->GetInstanceID() == 0) if (bg)
m_BattlegroundTemplates[bg->GetBgTypeID()] = bg; bgDataStore[bg->GetBgTypeID()]._Battlegrounds[bg->GetInstanceID()] = bg;
else
m_Battlegrounds[bg->GetInstanceID()] = bg;
sScriptMgr->OnBattlegroundCreate(bg); sScriptMgr->OnBattlegroundCreate(bg);
} }
void BattlegroundMgr::RemoveBattleground(BattlegroundTypeId bgTypeId, uint32 instanceId) void BattlegroundMgr::RemoveBattleground(BattlegroundTypeId bgTypeId, uint32 instanceId)
{ {
if (instanceId == 0) bgDataStore[bgTypeId]._Battlegrounds.erase(instanceId);
m_BattlegroundTemplates.erase(bgTypeId);
else
m_Battlegrounds.erase(instanceId);
}
void BattlegroundMgr::DoForAllBattlegrounds(std::function<void(Battleground*)> const& worker)
{
for (auto const& [_, bg] : m_Battlegrounds)
{
worker(bg);
}
} }
// init/update unordered_map // init/update unordered_map
+46 -35
View File
@@ -27,29 +27,38 @@
#include <functional> #include <functional>
typedef std::map<uint32, Battleground*> BattlegroundContainer; typedef std::map<uint32, Battleground*> BattlegroundContainer;
typedef std::set<uint32> BattlegroundClientIdsContainer;
typedef std::unordered_map<uint32, BattlegroundTypeId> BattleMastersMap; typedef std::unordered_map<uint32, BattlegroundTypeId> BattleMastersMap;
typedef Battleground* (*bgRef)(Battleground*); typedef Battleground* (*bgRef)(Battleground*);
typedef void(*bgMapRef)(WorldPacket*, Battleground::BattlegroundScoreMap::const_iterator); typedef void(*bgMapRef)(WorldPacket*, Battleground::BattlegroundScoreMap::const_iterator);
typedef void(*bgTypeRef)(WorldPacket*, Battleground::BattlegroundScoreMap::const_iterator, Battleground*); typedef void(*bgTypeRef)(WorldPacket*, Battleground::BattlegroundScoreMap::const_iterator, Battleground*);
struct CreateBattlegroundData // this container can't be deque, because deque doesn't like removing the last element - if you remove it, it invalidates next iterator and crash appears
using BGFreeSlotQueueContainer = std::list<Battleground*>;
struct BattlegroundData
{ {
BattlegroundTypeId bgTypeId; BattlegroundContainer _Battlegrounds;
bool IsArena; std::array<BattlegroundClientIdsContainer, MAX_BATTLEGROUND_BRACKETS> _ClientBattlegroundIds;
uint32 MinPlayersPerTeam; BGFreeSlotQueueContainer BGFreeSlotQueue;
uint32 MaxPlayersPerTeam;
uint32 LevelMin;
uint32 LevelMax;
char const* BattlegroundName;
uint32 MapID;
float StartMaxDist;
std::array<Position, PVP_TEAMS_COUNT> StartLocation;
uint32 scriptId;
uint8 Weight;
}; };
struct GroupQueueInfo; struct BattlegroundTemplate
{
BattlegroundTypeId Id;
uint16 MinPlayersPerTeam;
uint16 MaxPlayersPerTeam;
uint8 MinLevel;
uint8 MaxLevel;
std::array<Position, PVP_TEAMS_COUNT> StartLocation;
float MaxStartDistSq;
uint8 Weight;
uint32 ScriptId;
BattlemasterListEntry const* BattlemasterEntry;
bool IsArena() const;
};
class BattlegroundMgr class BattlegroundMgr
{ {
@@ -71,21 +80,25 @@ public:
void SendAreaSpiritHealerQueryOpcode(Player* player, Battleground* bg, ObjectGuid guid); void SendAreaSpiritHealerQueryOpcode(Player* player, Battleground* bg, ObjectGuid guid);
/* Battlegrounds */ /* Battlegrounds */
Battleground* GetBattleground(uint32 InstanceID); Battleground* GetBattlegroundThroughClientInstance(uint32 instanceId, BattlegroundTypeId bgTypeId);
Battleground* GetBattleground(uint32 instanceID, BattlegroundTypeId bgTypeId);
Battleground* GetBattlegroundTemplate(BattlegroundTypeId bgTypeId); Battleground* GetBattlegroundTemplate(BattlegroundTypeId bgTypeId);
Battleground* CreateNewBattleground(BattlegroundTypeId bgTypeId, uint32 minLevel, uint32 maxLevel, uint8 arenaType, bool isRated); Battleground* CreateNewBattleground(BattlegroundTypeId bgTypeId, PvPDifficultyEntry const* bracketEntry, uint8 arenaType, bool isRated);
void AddBattleground(Battleground* bg); void AddBattleground(Battleground* bg);
void RemoveBattleground(BattlegroundTypeId bgTypeId, uint32 instanceId); void RemoveBattleground(BattlegroundTypeId bgTypeId, uint32 instanceId);
void AddToBGFreeSlotQueue(BattlegroundTypeId bgTypeId, Battleground* bg);
void RemoveFromBGFreeSlotQueue(BattlegroundTypeId bgTypeId, uint32 instanceId);
BGFreeSlotQueueContainer& GetBGFreeSlotQueueStore(BattlegroundTypeId bgTypeId);
void CreateInitialBattlegrounds(); void LoadBattlegroundTemplates();
void DeleteAllBattlegrounds(); void DeleteAllBattlegrounds();
void SendToBattleground(Player* player, uint32 InstanceID, BattlegroundTypeId bgTypeId); void SendToBattleground(Player* player, uint32 InstanceID, BattlegroundTypeId bgTypeId);
/* Battleground queues */ /* Battleground queues */
BattlegroundQueue& GetBattlegroundQueue(BattlegroundQueueTypeId bgQueueTypeId) { return m_BattlegroundQueues[bgQueueTypeId]; } BattlegroundQueue& GetBattlegroundQueue(BattlegroundQueueTypeId bgQueueTypeId) { return m_BattlegroundQueues[bgQueueTypeId]; }
void ScheduleArenaQueueUpdate(uint32 arenaRatedTeamId, BattlegroundQueueTypeId bgQueueTypeId, BattlegroundBracketId bracket_id); void ScheduleQueueUpdate(uint32 arenaMatchmakerRating, uint8 arenaType, BattlegroundQueueTypeId bgQueueTypeId, BattlegroundTypeId bgTypeId, BattlegroundBracketId bracket_id);
uint32 GetPrematureFinishTime() const; uint32 GetPrematureFinishTime() const;
void ToggleArenaTesting(); void ToggleArenaTesting();
@@ -105,10 +118,12 @@ public:
static BattlegroundTypeId WeekendHolidayIdToBGType(HolidayIds holiday); static BattlegroundTypeId WeekendHolidayIdToBGType(HolidayIds holiday);
static bool IsBGWeekend(BattlegroundTypeId bgTypeId); static bool IsBGWeekend(BattlegroundTypeId bgTypeId);
uint32 GetMaxRatingDifference() const;
uint32 GetRatingDiscardTimer() const; uint32 GetRatingDiscardTimer() const;
void InitAutomaticArenaPointDistribution(); void InitAutomaticArenaPointDistribution();
void LoadBattleMastersEntry(); void LoadBattleMastersEntry();
void CheckBattleMasters(); void CheckBattleMasters();
BattlegroundTypeId GetBattleMasterBG(uint32 entry) const BattlegroundTypeId GetBattleMasterBG(uint32 entry) const
{ {
BattleMastersMap::const_iterator itr = mBattleMastersMap.find(entry); BattleMastersMap::const_iterator itr = mBattleMastersMap.find(entry);
@@ -117,8 +132,6 @@ public:
return BATTLEGROUND_TYPE_NONE; return BATTLEGROUND_TYPE_NONE;
} }
const BattlegroundContainer& GetBattlegroundList() { return m_Battlegrounds; } // pussywizard
static std::unordered_map<int, BattlegroundQueueTypeId> bgToQueue; // BattlegroundTypeId -> BattlegroundQueueTypeId static std::unordered_map<int, BattlegroundQueueTypeId> bgToQueue; // BattlegroundTypeId -> BattlegroundQueueTypeId
static std::unordered_map<int, BattlegroundTypeId> queueToBg; // BattlegroundQueueTypeId -> BattlegroundTypeId static std::unordered_map<int, BattlegroundTypeId> queueToBg; // BattlegroundQueueTypeId -> BattlegroundTypeId
static std::unordered_map<int, Battleground*> bgtypeToBattleground; // BattlegroundTypeId -> Battleground* static std::unordered_map<int, Battleground*> bgtypeToBattleground; // BattlegroundTypeId -> Battleground*
@@ -128,48 +141,46 @@ public:
static std::unordered_map<uint32, BattlegroundQueueTypeId> ArenaTypeToQueue; // ArenaType -> BattlegroundQueueTypeId static std::unordered_map<uint32, BattlegroundQueueTypeId> ArenaTypeToQueue; // ArenaType -> BattlegroundQueueTypeId
static std::unordered_map<uint32, ArenaType> QueueToArenaType; // BattlegroundQueueTypeId -> ArenaType static std::unordered_map<uint32, ArenaType> QueueToArenaType; // BattlegroundQueueTypeId -> ArenaType
void DoForAllBattlegrounds(std::function<void(Battleground*)> const& worker);
private: private:
bool CreateBattleground(CreateBattlegroundData& data); bool CreateBattleground(BattlegroundTemplate const* bgTemplate);
uint32 GetNextClientVisibleInstanceId(); uint32 CreateClientVisibleInstanceId(BattlegroundTypeId bgTypeId, BattlegroundBracketId bracket_id);
BattlegroundTypeId GetRandomBG(BattlegroundTypeId id, uint32 minLevel); BattlegroundTypeId GetRandomBG(BattlegroundTypeId id, uint32 minLevel);
typedef std::map<BattlegroundTypeId, Battleground*> BattlegroundTemplateContainer; typedef std::map<BattlegroundTypeId, BattlegroundData> BattlegroundDataContainer;
BattlegroundTemplateContainer m_BattlegroundTemplates; BattlegroundDataContainer bgDataStore;
BattlegroundContainer m_Battlegrounds;
BattlegroundQueue m_BattlegroundQueues[MAX_BATTLEGROUND_QUEUE_TYPES]; BattlegroundQueue m_BattlegroundQueues[MAX_BATTLEGROUND_QUEUE_TYPES];
std::vector<uint64> m_ArenaQueueUpdateScheduler; std::vector<uint64> m_QueueUpdateScheduler;
bool m_ArenaTesting; bool m_ArenaTesting;
bool m_Testing; bool m_Testing;
uint32 m_lastClientVisibleInstanceId;
Seconds m_NextAutoDistributionTime; Seconds m_NextAutoDistributionTime;
uint32 m_AutoDistributionTimeChecker; uint32 m_AutoDistributionTimeChecker;
uint32 m_NextPeriodicQueueUpdateTime; uint32 m_NextPeriodicQueueUpdateTime;
BattleMastersMap mBattleMastersMap; BattleMastersMap mBattleMastersMap;
CreateBattlegroundData const* GetBattlegroundTemplateByTypeId(BattlegroundTypeId id) BattlegroundTemplate const* GetBattlegroundTemplateByTypeId(BattlegroundTypeId id)
{ {
BattlegroundTemplateMap::const_iterator itr = _battlegroundTemplates.find(id); auto const& itr = _battlegroundTemplates.find(id);
if (itr != _battlegroundTemplates.end()) if (itr != _battlegroundTemplates.end())
return &itr->second; return &itr->second;
return nullptr; return nullptr;
} }
CreateBattlegroundData const* GetBattlegroundTemplateByMapId(uint32 mapId) BattlegroundTemplate const* GetBattlegroundTemplateByMapId(uint32 mapId)
{ {
BattlegroundMapTemplateContainer::const_iterator itr = _battlegroundMapTemplates.find(mapId); auto const& itr = _battlegroundMapTemplates.find(mapId);
if (itr != _battlegroundMapTemplates.end()) if (itr != _battlegroundMapTemplates.end())
return itr->second; return itr->second;
return nullptr; return nullptr;
} }
typedef std::map<BattlegroundTypeId, uint8 /*weight*/> BattlegroundSelectionWeightMap; typedef std::map<BattlegroundTypeId, uint8 /*weight*/> BattlegroundSelectionWeightMap;
typedef std::map<BattlegroundTypeId, CreateBattlegroundData> BattlegroundTemplateMap; typedef std::map<BattlegroundTypeId, BattlegroundTemplate> BattlegroundTemplateMap;
typedef std::map<uint32 /*mapId*/, CreateBattlegroundData*> BattlegroundMapTemplateContainer; typedef std::map<uint32 /*mapId*/, BattlegroundTemplate*> BattlegroundMapTemplateContainer;
BattlegroundTemplateMap _battlegroundTemplates; BattlegroundTemplateMap _battlegroundTemplates;
BattlegroundMapTemplateContainer _battlegroundMapTemplates; BattlegroundMapTemplateContainer _battlegroundMapTemplates;
}; };
File diff suppressed because it is too large Load Diff
@@ -25,7 +25,7 @@
#include <array> #include <array>
#include <deque> #include <deque>
#define COUNT_OF_PLAYERS_TO_AVERAGE_WAIT_TIME 10 constexpr auto COUNT_OF_PLAYERS_TO_AVERAGE_WAIT_TIME = 10;
struct GroupQueueInfo // stores information about the group in queue (also used when joined as solo!) struct GroupQueueInfo // stores information about the group in queue (also used when joined as solo!)
{ {
@@ -43,10 +43,9 @@ struct GroupQueueInfo // stores informatio
uint32 ArenaMatchmakerRating; // if rated match, inited to the rating of the team uint32 ArenaMatchmakerRating; // if rated match, inited to the rating of the team
uint32 OpponentsTeamRating; // for rated arena matches uint32 OpponentsTeamRating; // for rated arena matches
uint32 OpponentsMatchmakerRating; // for rated arena matches uint32 OpponentsMatchmakerRating; // for rated arena matches
uint32 PreviousOpponentsTeamId; // excluded from the current queue until the timer is met
// pussywizard: for internal use uint8 BracketId; // BattlegroundBracketId
uint8 _bracketId; uint8 GroupType; // BattlegroundQueueGroupTypes
uint8 _groupType;
}; };
enum BattlegroundQueueGroupTypes enum BattlegroundQueueGroupTypes
@@ -61,22 +60,21 @@ enum BattlegroundQueueGroupTypes
BG_QUEUE_MAX = 10 BG_QUEUE_MAX = 10
}; };
class Battleground;
class BattlegroundQueue class BattlegroundQueue
{ {
public: public:
BattlegroundQueue(); BattlegroundQueue();
~BattlegroundQueue(); ~BattlegroundQueue();
void BattlegroundQueueUpdate(uint32 diff, BattlegroundBracketId bracket_id, bool isRated, uint32 arenaRatedTeamId); void BattlegroundQueueUpdate(uint32 diff, BattlegroundTypeId bgTypeId, BattlegroundBracketId bracket_id, uint8 arenaType, bool isRated, uint32 arenaRating);
void UpdateEvents(uint32 diff); void UpdateEvents(uint32 diff);
void FillPlayersToBG(Battleground* bg, int32 aliFree, int32 hordeFree, BattlegroundBracketId bracket_id); void FillPlayersToBG(Battleground* bg, BattlegroundBracketId bracket_id);
bool CheckPremadeMatch(BattlegroundBracketId bracket_id, uint32 MinPlayersPerTeam, uint32 MaxPlayersPerTeam); bool CheckPremadeMatch(BattlegroundBracketId bracket_id, uint32 MinPlayersPerTeam, uint32 MaxPlayersPerTeam);
bool CheckNormalMatch(Battleground* bgTemplate, BattlegroundBracketId bracket_id, uint32 minPlayers, uint32 maxPlayers); bool CheckNormalMatch(Battleground* bgTemplate, BattlegroundBracketId bracket_id, uint32 minPlayers, uint32 maxPlayers);
bool CheckSkirmishForSameFaction(BattlegroundBracketId bracket_id, uint32 minPlayersPerTeam); bool CheckSkirmishForSameFaction(BattlegroundBracketId bracket_id, uint32 minPlayersPerTeam);
GroupQueueInfo* AddGroup(Player* leader, Group* group, PvPDifficultyEntry const* bracketEntry, bool isRated, bool isPremade, uint32 ArenaRating, uint32 MatchmakerRating, uint32 ArenaTeamId); GroupQueueInfo* AddGroup(Player* leader, Group* group, BattlegroundTypeId bgTypeId, PvPDifficultyEntry const* bracketEntry, uint8 arenaType, bool isRated, bool isPremade, uint32 arenaRating, uint32 matchmakerRating, uint32 arenaTeamId = 0, uint32 opponentsArenaTeamId = 0);
void RemovePlayer(ObjectGuid guid, bool sentToBg, uint32 playerQueueSlot); void RemovePlayer(ObjectGuid guid, bool decreaseInvitedCount);
bool IsPlayerInvitedToRatedArena(ObjectGuid pl_guid); bool IsPlayerInvitedToRatedArena(ObjectGuid pl_guid);
bool IsPlayerInvited(ObjectGuid pl_guid, uint32 bgInstanceGuid, uint32 removeTime); bool IsPlayerInvited(ObjectGuid pl_guid, uint32 bgInstanceGuid, uint32 removeTime);
bool GetPlayerGroupInfoData(ObjectGuid guid, GroupQueueInfo* ginfo); bool GetPlayerGroupInfoData(ObjectGuid guid, GroupQueueInfo* ginfo);
@@ -89,7 +87,6 @@ public:
void SendJoinMessageArenaQueue(Player* leader, GroupQueueInfo* ginfo, PvPDifficultyEntry const* bracketEntry, bool isRated); void SendJoinMessageArenaQueue(Player* leader, GroupQueueInfo* ginfo, PvPDifficultyEntry const* bracketEntry, bool isRated);
void SendExitMessageArenaQueue(GroupQueueInfo* ginfo); void SendExitMessageArenaQueue(GroupQueueInfo* ginfo);
void SetBgTypeIdAndArenaType(BattlegroundTypeId b, uint8 a) { m_bgTypeId = b; m_arenaType = ArenaType(a); } // pussywizard
void AddEvent(BasicEvent* Event, uint64 e_time); void AddEvent(BasicEvent* Event, uint64 e_time);
typedef std::map<ObjectGuid, GroupQueueInfo*> QueuedPlayersMap; typedef std::map<ObjectGuid, GroupQueueInfo*> QueuedPlayersMap;
@@ -127,15 +124,10 @@ public:
//one selection pool for horde, other one for alliance //one selection pool for horde, other one for alliance
SelectionPool m_SelectionPools[PVP_TEAMS_COUNT]; SelectionPool m_SelectionPools[PVP_TEAMS_COUNT];
ArenaType GetArenaType() { return m_arenaType; }
BattlegroundTypeId GetBGTypeID() { return m_bgTypeId; }
void SetQueueAnnouncementTimer(uint32 bracketId, int32 timer, bool isCrossFactionBG = true); void SetQueueAnnouncementTimer(uint32 bracketId, int32 timer, bool isCrossFactionBG = true);
[[nodiscard]] int32 GetQueueAnnouncementTimer(uint32 bracketId) const; [[nodiscard]] int32 GetQueueAnnouncementTimer(uint32 bracketId) const;
private: private:
BattlegroundTypeId m_bgTypeId;
ArenaType m_arenaType;
uint32 m_WaitTimes[PVP_TEAMS_COUNT][MAX_BATTLEGROUND_BRACKETS][COUNT_OF_PLAYERS_TO_AVERAGE_WAIT_TIME]; uint32 m_WaitTimes[PVP_TEAMS_COUNT][MAX_BATTLEGROUND_BRACKETS][COUNT_OF_PLAYERS_TO_AVERAGE_WAIT_TIME];
uint32 m_WaitTimeLastIndex[PVP_TEAMS_COUNT][MAX_BATTLEGROUND_BRACKETS]; uint32 m_WaitTimeLastIndex[PVP_TEAMS_COUNT][MAX_BATTLEGROUND_BRACKETS];
@@ -176,9 +168,8 @@ private:
class BGQueueRemoveEvent : public BasicEvent class BGQueueRemoveEvent : public BasicEvent
{ {
public: public:
BGQueueRemoveEvent(ObjectGuid pl_guid, uint32 bgInstanceGUID, BattlegroundQueueTypeId bgQueueTypeId, uint32 removeTime) BGQueueRemoveEvent(ObjectGuid pl_guid, uint32 bgInstanceGUID, BattlegroundTypeId BgTypeId, BattlegroundQueueTypeId bgQueueTypeId, uint32 removeTime) :
: m_PlayerGuid(pl_guid), m_BgInstanceGUID(bgInstanceGUID), m_RemoveTime(removeTime), m_BgQueueTypeId(bgQueueTypeId) m_PlayerGuid(pl_guid), m_BgInstanceGUID(bgInstanceGUID), m_RemoveTime(removeTime), m_BgTypeId(BgTypeId), m_BgQueueTypeId(bgQueueTypeId) { }
{}
~BGQueueRemoveEvent() override = default; ~BGQueueRemoveEvent() override = default;
@@ -188,6 +179,7 @@ private:
ObjectGuid m_PlayerGuid; ObjectGuid m_PlayerGuid;
uint32 m_BgInstanceGUID; uint32 m_BgInstanceGUID;
uint32 m_RemoveTime; uint32 m_RemoveTime;
BattlegroundTypeId m_BgTypeId;
BattlegroundQueueTypeId m_BgQueueTypeId; BattlegroundQueueTypeId m_BgQueueTypeId;
}; };
+1 -1
View File
@@ -1708,7 +1708,7 @@ namespace lfg
if (bgQueueTypeId != BATTLEGROUND_QUEUE_NONE) if (bgQueueTypeId != BATTLEGROUND_QUEUE_NONE)
{ {
plr->RemoveBattlegroundQueueId(bgQueueTypeId); plr->RemoveBattlegroundQueueId(bgQueueTypeId);
sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId).RemovePlayer(plr->GetGUID(), false, i); sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId).RemovePlayer(plr->GetGUID(), true);
} }
} }
} }
+99 -12
View File
@@ -248,7 +248,10 @@ Player::Player(WorldSession* session): Unit(true), m_mover(this)
m_swingErrorMsg = 0; m_swingErrorMsg = 0;
for (uint8 j = 0; j < PLAYER_MAX_BATTLEGROUND_QUEUES; ++j) for (uint8 j = 0; j < PLAYER_MAX_BATTLEGROUND_QUEUES; ++j)
m_bgBattlegroundQueueID[j] = BATTLEGROUND_QUEUE_NONE; {
_BgBattlegroundQueueID[j].bgQueueTypeId = BATTLEGROUND_QUEUE_NONE;
_BgBattlegroundQueueID[j].invitedToInstance = 0;
}
m_logintime = GameTime::GetGameTime().count(); m_logintime = GameTime::GetGameTime().count();
m_Last_tick = m_logintime; m_Last_tick = m_logintime;
@@ -11025,6 +11028,8 @@ void Player::LeaveBattleground(Battleground* bg)
sScriptMgr->OnBattlegroundDesertion(this, BG_DESERTION_TYPE_LEAVE_BG); sScriptMgr->OnBattlegroundDesertion(this, BG_DESERTION_TYPE_LEAVE_BG);
} }
bg->RemovePlayerAtLeave(this);
// xinef: reset corpse reclaim time // xinef: reset corpse reclaim time
m_deathExpireTime = GameTime::GetGameTime().count(); m_deathExpireTime = GameTime::GetGameTime().count();
@@ -11853,10 +11858,102 @@ Battleground* Player::GetBattleground(bool create) const
if (GetBattlegroundId() == 0) if (GetBattlegroundId() == 0)
return nullptr; return nullptr;
Battleground* bg = sBattlegroundMgr->GetBattleground(GetBattlegroundId()); Battleground* bg = sBattlegroundMgr->GetBattleground(GetBattlegroundId(), GetBattlegroundTypeId());
return (create || (bg && bg->FindBgMap()) ? bg : nullptr); return (create || (bg && bg->FindBgMap()) ? bg : nullptr);
} }
bool Player::InBattlegroundQueue(bool ignoreArena) const
{
for (uint8 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; ++i)
if (_BgBattlegroundQueueID[i].bgQueueTypeId != BATTLEGROUND_QUEUE_NONE &&
(!ignoreArena || (_BgBattlegroundQueueID[i].bgQueueTypeId != BATTLEGROUND_QUEUE_2v2 &&
_BgBattlegroundQueueID[i].bgQueueTypeId != BATTLEGROUND_QUEUE_3v3 &&
_BgBattlegroundQueueID[i].bgQueueTypeId != BATTLEGROUND_QUEUE_5v5)))
return true;
return false;
}
BattlegroundQueueTypeId Player::GetBattlegroundQueueTypeId(uint32 index) const
{
return _BgBattlegroundQueueID[index].bgQueueTypeId;
}
uint32 Player::GetBattlegroundQueueIndex(BattlegroundQueueTypeId bgQueueTypeId) const
{
for (uint8 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; ++i)
if (_BgBattlegroundQueueID[i].bgQueueTypeId == bgQueueTypeId)
return i;
return PLAYER_MAX_BATTLEGROUND_QUEUES;
}
bool Player::IsInvitedForBattlegroundQueueType(BattlegroundQueueTypeId bgQueueTypeId) const
{
for (uint8 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; ++i)
if (_BgBattlegroundQueueID[i].bgQueueTypeId == bgQueueTypeId)
return _BgBattlegroundQueueID[i].invitedToInstance != 0;
return false;
}
bool Player::InBattlegroundQueueForBattlegroundQueueType(BattlegroundQueueTypeId bgQueueTypeId) const
{
return GetBattlegroundQueueIndex(bgQueueTypeId) < PLAYER_MAX_BATTLEGROUND_QUEUES;
}
uint32 Player::AddBattlegroundQueueId(BattlegroundQueueTypeId val)
{
for (uint8 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; ++i)
{
if (_BgBattlegroundQueueID[i].bgQueueTypeId == BATTLEGROUND_QUEUE_NONE || _BgBattlegroundQueueID[i].bgQueueTypeId == val)
{
_BgBattlegroundQueueID[i].bgQueueTypeId = val;
_BgBattlegroundQueueID[i].invitedToInstance = 0;
return i;
}
}
return PLAYER_MAX_BATTLEGROUND_QUEUES;
}
bool Player::HasFreeBattlegroundQueueId() const
{
for (uint8 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; ++i)
if (_BgBattlegroundQueueID[i].bgQueueTypeId == BATTLEGROUND_QUEUE_NONE)
return true;
return false;
}
void Player::RemoveBattlegroundQueueId(BattlegroundQueueTypeId val)
{
for (uint8 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; ++i)
{
if (_BgBattlegroundQueueID[i].bgQueueTypeId == val)
{
_BgBattlegroundQueueID[i].bgQueueTypeId = BATTLEGROUND_QUEUE_NONE;
_BgBattlegroundQueueID[i].invitedToInstance = 0;
return;
}
}
}
void Player::SetInviteForBattlegroundQueueType(BattlegroundQueueTypeId bgQueueTypeId, uint32 instanceId)
{
for (uint8 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; ++i)
if (_BgBattlegroundQueueID[i].bgQueueTypeId == bgQueueTypeId)
_BgBattlegroundQueueID[i].invitedToInstance = instanceId;
}
bool Player::IsInvitedForBattlegroundInstance(uint32 instanceId) const
{
for (uint8 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; ++i)
if (_BgBattlegroundQueueID[i].invitedToInstance == instanceId)
return true;
return false;
}
bool Player::InArena() const bool Player::InArena() const
{ {
Battleground* bg = GetBattleground(); Battleground* bg = GetBattleground();
@@ -11868,16 +11965,6 @@ bool Player::InArena() const
void Player::SetBattlegroundId(uint32 id, BattlegroundTypeId bgTypeId, uint32 queueSlot, bool invited, bool isRandom, TeamId teamId) void Player::SetBattlegroundId(uint32 id, BattlegroundTypeId bgTypeId, uint32 queueSlot, bool invited, bool isRandom, TeamId teamId)
{ {
// if leaving current bg (and was invited) - decrease invited count for current one
if (m_bgData.bgInstanceID && m_bgData.isInvited)
if (Battleground* bg = sBattlegroundMgr->GetBattleground(m_bgData.bgInstanceID))
bg->DecreaseInvitedCount(m_bgData.bgTeamId);
// if entering new bg (and is invited) - increase invited count for new one
if (id && invited)
if (Battleground* bg = sBattlegroundMgr->GetBattleground(id))
bg->IncreaseInvitedCount(teamId);
m_bgData.bgInstanceID = id; m_bgData.bgInstanceID = id;
m_bgData.bgTypeID = bgTypeId; m_bgData.bgTypeID = bgTypeId;
m_bgData.bgQueueSlot = queueSlot; m_bgData.bgQueueSlot = queueSlot;
+18 -51
View File
@@ -2188,59 +2188,20 @@ public:
void SetBGData(BGData& bgdata) { m_bgData = bgdata; } void SetBGData(BGData& bgdata) { m_bgData = bgdata; }
[[nodiscard]] Battleground* GetBattleground(bool create = false) const; [[nodiscard]] Battleground* GetBattleground(bool create = false) const;
[[nodiscard]] bool InBattlegroundQueue() const [[nodiscard]] bool InBattlegroundQueue(bool ignoreArena = false) const;
{ [[nodiscard]] bool IsDeserter() const { return HasAura(26013); }
for (auto i : m_bgBattlegroundQueueID)
if (i != BATTLEGROUND_QUEUE_NONE)
return true;
return false;
}
[[nodiscard]] BattlegroundQueueTypeId GetBattlegroundQueueTypeId(uint32 index) const { return m_bgBattlegroundQueueID[index]; } [[nodiscard]] BattlegroundQueueTypeId GetBattlegroundQueueTypeId(uint32 index) const;
[[nodiscard]] uint32 GetBattlegroundQueueIndex(BattlegroundQueueTypeId bgQueueTypeId) const;
[[nodiscard]] uint32 GetBattlegroundQueueIndex(BattlegroundQueueTypeId bgQueueTypeId) const [[nodiscard]] bool IsInvitedForBattlegroundQueueType(BattlegroundQueueTypeId bgQueueTypeId) const;
{ [[nodiscard]] bool InBattlegroundQueueForBattlegroundQueueType(BattlegroundQueueTypeId bgQueueTypeId) const;
for (uint8 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; ++i)
if (m_bgBattlegroundQueueID[i] == bgQueueTypeId)
return i;
return PLAYER_MAX_BATTLEGROUND_QUEUES;
}
[[nodiscard]] bool InBattlegroundQueueForBattlegroundQueueType(BattlegroundQueueTypeId bgQueueTypeId) const
{
return GetBattlegroundQueueIndex(bgQueueTypeId) < PLAYER_MAX_BATTLEGROUND_QUEUES;
}
void SetBattlegroundId(uint32 id, BattlegroundTypeId bgTypeId, uint32 queueSlot, bool invited, bool isRandom, TeamId teamId); void SetBattlegroundId(uint32 id, BattlegroundTypeId bgTypeId, uint32 queueSlot, bool invited, bool isRandom, TeamId teamId);
uint32 AddBattlegroundQueueId(BattlegroundQueueTypeId val);
uint32 AddBattlegroundQueueId(BattlegroundQueueTypeId val) bool HasFreeBattlegroundQueueId() const;
{ void RemoveBattlegroundQueueId(BattlegroundQueueTypeId val);
for (uint8 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; ++i) void SetInviteForBattlegroundQueueType(BattlegroundQueueTypeId bgQueueTypeId, uint32 instanceId);
if (m_bgBattlegroundQueueID[i] == BATTLEGROUND_QUEUE_NONE || m_bgBattlegroundQueueID[i] == val) bool IsInvitedForBattlegroundInstance(uint32 instanceId) const;
{
m_bgBattlegroundQueueID[i] = val;
return i;
}
return PLAYER_MAX_BATTLEGROUND_QUEUES;
}
bool HasFreeBattlegroundQueueId()
{
for (auto & i : m_bgBattlegroundQueueID)
if (i == BATTLEGROUND_QUEUE_NONE)
return true;
return false;
}
void RemoveBattlegroundQueueId(BattlegroundQueueTypeId val)
{
for (auto & i : m_bgBattlegroundQueueID)
if (i == val)
{
i = BATTLEGROUND_QUEUE_NONE;
return;
}
}
[[nodiscard]] TeamId GetBgTeamId() const { return m_bgData.bgTeamId != TEAM_NEUTRAL ? m_bgData.bgTeamId : GetTeamId(); } [[nodiscard]] TeamId GetBgTeamId() const { return m_bgData.bgTeamId != TEAM_NEUTRAL ? m_bgData.bgTeamId : GetTeamId(); }
@@ -2601,7 +2562,13 @@ public:
/*** BATTLEGROUND SYSTEM ***/ /*** BATTLEGROUND SYSTEM ***/
/*********************************************************/ /*********************************************************/
BattlegroundQueueTypeId m_bgBattlegroundQueueID[PLAYER_MAX_BATTLEGROUND_QUEUES]; struct BgBattlegroundQueueID_Rec
{
BattlegroundQueueTypeId bgQueueTypeId;
uint32 invitedToInstance;
};
std::array<BgBattlegroundQueueID_Rec, PLAYER_MAX_BATTLEGROUND_QUEUES> _BgBattlegroundQueueID;
BGData m_bgData; BGData m_bgData;
bool m_IsBGRandomWinner; bool m_IsBGRandomWinner;
+17
View File
@@ -2189,6 +2189,11 @@ ObjectGuid Group::GetLeaderGUID() const
return m_leaderGuid; return m_leaderGuid;
} }
Player* Group::GetLeader()
{
return ObjectAccessor::FindConnectedPlayer(m_leaderGuid);
}
ObjectGuid Group::GetGUID() const ObjectGuid Group::GetGUID() const
{ {
return m_guid; return m_guid;
@@ -2425,3 +2430,15 @@ void Group::SetDifficultyChangePrevention(DifficultyPreventionChangeType type)
_difficultyChangePreventionTime = GameTime::GetGameTime().count() + MINUTE; _difficultyChangePreventionTime = GameTime::GetGameTime().count() + MINUTE;
_difficultyChangePreventionType = type; _difficultyChangePreventionType = type;
} }
void Group::DoForAllMembers(std::function<void(Player*)> const& worker)
{
for (GroupReference* itr = GetFirstMember(); itr != nullptr; itr = itr->next())
{
Player* member = itr->GetSource();
if (!member)
continue;
worker(member);
}
}
+4
View File
@@ -23,6 +23,7 @@
#include "LootMgr.h" #include "LootMgr.h"
#include "QueryResult.h" #include "QueryResult.h"
#include "SharedDefines.h" #include "SharedDefines.h"
#include <functional>
class Battlefield; class Battlefield;
class Battleground; class Battleground;
@@ -214,6 +215,7 @@ public:
bool isBGGroup() const; bool isBGGroup() const;
bool IsCreated() const; bool IsCreated() const;
ObjectGuid GetLeaderGUID() const; ObjectGuid GetLeaderGUID() const;
Player* GetLeader();
ObjectGuid GetGUID() const; ObjectGuid GetGUID() const;
const char* GetLeaderName() const; const char* GetLeaderName() const;
LootMethod GetLootMethod() const; LootMethod GetLootMethod() const;
@@ -313,6 +315,8 @@ public:
DifficultyPreventionChangeType GetDifficultyChangePreventionReason() const { return _difficultyChangePreventionType; } DifficultyPreventionChangeType GetDifficultyChangePreventionReason() const { return _difficultyChangePreventionType; }
void SetDifficultyChangePrevention(DifficultyPreventionChangeType type); void SetDifficultyChangePrevention(DifficultyPreventionChangeType type);
void DoForAllMembers(std::function<void(Player*)> const& worker);
protected: protected:
void _homebindIfInstance(Player* player); void _homebindIfInstance(Player* player);
void _cancelHomebindIfInstance(Player* player); void _cancelHomebindIfInstance(Player* player);
+173 -149
View File
@@ -72,8 +72,9 @@ void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket& recvData)
{ {
ObjectGuid guid; ObjectGuid guid;
uint32 bgTypeId_; uint32 bgTypeId_;
uint32 instanceId; // sent to queue for particular bg from battlemaster's list, currently not used uint32 instanceId;
uint8 joinAsGroup; uint8 joinAsGroup;
bool isPremade = false;
recvData >> guid; // battlemaster guid recvData >> guid; // battlemaster guid
recvData >> bgTypeId_; // battleground type id (DBC id) recvData >> bgTypeId_; // battleground type id (DBC id)
@@ -82,7 +83,10 @@ void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket& recvData)
// entry not found // entry not found
if (!sBattlemasterListStore.LookupEntry(bgTypeId_)) if (!sBattlemasterListStore.LookupEntry(bgTypeId_))
{
LOG_ERROR("network", "Battleground: invalid bgtype ({}) received. possible cheater? player {}", bgTypeId_, _player->GetGUID().ToString());
return; return;
}
// chosen battleground type is disabled // chosen battleground type is disabled
if (DisableMgr::IsDisabledFor(DISABLE_TYPE_BATTLEGROUND, bgTypeId_, nullptr)) if (DisableMgr::IsDisabledFor(DISABLE_TYPE_BATTLEGROUND, bgTypeId_, nullptr))
@@ -91,6 +95,8 @@ void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket& recvData)
return; return;
} }
LOG_DEBUG("network", "WORLD: Recvd CMSG_BATTLEMASTER_JOIN Message from {}", guid.ToString());
// get queue typeid and random typeid to check if already queued for them // get queue typeid and random typeid to check if already queued for them
BattlegroundTypeId bgTypeId = BattlegroundTypeId(bgTypeId_); BattlegroundTypeId bgTypeId = BattlegroundTypeId(bgTypeId_);
BattlegroundQueueTypeId bgQueueTypeId = BattlegroundMgr::BGQueueTypeId(bgTypeId, 0); BattlegroundQueueTypeId bgQueueTypeId = BattlegroundMgr::BGQueueTypeId(bgTypeId, 0);
@@ -100,35 +106,26 @@ void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket& recvData)
if (bgQueueTypeId == BATTLEGROUND_QUEUE_NONE) if (bgQueueTypeId == BATTLEGROUND_QUEUE_NONE)
return; return;
// get bg template // ignore if player is already in BG
Battleground* bgt = sBattlegroundMgr->GetBattlegroundTemplate(bgTypeId); if (_player->InBattleground())
if (!bgt) return;
// get bg instance or bg template if instance not found
Battleground* bg = nullptr;
if (instanceId)
bg = sBattlegroundMgr->GetBattlegroundThroughClientInstance(instanceId, bgTypeId);
if (!bg)
bg = sBattlegroundMgr->GetBattlegroundTemplate(bgTypeId);
if (!bg)
return; return;
// expected bracket entry // expected bracket entry
PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketByLevel(bgt->GetMapId(), _player->getLevel()); PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketByLevel(bg->GetMapId(), _player->getLevel());
if (!bracketEntry) if (!bracketEntry)
return; return;
// pussywizard: if trying to queue for already queued
// just remove from queue and it will requeue!
uint32 qSlot = _player->GetBattlegroundQueueIndex(bgQueueTypeId);
if (qSlot < PLAYER_MAX_BATTLEGROUND_QUEUES)
{
BattlegroundQueue& bgQueue = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId);
if (bgQueue.IsPlayerInvitedToRatedArena(_player->GetGUID()))
{
WorldPacket data;
sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, ERR_BATTLEGROUND_JOIN_FAILED);
SendPacket(&data);
return;
}
bgQueue.RemovePlayer(_player->GetGUID(), false, qSlot);
_player->RemoveBattlegroundQueueId(bgQueueTypeId);
}
// must have free queue slot // must have free queue slot
if (!_player->HasFreeBattlegroundQueueId()) if (!_player->HasFreeBattlegroundQueueId())
{ {
@@ -139,7 +136,7 @@ void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket& recvData)
} }
// queue result (default ok) // queue result (default ok)
GroupJoinBattlegroundResult err = GroupJoinBattlegroundResult(bgt->GetBgTypeID()); GroupJoinBattlegroundResult err = GroupJoinBattlegroundResult(bg->GetBgTypeID());
if (!sScriptMgr->CanJoinInBattlegroundQueue(_player, guid, bgTypeId, joinAsGroup, err) && err <= 0) if (!sScriptMgr->CanJoinInBattlegroundQueue(_player, guid, bgTypeId, joinAsGroup, err) && err <= 0)
{ {
@@ -149,6 +146,8 @@ void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket& recvData)
return; return;
} }
BattlegroundQueue& bgQueue = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId);
// check if player can queue: // check if player can queue:
if (!joinAsGroup) if (!joinAsGroup)
{ {
@@ -169,6 +168,10 @@ void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket& recvData)
{ {
err = ERR_IN_RANDOM_BG; err = ERR_IN_RANDOM_BG;
} }
else if (_player->InBattlegroundQueueForBattlegroundQueueType(bgQueueTypeId)) // queued for this bg
{
err = ERR_BATTLEGROUND_NONE;
}
else if (_player->InBattlegroundQueue() && bgTypeId == BATTLEGROUND_RB) // already in queue, so can't queue for random else if (_player->InBattlegroundQueue() && bgTypeId == BATTLEGROUND_RB) // already in queue, so can't queue for random
{ {
err = ERR_IN_NON_RANDOM_BG; err = ERR_IN_NON_RANDOM_BG;
@@ -193,15 +196,13 @@ void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket& recvData)
return; return;
} }
BattlegroundQueue& bgQueue = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId); GroupQueueInfo* ginfo = bgQueue.AddGroup(_player, nullptr, bgTypeId, bracketEntry, 0, false, isPremade, 0, 0);
GroupQueueInfo* ginfo = bgQueue.AddGroup(_player, nullptr, bracketEntry, false, false, 0, 0, 0);
uint32 avgWaitTime = bgQueue.GetAverageQueueWaitTime(ginfo); uint32 avgWaitTime = bgQueue.GetAverageQueueWaitTime(ginfo);
uint32 queueSlot = _player->AddBattlegroundQueueId(bgQueueTypeId); uint32 queueSlot = _player->AddBattlegroundQueueId(bgQueueTypeId);
// send status packet // send status packet
WorldPacket data; WorldPacket data;
sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bgt, queueSlot, STATUS_WAIT_QUEUE, avgWaitTime, 0, 0, TEAM_NEUTRAL); sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgWaitTime, 0, 0, TEAM_NEUTRAL);
SendPacket(&data); SendPacket(&data);
sScriptMgr->OnPlayerJoinBG(_player); sScriptMgr->OnPlayerJoinBG(_player);
@@ -214,30 +215,6 @@ void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket& recvData)
if (!grp || grp->GetLeaderGUID() != _player->GetGUID()) if (!grp || grp->GetLeaderGUID() != _player->GetGUID())
return; return;
// pussywizard: for party members - remove queues for which leader is not queued to!
std::set<uint32> leaderQueueTypeIds;
for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; ++i)
leaderQueueTypeIds.insert((uint32)_player->GetBattlegroundQueueTypeId(i));
for (GroupReference* itr = grp->GetFirstMember(); itr != nullptr; itr = itr->next())
if (Player* member = itr->GetSource())
for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; ++i)
if (BattlegroundQueueTypeId mqtid = member->GetBattlegroundQueueTypeId(i))
if (leaderQueueTypeIds.count((uint32)mqtid) == 0)
{
BattlegroundQueue& bgQueue = sBattlegroundMgr->GetBattlegroundQueue(mqtid);
if (bgQueue.IsPlayerInvitedToRatedArena(member->GetGUID()))
{
WorldPacket data;
sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, ERR_BATTLEGROUND_JOIN_FAILED);
SendPacket(&data);
return;
}
bgQueue.RemovePlayer(member->GetGUID(), false, i);
member->RemoveBattlegroundQueueId(mqtid);
}
if (_player->InBattlegroundQueueForBattlegroundQueueType(bgQueueTypeIdRandom)) // queued for random bg, so can't queue for anything else if (_player->InBattlegroundQueueForBattlegroundQueueType(bgQueueTypeIdRandom)) // queued for random bg, so can't queue for anything else
err = ERR_IN_RANDOM_BG; err = ERR_IN_RANDOM_BG;
else if (_player->InBattlegroundQueue() && bgTypeId == BATTLEGROUND_RB) // already in queue, so can't queue for random else if (_player->InBattlegroundQueue() && bgTypeId == BATTLEGROUND_RB) // already in queue, so can't queue for random
@@ -248,44 +225,42 @@ void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket& recvData)
err = ERR_BATTLEGROUND_QUEUED_FOR_RATED; err = ERR_BATTLEGROUND_QUEUED_FOR_RATED;
if (err > 0) if (err > 0)
err = grp->CanJoinBattlegroundQueue(bgt, bgQueueTypeId, 0, bgt->GetMaxPlayersPerTeam(), false, 0); err = grp->CanJoinBattlegroundQueue(bg, bgQueueTypeId, 0, bg->GetMaxPlayersPerTeam(), false, 0);
bool isPremade = (grp->GetMembersCount() >= bgt->GetMinPlayersPerTeam() && bgTypeId != BATTLEGROUND_RB); isPremade = (grp->GetMembersCount() >= bg->GetMinPlayersPerTeam() && bgTypeId != BATTLEGROUND_RB);
uint32 avgWaitTime = 0; uint32 avgWaitTime = 0;
if (err > 0) if (err > 0)
{ {
BattlegroundQueue& bgQueue = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId); GroupQueueInfo* ginfo = bgQueue.AddGroup(_player, grp, bgTypeId, bracketEntry, 0, false, isPremade, 0, 0);
GroupQueueInfo* ginfo = bgQueue.AddGroup(_player, grp, bracketEntry, false, isPremade, 0, 0, 0);
avgWaitTime = bgQueue.GetAverageQueueWaitTime(ginfo); avgWaitTime = bgQueue.GetAverageQueueWaitTime(ginfo);
} }
WorldPacket data; grp->DoForAllMembers([bg, err, bgQueueTypeId, avgWaitTime](Player* member)
for (GroupReference* itr = grp->GetFirstMember(); itr != nullptr; itr = itr->next())
{ {
Player* member = itr->GetSource(); WorldPacket data;
if (!member)
continue;
if (err <= 0) if (err <= 0)
{ {
sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, err); sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, err);
member->GetSession()->SendPacket(&data); member->GetSession()->SendPacket(&data);
continue; return;
} }
uint32 queueSlot = member->AddBattlegroundQueueId(bgQueueTypeId); uint32 queueSlot = member->AddBattlegroundQueueId(bgQueueTypeId);
// send status packet // send status packet
sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bgt, queueSlot, STATUS_WAIT_QUEUE, avgWaitTime, 0, 0, TEAM_NEUTRAL); sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgWaitTime, 0, 0, TEAM_NEUTRAL);
member->GetSession()->SendPacket(&data); member->GetSession()->SendPacket(&data);
sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, err); sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, err);
member->GetSession()->SendPacket(&data); member->GetSession()->SendPacket(&data);
sScriptMgr->OnPlayerJoinBG(member); sScriptMgr->OnPlayerJoinBG(member);
});
} }
}
sBattlegroundMgr->ScheduleQueueUpdate(0, 0, bgQueueTypeId, bgTypeId, bracketEntry->GetBracketId());
} }
void WorldSession::HandleBattlegroundPlayerPositionsOpcode(WorldPacket& /*recvData*/) void WorldSession::HandleBattlegroundPlayerPositionsOpcode(WorldPacket& /*recvData*/)
@@ -373,7 +348,10 @@ void WorldSession::HandleBattlefieldListOpcode(WorldPacket& recvData)
BattlemasterListEntry const* bl = sBattlemasterListStore.LookupEntry(bgTypeId); BattlemasterListEntry const* bl = sBattlemasterListStore.LookupEntry(bgTypeId);
if (!bl) if (!bl)
{
LOG_DEBUG("bg.battleground", "BattlegroundHandler: invalid bgtype ({}) with player (Name: {}, {}) received.", bgTypeId, _player->GetName(), _player->GetGUID().ToString());
return; return;
}
WorldPacket data; WorldPacket data;
sBattlegroundMgr->BuildBattlegroundListPacket(&data, ObjectGuid::Empty, _player, BattlegroundTypeId(bgTypeId), fromWhere); sBattlegroundMgr->BuildBattlegroundListPacket(&data, ObjectGuid::Empty, _player, BattlegroundTypeId(bgTypeId), fromWhere);
@@ -392,11 +370,17 @@ void WorldSession::HandleBattleFieldPortOpcode(WorldPacket& recvData)
// bgTypeId not valid // bgTypeId not valid
if (!sBattlemasterListStore.LookupEntry(bgTypeId_)) if (!sBattlemasterListStore.LookupEntry(bgTypeId_))
{
LOG_DEBUG("bg.battleground", "CMSG_BATTLEFIELD_PORT {} ArenaType: {}, Unk: {}, BgType: {}, Action: {}. Invalid BgType!", GetPlayerInfo(), arenaType, unk2, bgTypeId_, action);
return; return;
}
// player not in any queue, so can't really answer // player not in any queue, so can't really answer
if (!_player->InBattlegroundQueue()) if (!_player->InBattlegroundQueue())
{
LOG_DEBUG("bg.battleground", "CMSG_BATTLEFIELD_PORT {} ArenaType: {}, Unk: {}, BgType: {}, Action: {}. Player not in queue!", GetPlayerInfo(), arenaType, unk2, bgTypeId_, action);
return; return;
}
// get BattlegroundQueue for received // get BattlegroundQueue for received
BattlegroundTypeId bgTypeId = BattlegroundTypeId(bgTypeId_); BattlegroundTypeId bgTypeId = BattlegroundTypeId(bgTypeId_);
@@ -409,20 +393,40 @@ void WorldSession::HandleBattleFieldPortOpcode(WorldPacket& recvData)
// get group info from queue // get group info from queue
GroupQueueInfo ginfo; GroupQueueInfo ginfo;
if (!bgQueue.GetPlayerGroupInfoData(_player->GetGUID(), &ginfo)) if (!bgQueue.GetPlayerGroupInfoData(_player->GetGUID(), &ginfo))
{
LOG_DEBUG("bg.battleground", "CMSG_BATTLEFIELD_PORT {} ArenaType: {}, Unk: {}, BgType: {}, Action: {}. Player not in queue (No player Group Info)!",
GetPlayerInfo(), arenaType, unk2, bgTypeId_, action);
return; return;
}
// to accept, player must be invited to particular battleground id // to accept, player must be invited to particular battleground id
if (!ginfo.IsInvitedToBGInstanceGUID && action == 1) if (!ginfo.IsInvitedToBGInstanceGUID && action == 1)
{
LOG_DEBUG("bg.battleground", "CMSG_BATTLEFIELD_PORT {} ArenaType: {}, Unk: {}, BgType: {}, Action: {}. Player is not invited to any bg!",
GetPlayerInfo(), arenaType, unk2, bgTypeId_, action);
return; return;
}
Battleground* bg = sBattlegroundMgr->GetBattleground(ginfo.IsInvitedToBGInstanceGUID); Battleground* bg = sBattlegroundMgr->GetBattleground(ginfo.IsInvitedToBGInstanceGUID, bgTypeId);
// use template if leaving queue (instance might not be created yet)
if (!bg && action == 0)
bg = sBattlegroundMgr->GetBattlegroundTemplate(bgTypeId);
if (!bg) if (!bg)
{
if (action)
{
LOG_DEBUG("bg.battleground", "CMSG_BATTLEFIELD_PORT {} ArenaType: {}, Unk: {}, BgType: {}, Action: {}. Cant find BG with id {}!",
GetPlayerInfo(), arenaType, unk2, bgTypeId_, action, ginfo.IsInvitedToBGInstanceGUID);
return; return;
}
bg = sBattlegroundMgr->GetBattlegroundTemplate(bgTypeId);
if (!bg)
{
LOG_ERROR("network", "BattlegroundHandler: bg_template not found for type id {}.", bgTypeId);
return;
}
}
LOG_DEBUG("bg.battleground", "CMSG_BATTLEFIELD_PORT {} ArenaType: {}, Unk: {}, BgType: {}, Action: {}.",
GetPlayerInfo(), arenaType, unk2, bgTypeId_, action);
// expected bracket entry // expected bracket entry
PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketByLevel(bg->GetMapId(), _player->getLevel()); PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketByLevel(bg->GetMapId(), _player->getLevel());
@@ -439,20 +443,30 @@ void WorldSession::HandleBattleFieldPortOpcode(WorldPacket& recvData)
sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, ERR_GROUP_JOIN_BATTLEGROUND_DESERTERS); sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, ERR_GROUP_JOIN_BATTLEGROUND_DESERTERS);
SendPacket(&data); SendPacket(&data);
action = 0; action = 0;
LOG_DEBUG("bg.battleground", "Player {} {} has a deserter debuff, do not port him to battleground!", _player->GetName(), _player->GetGUID().ToString());
} }
if (_player->getLevel() > bg->GetMaxLevel()) if (_player->getLevel() > bg->GetMaxLevel())
{
LOG_ERROR("network", "Player {} {} has level ({}) higher than maxlevel ({}) of battleground ({})! Do not port him to battleground!",
_player->GetName(), _player->GetGUID().ToString(), _player->getLevel(), bg->GetMaxLevel(), bg->GetBgTypeID());
action = 0; action = 0;
} }
}
// get player queue slot index for this bg (can be in up to 2 queues at the same time) // get player queue slot index for this bg (can be in up to 2 queues at the same time)
uint32 queueSlot = _player->GetBattlegroundQueueIndex(bgQueueTypeId); uint32 queueSlot = _player->GetBattlegroundQueueIndex(bgQueueTypeId);
WorldPacket data; WorldPacket data;
switch (action)
{ if (action) // accept
case 1: // accept
{ {
// check Freeze debuff
if (_player->HasAura(9454))
return;
if (!_player->IsInvitedForBattlegroundQueueType(bgQueueTypeId))
return; // cheating?
// set entry point if not in battleground // set entry point if not in battleground
if (!_player->InBattleground()) if (!_player->InBattleground())
_player->SetEntryPoint(); _player->SetEntryPoint();
@@ -466,30 +480,40 @@ void WorldSession::HandleBattleFieldPortOpcode(WorldPacket& recvData)
TeamId teamId = ginfo.teamId; TeamId teamId = ginfo.teamId;
// remove player from all bg queues
for (uint32 qslot = 0; qslot < PLAYER_MAX_BATTLEGROUND_QUEUES; ++qslot)
if (BattlegroundQueueTypeId q = _player->GetBattlegroundQueueTypeId(qslot))
{
BattlegroundQueue& queue = sBattlegroundMgr->GetBattlegroundQueue(q);
queue.RemovePlayer(_player->GetGUID(), (bgQueueTypeId == q), qslot);
_player->RemoveBattlegroundQueueId(q);
}
// send status packet // send status packet
sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, queueSlot, STATUS_IN_PROGRESS, 0, bg->GetStartTime(), bg->GetArenaType(), teamId); sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, queueSlot, STATUS_IN_PROGRESS, 0, bg->GetStartTime(), bg->GetArenaType(), teamId);
SendPacket(&data); SendPacket(&data);
// remove battleground queue status from BGmgr
bgQueue.RemovePlayer(_player->GetGUID(), false);
// this is still needed here if battleground "jumping" shouldn't add deserter debuff
// also this is required to prevent stuck at old battleground after SetBattlegroundId set to new
if (Battleground* currentBg = _player->GetBattleground())
currentBg->RemovePlayerAtLeave(_player);
// Remove from LFG queues // Remove from LFG queues
sLFGMgr->LeaveAllLfgQueues(_player->GetGUID(), false); sLFGMgr->LeaveAllLfgQueues(_player->GetGUID(), false);
_player->SetBattlegroundId(bg->GetInstanceID(), bg->GetBgTypeID(), queueSlot, true, bgTypeId == BATTLEGROUND_RB, teamId); _player->SetBattlegroundId(bg->GetInstanceID(), bg->GetBgTypeID(), queueSlot, true, bgTypeId == BATTLEGROUND_RB, teamId);
sBattlegroundMgr->SendToBattleground(_player, ginfo.IsInvitedToBGInstanceGUID, bgTypeId); sBattlegroundMgr->SendToBattleground(_player, ginfo.IsInvitedToBGInstanceGUID, bgTypeId);
LOG_DEBUG("bg.battleground", "Battleground: player {} {} joined battle for bg {}, bgtype {}, queue type {}.", _player->GetName(), _player->GetGUID().ToString(), bg->GetInstanceID(), bg->GetBgTypeID(), bgQueueTypeId);
} }
break; else // leave queue
case 0: // leave queue
{ {
bgQueue.RemovePlayer(_player->GetGUID(), false, queueSlot); bgQueue.RemovePlayer(_player->GetGUID(), true);
_player->RemoveBattlegroundQueueId(bgQueueTypeId); _player->RemoveBattlegroundQueueId(bgQueueTypeId);
sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, queueSlot, STATUS_NONE, 0, 0, 0, TEAM_NEUTRAL);
SendPacket(&data);
LOG_DEBUG("bg.battleground", "Battleground: player {} {} left queue for bgtype {}, queue type {}.", _player->GetName(), _player->GetGUID().ToString(), bg->GetBgTypeID(), bgQueueTypeId);
// 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());
// track if player refuses to join the BG after being invited // track if player refuses to join the BG after being invited
if (bg->isBattleground() && (bg->GetStatus() == STATUS_IN_PROGRESS || bg->GetStatus() == STATUS_WAIT_JOIN)) if (bg->isBattleground() && (bg->GetStatus() == STATUS_IN_PROGRESS || bg->GetStatus() == STATUS_WAIT_JOIN))
{ {
@@ -504,10 +528,6 @@ void WorldSession::HandleBattleFieldPortOpcode(WorldPacket& recvData)
sScriptMgr->OnBattlegroundDesertion(_player, BG_DESERTION_TYPE_LEAVE_QUEUE); sScriptMgr->OnBattlegroundDesertion(_player, BG_DESERTION_TYPE_LEAVE_QUEUE);
} }
} }
break;
default:
break;
}
} }
void WorldSession::HandleBattlefieldLeaveOpcode(WorldPacket& recvData) void WorldSession::HandleBattlefieldLeaveOpcode(WorldPacket& recvData)
@@ -562,7 +582,7 @@ void WorldSession::HandleBattlefieldStatusOpcode(WorldPacket& /*recvData*/)
// if invited - send STATUS_WAIT_JOIN // if invited - send STATUS_WAIT_JOIN
if (ginfo.IsInvitedToBGInstanceGUID) if (ginfo.IsInvitedToBGInstanceGUID)
{ {
Battleground* bg = sBattlegroundMgr->GetBattleground(ginfo.IsInvitedToBGInstanceGUID); Battleground* bg = sBattlegroundMgr->GetBattleground(ginfo.IsInvitedToBGInstanceGUID, bgTypeId);
if (!bg) if (!bg)
continue; continue;
@@ -591,6 +611,8 @@ void WorldSession::HandleBattlefieldStatusOpcode(WorldPacket& /*recvData*/)
void WorldSession::HandleBattlemasterJoinArena(WorldPacket& recvData) void WorldSession::HandleBattlemasterJoinArena(WorldPacket& recvData)
{ {
LOG_DEBUG("network", "WORLD: CMSG_BATTLEMASTER_JOIN_ARENA");
ObjectGuid guid; // arena Battlemaster guid ObjectGuid guid; // arena Battlemaster guid
uint8 arenaslot; // 2v2, 3v3 or 5v5 uint8 arenaslot; // 2v2, 3v3 or 5v5
uint8 asGroup; // asGroup uint8 asGroup; // asGroup
@@ -602,6 +624,10 @@ void WorldSession::HandleBattlemasterJoinArena(WorldPacket& recvData)
if (isRated && !asGroup) if (isRated && !asGroup)
return; return;
// ignore if we already in BG or BG queue
if (_player->InBattleground())
return;
// find creature by guid // find creature by guid
Creature* unit = GetPlayer()->GetMap()->GetCreature(guid); Creature* unit = GetPlayer()->GetMap()->GetCreature(guid);
if (!unit || !unit->IsBattleMaster()) if (!unit || !unit->IsBattleMaster())
@@ -609,6 +635,11 @@ void WorldSession::HandleBattlemasterJoinArena(WorldPacket& recvData)
// get arena type // get arena type
uint8 arenatype = 0; uint8 arenatype = 0;
uint32 ateamId = 0;
uint32 arenaRating = 0;
uint32 matchmakerRating = 0;
uint32 previousOpponents = 0;
switch (arenaslot) switch (arenaslot)
{ {
case 0: case 0:
@@ -621,13 +652,17 @@ void WorldSession::HandleBattlemasterJoinArena(WorldPacket& recvData)
arenatype = ARENA_TYPE_5v5; arenatype = ARENA_TYPE_5v5;
break; break;
default: default:
LOG_ERROR("network", "Unknown arena slot {} at HandleBattlemasterJoinArena()", arenaslot);
return; return;
} }
// get template for all arenas // get template for all arenas
Battleground* bgt = sBattlegroundMgr->GetBattlegroundTemplate(BATTLEGROUND_AA); Battleground* bgt = sBattlegroundMgr->GetBattlegroundTemplate(BATTLEGROUND_AA);
if (!bgt) if (!bgt)
{
LOG_ERROR("network", "Battleground: template bg (all arenas) not found");
return; return;
}
// arenas disabled // arenas disabled
if (DisableMgr::IsDisabledFor(DISABLE_TYPE_BATTLEGROUND, BATTLEGROUND_AA, nullptr)) if (DisableMgr::IsDisabledFor(DISABLE_TYPE_BATTLEGROUND, BATTLEGROUND_AA, nullptr))
@@ -637,32 +672,12 @@ void WorldSession::HandleBattlemasterJoinArena(WorldPacket& recvData)
} }
BattlegroundTypeId bgTypeId = bgt->GetBgTypeID(); BattlegroundTypeId bgTypeId = bgt->GetBgTypeID();
BattlegroundQueueTypeId bgQueueTypeId = BattlegroundMgr::BGQueueTypeId(bgTypeId, arenatype);
// expected bracket entry // expected bracket entry
PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketByLevel(bgt->GetMapId(), _player->getLevel()); PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketByLevel(bgt->GetMapId(), _player->getLevel());
if (!bracketEntry) if (!bracketEntry)
return; return;
// pussywizard: if trying to queue for already queued
// just remove from queue and it will requeue!
uint32 qSlot = _player->GetBattlegroundQueueIndex(bgQueueTypeId);
if (qSlot < PLAYER_MAX_BATTLEGROUND_QUEUES)
{
BattlegroundQueue& bgQueue = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId);
if (bgQueue.IsPlayerInvitedToRatedArena(_player->GetGUID()))
{
WorldPacket data;
sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, ERR_BATTLEGROUND_JOIN_FAILED);
SendPacket(&data);
return;
}
bgQueue.RemovePlayer(_player->GetGUID(), false, qSlot);
_player->RemoveBattlegroundQueueId(bgQueueTypeId);
}
// must have free queue slot // must have free queue slot
// pussywizard: allow being queued only in one arena queue, and it even cannot be together with bg queues // pussywizard: allow being queued only in one arena queue, and it even cannot be together with bg queues
if (_player->InBattlegroundQueue()) if (_player->InBattlegroundQueue())
@@ -684,6 +699,9 @@ void WorldSession::HandleBattlemasterJoinArena(WorldPacket& recvData)
return; return;
} }
BattlegroundQueueTypeId bgQueueTypeId = BattlegroundMgr::BGQueueTypeId(bgTypeId, arenatype);
BattlegroundQueue& bgQueue = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId);
// check if player can queue: // check if player can queue:
if (!asGroup) if (!asGroup)
{ {
@@ -705,16 +723,25 @@ void WorldSession::HandleBattlemasterJoinArena(WorldPacket& recvData)
return; return;
} }
BattlegroundQueue& bgQueue = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId); // check if already in queue
GroupQueueInfo* ginfo = bgQueue.AddGroup(_player, nullptr, bracketEntry, false, false, 0, 0, 0); if (_player->GetBattlegroundQueueIndex(bgQueueTypeId) < PLAYER_MAX_BATTLEGROUND_QUEUES)
uint32 avgWaitTime = bgQueue.GetAverageQueueWaitTime(ginfo); //player is already in this queue
return;
// check if has free queue slots
if (!_player->HasFreeBattlegroundQueueId())
return;
GroupQueueInfo* ginfo = bgQueue.AddGroup(_player, nullptr, bgTypeId, bracketEntry, arenatype, isRated != 0, false, arenaRating, matchmakerRating, ateamId, previousOpponents);
uint32 avgWaitTime = bgQueue.GetAverageQueueWaitTime(ginfo);
uint32 queueSlot = _player->AddBattlegroundQueueId(bgQueueTypeId); uint32 queueSlot = _player->AddBattlegroundQueueId(bgQueueTypeId);
WorldPacket data; WorldPacket data;
sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bgt, queueSlot, STATUS_WAIT_QUEUE, avgWaitTime, 0, arenatype, TEAM_NEUTRAL); sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bgt, queueSlot, STATUS_WAIT_QUEUE, avgWaitTime, 0, arenatype, TEAM_NEUTRAL);
SendPacket(&data); SendPacket(&data);
LOG_DEBUG("bg.battleground", "Battleground: player joined queue for arena, skirmish, bg queue type {} bg type {}: {}, NAME {}", bgQueueTypeId, bgTypeId, _player->GetGUID().ToString(), _player->GetName());
sScriptMgr->OnPlayerJoinArena(_player); sScriptMgr->OnPlayerJoinArena(_player);
} }
// check if group can queue: // check if group can queue:
@@ -725,34 +752,6 @@ void WorldSession::HandleBattlemasterJoinArena(WorldPacket& recvData)
if (!grp || grp->GetLeaderGUID() != _player->GetGUID()) if (!grp || grp->GetLeaderGUID() != _player->GetGUID())
return; return;
// pussywizard: for party members - remove queues for which leader is not queued to!
std::set<uint32> leaderQueueTypeIds;
for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; ++i)
leaderQueueTypeIds.insert((uint32)_player->GetBattlegroundQueueTypeId(i));
for (GroupReference* itr = grp->GetFirstMember(); itr != nullptr; itr = itr->next())
if (Player* member = itr->GetSource())
for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; ++i)
if (BattlegroundQueueTypeId mqtid = member->GetBattlegroundQueueTypeId(i))
if (leaderQueueTypeIds.count((uint32)mqtid) == 0)
{
BattlegroundQueue& bgQueue = sBattlegroundMgr->GetBattlegroundQueue(mqtid);
if (bgQueue.IsPlayerInvitedToRatedArena(member->GetGUID()))
{
WorldPacket data;
sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, ERR_BATTLEGROUND_JOIN_FAILED);
SendPacket(&data);
return;
}
bgQueue.RemovePlayer(member->GetGUID(), false, i);
member->RemoveBattlegroundQueueId(mqtid);
}
uint32 ateamId = 0;
uint32 arenaRating = 0;
uint32 matchmakerRating = 0;
// additional checks for rated arenas // additional checks for rated arenas
if (isRated) if (isRated)
{ {
@@ -775,15 +774,40 @@ void WorldSession::HandleBattlemasterJoinArena(WorldPacket& recvData)
matchmakerRating = at->GetAverageMMR(grp); matchmakerRating = at->GetAverageMMR(grp);
if (arenaRating <= 0) if (arenaRating <= 0)
arenaRating = 1; arenaRating = 1;
previousOpponents = at->GetPreviousOpponents();
} }
err = grp->CanJoinBattlegroundQueue(bgt, bgQueueTypeId, arenatype, arenatype, (bool)isRated, arenaslot); err = grp->CanJoinBattlegroundQueue(bgt, bgQueueTypeId, arenatype, arenatype, (bool)isRated, arenaslot);
// Check queue group members
if (err)
{
grp->DoForAllMembers([&bgQueue, &err](Player* member)
{
if (bgQueue.IsPlayerInvitedToRatedArena(member->GetGUID()))
{
err = ERR_BATTLEGROUND_JOIN_FAILED;
}
});
}
uint32 avgWaitTime = 0; uint32 avgWaitTime = 0;
if (err > 0) if (err > 0)
{ {
BattlegroundQueue& bgQueue = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId); LOG_DEBUG("bg.battleground", "Battleground: arena join as group start");
GroupQueueInfo* ginfo = bgQueue.AddGroup(_player, grp, bracketEntry, isRated, false, arenaRating, matchmakerRating, ateamId);
if (isRated)
{
LOG_DEBUG("bg.battleground", "Battleground: arena team id {}, leader {} queued with matchmaker rating {} for type {}", _player->GetArenaTeamId(arenaslot), _player->GetName(), matchmakerRating, arenatype);
bgt->SetRated(true);
}
else
{
bgt->SetRated(false);
}
GroupQueueInfo* ginfo = bgQueue.AddGroup(_player, grp, bgTypeId, bracketEntry, arenatype, isRated != 0, false, arenaRating, matchmakerRating, ateamId, previousOpponents);
avgWaitTime = bgQueue.GetAverageQueueWaitTime(ginfo); avgWaitTime = bgQueue.GetAverageQueueWaitTime(ginfo);
} }
@@ -810,13 +834,13 @@ void WorldSession::HandleBattlemasterJoinArena(WorldPacket& recvData)
sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, err); sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, err);
member->GetSession()->SendPacket(&data); member->GetSession()->SendPacket(&data);
LOG_DEBUG("bg.battleground", "Battleground: player joined queue for arena as group bg queue type {} bg type {}: {}, NAME {}", bgQueueTypeId, bgTypeId, member->GetGUID().ToString(), member->GetName());
sScriptMgr->OnPlayerJoinArena(member); sScriptMgr->OnPlayerJoinArena(member);
} }
// pussywizard: schedule update for rated arena
if (ateamId)
sBattlegroundMgr->ScheduleArenaQueueUpdate(ateamId, bgQueueTypeId, bracketEntry->GetBracketId());
} }
sBattlegroundMgr->ScheduleQueueUpdate(matchmakerRating, arenatype, bgQueueTypeId, bgTypeId, bracketEntry->GetBracketId());
} }
void WorldSession::HandleReportPvPAFK(WorldPacket& recvData) void WorldSession::HandleReportPvPAFK(WorldPacket& recvData)
+3 -3
View File
@@ -170,7 +170,7 @@ void WorldSession::HandleMoveWorldportAck()
if (uint32 inviteInstanceId = _player->GetPendingSpectatorInviteInstanceId()) if (uint32 inviteInstanceId = _player->GetPendingSpectatorInviteInstanceId())
{ {
if (Battleground* tbg = sBattlegroundMgr->GetBattleground(inviteInstanceId)) if (Battleground* tbg = sBattlegroundMgr->GetBattleground(inviteInstanceId, BATTLEGROUND_TYPE_NONE))
tbg->RemoveToBeTeleported(_player->GetGUID()); tbg->RemoveToBeTeleported(_player->GetGUID());
_player->SetPendingSpectatorInviteInstanceId(0); _player->SetPendingSpectatorInviteInstanceId(0);
} }
@@ -904,14 +904,14 @@ void WorldSession::ComputeNewClockDelta()
std::vector<uint32> latencies; std::vector<uint32> latencies;
std::vector<int64> clockDeltasAfterFiltering; std::vector<int64> clockDeltasAfterFiltering;
for (auto pair : _timeSyncClockDeltaQueue.content()) for (auto& pair : _timeSyncClockDeltaQueue.content())
latencies.push_back(pair.second); latencies.push_back(pair.second);
uint32 latencyMedian = median(latencies); uint32 latencyMedian = median(latencies);
uint32 latencyStandardDeviation = standard_deviation(latencies); uint32 latencyStandardDeviation = standard_deviation(latencies);
uint32 sampleSizeAfterFiltering = 0; uint32 sampleSizeAfterFiltering = 0;
for (auto pair : _timeSyncClockDeltaQueue.content()) for (auto& pair : _timeSyncClockDeltaQueue.content())
{ {
if (pair.second <= latencyMedian + latencyStandardDeviation) { if (pair.second <= latencyMedian + latencyStandardDeviation) {
clockDeltasAfterFiltering.push_back(pair.first); clockDeltasAfterFiltering.push_back(pair.first);
@@ -66,58 +66,41 @@ void ScriptMgr::OnBattlegroundRemovePlayerAtLeave(Battleground* bg, Player* play
}); });
} }
void ScriptMgr::OnAddGroup(BattlegroundQueue* queue, GroupQueueInfo* ginfo, uint32& index, Player* leader, Group* grp, PvPDifficultyEntry const* bracketEntry, bool isPremade) void ScriptMgr::OnAddGroup(BattlegroundQueue* queue, GroupQueueInfo* ginfo, uint32& index, Player* leader, Group* group, BattlegroundTypeId bgTypeId, PvPDifficultyEntry const* bracketEntry,
uint8 arenaType, bool isRated, bool isPremade, uint32 arenaRating, uint32 matchmakerRating, uint32 arenaTeamId, uint32 opponentsArenaTeamId)
{ {
ExecuteScript<BGScript>([&](BGScript* script) ExecuteScript<BGScript>([&](BGScript* script)
{ {
script->OnAddGroup(queue, ginfo, index, leader, grp, bracketEntry, isPremade); script->OnAddGroup(queue, ginfo, index, leader, group, bgTypeId, bracketEntry,
arenaType, isRated, isPremade, arenaRating, matchmakerRating, arenaTeamId, opponentsArenaTeamId);
}); });
} }
bool ScriptMgr::CanFillPlayersToBG(BattlegroundQueue* queue, Battleground* bg, const int32 aliFree, const int32 hordeFree, BattlegroundBracketId bracket_id) bool ScriptMgr::CanFillPlayersToBG(BattlegroundQueue* queue, Battleground* bg, BattlegroundBracketId bracket_id)
{ {
auto ret = IsValidBoolScript<BGScript>([&](BGScript* script) auto ret = IsValidBoolScript<BGScript>([&](BGScript* script)
{ {
return !script->CanFillPlayersToBG(queue, bg, aliFree, hordeFree, bracket_id); return !script->CanFillPlayersToBG(queue, bg, bracket_id);
}); });
if (ret && *ret) return ReturnValidBool(ret);
{
return false;
}
return true;
} }
bool ScriptMgr::CanFillPlayersToBGWithSpecific(BattlegroundQueue* queue, Battleground* bg, const int32 aliFree, const int32 hordeFree, bool ScriptMgr::IsCheckNormalMatch(BattlegroundQueue* queue, Battleground* bgTemplate, BattlegroundBracketId bracket_id, uint32 minPlayers, uint32 maxPlayers)
BattlegroundBracketId thisBracketId, BattlegroundQueue* specificQueue, BattlegroundBracketId specificBracketId)
{ {
auto ret = IsValidBoolScript<BGScript>([&](BGScript* script) auto ret = IsValidBoolScript<BGScript>([&](BGScript* script)
{ {
return !script->CanFillPlayersToBGWithSpecific(queue, bg, aliFree, hordeFree, thisBracketId, specificQueue, specificBracketId); return script->IsCheckNormalMatch(queue, bgTemplate, bracket_id, minPlayers, maxPlayers);
}); });
if (ret && *ret) return ReturnValidBool(ret, true);
{
return false;
}
return true;
} }
void ScriptMgr::OnCheckNormalMatch(BattlegroundQueue* queue, uint32& Coef, Battleground* bgTemplate, BattlegroundBracketId bracket_id, uint32& minPlayers, uint32& maxPlayers) void ScriptMgr::OnQueueUpdate(BattlegroundQueue* queue, uint32 diff, BattlegroundTypeId bgTypeId, BattlegroundBracketId bracket_id, uint8 arenaType, bool isRated, uint32 arenaRating)
{ {
ExecuteScript<BGScript>([&](BGScript* script) ExecuteScript<BGScript>([&](BGScript* script)
{ {
script->OnCheckNormalMatch(queue, Coef, bgTemplate, bracket_id, minPlayers, maxPlayers); script->OnQueueUpdate(queue, diff, bgTypeId, bracket_id, arenaType, isRated, arenaRating);
});
}
void ScriptMgr::OnQueueUpdate(BattlegroundQueue* queue, BattlegroundBracketId bracket_id, bool isRated, uint32 arenaRatedTeamId)
{
ExecuteScript<BGScript>([&](BGScript* script)
{
script->OnQueueUpdate(queue, bracket_id, isRated, arenaRatedTeamId);
}); });
} }
@@ -128,12 +111,7 @@ bool ScriptMgr::CanSendMessageBGQueue(BattlegroundQueue* queue, Player* leader,
return !script->CanSendMessageBGQueue(queue, leader, bg, bracketEntry); return !script->CanSendMessageBGQueue(queue, leader, bg, bracketEntry);
}); });
if (ret && *ret) return ReturnValidBool(ret);
{
return false;
}
return true;
} }
bool ScriptMgr::OnBeforeSendJoinMessageArenaQueue(BattlegroundQueue* queue, Player* leader, GroupQueueInfo* ginfo, PvPDifficultyEntry const* bracketEntry, bool isRated) bool ScriptMgr::OnBeforeSendJoinMessageArenaQueue(BattlegroundQueue* queue, Player* leader, GroupQueueInfo* ginfo, PvPDifficultyEntry const* bracketEntry, bool isRated)
@@ -143,12 +121,7 @@ bool ScriptMgr::OnBeforeSendJoinMessageArenaQueue(BattlegroundQueue* queue, Play
return !script->OnBeforeSendJoinMessageArenaQueue(queue, leader, ginfo, bracketEntry, isRated); return !script->OnBeforeSendJoinMessageArenaQueue(queue, leader, ginfo, bracketEntry, isRated);
}); });
if (ret && *ret) return ReturnValidBool(ret);
{
return false;
}
return true;
} }
bool ScriptMgr::OnBeforeSendExitMessageArenaQueue(BattlegroundQueue* queue, GroupQueueInfo* ginfo) bool ScriptMgr::OnBeforeSendExitMessageArenaQueue(BattlegroundQueue* queue, GroupQueueInfo* ginfo)
@@ -158,12 +131,7 @@ bool ScriptMgr::OnBeforeSendExitMessageArenaQueue(BattlegroundQueue* queue, Grou
return !script->OnBeforeSendExitMessageArenaQueue(queue, ginfo); return !script->OnBeforeSendExitMessageArenaQueue(queue, ginfo);
}); });
if (ret && *ret) return ReturnValidBool(ret);
{
return false;
}
return true;
} }
void ScriptMgr::OnBattlegroundEnd(Battleground* bg, TeamId winnerTeam) void ScriptMgr::OnBattlegroundEnd(Battleground* bg, TeamId winnerTeam)
+10 -13
View File
@@ -1566,16 +1566,14 @@ public:
// Remove player at leave BG // Remove player at leave BG
virtual void OnBattlegroundRemovePlayerAtLeave(Battleground* /*bg*/, Player* /*player*/) { } virtual void OnBattlegroundRemovePlayerAtLeave(Battleground* /*bg*/, Player* /*player*/) { }
virtual void OnQueueUpdate(BattlegroundQueue* /*queue*/, BattlegroundBracketId /*bracket_id*/, bool /*isRated*/, uint32 /*arenaRatedTeamId*/) { } virtual void OnQueueUpdate(BattlegroundQueue* /*queue*/, uint32 /* diff */, BattlegroundTypeId /* bgTypeId */, BattlegroundBracketId /* bracket_id */, uint8 /* arenaType */, bool /* isRated */, uint32 /* arenaRating */) { }
virtual void OnAddGroup(BattlegroundQueue* /*queue*/, GroupQueueInfo* /*ginfo*/, uint32& /*index*/, Player* /*leader*/, Group* /*grp*/, PvPDifficultyEntry const* /*bracketEntry*/, bool /*isPremade*/) { } virtual void OnAddGroup(BattlegroundQueue* /*queue*/, GroupQueueInfo* /*ginfo*/, uint32& /*index*/, Player* /*leader*/, Group* /*group*/, BattlegroundTypeId /* bgTypeId */, PvPDifficultyEntry const* /* bracketEntry */,
uint8 /* arenaType */, bool /* isRated */, bool /* isPremade */, uint32 /* arenaRating */, uint32 /* matchmakerRating */, uint32 /* arenaTeamId */, uint32 /* opponentsArenaTeamId */) { }
[[nodiscard]] virtual bool CanFillPlayersToBG(BattlegroundQueue* /*queue*/, Battleground* /*bg*/, const int32 /*aliFree*/, const int32 /*hordeFree*/, BattlegroundBracketId /*bracket_id*/) { return true; } [[nodiscard]] virtual bool CanFillPlayersToBG(BattlegroundQueue* /*queue*/, Battleground* /*bg*/, BattlegroundBracketId /*bracket_id*/) { return true; }
[[nodiscard]] virtual bool CanFillPlayersToBGWithSpecific(BattlegroundQueue* /*queue*/, Battleground* /*bg*/, const int32 /*aliFree*/, const int32 /*hordeFree*/, [[nodiscard]] virtual bool IsCheckNormalMatch(BattlegroundQueue* /*queue*/, Battleground* /*bgTemplate*/, BattlegroundBracketId /*bracket_id*/, uint32 /*minPlayers*/, uint32 /*maxPlayers*/) { return false; };
BattlegroundBracketId /*thisBracketId*/, BattlegroundQueue* /*specificQueue*/, BattlegroundBracketId /*specificBracketId*/) { return true; }
virtual void OnCheckNormalMatch(BattlegroundQueue* /*queue*/, uint32& /*Coef*/, Battleground* /*bgTemplate*/, BattlegroundBracketId /*bracket_id*/, uint32& /*minPlayers*/, uint32& /*maxPlayers*/) { }
[[nodiscard]] virtual bool CanSendMessageBGQueue(BattlegroundQueue* /*queue*/, Player* /*leader*/, Battleground* /*bg*/, PvPDifficultyEntry const* /*bracketEntry*/) { return true; } [[nodiscard]] virtual bool CanSendMessageBGQueue(BattlegroundQueue* /*queue*/, Player* /*leader*/, Battleground* /*bg*/, PvPDifficultyEntry const* /*bracketEntry*/) { return true; }
@@ -2402,12 +2400,11 @@ public: /* BGScript */
void OnBattlegroundAddPlayer(Battleground* bg, Player* player); void OnBattlegroundAddPlayer(Battleground* bg, Player* player);
void OnBattlegroundBeforeAddPlayer(Battleground* bg, Player* player); void OnBattlegroundBeforeAddPlayer(Battleground* bg, Player* player);
void OnBattlegroundRemovePlayerAtLeave(Battleground* bg, Player* player); void OnBattlegroundRemovePlayerAtLeave(Battleground* bg, Player* player);
void OnQueueUpdate(BattlegroundQueue* queue, BattlegroundBracketId bracket_id, bool isRated, uint32 arenaRatedTeamId); void OnQueueUpdate(BattlegroundQueue* queue, uint32 diff, BattlegroundTypeId bgTypeId, BattlegroundBracketId bracket_id, uint8 arenaType, bool isRated, uint32 arenaRating);
void OnAddGroup(BattlegroundQueue* queue, GroupQueueInfo* ginfo, uint32& index, Player* leader, Group* grp, PvPDifficultyEntry const* bracketEntry, bool isPremade); void OnAddGroup(BattlegroundQueue* queue, GroupQueueInfo* ginfo, uint32& index, Player* leader, Group* group, BattlegroundTypeId bgTypeId, PvPDifficultyEntry const* bracketEntry,
bool CanFillPlayersToBG(BattlegroundQueue* queue, Battleground* bg, const int32 aliFree, const int32 hordeFree, BattlegroundBracketId bracket_id); uint8 arenaType, bool isRated, bool isPremade, uint32 arenaRating, uint32 matchmakerRating, uint32 arenaTeamId, uint32 opponentsArenaTeamId);
bool CanFillPlayersToBGWithSpecific(BattlegroundQueue* queue, Battleground* bg, const int32 aliFree, const int32 hordeFree, bool CanFillPlayersToBG(BattlegroundQueue* queue, Battleground* bg, BattlegroundBracketId bracket_id);
BattlegroundBracketId thisBracketId, BattlegroundQueue* specificQueue, BattlegroundBracketId specificBracketId); bool IsCheckNormalMatch(BattlegroundQueue* queue, Battleground* bgTemplate, BattlegroundBracketId bracket_id, uint32 minPlayers, uint32 maxPlayers);
void OnCheckNormalMatch(BattlegroundQueue* queue, uint32& Coef, Battleground* bgTemplate, BattlegroundBracketId bracket_id, uint32& minPlayers, uint32& maxPlayers);
bool CanSendMessageBGQueue(BattlegroundQueue* queue, Player* leader, Battleground* bg, PvPDifficultyEntry const* bracketEntry); bool CanSendMessageBGQueue(BattlegroundQueue* queue, Player* leader, Battleground* bg, PvPDifficultyEntry const* bracketEntry);
bool OnBeforeSendJoinMessageArenaQueue(BattlegroundQueue* queue, Player* leader, GroupQueueInfo* ginfo, PvPDifficultyEntry const* bracketEntry, bool isRated); bool OnBeforeSendJoinMessageArenaQueue(BattlegroundQueue* queue, Player* leader, GroupQueueInfo* ginfo, PvPDifficultyEntry const* bracketEntry, bool isRated);
bool OnBeforeSendExitMessageArenaQueue(BattlegroundQueue* queue, GroupQueueInfo* ginfo); bool OnBeforeSendExitMessageArenaQueue(BattlegroundQueue* queue, GroupQueueInfo* ginfo);
@@ -64,4 +64,9 @@ inline void ExecuteScript(std::function<void(ScriptName*)> executeHook)
} }
} }
inline bool ReturnValidBool(Optional<bool> ret, bool need = false)
{
return ret && *ret ? need : !need;
}
#endif // _SCRIPT_MGR_MACRO_H_ #endif // _SCRIPT_MGR_MACRO_H_
+4 -2
View File
@@ -587,8 +587,6 @@ void WorldSession::LogoutPlayer(bool save)
for (int i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; ++i) for (int i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; ++i)
if (BattlegroundQueueTypeId bgQueueTypeId = _player->GetBattlegroundQueueTypeId(i)) if (BattlegroundQueueTypeId bgQueueTypeId = _player->GetBattlegroundQueueTypeId(i))
{ {
_player->RemoveBattlegroundQueueId(bgQueueTypeId);
sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId).RemovePlayer(_player->GetGUID(), false, i);
// track if player logs out after invited to join BG // track if player logs out after invited to join BG
if (_player->IsInvitedForBattlegroundInstance()) if (_player->IsInvitedForBattlegroundInstance())
{ {
@@ -599,8 +597,12 @@ void WorldSession::LogoutPlayer(bool save)
stmt->SetData(1, BG_DESERTION_TYPE_INVITE_LOGOUT); stmt->SetData(1, BG_DESERTION_TYPE_INVITE_LOGOUT);
CharacterDatabase.Execute(stmt); CharacterDatabase.Execute(stmt);
} }
sScriptMgr->OnBattlegroundDesertion(_player, BG_DESERTION_TYPE_INVITE_LOGOUT); sScriptMgr->OnBattlegroundDesertion(_player, BG_DESERTION_TYPE_INVITE_LOGOUT);
} }
_player->RemoveBattlegroundQueueId(bgQueueTypeId);
sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId).RemovePlayer(_player->GetGUID(), true);
} }
///- If the player is in a guild, update the guild roster and broadcast a logout message to other guild members ///- If the player is in a guild, update the guild roster and broadcast a logout message to other guild members
+1
View File
@@ -307,6 +307,7 @@ enum WorldIntConfigs
CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_LIMIT_MIN_PLAYERS, CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_LIMIT_MIN_PLAYERS,
CONFIG_ARENA_MAX_RATING_DIFFERENCE, CONFIG_ARENA_MAX_RATING_DIFFERENCE,
CONFIG_ARENA_RATING_DISCARD_TIMER, CONFIG_ARENA_RATING_DISCARD_TIMER,
CONFIG_ARENA_PREV_OPPONENTS_DISCARD_TIMER,
CONFIG_ARENA_AUTO_DISTRIBUTE_INTERVAL_DAYS, CONFIG_ARENA_AUTO_DISTRIBUTE_INTERVAL_DAYS,
CONFIG_ARENA_GAMES_REQUIRED, CONFIG_ARENA_GAMES_REQUIRED,
CONFIG_ARENA_SEASON_ID, CONFIG_ARENA_SEASON_ID,
+13 -12
View File
@@ -1163,25 +1163,26 @@ void World::LoadConfigSettings(bool reload)
m_int_configs[CONFIG_BATTLEGROUND_SPEED_BUFF_RESPAWN] = 150; m_int_configs[CONFIG_BATTLEGROUND_SPEED_BUFF_RESPAWN] = 150;
} }
m_int_configs[CONFIG_ARENA_MAX_RATING_DIFFERENCE] = sConfigMgr->GetOption<int32> ("Arena.MaxRatingDifference", 150); m_int_configs[CONFIG_ARENA_MAX_RATING_DIFFERENCE] = sConfigMgr->GetOption<uint32>("Arena.MaxRatingDifference", 150);
m_int_configs[CONFIG_ARENA_RATING_DISCARD_TIMER] = sConfigMgr->GetOption<int32> ("Arena.RatingDiscardTimer", 10 * MINUTE * IN_MILLISECONDS); m_int_configs[CONFIG_ARENA_RATING_DISCARD_TIMER] = sConfigMgr->GetOption<uint32>("Arena.RatingDiscardTimer", 10 * MINUTE * IN_MILLISECONDS);
m_int_configs[CONFIG_ARENA_PREV_OPPONENTS_DISCARD_TIMER] = sConfigMgr->GetOption<uint32>("Arena.PreviousOpponentsDiscardTimer", 2 * MINUTE * IN_MILLISECONDS);
m_bool_configs[CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS] = sConfigMgr->GetOption<bool>("Arena.AutoDistributePoints", false); m_bool_configs[CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS] = sConfigMgr->GetOption<bool>("Arena.AutoDistributePoints", false);
m_int_configs[CONFIG_ARENA_AUTO_DISTRIBUTE_INTERVAL_DAYS] = sConfigMgr->GetOption<int32> ("Arena.AutoDistributeInterval", 7); // pussywizard: spoiled by implementing constant day and hour, always 7 now m_int_configs[CONFIG_ARENA_AUTO_DISTRIBUTE_INTERVAL_DAYS] = sConfigMgr->GetOption<uint32>("Arena.AutoDistributeInterval", 7); // pussywizard: spoiled by implementing constant day and hour, always 7 now
m_int_configs[CONFIG_ARENA_GAMES_REQUIRED] = sConfigMgr->GetOption<int32> ("Arena.GamesRequired", 10); m_int_configs[CONFIG_ARENA_GAMES_REQUIRED] = sConfigMgr->GetOption<uint32>("Arena.GamesRequired", 10);
m_int_configs[CONFIG_ARENA_SEASON_ID] = sConfigMgr->GetOption<int32> ("Arena.ArenaSeason.ID", 1); m_int_configs[CONFIG_ARENA_SEASON_ID] = sConfigMgr->GetOption<uint32>("Arena.ArenaSeason.ID", 1);
m_int_configs[CONFIG_ARENA_START_RATING] = sConfigMgr->GetOption<int32> ("Arena.ArenaStartRating", 0); m_int_configs[CONFIG_ARENA_START_RATING] = sConfigMgr->GetOption<uint32>("Arena.ArenaStartRating", 0);
m_int_configs[CONFIG_ARENA_START_PERSONAL_RATING] = sConfigMgr->GetOption<int32> ("Arena.ArenaStartPersonalRating", 1000); m_int_configs[CONFIG_ARENA_START_PERSONAL_RATING] = sConfigMgr->GetOption<uint32>("Arena.ArenaStartPersonalRating", 1000);
m_int_configs[CONFIG_ARENA_START_MATCHMAKER_RATING] = sConfigMgr->GetOption<int32> ("Arena.ArenaStartMatchmakerRating", 1500); m_int_configs[CONFIG_ARENA_START_MATCHMAKER_RATING] = sConfigMgr->GetOption<uint32>("Arena.ArenaStartMatchmakerRating", 1500);
m_bool_configs[CONFIG_ARENA_SEASON_IN_PROGRESS] = sConfigMgr->GetOption<bool>("Arena.ArenaSeason.InProgress", true); m_bool_configs[CONFIG_ARENA_SEASON_IN_PROGRESS] = sConfigMgr->GetOption<bool>("Arena.ArenaSeason.InProgress", true);
m_float_configs[CONFIG_ARENA_WIN_RATING_MODIFIER_1] = sConfigMgr->GetOption<float>("Arena.ArenaWinRatingModifier1", 48.0f); m_float_configs[CONFIG_ARENA_WIN_RATING_MODIFIER_1] = sConfigMgr->GetOption<float>("Arena.ArenaWinRatingModifier1", 48.0f);
m_float_configs[CONFIG_ARENA_WIN_RATING_MODIFIER_2] = sConfigMgr->GetOption<float>("Arena.ArenaWinRatingModifier2", 24.0f); m_float_configs[CONFIG_ARENA_WIN_RATING_MODIFIER_2] = sConfigMgr->GetOption<float>("Arena.ArenaWinRatingModifier2", 24.0f);
m_float_configs[CONFIG_ARENA_LOSE_RATING_MODIFIER] = sConfigMgr->GetOption<float>("Arena.ArenaLoseRatingModifier", 24.0f); m_float_configs[CONFIG_ARENA_LOSE_RATING_MODIFIER] = sConfigMgr->GetOption<float>("Arena.ArenaLoseRatingModifier", 24.0f);
m_float_configs[CONFIG_ARENA_MATCHMAKER_RATING_MODIFIER] = sConfigMgr->GetOption<float>("Arena.ArenaMatchmakerRatingModifier", 24.0f); m_float_configs[CONFIG_ARENA_MATCHMAKER_RATING_MODIFIER] = sConfigMgr->GetOption<float>("Arena.ArenaMatchmakerRatingModifier", 24.0f);
m_bool_configs[CONFIG_ARENA_QUEUE_ANNOUNCER_ENABLE] = sConfigMgr->GetOption<bool> ("Arena.QueueAnnouncer.Enable", false); m_bool_configs[CONFIG_ARENA_QUEUE_ANNOUNCER_ENABLE] = sConfigMgr->GetOption<bool>("Arena.QueueAnnouncer.Enable", false);
m_bool_configs[CONFIG_ARENA_QUEUE_ANNOUNCER_PLAYERONLY] = sConfigMgr->GetOption<bool> ("Arena.QueueAnnouncer.PlayerOnly", false); m_bool_configs[CONFIG_ARENA_QUEUE_ANNOUNCER_PLAYERONLY] = sConfigMgr->GetOption<bool>("Arena.QueueAnnouncer.PlayerOnly", false);
m_bool_configs[CONFIG_OFFHAND_CHECK_AT_SPELL_UNLEARN] = sConfigMgr->GetOption<bool>("OffhandCheckAtSpellUnlearn", true); m_bool_configs[CONFIG_OFFHAND_CHECK_AT_SPELL_UNLEARN] = sConfigMgr->GetOption<bool>("OffhandCheckAtSpellUnlearn", true);
m_int_configs[CONFIG_CREATURE_STOP_FOR_PLAYER] = sConfigMgr->GetOption<int32>("Creature.MovingStopTimeForPlayer", 3 * MINUTE * IN_MILLISECONDS); m_int_configs[CONFIG_CREATURE_STOP_FOR_PLAYER] = sConfigMgr->GetOption<uint32>("Creature.MovingStopTimeForPlayer", 3 * MINUTE * IN_MILLISECONDS);
if (int32 clientCacheId = sConfigMgr->GetOption<int32>("ClientCacheVersion", 0)) if (int32 clientCacheId = sConfigMgr->GetOption<int32>("ClientCacheVersion", 0))
{ {
@@ -2046,7 +2047,7 @@ void World::SetInitialWorldSettings()
///- Initialize Battlegrounds ///- Initialize Battlegrounds
LOG_INFO("server.loading", "Starting Battleground System"); LOG_INFO("server.loading", "Starting Battleground System");
sBattlegroundMgr->CreateInitialBattlegrounds(); sBattlegroundMgr->LoadBattlegroundTemplates();
sBattlegroundMgr->InitAutomaticArenaPointDistribution(); sBattlegroundMgr->InitAutomaticArenaPointDistribution();
///- Initialize outdoor pvp ///- Initialize outdoor pvp
+1 -1
View File
@@ -412,7 +412,7 @@ public:
return false; return false;
} }
Battleground* bg = sBattlegroundMgr->CreateNewBattleground(randomizedArenaBgTypeId, 80, 80, ArenaType(hcnt >= 2 ? hcnt : 2), false); Battleground* bg = sBattlegroundMgr->CreateNewBattleground(randomizedArenaBgTypeId, GetBattlegroundBracketById(bgt->GetMapId(), bgt->GetBracketId()), ArenaType(hcnt >= 2 ? hcnt : 2), false);
if (!bg) if (!bg)
{ {
handler->PSendSysMessage("Couldn't create arena map!"); handler->PSendSysMessage("Couldn't create arena map!");
+1 -1
View File
@@ -215,7 +215,7 @@ public:
static bool HandleReloadBattlegroundTemplate(ChatHandler* handler) static bool HandleReloadBattlegroundTemplate(ChatHandler* handler)
{ {
LOG_INFO("server.loading", "Re-Loading Battleground Templates..."); LOG_INFO("server.loading", "Re-Loading Battleground Templates...");
sBattlegroundMgr->CreateInitialBattlegrounds(); sBattlegroundMgr->LoadBattlegroundTemplates();
handler->SendGlobalGMSysMessage("DB table `battleground_template` reloaded."); handler->SendGlobalGMSysMessage("DB table `battleground_template` reloaded.");
return true; return true;
} }
@@ -2923,6 +2923,14 @@ Arena.MaxRatingDifference = 150
Arena.RatingDiscardTimer = 600000 Arena.RatingDiscardTimer = 600000
#
# Arena.PreviousOpponentsDiscardTimer
# Description: Time (in milliseconds) after which the previous opponents will be ignored.
# Default: 120000 - (Enabled, 2 minutes - Blizzlike)
# 0 - (Disabled)
Arena.PreviousOpponentsDiscardTimer = 120000
# #
# Arena.AutoDistributePoints # Arena.AutoDistributePoints
# Description: Automatically distribute arena points. # Description: Automatically distribute arena points.