--- /dev/null
+-- 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
--- /dev/null
+## Interface: 70300
+## Title: Oma Unit Frame
+## Version: 1.0
+## Author: schyrio
+## Notes: My unit frames
+
+Settings.lua
+Events.lua
+UnitFrames.lua
--- /dev/null
+-- 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
--- /dev/null
+-- 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);