vanilla-wow-addons – Rev 1

Subversion Repositories:
Rev:
ArcHUDRing_Party = ArcHUDRing:new({
        name = "Party",
        unit = {"party1", "party2", "party3", "party4", "partypet1", "partypet2", "partypet3", "partypet4"},
        defaults = {
                Enabled = TRUE,
                Outline = TRUE,
                ShowText = TRUE,
                ShowPerc = TRUE,
                ColorFade = TRUE,
                ShowBuffs = TRUE,
        },
        def_positions = {
                {"BOTTOMRIGHT", ArcHUD.Rings.Anchors.Left, "BOTTOMLEFT", -450, 96},
                {"BOTTOMRIGHT", ArcHUD.Rings.Anchors.Left, "TOPLEFT", -20, -230},
                {"BOTTOMLEFT", ArcHUD.Rings.Anchors.Right, "TOPLEFT", 20, -230},
                {"BOTTOMLEFT", ArcHUD.Rings.Anchors.Right, "BOTTOMLEFT", 450, 96},
        },
        options = {
                {name = "ShowText", text = ARCHUDOPTIONS.TEXT.SHOWTEXT, tooltip = ARCHUDOPTIONS.TOOLTIPS.SHOWTEXT},
                {name = "ShowPerc", text = ARCHUDOPTIONS.TEXT.SHOWPERC, tooltip = ARCHUDOPTIONS.TOOLTIPS.SHOWPERC},
                {name = "ColorFade", text = ARCHUDOPTIONS.TEXT.COLORFADE, tooltip = ARCHUDOPTIONS.TOOLTIPS.COLORFADE},
                {name = "ShowBuffs", text = ARCHUDOPTIONS.TEXT.SHOWBUFFS, tooltip = ARCHUDOPTIONS.TOOLTIPS.SHOWBUFFS},
                {name = "HideBlizzFrame", text = ARCHUDOPTIONS.TEXT.HIDEBLIZZ, tooltip = ARCHUDOPTIONS.TOOLTIPS.HIDEBLIZZ},
                {name = "EnableMenu", text = ARCHUDOPTIONS.TEXT.ENABLEMENU, tooltip = ARCHUDOPTIONS.TOOLTIPS.ENABLEMENU},
        },
        disableEvents = {
                option = "HideBlizzFrame",
        },

        Initialize = function(self)
                for i=1,4 do
                        self[self.unit[i]] = self:CreatePartyFrame(i);

                        self[self.unit[i]].fadeIn = 0.5;
                        self[self.unit[i]].fadeOut = 0.5;

                        -- Don't do updates from start
                        self[self.unit[i]].DoCompleteUpdate = false;
                        self[self.unit[i]].DoPetUpdate = false;

                        -- Make nameplates register clicks
                        self[self.unit[i]].NamePlate:RegisterForClicks("LeftButtonUp", "RightButtonUp", "MiddleButtonUp", "Button4Up", "Button5Up");
                        self[self.unit[i]].pet.NamePlate:RegisterForClicks("LeftButtonUp", "RightButtonUp", "MiddleButtonUp", "Button4Up", "Button5Up");

                        -- Enable dragging of the party rings
                        self[self.unit[i]].NamePlate:RegisterForDrag("LeftButton");

                        -- Set default positions
                        self[self.unit[i]]:SetPoint(unpack(self.def_positions[i]));

                        self[self.unit[i]]:Hide();

                        -- Add disableEvents entries
                        self.disableEvents[i] = {
                                frame = "PartyMemberFrame"..i,
                                hide = TRUE,
                                events = {"PARTY_MEMBERS_CHANGED", "PARTY_LEADER_CHANGED", "PARTY_MEMBER_ENABLE",
                                                  "PARTY_MEMBER_DISABLE", "PARTY_LOOT_METHOD_CHANGED", "UNIT_FACTION",
                                                  "UNIT_AURA", "UNIT_PET", "UNIT_PVP_UPDATE", "VARIABLES_LOADED",
                                                  "UNIT_NAME_UPDATE", "UNIT_PORTRAIT_UPDATE", "UNIT_DISPLAYPOWER"},
                        };
                        self.disableEvents[i+4] = {
                                frame = "PartyMemberFrame"..i.."HealthBar",
                                events = {"CVAR_UPDATE"},
                        };
                        self.disableEvents[i+8] = {
                                frame = "PartyMemberFrame"..i.."ManaBar",
                                events = {"CVAR_UPDATE"},
                        };
                        self.disableEvents[i+12] = {
                                frame = "PartyMemberFrame"..i.."PetFrame",
                                events = {"UNIT_NAME_UPDATE", "UNIT_PORTRAIT_UPDATE", "UNIT_DISPLAYPOWER"},
                        };
                        self.disableEvents[i+16] = {
                                frame = "PartyMemberFrame"..i.."PetFrameHealthBar",
                                events = {"CVAR_UPDATE"},
                        };
                end

        end,

        Enable = function(self)
                -- If we're in a raid and the user has set to hide party interface while in raid we
                -- will make sure to disable ourselves
                if(self.hide or HIDE_PARTY_INTERFACE == "1" and GetNumRaidMembers() > 0) then
                        self.hide = TRUE;
                        self:Disable();
                        return;
                end

                for i=1,4 do
                        if(self:Get("ShowText")) then
                                self[self.unit[i]].Health.Text:Show();
                                self[self.unit[i]].Mana.Text:Show();
                        else
                                self[self.unit[i]].Health.Text:Hide();
                                self[self.unit[i]].Mana.Text:Hide();
                        end

                        if(self:Get("ShowPerc")) then
                                self[self.unit[i]].Health.Perc:Show();
                                self[self.unit[i]].Mana.Perc:Show();
                        else
                                self[self.unit[i]].Health.Perc:Hide();
                                self[self.unit[i]].Mana.Perc:Hide();
                        end

                        if(self:Get("Outline")) then
                                self[self.unit[i]].Health.BG:Show();
                                self[self.unit[i]].Mana.BG:Show();
                        else
                                self[self.unit[i]].Health.BG:Hide();
                                self[self.unit[i]].Mana.BG:Hide();
                        end


                        self[self.unit[i]].ColorFade = self:Get("ColorFade");

                        -- If ring has been moved, position accordingly
                        local loc = self:Get(self.unit[i]);
                        if(loc) then
                                local x, y = self.app.SplitString(loc, ",");
                                --self:Msg("%s has been moved. Now location: %d, %d", self.unit[i], x, y);
                                self[self.unit[i]]:ClearAllPoints();
                                self[self.unit[i]]:SetPoint("BOTTOMLEFT", UIParent, "BOTTOMLEFT", x, y);
                        end

                        -- Hook nameplate scripts
                        self:HookScript(self[self.unit[i]].NamePlate, "OnEnter", self.NamePlate_Enter);
                        self:HookScript(self[self.unit[i]].NamePlate, "OnLeave", self.NamePlate_Leave);
                        self:HookScript(self[self.unit[i]].NamePlate, "OnClick", self.NamePlate_Click);
                        self:HookScript(self[self.unit[i]].NamePlate, "OnDragStart", self.NamePlate_DragStart);
                        self:HookScript(self[self.unit[i]].NamePlate, "OnDragStop", self.NamePlate_DragStop);

                        self:HookScript(self[self.unit[i]].pet.NamePlate, "OnEnter", self.NamePlate_Enter);
                        self:HookScript(self[self.unit[i]].pet.NamePlate, "OnLeave", self.NamePlate_Leave);
                        self:HookScript(self[self.unit[i]].pet.NamePlate, "OnClick", self.NamePlate_Click);

                        -- Update partymember data
                        self:UpdateMember(self.unit[i]);

                        -- Prepare timers
                        self.app.Metro:Register(self.unit[i] .. "Health_Fade", ArcHUDRingTemplate.DoFadeUpdate, 0.01, self[self.unit[i]].Health);
                        self.app.Metro:Register(self.unit[i] .. "Mana_Fade", ArcHUDRingTemplate.DoFadeUpdate, 0.01, self[self.unit[i]].Mana);
                        self.app.Metro:Register(self.unit[i] .. "PetHealth_Fade", ArcHUDRingTemplate.DoFadeUpdate, 0.01, self[self.unit[i]].pet.Health);
                        self.app.Metro:Register(self.unit[i] .. "PetMana_Fade", ArcHUDRingTemplate.DoFadeUpdate, 0.01, self[self.unit[i]].pet.Mana);

                        self.app.Metro:Register(self.unit[i] .. "Alpha", ArcHUDRingTemplate.AlphaUpdate, 0.01, self[self.unit[i]]);

                        -- Activate timers
                        self.app.Metro:Start(self.unit[i] .. "Health_Fade");
                        self.app.Metro:Start(self.unit[i] .. "Mana_Fade");
                        self.app.Metro:Start(self.unit[i] .. "PetHealth_Fade");
                        self.app.Metro:Start(self.unit[i] .. "PetMana_Fade");

                        self.app.Metro:Start(self.unit[i] .. "Alpha");

                end

                -- Set up events
                if(self:Get("ShowBuffs")) then
                        self:RegisterEvent("UNIT_AURA");
                end
                self:RegisterEvent("UNIT_PVP_UPDATE");
                self:RegisterEvent("UNIT_PET");
                self:RegisterEvent("PARTY_LEADER_CHANGED");
                self:RegisterEvent("PARTY_MEMBER_DISABLE");
                self:RegisterEvent("PARTY_LOOT_METHOD_CHANGED");

                self:RegisterEvent("ARCHUD_PARTY_LOCKED");
                self:RegisterEvent("ARCHUD_PARTY_UNLOCKED");
                self:RegisterEvent("ARCHUD_PARTY_RESET");

                self:RegisterEvent("UNIT_HEALTH",                               "EventHandler");
                self:RegisterEvent("UNIT_MAXHEALTH",                    "EventHandler");
                self:RegisterEvent("UNIT_MANA",                                 "EventHandler");
                self:RegisterEvent("UNIT_MAXMANA",                              "EventHandler");
                self:RegisterEvent("UNIT_ENERGY",                               "EventHandler");
                self:RegisterEvent("UNIT_MAXENERGY",                    "EventHandler");
                self:RegisterEvent("UNIT_RAGE",                                 "EventHandler");
                self:RegisterEvent("UNIT_MAXRAGE",                              "EventHandler");
                self:RegisterEvent("UNIT_FOCUS",                                "EventHandler");
                self:RegisterEvent("UNIT_MAXFOCUS",                     "EventHandler");
                self:RegisterEvent("UNIT_DISPLAYPOWER",                 "EventHandler");

                self:RegisterEvent("UNIT_COMBAT",                               "EventHandler");
                self:RegisterEvent("UNIT_LEVEL",                                "EventHandler");

                self:RegisterEvent("PARTY_MEMBERS_CHANGED",     "EventHandler");
                self:RegisterEvent("PARTY_MEMBER_ENABLE",               "EventHandler");
                self:RegisterEvent("RAID_ROSTER_UPDATE",                "EventHandler");

                self:RegisterEvent("CVAR_UPDATE",                               "EventHandler");

                -- Prepare timers
                self.app.Metro:Register(self.name .. "UpdateAlpha", self.UpdateAlpha, 0.05, self);
                self.app.Metro:Register(self.name .. "DoUpdate", self.DoUpdate, 1, self);

                -- Activate timers
                self.app.Metro:Start(self.name .. "UpdateAlpha");
                self.app.Metro:Start(self.name .. "DoUpdate");

                -- Show/Hide Blizzard party frames
--[[            if(self:Get("Enabled") and self:Get("HideBlizzFrame")) then
                        if(GetNumPartyMembers() > 0 and PartyMemberFrame1:IsVisible()) then
                                self.PartyHidden = TRUE;
                        end
                        HidePartyFrame();
                else
                        ShowPartyFrame();
                end]]

                -- Check if partyrings are locked
                if(self.app:Get("PartyLock")) then
                        self:TriggerEvent("ARCHUD_PARTY_LOCKED");
                else
                        self:TriggerEvent("ARCHUD_PARTY_UNLOCKED");
                end

        end,

        Disable = function(self)
                for i=1,4 do
                        self.app.Metro:Stop(self.unit[i] .. "Health_Fade");
                        self.app.Metro:Stop(self.unit[i] .. "Mana_Fade");
                        self.app.Metro:Stop(self.unit[i] .. "PetHealth_Fade");
                        self.app.Metro:Stop(self.unit[i] .. "PetMana_Fade");
                        self.app.Metro:Stop(self.unit[i] .. "Alpha");
                        self[self.unit[i]]:Hide();
                end

                if(self:Get("Enabled") and self:Get("HideBlizzFrame") and self.PartyHidden and
                  (HIDE_PARTY_INTERFACE == "1" and GetNumRaidMembers() == 0) or
                  (HIDE_PARTY_INTERFACE == "0" and GetNumRaidMembers() > 0)) then
                        self.PartyHidden = FALSE;
                        ShowPartyFrame();
                end

                self.app.Metro:Stop(self.name .. "UpdateAlpha");
                self.app.Metro:Stop(self.name .. "DoUpdate");

                ArcHUDRing.Disable(self);

                UnitFrame_OnEvent("PARTY_MEMBERS_CHANGED")

                if(self.hide) then
                        self:RegisterEvent("PARTY_MEMBERS_CHANGED",     "EventHandler");
                        self:RegisterEvent("RAID_ROSTER_UPDATE",                "EventHandler");
                        self:RegisterEvent("CVAR_UPDATE",                               "EventHandler");
                end
        end,

        UpdateAlpha = function(self)
                if(not self.locked) then return; end
                for i=1,4 do
                        local frame = self[self.unit[i]];
                        if(frame.isInCombat) then
                                ArcHUDRingTemplate.SetRingAlpha(frame, ArcHUD.FadeIC);
                        else
                                if((frame.Health.startValue < frame.Health.maxValue) or
                                   (UnitPowerType(frame.unit) == 1 and floor(frame.Mana.startValue) > 0) or
                                   (not UnitPowerType(frame.unit) == 1 and frame.Mana.startValue < frame.Mana.maxValue)) then
                                        ArcHUDRingTemplate.SetRingAlpha(frame, ArcHUD.FadeOOC);
                                else
                                        ArcHUDRingTemplate.SetRingAlpha(frame, ArcHUD.FadeFull);
                                end
                        end
                end
        end,

        DoUpdate = function(self)
                for i=1,4 do
                        -- If we require a complete update, do so now
                        if(self[self.unit[i]].DoCompleteUpdate) then
                                self:UpdateMember(self.unit[i]);
                        end
                        if(self[self.unit[i]].DoPetUpdate) then
                                self:UpdatePet(self.unit[i]);
                        end
                end
        end,

        UpdateMember = function(self, unit)
                if(not self[unit]) then return; end
                if(not self.locked) then return; end
                local frame = self[unit];

                if(UnitInParty(unit)) then
                        -- Set up rings
                        frame.Health:SetMax(UnitHealthMax(unit));
                        frame.Health:SetValue(UnitHealth(unit));

                        frame.Mana:SetMax(UnitManaMax(unit));
                        frame.Mana:SetValue(UnitMana(unit));

                        local p=UnitHealth(unit)/UnitHealthMax(unit);
                        local r, g = 1, 1;
                        if ( p > 0.5 ) then
                                r = (1.0 - p) * 2;
                                g = 1.0;
                        else
                                r = 1.0;
                                g = p * 2;
                        end
                        if ( r < 0 ) then r = 0; elseif ( r > 1 ) then r = 1; end
                        if ( g < 0 ) then g = 0; elseif ( g > 1 ) then g = 1; end

                        if(UnitIsDead(unit)) then
                                frame.Health.Text:SetText("Dead");
                                frame.Health.Perc:SetText("");

                                frame.Mana.Text:SetText("");
                                frame.Mana.Perc:SetText("");
                        else
                                if(frame.ColorFade) then
                                        frame.Health:UpdateColor({["r"] = r, ["g"] = g, ["b"] = 0.0});
                                        frame.Health.Text:SetTextColor(r, g, 0);
                                else
                                        frame.Health.Text:SetTextColor(0, 1, 0);
                                        frame.Health:UpdateColor({["r"] = 0, ["g"] = 1, ["b"] = 0.0});
                                end
                                frame.Health.Text:SetText(UnitHealth(unit).."/"..UnitHealthMax(unit));
                                frame.Health.Perc:SetText(floor((UnitHealth(unit)/UnitHealthMax(unit))*100).."%");

                                if(UnitPowerType(unit) == 0) then
                                        info = { r = 0.00, g = 1.00, b = 1.00 };
                                else
                                        info = ManaBarColor[UnitPowerType(unit)];
                                end
                                frame.Mana:UpdateColor(ManaBarColor[UnitPowerType(unit)]);
                                frame.Mana.Text:SetVertexColor(info.r, info.g, info.b);
                                frame.Mana.Text:SetText(UnitMana(unit).."/"..UnitManaMax(unit));
                                frame.Mana.Perc:SetText(floor((UnitMana(unit)/UnitManaMax(unit))*100).."%");
                        end


                        -- Set name and level
                        local tmp, class = UnitClass(unit);
                        local color = ArcHUD.ClassColor[class];
                        if(color and UnitName(unit) ~= UNKNOWNOBJECT) then
                                frame.DoCompleteUpdate = false;
                                frame.Name:SetText("|cff"..color..UnitName(unit).."|r");
                        else
                                frame.DoCompleteUpdate = true;
                                frame.Name:SetText(UnitName(unit));
                        end

                        frame.Level:SetText(UnitLevel(unit));

                        self:UpdateGhostMode(unit);
                        self:PARTY_LOOT_METHOD_CHANGED(unit);
                        if(self:Get("ShowBuffs")) then
                                self:UNIT_AURA(unit);
                        end
                        self:UNIT_PVP_UPDATE(unit);
                        self:PARTY_LEADER_CHANGED(unit);
                        self:UNIT_PET(unit);
                        frame:Show();
                else
                        frame:Hide();
                end
        end,

        UpdateGhostMode = function(self, unit)
                if(not self[unit]) then return; end

                local color = {["r"] = 0.75, ["g"] = 0.75, ["b"] = 0.75};
                local frame = self[unit];
                if(UnitIsGhost(unit)) then
                        if(not frame.pulse) then
                                frame.pulse = true;
                                frame.alphaPulse = 0;

                                frame.Health:SetValue(UnitHealthMax(unit));
                                frame.Health:UpdateColor(color);
                                frame.Health.Text:SetText("Dead");
                                frame.Health.Text:SetTextColor(1, 0, 0);
                                frame.Health.Perc:SetText("");

                                frame.Mana:SetValue(UnitManaMax(unit));
                                frame.Mana:UpdateColor(color);
                                frame.Mana.Text:SetText("");
                                frame.Mana.Text:SetTextColor(1, 0, 0);
                                frame.Mana.Perc:SetText("");
                        end
                end
        end,

        ---------------------------------------------------------------------------
        ---------------------------------------------------------------------------
        --------  EVENT HANDLER FUNCTIONS
        -----------------------------------

        ARCHUD_PARTY_LOCKED = function(self)
                self.locked = true;
                for i=1,4 do
                        self[self.unit[i]].locked = true;
                        self[self.unit[i]].pet.locked = true;
                        if(self:Get("Enabled")) then
                                if(self:Get("EnableMenu")) then
                                        self[self.unit[i]].NamePlate:Show();
                                        self[self.unit[i]].pet.NamePlate:Show();
                                else
                                        self[self.unit[i]].NamePlate:Hide();
                                        self[self.unit[i]].pet.NamePlate:Hide();
                                end
                                for j=1,16 do
                                        self[self.unit[i]]["Buff"..j]:Hide();
                                        self[self.unit[i]]["DeBuff"..j]:Hide();
                                end
                                self:UpdateMember(self.unit[i]);
                        else
                                self[self.unit[i]]:Hide();
                        end
                        if(self[self.unit[i]].moved) then
                                self:Set(self.unit[i], self[self.unit[i]]:GetLeft() .. "," .. self[self.unit[i]]:GetBottom());
                                self[self.unit[i]].moved = FALSE;
                        end
                end
        end,

        ARCHUD_PARTY_UNLOCKED = function(self)
                self.locked = false;
                for i=1,4 do
                        self[self.unit[i]].locked = false;
                        self[self.unit[i]].pet.locked = false;
                        self[self.unit[i]].Name:SetText(self.unit[i]);
                        self[self.unit[i]].pet.Name:SetText(self.unit[i+4]);
                        if(self:Get("Enabled")) then
                                self[self.unit[i]]:Show();
                                self[self.unit[i]].NamePlate:Show();
                                for j=1,16 do
                                        self[self.unit[i]]["Buff"..j]:Show();
                                        self[self.unit[i]]["DeBuff"..j]:Show();
                                end
                                self[self.unit[i]].pet:Show();
                                ArcHUDRingTemplate.SetRingAlpha(self[self.unit[i]], 1.0);
                        else
                                self[self.unit[i]]:Hide();
                        end
                end
        end,

        ARCHUD_PARTY_RESET = function(self)
                for i=1,4 do
                        self[self.unit[i]]:ClearAllPoints();
                        self[self.unit[i]]:SetPoint(unpack(self.def_positions[i]));
                        self[self.unit[i]].moved = FALSE;
                        if(self:Get(self.unit[i])) then
                                self:Set(self.unit[i], nil);
                        end
                end
        end,

        PARTY_LOOT_METHOD_CHANGED = function(self, unit)
                if(not unit) then
                        unit = arg1;
                end

                -- Check loot settings
                local lootmethod, master = GetLootMethod();
                if(not self[unit]) then
                        for i=1,4 do
                                if(lootmethod == "master" and master == self[self.unit[i]]:GetID()) then
                                        self[self.unit[i]].MasterIcon:Show();
                                else
                                        self[self.unit[i]].MasterIcon:Hide();
                                end
                        end
                else
                        local frame = self[unit];
                        if(lootmethod == "master" and master == frame:GetID()) then
                                frame.MasterIcon:Show();
                        else
                                frame.MasterIcon:Hide();
                        end
                end
        end,

        UNIT_PET = function(self, unit)
                if(not unit) then
                        unit = arg1;
                end
                if(not self[unit]) then return; end
                local frame = self[unit].pet;

                if(UnitExists(frame.unit)) then
                        frame.Name:SetText(UnitName(frame.unit));

                        frame.Health:UpdateColor({["r"] = 0, ["g"] = 1, ["b"] = 0});
                        frame.Health:SetMax(UnitHealthMax(frame.unit));
                        frame.Health:SetValue(UnitHealth(frame.unit));
                        frame.Health.Perc:SetText(floor((UnitHealth(frame.unit)/UnitHealthMax(frame.unit))*100).."%");

                        frame.Mana:UpdateColor(ManaBarColor[UnitPowerType(frame.unit)]);
                        frame.Mana:SetMax(UnitManaMax(frame.unit));
                        frame.Mana:SetValue(UnitMana(frame.unit));
                        frame.Mana.Perc:SetText(floor((UnitMana(frame.unit)/UnitManaMax(frame.unit))*100).."%");

                        if(UnitName(frame.unit) == UNKNOWNOBJECT) then
                                frame.DoPetUpdate = true;
                        else
                                frame.DoPetUpdate = false;
                        end
                        frame:Show();
                else
                        frame:Hide();
                end
        end,

        UNIT_PVP_UPDATE = function(self, unit)
                if(not unit) then
                        unit = arg1;
                end
                if(not self[unit]) then return; end

                local icon = self[unit].PVPIcon;
                local factionGroup = UnitFactionGroup(unit);
                if (UnitIsPVPFreeForAll(unit)) then
                        icon:SetTexture("Interface\\TargetingFrame\\UI-PVP-FFA");
                        icon:ClearAllPoints();
                        icon:SetPoint("CENTER", self[unit], "BOTTOMLEFT", 136, 0);
                        icon:Show();
                elseif(factionGroup and UnitIsPVP(unit)) then
                        icon:SetTexture("Interface\\GroupFrame\\UI-Group-PVP-"..factionGroup);
                        icon:ClearAllPoints();
                        icon:SetPoint("CENTER", self[unit], "BOTTOMLEFT", 128, 0);
                        icon:Show();
                else
                        icon:Hide();
                end
        end,

        PARTY_LEADER_CHANGED = function(self, unit)
                if(not unit) then
                        unit = arg1;
                end
                if(not self[unit]) then
                        for i=1,4 do
                                -- Check party leader status
                                if(UnitIsPartyLeader(self.unit[i])) then
                                        self[self.unit[i]].LeaderIcon:Show();
                                else
                                        self[self.unit[i]].LeaderIcon:Hide();
                                end
                        end
                else
                        -- Check party leader status
                        if(UnitIsPartyLeader(unit)) then
                                self[unit].LeaderIcon:Show();
                        else
                                self[unit].LeaderIcon:Hide();
                        end
                end
        end,

        PARTY_MEMBER_DISABLE = function(self, unit)
                if(not unit) then
                        unit = arg1;
                end
                if(not self[unit]) then return; end
                if(UnitIsConnected(unit)) then return; end
                local frame = self[unit];

                frame.pulse = false;

                frame.Health:SetMax(1);
                frame.Health:SetValue(1);
                frame.Mana:SetMax(1);
                frame.Mana:SetValue(1);

                frame.Health:UpdateColor({ ["r"] = 0.5, ["g"] = 0.5, ["b"] = 0.5});
                frame.Mana:UpdateColor({ ["r"] = 0.5, ["g"] = 0.5, ["b"] = 0.5});

                frame.Health.Text:SetText("Offline");
                frame.Health.Text:SetTextColor(1, 1, 0);
                frame.Health.Perc:SetText("");

                frame.Mana.Text:SetText("");
                frame.Mana.Perc:SetText("");
        end,

        UNIT_AURA = function(self, unit)
                if(not unit) then
                        unit = arg1;
                end
                if(not self[unit]) then return; end
                local frame = self[unit];

                -- Don't update frames if they're not locked
                if(not frame.locked) then return; end

                local i, icon, buff, debuff, debuffborder, debuffcount, color;
                for i = 1, 16 do
                        buff = UnitBuff(unit, i);
                        button = frame["Buff"..i];
                        if (buff) then
                                button.Icon:SetTexture(buff);
                                button:Show();
                                button.unit = unit;
                        else
                                button:Hide();
                        end
                end

                for i = 1, 16 do
                        debuff, debuffApplications, debuffType = UnitDebuff(unit, i);
                        button = frame["DeBuff"..i];
                        if (debuff) then
                                button.Icon:SetTexture(debuff);
                                button:Show();
                                button.Border:Show();
                                button.isdebuff = 1;
                                button.unit = unit;
                                if ( debuffType ) then
                                        color = DebuffTypeColor[debuffType];
                                else
                                        color = DebuffTypeColor["none"];
                                end
                                debuffborder:SetVertexColor(color.r, color.g, color.b);
                                if (debuffApplications > 1) then
                                        button.Count:SetText(debuffApplications);
                                        button.Count:Show();
                                else
                                        button.Count:Hide();
                                end
                        else
                                button:Hide();
                        end
                end
        end,

        EventHandler = function(self)
                local unit = arg1;
                local frame, pet;
                if(unit and string.find(unit, "partypet")) then
                        frame = self[string.gsub(unit,"pet","")];
                        pet = 1;
                elseif(unit and string.find(unit, "party")) then
                        frame = self[unit];
                end

                -- No unit information passed along
                if(not frame) then
                        -- Handle party events first
                        if(event == "PARTY_MEMBERS_CHANGED" or event == "RAID_ROSTER_UPDATE" or event == "CVAR_UPDATE") then
                                if(self:Get("Enabled")) then
                                        if(HIDE_PARTY_INTERFACE == "1" and GetNumRaidMembers() > 0 and self.disabled == FALSE) then
                                                self.hide = TRUE;
                                                self:Disable();
                                                return;
                                        elseif(HIDE_PARTY_INTERFACE == "1" and GetNumRaidMembers() == 0 and self.disabled == TRUE) then
                                                self.hide = FALSE;
                                                self.disabled = FALSE;
                                                self:Enable();
                                                return;
                                        else
                                                if(not self.hide) then
                                                        for i=1,4 do
                                                                self:UpdateMember(self.unit[i]);
                                                        end
                                                end
                                        end
                                end
                        end
                else
                        if(string.find(event, "PARTY")) then
                                self:UpdateMember(unit);
                        end

                        -- We got unit information, process it based on if it's a pet or not
                        if(UnitAffectingCombat(unit)) then
                                frame.isInCombat = TRUE;
                        else
                                frame.isInCombat = FALSE;
                        end
                        if(not pet) then
                                if(event == "UNIT_LEVEL") then
                                        frame.Level:SetText(UnitLevel(unit));
                                elseif(event == "UNIT_NAME_UPDATE") then
                                        local _, class = UnitClass(unit);
                                        local color = ArcHUD.ClassColor[class];
                                        frame.Name:SetText("|cff"..color..UnitName(unit).."|r");
                                elseif(event == "UNIT_HEALTH" or event == "UNIT_MAXHEALTH") then
                                        local p=UnitHealth(unit)/UnitHealthMax(unit);
                                        local r, g = 1, 1;
                                        if ( p > 0.5 ) then
                                                r = (1.0 - p) * 2;
                                                g = 1.0;
                                        else
                                                r = 1.0;
                                                g = p * 2;
                                        end
                                        if ( r < 0 ) then r = 0; elseif ( r > 1 ) then r = 1; end
                                        if ( g < 0 ) then g = 0; elseif ( g > 1 ) then g = 1; end

                                        if(UnitIsDead(unit)) then
                                                frame.Health:SetValue(0);
                                                frame.Health.Text:SetText("Dead");
                                                frame.Health.Perc:SetText("");
                                        elseif(UnitIsGhost(unit)) then
                                                self:UpdateGhostMode(unit);
                                        else
                                                self.pulse = false;
                                                if(frame.ColorFade) then
                                                        frame.Health:UpdateColor({["r"] = r, ["g"] = g, ["b"] = 0.0});
                                                        frame.Health.Text:SetTextColor(r, g, 0);
                                                else
                                                        frame.Health.Text:SetTextColor(0, 1, 0);
                                                        frame.Health:UpdateColor({["r"] = 0, ["g"] = 1, ["b"] = 0.0});
                                                end
                                                frame.Health.Text:SetText(UnitHealth(unit).."/"..UnitHealthMax(unit));
                                                frame.Health.Perc:SetText(floor((UnitHealth(unit) / UnitHealthMax(unit)) * 100).."%");
                                                if (event == "UNIT_MAXHEALTH") then
                                                        frame.Health:SetMax(UnitHealthMax(unit));
                                                else
                                                        frame.Health:SetValue(UnitHealth(unit));
                                                end
                                        end
                                else
                                        if(UnitIsGhost(unit)) then
                                                self:UpdateGhostMode(unit);
                                        else
                                                self.pulse = false;

                                                if(UnitPowerType(unit) == 0) then
                                                        info = { r = 0.00, g = 1.00, b = 1.00 };
                                                else
                                                        info = ManaBarColor[UnitPowerType(unit)];
                                                end
                                                frame.Mana:UpdateColor(ManaBarColor[UnitPowerType(unit)]);

                                                if(UnitIsDead(unit)) then
                                                        frame.Mana.Text:SetText("");
                                                        frame.Mana.Perc:SetText("");
                                                else
                                                        frame.Mana.Text:SetText(UnitMana(unit).."/"..UnitManaMax(unit));
                                                        frame.Mana.Text:SetVertexColor(info.r, info.g, info.b);
                                                        frame.Mana.Perc:SetText(floor((UnitMana(unit)/UnitManaMax(unit))*100).."%");
                                                end

                                                if(event == "UNIT_MAXMANA" or event == "UNIT_MAXENERGY" or event == "UNIT_MAXRAGE") then
                                                        frame.Mana:SetMax(UnitManaMax(unit));
                                                else
                                                        frame.Mana:SetValue(UnitMana(unit));
                                                end
                                        end
                                end
                        else
                                if(event == "UNIT_HEALTH" or event == "UNIT_MAXHEALTH") then
                                        if(UnitIsDead(unit)) then
                                                frame.pet.Health.Perc:SetText("Dead");
                                        else
                                                frame.pet.Health.Perc:SetText(floor((UnitHealth(unit)/UnitHealthMax(unit))*100).."%");
                                        end
                                        if (event == "UNIT_MAXHEALTH") then
                                                frame.pet.Health:SetMax(UnitHealthMax(unit));
                                        else
                                                frame.pet.Health:SetValue(UnitHealth(unit));
                                        end
                                else
                                        if(UnitIsDead(unit)) then
                                                frame.pet.Mana.Perc:SetText("");
                                        else
                                                frame.pet.Mana.Perc:SetText(floor((UnitMana(unit)/UnitManaMax(unit))*100).."%");
                                        end
                                        frame.pet.Mana:UpdateColor(ManaBarColor[UnitPowerType(unit)]);

                                        if(event == "UNIT_MAXMANA" or event == "UNIT_MAXENERGY" or event == "UNIT_MAXRAGE" or event == "UNIT_MAXFOCUS") then
                                                frame.pet.Mana:SetMax(UnitManaMax(unit));
                                        else
                                                frame.pet.Mana:SetValue(UnitMana(unit));
                                        end
                                end
                        end
                end
        end;

        ---------------------------------------------------------------------------
        ---------------------------------------------------------------------------
        --------  NAMEPLATE EVENT FUNCTIONS
        -----------------------------------

        NamePlate_Enter = function()
                if(this:GetParent().locked) then
                        if(SpellIsTargeting()) then
                                if (SpellCanTargetUnit(this:GetParent().unit)) then
                                        SetCursor("CAST_CURSOR");
                                else
                                        SetCursor("CAST_ERROR_CURSOR");
                                end
                        end
                        --GameTooltip_SetDefaultAnchor(GameTooltip, this);
                        GameTooltip:SetOwner(this, ANCHOR_CURSOR);
                        GameTooltip:SetUnit(this:GetParent().unit);
                        GameTooltip:Show();
                end
        end,
        NamePlate_Leave = function()
                if(this:GetParent().locked) then
                        if(SpellIsTargeting()) then
                                SetCursor("CAST_ERROR_CURSOR");
                        end
                        if(GameTooltip:IsOwned(this)) then
                                GameTooltip:Hide();
                        end
                end
        end,
        NamePlate_Click = function()
                if(this:GetParent().locked) then
                        if((ArcHUD_CustomClick and type(ArcHUD_CustomClick) == "function" and not ArcHUD_CustomClick(arg1, this:GetParent().unit)) or
                           not ArcHUD_CustomClick) then
                                if(SpellIsTargeting() and arg1 == "RightButton") then
                                        SpellStopTargeting();
                                        return;
                                end
                                if(arg1 == "LeftButton") then
                                        if (SpellIsTargeting()) then
                                                SpellTargetUnit(this:GetParent().unit);
                                        elseif(CursorHasItem()) then
                                                DropItemOnUnit(this:GetParent().unit);
                                        else
                                                TargetUnit(this:GetParent().unit);
                                        end
                                elseif(arg1 == "RightButton" and not string.find(this:GetParent().unit, "pet")) then
                                        ToggleDropDownMenu(1, nil, getglobal("PartyMemberFrame"..this:GetParent():GetID().."DropDown"), "cursor", 0, 0);
                                end
                        end
                else
                        ArcHUD.cmd:msg("Party rings currently unlocked, lock party rings to enable clicking");
                end
        end,
        NamePlate_DragStart = function()
                if(not this:GetParent().locked) then
                        this:GetParent():ClearAllPoints();
                        this:GetParent():StartMoving();
                end
        end,
        NamePlate_DragStop = function()
                if(not this:GetParent().locked) then
                        this:GetParent():StopMovingOrSizing();
                        this:GetParent().moved = TRUE;
                end
        end,

        ---------------------------------------------------------------------------
        ---------------------------------------------------------------------------
        --------  FRAME CREATION FUNCTIONS
        -----------------------------------

        CreatePartyFrame = function(self, unitid, parent)
                -----------------------------------------------------------------------
                ------ PARTY
                ----
                -- Frame: Party unit
                local frame = CreateFrame("Frame", nil, parent);

                frame.unit = self.unit[unitid];
                frame:SetID(unitid);

                frame:SetWidth(256);
                frame:SetHeight(256);
                frame:SetScale(0.3);
                frame:SetFrameStrata("LOW");
                frame:SetMovable(true);

                local t, fs;

                -- FontString: Name
                frame.Name = self:CreateFontString(frame, "BACKGROUND", {256, 28}, 28, "CENTER", {1.0, 1.0, 1.0}, {"TOPLEFT", frame, "TOPLEFT", 0, 35});
                frame.Name:SetText("party"..unitid);

                -- FontString: Level
                frame.Level = self:CreateFontString(frame, "BACKGROUND", {256, 26}, 26, "CENTER", {1.0, 1.0, 0.0}, {"TOP", frame.Name, "BOTTOM", 0, -10});

                -- Texture: Leader Icon
                frame.LeaderIcon = self:CreateTexture(frame, "BACKGROUND", {32, 32}, "Interface\\GroupFrame\\UI-Group-LeaderIcon", {"TOPLEFT", frame.Level, "BOTTOMLEFT", 76, 5});

                -- Texture: Master Looter Icon
                frame.MasterIcon = self:CreateTexture(frame, "BACKGROUND", {32, 32}, "Interface\\GroupFrame\\UI-Group-MasterLooter", {"TOPLEFT", frame.Level, "BOTTOMLEFT", 150, 9});

                -- Texture: PvP Icon
                frame.PVPIcon = self:CreateTexture(frame, "BACKGROUND", {64, 64}, nil, {"CENTER", frame, "BOTTOMLEFT", 128, 0});

                local y;
                -- 1-16 Buff icons
                frame.Buff1 = self:CreatePartyBuffIcon(frame, unitid, 1, 36, 36);
                frame.Buff1:SetPoint("TOPRIGHT", frame, "TOPLEFT", -8, 35);
                for i=2,16 do
                        frame["Buff"..i] = self:CreatePartyBuffIcon(frame, unitid, i, 36, 36);
                        if(i == 6 or i == 14) then y = -2 else y = -3 end
                        frame["Buff"..i]:SetPoint("TOP", frame["Buff"..(i-1)], "BOTTOM", 0, y);
                end
                frame.Buff9:ClearAllPoints();
                frame.Buff9:SetPoint("TOPRIGHT", frame.Buff1, "TOPLEFT", -3, 0);

                -- 1-16 DeBuff icons
                frame.DeBuff1 = self:CreatePartyBuffIcon(frame, unitid, 1, 36, 36);
                frame.DeBuff1:SetPoint("TOPLEFT", frame, "TOPRIGHT", 8, 35);
                for i=2,16 do
                        frame["DeBuff"..i] = self:CreatePartyBuffIcon(frame, unitid, i, 36, 36);
                        if(i == 6 or i == 14) then y = -2 else y = -3 end
                        frame["DeBuff"..i]:SetPoint("TOP", frame["DeBuff"..(i-1)], "BOTTOM", 0, y);
                end
                frame.DeBuff9:ClearAllPoints();
                frame.DeBuff9:SetPoint("TOPLEFT", frame.DeBuff1, "TOPRIGHT", 3, 0);

                -- Ring: Party unit health
                frame.Health = self:CreateRing(true, frame);
                frame.Health.BG:SetAlpha(0.4);
                frame.Health:SetPoint("TOPLEFT", frame, "TOPLEFT", 128, 128);

                -- FontString: Health text
                frame.Health.Text = self:CreateFontString(frame.Health, "ARTWORK", {256, 24}, 24, "CENTER", nil, {"TOPLEFT", frame.Health, "BOTTOMLEFT", -128, 68});

                -- FontString: Health percentage
                frame.Health.Perc = self:CreateFontString(frame.Health, "ARTWORK", {128, 20}, 20, "LEFT", {1.0, 1.0, 1.0}, {"TOPRIGHT", frame.Health, "BOTTOMLEFT", 0, -112});

                -- Ring: Party unit mana
                frame.Mana = self:CreateRing(true, frame);
                frame.Mana:SetReversed(true);
                frame.Mana.BG:SetReversed(true);
                frame.Mana.BG:SetAlpha(0.4);
                frame.Mana.BG:SetAngle(180);
                frame.Mana:SetPoint("TOPRIGHT", frame, "TOPRIGHT", 128, 128);

                -- FontString: Mana text
                frame.Mana.Text = self:CreateFontString(frame.Mana, "ARTWORK", {256, 24}, 24, "CENTER", nil, {"TOPLEFT", frame.Mana, "BOTTOMLEFT", -128, 40});

                -- FontString: Mana percentage
                frame.Mana.Perc = self:CreateFontString(frame.Mana, "ARTWORK", {128, 20}, 20, "RIGHT", {1.0, 1.0, 1.0}, {"TOPLEFT", frame.Mana, "BOTTOMLEFT", 0, -112});

                -----------------------------------------------------------------------
                ------ PARTYPET
                ----
                -- Frame: Party unit pet
                frame.pet = CreateFrame("Frame", nil, frame);
                frame.pet.unit = self.unit[unitid+4];

                frame.pet:SetWidth(180);
                frame.pet:SetHeight(128);
                frame.pet:SetPoint("CENTER", frame, "BOTTOMLEFT", 128, 32);

                -- FontString: Partypet name
                frame.pet.Name = self:CreateFontString(frame.pet, "BACKGROUND", {180, 24}, 24, "CENTER", {1.0, 1.0, 0.0}, {"TOPLEFT", frame.pet, "TOPLEFT", 0, 35});

                -- Ring: Partypet health
                frame.pet.Health = self:CreateRing(true, frame.pet);
                frame.pet.Health.BG:SetAlpha(0.4);
                frame.pet.Health:SetPoint("TOPRIGHT", frame, "TOPRIGHT", 128+18, 128);

                -- FontString: Partypet health percentage
                frame.pet.Health.Perc = self:CreateFontString(frame.pet.Health, "BACKGROUND", {128, 20}, 20, "RIGHT", {1.0, 1.0, 1.0}, {"BOTTOMLEFT", frame.pet.Health, "BOTTOMLEFT", -160, -64});

                -- Ring: Partypet mana
                frame.pet.Mana = self:CreateRing(true, frame.pet);
                frame.pet.Mana:SetReversed(true);
                frame.pet.Mana.BG:SetReversed(true);
                frame.pet.Mana.BG:SetAlpha(0.4);
                frame.pet.Mana.BG:SetAngle(180);
                frame.pet.Mana:SetPoint("TOPRIGHT", frame, "TOPRIGHT", 128-18, 128);

                -- FontString: Partypet health percentage
                frame.pet.Mana.Perc = self:CreateFontString(frame.pet.Mana, "BACKGROUND", {128, 20}, 20, "RIGHT", {1.0, 1.0, 1.0}, {"BOTTOMLEFT", frame.pet.Mana, "BOTTOMLEFT", -36, -64});

                -----------------------------------------------------------------------
                ------ NAMEPLATES
                ----
                -- Party unit
                frame.NamePlate = CreateFrame("Button", nil, frame);
                frame.NamePlate:SetID(unitid);
                frame.NamePlate:SetWidth(256);
                frame.NamePlate:SetHeight(28);
                frame.NamePlate:SetPoint("TOPLEFT", frame, "TOPLEFT", 0, 35);
                frame.NamePlate:SetToplevel(true);
                frame.NamePlate:EnableMouse(true);

                -- Partypet
                frame.pet.NamePlate = CreateFrame("Button", nil, frame.pet);
                frame.pet.NamePlate:SetWidth(180);
                frame.pet.NamePlate:SetHeight(24);
                frame.pet.NamePlate:SetPoint("TOPLEFT", frame.pet, "TOPLEFT", 0, 35);
                frame.pet.NamePlate:SetToplevel(true);
                frame.pet.NamePlate:EnableMouse(true);

                return frame;
        end,

        CreatePartyBuffIcon = function(self, parent, unitid, buffid, width, height)
                local icon = CreateFrame("Button", nil, parent);

                icon:SetWidth(width);
                icon:SetHeight(height);
                icon:SetID(buffid);

                icon.Icon = icon:CreateTexture(nil, "ARTWORK");
                icon.Icon:SetAllPoints(icon);

                icon.Border = icon:CreateTexture(nil, "OVERLAY");
                icon.Border:SetTexture("Interface\\Buttons\\UI-Debuff-Overlays");
                icon.Border:SetWidth(width);
                icon.Border:SetHeight(height);
                icon.Border:SetPoint("CENTER", icon, "CENTER", 0, 0);

                icon.Count = icon:CreateFontString(nil, "OVERLAY");
                icon.Count:SetFont("Fonts\\ARIALN.TTF", 12, "THICKOUTLINE, MONOCHROME");
                icon.Count:SetPoint("BOTTOMRIGHT", icon, "BOTTOMRIGHT", -1, 0);

                icon.Icon:SetTexture("Interface\\Icons\\INV_Misc_Ear_Human_02");
                icon:SetScript("OnEnter", function() if(this:GetParent().locked) then ArcHUD:SetAuraTooltip(this); end end);
                icon:SetScript("OnLeave", function() GameTooltip:Hide(); end);

                return icon;
        end,
});

ArcHUD:Register(ArcHUDRing_Party);