Skip to content

Instantly share code, notes, and snippets.

@arcadepro
Created July 27, 2021 15:46
Show Gist options
  • Save arcadepro/b82f28fdc0fcac0af9a05928a422671c to your computer and use it in GitHub Desktop.
Save arcadepro/b82f28fdc0fcac0af9a05928a422671c to your computer and use it in GitHub Desktop.
MythicDungeonTools.lua
-- Made by Nnoggie, 2017-2020
local AddonName, MDT = ...
local L = MDT.L
local mainFrameStrata = "HIGH"
local canvasDrawLayer = "BORDER"
local twipe,tinsert,tremove,tgetn,CreateFrame,tonumber,pi,max,min,atan2,abs,pairs,ipairs,GetCursorPosition,GameTooltip = table.wipe,table.insert,table.remove,table.getn,CreateFrame,tonumber,math.pi,math.max,math.min,math.atan2,math.abs,pairs,ipairs,GetCursorPosition,GameTooltip
local SetPortraitTextureFromCreatureDisplayID,MouseIsOver = SetPortraitTextureFromCreatureDisplayID,MouseIsOver
local sizex = 840
local sizey = 555
local mythicColor = "|cFFFFFFFF"
MDT.BackdropColor = { 0.058823399245739, 0.058823399245739, 0.058823399245739, 0.9}
local AceGUI = LibStub("AceGUI-3.0")
local db
local icon = LibStub("LibDBIcon-1.0")
local LibDD = LibStub:GetLibrary("LibUIDropDownMenu-4.0")
local LDB = LibStub("LibDataBroker-1.1"):NewDataObject("MythicDungeonTools", {
type = "data source",
text = "Mythic Dungeon Tools",
icon = "Interface\\AddOns\\"..AddonName.."\\Textures\\NnoggieMinimap",
OnClick = function(button,buttonPressed)
if buttonPressed == "RightButton" then
if db.minimap.lock then
icon:Unlock("MythicDungeonTools")
else
icon:Lock("MythicDungeonTools")
end
else
MDT:ShowInterface()
end
end,
OnTooltipShow = function(tooltip)
if not tooltip or not tooltip.AddLine then return end
tooltip:AddLine(mythicColor .."Mythic Dungeon Tools|r")
tooltip:AddLine(L["Click to toggle AddOn Window"])
tooltip:AddLine(L["Right-click to lock Minimap Button"])
end,
})
SLASH_MYTHICDUNGEONTOOLS1 = "/mplus"
SLASH_MYTHICDUNGEONTOOLS2 = "/mdt"
SLASH_MYTHICDUNGEONTOOLS3 = "/mythicdungeontools"
BINDING_NAME_MDTTOGGLE = L["Toggle Window"]
BINDING_NAME_MDTNPC = L["New NPC at Cursor Position"]
BINDING_NAME_MDTWAYPOINT = L["New Patrol Waypoint at Cursor Position"]
function SlashCmdList.MYTHICDUNGEONTOOLS(cmd, editbox)
local rqst, arg = strsplit(' ', cmd)
if rqst == "devmode" then
MDT:ToggleDevMode()
elseif rqst == "reset" then
MDT:ResetMainFramePos()
elseif rqst == "dc" then
MDT:ToggleDataCollection()
elseif rqst == "hptrack" then
MDT:ToggleHealthTrack()
else
MDT:ShowInterface()
end
end
function MDT:GetLocaleIndex()
local localeToIndex = {
["enUS"] = 1,
["deDE"] = 2,
["esES"] = 3,
["esMX"] = 4,
["frFR"] = 5,
["itIT"] = 6,
["ptBR"] = 7,
["ruRU"] = 8,
["koKR"] = 9,
["zhCN"] = 10,
["zhTW"] = 11,
}
return localeToIndex[GetLocale()] or 1
end
local initFrames
-------------------------
--- Saved Variables ----
-------------------------
local defaultSavedVars = {
global = {
toolbarExpanded = true,
currentSeason = 6,
currentExpansion = 3,
scale = 1,
enemyForcesFormat = 2,
enemyStyle = 1,
currentDungeonIdx = 29,
currentDifficulty = 10,
xoffset = 0,
yoffset = -150,
defaultColor = "228b22",
anchorFrom = "TOP",
anchorTo = "TOP",
tooltipInCorner = false,
minimap = {
hide = false,
},
toolbar ={
color = {r=1,g=1,b=1,a=1},
brushSize = 3,
},
presets = {},
currentPreset = {},
dataCollectionActive = false,
colorPaletteInfo = {
autoColoring = true,
forceColorBlindMode = false,
colorPaletteIdx = 4,
customPaletteValues = {},
numberCustomColors = 12,
},
language = MDT:GetLocaleIndex(),
dungeonImport = {},
},
}
do
for i=1,37 do
defaultSavedVars.global.presets[i] = {
[1] = {text="Default",value={},colorPaletteInfo={autoColoring=true,colorPaletteIdx=4}},
[2] = {text="<New Preset>",value=0},
}
defaultSavedVars.global.currentPreset[i] = 1
end
end
-- Init db
do
local frame = CreateFrame("Frame")
frame:RegisterEvent("ADDON_LOADED")
frame:RegisterEvent("GROUP_ROSTER_UPDATE")
frame:RegisterEvent("PLAYER_ENTERING_WORLD")
--TODO Register Affix Changed event
frame:SetScript("OnEvent", function(self, event, ...)
return MDT[event](self,...)
end)
function MDT.ADDON_LOADED(self, addon)
if addon == "MythicDungeonTools" then
db = LibStub("AceDB-3.0"):New("MythicDungeonToolsDB", defaultSavedVars).global
icon:Register("MythicDungeonTools", LDB, db.minimap)
if not db.minimap.hide then
icon:Show("MythicDungeonTools")
end
--if db.dataCollectionActive then MDT.DataCollection:Init() end
--fix db corruption
do
for _,presets in pairs(db.presets) do
for presetIdx,preset in pairs(presets) do
if presetIdx == 1 then
if preset.text ~= "Default" then
preset.text = "Default"
preset.value = {}
end
end
end
end
for k,v in pairs(db.currentPreset) do
if v <= 0 then db.currentPreset[k] = 1 end
end
end
--register AddOn Options
MDT:RegisterOptions()
self:UnregisterEvent("ADDON_LOADED")
end
end
local last = 0
function MDT.GROUP_ROSTER_UPDATE(self, addon)
--check not more than once per second (blizzard event spam)
local now = GetTime()
if last < now - 1 then
if not MDT.main_frame then return end
local inGroup = UnitInRaid("player") or IsInGroup()
MDT.main_frame.LinkToChatButton:SetDisabled(not inGroup)
MDT.main_frame.LiveSessionButton:SetDisabled(not inGroup)
if inGroup then
MDT.main_frame.LinkToChatButton.text:SetTextColor(1,0.8196,0)
if MDT.liveSessionActive then
MDT.main_frame.LiveSessionButton:SetText(L["*Live*"])
MDT.main_frame.LiveSessionButton.text:SetTextColor(0,1,0)
else
MDT.main_frame.LiveSessionButton:SetText(L["Live"])
MDT.main_frame.LiveSessionButton.text:SetTextColor(1,0.8196,0)
end
else
MDT.main_frame.LinkToChatButton.text:SetTextColor(0.5,0.5,0.5)
MDT.main_frame.LiveSessionButton.text:SetTextColor(0.5,0.5,0.5)
end
last = now
--MDT:RequestDataCollectionUpdate()
end
end
function MDT.PLAYER_ENTERING_WORLD(self, addon)
--initialize Blizzard_ChallengesUI
C_Timer.After(1,function()
LoadAddOn("Blizzard_ChallengesUI")
C_MythicPlus.RequestCurrentAffixes()
C_MythicPlus.RequestMapInfo()
C_MythicPlus.RequestRewards()
end)
self:UnregisterEvent("PLAYER_ENTERING_WORLD")
end
end
MDT.mapInfo = {}
MDT.dungeonTotalCount = {}
MDT.scaleMultiplier = {}
--affixID as used in C_ChallengeMode.GetAffixInfo(affixID)
--https://www.wowhead.com/affixes
--lvl 4 affix, lvl 7 affix, tyrannical/fortified, seasonal affix
local affixWeeks = {
[1] = {11,124,10,128}, --bursting storming fortified tormented
[2] = {6,3,9,128}, --raging volcanic tyrannical tormented
[3] = {122,12,10,128}, -- insp grev
[4] = {123,4,9,128}, -- spite necro
[5] = {7,14,10,128}, -- bolster quaking
[6] = {0,0,9,128},
[7] = {0,0,10,128},
[8] = {0,0,9,128},
[9] = {0,0,10,128},
[10] = {0,0,9,128},
[11] = {0,0,10,128},
[12] = {0,0,9,128},
}
local dungeonList = {
[1] = L["Black Rook Hold"],
[2] = L["Cathedral of Eternal Night"],
[3] = L["Court of Stars"],
[4] = L["Darkheart Thicket"],
[5] = L["Eye of Azshara"],
[6] = L["Halls of Valor"],
[7] = L["Maw of Souls"],
[8] = L["Neltharion's Lair"],
[9] = L["Return to Karazhan Lower"],
[10] = L["Return to Karazhan Upper"],
[11] = L["Seat of the Triumvirate"],
[12] = L["The Arcway"],
[13] = L["Vault of the Wardens"],
[14] = " >"..L["Battle for Azeroth"],
[15] = L["Atal'Dazar"],
[16] = L["Freehold"],
[17] = L["Kings' Rest"],
[18] = L["Shrine of the Storm"],
[19] = L["Siege of Boralus"],
[20] = L["Temple of Sethraliss"],
[21] = L["The MOTHERLODE!!"],
[22] = L["The Underrot"],
[23] = L["Tol Dagor"],
[24] = L["Waycrest Manor"],
[25] = L["Mechagon - Junkyard"],
[26] = L["Mechagon - Workshop"],
[27] = " <"..L["Legion"],
[28] = " >"..L["Shadowlands"],
[29] = L["De Other Side"],
[30] = L["Halls of Atonement"],
[31] = L["Mists of Tirna Scithe"],
[32] = L["Plaguefall"],
[33] = L["Sanguine Depths"],
[34] = L["Spires of Ascension"],
[35] = L["The Necrotic Wake"],
[36] = L["Theater of Pain"],
[37] = " <"..L["Battle for Azeroth"],
}
function MDT:GetNumDungeons() return #dungeonList-1 end
function MDT:GetDungeonName(idx) return dungeonList[idx] end
local dungeonSubLevels = {
[1] = {
[1] = L["The Ravenscrypt"],
[2] = L["The Grand Hall"],
[3] = L["Ravenshold"],
[4] = L["The Rook's Host"],
[5] = L["Lord Ravencrest's Chamber"],
[6] = L["The Raven's Crown"],
},
[2] = {
[1] = L["Hall of the Moon"],
[2] = L["Twilight Grove"],
[3] = L["The Emerald Archives"],
[4] = L["Path of Illumination"],
[5] = L["Sacristy of Elune"],
},
[3] = {
[1] = L["Court of Stars Sublevel"],
[2] = L["The Jeweled Estate"],
[3] = L["The Balconies"],
},
[4] = {
[1] = L["Darkheart Thicket Sublevel"],
},
[5] = {
[1] = L["Eye of Azshara Sublevel"],
},
[6] = {
[1] = L["The High Gate"],
[2] = L["Field of the Eternal Hunt"],
[3] = L["Halls of Valor Sublevel"],
},
[7] = {
[1] = L["Helmouth Cliffs"],
[2] = L["The Hold"],
[3] = L["The Naglfar"],
},
[8] = {
[1] = L["Neltharion's Lair Sublevel"],
},
[9] = {
[1] = L["Master's Terrace"],
[2] = L["Opera Hall Balcony"],
[3] = L["The Guest Chambers"],
[4] = L["The Banquet Hall"],
[5] = L["Upper Livery Stables"],
[6] = L["The Servant's Quarters"],
},
[10] = {
[1] = L["Lower Broken Stair"],
[2] = L["Upper Broken Stair"],
[3] = L["The Menagerie"],
[4] = L["Guardian's Library"],
[5] = L["Library Floor"],
[6] = L["Upper Library"],
[7] = L["Gamesman's Hall"],
[8] = L["Netherspace"],
},
[11] = {
[1] = L["Seat of the Triumvirate Sublevel"],
},
[12] = {
[1] = L["The Arcway Sublevel"],
},
[13] = {
[1] = L["The Warden's Court"],
[2] = L["Vault of the Wardens Sublevel"],
[3] = L["Vault of the Betrayer"],
},
[15] = {
[1] = L["Atal'Dazar Sublevel"],
[2] = L["Sacrificial Pits"],
},
[16] = {
[1] = L["Freehold Sublevel"],
},
[17] = {
[1] = L["Kings' Rest Sublevel"],
},
[18] = {
[1] = L["Shrine of the Storm Sublevel"],
[2] = L["Storm's End"],
},
[19] = {
[1] = L["Siege of Boralus Sublevel"],
[2] = L["Siege of Boralus (Upstairs)"],
},
[20] = {
[1] = L["Temple of Sethraliss Sublevel"],
[2] = L["Atrium of Sethraliss"],
},
[21] = {
[1] = L["The MOTHERLODE!! Sublevel"],
},
[22] = {
[1] = L["The Underrot Sublevel"],
[2] = L["Ruin's Descent"],
},
[23] = {
[1] = L["Tol Dagor Sublevel1"],
[2] = L["The Drain"],
[3] = L["The Brig"],
[4] = L["Detention Block"],
[5] = L["Officer Quarters"],
[6] = L["Overseer's Redoubt"],
[7] = L["Overseer's Summit"],
},
[24] = {
[1] = L["The Grand Foyer"],
[2] = L["Upstairs"],
[3] = L["The Cellar"],
[4] = L["Catacombs"],
[5] = L["The Rupture"],
},
[25] = {
[1] = L["Mechagon Island"],
[2] = L["Mechagon Island (Tunnels)"],
},
[26] = {
[1] = L["The Robodrome"],
[2] = L["Waste Pipes"],
[3] = L["The Under Junk"],
[4] = L["Mechagon City"],
},
[29] = {
[1] = L["De Other Side"],
[2] = L["Mechagon"],
[3] = L["Zul'Gurub"],
[4] = L["Ardenweald"],
},
[30] = {
[1] = L["HallsOfAtonementFloor1"],
[2] = L["HallsOfAtonementFloor2"],
[3] = L["HallsOfAtonementFloor3"],
},
[31] = {
[1] = L["Mists of Tirna Scithe"],
},
[32] = {
[1] = L["Plaguefall"],
[2] = L["The Festering Sanctum"],
},
[33] = {
[1] = L["Sanguine DepthsFloor1"],
[2] = L["Sanguine DepthsFloor2"],
},
[34] = {
[1] = L["Honor's Ascent"],
[2] = L["Gardens of Repose"],
[3] = L["Font of Fealty"],
[4] = L["Seat of the Archon"],
},
[35] = {
[1] = L["TheNecroticWakeFloor1"],
[2] = L["TheNecroticWakeFloor2"],
[3] = L["TheNecroticWakeFloor3"],
},
[36] = {
[1] = L["TheaterOfPainFloor1"],
[2] = L["TheaterOfPainFloor2"],
[3] = L["TheaterOfPainFloor3"],
[4] = L["TheaterOfPainFloor4"],
[5] = L["TheaterOfPainFloor5"],
},
}
function MDT:GetDungeonSublevels()
return dungeonSubLevels
end
function MDT:GetSublevelName(dungeonIdx, sublevelIdx)
if not dungeonIdx then dungeonIdx = db.currentDungeonIdx end
return dungeonSubLevels[dungeonIdx][sublevelIdx]
end
MDT.dungeonMaps = {
[1] = {
[0]= "BlackRookHoldDungeon",
[1]= "BlackRookHoldDungeon1_",
[2]= "BlackRookHoldDungeon2_",
[3]= "BlackRookHoldDungeon3_",
[4]= "BlackRookHoldDungeon4_",
[5]= "BlackRookHoldDungeon5_",
[6]= "BlackRookHoldDungeon6_",
},
[2] = {
[0]= "TombofSargerasDungeon",
[1]= "TombofSargerasDungeon1_",
[2]= "TombofSargerasDungeon2_",
[3]= "TombofSargerasDungeon3_",
[4]= "TombofSargerasDungeon4_",
[5]= "TombofSargerasDungeon5_",
},
[3] = {
[0] = "SuramarNoblesDistrict",
[1] = "SuramarNoblesDistrict",
[2] = "SuramarNoblesDistrict1_",
[3] = "SuramarNoblesDistrict2_",
},
[4] = {
[0] = "DarkheartThicket",
[1] = "DarkheartThicket",
},
[5] = {
[0]= "AszunaDungeon",
[1]= "AszunaDungeon",
},
[6] = {
[0]= "Hallsofvalor",
[1]= "Hallsofvalor1_",
[2]= "Hallsofvalor",
[3]= "Hallsofvalor2_",
},
[7] = {
[0] = "HelheimDungeonDock",
[1] = "HelheimDungeonDock",
[2] = "HelheimDungeonDock1_",
[3] = "HelheimDungeonDock2_",
},
[8] = {
[0] = "NeltharionsLair",
[1] = "NeltharionsLair",
},
[9] = {
[0] = "LegionKarazhanDungeon",
[1] = "LegionKarazhanDungeon6_",
[2] = "LegionKarazhanDungeon5_",
[3] = "LegionKarazhanDungeon4_",
[4] = "LegionKarazhanDungeon3_",
[5] = "LegionKarazhanDungeon2_",
[6] = "LegionKarazhanDungeon1_",
},
[10] = {
[0] = "LegionKarazhanDungeon",
[1] = "LegionKarazhanDungeon7_",
[2] = "LegionKarazhanDungeon8_",
[3] = "LegionKarazhanDungeon9_",
[4] = "LegionKarazhanDungeon10_",
[5] = "LegionKarazhanDungeon11_",
[6] = "LegionKarazhanDungeon12_",
[7] = "LegionKarazhanDungeon13_",
[8] = "LegionKarazhanDungeon14_",
},
[11] = {
[0] = "ArgusDungeon",
[1] = "ArgusDungeon",
},
[12] = {
[0]= "SuamarCatacombsDungeon",
[1]= "SuamarCatacombsDungeon1_",
},
[13] = {
[0]= "VaultOfTheWardens",
[1]= "VaultOfTheWardens1_",
[2]= "VaultOfTheWardens2_",
[3]= "VaultOfTheWardens3_",
},
[15] = {
[0]= "CityOfGold",
[1]= "CityOfGold1_",
[2]= "CityOfGold2_",
},
[16] = {
[0]= "KulTirasPirateTownDungeon",
[1]= "KulTirasPirateTownDungeon",
},
[17] = {
[0] = "KingsRest",
[1] = "KingsRest1_"
},
[18] = {
[0] = "ShrineOfTheStorm",
[1] = "ShrineOfTheStorm",
[2] = "ShrineOfTheStorm1_",
},
[19] = {
[0] = "SiegeOfBoralus",
[1] = "SiegeOfBoralus",
[2] = "SiegeOfBoralus",
},
[20] = {
[0] = "TempleOfSethralissA",
[1] = "TempleOfSethralissA",
[2] = "TempleOfSethralissB",
},
[21] = {
[0] = "KezanDungeon",
[1] = "KezanDungeon",
},
[22] = {
[0] = "UnderrotExterior",
[1] = "UnderrotExterior",
[2] = "UnderrotInterior",
},
[23] = {
[0] = "PrisonDungeon",
[1] = "PrisonDungeon",
[2] = "PrisonDungeon1_",
[3] = "PrisonDungeon2_",
[4] = "PrisonDungeon3_",
[5] = "PrisonDungeon4_",
[6] = "PrisonDungeon5_",
[7] = "PrisonDungeon6_",
},
[24] = {
[0] = "Waycrest",
[1] = "Waycrest1_",
[2] = "Waycrest2_",
[3] = "Waycrest3_",
[4] = "Waycrest4_",
[5] = "Waycrest5_",
},
[25] = {
[0] = "MechagonDungeon",
[1] = "MechagonDungeonExterior",
[2] = "MechagonDungeonExterior",
},
[26] = {
[0] = "MechagonDungeon",
[1] = "MechagonDungeon1_",
[2] = "MechagonDungeon2_",
[3] = "MechagonDungeon3_",
[4] = "MechagonDungeon4_",
},
[29] = {
[0] = "DeOtherSide_Ardenweald",
[1] = "DeOtherSide_Main",
[2] = "DeOtherSide_Gnome",
[3] = "DeOtherSide_Hakkar",
[4] = "DeOtherSide_Ardenweald",
},
[30] = {
[0] = "HallsOfAtonement_A",
[1] = "HallsOfAttonementExterior",
[2] = "HallsOfAtonement_A",
[3] = "HallsOfAtonement_B",
},
[31] = {
[0] = "MistsOfTirneScithe",
[1] = "MistsOfTirneScithe",
},
[32] = {
[0] = "Plaguefall",
[1] = "Plaguefall",
[2] = "Plaguefall_B",
},
[33] = {
[0] = "SanguineDepths_A",
[1] = "SanguineDepths_A",
[2] = "SanguineDepths_B",
},
[34] = {
[0] = "SpiresOfAscension_A",
[1] = "SpiresOfAscension_A",
[2] = "SpiresOfAscension_B",
[3] = "SpiresOfAscension_C",
[4] = "SpiresOfAscension_D",
},
[35] = {
[0] = "NecroticWake_A",
[1] = "NecroticWake_Exterior",
[2] = "NecroticWake_A",
[3] = "NecroticWake_B",
},
[36] = {
[0] = "TheaterOfPain",
[1] = "TheaterOfPain",
[2] = "TheaterOfPain_Warlord",
[3] = "TheaterOfPain_Lich",
[4] = "TheaterOfPain_AbomTop",
[5] = "TheaterOfPain_AbomBot",
},
}
MDT.dungeonBosses = {}
MDT.dungeonEnemies = {}
MDT.mapPOIs = {}
function MDT:GetDB()
return db
end
local framesInitialized
function MDT:ShowInterface(force)
if not framesInitialized then initFrames() end
if self.main_frame:IsShown() and not force then
MDT:HideInterface()
else
self.main_frame:Show()
self.main_frame.HelpButton:Show()
self:CheckCurrentZone()
--edge case if user closed MDT window while in the process of dragging a corrupted blip
if self.draggedBlip then
if MDT.liveSessionActive then
MDT:LiveSession_SendCorruptedPositions(MDT:GetRiftOffsets())
end
self:UpdateMap()
self.draggedBlip = nil
end
MDT:UpdateBottomText()
end
end
function MDT:HideInterface()
self.main_frame:Hide()
self.main_frame.HelpButton:Hide()
end
function MDT:ToggleDevMode()
db.devMode = not db.devMode
ReloadUI()
end
function MDT:ToggleDataCollection()
db.dataCollectionActive = not db.dataCollectionActive
print(string.format("%sMDT|r: DataCollection %s. Reload Interface!", mythicColor,db.dataCollectionActive and "|cFF00FF00Enabled|r" or "|cFFFF0000Disabled|r"))
end
function MDT:ToggleHealthTrack()
MDT.DataCollection:InitHealthTrack()
print(string.format("%sMDT|r: HealthTrack %s.", mythicColor,"|cFF00FF00Enabled|r"))
end
function MDT:CreateMenu()
-- Close button
self.main_frame.closeButton = CreateFrame("Button", "MDTCloseButton", self.main_frame, "UIPanelCloseButton")
self.main_frame.closeButton:ClearAllPoints()
self.main_frame.closeButton:SetPoint("TOPRIGHT", self.main_frame.sidePanel, "TOPRIGHT", 0, 0)
self.main_frame.closeButton:SetScript("OnClick", function() self:HideInterface() end)
self.main_frame.closeButton:SetFrameLevel(4)
--Maximize Button
self.main_frame.maximizeButton = CreateFrame("Button", "MDTMaximizeButton", self.main_frame, "MaximizeMinimizeButtonFrameTemplate")
self.main_frame.maximizeButton:ClearAllPoints()
self.main_frame.maximizeButton:SetPoint("RIGHT", self.main_frame.closeButton, "LEFT", 0, 0)
self.main_frame.maximizeButton:SetFrameLevel(4)
db.maximized = db.maximized or false
if not db.maximized then self.main_frame.maximizeButton:Minimize() end
self.main_frame.maximizeButton:SetOnMaximizedCallback(self.Maximize)
self.main_frame.maximizeButton:SetOnMinimizedCallback(self.Minimize)
--return to live preset
self.main_frame.liveReturnButton = CreateFrame("Button", "MDTLiveReturnButton", self.main_frame, "UIPanelCloseButton")
local liveReturnButton = self.main_frame.liveReturnButton
liveReturnButton:ClearAllPoints()
liveReturnButton:SetPoint("RIGHT", self.main_frame.topPanel, "RIGHT", 0, 0)
liveReturnButton.Icon = liveReturnButton:CreateTexture(nil, "OVERLAY")
liveReturnButton.Icon:SetTexture("Interface\\Buttons\\UI-RefreshButton")
liveReturnButton.Icon:SetSize(16,16)
liveReturnButton.Icon:SetTexCoord(1, 0, 0, 1) --flipped image
liveReturnButton.Icon:SetPoint("CENTER",liveReturnButton,"CENTER")
liveReturnButton:SetScript("OnClick", function() self:ReturnToLivePreset() end)
liveReturnButton:SetFrameLevel(4)
liveReturnButton.tooltip = L["Return to the live preset"]
--set preset as new live preset
self.main_frame.setLivePresetButton = CreateFrame("Button", "MDTSetLivePresetButton", self.main_frame, "UIPanelCloseButton")
local setLivePresetButton = self.main_frame.setLivePresetButton
setLivePresetButton:ClearAllPoints()
setLivePresetButton:SetPoint("RIGHT", liveReturnButton, "LEFT", 0, 0)
setLivePresetButton.Icon = setLivePresetButton:CreateTexture(nil, "OVERLAY")
setLivePresetButton.Icon:SetTexture("Interface\\ChatFrame\\ChatFrameExpandArrow")
setLivePresetButton.Icon:SetSize(16,16)
setLivePresetButton.Icon:SetPoint("CENTER",setLivePresetButton,"CENTER")
setLivePresetButton:SetScript("OnClick", function() self:SetLivePreset() end)
setLivePresetButton:SetFrameLevel(4)
setLivePresetButton.tooltip = L["Make this preset the live preset"]
self:SkinMenuButtons()
--Resize Handle
self.main_frame.resizer = CreateFrame("BUTTON", nil, self.main_frame.sidePanel)
local resizer = self.main_frame.resizer
resizer:SetPoint("BOTTOMRIGHT", self.main_frame.sidePanel,"BOTTOMRIGHT",7,-7)
resizer:SetSize(25, 25)
resizer:EnableMouse()
resizer:SetScript("OnMouseDown", function()
self.main_frame:StartSizing("BOTTOMRIGHT")
self:StartScaling()
self:HideAllPresetObjects()
self:ReleaseHullTextures()
self.main_frame:SetScript("OnSizeChanged", function()
local height = self.main_frame:GetHeight()
self:SetScale(height/sizey)
end)
end)
resizer:SetScript("OnMouseUp", function()
self.main_frame:StopMovingOrSizing()
self:UpdateEnemyInfoFrame()
self:UpdateMap()
self:CreateTutorialButton(self.main_frame)
self.main_frame:SetScript("OnSizeChanged", function() end)
end)
local normal = resizer:CreateTexture(nil, "OVERLAY")
normal:SetTexture("Interface\\ChatFrame\\UI-ChatIM-SizeGrabber-Up")
normal:SetTexCoord(0, 1, 0, 1)
normal:SetPoint("BOTTOMLEFT", resizer, 0, 6)
normal:SetPoint("TOPRIGHT", resizer, -6, 0)
resizer:SetNormalTexture(normal)
local pushed = resizer:CreateTexture(nil, "OVERLAY")
pushed:SetTexture("Interface\\ChatFrame\\UI-ChatIM-SizeGrabber-Down")
pushed:SetTexCoord(0, 1, 0, 1)
pushed:SetPoint("BOTTOMLEFT", resizer, 0, 6)
pushed:SetPoint("TOPRIGHT", resizer, -6, 0)
resizer:SetPushedTexture(pushed)
local highlight = resizer:CreateTexture(nil, "OVERLAY")
highlight:SetTexture("Interface\\ChatFrame\\UI-ChatIM-SizeGrabber-Highlight")
highlight:SetTexCoord(0, 1, 0, 1)
highlight:SetPoint("BOTTOMLEFT", resizer, 0, 6)
highlight:SetPoint("TOPRIGHT", resizer, -6, 0)
resizer:SetHighlightTexture(highlight)
end
function MDT:SkinMenuButtons()
--attempt to skin close button for ElvUI
if IsAddOnLoaded("ElvUI") then
local E, L, V, P, G = unpack(ElvUI)
local S
if E then S = E:GetModule("Skins") end
if S then
S:HandleCloseButton(self.main_frame.closeButton)
S:HandleMaxMinFrame(self.main_frame.maximizeButton)
S:HandleButton(self.main_frame.liveReturnButton)
self.main_frame.liveReturnButton:Size(26)
--self.main_frame.liveReturnButton.Icon:SetVertexColor(0,1,1,1)
S:HandleButton(self.main_frame.setLivePresetButton)
self.main_frame.setLivePresetButton:Size(26)
self.main_frame.setLivePresetButton.Icon:SetVertexColor(1, .82, 0, 0.8)
end
end
end
---GetDefaultMapPanelSize
function MDT:GetDefaultMapPanelSize()
return sizex,sizey
end
---GetScale
---Returns scale factor stored in db
function MDT:GetScale()
if not db.scale then db.scale = 1 end
return db.scale
end
local oldScrollValues = {}
---StartScaling
---Stores values when we start scaling the frame
function MDT:StartScaling()
local f = self.main_frame
oldScrollValues.oldScrollH = f.scrollFrame:GetHorizontalScroll()
oldScrollValues.oldScrollV = f.scrollFrame:GetVerticalScroll()
oldScrollValues.oldSizeX = f.scrollFrame:GetWidth()
oldScrollValues.oldSizeY = f.scrollFrame:GetHeight()
HelpPlate_Hide(true)
self:DungeonEnemies_HideAllBlips()
self:POI_HideAllPoints()
self:KillAllAnimatedLines()
end
---SetScale
---Scales the map frame and it's sub frames to a factor and stores the scale in db
function MDT:SetScale(scale)
local f = self.main_frame
local newSizex = sizex*scale
local newSizey = sizey*scale
f:SetSize(newSizex,newSizey)
f.scrollFrame:SetSize(newSizex, newSizey)
f.mapPanelFrame:SetSize(newSizex, newSizey)
for i=1,12 do
f["mapPanelTile"..i]:SetSize((newSizex/4+5*scale),(newSizex/4+5*scale))
end
for i=1,10 do
for j=1,15 do
f["largeMapPanelTile"..i..j]:SetSize(newSizex/15,newSizex/15)
end
end
f.scrollFrame:SetVerticalScroll(oldScrollValues.oldScrollV * (newSizey / oldScrollValues.oldSizeY))
f.scrollFrame:SetHorizontalScroll(oldScrollValues.oldScrollH * (newSizex / oldScrollValues.oldSizeX))
f.scrollFrame.cursorY = f.scrollFrame.cursorY * (newSizey / oldScrollValues.oldSizeY)
f.scrollFrame.cursorX = f.scrollFrame.cursorX * (newSizex / oldScrollValues.oldSizeX)
self:ZoomMap(0)
db.scale = scale
db.nonFullscreenScale = scale
end
function MDT:GetFullScreenSizes()
local newSizey = GetScreenHeight()-60 --top and bottom panel 30 each
local newSizex = newSizey*(sizex/sizey)
local isNarrow
if newSizex+251>GetScreenWidth() then --251 sidebar
newSizex = GetScreenWidth()-251
newSizey = newSizex*(sizey/sizex)
isNarrow = true
end
local scale = newSizey/sizey --use this for adjusting NPC / POI positions later
return newSizex, newSizey, scale, isNarrow
end
---Maximize
---FULLSCREEN the UI
function MDT:Maximize()
local f = MDT.main_frame
local oldScrollH = f.scrollFrame:GetHorizontalScroll()
local oldScrollV = f.scrollFrame:GetVerticalScroll()
local oldSizeX = f.scrollFrame:GetWidth()
local oldSizeY = f.scrollFrame:GetHeight()
if not f.blackoutFrame then
f.blackoutFrame = CreateFrame("Frame", "MDTBlackoutFrame", f)
f.blackoutFrame:EnableMouse(true)
f.blackoutFrameTex = f.blackoutFrame:CreateTexture(nil, "BACKGROUND")
f.blackoutFrameTex:SetAllPoints()
f.blackoutFrameTex:SetDrawLayer(canvasDrawLayer, -6)
f.blackoutFrameTex:SetColorTexture(0.058823399245739,0.058823399245739,0.058823399245739,1)
f.blackoutFrame:ClearAllPoints()
f.blackoutFrame:SetAllPoints(UIParent)
end
f.blackoutFrame:Show()
f.topPanel:RegisterForDrag(nil)
f.bottomPanel:RegisterForDrag(nil)
local newSizex, newSizey, scale, isNarrow = MDT:GetFullScreenSizes()
db.scale = scale
f:ClearAllPoints()
if not isNarrow then
f:SetPoint("TOP", UIParent,"TOP", -(f.sidePanel:GetWidth()/2), -30)
else
f:SetPoint("LEFT", UIParent,"LEFT")
end
f:SetSize(newSizex,newSizey)
f.scrollFrame:SetSize(newSizex, newSizey)
f.mapPanelFrame:SetSize(newSizex, newSizey)
for i=1,12 do
f["mapPanelTile"..i]:SetSize((newSizex/4+5*db.scale),(newSizex/4+5*db.scale))
end
for i=1,10 do
for j=1,15 do
f["largeMapPanelTile"..i..j]:SetSize(newSizex/15,newSizex/15)
end
end
f.scrollFrame:SetVerticalScroll(oldScrollV * (newSizey / oldSizeY))
f.scrollFrame:SetHorizontalScroll(oldScrollH * (newSizex / oldSizeX))
f.scrollFrame.cursorY = f.scrollFrame.cursorY * (newSizey / oldSizeY)
f.scrollFrame.cursorX = f.scrollFrame.cursorX * (newSizex / oldSizeX)
MDT:ZoomMap(0)
MDT:UpdateEnemyInfoFrame()
MDT:UpdateMap()
if db.devMode then
f.devPanel:ClearAllPoints()
f.devPanel:SetPoint("TOPLEFT",f,"TOPLEFT",0,-45)
end
f.resizer:Hide()
MDT:CreateTutorialButton(MDT.main_frame)
db.maximized = true
end
---Minimize
---Restore normal UI
function MDT:Minimize()
local f = MDT.main_frame
local oldScrollH = f.scrollFrame:GetHorizontalScroll()
local oldScrollV = f.scrollFrame:GetVerticalScroll()
local oldSizeX = f.scrollFrame:GetWidth()
local oldSizeY = f.scrollFrame:GetHeight()
if f.blackoutFrame then f.blackoutFrame:Hide() end
f.topPanel:RegisterForDrag("LeftButton")
f.bottomPanel:RegisterForDrag("LeftButton")
db.scale = db.nonFullscreenScale
local newSizex = sizex*db.scale
local newSizey = sizey*db.scale
f:ClearAllPoints()
f:SetPoint(db.anchorTo, UIParent,db.anchorFrom, db.xoffset, db.yoffset)
f:SetSize(newSizex,newSizey)
f.scrollFrame:SetSize(newSizex, newSizey)
f.mapPanelFrame:SetSize(newSizex, newSizey)
for i=1,12 do
f["mapPanelTile"..i]:SetSize(newSizex/4+(5*db.scale),newSizex/4+(5*db.scale))
end
for i=1,10 do
for j=1,15 do
f["largeMapPanelTile"..i..j]:SetSize(newSizex/15,newSizex/15)
end
end
f.scrollFrame:SetVerticalScroll(oldScrollV * (newSizey / oldSizeY))
f.scrollFrame:SetHorizontalScroll(oldScrollH * (newSizex / oldSizeX))
f.scrollFrame.cursorY = f.scrollFrame.cursorY * (newSizey / oldSizeY)
f.scrollFrame.cursorX = f.scrollFrame.cursorX * (newSizex / oldSizeX)
MDT:ZoomMap(0)
MDT:UpdateEnemyInfoFrame()
MDT:UpdateMap()
if db.devMode then
f.devPanel:ClearAllPoints()
f.devPanel:SetPoint("TOPRIGHT",f.topPanel,"TOPLEFT",0,0)
end
f.resizer:Show()
MDT:CreateTutorialButton(MDT.main_frame)
db.maximized = false
end
function MDT:SkinProgressBar(progressBar)
local bar = progressBar and progressBar.Bar
if not bar then return end
bar.Icon:Hide()
bar.IconBG:Hide()
if IsAddOnLoaded("ElvUI") then
local E, L, V, P, G = unpack(ElvUI)
if bar.BarFrame then bar.BarFrame:Hide() end
if bar.BarFrame2 then bar.BarFrame2:Hide() end
if bar.BarFrame3 then bar.BarFrame3:Hide() end
if bar.BarGlow then bar.BarGlow:Hide() end
if bar.Sheen then bar.Sheen:Hide() end
if bar.IconBG then bar.IconBG:SetAlpha(0) end
if bar.BorderLeft then bar.BorderLeft:SetAlpha(0) end
if bar.BorderRight then bar.BorderRight:SetAlpha(0) end
if bar.BorderMid then bar.BorderMid:SetAlpha(0) end
bar:Height(18)
bar:StripTextures()
bar:CreateBackdrop("Transparent")
bar:SetStatusBarTexture(E.media.normTex)
local label = bar.Label
if not label then return end
label:ClearAllPoints()
label:SetPoint("CENTER",bar,"CENTER")
end
end
function MDT:IsFrameOffScreen()
local topPanel = MDT.main_frame.topPanel
local bottomPanel = MDT.main_frame.bottomPanel
local width = GetScreenWidth()
local height = GetScreenHeight()
local left = topPanel:GetLeft()-->width
local right = topPanel:GetRight()--<0
local bottom = topPanel:GetBottom()--<0
local top = bottomPanel:GetTop()-->height
return left>width or right<0 or bottom<0 or top>height
end
local bottomTips = {
[1] = L["Please report any bugs on https://github.com/Nnoggie/MythicDungeonTools/issues"],
[2] = L["Hold CTRL to single-select enemies."],
[3] = L["Hold SHIFT to create a new pull while selecting enemies."],
[4] = L["Hold SHIFT to delete all presets with the delete preset button."],
[5] = L["Right click a pull for more options."],
[6] = L["Right click an enemy to open the enemy info window."],
[7] = L["Drag the bottom right edge to resize MDT."],
[8] = L["Click the fullscreen button for a maximized view of MDT."],
[9] = L["Use /mdt reset to restore the default position and scale of MDT."],
[10] = L["Mouseover the Live button while in a group to learn more about Live mode."],
[11] = L["You are using MDT. You rock!"],
[12] = L["You can choose from different color palettes in the automatic pull coloring settings menu."],
[13] = L["You can cycle through different floors by holding CTRL and using the mousewheel."],
[14] = L["You can cycle through dungeons by holding ALT and using the mousewheel."],
[15] = L["Mouseover a patrolling enemy with a blue border to view the patrol path."],
[16] = L["Expand the top toolbar to gain access to drawing and note features."],
[17] = L["ConnectedTip"],
}
function MDT:UpdateBottomText()
local f = self.main_frame.bottomPanelString
f:SetText(bottomTips[math.random(#bottomTips)])
end
function MDT:MakeTopBottomTextures(frame)
frame:SetMovable(true)
if frame.topPanel == nil then
frame.topPanel = CreateFrame("Frame", "MDTTopPanel", frame)
frame.topPanelTex = frame.topPanel:CreateTexture(nil, "BACKGROUND")
frame.topPanelTex:SetAllPoints()
frame.topPanelTex:SetDrawLayer(canvasDrawLayer, -5)
frame.topPanelTex:SetColorTexture(unpack(MDT.BackdropColor))
frame.topPanelString = frame.topPanel:CreateFontString("MDT name")
--use default font if ElvUI is enabled
--if IsAddOnLoaded("ElvUI") then
frame.topPanelString:SetFontObject("GameFontNormalMed3")
frame.topPanelString:SetTextColor(1, 1, 1, 1)
frame.topPanelString:SetJustifyH("CENTER")
frame.topPanelString:SetJustifyV("CENTER")
--frame.topPanelString:SetWidth(600)
frame.topPanelString:SetHeight(20)
frame.topPanelString:SetText("Mythic Dungeon Tools")
frame.topPanelString:ClearAllPoints()
frame.topPanelString:SetPoint("CENTER", frame.topPanel, "CENTER", 10, 0)
frame.topPanelString:Show()
--frame.topPanelString:SetFont(frame.topPanelString:GetFont(), 20)
frame.topPanelLogo = frame.topPanel:CreateTexture(nil, "HIGH", nil, 7)
frame.topPanelLogo:SetTexture("Interface\\AddOns\\"..AddonName.."\\Textures\\Nnoggie")
frame.topPanelLogo:SetWidth(24)
frame.topPanelLogo:SetHeight(24)
frame.topPanelLogo:SetPoint("RIGHT",frame.topPanelString,"LEFT",-5,0)
frame.topPanelLogo:Show()
end
frame.topPanel:ClearAllPoints()
frame.topPanel:SetHeight(30)
frame.topPanel:SetPoint("BOTTOMLEFT", frame, "TOPLEFT")
frame.topPanel:SetPoint("BOTTOMRIGHT", frame, "TOPRIGHT")
frame.topPanel:EnableMouse(true)
frame.topPanel:RegisterForDrag("LeftButton")
frame.topPanel:SetScript("OnDragStart", function(self,button)
frame:SetMovable(true)
frame:StartMoving()
end)
frame.topPanel:SetScript("OnDragStop", function(self,button)
frame:StopMovingOrSizing()
frame:SetMovable(false)
if MDT:IsFrameOffScreen() then
MDT:ResetMainFramePos(true)
else
local from,_,to,x,y = MDT.main_frame:GetPoint()
db.anchorFrom = from
db.anchorTo = to
db.xoffset,db.yoffset = x,y
end
end)
if frame.bottomPanel == nil then
frame.bottomPanel = CreateFrame("Frame", "MDTBottomPanel", frame)
frame.bottomPanelTex = frame.bottomPanel:CreateTexture(nil, "BACKGROUND")
frame.bottomPanelTex:SetAllPoints()
frame.bottomPanelTex:SetDrawLayer(canvasDrawLayer, -5)
frame.bottomPanelTex:SetColorTexture(unpack(MDT.BackdropColor))
end
frame.bottomPanel:ClearAllPoints()
frame.bottomPanel:SetHeight(30)
frame.bottomPanel:SetPoint("TOPLEFT", frame, "BOTTOMLEFT")
frame.bottomPanel:SetPoint("TOPRIGHT", frame, "BOTTOMRIGHT")
frame.bottomPanelString = frame.bottomPanel:CreateFontString("MDTMid")
frame.bottomPanelString:SetFontObject("GameFontNormalSmall")
frame.bottomPanelString:SetJustifyH("CENTER")
frame.bottomPanelString:SetJustifyV("CENTER")
frame.bottomPanelString:SetPoint("CENTER", frame.bottomPanel, "CENTER", 0, 0)
frame.bottomPanelString:SetTextColor(1, 1, 1, 1)
frame.bottomPanelString:Show()
frame.bottomLeftPanelString = frame.bottomPanel:CreateFontString("MDTVersion")
frame.bottomLeftPanelString:SetFontObject("GameFontNormalSmall")
frame.bottomLeftPanelString:SetJustifyH("LEFT")
frame.bottomLeftPanelString:SetJustifyV("CENTER")
frame.bottomLeftPanelString:SetPoint("LEFT", frame.bottomPanel, "LEFT", 0, 0)
frame.bottomLeftPanelString:SetTextColor(1, 1, 1, 1)
frame.bottomLeftPanelString:SetText(" v"..GetAddOnMetadata(AddonName, "Version"))
frame.bottomLeftPanelString:Show()
frame.bottomPanel:EnableMouse(true)
frame.bottomPanel:RegisterForDrag("LeftButton")
frame.bottomPanel:SetScript("OnDragStart", function(self,button)
frame:SetMovable(true)
frame:StartMoving()
end)
frame.bottomPanel:SetScript("OnDragStop", function(self,button)
frame:StopMovingOrSizing()
frame:SetMovable(false)
if MDT:IsFrameOffScreen() then
MDT:ResetMainFramePos(true)
else
local from,_,to,x,y = MDT.main_frame:GetPoint()
db.anchorFrom = from
db.anchorTo = to
db.xoffset,db.yoffset = x,y
end
end)
end
function MDT:MakeSidePanel(frame)
if frame.sidePanel == nil then
frame.sidePanel = CreateFrame("Frame", "MDTSidePanel", frame)
frame.sidePanelTex = frame.sidePanel:CreateTexture(nil, "BACKGROUND")
frame.sidePanelTex:SetAllPoints()
frame.sidePanelTex:SetDrawLayer(canvasDrawLayer, -5)
frame.sidePanelTex:SetColorTexture(unpack(MDT.BackdropColor))
frame.sidePanelTex:Show()
end
frame.sidePanel:EnableMouse(true)
frame.sidePanel:ClearAllPoints()
frame.sidePanel:SetWidth(251)
frame.sidePanel:SetPoint("TOPLEFT", frame, "TOPRIGHT", 0, 30)
frame.sidePanel:SetPoint("BOTTOMLEFT", frame, "BOTTOMRIGHT", 0, -30)
frame.sidePanelString = frame.sidePanel:CreateFontString("MDTSidePanelText")
frame.sidePanelString:SetFont("Fonts\\FRIZQT__.TTF", 10)
frame.sidePanelString:SetTextColor(1, 1, 1, 1)
frame.sidePanelString:SetJustifyH("LEFT")
frame.sidePanelString:SetJustifyV("TOP")
frame.sidePanelString:SetWidth(200)
frame.sidePanelString:SetHeight(500)
frame.sidePanelString:SetText("")
frame.sidePanelString:ClearAllPoints()
frame.sidePanelString:SetPoint("TOPLEFT", frame.sidePanel, "TOPLEFT", 33, -120-30-25)
frame.sidePanelString:Hide()
frame.sidePanel.WidgetGroup = AceGUI:Create("SimpleGroup")
frame.sidePanel.WidgetGroup:SetWidth(245)
frame.sidePanel.WidgetGroup:SetHeight(frame:GetHeight()+(frame.topPanel:GetHeight()*2)-31)
frame.sidePanel.WidgetGroup:SetPoint("TOP",frame.sidePanel,"TOP",3,-1)
frame.sidePanel.WidgetGroup:SetLayout("Flow")
frame.sidePanel.WidgetGroup.frame:SetFrameStrata(mainFrameStrata)
if not frame.sidePanel.WidgetGroup.frame.SetBackdrop then
Mixin(frame.sidePanel.WidgetGroup.frame, BackdropTemplateMixin)
end
frame.sidePanel.WidgetGroup.frame:SetBackdropColor(1,1,1,0)
frame.sidePanel.WidgetGroup.frame:Hide()
--dirty hook to make widgetgroup show/hide
local originalShow,originalHide = frame.Show,frame.Hide
function frame:Show(...)
frame.sidePanel.WidgetGroup.frame:Show()
return originalShow(self, ...)
end
function frame:Hide(...)
frame.sidePanel.WidgetGroup.frame:Hide()
MDT.pullTooltip:Hide()
return originalHide(self, ...)
end
--preset selection
frame.sidePanel.WidgetGroup.PresetDropDown = AceGUI:Create("Dropdown")
local dropdown = frame.sidePanel.WidgetGroup.PresetDropDown
dropdown.frame:SetWidth(170)
dropdown.text:SetJustifyH("LEFT")
dropdown:SetCallback("OnValueChanged",function(widget,callbackName,key)
if db.presets[db.currentDungeonIdx][key].value==0 then
MDT:OpenNewPresetDialog()
MDT.main_frame.sidePanelDeleteButton:SetDisabled(true)
MDT.main_frame.sidePanelDeleteButton.text:SetTextColor(0.5,0.5,0.5)
else
if key == 1 then
MDT.main_frame.sidePanelDeleteButton:SetDisabled(true)
MDT.main_frame.sidePanelDeleteButton.text:SetTextColor(0.5,0.5,0.5)
else
if not MDT.liveSessionActive then
MDT.main_frame.sidePanelDeleteButton:SetDisabled(false)
MDT.main_frame.sidePanelDeleteButton.text:SetTextColor(1,0.8196,0)
else
MDT.main_frame.sidePanelDeleteButton:SetDisabled(true)
MDT.main_frame.sidePanelDeleteButton.text:SetTextColor(0.5,0.5,0.5)
end
end
db.currentPreset[db.currentDungeonIdx] = key
--Set affix dropdown to preset week
--frame.sidePanel.affixDropdown:SetAffixWeek(MDT:GetCurrentPreset().week or MDT:GetCurrentAffixWeek())
--UpdateMap is called in SetAffixWeek, no need to call twice
MDT:UpdateMap()
frame.sidePanel.affixDropdown:SetAffixWeek(MDT:GetCurrentPreset().week or MDT:GetCurrentAffixWeek() or 1)
end
end)
MDT:UpdatePresetDropDown()
frame.sidePanel.WidgetGroup:AddChild(dropdown)
---new profile,rename,export,delete
local buttonWidth = 80
frame.sidePanelNewButton = AceGUI:Create("Button")
frame.sidePanelNewButton:SetText(L["New"])
frame.sidePanelNewButton:SetWidth(buttonWidth)
--button fontInstance
local fontInstance = CreateFont("MDTButtonFont")
fontInstance:CopyFontObject(frame.sidePanelNewButton.frame:GetNormalFontObject())
local fontName,height = fontInstance:GetFont()
fontInstance:SetFont(fontName,10)
frame.sidePanelNewButton.frame:SetNormalFontObject(fontInstance)
frame.sidePanelNewButton.frame:SetHighlightFontObject(fontInstance)
frame.sidePanelNewButton.frame:SetDisabledFontObject(fontInstance)
frame.sidePanelNewButton:SetCallback("OnClick",function(widget,callbackName,value)
MDT:OpenNewPresetDialog()
end)
frame.sidePanelNewButton.frame:SetScript("OnEnter",function()
GameTooltip:SetOwner(frame.sidePanelNewButton.frame, "ANCHOR_BOTTOMLEFT",frame.sidePanelNewButton.frame:GetWidth()*(-0),frame.sidePanelNewButton.frame:GetHeight())
GameTooltip:AddLine(L["Create a new preset"],1,1,1)
GameTooltip:Show()
end)
frame.sidePanelNewButton.frame:SetScript("OnLeave",function()
GameTooltip:Hide()
end)
frame.sidePanelRenameButton = AceGUI:Create("Button")
frame.sidePanelRenameButton:SetWidth(buttonWidth)
frame.sidePanelRenameButton:SetText(L["Rename"])
frame.sidePanelRenameButton.frame:SetNormalFontObject(fontInstance)
frame.sidePanelRenameButton.frame:SetHighlightFontObject(fontInstance)
frame.sidePanelRenameButton.frame:SetDisabledFontObject(fontInstance)
frame.sidePanelRenameButton:SetCallback("OnClick",function(widget,callbackName,value)
MDT:HideAllDialogs()
local currentPresetName = db.presets[db.currentDungeonIdx][db.currentPreset[db.currentDungeonIdx]].text
MDT.main_frame.RenameFrame:Show()
MDT.main_frame.RenameFrame.RenameButton:SetDisabled(true)
MDT.main_frame.RenameFrame.RenameButton.text:SetTextColor(0.5,0.5,0.5)
MDT.main_frame.RenameFrame:ClearAllPoints()
MDT.main_frame.RenameFrame:SetPoint("CENTER", MDT.main_frame,"CENTER",0,50)
MDT.main_frame.RenameFrame.Editbox:SetText(currentPresetName)
MDT.main_frame.RenameFrame.Editbox:HighlightText(0, string.len(currentPresetName))
MDT.main_frame.RenameFrame.Editbox:SetFocus()
end)
frame.sidePanelRenameButton.frame:SetScript("OnEnter",function()
GameTooltip:SetOwner(frame.sidePanelRenameButton.frame, "ANCHOR_BOTTOMLEFT",frame.sidePanelRenameButton.frame:GetWidth()*(-1),frame.sidePanelRenameButton.frame:GetHeight())
GameTooltip:AddLine(L["Rename the preset"],1,1,1)
GameTooltip:Show()
end)
frame.sidePanelRenameButton.frame:SetScript("OnLeave",function()
GameTooltip:Hide()
end)
frame.sidePanelImportButton = AceGUI:Create("Button")
frame.sidePanelImportButton:SetText(L["Import"])
frame.sidePanelImportButton:SetWidth(buttonWidth)
frame.sidePanelImportButton.frame:SetNormalFontObject(fontInstance)
frame.sidePanelImportButton.frame:SetHighlightFontObject(fontInstance)
frame.sidePanelImportButton.frame:SetDisabledFontObject(fontInstance)
frame.sidePanelImportButton:SetCallback("OnClick",function(widget,callbackName,value)
MDT:OpenImportPresetDialog()
end)
frame.sidePanelImportButton.frame:SetScript("OnEnter",function()
GameTooltip:SetOwner(frame.sidePanelImportButton.frame, "ANCHOR_BOTTOMLEFT",frame.sidePanelImportButton.frame:GetWidth()*(-1),frame.sidePanelImportButton.frame:GetHeight())
GameTooltip:AddLine(L["Import a preset from a text string"],1,1,1)
GameTooltip:AddLine(L["You can find MDT exports from other users on the wago.io website"],1,1,1,1)
GameTooltip:Show()
end)
frame.sidePanelImportButton.frame:SetScript("OnLeave",function()
GameTooltip:Hide()
end)
frame.sidePanelExportButton = AceGUI:Create("Button")
frame.sidePanelExportButton:SetText(L["Export"])
frame.sidePanelExportButton:SetWidth(buttonWidth)
frame.sidePanelExportButton.frame:SetNormalFontObject(fontInstance)
frame.sidePanelExportButton.frame:SetHighlightFontObject(fontInstance)
frame.sidePanelExportButton.frame:SetDisabledFontObject(fontInstance)
frame.sidePanelExportButton:SetCallback("OnClick",function(widget,callbackName,value)
if db.colorPaletteInfo.forceColorBlindMode then MDT:ColorAllPulls(_,_,_,true) end
local preset = MDT:GetCurrentPreset()
MDT:SetUniqueID(preset)
preset.mdiEnabled = db.MDI.enabled
preset.difficulty = db.currentDifficulty
local export = MDT:TableToString(preset,true,5)
MDT:HideAllDialogs()
MDT.main_frame.ExportFrame:Show()
MDT.main_frame.ExportFrame:ClearAllPoints()
MDT.main_frame.ExportFrame:SetPoint("CENTER", MDT.main_frame,"CENTER",0,50)
MDT.main_frame.ExportFrameEditbox:SetText(export)
MDT.main_frame.ExportFrameEditbox:HighlightText(0, string.len(export))
MDT.main_frame.ExportFrameEditbox:SetFocus()
MDT.main_frame.ExportFrameEditbox:SetLabel(preset.text.." "..string.len(export))
if db.colorPaletteInfo.forceColorBlindMode then MDT:ColorAllPulls() end
end)
frame.sidePanelExportButton.frame:SetScript("OnEnter",function()
GameTooltip:SetOwner(frame.sidePanelExportButton.frame, "ANCHOR_BOTTOMLEFT",frame.sidePanelExportButton.frame:GetWidth()*(-2),frame.sidePanelExportButton.frame:GetHeight())
GameTooltip:AddLine(L["Export the preset as a text string"],1,1,1)
GameTooltip:AddLine(L["You can share MDT exports on the wago.io website"],1,1,1,1)
GameTooltip:Show()
end)
frame.sidePanelExportButton.frame:SetScript("OnLeave",function()
GameTooltip:Hide()
end)
frame.sidePanelDeleteButton = AceGUI:Create("Button")
frame.sidePanelDeleteButton:SetText(L["Delete"])
frame.sidePanelDeleteButton:SetWidth(buttonWidth)
frame.sidePanelDeleteButton.frame:SetScript("OnEnter",function()
GameTooltip:SetOwner(frame.sidePanelDeleteButton.frame, "ANCHOR_BOTTOMLEFT",frame.sidePanelDeleteButton.frame:GetWidth()*(-2),frame.sidePanelDeleteButton.frame:GetHeight())
GameTooltip:AddLine(L["Delete this preset"],1,1,1)
GameTooltip:AddLine(L["Shift-Click to delete all presets for this dungeon"],1,1,1)
GameTooltip:Show()
end)
frame.sidePanelDeleteButton.frame:SetScript("OnLeave",function()
GameTooltip:Hide()
end)
frame.sidePanelDeleteButton.frame:SetNormalFontObject(fontInstance)
frame.sidePanelDeleteButton.frame:SetHighlightFontObject(fontInstance)
frame.sidePanelDeleteButton.frame:SetDisabledFontObject(fontInstance)
frame.sidePanelDeleteButton:SetCallback("OnClick",function(widget,callbackName,value)
if IsShiftKeyDown() then
--delete all profiles
local numPresets = self:CountPresets()
local prompt = string.format(L["deleteAllWarning"],"\n","\n",numPresets,"\n")
MDT:OpenConfirmationFrame(450,150,L["Delete ALL presets"],L["Delete"],prompt, MDT.DeleteAllPresets)
else
MDT:HideAllDialogs()
frame.DeleteConfirmationFrame:ClearAllPoints()
frame.DeleteConfirmationFrame:SetPoint("CENTER", MDT.main_frame,"CENTER",0,50)
local currentPresetName = db.presets[db.currentDungeonIdx][db.currentPreset[db.currentDungeonIdx]].text
frame.DeleteConfirmationFrame.label:SetText(string.format(L["Delete %s?"],currentPresetName))
frame.DeleteConfirmationFrame:Show()
end
end)
frame.LinkToChatButton = AceGUI:Create("Button")
frame.LinkToChatButton:SetText(L["Share"])
frame.LinkToChatButton:SetWidth(buttonWidth)
frame.LinkToChatButton.frame:SetNormalFontObject(fontInstance)
frame.LinkToChatButton.frame:SetHighlightFontObject(fontInstance)
frame.LinkToChatButton.frame:SetDisabledFontObject(fontInstance)
frame.LinkToChatButton:SetCallback("OnClick",function(widget,callbackName,value)
local distribution = MDT:IsPlayerInGroup()
if not distribution then return end
local callback = function()
frame.LinkToChatButton:SetDisabled(true)
frame.LinkToChatButton.text:SetTextColor(0.5,0.5,0.5)
frame.LiveSessionButton:SetDisabled(true)
frame.LiveSessionButton.text:SetTextColor(0.5,0.5,0.5)
frame.LinkToChatButton:SetText("...")
frame.LiveSessionButton:SetText("...")
MDT:SendToGroup(distribution)
end
local presetSize = self:GetPresetSize(false,5)
if presetSize>25000 then
local prompt = string.format(L["LargePresetWarning"],presetSize,"\n","\n","\n")
MDT:OpenConfirmationFrame(450,150,L["Sharing large preset"],"Share",prompt, callback)
else
callback()
end
end)
frame.LinkToChatButton.frame:SetScript("OnEnter",function()
GameTooltip:SetOwner(frame.sidePanelDeleteButton.frame, "ANCHOR_BOTTOMLEFT",frame.LinkToChatButton.frame:GetWidth()*(-2),-frame.LinkToChatButton.frame:GetHeight())
GameTooltip:AddLine(L["Share the preset with your party members"],1,1,1)
GameTooltip:Show()
end)
frame.LinkToChatButton.frame:SetScript("OnLeave",function()
GameTooltip:Hide()
end)
local inGroup = UnitInRaid("player") or IsInGroup()
MDT.main_frame.LinkToChatButton:SetDisabled(not inGroup)
if inGroup then
MDT.main_frame.LinkToChatButton.text:SetTextColor(1,0.8196,0)
else
MDT.main_frame.LinkToChatButton.text:SetTextColor(0.5,0.5,0.5)
end
frame.ClearPresetButton = AceGUI:Create("Button")
frame.ClearPresetButton:SetText(L["Reset"])
frame.ClearPresetButton:SetWidth(buttonWidth)
frame.ClearPresetButton.frame:SetNormalFontObject(fontInstance)
frame.ClearPresetButton.frame:SetHighlightFontObject(fontInstance)
frame.ClearPresetButton.frame:SetDisabledFontObject(fontInstance)
frame.ClearPresetButton:SetCallback("OnClick",function(widget,callbackName,value)
MDT:OpenClearPresetDialog()
end)
frame.ClearPresetButton.frame:SetScript("OnEnter",function()
GameTooltip:SetOwner(frame.ClearPresetButton.frame, "ANCHOR_BOTTOMLEFT",frame.ClearPresetButton.frame:GetWidth()*(-0),frame.ClearPresetButton.frame:GetHeight())
GameTooltip:AddLine(L["Reset the preset to the default state"],1,1,1)
GameTooltip:AddLine(L["Does not delete your drawings"],1,1,1)
GameTooltip:Show()
end)
frame.ClearPresetButton.frame:SetScript("OnLeave",function()
GameTooltip:Hide()
end)
frame.LiveSessionButton = AceGUI:Create("Button")
frame.LiveSessionButton:SetText(L["Live"])
frame.LiveSessionButton:SetWidth(buttonWidth)
frame.LiveSessionButton.frame:SetNormalFontObject(fontInstance)
frame.LiveSessionButton.frame:SetHighlightFontObject(fontInstance)
frame.LiveSessionButton.frame:SetDisabledFontObject(fontInstance)
local c1,c2,c3 = frame.LiveSessionButton.text:GetTextColor()
frame.LiveSessionButton.normalTextColor = {r = c1,g = c2,b = c3,}
frame.LiveSessionButton:SetCallback("OnClick",function(widget,callbackName,value)
if MDT.liveSessionActive then
MDT:LiveSession_Disable()
else
MDT:LiveSession_Enable()
end
end)
frame.LiveSessionButton.frame:SetScript("OnEnter",function()
GameTooltip:SetOwner(frame.LiveSessionButton.frame, "ANCHOR_BOTTOMLEFT",frame.LiveSessionButton.frame:GetWidth()*(-1),frame.LiveSessionButton.frame:GetHeight())
GameTooltip:AddLine(L["Start or join the current |cFF00FF00Live Session|r"],1,1,1)
GameTooltip:AddLine(L["Clicking this button will attempt to join the ongoing Live Session of your group or create a new one if none is found"],1,1,1,1)
GameTooltip:AddLine(L["The preset will continuously synchronize between all party members participating in the Live Session"],1,1,1,1)
GameTooltip:AddLine(L["Players can join the live session by either clicking this button or the Live Session chat link"],1,1,1,1)
GameTooltip:AddLine(L["To share a different preset while the live session is active simply navigate to the preferred preset and click the new 'Set to Live' Button next to the preset-dropdown"],1,1,1,1)
GameTooltip:AddLine(L["You can always return to the current Live Session preset by clicking the 'Return to Live' button next to the preset-dropdown"],1,1,1,1)
GameTooltip:Show()
end)
frame.LiveSessionButton.frame:SetScript("OnLeave",function()
GameTooltip:Hide()
end)
MDT.main_frame.LiveSessionButton:SetDisabled(not inGroup)
if inGroup then
MDT.main_frame.LiveSessionButton.text:SetTextColor(1,0.8196,0)
else
MDT.main_frame.LiveSessionButton.text:SetTextColor(0.5,0.5,0.5)
end
--MDI
frame.MDIButton = AceGUI:Create("Button")
frame.MDIButton:SetText("MDI")
frame.MDIButton:SetWidth(buttonWidth)
frame.MDIButton.frame:SetNormalFontObject(fontInstance)
frame.MDIButton.frame:SetHighlightFontObject(fontInstance)
frame.MDIButton.frame:SetDisabledFontObject(fontInstance)
frame.MDIButton:SetCallback("OnClick",function(widget,callbackName,value)
MDT:ToggleMDIMode()
end)
frame.MDIButton.frame:SetScript("OnEnter",function()
GameTooltip:SetOwner(frame.MDIButton.frame, "ANCHOR_BOTTOMLEFT",frame.MDIButton.frame:GetWidth()*(-2),frame.MDIButton.frame:GetHeight())
GameTooltip:AddLine(L["Open MDI override options"],1,1,1)
GameTooltip:Show()
end)
frame.MDIButton.frame:SetScript("OnLeave",function()
end)
--AutomaticColorsCheckbox
frame.AutomaticColorsCheckSidePanel = AceGUI:Create("CheckBox")
frame.AutomaticColorsCheckSidePanel:SetLabel(L["Automatically color pulls"])
frame.AutomaticColorsCheckSidePanel:SetValue(db.colorPaletteInfo.autoColoring)
frame.AutomaticColorsCheckSidePanel:SetCallback("OnValueChanged",function(widget,callbackName,value)
db.colorPaletteInfo.autoColoring = value
MDT:SetPresetColorPaletteInfo()
frame.AutomaticColorsCheck:SetValue(db.colorPaletteInfo.autoColoring)
if value == true then
frame.toggleForceColorBlindMode:SetDisabled(false)
MDT:ColorAllPulls()
MDT.main_frame.AutomaticColorsCogwheel:SetImage("Interface\\AddOns\\MythicDungeonTools\\Textures\\helpIconRnbw")
else
frame.toggleForceColorBlindMode:SetDisabled(true)
MDT.main_frame.AutomaticColorsCogwheel:SetImage("Interface\\AddOns\\MythicDungeonTools\\Textures\\helpIconGrey")
end
end)
--AutomaticColorsCogwheel
frame.AutomaticColorsCogwheel = AceGUI:Create("Icon")
local colorCogwheel = frame.AutomaticColorsCogwheel
colorCogwheel:SetImage("Interface\\AddOns\\MythicDungeonTools\\Textures\\helpIconRnbw")
colorCogwheel:SetImageSize(25,25)
colorCogwheel:SetWidth(35)
colorCogwheel:SetCallback("OnEnter",function(...)
GameTooltip:SetOwner(colorCogwheel.frame, "ANCHOR_CURSOR")
GameTooltip:AddLine(L["Click to adjust color settings"],1,1,1)
GameTooltip:Show()
end)
colorCogwheel:SetCallback("OnLeave",function(...)
GameTooltip:Hide()
end)
colorCogwheel:SetCallback("OnClick",function(...)
self:OpenAutomaticColorsDialog()
end)
frame.sidePanel.WidgetGroup:AddChild(frame.sidePanelNewButton)
frame.sidePanel.WidgetGroup:AddChild(frame.sidePanelRenameButton)
frame.sidePanel.WidgetGroup:AddChild(frame.sidePanelDeleteButton)
frame.sidePanel.WidgetGroup:AddChild(frame.ClearPresetButton)
frame.sidePanel.WidgetGroup:AddChild(frame.sidePanelImportButton)
frame.sidePanel.WidgetGroup:AddChild(frame.sidePanelExportButton)
frame.sidePanel.WidgetGroup:AddChild(frame.LinkToChatButton)
frame.sidePanel.WidgetGroup:AddChild(frame.LiveSessionButton)
frame.sidePanel.WidgetGroup:AddChild(frame.MDIButton)
frame.sidePanel.WidgetGroup:AddChild(frame.AutomaticColorsCheckSidePanel)
frame.sidePanel.WidgetGroup:AddChild(frame.AutomaticColorsCogwheel)
--Week Dropdown (Infested / Affixes)
local function makeAffixString(week,affixes,longText)
local ret
local sep = ""
for _,affixID in ipairs(affixes) do
local name, _, filedataid = C_ChallengeMode.GetAffixInfo(affixID)
name = name or "Unknown"
filedataid = filedataid or 134400 --questionmark
if longText then
ret = ret or ""
ret = ret..sep..name
sep = ", "
else
ret = ret or week..(week>9 and ". " or ". ")
if week == MDT:GetCurrentAffixWeek() then
ret = WrapTextInColorCode(ret, "FF00FF00")
end
ret = ret..CreateTextureMarkup(filedataid, 64, 64, 20, 20, 0.1, 0.9, 0.1, 0.9,0,0).." "
end
end
return ret
end
frame.sidePanel.affixDropdown = AceGUI:Create("Dropdown")
local affixDropdown = frame.sidePanel.affixDropdown
affixDropdown.text:SetJustifyH("LEFT")
affixDropdown:SetLabel(L["Affixes"])
function affixDropdown:UpdateAffixList()
local affixWeekMarkups = {}
for week,affixes in ipairs(affixWeeks) do
tinsert(affixWeekMarkups,makeAffixString(week,affixes))
end
local order = {1,2,3,4,5,6,7,8,9,10,11,12}
affixDropdown:SetList(affixWeekMarkups,order)
--mouseover list items
for itemIdx,item in ipairs(affixDropdown.pullout.items) do
item:SetOnEnter(function()
GameTooltip:SetOwner(item.frame, "ANCHOR_LEFT",-11,-25)
local v = affixWeeks[itemIdx]
GameTooltip:SetText(makeAffixString(itemIdx,v,true),1,1,1,1)
GameTooltip:Show()
end)
item:SetOnLeave(function()
GameTooltip:Hide()
end)
end
end
function affixDropdown:SetAffixWeek(key,ignoreReloadPullButtons,ignoreUpdateProgressBar)
affixDropdown:SetValue(key)
if not MDT:GetCurrentAffixWeek() then
frame.sidePanel.affixWeekWarning.image:Hide()
frame.sidePanel.affixWeekWarning:SetDisabled(true)
elseif MDT:GetCurrentAffixWeek() == key then
frame.sidePanel.affixWeekWarning.image:Hide()
frame.sidePanel.affixWeekWarning:SetDisabled(true)
else
frame.sidePanel.affixWeekWarning.image:Show()
frame.sidePanel.affixWeekWarning:SetDisabled(false)
end
MDT:GetCurrentPreset().week = key
local teeming = MDT:IsPresetTeeming(MDT:GetCurrentPreset())
MDT:GetCurrentPreset().value.teeming = teeming
if MDT.EnemyInfoFrame and MDT.EnemyInfoFrame.frame:IsShown() then MDT:UpdateEnemyInfoData() end
MDT:UpdateMap(nil,ignoreReloadPullButtons,ignoreUpdateProgressBar)
end
affixDropdown:SetCallback("OnValueChanged",function(widget,callbackName,key)
affixDropdown:SetAffixWeek(key)
if MDT.liveSessionActive and MDT:GetCurrentPreset().uid == MDT.livePresetUID then
MDT:LiveSession_SendAffixWeek(key)
end
end)
affixDropdown:SetCallback("OnEnter",function(...)
local selectedWeek = affixDropdown:GetValue()
if not selectedWeek then return end
GameTooltip:SetOwner(affixDropdown.frame, "ANCHOR_LEFT",-6,-41)
local v = affixWeeks[selectedWeek]
GameTooltip:SetText(makeAffixString(selectedWeek,v,true),1,1,1,1)
GameTooltip:Show()
end)
affixDropdown:SetCallback("OnLeave",function(...)
GameTooltip:Hide()
end)
frame.sidePanel.WidgetGroup:AddChild(affixDropdown)
--affix not current week warning
frame.sidePanel.affixWeekWarning = AceGUI:Create("Icon")
local affixWeekWarning = frame.sidePanel.affixWeekWarning
affixWeekWarning:SetImage("Interface\\DialogFrame\\UI-Dialog-Icon-AlertNew")
affixWeekWarning:SetImageSize(25,25)
affixWeekWarning:SetWidth(35)
affixWeekWarning:SetCallback("OnEnter",function(...)
GameTooltip:SetOwner(affixDropdown.frame, "ANCHOR_CURSOR")
GameTooltip:AddLine(L["The selected affixes are not the ones of the current week"],1,1,1)
GameTooltip:AddLine(L["Click to switch to current week"],1,1,1)
GameTooltip:Show()
end)
affixWeekWarning:SetCallback("OnLeave",function(...)
GameTooltip:Hide()
end)
affixWeekWarning:SetCallback("OnClick",function(...)
if not MDT:GetCurrentAffixWeek() then return end
affixDropdown:SetAffixWeek(MDT:GetCurrentAffixWeek())
if MDT.liveSessionActive and MDT:GetCurrentPreset().uid == MDT.livePresetUID then
MDT:LiveSession_SendAffixWeek(MDT:GetCurrentAffixWeek())
end
end)
affixWeekWarning.image:Hide()
affixWeekWarning:SetDisabled(true)
frame.sidePanel.WidgetGroup:AddChild(affixWeekWarning)
--difficulty slider
frame.sidePanel.DifficultySlider = AceGUI:Create("Slider")
frame.sidePanel.DifficultySlider:SetSliderValues(1,35,1)
frame.sidePanel.DifficultySlider:SetLabel(L["Dungeon Level"])
frame.sidePanel.DifficultySlider.label:SetJustifyH("LEFT")
frame.sidePanel.DifficultySlider.label:SetFontObject("GameFontNormalSmall")
frame.sidePanel.DifficultySlider:SetWidth(200)
frame.sidePanel.DifficultySlider:SetValue(db.currentDifficulty)
local timer
frame.sidePanel.DifficultySlider:SetCallback("OnValueChanged",function(widget,callbackName,value)
local difficulty = tonumber(value)
if (difficulty>=10 and db.currentDifficulty<10) or (difficulty<10 and db.currentDifficulty>=10) then
db.currentDifficulty = difficulty or db.currentDifficulty
MDT:DungeonEnemies_UpdateSeasonalAffix()
frame.sidePanel.difficultyWarning:Toggle(difficulty)
MDT:POI_UpdateAll()
MDT:KillAllAnimatedLines()
MDT:DrawAllAnimatedLines()
else
db.currentDifficulty = difficulty or db.currentDifficulty
end
MDT:GetCurrentPreset().difficulty = db.currentDifficulty
MDT:UpdateProgressbar()
if MDT.EnemyInfoFrame and MDT.EnemyInfoFrame.frame:IsShown() then MDT:UpdateEnemyInfoData() end
if timer then timer:Cancel() end
timer = C_Timer.NewTimer(2, function()
MDT:ReloadPullButtons()
if MDT.liveSessionActive then
local livePreset = MDT:GetCurrentLivePreset()
local shouldUpdate = livePreset == MDT:GetCurrentPreset()
if shouldUpdate then MDT:LiveSession_SendDifficulty() end
end
end)
end)
frame.sidePanel.DifficultySlider:SetCallback("OnMouseUp",function()
if timer then timer:Cancel() end
MDT:ReloadPullButtons()
if MDT.liveSessionActive then
local livePreset = MDT:GetCurrentLivePreset()
local shouldUpdate = livePreset == MDT:GetCurrentPreset()
if shouldUpdate then MDT:LiveSession_SendDifficulty() end
end
end)
frame.sidePanel.DifficultySlider:SetCallback("OnEnter",function()
GameTooltip:SetOwner(frame.sidePanel.DifficultySlider.frame, "ANCHOR_BOTTOMLEFT",0,40)
GameTooltip:AddLine(L["Select the dungeon level"],1,1,1)
GameTooltip:AddLine(L["The selected level will affect displayed npc health"],1,1,1)
GameTooltip:AddLine(L["Levels below 10 will hide enemies related to seasonal affixes"],1,1,1)
GameTooltip:Show()
end)
frame.sidePanel.DifficultySlider:SetCallback("OnLeave",function()
GameTooltip:Hide()
end)
frame.sidePanel.WidgetGroup:AddChild(frame.sidePanel.DifficultySlider)
--dungeon level below 10 warning
frame.sidePanel.difficultyWarning = AceGUI:Create("Icon")
local difficultyWarning = frame.sidePanel.difficultyWarning
difficultyWarning:SetImage("Interface\\DialogFrame\\UI-Dialog-Icon-AlertNew")
difficultyWarning:SetImageSize(25,25)
difficultyWarning:SetWidth(35)
difficultyWarning:SetCallback("OnEnter",function(...)
GameTooltip:SetOwner(frame.sidePanel.DifficultySlider.frame, "ANCHOR_CURSOR")
GameTooltip:AddLine(L["The selected dungeon level is below 10"],1,1,1)
GameTooltip:AddLine(L["Enemies related to seasonal affixes are currently hidden"],1,1,1)
GameTooltip:AddLine(L["Click to set dungeon level to 10"],1,1,1)
GameTooltip:Show()
end)
difficultyWarning:SetCallback("OnLeave",function(...)
GameTooltip:Hide()
end)
difficultyWarning:SetCallback("OnClick",function(...)
frame.sidePanel.DifficultySlider:SetValue(10)
db.currentDifficulty = 10
MDT:GetCurrentPreset().difficulty = db.currentDifficulty
MDT:DungeonEnemies_UpdateSeasonalAffix()
MDT:POI_UpdateAll()
MDT:UpdateProgressbar()
MDT:ReloadPullButtons()
difficultyWarning:Toggle(db.currentDifficulty)
if MDT.liveSessionActive then
local livePreset = MDT:GetCurrentLivePreset()
local shouldUpdate = livePreset == MDT:GetCurrentPreset()
if shouldUpdate then MDT:LiveSession_SendDifficulty() end
end
MDT:KillAllAnimatedLines()
MDT:DrawAllAnimatedLines()
end)
function difficultyWarning:Toggle(difficulty)
if difficulty<10 then
self.image:Show()
self:SetDisabled(false)
else
self.image:Hide()
self:SetDisabled(true)
end
end
difficultyWarning:Toggle(db.currentDifficulty)
frame.sidePanel.WidgetGroup:AddChild(difficultyWarning)
frame.sidePanel.middleLine = AceGUI:Create("Heading")
frame.sidePanel.middleLine:SetWidth(240)
frame.sidePanel.WidgetGroup:AddChild(frame.sidePanel.middleLine)
frame.sidePanel.WidgetGroup.frame:SetFrameLevel(3)
--progress bar
frame.sidePanel.ProgressBar = CreateFrame("Frame", nil, frame.sidePanel, "ScenarioTrackerProgressBarTemplate")
frame.sidePanel.ProgressBar:Show()
frame.sidePanel.ProgressBar:ClearAllPoints()
frame.sidePanel.ProgressBar:SetPoint("TOP",frame.sidePanel.WidgetGroup.frame,"BOTTOM",-10,5)
MDT:SkinProgressBar(frame.sidePanel.ProgressBar)
end
---ToggleMDIMode
---Enables display to override beguiling+freehold week
function MDT:ToggleMDIMode()
db.MDI.enabled = not db.MDI.enabled
self:DisplayMDISelector()
if self.liveSessionActive then self:LiveSession_SendMDI("toggle",db.MDI.enabled and "1" or "0") end
end
function MDT:DisplayMDISelector()
local show = db.MDI.enabled
db = MDT:GetDB()
if not MDT.MDISelector then
MDT.MDISelector = AceGUI:Create("SimpleGroup")
MDT.MDISelector.frame:SetFrameStrata("HIGH")
MDT.MDISelector.frame:SetFrameLevel(50)
if not MDT.MDISelector.frame.SetBackdrop then
Mixin(MDT.MDISelector.frame, BackdropTemplateMixin)
end
MDT.MDISelector.frame:SetBackdropColor(unpack(MDT.BackdropColor))
--fix show hide
local frame = MDT.main_frame
local originalShow,originalHide = frame.Show,frame.Hide
local widget = MDT.MDISelector.frame
function frame:Hide(...)
widget:Hide()
return originalHide(self, ...)
end
function frame:Show(...)
if db.MDI.enabled then widget:Show() end
return originalShow(self, ...)
end
MDT.MDISelector:SetLayout("Flow")
MDT.MDISelector.frame.bg = MDT.MDISelector.frame:CreateTexture(nil, "BACKGROUND")
MDT.MDISelector.frame.bg:SetAllPoints(MDT.MDISelector.frame)
MDT.MDISelector.frame.bg:SetColorTexture(unpack(MDT.BackdropColor))
MDT.MDISelector:SetWidth(145)
MDT.MDISelector:SetHeight(90)
MDT.MDISelector.frame:ClearAllPoints()
MDT.MDISelector.frame:SetPoint("BOTTOMRIGHT", MDT.main_frame,"BOTTOMRIGHT",0,0)
local label = AceGUI:Create("Label")
label:SetText(L["MDI Mode"])
MDT.MDISelector:AddChild(label)
--beguiling
MDT.MDISelector.BeguilingDropDown = AceGUI:Create("Dropdown")
MDT.MDISelector.BeguilingDropDown:SetLabel(L["Seasonal Affix:"])
local beguilingList = {[1]=L["Beguiling 1 Void"],[2]=L["Beguiling 2 Tides"],[3]=L["Beguiling 3 Ench."],[13]=L["Reaping"],[14]=L["Awakened A"],[15]=L["Awakened B"]}
MDT.MDISelector.BeguilingDropDown:SetList(beguilingList)
MDT.MDISelector.BeguilingDropDown:SetCallback("OnValueChanged",function(widget, callbackName, key)
local preset = self:GetCurrentPreset()
preset.mdi.beguiling = key
db.currentSeason = self:GetEffectivePresetSeason(preset)
self:UpdateMap()
if self.liveSessionActive and preset.uid == self.livePresetUID then
self:LiveSession_SendMDI("beguiling",key)
end
end)
MDT.MDISelector:AddChild(MDT.MDISelector.BeguilingDropDown)
--freehold
MDT.MDISelector.FreeholdDropDown = AceGUI:Create("Dropdown")
MDT.MDISelector.FreeholdDropDown:SetLabel(L["Freehold:"])
local freeholdList = {string.format("1. %s",L["Cutwater"]),string.format("2. %s",L["Blacktooth"]),string.format("3. %s",L["Bilge Rats"])}
MDT.MDISelector.FreeholdDropDown:SetList(freeholdList)
MDT.MDISelector.FreeholdDropDown:SetCallback("OnValueChanged",function(widget, callbackName, key)
local preset = MDT:GetCurrentPreset()
preset.mdi.freehold = key
if preset.mdi.freeholdJoined then
MDT:DungeonEnemies_UpdateFreeholdCrew(preset.mdi.freehold)
end
MDT:DungeonEnemies_UpdateBlacktoothEvent()
MDT:UpdateProgressbar()
MDT:ReloadPullButtons()
if self.liveSessionActive and self:GetCurrentPreset().uid == self.livePresetUID then
self:LiveSession_SendMDI("freehold",key)
end
end)
MDT.MDISelector:AddChild(MDT.MDISelector.FreeholdDropDown)
MDT.MDISelector.FreeholdCheck = AceGUI:Create("CheckBox")
MDT.MDISelector.FreeholdCheck:SetLabel(L["Join Crew"])
MDT.MDISelector.FreeholdCheck:SetCallback("OnValueChanged",function(widget, callbackName, value)
local preset = MDT:GetCurrentPreset()
preset.mdi.freeholdJoined = value
MDT:DungeonEnemies_UpdateFreeholdCrew()
MDT:ReloadPullButtons()
MDT:UpdateProgressbar()
if self.liveSessionActive and self:GetCurrentPreset().uid == self.livePresetUID then
self:LiveSession_SendMDI("join",value and "1" or "0")
end
end)
MDT.MDISelector:AddChild(MDT.MDISelector.FreeholdCheck)
end
if show then
local preset = MDT:GetCurrentPreset()
preset.mdi = preset.mdi or {}
--beguiling
preset.mdi.beguiling = preset.mdi.beguiling or 1
MDT.MDISelector.BeguilingDropDown:SetValue(preset.mdi.beguiling)
db.currentSeason = MDT:GetEffectivePresetSeason(preset)
MDT:DungeonEnemies_UpdateSeasonalAffix()
MDT:DungeonEnemies_UpdateBoralusFaction(MDT:GetCurrentPreset().faction)
--freehold
preset.mdi.freehold = preset.mdi.freehold or 1
MDT.MDISelector.FreeholdDropDown:SetValue(preset.mdi.freehold)
preset.mdi.freeholdJoined = preset.mdi.freeholdJoined or false
MDT.MDISelector.FreeholdCheck:SetValue(preset.mdi.freeholdJoined)
MDT:DungeonEnemies_UpdateFreeholdCrew()
MDT:DungeonEnemies_UpdateBlacktoothEvent()
MDT:UpdateProgressbar()
MDT:ReloadPullButtons()
MDT.MDISelector.frame:Show()
MDT:ToggleFreeholdSelector(false)
else
db.currentSeason = defaultSavedVars.global.currentSeason
MDT:DungeonEnemies_UpdateSeasonalAffix()
MDT:DungeonEnemies_UpdateBoralusFaction(MDT:GetCurrentPreset().faction)
MDT:UpdateFreeholdSelector(MDT:GetCurrentPreset().week)
MDT:DungeonEnemies_UpdateBlacktoothEvent()
MDT:UpdateProgressbar()
MDT:ReloadPullButtons()
MDT.MDISelector.frame:Hide()
MDT:ToggleFreeholdSelector(db.currentDungeonIdx == 16)
end
MDT:POI_UpdateAll()
MDT:KillAllAnimatedLines()
MDT:DrawAllAnimatedLines()
end
function MDT:UpdatePresetDropDown()
local dropdown = MDT.main_frame.sidePanel.WidgetGroup.PresetDropDown
local presetList = {}
for k,v in pairs(db.presets[db.currentDungeonIdx]) do
table.insert(presetList,k,v.text)
end
dropdown:SetList(presetList)
dropdown:SetValue(db.currentPreset[db.currentDungeonIdx])
dropdown:ClearFocus()
end
function MDT:UpdatePresetDropdownTextColor(forceReset)
local preset = self:GetCurrentPreset()
local livePreset = self:GetCurrentLivePreset()
if self.liveSessionActive and preset == livePreset and (not forceReset) then
local dropdown = MDT.main_frame.sidePanel.WidgetGroup.PresetDropDown
dropdown.text:SetTextColor(0,1,0,1)
else
local dropdown = MDT.main_frame.sidePanel.WidgetGroup.PresetDropDown
dropdown.text:SetTextColor(1,1,1,1)
end
end
---FormatEnemyForces
function MDT:FormatEnemyForces(forces, forcesmax, progressbar)
if not forcesmax then forcesmax = MDT:IsCurrentPresetTeeming() and MDT.dungeonTotalCount[db.currentDungeonIdx].teeming or MDT.dungeonTotalCount[db.currentDungeonIdx].normal end
if db.enemyForcesFormat == 1 then
if progressbar then return forces.."/"..forcesmax end
return forces
elseif db.enemyForcesFormat == 2 then
if progressbar then return string.format((forces.."/"..forcesmax.." (%.2f%%)"),(forces/forcesmax)*100) end
return string.format(forces.." (%.2f%%)",(forces/forcesmax)*100)
end
end
---Progressbar_SetValue
---Sets the value/progress/color of the count progressbar to the apropriate data
function MDT:Progressbar_SetValue(self, totalCurrent, totalMax)
local percent = (totalCurrent/totalMax)*100
if percent >= 102 then
if totalCurrent-totalMax > 8 then
self.Bar:SetStatusBarColor(1,0,0,1)
else
self.Bar:SetStatusBarColor(0,1,0,1)
end
elseif percent >= 100 then
self.Bar:SetStatusBarColor(0,1,0,1)
else
self.Bar:SetStatusBarColor(0.26,0.42,1)
end
self.Bar:SetValue(percent)
self.Bar.Label:SetText(MDT:FormatEnemyForces(totalCurrent,totalMax,true))
self.AnimValue = percent
end
---UpdateProgressbar
---Update the progressbar on the sidepanel with the correct values
function MDT:UpdateProgressbar()
local teeming = db.presets[db.currentDungeonIdx][db.currentPreset[db.currentDungeonIdx]].value.teeming
MDT:EnsureDBTables()
local grandTotal = MDT:CountForces()
MDT:Progressbar_SetValue(MDT.main_frame.sidePanel.ProgressBar,grandTotal,teeming==true and MDT.dungeonTotalCount[db.currentDungeonIdx].teeming or MDT.dungeonTotalCount[db.currentDungeonIdx].normal)
end
function MDT:OnPan(cursorX, cursorY)
local scrollFrame = MDTScrollFrame
local scale = MDTMapPanelFrame:GetScale()/1.5
local deltaX = (scrollFrame.cursorX - cursorX)/scale
local deltaY = (cursorY - scrollFrame.cursorY)/scale
if(scrollFrame.panning)then
local newHorizontalPosition = max(0, deltaX + scrollFrame:GetHorizontalScroll())
newHorizontalPosition = min(newHorizontalPosition, scrollFrame.maxX)
local newVerticalPosition = max(0, deltaY + scrollFrame:GetVerticalScroll())
newVerticalPosition = min(newVerticalPosition, scrollFrame.maxY)
scrollFrame:SetHorizontalScroll(newHorizontalPosition)
scrollFrame:SetVerticalScroll(newVerticalPosition)
scrollFrame.cursorX = cursorX
scrollFrame.cursorY = cursorY
scrollFrame.wasPanningLastFrame = true;
scrollFrame.lastDeltaX = deltaX;
scrollFrame.lastDeltaY = deltaY;
else
if(scrollFrame.wasPanningLastFrame)then
scrollFrame.isFadeOutPanning = true
scrollFrame.fadeOutXStart = scrollFrame.lastDeltaX
scrollFrame.fadeOutYStart = scrollFrame.lastDeltaY
scrollFrame.panDuration = 0
scrollFrame.wasPanningLastFrame = false;
end
end
end
function MDT:OnPanFadeOut(deltaTime)
local scrollFrame = MDTScrollFrame
local panDuration = 0.5
local panAtenuation = 7
if(scrollFrame.isFadeOutPanning)then
scrollFrame.panDuration = scrollFrame.panDuration + deltaTime
local phase = scrollFrame.panDuration / panDuration
local phaseLog = -math.log(phase)
local stepX = (scrollFrame.fadeOutXStart * phaseLog) / panAtenuation
local stepY = (scrollFrame.fadeOutYStart * phaseLog) / panAtenuation
local newHorizontalPosition = max(0, stepX + scrollFrame:GetHorizontalScroll())
newHorizontalPosition = min(newHorizontalPosition, scrollFrame.maxX)
local newVerticalPosition = max(0, stepY + scrollFrame:GetVerticalScroll())
newVerticalPosition = min(newVerticalPosition, scrollFrame.maxY)
scrollFrame:SetHorizontalScroll(newHorizontalPosition)
scrollFrame:SetVerticalScroll(newVerticalPosition)
if(scrollFrame.panDuration > panDuration)then
scrollFrame.isFadeOutPanning = false
end
end
end
function MDT:ExportCurrentZoomPanSettings()
local mainFrame = MDTMapPanelFrame
local scrollFrame = MDTScrollFrame
local zoom = MDTMapPanelFrame:GetScale()
local panH = MDTScrollFrame:GetHorizontalScroll() / MDT:GetScale()
local panV = MDTScrollFrame:GetVerticalScroll() / MDT:GetScale()
local output = " ["..db.presets[db.currentDungeonIdx][db.currentPreset[db.currentDungeonIdx]].value.currentSublevel.."] = {\n"
output = output.." zoomScale = "..zoom..";\n"
output = output.." horizontalPan = "..panH..";\n"
output = output.." verticalPan = "..panV..";\n"
output = output.." };\n"
MDT:HideAllDialogs()
MDT.main_frame.ExportFrame:Show()
MDT.main_frame.ExportFrame:ClearAllPoints()
MDT.main_frame.ExportFrame:SetPoint("CENTER", MDT.main_frame,"CENTER",0,50)
MDT.main_frame.ExportFrameEditbox:SetText(output)
MDT.main_frame.ExportFrameEditbox:HighlightText(0, string.len(output))
MDT.main_frame.ExportFrameEditbox:SetFocus()
MDT.main_frame.ExportFrameEditbox:SetLabel("Current pan/zoom settings");
end
function MDT:ZoomMapToDefault()
local currentMap = db.presets[db.currentDungeonIdx]
local currentSublevel = currentMap[db.currentPreset[db.currentDungeonIdx]].value.currentSublevel
local mainFrame = MDTMapPanelFrame
local scrollFrame = MDTScrollFrame
local currentMapInfo = MDT.mapInfo[db.currentDungeonIdx]
if(currentMapInfo and currentMapInfo.viewportPositionOverrides and currentMapInfo.viewportPositionOverrides[currentSublevel])then
local data = currentMapInfo.viewportPositionOverrides[currentSublevel];
local scaledSizeX = mainFrame:GetWidth() * data.zoomScale
local scaledSizeY = mainFrame:GetHeight() * data.zoomScale
scrollFrame.maxX = (scaledSizeX - mainFrame:GetWidth()) / data.zoomScale
scrollFrame.maxY = (scaledSizeY - mainFrame:GetHeight()) / data.zoomScale
scrollFrame.zoomedIn = abs(data.zoomScale - 1) > 0.02
mainFrame:SetScale(data.zoomScale)
scrollFrame:SetHorizontalScroll(data.horizontalPan * MDT:GetScale())
scrollFrame:SetVerticalScroll(data.verticalPan * MDT:GetScale())
else
scrollFrame.maxX = 1
scrollFrame.maxY = 1
scrollFrame.zoomedIn = false
mainFrame:SetScale(1);
scrollFrame:SetHorizontalScroll(0)
scrollFrame:SetVerticalScroll(0)
end
end
function MDT:ZoomMap(delta)
local scrollFrame = MDTScrollFrame
if not scrollFrame:GetLeft() then return end
local oldScrollH = scrollFrame:GetHorizontalScroll()
local oldScrollV = scrollFrame:GetVerticalScroll()
local mainFrame = MDTMapPanelFrame
local oldScale = mainFrame:GetScale()
local newScale = oldScale + delta * 0.3
newScale = max(1, newScale)
newScale = min(15, newScale)
mainFrame:SetScale(newScale)
local scaledSizeX = mainFrame:GetWidth() * newScale
local scaledSizeY = mainFrame:GetHeight() * newScale
scrollFrame.maxX = (scaledSizeX - mainFrame:GetWidth()) / newScale
scrollFrame.maxY = (scaledSizeY - mainFrame:GetHeight()) / newScale
scrollFrame.zoomedIn = abs(newScale - 1) > 0.02
local cursorX,cursorY = GetCursorPosition()
local frameX = (cursorX / UIParent:GetScale()) - scrollFrame:GetLeft()
local frameY = scrollFrame:GetTop() - (cursorY / UIParent:GetScale())
local scaleChange = newScale / oldScale
local newScrollH = (scaleChange * frameX - frameX) / newScale + oldScrollH
local newScrollV = (scaleChange * frameY - frameY) / newScale + oldScrollV
newScrollH = min(newScrollH, scrollFrame.maxX)
newScrollH = max(0, newScrollH)
newScrollV = min(newScrollV, scrollFrame.maxY)
newScrollV = max(0, newScrollV)
scrollFrame:SetHorizontalScroll(newScrollH)
scrollFrame:SetVerticalScroll(newScrollV)
MDT:SetPingOffsets(newScale)
end
---ActivatePullTooltip
---
function MDT:ActivatePullTooltip(pull)
local pullTooltip = MDT.pullTooltip
--[[
if not pullTooltip.ranOnce then
--fix elvui skinning
pullTooltip:SetPoint("TOPRIGHT",UIParent,"BOTTOMRIGHT")
pullTooltip:SetPoint("BOTTOMRIGHT",UIParent,"BOTTOMRIGHT")
pullTooltip:Show()
pullTooltip.ranOnce = true
end
]]
pullTooltip.currentPull = pull
pullTooltip:Show()
end
---UpdatePullTooltip
---Updates the tooltip which is being displayed when a pull is mouseovered
function MDT:UpdatePullTooltip(tooltip)
local frame = MDT.main_frame
if not MouseIsOver(frame.sidePanel.pullButtonsScrollFrame.frame) then
tooltip:Hide()
elseif MouseIsOver(frame.sidePanel.newPullButton.frame) then
tooltip:Hide()
else
if frame.sidePanel.newPullButtons and tooltip.currentPull and frame.sidePanel.newPullButtons[tooltip.currentPull] then
--enemy portraits
local showData
for k,v in pairs(frame.sidePanel.newPullButtons[tooltip.currentPull].enemyPortraits) do
if MouseIsOver(v) then
if v:IsShown() then
--model
if v.enemyData.displayId and (not tooltip.modelNpcId or (tooltip.modelNpcId ~= v.enemyData.displayId)) then
tooltip.Model:SetDisplayInfo(v.enemyData.displayId)
tooltip.modelNpcId = v.enemyData.displayId
end
--topString
local newLine = "\n"
local text = newLine..newLine..newLine..L[v.enemyData.name].." x"..v.enemyData.quantity..newLine
text = text..string.format(L["Level %d %s"],v.enemyData.level,L[v.enemyData.creatureType])..newLine
local boss = v.enemyData.isBoss or false
local health = MDT:CalculateEnemyHealth(boss,v.enemyData.baseHealth,db.currentDifficulty,v.enemyData.ignoreFortified)
text = text.. string.format(L["%s HP"],MDT:FormatEnemyHealth(health))..newLine
local totalForcesMax = MDT:IsCurrentPresetTeeming() and MDT.dungeonTotalCount[db.currentDungeonIdx].teeming or MDT.dungeonTotalCount[db.currentDungeonIdx].normal
local count = MDT:IsCurrentPresetTeeming() and v.enemyData.teemingCount or v.enemyData.count
text = text..L["Forces"]..": ".. MDT:FormatEnemyForces(count,totalForcesMax,false)
tooltip.topString:SetText(text)
showData = true
end
break
end
end
if showData then
tooltip.topString:Show()
tooltip.Model:Show()
else
tooltip.topString:Hide()
tooltip.Model:Hide()
end
local countEnemies = 0
for k,v in pairs(frame.sidePanel.newPullButtons[tooltip.currentPull].enemyPortraits) do
if v:IsShown() then countEnemies = countEnemies + 1 end
end
if countEnemies == 0 then
tooltip:Hide()
return
end
local pullForces = MDT:CountForces(tooltip.currentPull,true)
local totalForces = MDT:CountForces(tooltip.currentPull,false)
local totalForcesMax = MDT:IsCurrentPresetTeeming() and MDT.dungeonTotalCount[db.currentDungeonIdx].teeming or MDT.dungeonTotalCount[db.currentDungeonIdx].normal
local text = L["Forces"]..": ".. MDT:FormatEnemyForces(pullForces,totalForcesMax,false)
text = text.. "\n"..L["Total"]..": ".. MDT:FormatEnemyForces(totalForces,totalForcesMax,true)
tooltip.botString:SetText(text)
tooltip.botString:Show()
end
end
end
---CountForces
---Counts total selected enemy forces in the current preset up to pull
function MDT:CountForces(currentPull, currentOnly)
--count up to and including the currently selected pull
currentPull = currentPull or 1000
local preset = self:GetCurrentPreset()
local teeming = self:IsCurrentPresetTeeming()
local pullCurrent = 0
for pullIdx,pull in pairs(preset.value.pulls) do
if not currentOnly or (currentOnly and pullIdx == currentPull) then
if pullIdx <= currentPull then
for enemyIdx,clones in pairs(pull) do
if tonumber(enemyIdx) then
for k,v in pairs(clones) do
if MDT:IsCloneIncluded(enemyIdx,v) then
local count = teeming
and self.dungeonEnemies[db.currentDungeonIdx][enemyIdx].teemingCount
or self.dungeonEnemies[db.currentDungeonIdx][enemyIdx].count
pullCurrent = pullCurrent + count
end
end
end
end
else
break
end
end
end
return pullCurrent
end
local emissaryIds = {[155432]=true,[155433]=true,[155434]=true}
---Checks if the specified clone is part of the current map configuration
function MDT:IsCloneIncluded(enemyIdx, cloneIdx)
local preset = MDT:GetCurrentPreset()
local isCloneBlacktoothEvent = MDT.dungeonEnemies[db.currentDungeonIdx][enemyIdx]["clones"][cloneIdx].blacktoothEvent
local cloneFaction = MDT.dungeonEnemies[db.currentDungeonIdx][enemyIdx]["clones"][cloneIdx].faction
local week = self:GetEffectivePresetWeek()
if db.currentSeason ~= 3 then
if emissaryIds[MDT.dungeonEnemies[db.currentDungeonIdx][enemyIdx].id] then return false end
elseif db.currentSeason ~= 4 then
if MDT.dungeonEnemies[db.currentDungeonIdx][enemyIdx].corrupted then return false end
end
--beguiling weekly configuration
local weekData = MDT.dungeonEnemies[db.currentDungeonIdx][enemyIdx]["clones"][cloneIdx].week
if weekData then
if weekData[week] and not (cloneFaction and cloneFaction~= preset.faction) and db.currentDifficulty >= 10 then
return true
else
return false
end
end
week = week%3
if week == 0 then week = 3 end
local isBlacktoothWeek = week == 2
if not isCloneBlacktoothEvent or isBlacktoothWeek then
if not (cloneFaction and cloneFaction~= preset.faction) then
local isCloneTeeming = MDT.dungeonEnemies[db.currentDungeonIdx][enemyIdx]["clones"][cloneIdx].teeming
local isCloneNegativeTeeming = MDT.dungeonEnemies[db.currentDungeonIdx][enemyIdx]["clones"][cloneIdx].negativeTeeming
if MDT:IsCurrentPresetTeeming() or ((isCloneTeeming and isCloneTeeming == false) or (not isCloneTeeming)) then
if not(MDT:IsCurrentPresetTeeming() and isCloneNegativeTeeming) then
return true
end
end
end
end
end
---IsCurrentPresetTeeming
---Returns true if the current preset has teeming turned on, false otherwise
function MDT:IsCurrentPresetTeeming()
--return self:GetCurrentPreset().week
return db.presets[db.currentDungeonIdx][db.currentPreset[db.currentDungeonIdx]].value.teeming
end
---IsCurrentPresetFortified
function MDT:IsCurrentPresetFortified()
return self:GetCurrentPreset().week%2 == 1
end
---IsCurrentPresetTyrannical
function MDT:IsCurrentPresetTyrannical()
return not MDT:IsCurrentPresetFortified()
end
---MouseDownHook
function MDT:MouseDownHook()
return
end
---Handles mouse-down events on the map scrollframe
MDT.OnMouseDown = function(self, button)
local scrollFrame = MDT.main_frame.scrollFrame
if scrollFrame.zoomedIn then
scrollFrame.panning = true
scrollFrame.cursorX,scrollFrame.cursorY = GetCursorPosition()
end
scrollFrame.oldX = scrollFrame.cursorX
scrollFrame.oldY = scrollFrame.cursorY
MDT:MouseDownHook()
end
---handles mouse-up events on the map scrollframe
MDT.OnMouseUp = function(self, button)
local scrollFrame = MDT.main_frame.scrollFrame
if scrollFrame.panning then scrollFrame.panning = false end
--play minimap ping on right click at cursor position
--only ping if we didnt pan
if scrollFrame.oldX==scrollFrame.cursorX or scrollFrame.oldY==scrollFrame.cursorY then
if button == "RightButton" then
local x,y = MDT:GetCursorPosition()
MDT:PingMap(x,y)
local sublevel = MDT:GetCurrentSubLevel()
if MDT.liveSessionActive then MDT:LiveSession_SendPing(x,y,sublevel) end
end
end
end
---Pings the map
function MDT:PingMap(x, y)
self.ping:ClearAllPoints()
self.ping:SetPoint("CENTER",self.main_frame.mapPanelTile1,"TOPLEFT",x,y)
self.ping:SetModel("interface/minimap/ping/minimapping.m2")
local mainFrame = MDTMapPanelFrame
local mapScale = mainFrame:GetScale()
self:SetPingOffsets(mapScale)
self.ping:Show()
UIFrameFadeOut(self.ping, 2, 1, 0)
self.ping:SetSequence(0)
end
function MDT:SetPingOffsets(mapScale)
local scale = 0.35
local offset = (10.25/1000)*mapScale
MDT.ping:SetTransform(offset,offset,0,0,0,0,scale)
end
---SetCurrentSubLevel
---Sets the sublevel of the currently active preset, need to UpdateMap to reflect the change in UI
function MDT:SetCurrentSubLevel(sublevel)
MDT:GetCurrentPreset().value.currentSublevel = sublevel
end
---GetCurrentPull
---Returns the current pull of the currently active preset
function MDT:GetCurrentPull()
local selection = MDT:GetSelection()
return selection[#selection]
end
---GetCurrentSubLevel
---Returns the sublevel of the currently active preset
function MDT:GetCurrentSubLevel()
return MDT:GetCurrentPreset().value.currentSublevel
end
---GetCurrentPreset
---Returns the current preset
function MDT:GetCurrentPreset()
return db.presets[db.currentDungeonIdx][db.currentPreset[db.currentDungeonIdx]]
end
---GetCurrentLivePreset
function MDT:GetCurrentLivePreset()
if not self.livePresetUID then return end
if self.liveUpdateFrameOpen then
for fullName,cachedPreset in pairs(self.transmissionCache) do
if cachedPreset.uid == self.livePresetUID then
return cachedPreset
end
end
end
for dungeonIdx,presets in pairs(db.presets) do
for presetIdx,preset in pairs(presets) do
if preset.uid and preset.uid == self.livePresetUID then
return preset,presetIdx
end
end
end
end
---GetEffectivePresetWeek
function MDT:GetEffectivePresetWeek(preset)
preset = preset or self:GetCurrentPreset()
local week
if db.MDI.enabled then
week = preset.mdi.beguiling or 1
if week == 14 then week = 1 end
if week == 15 then week = 3 end
else
week = preset.week
end
return week
end
---GetEffectivePresetSeason
function MDT:GetEffectivePresetSeason(preset)
local season = db.currentSeason
if db.MDI.enabled then
local mdiWeek = preset.mdi.beguiling
season = (mdiWeek == 1 or mdiWeek == 2 or mdiWeek == 3) and 3 or mdiWeek == 13 and 2 or (mdiWeek == 14 or mdiWeek == 15) and 4
end
return season
end
---ReturnToLivePreset
function MDT:ReturnToLivePreset()
local preset,presetIdx = self:GetCurrentLivePreset()
self:UpdateToDungeon(preset.value.currentDungeonIdx,true)
db.currentPreset[db.currentDungeonIdx] = presetIdx
self:UpdatePresetDropDown()
self:UpdateMap()
end
---SetLivePreset
function MDT:SetLivePreset()
local preset = self:GetCurrentPreset()
self:SetUniqueID(preset)
self.livePresetUID = preset.uid
self:LiveSession_SendPreset(preset)
self:UpdatePresetDropdownTextColor()
self.main_frame.setLivePresetButton:Hide()
self.main_frame.liveReturnButton:Hide()
end
---IsWeekTeeming
---Returns if the current week has an affix week set that includes the teeming affix
function MDT:IsWeekTeeming(week)
if not week then week = MDT:GetCurrentAffixWeek() or 1 end
return affixWeeks[week][1] == 5
end
---Returns if the current week has an affix weeks set that includes the inspiring affix
function MDT:IsWeekInspiring(week)
if not week then week = MDT:GetCurrentAffixWeek() or 1 end
return affixWeeks[week][1] == 122 or affixWeeks[week][2] == 122
end
---IsPresetTeeming
---Returns if the preset is set to a week which contains the teeming affix
function MDT:IsPresetTeeming(preset)
return MDT:IsWeekTeeming(preset.week)
end
function MDT:GetRiftOffsets()
local week = self:GetEffectivePresetWeek()
local preset = self:GetCurrentPreset()
preset.value.riftOffsets = preset.value.riftOffsets or {}
local riftOffsets = preset.value.riftOffsets
riftOffsets[week] = riftOffsets[week] or {}
return riftOffsets[week]
end
function MDT:MakeMapTexture(frame)
MDT.contextMenuList = {}
tinsert(MDT.contextMenuList, {
text = "Close",
notCheckable = 1,
func = frame.contextDropdown:Hide()
})
-- Scroll Frame
if frame.scrollFrame == nil then
frame.scrollFrame = CreateFrame("ScrollFrame", "MDTScrollFrame",frame)
frame.scrollFrame:ClearAllPoints()
frame.scrollFrame:SetSize(sizex*db.scale, sizey*db.scale)
--frame.scrollFrame:SetPoint("TOPLEFT", frame, "TOPLEFT", 0, 0)
frame.scrollFrame:SetAllPoints(frame)
-- Enable mousewheel scrolling
frame.scrollFrame:EnableMouseWheel(true)
local lastModifiedScroll
local ignoredTargets = {--ignore alt scroll if expansion would be changed
[14] = true,
[27] = true,
[28] = true,
[37] = true,
}
frame.scrollFrame:SetScript("OnMouseWheel", function(self, delta)
if IsControlKeyDown() then
if not lastModifiedScroll or lastModifiedScroll < GetTime() - 0.1 then
lastModifiedScroll = GetTime()
delta = delta*-1
local target = MDT:GetCurrentSubLevel()+delta
if dungeonSubLevels[db.currentDungeonIdx][target] then
MDT:SetCurrentSubLevel(target)
MDT:UpdateMap()
MDT:ZoomMapToDefault()
end
end
elseif IsAltKeyDown() then
if not lastModifiedScroll or lastModifiedScroll < GetTime() - 0.3 then
lastModifiedScroll = GetTime()
delta = delta*-1
local target = db.currentDungeonIdx+delta
if dungeonList[target] and not ignoredTargets[target] then
local group = MDT.main_frame.DungeonSelectionGroup
group.DungeonDropdown:Fire("OnValueChanged", target)
end
end
else
MDT:ZoomMap(delta)
end
end)
--PAN
frame.scrollFrame:EnableMouse(true)
frame.scrollFrame:SetScript("OnMouseDown", MDT.OnMouseDown)
frame.scrollFrame:SetScript("OnMouseUp", MDT.OnMouseUp)
frame.scrollFrame:SetScript("OnUpdate", function(self,elapsed)
local x, y = GetCursorPosition()
MDT:OnPan(x, y)
MDT:OnPanFadeOut(elapsed)
end)
if frame.mapPanelFrame == nil then
frame.mapPanelFrame = CreateFrame("frame","MDTMapPanelFrame",nil)
frame.mapPanelFrame:ClearAllPoints()
frame.mapPanelFrame:SetSize(sizex*db.scale, sizey*db.scale)
--frame.mapPanelFrame:SetPoint("TOPLEFT", frame, "TOPLEFT", 0, 0)
frame.mapPanelFrame:SetAllPoints(frame)
end
--create the 12 tiles and set the scrollchild
for i=1,12 do
frame["mapPanelTile"..i] = frame.mapPanelFrame:CreateTexture("MDTmapPanelTile"..i, "BACKGROUND")
frame["mapPanelTile"..i]:SetDrawLayer(canvasDrawLayer, 0)
--frame["mapPanelTile"..i]:SetAlpha(0.3)
frame["mapPanelTile"..i]:SetSize(frame:GetWidth()/4+(5*db.scale),frame:GetWidth()/4+(5*db.scale))
end
frame.mapPanelTile1:SetPoint("TOPLEFT",frame.mapPanelFrame,"TOPLEFT",0,0)
frame.mapPanelTile2:SetPoint("TOPLEFT",frame.mapPanelTile1,"TOPRIGHT")
frame.mapPanelTile3:SetPoint("TOPLEFT",frame.mapPanelTile2,"TOPRIGHT")
frame.mapPanelTile4:SetPoint("TOPLEFT",frame.mapPanelTile3,"TOPRIGHT")
frame.mapPanelTile5:SetPoint("TOPLEFT",frame.mapPanelTile1,"BOTTOMLEFT")
frame.mapPanelTile6:SetPoint("TOPLEFT",frame.mapPanelTile5,"TOPRIGHT")
frame.mapPanelTile7:SetPoint("TOPLEFT",frame.mapPanelTile6,"TOPRIGHT")
frame.mapPanelTile8:SetPoint("TOPLEFT",frame.mapPanelTile7,"TOPRIGHT")
frame.mapPanelTile9:SetPoint("TOPLEFT",frame.mapPanelTile5,"BOTTOMLEFT")
frame.mapPanelTile10:SetPoint("TOPLEFT",frame.mapPanelTile9,"TOPRIGHT")
frame.mapPanelTile11:SetPoint("TOPLEFT",frame.mapPanelTile10,"TOPRIGHT")
frame.mapPanelTile12:SetPoint("TOPLEFT",frame.mapPanelTile11,"TOPRIGHT")
--create the 150 large map tiles
for i=1,10 do
for j=1,15 do
frame["largeMapPanelTile"..i..j] = frame.mapPanelFrame:CreateTexture("MDTLargeMapPanelTile"..i..j, "BACKGROUND")
local tile = frame["largeMapPanelTile"..i..j]
tile:SetDrawLayer(canvasDrawLayer, 5)
tile:SetSize(frame:GetWidth()/15,frame:GetWidth()/15)
if i==1 and j==1 then
--to mapPanel
tile:SetPoint("TOPLEFT",frame.mapPanelFrame,"TOPLEFT",0,0)
elseif j==1 then
--to tile above
tile:SetPoint("TOPLEFT",frame["largeMapPanelTile"..(i-1)..j],"BOTTOMLEFT",0,0)
else
--to tile to the left
tile:SetPoint("TOPLEFT",frame["largeMapPanelTile"..i..(j-1)],"TOPRIGHT",0,0)
end
tile:SetColorTexture(i/10,j/10,0,1)
tile:Hide()
end
end
frame.scrollFrame:SetScrollChild(frame.mapPanelFrame)
frame.scrollFrame.cursorX = 0
frame.scrollFrame.cursorY = 0
frame.scrollFrame.queuedDeltaX = 0;
frame.scrollFrame.queuedDeltaY = 0;
end
end
local function round(number, decimals)
return (("%%.%df"):format(decimals)):format(number)
end
function MDT:CalculateEnemyHealth(boss, baseHealth, level, ignoreFortified)
local fortified = MDT:IsCurrentPresetFortified()
local tyrannical = MDT:IsCurrentPresetTyrannical()
local mult = 1
if boss == false and fortified == true and (not ignoreFortified) then mult = 1.2 end
if boss == true and tyrannical == true then mult = 1.3 end
mult = round((1.08^math.max(level-2,0))*mult,2)
return round(mult*baseHealth,0)
end
function MDT:ReverseCalcEnemyHealth(unit, level, boss)
local health = UnitHealthMax(unit)
local fortified = MDT:IsCurrentPresetFortified()
local tyrannical = MDT:IsCurrentPresetTyrannical()
local mult = 1
if boss == false and fortified == true then mult = 1.2 end
if boss == true and tyrannical == true then mult = 1.3 end
mult = round((1.08^math.max(level-2,0))*mult,2)
local baseHealth = health/mult
return baseHealth
end
function MDT:FormatEnemyHealth(amount)
amount = tonumber(amount)
if not amount then return "" end
if self:GetLocaleIndex() == 9 then
if amount < 1e3 then
return 0
elseif amount >= 1e16 then
return string.format("%.3f경", amount/1e16)
elseif amount >= 1e12 then
return string.format("%.3f조", amount/1e12)
elseif amount >= 1e8 then
return string.format("%.2f억", amount/1e8)
elseif amount >= 1e4 then
return string.format("%.1f만", amount/1e4)
end
else
if amount < 1e3 then
return 0
elseif amount >= 1e12 then
return string.format("%.3ft", amount/1e12)
elseif amount >= 1e9 then
return string.format("%.3fb", amount/1e9)
elseif amount >= 1e6 then
return string.format("%.2fm", amount/1e6)
elseif amount >= 1e3 then
return string.format("%.1fk", amount/1e3)
end
end
end
function MDT:UpdateDungeonEnemies()
MDT:DungeonEnemies_UpdateEnemies()
end
function MDT:HideAllDialogs()
MDT.main_frame.presetCreationFrame:Hide()
MDT.main_frame.presetImportFrame:Hide()
MDT.main_frame.ExportFrame:Hide()
MDT.main_frame.RenameFrame:Hide()
MDT.main_frame.ClearConfirmationFrame:Hide()
MDT.main_frame.DeleteConfirmationFrame:Hide()
MDT.main_frame.automaticColorsFrame.CustomColorFrame:Hide()
MDT.main_frame.automaticColorsFrame:Hide()
if MDT.main_frame.ConfirmationFrame then MDT.main_frame.ConfirmationFrame:Hide() end
end
function MDT:OpenImportPresetDialog()
MDT:HideAllDialogs()
MDT.main_frame.presetImportFrame:ClearAllPoints()
MDT.main_frame.presetImportFrame:SetPoint("CENTER", MDT.main_frame,"CENTER",0,50)
MDT.main_frame.presetImportFrame:Show()
MDT.main_frame.presetImportBox:SetText("")
MDT.main_frame.presetImportBox:SetFocus()
MDT.main_frame.presetImportLabel:SetText(nil)
end
function MDT:OpenNewPresetDialog()
MDT:HideAllDialogs()
local presetList = {}
local countPresets = 0
for k,v in pairs(db.presets[db.currentDungeonIdx]) do
if v.text ~= "<New Preset>" then
table.insert(presetList,k,v.text)
countPresets=countPresets+1
end
end
table.insert(presetList,1,"Empty")
MDT.main_frame.PresetCreationDropDown:SetList(presetList)
MDT.main_frame.PresetCreationDropDown:SetValue(1)
MDT.main_frame.PresetCreationEditbox:SetText(L["defaultPresetName"].." "..countPresets+1)
MDT.main_frame.presetCreationFrame:ClearAllPoints()
MDT.main_frame.presetCreationFrame:SetPoint("CENTER", MDT.main_frame,"CENTER",0,50)
MDT.main_frame.presetCreationFrame:SetStatusText("")
MDT.main_frame.presetCreationFrame:Show()
MDT.main_frame.presetCreationCreateButton:SetDisabled(false)
MDT.main_frame.presetCreationCreateButton.text:SetTextColor(1,0.8196,0)
MDT.main_frame.PresetCreationEditbox:SetFocus()
MDT.main_frame.PresetCreationEditbox:HighlightText(0,50)
MDT.main_frame.presetImportBox:SetText("")
end
function MDT:OpenClearPresetDialog()
MDT:HideAllDialogs()
MDT.main_frame.ClearConfirmationFrame:ClearAllPoints()
MDT.main_frame.ClearConfirmationFrame:SetPoint("CENTER", MDT.main_frame,"CENTER",0,50)
local currentPresetName = db.presets[db.currentDungeonIdx][db.currentPreset[db.currentDungeonIdx]].text
MDT.main_frame.ClearConfirmationFrame.label:SetText(string.format(L["Reset %s?"],currentPresetName))
MDT.main_frame.ClearConfirmationFrame:Show()
end
function MDT:OpenAutomaticColorsDialog()
MDT:HideAllDialogs()
MDT.main_frame.automaticColorsFrame:ClearAllPoints()
MDT.main_frame.automaticColorsFrame:SetPoint("CENTER", MDT.main_frame,"CENTER",0,50)
MDT.main_frame.automaticColorsFrame:SetStatusText("")
MDT.main_frame.automaticColorsFrame:Show()
MDT.main_frame.automaticColorsFrame.CustomColorFrame:Hide()
if db.colorPaletteInfo.colorPaletteIdx == 6 then
MDT:OpenCustomColorsDialog()
end
end
function MDT:OpenCustomColorsDialog(frame)
MDT:HideAllDialogs()
MDT.main_frame.automaticColorsFrame:Show() --Not the prettiest way to handle this, but it works.
MDT.main_frame.automaticColorsFrame.CustomColorFrame:ClearAllPoints()
MDT.main_frame.automaticColorsFrame.CustomColorFrame:SetPoint("CENTER",264,-7)
MDT.main_frame.automaticColorsFrame.CustomColorFrame:SetStatusText("")
MDT.main_frame.automaticColorsFrame.CustomColorFrame:Show()
end
function MDT:UpdateDungeonDropDown()
local group = MDT.main_frame.DungeonSelectionGroup
group.DungeonDropdown:SetList({})
if db.currentExpansion == 1 then
for i=1,14 do
group.DungeonDropdown:AddItem(i,dungeonList[i])
end
elseif db.currentExpansion == 2 then
for i=15,28 do
group.DungeonDropdown:AddItem(i,dungeonList[i])
end
elseif db.currentExpansion == 3 then
for i = 29,37 do
group.DungeonDropdown:AddItem(i,dungeonList[i])
end
end
group.DungeonDropdown:SetValue(db.currentDungeonIdx)
group.SublevelDropdown:SetList(dungeonSubLevels[db.currentDungeonIdx])
group.SublevelDropdown:SetValue(db.presets[db.currentDungeonIdx][db.currentPreset[db.currentDungeonIdx]].value.currentSublevel)
group.DungeonDropdown:ClearFocus()
group.SublevelDropdown:ClearFocus()
end
---CreateDungeonSelectDropdown
---Creates both dungeon and sublevel dropdowns
function MDT:CreateDungeonSelectDropdown(frame)
--Simple Group to hold both dropdowns
frame.DungeonSelectionGroup = AceGUI:Create("SimpleGroup")
local group = frame.DungeonSelectionGroup
group.frame:SetFrameStrata("HIGH")
group.frame:SetFrameLevel(50)
group:SetWidth(200)
group:SetHeight(50)
group:SetPoint("TOPLEFT",frame.topPanel,"BOTTOMLEFT",0,2)
group:SetLayout("List")
MDT:FixAceGUIShowHide(group)
--dungeon select
group.DungeonDropdown = AceGUI:Create("Dropdown")
group.DungeonDropdown.text:SetJustifyH("LEFT")
group.DungeonDropdown:SetCallback("OnValueChanged",function(widget,callbackName,key)
if key == 14 then
db.currentExpansion = 2
db.currentDungeonIdx = 15
MDT:UpdateDungeonDropDown()
MDT:UpdateToDungeon(db.currentDungeonIdx)
elseif key == 27 then
db.currentExpansion = 1
db.currentDungeonIdx = 1
MDT:UpdateDungeonDropDown()
MDT:UpdateToDungeon(db.currentDungeonIdx)
elseif key == 28 then
db.currentExpansion = 3
db.currentDungeonIdx = 29
MDT:UpdateDungeonDropDown()
MDT:UpdateToDungeon(db.currentDungeonIdx)
elseif key == 37 then
db.currentExpansion = 2
db.currentDungeonIdx = 15
MDT:UpdateDungeonDropDown()
MDT:UpdateToDungeon(db.currentDungeonIdx)
else
MDT:UpdateToDungeon(key)
end
end)
group:AddChild(group.DungeonDropdown)
--sublevel select
group.SublevelDropdown = AceGUI:Create("Dropdown")
group.SublevelDropdown.text:SetJustifyH("LEFT")
group.SublevelDropdown:SetCallback("OnValueChanged",function(widget,callbackName,key)
db.presets[db.currentDungeonIdx][db.currentPreset[db.currentDungeonIdx]].value.currentSublevel = key
MDT:UpdateMap()
MDT:ZoomMapToDefault()
end)
group:AddChild(group.SublevelDropdown)
MDT:UpdateDungeonDropDown()
end
---EnsureDBTables
---Makes sure profiles are valid and have their fields set
function MDT:EnsureDBTables()
--dungeonIdx doesnt exist
if not dungeonList[db.currentDungeonIdx] or string.find(dungeonList[db.currentDungeonIdx],">") then
db.currentDungeonIdx = db.currentExpansion == 1 and 1 or db.currentExpansion == 2 and 15
end
local preset = MDT:GetCurrentPreset()
preset.week = preset.week or MDT:GetCurrentAffixWeek()
db.currentPreset[db.currentDungeonIdx] = db.currentPreset[db.currentDungeonIdx] or 1
db.presets[db.currentDungeonIdx][db.currentPreset[db.currentDungeonIdx]].value.currentDungeonIdx = db.currentDungeonIdx
db.presets[db.currentDungeonIdx][db.currentPreset[db.currentDungeonIdx]].value.currentSublevel = db.presets[db.currentDungeonIdx][db.currentPreset[db.currentDungeonIdx]].value.currentSublevel or 1
db.presets[db.currentDungeonIdx][db.currentPreset[db.currentDungeonIdx]].value.currentPull = db.presets[db.currentDungeonIdx][db.currentPreset[db.currentDungeonIdx]].value.currentPull or 1
db.presets[db.currentDungeonIdx][db.currentPreset[db.currentDungeonIdx]].value.pulls = db.presets[db.currentDungeonIdx][db.currentPreset[db.currentDungeonIdx]].value.pulls or {}
-- make sure, that at least 1 pull exists
if #db.presets[db.currentDungeonIdx][db.currentPreset[db.currentDungeonIdx]].value.pulls == 0 then
db.presets[db.currentDungeonIdx][db.currentPreset[db.currentDungeonIdx]].value.pulls[1] = {}
end
--detect gaps in pull list and delete invalid pulls
for k,v in pairs(preset.value.pulls) do
if k == 0 or k>#preset.value.pulls then
preset.value.pulls[k] = nil
end
end
-- Set current pull to last pull, if the actual current pull does not exists anymore
if not db.presets[db.currentDungeonIdx][db.currentPreset[db.currentDungeonIdx]].value.pulls[db.presets[db.currentDungeonIdx][db.currentPreset[db.currentDungeonIdx]].value.currentPull] then
db.presets[db.currentDungeonIdx][db.currentPreset[db.currentDungeonIdx]].value.currentPull = #db.presets[db.currentDungeonIdx][db.currentPreset[db.currentDungeonIdx]].value.pulls
end
for k,v in pairs(db.presets[db.currentDungeonIdx][db.currentPreset[db.currentDungeonIdx]].value.pulls) do
if k ==0 then
db.presets[db.currentDungeonIdx][db.currentPreset[db.currentDungeonIdx]].value.pulls[0] = nil
break
end
end
--removed clones: remove data from presets
for pullIdx,pull in pairs(preset.value.pulls) do
for enemyIdx,clones in pairs(pull) do
if tonumber(enemyIdx) then
--enemy does not exist at all anymore
if not MDT.dungeonEnemies[db.currentDungeonIdx][enemyIdx] then
pull[enemyIdx] = nil
else
--only clones
for k,v in pairs(clones) do
if not MDT.dungeonEnemies[db.currentDungeonIdx][enemyIdx]["clones"][v] then
clones[k] = nil
end
end
end
end
end
pull["color"] = pull["color"] or db.defaultColor
end
MDT:GetCurrentPreset().week = MDT:GetCurrentPreset().week or MDT:GetCurrentAffixWeek()
if db.currentDungeonIdx == 19 then
local englishFaction = UnitFactionGroup("player")
preset.faction = preset.faction or (englishFaction and englishFaction=="Alliance") and 2 or 1
end
if db.currentDungeonIdx == 16 and (not preset.freeholdCrewSelected) then
local week = preset.week
week = week%3
if week == 0 then week = 3 end
preset.freeholdCrew = week
preset.freeholdCrewSelected = true
end
db.MDI = db.MDI or {}
preset.mdi = preset.mdi or {}
preset.mdi.freehold = preset.mdi.freehold or 1
preset.mdi.freeholdJoined = preset.mdi.freeholdJoined or false
preset.mdi.beguiling = preset.mdi.beguiling or 1
preset.difficulty = preset.difficulty or db.currentDifficulty
preset.mdiEnabled = preset.mdiEnabled or db.MDI.enabled
--make sure sublevel actually exists for the dungeon
--this might have been caused by bugged dropdowns in the past
local maxSublevel = -1
for _,_ in pairs(MDT.dungeonMaps[db.currentDungeonIdx]) do
maxSublevel = maxSublevel + 1
end
if preset.value.currentSublevel > maxSublevel then preset.value.currentSublevel = maxSublevel end
--make sure teeeming flag is set
preset.value.teeming = MDT:IsWeekTeeming(preset.week)
end
function MDT:GetTileFormat(dungeonIdx)
local mapInfo = MDT.mapInfo[dungeonIdx]
return mapInfo and mapInfo.tileFormat or 4
end
function MDT:UpdateMap(ignoreSetSelection, ignoreReloadPullButtons, ignoreUpdateProgressBar)
local mapName
local frame = MDT.main_frame
mapName = MDT.dungeonMaps[db.currentDungeonIdx][0]
MDT:EnsureDBTables()
local preset = MDT:GetCurrentPreset()
if preset.difficulty then
db.currentDifficulty = preset.difficulty
frame.sidePanel.DifficultySlider:SetValue(db.currentDifficulty)
frame.sidePanel.difficultyWarning:Toggle(db.currentDifficulty)
end
local fileName = MDT.dungeonMaps[db.currentDungeonIdx][preset.value.currentSublevel]
local path = "Interface\\WorldMap\\"..mapName.."\\"
local tileFormat = MDT:GetTileFormat(db.currentDungeonIdx)
for i=1,12 do
if tileFormat == 4 then
local texName = path..fileName..i
if frame["mapPanelTile"..i] then
frame["mapPanelTile"..i]:SetTexture(texName)
frame["mapPanelTile"..i]:Show()
end
else
if frame["mapPanelTile"..i] then
frame["mapPanelTile"..i]:Hide()
end
end
end
for i=1,10 do
for j=1,15 do
if tileFormat == 15 then
local texName= path..fileName..((i - 1) * 15 + j)
frame["largeMapPanelTile"..i..j]:SetTexture(texName)
frame["largeMapPanelTile"..i..j]:Show()
else
frame["largeMapPanelTile"..i..j]:Hide()
end
end
end
MDT:UpdateDungeonEnemies()
MDT:DungeonEnemies_UpdateTeeming()
MDT:DungeonEnemies_UpdateSeasonalAffix()
MDT:DungeonEnemies_UpdateInspiring()
if not ignoreReloadPullButtons then
MDT:ReloadPullButtons()
end
--handle delete button disable/enable
local presetCount = 0
for k,v in pairs(db.presets[db.currentDungeonIdx]) do
presetCount = presetCount + 1
end
if (db.currentPreset[db.currentDungeonIdx] == 1 or db.currentPreset[db.currentDungeonIdx] == presetCount) or MDT.liveSessionActive then
MDT.main_frame.sidePanelDeleteButton:SetDisabled(true)
MDT.main_frame.sidePanelDeleteButton.text:SetTextColor(0.5,0.5,0.5)
else
MDT.main_frame.sidePanelDeleteButton:SetDisabled(false)
MDT.main_frame.sidePanelDeleteButton.text:SetTextColor(1,0.8196,0)
end
--live mode
local livePreset = MDT:GetCurrentLivePreset()
if MDT.liveSessionActive and preset ~= livePreset then
MDT.main_frame.liveReturnButton:Show()
MDT.main_frame.setLivePresetButton:Show()
else
MDT.main_frame.liveReturnButton:Hide()
MDT.main_frame.setLivePresetButton:Hide()
end
MDT:UpdatePresetDropdownTextColor()
if not ignoreSetSelection then MDT:SetSelectionToPull(preset.value.currentPull) end
MDT:UpdateDungeonDropDown()
--frame.sidePanel.affixDropdown:SetAffixWeek(MDT:GetCurrentPreset().week,ignoreReloadPullButtons,ignoreUpdateProgressBar)
frame.sidePanel.affixDropdown:SetValue(MDT:GetCurrentPreset().week)
MDT:ToggleFreeholdSelector(db.currentDungeonIdx == 16)
MDT:ToggleBoralusSelector(db.currentDungeonIdx == 19)
MDT:DisplayMDISelector()
MDT:DrawAllPresetObjects()
MDT:KillAllAnimatedLines()
MDT:DrawAllAnimatedLines()
end
---UpdateToDungeon
---Updates the map to the specified dungeon
function MDT:UpdateToDungeon(dungeonIdx, ignoreUpdateMap, init)
db.currentExpansion = 1
if dungeonIdx>=15 then db.currentExpansion = 2 end
if dungeonIdx>=29 then db.currentExpansion = 3 end
db.currentDungeonIdx = dungeonIdx
if not db.presets[db.currentDungeonIdx][db.currentPreset[db.currentDungeonIdx]].value.currentSublevel then
db.presets[db.currentDungeonIdx][db.currentPreset[db.currentDungeonIdx]].value.currentSublevel=1
end
if init then return end
MDT:UpdatePresetDropDown()
if not ignoreUpdateMap then MDT:UpdateMap() end
MDT:ZoomMapToDefault()
--Colors the first pull in "Default" presets
if db.currentPreset[db.currentDungeonIdx] == 1 then MDT:ColorPull() end
end
function MDT:DeletePreset(index)
tremove(db.presets[db.currentDungeonIdx],index)
db.currentPreset[db.currentDungeonIdx] = index-1
MDT:UpdatePresetDropDown()
MDT:UpdateMap()
MDT:ZoomMapToDefault()
end
MDT.zoneIdToDungeonIdx = {
[934] = 15,--atal
[935] = 15,--atal
[936] = 16,--fh
[1004] = 17,--kr
[1039] = 18,--shrine
[1040] = 18,--shrine
[1162] = 19,--siege
[1038] = 20,--temple
[1043] = 20,--temple
[1010] = 21,--motherlode
[1041] = 22,--underrot
[1042] = 22,--underrot
[974] = 23,--toldagor
[975] = 23,--toldagor
[976] = 23,--toldagor
[977] = 23,--toldagor
[978] = 23,--toldagor
[979] = 23,--toldagor
[980] = 23,--toldagor
[1015] = 24,--wcm
[1016] = 24,--wcm
[1017] = 24,--wcm
[1018] = 24,--wcm
[1029] = 24,--wcm
[1490] = 25,--lower mecha
[1491] = 26,--upper mecha
[1493] = 26,--upper mecha
[1494] = 26,--upper mecha
[1497] = 26,--upper mecha
[1663] = 30,
[1664] = 30,
[1665] = 30,
[1666] = 35,
[1667] = 35,
[1668] = 35,
[1669] = 31,
[1674] = 32,
[1675] = 33,
[1676] = 33,
[1677] = 29,
[1678] = 29,
[1679] = 29,
[1680] = 29,
[1683] = 36,
[1684] = 36,
[1685] = 36,
[1686] = 36,
[1687] = 36,
[1692] = 34,
[1693] = 34,
[1694] = 34,
[1695] = 34,
[1697] = 32,
}
local lastUpdatedDungeonIdx
function MDT:CheckCurrentZone(init)
local zoneId = C_Map.GetBestMapForUnit("player")
local dungeonIdx = MDT.zoneIdToDungeonIdx[zoneId]
if dungeonIdx and (not lastUpdatedDungeonIdx or dungeonIdx ~= lastUpdatedDungeonIdx) then
lastUpdatedDungeonIdx = dungeonIdx
MDT:UpdateToDungeon(dungeonIdx,nil,init)
end
end
---CountPresets
---Counts the number of presets of the current dungeon
function MDT:CountPresets()
return #db.presets[db.currentDungeonIdx]-2
end
---DeleteAllPresets
---Deletes all presets from the current dungeon
function MDT:DeleteAllPresets()
local countPresets = #db.presets[db.currentDungeonIdx]-1
for i=countPresets,2,-1 do
tremove(db.presets[db.currentDungeonIdx],i)
db.currentPreset[db.currentDungeonIdx] = i-1
end
MDT:UpdatePresetDropDown()
MDT:UpdateMap()
end
function MDT:ClearPreset(preset, silent)
if preset == self:GetCurrentPreset() then silent = false end
table.wipe(preset.value.pulls)
preset.value.currentPull = 1
table.wipe(preset.value.riftOffsets)
--MDT:DeleteAllPresetObjects()
self:EnsureDBTables()
if not silent then
self:UpdateMap()
self:ReloadPullButtons()
end
MDT:ColorPull()
end
function MDT:CreateNewPreset(name)
if name == "<New Preset>" then
MDT.main_frame.presetCreationLabel:SetText(string.format(L["Cannot create preset '%s'"],name))
MDT.main_frame.presetCreationCreateButton:SetDisabled(true)
MDT.main_frame.presetCreationCreateButton.text:SetTextColor(0.5,0.5,0.5)
MDT.main_frame.presetCreationFrame:DoLayout()
return
end
local duplicate = false
local countPresets = 0
for k,v in pairs(db.presets[db.currentDungeonIdx]) do
countPresets = countPresets + 1
if v.text == name then duplicate = true end
end
if duplicate == false then
db.presets[db.currentDungeonIdx][countPresets+1] = db.presets[db.currentDungeonIdx][countPresets] --put <New Preset> at the end of the list
local startingPointPresetIdx = MDT.main_frame.PresetCreationDropDown:GetValue()-1
if startingPointPresetIdx>0 then
db.presets[db.currentDungeonIdx][countPresets] = MDT:CopyObject(db.presets[db.currentDungeonIdx][startingPointPresetIdx])
db.presets[db.currentDungeonIdx][countPresets].text = name
db.presets[db.currentDungeonIdx][countPresets].uid = nil
else
db.presets[db.currentDungeonIdx][countPresets] = {text=name,value={}}
end
db.currentPreset[db.currentDungeonIdx] = countPresets
MDT.main_frame.presetCreationFrame:Hide()
MDT:UpdatePresetDropDown()
MDT:UpdateMap()
MDT:ZoomMapToDefault()
MDT:SetPresetColorPaletteInfo()
MDT:ColorAllPulls()
else
MDT.main_frame.presetCreationLabel:SetText(string.format(L["Preset '%s' already exists"],name))
MDT.main_frame.presetCreationCreateButton:SetDisabled(true)
MDT.main_frame.presetCreationCreateButton.text:SetTextColor(0.5,0.5,0.5)
MDT.main_frame.presetCreationFrame:DoLayout()
end
end
function MDT:SanitizePresetName(text)
--check if name is valid, block button if so, unblock if valid
if text == "<New Preset>" then
return false
else
local duplicate = false
local countPresets = 0
for k,v in pairs(db.presets[db.currentDungeonIdx]) do
countPresets = countPresets + 1
if v.text == text then duplicate = true end
end
return not duplicate and text or false
end
end
function MDT:MakeChatPresetImportFrame(frame)
frame.chatPresetImportFrame = AceGUI:Create("Frame")
local chatImport = frame.chatPresetImportFrame
chatImport:SetTitle(L["Import Preset"])
chatImport:SetWidth(400)
chatImport:SetHeight(100)
chatImport:EnableResize(false)
chatImport:SetLayout("Flow")
chatImport:SetCallback("OnClose", function(widget)
MDT:UpdatePresetDropDown()
if db.currentPreset[db.currentDungeonIdx] ~= 1 then
MDT.main_frame.sidePanelDeleteButton:SetDisabled(false)
MDT.main_frame.sidePanelDeleteButton.text:SetTextColor(1,0.8196,0)
end
end)
chatImport.defaultText = L["Import Preset"]..":\n"
chatImport.importLabel = AceGUI:Create("Label")
chatImport.importLabel:SetText(chatImport.defaultText)
chatImport.importLabel:SetWidth(250)
--chatImport.importLabel:SetColor(1,0,0)
chatImport.importButton = AceGUI:Create("Button")
local importButton = chatImport.importButton
importButton:SetText(L["Import"])
importButton:SetWidth(100)
importButton:SetCallback("OnClick", function()
local newPreset = chatImport.currentPreset
if MDT:ValidateImportPreset(newPreset) then
chatImport:Hide()
MDT:ImportPreset(MDT:DeepCopy(newPreset))
else
print(L["MDT: Error importing preset"])
end
end)
chatImport:AddChild(chatImport.importLabel)
chatImport:AddChild(importButton)
chatImport:Hide()
end
function MDT:OpenChatImportPresetDialog(sender, preset, live)
MDT:HideAllDialogs()
local chatImport = MDT.main_frame.chatPresetImportFrame
chatImport:ClearAllPoints()
chatImport:SetPoint("CENTER", MDT.main_frame,"CENTER",0,50)
chatImport.currentPreset = preset
local dungeon = MDT:GetDungeonName(preset.value.currentDungeonIdx)
local name = preset.text
chatImport:Show()
chatImport.importLabel:SetText(chatImport.defaultText..sender.. ": "..dungeon.." - "..name)
chatImport:SetTitle(L["Import Preset"])
chatImport.importButton:SetText(L["Import"])
chatImport.live = nil
if live then
chatImport.importLabel:SetText(string.format(L["Join Live Session"],"\n",sender,dungeon,name))
chatImport:SetTitle(L["Live Session"])
chatImport.importButton:SetText(L["Join"])
chatImport.live = true
end
end
function MDT:MakePresetImportFrame(frame)
frame.presetImportFrame = AceGUI:Create("Frame")
frame.presetImportFrame:SetTitle(L["Import Preset"])
frame.presetImportFrame:SetWidth(400)
frame.presetImportFrame:SetHeight(200)
frame.presetImportFrame:EnableResize(false)
frame.presetImportFrame:SetLayout("Flow")
frame.presetImportFrame:SetCallback("OnClose", function(widget)
MDT:UpdatePresetDropDown()
if db.currentPreset[db.currentDungeonIdx] ~= 1 then
MDT.main_frame.sidePanelDeleteButton:SetDisabled(false)
MDT.main_frame.sidePanelDeleteButton.text:SetTextColor(1,0.8196,0)
end
end)
frame.presetImportLabel = AceGUI:Create("Label")
frame.presetImportLabel:SetText(nil)
frame.presetImportLabel:SetWidth(390)
frame.presetImportLabel:SetColor(1,0,0)
local importString = ""
frame.presetImportBox = AceGUI:Create("EditBox")
frame.presetImportBox:SetLabel(L["Import Preset"]..":")
frame.presetImportBox:SetWidth(255)
frame.presetImportBox:SetCallback("OnEnterPressed", function(widget, event, text) importString = text end)
frame.presetImportFrame:AddChild(frame.presetImportBox)
local importButton = AceGUI:Create("Button")
importButton:SetText(L["Import"])
importButton:SetWidth(100)
importButton:SetCallback("OnClick", function()
local newPreset = MDT:StringToTable(importString, true)
if MDT:ValidateImportPreset(newPreset) then
MDT.main_frame.presetImportFrame:Hide()
MDT:ImportPreset(newPreset)
if db.colorPaletteInfo.forceColorBlindMode then
MDT:ColorAllPulls()
end
else
frame.presetImportLabel:SetText(L["Invalid import string"])
end
end)
frame.presetImportFrame:AddChild(importButton)
frame.presetImportFrame:AddChild(frame.presetImportLabel)
frame.presetImportFrame:Hide()
end
function MDT:MakePresetCreationFrame(frame)
frame.presetCreationFrame = AceGUI:Create("Frame")
frame.presetCreationFrame:SetTitle(L["New Preset"])
frame.presetCreationFrame:SetWidth(400)
frame.presetCreationFrame:SetHeight(200)
frame.presetCreationFrame:EnableResize(false)
--frame.presetCreationFrame:SetCallback("OnClose", function(widget) AceGUI:Release(widget) end)
frame.presetCreationFrame:SetLayout("Flow")
frame.presetCreationFrame:SetCallback("OnClose", function(widget)
MDT:UpdatePresetDropDown()
if db.currentPreset[db.currentDungeonIdx] ~= 1 then
MDT.main_frame.sidePanelDeleteButton:SetDisabled(false)
MDT.main_frame.sidePanelDeleteButton.text:SetTextColor(1,0.8196,0)
end
end)
frame.PresetCreationEditbox = AceGUI:Create("EditBox")
frame.PresetCreationEditbox:SetLabel(L["Preset Name"]..":")
frame.PresetCreationEditbox:SetWidth(255)
frame.PresetCreationEditbox:SetCallback("OnEnterPressed", function(widget, event, text)
--check if name is valid, block button if so, unblock if valid
if MDT:SanitizePresetName(text) then
frame.presetCreationLabel:SetText(nil)
frame.presetCreationCreateButton:SetDisabled(false)
frame.presetCreationCreateButton.text:SetTextColor(1,0.8196,0)
else
frame.presetCreationLabel:SetText(string.format(L["Cannot create preset '%s'"],text))
frame.presetCreationCreateButton:SetDisabled(true)
frame.presetCreationCreateButton.text:SetTextColor(0.5,0.5,0.5)
end
frame.presetCreationFrame:DoLayout()
end)
frame.presetCreationFrame:AddChild(frame.PresetCreationEditbox)
frame.presetCreationCreateButton = AceGUI:Create("Button")
frame.presetCreationCreateButton:SetText(L["Create"])
frame.presetCreationCreateButton:SetWidth(100)
frame.presetCreationCreateButton:SetCallback("OnClick", function()
local name = frame.PresetCreationEditbox:GetText()
MDT:CreateNewPreset(name)
end)
frame.presetCreationFrame:AddChild(frame.presetCreationCreateButton)
frame.presetCreationLabel = AceGUI:Create("Label")
frame.presetCreationLabel:SetText(nil)
frame.presetCreationLabel:SetWidth(390)
frame.presetCreationLabel:SetColor(1,0,0)
frame.presetCreationFrame:AddChild(frame.presetCreationLabel)
frame.PresetCreationDropDown = AceGUI:Create("Dropdown")
frame.PresetCreationDropDown:SetLabel(L["Use as a starting point:"])
frame.PresetCreationDropDown.text:SetJustifyH("LEFT")
frame.presetCreationFrame:AddChild(frame.PresetCreationDropDown)
frame.presetCreationFrame:Hide()
end
function MDT:ValidateImportPreset(preset)
if type(preset) ~= "table" then return false end
if not preset.text then return false end
if not preset.value then return false end
if type(preset.text) ~= "string" then return false end
if type(preset.value) ~= "table" then return false end
if not preset.value.currentDungeonIdx then return false end
if not preset.value.currentPull then return false end
if not preset.value.currentSublevel then return false end
if not preset.value.pulls then return false end
if type(preset.value.pulls) ~= "table" then return false end
return true
end
function MDT:ImportPreset(preset, fromLiveSession)
--change dungeon to dungeon of the new preset
self:UpdateToDungeon(preset.value.currentDungeonIdx,true)
local mdiEnabled = preset.mdiEnabled
--search for uid
local updateIndex
local duplicatePreset
for k,v in pairs(db.presets[db.currentDungeonIdx]) do
if v.uid and v.uid == preset.uid then
updateIndex = k
duplicatePreset = v
break
end
end
local updateCallback = function()
if self.main_frame.ConfirmationFrame then
self.main_frame.ConfirmationFrame:SetCallback("OnClose", function() end)
end
db.MDI.enabled = mdiEnabled
db.presets[db.currentDungeonIdx][updateIndex] = preset
db.currentPreset[db.currentDungeonIdx] = updateIndex
self.liveUpdateFrameOpen = nil
self:UpdatePresetDropDown()
self:UpdateMap()
if fromLiveSession then
self.main_frame.SendingStatusBar:Hide()
if self.main_frame.LoadingSpinner then
self.main_frame.LoadingSpinner:Hide()
self.main_frame.LoadingSpinner.Anim:Stop()
end
end
end
local copyCallback = function()
if self.main_frame.ConfirmationFrame then
self.main_frame.ConfirmationFrame:SetCallback("OnClose", function() end)
end
db.MDI.enabled = mdiEnabled
local name = preset.text
local num = 2
for k,v in pairs(db.presets[db.currentDungeonIdx]) do
if name == v.text then
name = preset.text.." "..num
num = num + 1
end
end
preset.text = name
if fromLiveSession then
if duplicatePreset then duplicatePreset.uid = nil end
else
preset.uid = nil
end
local countPresets = 0
for k,v in pairs(db.presets[db.currentDungeonIdx]) do
countPresets = countPresets + 1
end
db.presets[db.currentDungeonIdx][countPresets+1] = db.presets[db.currentDungeonIdx][countPresets] --put <New Preset> at the end of the list
db.presets[db.currentDungeonIdx][countPresets] = preset
db.currentPreset[db.currentDungeonIdx] = countPresets
self.liveUpdateFrameOpen = nil
self:UpdatePresetDropDown()
self:UpdateMap()
if fromLiveSession then
self.main_frame.SendingStatusBar:Hide()
if self.main_frame.LoadingSpinner then
self.main_frame.LoadingSpinner:Hide()
self.main_frame.LoadingSpinner.Anim:Stop()
end
end
end
local closeCallback = function()
self.liveUpdateFrameOpen = nil
self:LiveSession_Disable()
self.main_frame.ConfirmationFrame:SetCallback("OnClose", function() end)
if fromLiveSession then
self.main_frame.SendingStatusBar:Hide()
if self.main_frame.LoadingSpinner then
self.main_frame.LoadingSpinner:Hide()
self.main_frame.LoadingSpinner.Anim:Stop()
end
end
end
--open dialog to ask for replacing
if updateIndex then
local prompt = string.format(L["Earlier Version"],duplicatePreset.text,"\n","\n","\n","\n")
self:OpenConfirmationFrame(450,150,L["Import Preset"],L["Update"],prompt, updateCallback,L["Copy"],copyCallback)
if fromLiveSession then
self.liveUpdateFrameOpen = true
self.main_frame.ConfirmationFrame:SetCallback("OnClose", function()closeCallback() end)
end
else
copyCallback()
end
end
---Stores r g b values for coloring pulls with MDT:ColorPull()
local colorPaletteValues = {
[1] = { --Rainbow values
[1] = {[1]=0.2446, [2]=1, [3]=0.2446},
[2] = {[1]=0.2446, [2]=1, [3]=0.6223},
[3] = {[1]=0.2446, [2]=1, [3]=1},
[4] = {[1]=0.2446, [2]=0.6223, [3]=1},
[5] = {[1]=0.2446, [2]=0.2446, [3]=1},
[6] = {[1]=0.6223, [2]=0.6223, [3]=1},
[7] = {[1]=1, [2]=0.2446, [3]=1},
[8] = {[1]=1, [2]=0.2446, [3]=0.6223},
[9] = {[1]=1, [2]=0.2446, [3]=0.2446},
[10] = {[1]=1, [2]=0.60971, [3]=0.2446},
[11] = {[1]=1, [2]=0.98741, [3]=0.2446},
[12] = {[1]=0.63489, [2]=1, [3]=0.2446},
--[13] = {[1]=1, [2]=0.2446, [3]=0.54676},
--[14] = {[1]=1, [2]=0.2446, [3]=0.32014},
--[15] = {[1]=1, [2]=0.38309, [3]=0.2446},
--[16] = {[1]=1, [2]=0.60971, [3]=0.2446},
--[17] = {[1]=1, [2]=0.83633, [3]=0.2446},
--[18] = {[1]=0.93705, [2]=1, [3]=0.2446},
--[19] = {[1]=0.71043, [2]=1, [3]=0.2446},
--[20] = {[1]=0.48381, [2]=1, [3]=0.2446},
},
[2] = { --Black and Yellow values
[1] = {[1]=0.4, [2]=0.4, [3]=0.4},
[2] = {[1]=1, [2]=1, [3]=0.0},
},
[3] = { --Red, Green and Blue values
[1] = {[1]=0.85882, [2]=0.058824, [3]=0.15294},
[2] = {[1]=0.49804, [2]=1.0, [3]=0.0},
[3] = {[1]=0.0, [2]=0.50196, [3]=1.0},
},
[4] = { --High Contrast values
[1] = {[1]=1, [2]=0.2446, [3]=1},
[2] = {[1]=0.2446, [2]=1, [3]=0.6223},
[3] = {[1]=1, [2]=0.2446, [3]=0.2446},
[4] = {[1]=0.2446, [2]=0.6223, [3]=1},
[5] = {[1]=1, [2]=0.98741, [3]=0.2446},
[6] = {[1]=0.2446, [2]=1, [3]=0.2446},
[7] = {[1]=1, [2]=0.2446, [3]=0.6223},
[8] = {[1]=0.2446, [2]=1, [3]=1},
[9] = {[1]=1, [2]=0.60971, [3]=0.2446},
[10] = {[1]=0.2446, [2]=0.2446, [3]=1},
[11] = {[1]=0.63489, [2]=1, [3]=0.2446},
},
[5] = { --Color Blind Friendly values (Based on IBM's color library "Color blind safe"
[1] = {[1]=0.39215686274509803, [2]=0.5607843137254902, [3]=1.0},
--[2] = {[1]=0.47058823529411764, [2]=0.3686274509803922, [3]=0.9411764705882353},
[2] = {[1]=0.8627450980392157, [2]=0.14901960784313725, [3]=0.4980392156862745},
[3] = {[1]=0.996078431372549, [2]=0.3803921568627451, [3]=0.0},
[4] = {[1]=1.0, [2]=0.6901960784313725, [3]=0.0},
},
}
---Dropdown menu items for color settings frame
local colorPaletteNames = {
[1] = L["Rainbow"],
[2] = L["Black and Yellow"],
[3] = L["Red, Green and Blue"],
[4] = L["High Contrast"],
[5] = L["Color Blind Friendly"],
[6] = L["Custom"],
}
---SetPresetColorPaletteInfo
---Saves currently selected automatic coloring settings to the current
---This can be achieved easier, but it will increase the export text length significantly for non custom palettes.
function MDT:SetPresetColorPaletteInfo()
local preset = MDT:GetCurrentPreset()
preset.colorPaletteInfo = {}
preset.colorPaletteInfo.autoColoring = db.colorPaletteInfo.autoColoring
if preset.colorPaletteInfo.autoColoring then
preset.colorPaletteInfo.colorPaletteIdx = db.colorPaletteInfo.colorPaletteIdx
if preset.colorPaletteInfo.colorPaletteIdx == 6 then
preset.colorPaletteInfo.customPaletteValues = db.colorPaletteInfo.customPaletteValues
preset.colorPaletteInfo.numberCustomColors = db.colorPaletteInfo.numberCustomColors
end
end
--Code below works, but in most cases it saves more data to the preset and thereby significantly increases the export string length
--MDT:GetCurrentPreset().colorPaletteInfo = db.colorPaletteInfo
end
---GetPresetColorPaletteInfo
function MDT:GetPresetColorPaletteInfo(preset)
preset = preset or MDT:GetCurrentPreset()
return preset.colorPaletteInfo
end
---ColorPull
---Function executes full coloring of a pull and it's blips
function MDT:ColorPull(colorValues, pullIdx, preset, bypass, exportColorBlind) -- bypass can be passed as true to color even when automatic coloring is toggled off
local colorPaletteInfo = MDT:GetPresetColorPaletteInfo(preset)
local pullIdx = pullIdx or MDT:GetCurrentPull()
if(pullIdx) then
local colorValues
local numberColors
local r,g,b
if colorPaletteInfo.autoColoring or bypass == true then
--Force color blind mode locally, will not alter the color values saved to a preset
if db.colorPaletteInfo.forceColorBlindMode == true and not exportColorBlind then
--Local color blind mode, will not alter the colorPaletteInfo saved to a preset
colorValues = colorValues or colorPaletteValues[colorValues] or colorPaletteValues[5]
numberColors = #colorValues
else
--Regular coloring
colorValues = colorValues or colorPaletteValues[colorValues] or colorPaletteInfo.colorPaletteIdx == 6 and colorPaletteInfo.customPaletteValues or colorPaletteValues[colorPaletteInfo.colorPaletteIdx]
numberColors = colorPaletteInfo.colorPaletteIdx == 6 and colorPaletteInfo.numberCustomColors or #colorValues -- tables must start from 1 and have no blank rows
end
local colorIdx = (pullIdx-1)%numberColors+1
r,g,b = colorValues[colorIdx][1],colorValues[colorIdx][2],colorValues[colorIdx][3]
MDT:DungeonEnemies_SetPullColor(pullIdx,r,g,b)
MDT:UpdatePullButtonColor(pullIdx,r,g,b)
MDT:DungeonEnemies_UpdateBlipColors(pullIdx,r,g,b)
end
end
end
---ColorAllPulls
---Loops over all pulls in a preset and colors them
function MDT:ColorAllPulls(colorValues, startFrom, bypass, exportColorBlind)
local preset = self:GetCurrentPreset()
local startFrom = startFrom or 0
for pullIdx,_ in pairs(preset.value.pulls) do
if pullIdx >= startFrom then
MDT:ColorPull(colorValues, pullIdx, preset, bypass, exportColorBlind)
end
end
end
---MakeCustomColorFrame
---creates frame housing settings for user customized color palette
function MDT:MakeCustomColorFrame(frame)
--Base frame for custom palette setup
frame.CustomColorFrame = AceGUI:Create("Frame")
frame.CustomColorFrame:SetTitle(L["Custom Color Palette"])
frame.CustomColorFrame:SetWidth(290)
frame.CustomColorFrame:SetHeight(220)
frame.CustomColorFrame:EnableResize(false)
frame.CustomColorFrame:SetLayout("Flow")
frame:AddChild(frame.CustomColorFrame)
--Slider to adjust number of different colors and remake the frame OnMouseUp
frame.CustomColorFrame.ColorSlider = AceGUI:Create("Slider")
frame.CustomColorFrame.ColorSlider:SetSliderValues(2,20,1)
frame.CustomColorFrame.ColorSlider:SetValue(db.colorPaletteInfo.numberCustomColors)
frame.CustomColorFrame.ColorSlider:SetLabel(L["Choose number of colors"])
frame.CustomColorFrame.ColorSlider:SetRelativeWidth(1)
frame.CustomColorFrame.ColorSlider:SetCallback("OnMouseUp", function(event, callbackName, value)
if value>20 then
db.colorPaletteInfo.numberCustomColors = 20
elseif value<2 then
db.colorPaletteInfo.numberCustomColors = 2
else
db.colorPaletteInfo.numberCustomColors = value
end
MDT:SetPresetColorPaletteInfo()
MDT:ColorAllPulls()
MDT:DrawAllHulls()
frame.CustomColorFrame:ReleaseChildren()
frame.CustomColorFrame:Release()
MDT:MakeCustomColorFrame(frame)
MDT:OpenCustomColorsDialog()
end)
frame.CustomColorFrame:AddChild(frame.CustomColorFrame.ColorSlider)
--Loop to create as many colorpickers as requested limited by db.colorPaletteInfo.numberCustomColors
local ColorPicker = {}
for i= 1,db.colorPaletteInfo.numberCustomColors do
ColorPicker[i] = AceGUI:Create("ColorPicker")
if db.colorPaletteInfo.customPaletteValues[i] then
ColorPicker[i]:SetColor(db.colorPaletteInfo.customPaletteValues[i][1], db.colorPaletteInfo.customPaletteValues[i][2], db.colorPaletteInfo.customPaletteValues[i][3])
else
db.colorPaletteInfo.customPaletteValues[i] = {1,1,1}
ColorPicker[i]:SetColor(db.colorPaletteInfo.customPaletteValues[i][1], db.colorPaletteInfo.customPaletteValues[i][2], db.colorPaletteInfo.customPaletteValues[i][3])
end
ColorPicker[i]:SetLabel(" "..i)
ColorPicker[i]:SetRelativeWidth(0.25)
ColorPicker[i]:SetHeight(15)
ColorPicker[i]:SetCallback("OnValueConfirmed", function(widget, event, r, g, b)
db.colorPaletteInfo.customPaletteValues[i] = {r,g,b}
MDT:SetPresetColorPaletteInfo()
MDT:ColorAllPulls()
MDT:DrawAllHulls()
end)
frame.CustomColorFrame:AddChild(ColorPicker[i])
end
frame.CustomColorFrame:Hide()
end
function MDT:MakeAutomaticColorsFrame(frame)
frame.automaticColorsFrame = AceGUI:Create("Frame")
frame.automaticColorsFrame:SetTitle(L["Automatic Coloring"])
frame.automaticColorsFrame:SetWidth(240)
frame.automaticColorsFrame:SetHeight(220)
frame.automaticColorsFrame:EnableResize(false)
frame.automaticColorsFrame:SetLayout("Flow")
frame.AutomaticColorsCheck = AceGUI:Create("CheckBox")
frame.AutomaticColorsCheck:SetLabel(L["Automatically color pulls"])
frame.AutomaticColorsCheck:SetValue(db.colorPaletteInfo.autoColoring)
frame.AutomaticColorsCheck:SetCallback("OnValueChanged",function(widget,callbackName,value)
db.colorPaletteInfo.autoColoring = value
MDT:SetPresetColorPaletteInfo()
frame.AutomaticColorsCheckSidePanel:SetValue(db.colorPaletteInfo.autoColoring)
if value == true then
frame.toggleForceColorBlindMode:SetDisabled(false)
MDT:ColorAllPulls()
MDT:DrawAllHulls()
MDT.main_frame.AutomaticColorsCogwheel:SetImage("Interface\\AddOns\\MythicDungeonTools\\Textures\\helpIconRnbw")
else
frame.toggleForceColorBlindMode:SetDisabled(true)
MDT.main_frame.AutomaticColorsCogwheel:SetImage("Interface\\AddOns\\MythicDungeonTools\\Textures\\helpIconGrey")
end
end)
frame.automaticColorsFrame:AddChild(frame.AutomaticColorsCheck)
--Toggle local color blind mode
frame.toggleForceColorBlindMode = AceGUI:Create("CheckBox")
frame.toggleForceColorBlindMode:SetLabel(L["Local color blind mode"])
frame.toggleForceColorBlindMode:SetValue(db.colorPaletteInfo.forceColorBlindMode)
frame.toggleForceColorBlindMode:SetCallback("OnValueChanged",function(widget,callbackName,value)
db.colorPaletteInfo.forceColorBlindMode = value
MDT:SetPresetColorPaletteInfo()
MDT:ColorAllPulls()
MDT:DrawAllHulls()
end)
frame.automaticColorsFrame:AddChild(frame.toggleForceColorBlindMode)
frame.PaletteSelectDropdown = AceGUI:Create("Dropdown")
frame.PaletteSelectDropdown:SetList(colorPaletteNames)
frame.PaletteSelectDropdown:SetLabel(L["Choose preferred color palette"])
frame.PaletteSelectDropdown:SetValue(db.colorPaletteInfo.colorPaletteIdx)
frame.PaletteSelectDropdown:SetCallback("OnValueChanged", function(widget,callbackName,value)
if value == 6 then
db.colorPaletteInfo.colorPaletteIdx = value
MDT:OpenCustomColorsDialog()
else
MDT.main_frame.automaticColorsFrame.CustomColorFrame:Hide()
db.colorPaletteInfo.colorPaletteIdx = value
end
MDT:SetPresetColorPaletteInfo()
MDT:ColorAllPulls()
MDT:DrawAllHulls()
end)
frame.automaticColorsFrame:AddChild(frame.PaletteSelectDropdown)
-- The reason this button exists is to allow altering colorPaletteInfo of an imported preset
-- Without the need to untoggle/toggle or swap back and forth in the PaletteSelectDropdown
frame.button = AceGUI:Create("Button")
frame.button:SetText(L["Apply to preset"])
frame.button:SetCallback("OnClick", function(widget, callbackName)
if not db.colorPaletteInfo.autoColoring then
db.colorPaletteInfo.autoColoring = true
frame.AutomaticColorsCheck:SetValue(db.colorPaletteInfo.autoColoring)
frame.AutomaticColorsCheckSidePanel:SetValue(db.colorPaletteInfo.autoColoring)
MDT.main_frame.AutomaticColorsCogwheel:SetImage("Interface\\AddOns\\MythicDungeonTools\\Textures\\helpIconRnbw")
frame.toggleForceColorBlindMode:SetDisabled(false)
end
MDT:SetPresetColorPaletteInfo()
MDT:ColorAllPulls()
MDT:DrawAllHulls()
end)
frame.automaticColorsFrame:AddChild(frame.button)
frame.automaticColorsFrame:Hide()
end
function MDT:MakePullSelectionButtons(frame)
frame.PullButtonScrollGroup = AceGUI:Create("SimpleGroup")
frame.PullButtonScrollGroup:SetWidth(248)
frame.PullButtonScrollGroup:SetHeight(410)
frame.PullButtonScrollGroup:SetPoint("TOPLEFT",frame.WidgetGroup.frame,"BOTTOMLEFT",-4,-32)
frame.PullButtonScrollGroup:SetPoint("BOTTOMLEFT",frame,"BOTTOMLEFT",0,30)
frame.PullButtonScrollGroup:SetLayout("Fill")
frame.PullButtonScrollGroup.frame:SetFrameStrata(mainFrameStrata)
if not frame.PullButtonScrollGroup.frame.SetBackdrop then
Mixin(frame.PullButtonScrollGroup.frame, BackdropTemplateMixin)
end
frame.PullButtonScrollGroup.frame:SetBackdropColor(1,1,1,0)
frame.PullButtonScrollGroup.frame:Show()
self:FixAceGUIShowHide(frame.PullButtonScrollGroup)
frame.pullButtonsScrollFrame = AceGUI:Create("ScrollFrame")
frame.pullButtonsScrollFrame:SetLayout("Flow")
frame.PullButtonScrollGroup:AddChild(frame.pullButtonsScrollFrame)
frame.newPullButtons = {}
--rightclick context menu
frame.optionsDropDown = LibDD:Create_UIDropDownMenu("PullButtonsOptionsDropDown", nil)
end
function MDT:PresetsAddPull(index, data, preset)
preset = preset or self:GetCurrentPreset()
if not data then data = {} end
if index then
tinsert(preset.value.pulls,index,data)
else
tinsert(preset.value.pulls,data)
end
self:EnsureDBTables()
end
---Merges a list of pulls and inserts them at a specified destination.
---
---@param pulls table List of all pull indices, that shall be merged (and deleted). If pulls
--- is a number, then the pull list is automatically generated from pulls
--- and destination.
---@param destination number The pull index, where the merged pull shall be inserted.
---
---@author Dradux
function MDT:PresetsMergePulls(pulls, destination)
if type(pulls) == "number" then
pulls = {pulls, destination}
end
if not destination then
destination = pulls[#pulls]
end
local count_if = self.U.count_if
local newPull = {}
local removed_pulls = {}
for _, pullIdx in ipairs(pulls) do
local offset = count_if(removed_pulls, function(entry)
return entry < pullIdx
end)
local index = pullIdx - offset
local pull = self:GetCurrentPreset().value.pulls[index]
for enemyIdx,clones in pairs(pull) do
if string.match(enemyIdx, "^%d+$") then
-- it's really an enemy index
if tonumber(enemyIdx) then
if not newPull[enemyIdx] then
newPull[enemyIdx] = clones
else
for k,v in pairs(clones) do
if newPull[enemyIdx][k] ~= nil then
local newIndex = #newPull[enemyIdx] + 1
newPull[enemyIdx][newIndex] = v
else
newPull[enemyIdx][k] = v
end
end
end
end
else
-- it's another pull option like color
local optionName = enemyIdx
local optionValue = clones
newPull[optionName] = optionValue
end
end
self:PresetsDeletePull(index)
tinsert(removed_pulls, pullIdx)
end
local offset = count_if(removed_pulls, function(entry)
return entry < destination
end)
local index = destination - offset
self:PresetsAddPull(index, newPull)
return index
end
function MDT:PresetsDeletePull(p, preset)
preset = preset or self:GetCurrentPreset()
if p == preset.value.currentPull then
preset.value.currentPull = math.max(p - 1, 1)
end
tremove(preset.value.pulls,p)
end
function MDT:GetPulls(preset)
preset = preset or self:GetCurrentPreset()
return preset.value.pulls
end
function MDT:GetPullsNum(preset)
preset = preset or self:GetCurrentPreset()
return table.getn(preset.value.pulls)
end
function MDT:CopyObject(obj, seen)
if type(obj) ~= 'table' then return obj end
if seen and seen[obj] then return seen[obj] end
local s = seen or {}
local res = setmetatable({}, getmetatable(obj))
s[obj] = res
for k, v in pairs(obj) do res[self:CopyObject(k, s)] = self:CopyObject(v, s) end
return res
end
function MDT:PresetsSwapPulls(p1, p2)
local p1copy = self:CopyObject(self:GetCurrentPreset().value.pulls[p1])
local p2copy = self:CopyObject(self:GetCurrentPreset().value.pulls[p2])
self:GetCurrentPreset().value.pulls[p1] = p2copy
self:GetCurrentPreset().value.pulls[p2] = p1copy
end
function MDT:SetMapSublevel(pull)
--set map sublevel
local shouldResetZoom = false
local lastSubLevel
for enemyIdx,clones in pairs(db.presets[db.currentDungeonIdx][db.currentPreset[db.currentDungeonIdx]].value.pulls[pull]) do
if tonumber(enemyIdx) then
for idx,cloneIdx in pairs(clones) do
if MDT.dungeonEnemies[db.currentDungeonIdx][enemyIdx]["clones"][cloneIdx] then
lastSubLevel = MDT.dungeonEnemies[db.currentDungeonIdx][enemyIdx]["clones"][cloneIdx].sublevel
end
end
end
end
if lastSubLevel then
shouldResetZoom = db.presets[db.currentDungeonIdx][db.currentPreset[db.currentDungeonIdx]].value.currentSublevel ~= lastSubLevel
db.presets[db.currentDungeonIdx][db.currentPreset[db.currentDungeonIdx]].value.currentSublevel = lastSubLevel
if shouldResetZoom then
MDT:UpdateMap(true,true,true)
end
end
MDT:UpdateDungeonDropDown()
if shouldResetZoom then MDT:ZoomMapToDefault() end
end
function MDT:SetSelectionToPull(pull)
--if pull is not specified set pull to last pull in preset (for adding new pulls)
if not pull then
local count = 0
for k,v in pairs(MDT:GetCurrentPreset().value.pulls) do
count = count + 1
end
pull = count
end
--SaveCurrentPresetPull
if type(pull) == "number" and pull > 0 then
MDT:GetCurrentPreset().value.currentPull = pull
MDT:GetCurrentPreset().value.selection = { pull }
MDT:PickPullButton(pull)
MDT:DungeonEnemies_UpdateSelected(pull)
elseif type(pull) == "table" then
MDT:GetCurrentPreset().value.currentPull = pull[#pull]
MDT:GetCurrentPreset().value.selection = pull
MDT:ClearPullButtonPicks()
for _, pullIdx in ipairs(MDT:GetSelection()) do
MDT:PickPullButton(pullIdx, true)
MDT:DungeonEnemies_UpdateSelected(pullIdx)
end
end
end
---UpdatePullButtonNPCData
---Updates the portraits display of a button to show which and how many npcs are selected
function MDT:UpdatePullButtonNPCData(idx)
if db.devMode then return end
local preset = MDT:GetCurrentPreset()
local frame = MDT.main_frame.sidePanel
local enemyTable = {}
if preset.value.pulls[idx] then
local enemyTableIdx = 0
for enemyIdx,clones in pairs(preset.value.pulls[idx]) do
if tonumber(enemyIdx) then
--check if enemy exists, remove if not
if MDT.dungeonEnemies[db.currentDungeonIdx][enemyIdx] then
local incremented = false
local npcId = MDT.dungeonEnemies[db.currentDungeonIdx][enemyIdx]["id"]
local name = MDT.dungeonEnemies[db.currentDungeonIdx][enemyIdx]["name"]
local creatureType = MDT.dungeonEnemies[db.currentDungeonIdx][enemyIdx]["creatureType"]
local level = MDT.dungeonEnemies[db.currentDungeonIdx][enemyIdx]["level"]
local baseHealth = MDT.dungeonEnemies[db.currentDungeonIdx][enemyIdx]["health"]
for k,cloneIdx in pairs(clones) do
--check if clone exists, remove if not
if MDT.dungeonEnemies[db.currentDungeonIdx][enemyIdx]["clones"][cloneIdx] then
if self:IsCloneIncluded(enemyIdx,cloneIdx) then
if not incremented then enemyTableIdx = enemyTableIdx + 1 incremented = true end
if not enemyTable[enemyTableIdx] then enemyTable[enemyTableIdx] = {} end
enemyTable[enemyTableIdx].quantity = enemyTable[enemyTableIdx].quantity or 0
enemyTable[enemyTableIdx].npcId = npcId
enemyTable[enemyTableIdx].count = MDT.dungeonEnemies[db.currentDungeonIdx][enemyIdx]["count"]
enemyTable[enemyTableIdx].teemingCount = MDT.dungeonEnemies[db.currentDungeonIdx][enemyIdx]["teemingCount"]
enemyTable[enemyTableIdx].displayId = MDT.dungeonEnemies[db.currentDungeonIdx][enemyIdx]["displayId"]
enemyTable[enemyTableIdx].quantity = enemyTable[enemyTableIdx].quantity + 1
enemyTable[enemyTableIdx].name = name
enemyTable[enemyTableIdx].level = level
enemyTable[enemyTableIdx].creatureType = creatureType
enemyTable[enemyTableIdx].baseHealth = baseHealth
enemyTable[enemyTableIdx].ignoreFortified = MDT.dungeonEnemies[db.currentDungeonIdx][enemyIdx]["ignoreFortified"]
end
end
end
end
end
end
end
frame.newPullButtons[idx]:SetNPCData(enemyTable)
if db.MDI.enabled and preset.mdi.beguiling == 13 then end
--display reaping icon
local pullForces = MDT:CountForces(idx,false)
local totalForcesMax = MDT:IsCurrentPresetTeeming() and MDT.dungeonTotalCount[db.currentDungeonIdx].teeming or MDT.dungeonTotalCount[db.currentDungeonIdx].normal
local currentPercent = pullForces/totalForcesMax
local oldPullForces
if idx == 1 then
oldPullForces = 0
else
oldPullForces = MDT:CountForces(idx-1,false)
end
local oldPercent = oldPullForces/totalForcesMax
if (math.floor(currentPercent/0.2)>math.floor(oldPercent/0.2)) and oldPercent<1 and db.MDI.enabled and preset.mdi.beguiling == 13 then
frame.newPullButtons[idx]:ShowReapingIcon(true,currentPercent,oldPercent)
else
frame.newPullButtons[idx]:ShowReapingIcon(false,currentPercent,oldPercent)
end
--prideful icon
if (math.floor(currentPercent/0.2)>math.floor(oldPercent/0.2)) and oldPercent<1 and db.currentSeason == 5 then
frame.newPullButtons[idx]:ShowPridefulIcon(true,currentPercent,oldPercent)
else
frame.newPullButtons[idx]:ShowPridefulIcon(false,currentPercent,oldPercent)
end
--count per health
if pullForces>0 then
frame.newPullButtons[idx]:ShowCountPerHealth(true,pullForces,totalForcesMax)
else
frame.newPullButtons[idx]:ShowCountPerHealth(true,pullForces,totalForcesMax)
end
end
---ReloadPullButtons
---Reloads all pull buttons in the scroll frame
function MDT:ReloadPullButtons()
local frame = MDT.main_frame.sidePanel
if not frame.pullButtonsScrollFrame then return end
local preset = db.presets[db.currentDungeonIdx][db.currentPreset[db.currentDungeonIdx]]
--store scroll value
local oldScrollValue = frame.pullButtonsScrollFrame.localstatus.scrollvalue
--first release all children of the scroll frame
frame.pullButtonsScrollFrame:ReleaseChildren()
local maxPulls = 0
for k,v in pairs(preset.value.pulls) do
maxPulls = maxPulls + 1
end
--add new children to the scrollFrame, the frames are from the widget pool so no memory is wasted
local idx = 0
for k,pull in ipairs(preset.value.pulls) do
idx = idx+1
frame.newPullButtons[idx] = AceGUI:Create("MDTPullButton")
frame.newPullButtons[idx]:SetMaxPulls(maxPulls)
frame.newPullButtons[idx]:SetIndex(idx)
MDT:UpdatePullButtonNPCData(idx)
frame.newPullButtons[idx]:Initialize()
frame.newPullButtons[idx]:Enable()
frame.pullButtonsScrollFrame:AddChild(frame.newPullButtons[idx])
end
--add the "new pull" button
frame.newPullButton = AceGUI:Create("MDTNewPullButton")
frame.newPullButton:Initialize()
frame.newPullButton:Enable()
frame.pullButtonsScrollFrame:AddChild(frame.newPullButton)
--set the scroll value back to the old value
frame.pullButtonsScrollFrame.scrollframe.obj:SetScroll(oldScrollValue)
frame.pullButtonsScrollFrame.scrollframe.obj:FixScroll()
if self:GetCurrentPreset().value.currentPull then
self:PickPullButton(self:GetCurrentPreset().value.currentPull)
end
end
---ClearPullButtonPicks
---Deselects all pull buttons
function MDT:ClearPullButtonPicks()
local frame = MDT.main_frame.sidePanel
for k,v in pairs(frame.newPullButtons) do
v:ClearPick()
end
end
---PickPullButton
---Selects the current pull button and deselects all other buttons
function MDT:PickPullButton(idx, keepPicked)
if db.devMode then return end
if not keepPicked then
MDT:ClearPullButtonPicks()
end
local frame = MDT.main_frame.sidePanel
frame.newPullButtons[idx]:Pick()
end
---AddPull
---Creates a new pull in the current preset and calls ReloadPullButtons to reflect the change in the scrollframe
function MDT:AddPull(index)
MDT:PresetsAddPull(index)
MDT:ReloadPullButtons()
MDT:SetSelectionToPull(index)
MDT:ColorPull()
MDT:DrawAllHulls()
end
function MDT:SetAutomaticColor(index)
--if not db.colorPaletteInfo.autoColoring then return end
local H = (index - 1) * 360 / 12 + 120 --db.automaticColorsNum
--if db.alternatingColors and index % 2 == 0 then
-- H = H + 180
--end
local V = 1--0.5451
--if db.brightColors then V = 1 end
local r, g, b = self:HSVtoRGB(H, 0.7554, V)
--self:DungeonEnemies_SetPullColor(index, r, g, b)
--self:UpdatePullButtonColor(index, r, g, b)
--self:DungeonEnemies_UpdateBlipColors(index, r, g, b)
--if self.liveSessionActive and self:GetCurrentPreset().uid == self.livePresetUID then
-- self:LiveSession_QueueColorUpdate()
--end
end
function MDT:UpdateAutomaticColors(index)
if not db.colorPaletteInfo.autoColoring then return end
for i = index or 1, self:GetPullsNum() do
self:SetAutomaticColor(i)
end
end
---Clears all the npcs out of a pull
function MDT:ClearPull(index)
table.wipe(db.presets[db.currentDungeonIdx][db.currentPreset[db.currentDungeonIdx]].value.pulls[index])
MDT:EnsureDBTables()
MDT:ReloadPullButtons()
MDT:SetSelectionToPull(index)
MDT:ColorPull()
MDT:DrawAllHulls()
--MDT:SetAutomaticColor(index)
end
---Moves the selected pull up
function MDT:MovePullUp(index)
MDT:PresetsSwapPulls(index,index-1)
MDT:ReloadPullButtons()
MDT:SetSelectionToPull(index-1)
MDT:ColorAllPulls(_, index-1)
MDT:DrawAllHulls()
--MDT:UpdateAutomaticColors(index - 1)
end
---Moves the selected pull down
function MDT:MovePullDown(index)
MDT:PresetsSwapPulls(index,index+1)
MDT:ReloadPullButtons()
MDT:SetSelectionToPull(index+1)
MDT:ColorAllPulls(_, index)
MDT:DrawAllHulls()
--MDT:UpdateAutomaticColors(index)
end
---Deletes the selected pull and makes sure that a pull will be selected afterwards
function MDT:DeletePull(index)
local pulls = self:GetPulls()
if #pulls == 1 then return end
self:PresetsDeletePull(index)
self:ReloadPullButtons()
local pullCount = 0
for k,v in pairs(pulls) do
pullCount = pullCount + 1
end
if index>pullCount then index = pullCount end
self:SetSelectionToPull(index)
--self:UpdateAutomaticColors(index)
self:ColorAllPulls(_, index-1)
MDT:DrawAllHulls()
end
---RenamePreset
function MDT:RenamePreset(renameText)
db.presets[db.currentDungeonIdx][db.currentPreset[db.currentDungeonIdx]].text = renameText
MDT.main_frame.RenameFrame:Hide()
MDT:UpdatePresetDropDown()
end
---GetFirstNotSelectedPullButton
function MDT:GetFirstNotSelectedPullButton(start, direction)
if not direction then
direction = -1
elseif direction == "UP" then
direction = -1
elseif direction == "DOWN" then
direction = 1
end
local pullIdx = start
while MDT.U.contains(MDT:GetCurrentPreset().value.selection, pullIdx)
and MDT.U.isInRange(pullIdx, 1, #MDT:GetCurrentPreset().value.pulls) do
pullIdx = pullIdx + direction
end
if not MDT.U.isInRange(pullIdx, 1, #MDT:GetCurrentPreset().value.pulls) then
return
end
return pullIdx
end
function MDT:MakeRenameFrame(frame)
frame.RenameFrame = AceGUI:Create("Frame")
frame.RenameFrame:SetTitle(L["Rename Preset"])
frame.RenameFrame:SetWidth(350)
frame.RenameFrame:SetHeight(150)
frame.RenameFrame:EnableResize(false)
frame.RenameFrame:SetLayout("Flow")
frame.RenameFrame:SetCallback("OnClose", function(widget)
end)
frame.RenameFrame:Hide()
local renameText
frame.RenameFrame.Editbox = AceGUI:Create("EditBox")
frame.RenameFrame.Editbox:SetLabel(L["Preset Name"]..":")
frame.RenameFrame.Editbox:SetWidth(200)
frame.RenameFrame.Editbox:SetCallback("OnEnterPressed", function(...)
local widget, event, text = ...
--check if name is valid, block button if so, unblock if valid
if MDT:SanitizePresetName(text) then
frame.RenameFrame.PresetRenameLabel:SetText(nil)
frame.RenameFrame.RenameButton:SetDisabled(false)
frame.RenameFrame.RenameButton.text:SetTextColor(1,0.8196,0)
renameText = text
else
frame.RenameFrame.PresetRenameLabel:SetText(string.format(L["Cannot rename preset to '%s'"],text))
frame.RenameFrame.RenameButton:SetDisabled(true)
frame.RenameFrame.RenameButton.text:SetTextColor(0.5,0.5,0.5)
renameText = nil
end
frame.presetCreationFrame:DoLayout()
end)
frame.RenameFrame:AddChild(frame.RenameFrame.Editbox)
frame.RenameFrame.RenameButton = AceGUI:Create("Button")
frame.RenameFrame.RenameButton:SetText(L["Rename"])
frame.RenameFrame.RenameButton:SetWidth(100)
frame.RenameFrame.RenameButton:SetCallback("OnClick",function() MDT:RenamePreset(renameText) end)
frame.RenameFrame:AddChild(frame.RenameFrame.RenameButton)
frame.RenameFrame.PresetRenameLabel = AceGUI:Create("Label")
frame.RenameFrame.PresetRenameLabel:SetText(nil)
frame.RenameFrame.PresetRenameLabel:SetWidth(390)
frame.RenameFrame.PresetRenameLabel:SetColor(1,0,0)
frame.RenameFrame:AddChild(frame.RenameFrame.PresetRenameLabel)
end
---MakeExportFrame
---Creates the frame used to export presets to a string which can be uploaded to text sharing websites like pastebin
function MDT:MakeExportFrame(frame)
frame.ExportFrame = AceGUI:Create("Frame")
frame.ExportFrame:SetTitle(L["Preset Export"])
frame.ExportFrame:SetWidth(600)
frame.ExportFrame:SetHeight(400)
frame.ExportFrame:EnableResize(false)
frame.ExportFrame:SetLayout("Flow")
frame.ExportFrame:SetCallback("OnClose", function(widget)
end)
frame.ExportFrameEditbox = AceGUI:Create("MultiLineEditBox")
frame.ExportFrameEditbox:SetWidth(600)
frame.ExportFrameEditbox:DisableButton(true)
frame.ExportFrameEditbox:SetNumLines(20)
frame.ExportFrameEditbox:SetCallback("OnEnterPressed", function(widget, event, text)
end)
frame.ExportFrame:AddChild(frame.ExportFrameEditbox)
--frame.presetCreationFrame:SetStatusText("AceGUI-3.0 Example Container Frame")
frame.ExportFrame:Hide()
end
---MakeDeleteConfirmationFrame
---Creates the delete confirmation dialog that pops up when a user wants to delete a preset
function MDT:MakeDeleteConfirmationFrame(frame)
frame.DeleteConfirmationFrame = AceGUI:Create("Frame")
frame.DeleteConfirmationFrame:SetTitle(L["Delete Preset"])
frame.DeleteConfirmationFrame:SetWidth(250)
frame.DeleteConfirmationFrame:SetHeight(120)
frame.DeleteConfirmationFrame:EnableResize(false)
frame.DeleteConfirmationFrame:SetLayout("Flow")
frame.DeleteConfirmationFrame:SetCallback("OnClose", function(widget)
end)
frame.DeleteConfirmationFrame.label = AceGUI:Create("Label")
frame.DeleteConfirmationFrame.label:SetWidth(390)
frame.DeleteConfirmationFrame.label:SetHeight(10)
--frame.DeleteConfirmationFrame.label:SetColor(1,0,0)
frame.DeleteConfirmationFrame:AddChild(frame.DeleteConfirmationFrame.label)
frame.DeleteConfirmationFrame.OkayButton = AceGUI:Create("Button")
frame.DeleteConfirmationFrame.OkayButton:SetText(L["Delete"])
frame.DeleteConfirmationFrame.OkayButton:SetWidth(100)
frame.DeleteConfirmationFrame.OkayButton:SetCallback("OnClick",function()
MDT:DeletePreset(db.currentPreset[db.currentDungeonIdx])
frame.DeleteConfirmationFrame:Hide()
end)
frame.DeleteConfirmationFrame.CancelButton = AceGUI:Create("Button")
frame.DeleteConfirmationFrame.CancelButton:SetText(L["Cancel"])
frame.DeleteConfirmationFrame.CancelButton:SetWidth(100)
frame.DeleteConfirmationFrame.CancelButton:SetCallback("OnClick",function()
frame.DeleteConfirmationFrame:Hide()
end)
frame.DeleteConfirmationFrame:AddChild(frame.DeleteConfirmationFrame.OkayButton)
frame.DeleteConfirmationFrame:AddChild(frame.DeleteConfirmationFrame.CancelButton)
frame.DeleteConfirmationFrame:Hide()
end
---MakeClearConfirmationFrame
---Creates the clear confirmation dialog that pops up when a user wants to clear a preset
function MDT:MakeClearConfirmationFrame(frame)
frame.ClearConfirmationFrame = AceGUI:Create("Frame")
frame.ClearConfirmationFrame:SetTitle(L["Reset Preset"])
frame.ClearConfirmationFrame:SetWidth(250)
frame.ClearConfirmationFrame:SetHeight(120)
frame.ClearConfirmationFrame:EnableResize(false)
frame.ClearConfirmationFrame:SetLayout("Flow")
frame.ClearConfirmationFrame:SetCallback("OnClose", function(widget)
end)
frame.ClearConfirmationFrame.label = AceGUI:Create("Label")
frame.ClearConfirmationFrame.label:SetWidth(390)
frame.ClearConfirmationFrame.label:SetHeight(10)
--frame.DeleteConfirmationFrame.label:SetColor(1,0,0)
frame.ClearConfirmationFrame:AddChild(frame.ClearConfirmationFrame.label)
frame.ClearConfirmationFrame.OkayButton = AceGUI:Create("Button")
frame.ClearConfirmationFrame.OkayButton:SetText(L["Reset"])
frame.ClearConfirmationFrame.OkayButton:SetWidth(100)
frame.ClearConfirmationFrame.OkayButton:SetCallback("OnClick",function()
self:ClearPreset(self:GetCurrentPreset())
if self.liveSessionActive and self:GetCurrentPreset().uid == self.livePresetUID then MDT:LiveSession_SendCommand("clear") end
frame.ClearConfirmationFrame:Hide()
end)
frame.ClearConfirmationFrame.CancelButton = AceGUI:Create("Button")
frame.ClearConfirmationFrame.CancelButton:SetText(L["Cancel"])
frame.ClearConfirmationFrame.CancelButton:SetWidth(100)
frame.ClearConfirmationFrame.CancelButton:SetCallback("OnClick",function()
frame.ClearConfirmationFrame:Hide()
end)
frame.ClearConfirmationFrame:AddChild(frame.ClearConfirmationFrame.OkayButton)
frame.ClearConfirmationFrame:AddChild(frame.ClearConfirmationFrame.CancelButton)
frame.ClearConfirmationFrame:Hide()
end
---OpenConfirmationFrame
---Creates a generic dialog that pops up when a user wants needs confirmation for an action
function MDT:OpenConfirmationFrame(width, height, title, buttonText, prompt, callback, buttonText2, callback2)
local f = MDT.main_frame.ConfirmationFrame
if not f then
MDT.main_frame.ConfirmationFrame = AceGUI:Create("Frame")
f = MDT.main_frame.ConfirmationFrame
f:EnableResize(false)
f:SetLayout("Flow")
f:SetCallback("OnClose", function(widget) end)
f.label = AceGUI:Create("Label")
f.label:SetWidth(390)
f.label:SetHeight(height-20)
f:AddChild(f.label)
f.OkayButton = AceGUI:Create("Button")
f.OkayButton:SetWidth(100)
f:AddChild(f.OkayButton)
f.CancelButton = AceGUI:Create("Button")
f.CancelButton:SetText(L["Cancel"])
f.CancelButton:SetWidth(100)
f.CancelButton:SetCallback("OnClick",function()
MDT:HideAllDialogs()
end)
f:AddChild(f.CancelButton)
end
f:SetWidth(width or 250)
f:SetHeight(height or 120)
f:SetTitle(title)
f.OkayButton:SetText(buttonText)
f.OkayButton:SetCallback("OnClick",function()callback()
MDT:HideAllDialogs() end)
if buttonText2 then
f.CancelButton:SetText(buttonText2) else
f.CancelButton:SetText(L["Cancel"])
end
if callback2 then
f.CancelButton:SetCallback("OnClick",function()callback2()
MDT:HideAllDialogs() end)
else
f.CancelButton:SetCallback("OnClick",function()
MDT:HideAllDialogs() end)
end
MDT:HideAllDialogs()
f:ClearAllPoints()
f:SetPoint("CENTER", MDT.main_frame,"CENTER",0,50)
f.label:SetText(prompt)
f:Show()
end
---CreateTutorialButton
---Creates the tutorial button and sets up the help plate frames
function MDT:CreateTutorialButton(parent)
local scale = self:GetScale()
local sidePanelHeight = MDT.main_frame.sidePanel.PullButtonScrollGroup.frame:GetHeight()
local helpPlate = {
FramePos = { x = 0, y = 0 },
FrameSize = { width = sizex, height = sizey },
[1] = { ButtonPos = { x = 205, y = 0 }, HighLightBox = { x = 0, y = 0, width = 200, height = 56 }, ToolTipDir = "RIGHT", ToolTipText = L["helpPlateDungeonSelect"] },
[2] = { ButtonPos = { x = 205, y = -210*scale }, HighLightBox = { x = 0, y = -58, width = (sizex-6)*scale, height = (sizey*scale)-58 }, ToolTipDir = "RIGHT", ToolTipText = string.format(L["helpPlateNPC"],"\n","\n") },
[3] = { ButtonPos = { x = 900*scale, y = 0*scale }, HighLightBox = { x = 838*scale, y = 30, width = 251, height = 115 }, ToolTipDir = "LEFT", ToolTipText = L["helpPlatePresets"] },
[4] = { ButtonPos = { x = 900*scale, y = -87*scale }, HighLightBox = { x = 838*scale, y = 30-115, width = 251, height = 102 }, ToolTipDir = "LEFT", ToolTipText = L["helpPlateDungeon"] },
[5] = { ButtonPos = { x = 900*scale, y = -(115+102*scale) }, HighLightBox = { x = 838*scale, y = (30-(115+102)), width = 251, height = (sidePanelHeight)+43 }, ToolTipDir = "LEFT", ToolTipText = string.format(L["helpPlatePulls"],"\n") },
}
if not parent.HelpButton then
parent.HelpButton = CreateFrame("Button","MDTMainHelpPlateButton",parent,"MainHelpPlateButton")
parent.HelpButton:ClearAllPoints()
parent.HelpButton:SetPoint("TOPLEFT",parent,"TOPLEFT",0,48)
parent.HelpButton:SetScale(0.8)
parent.HelpButton:SetFrameStrata(mainFrameStrata)
parent.HelpButton:SetFrameLevel(6)
parent.HelpButton:Hide()
--hook to make button hide
local originalHide = parent.Hide
function parent:Hide(...)
parent.HelpButton:Hide()
return originalHide(self, ...)
end
local function TutorialButtonOnHide(self)
HelpPlate_Hide(true)
end
parent.HelpButton:SetScript("OnHide",TutorialButtonOnHide)
end
local function TutorialButtonOnClick(self)
if not HelpPlate_IsShowing(helpPlate) then
HelpPlate_Show(helpPlate, MDT.main_frame, self)
else
HelpPlate_Hide(true)
end
end
parent.HelpButton:SetScript("OnClick",TutorialButtonOnClick)
end
---RegisterOptions
---Register the options of the addon to the blizzard options
function MDT:RegisterOptions()
MDT.blizzardOptionsMenuTable = {
name = "Mythic Dungeon Tools",
type = 'group',
args = {
--[[
language = {
type = 'select',
style = 'dropdown',
name = "Language",
desc = "Sets the Language of the AddOn. Requires Reload to take effect",
values = {
[1] = "English",
[2] = "Deutsch",
[3] = "Español (esES)",
[4] = "Español (esMX)",
[5] = "Français",
[6] = "Italiano",
[7] = "Português Brasileiro",
[8] = "Русский",
[9] = "한국어",
[10] = "简体中文 (zhCN)",
[11] = "國語 (zhTW)",
},
get = function() return db.language end,
set = function(_, newValue)
db.language = newValue
end,
},
]]
enable = {
type = 'toggle',
name = L["Enable Minimap Button"],
desc = L["If the Minimap Button is enabled"],
get = function() return not db.minimap.hide end,
set = function(_, newValue)
db.minimap.hide = not newValue
if not db.minimap.hide then
icon:Show("MythicDungeonTools")
else
icon:Hide("MythicDungeonTools")
end
end,
order = 1,
width = "full",
},
tooltipSelect ={
type = 'select',
name = L["Choose NPC tooltip position"],
values = {
[1] = L["Next to the NPC"],
[2] = L["In the bottom right corner"],
},
get = function() return db.tooltipInCorner and 2 or 1 end,
set = function(_,newValue)
if newValue == 1 then db.tooltipInCorner = false end
if newValue == 2 then db.tooltipInCorner = true end
end,
style = 'dropdown',
},
enemyForcesFormat = {
type = "select",
name = L["Choose Enemy Forces Format"],
values = {
[1] = L["Forces only: 5/200"],
[2] = L["Forces+%: 5/200 (2.5%)"],
},
get = function() return db.enemyForcesFormat end,
set = function(_,newValue) db.enemyForcesFormat = newValue end,
style = "dropdown",
},
enemyStyle = {
type = "select",
name = L["Choose Enemy Style. Requires Reload"],
values = {
[1] = L["Portrait"],
[2] = L["Plain Texture"],
},
get = function() return db.enemyStyle end,
set = function(_,newValue) db.enemyStyle = newValue end,
style = "dropdown",
},
}
}
LibStub("AceConfigRegistry-3.0"):RegisterOptionsTable("MythicDungeonTools", MDT.blizzardOptionsMenuTable)
self.blizzardOptionsMenu = LibStub("AceConfigDialog-3.0"):AddToBlizOptions("MythicDungeonTools", "MythicDungeonTools")
end
function MDT:Round(number, decimals)
return (("%%.%df"):format(decimals)):format(number)
end
function MDT:RGBToHex(r, g, b)
r = r*255
g = g*255
b = b*255
return ("%.2x%.2x%.2x"):format(r, g, b)
end
function MDT:HexToRGB(rgb)
if string.len(rgb) == 6 then
local r, g, b
r, g, b = tonumber('0x'..strsub(rgb, 0, 2)), tonumber('0x'..strsub(rgb, 3, 4)), tonumber('0x'..strsub(rgb, 5, 6))
if not r then r = 0 else r = r/255 end
if not g then g = 0 else g = g/255 end
if not b then b = 0 else b = b/255 end
return r,g,b
else
return
end
end
---https://en.wikipedia.org/wiki/HSL_and_HSV#HSV_to_RGB_alternative
function MDT:HSVtoRGB(H, S, V)
H = H % 361
local function f(n)
k = (n + H/60) % 6
return V - V * S * math.max(math.min(k, 4 - k, 1), 0)
end
return f(5), f(3), f(1)
end
function MDT:DeepCopy(orig)
local orig_type = type(orig)
local copy
if orig_type == 'table' then
copy = {}
for orig_key, orig_value in next, orig, nil do
copy[MDT:DeepCopy(orig_key)] = MDT:DeepCopy(orig_value)
end
setmetatable(copy, MDT:DeepCopy(getmetatable(orig)))
else -- number, string, boolean, etc
copy = orig
end
return copy
end
---scale if preset comes from live session
function MDT:StorePresetObject(obj, ignoreScale, preset)
--adjust scale
if not ignoreScale then
local scale = self:GetScale()
if obj.n then
obj.d[1] = obj.d[1]*(1/scale)
obj.d[2] = obj.d[2]*(1/scale)
else
for idx,coord in pairs(obj.l) do
obj.l[idx] = self:Round(obj.l[idx]*(1/scale),1)
end
end
end
preset = preset or self:GetCurrentPreset()
preset.objects = preset.objects or {}
--we insert the object infront of the first hidden oject
local pos = 1
for k,v in ipairs(preset.objects) do
pos = pos + 1
if v.d[4]==false then
pos = pos - 1
end
end
if pos>1 then
tinsert(preset.objects,pos,self:DeepCopy(obj))
else
tinsert(preset.objects,self:DeepCopy(obj))
end
end
---excluding notes, these are handled in OverrideScrollFrameScripts
function MDT:UpdatePresetObjectOffsets(idx, x, y, preset, silent)
--adjust coords to scale
local scale = self:GetScale()
x = self:Round(x*(1/scale),1)
y = self:Round(y*(1/scale),1)
preset = preset or self:GetCurrentPreset()
for objectIndex,obj in pairs(preset.objects) do
if objectIndex == idx then
for coordIdx,coord in pairs(obj.l) do
if coordIdx%2==1 then
obj.l[coordIdx] = coord-x
else
obj.l[coordIdx] = coord-y
end
end
end
end
--redraw everything
if not silent then self:DrawAllPresetObjects() end
end
---Draws all Preset objects on the map canvas/sublevel
function MDT:DrawAllPresetObjects()
self:ReleaseAllActiveTextures()
local scale = self:GetScale()
local currentPreset = self:GetCurrentPreset()
local currentSublevel = self:GetCurrentSubLevel()
currentPreset.objects = currentPreset.objects or {}
for objectIndex,obj in pairs(currentPreset.objects) do
self:DrawPresetObject(obj,objectIndex,scale,currentPreset,currentSublevel)
end
end
---Draws specific preset object
function MDT:DrawPresetObject(obj, objectIndex, scale, currentPreset, currentSublevel)
if not objectIndex then
for oIndex,o in pairs(currentPreset.objects) do
if o == obj then
objectIndex = oIndex
break
end
end
end
--d: size,lineFactor,sublevel,shown,colorstring,drawLayer,[smooth]
--l: x1,y1,x2,y2,...
local color = {}
if obj.d[3] == currentSublevel and obj.d[4] then
if obj.n then
local x = obj.d[1]*scale
local y = obj.d[2]*scale
local text = obj.d[5]
self:DrawNote(x,y,text,objectIndex)
else
obj.d[1] = obj.d[1] or 5
color.r,color.g,color.b = self:HexToRGB(obj.d[5])
--lines
local x1,y1,x2,y2
local lastx,lasty
for _,coord in pairs(obj.l) do
if not x1 then x1 = coord
elseif not y1 then y1 = coord
elseif not x2 then
x2 = coord
lastx = coord
elseif not y2 then
y2 = coord
lasty = coord
end
if x1 and y1 and x2 and y2 then
x1 = x1*scale
x2 = x2*scale
y1 = y1*scale
y2 = y2*scale
self:DrawLine(x1,y1,x2,y2,obj.d[1]*0.3*scale,color,obj.d[7],nil,obj.d[6],obj.d[2],nil,objectIndex)
--circles if smooth
if obj.d[7] then
self:DrawCircle(x1,y1,obj.d[1]*0.3*scale,color,nil,obj.d[6],nil,objectIndex)
self:DrawCircle(x2,y2,obj.d[1]*0.3*scale,color,nil,obj.d[6],nil,objectIndex)
end
x1,y1,x2,y2 = nil,nil,nil,nil
end
end
--triangle
if obj.t and lastx and lasty then
lastx = lastx*scale
lasty = lasty*scale
self:DrawTriangle(lastx,lasty,obj.t[1],obj.d[1]*scale,color,nil,obj.d[6],nil,objectIndex)
end
--remove empty objects leftover from erasing
if obj.l then
local lineCount = 0
for _,_ in pairs(obj.l) do
lineCount = lineCount +1
end
if lineCount == 0 then
currentPreset.objects[objectIndex] = nil
end
end
end
end
end
---DeletePresetObjects
---Deletes objects from the current preset in the current sublevel
function MDT:DeletePresetObjects(preset, silent)
preset = preset or self:GetCurrentPreset()
if preset == self:GetCurrentPreset() then silent = false end
local currentSublevel = self:GetCurrentSubLevel()
for objectIndex,obj in pairs(preset.objects) do
if obj.d[3] == currentSublevel then
preset.objects[objectIndex] = nil
end
end
if not silent then self:DrawAllPresetObjects() end
end
---StepBack
---Undo the latest drawing
function MDT:PresetObjectStepBack(preset, silent)
preset = preset or self:GetCurrentPreset()
if preset == self:GetCurrentPreset() then silent = false end
preset.objects = preset.objects or {}
local length = 0
for k,v in pairs(preset.objects) do
length = length + 1
end
if length>0 then
for i = length,1,-1 do
if preset.objects[i] and preset.objects[i].d[4] then
preset.objects[i].d[4] = false
if not silent then self:DrawAllPresetObjects() end
break
end
end
end
end
---StepForward
---Redo the latest drawing
function MDT:PresetObjectStepForward(preset, silent)
preset = preset or MDT:GetCurrentPreset()
if preset == self:GetCurrentPreset() then silent = false end
preset.objects = preset.objects or {}
local length = 0
for k,v in ipairs(preset.objects) do
length = length + 1
end
if length>0 then
for i = 1,length do
if preset.objects[i] and not preset.objects[i].d[4] then
preset.objects[i].d[4] = true
if not silent then self:DrawAllPresetObjects() end
break
end
end
end
end
function MDT:FixAceGUIShowHide(widget, frame, isFrame, hideOnly)
frame = frame or MDT.main_frame
local originalShow,originalHide = frame.Show,frame.Hide
if not isFrame then
widget = widget.frame
end
function frame:Hide(...)
widget:Hide()
return originalHide(self, ...)
end
if hideOnly then return end
function frame:Show(...)
widget:Show()
return originalShow(self, ...)
end
end
function MDT:GetCurrentAffixWeek()
if not IsAddOnLoaded("Blizzard_ChallengesUI") then
LoadAddOn("Blizzard_ChallengesUI")
end
C_MythicPlus.RequestCurrentAffixes()
C_MythicPlus.RequestMapInfo()
C_MythicPlus.RequestRewards()
local affixIds = C_MythicPlus.GetCurrentAffixes() --table
if not affixIds then return end
if not affixIds[1] then return 1 end
for week,affixes in ipairs(affixWeeks) do
if affixes[1] == affixIds[2].id and affixes[2] == affixIds[3].id and affixes[3] == affixIds[1].id then
return week
end
end
return 1
end
---PrintCurrentAffixes
---Helper function to print out current affixes with their ids and their names
function MDT:PrintCurrentAffixes()
--run this once so blizz stuff is loaded
MDT:GetCurrentAffixWeek()
--https://www.wowhead.com/affixes
local affixNames = {
[1] =L["Overflowing"],
[2] =L["Skittish"],
[3] =L["Volcanic"],
[4] =L["Necrotic"],
[5] =L["Teeming"],
[6] =L["Raging"],
[7] =L["Bolstering"],
[8] =L["Sanguine"],
[9] =L["Tyrannical"],
[10] =L["Fortified"],
[11] =L["Bursting"],
[12] =L["Grievous"],
[13] =L["Explosive"],
[14] =L["Quaking"],
[15] =L["Relentless"],
[16] =L["Infested"],
[117] =L["Reaping"],
[119] =L["Beguiling"],
[120] =L["Awakened"],
[121] =L["Prideful"],
[122] =L["Inspiring"],
[123] =L["Spiteful"],
[124] =L["Storming"],
[128] =L["Tormented"],
}
local affixIds = C_MythicPlus.GetCurrentAffixes()
for idx,data in ipairs(affixIds) do
print(data.id,affixNames[data.id])
end
end
---IsPlayerInGroup
---Checks if the players is in a group/raid and returns the type
function MDT:IsPlayerInGroup()
local inGroup = (UnitInRaid("player") and "RAID") or (IsInGroup() and "PARTY")
return inGroup
end
function MDT:ResetMainFramePos(soft)
--soft reset just redraws the window with existing coordinates from db
local f = self.main_frame
if not soft then
db.nonFullscreenScale = 1
db.maximized = false
if not framesInitialized then initFrames() end
f.maximizeButton:Minimize()
db.xoffset = 0
db.yoffset = -150
db.anchorFrom = "TOP"
db.anchorTo = "TOP"
end
f:ClearAllPoints()
f:SetPoint(db.anchorTo, UIParent,db.anchorFrom, db.xoffset, db.yoffset)
end
function MDT:DropIndicator()
local indicator = MDT.main_frame.drop_indicator
if not indicator then
indicator = CreateFrame("Frame", "MDT_DropIndicator")
indicator:SetHeight(4)
indicator:SetFrameStrata("FULLSCREEN")
local texture = indicator:CreateTexture(nil, "FULLSCREEN")
texture:SetBlendMode("ADD")
texture:SetAllPoints(indicator)
texture:SetTexture("Interface\\PaperDollInfoFrame\\UI-Character-Tab-Highlight")
local icon = indicator:CreateTexture(nil, "OVERLAY")
icon:ClearAllPoints()
icon:SetSize(16, 16)
icon:SetPoint("CENTER", indicator)
indicator.icon = icon
indicator.texture = texture
MDT.main_frame.drop_indicator = indicator
indicator:Hide()
end
return indicator
end
function MDT:IsShown_DropIndicator()
local indicator = MDT:DropIndicator()
return indicator:IsShown()
end
function MDT:Show_DropIndicator(target, pos)
local indicator = MDT:DropIndicator()
indicator:ClearAllPoints()
if pos == "TOP" then
indicator:SetPoint("BOTTOMLEFT", target.frame, "TOPLEFT", 0, -1)
indicator:SetPoint("BOTTOMRIGHT", target.frame, "TOPRIGHT", 0, -1)
indicator:Show()
elseif pos == "BOTTOM" then
indicator:SetPoint("TOPLEFT", target.frame, "BOTTOMLEFT", 0, 1)
indicator:SetPoint("TOPRIGHT", target.frame, "BOTTOMRIGHT", 0, 1)
indicator:Show()
end
end
function MDT:Hide_DropIndicator()
local indicator = MDT:DropIndicator()
indicator:Hide()
end
function MDT:GetSelection()
if not MDT:GetCurrentPreset().value.selection or #MDT:GetCurrentPreset().value.selection == 0 then
MDT:GetCurrentPreset().value.selection = { MDT:GetCurrentPreset().value.currentPull }
end
return MDT:GetCurrentPreset().value.selection
end
function MDT:GetScrollingAmount(scrollFrame, pixelPerSecond)
local viewheight = scrollFrame.frame.obj.content:GetHeight()
return (pixelPerSecond / viewheight) * 1000
end
function MDT:ScrollToPull(pullIdx)
-- Get scroll frame
local scrollFrame = MDT.main_frame.sidePanel.pullButtonsScrollFrame
-- Get amount of total pulls plus the extra button "+ Add Pull"
local pulls = #MDT:GetCurrentPreset().value.pulls + 1 or 1
local percentage = pullIdx / pulls
local value = percentage * 1000
scrollFrame:SetScroll(value)
scrollFrame:FixScroll()
end
function MDT:CopyPullOptions(sourceIdx, destinationIdx)
local preset = MDT:GetCurrentPreset()
local pulls = preset.value.pulls
local source = pulls[sourceIdx]
local destination = pulls[destinationIdx]
if source and destination then
for optionName, optionValue in pairs(source) do
-- Assure, that it is an option and not an enemy index
if not string.match(optionName, "^%d+$") then
destination[optionName] = optionValue
end
end
end
end
function MDT:GetPullButton(pullIdx)
local frame = MDT.main_frame.sidePanel
return frame.newPullButtons[pullIdx]
end
function MDT:UpdatePullButtonColor(pullIdx, r, g, b)
local button = MDT:GetPullButton(pullIdx)
local function updateSwatch(t)
for k,v in pairs(t) do
if v.hasColorSwatch then
v.r,v.g,v.b = r,g,b
return
end
end
end
button.color.r, button.color.g, button.color.b = r, g, b
updateSwatch(button.menu)
updateSwatch(button.multiselectMenu)
button:UpdateColor()
end
--/run MDT:ResetDataCache();
function MDT:ResetDataCache()
db.dungeonEnemies = nil
db.mapPOIs = nil
ReloadUI()
end
function MDT:HardReset()
MythicDungeonToolsDB = nil
ReloadUI()
end
function initFrames()
local main_frame = CreateFrame("frame", "MDTFrame", UIParent)
tinsert(UISpecialFrames,"MDTFrame")
--cache dungeon data to not lose data during reloads
if db.devMode then
if db.dungeonEnemies then
MDT.dungeonEnemies = db.dungeonEnemies
else
db.dungeonEnemies = MDT.dungeonEnemies
end
if db.mapPOIs then
MDT.mapPOIs = db.mapPOIs
else
db.mapPOIs = MDT.mapPOIs
end
end
db.nonFullscreenScale = db.nonFullscreenScale or 1
if not db.maximized then db.scale = db.nonFullscreenScale end
main_frame:SetFrameStrata(mainFrameStrata)
main_frame:SetFrameLevel(1)
main_frame.background = main_frame:CreateTexture(nil, "BACKGROUND")
main_frame.background:SetAllPoints()
main_frame.background:SetDrawLayer(canvasDrawLayer, 1)
main_frame.background:SetColorTexture(unpack(MDT.BackdropColor))
main_frame.background:SetAlpha(0.2)
main_frame:SetSize(sizex*db.scale, sizey*db.scale)
main_frame:SetResizable(true)
main_frame:SetMinResize(sizex*0.75,sizey*0.75)
local _,_,fullscreenScale = MDT:GetFullScreenSizes()
main_frame:SetMaxResize(sizex*fullscreenScale,sizey*fullscreenScale)
MDT.main_frame = main_frame
main_frame.mainFrametex = main_frame:CreateTexture(nil, "BACKGROUND")
main_frame.mainFrametex:SetAllPoints()
main_frame.mainFrametex:SetDrawLayer(canvasDrawLayer, -5)
main_frame.mainFrametex:SetColorTexture(unpack(MDT.BackdropColor))
local version = GetAddOnMetadata(AddonName, "Version"):gsub("%.","")
db.version = tonumber(version)
-- Set frame position
main_frame:ClearAllPoints()
main_frame:SetPoint(db.anchorTo, UIParent,db.anchorFrom, db.xoffset, db.yoffset)
main_frame.contextDropdown = LibDD:Create_UIDropDownMenu("MDTContextDropDown", nil)
MDT:CheckCurrentZone(true)
MDT:EnsureDBTables()
MDT:MakeTopBottomTextures(main_frame)
MDT:MakeMapTexture(main_frame)
MDT:MakeSidePanel(main_frame)
MDT:CreateMenu()
MDT:MakePresetCreationFrame(main_frame)
MDT:MakePresetImportFrame(main_frame)
MDT:DungeonEnemies_CreateFramePools()
--MDT:UpdateDungeonEnemies(main_frame)
MDT:CreateDungeonSelectDropdown(main_frame)
MDT:MakePullSelectionButtons(main_frame.sidePanel)
MDT:MakeExportFrame(main_frame)
MDT:MakeRenameFrame(main_frame)
MDT:MakeDeleteConfirmationFrame(main_frame)
MDT:MakeClearConfirmationFrame(main_frame)
MDT:CreateTutorialButton(main_frame)
MDT:POI_CreateFramePools()
MDT:MakeChatPresetImportFrame(main_frame)
MDT:MakeSendingStatusBar(main_frame)
MDT:MakeAutomaticColorsFrame(main_frame)
MDT:MakeCustomColorFrame(main_frame.automaticColorsFrame)
--devMode
if db.devMode and MDT.CreateDevPanel then
MDT:CreateDevPanel(MDT.main_frame)
end
if not db.MDI.enabled then
db.currentSeason = defaultSavedVars.global.currentSeason
end
--ElvUI skinning
local skinTooltip = function(tooltip)
if IsAddOnLoaded("ElvUI") and ElvUI[1].Tooltip then
local borderTextures = {"BorderBottom","BorderBottomLeft","BorderBottomRight","BorderLeft","BorderRight","BorderTop","BorderTopLeft","BorderTopRight"}
for k,v in pairs(borderTextures) do
tooltip[v]:Kill()
end
tooltip.Background:Kill()
if not tooltip.SetBackdrop then
Mixin(tooltip, BackdropTemplateMixin)
end
tooltip:HookScript("OnShow",function(self)
if self:IsForbidden() then return end
self:SetTemplate("Transparent", nil, true) --ignore updates
local r, g, b = self:GetBackdropColor()
self:SetBackdropColor(r, g, b, ElvUI[1].Tooltip.db.colorAlpha)
end)
if tooltip.String then tooltip.String:SetFont(tooltip.String:GetFont(),11) end
if tooltip.topString then tooltip.topString:SetFont(tooltip.topString:GetFont(),11) end
if tooltip.botString then tooltip.botString:SetFont(tooltip.botString:GetFont(),11) end
end
end
--tooltip new
do
MDT.tooltip = CreateFrame("Frame", "MDTModelTooltip", UIParent, "TooltipBorderedFrameTemplate")
local tooltip = MDT.tooltip
tooltip:SetClampedToScreen(true)
tooltip:SetFrameStrata("TOOLTIP")
tooltip.mySizes ={x=290,y=120}
tooltip:SetSize(tooltip.mySizes.x, tooltip.mySizes.y)
tooltip.Model = CreateFrame("PlayerModel", nil, tooltip)
tooltip.Model:SetFrameLevel(1)
tooltip.Model:SetSize(100,100)
tooltip.Model.fac = 0
tooltip.Model:SetScript("OnUpdate",function (self,elapsed)
self.fac = self.fac + 0.5
if self.fac >= 360 then
self.fac = 0
end
self:SetFacing(PI*2 / 360 * self.fac)
end)
tooltip.Model:SetPoint("TOPLEFT", tooltip, "TOPLEFT",7,-7)
tooltip.String = tooltip:CreateFontString("MDTToolTipString")
tooltip.String:SetFontObject("GameFontNormalSmall")
tooltip.String:SetFont(tooltip.String:GetFont(),10)
tooltip.String:SetTextColor(1, 1, 1, 1)
tooltip.String:SetJustifyH("LEFT")
--tooltip.String:SetJustifyV("CENTER")
tooltip.String:SetWidth(tooltip:GetWidth())
tooltip.String:SetHeight(90)
tooltip.String:SetWidth(175)
tooltip.String:SetText(" ")
tooltip.String:SetPoint("TOPLEFT", tooltip, "TOPLEFT", 110, -10)
tooltip.String:Show()
skinTooltip(tooltip)
end
--pullTooltip
do
MDT.pullTooltip = CreateFrame("Frame", "MDTPullTooltip", UIParent, "TooltipBorderedFrameTemplate")
--MDT.pullTooltip:SetOwner(UIParent, "ANCHOR_NONE")
local pullTT = MDT.pullTooltip
MDT.pullTooltip:SetClampedToScreen(true)
MDT.pullTooltip:SetFrameStrata("TOOLTIP")
MDT.pullTooltip.myHeight = 160
MDT.pullTooltip:SetSize(250, MDT.pullTooltip.myHeight)
MDT.pullTooltip.Model = CreateFrame("PlayerModel", nil, MDT.pullTooltip)
MDT.pullTooltip.Model:SetFrameLevel(1)
MDT.pullTooltip.Model.fac = 0
if true then
MDT.pullTooltip.Model:SetScript("OnUpdate",function (self, elapsed)
self.fac = self.fac + 0.5
if self.fac >= 360 then
self.fac = 0
end
self:SetFacing(PI*2 / 360 * self.fac)
end)
else
MDT.pullTooltip.Model:SetPortraitZoom(1)
MDT.pullTooltip.Model:SetFacing(PI*2 / 360 * 2)
end
MDT.pullTooltip.Model:SetSize(110,110)
MDT.pullTooltip.Model:SetPoint("TOPLEFT", MDT.pullTooltip, "TOPLEFT",7,-7)
MDT.pullTooltip.topString = MDT.pullTooltip:CreateFontString("MDTToolTipString")
MDT.pullTooltip.topString:SetFontObject("GameFontNormalSmall")
MDT.pullTooltip.topString:SetFont(MDT.pullTooltip.topString:GetFont(),10)
MDT.pullTooltip.topString:SetTextColor(1, 1, 1, 1)
MDT.pullTooltip.topString:SetJustifyH("LEFT")
MDT.pullTooltip.topString:SetJustifyV("TOP")
MDT.pullTooltip.topString:SetHeight(110)
MDT.pullTooltip.topString:SetWidth(130)
MDT.pullTooltip.topString:SetPoint("TOPLEFT", MDT.pullTooltip, "TOPLEFT", 110, -7)
MDT.pullTooltip.topString:Hide()
local heading = MDT.pullTooltip:CreateTexture(nil, "TOOLTIP")
heading:SetHeight(8)
heading:SetPoint("LEFT", 12, -30)
heading:SetPoint("RIGHT", MDT.pullTooltip, "RIGHT", -12, -30)
heading:SetTexture("Interface\\Tooltips\\UI-Tooltip-Border")
heading:SetTexCoord(0.81, 0.94, 0.5, 1)
heading:Show()
MDT.pullTooltip.botString = MDT.pullTooltip:CreateFontString("MDTToolTipString")
local botString = MDT.pullTooltip.botString
botString:SetFontObject("GameFontNormalSmall")
botString:SetFont(MDT.pullTooltip.topString:GetFont(),10)
botString:SetTextColor(1, 1, 1, 1)
botString:SetJustifyH("TOP")
botString:SetJustifyV("TOP")
botString:SetHeight(23)
botString:SetWidth(250)
botString:SetPoint("TOPLEFT", heading, "LEFT", -12, -7)
botString:Hide()
skinTooltip(pullTT)
end
MDT:initToolbar(main_frame)
if db.toolbarExpanded then
main_frame.toolbar.toggleButton:Click()
end
--ping
MDT.ping = CreateFrame("PlayerModel", nil, MDT.main_frame.mapPanelFrame)
local ping = MDT.ping
--ping:SetModel("interface/minimap/ping/minimapping.m2")
ping:SetModel(120590)
ping:SetPortraitZoom(1)
ping:SetCamera(1)
ping:SetFrameLevel(50)
ping:SetFrameStrata("DIALOG")
ping.mySize = 45
ping:SetSize(ping.mySize,ping.mySize)
ping:Hide()
--Set affix dropdown to preset week
--gotta set the list here, as affixes are not ready to be retrieved yet on login
main_frame.sidePanel.affixDropdown:UpdateAffixList()
main_frame.sidePanel.affixDropdown:SetAffixWeek(MDT:GetCurrentPreset().week or (MDT:GetCurrentAffixWeek() or 1))
MDT:UpdateToDungeon(db.currentDungeonIdx)
main_frame:Hide()
--Maximize if needed
if db.maximized then MDT:Maximize() end
if MDT:IsFrameOffScreen() then
MDT:ResetMainFramePos()
end
framesInitialized = true
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment