local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB local UF = E:GetModule("UnitFrames") local LSM = E.Libs.LSM UF.LSM = E.Libs.LSM --Lua functions local _G = _G local select, pairs, type, unpack, assert, tostring = select, pairs, type, unpack, assert, tostring local tremove, tinsert = table.remove, table.insert local find, gsub, format = string.find, string.gsub, string.format --WoW API / Variables local hooksecurefunc = hooksecurefunc local CreateFrame = CreateFrame local IsAddOnLoaded = IsAddOnLoaded local UnitFrame_OnEnter = UnitFrame_OnEnter local UnitFrame_OnLeave = UnitFrame_OnLeave local IsInInstance = IsInInstance local InCombatLockdown = InCombatLockdown local GetInstanceInfo = GetInstanceInfo local UnregisterStateDriver = UnregisterStateDriver local RegisterStateDriver = RegisterStateDriver local MAX_BOSS_FRAMES = MAX_BOSS_FRAMES local _, ns = ... local ElvUF = ns.oUF assert(ElvUF, "ElvUI was unable to locate oUF.") UF.headerstoload = {} UF.unitgroupstoload = {} UF.unitstoload = {} UF.groupPrototype = {} UF.headerPrototype = {} UF.headers = {} UF.groupunits = {} UF.units = {} UF.statusbars = {} UF.fontstrings = {} UF.badHeaderPoints = { ["TOP"] = "BOTTOM", ["LEFT"] = "RIGHT", ["BOTTOM"] = "TOP", ["RIGHT"] = "LEFT" } UF.headerFunctions = {} UF.classMaxResourceBar = { ["DRUID"] = 1, ["HERO"] = 1 } UF.instanceMapIDs = { [444] = 10, [541] = 40, [513] = 15, [402] = 40, [462] = 15, [483] = 15, } UF.headerGroupBy = { ["CLASS"] = function(header) header:SetAttribute("groupingOrder", "HERO,DEATHKNIGHT,DRUID,HUNTER,MAGE,PALADIN,PRIEST,ROGUE,SHAMAN,WARLOCK,WARRIOR") header:SetAttribute("sortMethod", "NAME") header:SetAttribute("groupBy", "CLASS") end, ["MTMA"] = function(header) header:SetAttribute("groupingOrder", "MAINTANK,MAINASSIST,NONE") header:SetAttribute("sortMethod", "NAME") header:SetAttribute("groupBy", "ROLE") end, ["NAME"] = function(header) header:SetAttribute("groupingOrder", "1,2,3,4,5,6,7,8") header:SetAttribute("sortMethod", "NAME") header:SetAttribute("groupBy", nil) end, ["GROUP"] = function(header) header:SetAttribute("groupingOrder", "1,2,3,4,5,6,7,8") header:SetAttribute("sortMethod", "INDEX") header:SetAttribute("groupBy", "GROUP") end, ["PETNAME"] = function(header) header:SetAttribute("groupingOrder", "1,2,3,4,5,6,7,8") header:SetAttribute("sortMethod", "NAME") header:SetAttribute("groupBy", nil) header:SetAttribute("filterOnPet", true) --This is the line that matters. Without this, it sorts based on the owners name end, } local POINT_COLUMN_ANCHOR_TO_DIRECTION = { ["TOPTOP"] = "UP_RIGHT", ["BOTTOMBOTTOM"] = "TOP_RIGHT", ["LEFTLEFT"] = "RIGHT_UP", ["RIGHTRIGHT"] = "LEFT_UP", ["RIGHTTOP"] = "LEFT_DOWN", ["LEFTTOP"] = "RIGHT_DOWN", ["LEFTBOTTOM"] = "RIGHT_UP", ["RIGHTBOTTOM"] = "LEFT_UP", ["BOTTOMRIGHT"] = "UP_LEFT", ["BOTTOMLEFT"] = "UP_RIGHT", ["TOPRIGHT"] = "DOWN_LEFT", ["TOPLEFT"] = "DOWN_RIGHT" } local DIRECTION_TO_POINT = { DOWN_RIGHT = "TOP", DOWN_LEFT = "TOP", UP_RIGHT = "BOTTOM", UP_LEFT = "BOTTOM", RIGHT_DOWN = "LEFT", RIGHT_UP = "LEFT", LEFT_DOWN = "RIGHT", LEFT_UP = "RIGHT", UP = "BOTTOM", DOWN = "TOP" } local DIRECTION_TO_GROUP_ANCHOR_POINT = { DOWN_RIGHT = "TOPLEFT", DOWN_LEFT = "TOPRIGHT", UP_RIGHT = "BOTTOMLEFT", UP_LEFT = "BOTTOMRIGHT", RIGHT_DOWN = "TOPLEFT", RIGHT_UP = "BOTTOMLEFT", LEFT_DOWN = "TOPRIGHT", LEFT_UP = "BOTTOMRIGHT", OUT_RIGHT_UP = "BOTTOM", OUT_LEFT_UP = "BOTTOM", OUT_RIGHT_DOWN = "TOP", OUT_LEFT_DOWN = "TOP", OUT_UP_RIGHT = "LEFT", OUT_UP_LEFT = "RIGHT", OUT_DOWN_RIGHT = "LEFT", OUT_DOWN_LEFT = "RIGHT" } local INVERTED_DIRECTION_TO_COLUMN_ANCHOR_POINT = { DOWN_RIGHT = "RIGHT", DOWN_LEFT = "LEFT", UP_RIGHT = "RIGHT", UP_LEFT = "LEFT", RIGHT_DOWN = "BOTTOM", RIGHT_UP = "TOP", LEFT_DOWN = "BOTTOM", LEFT_UP = "TOP", UP = "TOP", DOWN = "BOTTOM" } local DIRECTION_TO_COLUMN_ANCHOR_POINT = { DOWN_RIGHT = "LEFT", DOWN_LEFT = "RIGHT", UP_RIGHT = "LEFT", UP_LEFT = "RIGHT", RIGHT_DOWN = "TOP", RIGHT_UP = "BOTTOM", LEFT_DOWN = "TOP", LEFT_UP = "BOTTOM" } local DIRECTION_TO_HORIZONTAL_SPACING_MULTIPLIER = { DOWN_RIGHT = 1, DOWN_LEFT = -1, UP_RIGHT = 1, UP_LEFT = -1, RIGHT_DOWN = 1, RIGHT_UP = 1, LEFT_DOWN = -1, LEFT_UP = -1 } local DIRECTION_TO_VERTICAL_SPACING_MULTIPLIER = { DOWN_RIGHT = -1, DOWN_LEFT = -1, UP_RIGHT = 1, UP_LEFT = 1, RIGHT_DOWN = -1, RIGHT_UP = 1, LEFT_DOWN = -1, LEFT_UP = 1 } function UF:ConvertGroupDB(group) local db = self.db.units[group.groupName] if db.point and db.columnAnchorPoint then db.growthDirection = POINT_COLUMN_ANCHOR_TO_DIRECTION[db.point..db.columnAnchorPoint] db.point = nil db.columnAnchorPoint = nil end if db.growthDirection == "UP" then db.growthDirection = "UP_RIGHT" end if db.growthDirection == "DOWN" then db.growthDirection = "DOWN_RIGHT" end end function UF:Construct_UF(frame, unit) frame:SetScript("OnEnter", UnitFrame_OnEnter) frame:SetScript("OnLeave", UnitFrame_OnLeave) if self.thinBorders then frame.SPACING = 0 frame.BORDER = E.mult else frame.BORDER = E.Border frame.SPACING = E.Spacing end frame.SHADOW_SPACING = 3 frame.CLASSBAR_YOFFSET = 0 --placeholder frame.BOTTOM_OFFSET = 0 --placeholder frame.RaisedElementParent = CreateFrame("Frame", nil, frame) frame.RaisedElementParent.TextureParent = CreateFrame("Frame", nil, frame.RaisedElementParent) frame.RaisedElementParent:SetFrameLevel(frame:GetFrameLevel() + 125) if not self.groupunits[unit] then local stringTitle = E:StringTitle(unit) if find(stringTitle, "target") then stringTitle = gsub(stringTitle, "target", "Target") end self["Construct_"..stringTitle.."Frame"](self, frame, unit) else UF["Construct_"..E:StringTitle(self.groupunits[unit]).."Frames"](self, frame, unit) end self:Update_StatusBars() self:Update_FontStrings() return frame end function UF:GetObjectAnchorPoint(frame, point) if not frame[point] or point == "Frame" then return frame elseif frame[point] and not frame[point]:IsShown() then return frame.Health else return frame[point] end end function UF:GetPositionOffset(position, offset) if not offset then offset = 2 end local x, y = 0, 0 if find(position, "LEFT") then x = offset elseif find(position, "RIGHT") then x = -offset end if find(position, "TOP") then y = -offset elseif find(position, "BOTTOM") then y = offset end return x, y end function UF:GetAuraOffset(p1, p2) local x, y = 0, 0 if p1 == "RIGHT" and p2 == "LEFT" then x = -3 elseif p1 == "LEFT" and p2 == "RIGHT" then x = 3 end if find(p1, "TOP") and find(p2, "BOTTOM") then y = -1 elseif find(p1, "BOTTOM") and find(p2, "TOP") then y = 1 end return E:Scale(x), E:Scale(y) end function UF:GetAuraAnchorFrame(frame, attachTo, isConflict) if isConflict then E:Print(format(L["%s frame(s) has a conflicting anchor point, please change either the buff or debuff anchor point so they are not attached to each other. Forcing the debuffs to be attached to the main unitframe until fixed."], E:StringTitle(frame:GetName()))) end if isConflict or attachTo == "FRAME" then return frame elseif attachTo == "TRINKET" then if select(2, IsInInstance()) == "arena" then return frame.Trinket end elseif attachTo == "BUFFS" then return frame.Buffs elseif attachTo == "DEBUFFS" then return frame.Debuffs elseif attachTo == "HEALTH" then return frame.Health elseif attachTo == "POWER" and frame.Power then return frame.Power elseif attachTo == "ENERGY" and frame.Energy then return frame.Energy elseif attachTo == "RAGE" and frame.Rage then return frame.Rage else return frame end end function UF:ClearChildPoints(...) for i = 1, select("#", ...) do local child = select(i, ...) child:ClearAllPoints() end end function UF:UpdateColors() local db = self.db.colors ElvUF.colors.tapped = E:SetColorTable(ElvUF.colors.tapped, db.tapped) ElvUF.colors.disconnected = E:SetColorTable(ElvUF.colors.disconnected, db.disconnected) ElvUF.colors.health = E:SetColorTable(ElvUF.colors.health, db.health) ElvUF.colors.power.MANA = E:SetColorTable(ElvUF.colors.power.MANA, db.power.MANA) ElvUF.colors.power.RAGE = E:SetColorTable(ElvUF.colors.power.RAGE, db.power.RAGE) ElvUF.colors.power.FOCUS = E:SetColorTable(ElvUF.colors.power.FOCUS, db.power.FOCUS) ElvUF.colors.power.ENERGY = E:SetColorTable(ElvUF.colors.power.ENERGY, db.power.ENERGY) ElvUF.colors.power.RUNIC_POWER = E:SetColorTable(ElvUF.colors.power.RUNIC_POWER, db.power.RUNIC_POWER) ElvUF.colors.threat[0] = E:SetColorTable(ElvUF.colors.threat[0], db.threat[0]) ElvUF.colors.threat[1] = E:SetColorTable(ElvUF.colors.threat[1], db.threat[1]) ElvUF.colors.threat[2] = E:SetColorTable(ElvUF.colors.threat[2], db.threat[2]) ElvUF.colors.threat[3] = E:SetColorTable(ElvUF.colors.threat[3], db.threat[3]) if not ElvUF.colors.ComboPoints then ElvUF.colors.ComboPoints = {} end ElvUF.colors.ComboPoints[1] = E:SetColorTable(ElvUF.colors.ComboPoints[1], db.classResources.comboPoints[1]) ElvUF.colors.ComboPoints[2] = E:SetColorTable(ElvUF.colors.ComboPoints[2], db.classResources.comboPoints[2]) ElvUF.colors.ComboPoints[3] = E:SetColorTable(ElvUF.colors.ComboPoints[3], db.classResources.comboPoints[3]) ElvUF.colors.ComboPoints[4] = E:SetColorTable(ElvUF.colors.ComboPoints[4], db.classResources.comboPoints[4]) ElvUF.colors.ComboPoints[5] = E:SetColorTable(ElvUF.colors.ComboPoints[5], db.classResources.comboPoints[5]) -- Death Knight if not ElvUF.colors.runes then ElvUF.colors.runes = {} end if not ElvUF.colors.ClassBars then ElvUF.colors.ClassBars = {} end if not ElvUF.colors.ClassBars.DEATHKNIGHT then ElvUF.colors.ClassBars.DEATHKNIGHT = {} end ElvUF.colors.runes[1] = E:SetColorTable(ElvUF.colors.ClassBars.DEATHKNIGHT[1], db.classResources.DEATHKNIGHT[1]) ElvUF.colors.runes[2] = E:SetColorTable(ElvUF.colors.ClassBars.DEATHKNIGHT[2], db.classResources.DEATHKNIGHT[2]) ElvUF.colors.runes[3] = E:SetColorTable(ElvUF.colors.ClassBars.DEATHKNIGHT[3], db.classResources.DEATHKNIGHT[3]) ElvUF.colors.runes[4] = E:SetColorTable(ElvUF.colors.ClassBars.DEATHKNIGHT[4], db.classResources.DEATHKNIGHT[4]) -- these are just holders.. to maintain and update tables if not ElvUF.colors.reaction.good then ElvUF.colors.reaction.good = {} end if not ElvUF.colors.reaction.bad then ElvUF.colors.reaction.bad = {} end if not ElvUF.colors.reaction.neutral then ElvUF.colors.reaction.neutral = {} end ElvUF.colors.reaction.good = E:SetColorTable(ElvUF.colors.reaction.good, db.reaction.GOOD) ElvUF.colors.reaction.bad = E:SetColorTable(ElvUF.colors.reaction.bad, db.reaction.BAD) ElvUF.colors.reaction.neutral = E:SetColorTable(ElvUF.colors.reaction.neutral, db.reaction.NEUTRAL) if not ElvUF.colors.smoothHealth then ElvUF.colors.smoothHealth = {} end ElvUF.colors.smoothHealth = E:SetColorTable(ElvUF.colors.smoothHealth, db.health) if not ElvUF.colors.smooth then ElvUF.colors.smooth = {1, 0, 0, 1, 1, 0} end ElvUF.colors.reaction[1] = ElvUF.colors.reaction.bad ElvUF.colors.reaction[2] = ElvUF.colors.reaction.bad ElvUF.colors.reaction[3] = ElvUF.colors.reaction.bad ElvUF.colors.reaction[4] = ElvUF.colors.reaction.neutral ElvUF.colors.reaction[5] = ElvUF.colors.reaction.good ElvUF.colors.reaction[6] = ElvUF.colors.reaction.good ElvUF.colors.reaction[7] = ElvUF.colors.reaction.good ElvUF.colors.reaction[8] = ElvUF.colors.reaction.good ElvUF.colors.smooth[7] = ElvUF.colors.smoothHealth[1] ElvUF.colors.smooth[8] = ElvUF.colors.smoothHealth[2] ElvUF.colors.smooth[9] = ElvUF.colors.smoothHealth[3] ElvUF.colors.castColor = E:SetColorTable(ElvUF.colors.castColor, db.castColor) ElvUF.colors.castNoInterrupt = E:SetColorTable(ElvUF.colors.castNoInterrupt, db.castNoInterrupt) if not ElvUF.colors.DebuffHighlight then ElvUF.colors.DebuffHighlight = {} end ElvUF.colors.DebuffHighlight.Magic = E:SetColorTable(ElvUF.colors.DebuffHighlight.Magic, db.debuffHighlight.Magic) ElvUF.colors.DebuffHighlight.Curse = E:SetColorTable(ElvUF.colors.DebuffHighlight.Curse, db.debuffHighlight.Curse) ElvUF.colors.DebuffHighlight.Disease = E:SetColorTable(ElvUF.colors.DebuffHighlight.Disease, db.debuffHighlight.Disease) ElvUF.colors.DebuffHighlight.Poison = E:SetColorTable(ElvUF.colors.DebuffHighlight.Poison, db.debuffHighlight.Poison) end function UF:Update_StatusBars() local statusBarTexture = LSM:Fetch("statusbar", self.db.statusbar) for statusbar in pairs(UF.statusbars) do if statusbar then local useBlank = statusbar.isTransparent if statusbar.parent then useBlank = statusbar.parent.isTransparent end if statusbar:IsObjectType("StatusBar") then if not useBlank then statusbar:SetStatusBarTexture(statusBarTexture) if statusbar.texture then statusbar.texture = statusBarTexture end --Update .texture on oUF Power element end elseif statusbar:IsObjectType("Texture") then statusbar:SetTexture(statusBarTexture) end UF:Update_StatusBar(statusbar.bg or statusbar.BG, (not useBlank and statusBarTexture) or E.media.blankTex) end end end function UF:Update_StatusBar(statusbar, texture) if not statusbar then return end if not texture then texture = LSM:Fetch("statusbar", self.db.statusbar) end if statusbar:IsObjectType("StatusBar") then statusbar:SetStatusBarTexture(texture) elseif statusbar:IsObjectType("Texture") then statusbar:SetTexture(texture) end end function UF:Update_FontString(object) object:FontTemplate(LSM:Fetch("font", self.db.font), self.db.fontSize, self.db.fontOutline) end function UF:Update_FontStrings() local stringFont = LSM:Fetch("font", self.db.font) for font in pairs(UF.fontstrings) do font:FontTemplate(stringFont, self.db.fontSize, self.db.fontOutline) end end function UF:Construct_Fader() return {UpdateRange = UF.UpdateRange} end function UF:Configure_Fader(frame) if frame.db and frame.db.enable and (frame.db.fader and frame.db.fader.enable) then if not frame:IsElementEnabled("Fader") then frame:EnableElement("Fader") end frame.Fader:SetOption("Hover", frame.db.fader.hover) frame.Fader:SetOption("Combat", frame.db.fader.combat) frame.Fader:SetOption("PlayerTarget", frame.db.fader.playertarget) frame.Fader:SetOption("Focus", frame.db.fader.focus) frame.Fader:SetOption("Health", frame.db.fader.health) frame.Fader:SetOption("Power", frame.db.fader.power) frame.Fader:SetOption("Vehicle", frame.db.fader.vehicle) frame.Fader:SetOption("Casting", frame.db.fader.casting) frame.Fader:SetOption("MinAlpha", frame.db.fader.minAlpha) frame.Fader:SetOption("MaxAlpha", frame.db.fader.maxAlpha) if frame ~= ElvUF_Player then frame.Fader:SetOption("Range", frame.db.fader.range) frame.Fader:SetOption("UnitTarget", frame.db.fader.unittarget) end frame.Fader:SetOption("Smooth", (frame.db.fader.smooth > 0 and frame.db.fader.smooth) or nil) frame.Fader:SetOption("Delay", (frame.db.fader.delay > 0 and frame.db.fader.delay) or nil) frame.Fader:ClearTimers() frame.Fader.configTimer = E:ScheduleTimer(frame.Fader.ForceUpdate, 0.25, frame.Fader, true) elseif frame:IsElementEnabled("Fader") then frame:DisableElement("Fader") E:UIFrameFadeIn(frame, 1, frame:GetAlpha(), 1) end end function UF:Construct_ClipFrame(frame, bar) local clipFrame = CreateFrame('ScrollFrame', nil, bar) clipFrame:SetAllPoints() clipFrame:EnableMouse(false) local child = CreateFrame("Frame", nil, clipFrame) child:SetPoint("CENTER") child:SetSize(clipFrame:GetSize()) child.__frame = frame bar.ClipFrame = child return child end function UF:Configure_FontString(obj) UF.fontstrings[obj] = true obj:FontTemplate() --This is temporary. end function UF:Update_AllFrames() if InCombatLockdown() then self:RegisterEvent("PLAYER_REGEN_ENABLED") return end if E.private.unitframe.enable ~= true then return end self:UpdateColors() self:Update_FontStrings() self:Update_StatusBars() for unit in pairs(self.units) do if self.db.units[unit].enable then self[unit]:Update() self[unit]:Enable() E:EnableMover(self[unit].mover:GetName()) else self[unit]:Update() self[unit]:Disable() E:DisableMover(self[unit].mover:GetName()) end end for unit, group in pairs(self.groupunits) do if self.db.units[group].enable then self[unit]:Enable() self[unit]:Update() E:EnableMover(self[unit].mover:GetName()) else self[unit]:Disable() E:DisableMover(self[unit].mover:GetName()) end end UF:UpdateAllHeaders() end function UF:CreateAndUpdateUFGroup(group, numGroup) if InCombatLockdown() then self:RegisterEvent("PLAYER_REGEN_ENABLED") return end for i = 1, numGroup do local unit = group..i local frameName = E:StringTitle(unit) frameName = gsub(frameName, "t(arget)", "T%1") local frame = self[unit] if not frame then self.groupunits[unit] = group frame = ElvUF:Spawn(unit, "ElvUF_"..frameName) frame.index = i frame:SetParent(ElvUF_Parent) frame:SetID(i) self[unit] = frame end frameName = E:StringTitle(group) frameName = gsub(frameName, "t(arget)", "T%1") frame.Update = function() UF["Update_"..E:StringTitle(frameName).."Frames"](self, frame, self.db.units[group]) end if self.db.units[group].enable then frame:Enable() frame.Update() if frame.isForced then self:ForceShow(frame) end E:EnableMover(frame.mover:GetName()) else frame:Disable() -- for some reason the boss/arena 'uncheck disable' doesnt fire this, we need to so putting it here. if group == "boss" or group == "arena" then UF:Configure_Fader(frame) end E:DisableMover(frame.mover:GetName()) end end end function UF:HeaderUpdateSpecificElement(group, elementName) assert(self[group], "Invalid group specified.") for i = 1, self[group]:GetNumChildren() do local frame = select(i, self[group]:GetChildren()) if frame and frame.Health then frame:UpdateElement(elementName) end end end function UF.groupPrototype:GetAttribute(name) return self.groups[1]:GetAttribute(name) end function UF.groupPrototype:Configure_Groups(frame) local db = UF.db.units[frame.groupName] local point local width, height, newCols, newRows = 0, 0, 0, 0 local direction = db.growthDirection local xMult, yMult = DIRECTION_TO_HORIZONTAL_SPACING_MULTIPLIER[direction], DIRECTION_TO_VERTICAL_SPACING_MULTIPLIER[direction] local UNIT_HEIGHT = db.infoPanel and db.infoPanel.enable and (db.height + db.infoPanel.height) or db.height local groupSpacing = db.groupSpacing local numGroups = frame.numGroups for i = 1, numGroups do local group = frame.groups[i] point = DIRECTION_TO_POINT[direction] if group then group:Hide() UF:ConvertGroupDB(group) if point == "LEFT" or point == "RIGHT" then group:SetAttribute("xOffset", db.horizontalSpacing * DIRECTION_TO_HORIZONTAL_SPACING_MULTIPLIER[direction]) group:SetAttribute("yOffset", 0) group:SetAttribute("columnSpacing", db.verticalSpacing) else group:SetAttribute("xOffset", 0) group:SetAttribute("yOffset", db.verticalSpacing * DIRECTION_TO_VERTICAL_SPACING_MULTIPLIER[direction]) group:SetAttribute("columnSpacing", db.horizontalSpacing) end --[[if not group.isForced then if not group.initialized then group:SetAttribute("startingIndex", db.raidWideSorting and (-min(numGroups * (db.groupsPerRowCol * 5), MAX_RAID_MEMBERS) + 1) or -4) group:Show() group.initialized = true end group:SetAttribute("startingIndex", 1) end]] group:ClearAllPoints() if db.raidWideSorting and db.invertGroupingOrder then group:SetAttribute("columnAnchorPoint", INVERTED_DIRECTION_TO_COLUMN_ANCHOR_POINT[direction]) else group:SetAttribute("columnAnchorPoint", DIRECTION_TO_COLUMN_ANCHOR_POINT[direction]) end group:ClearChildPoints() group:SetAttribute("point", point) if not group.isForced then group:SetAttribute("maxColumns", db.raidWideSorting and numGroups or 1) group:SetAttribute("unitsPerColumn", db.raidWideSorting and (db.groupsPerRowCol * 5) or 5) if UF.headerGroupBy[db.groupBy] then UF.headerGroupBy[db.groupBy](group) else UF.headerGroupBy["GROUP"](group) end group:SetAttribute("sortDir", db.sortDir) group:SetAttribute("showPlayer", db.showPlayer) end if i == 1 and db.raidWideSorting then group:SetAttribute("groupFilter", "1,2,3,4,5,6,7,8") else group:SetAttribute("groupFilter", tostring(i)) end -- group:Show() end --MATH!! WOOT point = DIRECTION_TO_GROUP_ANCHOR_POINT[direction] if db.raidWideSorting and db.startFromCenter then point = DIRECTION_TO_GROUP_ANCHOR_POINT["OUT_"..direction] end if (i - 1) % db.groupsPerRowCol == 0 then if DIRECTION_TO_POINT[direction] == "LEFT" or DIRECTION_TO_POINT[direction] == "RIGHT" then if group then group:Point(point, frame, point, 0, height * yMult) end height = height + UNIT_HEIGHT + db.verticalSpacing + groupSpacing newRows = newRows + 1 else if group then group:Point(point, frame, point, width * xMult, 0) end width = width + db.width + db.horizontalSpacing + groupSpacing newCols = newCols + 1 end else if DIRECTION_TO_POINT[direction] == "LEFT" or DIRECTION_TO_POINT[direction] == "RIGHT" then if newRows == 1 then if group then group:Point(point, frame, point, width * xMult, 0) end width = width + ((db.width + db.horizontalSpacing) * 5) + groupSpacing newCols = newCols + 1 elseif group then group:Point(point, frame, point, ((((db.width + db.horizontalSpacing) * 5) * ((i - 1) % db.groupsPerRowCol)) + ((i - 1) % db.groupsPerRowCol)*groupSpacing) * xMult, (((UNIT_HEIGHT + db.verticalSpacing+groupSpacing) * (newRows - 1))) * yMult) end else if newCols == 1 then if group then group:Point(point, frame, point, 0, height * yMult) end height = height + ((UNIT_HEIGHT + db.verticalSpacing) * 5) + groupSpacing newRows = newRows + 1 elseif group then group:Point(point, frame, point, (((db.width + db.horizontalSpacing +groupSpacing) * (newCols - 1))) * xMult, ((((UNIT_HEIGHT + db.verticalSpacing) * 5) * ((i-1) % db.groupsPerRowCol))+((i-1) % db.groupsPerRowCol)*groupSpacing) * yMult) end end end if height == 0 then height = height + ((UNIT_HEIGHT + db.verticalSpacing) * 5) + groupSpacing elseif width == 0 then width = width + ((db.width + db.horizontalSpacing) * 5) + groupSpacing end end if not frame.isInstanceForced then frame.dirtyWidth = width - db.horizontalSpacing -groupSpacing frame.dirtyHeight = height - db.verticalSpacing -groupSpacing end if frame.mover then frame.mover.positionOverride = DIRECTION_TO_GROUP_ANCHOR_POINT[direction] E:UpdatePositionOverride(frame.mover:GetName()) frame:GetScript("OnSizeChanged")(frame) --Mover size is not updated if frame is hidden, so call an update manually end frame:Size(width - db.horizontalSpacing -groupSpacing, height - db.verticalSpacing - groupSpacing) end function UF.groupPrototype:Update(frame) local group = frame.groupName UF[group].db = UF.db.units[group] for i = 1, #frame.groups do frame.groups[i].db = UF.db.units[group] frame.groups[i]:Update() end end function UF.groupPrototype:AdjustVisibility(frame) -- if not frame.isForced then local numGroups = frame.numGroups for i = 1, #frame.groups do local group = frame.groups[i] if (i <= numGroups) and ((frame.db.raidWideSorting and i <= 1) or not frame.db.raidWideSorting) then group:Show() else if group.forceShow then group:Hide() UF:UnshowChildUnits(group, group:GetChildren()) group:SetAttribute("startingIndex", 1) else group:Reset() end end end -- end end function UF.headerPrototype:ClearChildPoints() for i = 1, self:GetNumChildren() do local child = select(i, self:GetChildren()) child:ClearAllPoints() end end function UF.headerPrototype:Update() local group = self.groupName local db = UF.db.units[group] UF["Update_"..E:StringTitle(group).."Header"](UF, self, db) local i = 1 local child = self:GetAttribute("child"..i) while child do UF["Update_"..E:StringTitle(group).."Frames"](UF, child, db) if _G[child:GetName().."Pet"] then UF["Update_"..E:StringTitle(group).."Frames"](UF, _G[child:GetName().."Pet"], db) end if _G[child:GetName().."Target"] then UF["Update_"..E:StringTitle(group).."Frames"](UF, _G[child:GetName().."Target"], db) end i = i + 1 child = self:GetAttribute("child"..i) end end function UF.headerPrototype:Reset() self:Hide() self:SetAttribute("showPlayer", true) self:SetAttribute("showSolo", true) self:SetAttribute("showParty", true) self:SetAttribute("showRaid", true) self:SetAttribute("columnSpacing", nil) self:SetAttribute("columnAnchorPoint", nil) self:SetAttribute("groupBy", nil) self:SetAttribute("groupFilter", nil) self:SetAttribute("groupingOrder", nil) self:SetAttribute("maxColumns", nil) self:SetAttribute("nameList", nil) self:SetAttribute("point", nil) self:SetAttribute("sortDir", nil) self:SetAttribute("sortMethod", "NAME") self:SetAttribute("startingIndex", nil) self:SetAttribute("strictFiltering", nil) self:SetAttribute("unitsPerColumn", nil) self:SetAttribute("xOffset", nil) self:SetAttribute("yOffset", nil) end function UF:CreateHeader(parent, groupFilter, overrideName, template, groupName, headerTemplate) local group = parent.groupName or groupName ElvUF:SetActiveStyle("ElvUF_"..E:StringTitle(group)) local header = ElvUF:SpawnHeader(overrideName, headerTemplate, nil, "groupFilter", groupFilter, "showParty", true, "showRaid", group == "party" and false or true, "showSolo", true, template and "template", template) header.groupName = group header:SetParent(parent) --header:Show() for k, v in pairs(self.headerPrototype) do header[k] = v end return header end function UF:CreateAndUpdateHeaderGroup(group, groupFilter, template, headerUpdate, headerTemplate) if InCombatLockdown() then self:RegisterEvent("PLAYER_REGEN_ENABLED") return end local db = self.db.units[group] local raidFilter = UF.db.smartRaidFilter local numGroups = db.numGroups if raidFilter and numGroups and (self[group] and not self[group].blockVisibilityChanges) then local _, instanceType, _, _, maxPlayers = GetInstanceInfo() if instanceType == "raid" or instanceType == "pvp" then local mapID = GetCurrentMapAreaID() if UF.instanceMapIDs[mapID] then maxPlayers = UF.instanceMapIDs[mapID] end if maxPlayers > 0 then numGroups = E:Round(maxPlayers/5) end end end if not self[group] then local stringTitle = E:StringTitle(group) ElvUF:RegisterStyle("ElvUF_"..stringTitle, UF["Construct_"..stringTitle.."Frames"]) ElvUF:SetActiveStyle("ElvUF_"..stringTitle) if db.numGroups then self[group] = CreateFrame("Frame", "ElvUF_"..stringTitle, ElvUF_Parent, "SecureHandlerStateTemplate") self[group]:Hide() self[group].groups = {} self[group].groupName = group self[group].template = self[group].template or template self[group].headerTemplate = self[group].headerTemplate or headerTemplate if not UF.headerFunctions[group] then UF.headerFunctions[group] = {} end for k, v in pairs(self.groupPrototype) do UF.headerFunctions[group][k] = v end else self[group] = self:CreateHeader(ElvUF_Parent, groupFilter, "ElvUF_"..E:StringTitle(group), template, group, headerTemplate) end self[group].db = db self.headers[group] = self[group] --self[group]:Show() end self[group].numGroups = numGroups if numGroups then if db.raidWideSorting then if not self[group].groups[1] then self[group].groups[1] = self:CreateHeader(self[group], nil, "ElvUF_"..E:StringTitle(self[group].groupName).."Group1", template or self[group].template, nil, headerTemplate or self[group].headerTemplate) end else while numGroups > #self[group].groups do local index = tostring(#self[group].groups + 1) tinsert(self[group].groups, self:CreateHeader(self[group], index, "ElvUF_"..E:StringTitle(self[group].groupName).."Group"..index, template or self[group].template, nil, headerTemplate or self[group].headerTemplate)) end end -- UF.headerFunctions[group]:AdjustVisibility(self[group]) if headerUpdate or not self[group].mover then UF.headerFunctions[group]:Configure_Groups(self[group]) if not self[group].isForced and not self[group].blockVisibilityChanges then RegisterStateDriver(self[group], "visibility", db.visibility) end if not self[group].mover then UF.headerFunctions[group]:Update(self[group]) end else UF.headerFunctions[group]:Configure_Groups(self[group]) UF.headerFunctions[group]:Update(self[group]) end UF.headerFunctions[group]:AdjustVisibility(self[group]) if db.enable then if self[group].mover then E:EnableMover(self[group].mover:GetName()) end else UnregisterStateDriver(self[group], "visibility") self[group]:Hide() if self[group].mover then E:DisableMover(self[group].mover:GetName()) end return end else self[group].db = db if not UF.headerFunctions[group] then UF.headerFunctions[group] = {} end UF.headerFunctions[group].Update = function() -- local db = UF.db.units[group] if db.enable ~= true then UnregisterStateDriver(UF[group], "visibility") UF[group]:Hide() if UF[group].mover then E:DisableMover(UF[group].mover:GetName()) end return end UF["Update_"..E:StringTitle(group).."Header"](UF, UF[group], db) for i = 1, UF[group]:GetNumChildren() do local child = select(i, UF[group]:GetChildren()) UF["Update_"..E:StringTitle(group).."Frames"](UF, child, UF.db.units[group]) if _G[child:GetName().."Target"] then UF["Update_"..E:StringTitle(group).."Frames"](UF, _G[child:GetName().."Target"], UF.db.units[group]) end if _G[child:GetName().."Pet"] then UF["Update_"..E:StringTitle(group).."Frames"](UF, _G[child:GetName().."Pet"], UF.db.units[group]) end end E:EnableMover(UF[group].mover:GetName()) end if headerUpdate then UF["Update_"..E:StringTitle(group).."Header"](self, self[group], db) else UF.headerFunctions[group]:Update(self[group]) end end end function UF:PLAYER_REGEN_ENABLED() self:Update_AllFrames() self:UnregisterEvent("PLAYER_REGEN_ENABLED") end function UF:CreateAndUpdateUF(unit) assert(unit, "No unit provided to create or update.") if InCombatLockdown() then self:RegisterEvent("PLAYER_REGEN_ENABLED") return end local frameName = E:StringTitle(unit) frameName = gsub(frameName, "t(arget)", "T%1") if not self[unit] then self[unit] = ElvUF:Spawn(unit, "ElvUF_"..frameName) self.units[unit] = unit end self[unit].Update = function() UF["Update_"..frameName.."Frame"](self, self[unit], self.db.units[unit]) end if self[unit]:GetParent() ~= ElvUF_Parent then self[unit]:SetParent(ElvUF_Parent) end if self.db.units[unit].enable then self[unit]:Enable() self[unit].Update() E:EnableMover(self[unit].mover:GetName()) else self[unit].Update() self[unit]:Disable() E:DisableMover(self[unit].mover:GetName()) end end function UF:LoadUnits() for _, unit in pairs(self.unitstoload) do self:CreateAndUpdateUF(unit) end self.unitstoload = nil for group, groupOptions in pairs(self.unitgroupstoload) do local numGroup, template = unpack(groupOptions) self:CreateAndUpdateUFGroup(group, numGroup, template) end self.unitgroupstoload = nil for group, groupOptions in pairs(self.headerstoload) do local groupFilter, template, headerTemplate if type(groupOptions) == "table" then groupFilter, template, headerTemplate = unpack(groupOptions) end self:CreateAndUpdateHeaderGroup(group, groupFilter, template, nil, headerTemplate) end self.headerstoload = nil end function UF:RegisterRaidDebuffIndicator() local ORD = ns.oUF_RaidDebuffs or oUF_RaidDebuffs if ORD then ORD:ResetDebuffData() local _, instanceType = GetInstanceInfo() if instanceType == "party" or instanceType == "raid" then local instance = E.global.unitframe.raidDebuffIndicator.instanceFilter local instanceSpells = ((E.global.unitframe.aurafilters[instance] and E.global.unitframe.aurafilters[instance].spells) or E.global.unitframe.aurafilters.RaidDebuffs.spells) ORD:RegisterDebuffs(instanceSpells) else local other = E.global.unitframe.raidDebuffIndicator.otherFilter local otherSpells = ((E.global.unitframe.aurafilters[other] and E.global.unitframe.aurafilters[other].spells) or E.global.unitframe.aurafilters.CCDebuffs.spells) ORD:RegisterDebuffs(otherSpells) end end end function UF:UpdateAllHeaders(event) if InCombatLockdown() then self:RegisterEvent("PLAYER_REGEN_ENABLED", "UpdateAllHeaders") return end if event == "PLAYER_REGEN_ENABLED" then self:UnregisterEvent("PLAYER_REGEN_ENABLED") end if E.private.unitframe.disabledBlizzardFrames.party then ElvUF:DisableBlizzard("party") end if E.private.unitframe.disabledBlizzardFrames.raid then ElvUF:DisableBlizzard("raid") end self:RegisterRaidDebuffIndicator() local smartRaidFilterEnabled = self.db.smartRaidFilter for group, header in pairs(self.headers) do UF.headerFunctions[group]:Update(header) local shouldUpdateHeader if header.numGroups == nil or smartRaidFilterEnabled then shouldUpdateHeader = false elseif header.numGroups ~= nil and not smartRaidFilterEnabled then shouldUpdateHeader = true end self:CreateAndUpdateHeaderGroup(group, nil, nil, shouldUpdateHeader) if group == "party" or group == "raid" or group == "raid40" then --Update BuffIndicators on profile change as they might be using profile specific data self:UpdateAuraWatchFromHeader(group) end end end local SetFrameUp = {} local SetFrameUnit = {} local AllowedFuncs = {} if _G.DefaultCompactUnitFrameSetup then AllowedFuncs[_G.DefaultCompactUnitFrameSetup] = true end function UF:DisableBlizzard_SetUpFrame(func) if not AllowedFuncs[func] then return end local name = (not self.IsForbidden or not self:IsForbidden()) and self:GetName() if not name then return end for _, pattern in next, SetFrameUp do if strmatch(name, pattern) then SetFrameUnit[self] = name end end end function UF:DisableBlizzard_SetUnit(token) if SetFrameUnit[self] and token ~= nil then self:SetScript('OnEvent', nil) self:SetScript('OnUpdate', nil) end end local hiddenParent = CreateFrame("Frame") hiddenParent:SetAllPoints() hiddenParent:Hide() local HandleFrame = function(baseName) local frame if type(baseName) == "string" then frame = _G[baseName] else frame = baseName end if frame then frame:UnregisterAllEvents() frame:Hide() -- Keep frame hidden without causing taint frame:SetParent(hiddenParent) local health = frame.healthbar if health then health:UnregisterAllEvents() end local power = frame.manabar if power then power:UnregisterAllEvents() end local spell = frame.spellbar if spell then spell:UnregisterAllEvents() end end end local HandleCompactUnitFrame = function(frame, pattern) if SetFrameUp[frame] ~= pattern then SetFrameUp[frame] = pattern end HandleFrame(frame) end function ElvUF:DisableBlizzard(unit) if (not unit) or InCombatLockdown() then return end if (unit == "player") and E.private.unitframe.disabledBlizzardFrames.player then HandleFrame(PlayerFrame) -- For the damn vehicle support: PlayerFrame:RegisterEvent("UNIT_ENTERING_VEHICLE") PlayerFrame:RegisterEvent("UNIT_ENTERED_VEHICLE") PlayerFrame:RegisterEvent("UNIT_EXITING_VEHICLE") PlayerFrame:RegisterEvent("UNIT_EXITED_VEHICLE") RuneFrame:SetParent(PlayerFrame) elseif (unit == "pet") and E.private.unitframe.disabledBlizzardFrames.player then HandleFrame(PetFrame) elseif (unit == "target") and E.private.unitframe.disabledBlizzardFrames.target then HandleFrame(TargetFrame) HandleFrame(ComboFrame) elseif (unit == "focus") and E.private.unitframe.disabledBlizzardFrames.focus then HandleFrame(FocusFrame) HandleFrame(FocusFrameToT) elseif (unit == "targettarget") and E.private.unitframe.disabledBlizzardFrames.target then HandleFrame(TargetFrameToT) elseif (unit:match"(boss)%d?$" == "boss") and E.private.unitframe.disabledBlizzardFrames.boss then local id = unit:match"boss(%d)" if id then HandleFrame("Boss"..id.."TargetFrame") else for i = 1, MAX_BOSS_FRAMES do HandleFrame(format("Boss%dTargetFrame", i)) end end elseif (unit:match"(party)%d?$" == "party") and E.private.unitframe.disabledBlizzardFrames.party then local id = unit:match"party(%d)" HandleCompactUnitFrame("CompactPartyFrame", '^CompactPartyFrameMember%d+$') if id then HandleFrame("PartyMemberFrame"..id) else for i = 1, 4 do HandleFrame(format("PartyMemberFrame%d", i)) end end HandleFrame(PartyMemberBackground) elseif (unit:match"(arena)%d?$" == "arena") and E.private.unitframe.disabledBlizzardFrames.arena then local id = unit:match"arena(%d)" if id then HandleFrame("ArenaEnemyFrame"..id) HandleFrame("ArenaEnemyFrame"..id.."PetFrame") else for i = 1, 5 do HandleFrame(format("ArenaEnemyFrame%d", i)) HandleFrame(format("ArenaEnemyFrame%dPetFrame", i)) end end elseif (unit:match("(raid)%d?$") == "raid") and E.private.unitframe.disabledBlizzardFrames.raid then HandleCompactUnitFrame("CompactPartyFrame", '^CompactRaidGroup%d+Member%d+$') if CompactRaidFrameManager then CompactRaidFrameManager:UnregisterAllEvents() CompactRaidFrameManager:SetParent(E.HiddenFrame) CompactRaidFrameManager:SetSetting('IsShown', '0') end end end function UF:ADDON_LOADED(_, addon) if addon ~= "Blizzard_ArenaUI" then return end ElvUF:DisableBlizzard("arena") self:UnregisterEvent("ADDON_LOADED") end do local hasEnteredWorld = false function UF:PLAYER_ENTERING_WORLD() if not hasEnteredWorld then --We only want to run Update_AllFrames once when we first log in or /reload UF:Update_AllFrames() hasEnteredWorld = true else local _, instanceType = IsInInstance() if instanceType ~= "none" then --We need to update headers when we zone into an instance UF:UpdateAllHeaders() end end end end function UF:UnitFrameThreatIndicator_Initialize(_, unitFrame) unitFrame:UnregisterAllEvents() --Arena Taint Fix end function UF:ResetUnitSettings(unit) E:CopyTable(self.db.units[unit], P.unitframe.units[unit]) if self.db.units[unit].buffs and self.db.units[unit].buffs.sizeOverride then self.db.units[unit].buffs.sizeOverride = P.unitframe.units[unit].buffs.sizeOverride or 0 end if self.db.units[unit].debuffs and self.db.units[unit].debuffs.sizeOverride then self.db.units[unit].debuffs.sizeOverride = P.unitframe.units[unit].debuffs.sizeOverride or 0 end self:Update_AllFrames() end function UF:ToggleForceShowGroupFrames(unitGroup, numGroup) for i = 1, numGroup do if self[unitGroup..i] and not self[unitGroup..i].isForced then UF:ForceShow(self[unitGroup..i]) elseif self[unitGroup..i] then UF:UnforceShow(self[unitGroup..i]) end end end local ignoreSettings = { ["position"] = true, ["priority"] = true } local ignoreSettingsGroup = { ["visibility"] = true } local allowPass = { ["sizeOverride"] = true } function UF:MergeUnitSettings(fromUnit, toUnit, isGroupUnit) local db = self.db.units local filter = ignoreSettings if isGroupUnit then filter = ignoreSettingsGroup end if fromUnit ~= toUnit then for option, value in pairs(db[fromUnit]) do if type(value) ~= "table" and not filter[option] then if db[toUnit][option] ~= nil then db[toUnit][option] = value end elseif not filter[option] then if type(value) == "table" then for opt, val in pairs(db[fromUnit][option]) do --local val = db[fromUnit][option][opt] if type(val) ~= "table" and not filter[opt] then if db[toUnit][option] ~= nil and (db[toUnit][option][opt] ~= nil or allowPass[opt]) then db[toUnit][option][opt] = val end elseif not filter[opt] then if type(val) == "table" then for o, v in pairs(db[fromUnit][option][opt]) do if not filter[o] then if db[toUnit][option] ~= nil and db[toUnit][option][opt] ~= nil and db[toUnit][option][opt][o] ~= nil then db[toUnit][option][opt][o] = v end end end end end end end end end else E:Print(L["You cannot copy settings from the same unit."]) end self:Update_AllFrames() end function UF:UpdateBackdropTextureColor(r, g, b) local m = 0.35 local n = self.isTransparent and (m * 2) or m if self.invertColors then local nn = n;n=m;m=nn end if self.isTransparent then if self.backdrop then local _, _, _, a = self.backdrop:GetBackdropColor() self.backdrop:SetBackdropColor(r * n, g * n, b * n, a) else local parent = self:GetParent() if parent and parent.template then local _, _, _, a = parent:GetBackdropColor() parent:SetBackdropColor(r * n, g * n, b * n, a) end end end local bg = self.bg or self.BG if bg and bg:IsObjectType("Texture") and not bg.multiplier then if self.custom_backdrop then bg:SetVertexColor(self.custom_backdrop.r, self.custom_backdrop.g, self.custom_backdrop.b) else bg:SetVertexColor(r * m, g * m, b * m) end end end function UF:UpdatePredictionStatusBar(prediction, parent) if not (prediction and parent) then return end local texture = (not parent.isTransparent and parent:GetStatusBarTexture():GetTexture()) or E.media.blankTex UF:Update_StatusBar(prediction.myBar, texture) UF:Update_StatusBar(prediction.otherBar, texture) end function UF:SetStatusBarBackdropPoints(statusBar, statusBarTex, backdropTex, statusBarOrientation) backdropTex:ClearAllPoints() if statusBarOrientation == "VERTICAL" then backdropTex:SetPoint("TOPLEFT", statusBar) backdropTex:SetPoint("BOTTOMRIGHT", statusBarTex, "TOPRIGHT") else backdropTex:SetPoint("TOPRIGHT", statusBar) backdropTex:SetPoint("BOTTOMLEFT", statusBarTex, "BOTTOMRIGHT") end end function UF:ToggleTransparentStatusBar(isTransparent, statusBar, backdropTex, adjustBackdropPoints, invertColors) statusBar.isTransparent = isTransparent statusBar.invertColors = invertColors statusBar.backdropTex = backdropTex local statusBarTex = statusBar:GetStatusBarTexture() local statusBarOrientation = statusBar:GetOrientation() if not statusBar.hookedColor then hooksecurefunc(statusBar, "SetStatusBarColor", UF.UpdateBackdropTextureColor) statusBar.hookedColor = true end if isTransparent then if statusBar.backdrop then statusBar.backdrop:SetTemplate("Transparent", nil, nil, nil, true) elseif statusBar:GetParent().template then statusBar:GetParent():SetTemplate("Transparent", nil, nil, nil, true) end statusBar:SetStatusBarTexture("") UF:Update_StatusBar(statusBar.bg or statusBar.BG, E.media.blankTex) if statusBar.texture then statusBar.texture = statusBar:GetStatusBarTexture() end --Needed for Power element UF:SetStatusBarBackdropPoints(statusBar, statusBarTex, backdropTex, statusBarOrientation) else if statusBar.backdrop then statusBar.backdrop:SetTemplate(nil, nil, nil, not statusBar.PostCastStart and self.thinBorders, true) elseif statusBar:GetParent().template then statusBar:GetParent():SetTemplate(nil, nil, nil, self.thinBorders, true) end local texture = LSM:Fetch("statusbar", self.db.statusbar) statusBar:SetStatusBarTexture(texture) UF:Update_StatusBar(statusBar.bg or statusBar.BG, texture) if statusBar.texture then statusBar.texture = statusBar:GetStatusBarTexture() end if adjustBackdropPoints then backdropTex:ClearAllPoints() backdropTex:SetAllPoints(statusBar) end end end function UF:Initialize() self.db = E.db.unitframe self.thinBorders = self.db.thinBorders or E.PixelMode if E.private.unitframe.enable ~= true then return end self.Initialized = true local ElvUF_Parent = CreateFrame("Frame", "ElvUF_Parent", E.UIParent, "SecureHandlerStateTemplate") ElvUF_Parent:SetFrameStrata("LOW") self:UpdateColors() ElvUF:RegisterStyle("ElvUF", function(frame, unit) self:Construct_UF(frame, unit) end) self:LoadUnits() self:RegisterEvent("PLAYER_ENTERING_WORLD") for k in pairs(UnitPopupMenus) do for x, y in pairs(UnitPopupMenus[k]) do if y == "SET_FOCUS" or y == "CLEAR_FOCUS" or y == "LOCK_FOCUS_FRAME" or y == "UNLOCK_FOCUS_FRAME" then tremove(UnitPopupMenus[k], x) end end end if CompactUnitMixin then hooksecurefunc(CompactUnitMixin, "SetUpFrame", UF.DisableBlizzard_SetUpFrame) hooksecurefunc(CompactUnitMixin, "SetUnit", UF.DisableBlizzard_SetUnit) end -- The CoA client's reworked options panels may omit these legacy -- InterfaceOptions* widgets; guard every access so a missing global -- cannot abort UnitFrames initialisation. if E.private.unitframe.disabledBlizzardFrames.arena and E.private.unitframe.disabledBlizzardFrames.focus and E.private.unitframe.disabledBlizzardFrames.party then if InterfaceOptionsFrameCategoriesButton10 then InterfaceOptionsFrameCategoriesButton10:SetScale(0.0001) end end if E.private.unitframe.disabledBlizzardFrames.player then if InterfaceOptionsStatusTextPanelPlayer then InterfaceOptionsStatusTextPanelPlayer:SetScale(0.0001) InterfaceOptionsStatusTextPanelPlayer:SetAlpha(0) end if InterfaceOptionsStatusTextPanelPet then InterfaceOptionsStatusTextPanelPet:SetScale(0.0001) InterfaceOptionsStatusTextPanelPet:SetAlpha(0) end end if E.private.unitframe.disabledBlizzardFrames.target then if InterfaceOptionsStatusTextPanelTarget then InterfaceOptionsStatusTextPanelTarget:SetScale(0.0001) InterfaceOptionsStatusTextPanelTarget:SetAlpha(0) end if InterfaceOptionsCombatPanelEnemyCastBarsOnPortrait and InterfaceOptionsCombatPanelEnemyCastBarsOnNameplates then InterfaceOptionsCombatPanelEnemyCastBarsOnPortrait:SetAlpha(0) InterfaceOptionsCombatPanelEnemyCastBarsOnPortrait:EnableMouse(false) InterfaceOptionsCombatPanelEnemyCastBarsOnNameplates:ClearAllPoints() InterfaceOptionsCombatPanelEnemyCastBarsOnNameplates:Point(InterfaceOptionsCombatPanelEnemyCastBarsOnPortrait:GetPoint()) end if InterfaceOptionsCombatPanelTargetOfTarget then InterfaceOptionsCombatPanelTargetOfTarget:SetScale(0.0001) InterfaceOptionsCombatPanelTargetOfTarget:SetAlpha(0) end if InterfaceOptionsDisplayPanelShowAggroPercentage then InterfaceOptionsDisplayPanelShowAggroPercentage:SetScale(0.0001) InterfaceOptionsDisplayPanelShowAggroPercentage:SetAlpha(0) end end if E.private.unitframe.disabledBlizzardFrames.party then if InterfaceOptionsStatusTextPanelParty then InterfaceOptionsStatusTextPanelParty:SetScale(0.0001) InterfaceOptionsStatusTextPanelParty:SetAlpha(0) end if InterfaceOptionsFrameCategoriesButton11 then InterfaceOptionsFrameCategoriesButton11:SetScale(0.0001) end end if E.private.unitframe.disabledBlizzardFrames.arena then self:SecureHook("UnitFrameThreatIndicator_Initialize") if not IsAddOnLoaded("Blizzard_ArenaUI") then self:RegisterEvent("ADDON_LOADED") else ElvUF:DisableBlizzard("arena") end end local ORD = ns.oUF_RaidDebuffs or oUF_RaidDebuffs if ORD then ORD.ShowDispellableDebuff = true ORD.MatchBySpellName = true end self:UpdateRangeCheckSpells() self:RegisterEvent("LEARNED_SPELL_IN_TAB", "UpdateRangeCheckSpells") end local function InitializeCallback() UF:Initialize() end E:RegisterInitialModule(UF:GetName(), InitializeCallback)