feat(Core/Battleground): split Arena and Battleground score (#10616)

This commit is contained in:
Kargatum
2022-02-18 05:20:04 +07:00
committed by GitHub
parent dbd7680f5b
commit 5143872aed
41 changed files with 1750 additions and 1766 deletions

View File

@@ -37,7 +37,7 @@
BattlegroundQueue::BattlegroundQueue() : m_bgTypeId(BATTLEGROUND_TYPE_NONE), m_arenaType(ArenaType(0))
{
for (uint32 i = 0; i < BG_TEAMS_COUNT; ++i)
for (uint32 i = 0; i < PVP_TEAMS_COUNT; ++i)
{
for (uint32 j = 0; j < MAX_BATTLEGROUND_BRACKETS; ++j)
{
@@ -87,7 +87,7 @@ bool BattlegroundQueue::SelectionPool::KickGroup(const uint32 size)
// find last group with proper size or largest
bool foundProper = false;
auto groupToKick = SelectedGroups.begin();
for (auto itr = groupToKick; itr != SelectedGroups.end(); ++itr)
for (auto& itr = groupToKick; itr != SelectedGroups.end(); ++itr)
{
// if proper size - overwrite to kick last one
if (std::abs(int32((*itr)->Players.size()) - (int32)size) <= 1)
@@ -154,7 +154,7 @@ GroupQueueInfo* BattlegroundQueue::AddGroup(Player* leader, Group* grp, PvPDiffi
uint32 index = 0;
if (!isRated && !isPremade)
index += BG_TEAMS_COUNT;
index += PVP_TEAMS_COUNT;
if (ginfo->teamId == TEAM_HORDE)
index++;
@@ -453,88 +453,6 @@ void BattlegroundQueue::FillPlayersToBG(Battleground* bg, const int32 aliFree, c
}
}
void BattlegroundQueue::FillPlayersToBGWithSpecific(Battleground* bg, const int32 aliFree, const int32 hordeFree, BattlegroundBracketId thisBracketId, BattlegroundQueue* specificQueue, BattlegroundBracketId specificBracketId)
{
if (!sScriptMgr->CanFillPlayersToBGWithSpecific(this, bg, aliFree, hordeFree, thisBracketId, specificQueue, specificBracketId))
return;
// clear selection pools
m_SelectionPools[TEAM_ALLIANCE].Init();
m_SelectionPools[TEAM_HORDE].Init();
// quick check if nothing we can do:
if (!sBattlegroundMgr->isTesting())
if ((m_QueuedGroups[thisBracketId][BG_QUEUE_NORMAL_ALLIANCE].empty() && specificQueue->m_QueuedGroups[specificBracketId][BG_QUEUE_NORMAL_ALLIANCE].empty()) ||
(m_QueuedGroups[thisBracketId][BG_QUEUE_NORMAL_HORDE].empty() && specificQueue->m_QueuedGroups[specificBracketId][BG_QUEUE_NORMAL_HORDE].empty()))
return;
// copy groups from both queues to new joined container
GroupsQueueType m_QueuedBoth[BG_TEAMS_COUNT];
m_QueuedBoth[TEAM_ALLIANCE].insert(m_QueuedBoth[TEAM_ALLIANCE].end(), specificQueue->m_QueuedGroups[specificBracketId][BG_QUEUE_NORMAL_ALLIANCE].begin(), specificQueue->m_QueuedGroups[specificBracketId][BG_QUEUE_NORMAL_ALLIANCE].end());
m_QueuedBoth[TEAM_ALLIANCE].insert(m_QueuedBoth[TEAM_ALLIANCE].end(), m_QueuedGroups[thisBracketId][BG_QUEUE_NORMAL_ALLIANCE].begin(), m_QueuedGroups[thisBracketId][BG_QUEUE_NORMAL_ALLIANCE].end());
m_QueuedBoth[TEAM_HORDE].insert(m_QueuedBoth[TEAM_HORDE].end(), specificQueue->m_QueuedGroups[specificBracketId][BG_QUEUE_NORMAL_HORDE].begin(), specificQueue->m_QueuedGroups[specificBracketId][BG_QUEUE_NORMAL_HORDE].end());
m_QueuedBoth[TEAM_HORDE].insert(m_QueuedBoth[TEAM_HORDE].end(), m_QueuedGroups[thisBracketId][BG_QUEUE_NORMAL_HORDE].begin(), m_QueuedGroups[thisBracketId][BG_QUEUE_NORMAL_HORDE].end());
// ally: at first fill as much as possible
auto Ali_itr = m_QueuedBoth[TEAM_ALLIANCE].begin();
for (; Ali_itr != m_QueuedBoth[TEAM_ALLIANCE].end() && m_SelectionPools[TEAM_ALLIANCE].AddGroup((*Ali_itr), aliFree); ++Ali_itr);
// horde: at first fill as much as possible
auto Horde_itr = m_QueuedBoth[TEAM_HORDE].begin();
for (; Horde_itr != m_QueuedBoth[TEAM_HORDE].end() && m_SelectionPools[TEAM_HORDE].AddGroup((*Horde_itr), hordeFree); ++Horde_itr);
// calculate free space after adding
int32 aliDiff = aliFree - int32(m_SelectionPools[TEAM_ALLIANCE].GetPlayerCount());
int32 hordeDiff = hordeFree - int32(m_SelectionPools[TEAM_HORDE].GetPlayerCount());
int32 invType = sWorld->getIntConfig(CONFIG_BATTLEGROUND_INVITATION_TYPE);
int32 invDiff = 0;
// check balance configuration and set the max difference between teams
switch (invType)
{
case BG_QUEUE_INVITATION_TYPE_NO_BALANCE:
return;
case BG_QUEUE_INVITATION_TYPE_BALANCED:
invDiff = 1;
break;
case BG_QUEUE_INVITATION_TYPE_EVEN:
break;
default:
return;
}
// if free space differs too much, ballance
while (std::abs(aliDiff - hordeDiff) > invDiff && (m_SelectionPools[TEAM_HORDE].GetPlayerCount() > 0 || m_SelectionPools[TEAM_ALLIANCE].GetPlayerCount() > 0))
{
// if results in more alliance players than horde:
if (aliDiff < hordeDiff)
{
// no more alliance in pool, invite whatever we can from horde
if (!m_SelectionPools[TEAM_ALLIANCE].GetPlayerCount())
break;
// kick alliance, returns true if kicked more than needed, so then try to fill up
if (m_SelectionPools[TEAM_ALLIANCE].KickGroup(hordeDiff - aliDiff))
for (; Ali_itr != m_QueuedBoth[TEAM_ALLIANCE].end() && m_SelectionPools[TEAM_ALLIANCE].AddGroup((*Ali_itr), aliFree >= hordeDiff ? aliFree - hordeDiff : 0); ++Ali_itr);
}
else // if results in more horde players than alliance:
{
// no more horde in pool, invite whatever we can from alliance
if (!m_SelectionPools[TEAM_HORDE].GetPlayerCount())
break;
// kick horde, returns true if kicked more than needed, so then try to fill up
if (m_SelectionPools[TEAM_HORDE].KickGroup(aliDiff - hordeDiff))
for (; Horde_itr != m_QueuedBoth[TEAM_HORDE].end() && m_SelectionPools[TEAM_HORDE].AddGroup((*Horde_itr), hordeFree >= aliDiff ? hordeFree - aliDiff : 0); ++Horde_itr);
}
// recalculate free space after adding
aliDiff = aliFree - static_cast<int32>(m_SelectionPools[TEAM_ALLIANCE].GetPlayerCount());
hordeDiff = hordeFree - static_cast<int32>(m_SelectionPools[TEAM_HORDE].GetPlayerCount());
}
}
// this method checks if premade versus premade battleground is possible
// then after 30 mins (default) in queue it moves premade group to normal queue
bool BattlegroundQueue::CheckPremadeMatch(BattlegroundBracketId bracket_id, uint32 MinPlayersPerTeam, uint32 MaxPlayersPerTeam)
@@ -573,7 +491,7 @@ bool BattlegroundQueue::CheckPremadeMatch(BattlegroundBracketId bracket_id, uint
uint32 premade_time = sWorld->getIntConfig(CONFIG_BATTLEGROUND_PREMADE_GROUP_WAIT_FOR_MATCH);
uint32 time_before = GameTime::GetGameTimeMS().count() >= premade_time ? GameTime::GetGameTimeMS().count() - premade_time : 0;
for (uint32 i = 0; i < BG_TEAMS_COUNT; i++)
for (uint32 i = 0; i < PVP_TEAMS_COUNT; i++)
if (!m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_ALLIANCE + i].empty())
for (auto itr = m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_ALLIANCE + i].begin(); itr != m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_ALLIANCE + i].end(); )
{
@@ -624,7 +542,7 @@ bool BattlegroundQueue::CheckNormalMatch(Battleground* bgTemplate, BattlegroundB
// this method will check if we can invite players to same faction skirmish match
bool BattlegroundQueue::CheckSkirmishForSameFaction(BattlegroundBracketId bracket_id, uint32 minPlayersPerTeam)
{
for (uint32 i = 0; i < BG_TEAMS_COUNT; i++)
for (uint32 i = 0; i < PVP_TEAMS_COUNT; i++)
if (!m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_ALLIANCE + i].empty())
{
// clear selection pools
@@ -633,7 +551,7 @@ bool BattlegroundQueue::CheckSkirmishForSameFaction(BattlegroundBracketId bracke
// fill one queue to both selection pools
for (auto itr = m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_ALLIANCE + i].begin(); itr != m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_ALLIANCE + i].end(); ++itr)
for (uint32 j = 0; j < BG_TEAMS_COUNT; j++) // try to add this group to both pools
for (uint32 j = 0; j < PVP_TEAMS_COUNT; j++) // try to add this group to both pools
if (m_SelectionPools[TEAM_ALLIANCE + j].GetPlayerCount() < minPlayersPerTeam) // if this pool is not full
if (m_SelectionPools[TEAM_ALLIANCE + j].AddGroup((*itr), minPlayersPerTeam)) // successfully added
{
@@ -676,9 +594,6 @@ void BattlegroundQueue::UpdateEvents(uint32 diff)
m_events.Update(diff);
}
struct BgEmptinessComp { bool operator()(Battleground* const& bg1, Battleground* const& bg2) const { return ((float)bg1->GetMaxFreeSlots() / (float)bg1->GetMaxPlayersPerTeam()) > ((float)bg2->GetMaxFreeSlots() / (float)bg2->GetMaxPlayersPerTeam()); } };
typedef std::set<Battleground*, BgEmptinessComp> BattlegroundNeedSet;
void BattlegroundQueue::BattlegroundQueueUpdate(uint32 diff, BattlegroundBracketId bracket_id, bool isRated, uint32 arenaRatedTeamId)
{
// if no players in queue - do nothing
@@ -696,28 +611,35 @@ void BattlegroundQueue::BattlegroundQueueUpdate(uint32 diff, BattlegroundBracket
// battlegrounds with free slots should be populated first using players in queue
if (!BattlegroundMgr::IsArenaType(m_bgTypeId))
{
const BattlegroundContainer& bgList = sBattlegroundMgr->GetBattlegroundList();
BattlegroundNeedSet bgsToCheck;
std::vector<Battleground*> bgsToCheck;
// sort from most needing (most empty) to least needing using a std::set with functor
for (auto itr : bgList)
sBattlegroundMgr->DoForAllBattlegrounds([&](Battleground* bg)
{
Battleground* bg = itr.second;
if (!BattlegroundMgr::IsArenaType(bg->GetBgTypeID()) && (bg->GetBgTypeID(true) == m_bgTypeId || m_bgTypeId == BATTLEGROUND_RB) &&
bg->HasFreeSlots() && bg->GetMinLevel() <= bracketEntry->minLevel && bg->GetMaxLevel() >= bracketEntry->maxLevel)
bgsToCheck.insert(bg);
}
if (!BattlegroundMgr::IsArenaType(bg->GetBgTypeID()) &&
(bg->GetBgTypeID(true) == m_bgTypeId || m_bgTypeId == BATTLEGROUND_RB) &&
bg->HasFreeSlots() && bg->GetMinLevel() <= bracketEntry->minLevel &&
bg->GetMaxLevel() >= bracketEntry->maxLevel)
{
bgsToCheck.emplace_back(bg);
}
});
std::sort(bgsToCheck.begin(), bgsToCheck.end(), [](Battleground* const& bg1, Battleground* const& bg2)
{
return ((float)bg1->GetMaxFreeSlots() / (float)bg1->GetMaxPlayersPerTeam()) > ((float)bg2->GetMaxFreeSlots() / (float)bg2->GetMaxPlayersPerTeam());
});
// now iterate needing battlegrounds
for (auto bg : bgsToCheck)
for (auto const& bg : bgsToCheck)
{
// call a function that fills whatever we can from normal queues
FillPlayersToBG(bg, bg->GetFreeSlotsForTeam(TEAM_ALLIANCE), bg->GetFreeSlotsForTeam(TEAM_HORDE), bracket_id);
// invite players
for (uint32 i = 0; i < BG_TEAMS_COUNT; i++)
for (uint32 i = 0; i < PVP_TEAMS_COUNT; i++)
for (auto itr : m_SelectionPools[TEAM_ALLIANCE + i].SelectedGroups)
BattlegroundMgr::InviteGroupToBG(itr, bg, itr->RealTeamID);
InviteGroupToBG(itr, bg, itr->RealTeamID);
}
// prevent new BGs to be created if there are some non-empty BGs running
@@ -751,9 +673,9 @@ void BattlegroundQueue::BattlegroundQueueUpdate(uint32 diff, BattlegroundBracket
return;
// invite players
for (uint32 i = 0; i < BG_TEAMS_COUNT; i++)
for (uint32 i = 0; i < PVP_TEAMS_COUNT; i++)
for (auto& SelectedGroup : m_SelectionPools[TEAM_ALLIANCE + i].SelectedGroups)
BattlegroundMgr::InviteGroupToBG(SelectedGroup, bg, SelectedGroup->teamId);
InviteGroupToBG(SelectedGroup, bg, SelectedGroup->teamId);
bg->StartBattleground();
@@ -764,9 +686,9 @@ void BattlegroundQueue::BattlegroundQueueUpdate(uint32 diff, BattlegroundBracket
FillPlayersToBG(bg, bg->GetFreeSlotsForTeam(TEAM_ALLIANCE), bg->GetFreeSlotsForTeam(TEAM_HORDE), bracket_id);
// invite players
for (uint32 i = 0; i < BG_TEAMS_COUNT; i++)
for (uint32 i = 0; i < PVP_TEAMS_COUNT; i++)
for (auto& SelectedGroup : m_SelectionPools[TEAM_ALLIANCE + i].SelectedGroups)
BattlegroundMgr::InviteGroupToBG(SelectedGroup, bg, SelectedGroup->teamId);
InviteGroupToBG(SelectedGroup, bg, SelectedGroup->teamId);
}
}
@@ -786,9 +708,9 @@ void BattlegroundQueue::BattlegroundQueueUpdate(uint32 diff, BattlegroundBracket
return;
// invite players
for (uint32 i = 0; i < BG_TEAMS_COUNT; i++)
for (uint32 i = 0; i < PVP_TEAMS_COUNT; i++)
for (auto& SelectedGroup : m_SelectionPools[TEAM_ALLIANCE + i].SelectedGroups)
BattlegroundMgr::InviteGroupToBG(SelectedGroup, bg, SelectedGroup->teamId);
InviteGroupToBG(SelectedGroup, bg, SelectedGroup->teamId);
bg->StartBattleground();
}
@@ -804,7 +726,7 @@ void BattlegroundQueue::BattlegroundQueueUpdate(uint32 diff, BattlegroundBracket
const uint32 maxCountedMMR = 2500;
// we need to find 2 teams which will play next game
GroupsQueueType::iterator itr_teams[BG_TEAMS_COUNT];
GroupsQueueType::iterator itr_teams[PVP_TEAMS_COUNT];
bool increaseItr = true;
bool reverse1 = urand(0, 1) != 0;
@@ -937,8 +859,8 @@ void BattlegroundQueue::BattlegroundQueueUpdate(uint32 diff, BattlegroundBracket
arena->SetArenaMatchmakerRating(TEAM_ALLIANCE, aTeam->ArenaMatchmakerRating);
arena->SetArenaMatchmakerRating(TEAM_HORDE, hTeam->ArenaMatchmakerRating);
BattlegroundMgr::InviteGroupToBG(aTeam, arena, TEAM_ALLIANCE);
BattlegroundMgr::InviteGroupToBG(hTeam, arena, TEAM_HORDE);
InviteGroupToBG(aTeam, arena, TEAM_ALLIANCE);
InviteGroupToBG(hTeam, arena, TEAM_HORDE);
arena->StartBattleground();
}
@@ -980,12 +902,12 @@ void BattlegroundQueue::BattlegroundQueueUpdate(uint32 diff, BattlegroundBracket
{
_queueAnnouncementTimer[bracket_id] = -1;
char const* bgName = bg_template->GetName();
auto bgName = bg_template->GetName();
uint32 MaxPlayers = bg_template->GetMinPlayersPerTeam() * 2;
uint32 q_min_level = std::min(bracketEntry->minLevel, (uint32) 80);
uint32 q_max_level = std::min(bracketEntry->maxLevel, (uint32) 80);
sWorld->SendWorldTextOptional(LANG_BG_QUEUE_ANNOUNCE_WORLD, ANNOUNCER_FLAG_DISABLE_BG_QUEUE, bgName, q_min_level, q_max_level, qPlayers, MaxPlayers);
sWorld->SendWorldTextOptional(LANG_BG_QUEUE_ANNOUNCE_WORLD, ANNOUNCER_FLAG_DISABLE_BG_QUEUE, bgName.c_str(), q_min_level, q_max_level, qPlayers, MaxPlayers);
}
else
{
@@ -1031,7 +953,7 @@ void BattlegroundQueue::SendMessageBGQueue(Player* leader, Battleground* bg, PvP
}
BattlegroundBracketId bracketId = bracketEntry->GetBracketId();
char const* bgName = bg->GetName();
auto bgName = bg->GetName();
uint32 MinPlayers = bg->GetMinPlayersPerTeam();
uint32 MaxPlayers = MinPlayers * 2;
uint32 q_min_level = std::min(bracketEntry->minLevel, (uint32)80);
@@ -1046,12 +968,9 @@ void BattlegroundQueue::SendMessageBGQueue(Player* leader, Battleground* bg, PvP
// Show queue status to player only (when joining battleground queue or Arena and arena world announcer is disabled)
if (sWorld->getBoolConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_PLAYERONLY))
{
ChatHandler(leader->GetSession()).PSendSysMessage(LANG_BG_QUEUE_ANNOUNCE_SELF, bgName, q_min_level, q_max_level,
qAlliance,
(MinPlayers > qAlliance) ? MinPlayers - qAlliance : (uint32)0,
qHorde,
(MinPlayers > qHorde) ? MinPlayers - qHorde : (uint32)0
);
ChatHandler(leader->GetSession()).PSendSysMessage(LANG_BG_QUEUE_ANNOUNCE_SELF, bgName.c_str(), q_min_level, q_max_level,
qAlliance, (MinPlayers > qAlliance) ? MinPlayers - qAlliance : (uint32)0,
qHorde, (MinPlayers > qHorde) ? MinPlayers - qHorde : (uint32)0);
}
else // Show queue status to server (when joining battleground queue)
{
@@ -1069,7 +988,7 @@ void BattlegroundQueue::SendMessageBGQueue(Player* leader, Battleground* bg, PvP
return;
}
sWorld->SendWorldTextOptional(LANG_BG_QUEUE_ANNOUNCE_WORLD, ANNOUNCER_FLAG_DISABLE_BG_QUEUE, bgName, q_min_level, q_max_level, qAlliance + qHorde, MaxPlayers);
sWorld->SendWorldTextOptional(LANG_BG_QUEUE_ANNOUNCE_WORLD, ANNOUNCER_FLAG_DISABLE_BG_QUEUE, bgName.c_str(), q_min_level, q_max_level, qAlliance + qHorde, MaxPlayers);
}
}
}
@@ -1120,7 +1039,7 @@ void BattlegroundQueue::SendJoinMessageArenaQueue(Player* leader, GroupQueueInfo
return;
}
sWorld->SendWorldTextOptional(LANG_ARENA_QUEUE_ANNOUNCE_WORLD, ANNOUNCER_FLAG_DISABLE_ARENA_QUEUE, bgName, arenatype.c_str(), q_min_level, q_max_level, qPlayers, playersNeed);
sWorld->SendWorldTextOptional(LANG_ARENA_QUEUE_ANNOUNCE_WORLD, ANNOUNCER_FLAG_DISABLE_ARENA_QUEUE, bgName.c_str(), arenatype.c_str(), q_min_level, q_max_level, qPlayers, playersNeed);
}
}
else
@@ -1175,6 +1094,63 @@ int32 BattlegroundQueue::GetQueueAnnouncementTimer(uint32 bracketId) const
return _queueAnnouncementTimer[bracketId];
}
void BattlegroundQueue::InviteGroupToBG(GroupQueueInfo* ginfo, Battleground* bg, TeamId teamId)
{
if (ginfo->IsInvitedToBGInstanceGUID)
return;
// set side if needed
if (teamId != TEAM_NEUTRAL)
ginfo->teamId = teamId;
// set invitation
ginfo->IsInvitedToBGInstanceGUID = bg->GetInstanceID();
BattlegroundQueueTypeId bgQueueTypeId = BattlegroundMgr::BGQueueTypeId(ginfo->BgTypeId, ginfo->ArenaType);
BattlegroundQueue& bgQueue = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId);
// set ArenaTeamId for rated matches
if (bg->isArena() && bg->isRated())
bg->SetArenaTeamIdForTeam(ginfo->teamId, ginfo->ArenaTeamId);
ginfo->RemoveInviteTime = GameTime::GetGameTimeMS().count() + INVITE_ACCEPT_WAIT_TIME;
// loop through the players
for (auto const& itr : ginfo->Players)
{
// get the player
Player* player = ObjectAccessor::FindConnectedPlayer(itr);
if (!player)
continue;
// update average wait time
bgQueue.PlayerInvitedToBGUpdateAverageWaitTime(ginfo);
// increase invited counter for each invited player
bg->IncreaseInvitedCount(ginfo->teamId);
// create remind invite events
BGQueueInviteEvent* inviteEvent = new BGQueueInviteEvent(player->GetGUID(), ginfo->IsInvitedToBGInstanceGUID, ginfo->BgTypeId, ginfo->ArenaType, ginfo->RemoveInviteTime);
bgQueue.AddEvent(inviteEvent, INVITATION_REMIND_TIME);
// create automatic remove events
BGQueueRemoveEvent* removeEvent = new BGQueueRemoveEvent(player->GetGUID(), ginfo->IsInvitedToBGInstanceGUID, bgQueueTypeId, ginfo->RemoveInviteTime);
bgQueue.AddEvent(removeEvent, INVITE_ACCEPT_WAIT_TIME);
// Check queueSlot
uint32 queueSlot = player->GetBattlegroundQueueIndex(bgQueueTypeId);
ASSERT(queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES);
// send status packet
WorldPacket data;
sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_JOIN, INVITE_ACCEPT_WAIT_TIME, 0, ginfo->ArenaType, TEAM_NEUTRAL, bg->isRated(), ginfo->BgTypeId);
player->GetSession()->SendPacket(&data);
// pussywizard:
if (bg->isArena() && bg->isRated())
bg->ArenaLogEntries[player->GetGUID()].Fill(player->GetName().c_str(), player->GetGUID().GetCounter(), player->GetSession()->GetAccountId(), ginfo->ArenaTeamId, player->GetSession()->GetRemoteAddress());
}
}
/*********************************************************/
/*** BATTLEGROUND QUEUE EVENTS ***/
/*********************************************************/