Advertisement
Guest User

Garrison Mission Manager - new features v2 - merged with v7

a guest
Nov 28th, 2014
299
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 23.35 KB | None | 0 0
  1. -- Confused about mix of CamelCase and_underscores?
  2. -- Camel case comes from copypasta of how Blizzard calls returns/fields in their code and deriveates
  3. -- Underscore are my own variables
  4.  
  5. local dump = DevTools_Dump
  6. local tinsert = table.insert
  7. local tsort = table.sort
  8. local wipe = wipe
  9. local pairs = pairs
  10. local GARRISON_CURRENCY = GARRISON_CURRENCY
  11. local GarrisonMissionFrame = GarrisonMissionFrame
  12. local GarrisonLandingPage = GarrisonLandingPage
  13. local GarrisonRecruitSelectFrame = GarrisonRecruitSelectFrame
  14. local MissionPage = GarrisonMissionFrame.MissionTab.MissionPage
  15. local AddFollowerToMission = C_Garrison.AddFollowerToMission
  16. local GetPartyMissionInfo = C_Garrison.GetPartyMissionInfo
  17. local RemoveFollowerFromMission = C_Garrison.RemoveFollowerFromMission
  18. local GARRISON_FOLLOWER_IN_PARTY = GARRISON_FOLLOWER_IN_PARTY
  19. local NUM_OPTIONS = 1
  20.  
  21. local top_for_mission = {}
  22. local top_for_mission_dirty = true
  23.  
  24. local metrics = {"successChance", "expectedResources", "expectedProgress", "expectedProgressPerFollowerHour"}
  25.  
  26. local filtered_followers = {}
  27. local filtered_followers_count
  28. local filtered_followers_dirty = true
  29.  
  30. local event_frame = CreateFrame("Frame")
  31. local events_filtered_followers_dirty = {
  32.    GARRISON_FOLLOWER_LIST_UPDATE = true,
  33.    GARRISON_FOLLOWER_XP_CHANGED = true,
  34.    GARRISON_FOLLOWER_REMOVED = true,
  35. }
  36. local events_top_for_mission_dirty = {
  37.    GARRISON_MISSION_NPC_OPENED = true,
  38.    GARRISON_MISSION_LIST_UPDATE = true,
  39. }
  40. event_frame:SetScript("OnEvent", function(self, event)
  41.    -- if events_top_for_mission_dirty[event] then top_for_mission_dirty = true end
  42.    -- if events_filtered_followers_dirty[event] then filtered_followers_dirty = true end
  43.    -- Let's clear both for now, or else we often miss one follower state update when we start mission
  44.    if events_top_for_mission_dirty[event] or events_filtered_followers_dirty[event] then
  45.       top_for_mission_dirty = true
  46.       filtered_followers_dirty = true
  47.    end
  48. end)
  49. for event in pairs(events_top_for_mission_dirty) do event_frame:RegisterEvent(event) end
  50. for event in pairs(events_filtered_followers_dirty) do event_frame:RegisterEvent(event) end
  51.  
  52. local gmm_buttons = {}
  53.  
  54. function GMM_dumpl(pattern, ...)
  55.    local names = { strsplit(",", pattern) }
  56.    for idx = 1, select('#', ...) do
  57.       local name = names[idx]
  58.       if name then name = name:gsub("^%s+", ""):gsub("%s+$", "") end
  59.       print(GREEN_FONT_COLOR_CODE, idx, name, FONT_COLOR_CODE_CLOSE)
  60.       dump((select(idx, ...)))
  61.    end
  62. end
  63.  
  64. -- Print contents of `tbl`, with indentation.
  65. -- `indent` sets the initial level of indentation.
  66. function tprint (tbl, indent)
  67.    if not indent then indent = 0 end
  68.    for k, v in pairs(tbl) do
  69.       formatting = string.rep("  ", indent) .. k .. ": "
  70.       if type(v) == "table" then
  71.          print(formatting)
  72.          tprint(v, indent+1)
  73.       else
  74.          print(formatting .. tostring(v))
  75.       end
  76.    end
  77. end
  78.  
  79. local xp_to_level = {[90]=400, [91]=800, [92]=1200, [93]=1600, [94]=2000,
  80.                      [95]=3000, [96]=3500, [97]=4000,
  81.                      [98]=5400, [99]=6000}
  82. local xp_to_upgrade = {[2]=60000, [3]=120000}
  83. local function follower_progress(mission_level, follower, xp)
  84.    if not follower then return 0 end
  85.    if follower.level >= 100 and follower.quality >= 4 then return 0 end -- epic followers at max level cannot gain xp
  86.  
  87.    -- express follower xp as a percentage of next level/upgrade
  88.    local progress = 0
  89.    if follower.level < 100 then
  90.       progress = xp / xp_to_level[follower.level] * 100
  91.    else
  92.       progress = xp / xp_to_upgrade[follower.quality] * 100
  93.    end
  94.  
  95.    -- scale follower xp by level delta
  96.    local level_delta = mission_level - follower.level
  97.    if level_delta <= 0 then return progress end  -- normal xp gain
  98.    if level_delta <= 2 then return progress / 2 end  -- slightly underlevel followers gain half xp
  99.    return progress / 10  -- very underlevel followers gain 10% xp
  100. end
  101.  
  102. -- return which of left or right is better
  103. -- if metric is any field present in left/right, it will be prioritized first (higher is better)
  104. local function BetterMissionOutcome(left, right, metric)
  105.    if not left then return 1 end
  106.    if not right then return -1 end
  107.  
  108.    if metric and left[metric] and right[metric] then
  109.       if left[metric] < right[metric] then return 1 end
  110.       if left[metric] > right[metric] then return -1 end
  111.    end
  112.  
  113.    -- if no metric specified, or tied on that metric, break ties by the old algorithm:
  114.    
  115.    if left.expectedResources < right.expectedResources then return 1 end
  116.    if left.expectedResources > right.expectedResources then return -1 end
  117.  
  118.    if left.successItem or right.successItem then
  119.       if left.successChance < right.successChance then return 1 end
  120.       if left.successChance > right.successChance then return -1 end
  121.    end
  122.  
  123.    if left.expectedProgressPerFollowerHour < right.expectedProgressPerFollowerHour then return 1  end
  124.    if left.expectedProgressPerFollowerHour > right.expectedProgressPerFollowerHour then return -1 end
  125.  
  126.    if left.expectedProgress < right.expectedProgress then return 1  end
  127.    if left.expectedProgress > right.expectedProgress then return -1 end
  128.  
  129.    if left.successChance < right.successChance then return 1 end
  130.    if left.successChance > right.successChance then return -1 end
  131.  
  132.    if left.totalTimeSeconds > right.totalTimeSeconds then return 1  end
  133.    if left.totalTimeSeconds < right.totalTimeSeconds then return -1 end
  134.  
  135.    return 0
  136. end
  137.  
  138. local _, _, garrison_currency_texture = GetCurrencyInfo(GARRISON_CURRENCY)
  139. garrison_currency_texture = "|T" .. garrison_currency_texture .. ":0|t"
  140. local time_texture = "|TInterface\\Icons\\spell_holy_borrowedtime:0|t"
  141.  
  142. local function FindBestFollowersForMission(mission, followers)
  143.    local top_by_metrics = {}
  144.    for _, metric in ipairs(metrics) do
  145.       top_by_metrics[metric] = {}
  146.    end
  147.  
  148.    local min, max = {}, {}
  149.    local followers_count = #followers
  150.  
  151.    local slots = mission.numFollowers
  152.    if slots > followers_count then return top_by_metrics end
  153.  
  154.    event_frame:UnregisterEvent("GARRISON_FOLLOWER_LIST_UPDATE")
  155.    GarrisonMissionFrame:UnregisterEvent("GARRISON_FOLLOWER_LIST_UPDATE")
  156.    GarrisonLandingPage:UnregisterEvent("GARRISON_FOLLOWER_LIST_UPDATE")
  157.    GarrisonRecruitSelectFrame:UnregisterEvent("GARRISON_FOLLOWER_LIST_UPDATE")
  158.    if FollowerLocationInfoFrame then FollowerLocationInfoFrame:UnregisterEvent("GARRISON_FOLLOWER_LIST_UPDATE") end
  159.  
  160.    local mission_id = mission.missionID
  161.    if C_Garrison.GetNumFollowersOnMission(mission_id) > 0 then
  162.       for idx = 1, #followers do
  163.          RemoveFollowerFromMission(mission_id, followers[idx].followerID)
  164.       end
  165.    end
  166.  
  167.    for idx = 1, slots do
  168.       max[idx] = followers_count - slots + idx
  169.       min[idx] = nil
  170.    end
  171.    for idx = slots+1, 3 do
  172.       max[idx] = followers_count + 1
  173.       min[idx] = followers_count + 1
  174.    end
  175.  
  176.    local mission_level = C_Garrison.GetBasicMissionInfo(mission_id).level
  177.    local _, baseXP = C_Garrison.GetMissionInfo(mission_id)
  178.  
  179.    local successXP = 0
  180.    local successResources = 0
  181.    local successItem = nil
  182.    for _, reward in pairs(mission.rewards) do
  183.       if reward.currencyID == GARRISON_CURRENCY then successResources = successResources + reward.quantity end  
  184.       if reward.followerXP then successXP = successXP + reward.followerXP end
  185.       if reward.itemID and reward.itemID ~= 120205 then successItem = reward.itemID end  -- itemID 120205 is player XP reward
  186.    end
  187.  
  188.    for i1 = 1, max[1] do
  189.       local follower1 = followers[i1]
  190.       local follower1_id = follower1.followerID
  191.       for i2 = min[2] or (i1 + 1), max[2] do
  192.          local follower2 = followers[i2]
  193.          local follower2_id = follower2 and follower2.followerID
  194.          for i3 = min[3] or (i2 + 1), max[3] do
  195.             local follower3 = followers[i3]
  196.             local follower3_id = follower3 and follower3.followerID
  197.  
  198.             -- Assign followers to mission
  199.             if not AddFollowerToMission(mission_id, follower1_id) then --[[ error handling! ]] end
  200.             if follower2 and not AddFollowerToMission(mission_id, follower2_id) then --[[ error handling! ]] end
  201.             if follower3 and not AddFollowerToMission(mission_id, follower3_id) then --[[ error handling! ]] end
  202.  
  203.             -- Calculate result
  204.             local totalTimeString, totalTimeSeconds, isMissionTimeImproved, successChance, partyBuffs, isEnvMechanicCountered, xpBonus, materialMultiplier = GetPartyMissionInfo(mission_id)
  205.  
  206.             local baseProgress = 0
  207.             baseProgress = baseProgress + follower_progress(mission_level, follower1, baseXP + xpBonus)
  208.             baseProgress = baseProgress + follower_progress(mission_level, follower2, baseXP + xpBonus)
  209.             baseProgress = baseProgress + follower_progress(mission_level, follower3, baseXP + xpBonus)
  210.  
  211.             local successProgress = 0
  212.             -- TODO: how does bonusXP apply to success rewards?
  213.             successProgress = successProgress + follower_progress(mission_level, follower1, successXP)
  214.             successProgress = successProgress + follower_progress(mission_level, follower2, successXP)
  215.             successProgress = successProgress + follower_progress(mission_level, follower3, successXP)
  216.  
  217.             local expectedResources = successResources * materialMultiplier * successChance / 100
  218.             local expectedProgress = baseProgress + (successProgress * successChance / 100)
  219.             local expectedProgressPerFollowerHour = expectedProgress * 3600 / totalTimeSeconds / mission.numFollowers
  220.  
  221.             local outcome = {}
  222.             outcome[1] = follower1
  223.             outcome[2] = follower2
  224.             outcome[3] = follower3
  225.             outcome.successChance = successChance
  226.             outcome.successItem = successItem
  227.             outcome.expectedResources = expectedResources
  228.             outcome.expectedProgress = expectedProgress
  229.             outcome.expectedProgressPerFollowerHour = expectedProgressPerFollowerHour
  230.             outcome.totalTimeSeconds = totalTimeSeconds
  231.             outcome.followersUsed = mission.numFollowers
  232.  
  233.             for _, metric in ipairs(metrics) do
  234.                local top_by_metric = top_by_metrics[metric]
  235.                for idx = 1, NUM_OPTIONS do
  236.                   if BetterMissionOutcome(top_by_metric[idx], outcome, metric) > 0 then
  237.                      tinsert(top_by_metric, idx, outcome)
  238.                      tremove(top_by_metric, NUM_OPTIONS + 1)
  239.                      break
  240.                   end
  241.                end
  242.             end
  243.  
  244.             -- Unasssign
  245.             RemoveFollowerFromMission(mission_id, follower1_id)
  246.             if follower2 then RemoveFollowerFromMission(mission_id, follower2_id) end
  247.             if follower3 then RemoveFollowerFromMission(mission_id, follower3_id) end
  248.          end
  249.       end
  250.    end
  251.    -- dump(top[1])
  252.  
  253.    event_frame:RegisterEvent("GARRISON_FOLLOWER_LIST_UPDATE")
  254.    GarrisonMissionFrame:RegisterEvent("GARRISON_FOLLOWER_LIST_UPDATE")
  255.    GarrisonLandingPage:RegisterEvent("GARRISON_FOLLOWER_LIST_UPDATE")
  256.    GarrisonRecruitSelectFrame:RegisterEvent("GARRISON_FOLLOWER_LIST_UPDATE")
  257.    if FollowerLocationInfoFrame then FollowerLocationInfoFrame:RegisterEvent("GARRISON_FOLLOWER_LIST_UPDATE") end
  258.  
  259.    -- dump(top)
  260.    -- local location, xp, environment, environmentDesc, environmentTexture, locPrefix, isExhausting, enemies = C_Garrison.GetMissionInfo(missionID);
  261.    -- /run GMM_dumpl("location, xp, environment, environmentDesc, environmentTexture, locPrefix, isExhausting, enemies", C_Garrison.GetMissionInfo(GarrisonMissionFrame.MissionTab.MissionPage.missionInfo.missionID))
  262.    -- /run GMM_dumpl("totalTimeString, totalTimeSeconds, isMissionTimeImproved, successChance, partyBuffs, isEnvMechanicCountered, xpBonus, materialMultiplier", C_Garrison.GetPartyMissionInfo(GarrisonMissionFrame.MissionTab.MissionPage.missionInfo.missionID))
  263.    return top_by_metrics
  264. end
  265.  
  266. local function SortFollowersByLevel(a, b)
  267.    local a_level = a.level
  268.    local b_level = b.level
  269.    if a_level ~= b_level then return a_level > b_level end
  270.    return a.iLevel > b.iLevel
  271. end
  272.  
  273. local function GetFilteredFollowers()
  274.    if not filtered_followers_dirty then
  275.       return filtered_followers, filtered_followers_count
  276.    end
  277.  
  278.    local followers = C_Garrison.GetFollowers()
  279.    wipe(filtered_followers)
  280.    filtered_followers_count = 0
  281.    for idx = 1, #followers do
  282.       local follower = followers[idx]
  283.       repeat
  284.          if not follower.isCollected then break end
  285.          local status = follower.status
  286.          if status and status ~= GARRISON_FOLLOWER_IN_PARTY then break end
  287.  
  288.          filtered_followers_count = filtered_followers_count + 1
  289.          filtered_followers[filtered_followers_count] = follower
  290.       until true
  291.    end
  292.  
  293.    tsort(filtered_followers, SortFollowersByLevel)
  294.  
  295.    -- dump(filtered_followers)
  296.    filtered_followers_dirty = false
  297.    top_for_mission_dirty = true
  298.    return filtered_followers, filtered_followers_count
  299. end
  300.  
  301. -- only works for positive numbers
  302. function sigfigs(number, sigDigits)
  303.    if not number then return "" end
  304.    if number == 0 then return "0" end
  305.    local target = math.pow(10, sigDigits)
  306.    local shifted = 0
  307.    while number < target do
  308.       number = number * 10
  309.       shifted = shifted + 1
  310.    end
  311.    while number >= target do
  312.       number = number / 10
  313.       shifted = shifted - 1
  314.    end
  315.    number = math.floor(number + 0.5)
  316.    number = number / math.pow(10, shifted)
  317.    return string.format("%." .. shifted .. "f", number)
  318. end
  319.  
  320. local function FormatTextForMetric(outcome, metric)
  321.    if not outcome then
  322.       return ""
  323.    elseif metric == "successChance" then
  324.       local itemRewardString = ""
  325.       if outcome.successItem then
  326.          local itemName, itemLink, itemRarity, itemLevel, itemMinLevel, itemType, itemSubType, itemStackCount, itemEquipLoc, itemTexture, itemSellPrice = GetItemInfo(outcome.successItem)
  327.          if itemTexture then
  328.             itemRewardString = string.format("|T%s:0|t ", itemTexture)
  329.          end
  330.       end
  331.       return string.format("%s%d%%", itemRewardString, outcome.successChance)
  332.    elseif metric == "expectedResources" then
  333.       return string.format("%.1f %s", outcome.expectedResources, garrison_currency_texture)
  334.    elseif metric == "expectedProgress" then
  335.       return string.format("%s%% |TInterface\\Icons\\Spell_ChargePositive:0|t", sigfigs(outcome.expectedProgress, 2))
  336.    elseif metric == "expectedProgressPerFollowerHour" then
  337.       return string.format("%s%% |TInterface\\Icons\\Spell_ChargePositive:0|t/|TInterface\\Icons\\Achievement_Character_Human_Female:0|t|TInterface\\Icons\\INV_Misc_PocketWatch_01:0|t", sigfigs(outcome.expectedProgressPerFollowerHour, 2))
  338.    else
  339.       return string.format("%d%% ??", outcome.successChance)
  340.    end
  341. end
  342.  
  343. local function PickMetric(outcomes)
  344.    -- Always prioritize garrison resources, if they're available.
  345.    if outcomes["expectedResources"]["expectedResources"] > 0 then return "expectedResources" end
  346.  
  347.    -- Then prioritize winning items.
  348.    if outcomes["successChance"]["successItem"] then return "successChance" end
  349.  
  350.    -- Finally, prioritize experience.
  351.    return "expectedProgressPerFollowerHour"
  352. end
  353.  
  354. local function SetTeamButtonText(button, top_entry)
  355.    local metric = PickMetric(top_entry)
  356.    button:SetText(FormatTextForMetric(top_entry[metric], metric))
  357. end
  358.  
  359. local available_missions = {}
  360. local function BestForCurrentSelectedMission()
  361.    local missionInfo = MissionPage.missionInfo
  362.    local mission_id = missionInfo.missionID
  363.  
  364.    -- print("Mission ID:", mission_id)
  365.  
  366.    local filtered_followers, filtered_followers_count = GetFilteredFollowers()
  367.  
  368.    C_Garrison.GetAvailableMissions(available_missions)
  369.    local mission
  370.    for idx = 1, #available_missions do
  371.       if available_missions[idx].missionID == mission_id then
  372.          mission = available_missions[idx]
  373.          break
  374.       end
  375.    end
  376.  
  377.    -- dump(mission)
  378.  
  379.    local top_by_metrics = FindBestFollowersForMission(mission, filtered_followers)
  380.  
  381.    for _, metric in ipairs(metrics) do
  382.       for idx = 1, NUM_OPTIONS do
  383.          local button = gmm_buttons['MissionPage_' .. metric .. idx]
  384.          local top_entry = top_by_metrics[metric][idx]
  385.          button[1] = top_entry[1] and top_entry[1].followerID or nil
  386.          button[2] = top_entry[2] and top_entry[2].followerID or nil
  387.          button[3] = top_entry[3] and top_entry[3].followerID or nil
  388.          button:SetText(FormatTextForMetric(top_entry, metric))
  389.       end
  390.    end
  391. end
  392.  
  393. local function MissionPage_PartyButtonOnClick(self)
  394.    if self[1] then
  395.       event_frame:UnregisterEvent("GARRISON_FOLLOWER_LIST_UPDATE")
  396.       local MissionPageFollowers = GarrisonMissionFrame.MissionTab.MissionPage.Followers
  397.       for idx = 1, #MissionPageFollowers do
  398.          GarrisonMissionPage_ClearFollower(MissionPageFollowers[idx])
  399.       end
  400.  
  401.       for idx = 1, #MissionPageFollowers do
  402.          local followerFrame = MissionPageFollowers[idx]
  403.          local follower = self[idx]
  404.          if follower then
  405.             local followerInfo = C_Garrison.GetFollowerInfo(follower)
  406.             GarrisonMissionPage_SetFollower(followerFrame, followerInfo)
  407.          end
  408.       end
  409.       event_frame:RegisterEvent("GARRISON_FOLLOWER_LIST_UPDATE")
  410.    end
  411.  
  412.    GarrisonMissionPage_UpdateMissionForParty()
  413. end
  414.  
  415. local function MissionList_PartyButtonOnClick(self)
  416.    return self:GetParent():Click()
  417. end
  418.  
  419. -- Add more data to mission list over Blizzard's own
  420. -- GarrisonMissionList_Update
  421. local function GarrisonMissionList_Update_More()
  422.    local self = GarrisonMissionFrame.MissionTab.MissionList
  423.    local scrollFrame = self.listScroll
  424.    local buttons = scrollFrame.buttons
  425.    local numButtons = #buttons
  426.  
  427.    if self.showInProgress then
  428.       for i = 1, numButtons do
  429.          gmm_buttons['MissionList' .. i]:Hide()
  430.       end
  431.       return
  432.    end
  433.  
  434.    local missions = self.availableMissions
  435.    local numMissions = #missions
  436.    if numMissions == 0 then return end
  437.  
  438.    if top_for_mission_dirty then
  439.       wipe(top_for_mission)
  440.       top_for_mission_dirty = false
  441.    end
  442.  
  443.    local missions = self.availableMissions
  444.    local offset = HybridScrollFrame_GetOffset(scrollFrame)
  445.  
  446.    local filtered_followers, filtered_followers_count = GetFilteredFollowers()
  447.    local more_missions_to_cache
  448.  
  449.    for i = 1, numButtons do
  450.       local button = buttons[i]
  451.       local alpha = 1
  452.       local index = offset + i
  453.       if index <= numMissions then
  454.          local mission = missions[index]
  455.          local gmm_button = gmm_buttons['MissionList' .. i]
  456.          if mission.numFollowers > filtered_followers_count then
  457.             button:SetAlpha(0.3)
  458.             gmm_button:SetText("")
  459.          else
  460.             local top_for_this_mission = top_for_mission[mission.missionID]
  461.             if not top_for_this_mission then
  462.                if more_missions_to_cache then
  463.                   more_missions_to_cache = more_missions_to_cache + 1
  464.                else
  465.                   more_missions_to_cache = 0
  466.                   local outcomes = FindBestFollowersForMission(mission, filtered_followers)  
  467.                   top_for_this_mission = {}
  468.                   for _, metric in ipairs(metrics) do
  469.                      top_for_this_mission[metric] = outcomes[metric][1]
  470.                   end
  471.                   top_for_mission[mission.missionID] = top_for_this_mission
  472.                end
  473.             end
  474.  
  475.             if top_for_this_mission then
  476.                SetTeamButtonText(gmm_button, top_for_this_mission)
  477.             else
  478.                gmm_button:SetText("...")
  479.             end
  480.             button:SetAlpha(1)
  481.          end
  482.          gmm_button:Show()
  483.       end
  484.    end
  485.  
  486.    if more_missions_to_cache and more_missions_to_cache > 0 then
  487.       -- print(more_missions_to_cache, GetTime())
  488.       C_Timer.After(0.001, GarrisonMissionList_Update_More)
  489.    end
  490. end
  491. hooksecurefunc("GarrisonMissionList_Update", GarrisonMissionList_Update_More)
  492. hooksecurefunc(GarrisonMissionFrame.MissionTab.MissionList.listScroll, "update", GarrisonMissionList_Update_More)
  493.  
  494. local function MissionPage_ButtonsInit()
  495.    local prev_metric
  496.    for _, metric in ipairs(metrics) do
  497.       local prev_option
  498.       for idx = 1, NUM_OPTIONS do
  499.          local button_name = 'MissionPage_' .. metric .. idx
  500.          if not gmm_buttons[button_name] then
  501.             local set_followers_button = CreateFrame("Button", nil, GarrisonMissionFrame.MissionTab.MissionPage, "UIPanelButtonTemplate")
  502.             set_followers_button:SetText(button_name)
  503.             set_followers_button:SetWidth(120)
  504.             set_followers_button:SetHeight(35)
  505.             if prev_option then
  506.                set_followers_button:SetPoint("TOPLEFT", prev_option, "TOPRIGHT", 0, 0)
  507.             else
  508.                if prev_metric then
  509.                   set_followers_button:SetPoint("TOPLEFT", prev_metric, "BOTTOMLEFT", 0, -20)
  510.                else
  511.                   set_followers_button:SetPoint("TOPLEFT", GarrisonMissionFrame.MissionTab.MissionPage, "TOPRIGHT", 0, 0)
  512.                end
  513.                prev_metric = set_followers_button
  514.             end
  515.             set_followers_button:SetScript("OnClick", MissionPage_PartyButtonOnClick)
  516.             set_followers_button:Show()
  517.             prev_option = set_followers_button
  518.             gmm_buttons[button_name] = set_followers_button
  519.          end
  520.       end
  521.    end
  522. end
  523.  
  524. local function MissionList_ButtonsInit()
  525.    local level_anchor = GarrisonMissionFrame.MissionTab.MissionList.listScroll
  526.    local blizzard_buttons = GarrisonMissionFrame.MissionTab.MissionList.listScroll.buttons
  527.    for idx = 1, #blizzard_buttons do
  528.       if not gmm_buttons['MissionList' .. idx] then
  529.          local blizzard_button = blizzard_buttons[idx]
  530.  
  531.          -- move first reward to left a little, rest are anchored to first
  532.          local reward = blizzard_button.Rewards[1]
  533.          for point_idx = 1, reward:GetNumPoints() do
  534.             local point, relative_to, relative_point, x, y = reward:GetPoint(point_idx)
  535.             if point == "RIGHT" then
  536.                x = x - 60
  537.                reward:SetPoint(point, relative_to, relative_point, x, y)
  538.                break
  539.             end
  540.          end
  541.  
  542.          local set_followers_button = CreateFrame("Button", nil, blizzard_button, "UIPanelButtonTemplate")
  543.          set_followers_button:SetText(idx)
  544.          set_followers_button:SetWidth(80)
  545.          set_followers_button:SetHeight(35)
  546.          set_followers_button:SetPoint("LEFT", blizzard_button, "RIGHT", -65, 0)
  547.          set_followers_button:SetScript("OnClick", MissionList_PartyButtonOnClick)
  548.          gmm_buttons['MissionList' .. idx] = set_followers_button
  549.       end
  550.    end
  551.    -- GarrisonMissionFrame.MissionTab.MissionList.listScroll.scrollBar:SetFrameLevel(gmm_buttons['MissionList1']:GetFrameLevel() - 3)
  552. end
  553.  
  554. MissionPage_ButtonsInit()
  555. MissionList_ButtonsInit()
  556. hooksecurefunc("GarrisonMissionPage_ShowMission", BestForCurrentSelectedMission)
  557. -- local count = 0
  558. -- hooksecurefunc("GarrisonFollowerList_UpdateFollowers", function(self) count = count + 1 print("GarrisonFollowerList_UpdateFollowers", count, self:GetName(), self:GetParent():GetName()) end)
  559.  
  560. -- Globals deliberately exposed for people outside
  561. function GMM_Click(button_name)
  562.    local button = gmm_buttons[button_name]
  563.    if button then button:Click() end
  564. end
  565.  
  566. -- /dump GarrisonMissionFrame.MissionTab.MissionList.listScroll.buttons
  567. -- /dump GarrisonMissionFrame.MissionTab.MissionList.listScroll.scrollBar
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement