From bf7bbcc53ab8a1db9cef615c4db7ce0c7abe797d Mon Sep 17 00:00:00 2001 From: Aleksi Blinnikka Date: Sun, 14 Jan 2018 22:56:07 +0200 Subject: [PATCH 1/1] Create own frames Attaching to blizzard frames just caused taints in combat if people joined. --- OmaRF/CFrame.lua | 458 +++++++++++++++++++++++++++++++++ OmaRF/LayoutFramesHook.lua | 28 -- OmaRF/NewIndicators.lua | 248 +++++++++++++----- OmaRF/OmaRF.toc | 8 +- OmaRF/UnitFrameSetupHook.lua | 6 - OmaRF/UpdateAuras.lua | 23 -- OmaRF/UpdateNameHook.lua | 19 -- OmaRF/UpdateStatusTextHook.lua | 33 --- 8 files changed, 645 insertions(+), 178 deletions(-) create mode 100644 OmaRF/CFrame.lua delete mode 100644 OmaRF/LayoutFramesHook.lua delete mode 100644 OmaRF/UnitFrameSetupHook.lua delete mode 100644 OmaRF/UpdateAuras.lua delete mode 100644 OmaRF/UpdateNameHook.lua delete mode 100644 OmaRF/UpdateStatusTextHook.lua diff --git a/OmaRF/CFrame.lua b/OmaRF/CFrame.lua new file mode 100644 index 0000000..5049497 --- /dev/null +++ b/OmaRF/CFrame.lua @@ -0,0 +1,458 @@ +-- CFrame.lua +local _; +local unpack, pairs, ipairs = unpack, pairs, ipairs; +local ssub = string.sub; +local min = math.min; +local UnitName, UnitInRange, UnitDebuff = UnitName, UnitInRange, UnitDebuff; +local UnitPower, UnitPowerMax, UnitPowerType = UnitPower, UnitPowerMax, UnitPowerType; +local UnitHealth, UnitHealthMax = UnitHealth, UnitHealthMax; +local UnitInParty, UnitInRaid = UnitInParty, UnitInRaid; +local UnitGetIncomingHeals, UnitGetTotalAbsorbs = UnitGetIncomingHeals, UnitGetTotalAbsorbs; +local UnitGetTotalHealAbsorbs = UnitGetTotalHealAbsorbs; +local IsInGroup, IsInRaid = IsInGroup, IsInRaid; +local UnitIsCharmed = UnitIsCharmed; +local CreateFrame, RegisterStateDriver, RegisterUnitWatch = CreateFrame, RegisterStateDriver, RegisterUnitWatch; +local SPELL_POWER_MANA = SPELL_POWER_MANA; + +local CFrame = CreateFrame("Frame", "OmaCFrame", UIParent); +local party = {}; +local raid = {}; +local positions = {"TOPRIGHT", "BOTTOMLEFT"}; + +-- configurable settings +local width, height = 80, 40; +local anchorX, anchorY = 0, -200; +local indSize = 14; +local bgColor = {0.7, 0.7, 0.7}; +local bgColorDispel = {1, 0.5, 0}; +local healthColor = {0.3, 0.3, 0.3}; +local healthColorDispel = {0.8, 0.4, 0}; +local shieldColor = {0, 0.7, 1}; +local shieldhlColor = {0.5, 0.8, 1}; +local healpredColor = {0.5, 0.6, 0.5}; +local healabsorbColor = {0.1, 0.1, 0.1}; +local powerColors = { + [SPELL_POWER_MANA] = {0, 0.5, 1}, + [SPELL_POWER_RAGE] = {1, 0.2, 0}, + [SPELL_POWER_FOCUS] = {1, 0.5, 0}, + [SPELL_POWER_ENERGY] = {1, 0.8, 0}, + [SPELL_POWER_RUNIC_POWER] = {0.9, 0, 0.1}, +}; +-- watch to not remove mana entry +setmetatable(powerColors, {__index = function(t) return t[SPELL_POWER_MANA] end}); + +local function updateHealth(frame, unit) + local current = UnitHealth(unit); + local _, max = frame.health:GetMinMaxValues(); + local healthLost = max - current; + frame.health:SetValue(current); + if healthLost > 0 then + if healthLost > 1200000000 then -- 1.2B + frame.text:SetFormattedText("-%.1fB", healthLost / 1000000000); + elseif healthLost > 1200000 then -- 1.2M + frame.text:SetFormattedText("-%.1fM", healthLost / 1000000); + elseif healthLost > 1000 then -- 1K + frame.text:SetFormattedText("-%dK", healthLost / 1000); + else + frame.text:SetFormattedText("-%d", healthLost) + end + if not frame.text:IsShown() then frame.text:Show() end + else + if frame.text:IsShown() then frame.text:Hide() end + end +end + +local function updateMaxHealth(frame, unit) + frame.health:SetMinMaxValues(0, UnitHealthMax(unit)); +end + +local function updatePower(frame, unit) + frame.mana:SetValue(UnitPower(unit)); +end + +local function updateMaxPower(frame, unit) + frame.mana:SetMinMaxValues(0, UnitPowerMax(unit)); +end + +local function updatePowerColor(frame, unit) + frame.mana:SetStatusBarColor(unpack(powerColors[UnitPowerType(unit)])); +end + +local function updateName(frame, unit) + frame.name:SetText(ssub(UnitName(unit), 1, 6)); +end + +local function updateHealPred(frame, unit) + local incoming = UnitGetIncomingHeals(unit) or 0; + if incoming > 0 then + local _, max = frame.health:GetMinMaxValues(); + local space = width - frame.health.bar:GetWidth() + 1; + local pred = (incoming / max) * width; + frame.healpred:SetWidth(min(space, pred)); + if not frame.healpred:IsShown() then frame.healpred:Show() end + else + if frame.healpred:IsShown() then frame.healpred:Hide() end + end +end + +local function updateShield(frame, unit) + local shield = UnitGetTotalAbsorbs(unit) or 0; + if shield > 0 then + local _, max = frame.health:GetMinMaxValues(); + local space = width - frame.health.bar:GetWidth(); + shield = (shield / max) * width; + frame.shield:SetWidth(min(space, shield)); + if not frame.shield:IsShown() then + frame.shield:Show(); + frame.shieldhl:Show(); + end + else + if frame.shield:IsShown() then + frame.shield:Hide(); + frame.shieldhl:Hide(); + end + end +end + +local function updateHealAbsorb(frame, unit) + local absorb = UnitGetTotalHealAbsorbs(unit) or 0; + if absorb > 0 then + local _, max = frame.health:GetMinMaxValues(); + local space = frame.health.bar:GetWidth(); + absorb = (absorb / max) * width; + frame.healabsorb:SetWidth(min(space, absorb)); + if not frame.healabsorb:IsShown() then frame.healabsorb:Show() end + else + if frame.healabsorb:IsShown() then frame.healabsorb:Hide() end + end +end + +local function updateAuras(frame, unit) + if UnitDebuff(unit, 1, "RAID") ~= nil then + -- something dispellable + if frame.health.color ~= healthColorDispel then + -- TODO change to a texture layered on top tinting whole bar + frame.health:SetStatusBarColor(unpack(healthColorDispel)); + frame.background:SetColorTexture(unpack(bgColorDispel)); + frame.health.color = healthColorDispel; + end + elseif UnitIsCharmed(unit) then + -- TODO purple + else + if frame.health.color ~= healthColor then + frame.health:SetStatusBarColor(unpack(healthColor)); + frame.background:SetColorTexture(unpack(bgColor)); + frame.health.color = healthColor; + end + end +end + +local function unitEvent(self, event, ...) + local arg1, arg2, arg3, arg4 = ...; + if event == "UNIT_HEALTH" or event == "UNIT_HEALTH_FREQUENT" then + updateHealth(self, arg1); + elseif event == "UNIT_POWER" then + updatePower(self, arg1); + elseif event == "UNIT_AURA" then + updateAuras(self, arg1); + elseif event == "UNIT_ABSORB_AMOUNT_CHANGED" then + updateShield(self, arg1); + elseif event == "UNIT_HEAL_PREDICTION" then + updateHealPred(self, arg1); + elseif event == "UNIT_HEAL_ABSORB_AMOUNT_CHANGED" then + updateHealAbsorb(self, arg1); + elseif event == "UNIT_MAXHEALTH" then + updateMaxHealth(self, arg1); + elseif event == "UNIT_MAXPOWER" then + updateMaxPower(self, arg1); + elseif event == "UNIT_DISPLAYPOWER" then + updatePowerColor(self, arg1); + elseif event == "UNIT_NAME_UPDATE" then + updateName(self, arg1); + elseif event == "UPDATE_ALL_BARS" then + updateHealth(self, arg1); + updatePower(self, arg1); + updateAuras(self, arg1); + updateShield(self, arg1); + updateHealPred(self, arg1); + updateMaxHealth(self, arg1); + updateMaxPower(self, arg1); + updatePowerColor(self, arg1); + updateName(self, arg1); + end +end + +local function unitUpdate(self, elapsed) + -- there's no in/out of range event, have to check each frame + -- indicator update here? + local inRange, checked = UnitInRange(self.unit); + if checked and not inRange then + self:SetAlpha(0.55); + else + self:SetAlpha(1); + end +end + +local function registerEvents(frame, unit) + frame:RegisterUnitEvent("UNIT_HEALTH", unit); + frame:RegisterUnitEvent("UNIT_HEALTH_FREQUENT", unit); + frame:RegisterUnitEvent("UNIT_MAXHEALTH", unit); + frame:RegisterUnitEvent("UNIT_POWER", unit); + frame:RegisterUnitEvent("UNIT_MAXPOWER", unit); + frame:RegisterUnitEvent("UNIT_DISPLAYPOWER", unit); + frame:RegisterUnitEvent("UNIT_NAME_UPDATE", unit); + frame:RegisterUnitEvent("UNIT_AURA", unit); + frame:RegisterUnitEvent("UNIT_HEAL_PREDICTION", unit); + frame:RegisterUnitEvent("UNIT_ABSORB_AMOUNT_CHANGED", unit); + frame:RegisterUnitEvent("UNIT_HEAL_ABSORB_AMOUNT_CHANGED", unit); +end + +local function vis(frame, vis) + if vis then + frame:Show(); + frame:SetScript("OnUpdate", unitUpdate); + frame:UnregisterAllEvents(); + registerEvents(frame, frame.unit); + unitEvent(frame, "UPDATE_ALL_BARS", frame.unit); + else + frame:Hide(); + frame:SetScript("OnUpdate", nil); + frame:UnregisterAllEvents(); + end; +end + +local function updateGroup() + if IsInGroup() then + if IsInRaid() then + -- show raid + for _, val in ipairs(raid) do + if UnitInRaid(val.frame.unit) then + if not val.frame:IsShown() then vis(val.frame, true) end + elseif val.frame:IsShown() then + vis(val.frame, false); + end + end + -- hide player + party (use pairs, not ipairs) + for _, val in pairs(party) do + if val.frame:IsShown() then vis(val.frame, false) end + end + else + -- show player + party + for _, val in pairs(party) do + if UnitInParty(val.frame.unit) then + if not val.frame:IsShown() then vis(val.frame, true) end + elseif val.frame:IsShown() then + vis(val.frame, false); + end + end + -- hide raid + for _, val in ipairs(raid) do + if val.frame:IsShown() then vis(val.frame, false) end + end + end + else + -- show player + if not party[0].frame:IsShown() then vis(party[0].frame, true) end + -- hide all other frames + for _, val in ipairs(party) do + if val.frame:IsShown() then vis(val.frame, false) end + end + for _, val in ipairs(raid) do + if val.frame:IsShown() then vis(val.frame, false) end + end + end +end + +local function setupIndicators(frame) + frame.inds = CreateFrame("Frame", nil, frame); + frame.inds:SetAllPoints(); + for _, pos in pairs(positions) do + frame.inds[pos] = frame.inds:CreateTexture(nil, "OVERLAY"); + frame.inds[pos]:SetPoint(pos, frame.inds, pos); + frame.inds[pos]:SetWidth(indSize); + frame.inds[pos]:SetHeight(indSize); + frame.inds[pos]:SetTexture("Interface\\AddOns\\OmaRF\\images\\rhomb"); + end +end + +local function setupFrame(frame, secure, unit) + -- create visuals + secure:SetWidth(width+2); + frame:SetWidth(width+2); + frame.base = frame:CreateTexture(nil, "BACKGROUND"); + frame.base:SetAllPoints(); + frame.base:SetColorTexture(0, 0, 0); + frame.background = frame:CreateTexture(nil, "BACKGROUND", nil, 1); + frame.background:SetPoint("TOPLEFT", frame, "TOPLEFT", 1, -1); + frame.background:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -1, 1); + frame.background:SetColorTexture(unpack(bgColor)); + frame.health = CreateFrame("StatusBar", nil, frame); + frame.health:SetPoint("TOPLEFT", frame.background, "TOPLEFT"); + frame.health:SetPoint("BOTTOMRIGHT", frame.background, "BOTTOMRIGHT", 0, 2); + frame.health.bar = frame.health:CreateTexture(nil, "ARTWORK"); + frame.health.bar:SetTexture("Interface\\RaidFrame\\Raid-Bar-Hp-Fill"); + frame.health:SetStatusBarTexture(frame.health.bar); + frame.health:SetStatusBarColor(unpack(healthColor)); + frame.health.color = healthColor; + frame.shield = frame.health:CreateTexture(nil, "ARTWORK"); + frame.shield:SetPoint("TOPLEFT", frame.health.bar, "TOPRIGHT"); + frame.shield:SetPoint("BOTTOMLEFT", frame.health.bar, "BOTTOMRIGHT"); + frame.shield:SetColorTexture(unpack(shieldColor)); + frame.shield:Hide(); + frame.shieldhl = frame:CreateTexture(nil, "ARTWORK"); + frame.shieldhl:SetPoint("TOPLEFT", frame.shield, "TOPRIGHT", -1, 0); + frame.shieldhl:SetPoint("BOTTOMRIGHT", frame.shield, "BOTTOMRIGHT", 1, 0); + frame.shieldhl:SetColorTexture(unpack(shieldhlColor)); + frame.shieldhl:Hide(); + frame.healpred = frame.health:CreateTexture(nil, "ARTWORK", nil, 1); + frame.healpred:SetPoint("TOPLEFT", frame.health.bar, "TOPRIGHT"); + frame.healpred:SetPoint("BOTTOMLEFT", frame.health.bar, "BOTTOMRIGHT"); + frame.healpred:SetColorTexture(unpack(healpredColor)); + frame.healpred:Hide(); + frame.healabsorb = frame.health:CreateTexture(nil, "ARTWORK", nil, 1); + frame.healabsorb:SetPoint("TOPRIGHT", frame.health.bar, "TOPRIGHT"); + frame.healabsorb:SetPoint("BOTTOMRIGHT", frame.health.bar, "BOTTOMRIGHT"); + frame.healabsorb:SetColorTexture(unpack(healabsorbColor)); + frame.healabsorb:Hide(); + frame.mana = CreateFrame("StatusBar", nil, frame); + frame.mana:SetPoint("TOPLEFT", frame.background, "BOTTOMLEFT", 0, 2); + frame.mana:SetPoint("BOTTOMRIGHT", frame.background, "BOTTOMRIGHT"); + frame.mana.bar = frame.mana:CreateTexture(nil, "ARTWORK"); + frame.mana.bar:SetColorTexture(1, 1, 1); + frame.mana:SetStatusBarTexture(frame.mana.bar); + frame.name = frame.health:CreateFontString(nil, "OVERLAY", "GameFontHighlight"); + frame.name:SetPoint("TOPLEFT", frame.background, "TOPLEFT"); + local name = UnitName(unit); + frame.name:SetText(name and ssub(name, 1, 6) or ""); + frame.text = frame.health:CreateFontString(nil, "OVERLAY", "GameFontHighlight"); + frame.text:SetFont(STANDARD_TEXT_FONT, 13); + frame.text:SetPoint("CENTER", frame.background, "CENTER"); + frame.text:Hide(); + setupIndicators(frame); + -- set attributes + secure:RegisterForClicks("AnyDown"); + secure:SetAttribute("type1", "spell"); -- left click + secure:SetAttribute("type2", "spell"); -- right click + secure:SetAttribute("shift-type1", "spell"); -- shift left click + secure:SetAttribute("shift-type2", "spell"); -- shift right click + secure:SetAttribute("ctrl-type1", "spell"); -- ctrl left click + secure:SetAttribute("alt-type2", "spell"); -- alt right click + secure:SetAttribute("alt-shift-type1", "spell"); -- alt+shift left click + secure:SetAttribute("alt-shift-type2", "spell"); -- alt+shift right click + secure:SetAttribute("spell1", "Holy Light"); + secure:SetAttribute("spell2", "Bestow Faith"); + secure:SetAttribute("shift-spell1", "Flash of Light"); + secure:SetAttribute("shift-spell2", "Light of the Martyr"); + secure:SetAttribute("ctrl-spell1", "Cleanse"); + secure:SetAttribute("alt-spell2", "Lay on Hands"); + secure:SetAttribute("alt-shift-spell1", "Beacon of Light"); + secure:SetAttribute("alt-shift-spell2", "Beacon of Faith"); + -- rest give target and menu + secure:SetAttribute("*type1", "target"); + secure:SetAttribute("*type2", "togglemenu"); +end + +local function initializeParty() + local secure = CreateFrame("Button", "OmaPartySecure0", CFrame, "SecureUnitButtonTemplate"); + local frame = CreateFrame("Frame", "OmaParty0", CFrame); + local unit = "player"; + secure:SetAttribute("unit", unit); + secure:SetPoint("TOPLEFT", CFrame, "TOPLEFT"); + secure:SetHeight(height+2); + frame.unit = unit; + frame:SetPoint("TOPLEFT", CFrame, "TOPLEFT"); + frame:SetHeight(height+2); + frame:SetScript("OnEvent", unitEvent); + frame:Hide(); + setupFrame(frame, secure, unit); + RegisterStateDriver(secure, "visibility", "[@player,group:raid] hide; show"); + party[0] = {secure=secure, frame=frame}; + for i = 1,4 do + local secure = CreateFrame("Button", "OmaPartySecure"..i, CFrame, "SecureUnitButtonTemplate"); + local frame = CreateFrame("Frame", "OmaParty"..i, CFrame); + local unit = "party"..i; + secure:SetAttribute("unit", unit); + secure:SetPoint("TOPLEFT", party[i-1].secure, "TOPRIGHT"); + secure:SetPoint("BOTTOMLEFT", party[i-1].secure, "BOTTOMRIGHT"); + frame.unit = unit; + frame:SetPoint("TOPLEFT", party[i-1].frame, "TOPRIGHT"); + frame:SetPoint("BOTTOMLEFT", party[i-1].frame, "BOTTOMRIGHT"); + frame:SetScript("OnEvent", unitEvent); + frame:Hide(); + setupFrame(frame, secure, unit); + RegisterUnitWatch(secure); + party[i] = {secure=secure, frame=frame}; + end +end + +local function initializeRaid() + local secure = CreateFrame("Button", "OmaRaidSecure1", CFrame, "SecureUnitButtonTemplate"); + local frame = CreateFrame("Frame", "OmaRaid1", CFrame); + local unit = "raid1"; + secure:SetAttribute("unit", unit); + secure:SetPoint("TOPLEFT", CFrame, "TOPLEFT"); + secure:SetHeight(height+2); + frame.unit = unit; + frame:SetPoint("TOPLEFT", CFrame, "TOPLEFT"); + frame:SetHeight(height+2); + frame:SetScript("OnEvent", unitEvent); + frame:Hide(); + setupFrame(frame, secure, unit); + RegisterUnitWatch(secure); + raid[1] = {secure=secure, frame=frame}; + for y = 1,7 do + local i = y*5+1; + local secure = CreateFrame("Button", "OmaRaidSecure"..i, CFrame, "SecureUnitButtonTemplate"); + local frame = CreateFrame("Frame", "OmaRaid"..i, CFrame); + local unit = "raid"..i; + secure:SetAttribute("unit", unit); + secure:SetPoint("TOPLEFT", raid[i-5].secure, "BOTTOMLEFT"); + secure:SetHeight(height+2); + frame.unit = unit; + frame:SetPoint("TOPLEFT", raid[i-5].frame, "BOTTOMLEFT"); + frame:SetHeight(height+2); + frame:SetScript("OnEvent", unitEvent); + frame:Hide(); + setupFrame(frame, secure, unit); + RegisterUnitWatch(secure); + raid[i] = {secure=secure, frame=frame}; + end + for y = 0,7 do + for x = 1,4 do + local i = y*5+x+1; + local secure = CreateFrame("Button", "OmaRaidSecure"..i, CFrame, "SecureUnitButtonTemplate"); + local frame = CreateFrame("Frame", "OmaRaid"..i, CFrame); + local unit = "raid"..i; + secure:SetAttribute("unit", unit); + secure:SetPoint("TOPLEFT", raid[i-1].secure, "TOPRIGHT"); + secure:SetPoint("BOTTOMLEFT", raid[i-1].secure, "BOTTOMRIGHT"); + frame.unit = unit; + frame:SetPoint("TOPLEFT", raid[i-1].frame, "TOPRIGHT"); + frame:SetPoint("BOTTOMLEFT", raid[i-1].frame, "BOTTOMRIGHT"); + frame:SetScript("OnEvent", unitEvent); + frame:Hide(); + setupFrame(frame, secure, unit); + RegisterUnitWatch(secure); + raid[i] = {secure=secure, frame=frame}; + end + end +end + +local function initialize() + CFrame:SetPoint("CENTER", nil, "CENTER", anchorX, anchorY); + CFrame:SetHeight((height+2)*8); + CFrame:SetWidth((width+2)*5+1); -- extra pixel for shield overflow + initializeParty(); + initializeRaid(); + updateGroup(); +end + +CFrame:RegisterEvent("PLAYER_LOGIN"); +CFrame:RegisterEvent("GROUP_ROSTER_UPDATE"); +CFrame:SetScript("OnEvent", function(self, event, ...) + if event == "GROUP_ROSTER_UPDATE" then + updateGroup(); + elseif event == "PLAYER_LOGIN" then + initialize(); + end +end); diff --git a/OmaRF/LayoutFramesHook.lua b/OmaRF/LayoutFramesHook.lua deleted file mode 100644 index 168891c..0000000 --- a/OmaRF/LayoutFramesHook.lua +++ /dev/null @@ -1,28 +0,0 @@ -local normalBarColor = OmaRF.normalBarColor; -local normalBackColor = OmaRF.normalBackColor; -local UnitGroupRolesAssigned = UnitGroupRolesAssigned; -local CompactUnitFrame_UpdateHealthColor = CompactUnitFrame_UpdateHealthColor; -local CompactRaidFrameContainer_ApplyToFrames = CompactRaidFrameContainer_ApplyToFrames; -local unpack = unpack; - --- TODO remove 1px border -local function layoutHook(frame) - if InCombatLockdown() then - OmaRF.ooc_queue["layoutHook"] = {func = layoutHook, args = {frame}}; - return; - end - CompactRaidFrameContainer_ApplyToFrames(frame, "normal", function(frame) - -- Health bar color -- - -- used in CompactUnitFrame_UpdateHealthColor, might not be set prior - frame.optionTable.healthBarColorOverride = normalBarColor; - frame.background:SetColorTexture(unpack(normalBackColor)); - -- Power bar display -- - local role = UnitGroupRolesAssigned(frame.unit); - local options = DefaultCompactUnitFrameSetupOptions; - if options.displayPowerBar and role ~= "HEALER" then - frame.healthBar:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -1, 1); - frame.powerBar:Hide(); - end - end); -end -hooksecurefunc("CompactRaidFrameContainer_LayoutFrames", layoutHook); diff --git a/OmaRF/NewIndicators.lua b/OmaRF/NewIndicators.lua index 01c1ae9..bcc4260 100644 --- a/OmaRF/NewIndicators.lua +++ b/OmaRF/NewIndicators.lua @@ -2,7 +2,8 @@ local unpack, ipairs, pairs, ceil, floor = unpack, ipairs, pairs, ceil, floor; local UnitIsConnected, UnitIsDeadOrGhost = UnitIsConnected, UnitIsDeadOrGhost; local UnitAura, UnitIsPlayer, GetTime = UnitAura, UnitIsPlayer, GetTime; -local C_TimerAfter = C_Timer.After; +local UnitName, C_TimerAfter = UnitName, C_Timer.After; +local IsInGroup, IsInRaid, GetNumGroupMembers = IsInGroup, IsInRaid, GetNumGroupMembers; local format = string.format; local positions = OmaRF.positions; @@ -15,6 +16,8 @@ local frames = {}; local watchedAuras = {}; local majorAuras = {}; local majorMax; +local partyState = "solo"; +local partyMembers = {"player", "party1", "party2", "party3", "party4"}; local function remaining(expires, current) if expires == 0 then return "" end @@ -57,57 +60,56 @@ local function showMajorIndicator(ind, icon, count, expires, current) if not ind.expireText:IsShown() then ind.expireText:Show() end end --- update current auras -hooksecurefunc("CompactUnitFrame_UpdateAuras", function(unitFrame) - local frameName = unitFrame:GetName(); - if frames[frameName] then - local frame = frames[frameName]; - for _, ind in pairs(frame.inds) do ind.expires = nil end - for _, ind in ipairs(frame.majorInds) do ind.expires = nil end +-- update current auras TODO add bar coloring back with extra options +local function updateAuras(frame, unit) + for _, ind in pairs(frame.inds) do ind.expires = nil end + for _, ind in ipairs(frame.majorInds) do ind.expires = nil end - local name, icon, count, expires, caster, id; - local unit = unitFrame.displayedUnit; - local majorPos = 1; - local current = GetTime(); - for _, filter in ipairs(auraFilters) do - local i = 1; - while true do - name, _, icon, count, _, _, expires, caster, _, _, id = UnitAura(unit, i, filter); - if not id then break end - local pos = watchedAuras[id] or watchedAuras[name]; - if pos then - showIndicator( - frame.inds[pos], icon, caster, expires, current, - OmaRF.db.profile.indicators[pos] - ); - end - if (majorAuras[id] or majorAuras[name]) and majorPos <= majorMax then - showMajorIndicator(frame.majorInds[majorPos], icon, count, expires, current); - majorPos = majorPos + 1; - end - i = i + 1; + local name, icon, count, expires, caster, id; + local majorPos = 1; + local current = GetTime(); + for _, filter in ipairs(auraFilters) do + local i = 1; + while true do + name, _, icon, count, _, _, expires, caster, _, _, id = UnitAura(unit, i, filter); + if not id then break end + local pos = watchedAuras[id] or watchedAuras[name]; + if pos then + showIndicator( + frame.inds[pos], icon, caster, expires, current, + OmaRF.db.profile.indicators[pos] + ); end + if (majorAuras[id] or majorAuras[name]) and majorPos <= majorMax then + showMajorIndicator(frame.majorInds[majorPos], icon, count, expires, current); + majorPos = majorPos + 1; + end + i = i + 1; end end -end); +end -- Check the indicators on a frame and update the times on them -local function updateIndicators(frame, name) - local unitFrame = _G[name]; -- has to always reference global - if unitFrame == nil then - return; - elseif not unitFrame:IsVisible() then +local function updateIndicators(frame, i) + local unit = "player"; + if partyState == "solo" then if frame:IsShown() then frame:Hide() end return; + elseif partyState == "raid" then + unit = partyState..i; + elseif i ~= 1 then + -- party frames have player separate + unit = partyState..(i-1); end - local unit = unitFrame.unit; - local displayedUnit = unitFrame.displayedUnit; - if not unit or not UnitIsConnected(unit) or UnitIsDeadOrGhost(displayedUnit) then + if not UnitExists(unit) then + return; + elseif not UnitIsConnected(unit) or UnitIsDeadOrGhost(unit) then if frame:IsShown() then frame:Hide() end return; + elseif not frame:IsShown() then + frame:Show(); end - if not frame:IsShown() then frame:Show() end local current = GetTime(); for pos, ind in pairs(frame.inds) do @@ -185,7 +187,9 @@ end -- Update all indicators local function updateAllIndicators() - for name, frame in pairs(frames) do updateIndicators(frame, name) end + for i, frame in ipairs(frames) do + updateIndicators(frame, i); + end if OmaRF.running then C_TimerAfter(0.15, updateAllIndicators) end end @@ -207,54 +211,168 @@ function OmaRF:RefreshConfig() end if next(watchedAuras) ~= nil or next(majorAuras) ~= nil then - frameBase:Show(); + if not frameBase:IsShown() then frameBase:Show() end self.running = true; C_TimerAfter(0.15, updateAllIndicators); end end end +local function updateStatusText(self, unit) + if not UnitIsConnected(unit) then + self.statusText:SetText("DC"); + elseif UnitIsDeadOrGhost(unit) then + self.statusText:SetText("rip"); + else + local healthLost = UnitHealthMax(unit) - UnitHealth(unit); + if healthLost <= 0 then + self.statusText:SetText(""); + return; + end + + local prettyHealth; + if healthLost > 1200000000 then -- 1.2B + prettyHealth = format("-%.1fB", healthLost / 1000000000); + elseif healthLost > 1200000 then -- 1.2M + prettyHealth = format("-%.1fM", healthLost / 1000000); + elseif healthLost > 1000 then -- 1K + prettyHealth = format("-%dK", healthLost / 1000); + else + prettyHealth = format("-%d", healthLost) + end + + self.statusText:SetText(prettyHealth); + end +end + +local function frameEvent(self, event, ...) + local arg1, arg2, arg3, arg4 = ...; + if event == "UNIT_HEALTH" or event == "UNIT_HEALTH_FREQUENT" then + updateStatusText(self, arg1); + elseif event == "UNIT_AURA" then + updateAuras(self, arg1); + end +end + +--[[ TODO powerBar display and bar coloring + if options.displayPowerBar and role ~= "HEALER" then + frame.healthBar:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -1, 1); + frame.powerBar:Hide(); + end +]] + +--local update_ooc = false; local function updateFrames() - for name, frame in pairs(frames) do + if not IsInGroup() or GetNumGroupMembers() == 1 then + -- solo + partyState = "solo"; + local frame = frames[1]; + frame:UnregisterAllEvents(); + frame:RegisterUnitEvent("UNIT_AURA", "player"); + frame:RegisterUnitEvent("UNIT_HEALTH", "player"); + frame:RegisterUnitEvent("UNIT_HEALTH_FREQUENT", "player"); + else + if IsInRaid() then + partyState = "raid"; + for i, frame in ipairs(frames) do + local name = partyState..i; + if not UnitExists(name) then break end + frame:UnregisterAllEvents(); + frame:RegisterUnitEvent("UNIT_AURA", name); + frame:RegisterUnitEvent("UNIT_HEALTH", name); + frame:RegisterUnitEvent("UNIT_HEALTH_FREQUENT", name); + end + else + partyState = "party"; + for i, name in ipairs(partyMembers) do + local frame = frames[i]; + if not UnitExists(name) then break end + frame:UnregisterAllEvents(); + frame:RegisterUnitEvent("UNIT_AURA", name); + frame:RegisterUnitEvent("UNIT_HEALTH", name); + frame:RegisterUnitEvent("UNIT_HEALTH_FREQUENT", name); + end + end + end + --[[for name, frame in pairs(frames) do local unitFrame = _G[name]; if unitFrame then - if not frame.pointsSet then - frame:SetAllPoints(unitFrame); - frame.pointsSet = true; + if not frame.unitFrameSetup then + if InCombatLockdown() then + update_ooc = true; + else + unitFrame.name:SetFont(STANDARD_TEXT_FONT, 12, ""); + unitFrame.optionTable.displayBuffs = false; + unitFrame.optionTable.displayDebuffs = false; + unitFrame.optionTable.displayDispelDebuffs = false; + frame.unitFrameSetup = true; + end + end + local unit = unitFrame.unit; + if unit then + if InCombatLockdown() then + update_ooc = true; + else + local name = UnitName(unit); + unitFrame.name:SetText(name); + end end end - end + end]] +end + +local function createStatusText(frame) + frame.statusText = frame:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall"); + frame.statusText:SetPoint("CENTER", frame, "CENTER"); + frame.statusText:SetFont(STANDARD_TEXT_FONT, 14, ""); end local function initialize(frame) - local name = "CompactRaidFrame1"; - frames[name] = CreateFrame("Frame", "OmaRF1", frameBase); - frames[name]:SetAllPoints(name); - frames[name]:Hide(); - createIndicators(frames[name]); + frames[1] = CreateFrame("Frame", "OmaRF1", frameBase); + frames[1]:SetAllPoints("CompactRaidFrame1"); -- only connection to blizzard frames + frames[1]:SetScript("OnEvent", frameEvent); + frames[1]:Hide(); + createStatusText(frames[1]); + createIndicators(frames[1]); local i = 2; + -- TODO size could change + local width, height = frames[1]:GetWidth(), frames[1]:GetHeight(); for y = 2,5 do - local name = "CompactRaidFrame"..i; - frames[name] = CreateFrame("Frame", "OmaRF"..i, frameBase); - frames[name]:Hide(); - createIndicators(frames[name]); + frames[i] = CreateFrame("Frame", "OmaRF"..i, frameBase); + frames[i]:SetPoint("TOPLEFT", frames[i-1], "BOTTOMLEFT"); + frames[i]:SetWidth(width); + frames[i]:SetHeight(height); + frames[i]:SetScript("OnEvent", frameEvent); + frames[i]:Hide(); + createStatusText(frames[i]); + createIndicators(frames[i]); i = i + 1; end - for x = 1,7 do + for x = 0,6 do for y = 1,5 do - local name = "CompactRaidFrame"..i; - frames[name] = CreateFrame("Frame", "OmaRF"..i, frameBase); - frames[name]:Hide(); - createIndicators(frames[name]); + frames[i] = CreateFrame("Frame", "OmaRF"..i, frameBase); + frames[i]:SetPoint("TOPLEFT", frames[x*5+y], "TOPRIGHT"); + frames[i]:SetWidth(width); + frames[i]:SetHeight(height); + frames[i]:SetScript("OnEvent", frameEvent); + frames[i]:Hide(); + createStatusText(frames[i]); + createIndicators(frames[i]); i = i + 1; end end + C_TimerAfter(0.01, updateFrames); end -local function onEvent(self, event, ...) +local function baseEvent(self, event, ...) if event == "GROUP_ROSTER_UPDATE" then -- not sure if fired before LayoutFrames, wait a bit C_TimerAfter(0.01, updateFrames); + --[[elseif event == "PLAYER_REGEN_ENABLED" then + if update_ooc then + updateFrames(); + update_ooc = false; + end]] elseif event == "PLAYER_LOGIN" then initialize(); end @@ -263,6 +381,12 @@ end frameBase = CreateFrame("Frame", nil, UIParent); frameBase:SetFrameStrata("HIGH"); frameBase:RegisterEvent("PLAYER_LOGIN"); +frameBase:RegisterEvent("PLAYER_REGEN_ENABLED"); frameBase:RegisterEvent("GROUP_ROSTER_UPDATE"); -frameBase:SetScript("OnEvent", onEvent); +frameBase:SetScript("OnEvent", baseEvent); OmaRF.frameBase = frameBase; + +-- hide buffs, debuffs from Blizzard frames +--DefaultCompactUnitFrameOptions.displayBuffs = false; +--DefaultCompactUnitFrameOptions.displayDebuffs = false; +--DefaultCompactUnitFrameOptions.displayDispelDebuffs = false; diff --git a/OmaRF/OmaRF.toc b/OmaRF/OmaRF.toc index 9e4a6aa..15d4244 100644 --- a/OmaRF/OmaRF.toc +++ b/OmaRF/OmaRF.toc @@ -7,11 +7,5 @@ embeds.xml -Core.lua -NewIndicators.lua -UnitFrameSetupHook.lua -UpdateNameHook.lua -UpdateStatusTextHook.lua -UpdateAuras.lua -LayoutFramesHook.lua +CFrame.lua PlayerFrameHooks.lua diff --git a/OmaRF/UnitFrameSetupHook.lua b/OmaRF/UnitFrameSetupHook.lua deleted file mode 100644 index 9a29992..0000000 --- a/OmaRF/UnitFrameSetupHook.lua +++ /dev/null @@ -1,6 +0,0 @@ -hooksecurefunc("DefaultCompactUnitFrameSetup", function(frame) - -- used in CompactUnitFrame_UpdateAuras (Buffs, Debuffs, DispellableDebuffs) - frame.optionTable.displayBuffs = false; - frame.optionTable.displayDebuffs = false; - frame.optionTable.displayDispelDebuffs = false; -end); diff --git a/OmaRF/UpdateAuras.lua b/OmaRF/UpdateAuras.lua deleted file mode 100644 index e6d82f0..0000000 --- a/OmaRF/UpdateAuras.lua +++ /dev/null @@ -1,23 +0,0 @@ -local normalBarColor = OmaRF.normalBarColor; -local dispelBarColor = OmaRF.dispelBarColor; -local normalBackColor = OmaRF.normalBackColor; -local dispelBackColor = OmaRF.dispelBackColor; - -local UnitDebuff = UnitDebuff; -local CompactUnitFrame_UpdateHealthColor = CompactUnitFrame_UpdateHealthColor; -local unpack = unpack; - -hooksecurefunc("CompactUnitFrame_UpdateAuras", function(frame) - -- allowClassColorsForNPCs only in regular raid frames - if frame.optionTable.allowClassColorsForNPCs ~= nil then - -- try to find dispellable debuff - if UnitDebuff(frame.displayedUnit, 1, "RAID") ~= nil then - frame.optionTable.healthBarColorOverride = dispelBarColor; - frame.background:SetColorTexture(unpack(dispelBackColor)); - else - frame.optionTable.healthBarColorOverride = normalBarColor; - frame.background:SetColorTexture(unpack(normalBackColor)); - end - CompactUnitFrame_UpdateHealthColor(frame); - end -end); diff --git a/OmaRF/UpdateNameHook.lua b/OmaRF/UpdateNameHook.lua deleted file mode 100644 index 8165c7d..0000000 --- a/OmaRF/UpdateNameHook.lua +++ /dev/null @@ -1,19 +0,0 @@ -local UnitName = UnitName; - -local function nameHook(frame) - if InCombatLockdown() then - table.insert(OmaRF.ooc_queue, {func = nameHook, args = {frame}}); - return; - end - -- allowClassColorsForNPCs only in regular raid frames, - -- match only to them - if frame.optionTable.allowClassColorsForNPCs ~= nil then - local name, _; - name, _ = UnitName(frame.unit); - if name then - frame.name:SetFont(STANDARD_TEXT_FONT, 12, ""); - frame.name:SetText(name); - end - end -end -hooksecurefunc("CompactUnitFrame_UpdateName", nameHook); diff --git a/OmaRF/UpdateStatusTextHook.lua b/OmaRF/UpdateStatusTextHook.lua deleted file mode 100644 index 76a677e..0000000 --- a/OmaRF/UpdateStatusTextHook.lua +++ /dev/null @@ -1,33 +0,0 @@ -local UnitIsConnected = UnitIsConnected; -local UnitIsDeadOrGhost = UnitIsDeadOrGhost; -local UnitHealthMax = UnitHealthMax; -local UnitHealth = UnitHealth; -local format = string.format - -hooksecurefunc("CompactUnitFrame_UpdateStatusText", function(frame) - -- allowClassColorsForNPCs only in regular raid frames, - -- match only to them - if frame.optionTable.allowClassColorsForNPCs ~= nil 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); - if healthLost <= 0 then return end - - local prettyHealth; - if healthLost > 1200000000 then -- 1.2B - prettyHealth = format("-%.1fB", healthLost / 1000000000); - elseif healthLost > 1200000 then -- 1.2M - prettyHealth = format("-%.1fM", healthLost / 1000000); - elseif healthLost > 1000 then -- 1K - prettyHealth = format("-%dK", healthLost / 1000); - else - prettyHealth = format("-%d", healthLost) - end - - frame.statusText:SetText(prettyHealth); - end - end -end); -- 2.39.5