From 688cba6df9565c5155e8ea285ad5311cb82132cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=2E=20Jackar=20Muti=C5=A1?= Date: Sun, 29 Jan 2023 13:41:17 +0100 Subject: [PATCH] feat: spec detection, new raids, dualspec, bugfix --- .gitignore | 2 + RaidBrowser/core.lua | 16 ++-- RaidBrowser/gui.lua | 8 +- RaidBrowser/raidset_frame.lua | 98 +++++++++++++++++++- RaidBrowser/stats.lua | 168 +++++++++++++++++++++++++++++++--- 5 files changed, 266 insertions(+), 26 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a414a50 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.vscode/ +.history/ diff --git a/RaidBrowser/core.lua b/RaidBrowser/core.lua index 620d35a..219619c 100644 --- a/RaidBrowser/core.lua +++ b/RaidBrowser/core.lua @@ -157,7 +157,7 @@ local raid_list = { }, { - name = 'toc10hc', + name = 'togc10hc', instance_name = 'Trial of the Crusader', size = 10, patterns = std.algorithm.copy_back( @@ -170,7 +170,7 @@ local raid_list = { }, { - name = 'toc25hc', + name = 'togc25hc', instance_name = 'Trial of the Crusader', size = 25, patterns = std.algorithm.copy_back( @@ -884,12 +884,13 @@ end lfm_channel_listeners = { ['CHAT_MSG_CHANNEL'] = {}, ['CHAT_MSG_YELL'] = {}, + ['CHAT_MSG_SAY'] = {}, }; local channel_listeners = {}; local function is_lfm_channel(channel) - return channel == 'CHAT_MSG_CHANNEL' or channel == 'CHAT_MSG_YELL'; + return channel == 'CHAT_MSG_CHANNEL' or channel == 'CHAT_MSG_YELL' or channel == 'CHAT_MSG_SAY'; end local function event_handler(self, event, message, sender) @@ -927,7 +928,7 @@ local function refresh_lfm_messages() end function raid_browser:OnEnable() - raid_browser:Print('loaded. Type /rb to toggle the raid browser.') + -- raid_browser:Print('loaded. Type /rb to toggle the raid browser.') if not raid_browser_character_current_raidset then raid_browser_character_current_raidset = 'Active'; @@ -935,13 +936,13 @@ function raid_browser:OnEnable() if not raid_browser_character_raidsets then raid_browser_character_raidsets = { - primary = {}, - secondary = {}, + Primary = {}, + Secondary = {}, }; end -- LFM messages expire after 60 seconds - raid_browser.expiry_time = 60; + raid_browser.expiry_time = 120; raid_browser.lfm_messages = {} raid_browser.timer = raid_browser.set_timer(10, refresh_lfm_messages, true) @@ -950,6 +951,7 @@ function raid_browser:OnEnable() end raid_browser.gui.raidset.initialize(); + raid_browser.check_button() end function raid_browser:OnDisable() diff --git a/RaidBrowser/gui.lua b/RaidBrowser/gui.lua index 4dd6491..0569d98 100644 --- a/RaidBrowser/gui.lua +++ b/RaidBrowser/gui.lua @@ -43,6 +43,10 @@ local function set_sort(column) end end +function raid_browser.set_sort(column) + set_sort(column) +end + local function get_sorted_messages() local keys = {} for key,info in pairs(raid_browser.lfm_messages) do @@ -193,6 +197,8 @@ local function assign_lfr_button(button, host_name, lfm_info, index) button.damageIcon:SetTexture("Interface\\LFGFrame\\LFGRole"); button.partyIcon:SetTexture("Interface\\LFGFrame\\LFGRole"); +button:SetScript("OnDoubleClick", on_join) + button:SetScript('OnEnter', function(button) GameTooltip:SetOwner(button, 'ANCHOR_RIGHT'); @@ -306,4 +312,4 @@ LFRBrowseFrameListButton_SetData = insert_lfm_button LFRFrame_SetActiveTab(2) LFRParentFrameTab1:Hide(); -LFRParentFrameTab2:Hide(); \ No newline at end of file +LFRParentFrameTab2:Hide(); diff --git a/RaidBrowser/raidset_frame.lua b/RaidBrowser/raidset_frame.lua index 67da821..7fff430 100644 --- a/RaidBrowser/raidset_frame.lua +++ b/RaidBrowser/raidset_frame.lua @@ -18,17 +18,44 @@ local function is_secondary_selected(option) return ('Secondary' == current_selection); end +local function is_both_selected(option) + return ('Both' == current_selection); +end + local function set_selection(selection) local text = ''; if selection == 'Active' then text = 'Active'; + + elseif selection == 'Both' then + local spec1, gs1 = raid_browser.stats.get_raidset('Primary') + local spec2, gs2 = raid_browser.stats.get_raidset('Secondary') + + + if spec1 and gs1 then + text = text .. gs1 .. ' ' .. spec1 + else + text = text .. '-' + end + text = text .. ' / ' + if spec2 and gs2 then + text = text .. gs2 .. ' ' .. spec2 + else + text = text .. '-' + end + if not (spec1 or spec2) then + text = 'Set any spec first'; + end + else local spec, gs = raid_browser.stats.get_raidset(selection) if not spec then text = 'Open'; elseif not gs then text = spec; + else + text = gs..' '..spec end end @@ -39,16 +66,25 @@ end local function on_active() set_selection('Active'); raid_browser.stats.select_current_raidset('Active'); + raid_browser.check_button() end local function on_primary() set_selection('Primary'); raid_browser.stats.select_current_raidset('Primary'); + raid_browser.check_button() end local function on_secondary() set_selection('Secondary'); raid_browser.stats.select_current_raidset('Secondary'); + raid_browser.check_button() +end + +local function on_both() + set_selection('Both'); + raid_browser.stats.select_current_raidset('Both'); + raid_browser.check_button() end local menu = { @@ -69,16 +105,49 @@ local menu = { func = on_secondary, checked = is_secondary_selected, }, + + { + text = "Both", + func = on_both, + checked = is_both_selected, + } } +-- Get the menu option text +local function get_option_active(option) + local spec, gs = raid_browser.stats.active_spec(), GearScore_GetScore(UnitName('player'), 'player'); + return (option .. ': ' .. gs .. ' ' .. spec) +end + -- Get the menu option text local function get_option_text(option) - local spec = raid_browser.stats.get_raidset(option); + local spec, gs = raid_browser.stats.get_raidset(option); if not spec then return (option .. ': Open'); end - return (option .. ': ' .. spec); + return (option .. ': ' .. gs .. ' ' .. spec); +end + +-- Get the menu option texts +local function get_option_texts(option) + local spec1, gs1 = raid_browser.stats.get_raidset('Primary'); + local spec2, gs2 = raid_browser.stats.get_raidset('Secondary'); + if not spec1 then + return (option .. ': Open'); + end + + if not (spec1 or spec2) then + return (option .. ': Set any spec first') + elseif (spec1 and spec2) then + return (option .. ': ' .. gs1 .. ' ' .. spec1 .. ' / ' .. gs2 .. ' ' .. spec2) + elseif spec1 then + return (option .. ': ' .. gs1 .. ' ' .. spec1 .. ' / ' .. '-') + elseif spec2 then + return (option .. ': ' .. '-' .. ' / ' .. gs2 .. ' ' .. spec2) + end + + return (option .. ': ' .. gs1 .. ' ' .. spec1 .. ' / ' .. gs2 .. ' ' .. spec2); end -- Setup dropdown menu for the raidset selection @@ -86,8 +155,10 @@ frame:SetPoint("CENTER", LFRBrowseFrame, "CENTER", 30, 165) UIDropDownMenu_Initialize(frame, EasyMenu_Initialize, nil, nil, menu); local function show_menu() + menu[1].text = get_option_active('Active'); menu[2].text = get_option_text('Primary'); menu[3].text = get_option_text('Secondary'); + menu[4].text = get_option_texts('Both'); ToggleDropDownMenu(1, nil, frame, frame, 25, 10, menu); end @@ -110,6 +181,27 @@ function raid_browser.gui.raidset.initialize() set_selection(raid_browser_character_current_raidset); end +local function check_button(button) + if is_active_selected() or is_both_selected() then + button:Disable() + else + button:Enable() + end +end + +function raid_browser.check_button() + if is_active_selected() or is_both_selected() then + RaidBrowserRaidSetSaveButton:Disable() + RaidBrowserRaidSetSaveButton:SetText("Select spec first") + RaidBrowserRaidSetSaveButton:Hide() + else + RaidBrowserRaidSetSaveButton:Enable() + RaidBrowserRaidSetSaveButton:SetText("Save gear+spec") + RaidBrowserRaidSetSaveButton:Show() + end +end + + -- Create raidset save button local button = CreateFrame("BUTTON","RaidBrowserRaidSetSaveButton", LFRBrowseFrame, "OptionsButtonTemplate") button:SetPoint("CENTER", LFRBrowseFrame, "CENTER", -53, 168) @@ -120,4 +212,4 @@ button:SetText("Save Raid Gear"); button:SetWidth(110); button:SetScript("OnClick", on_raidset_save); button:Show(); - +check_button(button); diff --git a/RaidBrowser/stats.lua b/RaidBrowser/stats.lua index 728193b..eb26a4e 100644 --- a/RaidBrowser/stats.lua +++ b/RaidBrowser/stats.lua @@ -1,6 +1,14 @@ raid_browser.stats = {}; local raid_achievements = { + + rs = { + 4817, -- The Twilight Destroyer 10 + 4815, -- The Twilight Destroyer 25 + 4818, -- The Twilight Destroyer 10 HC + 4816, -- The Twilight Destroyer 25 HC + }, + icc = { 4531, -- Storming the Citadel 10-man 4604, -- Storming the Citadel 25-man @@ -19,24 +27,108 @@ local raid_achievements = { 4631, -- The Frostwing Halls 10-man HC 4635, -- The Frostwing Halls 25-man HC 4530, -- The Frozen Throne (LK10 NM) + 4532, -- Fall of the Lich King (10 NM) 4597, -- The Frozen Throne (LK25 NM) + 4608, -- Fall of the Lich King (25 NM) 4583, -- Bane of the Fallen King (LK10 HC) + 4636, -- Heroic: Fall of the Lich King (10 HC) + 4602, -- Glory of the Icecrown Raider 10 4584, -- The Light of Dawn (LK25 HC) + 4637, -- Heroic: Fall of the Lich King (25 HC) + 4603, -- Glory of the Icecrown Raider 25 + 4576, -- Realm First! Fall of the Lich King (25 HC) }, toc = { 3917, -- Call of the Crusade 10-man 3916, -- Call of the Crusade 25-man 3918, -- Call of the Grand Crusade (10 HC) + 3810, -- A Tribute to Insanity (10 HC) 3812, -- Call of the Grand Crusade (25 HC) + 3819, -- A Tribute to Insanity (25 HC) + 4080, -- A Tribute to Dedicated Insanity (10 HC) + 4079, -- A Tribute to Immortality (25 HC Horde) + 4156, -- A Tribute to Immortality (25 HC Alliance) + 4078, -- Realm First! Grand Crusader }, - rs = { - 4817, -- The Twilight Destroyer 10 - 4815, -- The Twilight Destroyer 25 - 4818, -- The Twilight Destroyer 10 HC - 4816, -- The Twilight Destroyer 25 HC + togc = { + 3917, -- Call of the Crusade 10-man + 3916, -- Call of the Crusade 25-man + 3918, -- Call of the Grand Crusade (10 HC) + 3810, -- A Tribute to Insanity (10 HC) + 3812, -- Call of the Grand Crusade (25 HC) + 3819, -- A Tribute to Insanity (25 HC) + 4080, -- A Tribute to Dedicated Insanity (10 HC) + 4079, -- A Tribute to Immortality (25 HC Horde) + 4156, -- A Tribute to Immortality (25 HC Alliance) + 4078, -- Realm First! Grand Crusader }, + + ulduar = { + 2894, -- The Secrets of Ulduar 10 + 2895, -- The Secrets of Ulduar 25 + 3036, -- Observed 10 + 3037, -- Observed 25 + 3141, -- Two Lights in the Darkness 10 + 3158, -- One Light in the Darkness 10 + 3159, -- Alone in the Darkness 10 + 3162, -- Two Lights in the Darkness 25 + 3163, -- One Light in the Darkness 25 + 3004, -- He Feeds on your Tears 10 + 3005, -- He Feeds on your Tears 25 + 2957, -- Glory of the Ulduar Raider 10 + 3316, -- Herald of the Titans + 3164, -- Alone in the Darkness 25 + 2958, -- Glory of the Ulduar Raider 25 + 3259, -- Realm First! Celestial Defender + 3117, -- Realm First! Death's Demise + }, + + eoe = { + 622, -- Spellweaver 10 + 1874, -- You don't have an eternity 10 + 623, -- Spellweaver 25 + 1875, -- You don't have an eternity 25 + 1400, -- Realm First! Magic Seeker + }, + + os = { + 1876, -- Besting the Black Dragonflight 10 + 2049, -- Twilight Assist 10 + 2050, -- Twilight Duo 10 + 625, -- Besting the Black Dragonflight 25 + 2052, -- Twilight Assist 25 + 2051, -- Twilight Zone 10 + 2053, -- Twilight Duo 25 + 2054, -- Twilight Zone 25 + 456, -- Realm First! Obsidian Slayer + }, + + naxx = { + 574, -- Kel'Thuzad's Defeat 10 + 575, -- Kel'Thuzad's Defeat 25 + 576, -- The Fall of Naxxramas 10 + 577, -- The Fall of Naxxramas 25 + 578, -- The Dedicated Few 10 + 579, -- The Dedicated Few 25 + 2187, -- The Undying 10 + 2186, -- The Immortal 25 + 2137, -- Glory of the Raider 10 + 2138, -- Glory of the Raider 25 + 1402, -- Realm First! Conqueror of Naxxramas + }, + + voa = { + 1722, -- Archavon the Stone Watcher 10 + 3136, -- Emalon the Storm Watcher 10 + 3836, -- Koralon the Flame Watcher 10 + 4585, -- Toravon the Ice Watcher 10 + 1721, -- Archavon the Stone Watcher 25 + 3137, -- Emalon the Storm Watcher 25 + 3837, -- Koralon the Flame Watcher 25 + 4586, -- Toravon the Ice Watcher 25 + } }; local function find_best_achievement(raid) @@ -57,11 +149,17 @@ local function find_best_achievement(raid) -- Find the highest ranking completed achievement criterion for i, id in ipairs(ids) do + local fully_completed for j = 1, GetAchievementNumCriteria(id) do local _, _, completed = GetAchievementCriteriaInfo(id, j) - if completed and (not max_achievement or max_achievement[1] <= i) then - max_achievement = {i, id}; - end + if not completed then + fully_completed = false + break + end + fully_completed = true + end + if fully_completed and (not max_achievement or max_achievement[1] <= i) then + max_achievement = {i, id}; end end @@ -87,15 +185,30 @@ end function raid_browser.stats.active_spec() local active_tab = raid_browser.stats.active_spec_index() local tab_name = GetTalentTabInfo(active_tab); + local _,class = UnitClass("player"); -- If we're a feral druid, then we need to distinguish between tank and cat feral. if tab_name == 'Feral Combat' then local protector_of_pack_talent = 22; - local _, _, _, _, points = GetTalentInfo(active_tab, protector_of_pack_talent) - if points > 0 then - return 'Feral (Bear)' + local thick_hide_talent = 5; + local _, _, _, _, points = GetTalentInfo(active_tab, thick_hide_talent) + if points > 1 then + return 'Feral (Tank)' else - return 'Feral (Cat)' + return 'Feral (DPS)' + end + end + + -- If we're a death knight, then we need to distinguish between tank and dps. + if class == 'DEATHKNIGHT' then + local toughness_talent = 3; + local blade_barrier_talent = 3; + local _, _, _, _, points = GetTalentInfo(2, toughness_talent) + local _, _, _, _, points2 = GetTalentInfo(1, 3) + if points > 3 and points2 > 3 then + return tab_name .. ' (Tank)' + else + return tab_name .. ' (DPS)' end end @@ -136,9 +249,25 @@ function raid_browser.stats.get_raidset(set) return raidset.spec, raidset.gs; end +function raid_browser.stats.get_raidsets() + local raidset1 = raid_browser_character_raidsets['Primary'] or nil; + local raidset2 = raid_browser_character_raidsets['Secondary'] or nil; + if not (raidset1 or raidset2) then + return + elseif (raidset1 and raidset2) then + return raidset1.spec , raidset1.gs , raidset2.spec , raidset2.gs + elseif raidset1 then + return raidset1.spec, raidset1.gs + elseif raidset2 then + return raidset2.spec, raidset2.gs + end +end + function raid_browser.stats.current_raidset() if raid_browser_character_current_raidset == 'Active' then return raid_browser.stats.get_active_raidset(); + elseif raid_browser_character_current_raidset == 'Both' then + return raid_browser.stats.get_raidsets(); end return raid_browser.stats.get_raidset(raid_browser_character_current_raidset); @@ -162,11 +291,20 @@ function raid_browser.stats.build_inv_string(raid_name) local message = 'inv '; local class = UnitClass("player"); - local spec, gs = raid_browser.stats.current_raidset(); - message = message .. gs .. 'gs ' .. spec .. ' ' .. class; + local spec1, gs1, spec2, gs2 = raid_browser.stats.current_raidset(); + if spec1 and gs1 then + message = message .. gs1 .. 'gs ' .. spec1 + end + if spec1 and gs1 and spec2 and gs2 then + message = message .. ' / ' + end + if spec2 and gs2 then + message = message .. gs2 .. 'gs ' .. spec2 + end + message = message .. ' ' .. class; -- Remove difficulty and raid_name size from the string - raid_name = string.gsub(raid_name, '[1|2][0|5](%w+)', ''); + raid_name = string.gsub(raid_name, '[1|2][0|5](%w*)', ''); -- Find the best possible achievement for the given raid_name. local achieve_id = find_best_achievement(raid_name);