From d96efe67ff19d35fde9f341e2fc1139fe3cb24b4 Mon Sep 17 00:00:00 2001 From: Wurmschwanz Date: Tue, 8 Sep 2026 22:00:17 +0200 Subject: [PATCH] Delete core directory --- core/bridge.lua | 10 - core/compat_shagutweaks.lua | 94 -- core/config.lua | 393 -------- core/core.lua | 43 - core/libnameplate.lua | 173 ---- core/options.lua | 1696 ----------------------------------- core/ui.lua | 15 - 7 files changed, 2424 deletions(-) delete mode 100644 core/bridge.lua delete mode 100644 core/compat_shagutweaks.lua delete mode 100644 core/config.lua delete mode 100644 core/core.lua delete mode 100644 core/libnameplate.lua delete mode 100644 core/options.lua delete mode 100644 core/ui.lua diff --git a/core/bridge.lua b/core/bridge.lua deleted file mode 100644 index 3921255..0000000 --- a/core/bridge.lua +++ /dev/null @@ -1,10 +0,0 @@ -BNP = BNP or {} - -function BNP:RegisterPlate(plate) - plate = plate or this - if not plate then return end - if BNP.plates[plate] then return end - - BNP.plates[plate] = true - BNP.detected = BNP.detected + 1 -end diff --git a/core/compat_shagutweaks.lua b/core/compat_shagutweaks.lua deleted file mode 100644 index a4ccf97..0000000 --- a/core/compat_shagutweaks.lua +++ /dev/null @@ -1,94 +0,0 @@ -BNP = BNP or {} - --- Robust ShaguTweaks compatibility. --- BNP owns Scale / Class Colors / Castbar while loaded. --- ShaguTweaks settings are NOT changed. - -BNP.shaguCompat = BNP.shaguCompat or { - patched = {}, - registerHooked = false, -} - -local wanted = { - ["Nameplate Scale"] = true, - ["Nameplate Class Colors"] = true, - ["Nameplate Castbar"] = true, -} - -local function IsWantedTitle(title) - if not title then return false end - - if wanted[title] then return true end - - if ShaguTweaks and ShaguTweaks.T then - if title == ShaguTweaks.T["Nameplate Scale"] then return true end - if title == ShaguTweaks.T["Nameplate Class Colors"] then return true end - if title == ShaguTweaks.T["Nameplate Castbar"] then return true end - end - - return false -end - -local function DisableModule(mod) - if not mod or type(mod) ~= "table" then return false end - if not IsWantedTitle(mod.title) then return false end - if mod.BNPCompatibilityPatched then return true end - - mod.BNPOriginalEnable = mod.enable - mod.enable = function(self) - return - end - - mod.BNPCompatibilityPatched = true - BNP.shaguCompat.patched[mod.title or "?"] = true - return true -end - -local function PatchExistingModules() - if not ShaguTweaks or not ShaguTweaks.mods then return end - - local title, mod - for title, mod in pairs(ShaguTweaks.mods) do - -- Some registered module tables use localized title as the map key. - if mod and not mod.title then mod.title = title end - DisableModule(mod) - end -end - -local function HookRegister() - if not ShaguTweaks or not ShaguTweaks.register then return end - if BNP.shaguCompat.registerHooked then return end - - local originalRegister = ShaguTweaks.register - - ShaguTweaks.register = function(self, mod) - local registered = originalRegister(self, mod) - DisableModule(registered or mod) - return registered - end - - BNP.shaguCompat.registerHooked = true -end - -function BNP:ApplyShaguTweaksCompatibility() - if not ShaguTweaks then return false end - - -- Covers BNP loading before Shagu's modules register. - HookRegister() - - -- Covers BNP loading after Shagu's modules registered. - PatchExistingModules() - - return true -end - --- Try immediately in case ShaguTweaks is already loaded. -BNP:ApplyShaguTweaksCompatibility() - --- Also retry after every addon load. This safely covers all Vanilla/Turtle --- load-order variations without touching ShaguTweaks saved settings. -local loader = CreateFrame("Frame") -loader:RegisterEvent("ADDON_LOADED") -loader:SetScript("OnEvent", function() - BNP:ApplyShaguTweaksCompatibility() -end) diff --git a/core/config.lua b/core/config.lua deleted file mode 100644 index c24fba1..0000000 --- a/core/config.lua +++ /dev/null @@ -1,393 +0,0 @@ -BNP = BNP or {} - -BNP.defaults = BNP.defaults or { - nameplateScale = 1.0, - nameplateYOffset = 0, - comboPointsYOffset = 0, - nameFontSize = 12, - nameFontYOffset = 0, - nonTargetAlpha = 1.0, - iconSize = 18, - ccIconSize = 18, - debuffYOffset = 0, - ccYOffset = 0, - debuffPosition = "top", - ccPosition = "top", - tankMode = false, - classColors = true, - hidePlayerNames = false, - hideNPCNames = false, - castbars = true, - debuffs = true, - crowdControl = true, - separateCCRow = true, - showOtherCCs = true, - pvpImmunities = true, - immunityIconSize = 18, - immunityPosition = "top", - immunityYOffset = 0, - castbarHeight = 6, - castbarSpacing = 4, - minimapAngle = 225, - healthPercent = false, - healthText = "off", - healthTextFontSize = 9, - healthTextOutline = "outline", - targetFocus = true, - targetGlowColor = "white", - targetGlowSize = 0, - targetGlowOpacity = 1.0, - targetArrows = false, - targetArrowColor = "match", - targetArrowSize = 14, - targetArrowThick = false, - targetArrowStyle = "chevron", - comboPoints = true, - totemIndicators = true, - totemIconSize = 24, -} - -function BNP:InitConfig() - BNP_DB = BNP_DB or {} - - if BNP_DB.nameplateScale == nil then BNP_DB.nameplateScale = self.defaults.nameplateScale end - if BNP_DB.nameplateYOffset == nil then BNP_DB.nameplateYOffset = self.defaults.nameplateYOffset end - if BNP_DB.comboPointsYOffset == nil then BNP_DB.comboPointsYOffset = self.defaults.comboPointsYOffset end - -- nameFontSize intentionally stays nil until the user moves the slider. - -- This preserves the exact font size provided by Blizzard/skin addons on update. - if BNP_DB.nameFontYOffset == nil then BNP_DB.nameFontYOffset = self.defaults.nameFontYOffset end - if BNP_DB.nonTargetAlpha == nil then BNP_DB.nonTargetAlpha = self.defaults.nonTargetAlpha end - if BNP_DB.iconSize == nil then BNP_DB.iconSize = self.defaults.iconSize end - if BNP_DB.ccIconSize == nil then BNP_DB.ccIconSize = BNP_DB.iconSize or self.defaults.ccIconSize end - if BNP_DB.debuffYOffset == nil then BNP_DB.debuffYOffset = self.defaults.debuffYOffset end - if BNP_DB.ccYOffset == nil then BNP_DB.ccYOffset = self.defaults.ccYOffset end - if BNP_DB.debuffPosition == nil then BNP_DB.debuffPosition = self.defaults.debuffPosition end - if BNP_DB.ccPosition == nil then BNP_DB.ccPosition = BNP_DB.debuffPosition or self.defaults.ccPosition end - if BNP_DB.tankMode == nil then BNP_DB.tankMode = self.defaults.tankMode end - if BNP_DB.classColors == nil then BNP_DB.classColors = self.defaults.classColors end - if BNP_DB.hidePlayerNames == nil then BNP_DB.hidePlayerNames = self.defaults.hidePlayerNames end - if BNP_DB.hideNPCNames == nil then BNP_DB.hideNPCNames = self.defaults.hideNPCNames end - if BNP_DB.castbars == nil then BNP_DB.castbars = self.defaults.castbars end - if BNP_DB.debuffs == nil then BNP_DB.debuffs = self.defaults.debuffs end - if BNP_DB.crowdControl == nil then BNP_DB.crowdControl = (BNP_DB.debuffs ~= false) and true or false end - if BNP_DB.separateCCRow == nil then BNP_DB.separateCCRow = self.defaults.separateCCRow end - if BNP_DB.showOtherCCs == nil then BNP_DB.showOtherCCs = self.defaults.showOtherCCs end - if BNP_DB.pvpImmunities == nil then BNP_DB.pvpImmunities = self.defaults.pvpImmunities end - if BNP_DB.immunityIconSize == nil then BNP_DB.immunityIconSize = BNP_DB.iconSize or self.defaults.immunityIconSize end - if BNP_DB.immunityPosition == nil then BNP_DB.immunityPosition = self.defaults.immunityPosition end - if BNP_DB.immunityYOffset == nil then BNP_DB.immunityYOffset = self.defaults.immunityYOffset end - -- Position migration from the temporary all-Bottom test build. - if BNP_DB.debuffPosition == "bottom" then BNP_DB.debuffPosition = "bottom_mid" end - if BNP_DB.ccPosition == "bottom" then BNP_DB.ccPosition = "top" end - if BNP_DB.immunityPosition == "bottom" then BNP_DB.immunityPosition = "top" end - if BNP_DB.castbarHeight == nil then BNP_DB.castbarHeight = self.defaults.castbarHeight end - if BNP_DB.castbarSpacing == nil then BNP_DB.castbarSpacing = self.defaults.castbarSpacing end - if BNP_DB.minimapAngle == nil then BNP_DB.minimapAngle = self.defaults.minimapAngle end - if BNP_DB.healthPercent == nil then BNP_DB.healthPercent = self.defaults.healthPercent end - if BNP_DB.healthText == nil then - -- Backwards-compatible migration from the old Health % checkbox. - BNP_DB.healthText = BNP_DB.healthPercent and "percent" or self.defaults.healthText - end - if BNP_DB.healthTextFontSize == nil then BNP_DB.healthTextFontSize = self.defaults.healthTextFontSize end - if BNP_DB.healthTextOutline == nil then BNP_DB.healthTextOutline = self.defaults.healthTextOutline end - if BNP_DB.targetFocus == nil then BNP_DB.targetFocus = self.defaults.targetFocus end - if BNP_DB.targetGlowColor == nil then BNP_DB.targetGlowColor = self.defaults.targetGlowColor end - if BNP_DB.targetGlowSize == nil then BNP_DB.targetGlowSize = self.defaults.targetGlowSize end - if BNP_DB.targetGlowOpacity == nil then BNP_DB.targetGlowOpacity = self.defaults.targetGlowOpacity end - if BNP_DB.targetArrows == nil then BNP_DB.targetArrows = self.defaults.targetArrows end - if BNP_DB.targetArrowColor == nil then BNP_DB.targetArrowColor = self.defaults.targetArrowColor end - if BNP_DB.targetArrowSize == nil then BNP_DB.targetArrowSize = self.defaults.targetArrowSize end - if BNP_DB.targetArrowThick == nil then BNP_DB.targetArrowThick = self.defaults.targetArrowThick end - if BNP_DB.targetArrowStyle == nil then BNP_DB.targetArrowStyle = self.defaults.targetArrowStyle end - if BNP_DB.comboPoints == nil then BNP_DB.comboPoints = self.defaults.comboPoints end - if BNP_DB.totemIndicators == nil then BNP_DB.totemIndicators = self.defaults.totemIndicators end - if BNP_DB.totemIconSize == nil then BNP_DB.totemIconSize = self.defaults.totemIconSize end -end - -function BNP:GetNameplateScale() - return (BNP_DB and tonumber(BNP_DB.nameplateScale)) or self.defaults.nameplateScale -end - -function BNP:GetNameplateYOffset() - local value = (BNP_DB and tonumber(BNP_DB.nameplateYOffset)) or self.defaults.nameplateYOffset or 0 - if value < 0 then value = 0 end - if value > 50 then value = 50 end - return value -end - - -local function ClampVisualYOffset(value) - value = tonumber(value) or 0 - if value < -50 then value = -50 end - if value > 50 then value = 50 end - return value >= 0 and math.floor(value + 0.5) or math.ceil(value - 0.5) -end - -function BNP:GetComboPointsYOffset() - return ClampVisualYOffset(BNP_DB and BNP_DB.comboPointsYOffset or self.defaults.comboPointsYOffset) -end - -function BNP:GetNameFontSize() - local explicit = BNP_DB and tonumber(BNP_DB.nameFontSize) - local value = explicit or tonumber(self.defaultNameFontSize) or self.defaults.nameFontSize or 12 - if value < 8 then value = 8 end - if value > 24 then value = 24 end - return math.floor(value + 0.5) -end - -function BNP:GetNameFontYOffset() - return ClampVisualYOffset(BNP_DB and BNP_DB.nameFontYOffset or self.defaults.nameFontYOffset) -end - -function BNP:GetDebuffYOffset() - return ClampVisualYOffset(BNP_DB and BNP_DB.debuffYOffset or self.defaults.debuffYOffset) -end - -function BNP:GetCCYOffset() - return ClampVisualYOffset(BNP_DB and BNP_DB.ccYOffset or self.defaults.ccYOffset) -end - -function BNP:GetImmunityYOffset() - return ClampVisualYOffset(BNP_DB and BNP_DB.immunityYOffset or self.defaults.immunityYOffset) -end - -function BNP:GetNonTargetAlpha() - local value = (BNP_DB and tonumber(BNP_DB.nonTargetAlpha)) or self.defaults.nonTargetAlpha or 1.0 - if value < 0.30 then value = 0.30 end - if value > 1.00 then value = 1.00 end - return value -end - -function BNP:GetIconSize() - return (BNP_DB and tonumber(BNP_DB.iconSize)) or self.defaults.iconSize -end - -function BNP:GetCCIconSize() - local value = (BNP_DB and tonumber(BNP_DB.ccIconSize)) or self.defaults.ccIconSize or self:GetIconSize() - if value < 12 then value = 12 end - if value > 32 then value = 32 end - return value -end - -function BNP:GetDebuffPosition() - local position = (BNP_DB and BNP_DB.debuffPosition) or self.defaults.debuffPosition or "top" - -- Migrate the first Bottom implementation to the new centered Bottom option. - if position == "bottom" then position = "bottom_mid" end - if position ~= "top" and position ~= "top_left" and position ~= "top_right" - and position ~= "left" and position ~= "right" - and position ~= "bottom_mid" and position ~= "bottom_left" and position ~= "bottom_right" then - position = "top" - end - return position -end - -function BNP:GetCCPosition() - local position = (BNP_DB and BNP_DB.ccPosition) or self.defaults.ccPosition or "top" - -- Bottom is intentionally not supported for CCs. - if position ~= "top" and position ~= "left" and position ~= "right" then - position = "top" - end - return position -end - -function BNP:GetImmunityIconSize() - local value = (BNP_DB and tonumber(BNP_DB.immunityIconSize)) or self.defaults.immunityIconSize or self:GetIconSize() - if value < 12 then value = 12 end - if value > 32 then value = 32 end - return value -end - -function BNP:GetImmunityPosition() - local position = (BNP_DB and BNP_DB.immunityPosition) or self.defaults.immunityPosition or "top" - -- Bottom is intentionally not supported for immunities. - if position ~= "top" and position ~= "left" and position ~= "right" then - position = "top" - end - return position -end - - -function BNP:IsTankModeEnabled() - return BNP_DB and BNP_DB.tankMode and true or false -end - -function BNP:AreClassColorsEnabled() - return not BNP_DB or BNP_DB.classColors ~= false -end - -function BNP:HidePlayerNamesEnabled() - return BNP_DB and BNP_DB.hidePlayerNames and true or false -end - -function BNP:HideNPCNamesEnabled() - return BNP_DB and BNP_DB.hideNPCNames and true or false -end - -function BNP:AreCastbarsEnabled() - return not BNP_DB or BNP_DB.castbars ~= false -end - -function BNP:GetCastbarHeight() - local value = (BNP_DB and tonumber(BNP_DB.castbarHeight)) or self.defaults.castbarHeight - if value < 4 then value = 4 end - if value > 14 then value = 14 end - return value -end - -function BNP:GetCastbarSpacing() - local value = (BNP_DB and tonumber(BNP_DB.castbarSpacing)) or self.defaults.castbarSpacing or 4 - if value < 0 then value = 0 end - if value > 10 then value = 10 end - return value -end - -function BNP:GetHealthTextMode() - local mode = (BNP_DB and BNP_DB.healthText) or self.defaults.healthText or "off" - if mode ~= "off" and mode ~= "percent" and mode ~= "hp" and mode ~= "both" then - mode = "off" - end - return mode -end - -function BNP:IsHealthPercentEnabled() - local mode = self:GetHealthTextMode() - return mode == "percent" or mode == "both" -end - -function BNP:IsHealthTextEnabled() - return self:GetHealthTextMode() ~= "off" -end - -function BNP:GetHealthTextFontSize() - local value = (BNP_DB and tonumber(BNP_DB.healthTextFontSize)) or self.defaults.healthTextFontSize or 9 - if value < 8 then value = 8 end - if value > 20 then value = 20 end - return math.floor(value + 0.5) -end - -function BNP:GetHealthTextOutline() - local value = (BNP_DB and BNP_DB.healthTextOutline) or self.defaults.healthTextOutline or "outline" - if value ~= "none" and value ~= "outline" and value ~= "thick" then - value = "outline" - end - return value -end - -function BNP:IsTargetFocusEnabled() - return not BNP_DB or BNP_DB.targetFocus ~= false -end - -function BNP:GetTargetGlowColor() - local key = (BNP_DB and BNP_DB.targetGlowColor) or self.defaults.targetGlowColor or "white" - - local colors = { - white = { 1.00, 1.00, 1.00 }, - gold = { 1.00, 0.82, 0.10 }, - blue = { 0.25, 0.55, 1.00 }, - green = { 0.25, 1.00, 0.35 }, - red = { 1.00, 0.20, 0.20 }, - purple = { 0.75, 0.35, 1.00 }, - } - - local c = colors[key] or colors.white - return c[1], c[2], c[3], key -end - - -function BNP:GetTargetGlowSize() - local value = (BNP_DB and tonumber(BNP_DB.targetGlowSize)) or self.defaults.targetGlowSize or 0 - if value < 0 then value = 0 end - if value > 20 then value = 20 end - return value -end - -function BNP:GetTargetGlowOpacity() - local value = (BNP_DB and tonumber(BNP_DB.targetGlowOpacity)) or self.defaults.targetGlowOpacity or 1.0 - if value < 0.20 then value = 0.20 end - if value > 1.00 then value = 1.00 end - return value -end - -function BNP:AreTargetArrowsEnabled() - return BNP_DB and BNP_DB.targetArrows == true -end - -function BNP:GetTargetArrowColor() - local key = (BNP_DB and BNP_DB.targetArrowColor) or self.defaults.targetArrowColor or "match" - if key == "match" then - local r, g, b = self:GetTargetGlowColor() - return r, g, b, key - end - - local colors = { - white = { 1.00, 1.00, 1.00 }, - gold = { 1.00, 0.82, 0.10 }, - blue = { 0.25, 0.55, 1.00 }, - green = { 0.25, 1.00, 0.35 }, - red = { 1.00, 0.20, 0.20 }, - purple = { 0.75, 0.35, 1.00 }, - } - - local c = colors[key] or colors.white - return c[1], c[2], c[3], key -end - -function BNP:GetTargetArrowSize() - local value = (BNP_DB and tonumber(BNP_DB.targetArrowSize)) or self.defaults.targetArrowSize or 14 - if value < 10 then value = 10 end - if value > 24 then value = 24 end - return value -end - -function BNP:AreTargetArrowsThick() - return BNP_DB and BNP_DB.targetArrowThick == true -end - -function BNP:GetTargetArrowStyle() - local style = (BNP_DB and BNP_DB.targetArrowStyle) or self.defaults.targetArrowStyle or "chevron" - if style ~= "chevron" and style ~= "triangle" and style ~= "slim_triangle" - and style ~= "double_chevron" and style ~= "diamond_tip" then - style = "chevron" - end - return style -end - -function BNP:AreComboPointsEnabled() - return not BNP_DB or BNP_DB.comboPoints ~= false -end - -function BNP:AreTotemIndicatorsEnabled() - return not BNP_DB or BNP_DB.totemIndicators ~= false -end - -function BNP:GetTotemIconSize() - local value = (BNP_DB and tonumber(BNP_DB.totemIconSize)) or self.defaults.totemIconSize or 24 - if value < 16 then value = 16 end - if value > 36 then value = 36 end - return value -end - - -function BNP:AreDebuffsEnabled() - return not BNP_DB or BNP_DB.debuffs ~= false -end - -function BNP:AreCrowdControlEnabled() - return not BNP_DB or BNP_DB.crowdControl ~= false -end - -function BNP:AreAnyAurasEnabled() - return self:AreDebuffsEnabled() or self:AreCrowdControlEnabled() -end - -function BNP:IsSeparateCCRowEnabled() - return not BNP_DB or BNP_DB.separateCCRow ~= false -end - -function BNP:ShowOtherPlayersCCs() - return not BNP_DB or BNP_DB.showOtherCCs ~= false -end - -function BNP:ArePvPImmunitiesEnabled() - return not BNP_DB or BNP_DB.pvpImmunities ~= false -end diff --git a/core/core.lua b/core/core.lua deleted file mode 100644 index bfd2d99..0000000 --- a/core/core.lua +++ /dev/null @@ -1,43 +0,0 @@ -BNP = BNP or {} -BNP.version = "1.0.9" -BNP.plates = BNP.plates or {} -BNP.detected = 0 -BNP.debugEnabled = false - -function BNP:Print(msg) - if DEFAULT_CHAT_FRAME then - DEFAULT_CHAT_FRAME:AddMessage("|cff33ff99Blizz Nameplates+:|r " .. tostring(msg)) - end -end - -local eventFrame = CreateFrame("Frame") -eventFrame:RegisterEvent("VARIABLES_LOADED") -eventFrame:SetScript("OnEvent", function() - BNP_DB = BNP_DB or {} - - if BNP.InitConfig then BNP:InitConfig() end - if BNP.CreateMinimapButton then BNP:CreateMinimapButton() end - if BNP.InstallTankMode then BNP:InstallTankMode() end - - if BNP_DB.debugEnabled == nil then BNP_DB.debugEnabled = false end - BNP.debugEnabled = BNP_DB.debugEnabled - - local classicNameplates = CLASSIC_API_VERSION and C_NamePlate and - type(C_NamePlate.GetNamePlateForUnit) == "function" - - if CombatLogAdd and SpellInfo and classicNameplates then - BNP:Print(BNP.version .. " loaded. SuperWoW + ClassicAPI nameplate tracking active.") - BNP:Print("Dragon command test build loaded.") - if ShaguTweaks then - BNP:ApplyShaguTweaksCompatibility() - local count = 0 - local k - for k in pairs(BNP.shaguCompat.patched or {}) do count = count + 1 end - BNP:Print("ShaguTweaks compatibility active (" .. tostring(count) .. "/3 nameplate modules suppressed).") - end - elseif not CombatLogAdd or not SpellInfo then - BNP:Print("ERROR: SuperWoW API not detected. Blizz Nameplates+ requires SuperWoW.") - else - BNP:Print("ERROR: ClassicAPI nameplate API not detected. Please update ClassicAPI.dll.") - end -end) diff --git a/core/libnameplate.lua b/core/libnameplate.lua deleted file mode 100644 index 3991b27..0000000 --- a/core/libnameplate.lua +++ /dev/null @@ -1,173 +0,0 @@ -BNP = BNP or {} - -BNP.libnameplate = BNP.libnameplate or { - OnInit = {}, - OnShow = {}, - OnUpdate = {}, -} - -local lib = BNP.libnameplate -local known = {} -local initializedChildren = 0 - -local function FindHealthBar(frame) - if not frame or not frame.GetChildren then return nil end - - local children = { frame:GetChildren() } - local i - for i = 1, table.getn(children) do - local child = children[i] - if child and child.GetObjectType and child:GetObjectType() == "StatusBar" then - return child - end - end - - return nil -end - -local function IsNamePlate(frame) - if not frame or not frame.GetObjectType then return false end - if frame:GetObjectType() ~= "Button" then return false end - - -- Fast path for untouched Blizzard nameplates. - local firstRegion = frame:GetRegions() - if firstRegion and firstRegion.GetObjectType and firstRegion.GetTexture and - firstRegion:GetObjectType() == "Texture" and - firstRegion:GetTexture() == "Interface\\Tooltips\\Nameplate-Border" then - return true - end - - -- Compatibility fallback: some UI/skin addons replace, blank or hide the - -- native border before BNP's WorldFrame scan sees the plate. Do not make - -- nameplate discovery depend on a mutable texture path. - local replacement = frame.nameplate - local original = replacement and replacement.original - - -- Known replacement-overlay shape: the addon kept references to Blizzard's - -- original health/name/level objects even if it already reparented them. - if original and (original.health or original.healthbar) and - original.name and original.level then - return true - end - - -- Generic safe fallback. Keep the structural test deliberately strict to - -- avoid mistaking unrelated WorldFrame Buttons for nameplates. - if not firstRegion or not firstRegion.GetObjectType or - firstRegion:GetObjectType() ~= "Texture" then - return false - end - if not FindHealthBar(frame) then return false end - - local fontStrings = 0 - local regions = { frame:GetRegions() } - local i - for i = 1, table.getn(regions) do - local region = regions[i] - if region and region.GetObjectType and region:GetObjectType() == "FontString" then - fontStrings = fontStrings + 1 - if fontStrings >= 2 then return true end - end - end - - return false -end - -local function AttachPlateShortcuts(plate) - if plate.BNPShortcutsReady then return end - - -- Do not assume another addon left the native StatusBar as the first child. - local replacement = plate.nameplate - local original = replacement and replacement.original - plate.healthbar = (original and (original.health or original.healthbar)) or - FindHealthBar(plate) - - -- Vanilla region order: - -- 1 border, 2 glow, 3 name, 4 level, 5 level icon, 6 raid icon. - -- Fall back to common replacement-overlay references only when direct native - -- regions are unavailable; normal Blizzard plates keep the exact old path. - local regions = { plate:GetRegions() } - plate.border = (original and original.border) or regions[1] - plate.glow = regions[2] or (original and original.glow) - plate.name = regions[3] or (original and original.name) - plate.level = regions[4] or (original and original.level) - plate.levelicon = regions[5] or (original and (original.levelicon or original.bossicon)) - plate.raidicon = regions[6] or (replacement and replacement.raidicon) or - (original and original.raidicon) - - plate.BNPShortcutsReady = true -end - -local function Fire(list, plate) - plate = plate or this - if not plate then return end - - local i - for i = 1, table.getn(list) do - if list[i] then - pcall(list[i], plate) - end - end -end - -local function RegisterPlate(plate) - plate = plate or this - if not plate then return end - if known[plate] then return end - known[plate] = true - - AttachPlateShortcuts(plate) - - if BNP.RegisterPlate then - BNP:RegisterPlate(plate) - end - - Fire(lib.OnInit, plate) - if plate:IsShown() then - Fire(lib.OnShow, plate) - end - - -- Run OnShow callbacks when Blizzard reuses the same plate. - local oldOnShow = plate:GetScript("OnShow") - plate:SetScript("OnShow", function(self) - local current = self or this or plate - if not current then return end - if oldOnShow then oldOnShow(current) end - AttachPlateShortcuts(current) - Fire(lib.OnShow, current) - end) -end - -local scanner = CreateFrame("Frame") -local scanElapsed = 0 - -scanner:SetScript("OnUpdate", function() - scanElapsed = scanElapsed + arg1 - if scanElapsed < 0.10 then return end - scanElapsed = 0 - - local count = WorldFrame:GetNumChildren() - - -- Full scan only when WorldFrame gained children. This mirrors the lightweight - -- discovery strategy used by Shagu's Vanilla nameplate code. - if count > initializedChildren then - local children = { WorldFrame:GetChildren() } - local i - for i = 1, table.getn(children) do - local frame = children[i] - if not known[frame] and IsNamePlate(frame) then - RegisterPlate(frame) - end - end - initializedChildren = count - end - - -- Compatibility callback list for modules that want a throttled plate update. - if table.getn(lib.OnUpdate) > 0 then - local plate - for plate in pairs(known) do - if plate:IsShown() then - Fire(lib.OnUpdate, plate) - end - end - end -end) diff --git a/core/options.lua b/core/options.lua deleted file mode 100644 index fe35e0f..0000000 --- a/core/options.lua +++ /dev/null @@ -1,1696 +0,0 @@ -BNP = BNP or {} - -local _, optionsPlayerClass = UnitClass("player") -local comboOptionsClass = (optionsPlayerClass == "ROGUE" or optionsPlayerClass == "DRUID") - -local function Round(value, step) - return math.floor((value / step) + 0.5) * step -end - -local function RoundSignedInteger(value) - value = tonumber(value) or 0 - if value >= 0 then return math.floor(value + 0.5) end - return math.ceil(value - 0.5) -end - -local sliderCount = 0 -local function CreateSlider(parent, label, minValue, maxValue, step, y, x, width) - sliderCount = sliderCount + 1 - local slider = CreateFrame("Slider", "BNPOptionsSlider" .. sliderCount, parent, "OptionsSliderTemplate") - slider:SetPoint("TOPLEFT", parent, "TOPLEFT", x or 28, y) - slider:SetWidth(width or 220) - slider:SetHeight(16) - slider:SetMinMaxValues(minValue, maxValue) - slider:SetValueStep(step) - getglobal(slider:GetName() .. "Low"):SetText(tostring(minValue)) - getglobal(slider:GetName() .. "High"):SetText(tostring(maxValue)) - getglobal(slider:GetName() .. "Text"):SetText(label) - return slider -end - -local function CreateCheck(parent, label, y, onclick, x) - local check = CreateFrame("CheckButton", nil, parent, "UICheckButtonTemplate") - check:SetPoint("TOPLEFT", parent, "TOPLEFT", x or 22, y) - check:SetWidth(24) - check:SetHeight(24) - - local text = parent:CreateFontString(nil, "OVERLAY", "GameFontNormal") - text:SetPoint("LEFT", check, "RIGHT", 4, 0) - text:SetText(label) - check.BNPLabel = text - - check:SetScript("OnClick", onclick) - return check -end - --- 1.12-safe emergency recorder ------------------------------------------------ --- --- Keep a compact recorder directly in this already proven options file. The --- full diagnostic module replaces BNP.OpenAuraRecorder later when it loads. --- If an old/private 1.12 client refuses that larger module, this fallback still --- provides the window and the ClassicAPI aura data we actually need. - -local emergency = BNP.emergencyAuraRecorder or {} -BNP.emergencyAuraRecorder = emergency -emergency.lines = emergency.lines or {} -emergency.active = false - -local function EmergencyValue(value, limit) - if value == nil then return "nil" end - local text = tostring(value) - text = string.gsub(text, "\r", "\\r") - text = string.gsub(text, "\n", "\\n") - text = string.gsub(text, "\t", "\\t") - limit = limit or 240 - if string.len(text) > limit then text = string.sub(text, 1, limit) .. "..." end - return text -end - -local function EmergencyAppend(text) - text = EmergencyValue(text, 1300) - if string.len(table.concat(emergency.lines, "\n")) + string.len(text) > 60000 then - if not emergency.limitHit then - table.insert(emergency.lines, "[REPORT LIMIT REACHED - recording stopped]") - emergency.limitHit = true - emergency.active = false - end - return - end - table.insert(emergency.lines, text) - emergency.dirty = true -end - -local function EmergencyFields(data) - if type(data) ~= "table" then return EmergencyValue(data) end - local fields = {} - local key, value - for key, value in pairs(data) do - local kind = type(value) - if kind ~= "table" and kind ~= "function" and kind ~= "userdata" then - table.insert(fields, EmergencyValue(key, 80) .. "=" .. EmergencyValue(value, 180)) - end - end - table.sort(fields) - return table.concat(fields, " | ") -end - -local function EmergencyGUID(unit) - local exists, guid = UnitExists(unit) - if exists and guid then return guid end - if UnitGUID then - local ok, value = pcall(UnitGUID, unit) - if ok then return value end - end - return nil -end - -local function EmergencyWantedAura(aura) - if type(aura) ~= "table" then return true end - local spellID = tonumber(aura.spellId or aura.spellID) - local name = string.lower(tostring(aura.name or "")) - if spellID == 17794 or spellID == 17797 or spellID == 17798 or spellID == 17799 or spellID == 17800 then return true end - if name == "shadow vulnerability" or name == "schattenverwundbarkeit" then return true end - - local playerGUID = EmergencyGUID("player") - if aura.sourceGUID and playerGUID then return aura.sourceGUID == playerGUID end - if aura.sourceUnit then return aura.sourceUnit == "player" end - return false -end - -local function EmergencyIsShadowBolt(spellID, spellName) - local numeric = tonumber(spellID) - if numeric == 686 or numeric == 695 or numeric == 705 or numeric == 1088 or - numeric == 1106 or numeric == 7641 or numeric == 11659 or numeric == 11660 or - numeric == 11661 or numeric == 25307 then return true end - local name = string.lower(tostring(spellName or "")) - return name == "shadow bolt" or name == "schattenblitz" -end - -local function EmergencyRefresh() - if not emergency.edit then return end - emergency.edit:SetText(table.concat(emergency.lines, "\n")) - emergency.edit:SetHeight(math.max(300, table.getn(emergency.lines) * 16 + 30)) - if emergency.status then - if emergency.active then - emergency.status:SetText("RECORDING | Target: " .. EmergencyValue(UnitName("target") or "none", 100)) - emergency.status:SetTextColor(0.2, 1, 0.35) - else - emergency.status:SetText("STOPPED | " .. tostring(table.getn(emergency.lines)) .. " lines") - emergency.status:SetTextColor(1, 0.82, 0) - end - end - emergency.dirty = false -end - -local function EmergencySnapshot(reason, force) - if not UnitExists("target") then - if force then EmergencyAppend("AURA_SNAPSHOT | reason=" .. reason .. " | no target") end - return - end - - local auraLines = {} - local signatureParts = {} - local count = 0 - local classic = type(C_UnitAuras) == "table" and type(C_UnitAuras.GetDebuffDataByIndex) == "function" - local i - - if classic then - for i = 1, 64 do - local ok, aura = pcall(C_UnitAuras.GetDebuffDataByIndex, "target", i) - if not ok then - EmergencyAppend("CLASSICAPI_ERROR | " .. EmergencyValue(aura, 800)) - break - end - if not aura then break end - if EmergencyWantedAura(aura) then - count = count + 1 - local fields = EmergencyFields(aura) - table.insert(signatureParts, fields) - table.insert(auraLines, " CLASSIC_AURA " .. tostring(i) .. " | " .. fields) - end - end - else - for i = 1, 64 do - local ok, texture, stacks, dispelType, spellID, r5, r6, r7, r8, r9, r10 = pcall(UnitDebuff, "target", i) - if not ok or not texture then break end - count = count + 1 - local fields = "spellId=" .. EmergencyValue(spellID) .. - " | stacks=" .. EmergencyValue(stacks) .. - " | type=" .. EmergencyValue(dispelType) .. - " | texture=" .. EmergencyValue(texture, 160) .. - " | r5=" .. EmergencyValue(r5) .. " | r6=" .. EmergencyValue(r6) .. - " | r7=" .. EmergencyValue(r7) .. " | r8=" .. EmergencyValue(r8) .. - " | r9=" .. EmergencyValue(r9) .. " | r10=" .. EmergencyValue(r10) - table.insert(signatureParts, fields) - table.insert(auraLines, " LEGACY_AURA " .. tostring(i) .. " | " .. fields) - end - end - - local signature = table.concat(signatureParts, "||") - if emergency.baselineOnly then - emergency.lastSignature = signature - return - end - if not force and signature == emergency.lastSignature then return end - emergency.lastSignature = signature - EmergencyAppend( - "[+" .. string.format("%.3f", GetTime() - (emergency.startedAt or GetTime())) .. "] AURA_SNAPSHOT" .. - " | reason=" .. EmergencyValue(reason) .. - " | guid=" .. EmergencyValue(EmergencyGUID("target")) .. - " | source=" .. (classic and "ClassicAPI" or "UnitDebuff") .. - " | count=" .. tostring(count) - ) - if count == 0 then - EmergencyAppend(" AURA none") - else - for i = 1, table.getn(auraLines) do EmergencyAppend(auraLines[i]) end - end -end - -local function EmergencyUnregister() - if emergency.eventFrame then pcall(emergency.eventFrame.UnregisterAllEvents, emergency.eventFrame) end -end - -local function EmergencyStop(reason) - if not emergency.active then EmergencyRefresh() return end - EmergencySnapshot("final", true) - emergency.active = false - EmergencyUnregister() - if emergency.frame then emergency.frame:SetScript("OnUpdate", nil) end - EmergencyAppend("=== END | reason=" .. EmergencyValue(reason or "user") .. " ===") - EmergencyRefresh() -end - -local function EmergencyStart() - EmergencyUnregister() - emergency.lines = {} - emergency.limitHit = false - emergency.lastSignature = nil - emergency.startedAt = GetTime() - emergency.elapsed = 0 - emergency.active = true - if emergency.frame and emergency.onUpdate then emergency.frame:SetScript("OnUpdate", emergency.onUpdate) end - EmergencyAppend("BNP_CLASSICAPI_AURA_REPORT v2") - EmergencyAppend( - "ClassicAPI | version=" .. EmergencyValue(CLASSIC_API_VERSION or "not detected") .. - " | C_UnitAuras=" .. ((type(C_UnitAuras) == "table" and type(C_UnitAuras.GetDebuffDataByIndex) == "function") and "yes" or "no") .. - " | CopyToClipboard=" .. (CopyToClipboard and "yes" or "no") - ) - EmergencyAppend("Aura filter | own auras + Shadow Vulnerability from any Warlock") - EmergencyAppend("Target | name=" .. EmergencyValue(UnitName("target")) .. " | guid=" .. EmergencyValue(EmergencyGUID("target"))) - EmergencyAppend("Test | proc aura, refresh it while active, then let it expire") - EmergencyAppend("=== LIVE RECORDING ===") - - local events = { - "UNIT_CASTEVENT", "UNIT_AURA", "PLAYER_TARGET_CHANGED", - "UNIT_SPELLCAST_SENT", "UNIT_SPELLCAST_START", "UNIT_SPELLCAST_STOP", - "UNIT_SPELLCAST_SUCCEEDED", "UNIT_SPELLCAST_CHANNEL_START", "UNIT_SPELLCAST_CHANNEL_STOP", - } - local i - for i = 1, table.getn(events) do pcall(emergency.eventFrame.RegisterEvent, emergency.eventFrame, events[i]) end - -- Learn the target's existing auras without printing them. Only changes - -- occurring after Start Recording belong in the diagnostic report. - emergency.baselineOnly = true - EmergencySnapshot("baseline", false) - emergency.baselineOnly = false - EmergencyRefresh() -end - -local function EmergencyCreateWindow() - if emergency.frame then return emergency.frame end - - local frame = CreateFrame("Frame", "BNPEmergencyAuraRecorderFrame", UIParent) - frame:SetWidth(720) - frame:SetHeight(520) - frame:SetPoint("CENTER", UIParent, "CENTER", 0, 20) - frame:SetFrameStrata("DIALOG") - frame:SetBackdrop({ - bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background", - edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border", - tile = true, tileSize = 32, edgeSize = 32, - insets = { left = 11, right = 12, top = 12, bottom = 11 } - }) - frame:SetMovable(true) - frame:EnableMouse(true) - frame:RegisterForDrag("LeftButton") - frame:SetScript("OnDragStart", function() this:StartMoving() end) - frame:SetScript("OnDragStop", function() this:StopMovingOrSizing() end) - frame:SetScript("OnHide", function() EmergencyStop("window closed") end) - emergency.frame = frame - - local title = frame:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge") - title:SetPoint("TOP", frame, "TOP", 0, -18) - title:SetText("Missing Spell / Aura Recorder") - - local status = frame:CreateFontString(nil, "OVERLAY", "GameFontNormal") - status:SetPoint("TOPLEFT", frame, "TOPLEFT", 26, -50) - status:SetWidth(660) - status:SetJustifyH("LEFT") - emergency.status = status - - local start = CreateFrame("Button", nil, frame, "UIPanelButtonTemplate") - start:SetPoint("TOPLEFT", frame, "TOPLEFT", 26, -76) - start:SetWidth(126) - start:SetHeight(24) - start:SetText("Start Recording") - start:SetScript("OnClick", EmergencyStart) - - local stop = CreateFrame("Button", nil, frame, "UIPanelButtonTemplate") - stop:SetPoint("LEFT", start, "RIGHT", 8, 0) - stop:SetWidth(82) - stop:SetHeight(24) - stop:SetText("Stop") - stop:SetScript("OnClick", function() EmergencyStop("user") end) - - local copy = CreateFrame("Button", nil, frame, "UIPanelButtonTemplate") - copy:SetPoint("LEFT", stop, "RIGHT", 8, 0) - copy:SetWidth(110) - copy:SetHeight(24) - copy:SetText(CopyToClipboard and "Copy Report" or "Select All") - copy:SetScript("OnClick", function() - EmergencyRefresh() - local report = table.concat(emergency.lines, "\n") - if CopyToClipboard and pcall(CopyToClipboard, report) then - emergency.status:SetText("COPIED | Paste with Ctrl+V") - emergency.status:SetTextColor(0.2, 1, 0.35) - else - emergency.edit:SetFocus() - emergency.edit:HighlightText() - emergency.status:SetText("SELECTED | Press Ctrl+C") - end - end) - - local close = CreateFrame("Button", nil, frame, "UIPanelCloseButton") - close:SetPoint("TOPRIGHT", frame, "TOPRIGHT", -5, -5) - - local scroll = CreateFrame("ScrollFrame", "BNPEmergencyAuraRecorderScroll", frame, "UIPanelScrollFrameTemplate") - scroll:SetPoint("TOPLEFT", frame, "TOPLEFT", 26, -112) - scroll:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -48, 30) - - local edit = CreateFrame("EditBox", "BNPEmergencyAuraRecorderEdit", scroll) - edit:SetWidth(640) - edit:SetHeight(300) - edit:SetMultiLine(true) - edit:SetAutoFocus(false) - edit:SetFontObject(ChatFontNormal) - edit:SetMaxLetters(65000) - edit:SetScript("OnEscapePressed", function() this:ClearFocus() end) - scroll:SetScrollChild(edit) - emergency.edit = edit - - emergency.eventFrame = CreateFrame("Frame", "BNPEmergencyAuraRecorderEvents") - emergency.eventFrame:SetScript("OnEvent", function() - if not emergency.active then return end - if event == "UNIT_AURA" and arg1 ~= "target" then return end - if event == "UNIT_CASTEVENT" and arg1 ~= EmergencyGUID("player") then return end - EmergencyAppend( - "[+" .. string.format("%.3f", GetTime() - emergency.startedAt) .. "] EVENT | " .. EmergencyValue(event) .. - " | a1=" .. EmergencyValue(arg1) .. " | a2=" .. EmergencyValue(arg2) .. - " | a3=" .. EmergencyValue(arg3) .. " | a4=" .. EmergencyValue(arg4) .. - " | a5=" .. EmergencyValue(arg5) .. " | a6=" .. EmergencyValue(arg6) - ) - emergency.forceSnapshot = event == "PLAYER_TARGET_CHANGED" or - (event == "UNIT_CASTEVENT" and EmergencyIsShadowBolt(arg4)) or - (event == "UNIT_SPELLCAST_SENT" and EmergencyIsShadowBolt(arg4, arg5)) or - (event ~= "UNIT_SPELLCAST_SENT" and string.find(tostring(event or ""), "UNIT_SPELLCAST_", 1, true) and EmergencyIsShadowBolt(arg3, arg4)) - end) - - emergency.onUpdate = function() - if not emergency.active then return end - emergency.elapsed = (emergency.elapsed or 0) + arg1 - if emergency.elapsed >= 0.12 then - emergency.elapsed = 0 - EmergencySnapshot(emergency.forceSnapshot and "event" or "poll", emergency.forceSnapshot) - emergency.forceSnapshot = false - if emergency.dirty then EmergencyRefresh() end - end - end - - return frame -end - --- This remains available even if the full recorder loads, so that module can --- fall back when a private client rejects one of the larger window calls. -function BNP:OpenEmergencyAuraRecorder() - local frame = EmergencyCreateWindow() - frame:Show() - EmergencyRefresh() -end - -function BNP:StartEmergencyAuraRecorder() - EmergencyStart() -end - --- This is intentionally defined before the large optional recorder module. --- A successful module load overwrites it; otherwise the button still works. -function BNP:OpenAuraRecorder() - self:OpenEmergencyAuraRecorder() -end - -function BNP:CreateOptions() - if self.optionsFrame then return end - - local frame = CreateFrame("Frame", "BNPOptionsFrame", UIParent) - frame:SetWidth(430) - frame:SetHeight(550) - frame:SetPoint("CENTER", UIParent, "CENTER", 0, 40) - frame:SetFrameStrata("DIALOG") - frame:SetBackdrop({ - bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background", - edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border", - tile = true, tileSize = 32, edgeSize = 32, - insets = { left = 11, right = 12, top = 12, bottom = 11 } - }) - frame:SetMovable(true) - frame:EnableMouse(true) - frame:RegisterForDrag("LeftButton") - frame:SetScript("OnDragStart", function() this:StartMoving() end) - frame:SetScript("OnDragStop", function() this:StopMovingOrSizing() end) - frame:Hide() - - local title = frame:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge") - title:SetPoint("TOP", frame, "TOP", 0, -18) - title:SetText("Blizz Nameplates+") - - local version = frame:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall") - version:SetPoint("TOP", title, "BOTTOM", 0, -4) - version:SetText("Version " .. tostring(BNP.version or "?")) - frame.versionText = version - - local close = CreateFrame("Button", nil, frame, "UIPanelCloseButton") - close:SetPoint("TOPRIGHT", frame, "TOPRIGHT", -5, -5) - - local function CreatePage() - local page = CreateFrame("Frame", nil, frame) - page:SetPoint("TOPLEFT", frame, "TOPLEFT", 18, -104) - page:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -18, 22) - page:Hide() - return page - end - - local function CreateSection(parent, label, y) - local text = parent:CreateFontString(nil, "OVERLAY", "GameFontNormal") - text:SetPoint("TOPLEFT", parent, "TOPLEFT", 8, y) - text:SetText(label) - - local line = parent:CreateTexture(nil, "ARTWORK") - line:SetTexture(1, 1, 1, 0.16) - line:SetPoint("LEFT", text, "RIGHT", 8, 0) - line:SetPoint("RIGHT", parent, "RIGHT", -8, 0) - line:SetHeight(1) - - return text - end - - local function SetCheckEnabled(check, enabled) - if not check then return end - if enabled then - if check.Enable then check:Enable() end - check:SetAlpha(1.0) - if check.BNPLabel then check.BNPLabel:SetTextColor(1, 0.82, 0) end - else - if check.Disable then check:Disable() end - check:SetAlpha(0.45) - if check.BNPLabel then check.BNPLabel:SetTextColor(0.5, 0.5, 0.5) end - end - end - - -- Compact tab navigation. Totems stays separate from aura tracking so PvP - -- nameplate indicators never touch the debuff/CC state machine. - frame.pages = { - nameplates = CreatePage(), - auras = CreatePage(), - totems = CreatePage(), - castbar = CreatePage(), - target = CreatePage(), - tools = CreatePage(), - } - frame.tabs = {} - - local tabDefs = { - { key = "nameplates", label = "Nameplates", width = 76 }, - { key = "auras", label = "Auras", width = 52 }, - { key = "totems", label = "Totems", width = 58 }, - { key = "castbar", label = "Castbar", width = 60 }, - { key = "target", label = "Target", width = 56 }, - { key = "tools", label = "Tools", width = 50 }, - } - - function frame:ShowTab(key) - local pageKey, page - for pageKey, page in pairs(self.pages) do - if pageKey == key then page:Show() else page:Hide() end - end - - local i - for i = 1, table.getn(tabDefs) do - local def = tabDefs[i] - local button = self.tabs[def.key] - if button then - if def.key == key then - if button.Disable then button:Disable() end - button:SetAlpha(1.0) - else - if button.Enable then button:Enable() end - button:SetAlpha(0.80) - end - end - end - self.selectedTab = key - end - - local tabX = 28 - local i - for i = 1, table.getn(tabDefs) do - local def = tabDefs[i] - local button = CreateFrame("Button", nil, frame, "UIPanelButtonTemplate") - button:SetWidth(def.width) - button:SetHeight(24) - button:SetPoint("TOPLEFT", frame, "TOPLEFT", tabX, -68) - button:SetText(def.label) - button.BNPTabKey = def.key - button:SetScript("OnClick", function() - frame:ShowTab(this.BNPTabKey) - end) - frame.tabs[def.key] = button - tabX = tabX + def.width + 4 - end - - -- NAMEPLATES TAB --------------------------------------------------------- - local nameplatesPage = frame.pages.nameplates - CreateSection(nameplatesPage, "General", -4) - - local scale = CreateSlider(nameplatesPage, "Nameplate Scale", 0.70, 1.50, 0.05, -36, 28, 150) - scale:SetScript("OnValueChanged", function() - if not BNP_DB then return end - local value = Round(this:GetValue(), 0.05) - BNP_DB.nameplateScale = value - getglobal(this:GetName() .. "Text"):SetText("Nameplate Scale: " .. string.format("%.2f", value)) - if BNP.ApplyNameplateScaleAll then BNP:ApplyNameplateScaleAll() end - end) - frame.scaleSlider = scale - - local yOffset = CreateSlider(nameplatesPage, "Nameplate Y Offset", 0, 50, 1, -36, 220, 150) - yOffset:SetScript("OnValueChanged", function() - if not BNP_DB then return end - local value = math.floor(this:GetValue() + 0.5) - BNP_DB.nameplateYOffset = value - getglobal(this:GetName() .. "Text"):SetText("Nameplate Y Offset: +" .. value) - if BNP.ApplyNameplateYOffsetAll then BNP:ApplyNameplateYOffsetAll() end - end) - frame.yOffsetSlider = yOffset - - local nonTargetAlpha = CreateSlider(nameplatesPage, "Non-Target Alpha", 30, 100, 5, -82, 28, 150) - nonTargetAlpha:SetScript("OnValueChanged", function() - if not BNP_DB then return end - local percent = math.floor((this:GetValue() / 5) + 0.5) * 5 - if percent < 30 then percent = 30 end - if percent > 100 then percent = 100 end - BNP_DB.nonTargetAlpha = percent / 100 - getglobal(this:GetName() .. "Text"):SetText("Non-Target Alpha: " .. percent .. "%") - if BNP.RefreshNonTargetAlpha then BNP:RefreshNonTargetAlpha() end - end) - frame.nonTargetAlphaSlider = nonTargetAlpha - - local classColors = CreateCheck(nameplatesPage, "Class Colors", -78, function() - BNP_DB.classColors = this:GetChecked() and true or false - if BNP.RefreshClassColors then BNP:RefreshClassColors() end - end, 214) - frame.classColorsCheck = classColors - - CreateSection(nameplatesPage, "Names", -138) - - local hidePlayerNames = CreateCheck(nameplatesPage, "Hide Player Names", -166, function() - BNP_DB.hidePlayerNames = this:GetChecked() and true or false - if BNP.RefreshNameVisibility then BNP:RefreshNameVisibility() end - end, 22) - frame.hidePlayerNamesCheck = hidePlayerNames - - local tank = CreateCheck(nameplatesPage, "Tank Mode", -106, function() - BNP_DB.tankMode = this:GetChecked() and true or false - if BNP.UpdateTankMode then BNP:UpdateTankMode() end - end) - tank:SetScript("OnEnter", function() - GameTooltip:SetOwner(this, "ANCHOR_RIGHT") - GameTooltip:SetText("Tank Mode", 1, 0.82, 0) - GameTooltip:AddLine("Green: the unit is targeting you.", 1, 1, 1) - GameTooltip:AddLine("Red: the unit is targeting someone else.", 1, 1, 1) - GameTooltip:Show() - end) - tank:SetScript("OnLeave", function() GameTooltip:Hide() end) - frame.tankCheck = tank - - local hideNPCNames = CreateCheck(nameplatesPage, "Hide NPC/Mob Names", -166, function() - BNP_DB.hideNPCNames = this:GetChecked() and true or false - if BNP.RefreshNameVisibility then BNP:RefreshNameVisibility() end - end, 214) - frame.hideNPCNamesCheck = hideNPCNames - - CreateSection(nameplatesPage, "Health Text", -250) - - local healthTextLabel = nameplatesPage:CreateFontString(nil, "OVERLAY", "GameFontNormal") - healthTextLabel:SetPoint("TOPLEFT", nameplatesPage, "TOPLEFT", 28, -278) - healthTextLabel:SetText("Display") - - local healthTextDropdown = CreateFrame("Frame", "BNPHealthTextDropdown", nameplatesPage, "UIDropDownMenuTemplate") - healthTextDropdown:SetPoint("TOPLEFT", nameplatesPage, "TOPLEFT", 10, -290) - UIDropDownMenu_SetWidth(150, healthTextDropdown) - - local healthModeLabels = { - off = "Off", - percent = "Percent", - hp = "HP", - both = "HP + Percent", - } - - local function SetHealthTextMode(mode) - if not healthModeLabels[mode] then mode = "off" end - BNP_DB.healthText = mode - BNP_DB.healthPercent = (mode == "percent" or mode == "both") - UIDropDownMenu_SetSelectedValue(healthTextDropdown, mode) - UIDropDownMenu_SetText(healthModeLabels[mode], healthTextDropdown) - if BNP.RefreshHealthPercent then BNP:RefreshHealthPercent() end - end - - UIDropDownMenu_Initialize(healthTextDropdown, function() - local modes = { "off", "percent", "hp", "both" } - local n - for n = 1, table.getn(modes) do - local mode = modes[n] - local info = {} - info.text = healthModeLabels[mode] - info.value = mode - info.func = function() SetHealthTextMode(this.value) end - info.checked = (BNP:GetHealthTextMode() == mode) - UIDropDownMenu_AddButton(info) - end - end) - frame.healthTextDropdown = healthTextDropdown - frame.SetHealthTextMode = SetHealthTextMode - - local healthFontSize = CreateSlider(nameplatesPage, "Health Font Size", 8, 20, 1, -344, 28, 150) - healthFontSize:SetScript("OnValueChanged", function() - if not BNP_DB or frame.BNPSyncingHealthTextControls then return end - local value = math.floor(this:GetValue() + 0.5) - BNP_DB.healthTextFontSize = value - getglobal(this:GetName() .. "Text"):SetText("Health Font Size: " .. value) - if BNP.RefreshHealthPercent then BNP:RefreshHealthPercent() end - end) - frame.healthTextFontSizeSlider = healthFontSize - - local healthOutlineLabel = nameplatesPage:CreateFontString(nil, "OVERLAY", "GameFontNormal") - healthOutlineLabel:SetPoint("TOPLEFT", nameplatesPage, "TOPLEFT", 220, -278) - healthOutlineLabel:SetText("Outline") - - local healthOutlineDropdown = CreateFrame("Frame", "BNPHealthOutlineDropdown", nameplatesPage, "UIDropDownMenuTemplate") - healthOutlineDropdown:SetPoint("TOPLEFT", nameplatesPage, "TOPLEFT", 200, -290) - UIDropDownMenu_SetWidth(150, healthOutlineDropdown) - - local healthOutlineLabels = { - none = "None", - outline = "Outline", - thick = "Thick Outline", - } - - local function SetHealthTextOutline(value) - if not healthOutlineLabels[value] then value = "outline" end - BNP_DB.healthTextOutline = value - UIDropDownMenu_SetSelectedValue(healthOutlineDropdown, value) - UIDropDownMenu_SetText(healthOutlineLabels[value], healthOutlineDropdown) - if BNP.RefreshHealthPercent then BNP:RefreshHealthPercent() end - end - - UIDropDownMenu_Initialize(healthOutlineDropdown, function() - local values = { "none", "outline", "thick" } - local n - for n = 1, table.getn(values) do - local value = values[n] - local info = {} - info.text = healthOutlineLabels[value] - info.value = value - info.func = function() SetHealthTextOutline(this.value) end - info.checked = (BNP:GetHealthTextOutline() == value) - UIDropDownMenu_AddButton(info) - end - end) - frame.healthTextOutlineDropdown = healthOutlineDropdown - frame.SetHealthTextOutline = SetHealthTextOutline - - if comboOptionsClass then - CreateSection(nameplatesPage, "Combo Points", -380) - - local comboPoints = CreateCheck(nameplatesPage, "Combo Points", -406, function() - BNP_DB.comboPoints = this:GetChecked() and true or false - if BNP.RefreshComboPoints then BNP:RefreshComboPoints() end - if BNP.RefreshAllAuraLayouts then BNP:RefreshAllAuraLayouts() end - if BNP.RefreshAllImmunityLayouts then BNP:RefreshAllImmunityLayouts() end - if frame.UpdateDependentControls then frame:UpdateDependentControls() end - end, 22) - frame.comboPointsCheck = comboPoints - - local comboYOffset = CreateSlider(nameplatesPage, "Combo Point Y Offset", -50, 50, 1, -408, 220, 150) - comboYOffset:SetScript("OnValueChanged", function() - if not BNP_DB then return end - local value = RoundSignedInteger(this:GetValue()) - BNP_DB.comboPointsYOffset = value - getglobal(this:GetName() .. "Text"):SetText("Combo Point Y Offset: " .. (value > 0 and "+" or "") .. value) - if BNP.RefreshComboPoints then BNP:RefreshComboPoints() end - end) - frame.comboPointsYOffsetSlider = comboYOffset - end - - -- Name text controls are independent from Nameplate Scale. The size setting - -- only touches the Blizzard name FontString; the Y offset only moves it. - local nameFontSize = CreateSlider(nameplatesPage, "Name Font Size", 8, 24, 1, -210, 28, 150) - nameFontSize:SetScript("OnValueChanged", function() - if not BNP_DB or frame.BNPSyncingNameControls then return end - local value = math.floor(this:GetValue() + 0.5) - BNP_DB.nameFontSize = value - getglobal(this:GetName() .. "Text"):SetText("Name Font Size: " .. value) - if BNP.RefreshNameAppearance then BNP:RefreshNameAppearance() end - end) - frame.nameFontSizeSlider = nameFontSize - - local nameFontYOffset = CreateSlider(nameplatesPage, "Name Y Offset", -50, 50, 1, -210, 220, 150) - nameFontYOffset:SetScript("OnValueChanged", function() - if not BNP_DB or frame.BNPSyncingNameControls then return end - local value = RoundSignedInteger(this:GetValue()) - BNP_DB.nameFontYOffset = value - getglobal(this:GetName() .. "Text"):SetText("Name Y Offset: " .. (value > 0 and "+" or "") .. value) - if BNP.ApplyNameFontYOffsetAll then BNP:ApplyNameFontYOffsetAll() end - end) - frame.nameFontYOffsetSlider = nameFontYOffset - - -- AURAS TAB -------------------------------------------------------------- - local aurasPage = frame.pages.auras - CreateSection(aurasPage, "Debuffs", -4) - - local icon = CreateSlider(aurasPage, "Aura Icon Size", 12, 32, 1, -78, 28, 150) - icon:SetScript("OnValueChanged", function() - if not BNP_DB then return end - local value = math.floor(this:GetValue() + 0.5) - BNP_DB.iconSize = value - getglobal(this:GetName() .. "Text"):SetText("Aura Icon Size: " .. value) - if BNP.RefreshAllAuraLayouts then BNP:RefreshAllAuraLayouts() end - if BNP.RefreshAllImmunityLayouts then BNP:RefreshAllImmunityLayouts() end - if BNP.RefreshCastbarLayout then BNP:RefreshCastbarLayout() end - end) - frame.iconSlider = icon - - local debuffYOffset = CreateSlider(aurasPage, "Debuff Y Offset", -50, 50, 1, -78, 220, 150) - debuffYOffset:SetScript("OnValueChanged", function() - if not BNP_DB then return end - local value = RoundSignedInteger(this:GetValue()) - BNP_DB.debuffYOffset = value - getglobal(this:GetName() .. "Text"):SetText("Debuff Y Offset: " .. (value > 0 and "+" or "") .. value) - if BNP.RefreshAllAuraLayouts then BNP:RefreshAllAuraLayouts() end - if BNP.RefreshDebuffVisibility then BNP:RefreshDebuffVisibility() end - if BNP.RefreshAllImmunityLayouts then BNP:RefreshAllImmunityLayouts() end - if BNP.RefreshCastbarLayout then BNP:RefreshCastbarLayout() end - end) - frame.debuffYOffsetSlider = debuffYOffset - - local ccIcon = CreateSlider(aurasPage, "CC Icon Size", 12, 32, 1, -196, 28, 150) - ccIcon:SetScript("OnValueChanged", function() - if not BNP_DB then return end - local value = math.floor(this:GetValue() + 0.5) - BNP_DB.ccIconSize = value - getglobal(this:GetName() .. "Text"):SetText("CC Icon Size: " .. value) - if BNP.RefreshAllAuraLayouts then BNP:RefreshAllAuraLayouts() end - if BNP.RefreshAllImmunityLayouts then BNP:RefreshAllImmunityLayouts() end - if BNP.RefreshCastbarLayout then BNP:RefreshCastbarLayout() end - end) - frame.ccIconSlider = ccIcon - - local ccYOffset = CreateSlider(aurasPage, "CC Y Offset", -50, 50, 1, -196, 220, 150) - ccYOffset:SetScript("OnValueChanged", function() - if not BNP_DB then return end - local value = RoundSignedInteger(this:GetValue()) - BNP_DB.ccYOffset = value - getglobal(this:GetName() .. "Text"):SetText("CC Y Offset: " .. (value > 0 and "+" or "") .. value) - if BNP.RefreshAllAuraLayouts then BNP:RefreshAllAuraLayouts() end - if BNP.RefreshAllImmunityLayouts then BNP:RefreshAllImmunityLayouts() end - if BNP.RefreshDebuffVisibility then BNP:RefreshDebuffVisibility() end - if BNP.RefreshCastbarLayout then BNP:RefreshCastbarLayout() end - end) - frame.ccYOffsetSlider = ccYOffset - - local debuffs = CreateCheck(aurasPage, "Enable Debuffs", -30, function() - BNP_DB.debuffs = this:GetChecked() and true or false - if BNP.RefreshDebuffVisibility then BNP:RefreshDebuffVisibility() end - if frame.UpdateDependentControls then frame:UpdateDependentControls() end - if BNP.RefreshAllImmunityLayouts then BNP:RefreshAllImmunityLayouts() end - if BNP.RefreshCastbarLayout then BNP:RefreshCastbarLayout() end - end) - frame.debuffsCheck = debuffs - - local debuffPositionDropdown = CreateFrame("Frame", "BNPDebuffPositionDropdown", aurasPage, "UIDropDownMenuTemplate") - debuffPositionDropdown:SetPoint("TOPLEFT", aurasPage, "TOPLEFT", 188, -24) - UIDropDownMenu_SetWidth(112, debuffPositionDropdown) - - local debuffPositionLabels = { - top = "Top Mid", - top_left = "Top Left", - top_right = "Top Right", - left = "Left", - right = "Right", - bottom_mid = "Bottom Mid", - bottom_left = "Bottom Left", - bottom_right = "Bottom Right", - } - - local function SetDebuffPosition(position) - if not debuffPositionLabels[position] then position = "top" end - BNP_DB.debuffPosition = position - UIDropDownMenu_SetSelectedValue(debuffPositionDropdown, position) - UIDropDownMenu_SetText(debuffPositionLabels[position], debuffPositionDropdown) - if frame.UpdateDependentControls then frame:UpdateDependentControls() end - if BNP.RefreshAllAuraLayouts then BNP:RefreshAllAuraLayouts() end - if BNP.RefreshAllImmunityLayouts then BNP:RefreshAllImmunityLayouts() end - if BNP.RefreshDebuffVisibility then BNP:RefreshDebuffVisibility() end - if BNP.RefreshTotemIndicators then BNP:RefreshTotemIndicators() end - if BNP.RefreshCastbarLayout then BNP:RefreshCastbarLayout() end - end - - UIDropDownMenu_Initialize(debuffPositionDropdown, function() - local positions = { "top", "top_left", "top_right", "left", "right", "bottom_mid", "bottom_left", "bottom_right" } - local n - for n = 1, table.getn(positions) do - local position = positions[n] - local info = {} - info.text = debuffPositionLabels[position] - info.value = position - info.func = function() SetDebuffPosition(this.value) end - info.checked = (BNP:GetDebuffPosition() == position) - UIDropDownMenu_AddButton(info) - end - end) - frame.debuffPositionDropdown = debuffPositionDropdown - frame.SetDebuffPosition = SetDebuffPosition - - local debuffPositionLabel = aurasPage:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall") - debuffPositionLabel:SetPoint("BOTTOMLEFT", debuffPositionDropdown, "TOPLEFT", 18, 5) - debuffPositionLabel:SetText("Debuff Position") - frame.debuffPositionLabel = debuffPositionLabel - - CreateSection(aurasPage, "Crowd Control", -122) - - local crowdControl = CreateCheck(aurasPage, "Enable Crowd Control", -148, function() - BNP_DB.crowdControl = this:GetChecked() and true or false - if BNP.RefreshDebuffVisibility then BNP:RefreshDebuffVisibility() end - if BNP.RefreshAllImmunityLayouts then BNP:RefreshAllImmunityLayouts() end - if frame.UpdateDependentControls then frame:UpdateDependentControls() end - if BNP.RefreshCastbarLayout then BNP:RefreshCastbarLayout() end - end) - frame.crowdControlCheck = crowdControl - - local ccPositionDropdown = CreateFrame("Frame", "BNPCCPositionDropdown", aurasPage, "UIDropDownMenuTemplate") - ccPositionDropdown:SetPoint("TOPLEFT", aurasPage, "TOPLEFT", 188, -142) - UIDropDownMenu_SetWidth(92, ccPositionDropdown) - - local ccPositionLabels = { - top = "Top", - left = "Left", - right = "Right", - } - - local function SetCCPosition(position) - if not ccPositionLabels[position] then position = "top" end - BNP_DB.ccPosition = position - UIDropDownMenu_SetSelectedValue(ccPositionDropdown, position) - UIDropDownMenu_SetText(ccPositionLabels[position], ccPositionDropdown) - if frame.UpdateDependentControls then frame:UpdateDependentControls() end - if BNP.RefreshAllAuraLayouts then BNP:RefreshAllAuraLayouts() end - if BNP.RefreshDebuffVisibility then BNP:RefreshDebuffVisibility() end - if BNP.RefreshCastbarLayout then BNP:RefreshCastbarLayout() end - end - - UIDropDownMenu_Initialize(ccPositionDropdown, function() - local positions = { "top", "left", "right" } - local n - for n = 1, table.getn(positions) do - local position = positions[n] - local info = {} - info.text = ccPositionLabels[position] - info.value = position - info.func = function() SetCCPosition(this.value) end - info.checked = (BNP:GetCCPosition() == position) - UIDropDownMenu_AddButton(info) - end - end) - frame.ccPositionDropdown = ccPositionDropdown - frame.SetCCPosition = SetCCPosition - - local ccPositionLabel = aurasPage:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall") - ccPositionLabel:SetPoint("BOTTOMLEFT", ccPositionDropdown, "TOPLEFT", 18, 5) - ccPositionLabel:SetText("CC Position") - frame.ccPositionLabel = ccPositionLabel - - local separateCCRow = CreateCheck(aurasPage, "Display CCs in Separate Row", -230, function() - BNP_DB.separateCCRow = this:GetChecked() and true or false - if BNP.RefreshAllAuraLayouts then BNP:RefreshAllAuraLayouts() end - if BNP.RefreshAllImmunityLayouts then BNP:RefreshAllImmunityLayouts() end - if BNP.RefreshDebuffVisibility then BNP:RefreshDebuffVisibility() end - if BNP.RefreshCastbarLayout then BNP:RefreshCastbarLayout() end - end, 42) - frame.separateCCRowCheck = separateCCRow - - local showOtherCCs = CreateCheck(aurasPage, "Show CCs from Other Players", -256, function() - BNP_DB.showOtherCCs = this:GetChecked() and true or false - if BNP.RefreshDebuffVisibility then BNP:RefreshDebuffVisibility() end - end, 42) - frame.showOtherCCsCheck = showOtherCCs - - CreateSection(aurasPage, "Immunities / Important Buffs", -294) - - local pvpImmunities = CreateCheck(aurasPage, "Enable PvP Immunities", -320, function() - BNP_DB.pvpImmunities = this:GetChecked() and true or false - if BNP.RefreshImmunityVisibility then BNP:RefreshImmunityVisibility() end - if frame.UpdateDependentControls then frame:UpdateDependentControls() end - if BNP.RefreshCastbarLayout then BNP:RefreshCastbarLayout() end - end, 22) - frame.pvpImmunitiesCheck = pvpImmunities - - local immunityPositionDropdown = CreateFrame("Frame", "BNPImmunityPositionDropdown", aurasPage, "UIDropDownMenuTemplate") - immunityPositionDropdown:SetPoint("TOPLEFT", aurasPage, "TOPLEFT", 188, -314) - UIDropDownMenu_SetWidth(92, immunityPositionDropdown) - - local immunityPositionLabels = { - top = "Top", - left = "Left", - right = "Right", - } - - local function SetImmunityPosition(position) - if not immunityPositionLabels[position] then position = "top" end - BNP_DB.immunityPosition = position - UIDropDownMenu_SetSelectedValue(immunityPositionDropdown, position) - UIDropDownMenu_SetText(immunityPositionLabels[position], immunityPositionDropdown) - if BNP.RefreshAllImmunityLayouts then BNP:RefreshAllImmunityLayouts() end - if BNP.RefreshCastbarLayout then BNP:RefreshCastbarLayout() end - end - - UIDropDownMenu_Initialize(immunityPositionDropdown, function() - local positions = { "top", "left", "right" } - local n - for n = 1, table.getn(positions) do - local position = positions[n] - local info = {} - info.text = immunityPositionLabels[position] - info.value = position - info.func = function() SetImmunityPosition(this.value) end - info.checked = (BNP:GetImmunityPosition() == position) - UIDropDownMenu_AddButton(info) - end - end) - frame.immunityPositionDropdown = immunityPositionDropdown - frame.SetImmunityPosition = SetImmunityPosition - - local immunityPositionLabel = aurasPage:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall") - immunityPositionLabel:SetPoint("BOTTOMLEFT", immunityPositionDropdown, "TOPLEFT", 18, 5) - immunityPositionLabel:SetText("Immunity Position") - frame.immunityPositionLabel = immunityPositionLabel - - local immunityIcon = CreateSlider(aurasPage, "Immunity Icon Size", 12, 32, 1, -368, 28, 150) - immunityIcon:SetScript("OnValueChanged", function() - if not BNP_DB then return end - local value = math.floor(this:GetValue() + 0.5) - BNP_DB.immunityIconSize = value - getglobal(this:GetName() .. "Text"):SetText("Immunity Icon Size: " .. value) - if BNP.RefreshAllImmunityLayouts then BNP:RefreshAllImmunityLayouts() end - if BNP.RefreshCastbarLayout then BNP:RefreshCastbarLayout() end - end) - frame.immunityIconSlider = immunityIcon - - local immunityYOffset = CreateSlider(aurasPage, "Immunity Y Offset", -50, 50, 1, -368, 220, 150) - immunityYOffset:SetScript("OnValueChanged", function() - if not BNP_DB then return end - local value = RoundSignedInteger(this:GetValue()) - BNP_DB.immunityYOffset = value - getglobal(this:GetName() .. "Text"):SetText("Immunity Y Offset: " .. (value > 0 and "+" or "") .. value) - if BNP.RefreshAllImmunityLayouts then BNP:RefreshAllImmunityLayouts() end - if BNP.RefreshCastbarLayout then BNP:RefreshCastbarLayout() end - end) - frame.immunityYOffsetSlider = immunityYOffset - - -- TOTEMS TAB ------------------------------------------------------------- - local totemsPage = frame.pages.totems - CreateSection(totemsPage, "Totem Indicators", -4) - - local totemIndicators = CreateCheck(totemsPage, "Enable Totem Icons", -42, function() - BNP_DB.totemIndicators = this:GetChecked() and true or false - if BNP.RefreshTotemIndicators then BNP:RefreshTotemIndicators() end - if frame.UpdateDependentControls then frame:UpdateDependentControls() end - end) - frame.totemIndicatorsCheck = totemIndicators - - local totemIcon = CreateSlider(totemsPage, "Totem Icon Size", 16, 36, 1, -92) - totemIcon:SetScript("OnValueChanged", function() - if not BNP_DB then return end - local value = math.floor(this:GetValue() + 0.5) - BNP_DB.totemIconSize = value - getglobal(this:GetName() .. "Text"):SetText("Totem Icon Size: " .. value) - if BNP.RefreshTotemIndicators then BNP:RefreshTotemIndicators() end - end) - frame.totemIconSlider = totemIcon - - local totemNote = totemsPage:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall") - totemNote:SetPoint("TOPLEFT", totemsPage, "TOPLEFT", 28, -150) - totemNote:SetWidth(340) - totemNote:SetJustifyH("LEFT") - totemNote:SetText("Replaces all visible shaman totem nameplates with compact icons. There are no individual totem filters.") - - - -- CASTBAR TAB ------------------------------------------------------------ - local castbarPage = frame.pages.castbar - CreateSection(castbarPage, "Castbar", -4) - - local castbars = CreateCheck(castbarPage, "Castbars", -42, function() - local enabled = this:GetChecked() and true or false - if BNP.SetCastbarsEnabled then BNP:SetCastbarsEnabled(enabled) else BNP_DB.castbars = enabled end - end) - frame.castbarsCheck = castbars - - local castbarTest = CreateCheck(castbarPage, "Test Castbars", -42, function() - if BNP.SetCastbarTestMode then BNP:SetCastbarTestMode(this:GetChecked() and true or false) end - end, 164) - castbarTest:SetScript("OnEnter", function() - GameTooltip:SetOwner(this, "ANCHOR_RIGHT") - GameTooltip:SetText("Test Castbars", 1, 0.82, 0) - GameTooltip:AddLine("Shows a looping simulated castbar on every visible nameplate.", 1, 1, 1, true) - GameTooltip:AddLine("Use it to adjust height and spacing live. The test mode is not saved.", 0.8, 0.8, 0.8, true) - GameTooltip:Show() - end) - castbarTest:SetScript("OnLeave", function() GameTooltip:Hide() end) - frame.castbarTestCheck = castbarTest - - local castbarHeight = CreateSlider(castbarPage, "Castbar Height", 4, 14, 1, -94) - castbarHeight:SetScript("OnValueChanged", function() - if not BNP_DB then return end - local value = math.floor(this:GetValue() + 0.5) - BNP_DB.castbarHeight = value - getglobal(this:GetName() .. "Text"):SetText("Castbar Height: " .. value) - if BNP.RefreshCastbarLayout then BNP:RefreshCastbarLayout() elseif BNP.RefreshCastbarHeights then BNP:RefreshCastbarHeights() end - end) - frame.castbarHeightSlider = castbarHeight - - local castbarSpacing = CreateSlider(castbarPage, "Castbar Spacing", 0, 10, 1, -148) - castbarSpacing:SetScript("OnValueChanged", function() - if not BNP_DB then return end - local value = math.floor(this:GetValue() + 0.5) - BNP_DB.castbarSpacing = value - getglobal(this:GetName() .. "Text"):SetText("Castbar Spacing: " .. value .. " px") - if BNP.RefreshCastbarLayout then BNP:RefreshCastbarLayout() end - end) - frame.castbarSpacingSlider = castbarSpacing - - -- TARGET TAB ------------------------------------------------------------- - local targetPage = frame.pages.target - CreateSection(targetPage, "Target", -4) - - local targetFocus = CreateCheck(targetPage, "Target Glow", -42, function() - BNP_DB.targetFocus = this:GetChecked() and true or false - if BNP.RefreshTargetFocus then BNP:RefreshTargetFocus() end - if frame.UpdateDependentControls then frame:UpdateDependentControls() end - end) - frame.targetFocusCheck = targetFocus - - local glowColorLabel = targetPage:CreateFontString(nil, "OVERLAY", "GameFontNormal") - glowColorLabel:SetPoint("TOPLEFT", targetPage, "TOPLEFT", 28, -88) - glowColorLabel:SetText("Target Color") - frame.glowColorLabel = glowColorLabel - - local glowColorDropdown = CreateFrame("Frame", "BNPTargetGlowColorDropdown", targetPage, "UIDropDownMenuTemplate") - glowColorDropdown:SetPoint("TOPLEFT", targetPage, "TOPLEFT", 10, -100) - UIDropDownMenu_SetWidth(150, glowColorDropdown) - - local glowColorLabels = { - white = "White", - gold = "Gold", - blue = "Blue", - green = "Green", - red = "Red", - purple = "Purple", - } - - local function SetTargetGlowColor(color) - if not glowColorLabels[color] then color = "white" end - BNP_DB.targetGlowColor = color - UIDropDownMenu_SetSelectedValue(glowColorDropdown, color) - UIDropDownMenu_SetText(glowColorLabels[color], glowColorDropdown) - if BNP.RefreshTargetFocus then BNP:RefreshTargetFocus() end - end - - UIDropDownMenu_Initialize(glowColorDropdown, function() - local colors = { "white", "gold", "blue", "green", "red", "purple" } - local n - for n = 1, table.getn(colors) do - local color = colors[n] - local info = {} - info.text = glowColorLabels[color] - info.value = color - info.func = function() SetTargetGlowColor(this.value) end - info.checked = ((BNP_DB and BNP_DB.targetGlowColor) or "white") == color - UIDropDownMenu_AddButton(info) - end - end) - frame.glowColorDropdown = glowColorDropdown - frame.SetTargetGlowColor = SetTargetGlowColor - - local glowSize = CreateSlider(targetPage, "Target Glow Size", 0, 20, 1, -168) - glowSize:SetWidth(145) - glowSize:SetScript("OnValueChanged", function() - if not BNP_DB then return end - local value = math.floor(this:GetValue() + 0.5) - BNP_DB.targetGlowSize = value - getglobal(this:GetName() .. "Text"):SetText("Target Glow Size: +" .. value .. " px") - if BNP.RefreshTargetFocus then BNP:RefreshTargetFocus() end - end) - frame.targetGlowSizeSlider = glowSize - - local glowOpacity = CreateSlider(targetPage, "Target Glow Opacity", 20, 100, 5, -222) - glowOpacity:SetWidth(145) - glowOpacity:SetScript("OnValueChanged", function() - if not BNP_DB then return end - local value = math.floor(this:GetValue() + 0.5) - BNP_DB.targetGlowOpacity = value / 100 - getglobal(this:GetName() .. "Text"):SetText("Target Glow Opacity: " .. value .. "%") - if BNP.RefreshTargetFocus then BNP:RefreshTargetFocus() end - end) - frame.targetGlowOpacitySlider = glowOpacity - - local targetArrows = CreateCheck(targetPage, "Target Arrows", -42, function() - BNP_DB.targetArrows = this:GetChecked() and true or false - if BNP.RefreshTargetFocus then BNP:RefreshTargetFocus() end - if frame.UpdateDependentControls then frame:UpdateDependentControls() end - end) - targetArrows:ClearAllPoints() - targetArrows:SetPoint("TOPLEFT", targetPage, "TOPLEFT", 204, -42) - frame.targetArrowsCheck = targetArrows - - local arrowColorLabel = targetPage:CreateFontString(nil, "OVERLAY", "GameFontNormal") - arrowColorLabel:SetPoint("TOPLEFT", targetPage, "TOPLEFT", 210, -88) - arrowColorLabel:SetText("Arrow Color") - frame.arrowColorLabel = arrowColorLabel - - local arrowColorDropdown = CreateFrame("Frame", "BNPTargetArrowColorDropdown", targetPage, "UIDropDownMenuTemplate") - arrowColorDropdown:SetPoint("TOPLEFT", targetPage, "TOPLEFT", 192, -100) - UIDropDownMenu_SetWidth(140, arrowColorDropdown) - - local arrowColorLabels = { - match = "Match Target Color", - white = "White", - gold = "Gold", - blue = "Blue", - green = "Green", - red = "Red", - purple = "Purple", - } - - local function SetTargetArrowColor(color) - if not arrowColorLabels[color] then color = "match" end - BNP_DB.targetArrowColor = color - UIDropDownMenu_SetSelectedValue(arrowColorDropdown, color) - UIDropDownMenu_SetText(arrowColorLabels[color], arrowColorDropdown) - if BNP.RefreshTargetFocus then BNP:RefreshTargetFocus() end - end - - UIDropDownMenu_Initialize(arrowColorDropdown, function() - local colors = { "match", "white", "gold", "blue", "green", "red", "purple" } - local n - for n = 1, table.getn(colors) do - local color = colors[n] - local info = {} - info.text = arrowColorLabels[color] - info.value = color - info.func = function() SetTargetArrowColor(this.value) end - info.checked = ((BNP_DB and BNP_DB.targetArrowColor) or "match") == color - UIDropDownMenu_AddButton(info) - end - end) - frame.arrowColorDropdown = arrowColorDropdown - frame.SetTargetArrowColor = SetTargetArrowColor - - local arrowStyleLabel = targetPage:CreateFontString(nil, "OVERLAY", "GameFontNormal") - arrowStyleLabel:SetPoint("TOPLEFT", targetPage, "TOPLEFT", 210, -142) - arrowStyleLabel:SetText("Arrow Style") - frame.arrowStyleLabel = arrowStyleLabel - - local arrowStyleDropdown = CreateFrame("Frame", "BNPTargetArrowStyleDropdown", targetPage, "UIDropDownMenuTemplate") - arrowStyleDropdown:SetPoint("TOPLEFT", targetPage, "TOPLEFT", 192, -154) - UIDropDownMenu_SetWidth(140, arrowStyleDropdown) - - local arrowStyleLabels = { - chevron = "Chevron", - triangle = "Triangle", - slim_triangle = "Slim Triangle", - double_chevron = "Double Chevron", - diamond_tip = "Diamond Tip", - } - - local function SetTargetArrowStyle(style) - if not arrowStyleLabels[style] then style = "chevron" end - BNP_DB.targetArrowStyle = style - UIDropDownMenu_SetSelectedValue(arrowStyleDropdown, style) - UIDropDownMenu_SetText(arrowStyleLabels[style], arrowStyleDropdown) - if BNP.RefreshTargetFocus then BNP:RefreshTargetFocus() end - end - - UIDropDownMenu_Initialize(arrowStyleDropdown, function() - local styles = { "chevron", "triangle", "slim_triangle", "double_chevron", "diamond_tip" } - local n - for n = 1, table.getn(styles) do - local style = styles[n] - local info = {} - info.text = arrowStyleLabels[style] - info.value = style - info.func = function() SetTargetArrowStyle(this.value) end - info.checked = ((BNP_DB and BNP_DB.targetArrowStyle) or "chevron") == style - UIDropDownMenu_AddButton(info) - end - end) - frame.arrowStyleDropdown = arrowStyleDropdown - frame.SetTargetArrowStyle = SetTargetArrowStyle - - local arrowSize = CreateSlider(targetPage, "Target Arrow Size", 10, 24, 1, -222) - arrowSize:ClearAllPoints() - arrowSize:SetPoint("TOPLEFT", targetPage, "TOPLEFT", 210, -222) - arrowSize:SetWidth(145) - arrowSize:SetScript("OnValueChanged", function() - if not BNP_DB then return end - local value = math.floor(this:GetValue() + 0.5) - BNP_DB.targetArrowSize = value - getglobal(this:GetName() .. "Text"):SetText("Target Arrow Size: " .. value) - if BNP.RefreshTargetFocus then BNP:RefreshTargetFocus() end - end) - frame.targetArrowSizeSlider = arrowSize - - local thickArrows = CreateCheck(targetPage, "Thick Arrows", -276, function() - BNP_DB.targetArrowThick = this:GetChecked() and true or false - if BNP.RefreshTargetFocus then BNP:RefreshTargetFocus() end - end) - thickArrows:ClearAllPoints() - thickArrows:SetPoint("TOPLEFT", targetPage, "TOPLEFT", 204, -276) - frame.targetArrowThickCheck = thickArrows - - -- TOOLS TAB -------------------------------------------------------------- - local toolsPage = frame.pages.tools - CreateSection(toolsPage, "Tools", -4) - - local auraRecorder = CreateFrame("Button", nil, toolsPage, "UIPanelButtonTemplate") - auraRecorder:SetPoint("TOPLEFT", toolsPage, "TOPLEFT", 28, -48) - auraRecorder:SetWidth(254) - auraRecorder:SetHeight(24) - auraRecorder:SetText("Missing Spell / Aura...") - auraRecorder:SetScript("OnClick", function() BNP:OpenAuraRecorder() end) - auraRecorder:SetScript("OnEnter", function() - GameTooltip:SetOwner(this, "ANCHOR_RIGHT") - GameTooltip:SetText("Missing Spell / Aura Recorder", 1, 0.82, 0) - GameTooltip:AddLine("Records target aura IDs, SuperWoW events and refresh signals in one copyable report.", 1, 1, 1, true) - GameTooltip:Show() - end) - auraRecorder:SetScript("OnLeave", function() GameTooltip:Hide() end) - frame.auraRecorderButton = auraRecorder - - local note = toolsPage:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall") - note:SetPoint("TOPLEFT", toolsPage, "TOPLEFT", 28, -88) - note:SetWidth(330) - note:SetJustifyH("LEFT") - note:SetText("Diagnostic tools for testing missing spells and aura refresh behavior.") - - function frame:UpdateDependentControls() - local ccEnabled = BNP:AreCrowdControlEnabled() - local debuffsEnabled = BNP:AreDebuffsEnabled() - local debuffPosition = BNP.GetDebuffPosition and BNP:GetDebuffPosition() or "top" - local ccPosition = BNP.GetCCPosition and BNP:GetCCPosition() or debuffPosition - local separateRowAvailable = ccEnabled and debuffsEnabled and (debuffPosition == "top" or debuffPosition == "top_left" or debuffPosition == "top_right") and ccPosition == "top" - - SetCheckEnabled(self.separateCCRowCheck, separateRowAvailable) - if self.separateCCRowCheck then - self.separateCCRowCheck:SetChecked(separateRowAvailable and BNP:IsSeparateCCRowEnabled() or false) - end - SetCheckEnabled(self.showOtherCCsCheck, ccEnabled) - if self.debuffYOffsetSlider then - self.debuffYOffsetSlider:SetAlpha(debuffsEnabled and 1.0 or 0.45) - if self.debuffYOffsetSlider.EnableMouse then self.debuffYOffsetSlider:EnableMouse(debuffsEnabled) end - end - if self.ccYOffsetSlider then - self.ccYOffsetSlider:SetAlpha(ccEnabled and 1.0 or 0.45) - if self.ccYOffsetSlider.EnableMouse then self.ccYOffsetSlider:EnableMouse(ccEnabled) end - end - - local comboEnabled = BNP.AreComboPointsEnabled and BNP:AreComboPointsEnabled() or false - if self.comboPointsYOffsetSlider then - self.comboPointsYOffsetSlider:SetAlpha(comboEnabled and 1.0 or 0.45) - if self.comboPointsYOffsetSlider.EnableMouse then self.comboPointsYOffsetSlider:EnableMouse(comboEnabled) end - end - - local immunitiesEnabled = BNP.ArePvPImmunitiesEnabled and BNP:ArePvPImmunitiesEnabled() or false - if self.immunityIconSlider then - self.immunityIconSlider:SetAlpha(immunitiesEnabled and 1.0 or 0.45) - if self.immunityIconSlider.EnableMouse then self.immunityIconSlider:EnableMouse(immunitiesEnabled) end - end - if self.immunityYOffsetSlider then - self.immunityYOffsetSlider:SetAlpha(immunitiesEnabled and 1.0 or 0.45) - if self.immunityYOffsetSlider.EnableMouse then self.immunityYOffsetSlider:EnableMouse(immunitiesEnabled) end - end - if self.immunityPositionLabel then - self.immunityPositionLabel:SetTextColor(immunitiesEnabled and 1 or 0.5, immunitiesEnabled and 1 or 0.5, immunitiesEnabled and 1 or 0.5) - end - if self.immunityPositionDropdown then - self.immunityPositionDropdown:SetAlpha(immunitiesEnabled and 1.0 or 0.45) - if immunitiesEnabled then - if UIDropDownMenu_EnableDropDown then UIDropDownMenu_EnableDropDown(self.immunityPositionDropdown) end - else - if UIDropDownMenu_DisableDropDown then UIDropDownMenu_DisableDropDown(self.immunityPositionDropdown) end - end - end - - local totemsEnabled = BNP.AreTotemIndicatorsEnabled and BNP:AreTotemIndicatorsEnabled() or false - if self.totemIconSlider then - self.totemIconSlider:SetAlpha(totemsEnabled and 1.0 or 0.45) - if self.totemIconSlider.EnableMouse then self.totemIconSlider:EnableMouse(totemsEnabled) end - end - - local glowEnabled = BNP:IsTargetFocusEnabled() - local arrowsEnabled = BNP.AreTargetArrowsEnabled and BNP:AreTargetArrowsEnabled() or false - local targetColorEnabled = glowEnabled or arrowsEnabled - if self.glowColorLabel then - self.glowColorLabel:SetTextColor(targetColorEnabled and 1 or 0.5, targetColorEnabled and 0.82 or 0.5, targetColorEnabled and 0 or 0.5) - end - if self.glowColorDropdown then - self.glowColorDropdown:SetAlpha(targetColorEnabled and 1.0 or 0.45) - if targetColorEnabled then - if UIDropDownMenu_EnableDropDown then UIDropDownMenu_EnableDropDown(self.glowColorDropdown) end - else - if UIDropDownMenu_DisableDropDown then UIDropDownMenu_DisableDropDown(self.glowColorDropdown) end - end - end - if self.targetGlowSizeSlider then - self.targetGlowSizeSlider:SetAlpha(glowEnabled and 1.0 or 0.45) - if self.targetGlowSizeSlider.EnableMouse then self.targetGlowSizeSlider:EnableMouse(glowEnabled) end - end - if self.targetGlowOpacitySlider then - self.targetGlowOpacitySlider:SetAlpha(glowEnabled and 1.0 or 0.45) - if self.targetGlowOpacitySlider.EnableMouse then self.targetGlowOpacitySlider:EnableMouse(glowEnabled) end - end - if self.arrowColorLabel then - self.arrowColorLabel:SetTextColor(arrowsEnabled and 1 or 0.5, arrowsEnabled and 0.82 or 0.5, arrowsEnabled and 0 or 0.5) - end - if self.arrowColorDropdown then - self.arrowColorDropdown:SetAlpha(arrowsEnabled and 1.0 or 0.45) - if arrowsEnabled then - if UIDropDownMenu_EnableDropDown then UIDropDownMenu_EnableDropDown(self.arrowColorDropdown) end - else - if UIDropDownMenu_DisableDropDown then UIDropDownMenu_DisableDropDown(self.arrowColorDropdown) end - end - end - if self.arrowStyleLabel then - self.arrowStyleLabel:SetTextColor(arrowsEnabled and 1 or 0.5, arrowsEnabled and 0.82 or 0.5, arrowsEnabled and 0 or 0.5) - end - if self.arrowStyleDropdown then - self.arrowStyleDropdown:SetAlpha(arrowsEnabled and 1.0 or 0.45) - if arrowsEnabled then - if UIDropDownMenu_EnableDropDown then UIDropDownMenu_EnableDropDown(self.arrowStyleDropdown) end - else - if UIDropDownMenu_DisableDropDown then UIDropDownMenu_DisableDropDown(self.arrowStyleDropdown) end - end - end - if self.targetArrowSizeSlider then - self.targetArrowSizeSlider:SetAlpha(arrowsEnabled and 1.0 or 0.45) - if self.targetArrowSizeSlider.EnableMouse then self.targetArrowSizeSlider:EnableMouse(arrowsEnabled) end - end - SetCheckEnabled(self.targetArrowThickCheck, arrowsEnabled) - end - - frame:ShowTab("nameplates") - self.optionsFrame = frame -end - -function BNP:SyncOptions() - self:CreateOptions() - local frame = self.optionsFrame - frame.scaleSlider:SetValue(self:GetNameplateScale()) - if frame.yOffsetSlider then - local yOffset = self:GetNameplateYOffset() - frame.yOffsetSlider:SetValue(yOffset) - getglobal(frame.yOffsetSlider:GetName() .. "Text"):SetText("Nameplate Y Offset: +" .. yOffset) - end - if frame.nameFontSizeSlider or frame.nameFontYOffsetSlider then - frame.BNPSyncingNameControls = true - if frame.nameFontSizeSlider then - local value = self:GetNameFontSize() - frame.nameFontSizeSlider:SetValue(value) - getglobal(frame.nameFontSizeSlider:GetName() .. "Text"):SetText("Name Font Size: " .. value) - end - if frame.nameFontYOffsetSlider then - local value = self:GetNameFontYOffset() - frame.nameFontYOffsetSlider:SetValue(value) - getglobal(frame.nameFontYOffsetSlider:GetName() .. "Text"):SetText("Name Y Offset: " .. (value > 0 and "+" or "") .. value) - end - frame.BNPSyncingNameControls = nil - end - if frame.comboPointsYOffsetSlider then - local value = self:GetComboPointsYOffset() - frame.comboPointsYOffsetSlider:SetValue(value) - getglobal(frame.comboPointsYOffsetSlider:GetName() .. "Text"):SetText("Combo Point Y Offset: " .. (value > 0 and "+" or "") .. value) - end - if frame.debuffYOffsetSlider then - local value = self:GetDebuffYOffset() - frame.debuffYOffsetSlider:SetValue(value) - getglobal(frame.debuffYOffsetSlider:GetName() .. "Text"):SetText("Debuff Y Offset: " .. (value > 0 and "+" or "") .. value) - end - if frame.ccYOffsetSlider then - local value = self:GetCCYOffset() - frame.ccYOffsetSlider:SetValue(value) - getglobal(frame.ccYOffsetSlider:GetName() .. "Text"):SetText("CC Y Offset: " .. (value > 0 and "+" or "") .. value) - end - if frame.immunityYOffsetSlider then - local value = self:GetImmunityYOffset() - frame.immunityYOffsetSlider:SetValue(value) - getglobal(frame.immunityYOffsetSlider:GetName() .. "Text"):SetText("Immunity Y Offset: " .. (value > 0 and "+" or "") .. value) - end - if frame.nonTargetAlphaSlider then - local alphaPercent = math.floor((self:GetNonTargetAlpha() * 100) + 0.5) - frame.nonTargetAlphaSlider:SetValue(alphaPercent) - getglobal(frame.nonTargetAlphaSlider:GetName() .. "Text"):SetText("Non-Target Alpha: " .. alphaPercent .. "%") - end - frame.iconSlider:SetValue(self:GetIconSize()) - if frame.ccIconSlider then - local ccSize = self:GetCCIconSize() - frame.ccIconSlider:SetValue(ccSize) - getglobal(frame.ccIconSlider:GetName() .. "Text"):SetText("CC Icon Size: " .. ccSize) - end - if frame.immunityIconSlider then - local immunitySize = self:GetImmunityIconSize() - frame.immunityIconSlider:SetValue(immunitySize) - getglobal(frame.immunityIconSlider:GetName() .. "Text"):SetText("Immunity Icon Size: " .. immunitySize) - end - if frame.totemIconSlider then - local totemSize = self:GetTotemIconSize() - frame.totemIconSlider:SetValue(totemSize) - getglobal(frame.totemIconSlider:GetName() .. "Text"):SetText("Totem Icon Size: " .. totemSize) - end - frame.castbarHeightSlider:SetValue(self:GetCastbarHeight()) - if frame.castbarSpacingSlider then - local spacing = self:GetCastbarSpacing() - frame.castbarSpacingSlider:SetValue(spacing) - getglobal(frame.castbarSpacingSlider:GetName() .. "Text"):SetText("Castbar Spacing: " .. spacing .. " px") - end - frame.classColorsCheck:SetChecked(self:AreClassColorsEnabled()) - if frame.hidePlayerNamesCheck then frame.hidePlayerNamesCheck:SetChecked(self:HidePlayerNamesEnabled()) end - if frame.hideNPCNamesCheck then frame.hideNPCNamesCheck:SetChecked(self:HideNPCNamesEnabled()) end - if frame.debuffsCheck then frame.debuffsCheck:SetChecked(self:AreDebuffsEnabled()) end - if frame.debuffPositionDropdown then - local position = self:GetDebuffPosition() - local labels = { top = "Top Mid", top_left = "Top Left", top_right = "Top Right", left = "Left", right = "Right", bottom_mid = "Bottom Mid", bottom_left = "Bottom Left", bottom_right = "Bottom Right" } - UIDropDownMenu_SetSelectedValue(frame.debuffPositionDropdown, position) - UIDropDownMenu_SetText(labels[position] or "Top Mid", frame.debuffPositionDropdown) - end - if frame.ccPositionDropdown then - local position = self:GetCCPosition() - local labels = { top = "Top", left = "Left", right = "Right" } - UIDropDownMenu_SetSelectedValue(frame.ccPositionDropdown, position) - UIDropDownMenu_SetText(labels[position] or "Top", frame.ccPositionDropdown) - end - if frame.crowdControlCheck then frame.crowdControlCheck:SetChecked(self:AreCrowdControlEnabled()) end - if frame.separateCCRowCheck then frame.separateCCRowCheck:SetChecked(self:IsSeparateCCRowEnabled()) end - if frame.showOtherCCsCheck then frame.showOtherCCsCheck:SetChecked(self:ShowOtherPlayersCCs()) end - if frame.pvpImmunitiesCheck then frame.pvpImmunitiesCheck:SetChecked(self:ArePvPImmunitiesEnabled()) end - if frame.immunityPositionDropdown then - local position = self:GetImmunityPosition() - local labels = { top = "Top", left = "Left", right = "Right" } - UIDropDownMenu_SetSelectedValue(frame.immunityPositionDropdown, position) - UIDropDownMenu_SetText(labels[position] or "Top", frame.immunityPositionDropdown) - end - if frame.totemIndicatorsCheck then frame.totemIndicatorsCheck:SetChecked(self:AreTotemIndicatorsEnabled()) end - frame.castbarsCheck:SetChecked(self:AreCastbarsEnabled()) - if frame.castbarTestCheck then - frame.castbarTestCheck:SetChecked(self.IsCastbarTestMode and self:IsCastbarTestMode() or false) - end - frame.tankCheck:SetChecked(self:IsTankModeEnabled()) - if frame.comboPointsCheck and comboOptionsClass then - frame.comboPointsCheck:SetChecked(self:AreComboPointsEnabled()) - end - if frame.healthTextDropdown then - local mode = self:GetHealthTextMode() - UIDropDownMenu_SetSelectedValue(frame.healthTextDropdown, mode) - local labels = { off = "Off", percent = "Percent", hp = "HP", both = "HP + Percent" } - UIDropDownMenu_SetText(labels[mode] or "Off", frame.healthTextDropdown) - end - if frame.healthTextFontSizeSlider then - frame.BNPSyncingHealthTextControls = true - local size = self:GetHealthTextFontSize() - frame.healthTextFontSizeSlider:SetValue(size) - getglobal(frame.healthTextFontSizeSlider:GetName() .. "Text"):SetText("Health Font Size: " .. size) - frame.BNPSyncingHealthTextControls = nil - end - if frame.healthTextOutlineDropdown then - local outline = self:GetHealthTextOutline() - local labels = { none = "None", outline = "Outline", thick = "Thick Outline" } - UIDropDownMenu_SetSelectedValue(frame.healthTextOutlineDropdown, outline) - UIDropDownMenu_SetText(labels[outline] or "Outline", frame.healthTextOutlineDropdown) - end - frame.targetFocusCheck:SetChecked(self:IsTargetFocusEnabled()) - if frame.targetArrowsCheck then - frame.targetArrowsCheck:SetChecked(self.AreTargetArrowsEnabled and self:AreTargetArrowsEnabled() or false) - end - if frame.arrowColorDropdown then - local _, _, _, color = self:GetTargetArrowColor() - local labels = { - match = "Match Target Color", - white = "White", - gold = "Gold", - blue = "Blue", - green = "Green", - red = "Red", - purple = "Purple", - } - UIDropDownMenu_SetSelectedValue(frame.arrowColorDropdown, color or "match") - UIDropDownMenu_SetText(labels[color] or "Match Target Color", frame.arrowColorDropdown) - end - if frame.arrowStyleDropdown then - local style = self:GetTargetArrowStyle() - local labels = { - chevron = "Chevron", - triangle = "Triangle", - slim_triangle = "Slim Triangle", - double_chevron = "Double Chevron", - diamond_tip = "Diamond Tip", - } - UIDropDownMenu_SetSelectedValue(frame.arrowStyleDropdown, style) - UIDropDownMenu_SetText(labels[style] or "Chevron", frame.arrowStyleDropdown) - end - if frame.targetArrowSizeSlider then - local arrowSize = self:GetTargetArrowSize() - frame.targetArrowSizeSlider:SetValue(arrowSize) - getglobal(frame.targetArrowSizeSlider:GetName() .. "Text"):SetText("Target Arrow Size: " .. arrowSize) - end - if frame.targetArrowThickCheck then - frame.targetArrowThickCheck:SetChecked(self.AreTargetArrowsThick and self:AreTargetArrowsThick() or false) - end - - if frame.glowColorDropdown then - local _, _, _, color = self:GetTargetGlowColor() - local labels = { - white = "White", - gold = "Gold", - blue = "Blue", - green = "Green", - red = "Red", - purple = "Purple", - } - UIDropDownMenu_SetSelectedValue(frame.glowColorDropdown, color or "white") - UIDropDownMenu_SetText(labels[color] or "White", frame.glowColorDropdown) - end - if frame.targetGlowSizeSlider then - local glowSize = self:GetTargetGlowSize() - frame.targetGlowSizeSlider:SetValue(glowSize) - getglobal(frame.targetGlowSizeSlider:GetName() .. "Text"):SetText("Target Glow Size: +" .. glowSize .. " px") - end - if frame.targetGlowOpacitySlider then - local opacityPercent = math.floor((self:GetTargetGlowOpacity() * 100) + 0.5) - frame.targetGlowOpacitySlider:SetValue(opacityPercent) - getglobal(frame.targetGlowOpacitySlider:GetName() .. "Text"):SetText("Target Glow Opacity: " .. opacityPercent .. "%") - end - - if frame.UpdateDependentControls then frame:UpdateDependentControls() end - frame.versionText:SetText("Version " .. tostring(self.version or "?")) -end - -function BNP:ToggleOptions() - self:SyncOptions() - if self.optionsFrame:IsShown() then - self.optionsFrame:Hide() - else - self.optionsFrame:Show() - end -end - -function BNP:CreateMinimapButton() - if self.minimapButton then return end - - BNP_DB = BNP_DB or {} - if BNP_DB.minimapAngle == nil then BNP_DB.minimapAngle = 225 end - - local button = CreateFrame("Button", "BNPMinimapButton", Minimap) - button:SetWidth(31) - button:SetHeight(31) - button:SetFrameStrata("MEDIUM") - button:SetFrameLevel((Minimap:GetFrameLevel() or 1) + 8) - button:RegisterForClicks("LeftButtonUp") - button:RegisterForDrag("LeftButton") - button:EnableMouse(true) - button:SetMovable(true) - - -- Classic round minimap-button background. - local bg = button:CreateTexture(nil, "BACKGROUND") - bg:SetTexture("Interface\\Minimap\\UI-Minimap-Background") - bg:SetWidth(22) - bg:SetHeight(22) - bg:SetPoint("CENTER", button, "CENTER", 0, 0) - button.bg = bg - - -- Addon identity: simple BN+ lettering instead of a spell/item icon. - -- Rendered directly by the client, so no external texture file is needed. - local iconBG = button:CreateTexture(nil, "ARTWORK") - iconBG:SetTexture(0.03, 0.03, 0.03, 1) - iconBG:SetWidth(20) - iconBG:SetHeight(20) - iconBG:SetPoint("CENTER", button, "CENTER", 0, 0) - button.iconBG = iconBG - - local label = button:CreateFontString(nil, "OVERLAY") - label:SetFont("Fonts\\FRIZQT__.TTF", 10, "OUTLINE") - label:SetPoint("CENTER", button, "CENTER", 0, 0) - label:SetText("BN+") - label:SetTextColor(0.20, 0.60, 1.00) - button.label = label - - -- Standard Blizzard circular minimap border. - local border = button:CreateTexture(nil, "OVERLAY") - border:SetTexture("Interface\\Minimap\\MiniMap-TrackingBorder") - border:SetWidth(54) - border:SetHeight(54) - border:SetPoint("TOPLEFT", button, "TOPLEFT", 0, 0) - button.border = border - - local highlight = button:CreateTexture(nil, "HIGHLIGHT") - highlight:SetTexture("Interface\\Minimap\\UI-Minimap-ZoomButton-Highlight") - highlight:SetBlendMode("ADD") - highlight:SetAllPoints(button) - button.highlight = highlight - - local function UpdatePosition() - local angle = tonumber(BNP_DB.minimapAngle) or 225 - local radius = 78 - local rad = math.rad(angle) - - button:ClearAllPoints() - button:SetPoint( - "CENTER", - Minimap, - "CENTER", - math.cos(rad) * radius, - math.sin(rad) * radius - ) - end - - local function UpdateAngleFromCursor() - local mx, my = Minimap:GetCenter() - local scale = 1 - if UIParent.GetEffectiveScale then - scale = UIParent:GetEffectiveScale() or 1 - elseif UIParent.GetScale then - scale = UIParent:GetScale() or 1 - end - local cx, cy = GetCursorPosition() - cx = cx / scale - cy = cy / scale - - local dx = cx - mx - local dy = cy - my - - local angle - if math.atan2 then - angle = math.deg(math.atan2(dy, dx)) - else - if dx == 0 then - angle = dy >= 0 and 90 or -90 - else - angle = math.deg(math.atan(dy / dx)) - if dx < 0 then angle = angle + 180 end - end - end - BNP_DB.minimapAngle = angle - UpdatePosition() - end - - button:SetScript("OnDragStart", function() - this:SetScript("OnUpdate", UpdateAngleFromCursor) - end) - - button:SetScript("OnDragStop", function() - this:SetScript("OnUpdate", nil) - UpdateAngleFromCursor() - end) - - button:SetScript("OnClick", function() - BNP:ToggleOptions() - end) - - button:SetScript("OnEnter", function() - GameTooltip:SetOwner(this, "ANCHOR_LEFT") - GameTooltip:SetText("Blizz Nameplates+") - GameTooltip:AddLine("Left-click: Open settings", 1, 1, 1) - GameTooltip:AddLine("Drag: Move minimap button", 0.8, 0.8, 0.8) - GameTooltip:Show() - end) - - button:SetScript("OnLeave", function() - GameTooltip:Hide() - end) - - UpdatePosition() - self.minimapButton = button -end diff --git a/core/ui.lua b/core/ui.lua deleted file mode 100644 index 57b6782..0000000 --- a/core/ui.lua +++ /dev/null @@ -1,15 +0,0 @@ -BNP = BNP or {} - --- Central visual constants. Keeping these values in one place lets us polish --- the Blizzard-style presentation without touching aura tracking logic. -BNP.UI = BNP.UI or { - ICON_SIZE = 18, - ICON_OFFSET_Y = 15, - ICON_SPACING = 2, - TIMER_FONT = "Fonts\\FRIZQT__.TTF", - TIMER_SIZE = 8, - TIMER_OFFSET_X = 0, - TIMER_OFFSET_Y = 0, - TIMER_SHADOW_X = 1, - TIMER_SHADOW_Y = -1, -}