Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- void SoloQueue::DynamicUpdate()
- {
- uint32 threshold = sWorld->getIntConfig(CONFIG_ARENA_PROGRESSIVE_MMR_TIMER) / (15 * IN_MILLISECONDS);
- if (_dynamicUpdateCount == threshold)
- {
- _dynamicUpdateCount = 0;
- BattlegroundBracketId bracket_id = GetSoloQueueBracketId();
- auto& alliance = m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_ALLIANCE];
- auto& horde = m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_HORDE];
- if (alliance.size() + horde.size() < SoloQueue::TeamSize() * 2)
- return;
- uint32 now = getMSTime();
- for (auto&& team : { alliance, horde })
- {
- size_t i = 0;
- for (auto&& it : team)
- {
- uint32 timeinq = now - it->JoinTime;
- if (i >= team.size() / 2 || timeinq < 30 * IN_MILLISECONDS)
- break;
- ++i;
- TaskScheduler::Default()->ScheduleInvocation(new CallbackTask([=]()
- {
- if (team.size() <= i)
- return;
- auto itr = team.begin();
- std::advance(itr, i);
- if ((*itr)->IsInvitedToBGInstanceGUID)
- return;
- uint32 extradiff = (timeinq / sWorld->getIntConfig(CONFIG_ARENA_PROGRESSIVE_MMR_TIMER)) * sWorld->getIntConfig(CONFIG_ARENA_PROGRESSIVE_MMR_STEPSIZE);
- if (sWorld->getIntConfig(CONFIG_SOLO_QUEUE_PROGRESSIVE_MMR_THRESHOLD))
- extradiff = std::min(extradiff, sWorld->getIntConfig(CONFIG_SOLO_QUEUE_PROGRESSIVE_MMR_THRESHOLD));
- DoMatchmaking(*itr, extradiff, false);
- }));
- }
- }
- }
- else
- ++_dynamicUpdateCount;
- }
- void SoloQueue::DoMatchmaking(GroupQueueInfo* ginfo, uint32 extraDiff, bool strong)
- {
- if (!sWorld->getBoolConfig(CONFIG_SOLO_QUEUE_BALANCE_PRIORITY_ENABLED))
- strong = false;
- BattlegroundBracketId bracket_id = GetSoloQueueBracketId();
- auto& alliance = m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_ALLIANCE];
- auto& horde = m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_HORDE];
- if (alliance.empty() && horde.empty())
- return;
- Battleground* bg = sBattlegroundMgr->GetBattlegroundTemplate(BATTLEGROUND_AA);
- PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketById(bg->GetMapId(), bracket_id);
- if (!bracketEntry)
- {
- sLog->outError("Battleground: Update: bg bracket entry not found for map %u bracket id %u", bg->GetMapId(), bracket_id);
- return;
- }
- StartStopwatch();
- uint32 arenaRating = ginfo->ArenaMatchmakerRating;
- uint32 baseRange = sWorld->getIntConfig(CONFIG_SOLO_QUEUE_MATCH_MAKER_RATING_DIFFERENCE);
- uint32 range = baseRange + extraDiff;
- uint32 lower = arenaRating > range ? arenaRating - range : 0;
- uint32 upper = arenaRating + range;
- // Let's try do it in cache-positive way.
- std::vector<SoloGroup> all;
- std::vector<SoloGroup*> selection;
- all.reserve(alliance.size() + horde.size());
- selection.reserve(all.capacity());
- SoloGroup* aTeam = nullptr;
- SoloGroup* hTeam = nullptr;
- for (auto&& team : { alliance, horde })
- {
- for (auto&& it : team)
- {
- if (it->ArenaMatchmakerRating >= lower && it->ArenaMatchmakerRating <= upper && !it->IsInvitedToBGInstanceGUID)
- {
- SoloGroup g;
- if (g.Create(it))
- all.push_back(g);
- }
- }
- }
- if (all.empty())
- return;
- SoloGroup* opponent = &all.front();
- int32 min = std::abs(int32(ginfo->ArenaMatchmakerRating) - int32(opponent->Rating));
- for (auto&& it : all)
- {
- for (auto&& p : it.Members)
- {
- p.OriginalGroup = ⁢ // Now the pointer won't be changed, we can use it.
- it.AddPlayer(p);
- }
- selection.push_back(&it);
- int32 diff = std::abs(int32(ginfo->ArenaMatchmakerRating) - int32(it.Rating));
- if (diff < min && it.Members.front().Info != ginfo)
- {
- min = diff;
- opponent = ⁢
- }
- }
- if (sWorld->getBoolConfig(CONFIG_SOLO_QUEUE_RATING_BALANCE_ENABLED))
- {
- std::sort(selection.begin(), selection.end(),
- [](SoloGroup const* lhs, SoloGroup const* rhs)
- {
- return lhs->Rating < rhs->Rating;
- });
- }
- else
- {
- std::random_shuffle(selection.begin(), selection.end(),
- [&](int i)
- {
- if (i < 2)
- return 0;
- return irand(0, i - 1);
- });
- }
- uint32 now = getMSTime();
- for (auto&& it : selection)
- {
- auto& i = it->Current.front();
- _log.Write("%u (%s) - %u rating (%u in queue)", i.Target->GetGUIDLow(),
- i.Target->GetSpecialization() == PlayerSpec::Healer ? "healer" : "damager", i.Info->ArenaMatchmakerRating, (now - i.Info->JoinTime) / IN_MILLISECONDS);
- }
- _log.Write("Total queued: %u", uint32(selection.size()));
- if (selection.size() < 4)
- return;
- auto it = std::find_if(selection.begin(), selection.end(), [=](SoloGroup const* g) { return g->Members.front().Info == ginfo; });
- ASSERT(it != selection.end());
- size_t groupIndex = std::distance(selection.begin(), it);
- ASSERT(groupIndex < selection.size());
- SoloGroup* group = *it;
- if (sWorld->getBoolConfig(CONFIG_SOLO_QUEUE_RATING_BALANCE_ENABLED))
- {
- //auto it = std::find(selection.begin(), selection.end(), opponent);
- //ASSERT(it != selection.end());
- size_t opponentIndex = selection.size() / 2;// std::distance(selection.begin(), it);
- auto makeTeam = [&](SoloGroup* group, size_t index, bool forward) -> bool
- {
- if (group->Current.size() == SoloQueue::TeamSize())
- return true;
- uint32 lower = group->Rating > baseRange ? group->Rating - baseRange : 0;
- uint32 upper = group->Rating + baseRange;
- if (forward)
- {
- for (size_t i = index; i < selection.size(); ++i)
- {
- auto right = selection[i];
- if (right->InTeam || right->Rating > upper || right->Rating < lower)
- continue;
- if (Merge(group, right, strong))
- return true;
- }
- }
- else
- {
- for (size_t i = index; i != 0; --i)
- {
- auto right = selection[i];
- if (right->InTeam || right->Rating > upper || right->Rating < lower)
- continue;
- if (Merge(group, right, strong))
- return true;
- }
- }
- return false;
- };
- std::vector<size_t> opponents;
- opponents.reserve(selection.size());
- opponents.push_back(opponentIndex);
- size_t i = 0;
- bool plus = true;
- bool minus = true;
- while (plus || minus)
- {
- ++i;
- plus = opponentIndex + i < selection.size();
- minus = i <= opponentIndex;
- if (plus)
- opponents.push_back(opponentIndex + i);
- if (minus)
- opponents.push_back(opponentIndex - i);
- }
- for (auto&& idx : opponents)
- {
- opponent = selection[idx];
- if (opponent == group)
- continue;
- group->InTeam = true;
- opponent->InTeam = true;
- bool forward = opponent->Rating < group->Rating;
- if (makeTeam(opponent, idx, forward) || makeTeam(opponent, idx, !forward)) // 2 players in opponent
- {
- forward = group->Rating < opponent->Rating;
- if (makeTeam(group, groupIndex, forward) || makeTeam(group, groupIndex, !forward)) // 2 players in group
- {
- forward = opponent->Rating < group->Rating;
- if (makeTeam(opponent, idx, forward) || makeTeam(opponent, idx, !forward)) // 3 players in opponent
- {
- forward = group->Rating < opponent->Rating;
- if (makeTeam(group, groupIndex, forward) || makeTeam(group, groupIndex, !forward)) // 3 players in group
- {
- aTeam = group;
- hTeam = opponent;
- break;
- }
- }
- }
- }
- group->Reset();
- opponent->Reset();
- }
- }
- else
- {
- for (auto&& opponent : selection)
- {
- if (opponent == group)
- continue;
- lower = opponent->Rating > baseRange ? opponent->Rating - baseRange : 0;
- upper = opponent->Rating + baseRange;
- group->InTeam = true;
- opponent->InTeam = true;
- if (MakeTeam(opponent, upper, lower, selection, strong))
- {
- lower = group->Rating > baseRange ? group->Rating - baseRange : 0;
- upper = group->Rating + baseRange;
- if (MakeTeam(group, upper, lower, selection, strong))
- {
- aTeam = group;
- hTeam = opponent;
- break;
- }
- }
- group->Reset();
- opponent->Reset();
- }
- }
- if (!aTeam || !hTeam)
- {
- if (!strong)
- return;
- TaskScheduler::Default()->ScheduleInvocation(new CallbackTask([=]()
- {
- auto it = std::find(alliance.begin(), alliance.end(), ginfo);
- if (it == alliance.end())
- {
- it = std::find(horde.begin(), horde.end(), ginfo);
- if (it == horde.end())
- return;
- }
- DoMatchmaking(*it, extraDiff, false);
- }));
- return;
- }
- _buff << "Groups are picked: ";
- for (auto&& it : aTeam->Current)
- _buff << it.Target->GetGUIDLow() << ' ';
- _buff << "vs ";
- for (auto&& it : hTeam->Current)
- _buff << it.Target->GetGUIDLow() << ' ';
- _log.Write(_buff.str().c_str());
- _buff.str(std::string());
- // Invite to arena
- uint32 mmr = 0;
- uint32 rating = 0;
- for (auto&& it : aTeam->Current)
- {
- mmr += it.Info->ArenaMatchmakerRating;
- rating += it.Info->ArenaTeamRating;
- }
- mmr /= aTeam->Current.size();
- rating /= aTeam->Current.size();
- for (auto&& it : aTeam->Current)
- {
- it.Info->ArenaMatchmakerRating = mmr;
- it.Info->ArenaTeamRating = rating;
- }
- mmr = 0;
- rating = 0;
- for (auto&& it : hTeam->Current)
- {
- mmr += it.Info->ArenaMatchmakerRating;
- rating += it.Info->ArenaTeamRating;
- }
- mmr /= hTeam->Current.size();
- rating /= hTeam->Current.size();
- for (auto&& it : hTeam->Current)
- {
- it.Info->ArenaMatchmakerRating = mmr;
- it.Info->ArenaTeamRating = rating;
- it.Info->OpponentsMatchmakerRating = aTeam->Current.front().Info->ArenaMatchmakerRating;
- it.Info->OpponentsTeamRating = aTeam->Current.front().Info->ArenaMatchmakerRating;
- }
- for (auto&& it : aTeam->Current)
- {
- it.Info->OpponentsMatchmakerRating = mmr;
- it.Info->OpponentsTeamRating = rating;
- }
- for (auto&& it : aTeam->Current)
- {
- if (it.Info->Team != ALLIANCE)
- {
- if (alliance.empty() || it.Info != alliance.back())
- {
- horde.remove(it.Info);
- alliance.push_back(it.Info);
- }
- }
- }
- for (auto&& it : hTeam->Current)
- {
- if (it.Info->Team != HORDE)
- {
- if (horde.empty() || it.Info != horde.back())
- {
- alliance.remove(it.Info);
- horde.push_back(it.Info);
- }
- }
- }
- Battleground* arena = sBattlegroundMgr->CreateNewBattleground(BATTLEGROUND_AA, bracketEntry, ARENA_TYPE_3v3, true);
- if (!arena)
- {
- sLog->outError("BattlegroundQueue::Update couldn't create arena instance for rated arena match!");
- return;
- }
- arena->EnableSoloMode();
- arena->SetArenaMatchmakerRating(ALLIANCE, aTeam->Current.front().Info->ArenaMatchmakerRating);
- arena->SetArenaMatchmakerRating(HORDE, hTeam->Current.front().Info->ArenaMatchmakerRating);
- arena->SetArenaTeamRating(ALLIANCE, aTeam->Current.front().Info->ArenaTeamRating);
- arena->SetArenaTeamRating(HORDE, hTeam->Current.front().Info->ArenaTeamRating);
- for (auto&& team : { aTeam, hTeam })
- {
- for (auto&& it : team->Current)
- {
- InviteGroupToBG(it.Info, arena, team == aTeam ? ALLIANCE : HORDE);
- arena->AddParticipant(team == aTeam ? TEAM_ALLIANCE : TEAM_HORDE, it.Target->GetGUID(), it.Target->GetArenaTeamId(ARENA_SLOT_5v5));
- }
- }
- arena->SetArenaTeamIdForTeam(ALLIANCE, 0);
- arena->SetArenaTeamIdForTeam(HORDE, 0);
- arena->StartBattleground();
- sArenaMgr->AddMatchForWatching(aTeam, hTeam, arena);
- RecordResult("SoloQueue::DoMatchmaking");
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement