Advertisement
Guest User

Untitled

a guest
Oct 23rd, 2016
70
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 13.42 KB | None | 0 0
  1. void SoloQueue::DynamicUpdate()
  2. {
  3.     uint32 threshold = sWorld->getIntConfig(CONFIG_ARENA_PROGRESSIVE_MMR_TIMER) / (15 * IN_MILLISECONDS);
  4.     if (_dynamicUpdateCount == threshold)
  5.     {
  6.         _dynamicUpdateCount = 0;
  7.         BattlegroundBracketId bracket_id = GetSoloQueueBracketId();
  8.         auto& alliance = m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_ALLIANCE];
  9.         auto& horde = m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_HORDE];
  10.         if (alliance.size() + horde.size() < SoloQueue::TeamSize() * 2)
  11.             return;
  12.  
  13.         uint32 now = getMSTime();
  14.         for (auto&& team : { alliance, horde })
  15.         {
  16.             size_t i = 0;
  17.             for (auto&& it : team)
  18.             {
  19.                 uint32 timeinq = now - it->JoinTime;
  20.                 if (i >= team.size() / 2 || timeinq < 30 * IN_MILLISECONDS)
  21.                     break;
  22.  
  23.                 ++i;
  24.                 TaskScheduler::Default()->ScheduleInvocation(new CallbackTask([=]()
  25.                 {
  26.                     if (team.size() <= i)
  27.                         return;
  28.  
  29.                     auto itr = team.begin();
  30.                     std::advance(itr, i);
  31.  
  32.                     if ((*itr)->IsInvitedToBGInstanceGUID)
  33.                         return;
  34.  
  35.                     uint32 extradiff = (timeinq / sWorld->getIntConfig(CONFIG_ARENA_PROGRESSIVE_MMR_TIMER)) * sWorld->getIntConfig(CONFIG_ARENA_PROGRESSIVE_MMR_STEPSIZE);
  36.                     if (sWorld->getIntConfig(CONFIG_SOLO_QUEUE_PROGRESSIVE_MMR_THRESHOLD))
  37.                         extradiff = std::min(extradiff, sWorld->getIntConfig(CONFIG_SOLO_QUEUE_PROGRESSIVE_MMR_THRESHOLD));
  38.                     DoMatchmaking(*itr, extradiff, false);
  39.                 }));
  40.             }
  41.         }
  42.     }
  43.     else
  44.         ++_dynamicUpdateCount;
  45. }
  46.  
  47. void SoloQueue::DoMatchmaking(GroupQueueInfo* ginfo, uint32 extraDiff, bool strong)
  48. {
  49.     if (!sWorld->getBoolConfig(CONFIG_SOLO_QUEUE_BALANCE_PRIORITY_ENABLED))
  50.         strong = false;
  51.  
  52.     BattlegroundBracketId bracket_id = GetSoloQueueBracketId();
  53.     auto& alliance = m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_ALLIANCE];
  54.     auto& horde = m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_HORDE];
  55.     if (alliance.empty() && horde.empty())
  56.         return;
  57.  
  58.     Battleground* bg = sBattlegroundMgr->GetBattlegroundTemplate(BATTLEGROUND_AA);
  59.     PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketById(bg->GetMapId(), bracket_id);
  60.     if (!bracketEntry)
  61.     {
  62.         sLog->outError("Battleground: Update: bg bracket entry not found for map %u bracket id %u", bg->GetMapId(), bracket_id);
  63.         return;
  64.     }
  65.  
  66.     StartStopwatch();
  67.  
  68.     uint32 arenaRating = ginfo->ArenaMatchmakerRating;
  69.     uint32 baseRange = sWorld->getIntConfig(CONFIG_SOLO_QUEUE_MATCH_MAKER_RATING_DIFFERENCE);
  70.     uint32 range = baseRange + extraDiff;
  71.     uint32 lower = arenaRating > range ? arenaRating - range : 0;
  72.     uint32 upper = arenaRating + range;
  73.  
  74.     // Let's try do it in cache-positive way.
  75.     std::vector<SoloGroup> all;
  76.     std::vector<SoloGroup*> selection;
  77.     all.reserve(alliance.size() + horde.size());
  78.     selection.reserve(all.capacity());
  79.  
  80.     SoloGroup* aTeam = nullptr;
  81.     SoloGroup* hTeam = nullptr;
  82.  
  83.     for (auto&& team : { alliance, horde })
  84.     {
  85.         for (auto&& it : team)
  86.         {
  87.             if (it->ArenaMatchmakerRating >= lower && it->ArenaMatchmakerRating <= upper && !it->IsInvitedToBGInstanceGUID)
  88.             {
  89.                 SoloGroup g;
  90.                 if (g.Create(it))
  91.                     all.push_back(g);
  92.             }
  93.         }
  94.     }
  95.  
  96.     if (all.empty())
  97.         return;
  98.  
  99.     SoloGroup* opponent = &all.front();
  100.     int32 min = std::abs(int32(ginfo->ArenaMatchmakerRating) - int32(opponent->Rating));
  101.     for (auto&& it : all)
  102.     {
  103.         for (auto&& p : it.Members)
  104.         {
  105.             p.OriginalGroup = &it;      // Now the pointer won't be changed, we can use it.
  106.             it.AddPlayer(p);
  107.         }
  108.         selection.push_back(&it);
  109.         int32 diff = std::abs(int32(ginfo->ArenaMatchmakerRating) - int32(it.Rating));
  110.         if (diff < min && it.Members.front().Info != ginfo)
  111.         {
  112.             min = diff;
  113.             opponent = &it;
  114.         }
  115.     }
  116.  
  117.     if (sWorld->getBoolConfig(CONFIG_SOLO_QUEUE_RATING_BALANCE_ENABLED))
  118.     {
  119.         std::sort(selection.begin(), selection.end(),
  120.             [](SoloGroup const* lhs, SoloGroup const* rhs)
  121.         {
  122.             return lhs->Rating < rhs->Rating;
  123.         });
  124.     }
  125.     else
  126.     {
  127.         std::random_shuffle(selection.begin(), selection.end(),
  128.             [&](int i)
  129.         {
  130.             if (i < 2)
  131.                 return 0;
  132.             return irand(0, i - 1);
  133.         });
  134.     }
  135.  
  136.     uint32 now = getMSTime();
  137.     for (auto&& it : selection)
  138.     {
  139.         auto& i = it->Current.front();
  140.         _log.Write("%u (%s) - %u rating (%u in queue)", i.Target->GetGUIDLow(),
  141.             i.Target->GetSpecialization() == PlayerSpec::Healer ? "healer" : "damager", i.Info->ArenaMatchmakerRating, (now - i.Info->JoinTime) / IN_MILLISECONDS);
  142.     }
  143.     _log.Write("Total queued: %u", uint32(selection.size()));
  144.  
  145.     if (selection.size() < 4)
  146.         return;
  147.  
  148.     auto it = std::find_if(selection.begin(), selection.end(), [=](SoloGroup const* g) { return g->Members.front().Info == ginfo; });
  149.     ASSERT(it != selection.end());
  150.     size_t groupIndex = std::distance(selection.begin(), it);
  151.     ASSERT(groupIndex < selection.size());
  152.     SoloGroup* group = *it;
  153.  
  154.     if (sWorld->getBoolConfig(CONFIG_SOLO_QUEUE_RATING_BALANCE_ENABLED))
  155.     {
  156.         //auto it = std::find(selection.begin(), selection.end(), opponent);
  157.         //ASSERT(it != selection.end());
  158.         size_t opponentIndex = selection.size() / 2;// std::distance(selection.begin(), it);
  159.  
  160.         auto makeTeam = [&](SoloGroup* group, size_t index, bool forward) -> bool
  161.         {
  162.             if (group->Current.size() == SoloQueue::TeamSize())
  163.                 return true;
  164.  
  165.             uint32 lower = group->Rating > baseRange ? group->Rating - baseRange : 0;
  166.             uint32 upper = group->Rating + baseRange;
  167.  
  168.             if (forward)
  169.             {
  170.                 for (size_t i = index; i < selection.size(); ++i)
  171.                 {
  172.                     auto right = selection[i];
  173.                     if (right->InTeam || right->Rating > upper || right->Rating < lower)
  174.                         continue;
  175.                     if (Merge(group, right, strong))
  176.                         return true;
  177.                 }
  178.             }
  179.             else
  180.             {
  181.                 for (size_t i = index; i != 0; --i)
  182.                 {
  183.                     auto right = selection[i];
  184.                     if (right->InTeam || right->Rating > upper || right->Rating < lower)
  185.                         continue;
  186.                     if (Merge(group, right, strong))
  187.                         return true;
  188.                 }
  189.             }
  190.             return false;
  191.         };
  192.  
  193.         std::vector<size_t> opponents;
  194.         opponents.reserve(selection.size());
  195.         opponents.push_back(opponentIndex);
  196.  
  197.         size_t i = 0;
  198.         bool plus = true;
  199.         bool minus = true;
  200.  
  201.         while (plus || minus)
  202.         {
  203.             ++i;
  204.             plus = opponentIndex + i < selection.size();
  205.             minus = i <= opponentIndex;
  206.             if (plus)
  207.                 opponents.push_back(opponentIndex + i);
  208.             if (minus)
  209.                 opponents.push_back(opponentIndex - i);
  210.         }
  211.  
  212.         for (auto&& idx : opponents)
  213.         {
  214.             opponent = selection[idx];
  215.             if (opponent == group)
  216.                 continue;
  217.  
  218.             group->InTeam = true;
  219.             opponent->InTeam = true;
  220.  
  221.             bool forward = opponent->Rating < group->Rating;
  222.             if (makeTeam(opponent, idx, forward) || makeTeam(opponent, idx, !forward))  // 2 players in opponent
  223.             {
  224.                 forward = group->Rating < opponent->Rating;
  225.                 if (makeTeam(group, groupIndex, forward) || makeTeam(group, groupIndex, !forward)) // 2 players in group
  226.                 {
  227.                     forward = opponent->Rating < group->Rating;
  228.                     if (makeTeam(opponent, idx, forward) || makeTeam(opponent, idx, !forward))  // 3 players in opponent
  229.                     {
  230.                         forward = group->Rating < opponent->Rating;
  231.                         if (makeTeam(group, groupIndex, forward) || makeTeam(group, groupIndex, !forward)) // 3 players in group
  232.                         {
  233.                             aTeam = group;
  234.                             hTeam = opponent;
  235.                             break;
  236.                         }
  237.                     }
  238.                 }
  239.             }
  240.  
  241.             group->Reset();
  242.             opponent->Reset();
  243.         }
  244.     }
  245.     else
  246.     {
  247.         for (auto&& opponent : selection)
  248.         {
  249.             if (opponent == group)
  250.                 continue;
  251.  
  252.             lower = opponent->Rating > baseRange ? opponent->Rating - baseRange : 0;
  253.             upper = opponent->Rating + baseRange;
  254.             group->InTeam = true;
  255.             opponent->InTeam = true;
  256.  
  257.             if (MakeTeam(opponent, upper, lower, selection, strong))
  258.             {
  259.                 lower = group->Rating > baseRange ? group->Rating - baseRange : 0;
  260.                 upper = group->Rating + baseRange;
  261.  
  262.                 if (MakeTeam(group, upper, lower, selection, strong))
  263.                 {
  264.                     aTeam = group;
  265.                     hTeam = opponent;
  266.                     break;
  267.                 }
  268.             }
  269.  
  270.             group->Reset();
  271.             opponent->Reset();
  272.         }
  273.     }
  274.  
  275.     if (!aTeam || !hTeam)
  276.     {
  277.         if (!strong)
  278.             return;
  279.         TaskScheduler::Default()->ScheduleInvocation(new CallbackTask([=]()
  280.         {
  281.             auto it = std::find(alliance.begin(), alliance.end(), ginfo);
  282.             if (it == alliance.end())
  283.             {
  284.                 it = std::find(horde.begin(), horde.end(), ginfo);
  285.                 if (it == horde.end())
  286.                     return;
  287.             }
  288.             DoMatchmaking(*it, extraDiff, false);
  289.         }));
  290.         return;
  291.     }
  292.  
  293.     _buff << "Groups are picked: ";
  294.     for (auto&& it : aTeam->Current)
  295.         _buff << it.Target->GetGUIDLow() << ' ';
  296.     _buff << "vs ";
  297.     for (auto&& it : hTeam->Current)
  298.         _buff << it.Target->GetGUIDLow() << ' ';
  299.     _log.Write(_buff.str().c_str());
  300.     _buff.str(std::string());
  301.  
  302.     // Invite to arena
  303.  
  304.     uint32 mmr = 0;
  305.     uint32 rating = 0;
  306.     for (auto&& it : aTeam->Current)
  307.     {
  308.         mmr += it.Info->ArenaMatchmakerRating;
  309.         rating += it.Info->ArenaTeamRating;
  310.     }
  311.  
  312.     mmr /= aTeam->Current.size();
  313.     rating /= aTeam->Current.size();
  314.     for (auto&& it : aTeam->Current)
  315.     {
  316.         it.Info->ArenaMatchmakerRating = mmr;
  317.         it.Info->ArenaTeamRating = rating;
  318.     }
  319.  
  320.     mmr = 0;
  321.     rating = 0;
  322.     for (auto&& it : hTeam->Current)
  323.     {
  324.         mmr += it.Info->ArenaMatchmakerRating;
  325.         rating += it.Info->ArenaTeamRating;
  326.     }
  327.  
  328.     mmr /= hTeam->Current.size();
  329.     rating /= hTeam->Current.size();
  330.     for (auto&& it : hTeam->Current)
  331.     {
  332.         it.Info->ArenaMatchmakerRating = mmr;
  333.         it.Info->ArenaTeamRating = rating;
  334.         it.Info->OpponentsMatchmakerRating = aTeam->Current.front().Info->ArenaMatchmakerRating;
  335.         it.Info->OpponentsTeamRating = aTeam->Current.front().Info->ArenaMatchmakerRating;
  336.     }
  337.  
  338.     for (auto&& it : aTeam->Current)
  339.     {
  340.         it.Info->OpponentsMatchmakerRating = mmr;
  341.         it.Info->OpponentsTeamRating = rating;
  342.     }
  343.  
  344.     for (auto&& it : aTeam->Current)
  345.     {
  346.         if (it.Info->Team != ALLIANCE)
  347.         {
  348.             if (alliance.empty() || it.Info != alliance.back())
  349.             {
  350.                 horde.remove(it.Info);
  351.                 alliance.push_back(it.Info);
  352.             }
  353.         }
  354.     }
  355.     for (auto&& it : hTeam->Current)
  356.     {
  357.         if (it.Info->Team != HORDE)
  358.         {
  359.             if (horde.empty() || it.Info != horde.back())
  360.             {
  361.                 alliance.remove(it.Info);
  362.                 horde.push_back(it.Info);
  363.             }
  364.         }
  365.     }
  366.  
  367.     Battleground* arena = sBattlegroundMgr->CreateNewBattleground(BATTLEGROUND_AA, bracketEntry, ARENA_TYPE_3v3, true);
  368.     if (!arena)
  369.     {
  370.         sLog->outError("BattlegroundQueue::Update couldn't create arena instance for rated arena match!");
  371.         return;
  372.     }
  373.  
  374.     arena->EnableSoloMode();
  375.     arena->SetArenaMatchmakerRating(ALLIANCE, aTeam->Current.front().Info->ArenaMatchmakerRating);
  376.     arena->SetArenaMatchmakerRating(HORDE, hTeam->Current.front().Info->ArenaMatchmakerRating);
  377.     arena->SetArenaTeamRating(ALLIANCE, aTeam->Current.front().Info->ArenaTeamRating);
  378.     arena->SetArenaTeamRating(HORDE, hTeam->Current.front().Info->ArenaTeamRating);
  379.  
  380.     for (auto&& team : { aTeam, hTeam })
  381.     {
  382.         for (auto&& it : team->Current)
  383.         {
  384.             InviteGroupToBG(it.Info, arena, team == aTeam ? ALLIANCE : HORDE);
  385.             arena->AddParticipant(team == aTeam ? TEAM_ALLIANCE : TEAM_HORDE, it.Target->GetGUID(), it.Target->GetArenaTeamId(ARENA_SLOT_5v5));
  386.         }
  387.     }
  388.  
  389.     arena->SetArenaTeamIdForTeam(ALLIANCE, 0);
  390.     arena->SetArenaTeamIdForTeam(HORDE, 0);
  391.     arena->StartBattleground();
  392.  
  393.     sArenaMgr->AddMatchForWatching(aTeam, hTeam, arena);
  394.     RecordResult("SoloQueue::DoMatchmaking");
  395. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement