Quantcast

daily updates

Munglunch [04-09-15 - 20:13]
daily updates
Filename
SVUI_!Core/system/_docklets/garrison.lua
SVUI_!Core/system/_docklets/raidleader.lua
SVUI_!Core/system/dock.lua
SVUI_!Core/system/media.lua
SVUI_Chat/SVUI_Chat.lua
SVUI_UnitFrames/Loader.lua
SVUI_UnitFrames/bodyguard.lua
diff --git a/SVUI_!Core/system/_docklets/garrison.lua b/SVUI_!Core/system/_docklets/garrison.lua
index ac1a4cf..02816d4 100644
--- a/SVUI_!Core/system/_docklets/garrison.lua
+++ b/SVUI_!Core/system/_docklets/garrison.lua
@@ -1,7 +1,7 @@
 --[[
 ##########################################################
 S V U I   By: Munglunch
-##########################################################
+##########################################################
 LOCALIZED LUA FUNCTIONS
 ##########################################################
 ]]--
@@ -27,13 +27,13 @@ local find          = string.find;
 local match         = string.match;
 local gsub          = string.gsub;
 --TABLE
-local table 		= _G.table;
+local table 				= _G.table;
 local tinsert       = _G.tinsert;
 local tremove       = _G.tremove;
-local twipe 		= _G.wipe;
+local twipe 				= _G.wipe;
 --MATH
-local math      	= _G.math;
-local min 			= math.min;
+local math      		= _G.math;
+local min 					= math.min;
 local floor         = math.floor
 local ceil          = math.ceil

@@ -68,8 +68,8 @@ local IsSpellKnown         	= _G.IsSpellKnown;
 local GetGarrison       	= _G.GetGarrison;
 local GetProfessionInfo    	= _G.GetProfessionInfo;
 local GetCurrencyInfo    	= _G.GetCurrencyInfo;
