From: Aleksi Blinnikka Date: Fri, 26 Jan 2018 21:44:24 +0000 (+0200) Subject: Add basic player and target frames in separate addon X-Git-Url: https://www.aleksib.fi/git/wowui.git/commitdiff_plain/60bc5ec4ced3b57fd841af7f693728049a0d09a0?hp=555cd132c0888aa8f31370eddbe214d6d830195b Add basic player and target frames in separate addon --- diff --git a/OmaUF/Events.lua b/OmaUF/Events.lua new file mode 100644 index 0000000..6e4fa69 --- /dev/null +++ b/OmaUF/Events.lua @@ -0,0 +1,434 @@ +-- Events.lua +local _; +local unpack = unpack; +local ssub = string.sub; +local min = math.min; +local ceil = math.ceil; +local UnitName, UnitClass, UnitExists = UnitName, UnitClass, UnitExists; +local UnitDebuff, UnitIsCharmed = UnitDebuff, UnitIsCharmed; +local UnitPower, UnitPowerMax, UnitPowerType = UnitPower, UnitPowerMax, UnitPowerType; +local UnitHealth, UnitHealthMax = UnitHealth, UnitHealthMax; +local UnitGetIncomingHeals, UnitGetTotalAbsorbs = UnitGetIncomingHeals, UnitGetTotalAbsorbs; +local UnitThreatSituation, GetThreatStatusColor = UnitThreatSituation, GetThreatStatusColor; +local UnitIsDeadOrGhost, UnitIsConnected = UnitIsDeadOrGhost, UnitIsConnected; +local UnitGetTotalHealAbsorbs = UnitGetTotalHealAbsorbs; +local UnitHasVehicleUI, UnitTargetsVehicleInRaidUI = UnitHasVehicleUI, UnitTargetsVehicleInRaidUI; +local UnitGroupRolesAssigned = UnitGroupRolesAssigned; +local UnitLevel, UnitClassification = UnitLevel, UnitClassification; +local RAID_CLASS_COLORS = RAID_CLASS_COLORS; + +local Settings = OmaUFSettings; +local baseColor = Settings.BaseColor; +local overlayColorDispel = Settings.OverlayColorDispel; +local overlayColorCharm = Settings.OverlayColorCharm; +local overlayColorAlert = Settings.OverlayColorAlert; +local powerColors = Settings.PowerColors; +local width = 10; + +local M = {}; +OmaUFEvents = M; +function M.RegisterEvents(frame) + -- events are taken from FrameXML/CompactUnitFrame.lua + -- TODO raid marker support, + -- player flags support (/afk, /dnd) + local displayed = frame.unit ~= frame.displayed and frame.displayed or nil; + frame:RegisterUnitEvent("UNIT_HEALTH", frame.unit, displayed); + frame:RegisterUnitEvent("UNIT_HEALTH_FREQUENT", frame.unit, displayed); + frame:RegisterUnitEvent("UNIT_MAXHEALTH", frame.unit, displayed); + frame:RegisterUnitEvent("UNIT_POWER", frame.unit, displayed); + frame:RegisterUnitEvent("UNIT_MAXPOWER", frame.unit, displayed); + frame:RegisterUnitEvent("UNIT_DISPLAYPOWER", frame.unit, displayed); + frame:RegisterUnitEvent("UNIT_NAME_UPDATE", frame.unit, displayed); + frame:RegisterUnitEvent("UNIT_AURA", frame.unit, displayed); + frame:RegisterUnitEvent("UNIT_HEAL_PREDICTION", frame.unit, displayed); + frame:RegisterUnitEvent("UNIT_ABSORB_AMOUNT_CHANGED", frame.unit, displayed); + frame:RegisterUnitEvent("UNIT_HEAL_ABSORB_AMOUNT_CHANGED", frame.unit, displayed); + frame:RegisterUnitEvent("UNIT_THREAT_SITUATION_UPDATE", frame.unit, displayed); + frame:RegisterUnitEvent("UNIT_CONNECTION", frame.unit, displayed); + frame:RegisterUnitEvent("UNIT_FACTION", frame.unit, displayed); +end +local registerEvents = M.RegisterEvents; + +local function updateHealth(frame, unit) + local current, max = UnitHealth(unit), frame.health.max; + frame.health:Show(); + -- sanity check, occasionally UnitHealthMax gives zero + if current > max then + -- somehow current health has gone over the maximum (missed maxhealth event) + frame.health.max = UnitHealthMax(unit); + max = frame.health.max; + if current > max then + -- error state, still over maximum + frame.health:SetWidth(width); + return; + end + elseif max > 0 then + frame.health:SetWidth(current/frame.health.max*width); + else + frame.health:SetWidth(width); + return; + end + + if UnitIsDeadOrGhost(unit) then + frame.health:Hide(); + end +end + +local function updateHealthText(frame, unit) + local current, max = UnitHealth(unit), frame.health.max; + if UnitIsDeadOrGhost(unit) then + frame.healthText:SetText("Dead"); + frame.healthText:Show(); + elseif not UnitIsConnected(unit) then + frame.healthText:SetText("DC"); + frame.healthText:Show(); + elseif max > 0 and current < max then + frame.healthText:SetText(ceil(current/max*100)); + frame.healthText:Show(); + else + frame.healthText:Hide(); + end +end + +local function updateMaxHealth(frame, unit) + frame.health.max = UnitHealthMax(unit); +end + +local function updatePower(frame, unit) + local current, max = UnitPower(unit), frame.mana.max; + -- sanity check, occasionally UnitPowerMax gives zero + if current == 0 then + frame.mana:Hide(); + return; + elseif current > max then + frame.mana:Show(); + frame.mana.max = UnitPowerMax(unit); + max = frame.mana.max; + if current > max then + -- error + frame.mana:SetWidth(width); + return; + end + end + if max > 0 then + frame.mana:SetWidth(UnitPower(unit)/max*width); + frame.mana:Show(); + else + frame.mana:SetWidth(width); + frame.mana:Show(); + end +end + +local function updatePowerText(frame, unit) + local current, max = UnitPower(unit), frame.mana.max; + if UnitIsDeadOrGhost(unit) or not UnitIsConnected(unit) then + frame.healthText:Hide(); + elseif max > 0 and current > 0 and current < max then + frame.manaText:SetText(ceil(current/max*100)); + frame.manaText:Show(); + else + frame.manaText:Hide(); + end +end + +local function updateMaxPower(frame, unit) + frame.mana.max = UnitPowerMax(unit); +end + +local function updatePowerColor(frame, unit) + frame.mana:SetVertexColor(unpack(powerColors[UnitPowerType(unit)])); +end + +local function updateName(frame, unit) + local name = UnitName(unit); + if not name then return end + frame.name:SetText(ssub(name, 1, 10)); + + local _, class = UnitClass(unit); + local color = RAID_CLASS_COLORS[class]; + if color then frame.name:SetVertexColor(color.r, color.g, color.b) end +end + +local function updateHealPred(frame, unit) + local incoming = UnitGetIncomingHeals(unit) or 0; + if incoming > 0 then + local max = frame.health.max; + local space = width - frame.health:GetWidth() + 1; + local pred = (incoming / max) * width; + frame.healpred:SetWidth(min(space, pred)); + frame.healpred:Show(); + else + frame.healpred:Hide(); + end +end + +local function updateShield(frame, unit) + local shield = UnitGetTotalAbsorbs(unit) or 0; + if shield > 0 then + local max = frame.health.max; + local space = width - frame.health:GetWidth(); + shield = (shield / max) * width; + if space == 0 then + frame.shield:Hide(); + frame.shieldhl:Show(); + elseif space < shield then + frame.shield:SetWidth(space); + frame.shield:Show(); + frame.shieldhl:Show(); + else + frame.shield:SetWidth(shield); + frame.shield:Show(); + frame.shieldhl:Hide(); + end + else + frame.shield:Hide(); + frame.shieldhl:Hide(); + end +end + +local function updateHealAbsorb(frame, unit) + local absorb = UnitGetTotalHealAbsorbs(unit) or 0; + if absorb > 0 then + local max = frame.health.max; + local space = frame.health:GetWidth(); + absorb = (absorb / max) * width; + frame.healabsorb:SetWidth(min(space, absorb)); + frame.healabsorb:Show(); + else + frame.healabsorb:Hide(); + end +end + +local function updateAuras(frame, unit) + if UnitDebuff(unit, 1, "RAID") ~= nil then + -- something dispellable + if frame.overlay.color ~= overlayColorDispel then + frame.overlay:SetVertexColor(unpack(overlayColorDispel)); + frame.overlay:Show(); + frame.overlay.color = overlayColorDispel; + end + -- don't overlay charmed when in vehicle + elseif UnitIsCharmed(unit) and unit == frame.unit then + if frame.overlay.color ~= overlayColorCharm then + frame.overlay:SetVertexColor(unpack(overlayColorCharm)); + frame.overlay:Show(); + frame.overlay.color = overlayColorCharm; + end + else + if frame.overlay.color ~= nil then + frame.overlay:Hide(); + frame.overlay.color = nil; + end + end +end + +local function updateAggro(frame, unit) + local status = UnitThreatSituation(unit); + if status and status > 0 then + frame.base:SetVertexColor(GetThreatStatusColor(status)); + else + frame.base:SetVertexColor(unpack(baseColor)); + end +end + +local function updateVehicle(frame) + local shouldTargetVehicle = UnitHasVehicleUI(frame.unit) and UnitTargetsVehicleInRaidUI(frame.unit) and UnitExists(frame.vehicle); + if shouldTargetVehicle then + if not frame.inVehicle then + frame.inVehicle = true; + frame.displayed = frame.vehicle; + registerEvents(frame); + end + elseif frame.inVehicle then + frame.inVehicle = false; + frame.displayed = frame.unit; + registerEvents(frame); + end +end + +local function updateRole(frame, unit) + local role = UnitGroupRolesAssigned(unit); + if role == "HEALER" or role == "TANK" or role == "DAMAGER" then + frame.role:SetTexCoord(GetTexCoordsForRole(role)); + frame.role:Show(); + else + frame.role:Hide(); + end +end + +local function updateLevelText(frame, unit, levelup) + if levelup then + -- PLAYER_LEVEL_UP + frame.level:SetText(levelup); + else + local level = UnitLevel(unit); + local class = UnitClassification(unit); + local leveltext, classtext; + if level < 0 then + if class == "worldboss" then + leveltext = "Boss"; + else + leveltext = "??"; + end + else + leveltext = level; + end + if class == "rareelite" then + classtext = " Rare Elite"; + elseif class == "elite" then + classtext = " Elite"; + elseif class == "rare" then + classtext = " Rare"; + else + classtext = ""; + end + frame.level:SetFormattedText("%s%s", leveltext, classtext); + end +end + +local function updateStatus(frame, unit) + -- coords from PlayerFrame + if frame.inCombat or UnitAffectingCombat(unit) then + frame.status:SetTexCoord(0.5, 1, 0, 0.484375); + frame.status:Show(); + elseif unit == "player" and IsResting() then + frame.status:SetTexCoord(0, 0.5, 0, 0.421875); + frame.status:Show(); + else + frame.status:Hide(); + end +end + +local function updatePVP(frame, unit) + if UnitIsPVPFreeForAll(unit) then + frame.pvp:SetTexture("Interface\\TARGETINGFRAME\\UI-PVP-FFA"); + frame.pvp:Show(); + elseif UnitIsPVP(unit) then + local faction = UnitFactionGroup(unit); + if faction and faction ~= "Neutral" then + -- from PlayerFrame, mercenary checks + if UnitIsMercenary(unit) then + if faction == "Horde" then + faction = "Alliance"; + elseif faction == "Alliance" then + faction = "Horde"; + end + end + frame.pvp:SetTexture("Interface\\TARGETINGFRAME\\UI-PVP-"..faction); + frame.pvp:Show(); + else + frame.pvp:Hide(); + end + else + frame.pvp:Hide(); + end +end + +local eventFuncs = { + ["UNIT_HEALTH"] = function(frame) + updateHealth(frame, frame.displayed); + updateHealthText(frame, frame.displayed); + updateShield(frame, frame.displayed); + updateHealAbsorb(frame, frame.displayed); + -- no heal prediction update, that doesn't overflow too much + end, + ["UNIT_POWER"] = function(frame) + updatePower(frame, frame.displayed); + updatePowerText(frame, frame.displayed); + end, + ["UNIT_AURA"] = function(frame) + updateAuras(frame, frame.displayed); + end, + ["UNIT_HEAL_PREDICTION"] = function(frame) + updateHealPred(frame, frame.displayed); + end, + ["UNIT_ABSORB_AMOUNT_CHANGED"] = function(frame) + updateShield(frame, frame.displayed); + end, + ["UNIT_HEAL_ABSORB_AMOUNT_CHANGED"] = function(frame) + updateHealAbsorb(frame, frame.displayed); + end, + ["UNIT_THREAT_SITUATION_UPDATE"] = function(frame) + updateAggro(frame, frame.displayed); + end, + ["UNIT_MAXHEALTH"] = function(frame) + updateMaxHealth(frame, frame.displayed); + updateHealth(frame, frame.displayed); + updateHealthText(frame, frame.displayed); + updateShield(frame, frame.displayed); + updateHealAbsorb(frame, frame.displayed); + end, + ["UNIT_MAXPOWER"] = function(frame) + updateMaxPower(frame, frame.displayed); + updatePower(frame, frame.displayed); + updatePowerText(frame, frame.displayed); + end, + ["UNIT_DISPLAYPOWER"] = function(frame) + updatePowerColor(frame, frame.displayed); + end, + ["UNIT_NAME_UPDATE"] = function(frame) + updateName(frame, frame.displayed); + end, + ["UNIT_CONNECTION"] = function(frame) + updateHealthText(frame, frame.displayed); + updatePowerText(frame, frame.displayed); + end, + ["PLAYER_ROLES_ASSIGNED"] = function(frame) + updateRole(frame, frame.unit); + end, + ["UNIT_LEVEL"] = function(frame) + updateLevelText(frame, frame.unit); + end, + ["PLAYER_LEVEL_UP"] = function(frame, arg1) + updateLevelText(frame, frame.unit, arg1); + end, + ["PLAYER_UPDATE_RESTING"] = function(frame) + updateStatus(frame, frame.unit); + end, + ["PLAYER_REGEN_DISABLED"] = function(frame) + frame.inCombat = true; + updateStatus(frame, frame.unit); + end, + ["PLAYER_REGEN_ENABLED"] = function(frame) + frame.inCombat = false; + updateStatus(frame, frame.unit); + end, + ["UNIT_FACTION"] = function(frame) + updatePVP(frame, frame.unit); + end, + ["UPDATE_ALL_BARS"] = function(frame) + updateVehicle(frame); + updateMaxHealth(frame, frame.displayed); + updateMaxPower(frame, frame.displayed); + updateHealth(frame, frame.displayed); + updateHealthText(frame, frame.displayed); + updatePower(frame, frame.displayed); + updatePowerText(frame, frame.displayed); + updateAuras(frame, frame.displayed); + updateShield(frame, frame.displayed); + updateHealPred(frame, frame.displayed); + updateHealAbsorb(frame, frame.displayed); + updatePowerColor(frame, frame.displayed); + updateAggro(frame, frame.displayed); + updateName(frame, frame.displayed); + updateRole(frame, frame.unit); + updateLevelText(frame, frame.unit); + updateStatus(frame, frame.unit); + updatePVP(frame, frame.unit); + end, +}; +eventFuncs["UNIT_HEALTH_FREQUENT"] = eventFuncs["UNIT_HEALTH"]; +eventFuncs["UNIT_ENTERED_VEHICLE"] = eventFuncs["UPDATE_ALL_BARS"]; +eventFuncs["UNIT_EXITED_VEHICLE"] = eventFuncs["UPDATE_ALL_BARS"]; +eventFuncs["UNIT_PET"] = eventFuncs["UPDATE_ALL_BARS"]; +eventFuncs["GROUP_ROSTER_UPDATE"] = eventFuncs["UPDATE_ALL_BARS"]; +eventFuncs["PLAYER_ENTERING_WORLD"] = eventFuncs["UPDATE_ALL_BARS"]; +eventFuncs["PLAYER_TARGET_CHANGED"] = eventFuncs["UPDATE_ALL_BARS"]; + +function M.UnitEvent(self, event, arg1) + eventFuncs[event](self, arg1); +end + +function M.LoadChar() + width = Settings.Character.Width; +end diff --git a/OmaUF/OmaUF.toc b/OmaUF/OmaUF.toc new file mode 100644 index 0000000..8a3beed --- /dev/null +++ b/OmaUF/OmaUF.toc @@ -0,0 +1,9 @@ +## Interface: 70300 +## Title: Oma Unit Frame +## Version: 1.0 +## Author: schyrio +## Notes: My unit frames + +Settings.lua +Events.lua +UnitFrames.lua diff --git a/OmaUF/Settings.lua b/OmaUF/Settings.lua new file mode 100644 index 0000000..ce9441f --- /dev/null +++ b/OmaUF/Settings.lua @@ -0,0 +1,119 @@ +-- Settings.lua +local PowerTypeMana = Enum.PowerType.Mana; +local PowerTypeRage = Enum.PowerType.Rage; +local PowerTypeFocus = Enum.PowerType.Focus; +local PowerTypeEnergy = Enum.PowerType.Energy; +local PowerTypeRunic = Enum.PowerType.RunicPower; +local rawget = rawget; + +-- configurable settings +-- character specific settings +local charDefaults = { + Width = 80, + Height = 40, + AnchorX = 0, + AnchorY = -330, + Clickheal = { + }, +}; +local chars = { + ["Stormreaver"] = { + ["Vildan"] = { + Width = 160, + Height = 50, + AnchorX = 0, + AnchorY = -330, + Clickheal = { + ["type1"] = "spell", + ["type2"] = "spell", + ["shift-type1"] = "spell", + ["shift-type2"] = "spell", + ["ctrl-type1"] = "spell", + ["alt-type2"] = "spell", + ["alt-shift-type1"] = "spell", + ["alt-shift-type2"] = "spell", + ["spell1"] = "Holy Light", + ["spell2"] = "Bestow Faith", + ["shift-spell1"] = "Flash of Light", + ["shift-spell2"] = "Light of the Martyr", + ["ctrl-spell1"] = "Cleanse", + ["alt-spell2"] = "Lay on Hands", + ["alt-shift-spell1"] = "Beacon of Light", + ["alt-shift-spell2"] = "Beacon of Faith", + }, + }, + ["Gedren"] = { + Width = 160, + Height = 80, + AnchorX = 0, + AnchorY = -330, + Clickheal = { + ["type1"] = "spell", + ["type2"] = "spell", + ["shift-type1"] = "spell", + ["shift-type2"] = "spell", + ["ctrl-type1"] = "spell", + ["alt-type2"] = "spell", + ["spell1"] = "Healing Touch", + ["spell2"] = "Lifebloom", + ["shift-spell1"] = "Regrowth", + ["shift-spell2"] = "Swiftmend", + ["ctrl-spell1"] = "Nature's Cure", + ["alt-spell2"] = "Rebirth", + }, + }, + }, +}; + +-- account-wide settings +local settings = { + BaseColor = {0, 0, 0}, + BgColor = {0.9, 0.9, 0.9}, + HealthColor = {0.3, 0.3, 0.3}, + ShieldColor = {0.1, 0.8, 1}, + ShieldhlColor = {0.5, 0.8, 1}, + HealpredColor = {0.5, 0.6, 0.5}, + HealabsorbColor = {0.1, 0.1, 0.1}, + OverlayColorDispel = {1, 0.5, 0, 0.5}, + OverlayColorCharm = {0.8, 0, 1, 0.5}, + OverlayColorAlert = {1, 0, 0, 0.5}, + PowerColors = { + [PowerTypeMana] = {0, 0.5, 1}, + [PowerTypeRage] = {1, 0, 0}, + [PowerTypeFocus] = {1, 0.5, 0}, + [PowerTypeEnergy] = {1, 0.8, 0}, + [PowerTypeRunic] = {0.9, 0, 0.1}, + }, + MajorAuras = { + -- Antorus + ["Psychic Assault"] = true, + ["Everburning Flames"] = true, + ["Corrupt"] = true, + ["Sleep Canister"] = true, + ["Misery"] = true, + ["Necrotic Embrace"] = true, + ["Fulminating Pulse"] = true, + ["Chilled Blood"] = true, + ["Soulblight"] = true, + ["Soulburst"] = true, + ["Soulbomb"] = true, + -- Proving Grounds for testing + ["Aqua Bomb"] = true, + -- Mythic+ + [209858] = true, -- Necrotic Rot + [240559] = true, -- Grievous Wound + [240443] = true, -- Burst + }, +}; +OmaUFSettings = settings; +-- watch to not remove mana entry +setmetatable(settings.PowerColors, {__index = function(t) return rawget(t, PowerTypeMana) end}); + +function OmaUFLoadChar() + local name, realm = UnitFullName("player"); + if chars[realm] and chars[realm][name] then + settings.Character = chars[realm][name]; + else + settings.Character = charDefaults; + end +end diff --git a/OmaUF/UnitFrames.lua b/OmaUF/UnitFrames.lua new file mode 100644 index 0000000..8a49add --- /dev/null +++ b/OmaUF/UnitFrames.lua @@ -0,0 +1,255 @@ +-- RaidFrame.lua +local _; +local unpack, pairs = unpack, pairs; +local format = string.format; +local UnitHealthMax, UnitPowerMax = UnitHealthMax, UnitPowerMax; +local CreateFrame, RegisterStateDriver, RegisterUnitWatch = CreateFrame, RegisterStateDriver, RegisterUnitWatch; +local STANDARD_TEXT_FONT = STANDARD_TEXT_FONT; +local GameTooltip = nil; +local GameTooltip_SetDefaultAnchor = nil; + +local registerEvents = OmaUFEvents.RegisterEvents; +local unitEvent = OmaUFEvents.UnitEvent; + +local Settings = OmaUFSettings; +local indSize = Settings.IndSize; +local baseColor = Settings.BaseColor; +local bgColor = Settings.BgColor; +local healthColor = Settings.HealthColor; +local shieldColor = Settings.ShieldColor; +local shieldhlColor = Settings.ShieldhlColor; +local healpredColor = Settings.HealpredColor; +local healabsorbColor = Settings.HealabsorbColor; +-- placeholders with visible values when error happens +local width, height = 10, 10; +local anchorX, anchorY = 10, 10; +local attributes = {}; + +local UnitFrames = CreateFrame("Frame", "OmaUnitFrames"); +local inheritedFrames = "SecureUnitButtonTemplate,SecureHandlerStateTemplate"; + +local events = { + ["player"] = { + "UNIT_ENTERED_VEHICLE", + "UNIT_EXITED_VEHICLE", + "UNIT_PET", + "PLAYER_ROLES_ASSIGNED", + "PLAYER_ENTERING_WORLD", + "PLAYER_LEVEL_UP", + "PLAYER_REGEN_DISABLED", + "PLAYER_REGEN_ENABLED", + "PLAYER_UPDATE_RESTING", + }, + ["target"] = { + "UNIT_ENTERED_VEHICLE", + "UNIT_EXITED_VEHICLE", + "UNIT_PET", + "UNIT_LEVEL", + "GROUP_ROSTER_UPDATE", + "PLAYER_ROLES_ASSIGNED", + "PLAYER_ENTERING_WORLD", + "PLAYER_TARGET_CHANGED", + }, +}; + +local M = {}; +OmaUnitFrames = M; + +local function frameShow(frame) + for _, ev in pairs(events[frame.unit]) do + frame:RegisterEvent(ev); + end + registerEvents(frame); + unitEvent(frame, "UPDATE_ALL_BARS"); +end + +local function frameHide(frame) + frame:UnregisterAllEvents(); +end + +local function showTooltip(frame) + GameTooltip_SetDefaultAnchor(GameTooltip, PlayerFrame); + GameTooltip:SetUnit(frame:GetAttribute("unit")); +end + +local function hideTooltip(frame) + GameTooltip:FadeOut(); +end + +local function setupFrame(frame, secure, unit) + secure:SetAttribute("unit", unit); + frame:SetAttribute("unit", unit); + frame.unit = unit; + frame.displayed = unit; + -- hide frame to get initial frameShow call + frame:Hide(); + if unit == "player" then + frame.vehicle = "vehicle"; + else + frame.vehicle = unit.."pet"; + end + -- create visuals + frame.base = frame:CreateTexture(nil, "BACKGROUND"); + frame.base:SetAllPoints(); + frame.base:SetColorTexture(1, 1, 1); + frame.base:SetVertexColor(unpack(baseColor)); + frame.healthback = frame:CreateTexture(nil, "BACKGROUND", nil, 1); + frame.healthback:SetPoint("TOPLEFT", frame, "TOPLEFT", 1, -1); + frame.healthback:SetPoint("BOTTOMRIGHT", frame, "RIGHT", -1, -5); + frame.healthback:SetTexture("Interface\\RaidFrame\\Raid-Bar-Hp-Fill"); + frame.healthback:SetVertexColor(unpack(bgColor)); + frame.health = frame:CreateTexture(nil, "BORDER"); + frame.health:SetTexture("Interface\\RaidFrame\\Raid-Bar-Hp-Fill"); + frame.health:SetPoint("TOPLEFT", frame.healthback, "TOPLEFT"); + frame.health:SetPoint("BOTTOMLEFT", frame.healthback, "BOTTOMLEFT"); + frame.health:SetVertexColor(unpack(healthColor)); + frame.health:SetWidth(width); + frame.health.max = UnitHealthMax(unit); + frame.healthText = frame:CreateFontString(nil, "ARTWORK", "GameFontHighlightLarge"); + frame.healthText:SetPoint("RIGHT", frame.healthback, "RIGHT", -2, 0); + frame.healthText:Hide(); + frame.manaback = frame:CreateTexture(nil, "BACKGROUND", nil, 1); + frame.manaback:SetPoint("TOPLEFT", frame, "LEFT", 1, -5); + frame.manaback:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -1, 1); + frame.manaback:SetTexture("Interface\\RaidFrame\\Raid-Bar-Hp-Fill"); + frame.manaback:SetVertexColor(unpack(bgColor)); + frame.mana = frame:CreateTexture(nil, "BORDER"); + frame.mana:SetPoint("TOPLEFT", frame.manaback, "TOPLEFT"); + frame.mana:SetPoint("BOTTOMLEFT", frame.manaback, "BOTTOMLEFT"); + frame.mana:SetTexture("Interface\\RaidFrame\\Raid-Bar-Hp-Fill"); + frame.mana:SetWidth(width); + frame.mana.max = UnitPowerMax(unit); + frame.manaText = frame:CreateFontString(nil, "ARTWORK", "GameFontHighlight"); + frame.manaText:SetPoint("RIGHT", frame.manaback, "RIGHT", -2, 0); + frame.manaText:Hide(); + frame.shield = frame:CreateTexture(nil, "BORDER"); + frame.shield:SetPoint("TOPLEFT", frame.health, "TOPRIGHT"); + frame.shield:SetPoint("BOTTOMLEFT", frame.health, "BOTTOMRIGHT"); + frame.shield:SetTexture("Interface\\RaidFrame\\Shield-Fill"); + frame.shield:SetVertexColor(unpack(shieldColor)); + frame.shield:Hide(); + frame.shieldhl = frame:CreateTexture(nil, "ARTWORK"); + frame.shieldhl:SetPoint("TOPLEFT", frame.healthback, "TOPRIGHT", -1, 0); + frame.shieldhl:SetPoint("BOTTOMRIGHT", frame.healthback, "BOTTOMRIGHT", 1, 0); + frame.shieldhl:SetColorTexture(unpack(shieldhlColor)); + frame.shieldhl:Hide(); + frame.healpred = frame:CreateTexture(nil, "ARTWORK"); + frame.healpred:SetPoint("TOPLEFT", frame.health, "TOPRIGHT"); + frame.healpred:SetPoint("BOTTOMLEFT", frame.health, "BOTTOMRIGHT"); + frame.healpred:SetColorTexture(unpack(healpredColor)); + frame.healpred:Hide(); + frame.healabsorb = frame:CreateTexture(nil, "ARTWORK"); + frame.healabsorb:SetPoint("TOPRIGHT", frame.health, "TOPRIGHT"); + frame.healabsorb:SetPoint("BOTTOMRIGHT", frame.health, "BOTTOMRIGHT"); + frame.healabsorb:SetColorTexture(unpack(healabsorbColor)); + frame.healabsorb:Hide(); + frame.overlay = frame:CreateTexture(nil, "ARTWORK", nil, 1); + frame.overlay:SetPoint("TOPLEFT", frame.healthback, "TOPLEFT"); + frame.overlay:SetPoint("BOTTOMRIGHT", frame.healthback, "BOTTOMRIGHT"); + frame.overlay:SetColorTexture(1, 1, 1); + frame.overlay:Hide(); + frame.role = frame:CreateTexture(nil, "OVERLAY"); + frame.role:SetPoint("TOPLEFT", frame.healthback, "TOPRIGHT", -8, 8); + frame.role:SetPoint("BOTTOMRIGHT", frame.healthback, "TOPRIGHT", 8, -8); + frame.role:SetTexture("Interface\\LFGFRAME\\UI-LFG-ICON-ROLES"); + frame.role:Hide(); + frame.status = frame:CreateTexture(nil, "OVERLAY"); + frame.status:SetPoint("TOPLEFT", frame.manaback, "BOTTOMLEFT", -8, 8); + frame.status:SetPoint("BOTTOMRIGHT", frame.manaback, "BOTTOMLEFT", 8, -8); + frame.status:SetTexture("Interface\\CHARACTERFRAME\\UI-StateIcon"); + frame.status:Hide(); + frame.pvp = frame:CreateTexture(nil, "OVERLAY"); + frame.pvp:SetPoint("TOPLEFT", frame.healthback, "TOPLEFT", -6, 6); + frame.pvp:SetPoint("BOTTOMRIGHT", frame.healthback, "TOPLEFT", 16, -16); + frame.pvp:SetTexture("Interface\\TARGETINGFRAME\\UI-PVP-Horde"); + frame.pvp:Hide(); + frame.name = frame:CreateFontString(nil, "OVERLAY", "GameFontHighlightLarge"); + frame.name:SetPoint("LEFT", frame.healthback, "LEFT", 2, 1); + frame.level = frame:CreateFontString(nil, "OVERLAY", "GameFontHighlight"); + frame.level:SetPoint("LEFT", frame.manaback, "LEFT", 2, 1); + -- set scripts + frame:SetScript("OnShow", frameShow); + frame:SetScript("OnHide", frameHide); + frame:SetScript("OnEvent", unitEvent); + -- let other addons hook these to anchor tooltip elsewhere + GameTooltip = _G["GameTooltip"]; + GameTooltip_SetDefaultAnchor = _G["GameTooltip_SetDefaultAnchor"]; + secure:SetScript("OnEnter", showTooltip); + secure:SetScript("OnLeave", hideTooltip); + -- set attributes + secure:RegisterForClicks("AnyDown"); + for attr, val in pairs(attributes) do + secure:SetAttribute(attr, val); + end + -- rest give target and menu + secure:SetAttribute("*type1", "target"); + secure:SetAttribute("*type2", "togglemenu"); +end + +-- vehicle toggle from Shadowed Unit Frames +local vehicletoggle = [=[ + local unit = self:GetAttribute("unit"); + if unit and newstate == "vehicle" and not UnitTargetsVehicleInRaidUI(unit) then + self:SetAttribute("toggleForVehicle", false); + else + self:SetAttribute("toggleForVehicle", true); + end +]=] + +local function initializePlayer(parent) + local secure = CreateFrame("Button", "OmaPlayerSecure", parent, inheritedFrames); + local frame = CreateFrame("Frame", "OmaPlayer", parent); + local unit = "player"; + secure:SetPoint("CENTER", parent, "CENTER", -320, -100); + secure:SetWidth(width+2); + secure:SetHeight(height+2); + frame:SetPoint("CENTER", parent, "CENTER", -320, -100); + frame:SetWidth(width+2); + frame:SetHeight(height+2); + setupFrame(frame, secure, unit); + RegisterUnitWatch(frame); + RegisterUnitWatch(secure); + RegisterStateDriver(secure, "vehicleui", "[vehicleui] vehicle; no"); + secure:SetAttribute("_onstate-vehicleui", vehicletoggle); +end + +local function initializeTarget(parent) + local secure = CreateFrame("Button", "OmaTargetSecure", parent, inheritedFrames); + local frame = CreateFrame("Frame", "OmaTarget", parent); + local unit = "target"; + secure:SetPoint("CENTER", parent, "CENTER", 320, -100); + secure:SetWidth(width+2); + secure:SetHeight(height+2); + frame:SetPoint("CENTER", parent, "CENTER", 320, -100); + frame:SetWidth(width+2); + frame:SetHeight(height+2); + setupFrame(frame, secure, unit); + -- TODO target frame buffs/debuffs + RegisterUnitWatch(frame); + RegisterUnitWatch(secure); + RegisterStateDriver(secure, "vehicleui", "[vehicleui] vehicle; no"); + secure:SetAttribute("_onstate-vehicleui", vehicletoggle); +end + +local function initialize() + initializePlayer(UIParent); + initializeTarget(UIParent); +end + +local function loadCharSettings() + width, height = Settings.Character.Width, Settings.Character.Height; + anchorX, anchorY = Settings.Character.AnchorX, Settings.Character.AnchorY; + attributes = Settings.Character.Clickheal; +end + +UnitFrames:RegisterEvent("ADDON_LOADED"); +UnitFrames:RegisterEvent("PLAYER_LOGIN"); +UnitFrames:SetScript("OnEvent", function(self, event) + if event == "PLAYER_LOGIN" then + initialize(); + elseif event == "ADDON_LOADED" then + OmaUFLoadChar(); + loadCharSettings(); + OmaUFEvents.LoadChar(); + end +end);