local L = DBM_GUI_L DBM_GUI = { tabs = {}, panels = {} } local isRetail = WOW_PROJECT_ID == (WOW_PROJECT_MAINLINE or 1) local next, type, pairs, strsplit, tonumber, tostring, ipairs, tinsert, tsort, mfloor = next, type, pairs, strsplit, tonumber, tostring, ipairs, table.insert, table.sort, math.floor local CreateFrame, C_Timer, GetExpansionLevel, IsAddOnLoaded, GameFontNormal, GameFontNormalSmall, GameFontHighlight, GameFontHighlightSmall, ChatFontNormal, UIParent = CreateFrame, C_Timer, GetExpansionLevel, IsAddOnLoaded, GameFontNormal, GameFontNormalSmall, GameFontHighlight, GameFontHighlightSmall, ChatFontNormal, UIParent local RAID_DIFFICULTY1, RAID_DIFFICULTY2, RAID_DIFFICULTY3, RAID_DIFFICULTY4, PLAYER_DIFFICULTY1, PLAYER_DIFFICULTY2, PLAYER_DIFFICULTY3, PLAYER_DIFFICULTY6, PLAYER_DIFFICULTY_TIMEWALKER, CHALLENGE_MODE, ALL, CLOSE, SPECIALIZATION = RAID_DIFFICULTY1, RAID_DIFFICULTY2, RAID_DIFFICULTY3, RAID_DIFFICULTY4, PLAYER_DIFFICULTY1, PLAYER_DIFFICULTY2, PLAYER_DIFFICULTY3, PLAYER_DIFFICULTY6, PLAYER_DIFFICULTY_TIMEWALKER, CHALLENGE_MODE, ALL, CLOSE, SPECIALIZATION local LibStub, DBM, DBM_GUI, DBM_OPTION_SPACER = _G["LibStub"], DBM, DBM_GUI, DBM_OPTION_SPACER local playerName, realmName, playerLevel = UnitName("player"), GetRealmName(), UnitLevel("player") StaticPopupDialogs["IMPORTPROFILE_ERROR"] = { text = "There are one or more errors importing this profile. Please see the chat for more information. Would you like to continue and reset found errors to default?", button1 = "Import and fix", button2 = "No", OnAccept = function(self) self.importFunc() end, timeout = 0, whileDead = true, hideOnEscape = true, preferredIndex = 3, } do local soundsRegistered = false function DBM_GUI:MixinSharedMedia3(mediatype, mediatable) if not LibStub or not LibStub("LibSharedMedia-3.0", true) then return mediatable end if not soundsRegistered then local LSM = LibStub("LibSharedMedia-3.0") soundsRegistered = true -- Embedded Sound Clip media LSM:Register("sound", "AirHorn (DBM)", [[Interface\AddOns\DBM-Core\sounds\AirHorn.ogg]]) LSM:Register("sound", "Jaina: Beware", [[Interface\AddOns\DBM-Core\sounds\SoundClips\beware.ogg]]) LSM:Register("sound", "Jaina: Beware (reverb)", [[Interface\AddOns\DBM-Core\sounds\SoundClips\beware_with_reverb.ogg]]) LSM:Register("sound", "Thrall: That's Incredible!", [[Interface\AddOns\DBM-Core\sounds\SoundClips\incredible.ogg]]) LSM:Register("sound", "Saurfang: Don't Die", [[Interface\AddOns\DBM-Core\sounds\SoundClips\dontdie.ogg]]) -- Blakbyrd LSM:Register("sound", "Blakbyrd Alert 1", [[Interface\AddOns\DBM-Core\sounds\BlakbyrdAlerts\Alert1.ogg]]) LSM:Register("sound", "Blakbyrd Alert 2", [[Interface\AddOns\DBM-Core\sounds\BlakbyrdAlerts\Alert2.ogg]]) LSM:Register("sound", "Blakbyrd Alert 3", [[Interface\AddOns\DBM-Core\sounds\BlakbyrdAlerts\Alert3.ogg]]) -- User Media if DBM.Options.CustomSounds >= 1 then LSM:Register("sound", "DBM: Custom 1", [[Interface\AddOns\DBM-CustomSounds\Custom1.ogg]]) end if DBM.Options.CustomSounds >= 2 then LSM:Register("sound", "DBM: Custom 2", [[Interface\AddOns\DBM-CustomSounds\Custom2.ogg]]) end if DBM.Options.CustomSounds >= 3 then LSM:Register("sound", "DBM: Custom 3", [[Interface\AddOns\DBM-CustomSounds\Custom3.ogg]]) end if DBM.Options.CustomSounds >= 4 then LSM:Register("sound", "DBM: Custom 4", [[Interface\AddOns\DBM-CustomSounds\Custom4.ogg]]) end if DBM.Options.CustomSounds >= 5 then LSM:Register("sound", "DBM: Custom 5", [[Interface\AddOns\DBM-CustomSounds\Custom5.ogg]]) end if DBM.Options.CustomSounds >= 6 then LSM:Register("sound", "DBM: Custom 6", [[Interface\AddOns\DBM-CustomSounds\Custom6.ogg]]) end if DBM.Options.CustomSounds >= 7 then LSM:Register("sound", "DBM: Custom 7", [[Interface\AddOns\DBM-CustomSounds\Custom7.ogg]]) end if DBM.Options.CustomSounds >= 8 then LSM:Register("sound", "DBM: Custom 8", [[Interface\AddOns\DBM-CustomSounds\Custom8.ogg]]) end if DBM.Options.CustomSounds >= 9 then LSM:Register("sound", "DBM: Custom 9", [[Interface\AddOns\DBM-CustomSounds\Custom9.ogg]]) if DBM.Options.CustomSounds > 9 then DBM.Options.CustomSounds = 9 end end end -- Sort LibSharedMedia keys alphabetically (case-insensitive) local hashtable = LibStub("LibSharedMedia-3.0", true):HashTable(mediatype) local keytable = {} for k in next, hashtable do tinsert(keytable, k) end tsort(keytable, function(a, b) return a:lower() < b:lower() end); -- DBM values (mediatable) first, LibSharedMedia values (sorted alphabetically) afterwards local result = mediatable for i = 1, #result do if mediatype == "statusbar" then result[i].texture = true elseif mediatype == "font" then result[i].font = true elseif mediatype == "sound" then result[i].sound = true end end for i = 1, #keytable do if mediatype ~= "sound" or (keytable[i] ~= "None" and keytable[i] ~= "NPCScan") then local v = hashtable[keytable[i]] -- Filter duplicates local insertme = true for _, v2 in next, result do if v2.value == v then insertme = false break end end if insertme then local ins = { text = keytable[i], value = v } if mediatype == "statusbar" then ins.texture = true elseif mediatype == "font" then ins.font = true -- Only insert paths from addons folder, ignore file data ID, since there is no clean way to handle supporitng both FDID and soundkit at same time elseif mediatype == "sound" and type(v) == "string" and v:lower():find("addons") then ins.sound = true end if ins.texture or ins.font or ins.sound then tinsert(result, ins) end end end end return result end end do local LibSerialize = LibStub("LibSerialize") local LibDeflate = LibStub("LibDeflate") local canWeWork = LibStub and LibStub("LibDeflate", true) and LibStub("LibSerialize", true) local popupFrame local function createPopupFrame() popupFrame = CreateFrame("Frame", nil, UIParent, "BackdropTemplate") popupFrame:SetFrameStrata("DIALOG") popupFrame:SetFrameLevel(popupFrame:GetFrameLevel() + 10) popupFrame:SetSize(512, 512) popupFrame:SetPoint("CENTER") popupFrame.backdropInfo = { bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background", -- 131071 edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border", -- 131072 tile = true, tileSize = 32, edgeSize = 32, insets = { left = 8, right = 8, top = 8, bottom = 8 } } popupFrame:ApplyBackdrop() popupFrame:SetMovable(true) popupFrame:EnableMouse(true) popupFrame:RegisterForDrag("LeftButton") popupFrame:SetScript("OnDragStart", popupFrame.StartMoving) popupFrame:SetScript("OnDragStop", popupFrame.StopMovingOrSizing) popupFrame:Hide() popupFrame.text = "" local backdrop = CreateFrame("Frame", nil, popupFrame, "BackdropTemplate") backdrop.backdropInfo = { bgFile = "Interface\\ChatFrame\\ChatFrameBackground", edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border", tile = true, tileSize = 16, edgeSize = 16, insets = { left = 3, right = 3, top = 5, bottom = 3 } } backdrop:ApplyBackdrop() backdrop:SetBackdropColor(0.1, 0.1, 0.1, 0.6) backdrop:SetBackdropBorderColor(0.4, 0.4, 0.4) backdrop:SetPoint("TOPLEFT", 15, -15) backdrop:SetPoint("BOTTOMRIGHT", -40, 40) local scrollFrame = CreateFrame("ScrollFrame", nil, popupFrame, "UIPanelScrollFrameTemplate") scrollFrame:SetPoint("TOPLEFT", 15, -22) scrollFrame:SetPoint("BOTTOMRIGHT", -40, 45) local input = CreateFrame("EditBox", nil, scrollFrame) input:SetTextInsets(7, 7, 3, 3) input:SetFontObject(ChatFontNormal) input:SetMultiLine(true) input:EnableMouse(true) input:SetAutoFocus(false) input:SetMaxBytes(0) input:SetScript("OnMouseUp", function(self) self:HighlightText() end) input:SetScript("OnEscapePressed", function(self) self:ClearFocus() end) input:HighlightText() input:SetFocus() scrollFrame:SetScrollChild(input) input:ClearAllPoints() input:SetPoint("TOPLEFT", scrollFrame, "TOPLEFT") input:SetPoint("BOTTOMRIGHT", scrollFrame, "BOTTOMRIGHT") input:SetWidth(452) local import = CreateFrame("Button", nil, popupFrame, "UIPanelButtonTemplate") import:SetPoint("BOTTOMRIGHT", -120, 13) import:SetFrameLevel(import:GetFrameLevel() + 1) import:SetSize(100, 20) import:SetText(L.Import) import:SetScript("OnClick", function() if popupFrame:VerifyImport(input:GetText()) then input:ClearFocus() popupFrame:Hide() end end) popupFrame.import = import local close = CreateFrame("Button", nil, popupFrame, "UIPanelButtonTemplate") close:SetPoint("LEFT", import, "RIGHT", 5, 0) close:SetFrameLevel(close:GetFrameLevel() + 1) close:SetSize(100, 20) close:SetText(CLOSE) close:SetScript("OnClick", function() input:ClearFocus() popupFrame:Hide() end) input:SetScript("OnChar", function() if not import:IsShown() then input:SetText(popupFrame.text) input:HighlightText() end end) function popupFrame:SetText(text) input:SetText(text) self.text = text end end function DBM_GUI:CreateExportProfile(export) if not canWeWork then DBM:AddMsg("Missing required libraries to export.") return end if not popupFrame then createPopupFrame() end popupFrame.import:Hide() popupFrame:SetText(LibDeflate:EncodeForPrint(LibDeflate:CompressDeflate(LibSerialize:Serialize(export), {level = 9}))) popupFrame:Show() end function DBM_GUI:CreateImportProfile(importFunc) if not canWeWork then DBM:AddMsg("Missing required libraries to export.") return end if not popupFrame then createPopupFrame() end function popupFrame:VerifyImport(import) local success, deserialized = LibSerialize:Deserialize(LibDeflate:DecompressDeflate(LibDeflate:DecodeForPrint(import))) if not success then DBM:AddMsg("Failed to deserialize") return false end importFunc(deserialized) return true end popupFrame.import:Show() popupFrame:SetText("") popupFrame:Show() end end do local framecount = 0 function DBM_GUI:GetNewID() framecount = framecount + 1 return framecount end function DBM_GUI:GetCurrentID() return framecount end end function DBM_GUI:ShowHide(forceshow) local optionsFrame = _G["DBM_GUI_OptionsFrame"] if forceshow == true then self:UpdateModList() optionsFrame:Show() elseif forceshow == false then optionsFrame:Hide() else if optionsFrame:IsShown() then optionsFrame:Hide() else self:UpdateModList() optionsFrame:Show() end end end local catbutton, lastButton, addSpacer local function addOptions(mod, catpanel, v) if v == DBM_OPTION_SPACER then addSpacer = true else lastButton = catbutton if v.line then catbutton = catpanel:CreateLine(v.text) elseif type(mod.Options[v]) == "boolean" then if mod.Options[v .. "TColor"] then catbutton = catpanel:CreateCheckButton(mod.localization.options[v], true, nil, nil, nil, mod, v, nil, true) elseif mod.Options[v .. "SWSound"] then catbutton = catpanel:CreateCheckButton(mod.localization.options[v], true, nil, nil, nil, mod, v) else catbutton = catpanel:CreateCheckButton(mod.localization.options[v], true) end catbutton:SetScript("OnShow", function(self) self:SetChecked(mod.Options[v]) end) catbutton:SetScript("OnClick", function(self) mod.Options[v] = not mod.Options[v] if mod.optionFuncs and mod.optionFuncs[v] then mod.optionFuncs[v]() end end) elseif mod.dropdowns and mod.dropdowns[v] then local dropdownOptions = {} for _, val in ipairs(mod.dropdowns[v]) do tinsert(dropdownOptions, { text = mod.localization.options[val], value = val }) end catbutton = catpanel:CreateDropdown(mod.localization.options[v], dropdownOptions, mod, v, function(value) mod.Options[v] = value if mod.optionFuncs and mod.optionFuncs[v] then mod.optionFuncs[v]() end end, nil, 32) if not addSpacer then catbutton:SetPoint("TOPLEFT", lastButton, "BOTTOMLEFT", 0, -10) end end if addSpacer then catbutton:SetPoint("TOPLEFT", lastButton, "BOTTOMLEFT", 0, -6) addSpacer = false end end end function DBM_GUI:CreateBossModPanel(mod) if not mod.panel then DBM:AddMsg("Couldn't create boss mod panel for " .. mod.localization.general.name) return false end local panel = mod.panel local category local iconstat = panel.frame:CreateFontString("DBM_GUI_Mod_Icons" .. mod.localization.general.name, "ARTWORK") iconstat:SetPoint("TOP", panel.frame, 0, -10) iconstat:SetFontObject(GameFontNormal) iconstat:SetText(L.IconsInUse) for i = 1, 8 do local icon = panel.frame:CreateTexture() icon:SetTexture(137009) -- "Interface\\TargetingFrame\\UI-RaidTargetingIcons.blp" icon:SetPoint("TOP", panel.frame, 81 - (i * 18), -26) icon:SetSize(16, 16) if not mod.usedIcons or not mod.usedIcons[i] then icon:SetAlpha(0.25) end if i == 1 then icon:SetTexCoord(0, 0.25, 0, 0.25) elseif i == 2 then icon:SetTexCoord(0.25, 0.5, 0, 0.25) elseif i == 3 then icon:SetTexCoord(0.5, 0.75, 0, 0.25) elseif i == 4 then icon:SetTexCoord(0.75, 1, 0, 0.25) elseif i == 5 then icon:SetTexCoord(0, 0.25, 0.25, 0.5) elseif i == 6 then icon:SetTexCoord(0.25, 0.5, 0.25, 0.5) elseif i == 7 then icon:SetTexCoord(0.5, 0.75, 0.25, 0.5) elseif i == 8 then icon:SetTexCoord(0.75, 1, 0.25, 0.5) -- elseif i == 9 then icon:SetTexCoord(0, 0.25, 0.5, 0.75) -- elseif i == 10 then icon:SetTexCoord(0.25, 0.5, 0.5, 0.75) -- elseif i == 11 then icon:SetTexCoord(0.5, 0.75, 0.5, 0.75) -- elseif i == 12 then icon:SetTexCoord(0.75, 1, 0.5, 0.75) -- elseif i == 13 then icon:SetTexCoord(0, 0.25, 0.75, 1) -- elseif i == 14 then icon:SetTexCoord(0.25, 0.5, 0.75, 1) -- elseif i == 15 then icon:SetTexCoord(0.5, 0.75, 0.75, 1) -- elseif i == 16 then icon:SetTexCoord(0.75, 1, 0.75, 1) end end local reset = panel:CreateButton(L.Mod_Reset, 155, 30, nil, GameFontNormalSmall) reset.myheight = 40 reset:SetPoint("TOPRIGHT", panel.frame, "TOPRIGHT", -24, -4) reset:SetScript("OnClick", function(self) DBM:LoadModDefaultOption(mod) end) local button = panel:CreateCheckButton(L.Mod_Enabled, true) button:SetChecked(mod.Options.Enabled) button:SetPoint("TOPLEFT", panel.frame, "TOPLEFT", 8, -14) button:SetScript("OnClick", function(self) mod:Toggle() end) if mod.addon and not mod.addon.oldOptions and DBM.Options.GroupOptionsBySpell then for spellID, options in getmetatable(mod.groupOptions).__pairs(mod.groupOptions) do if spellID:find("^line") then panel:CreateLine(options) else local title, desc, _, icon if tonumber(spellID) then local _title = DBM:GetSpellInfo(spellID) if _title then title, desc, icon = _title, tonumber(spellID), GetSpellTexture(spellID) else--Not a valid spellid (Such as a ptr/beta mod loaded on live title, desc, icon = spellID, L.NoDescription, 136116 end elseif spellID:find("^ej") then title, desc, _, icon = DBM:EJ_GetSectionInfo(spellID:gsub("ej", "")) elseif spellID:find("^at") then spellID = spellID:gsub("at", "") _, title, _, _, _, _, _, desc, _, icon = GetAchievementInfo(spellID) else title = spellID end local catpanel = panel:CreateAbility(title, icon) if desc then catpanel:CreateSpellDesc(desc) end catbutton, lastButton, addSpacer = nil, nil, nil for _, v in ipairs(options) do addOptions(mod, catpanel, v) end end end end local scannedCategories = {} for _, catident in pairs(mod.categorySort) do category = mod.optionCategories[catident] if not scannedCategories[catident] and category then scannedCategories[catident] = true local catpanel = panel:CreateArea(mod.localization.cats[catident]) catbutton, lastButton, addSpacer = nil, nil, nil for _, v in ipairs(category) do addOptions(mod, catpanel, v) end end end end local function GetSpecializationGroup() if isRetail then return GetSpecialization() or 1 else local numTabs = GetNumTalentTabs() local highestPointsSpent, currentSpecGroup = 0, 1 if MAX_TALENT_TABS then for i=1, MAX_TALENT_TABS do if ( i <= numTabs ) then local _, _, pointsSpent = GetTalentTabInfo(i) if pointsSpent > highestPointsSpent then highestPointsSpent = pointsSpent currentSpecGroup = i end end end end return currentSpecGroup end end do local function CreateBossModTab(addon, panel, subtab) if not panel then error("Panel is nil", 2) end local modProfileArea if not subtab then local modProfileDropdown = {} modProfileArea = panel:CreateArea(L.Area_ModProfile) modProfileArea.frame:SetPoint("TOPLEFT", 10, -25) local resetButton = modProfileArea:CreateButton(L.ModAllReset, 200, 20) resetButton:SetPoint("TOPLEFT", 10, -14) resetButton:SetScript("OnClick", function() DBM:LoadAllModDefaultOption(addon.modId) end) for charname, charTable in pairs(_G[addon.modId:gsub("-", "") .. "_AllSavedVars"] or {}) do for _, optionTable in pairs(charTable) do if type(optionTable) == "table" then for i = 0, 4 do if optionTable[i] then tinsert(modProfileDropdown, { text = (i == 0 and charname .. " (" .. ALL.. ")") or charname .. " (" .. SPECIALIZATION .. i .. "-" .. (charTable["talent" .. i] or "") .. ")", value = charname .. "|" .. tostring(i) }) end end break end end end local resetStatButton = modProfileArea:CreateButton(L.ModAllStatReset, 200, 20) resetStatButton.myheight = 0 resetStatButton:SetPoint("LEFT", resetButton, "RIGHT", 40, 0) resetStatButton:SetScript("OnClick", function() DBM:ClearAllStats(addon.modId) end) local refresh local copyModProfile = modProfileArea:CreateDropdown(L.SelectModProfileCopy, modProfileDropdown, nil, nil, function(value) local name, profile = strsplit("|", value) DBM:CopyAllModOption(addon.modId, name, tonumber(profile)) C_Timer.After(0.05, refresh) end, 100) copyModProfile:SetPoint("TOPLEFT", -7, -54) copyModProfile:SetScript("OnShow", function() copyModProfile.value = nil copyModProfile.text = nil _G[copyModProfile:GetName() .. "Text"]:SetText("") end) local copyModSoundProfile = modProfileArea:CreateDropdown(L.SelectModProfileCopySound, modProfileDropdown, nil, nil, function(value) local name, profile = strsplit("|", value) DBM:CopyAllModTypeOption(addon.modId, name, tonumber(profile), "SWSound") C_Timer.After(0.05, refresh) end, 100) copyModSoundProfile.myheight = 0 copyModSoundProfile:SetPoint("LEFT", copyModProfile, "RIGHT", 27, 0) copyModSoundProfile:SetScript("OnShow", function() copyModSoundProfile.value = nil copyModSoundProfile.text = nil _G[copyModSoundProfile:GetName() .. "Text"]:SetText("") end) local copyModNoteProfile = modProfileArea:CreateDropdown(L.SelectModProfileCopyNote, modProfileDropdown, nil, nil, function(value) local name, profile = strsplit("|", value) DBM:CopyAllModTypeOption(addon.modId, name, tonumber(profile), "SWNote") C_Timer.After(0.05, refresh) end, 100) copyModNoteProfile.myheight = 0 copyModNoteProfile:SetPoint("LEFT", copyModSoundProfile, "RIGHT", 27, 0) copyModNoteProfile:SetScript("OnShow", function() copyModNoteProfile.value = nil copyModNoteProfile.text = nil _G[copyModNoteProfile:GetName() .. "Text"]:SetText("") end) local deleteModProfile = modProfileArea:CreateDropdown(L.SelectModProfileDelete, modProfileDropdown, nil, nil, function(value) local name, profile = strsplit("|", value) DBM:DeleteAllModOption(addon.modId, name, tonumber(profile)) C_Timer.After(0.05, refresh) end, 100) deleteModProfile.myheight = 60 deleteModProfile:SetPoint("TOPLEFT", copyModSoundProfile, "BOTTOMLEFT", 0, -10) deleteModProfile:SetScript("OnShow", function() deleteModProfile.value = nil deleteModProfile.text = nil _G[deleteModProfile:GetName() .. "Text"]:SetText("") end) function refresh() copyModProfile:GetScript("OnShow")() copyModSoundProfile:GetScript("OnShow")() copyModNoteProfile:GetScript("OnShow")() deleteModProfile:GetScript("OnShow")() end -- Start import/export local function actuallyImport(importTable) local profileID = playerLevel > 9 and DBM_UseDualProfile and GetSpecializationGroup() or 0 for _, id in ipairs(DBM.ModLists[addon.modId]) do _G[addon.modId:gsub("-", "") .. "_AllSavedVars"][playerName .. "-" .. realmName][id][profileID] = importTable[id] DBM:GetModByName(id).Options = importTable[id] end DBM:AddMsg("Profile imported.") end local importExportProfilesArea = panel:CreateArea(L.Area_ImportExportProfile) local test = importExportProfilesArea:CreateText(L.ImportExportInfo, nil, true) test:SetPoint("TOPLEFT", 15, -10) local exportProfile = importExportProfilesArea:CreateButton(L.ButtonExportProfile, 120, 20, function() local exportProfile = {} local profileID = playerLevel > 9 and DBM_UseDualProfile and GetSpecializationGroup() or 0 for _, id in ipairs(DBM.ModLists[addon.modId]) do exportProfile[id] = _G[addon.modId:gsub("-", "") .. "_AllSavedVars"][playerName .. "-" .. realmName][id][profileID] end DBM_GUI:CreateExportProfile(exportProfile) end) exportProfile.myheight = 0 exportProfile:SetPoint("TOPLEFT", 12, -25) local importProfile = importExportProfilesArea:CreateButton(L.ButtonImportProfile, 120, 20, function() DBM_GUI:CreateImportProfile(function(importTable) local errors = {} for id, table in pairs(importTable) do -- Check if sound packs are missing for settingName, settingValue in pairs(table) do local ending = settingName:sub(-6):lower() if ending == "cvoice" or ending == "wsound" then -- CVoice or SWSound (s is ignored so we only have to sub once) if type(settingValue) == "string" and settingValue:lower() ~= "none" and not DBM:ValidateSound(settingValue, true, true) then tinsert(errors, id .. "-" .. settingName) end end end end -- Create popup confirming if they wish to continue (and therefor resetting to default) if #errors > 0 then local popup = StaticPopup_Show("IMPORTPROFILE_ERROR") if popup then popup.importFunc = function() local modOptions = {} for _, soundSetting in ipairs(errors) do local modID, settingName = soundSetting:match("([^-]+)-([^-]+)") if not modOptions[modID] then modOptions[modID] = DBM:GetModByName(modID).DefaultOptions end importTable[modID][settingName] = modOptions[modID][settingName] end actuallyImport(importTable) end end else actuallyImport(importTable) end end) end) importProfile.myheight = 0 importProfile:SetPoint("LEFT", exportProfile, "RIGHT", 2, 0) end if addon.noStatistics then return end local ptext = panel:CreateText(L.BossModLoaded:format(subtab and addon.subTabs[subtab] or addon.name), nil, nil, nil, "CENTER") ptext:SetPoint("TOPLEFT", panel.frame, "TOPLEFT", 10, modProfileArea and -245 or -10) local singleLine, doubleLine, noHeaderLine = 0, 0, 0 local area = panel:CreateArea() area.frame.isStats = true area.frame:SetPoint("TOPLEFT", 10, modProfileArea and -260 or -25) local statOrder = { "lfr", "normal", "normal25", "heroic", "heroic25", "mythic", "challenge", "timewalker" } for _, mod in ipairs(DBM.Mods) do if mod.modId == addon.modId and (not subtab or subtab == mod.subTab) and not mod.isTrashMod and not mod.noStatistics then if not mod.stats then mod.stats = {} end --Create Frames local statSplit, statCount = {}, 0 for stat in (mod.statTypes or mod.addon.statTypes):gmatch("%s?([^%s,]+)%s?,?") do statSplit[stat] = true statCount = statCount + 1 end if statCount == 0 then DBM:AddMsg("No statTypes available for " .. mod.modId) return -- No stats available for this? Possibly a bug end local Title = area:CreateText(mod.localization.general.name, nil, nil, GameFontHighlight, "LEFT") local function CreateText(text, header) local frame = area:CreateText(text or "", nil, nil, header and GameFontHighlightSmall or GameFontNormalSmall, "LEFT") frame:Hide() return frame end local sections = {} for i = 1, 6 do local section = {} section.header = CreateText(nil, true) section.text1 = CreateText(L.Statistic_Kills) section.text2 = CreateText(L.Statistic_Wipes) section.text3 = CreateText(L.Statistic_BestKill) section.value1 = CreateText() section.value2 = CreateText() section.value3 = CreateText() if i == 1 then section.header:SetPoint("TOPLEFT", Title, "BOTTOMLEFT", 20, -5) elseif i == 4 then section.header:SetPoint("TOPLEFT", sections[1].text3, "BOTTOMLEFT", -20, -5) else section.header:SetPoint("LEFT", sections[i - 1].header, "LEFT", 150, 0) end section.text1:SetPoint("TOPLEFT", section.header, "BOTTOMLEFT", 20, -5) section.text2:SetPoint("TOPLEFT", section.text1, "BOTTOMLEFT", 0, -5) section.text3:SetPoint("TOPLEFT", section.text2, "BOTTOMLEFT", 0, -5) section.value1:SetPoint("TOPLEFT", section.text1, "TOPLEFT", 80, 0) section.value2:SetPoint("TOPLEFT", section.text2, "TOPLEFT", 80, 0) section.value3:SetPoint("TOPLEFT", section.text3, "TOPLEFT", 80, 0) section.header.OldSetText = section.header.SetText section.header.SetText = function(self, text) self:OldSetText(text) self:Show() section.text1:Show() section.text2:Show() section.text3:Show() section.value1:Show() section.value2:Show() section.value3:Show() end sections[i] = section end local statTypes = { lfr25 = PLAYER_DIFFICULTY3, normal = mod.addon.minExpansion < 5 and RAID_DIFFICULTY1 or PLAYER_DIFFICULTY1, normal25 = RAID_DIFFICULTY2, heroic = mod.addon.minExpansion < 5 and RAID_DIFFICULTY3 or PLAYER_DIFFICULTY2, heroic25 = RAID_DIFFICULTY4, mythic = PLAYER_DIFFICULTY6, challenge = (mod.addon.minExpansion < 6 and not mod.upgradedMPlus) and CHALLENGE_MODE or (PLAYER_DIFFICULTY6 .. "+"), timewalker = PLAYER_DIFFICULTY_TIMEWALKER } if (mod.addon.type == "PARTY" or mod.addon.type == "SCENARIO") or -- Fixes dungeons being labled incorrectly (mod.addon.type == "RAID" and statSplit["timewalker"]) or -- Fixes raids with timewalker being labled incorrectly (mod.addon.modId == "DBM-SiegeOfOrgrimmarV2") then -- Fixes SoO being labled incorrectly statTypes.normal = PLAYER_DIFFICULTY1 statTypes.heroic = PLAYER_DIFFICULTY2 end local lastArea = 0 for _, statType in ipairs(statOrder) do if statSplit[statType] then if statType == "lfr" then statType = "lfr25" -- Because Myst stores stats weird end if lastArea == 2 and statCount == 4 then -- Use top1, top2, bottom1, bottom2 lastArea = 3 end lastArea = lastArea + 1 local section = sections[lastArea] section.header:SetText(statTypes[statType]) area.frame:HookScript("OnShow", function() local kills, pulls, bestRank, bestTime = mod.stats[statType .. "Kills"] or 0, mod.stats[statType .. "Pulls"] or 0, mod.stats[statType .. "BestRank"] or 0, mod.stats[statType .. "BestTime"] section.value1:SetText(kills) section.value2:SetText(pulls - kills) if statType == "challenge" and bestRank > 0 then section.value3:SetText(bestTime and ("%d:%02d (%d)"):format(mfloor(bestTime / 60), bestTime % 60) or "-", bestRank) else section.value3:SetText(bestTime and ("%d:%02d"):format(mfloor(bestTime / 60), bestTime % 60) or "-") end end) end end Title:SetPoint("TOPLEFT", area.frame, "TOPLEFT", 10, -10 - (L.FontHeight * 5 * noHeaderLine) - (L.FontHeight * 6 * singleLine) - (L.FontHeight * 10 * doubleLine)) if statCount == 1 then sections[1].header:Hide() sections[1].text1:SetPoint("TOPLEFT", Title, "BOTTOMLEFT", 20, -5) noHeaderLine = noHeaderLine + 1 area.frame:SetHeight(area.frame:GetHeight() + L.FontHeight * 5) elseif statCount < 4 then singleLine = singleLine + 1 area.frame:SetHeight(area.frame:GetHeight() + L.FontHeight * 6) else doubleLine = doubleLine + 1 area.frame:SetHeight(area.frame:GetHeight() + L.FontHeight * 10) end end end end local category = {} local subTabId = 0 local expansions = { "CLASSIC", "BC", "WOTLK", "CATA", "MOP", "WOD", "LEG", "BFA", "SHADOWLANDS", "DRAGONFLIGHT" } function DBM_GUI:UpdateModList() for _, addon in ipairs(DBM.AddOns) do local cat = addon.category:upper() if not category[cat] then category[cat] = DBM_GUI:CreateNewPanel(_G["EXPANSION_NAME" .. (tIndexOf(expansions, cat) or 99) - 1] or cat == "AFFIXES" and L.TabCategory_AFFIXES or L.TabCategory_OTHER, nil, cat == expansions[GetExpansionLevel() + 1]) end if not addon.panel then -- Create a Panel for "Naxxramas" "Eye of Eternity" ... addon.panel = category[cat]:CreateNewPanel(addon.name or "Error: No-modId") if not IsAddOnLoaded(addon.modId) then local button = addon.panel:CreateButton(L.Button_LoadMod, 200, 30) button.modid = addon button.headline = addon.panel:CreateText(L.BossModLoad_now, 350, nil, nil, "CENTER") button.headline:SetHeight(50) button.headline:SetPoint("CENTER", button, "CENTER", 0, 80) button:SetScript("OnClick", function(self) if DBM:LoadMod(self.modid, true) then self:Hide() self.headline:Hide() CreateBossModTab(self.modid, self.modid.panel) _G["DBM_GUI_OptionsFrame"]:DisplayFrame(self.modid.panel.frame) end end) button:SetPoint("CENTER", 0, -20) else CreateBossModTab(addon, addon.panel) end end if addon.panel and addon.subTabs and IsAddOnLoaded(addon.modId) then -- Create a Panel for "Arachnid Quarter" "Plague Quarter" ... if not addon.subPanels then addon.subPanels = {} end for k, v in pairs(addon.subTabs) do if not addon.subPanels[k] then subTabId = subTabId + 1 addon.subPanels[k] = addon.panel:CreateNewPanel("SubTab" .. subTabId, nil, false, nil, v) CreateBossModTab(addon, addon.subPanels[k], k) end end end for _, mod in ipairs(DBM.Mods) do if mod.modId == addon.modId then if not mod.panel and (not addon.subTabs or (addon.subPanels and addon.subPanels[mod.subTab])) then if addon.subTabs and addon.subPanels[mod.subTab] then mod.panel = addon.subPanels[mod.subTab]:CreateNewPanel(mod.id or "Error: DBM.Mods", addon.optionsTab, nil, nil, mod.localization.general.name) else mod.panel = addon.panel:CreateNewPanel(mod.id or "Error: DBM.Mods", addon.optionsTab, nil, nil, mod.localization.general.name) end DBM_GUI:CreateBossModPanel(mod) end end end end local optionsFrame = _G["DBM_GUI_OptionsFrame"] if optionsFrame:IsShown() then optionsFrame:Hide() optionsFrame:Show() end end end