From: Aleksi Blinnikka Date: Mon, 18 Dec 2017 02:07:01 +0000 (+0200) Subject: Initial commit X-Git-Url: https://www.aleksib.fi/git/wowui.git/commitdiff_plain/8f4bc830f37b66724627f90628b8e3179ad98440?ds=inline Initial commit --- 8f4bc830f37b66724627f90628b8e3179ad98440 diff --git a/RaidFrameCustomization.toc b/RaidFrameCustomization.toc new file mode 100644 index 0000000..ac779a9 --- /dev/null +++ b/RaidFrameCustomization.toc @@ -0,0 +1,14 @@ +## Interface: 70300 +## Title: Raid Frame Customization + +## Version: 1.13 +## Author: Szandos, Jack, schyrio +## Notes: Customization to the standard raid frames +## SavedVariables: IndicatorsDB + +embeds.xml + +RaidFrameIndicators.lua +RaidFrameIndicatorsConfig.lua +RaidFrameNames.lua +RaidFrameHealth.lua \ No newline at end of file diff --git a/RaidFrameHealth.lua b/RaidFrameHealth.lua new file mode 100644 index 0000000..dbed189 --- /dev/null +++ b/RaidFrameHealth.lua @@ -0,0 +1,35 @@ +hooksecurefunc("CompactUnitFrame_UpdateStatusText", + function(frame) + if frame and not frame:IsForbidden() then + local frameName = frame:GetName(); + if frameName and frameName:match("^CompactRaidFrame%d") and frame.unit then + -- conditions taken from CompactUnitFrame.lua + if not UnitIsConnected(frame.unit) or UnitIsDeadOrGhost(frame.displayedUnit) then + return; + elseif ( frame.optionTable.healthText == "losthealth" ) then + -- only losthealth option is condensed + local healthLost = UnitHealthMax(frame.displayedUnit) - UnitHealth(frame.displayedUnit); + local prettyHealth; + if healthLost > 1200000000 then -- 1.2B + local h1b = healthLost / 1000000000; + local h100m = (healthLost % 1000000000) / 100000000; + prettyHealth = string.format("-%d.%dB", h1b, h100m); + elseif healthLost > 1200000 then -- 1.2M + prettyHealth = string.format("-%dM", healthLost / 1000000); + elseif healthLost > 1000 then -- 1K + prettyHealth = string.format("-%dK", healthLost / 1000); + else + prettyHealth = string.format("-%d", healthLost) + end + + if healthLost > 0 then + frame.statusText:SetText(prettyHealth); + frame.statusText:Show(); + else + frame.statusText:Hide(); + end + end + end + end + end +); diff --git a/RaidFrameIndicators.lua b/RaidFrameIndicators.lua new file mode 100644 index 0000000..782e5bd --- /dev/null +++ b/RaidFrameIndicators.lua @@ -0,0 +1,291 @@ +-- ---------------------------------------------------------------------------- +-- Raid Frame Indicators by Szandos, schyrio +-- ---------------------------------------------------------------------------- +Indicators = LibStub( "AceAddon-3.0" ):NewAddon( "Indicators", "AceTimer-3.0"); +local media = LibStub:GetLibrary("LibSharedMedia-3.0"); +local f = {}; -- Indicator objects +local pad = 2; +local _; +local watchedAuras; -- all watched auras +local indicatorAuras; -- watched auras per indicator +local DEFAULT_ICON = "Interface\\AddOns\\RaidFrameCustomization\\images\\rhomb"; + +-- Hide buff/debuff icons +local function hideBlizzardBuffs(frame) + -- used in CompactUnitFrame_UpdateAuras (Buffs, Debuffs, DispellableDebuffs) + if frame.optionTable.displayBuffs then + frame.optionTable.displayBuffs = false + -- used in CompactUnitFrame_UpdateHealthColor, might not be set prior + frame.optionTable.healthBarColorOverride = CreateColor(0.4, 0.4, 0.4); + end + if frame.optionTable.displayDebuffs then frame.optionTable.displayDebuffs = false end + -- TODO + if frame.optionTable.displayDispelDebuffs then frame.optionTable.displayDispelDebuffs = true end + +end +hooksecurefunc("CompactUnitFrame_SetOptionTable", hideBlizzardBuffs); + +-- Set the appearance of the FontStrings +local function setupIndicatorAppearance(frame) + local frameName = frame:GetName(); + if not f[frameName] then return end + local font = media and media:Fetch('font', Indicators.db.profile.indicatorFont) or STANDARD_TEXT_FONT; + + local i; + for i = 1, 5 do + f[frameName][i].text:SetFont(font, Indicators.db.profile["textSize"..i], ""); + f[frameName][i].icon:SetWidth(Indicators.db.profile["iconSize"..i]); + f[frameName][i].icon:SetHeight(Indicators.db.profile["iconSize"..i]); + if Indicators.db.profile["showIcon"..i] then + f[frameName][i].icon:Show(); + else + f[frameName][i].icon:Hide(); + end + end +end + +-- Create the FontStrings used for indicators +local function setupCompactUnitFrame(frame) + local frameName = frame:GetName(); + local i; + local positions = { + "TOPLEFT", "TOPRIGHT", "CENTER", "BOTTOMLEFT", "BOTTOMRIGHT" + }; + local paddings = { + {pad, -pad}, {-pad, -pad}, {0, 0}, {pad, pad}, {-pad, pad} + }; + + -- Create indicators + f[frameName] = {}; + for i = 1, 5 do + f[frameName][i] = {}; + f[frameName][i].text = frame:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall"); + f[frameName][i].text:SetPoint(positions[i], frame, positions[i], paddings[i][1], paddings[i][2]); + f[frameName][i].icon = frame:CreateTexture(nil, "OVERLAY"); + f[frameName][i].icon:SetPoint(positions[i], frame, positions[i], paddings[i][1], paddings[i][2]); + end + setupIndicatorAppearance(frame); +end + +-- Get all unit auras +local function getAuras(unit) + local unitBuffs = {}; + local unitDebuffs = {}; + local auraName, icon, count, expires, caster, debuffType, spellId; + local i = 1; + + -- Get all unit buffs + while true do + auraName, _, icon, count, _, _, expires, caster, _, _, spellId = UnitBuff(unit, i); + if not spellId then break end + if watchedAuras[auraName] or watchedAuras[spellId] then + -- possibly non-contiguous indexes, doesn't matter + unitBuffs[i] = {}; + unitBuffs[i].auraName = auraName; + unitBuffs[i].spellId = spellId; + unitBuffs[i].count = count; + unitBuffs[i].expires = expires; + unitBuffs[i].mine = UnitIsUnit(caster, "player"); + unitBuffs[i].icon = icon; + end + i = i + 1; + end + + -- Get all unit debuffs + i = 1; + while true do + auraName, _, icon, count, debuffType, _, expires, caster, _, _, spellId = UnitDebuff(unit, i); + if not spellId then break end + -- TODO debuffType check better + if watchedAuras[auraName] or watchedAuras[spellId] or watchedAuras[debuffType] then + unitDebuffs[i] = {}; + unitDebuffs[i].auraName = auraName; + unitDebuffs[i].spellId = spellId; + unitDebuffs[i].count = count; + unitDebuffs[i].expires = expires; + unitDebuffs[i].mine = UnitIsUnit(caster, "player"); + unitDebuffs[i].icon = icon; + unitDebuffs[i].debuffType = debuffType; + end + i = i + 1; + end + + return unitBuffs, unitDebuffs; +end + +-- Check the indicators on a frame and update the times on them +local function updateIndicator(frame) + if not frame.unit then return end + local unit = frame.unit; + local frameName = frame:GetName(); + local currentTime = GetTime(); + local i; + + -- Check if the indicator object exists, else create it + if not f[frameName] then setupCompactUnitFrame(frame) end + -- Hide if unit is dead/disconnected + if (not UnitIsConnected(unit)) or UnitIsDeadOrGhost(frame.displayedUnit) then + for i = 1, 5 do + f[frameName][i].text:SetText(""); + f[frameName][i].icon:SetTexture(""); + end + return; + end + + local unitBuffs, unitDebuffs = getAuras(unit); + for i = 1, 5 do + -- try to find matching aura + local found, aura; + for _, aura in pairs(unitBuffs) do + if indicatorAuras[i][aura.auraName] or indicatorAuras[i][aura.spellId] then + found = aura; + -- break on first matching buff cast by me + -- otherwise continue through + if aura.mine then break end + end + end + if not found then + -- search debuffs if buff was not found + for _, aura in pairs(unitDebuffs) do + if indicatorAuras[i][aura.auraName] or indicatorAuras[i][aura.spellId] or + indicatorAuras[i][aura.debuffType] then + found = aura; + -- break on first matching debuff cast by me + -- otherwise continue through + if aura.mine then break end + end + end + end + + if found then + if Indicators.db.profile["mine"..i] and not found.mine then + -- don't show + f[frameName][i].icon:SetTexture(""); + f[frameName][i].text:SetText(""); + else + if Indicators.db.profile["showIcon"..i] then + -- show icon TODO coloring + if Indicators.db.profile["useDefaultIcon"..i] then + f[frameName][i].icon:SetTexture(DEFAULT_ICON); + else + f[frameName][i].icon:SetTexture(found.icon); + end + end + -- TODO make show text into general setting + -- under which you can select what text to show + if Indicators.db.profile["showText"..i] then + -- show text + local text; + local remaining = found.expires - currentTime; + if remaining > 60 then + text = string.format("%dm", ceil(remaining/60)); + else + text = string.format("%d", floor(remaining+0.5)); + end + + if Indicators.db.profile["stack"..i] and found.count > 0 then + if text then + text = found.count.."-"..text; + else + text = found.count; + end + end + + -- colors + f[frameName][i].text:SetTextColor( + Indicators.db.profile["color"..i].r, + Indicators.db.profile["color"..i].g, + Indicators.db.profile["color"..i].b, + Indicators.db.profile["color"..i].a + ); + if Indicators.db.profile["debuffColor"..i] then + if found.debuffType then + if found.debuffType == "Curse" then + f[frameName][i].text:SetTextColor(0.6,0,1,1); + elseif found.debuffType == "Disease" then + f[frameName][i].text:SetTextColor(0.6,0.4,0,1); + elseif found.debuffType == "Magic" then + f[frameName][i].text:SetTextColor(0.2,0.6,1,1); + elseif found.debuffType == "Poison" then + f[frameName][i].text:SetTextColor(0,0.6,0,1); + end + end + end + + f[frameName][i].text:SetText(text); + end + end + else + -- not found, show nothing + f[frameName][i].icon:SetTexture(""); + f[frameName][i].text:SetText(""); + end + end +end + +-- Update all indicators +function Indicators:UpdateAllIndicators() + CompactRaidFrameContainer_ApplyToFrames(CompactRaidFrameContainer, "normal", updateIndicator); +end + +-- Used to update everything that is affected by the configuration +function Indicators:RefreshConfig() + local i; + CompactRaidFrameContainer_ApplyToFrames(CompactRaidFrameContainer, "normal", setupIndicatorAppearance); + + -- Format aura strings + watchedAuras = {}; + indicatorAuras = {}; + local auraName, i + for i = 1, 5 do + indicatorAuras[i] = {}; + for auraName in string.gmatch(Indicators.db.profile["auras"..i], "[^\n]+") do -- Grab each line + auraName = string.gsub(auraName, "^%s*(.-)%s*$", "%1"); -- Strip any whitespaces + if tonumber(auraName) then + watchedAuras[tonumber(auraName)] = true; + indicatorAuras[i][tonumber(auraName)] = true; + else + watchedAuras[auraName] = true; + indicatorAuras[i][auraName] = true; + end + end + end + + self:CancelAllTimers(); + if next(watchedAuras) ~= nil then + self.updateTimer = self:ScheduleRepeatingTimer("UpdateAllIndicators", 0.11); + end +end + +function Indicators:OnInitialize() + -- Set up config pane + self:SetupOptions(); + + -- Register callbacks for profile switching + self.db.RegisterCallback(self, "OnProfileChanged", "RefreshConfig"); + self.db.RegisterCallback(self, "OnProfileCopied", "RefreshConfig"); + self.db.RegisterCallback(self, "OnProfileReset", "RefreshConfig"); +end + +function Indicators:OnEnable() + if self.db.profile.enabled then + Indicators:RefreshConfig(); + end +end + +function Indicators:OnDisable() + local i; + -- Stop update + self:CancelAllTimers(); + -- Hide all indicators + for frameName, _ in pairs(f) do + for i = 1, 5 do + f[frameName][i].text:SetText(""); + f[frameName][i].icon:SetTexture(""); + end + end +end + +function dPrint(s) + DEFAULT_CHAT_FRAME:AddMessage("Indicators: ".. tostring(s)); +end diff --git a/RaidFrameIndicatorsConfig.lua b/RaidFrameIndicatorsConfig.lua new file mode 100644 index 0000000..8eb0c30 --- /dev/null +++ b/RaidFrameIndicatorsConfig.lua @@ -0,0 +1,218 @@ +local Defaults = {} + +function CreateDefaults() + Defaults.profile = { + indicatorFont = "Arial Narrow", + showIcons = true, + enabled = true, + }; + for i = 1, 5 do + Defaults.profile["auras"..i] = ""; + Defaults.profile["textSize"..i] = 10; + Defaults.profile["color"..i] = {r = 1, g = 1, b = 1, a = 1,}; + Defaults.profile["mine"..i] = false; + Defaults.profile["stack"..i] = true; + Defaults.profile["debuffColor"..i] = false; + Defaults.profile["showText"..i] = true; + Defaults.profile["showIcon"..i] = true; + Defaults.profile["useDefaultIcon"..i] = true; + Defaults.profile["iconSize"..i] = 10; + end +end + +local Options = {} +function CreateOptions () + Options = { + type = 'group', + childGroups = 'tree', + get = function(item) return Indicators.db.profile[item[#item]] end, + set = function(item, value) Indicators.db.profile[item[#item]] = value; Indicators:RefreshConfig() end, + args = { + indicatorFont = { + type = 'select', + dialogControl = "LSM30_Font", + name = "Indicator Font", + desc = "Adjust the font used for the indicators", + values = AceGUIWidgetLSMlists.font, + order = 17, + }, + enabled = { + type = "toggle", + name = "Enabled", + desc = "Enable/Disable indicators", + order = 18, + set = function(item, value) + Indicators.db.profile[item[#item]] = value + if value == true then + Indicators:OnEnable() + else + Indicators:OnDisable() + end + end, + } + } + } + + --- Add options for each indicator + local indicatorNames = {"Top Left", "Top Right", "Center", "Bottom Left", "Bottom Right"} + for i = 1, 5 do + Options.args["i"..i] = {} + Options.args["i"..i].type = 'group' + Options.args["i"..i].name = indicatorNames[i] + Options.args["i"..i].order = i*10+10 + Options.args["i"..i].args = {} + Options.args["i"..i].args["auras"..i] = { + type = "input", + name = "Buffs/Debuffs", + desc = "The buffs/debuffs to show in this indicator. Put each buff/debuff on a separate line. You can use 'Magic/Poison/Curse/Disease' to show any debuff of that type.", + multiline = true, + order = 1, + width = "full", + } + Options.args["i"..i].args["mine"..i] = { + type = "toggle", + name = "Mine only", + desc = "Only show buffs/debuffs cast by me", + order = 10, + } + Options.args["i"..i].args.textHeader = { + type = "header", + name = "Text Counter", + order = 100, + } + Options.args["i"..i].args["showText"..i] = { + type = "toggle", + name = "Show text counter", + desc = "Show a text counter specifying the time left of the buff/debuff", + order = 110, + } + Options.args["i"..i].args["textSize"..i] = { + type = "range", + name = "Size", + desc = "Text size", + min = 1, + max = 30, + step = 1, + order = 120, + width = "full", + } + Options.args["i"..i].args.coloringHeader = { + type = "header", + name = "Color", + order = 150, + } + Options.args["i"..i].args["debuffColor"..i] = { + type = "toggle", + name = "Color by debuff type", + desc = "Color the text depending on the debuff type, will override any other coloring (poison = green, magic = blue etc)", + order = 165, + } + Options.args["i"..i].args["color"..i] = { + type = "color", + name = "Default color", + desc = "Default color of the indicator", + get = function(item) + local t = Indicators.db.profile[item[#item]] + return t.r, t.g, t.b, t.a + end, + set = function(item, r, g, b, a) + local t = Indicators.db.profile[item[#item]] + t.r, t.g, t.b, t.a = r, g, b, a + Indicators:RefreshConfig() + end, + order = 170, + } + Options.args["i"..i].args.stackHeader = { + type = "header", + name = "Stack Size", + order = 200, + } + Options.args["i"..i].args["stack"..i] = { + type = "toggle", + name = "Show stack size", + desc = "Show stack size for buffs/debuffs that stack", + order = 210, + } + Options.args["i"..i].args.iconHeader = { + type = "header", + name = "Icon", + order = 300, + } + Options.args["i"..i].args["showIcon"..i] = { + type = "toggle", + name = "Show icon", + desc = "Show an icon if the buff/debuff are on the unit", + order = 310, + } + Options.args["i"..i].args["useDefaultIcon"..i] = { + type = "toggle", + name = "Use default icon", + desc = "Show default icon instead of the ability's.", + disabled = function () return not Indicators.db.profile["showIcon"..i] end, + order = 315, + } + Options.args["i"..i].args["iconSize"..i] = { + type = "range", + name = "Icon size", + desc = "Icon size", + min = 1, + max = 30, + step = 1, + order = 320, + width = "full", + } + end +end + +local SlashCommands = { + type = "group", + args = { + enable = { + type = "execute", + name = "enable", + desc = "Enable indicators", + func = function() Indicators.db.profile.enabled = true; Indicators:OnEnable() end, + }, + disable = { + type = "execute", + name = "disable", + desc = "Disable indicators", + func = function() Indicators.db.profile.enabled = false; Indicators:OnDisable() end, + }, + config = { + type = "execute", + name = "config", + desc = "Show config", + func = function() Indicators:ShowConfig() end, + }, + } +} + +function Indicators:ShowConfig() + InterfaceOptionsFrame_OpenToCategory(self.optionsFrames.Profile) + InterfaceOptionsFrame_OpenToCategory(self.optionsFrames.Indicators) +end + +function Indicators:SetupOptions() + -- Set up defaults + CreateDefaults() + self.db = LibStub("AceDB-3.0"):New("IndicatorsDB", Defaults) + + -- Profile handling + local profiles = LibStub("AceDBOptions-3.0"):GetOptionsTable(self.db) + + -- Get the config up + CreateOptions() + local config = LibStub("AceConfig-3.0") + config:RegisterOptionsTable("Raid Frame Indicators", Options) + config:RegisterOptionsTable("Raid Frame Indicators Profiles", profiles) + + -- Register slash commands + config:RegisterOptionsTable("Raid Frame Indicators Options", SlashCommands, {"indicators", "raidframeindicators"}) + + -- Add to Blizz option pane + local dialog = LibStub("AceConfigDialog-3.0") + self.optionsFrames = {} + self.optionsFrames.Indicators = dialog:AddToBlizOptions("Raid Frame Indicators","Raid Frame Indicators") + self.optionsFrames.Profile = dialog:AddToBlizOptions("Raid Frame Indicators Profiles","Profiles", "Raid Frame Indicators") +end \ No newline at end of file diff --git a/RaidFrameNames.lua b/RaidFrameNames.lua new file mode 100644 index 0000000..fb9944a --- /dev/null +++ b/RaidFrameNames.lua @@ -0,0 +1,15 @@ +hooksecurefunc("CompactUnitFrame_UpdateName", + function(frame) + if frame and not frame:IsForbidden() then + local frameName = frame:GetName(); + if frameName and frameName:match("^CompactRaidFrame%d") and frame.unit and frame.name then + local name, _; + name, _ = UnitName(frame.unit) + if name then + frame.name:SetFont(STANDARD_TEXT_FONT, 12, "") + frame.name:SetText(name) + end + end + end + end +); diff --git a/embeds.xml b/embeds.xml new file mode 100644 index 0000000..a4abcae --- /dev/null +++ b/embeds.xml @@ -0,0 +1,18 @@ + + + +