---[[
-##########################################################
+--[[
+##########################################################
 ADDON
 ##########################################################
 ]]--
@@ -77,21 +77,21 @@ local SV = select(2, ...)
 local L = SV.L
 local MOD = SV.Dock;
 local GarrisonData = {};
---[[
-##########################################################
+--[[
+##########################################################
 LOCALS
 ##########################################################
 ]]--
 local function GetDockCooldown(itemID)
 	local start,duration = GetItemCooldown(itemID)
 	local expires = duration - (GetTime() - start)
-	if expires > 0.05 then
+	if expires > 0.05 then
 		local timeLeft = 0;
 		local calc = 0;
 		if expires < 4 then
 			return format("|cffff0000%.1f|r", expires)
-		elseif expires < 60 then
-			return format("|cffffff00%d|r", floor(expires))
+		elseif expires < 60 then
+			return format("|cffffff00%d|r", floor(expires))
 		elseif expires < 3600 then
 			timeLeft = ceil(expires / 60);
 			calc = floor((expires / 60) + .5);
@@ -105,42 +105,38 @@ local function GetDockCooldown(itemID)
 			calc = floor((expires / 86400) + .5);
 			return format("|cff6666ff%dd|r", timeLeft)
 		end
-	else
+	else
 		return "|cff6666ffReady|r"
-	end
+	end
 end

 local GarrisonButton_OnEvent = function(self, event, ...)
-    if (event == "GARRISON_HIDE_LANDING_PAGE") then
-        if(not InCombatLockdown()) then
-        	self.Parent:SetWidth(self.Parent:GetWidth() - self:GetWidth())
-        	self:FadeOut(0.1,1,0,true)
-        end;
-    elseif (event == "GARRISON_SHOW_LANDING_PAGE") then
-    	if(not InCombatLockdown()) then
-    		self.Parent:SetWidth(self.Parent:GetWidth() + self:GetWidth())
-    		self:FadeIn()
-    	end;
-    end
-    if((not self.StartAlert) or (not self.StopAlert)) then return end
-    if ( event == "GARRISON_BUILDING_ACTIVATABLE" ) then
-        self:StartAlert();
-    elseif ( event == "GARRISON_BUILDING_ACTIVATED" or event == "GARRISON_ARCHITECT_OPENED") then
-        self:StopAlert();
-    elseif ( event == "GARRISON_MISSION_FINISHED" ) then
-        self:StartAlert();
-    elseif ( event == "GARRISON_MISSION_NPC_OPENED" ) then
-        self:StopAlert();
-    elseif (event == "GARRISON_INVASION_AVAILABLE") then
-        self:StartAlert();
-    elseif (event == "GARRISON_INVASION_UNAVAILABLE") then
-        self:StopAlert();
-    elseif (event == "SHIPMENT_UPDATE") then
-        local shipmentStarted = ...;
-        if (shipmentStarted) then
-            self:StartAlert();
-        end
-    end
+	if(not InCombatLockdown()) then
+		if (event == "GARRISON_HIDE_LANDING_PAGE") then
+			self:DockRemove()
+		elseif (event == "GARRISON_SHOW_LANDING_PAGE") then
+			self:DockAdd()
+		end
+	end
+	if((not self.StartAlert) or (not self.StopAlert)) then return end
+	if ( event == "GARRISON_BUILDING_ACTIVATABLE" ) then
+		self:StartAlert();
+	elseif ( event == "GARRISON_BUILDING_ACTIVATED" or event == "GARRISON_ARCHITECT_OPENED") then
+		self:StopAlert();
+	elseif ( event == "GARRISON_MISSION_FINISHED" ) then
+		self:StartAlert();
+	elseif ( event == "GARRISON_MISSION_NPC_OPENED" ) then
+		self:StopAlert();
+	elseif (event == "GARRISON_INVASION_AVAILABLE") then
+		self:StartAlert();
+	elseif (event == "GARRISON_INVASION_UNAVAILABLE") then
+		self:StopAlert();
+	elseif (event == "SHIPMENT_UPDATE") then
+		local shipmentStarted = ...;
+		if (shipmentStarted) then
+			self:StartAlert();
+		end
+	end
 end

 local function getColoredString(text, color)
@@ -231,7 +227,7 @@ local function GetBuildingData()
 			end
 			GameTooltip:AddDoubleLine(building, remaining, 0, 1, 0, 1, 1, 1)
 		end
-
+
 		hasBuildings = true
 	end

@@ -267,11 +263,13 @@ end
 local function LoadToolBarGarrison()
 	local mmButton = _G.GarrisonLandingPageMinimapButton;
 	if((not SV.db.Dock.dockTools.garrison) or (not mmButton) or MOD.GarrisonLoaded) then return end
-
-	if(InCombatLockdown()) then
-		MOD.GarrisonNeedsUpdate = true;
-		MOD:RegisterEvent("PLAYER_REGEN_ENABLED");
-		return
+
+	mmButton:FadeOut()
+
+	if(InCombatLockdown()) then
+		MOD.GarrisonNeedsUpdate = true;
+		MOD:RegisterEvent("PLAYER_REGEN_ENABLED");
+		return
 	end

 	local garrison = SV.Dock:SetDockButton("BottomLeft", L["Garrison Landing Page"], SV.media.dock.garrisonToolIcon, nil, "SVUI_Garrison", SetGarrisonTooltip, "SecureActionButtonTemplate")
@@ -293,12 +291,6 @@ local function LoadToolBarGarrison()
 	mmButton:SetHighlightTexture("")
 	mmButton:EnableMouse(false)

-	if(not mmButton:IsShown()) then
-		garrison.Parent:SetWidth(garrison.Parent:GetWidth() - garrison:GetWidth())
-		garrison:FadeOut(0.1,1,0,true)
-	end
-	mmButton:FadeOut()
-
 	garrison:RegisterEvent("GARRISON_HIDE_LANDING_PAGE");
 	garrison:RegisterEvent("GARRISON_SHOW_LANDING_PAGE");
 	garrison:RegisterEvent("GARRISON_BUILDING_ACTIVATABLE");
@@ -311,20 +303,25 @@ local function LoadToolBarGarrison()
 	garrison:RegisterEvent("SHIPMENT_UPDATE");

 	garrison:SetScript("OnEvent", GarrisonButton_OnEvent);
+
+	if(not mmButton:IsShown()) then
+		garrison:DockRemove()
+	end
+
 	C_Garrison.RequestLandingPageShipmentInfo();
 	MOD.GarrisonLoaded = true
 end
---[[
-##########################################################
+--[[
+##########################################################
 BUILD/UPDATE
 ##########################################################
 ]]--
-function MOD:UpdateGarrisonTool()
+function MOD:UpdateGarrisonTool()
 	if((not SV.db.Dock.dockTools.garrison) or self.GarrisonLoaded) then return end
 	LoadToolBarGarrison()
-end
+end

 function MOD:LoadGarrisonTool()
 	if((not SV.db.Dock.dockTools.garrison) or self.GarrisonLoaded or (not _G.GarrisonLandingPageMinimapButton)) then return end
 	SV.Timers:ExecuteTimer(LoadToolBarGarrison, 5)
-end
\ No newline at end of file
+end
diff --git a/SVUI_!Core/system/_docklets/raidleader.lua b/SVUI_!Core/system/_docklets/raidleader.lua
index edf5150..174c617 100644
--- a/SVUI_!Core/system/_docklets/raidleader.lua
+++ b/SVUI_!Core/system/_docklets/raidleader.lua
@@ -1,7 +1,7 @@
 --[[
 ##########################################################
 S V U I   By: Munglunch
-##########################################################
+##########################################################
 LOCALIZED LUA FUNCTIONS
 ##########################################################
 ]]--
@@ -23,16 +23,16 @@ local IsInInstance          = _G.IsInInstance;
 local ROLE_POLL          	= _G.ROLE_POLL;
 local READY_CHECK          	= _G.READY_CHECK;
 local RAID_CONTROL          = _G.RAID_CONTROL;
---[[
-##########################################################
+--[[
+##########################################################
 GET ADDON DATA
 ##########################################################
 ]]--
 local SV = select(2, ...)
 local L = SV.L
 local MOD = SV.Dock;
---[[
-##########################################################
+--[[
+##########################################################
 LOCALS
 ##########################################################
 ]]--
@@ -50,7 +50,7 @@ local Button_OnEnter = function(self)
 end

 local Button_OnLeave = function(self)
-	self:SetPanelColor("inverse")
+	self:SetPanelColor("default")
 	GameTooltip:Hide()
 end

@@ -62,7 +62,7 @@ local ToolButton_OnEnter = function(self, ...)
 	GameTooltip:ClearLines()
 	GameTooltip:AddDoubleLine("[Left-Click]", RAID_CONTROL, 0, 1, 0, 1, 1, 1)
 	GameTooltip:Show()
-end
+end

 local ToolButton_OnLeave = function(self, ...)
 	SVUI_RaidToolDockButton:SetPanelColor("default")
@@ -77,7 +77,7 @@ local function NewToolButton(name, parent, template, width, height, point, relat
 	button:ModWidth(width)
 	button:ModHeight(height)
 	button:ModPoint(point, relativeto, point2, xOfs, yOfs)
-	button:SetStyle("DockButton")
+	button:SetStyle("DockButton")

 	if(textDisplay) then
 		local text = button:CreateFontString(nil,"OVERLAY")
@@ -86,7 +86,7 @@ local function NewToolButton(name, parent, template, width, height, point, relat
 		text:SetJustifyH("CENTER")
 		text:SetText(textDisplay)

-		button:SetFontString(text)
+		button:SetFontString(text)
 	end

 	button:HookScript("OnEnter", Button_OnEnter)
@@ -95,32 +95,33 @@ local function NewToolButton(name, parent, template, width, height, point, relat
 	return button;
 end

-function MOD:UpdateRaidLeader(event)
+function MOD:UpdateRaidLeader(event)
 	if InCombatLockdown() then
 		self.RaidLeaderNeedsUpdate = true;
 		self:RegisterEvent("PLAYER_REGEN_ENABLED");
 		return
 	end
 	if CheckRaidStatus() then
-		SV.Dock.TopLeft.Bar:Add(self.RaidTool)
+		self.RaidTool:DockAdd()
 		if self.RaidTool.Menu.toggled == true then
-			self.RaidTool.Menu:Show()
+			self.RaidTool.Menu:Show()
 		else
 			self.RaidTool.Menu:Hide()
 		end
 	else
-		SV.Dock.TopLeft.Bar:Remove(self.RaidTool)
+		self.RaidTool:DockRemove()
 		self.RaidTool.Menu:Hide()
 	end
-end
+end

 function MOD:LoadRaidLeaderTools()
 	if(not SV.db.Dock.dockTools.leader) then return end
-	local dock = SV.Dock.TopLeft.Bar
-
+
 	self.RaidTool = SV.Dock:SetDockButton("TopLeft", RAID_CONTROL, SV.media.dock.raidToolIcon, nil, "SVUI_RaidToolDockButton");
 	self.RaidTool:SetAttribute("hasDropDown", false);

+	local dock = self.RaidTool.Parent
+
 	self.RaidTool.Menu = CreateFrame("Frame", "SVUI_RaidToolMenu", self.RaidTool, "SecureHandlerClickTemplate");
 	self.RaidTool.Menu:SetStyle("Frame", 'Transparent');
 	self.RaidTool.Menu:ModWidth(120);
@@ -140,17 +141,17 @@ function MOD:LoadRaidLeaderTools()
 	SVUI_RaidToolToggle:SetAttribute("_onclick", [=[
 		local raidUtil = self:GetFrameRef("SVUI_RaidToolMenu");
 		local closeButton = self:GetFrameRef("SVUI_RaidToolCloseButton");
-		raidUtil:Show();
-		local point = self:GetPoint();
+		raidUtil:Show();
+		local point = self:GetPoint();
 		local raidUtilPoint, raidUtilRelative, closeButtonPoint, closeButtonRelative
 		if point:find("BOTTOM") then
 			raidUtilPoint = "BOTTOMLEFT"
-			raidUtilRelative = "TOPLEFT"
+			raidUtilRelative = "TOPLEFT"
 		else
 			raidUtilPoint = "TOPLEFT"
-			raidUtilRelative = "BOTTOMLEFT"
+			raidUtilRelative = "BOTTOMLEFT"
 		end
-
+
 		raidUtil:ClearAllPoints()
 		closeButton:ClearAllPoints()
 		raidUtil:SetPoint(raidUtilPoint, self, raidUtilRelative, 2, -2)
@@ -204,7 +205,7 @@ function MOD:LoadRaidLeaderTools()
 		markerButton:ModHeight(18)
 		markerButton:SetWidth(109)
 		markerButton:RemoveTextures()
-		markerButton:SetStyle("DockButton")
+		markerButton:SetStyle("DockButton")

 		local markersText = markerButton:CreateFontString(nil,"OVERLAY")
 		markersText:SetFont(SV.media.font.default, 14, "NONE")
@@ -231,5 +232,5 @@ function MOD:LoadRaidLeaderTools()

 	self:RegisterEvent("GROUP_ROSTER_UPDATE", "UpdateRaidLeader")
 	self:RegisterEvent("PLAYER_ENTERING_WORLD", "UpdateRaidLeader")
-	self:UpdateRaidLeader()
-end
\ No newline at end of file
+	self:UpdateRaidLeader()
+end
diff --git a/SVUI_!Core/system/dock.lua b/SVUI_!Core/system/dock.lua
index a489712..2b2e8b2 100644
--- a/SVUI_!Core/system/dock.lua
+++ b/SVUI_!Core/system/dock.lua
@@ -1,7 +1,7 @@
 --[[
 ##############################################################################
 S V U I   By: Munglunch
-############################################################################## ]]--
+############################################################################## ]]--
 --[[ GLOBALS ]]--
 local _G = _G;
 local unpack        = _G.unpack;
@@ -24,7 +24,7 @@ local find          = string.find;
 local match         = string.match;
 local gsub          = string.gsub;
 --TABLE
-local table 		= _G.table;
+local table 		= _G.table;
 local tinsert       = _G.tinsert;
 local tremove       = _G.tremove;
 local wipe 			= _G.wipe;
@@ -57,8 +57,8 @@ local PlaySoundFile         = _G.PlaySoundFile;
 local UnitName              = _G.UnitName;
 local ToggleFrame           = _G.ToggleFrame;
 local ERR_NOT_IN_COMBAT     = _G.ERR_NOT_IN_COMBAT;
---[[
-##########################################################
+--[[
+##########################################################
 ADDON
 ##########################################################
 ]]--
@@ -66,8 +66,8 @@ local SV = select(2, ...);
 local L = SV.L;
 local MOD = SV:NewPackage("Dock", L["Docks"]);
 MOD.Border = {};
---[[
-##########################################################
+--[[
+##########################################################
 LOCALS
 ##########################################################
 ]]--
@@ -83,8 +83,8 @@ DOCK_DROPDOWN_OPTIONS["BottomLeft"] = { text = "To BottomLeft", func = function(
 DOCK_DROPDOWN_OPTIONS["BottomRight"] = { text = "To BottomRight", func = function(button) MOD.BottomRight.Bar:Add(button) end };
 DOCK_DROPDOWN_OPTIONS["TopLeft"] = { text = "To TopLeft", func = function(button) MOD.TopLeft.Bar:Add(button) end };
 --DOCK_DROPDOWN_OPTIONS["TopRight"] = { text = "To TopRight", func = function(button) MOD.TopRight.Bar:Add(button) end };
---[[
-##########################################################
+--[[
+##########################################################
 THEMEABLE ITEMS
 ##########################################################
 ]]--
@@ -99,7 +99,7 @@ function MOD.SetThemeDockStyle(frame, isBottom)
 	local bg = backdrop:CreateTexture(nil, "BORDER")
 	bg:InsetPoints(backdrop)
 	bg:SetTexture(1, 1, 1, 1)
-
+
 	if(isBottom) then
 		bg:SetGradientAlpha("VERTICAL", 0, 0, 0, 0.8, 0, 0, 0, 0)
 	else
@@ -152,19 +152,19 @@ function MOD.SetThemeDockStyle(frame, isBottom)
 		top:ModHeight(4)
 	end

-	return backdrop
+	return backdrop
 end

-function MOD:SetBorderTheme()
+function MOD:SetBorderTheme()
 	self.Border.Top:ModPoint("TOPLEFT", SV.Screen, "TOPLEFT", -1, 1)
 	self.Border.Top:ModPoint("TOPRIGHT", SV.Screen, "TOPRIGHT", 1, 1)
 	self.Border.Top:ModHeight(10)
 	self.Border.Top:SetBackdrop({
-		bgFile = SV.media.background.button,
-		edgeFile = [[Interface\BUTTONS\WHITE8X8]],
-		tile = false,
-		tileSize = 0,
-		edgeSize = 1,
+		bgFile = SV.media.background.button,
+		edgeFile = [[Interface\BUTTONS\WHITE8X8]],
+		tile = false,
+		tileSize = 0,
+		edgeSize = 1,
 		insets = {left = 0, right = 0, top = 0, bottom = 0}
 	})
 	self.Border.Top:SetBackdropColor(unpack(SV.media.color.dark))
@@ -180,11 +180,11 @@ function MOD:SetBorderTheme()
 	self.Border.Bottom:ModPoint("BOTTOMRIGHT", SV.Screen, "BOTTOMRIGHT", 1, -1)
 	self.Border.Bottom:ModHeight(10)
 	self.Border.Bottom:SetBackdrop({
-		bgFile = SV.media.background.button,
-		edgeFile = [[Interface\BUTTONS\WHITE8X8]],
-		tile = false,
-		tileSize = 0,
-		edgeSize = 1,
+		bgFile = SV.media.background.button,
+		edgeFile = [[Interface\BUTTONS\WHITE8X8]],
+		tile = false,
+		tileSize = 0,
+		edgeSize = 1,
 		insets = {left = 0, right = 0, top = 0, bottom = 0}
 	})
 	self.Border.Bottom:SetBackdropColor(unpack(SV.media.color.dark))
@@ -220,8 +220,8 @@ function MOD:SetButtonTheme(button, size)
 		self.Sparks.anim:Play()
 	end
 end
---[[
-##########################################################
+--[[
+##########################################################
 CORE FUNCTIONS
 ##########################################################
 ]]--
@@ -248,13 +248,13 @@ _G.ToggleSuperDockLeft = function(self, button)
 		MOD:UpdateDockBackdrops()
 		SV.Events:Trigger("DOCK_LEFT_EXPANDED");
 	else
-		if MOD.private.LeftFaded then
+		if MOD.private.LeftFaded then
 			MOD.private.LeftFaded = nil;
 			MOD.BottomLeft:FadeIn(0.2, MOD.BottomLeft:GetAlpha(), 1)
 			MOD.BottomLeft.Bar:FadeIn(0.2, MOD.BottomLeft.Bar:GetAlpha(), 1)
 			SV.Events:Trigger("DOCK_LEFT_FADE_IN");
 			PlaySoundFile([[sound\doodad\be_scryingorb_explode.ogg]])
-		else
+		else
 			MOD.private.LeftFaded = true;
 			MOD.BottomLeft:FadeOut(0.2, MOD.BottomLeft:GetAlpha(), 0)
 			MOD.BottomLeft.Bar:FadeOut(0.2, MOD.BottomLeft.Bar:GetAlpha(), 0)
@@ -287,13 +287,13 @@ _G.ToggleSuperDockRight = function(self, button)
 		MOD:UpdateDockBackdrops()
 		SV.Events:Trigger("DOCK_RIGHT_EXPANDED");
 	else
-		if MOD.private.RightFaded then
+		if MOD.private.RightFaded then
 			MOD.private.RightFaded = nil;
 			MOD.BottomRight:FadeIn(0.2, MOD.BottomRight:GetAlpha(), 1)
 			MOD.BottomRight.Bar:FadeIn(0.2, MOD.BottomRight.Bar:GetAlpha(), 1)
 			SV.Events:Trigger("DOCK_RIGHT_FADE_IN");
 			PlaySoundFile([[sound\doodad\be_scryingorb_explode.ogg]])
-		else
+		else
 			MOD.private.RightFaded = true;
 			MOD.BottomRight:FadeOut(0.2, MOD.BottomRight:GetAlpha(), 0)
 			MOD.BottomRight.Bar:FadeOut(0.2, MOD.BottomRight.Bar:GetAlpha(), 0)
@@ -340,7 +340,7 @@ function MOD:EnterFade()
 		self.BottomRight.Bar:FadeIn(0.2, self.BottomRight.Bar:GetAlpha(), 1)
 		SV.Events:Trigger("DOCK_RIGHT_FADE_IN");
 	end
-end
+end

 function MOD:ExitFade()
 	if MOD.private.LeftFaded then
@@ -354,8 +354,8 @@ function MOD:ExitFade()
 		SV.Events:Trigger("DOCK_RIGHT_FADE_OUT");
 	end
 end
---[[
-##########################################################
+--[[
+##########################################################
 SET DOCKBAR FUNCTIONS
 ##########################################################
 ]]--
@@ -443,7 +443,7 @@ local AlertActivate = function(self, child)
 	self.backdrop:Show()
 	child:ClearAllPoints()
 	child:SetAllPoints(self)
-end
+end

 local AlertDeactivate = function(self)
 	self.backdrop:Hide()
@@ -457,7 +457,7 @@ local Docklet_OnShow = function(self)
 			self.FrameLink:SetFrameLevel(10)
 		end
 		self.FrameLink:FadeIn()
-	end
+	end
 end

 local Docklet_OnHide = function(self)
@@ -469,7 +469,7 @@ local Docklet_OnHide = function(self)
 		else
 			self.FrameLink:FadeOut(0.2, 1, 0, true)
 		end
-	end
+	end
 end

 local DockButtonMakeDefault = function(self)
@@ -478,7 +478,7 @@ local DockButtonMakeDefault = function(self)
 	if(not self.Parent.Data.OriginalDefault) then
 		self.Parent.Data.OriginalDefault = self:GetName()
 	end
-end
+end

 local DockButtonActivate = function(self)
 	--print('DockButtonActivate')
@@ -491,7 +491,7 @@ local DockButtonActivate = function(self)
 		end
 		self.FrameLink:FadeIn()
 	end
-end
+end

 local DockButtonDeactivate = function(self)
 	--print('DockButtonDeactivate')
@@ -545,7 +545,7 @@ local DockletButton_OnEnter = function(self, ...)
 		GameTooltip:AddDoubleLine("[Alt + Click]", "Docking Options", 0, 0.5, 1, 0.5, 1, 0.5)
 	end
 	GameTooltip:Show()
-end
+end

 local DockletButton_OnLeave = function(self, ...)
 	MOD:ExitFade()
@@ -580,9 +580,9 @@ local DockletButton_OnClick = function(self, ...)
 end

 local DockletButton_OnPostClick = function(self, ...)
-	if InCombatLockdown() then
+	if InCombatLockdown() then
 		MOD.ErrorSound()
-		return
+		return
 	end
 	if(self.ClickTheme) then
 		self:ClickTheme()
@@ -615,10 +615,10 @@ local DockletRelocate = function(self, location)
 	if(not newParent) then return end

 	if(self.DockButton) then
-		newParent.Bar:Add(self.DockButton)
+		newParent.Bar:Add(self.DockButton)
 	end
-
-	if(self.Bar) then
+
+	if(self.Bar) then
 		local height = newParent.Bar.ToolBar:GetHeight();
 		local mod = newParent.Bar.Data[1];
 		local barAnchor = newParent.Bar.Data[2];
@@ -782,7 +782,7 @@ local AddToDock = function(self, button)

 	self.Data.Buttons[name] = button;
 	self:CheckOrder(name);
-
+
 	MOD.private.Locations[name] = currentLocation;
 	button.Parent = self;
 	button:SetParent(self.ToolBar);
@@ -804,12 +804,12 @@ local AddToDock = function(self, button)
 end

 local RemoveFromDock = function(self, button)
-	if not button then return end
+	if not button then return end
 	local name = button:GetName();
 	local registeredLocation = MOD.private.Locations[name];
 	local currentLocation = self.Data.Location

-	if(registeredLocation and (registeredLocation == currentLocation)) then
+	if(registeredLocation and (registeredLocation == currentLocation)) then
 		MOD.private.Locations[name] = nil;
 	end

@@ -837,12 +837,25 @@ local RemoveFromDock = function(self, button)
 	self:Update()
 end

+local AddToParentDock = function(self)
+	if((not self.Parent) or (not self.Parent.Add)) then return end
+	self.Parent:Add(self)
+end
+
+local RemoveFromParentDock = function(self)
+	if((not self.Parent) or (not self.Parent.Remove)) then return end
+	self.Parent:Remove(self)
+end
+
 local ActivateDockletButton = function(self, button, clickFunction, tipFunction, isAction)
 	button.Activate = DockButtonActivate
 	button.Deactivate = DockButtonDeactivate
 	button.MakeDefault = DockButtonMakeDefault
 	button.GetMenuList = GetDockablePositions

+	button.DockAdd = AddToParentDock
+	button.DockRemove = RemoveFromParentDock
+
 	if(tipFunction and type(tipFunction) == "function") then
 		button.CustomTooltip = tipFunction
 	end
@@ -875,22 +888,22 @@ local CreateBasicToolButton = function(self, displayName, texture, onclick, glob
 	local button = _G[globalName .. "DockletButton"] or CreateFrame("Button", globalName, self.ToolBar, template)

 	button:ClearAllPoints()
-	button:SetSize(size, size)
+	button:SetSize(size, size)
 	MOD:SetButtonTheme(button, size)
 	button.Icon:SetTexture(dockIcon)
 	button:SetAttribute("tipText", displayName)
 	button:SetAttribute("tipAnchor", self.Data.TipAnchor)
-    button:SetAttribute("ownerFrame", globalName)
+  button:SetAttribute("ownerFrame", globalName)

-    button.OrderIndex = 0;
+  button.OrderIndex = 0;

-    self:Add(button)
+  self:Add(button)
 	self:Initialize(button, onclick, tipFunction, primaryTemplate)
-
+
 	return button
 end
---[[
-##########################################################
+--[[
+##########################################################
 DOCKS
 ##########################################################
 ]]--
@@ -958,8 +971,8 @@ local function BorderColorUpdates()
 end

 --SV.Events:On("SHARED_MEDIA_UPDATED", BorderColorUpdates, true)
---[[
-##########################################################
+--[[
+##########################################################
 EXTERNALLY ACCESSIBLE METHODS
 ##########################################################
 ]]--
@@ -1069,8 +1082,8 @@ function MOD:NewAdvancedDocklet(location, globalName)
 	DOCK_CHECK = true
 	return frame
 end
---[[
-##########################################################
+--[[
+##########################################################
 BUILD/UPDATE
 ##########################################################
 ]]--
@@ -1095,22 +1108,22 @@ function MOD:UpdateDockBackdrops()
 	else
 		MOD.BottomLeft.backdrop:Hide()
 	end
-end
+end

 function MOD:BottomBorderVisibility()
-	if SV.db.Dock.bottomPanel then
+	if SV.db.Dock.bottomPanel then
 		SVUIDock_BottomBorder:Show()
-	else
+	else
 		SVUIDock_BottomBorder:Hide()
-	end
-end
+	end
+end

 function MOD:TopBorderVisibility()
-	if SV.db.Dock.topPanel then
+	if SV.db.Dock.topPanel then
 		SVUIDock_TopBorder:Show()
-	else
+	else
 		SVUIDock_TopBorder:Hide()
-	end
+	end
 end

 function MOD:ResetAllButtons()
@@ -1191,32 +1204,32 @@ function MOD:Load()
 	end

 	self.private = SV.private.Docks;
-
-	if(not self.private.AllFaded) then
+
+	if(not self.private.AllFaded) then
 		self.private.AllFaded = false
 	end

-	if(not self.private.LeftFaded) then
+	if(not self.private.LeftFaded) then
 		self.private.LeftFaded = false
 	end

-	if(not self.private.RightFaded) then
+	if(not self.private.RightFaded) then
 		self.private.RightFaded = false
 	end

-	if(not self.private.LeftExpanded) then
+	if(not self.private.LeftExpanded) then
 		self.private.LeftExpanded = false
 	end

-	if(not self.private.RightExpanded) then
+	if(not self.private.RightExpanded) then
 		self.private.RightExpanded = false
 	end

-	if(not self.private.Order) then
+	if(not self.private.Order) then
 		self.private.Order = {}
 	end

-	if(not self.private.Locations) then
+	if(not self.private.Locations) then
 		self.private.Locations = {}
 	end

@@ -1249,7 +1262,7 @@ function MOD:Load()
 		dock.Bar:SetSize(width, buttonsize)
 		dock.Bar:SetPoint(anchor, SV.Screen, anchor, (2 * mod), (2 * vertMod))

-		if(not MOD.private.Order[location]) then
+		if(not MOD.private.Order[location]) then
 			MOD.private.Order[location] = {}
 		end

@@ -1293,7 +1306,7 @@ function MOD:Load()
 			SV:NewAnchor(dock, location .. " Dock Window")
 		end
 	end
-
+
 	if MOD.private.LeftFaded then MOD.BottomLeft:Hide() end
 	if MOD.private.RightFaded then MOD.BottomRight:Hide() end

@@ -1338,4 +1351,4 @@ local function UpdateAllDocks()
 	MOD:UpdateDockBackdrops()
 end

-SV:NewScript(UpdateAllDocks)
\ No newline at end of file
+SV:NewScript(UpdateAllDocks)
diff --git a/SVUI_!Core/system/media.lua b/SVUI_!Core/system/media.lua
index 36ec069..dd44416 100644
--- a/SVUI_!Core/system/media.lua
+++ b/SVUI_!Core/system/media.lua
@@ -781,7 +781,7 @@ local function ChangeSystemFonts()
 	_alterFont("Tooltip_Small", "tipdialog", -1)
 	_alterFont("SystemFont_Shadow_Huge3", "combat", 0, "OUTLINE")
 	_alterFont("CombatTextFont", "combat", 64, "OUTLINE")
-	_alterFont("SubSpellFont", "dialog", 2, "NONE", 0, 0, 0)
+	_alterFont("SubSpellFont", "caps", 1, "OUTLINE", 0.8, 0.8, 0.8)
 	_alterFont("CoreAbilityFont", "zone", 10, "NONE", 0, 0, 0)
 end

diff --git a/SVUI_Chat/SVUI_Chat.lua b/SVUI_Chat/SVUI_Chat.lua
index 853d99e..aeda328 100644
--- a/SVUI_Chat/SVUI_Chat.lua
+++ b/SVUI_Chat/SVUI_Chat.lua
@@ -90,6 +90,7 @@ local NewHook = hooksecurefunc;
 	and once when the mod is loaded.
 ]]--
 local PLAYER_NAME = UnitName("player");
+local PLAYER_FILTER = PLAYER_NAME:upper();
 local CHAT_WIDTH = 350;
 local CHAT_HEIGHT = 180;
 local CHAT_THROTTLE = 45;
@@ -366,7 +367,6 @@ do
 	end

 	local AntiSpam_ChatEventFilter = function(self, event, message, author, ...)
-		if(event == 'CHAT_MSG_CHANNEL' and self:GetID() ~= 1) then return end
 		if locale == 'enUS' or locale == 'enGB' then
 			if message:find('[\227-\237]') then
 				return true;
@@ -382,15 +382,24 @@ do
 	    end

 		if(CHAT_THROTTLE ~= 0) then
-			local msg = author:upper() .. message;
-			if((msg ~= nil) and (not author:find(PLAYER_NAME))) then
-				if THROTTLE_CACHE[msg] then
-					local timeDiff = (time() - THROTTLE_CACHE[msg]) or 0
-					if timeDiff <= CHAT_THROTTLE then
-						return true;
+			local sentFrom = author:upper()
+			if(not sentFrom:find(PLAYER_FILTER)) then
+				local msg
+				if(self.GetID) then
+					local chatID = self:GetID() or 0;
+					msg = chatID .. sentFrom .. message;
+				else
+					msg = sentFrom .. message;
+				end
+				if(msg ~= nil) then
+					if THROTTLE_CACHE[msg] then
+						local timeDiff = (time() - THROTTLE_CACHE[msg]) or 0
+						if timeDiff <= CHAT_THROTTLE then
+							return true;
+						end
 					end
+					THROTTLE_CACHE[msg] = time()
 				end
-				THROTTLE_CACHE[msg] = time()
 			end
 		end
 		return SVUI_ParseMessage(self, event, message, author, ...)
@@ -1338,6 +1347,7 @@ end

 function MOD:UpdateLocals()
 	PLAYER_NAME = UnitName("player");
+	PLAYER_FILTER = PLAYER_NAME:upper();
 	CHAT_WIDTH = (SV.db.Dock.dockLeftWidth or 350) - 10;
 	CHAT_HEIGHT = (SV.db.Dock.dockLeftHeight or 180) - 15;
 	CHAT_THROTTLE = SV.db.Chat.throttleInterval;
diff --git a/SVUI_UnitFrames/Loader.lua b/SVUI_UnitFrames/Loader.lua
index 9ecf93d..f9e00a6 100644
--- a/SVUI_UnitFrames/Loader.lua
+++ b/SVUI_UnitFrames/Loader.lua
@@ -152,7 +152,7 @@ SV.defaults[Schema] = {
 			["fontSize"] = 11,
 			["classColor"] = true,
 			["valueColor"] = true,
-			["classBackdrop"] = true,
+			["classBackdrop"] = true,
 		},
 		["power"] =
 		{
@@ -2147,4 +2147,27 @@ SV.defaults[Schema] = {
 			["height"] = 28,
 		},
 	},
+	["bodyguard"] = {
+		["enable"] = true,
+		["width"] = 120,
+		["height"] = 28,
+		["health"] =
+		{
+			["position"] = "INNERRIGHT",
+			["orientation"] = "HORIZONTAL",
+			["yOffset"] = 0,
+			["xOffset"] = 0,
+			["reversed"] = false,
+			["fontSize"] = 10,
+		},
+		["name"] =
+		{
+			["position"] = "INNERLEFT",
+			["yOffset"] = 0,
+			["xOffset"] = 0,
+			["font"] = "SVUI Default Font",
+			["fontSize"] = 10,
+			["fontOutline"] = "OUTLINE",
+		},
+	},
 };
diff --git a/SVUI_UnitFrames/bodyguard.lua b/SVUI_UnitFrames/bodyguard.lua
index e829eda..c686c8f 100644
--- a/SVUI_UnitFrames/bodyguard.lua
+++ b/SVUI_UnitFrames/bodyguard.lua
@@ -62,583 +62,408 @@ LOCALS
 ##########################################################
 ]]--
 local BodyGuard = {};
-
-local defeated_spells = {
-    [173663] = true, -- Aeda Brightdawn
-    [173662] = true, -- Defender Illona
-    [173664] = true, -- Delvar Ironfist
-    [173977] = true, -- Leorajh
-    [173665] = true, -- Talonpriest Ishaal
-    [173656] = true, -- Tormmok
-    [173666] = true  -- Vivianne
-}
-
-local defeated_debuffs = {
-    [173660] = true, -- Aeda Brightdawn
-    [173657] = true, -- Defender Illona
-    [173658] = true, -- Delvar Ironfist
-    [173976] = true, -- Leorajh
-    [173659] = true, -- Talonpriest Ishaal
-    [173649] = true, -- Tormmok
-    [173661] = true  -- Vivianne
-}
-
-local defeated_pattern = "^([%w%s]+) %w+"
-
--- Get follower names for the defeated spells
-for id, _ in pairs(defeated_spells) do
+local CONTINENT_DRAENOR = 7;
+local BODYGUARD_NAMES, BARRACKS_LIST, BODYGUARD_BANNED_ZONES = {}, {[27]=true,[28]=true}, {[978]=true,[1009]=true,[1011]=true};
+local STATUS_INACTIVE, STATUS_ACTIVE, STATUS_UNKNOWN = 0, 1, 2;
+
+do
+  local AURA_SEARCH = {
+    [173663]=true,[173662]=true,[173664]=true,[173977]=true,[173665]=true,[173656]=true,[173666]=true,
+    [173660]=true,[173657]=true,[173658]=true,[173976]=true,[173659]=true,[173649]=true,[173661]=true
+  };
+  for id, _ in pairs(AURA_SEARCH) do
     local spellName = GetSpellInfo(id)
-    local name = spellName:match(defeated_pattern)
+    local name = spellName:match("^([%w%s]+) %w+")
     if name then
-        defeated_spells[id] = name
-    end
-end
-
--- Do the same for debuffs
-for id, _ in pairs(defeated_debuffs) do
-    local spellName = GetSpellInfo(id)
-    local name = spellName:match(defeated_pattern)
-    if name then
-        defeated_debuffs[id] = name
+      BODYGUARD_NAMES[id] = name
     end
+  end
 end

--- Valid barracks IDs, 27 = lvl 2 barracks, 28 = lvl 3 barracks
-local barracks_ids = {[27] = true, [28] = true}
-
---- Bodyguard status values.
--- @class table
--- @name BodyGuard.Status
--- @field Inactive Bodyguard is not with the player (stationed at barracks).
--- @field Active Bodyguard is with the player.
--- @field Unknown Status of bodyguard is unknown (this includes death).
-BodyGuard.Status = {
-    Inactive = 0,
-    Active = 1,
-    Unknown = 2
-}
-
 local bodyguard = {}

 local function ResetBodyguard()
-    bodyguard.name = nil
-    bodyguard.level = 0
-    bodyguard.health = 0
-    bodyguard.max_health = 0
-    bodyguard.npc_id = 0
-    bodyguard.follower_id = 0
-    bodyguard.last_known_guid = nil
-    bodyguard.status = BodyGuard.Status.Unknown
-    bodyguard.loaded_from_building = false
+  bodyguard.name = nil
+  bodyguard.health = 0
+  bodyguard.max_health = 0
+  bodyguard.npc_id = 0
+  bodyguard.follower_id = 0
+  bodyguard.status = STATUS_UNKNOWN
+  bodyguard.loaded_from_building = false
 end

 ResetBodyguard()

-local callbacks = {
-    guid = {},
-    name = {},
-    level = {},
-    health = {},
-    status = {},
-    gossip_opened = {},
-    gossip_closed = {}
-}
-
-local function RunCallback(cb_type, ...)
-    for func, enabled in pairs(callbacks[cb_type]) do
-        if enabled then pcall(func, BodyGuard, ...) end
-    end
-end
-
-local frame = CreateFrame("Frame")
-
 local events = {
-    player = {}
+  player = {}
 }

 local function UpdateFromBuildings()
-    ResetBodyguard()
-    bodyguard.loaded_from_building = true
-    local buildings = C_Garrison.GetBuildings()
-    for i = 1, #buildings do
-        local building = buildings[i]
-        local building_id = building.buildingID
-        local plot_id = building.plotID
-        if barracks_ids[building_id] then
-            local name, level, quality, displayID, followerID, garrFollowerID, status, portraitIconID = C_Garrison.GetFollowerInfoForBuilding(plot_id)
-            if not name then
-                bodyguard.status = BodyGuard.Status.Inactive
-                RunCallback("status", bodyguard.status)
-                return
-            end
-            bodyguard.name = name
-            bodyguard.level = level
-            bodyguard.follower_id = type(garrFollowerID) == "string" and tonumber(garrFollowerID, 16) or garrFollowerID
-            RunCallback("name", bodyguard.name)
-            RunCallback("level", bodyguard.level)
-            break
-        end
+  ResetBodyguard()
+  bodyguard.loaded_from_building = true
+  local buildings = C_Garrison.GetBuildings()
+  for i = 1, #buildings do
+    local building = buildings[i]
+    local building_id = building.buildingID
+    local plot_id = building.plotID
+    if BARRACKS_LIST[building_id] then
+      local name, level, quality, displayID, followerID, garrFollowerID, status, portraitIconID = C_Garrison.GetFollowerInfoForBuilding(plot_id)
+      if not name then
+        BodyGuard:StatusUpdate(STATUS_INACTIVE)
+        return
+      end
+      bodyguard.name = name
+      bodyguard.follower_id = type(garrFollowerID) == "string" and tonumber(garrFollowerID, 16) or garrFollowerID
+      BodyGuard:NameUpdate(name)
+      break
     end
+  end
 end

 local function UpdateFromUnit(unit)
-    local name = UnitName(unit)
-    if name ~= bodyguard.name then return end
-    bodyguard.last_known_guid = UnitGUID(unit)
-    bodyguard.health = UnitHealth(unit)
-    bodyguard.max_health = UnitHealthMax(unit)
-    RunCallback("guid", bodyguard.last_known_guid)
-    RunCallback("health", bodyguard.health, bodyguard.max_health)
+  local name = UnitName(unit)
+  if name ~= bodyguard.name then return end
+  bodyguard.health = UnitHealth(unit)
+  bodyguard.max_health = UnitHealthMax(unit)
+
+  BodyGuard:HealthUpdate(bodyguard.health, bodyguard.max_health)
 end

 function events.GARRISON_BUILDINGS_SWAPPED()
-    UpdateFromBuildings()
+  UpdateFromBuildings()
 end

 function events.GARRISON_BUILDING_ACTIVATED()
-    UpdateFromBuildings()
+  UpdateFromBuildings()
 end

 function events.GARRISON_BUILDING_UPDATE(buildingID)
-    if barracks_ids[buildingID] then UpdateFromBuildings() end
+  if BARRACKS_LIST[buildingID] then UpdateFromBuildings() end
 end

 function events.GARRISON_FOLLOWER_REMOVED()
-    UpdateFromBuildings()
+  UpdateFromBuildings()
 end

 function events.GARRISON_UPDATE()
-    UpdateFromBuildings()
+  UpdateFromBuildings()
 end

 function events.PLAYER_TARGET_CHANGED(cause)
-    if not bodyguard.name then return end
-    if cause ~= "LeftButton" and cause ~= "up" then return end
-    UpdateFromUnit("target")
+  if not bodyguard.name then return end
+  if cause ~= "LeftButton" and cause ~= "up" then return end
+  UpdateFromUnit("target")
 end

 function events.UPDATE_MOUSEOVER_UNIT()
-    if not bodyguard.name then return end
-    UpdateFromUnit("mouseover")
+  if not bodyguard.name then return end
+  UpdateFromUnit("mouseover")
 end

 function events.UNIT_HEALTH(unit)
-    if not bodyguard.name then return end
-    UpdateFromUnit(unit)
+  if not bodyguard.name then return end
+  UpdateFromUnit(unit)
 end

 local FLAGMASK = bor(COMBATLOG_OBJECT_TYPE_GUARDIAN, COMBATLOG_OBJECT_CONTROL_PLAYER, COMBATLOG_OBJECT_REACTION_FRIENDLY, COMBATLOG_OBJECT_AFFILIATION_MINE)
 function events.COMBAT_LOG_EVENT_UNFILTERED(timestamp, event, hideCaster, sourceGUID, sourceName, sourceFlags, sourceRaidFlags, destGUID, destName, destFlags, destRaidFlags, ...)
-    if not bodyguard.name or (not sourceName and not destName) then return end
-    if sourceName == bodyguard.name then
-        local isBodyguard = band(sourceFlags, FLAGMASK) == FLAGMASK
-        if not isBodyguard then return end
-        bodyguard.status = BodyGuard.Status.Active
-        bodyguard.last_known_guid = sourceGUID
-        RunCallback("guid", bodyguard.last_known_guid)
-        RunCallback("status", bodyguard.status)
-    elseif destName == bodyguard.name and bodyguard.status ~= BodyGuard.Status.Inactive then
-        local isBodyguard = band(destFlags, FLAGMASK) == FLAGMASK
-        if not isBodyguard then return end
-        local prefix, suffix = event:match("^([A-Z_]+)_([A-Z]+)$")
-
-        local amount = 0;
-        if prefix:match("^SPELL") then
-					amount = select(4, ...);
-        elseif prefix == "ENVIRONMENTAL" then
-					amount = select(2, ...);
-				else
-					amount = select(1, ...);
-        end
-
-        local changed = false
-
-        if suffix == "DAMAGE" then
-            bodyguard.health = bodyguard.health - amount
-            changed = true
-        elseif suffix == "HEAL" then
-            bodyguard.health = bodyguard.health + amount
-            if bodyguard.health >= bodyguard.max_health then
-                bodyguard.health = bodyguard.max_health
-            end
-            changed = true
-        elseif suffix == "INSTAKILL" then
-            bodyguard.health = 0
-            changed = true
-        end
-
-        if changed then
-            if bodyguard.health <= 0 then
-                bodyguard.health = 0
-                bodyguard.status = BodyGuard.Status.Unknown
-            else
-                bodyguard.status = BodyGuard.Status.Active
-            end
-            RunCallback("health", bodyguard.health, bodyguard.max_health)
-            RunCallback("status", bodyguard.status)
-        end
+  if not bodyguard.name or (not sourceName and not destName) then return end
+  if sourceName == bodyguard.name then
+    local isBodyguard = band(sourceFlags, FLAGMASK) == FLAGMASK
+    if not isBodyguard then return end
+    bodyguard.status = STATUS_ACTIVE
+    BodyGuard:StatusUpdate(bodyguard.status)
+
+  elseif destName == bodyguard.name and bodyguard.status ~= STATUS_INACTIVE then
+    local isBodyguard = band(destFlags, FLAGMASK) == FLAGMASK
+    if not isBodyguard then return end
+    local prefix, suffix = event:match("^([A-Z_]+)_([A-Z]+)$")
+
+    local amount = 0;
+    if prefix:match("^SPELL") then
+      amount = select(4, ...);
+    elseif prefix == "ENVIRONMENTAL" then
+      amount = select(2, ...);
+    else
+      amount = select(1, ...);
     end
-end

-function events.PLAYER_REGEN_ENABLED()
-    if bodyguard.health <= 0 then return end
-    bodyguard.health = bodyguard.max_health
-    RunCallback("health", bodyguard.health, bodyguard.max_health)
-end
-
-local bodyguard_gossip_open = false
-local bodyguard_confirm_showing = false
-
-function events.GOSSIP_SHOW()
-    if not BodyGuard:Exists() or UnitName("target") ~= bodyguard.name then return end
-    bodyguard_gossip_open = true
-    RunCallback("gossip_opened")
-end
+    local changed = false
+
+    if suffix == "DAMAGE" then
+      bodyguard.health = bodyguard.health - amount
+      changed = true
+    elseif suffix == "HEAL" then
+      bodyguard.health = bodyguard.health + amount
+      if bodyguard.health >= bodyguard.max_health then
+        bodyguard.health = bodyguard.max_health
+      end
+      changed = true
+    elseif suffix == "INSTAKILL" then
+      bodyguard.health = 0
+      changed = true
+    end

-function events.GOSSIP_CLOSED()
-    if bodyguard_gossip_open then RunCallback("gossip_closed") end
-    bodyguard_gossip_open = false
-    bodyguard_confirm_showing = false
+    if changed then
+      if bodyguard.health <= 0 then
+        bodyguard.health = 0
+        bodyguard.status = STATUS_UNKNOWN
+      else
+        bodyguard.status = STATUS_ACTIVE
+      end
+      BodyGuard:HealthUpdate(bodyguard.health, bodyguard.max_health)
+      BodyGuard:StatusUpdate(bodyguard.status)
+    end
+  end
 end

-function events.GOSSIP_CONFIRM(index, message, cost)
-    if not bodyguard_gossip_open or cost ~= 0 then return end
-    bodyguard_confirm_showing = true
+function events.PLAYER_REGEN_ENABLED()
+  if bodyguard.health <= 0 then return end
+  bodyguard.health = bodyguard.max_health
+  BodyGuard:HealthUpdate(bodyguard.health, bodyguard.max_health)
 end

 function events.player.UNIT_AURA()
-    for i = 1, 40 do
-        local _, _, _, _, _, duration, expireTime, _, _, _, id = UnitDebuff("player", i)
-        if not defeated_debuffs[id] then return end
-        local name = defeated_debuffs[id]
-        if name == bodyguard.name then
-            bodyguard.status = BodyGuard.Status.Inactive
-            bodyguard.health = 0
-            RunCallback("status", bodyguard.status)
-            RunCallback("health", bodyguard.health, bodyguard.max_health)
-            return
-        end
+  for i = 1, 40 do
+    local _, _, _, _, _, duration, expireTime, _, _, _, id = UnitDebuff("player", i)
+    if not BODYGUARD_NAMES[id] then return end
+    local name = BODYGUARD_NAMES[id]
+    if name == bodyguard.name then
+      bodyguard.status = STATUS_INACTIVE
+      bodyguard.health = 0
+      BodyGuard:StatusUpdate(bodyguard.status)
+      BodyGuard:HealthUpdate(bodyguard.health, bodyguard.max_health)
+      return
     end
+  end
 end

-function event:PLAYER_ENTERING_WORLD(event)
-	self:Update_AllFrames()
+function events.PLAYER_ENTERING_WORLD()
+  MOD:RefreshUnitFrames()
+  local showing = BodyGuard:IsShowing()

-    local showing = BodyGuard:IsShowing()
-
-    if not BodyGuard:Exists() and not BodyGuard.db.Active then
-        if showing then BodyGuard:HideFrame() end
-        return
-    end
+  if not BodyGuard:Exists() and not BodyGuard.IsActive then
+    if showing then BodyGuard:HideFrame() end
+    return
+  end

-    if(not BodyGuard:IsValidZone()) then
-		BodyGuard:HideFrame()
-    elseif showing then
-        BodyGuard:UpdateSettings()
-    elseif BodyGuard:GetStatus() ~= BodyGuard.Status.Inactive and BodyGuard.db.Active then
-        BodyGuard:ShowFrame()
-    end
+  if(not BodyGuard:IsValidZone()) then
+    BodyGuard:HideFrame()
+  elseif showing then
+    BodyGuard:UpdateSettings()
+  elseif BodyGuard:GetStatus() ~= STATUS_INACTIVE and BodyGuard.IsActive then
+    BodyGuard:ShowFrame()
+  end
 end

-function event:ZONE_CHANGED_NEW_AREA()
-    local validZone = BodyGuard:IsValidZone()
-    if not validZone then
-        if not BodyGuard:IsShowing() then return end
-		BodyGuard:HideFrame()
-    elseif BodyGuard.db.Active and BodyGuard:GetStatus() ~= BodyGuard.Status.Inactive then
-        BodyGuard:ShowFrame()
-    end
+function events.ZONE_CHANGED_NEW_AREA()
+  local validZone = BodyGuard:IsValidZone()
+  if not validZone then
+    if not BodyGuard:IsShowing() then return end
+    BodyGuard:HideFrame()
+  elseif BodyGuard.IsActive and BodyGuard:GetStatus() ~= STATUS_INACTIVE then
+    BodyGuard:ShowFrame()
+  end
 end

-frame:SetScript("OnEvent", function(f, e, ...)
-    if events[e] then events[e](...) return end
+local EventListener = CreateFrame("Frame")
+
+EventListener:SetScript("OnEvent", function(f, e, ...)
+  if events[e] then events[e](...) return end

-    for key, val in pairs(events) do
-        if type(val) == "table" then
-            if val[e] then val[e](...) return end
-        end
+  for key, val in pairs(events) do
+    if type(val) == "table" then
+      if val[e] then val[e](...) return end
     end
+  end
 end)

 for key, val in pairs(events) do
-    if key:match("^[A-Z0-9_]+$") then
-        frame:RegisterEvent(key)
-    else
-        for event, _ in pairs(events[key]) do
-            frame:RegisterUnitEvent(event, key)
-        end
+  if key:match("^[A-Z0-9_]+$") then
+    EventListener:RegisterEvent(key)
+  else
+    for event, _ in pairs(events[key]) do
+      EventListener:RegisterUnitEvent(event, key)
     end
+  end
 end

 -- Function hooks

 function BodyGuard:GOSSIP_CONFIRM_Hook(s, data)
-    if not bodyguard_confirm_showing then return end
+  if not bodyguard_confirm_showing then return end

-    bodyguard.status = BodyGuard.Status.Inactive
-    bodyguard.health = bodyguard.max_health
-    RunCallback("status", bodyguard.status)
-    RunCallback("health", bodyguard.health, bodyguard.max_health)
+  bodyguard.status = STATUS_INACTIVE
+  bodyguard.health = bodyguard.max_health
+  BodyGuard:StatusUpdate(bodyguard.status)
+  BodyGuard:HealthUpdate(bodyguard.health, bodyguard.max_health)
 end

 if not BodyGuard.GOSSIP_CONFIRM_Hooked then
-    hooksecurefunc(StaticPopupDialogs.GOSSIP_CONFIRM, "OnAccept", function(self, data)
-			BodyGuard:GOSSIP_CONFIRM_Hook(self, data)
-    end)
+  hooksecurefunc(StaticPopupDialogs.GOSSIP_CONFIRM, "OnAccept", function(self, data)
+    BodyGuard:GOSSIP_CONFIRM_Hook(self, data)
+  end)

-		BodyGuard.GOSSIP_CONFIRM_Hooked = true
+  BodyGuard.GOSSIP_CONFIRM_Hooked = true
 end

 function BodyGuard:Exists()
-    return bodyguard.name and bodyguard.loaded_from_building
+  return bodyguard.name and bodyguard.loaded_from_building
 end

 function BodyGuard:UpdateFromBuilding()
-    UpdateFromBuildings()
-end
-
-function BodyGuard:GetInfo()
-    return setmetatable({}, {__index = function(t, k) return bodyguard[k] end, __metatable = 'Forbidden'})
-end
-
-function BodyGuard:GetGUID()
-    return bodyguard.last_known_guid
-end
-
-function BodyGuard:GetStatus()
-    return bodyguard.status
+  UpdateFromBuildings()
 end

 function BodyGuard:GetName()
-    return bodyguard.name
-end
-
-function BodyGuard:GetLevel()
-    return bodyguard.level
-end
-
-function BodyGuard:GetHealth()
-    return bodyguard.health
-end
-
-function BodyGuard:GetMaxHealth()
-    return bodyguard.max_health
-end
-
-function BodyGuard:IsAlive()
-    return self:GetHealth() > 0
-end
-
-function BodyGuard:RegisterCallback(cb_type, cb_func)
-    if not callbacks[cb_type] then error("Invalid callback type: " .. tostring(cb_type)) end
-    if callbacks[cb_type][cb_func] then return end
-    callbacks[cb_type][cb_func] = true
-end
-
-function BodyGuard:UnregisterCallback(cb_type, cb_func)
-    if not callbacks[cb_type] then error("Invalid callback type: " .. tostring(cb_type)) end
-    callbacks[cb_type][cb_func] = nil
+  return bodyguard.name
 end

-
-local CONTINENT_DRAENOR = 7
-local BODYGUARD_BANNED_ZONES = {
-    [978] = true,  -- Ashran
-    [1009] = true, -- Stormshield
-    [1011] = true  -- Warspear
-}
-
 function BodyGuard:IsValidZone()
-    SetMapToCurrentZone()
-    local currentContinent = GetCurrentMapContinent()
-    local currentMapAreaID = GetCurrentMapAreaID()
-    local valid = currentContinent == CONTINENT_DRAENOR and not BODYGUARD_BANNED_ZONES[currentMapAreaID]
-    BodyGuard.db.IsInValidZone = valid
+  SetMapToCurrentZone()
+  local currentContinent = GetCurrentMapContinent()
+  local currentMapAreaID = GetCurrentMapAreaID()
+  local valid = currentContinent == CONTINENT_DRAENOR and not BODYGUARD_BANNED_ZONES[currentMapAreaID]
+  BodyGuard.IsInValidZone = valid

-    return valid
+  return valid
 end

 function BodyGuard:IsShowing()
-	if(self.frame:IsShown() or self.combatEvent == self.showFrame) then
-		return true
-	else
-		return false
-	end
+  if(self.UF:IsShown() or self.combatEvent == self.showFrame) then
+    return true
+  else
+    return false
+  end
 end

 function BodyGuard:HideFrame()
-	if(InCombatLockdown()) then
-		self.frame:RegisterEvent("COMBAT_REGEN_ENABLED")
-		self.combatEvent = self.HideFrame
-		return
-	elseif(self.frame:IsEventRegistered("COMBAT_REGEN_ENABLED")) then
-		self.frame:UnregisterEvent("COMBAT_REGEN_ENABLED")
-	end
+  if(InCombatLockdown()) then
+    self.UF:RegisterEvent("COMBAT_REGEN_ENABLED")
+    self.combatEvent = self.HideFrame
+    return
+  elseif(self.UF:IsEventRegistered("COMBAT_REGEN_ENABLED")) then
+    self.UF:UnregisterEvent("COMBAT_REGEN_ENABLED")
+  end

-	self.frame:Hide()
+  self.UF:Hide()
 end

 function BodyGuard:ShowFrame()
-	if(InCombatLockdown()) then
-		self.frame:RegisterEvent("COMBAT_REGEN_ENABLED")
-		self.combatEvent = self.ShowFrame
-		return
-	elseif(self.frame:IsEventRegistered("COMBAT_REGEN_ENABLED")) then
-		self.frame:UnregisterEvent("COMBAT_REGEN_ENABLED")
-	end
+  if(InCombatLockdown()) then
+    self.UF:RegisterEvent("COMBAT_REGEN_ENABLED")
+    self.combatEvent = self.ShowFrame
+    return
+  elseif(self.UF:IsEventRegistered("COMBAT_REGEN_ENABLED")) then
+    self.UF:UnregisterEvent("COMBAT_REGEN_ENABLED")
+  end

-	self.frame:Show()
+  self.UF:Show()
 end

 local function OnEvent(self, event)
-	if(event == "PLAYER_REGEN_ENABLED") then
-		self.combatEvent(BodyGuard, event)
-	elseif(event == "PLAYER_TARGET_CHANGED") then
-		if(UnitExists("target") and UnitName("target") == BodyGuard:GetName()) then
-			self.targetGlow:Show()
-		else
-			self.targetGlow:Hide()
-		end
-	end
-end
-
-local isCreated = false
-
-function BodyGuard:CreateFrame()
-	if(isCreated) then return end
-	local frame = CreateFrame("Button", "SVUI_BodyGuard", SV.Screen, "SecureActionButtonTemplate")
-	frame:SetScript("OnEvent", OnEvent)
-	frame:RegisterEvent("PLAYER_TARGET_CHANGED")
-
-	frame:SetStyle("Frame", "Icon")
-	frame.targetGlow = frame.Panel.Shadow
-	frame.targetGlow:SetBackdropBorderColor(0, 1, 0, 0.5)
-	frame.targetGlow:Hide()
-
-	BodyGuard.frame = frame
-	local name = self:GetName()
-	frame:SetAttribute("type1", "macro")
-	if name then
-		frame:SetAttribute("macrotext1", "/targetexact " .. name)
-	end
-
-	self:HideFrame()
-
-	frame:SetTemplate("Default", nil, true)
-	frame:SetPoint("CENTER", SV.Screen, "CENTER")
-	frame:SetWidth(SV.db.UnitFrames.bodyguard.width)
-	frame:SetHeight(SV.db.UnitFrames.bodyguard.height)
-
-	frame.healthBar = CreateFrame("StatusBar", nil, frame)
-	frame.healthBar:InsetPoints(frame)
-	frame.healthBar:SetMinMaxValues(0, 1)
-	frame.healthBar:SetValue(1)
-	frame.healthBar:SetStatusBarTexture(LSM:Fetch("statusbar", SV.db.UnitFrames.statusbar))
-
-	frame.healthBar.name = frame.healthBar:CreateFontString(nil, 'OVERLAY')
-	SV:FontManager(frame.healthBar.name, "unitsecondary")
-	frame.healthBar.name:SetPoint("CENTER", frame, "CENTER")
-
-	frame.healthBar.name:SetTextColor(unpack(oUF_SVUI.colors.reaction[5]))
-
-	SV:NewAnchor(frame, L["BodyGuard Frame"])
-
-	isCreated = true
+  if(event == "PLAYER_REGEN_ENABLED") then
+    self.combatEvent(BodyGuard, event)
+  elseif(event == "PLAYER_TARGET_CHANGED") then
+    if(UnitExists("target") and UnitName("target") == BodyGuard:GetName()) then
+      self.targetGlow:Show()
+    else
+      self.targetGlow:Hide()
+    end
+  end
 end

 function BodyGuard:UpdateSettings()
-	if(SV.db.UnitFrames.bodyguard.enable) then
-		self.frame:SetParent(SV.Screen)
-	else
-		self.frame:SetParent(SV.Hidden)
-	end
-
-	self:HealthUpdate(self.db.Health, self.db.MaxHealth)
-	self.frame:SetWidth(SV.db.UnitFrames.bodyguard.width)
-	self.frame:SetHeight(SV.db.UnitFrames.bodyguard.height)
-end
-
-
-function BodyGuard:GUIDUpdate(GUID)
+  if(SV.db.UnitFrames.bodyguard.enable) then
+    self.UF:SetParent(SV.Screen)
+  else
+    self.UF:SetParent(SV.Hidden)
+  end

+  self:HealthUpdate(self.CurrentHealth, self.CurrentMaxHealth)
+  self.UF:SetWidth(SV.db.UnitFrames.bodyguard.width)
+  self.UF:SetHeight(SV.db.UnitFrames.bodyguard.height)
 end

 function BodyGuard:StatusUpdate(status)
-	if status == self.Status.Active then
-		self:NameUpdate(self:GetName())
-		self:HealthUpdate(self.db.Health, self.db.MaxHealth)
-		self:ShowFrame()
-	elseif status == self.Status.Inactive then
-		self:HideFrame()
-	end
+  if status == STATUS_ACTIVE then
+    self:NameUpdate(self:GetName())
+    self:HealthUpdate(self.CurrentHealth, self.CurrentMaxHealth)
+    self:ShowFrame()
+  elseif status == STATUS_INACTIVE then
+    self:HideFrame()
+  end

-	self.db.Active = status ~= self.Status.Inactive
+  self.IsActive = status ~= STATUS_INACTIVE
 end

 function BodyGuard:NameUpdate(name)
-	if(not InCombatLockdown() and name) then
-		self.frame:SetAttribute("macrotext1", "/targetexact " .. name)
-	end
-
-	self.frame.healthBar.name:SetText(name)
-end
-
-function BodyGuard:LevelUpdate(...)
+  if(not InCombatLockdown() and name) then
+    self.UF:SetAttribute("macrotext1", "/targetexact " .. name)
+  end

+  self.UF.healthBar.name:SetText(name)
 end

 function BodyGuard:HealthUpdate(health, maxHealth)
-	self.frame.healthBar:SetMinMaxValues(0, maxHealth)
-	self.frame.healthBar:SetValue(health)
+  self.UF.healthBar:SetMinMaxValues(0, maxHealth)
+  self.UF.healthBar:SetValue(health)

-	local r, g, b = unpack(oUF_SVUI.colors.health)
-	if SV.db.UnitFrames.colors.healthclass then
-		r, g, b = unpack(oUF_SVUI.colors.reaction[5])
-	end
+  local r, g, b = unpack(oUF_SVUI.colors.health)
+  r, g, b = oUF_SVUI.ColorGradient(health, maxHealth, 1, 0, 0, 1, 1, 0, r, g, b)

-	if SV.db.UnitFrames.colors.colorhealthbyvalue then
-		r, g, b = oUF_SVUI.ColorGradient(health, maxHealth, 1, 0, 0, 1, 1, 0, r, g, b)
-	end
+  self.UF.healthBar:SetStatusBarColor(r, g, b)
+  self.UF.backdropTexture:SetVertexColor(r * 0.35, g * 0.35, b * 0.35)

-	self.frame.healthBar:SetStatusBarColor(r, g, b)
+  self.CurrentHealth = health
+  self.CurrentMaxHealth = maxHealth
+end

-	if(SV.db.UnitFrames.colors.customhealthbackdrop) then
-		self.frame.backdropTexture:SetVertexColor(SV.db.UnitFrames.colors.health_backdrop.r, SV.db.UnitFrames.colors.health_backdrop.g, SV.db.UnitFrames.colors.health_backdrop.b)
-	else
-		self.frame.backdropTexture:SetVertexColor(r * 0.35, g * 0.35, b * 0.35)
-	end
+function BodyGuard:Init(...)
+  self:UpdateFromBuilding()
+
+  local frame = CreateFrame("Button", "SVUI_BodyGuard", SV.Screen, "SecureActionButtonTemplate")
+  frame:SetPoint("CENTER", SV.Screen, "CENTER")
+  frame:SetWidth(SV.db.UnitFrames.bodyguard.width)
+  frame:SetHeight(SV.db.UnitFrames.bodyguard.height)
+  frame:SetScript("OnEvent", OnEvent)
+  frame:SetStyle("Frame", "Icon")
+
+  frame.targetGlow = frame.Panel.Shadow
+  frame.targetGlow:SetBackdropBorderColor(0, 1, 0, 0.5)
+  frame.targetGlow:Hide()
+
+  frame:RegisterEvent("PLAYER_TARGET_CHANGED")
+  frame.healthBar = CreateFrame("StatusBar", nil, frame)
+  frame.healthBar:InsetPoints(frame)
+  frame.healthBar:SetMinMaxValues(0, 1)
+  frame.healthBar:SetValue(1)
+  frame.healthBar:SetStatusBarTexture(LSM:Fetch("statusbar", SV.db.UnitFrames.statusbar))
+
+  frame.healthBar.name = frame.healthBar:CreateFontString(nil, 'OVERLAY')
+  SV:FontManager(frame.healthBar.name, "unitsecondary")
+  frame.healthBar.name:SetPoint("CENTER", frame, "CENTER")
+  frame.healthBar.name:SetTextColor(unpack(oUF_SVUI.colors.reaction[5]))
+
+  SV:NewAnchor(frame, L["BodyGuard Frame"])
+
+  local name = self:GetName()
+  frame:SetAttribute("type1", "macro")
+  if name then
+    frame:SetAttribute("macrotext1", "/targetexact " .. name)
+  end

-	self.db.Health = health
-	self.db.MaxHealth = maxHealth
-end
+  self.UF = frame

--- function BodyGuard:GossipOpened(...)
---
--- end
---
--- function BodyGuard:GossipClosed(...)
---
--- end
+  self:HideFrame()
+  self.LoginHealth = true

-function BodyGuard:Init(...)
-	self:UpdateFromBuilding()
-
-	self:CreateFrame()
-	self.LoginHealth = true
-	self:RegisterCallback('guid', self.GUIDUpdate)
-	self:RegisterCallback('status', self.StatusUpdate)
-	self:RegisterCallback('name', self.NameUpdate)
-	self:RegisterCallback('level', self.LevelUpdate)
-	self:RegisterCallback('health', self.HealthUpdate)
-	--self:RegisterCallback('gossip_opened', self.GossipOpened)
-	--self:RegisterCallback('gossip_closed', self.GossipClosed)
-
-    if type(self.db.IsInValidZone) ~= "boolean" then
-			self.db.IsInValidZone = self:IsValidZone()
-    end
+  if type(self.IsInValidZone) ~= "boolean" then
+    self.IsInValidZone = self:IsValidZone()
+  end

-	if self.db.Active and self.db.IsInValidZone then
-		self:ShowFrame()
-		self:HealthUpdate(self.db.Health, self.db.MaxHealth)
+  if self.IsActive and self.IsInValidZone then
+    self:ShowFrame()
+    self:HealthUpdate(self.CurrentHealth, self.CurrentMaxHealth)
   end
 end