local activeAffixes = {} local AIO = AIO or require("AIO") local L = { Text = function(self, category, key, localeIndex) if not self[category] or not self[category][key] then return key end if not self[category][key][localeIndex] then return self[category][key][0] end return self[category][key][localeIndex] end, Items = {}, Dungeons = {}, UI = {} } if AIO.AddAddon() then return end MythicPlusCharRunState = { active = false, mapId = nil, tier = nil, duration = nil, elapsed = nil, bossNames = {}, killedBosses = {}, potentialGain = 0, penalty = 0, bonus = 0, deaths = 0, maxDeaths = 0, enemyForces = { current = 0, required = 0, percentage = 0, completed = false }, saveTime = nil } AIO.AddSavedVarChar("MythicPlusCharRunState") local MythicHandlers = AIO.AddHandlers("AIO_Mythic", {}) local lastKeystoneLink = nil local lastMapName = nil local lastTierLevel = nil local fmt, floor = string.format, math.floor local localeDataReceived = false function MythicHandlers.ReceiveLocaleData(_, category, entries) if type(entries) == "table" then L[category] = entries if L.Items and L.Dungeons and L.UI then localeDataReceived = true if MythicPlusFrame then UpdateLocalizedElements() end end end end function MythicGetText(category, key) local localeIndex = GetLocale() and MythicGetLocaleIndex() or 0 return L:Text(category, key, localeIndex) end function MythicGetLocaleIndex() local locale = GetLocale() local localeMap = { ["enUS"] = 0, ["enGB"] = 0, ["koKR"] = 1, ["frFR"] = 2, ["deDE"] = 3, ["zhCN"] = 4, ["zhTW"] = 5, ["esES"] = 6, ["esMX"] = 7, ["ruRU"] = 8 } return localeMap[locale] or 0 end function UpdateLocalizedElements() if DUNGEONS then for mapId, dungeonData in pairs(DUNGEONS) do dungeonData.name = MythicGetText("Dungeons", dungeonData.originalName) end end if MythicPlusFrame then if tabs then for i, tab in ipairs(tabs) do if i == 1 then tab:SetText(MythicGetText("UI", "Overview")) elseif i == 2 then tab:SetText(MythicGetText("UI", "Score")) elseif i == 3 then tab:SetText(MythicGetText("UI", "Leaderboard")) end end end if MythicPlusFrame.overviewTitle then MythicPlusFrame.overviewTitle:SetText(MythicGetText("UI", "Overview")) end if MythicPlusFrame.scoreTitle then MythicPlusFrame.scoreTitle:SetText(MythicGetText("UI", "Score")) end if MythicPlusFrame.leaderboardTitle then MythicPlusFrame.leaderboardTitle:SetText(MythicGetText("UI", "Leaderboard")) end if frame and frame.affixButtons then for _, button in ipairs(frame.affixButtons) do if button.affixName then local isActive = frame.currentAffixes and (button.affixName == frame.currentAffixes[1] or button.affixName == frame.currentAffixes[2] or button.affixName == frame.currentAffixes[3]) button.label:SetText((isActive and "|cff00ff00" or "") .. MythicGetText("UI", button.affixName)) button:SetScript("OnEnter", function(self) GameTooltip:SetOwner(self, "ANCHOR_RIGHT") local color = AFFIXES[button.affixName].color or "|cffffffff" GameTooltip:SetText(color .. MythicGetText("UI", button.affixName) .. "|r") GameTooltip:AddLine(AFFIXES[button.affixName].description or "", 1, 1, 1, true) GameTooltip:Show() end) end end end if frame and frame.scoreButtons then for i, button in ipairs(frame.scoreButtons) do local mapId = DUNGEON_ORDER[i] if mapId and DUNGEONS[mapId] then button.nameLabel:SetText(DUNGEONS[mapId].name) end end end if frame and frame.leaderboardButtons then for i, button in ipairs(frame.leaderboardButtons) do local mapId = DUNGEON_ORDER[i] if mapId then button:SetScript("OnEnter", function(self) GameTooltip:SetOwner(self, "ANCHOR_RIGHT") GameTooltip:SetText(MythicGetText("Dungeons", DUNGEONS[mapId].originalName)) GameTooltip:Show() end) end end end if MythicPlusFrame:IsVisible() and MythicPlusFrame.currentTab then SetActiveTab(MythicPlusFrame.currentTab) end end end local DUNGEONS = { [574] = { originalName = "Utgarde Keep", name = "Utgarde Keep", icon = "Interface\\Icons\\achievement_boss_svalasorrowgrave" }, [575] = { originalName = "Utgarde Pinnacle", name = "Utgarde Pinnacle", icon = "Interface\\Icons\\achievement_boss_kingymiron" }, [576] = { originalName = "The Nexus", name = "The Nexus", icon = "Interface\\Icons\\spell_frost_frozencore" }, [578] = { originalName = "The Oculus", name = "The Oculus", icon = "Interface\\Icons\\achievement_boss_eregos" }, [595] = { originalName = "The Culling of Stratholme", name = "The Culling of Stratholme", icon = "Interface\\Icons\\achievement_dungeon_cotstratholme_normal" }, [599] = { originalName = "Halls of Stone", name = "Halls of Stone", icon = "Interface\\Icons\\achievement_boss_sjonnir" }, [600] = { originalName = "Drak'Tharon Keep", name = "Drak'Tharon Keep", icon = "Interface\\Icons\\inv_bone_skull_04" }, [601] = { originalName = "Azjol-Nerub", name = "Azjol-Nerub", icon = "Interface\\Icons\\inv_misc_head_nerubian_01" }, [602] = { originalName = "Halls of Lightning", name = "Halls of Lightning", icon = "Interface\\Icons\\achievement_boss_archaedas" }, [604] = { originalName = "Gundrak", name = "Gundrak", icon = "Interface\\Icons\\achievement_boss_galdarah" }, [608] = { originalName = "The Violet Hold", name = "The Violet Hold", icon = "Interface\\Icons\\achievement_reputation_kirintor" }, [619] = { originalName = "Ahn'kahet: The Old Kingdom", name = "Ahn'kahet: The Old Kingdom", icon = "Interface\\Icons\\achievement_boss_yoggsaron_01" }, [632] = { originalName = "The Forge of Souls", name = "The Forge of Souls", icon = "Interface\\Icons\\achievement_boss_devourerofsouls" }, [650] = { originalName = "Trial of the Champion", name = "Trial of the Champion", icon = "Interface\\Icons\\achievement_reputation_argentcrusader" }, [658] = { originalName = "Pit of Saron", name = "Pit of Saron", icon = "Interface\\Icons\\achievement_boss_scourgelordtyrannus" }, [668] = { originalName = "Halls of Reflection", name = "Halls of Reflection", icon = "Interface\\Icons\\achievement_dungeon_icecrown_frostmourne" }, } AIO.Handle("AIO_Mythic", "RequestLocaleData", "Items") AIO.Handle("AIO_Mythic", "RequestLocaleData", "Dungeons") AIO.Handle("AIO_Mythic", "RequestLocaleData", "UI") AIO.Handle("AIO_Mythic", "RequestRunState") local DUNGEON_ORDER = { 574, 575, 576, 578, 595, 599, 600, 601, 602, 604, 608, 619, 632, 650, 658, 668 } local AFFIXES = { ["Enrage"] = { icon = "Interface\\Icons\\spell_nature_shamanrage", color = "|cffff0000", description = function() return MythicGetText("UI", "Enrage Description") end }, ["Rejuvenating"] = { icon = "Interface\\Icons\\ability_druid_empoweredrejuvination", color = "|cff00ff00", description = function() return MythicGetText("UI", "Rejuvenating Description") end }, ["Turtling"] = { icon = "Interface\\Icons\\ability_warrior_shieldmastery", color = "|cffffff00", description = function() return MythicGetText("UI", "Turtling Description") end }, ["Shamanism"] = { icon = "Interface\\Icons\\spell_fire_totemofwrath", color = "|cffa335ee", description = function() return MythicGetText("UI", "Shamanism Description") end }, ["Magus"] = { icon = "Interface\\Icons\\ability_mage_hotstreak", color = "|cff3399ff", description = function() return MythicGetText("UI", "Magus Description") end }, ["Priest Empowered"] = { icon = "Interface\\Icons\\spell_holy_searinglightpriest", color = "|cffcccccc", description = function() return MythicGetText("UI", "Priest Empowered Description") end }, ["Demonism"] = { icon = "Interface\\Icons\\ability_warlock_demonicpower", color = "|cff8b0000", description = function() return MythicGetText("UI", "Demonism Description") end }, ["Falling Stars"] = { icon = "Interface\\Icons\\ability_druid_starfall", color = "|cff66ccff", description = function() return MythicGetText("UI", "Falling Stars Description") end }, } function MythicHandlers.ReceiveMapNameAndTier(_, mapName, tier) local originalMapName = mapName for id, dungeon in pairs(DUNGEONS) do if dungeon.originalName == mapName then mapName = MythicGetText("Dungeons", dungeon.originalName) break end end lastMapName = mapName lastTierLevel = tier if GameTooltip:IsShown() then local name, link = GameTooltip:GetItem() if link and name and (string.find(name, "Mythic Keystone") or string.find(name, MythicGetText("Items", "Mythic Keystone"))) then GameTooltip:Hide() GameTooltip:SetOwner(UIParent, "ANCHOR_CURSOR") GameTooltip:SetHyperlink(link) end end end local lineAdded = false function OnTooltipSetItem(tooltip) local name, link = tooltip:GetItem() local englishName = "Mythic Keystone" local localizedName = MythicGetText("Items", "Mythic Keystone") if not name or (not string.find(name, englishName) and not string.find(name, localizedName)) then return end if link ~= lastKeystoneLink then lastKeystoneLink = link lastMapName = "Loading..." lastTierLevel = "Loading..." AIO.Handle("AIO_Mythic", "RequestMapNameAndTier") end local line = _G[tooltip:GetName() .. "TextLeft2"] if line then local tierText = lastTierLevel and lastTierLevel ~= "Loading..." and ("+" .. lastTierLevel) or "" line:SetText("|cffa335ee" .. MythicGetText("UI", "Mythic") .. tierText .. " |r" .. (lastMapName or "Loading...")) line:Show() tooltip:Show() end end local function OnTooltipCleared(tooltip) lineAdded = false end GameTooltip:HookScript("OnTooltipSetItem", OnTooltipSetItem) GameTooltip:HookScript("OnTooltipCleared", OnTooltipCleared) local mythicMiniButton = CreateFrame("Button", "MythicPlusMiniButton", Minimap) mythicMiniButton:SetSize(24, 24) mythicMiniButton:SetFrameStrata("MEDIUM") mythicMiniButton:SetHighlightTexture("Interface\\Minimap\\UI-Minimap-ZoomButton-Highlight") mythicMiniButton:SetNormalTexture("Interface\\AddOns\\Blizzard_AchievementUI\\UI-Achievement-MinimapButton") mythicMiniButton:SetPushedTexture("Interface\\AddOns\\Blizzard_AchievementUI\\UI-Achievement-MinimapButton-Down") local icon = mythicMiniButton:CreateTexture(nil, "ARTWORK") icon:SetTexture("Interface\\Icons\\achievement_bg_wineos_underxminutes") icon:SetTexCoord(0.07, 0.93, 0.07, 0.93) icon:SetAllPoints(mythicMiniButton) local border = mythicMiniButton:CreateTexture(nil, "OVERLAY") border:SetTexture("Interface\\Minimap\\MiniMap-TrackingBorder") border:SetSize(64, 64) border:SetPoint("CENTER", mythicMiniButton, "CENTER", 12, -12) mythicMiniButton:SetPoint("TOPLEFT", Minimap, "BOTTOMLEFT", -20, 70) mythicMiniButton:SetScript("OnEnter", function(self) GameTooltip:SetOwner(self, "ANCHOR_LEFT") GameTooltip:SetText(MythicGetText("UI", "Mythic+")) if self.hasVaultLoot then GameTooltip:AddLine(MythicGetText("UI", "There is loot in your Vault in Dalaran City"), 1, 1, 0) end GameTooltip:Show() end) mythicMiniButton:SetScript("OnLeave", GameTooltip_Hide) mythicMiniButton:SetScript("OnClick", function() if MythicPlusFrame:IsShown() then PlaySound("igCharacterInfoClose") MythicPlusFrame:Hide() else PlaySound("igCharacterInfoOpen") MythicPlusFrame:Show() end end) function MythicHandlers.ReceiveWeeklyAffixes(_, affix1, affix2, affix3) local function colorize(name) return (AFFIXES[name].color or "|cffffffff") .. MythicGetText("UI", name) .. "|r" end local text = MythicGetText("UI", "This week's affixes:") .. " " .. colorize(affix1) .. ", " .. colorize(affix2) .. ", " .. colorize(affix3) MythicPlusFrame.affixText:SetText(text) MythicPlusFrame.currentAffixes = {affix1, affix2, affix3} for _, button in ipairs(MythicPlusFrame.affixButtons) do local name = button.affixName local label = button.label local isActive = name == affix1 or name == affix2 or name == affix3 label:SetText((isActive and "|cff00ff00" or "") .. MythicGetText("UI", name)) end end MythicPlusFrame = CreateFrame("Frame", "MythicPlusFrame", UIParent) local frame = MythicPlusFrame if localeDataReceived then UpdateLocalizedElements() end frame:SetSize(720, 480) frame:SetPoint("CENTER", UIParent, "CENTER", 270, 270) frame:SetToplevel(true) frame:SetClampedToScreen(true) frame:SetMovable(true) frame:EnableMouse(true) frame:RegisterForDrag("LeftButton") frame:SetScript("OnDragStart", frame.StartMoving) frame:SetScript("OnHide", function(self)PlaySound("igCharacterInfoClose") self:StopMovingOrSizing() end) frame:SetScript("OnDragStop", frame.StopMovingOrSizing) for _, region in ipairs({frame:GetRegions()}) do if region:GetObjectType() == "Texture" then region:Hide() end end local paperBG = frame:CreateTexture(nil, "BACKGROUND") paperBG:SetTexture("Interface\\MythicPlus\\textures\\Paper") paperBG:SetAllPoints(frame) paperBG:SetTexCoord(0, 1, 75/1024, (1024-75)/1024) local borderSize = 167 local borderCornerTexCoordW = 167/256 local borderCornerTexCoordH = 168/256 local borderExpansion = math.floor(borderSize * 0.1) local topLeftCorner = frame:CreateTexture(nil, "ARTWORK") topLeftCorner:SetTexture("Interface\\MythicPlus\\textures\\Border") topLeftCorner:SetSize(borderSize, borderSize) topLeftCorner:SetPoint("TOPLEFT", frame, "TOPLEFT", -borderExpansion, borderExpansion) topLeftCorner:SetTexCoord(0, borderCornerTexCoordW, 0, borderCornerTexCoordH) local topRightCorner = frame:CreateTexture(nil, "ARTWORK") topRightCorner:SetTexture("Interface\\MythicPlus\\textures\\Border") topRightCorner:SetSize(borderSize, borderSize) topRightCorner:SetPoint("TOPRIGHT", frame, "TOPRIGHT", borderExpansion, borderExpansion) topRightCorner:SetTexCoord(borderCornerTexCoordW, 0, 0, borderCornerTexCoordH) local bottomLeftCorner = frame:CreateTexture(nil, "ARTWORK") bottomLeftCorner:SetTexture("Interface\\MythicPlus\\textures\\Border") bottomLeftCorner:SetSize(borderSize, borderSize) bottomLeftCorner:SetPoint("BOTTOMLEFT", frame, "BOTTOMLEFT", -borderExpansion, -borderExpansion) bottomLeftCorner:SetTexCoord(0, borderCornerTexCoordW, borderCornerTexCoordH, 0) local bottomRightCorner = frame:CreateTexture(nil, "ARTWORK") bottomRightCorner:SetTexture("Interface\\MythicPlus\\textures\\Border") bottomRightCorner:SetSize(borderSize, borderSize) bottomRightCorner:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", borderExpansion, -borderExpansion) bottomRightCorner:SetTexCoord(borderCornerTexCoordW, 0, borderCornerTexCoordH, 0) local topBorder = frame:CreateTexture(nil, "ARTWORK") topBorder:SetTexture("Interface\\MythicPlus\\textures\\Border_Top") topBorder:SetHeight(32) topBorder:SetPoint("TOPLEFT", topLeftCorner, "TOPRIGHT", 0, 0) topBorder:SetPoint("TOPRIGHT", topRightCorner, "TOPLEFT", 0, 0) local topBorderWidth = 720 + (borderExpansion * 2) - (borderSize * 2) local topTexCoordRight = math.min(1.0, topBorderWidth / 1024) topBorder:SetTexCoord(0, topTexCoordRight, 0, 1) local bottomBorder = frame:CreateTexture(nil, "ARTWORK") bottomBorder:SetTexture("Interface\\MythicPlus\\textures\\Border_Bottom") bottomBorder:SetHeight(32) bottomBorder:SetPoint("BOTTOMLEFT", bottomLeftCorner, "BOTTOMRIGHT", 0, 0) bottomBorder:SetPoint("BOTTOMRIGHT", bottomRightCorner, "BOTTOMLEFT", 0, 0) local bottomTexCoordRight = math.min(1.0, topBorderWidth / 1024) bottomBorder:SetTexCoord(0, bottomTexCoordRight, 0, 1) local leftBorder = frame:CreateTexture(nil, "ARTWORK") leftBorder:SetTexture("Interface\\MythicPlus\\textures\\Border_Left") leftBorder:SetWidth(32) leftBorder:SetPoint("TOPLEFT", topLeftCorner, "BOTTOMLEFT", -1, 0) leftBorder:SetPoint("BOTTOMLEFT", bottomLeftCorner, "TOPLEFT", -1, 0) local leftBorderHeight = 480 + (borderExpansion * 2) - (borderSize * 2) local leftTexCoordBottom = math.min(1.0, leftBorderHeight / 1024) leftBorder:SetTexCoord(0, 1, 0, leftTexCoordBottom) local rightBorder = frame:CreateTexture(nil, "ARTWORK") rightBorder:SetTexture("Interface\\MythicPlus\\textures\\Border_Right") rightBorder:SetWidth(32) rightBorder:SetPoint("TOPRIGHT", topRightCorner, "BOTTOMRIGHT", 1, 0) rightBorder:SetPoint("BOTTOMRIGHT", bottomRightCorner, "TOPRIGHT", 1, 0) local rightTexCoordBottom = math.min(1.0, leftBorderHeight / 1024) rightBorder:SetTexCoord(0, 1, 0, rightTexCoordBottom) table.insert(UISpecialFrames, "MythicPlusFrame") frame:Hide() local tabBackground = CreateFrame("Frame", nil, frame) tabBackground:SetSize(120, 400) tabBackground:SetPoint("TOPLEFT", frame, "TOPLEFT", 20, -20) local function CreateStyledTabButton(parent, text, index, onClick) local button = CreateFrame("Button", nil, parent, "UIPanelButtonTemplate") button:SetSize(100, 32) button:SetPoint("TOPLEFT", parent, "TOPLEFT", 10, -20 - ((index - 1) * 35)) button:SetText(text) button:SetNormalFontObject("GameFontNormal") button:GetNormalTexture():SetVertexColor(0.8, 0.2, 0.2, 1) button:GetHighlightTexture():SetVertexColor(1, 0.3, 0.3, 1) button:GetPushedTexture():SetVertexColor(0.6, 0.1, 0.1, 1) button.isSelected = false button:SetScript("OnClick", function() onClick(index) end) return button end local function CreateBannerTitle(parent, text, anchorPoint) local banner = parent:CreateTexture(nil, "OVERLAY") banner:SetTexture("Interface\\MythicPlus\\textures\\Banner") banner:SetSize(256, 64) banner:SetPoint("TOP", parent, "TOP", 40, anchorPoint) local title = parent:CreateFontString(nil, "OVERLAY", "GameFontHighlightLarge") title:SetPoint("CENTER", banner, "CENTER", 0, 0) title:SetText(text) title:SetFont("Fonts\\FRIZQT__.TTF", 20, "OUTLINE") title:SetTextColor(1, 1, 1) return banner, title end local overviewBanner, overviewTitle = CreateBannerTitle(frame, MythicGetText("UI", "Overview"), 0) frame.overviewTitle = overviewTitle frame.overviewBanner = overviewBanner local scoreBanner, scoreTitle = CreateBannerTitle(frame, MythicGetText("UI", "Score"), 0) frame.scoreTitle = scoreTitle frame.scoreBanner = scoreBanner scoreBanner:Hide() scoreTitle:Hide() local leaderboardBanner, leaderboardTitle = CreateBannerTitle(frame, MythicGetText("UI", "Leaderboard"), 0) frame.leaderboardTitle = leaderboardTitle frame.leaderboardBanner = leaderboardBanner leaderboardBanner:Hide() leaderboardTitle:Hide() local affixText = frame:CreateFontString(nil, "OVERLAY", "GameFontNormal") affixText:SetPoint("TOP", overviewBanner, "BOTTOM", 0, -10) affixText:SetJustifyH("CENTER") affixText:SetFont("Fonts\\FRIZQT__.TTF", 14, "OUTLINE") affixText:SetText(MythicGetText("UI", "This week's affixes:") .. " Loading...") frame.affixText = affixText local scoreText = frame:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge") scoreText:SetPoint("TOP", scoreBanner, "BOTTOM", 0, -10) scoreText:SetText("Score: Loading...") frame.scoreText = scoreText scoreText:Hide() local affixNames = { "Enrage", "Rejuvenating", "Turtling", "Shamanism", "Magus", "Priest Empowered", "Demonism", "Falling Stars" } frame.affixButtons = {} local buttonSize = 80 local buttonSpacing = 30 local columns = 4 local totalWidth = columns * buttonSize + (columns - 1) * buttonSpacing local startX = -(totalWidth / 2) + 40 for i, name in ipairs(affixNames) do local button = CreateFrame("Button", nil, frame) button:SetSize(buttonSize, buttonSize) local row = math.floor((i - 1) / columns) local col = (i - 1) % columns button:SetPoint( "TOP", affixText, "BOTTOM", startX + col * (buttonSize + buttonSpacing), -40 - row * (buttonSize + buttonSpacing) ) local icon = button:CreateTexture(nil, "BACKGROUND") icon:SetAllPoints() icon:SetTexture(AFFIXES[name].icon or "Interface\\Icons\\spell_nature_polymorph") local label = button:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") label:SetPoint("TOP", button, "BOTTOM", 0, -2) label:SetFont("Fonts\\FRIZQT__.TTF", 12, "") label:SetText(name) button.affixName = name button.label = label button:SetScript("OnEnter", function(self) GameTooltip:SetOwner(self, "ANCHOR_RIGHT") local color = AFFIXES[name].color or "|cffffffff" GameTooltip:SetText(color .. MythicGetText("UI", name) .. "|r") local description = AFFIXES[name].description if type(description) == "function" then description = description() end GameTooltip:AddLine(description or "", 1, 1, 1, true) GameTooltip:Show() end) button:SetScript("OnLeave", function() GameTooltip:Hide() end) frame.affixButtons[i] = button end frame.scoreButtons = {} local scoreButtonSize = 50 local scoreCols = 4 local scoreButtonSpacingX = 60 local scoreButtonSpacingY = 26 local scoreStartX = -(scoreCols * scoreButtonSize + (scoreCols - 1) * scoreButtonSpacingX) / 2 + 25 for i, mapId in ipairs(DUNGEON_ORDER) do local name = DUNGEONS[mapId].name or ("Map " .. mapId) local icon = DUNGEONS[mapId].icon or "Interface\\Icons\\inv_misc_questionmark" local button = CreateFrame("Button", nil, frame) button:SetSize(scoreButtonSize, scoreButtonSize) local row = math.floor((i - 1) / scoreCols) local col = (i - 1) % scoreCols button:SetPoint( "TOP", scoreText, "BOTTOM", scoreStartX + col * (scoreButtonSize + scoreButtonSpacingX), -20 - row * (scoreButtonSize + scoreButtonSpacingY) ) local tex = button:CreateTexture(nil, "BACKGROUND") tex:SetAllPoints() tex:SetTexture(icon) local scoreFontSize = 16 local scoreLabel = button:CreateFontString(nil, "OVERLAY") scoreLabel:SetPoint("CENTER", button, "CENTER", 0, -15) scoreLabel:SetFont("Fonts\\FRIZQT__.TTF", scoreFontSize, "OUTLINE, THICK") scoreLabel:SetText("0") button.scoreLabel = scoreLabel local nameLabel = button:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") nameLabel:SetPoint("TOP", button, "BOTTOM", 0, 0) nameLabel:SetWidth(scoreButtonSize + 40) nameLabel:SetFont("Fonts\\FRIZQT__.TTF", 10, "OUTLINE") nameLabel:SetWordWrap(true) nameLabel:SetText(DUNGEONS[mapId].name or ("Map " .. mapId)) nameLabel:SetJustifyH("CENTER") nameLabel:SetJustifyV("TOP") button.nameLabel = nameLabel button:Hide() frame.scoreButtons[i] = button end frame.podiums = {} local podiumSpecs = { { height = 60, color = {0.8, 0.8, 0.8,}, x = -140 }, { height = 90, color = {0.95, 0.84, 0.0}, x = 0 }, { height = 40, color = {0.72, 0.45, 0.2}, x = 140 }, } for i, spec in ipairs(podiumSpecs) do local podium = CreateFrame("Frame", nil, frame) podium:SetSize(135, spec.height) podium:SetPoint("BOTTOM", leaderboardBanner, "TOP", spec.x + 0, -200) local bg = podium:CreateTexture(nil, "BACKGROUND") bg:SetAllPoints() bg:SetTexture(spec.color[1], spec.color[2], spec.color[3], 1) local name = podium:CreateFontString(nil, "OVERLAY", "GameFontNormal") name:SetPoint("BOTTOM", podium, "TOP", 0, 4) name:SetText("—") podium.name = name local score = podium:CreateFontString(nil, "OVERLAY", "GameFontHighlightLarge") score:SetPoint("CENTER", podium, "CENTER") score:SetText("0") podium.score = score podium:Hide() frame.podiums[i] = podium end frame.leaderboardButtons = {} local lbButtonSize = 53 local lbSpacingX = 20 local lbSpacingY = 15 local lbCols = 6 local lbStartX = -(lbCols * lbButtonSize + (lbCols - 1) * lbSpacingX) / 2 + 166 for i, mapId in ipairs(DUNGEON_ORDER) do local button = CreateFrame("Button", nil, frame) button:SetSize(lbButtonSize, lbButtonSize) local row = math.floor((i - 1) / lbCols) local col = (i - 1) % lbCols button:SetPoint( "TOP", frame.podiums[1], "BOTTOM", lbStartX + col * (lbButtonSize + lbSpacingX), -20 - row * (lbButtonSize + lbSpacingY) ) local icon = button:CreateTexture(nil, "BACKGROUND") icon:SetAllPoints() icon:SetTexture(DUNGEONS[mapId].icon or "Interface\\Icons\\inv_misc_questionmark") button:Hide() frame.leaderboardButtons[i] = button end local tabs = {} local function SetActiveTab(index) PlaySound("igMainMenuOptionCheckBoxOn") frame.currentTab = index for i, tab in ipairs(tabs) do if i == index then tab.isSelected = true tab:GetNormalTexture():SetVertexColor(1, 0.4, 0.4, 1) tab:GetHighlightTexture():SetVertexColor(1, 0.5, 0.5, 1) else tab.isSelected = false tab:GetNormalTexture():SetVertexColor(0.8, 0.2, 0.2, 1) tab:GetHighlightTexture():SetVertexColor(1, 0.3, 0.3, 1) end end local showOverview = index == 1 local showScore = index == 2 local showLeaderboard = index == 3 if showOverview then frame.overviewBanner:Show() frame.overviewTitle:Show() frame.affixText:Show() for _, button in ipairs(frame.affixButtons) do button:Show() end else frame.overviewBanner:Hide() frame.overviewTitle:Hide() frame.affixText:Hide() for _, button in ipairs(frame.affixButtons) do button:Hide() end end if showScore then frame.scoreBanner:Show() frame.scoreTitle:Show() frame.scoreText:Show() for _, btn in ipairs(frame.scoreButtons) do btn:Show() end AIO.Handle("AIO_Mythic", "RequestTotalPoints") else frame.scoreBanner:Hide() frame.scoreTitle:Hide() frame.scoreText:Hide() for _, btn in ipairs(frame.scoreButtons) do btn:Hide() end end if showLeaderboard then frame.leaderboardBanner:Show() frame.leaderboardTitle:Show() for _, podium in ipairs(frame.podiums) do podium:Show() end for _, btn in ipairs(frame.leaderboardButtons) do btn:Show() end AIO.Handle("AIO_Mythic", "RequestLeaderboard") else frame.leaderboardBanner:Hide() frame.leaderboardTitle:Hide() for _, podium in ipairs(frame.podiums) do podium:Hide() end for _, btn in ipairs(frame.leaderboardButtons) do btn:Hide() end end if showOverview then AIO.Handle("AIO_Mythic", "RequestWeeklyAffixes") end end tabs[1] = CreateStyledTabButton(tabBackground, MythicGetText("UI", "Overview"), 1, SetActiveTab) tabs[2] = CreateStyledTabButton(tabBackground, MythicGetText("UI", "Score"), 2, SetActiveTab) tabs[3] = CreateStyledTabButton(tabBackground, MythicGetText("UI", "Leaderboard"), 3, SetActiveTab) SetActiveTab(1) function MythicHandlers.ReceiveLeaderboard(_, topThree, dungeonTop) local visualToRank = {2, 1, 3} for i = 1, 3 do local rank = visualToRank[i] local entry = topThree[rank] local podium = frame.podiums[i] if entry then podium.name:SetText(entry.name) podium.score:SetText(string.format("%.2f", entry.points)) podium.name:SetFont("Fonts\\FRIZQT__.TTF", 14, "OUTLINE, THICK") podium.score:SetFont("Fonts\\FRIZQT__.TTF", 14, "OUTLINE") else podium.name:SetText("—") podium.score:SetText("0") podium.name:SetFont("Fonts\\FRIZQT__.TTF", 14, "OUTLINE, THICK") podium.score:SetFont("Fonts\\FRIZQT__.TTF", 14, "OUTLINE") end end for i, mapId in ipairs(DUNGEON_ORDER) do local top = dungeonTop[tostring(mapId)] local button = frame.leaderboardButtons[i] if button then button:SetScript("OnEnter", function(self) GameTooltip:SetOwner(self, "ANCHOR_RIGHT") GameTooltip:SetText(MythicGetText("Dungeons", DUNGEONS[mapId].originalName)) if top then GameTooltip:AddLine(MythicGetText("UI", "Highest Score:"), 1, 1, 0) GameTooltip:AddLine(" " .. top.name .. ": " .. top.score, 1, 1, 1) if top.highestKey and top.highestKey > 0 then local highestKeyText = MythicGetText("UI", "Highest Key +%d by:"):format(top.highestKey) GameTooltip:AddLine(highestKeyText, 1, 1, 0) if top.keyHolderNames and #top.keyHolderNames > 0 then for _, memberName in ipairs(top.keyHolderNames) do GameTooltip:AddLine(" " .. memberName, 0.8, 1, 0.8) end else GameTooltip:AddLine(" " .. MythicGetText("UI", "Unknown"), 0.8, 1, 0.8) end else GameTooltip:AddLine(MythicGetText("UI", "Highest Key: None completed in time"), 0.7, 0.7, 0.7) end else GameTooltip:AddLine(MythicGetText("UI", "No records available"), 0.7, 0.7, 0.7) end GameTooltip:Show() end) button:SetScript("OnLeave", GameTooltip_Hide) end end end local affixNames = { "Enrage", "Rejuvenating", "Turtling", "Shamanism", "Magus", "Priest Empowered", "Demonism", "Falling Stars" } local tabs = {} local function SetActiveTab(index) PlaySound("igMainMenuOptionCheckBoxOn") for i, tab in ipairs(tabs) do tab.bg:SetTexture(i == index and 0.8 or 0.3, i == index and 0.8 or 0.3, i == index and 0.2 or 0.3, 0.5) end local showOverview = index == 1 local showScore = index == 2 local showLeaderboard = index == 3 if showOverview then frame.overviewTitle:Show() frame.affixText:Show() for _, button in ipairs(frame.affixButtons) do button:Show() end else frame.overviewTitle:Hide() frame.affixText:Hide() for _, button in ipairs(frame.affixButtons) do button:Hide() end end if showScore then frame.scoreTitle:Show() frame.scoreText:Show() for _, btn in ipairs(frame.scoreButtons) do btn:Show() end AIO.Handle("AIO_Mythic", "RequestTotalPoints") else frame.scoreTitle:Hide() frame.scoreText:Hide() for _, btn in ipairs(frame.scoreButtons) do btn:Hide() end end if showLeaderboard then frame.leaderboardTitle:Show() for _, podium in ipairs(frame.podiums) do podium:Show() end for _, btn in ipairs(frame.leaderboardButtons) do btn:Show() end AIO.Handle("AIO_Mythic", "RequestLeaderboard") else frame.leaderboardTitle:Hide() for _, podium in ipairs(frame.podiums) do podium:Hide() end for _, btn in ipairs(frame.leaderboardButtons) do btn:Hide() end end if showOverview then AIO.Handle("AIO_Mythic", "RequestWeeklyAffixes") end end SetActiveTab(1) function MythicHandlers.StartMythicTimerGUI(_, mapId, tier, duration, bossNames, potentialGain, enemiesRequired) potentialGain = tonumber(potentialGain) or 0 enemiesRequired = tonumber(enemiesRequired) or 50 if type(bossNames) ~= "table" then bossNames = {} end local maxDeaths = (tier == 1) and 6 or 4 WatchFrame:Hide(); WATCHFRAME_COLLAPSED = true local baseHeight = 140 + #bossNames * 18 local frameHeight = (enemiesRequired > 0) and (baseHeight + 28) or baseHeight local timerFrame = CreateFrame("Frame", nil, UIParent) timerFrame:SetSize(320, frameHeight) timerFrame:SetPoint("TOPRIGHT", UIParent, "TOPRIGHT", -20, -120) timerFrame:SetMovable(true) timerFrame:EnableMouse(true) timerFrame:RegisterForDrag("LeftButton") timerFrame:SetScript("OnDragStart", function(self) self:StartMoving() end) timerFrame:SetScript("OnDragStop", function(self) self:StopMovingOrSizing() end) local progressBar = timerFrame:CreateTexture(nil, "BACKGROUND") progressBar:SetTexture("Interface\\MythicPlus\\textures\\MythicBar.blp") progressBar:SetSize(0, 128) progressBar:SetPoint("LEFT", timerFrame, "LEFT", 0, -10) progressBar:SetTexCoord(0, 0, 0, 1) progressBar:Hide() local function updateProgress(killedBosses, totalBosses) if totalBosses == 0 then return end local progress = math.min(killedBosses / totalBosses, 1.0) local maxWidth = 256 local currentWidth = maxWidth * progress if progress > 0 then progressBar:Show() progressBar:SetWidth(currentWidth) progressBar:SetTexCoord(0, progress, 0, 1) else progressBar:Hide() end end local goldenFrame = timerFrame:CreateTexture(nil, "ARTWORK") goldenFrame:SetTexture("Interface\\MythicPlus\\textures\\MythicFrame.blp") goldenFrame:SetSize(256, 128) goldenFrame:SetPoint("LEFT", timerFrame, "LEFT", 0, -10) goldenFrame:SetTexCoord(0, 1, 0, 1) local dungeonText = timerFrame:CreateFontString(nil, "OVERLAY", "GameFontHighlight") dungeonText:SetPoint("TOP", goldenFrame, "TOP", 0, -12) local dungeonName = (DUNGEONS[mapId] and DUNGEONS[mapId].name) or ("Map "..mapId) dungeonText:SetFont("Fonts\\FRIZQT__.TTF", 16, "OUTLINE") dungeonText:SetText(fmt("|cffFFD700%s|r", dungeonName)) local tierText = timerFrame:CreateFontString(nil, "OVERLAY", "GameFontNormal") tierText:SetPoint("TOP", goldenFrame, "LEFT", 50, 26) tierText:SetFont("Fonts\\FRIZQT__.TTF", 16, "") tierText:SetText(fmt("|cffFFD700Level %d|r", tier)) local timerText = timerFrame:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge") timerText:SetPoint("CENTER", goldenFrame, "LEFT", 48, -6) timerText:SetFont("Fonts\\FRIZQT__.TTF", 20, "OUTLINE") timerText:SetText(fmt("%02d:%02d", floor(duration/60), duration%60)) local deaths, penalty, bonus = 0, 0, 0 local scoreLabel = timerFrame:CreateFontString(nil, "OVERLAY", "GameFontHighlight") scoreLabel:SetPoint("BOTTOM", goldenFrame, "BOTTOM", 60, 50) local gold, red, green, reset = "|cffFFD700", "|cffff0000", "|cff33ff33", "|r" local scoreStr = gold..potentialGain..reset.." "..gold.."("..reset..red.."-"..penalty..reset..gold.."/"..reset..green.."+"..bonus..reset..gold..")"..reset.." "..gold..deaths.."/"..maxDeaths..reset scoreLabel:SetText(scoreStr) local affixContainer = CreateFrame("Frame", nil, timerFrame) affixContainer:SetSize(200, 30) affixContainer:SetPoint("BOTTOM", scoreLabel, "TOP", 40, 11) local affixIcons = {} local currentAffixes = {} if MythicPlusFrame and MythicPlusFrame.currentAffixes then currentAffixes = MythicPlusFrame.currentAffixes end local numAffixes = math.min(tier, 4) local iconSize = 20 local iconSpacing = 4 local totalWidth = (numAffixes * iconSize) + ((numAffixes - 1) * iconSpacing) local startX = -totalWidth / 2 for i = 1, numAffixes do local affixName = currentAffixes[i] if affixName and AFFIXES[affixName] then local icon = CreateFrame("Button", nil, affixContainer) icon:SetSize(iconSize, iconSize) icon:SetPoint("LEFT", affixContainer, "LEFT", startX + (i-1) * (iconSize + iconSpacing) + 30, -5) local texture = icon:CreateTexture(nil, "ARTWORK") texture:SetAllPoints() texture:SetTexture(AFFIXES[affixName].icon) icon:SetScript("OnEnter", function(self) GameTooltip:SetOwner(self, "ANCHOR_TOP") GameTooltip:SetText(affixName) GameTooltip:Show() end) icon:SetScript("OnLeave", function() GameTooltip:Hide() end) affixIcons[i] = icon end end local bossLabels = {} for i, name in ipairs(bossNames) do local lbl = timerFrame:CreateFontString(nil, "OVERLAY", "GameFontNormal") lbl:SetPoint("TOPLEFT", goldenFrame, "BOTTOMLEFT", 20, 10 - (i-1)*16) lbl:SetText(fmt("%d/%d %s", 0, 1, name)) lbl:SetTextColor(1, 0.82, 0) lbl.bossName = name bossLabels[i] = lbl end local enemyLabel, enemyProgressFrame, enemyPercentText if enemiesRequired > 0 then enemyLabel = timerFrame:CreateFontString(nil, "OVERLAY", "GameFontNormal") enemyLabel:SetPoint("TOPLEFT", goldenFrame, "BOTTOMLEFT", 20, 10 - #bossNames*16) enemyLabel:SetText("0/1 " .. MythicGetText("UI", "Enemy Forces")) enemyLabel:SetTextColor(1, 0.82, 0) enemyProgressFrame = CreateFrame("StatusBar", nil, timerFrame) enemyProgressFrame:SetSize(200, 12) enemyProgressFrame:SetPoint("TOPLEFT", enemyLabel, "BOTTOMLEFT", 0, -10) enemyProgressFrame:SetStatusBarTexture("Interface\\TargetingFrame\\UI-StatusBar") enemyProgressFrame:SetStatusBarColor(0.2, 0.8, 0.2) enemyProgressFrame:SetMinMaxValues(0, 100) enemyProgressFrame:SetValue(0) local enemyProgressBorder = CreateFrame("Frame", nil, timerFrame, BackdropTemplateMixin and "BackdropTemplate") enemyProgressBorder:SetAllPoints(enemyProgressFrame) enemyProgressBorder:SetBackdrop({ edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border", edgeSize = 8, insets = { left = 1, right = 1, top = 1, bottom = 1 } }) enemyProgressBorder:SetBackdropBorderColor(0.5, 0.5, 0.5, 1) enemyPercentText = enemyProgressFrame:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") enemyPercentText:SetPoint("CENTER", enemyProgressFrame, "CENTER") enemyPercentText:SetText("0%") end local elapsed = 0 timerFrame:SetScript("OnUpdate", function(self, dt) if self.stopped then return end elapsed = elapsed + dt local left = duration - elapsed if left < 0 then left = 0 end local m,s = floor(left/60), floor(left%60) local ratio = left/duration local color = "|cff00ff00" if ratio < 0.3 then color = "|cffff0000" elseif ratio < 0.6 then color = "|cffffff00" end timerText:SetText(fmt("%s%02d:%02d|r", color, m, s)) end) timerFrame:Show() MythicBossTimerUI = { frame = timerFrame, timerText = timerText, scoreLabel = scoreLabel, labels = bossLabels, progressBar = progressBar, updateProgress = updateProgress, totalBosses = #bossNames, killedBosses = 0, potentialGain = potentialGain, penalty = 0, bonus = 0, deaths = 0, maxDeaths = maxDeaths, enemyLabel = enemyLabel, enemyProgressFrame = enemyProgressFrame, enemyPercentText = enemyPercentText, enemiesRequired = enemiesRequired, enemiesCurrent = 0 } end function MythicHandlers.UpdateMythicScore(_, newPenalty, newDeaths) local ui = MythicBossTimerUI if not ui or not ui.scoreLabel then return end ui.penalty = tonumber(newPenalty) or ui.penalty ui.deaths = tonumber(newDeaths) or ui.deaths local gold = "|cffcc9933" local red = "|cffff0000" local green = "|cff33ff33" local reset = "|r" local scoreStr = gold..ui.potentialGain..reset.." ".. gold.."("..reset.. red.."-"..ui.penalty..reset.. gold.."/"..reset.. green.."+"..ui.bonus..reset.. gold..")"..reset.." ".. gold..ui.deaths.."/"..ui.maxDeaths..reset ui.scoreLabel:SetText(scoreStr) end function MythicHandlers.FinalizeMythicScore(_, finalPenalty, finalDeaths, finalBonus) local ui = MythicBossTimerUI if not ui or not ui.scoreLabel then return end ui.penalty = tonumber(finalPenalty) or ui.penalty ui.deaths = tonumber(finalDeaths) or ui.deaths ui.bonus = tonumber(finalBonus) or ui.bonus local gold = "|cffcc9933" local red = "|cffff0000" local green = "|cff33ff33" local reset = "|r" local scoreStr = gold..ui.potentialGain..reset.." ".. gold.."("..reset.. red.."-"..ui.penalty..reset.. gold.."/"..reset.. green.."+"..ui.bonus..reset.. gold..")"..reset.." ".. gold..ui.deaths.."/"..ui.maxDeaths..reset ui.scoreLabel:SetText(scoreStr) end function MythicHandlers.MarkBossKilled(_, mapId, bossIndex) local ui = MythicBossTimerUI if not ui or not ui.labels then return end local lbl = ui.labels[bossIndex] if lbl and lbl.bossName then lbl:SetText(fmt("|cff26c426%d/%d %s|r", 1, 1, lbl.bossName)) ui.killedBosses = ui.killedBosses + 1 if ui.updateProgress then ui.updateProgress(ui.killedBosses, ui.totalBosses) end end end function MythicHandlers.StopMythicTimerGUI(_, remaining) local ui = MythicBossTimerUI if ui and ui.timerText then if type(remaining) == "number" then local m, s = floor(remaining/60), floor(remaining%60) ui.timerText:SetText(fmt("|cffffff00%02d:%02d|r", m, s)) end ui.frame.stopped = true end end function MythicHandlers.KillMythicTimerGUI() WatchFrame:Show(); WATCHFRAME_COLLAPSED = nil if MythicBossTimerUI and MythicBossTimerUI.frame then MythicBossTimerUI.frame.stopped = true MythicBossTimerUI.frame:Hide() MythicBossTimerUI.frame:SetScript("OnUpdate", nil) MythicBossTimerUI.frame:SetParent(nil) MythicBossTimerUI.frame = nil end MythicBossTimerUI = nil end function MythicHandlers.StartCountdown(_, seconds) seconds = tonumber(seconds) or 10 if CountdownFrame then CountdownFrame:Hide() CountdownFrame:SetScript("OnUpdate", nil) end if not CountdownFrame then local frame = CreateFrame("Frame", "CountdownFrame", UIParent) frame:SetSize(512, 256) frame:SetPoint("CENTER", UIParent, "CENTER", 0, 250) frame:SetFrameStrata("FULLSCREEN_DIALOG") frame:Hide() frame.digit1 = frame:CreateTexture(nil, "ARTWORK") frame.digit1:SetSize(256, 170) frame.digit1:SetPoint("CENTER", frame, "CENTER", -70, 0) frame.digit1:SetTexture("Interface\\MythicPlus\\textures\\BigTimerNumbers") frame.digit2 = frame:CreateTexture(nil, "ARTWORK") frame.digit2:SetSize(256, 170) frame.digit2:SetPoint("CENTER", frame, "CENTER", 70, 0) frame.digit2:SetTexture("Interface\\MythicPlus\\textures\\BigTimerNumbers") CountdownFrame = frame end local frame = CountdownFrame frame:Show() local function setDigits(num) local texW, texH = 1024, 512 local digitW, digitH = 256, 170 local columns = 4 local n1 = math.floor(num / 10) local n2 = num % 10 local function setDigit(tex, digit) local col = digit % columns local row = math.floor(digit / columns) local l = (col * digitW) / texW local r = ((col + 1) * digitW) / texW local t = (row * digitH) / texH local b = ((row + 1) * digitH) / texH tex:SetTexCoord(l, r, t, b) tex:Show() end if n1 > 0 then setDigit(frame.digit1, n1) frame.digit1:Show() frame.digit2:SetPoint("CENTER", frame, "CENTER", 70, 0) else frame.digit1:Hide() frame.digit2:SetPoint("CENTER", frame, "CENTER", 0, 0) end setDigit(frame.digit2, n2) end setDigits(seconds) PlaySoundFile("Interface\\MythicPlus\\sounds\\UI_BattlegroundCountdown_Timer.ogg", "master") local remaining = seconds frame:SetScript("OnUpdate", function(self, elapsed) if not self.lastUpdate then self.lastUpdate = 0 end self.lastUpdate = self.lastUpdate + elapsed if self.lastUpdate >= 1 then self.lastUpdate = self.lastUpdate - 1 remaining = remaining - 1 if remaining > 0 then setDigits(remaining) PlaySoundFile("Interface\\MythicPlus\\sounds\\UI_BattlegroundCountdown_Timer.ogg", "master") else PlaySoundFile("Interface\\MythicPlus\\sounds\\UI_BattlegroundCountdown_End.ogg", "master") self:Hide() self:SetScript("OnUpdate", nil) end end end) end function MythicHandlers.UpdateVaultStatus(_, hasLoot) if hasLoot then mythicMiniButton.hasVaultLoot = true if not mythicMiniButton.glowTexture then mythicMiniButton.glowTexture = mythicMiniButton:CreateTexture(nil, "OVERLAY") mythicMiniButton.glowTexture:SetTexture("Interface\\SpellActivationOverlay\\IconAlert") mythicMiniButton.glowTexture:SetSize(48, 48) mythicMiniButton.glowTexture:SetPoint("CENTER") mythicMiniButton.glowTexture:SetBlendMode("ADD") end mythicMiniButton.glowTexture:Show() else mythicMiniButton.hasVaultLoot = false if mythicMiniButton.glowTexture then mythicMiniButton.glowTexture:Hide() end end end function MythicHandlers.QueryItemData(_, item1, item2, item3) if not MythicHiddenTooltip then MythicHiddenTooltip = CreateFrame("GameTooltip", "MythicHiddenTooltip", nil, "GameTooltipTemplate") MythicHiddenTooltip:SetOwner(UIParent, "ANCHOR_NONE") end local function QueryItem(itemId) if itemId and itemId > 0 then MythicHiddenTooltip:SetHyperlink("item:"..itemId..":0:0:0:0:0:0:0") MythicHiddenTooltip:Show() end end if item1 and item1 > 0 then QueryItem(item1) end if item2 and item2 > 0 then local item2Timer = CreateFrame("Frame") item2Timer.elapsed = 0 item2Timer:SetScript("OnUpdate", function(self, elapsed) self.elapsed = self.elapsed + elapsed if self.elapsed >= 0.1 then QueryItem(item2) self:SetScript("OnUpdate", nil) end end) end if item3 and item3 > 0 then local item3Timer = CreateFrame("Frame") item3Timer.elapsed = 0 item3Timer:SetScript("OnUpdate", function(self, elapsed) self.elapsed = self.elapsed + elapsed if self.elapsed >= 0.2 then QueryItem(item3) self:SetScript("OnUpdate", nil) end end) end end function MythicHandlers.ShowVaultGUI(_, item1, item2, item3, tier1, tier2, tier3) AIO.Handle("AIO_Mythic", "QueryItemData", item1, item2, item3) if VaultFrame then VaultFrame:Hide() end VaultFrame = CreateFrame("Frame", "MythicVaultFrame", UIParent) VaultFrame:SetSize(600, 450) VaultFrame:SetPoint("CENTER") VaultFrame:SetToplevel(true) local vaultBG = VaultFrame:CreateTexture(nil, "BACKGROUND") vaultBG:SetTexture("Interface\\MythicPlus\\textures\\VaultFrame") vaultBG:SetAllPoints(VaultFrame) vaultBG:SetTexCoord(0, 1, 177/1024, (1024-177)/1024) local title = VaultFrame:CreateFontString(nil, "OVERLAY", "GameFontHighlightLarge") title:SetPoint("TOP", VaultFrame, "TOP", 0, -40) title:SetText(MythicGetText("UI", "Mythic+ Vault")) title:SetFont("Fonts\\FRIZQT__.TTF", 20, "OUTLINE") title:SetTextColor(1, 0.82, 0) local subtitle = VaultFrame:CreateFontString(nil, "OVERLAY", "GameFontNormal") subtitle:SetPoint("TOP", title, "BOTTOM", 0, -2) subtitle:SetText(MythicGetText("UI", "Choose item reward")) subtitle:SetFont("Fonts\\FRIZQT__.TTF", 14, "OUTLINE") subtitle:SetTextColor(0.9, 0.9, 0.9) local items = {item1, item2, item3} local tiers = {tier1, tier2, tier3} local selectedIndex = nil local itemButtons = {} for i = 1, 3 do if items[i] and items[i] > 0 then local button = CreateFrame("Button", nil, VaultFrame) button:SetSize(72, 72) button:SetPoint("TOP", subtitle, "BOTTOM", -190 + (i-1)*190, -80) local icon = button:CreateTexture(nil, "ARTWORK") icon:SetAllPoints(button) button.icon = icon local itemTexture = GetItemIcon(items[i]) if itemTexture then icon:SetTexture(itemTexture) else icon:SetTexture("Interface\\Icons\\inv_misc_questionmark") end local tierLabel = button:CreateFontString(nil, "OVERLAY", "GameFontNormal") tierLabel:SetPoint("TOP", button, "BOTTOM", 0, -5) tierLabel:SetText(MythicGetText("UI", "Tier") .. " " .. (tiers[i] or "?")) tierLabel:SetFont("Fonts\\FRIZQT__.TTF", 12, "OUTLINE") tierLabel:SetTextColor(1, 0.82, 0) button.tierLabel = tierLabel button:SetScript("OnClick", function(self) selectedIndex = i for j, btn in ipairs(itemButtons) do if j == i then btn.icon:SetDesaturated(false) btn.tierLabel:SetTextColor(1, 0.82, 0) else btn.icon:SetDesaturated(true) btn.tierLabel:SetTextColor(0.5, 0.5, 0.5) end end if VaultFrame.confirmButton then VaultFrame.confirmButton:Enable() VaultFrame.confirmButton:SetText("Confirm Selection") end if VaultFrame.selectionText then local itemName, itemLink, itemRarity = GetItemInfo(items[i]) if itemLink then VaultFrame.selectionText:SetText("Selected: " .. itemLink) else VaultFrame.selectionText:SetText("Selected: |cffffffff[Unknown Item]|r") end VaultFrame.selectionText:SetTextColor(1, 0.82, 0) end end) button:SetScript("OnEnter", function(self) GameTooltip:SetOwner(self, "ANCHOR_RIGHT") local itemLink = select(2, GetItemInfo(items[i])) if itemLink then GameTooltip:SetHyperlink(tostring(itemLink)) else print("Item link not found for item ID:", items[i]) local tooltipTimer = CreateFrame("Frame") tooltipTimer.elapsed = 0 tooltipTimer:SetScript("OnUpdate", function(frame, elapsed) frame.elapsed = frame.elapsed + elapsed if frame.elapsed >= 0.1 then local link = select(2, GetItemInfo(items[i])) if link and GameTooltip:IsOwned(self) then GameTooltip:SetHyperlink(link) end frame:SetScript("OnUpdate", nil) end end) end GameTooltip:Show() if selectedIndex ~= i then if not self.highlightTexture then self.highlightTexture = self:CreateTexture(nil, "HIGHLIGHT") self.highlightTexture:SetTexture("Interface\\Buttons\\ButtonHilight-Square") self.highlightTexture:SetAllPoints(self) self.highlightTexture:SetBlendMode("ADD") self.highlightTexture:SetVertexColor(1, 1, 1, 0.3) end self.highlightTexture:Show() end end) button:SetScript("OnLeave", function(self) GameTooltip_Hide() if self.highlightTexture then self.highlightTexture:Hide() end end) button:SetScript("OnMouseDown", function(self) icon:SetPoint("TOPLEFT", 1, -1) icon:SetPoint("BOTTOMRIGHT", 1, -1) end) button:SetScript("OnMouseUp", function(self) icon:SetAllPoints(self) end) itemButtons[i] = button end end local selectionText = VaultFrame:CreateFontString(nil, "OVERLAY", "GameFontNormal") selectionText:SetPoint("TOP", VaultFrame, "TOP", 0, -300) selectionText:SetText(MythicGetText("UI", "No item selected")) selectionText:SetTextColor(1, 0.82, 0) selectionText:SetFont("Fonts\\FRIZQT__.TTF", 14, "") VaultFrame.selectionText = selectionText local confirmButton = CreateFrame("Button", nil, VaultFrame, "UIPanelButtonTemplate") confirmButton:SetSize(140, 30) confirmButton:SetPoint("BOTTOM", VaultFrame, "BOTTOM", 0, 40) confirmButton:SetText(MythicGetText("UI", "Select an Item")) confirmButton:Disable() VaultFrame.confirmButton = confirmButton confirmButton:SetScript("OnClick", function(self) if selectedIndex then AIO.Handle("AIO_Mythic", "SelectVaultItem", selectedIndex) VaultFrame:Hide() end end) local cancelButton = CreateFrame("Button", nil, VaultFrame, "UIPanelButtonTemplate") cancelButton:SetSize(100, 30) cancelButton:SetPoint("BOTTOMLEFT", VaultFrame, "BOTTOMLEFT", 20, 40) cancelButton:SetText(MythicGetText("UI", "Cancel")) cancelButton:SetScript("OnClick", function(self) VaultFrame:Hide() end) VaultFrame:SetScript("OnHide", function(self) selectedIndex = nil end) VaultFrame:Show() end function MythicHandlers.CloseVaultGUI() if VaultFrame then VaultFrame:Hide() end end function MythicHandlers.UpdateEnemyForces(_, current, required, percentage, completed) local ui = MythicBossTimerUI if not ui or not ui.enemyLabel then return end ui.enemiesCurrent = current ui.enemiesRequired = required local completedText = completed and "1" or "0" ui.enemyLabel:SetText(fmt("%s/1 %s", completedText, MythicGetText("UI", "Enemy Forces"))) ui.enemyProgressFrame:SetValue(percentage) ui.enemyPercentText:SetText(fmt("%.0f%%", percentage)) if completed then ui.enemyLabel:SetTextColor(0.15, 0.76, 0.15) else ui.enemyLabel:SetTextColor(1, 0.82, 0) end end function MythicHandlers.ReceiveTotalPoints(_, totalPoints, dungeonScores) if not frame.scoreText then return end frame.scoreText:SetText(MythicGetText("UI", "Total Score:") .. " " .. string.format("%.2f", totalPoints or 0)) for i, mapId in ipairs(DUNGEON_ORDER) do local button = frame.scoreButtons[i] if button and button.scoreLabel then local score = dungeonScores and dungeonScores[tostring(mapId)] or 0 button.scoreLabel:SetText(tostring(score)) if button.nameLabel and DUNGEONS[mapId] then button.nameLabel:SetText(MythicGetText("Dungeons", DUNGEONS[mapId].originalName)) end end end end function MythicHandlers.RestoreRunState(_, runState) if not runState or not runState.active then MythicPlusCharRunState = { active = false, mapId = nil, tier = nil, duration = nil, elapsed = nil, bossNames = {}, killedBosses = {}, potentialGain = 0, penalty = 0, bonus = 0, deaths = 0, maxDeaths = 0, enemyForces = { current = 0, required = 0, percentage = 0, completed = false }, saveTime = nil } return end MythicPlusCharRunState = runState MythicPlusCharRunState.saveTime = GetTime() MythicHandlers.StartMythicTimerGUI(nil, runState.mapId, runState.tier, runState.duration - runState.elapsed, runState.bossNames, runState.potentialGain, runState.enemyForces.required) if MythicBossTimerUI then MythicBossTimerUI.deaths = runState.deaths MythicBossTimerUI.penalty = runState.penalty MythicBossTimerUI.maxDeaths = runState.maxDeaths MythicHandlers.UpdateMythicScore(nil, runState.penalty, runState.deaths) for _, bossIndex in ipairs(runState.killedBosses) do MythicHandlers.MarkBossKilled(nil, runState.mapId, bossIndex) end if runState.enemyForces then MythicHandlers.UpdateEnemyForces(nil, runState.enemyForces.current, runState.enemyForces.required, runState.enemyForces.percentage, runState.enemyForces.completed) end if runState.overtime then MythicHandlers.StartOvertimeMode() end end end function MythicHandlers.ClearRunState() MythicPlusCharRunState = { active = false, mapId = nil, tier = nil, duration = nil, elapsed = nil, bossNames = {}, killedBosses = {}, potentialGain = 0, penalty = 0, bonus = 0, deaths = 0, maxDeaths = 0, enemyForces = { current = 0, required = 0, percentage = 0, completed = false }, saveTime = nil } end function MythicHandlers.StartOvertimeMode() if MythicBossTimerUI and MythicBossTimerUI.timerText then MythicBossTimerUI.timerText:SetText("|cffff0000OVERTIME|r") MythicBossTimerUI.frame.stopped = true end end