Core/Arenas: Allow queueing for rated arenas (#31148)

This commit is contained in:
Jeremy
2025-08-10 11:25:32 +02:00
committed by GitHub
parent ead7d1a4c9
commit 9ed3d12ec0
9 changed files with 41 additions and 56 deletions

View File

@@ -116,8 +116,8 @@ void Arena::RemovePlayerAtLeave(ObjectGuid guid, bool transport, bool sendPacket
// if the player was a match participant, calculate rating
Team team = itr->second.Team;
ArenaTeam* winnerArenaTeam = sArenaTeamMgr->GetArenaTeamById(GetArenaTeamIdForTeam(GetOtherTeam(team)));
ArenaTeam* loserArenaTeam = sArenaTeamMgr->GetArenaTeamById(GetArenaTeamIdForTeam(team));
ArenaTeam* winnerArenaTeam = nullptr;
ArenaTeam* loserArenaTeam = nullptr;
// left a rated match while the encounter was in progress, consider as loser
if (winnerArenaTeam && loserArenaTeam && winnerArenaTeam != loserArenaTeam)
@@ -159,8 +159,8 @@ void Arena::EndBattleground(Team winner)
// In case of arena draw, follow this logic:
// winnerArenaTeam => ALLIANCE, loserArenaTeam => HORDE
ArenaTeam* winnerArenaTeam = sArenaTeamMgr->GetArenaTeamById(GetArenaTeamIdForTeam(winner == TEAM_OTHER ? ALLIANCE : winner));
ArenaTeam* loserArenaTeam = sArenaTeamMgr->GetArenaTeamById(GetArenaTeamIdForTeam(winner == TEAM_OTHER ? HORDE : GetOtherTeam(winner)));
ArenaTeam* winnerArenaTeam = nullptr;
ArenaTeam* loserArenaTeam = nullptr;
if (winnerArenaTeam && loserArenaTeam && winnerArenaTeam != loserArenaTeam)
{
@@ -191,8 +191,8 @@ void Arena::EndBattleground(Team winner)
_arenaTeamScores[winnerTeam].Assign(winnerTeamRating, winnerTeamRating + winnerChange, winnerMatchmakerRating, GetArenaMatchmakerRating(winner));
_arenaTeamScores[loserTeam].Assign(loserTeamRating, loserTeamRating + loserChange, loserMatchmakerRating, GetArenaMatchmakerRating(GetOtherTeam(winner)));
TC_LOG_DEBUG("bg.arena", "Arena match Type: {} for Team1Id: {} - Team2Id: {} ended. WinnerTeamId: {}. Winner rating: +{}, Loser rating: {}",
GetArenaType(), GetArenaTeamIdByIndex(TEAM_ALLIANCE), GetArenaTeamIdByIndex(TEAM_HORDE), winnerArenaTeam->GetId(), winnerChange, loserChange);
TC_LOG_DEBUG("bg.arena", "Arena match Type: {} ended. WinnerTeamId: {}. Winner rating: +{}, Loser rating: {}",
GetArenaType(), winnerArenaTeam->GetId(), winnerChange, loserChange);
if (sWorld->getBoolConfig(CONFIG_ARENA_LOG_EXTENDED_INFO))
for (auto const& score : PlayerScores)

View File

@@ -80,9 +80,6 @@ Battleground::Battleground(BattlegroundTemplate const* battlegroundTemplate) : _
m_Map = nullptr;
m_ArenaTeamIds[TEAM_ALLIANCE] = 0;
m_ArenaTeamIds[TEAM_HORDE] = 0;
m_ArenaTeamMMR[TEAM_ALLIANCE] = 0;
m_ArenaTeamMMR[TEAM_HORDE] = 0;
@@ -955,7 +952,7 @@ void Battleground::StartBattleground()
sBattlegroundMgr->AddBattleground(this);
if (m_IsRated)
TC_LOG_DEBUG("bg.arena", "Arena match type: {} for Team1Id: {} - Team2Id: {} started.", m_ArenaType, m_ArenaTeamIds[TEAM_ALLIANCE], m_ArenaTeamIds[TEAM_HORDE]);
TC_LOG_DEBUG("bg.arena", "Arena match type: {} started.", m_ArenaType);
}
void Battleground::TeleportPlayerToExploitLocation(Player* player)

View File

@@ -393,9 +393,6 @@ class TC_GAME_API Battleground
virtual void CheckWinConditions() { }
// used for rated arena battles
void SetArenaTeamIdForTeam(Team team, uint32 ArenaTeamId) { m_ArenaTeamIds[GetTeamIndexByTeamId(team)] = ArenaTeamId; }
uint32 GetArenaTeamIdForTeam(Team team) const { return m_ArenaTeamIds[GetTeamIndexByTeamId(team)]; }
uint32 GetArenaTeamIdByIndex(TeamId teamId) const { return m_ArenaTeamIds[teamId]; }
void SetArenaMatchmakerRating(Team team, uint32 MMR){ m_ArenaTeamMMR[GetTeamIndexByTeamId(team)] = MMR; }
uint32 GetArenaMatchmakerRating(Team team) const { return m_ArenaTeamMMR[GetTeamIndexByTeamId(team)]; }
@@ -554,9 +551,6 @@ class TC_GAME_API Battleground
// Players count by team
uint32 m_PlayersCount[PVP_TEAMS_COUNT];
// Arena team ids by team
uint32 m_ArenaTeamIds[PVP_TEAMS_COUNT];
uint32 m_ArenaTeamMMR[PVP_TEAMS_COUNT];
// Start location

View File

@@ -465,19 +465,20 @@ void BattlegroundMgr::SendBattlegroundList(Player* player, ObjectGuid const& gui
player->SendDirectMessage(battlefieldList.Write());
}
void BattlegroundMgr::SendToBattleground(Player* player, uint32 instanceId, BattlegroundTypeId bgTypeId)
/*static*/ void BattlegroundMgr::SendToBattleground(Player* player, Battleground const* battleground)
{
if (Battleground* bg = GetBattleground(instanceId, bgTypeId))
if (!battleground)
{
uint32 mapid = bg->GetMapId();
Team team = player->GetBGTeam();
WorldSafeLocsEntry const* pos = bg->GetTeamStartPosition(Battleground::GetTeamIndexByTeamId(team));
TC_LOG_DEBUG("bg.battleground", "BattlegroundMgr::SendToBattleground: Sending {} to map {}, {} (bgType {})", player->GetName(), mapid, pos->Loc.ToString(), bgTypeId);
player->TeleportTo({ .Location = pos->Loc, .TransportGuid = pos->TransportSpawnId ? ObjectGuid::Create<HighGuid::Transport>(*pos->TransportSpawnId) : ObjectGuid::Empty });
TC_LOG_ERROR("bg.battleground", "BattlegroundMgr::SendToBattleground: Battleground not found while trying to teleport player {}", player->GetName());
return;
}
else
TC_LOG_ERROR("bg.battleground", "BattlegroundMgr::SendToBattleground: Instance {} (bgType {}) not found while trying to teleport player {}", instanceId, bgTypeId, player->GetName());
uint32 mapid = battleground->GetMapId();
Team team = player->GetBGTeam();
WorldSafeLocsEntry const* pos = battleground->GetTeamStartPosition(Battleground::GetTeamIndexByTeamId(team));
TC_LOG_DEBUG("bg.battleground", "BattlegroundMgr::SendToBattleground: Sending {} to map {}, {} (bgType {})", player->GetName(), mapid, pos->Loc.ToString(), battleground->GetTypeID());
player->TeleportTo({ .Location = pos->Loc, .TransportGuid = pos->TransportSpawnId ? ObjectGuid::Create<HighGuid::Transport>(*pos->TransportSpawnId) : ObjectGuid::Empty });
}
bool BattlegroundMgr::IsArenaType(BattlegroundTypeId bgTypeId)

View File

@@ -118,7 +118,7 @@ class TC_GAME_API BattlegroundMgr
void LoadBattlegroundTemplates();
void DeleteAllBattlegrounds();
void SendToBattleground(Player* player, uint32 InstanceID, BattlegroundTypeId bgTypeId);
static void SendToBattleground(Player* player, Battleground const* battleground);
/* Battleground queues */
static bool IsValidQueueId(BattlegroundQueueTypeId bgQueueTypeId);

View File

@@ -130,13 +130,12 @@ bool BattlegroundQueue::SelectionPool::AddGroup(GroupQueueInfo* ginfo, uint32 de
/*********************************************************/
// add group or player (grp == NULL) to bg queue with the given leader and bg specifications
GroupQueueInfo* BattlegroundQueue::AddGroup(Player const* leader, Group const* group, Team team, PVPDifficultyEntry const* bracketEntry, bool isPremade, uint32 ArenaRating, uint32 MatchmakerRating, uint32 arenateamid)
GroupQueueInfo* BattlegroundQueue::AddGroup(Player const* leader, Group const* group, Team team, PVPDifficultyEntry const* bracketEntry, bool isPremade, uint32 ArenaRating, uint32 MatchmakerRating)
{
BattlegroundBracketId bracketId = bracketEntry->GetBracketId();
// create new ginfo
GroupQueueInfo* ginfo = new GroupQueueInfo;
ginfo->ArenaTeamId = arenateamid;
ginfo->IsInvitedToBGInstanceGUID = 0;
ginfo->JoinTime = GameTime::GetGameTimeMS();
ginfo->RemoveInviteTime = 0;
@@ -161,7 +160,7 @@ GroupQueueInfo* BattlegroundQueue::AddGroup(Player const* leader, Group const* g
//announce world (this don't need mutex)
if (m_queueId.Rated && sWorld->getBoolConfig(CONFIG_ARENA_QUEUE_ANNOUNCER_ENABLE))
{
ArenaTeam* team = sArenaTeamMgr->GetArenaTeamById(arenateamid);
ArenaTeam* team = sArenaTeamMgr->GetArenaTeamById(0);
if (team)
sWorld->SendWorldText(LANG_ARENA_QUEUE_ANNOUNCE_WORLD_JOIN, team->GetName().c_str(), m_queueId.TeamSize, m_queueId.TeamSize, ginfo->ArenaTeamRating);
}
@@ -352,13 +351,13 @@ void BattlegroundQueue::RemovePlayer(ObjectGuid guid, bool decreaseInvitedCount)
// announce to world if arena team left queue for rated match, show only once
if (m_queueId.TeamSize && m_queueId.Rated && group->Players.empty() && sWorld->getBoolConfig(CONFIG_ARENA_QUEUE_ANNOUNCER_ENABLE))
if (ArenaTeam* team = sArenaTeamMgr->GetArenaTeamById(group->ArenaTeamId))
if (ArenaTeam* team = sArenaTeamMgr->GetArenaTeamById(0))
sWorld->SendWorldText(LANG_ARENA_QUEUE_ANNOUNCE_WORLD_EXIT, team->GetName().c_str(), m_queueId.TeamSize, m_queueId.TeamSize, group->ArenaTeamRating);
// if player leaves queue and he is invited to rated arena match, then he have to lose
if (group->IsInvitedToBGInstanceGUID && m_queueId.Rated && decreaseInvitedCount)
{
if (ArenaTeam* at = sArenaTeamMgr->GetArenaTeamById(group->ArenaTeamId))
if (ArenaTeam* at = sArenaTeamMgr->GetArenaTeamById(0))
{
TC_LOG_DEBUG("bg.battleground", "UPDATING memberLost's personal arena rating for {} by opponents rating: {}", guid.ToString(), group->OpponentsTeamRating);
if (Player* player = ObjectAccessor::FindConnectedPlayer(guid))
@@ -438,10 +437,6 @@ bool BattlegroundQueue::InviteGroupToBG(GroupQueueInfo* ginfo, Battleground* bg,
BattlegroundQueueTypeId bgQueueTypeId = m_queueId;
BattlegroundBracketId bracket_id = bg->GetBracketId();
// set ArenaTeamId for rated matches
if (bg->isArena() && bg->isRated())
bg->SetArenaTeamIdForTeam(ginfo->Team, ginfo->ArenaTeamId);
ginfo->RemoveInviteTime = GameTime::GetGameTimeMS() + INVITE_ACCEPT_WAIT_TIME;
// loop through the players
@@ -944,10 +939,14 @@ void BattlegroundQueue::BattlegroundQueueUpdate(uint32 /*diff*/, BattlegroundBra
{
for (GroupsQueueType::iterator itr3 = itr_teams[0]; itr3 != m_QueuedGroups[bracket_id][team].end(); ++itr3)
{
// disable this check to allow arena queue without other team
if (itr3 == itr_teams[0])
continue; // skip already found team
if (!(*itr3)->IsInvitedToBGInstanceGUID
&& (((*itr3)->ArenaMatchmakerRating >= arenaMinRating && (*itr3)->ArenaMatchmakerRating <= arenaMaxRating)
|| (int32)(*itr3)->JoinTime < discardTime)
&& (*itr_teams[0])->ArenaTeamId != (*itr3)->ArenaTeamId)
|| (int32)(*itr3)->JoinTime < discardTime))
{
itr_teams[found++] = itr3;
break;
@@ -971,8 +970,8 @@ void BattlegroundQueue::BattlegroundQueueUpdate(uint32 /*diff*/, BattlegroundBra
hTeam->OpponentsTeamRating = aTeam->ArenaTeamRating;
aTeam->OpponentsMatchmakerRating = hTeam->ArenaMatchmakerRating;
hTeam->OpponentsMatchmakerRating = aTeam->ArenaMatchmakerRating;
TC_LOG_DEBUG("bg.battleground", "setting oposite teamrating for team {} to {}", aTeam->ArenaTeamId, aTeam->OpponentsTeamRating);
TC_LOG_DEBUG("bg.battleground", "setting oposite teamrating for team {} to {}", hTeam->ArenaTeamId, hTeam->OpponentsTeamRating);
TC_LOG_DEBUG("bg.battleground", "setting oposite teamrating for to {}", aTeam->OpponentsTeamRating);
TC_LOG_DEBUG("bg.battleground", "setting oposite teamrating for to {}", hTeam->OpponentsTeamRating);
// now we must move team if we changed its faction to another faction queue, because then we will spam log by errors in Queue::RemovePlayer
if (aTeam->Team != ALLIANCE)

View File

@@ -39,7 +39,6 @@ struct GroupQueueInfo // stores informatio
{
std::map<ObjectGuid, PlayerQueueInfo*> Players; // player queue info map
::Team Team; // Player team (ALLIANCE/HORDE)
uint32 ArenaTeamId; // team id if rated match
uint32 JoinTime; // time when group was added
uint32 RemoveInviteTime; // time when we will remove invite for players in group
uint32 IsInvitedToBGInstanceGUID; // was invited to certain BG
@@ -79,7 +78,7 @@ class TC_GAME_API BattlegroundQueue
bool CheckPremadeMatch(BattlegroundBracketId bracket_id, uint32 MinPlayersPerTeam, uint32 MaxPlayersPerTeam);
bool CheckNormalMatch(BattlegroundBracketId bracket_id, uint32 minPlayers, uint32 maxPlayers);
bool CheckSkirmishForSameFaction(BattlegroundBracketId bracket_id, uint32 minPlayersPerTeam);
GroupQueueInfo* AddGroup(Player const* leader, Group const* group, Team team, PVPDifficultyEntry const* bracketEntry, bool isPremade, uint32 ArenaRating, uint32 MatchmakerRating, uint32 ArenaTeamId = 0);
GroupQueueInfo* AddGroup(Player const* leader, Group const* group, Team team, PVPDifficultyEntry const* bracketEntry, bool isPremade, uint32 ArenaRating, uint32 MatchmakerRating);
void RemovePlayer(ObjectGuid guid, bool decreaseInvitedCount);
bool IsPlayerInvited(ObjectGuid pl_guid, const uint32 bgInstanceGuid, const uint32 removeTime);
bool GetPlayerGroupInfoData(ObjectGuid guid, GroupQueueInfo* ginfo);

View File

@@ -1269,6 +1269,8 @@ GroupJoinBattlegroundResult Group::CanJoinBattlegroundQueue(BattlegroundTemplate
return ERR_BATTLEGROUND_JOIN_FAILED;
if (isMercenary != (member->HasAura(SPELL_MERCENARY_CONTRACT_HORDE) || member->HasAura(SPELL_MERCENARY_CONTRACT_ALLIANCE)))
return ERR_BATTLEGROUND_JOIN_MERCENARY;
memberscount++;
}
errorGuid = ObjectGuid::Empty;

View File

@@ -192,7 +192,7 @@ void WorldSession::HandleBattlemasterJoinOpcode(WorldPackets::Battleground::Batt
return;
BattlegroundQueue& bgQueue = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId);
GroupQueueInfo* ginfo = bgQueue.AddGroup(_player, nullptr, getQueueTeam(), bracketEntry, false, isPremade, 0, 0);
GroupQueueInfo* ginfo = bgQueue.AddGroup(_player, nullptr, getQueueTeam(), bracketEntry, false, isPremade, 0);
uint32 avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry->GetBracketId());
uint32 queueSlot = _player->AddBattlegroundQueueId(bgQueueTypeId);
@@ -220,7 +220,7 @@ void WorldSession::HandleBattlemasterJoinOpcode(WorldPackets::Battleground::Batt
if (!err)
{
TC_LOG_DEBUG("bg.battleground", "Battleground: the following players are joining as group:");
ginfo = bgQueue.AddGroup(_player, grp, getQueueTeam(), bracketEntry, false, isPremade, 0, 0);
ginfo = bgQueue.AddGroup(_player, grp, getQueueTeam(), bracketEntry, false, isPremade, 0);
avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry->GetBracketId());
}
@@ -403,7 +403,7 @@ void WorldSession::HandleBattleFieldPortOpcode(WorldPackets::Battleground::Battl
_player->SetBGTeam(ginfo.Team);
// bg->HandleBeforeTeleportToBattleground(_player);
sBattlegroundMgr->SendToBattleground(_player, ginfo.IsInvitedToBGInstanceGUID, bgTypeId);
BattlegroundMgr::SendToBattleground(_player, bg);
// add only in HandleMoveWorldPortAck()
// bg->AddPlayer(_player, team);
TC_LOG_DEBUG("bg.battleground", "Battleground: player {} ({}) joined battle for bg {}, bgtype {}, queue {{ BattlemasterListId: {}, Type: {}, Rated: {}, TeamSize: {} }}.",
@@ -546,16 +546,9 @@ void WorldSession::HandleBattlemasterJoinArena(WorldPackets::Battleground::Battl
if (grp->GetLeaderGUID() != _player->GetGUID())
return;
uint32 ateamId = _player->GetArenaTeamId(packet.TeamSizeIndex);
// check real arenateam existence only here (if it was moved to group->CanJoin .. () then we would ahve to get it twice)
ArenaTeam* at = sArenaTeamMgr->GetArenaTeamById(ateamId);
if (!at)
return;
// get the team rating for queuing
uint32 arenaRating = at->GetRating();
uint32 matchmakerRating = at->GetAverageMMR(grp);
// the arenateam id must match for everyone in the group
uint32 arenaRating = 1; //at->GetRating();
uint32 matchmakerRating = 1; //at->GetAverageMMR(grp);
if (arenaRating <= 0)
arenaRating = 1;
@@ -571,7 +564,7 @@ void WorldSession::HandleBattlemasterJoinArena(WorldPackets::Battleground::Battl
{
TC_LOG_DEBUG("bg.battleground", "Battleground: arena team id {}, leader {} queued with matchmaker rating {} for type {}", _player->GetArenaTeamId(packet.TeamSizeIndex), _player->GetName(), matchmakerRating, arenatype);
ginfo = bgQueue.AddGroup(_player, grp, Team(_player->GetTeam()), bracketEntry, false, arenaRating, matchmakerRating, ateamId);
ginfo = bgQueue.AddGroup(_player, grp, Team(_player->GetTeam()), bracketEntry, false, arenaRating, matchmakerRating);
avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry->GetBracketId());
}
@@ -636,7 +629,7 @@ void WorldSession::HandleGetPVPOptionsEnabled(WorldPackets::Battleground::GetPVP
pvpOptionsEnabled.PugBattlegrounds = true;
pvpOptionsEnabled.WargameBattlegrounds = false;
pvpOptionsEnabled.WargameArenas = false;
pvpOptionsEnabled.RatedArenas = false;
pvpOptionsEnabled.RatedArenas = true;
pvpOptionsEnabled.ArenaSkirmish = false;
pvpOptionsEnabled.SoloShuffle = false;
pvpOptionsEnabled.RatedSoloShuffle = false;