HideCoAUI = {} local f = CreateFrame("Frame") HideCoAUI.CUSTOM_CLASSES = { "NECROMANCER", "PYROMANCER", "CULTIST", "STARCALLER", "SUNCLERIC", "TINKER", "SPIRITMAGE", "WILDWALKER", "REAPER", "PROPHET", "CHRONOMANCER", "SONOFARUGAL", "GUARDIAN", "STORMBRINGER", "DEMONHUNTER", "BARBARIAN", "WITCHDOCTOR", "WITCHHUNTER", "FLESHWARDEN", "MONK", "RANGER", } HideCoAUI.FRAMES = { "CoAResourceSegmentBar", "CoAResourceOrb", "CoAResourceBar", "CoAMultiCastActionBarFrame", -- "CoASpellActivationOverlay", -- found via full frame scan, deliberately left without a checkbox -- "ExtraActionBar", } HideCoAUI.FRAME_DISPLAY_NAMES = { PYROMANCER = { CoAResourceSegmentBar = "Ember Gauge", CoAResourceBar = "Heat Gauge", }, CULTIST = { CoAResourceOrb = "Insanity", }, PROPHET = { CoAResourceSegmentBar = "Brood Marks", }, STARCALLER = { CoAResourceOrb = "Lunar Phase", }, SUNCLERIC = { CoAResourceOrb = "Solar Power", }, } local function GetFrameDisplayName(class, frameName) local classNames = HideCoAUI.FRAME_DISPLAY_NAMES[class] return classNames and classNames[frameName] end HideCoAUI.GetFrameDisplayName = GetFrameDisplayName local function CreateDefaultClassSettings() local classSettings = {} for _, class in ipairs(HideCoAUI.CUSTOM_CLASSES) do classSettings[class] = {} for _, frameName in ipairs(HideCoAUI.FRAMES) do classSettings[class][frameName] = false end end return classSettings end local function EnsureClassSettingsComplete(classSettings) for _, class in ipairs(HideCoAUI.CUSTOM_CLASSES) do if type(classSettings[class]) ~= "table" then classSettings[class] = {} end for _, frameName in ipairs(HideCoAUI.FRAMES) do if classSettings[class][frameName] == nil then classSettings[class][frameName] = false end end end end local function GetCharacterKey() local _, classToken = UnitClass("player") local className = (LOCALIZED_CLASS_NAMES_MALE and LOCALIZED_CLASS_NAMES_MALE[classToken]) or classToken return UnitName("player") .. " - " .. className .. " - " .. GetRealmName() end HideCoAUI.GetCharacterKey = GetCharacterKey local function GetActiveProfileName() local charKey = GetCharacterKey() local assigned = HideCoADB.charProfile and HideCoADB.charProfile[charKey] if assigned and HideCoADB.profiles[assigned] then return assigned end return charKey end HideCoAUI.GetActiveProfileName = GetActiveProfileName local function SetActiveProfileName(name) HideCoADB.charProfile[GetCharacterKey()] = name end HideCoAUI.SetActiveProfileName = SetActiveProfileName local function GetClassSettings() if not HideCoADB.classSettings then HideCoADB.classSettings = CreateDefaultClassSettings() end return HideCoADB.classSettings end HideCoAUI.GetClassSettings = GetClassSettings local function DeleteProfile(name) HideCoADB.profiles[name] = nil for charKey, assigned in pairs(HideCoADB.charProfile) do if assigned == name then -- Unassigning falls back to the character's own auto-created -- profile (see GetActiveProfileName/GetProfileOverride), -- which gets recreated on demand if it doesn't exist. HideCoADB.charProfile[charKey] = nil end end end HideCoAUI.DeleteProfile = DeleteProfile local function EnsureProfileOverride(name) local profile = HideCoADB.profiles[name] if not profile then profile = {} HideCoADB.profiles[name] = profile end if not profile.override then profile.override = { enabled = false, frameSettings = {} } end for _, frameName in ipairs(HideCoAUI.FRAMES) do if profile.override.frameSettings[frameName] == nil then profile.override.frameSettings[frameName] = false end end return profile.override end local function GetProfileOverride(name) return EnsureProfileOverride(name) end HideCoAUI.GetProfileOverride = GetProfileOverride local function SetProfileOverrideEnabled(name, enabled) GetProfileOverride(name).enabled = enabled HideCoAUI.ApplySetting() end HideCoAUI.SetProfileOverrideEnabled = SetProfileOverrideEnabled local function SetProfileOverrideFrameHidden(name, frameName, hide) GetProfileOverride(name).frameSettings[frameName] = hide HideCoAUI.ApplySetting() end HideCoAUI.SetProfileOverrideFrameHidden = SetProfileOverrideFrameHidden local function GetProfileNames() local names = {} for name in pairs(HideCoADB.profiles) do table.insert(names, name) end table.sort(names) return names end HideCoAUI.GetProfileNames = GetProfileNames local function SetAllClassesHidden(hide) local classSettings = GetClassSettings() for _, class in ipairs(HideCoAUI.CUSTOM_CLASSES) do for _, frameName in ipairs(HideCoAUI.FRAMES) do classSettings[class][frameName] = hide end end end local function HideAllFrames() SetAllClassesHidden(true) HideCoAUI.ApplySetting() end HideCoAUI.HideAllFrames = HideAllFrames local function ShowAllFrames() SetAllClassesHidden(false) HideCoAUI.ApplySetting() end HideCoAUI.ShowAllFrames = ShowAllFrames local function ShouldHideForClass(playerClass, frameName) local classSettings = GetClassSettings()[playerClass] if not classSettings or classSettings[frameName] == nil then return false end return classSettings[frameName] end local function ShouldHideFrame(frameName) local override = GetProfileOverride(GetActiveProfileName()) if override.enabled then return override.frameSettings[frameName] end local _, playerClass = UnitClass("player") return ShouldHideForClass(playerClass, frameName) end local hookedFrames = {} local seenNaturalShow = {} local function ApplySetting() for _, frameName in ipairs(HideCoAUI.FRAMES) do local frame = _G[frameName] if frame then if not hookedFrames[frameName] then frame:HookScript("OnShow", function(self) seenNaturalShow[frameName] = true if ShouldHideFrame(frameName) then self:Hide() end end) hookedFrames[frameName] = true end local hide = ShouldHideFrame(frameName) if hide then frame:Hide() elseif seenNaturalShow[frameName] then -- The server never Show()s a frame the current class doesn't use, -- so its data (powerType, maxValue, ...) is never populated. Forcing -- Show() on it exposes that uninitialized state and crashes the -- server's own OnUpdate handler. Only force-show a frame we've -- already seen the game display naturally at least once. frame:Show() end if frame.EnableMouse then frame:EnableMouse(not hide) end end end end HideCoAUI.ApplySetting = ApplySetting f:RegisterEvent("ADDON_LOADED") f:RegisterEvent("PLAYER_LOGIN") f:SetScript("OnEvent", function(self, event, arg1) if event == "ADDON_LOADED" and arg1 == "HideCoAUI" then if not HideCoADB then HideCoADB = {} end if not HideCoADB.profiles then HideCoADB.profiles = {} end if not HideCoADB.charProfile then HideCoADB.charProfile = {} end -- An older saved-variable format duplicated classSettings per profile -- instead of sharing one account-wide table. Pull whichever profile -- still has one as the seed so existing hide/show choices survive -- the upgrade to a single global classSettings. if not HideCoADB.classSettings then for _, profile in pairs(HideCoADB.profiles) do if profile.classSettings then HideCoADB.classSettings = profile.classSettings break end end end if not HideCoADB.classSettings then HideCoADB.classSettings = CreateDefaultClassSettings() end EnsureClassSettingsComplete(HideCoADB.classSettings) local charKey = GetCharacterKey() -- The profile-name syntax used to be "realm - character"; rename any -- existing profile created under that scheme to the new ordering -- instead of leaving it orphaned in the list. local ancientCharKey = GetRealmName() .. " - " .. UnitName("player") if HideCoADB.profiles[ancientCharKey] and not HideCoADB.profiles[charKey] then HideCoADB.profiles[charKey] = HideCoADB.profiles[ancientCharKey] HideCoADB.profiles[ancientCharKey] = nil end -- The syntax was later "character - realm", without the class; rename -- any existing profile/assignment created under that scheme too. local legacyCharKey = UnitName("player") .. " - " .. GetRealmName() if HideCoADB.profiles[legacyCharKey] and not HideCoADB.profiles[charKey] then HideCoADB.profiles[charKey] = HideCoADB.profiles[legacyCharKey] HideCoADB.profiles[legacyCharKey] = nil end if HideCoADB.charProfile[legacyCharKey] then local assigned = HideCoADB.charProfile[legacyCharKey] HideCoADB.charProfile[charKey] = (assigned == legacyCharKey) and charKey or assigned HideCoADB.charProfile[legacyCharKey] = nil end if HideCoADB.characterOverrides and HideCoADB.characterOverrides[legacyCharKey] and not HideCoADB.characterOverrides[charKey] then HideCoADB.characterOverrides[charKey] = HideCoADB.characterOverrides[legacyCharKey] HideCoADB.characterOverrides[legacyCharKey] = nil end if not HideCoADB.profiles[charKey] then HideCoADB.profiles[charKey] = {} end for name, profile in pairs(HideCoADB.profiles) do profile.classSettings = nil EnsureProfileOverride(name) end if not HideCoADB.charProfile[charKey] then HideCoADB.charProfile[charKey] = charKey end -- The override toggle used to live per-character; fold any existing -- per-character override into whichever profile is currently active -- for this character so nobody's existing choice silently vanishes. if HideCoADB.characterOverrides and HideCoADB.characterOverrides[charKey] then local activeName = GetActiveProfileName() local activeProfile = HideCoADB.profiles[activeName] if activeProfile and not activeProfile.override then activeProfile.override = HideCoADB.characterOverrides[charKey] EnsureProfileOverride(activeName) end HideCoADB.characterOverrides[charKey] = nil end HideCoADB.selectedProfile = nil elseif event == "PLAYER_LOGIN" then ApplySetting() end end)